Merge remote branch 'upstream/gallium-0.1' into nouveau-gallium-0.1

This commit is contained in:
Ben Skeggs
2008-05-25 14:19:18 +10:00
166 changed files with 14270 additions and 3997 deletions
+1
View File
@@ -108,6 +108,7 @@ linux-dri-x86 \
linux-dri-x86-64 \
linux-dri-ppc \
linux-dri-xcb \
linux-egl \
linux-indirect \
linux-fbdev \
linux-glide \
+3 -1
View File
@@ -59,8 +59,10 @@ SRC_DIRS := egl $(SRC_DIRS)
PROGRAM_DIRS = egl
endif
DRIVER_DIRS = dri
WINDOW_SYSTEM=dri
WINDOW_SYSTEM = dri
GALLIUM_WINSYS_DIRS = dri
# gamma are missing because they have not been converted to use the new
+65
View File
@@ -0,0 +1,65 @@
# -*-makefile-*-
# Configuration for linux-dri: Linux DRI hardware drivers for XFree86 & others
include $(TOP)/configs/default
CONFIG_NAME = linux-dri
# Compiler and flags
CC = gcc
CXX = g++
#MKDEP = /usr/X11R6/bin/makedepend
#MKDEP = gcc -M
#MKDEP_OPTIONS = -MF depend
OPT_FLAGS = -O -g
PIC_FLAGS = -fPIC
# Add '-DGLX_USE_TLS' to ARCH_FLAGS to enable TLS support.
ARCH_FLAGS ?=
DEFINES = -D_POSIX_SOURCE -D_POSIX_C_SOURCE=199309L -D_SVID_SOURCE \
-D_BSD_SOURCE -D_GNU_SOURCE \
-DPTHREADS -DUSE_EXTERNAL_DXTN_LIB=1 -DIN_DRI_DRIVER \
-DGLX_DIRECT_RENDERING -DGLX_INDIRECT_RENDERING \
-DHAVE_ALIAS -DHAVE_POSIX_MEMALIGN
X11_INCLUDES = -I/usr/X11R6/include
CFLAGS = -Wall -Wmissing-prototypes -std=c99 -ffast-math \
$(OPT_FLAGS) $(PIC_FLAGS) $(ARCH_FLAGS) $(DEFINES) $(ASM_FLAGS)
CXXFLAGS = -Wall $(OPT_FLAGS) $(PIC_FLAGS) $(ARCH_FLAGS) $(DEFINES)
MESA_ASM_SOURCES =
# Library/program dependencies
EXTRA_LIB_PATH=-L/usr/X11R6/lib
LIBDRM_CFLAGS = $(shell pkg-config --cflags libdrm)
LIBDRM_LIB = $(shell pkg-config --libs libdrm)
DRI_LIB_DEPS = $(EXTRA_LIB_PATH) -lm -lpthread -lexpat -ldl $(LIBDRM_LIB)
GL_LIB_DEPS = $(EXTRA_LIB_PATH) -lX11 -lXext -lXxf86vm -lXdamage -lXfixes \
-lm -lpthread -ldl \
$(LIBDRM_LIB)
# This is now 0 by default since it seems to confuse the hell out of people
# and generate a lot of extra noise on bugzilla. If you need to build with
# EGL, do 'make linux-dri USING_EGL=1'
USING_EGL=0
# Directories
SRC_DIRS = gallium mesa gallium/winsys glu egl
PROGRAM_DIRS = egl
DRIVER_DIRS = dri
WINDOW_SYSTEM = dri
GALLIUM_WINSYS_DIRS = egl_drm
# gamma are missing because they have not been converted to use the new
# interface.
DRI_DIRS = intel
+3
View File
@@ -0,0 +1,3 @@
demo
GLInfo
sample
+3 -1
View File
@@ -28,6 +28,7 @@ static GLfloat Zpos = -1.0;
static float Xzoom, Yzoom;
static GLboolean DrawFront = GL_FALSE;
static GLboolean Dither = GL_TRUE;
static int win = 0;
static void Reset( void )
@@ -215,6 +216,7 @@ static void Key( unsigned char key, int x, int y )
printf("glDrawBuffer(%s)\n", DrawFront ? "GL_FRONT" : "GL_BACK");
break;
case 27:
glutDestroyWindow(win);
exit(0);
break;
}
@@ -343,7 +345,7 @@ int main( int argc, char *argv[] )
else
glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE);
glutCreateWindow(argv[0]);
win = glutCreateWindow(argv[0]);
Init(ciMode, filename);
Usage();
+3 -2
View File
@@ -42,7 +42,7 @@ static GLfloat Xrot = 0, Yrot = -30, Zrot = 0;
static GLboolean Anim = GL_TRUE;
static GLint Bias = 0, BiasStepSign = +1; /* ints avoid fp precision problem */
static GLint BiasMin = -400, BiasMax = 400;
static int win = 0;
static void
@@ -172,6 +172,7 @@ static void Key( unsigned char key, int x, int y )
Bias = 100.0 * (key - '0');
break;
case 27:
glutDestroyWindow(win);
exit(0);
break;
}
@@ -281,7 +282,7 @@ int main( int argc, char *argv[] )
glutInitWindowPosition( 0, 0 );
glutInitWindowSize( 350, 350 );
glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE );
glutCreateWindow(argv[0]);
win = glutCreateWindow(argv[0]);
glutReshapeFunc( Reshape );
glutKeyboardFunc( Key );
glutSpecialFunc( SpecialKey );
+13 -12
View File
@@ -1,13 +1,9 @@
/*
* GL_ARB_multitexture demo
* GL_ARB_pixel_buffer_object test
*
* Command line options:
* -info print GL implementation information
* -w WIDTH -h HEIGHT sets window size
*
*
* Brian Paul November 1998 This program is in the public domain.
* Modified on 12 Feb 2002 for > 2 texture units.
*/
#define GL_GLEXT_PROTOTYPES
@@ -25,6 +21,8 @@
#define PBO 11
#define QUIT 100
static GLuint DrawPBO;
static GLboolean Animate = GL_TRUE;
static GLboolean use_pbo = 1;
static GLboolean whole_rect = 1;
@@ -49,7 +47,7 @@ static void Idle( void )
}
}
static int max( int a, int b ) { return a > b ? a : b; }
/*static int max( int a, int b ) { return a > b ? a : b; }*/
static int min( int a, int b ) { return a < b ? a : b; }
static void DrawObject()
@@ -62,6 +60,7 @@ static void DrawObject()
* release the old copy of the texture and allocate a new one
* without waiting for outstanding rendering to complete.
*/
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, DrawPBO);
glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_EXT, size, NULL, GL_STREAM_DRAW_ARB);
{
@@ -69,7 +68,7 @@ static void DrawObject()
printf("char %d\n", (unsigned char)(Drift * 255));
memset(image, size, (unsigned char)(Drift * 255));
memset(image, (unsigned char)(Drift * 255), size);
glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT);
}
@@ -86,7 +85,9 @@ static void DrawObject()
if (image == NULL)
image = malloc(size);
memset(image, size, (unsigned char)(Drift * 255));
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_EXT, 0);
memset(image, (unsigned char)(Drift * 255), size);
/* BGRA should be the fast path for regular uploads as well.
*/
@@ -227,12 +228,12 @@ static void SpecialKey( int key, int x, int y )
static void Init( int argc, char *argv[] )
{
const char *exten = (const char *) glGetString(GL_EXTENSIONS);
GLuint texObj, DrawPBO;
GLuint texObj;
GLint size;
if (!strstr(exten, "GL_ARB_multitexture")) {
printf("Sorry, GL_ARB_multitexture not supported by this renderer.\n");
if (!strstr(exten, "GL_ARB_pixel_buffer_object")) {
printf("Sorry, GL_ARB_pixel_buffer_object not supported by this renderer.\n");
exit(1);
}
+4
View File
@@ -0,0 +1,4 @@
df_gears
df_morph3d
df_reflect
multi_window
+5
View File
@@ -0,0 +1,5 @@
demo1
demo2
demo3
eglgears
eglinfo
+7 -1
View File
@@ -46,7 +46,7 @@ demo3.o: demo3.c $(HEADERS)
eglinfo: eglinfo.o $(TOP)/$(LIB_DIR)/libEGL.so
$(CC) $(CFLAGS) eglinfo.o -L$(TOP)/$(LIB_DIR) -lEGL $(LIBDRM_LIB) -o $@
$(CC) $(CFLAGS) eglinfo.o -L$(TOP)/$(LIB_DIR) -lGL -lEGL $(LIBDRM_LIB) -o $@
eglinfo.o: eglinfo.c $(HEADERS)
$(CC) -c $(CFLAGS) -I$(TOP)/include eglinfo.c
@@ -63,3 +63,9 @@ clean:
rm -f *.o *~
rm -f *.so
rm -f $(PROGRAMS)
run:
LD_LIBRARY_PATH=$(TOP)/lib ./eglgears
debug:
LD_LIBRARY_PATH=$(TOP)/lib gdb ./eglgears
+1 -1
View File
@@ -102,7 +102,7 @@ main(int argc, char *argv[])
/*
EGLDisplay d = eglGetDisplay(EGL_DEFAULT_DISPLAY);
*/
EGLDisplay d = eglGetDisplay("!fb_dri");
EGLDisplay d = eglGetDisplay("!EGL_i915");
assert(d);
if (!eglInitialize(d, &maj, &min)) {
+1 -1
View File
@@ -102,7 +102,7 @@ main(int argc, char *argv[])
/*
EGLDisplay d = eglGetDisplay(EGL_DEFAULT_DISPLAY);
*/
EGLDisplay d = eglGetDisplay("!fb_dri");
EGLDisplay d = eglGetDisplay("!EGL_i915");
assert(d);
if (!eglInitialize(d, &maj, &min)) {
+1 -1
View File
@@ -576,7 +576,7 @@ main(int argc, char *argv[])
/*
EGLDisplay d = eglGetDisplay(EGL_DEFAULT_DISPLAY);
*/
EGLDisplay d = eglGetDisplay(":0");
EGLDisplay d = eglGetDisplay("!EGL_i915");
assert(d);
if (!eglInitialize(d, &maj, &min)) {
+1 -1
View File
@@ -385,7 +385,7 @@ main(int argc, char *argv[])
}
/* DBR : Create EGL context/surface etc */
d = eglGetDisplay(":0");
d = eglGetDisplay("!EGL_i915");
assert(d);
if (!eglInitialize(d, &maj, &min)) {
+1 -1
View File
@@ -140,7 +140,7 @@ main(int argc, char *argv[])
{
int maj, min;
/*EGLDisplay d = eglGetDisplay(EGL_DEFAULT_DISPLAY);*/
EGLDisplay d = eglGetDisplay(":0");
EGLDisplay d = eglGetDisplay("!EGL_i915");
if (!eglInitialize(d, &maj, &min)) {
printf("eglinfo: eglInitialize failed\n");
+1
View File
@@ -0,0 +1 @@
glfbdevtest
+1
View File
@@ -1,5 +1,6 @@
brick
bump
convolutions
deriv
extfuncs.h
mandelbrot
+8 -1
View File
@@ -14,7 +14,8 @@ PROGS = \
mandelbrot \
noise \
toyball \
texdemo1
texdemo1 \
convolutions
##### RULES #####
@@ -62,6 +63,12 @@ texdemo1: texdemo1.o readtex.o
texdemo1.o: texdemo1.c readtex.h extfuncs.h
$(CC) -c -I$(INCDIR) $(CFLAGS) texdemo1.c
convolutions: convolutions.o readtex.o
$(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
clean:
-rm -f $(PROGS)
+21
View File
@@ -0,0 +1,21 @@
const int KernelSize = 9;
//texture offsets
uniform vec2 Offset[KernelSize];
//convolution kernel
uniform vec4 KernelValue[KernelSize];
uniform sampler2D srcTex;
uniform vec4 ScaleFactor;
uniform vec4 BaseColor;
void main(void)
{
int i;
vec4 sum = vec4(0.0);
for (i = 0; i < KernelSize; ++i) {
vec4 tmp = texture2D(srcTex, gl_TexCoord[0].st + Offset[i]);
sum += tmp * KernelValue[i];
}
gl_FragColor = sum * ScaleFactor + BaseColor;
}
+5
View File
@@ -0,0 +1,5 @@
void main() {
gl_FrontColor = gl_Color;
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
+441
View File
@@ -0,0 +1,441 @@
#define GL_GLEXT_PROTOTYPES
#include "readtex.h"
#include <GL/glut.h>
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>
enum Filter {
GAUSSIAN_BLUR,
SHARPEN,
MEAN_REMOVAL,
EMBOSS,
NO_FILTER,
LAST
};
#define QUIT LAST
struct BoundingBox {
float minx, miny, minz;
float maxx, maxy, maxz;
};
struct Texture {
GLuint id;
GLfloat x;
GLfloat y;
GLint width;
GLint height;
GLenum format;
};
static const char *textureLocation = "../images/girl2.rgb";
static GLfloat viewRotx = 0.0, viewRoty = 0.0, viewRotz = 0.0;
static struct BoundingBox box;
static struct Texture texture;
static GLuint program;
static GLint menuId;
static enum Filter filter = GAUSSIAN_BLUR;
static void checkError(int line)
{
GLenum err = glGetError();
if (err) {
printf("GL Error %s (0x%x) at line %d\n",
gluErrorString(err), (int) err, line);
}
}
static void loadAndCompileShader(GLuint shader, const char *text)
{
GLint stat;
glShaderSource(shader, 1, (const GLchar **) &text, NULL);
glCompileShader(shader);
glGetShaderiv(shader, GL_COMPILE_STATUS, &stat);
if (!stat) {
GLchar log[1000];
GLsizei len;
glGetShaderInfoLog(shader, 1000, &len, log);
fprintf(stderr, "Problem compiling shader: %s\n", log);
exit(1);
}
else {
printf("Shader compiled OK\n");
}
}
static void readShader(GLuint shader, const char *filename)
{
const int max = 100*1000;
int n;
char *buffer = (char*) malloc(max);
FILE *f = fopen(filename, "r");
if (!f) {
fprintf(stderr, "Unable to open shader file %s\n", filename);
exit(1);
}
n = fread(buffer, 1, max, f);
printf("Read %d bytes from shader file %s\n", n, filename);
if (n > 0) {
buffer[n] = 0;
loadAndCompileShader(shader, buffer);
}
fclose(f);
free(buffer);
}
static void
checkLink(GLuint prog)
{
GLint stat;
glGetProgramiv(prog, GL_LINK_STATUS, &stat);
if (!stat) {
GLchar log[1000];
GLsizei len;
glGetProgramInfoLog(prog, 1000, &len, log);
fprintf(stderr, "Linker error:\n%s\n", log);
}
else {
fprintf(stderr, "Link success!\n");
}
}
static void fillConvolution(GLint *k,
GLfloat *scale,
GLfloat *color)
{
switch(filter) {
case GAUSSIAN_BLUR:
k[0] = 1; k[1] = 2; k[2] = 1;
k[3] = 2; k[4] = 4; k[5] = 2;
k[6] = 1; k[7] = 2; k[8] = 1;
*scale = 1./16.;
break;
case SHARPEN:
k[0] = 0; k[1] = -2; k[2] = 0;
k[3] = -2; k[4] = 11; k[5] = -2;
k[6] = 0; k[7] = -2; k[8] = 0;
*scale = 1./3.;
break;
case MEAN_REMOVAL:
k[0] = -1; k[1] = -1; k[2] = -1;
k[3] = -1; k[4] = 9; k[5] = -1;
k[6] = -1; k[7] = -1; k[8] = -1;
*scale = 1./1.;
break;
case EMBOSS:
k[0] = -1; k[1] = 0; k[2] = -1;
k[3] = 0; k[4] = 4; k[5] = 0;
k[6] = -1; k[7] = 0; k[8] = -1;
*scale = 1./1.;
color[0] = 0.5;
color[1] = 0.5;
color[2] = 0.5;
color[3] = 0.5;
break;
case NO_FILTER:
k[0] = 0; k[1] = 0; k[2] = 0;
k[3] = 0; k[4] = 1; k[5] = 0;
k[6] = 0; k[7] = 0; k[8] = 0;
*scale = 1.;
break;
default:
assert(!"Unhandled switch value");
}
}
static void setupConvolution()
{
GLint *kernel = (GLint*)malloc(sizeof(GLint) * 9);
GLfloat scale;
GLfloat *vecKer = (GLfloat*)malloc(sizeof(GLfloat) * 9 * 4);
GLuint loc;
GLuint i;
GLfloat baseColor[4];
baseColor[0] = 0;
baseColor[1] = 0;
baseColor[2] = 0;
baseColor[3] = 0;
fillConvolution(kernel, &scale, baseColor);
/*vector of 4*/
for (i = 0; i < 9; ++i) {
vecKer[i*4 + 0] = kernel[i];
vecKer[i*4 + 1] = kernel[i];
vecKer[i*4 + 2] = kernel[i];
vecKer[i*4 + 3] = kernel[i];
}
loc = glGetUniformLocationARB(program, "KernelValue");
glUniform4fv(loc, 9, vecKer);
loc = glGetUniformLocationARB(program, "ScaleFactor");
glUniform4f(loc, scale, scale, scale, scale);
loc = glGetUniformLocationARB(program, "BaseColor");
glUniform4f(loc, baseColor[0], baseColor[1],
baseColor[2], baseColor[3]);
free(vecKer);
free(kernel);
}
static void createProgram(const char *vertProgFile,
const char *fragProgFile)
{
GLuint fragShader = 0, vertShader = 0;
program = glCreateProgram();
if (vertProgFile) {
vertShader = glCreateShader(GL_VERTEX_SHADER);
readShader(vertShader, vertProgFile);
glAttachShader(program, vertShader);
}
if (fragProgFile) {
fragShader = glCreateShader(GL_FRAGMENT_SHADER);
readShader(fragShader, fragProgFile);
glAttachShader(program, fragShader);
}
glLinkProgram(program);
checkLink(program);
glUseProgram(program);
assert(glIsProgram(program));
assert(glIsShader(fragShader));
assert(glIsShader(vertShader));
checkError(__LINE__);
{/*texture*/
GLuint texLoc = glGetUniformLocationARB(program, "srcTex");
glUniform1iARB(texLoc, 0);
}
{/*setup offsets */
float offsets[] = { 1.0 / texture.width, 1.0 / texture.height,
0.0 , 1.0 / texture.height,
-1.0 / texture.width, 1.0 / texture.height,
1.0 / texture.width, 0.0,
0.0 , 0.0,
-1.0 / texture.width, 0.0,
1.0 / texture.width, -1.0 / texture.height,
0.0 , -1.0 / texture.height,
-1.0 / texture.width, -1.0 / texture.height };
GLuint offsetLoc = glGetUniformLocationARB(program, "Offset");
glUniform2fv(offsetLoc, 9, offsets);
}
setupConvolution();
checkError(__LINE__);
}
static void readTexture(const char *filename)
{
GLubyte *data;
texture.x = 0;
texture.y = 0;
glGenTextures(1, &texture.id);
glBindTexture(GL_TEXTURE_2D, texture.id);
glTexParameteri(GL_TEXTURE_2D,
GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,
GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
data = LoadRGBImage(filename, &texture.width, &texture.height,
&texture.format);
if (!data) {
printf("Error: couldn't load texture image '%s'\n", filename);
exit(1);
}
printf("Texture %s (%d x %d)\n",
filename, texture.width, texture.height);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
texture.width, texture.height, 0, texture.format,
GL_UNSIGNED_BYTE, data);
}
static void menuSelected(int entry)
{
switch (entry) {
case QUIT:
exit(0);
break;
default:
filter = (enum Filter)entry;
}
setupConvolution();
glutPostRedisplay();
}
static void menuInit()
{
menuId = glutCreateMenu(menuSelected);
glutAddMenuEntry("Gaussian blur", GAUSSIAN_BLUR);
glutAddMenuEntry("Sharpen", SHARPEN);
glutAddMenuEntry("Mean removal", MEAN_REMOVAL);
glutAddMenuEntry("Emboss", EMBOSS);
glutAddMenuEntry("None", NO_FILTER);
glutAddMenuEntry("Quit", QUIT);
glutAttachMenu(GLUT_RIGHT_BUTTON);
}
static void init()
{
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));
menuInit();
readTexture(textureLocation);
createProgram("convolution.vert", "convolution.frag");
glEnable(GL_TEXTURE_2D);
glClearColor(1.0, 1.0, 1.0, 1.0);
/*glShadeModel(GL_SMOOTH);*/
glShadeModel(GL_FLAT);
}
static void reshape(int width, int height)
{
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
box.minx = 0;
box.maxx = width;
box.miny = 0;
box.maxy = height;
box.minz = 0;
box.maxz = 1;
glOrtho(box.minx, box.maxx, box.miny, box.maxy, -999999, 999999);
glMatrixMode(GL_MODELVIEW);
}
static void keyPress(unsigned char key, int x, int y)
{
switch(key) {
case 27:
exit(0);
default:
return;
}
glutPostRedisplay();
}
static void
special(int k, int x, int y)
{
switch (k) {
case GLUT_KEY_UP:
viewRotx += 2.0;
break;
case GLUT_KEY_DOWN:
viewRotx -= 2.0;
break;
case GLUT_KEY_LEFT:
viewRoty += 2.0;
break;
case GLUT_KEY_RIGHT:
viewRoty -= 2.0;
break;
default:
return;
}
glutPostRedisplay();
}
static void draw()
{
GLfloat center[2];
GLfloat anchor[2];
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glPushMatrix();
center[0] = box.maxx/2;
center[1] = box.maxy/2;
anchor[0] = center[0] - texture.width/2;
anchor[1] = center[1] - texture.height/2;
glTranslatef(center[0], center[1], 0);
glRotatef(viewRotx, 1.0, 0.0, 0.0);
glRotatef(viewRoty, 0.0, 1.0, 0.0);
glRotatef(viewRotz, 0.0, 0.0, 1.0);
glTranslatef(-center[0], -center[1], 0);
glTranslatef(anchor[0], anchor[1], 0);
glBegin(GL_TRIANGLE_STRIP);
{
glColor3f(1., 0., 0.);
glTexCoord2f(0, 0);
glVertex3f(0, 0, 0);
glColor3f(0., 1., 0.);
glTexCoord2f(0, 1.0);
glVertex3f(0, texture.height, 0);
glColor3f(1., 0., 0.);
glTexCoord2f(1.0, 0);
glVertex3f(texture.width, 0, 0);
glColor3f(0., 1., 0.);
glTexCoord2f(1, 1);
glVertex3f(texture.width, texture.height, 0);
}
glEnd();
glPopMatrix();
glFlush();
glutSwapBuffers();
}
int main(int argc, char **argv)
{
glutInit(&argc, argv);
glutInitWindowPosition(0, 0);
glutInitWindowSize(400, 400);
glutInitDisplayMode(GLUT_RGB | GLUT_ALPHA | GLUT_DOUBLE);
if (!glutCreateWindow("Image Convolutions")) {
fprintf(stderr, "Couldn't create window!\n");
exit(1);
}
init();
glutReshapeFunc(reshape);
glutKeyboardFunc(keyPress);
glutSpecialFunc(special);
glutDisplayFunc(draw);
glutMainLoop();
return 0;
}
+3 -1
View File
@@ -48,6 +48,7 @@ static GLfloat TexXrot = 0, TexYrot = 0;
static GLfloat Xrot = 20.0, Yrot = 20.0, Zrot = 0.0;
static GLfloat EyeDist = 10;
static GLboolean Anim = GL_TRUE;
static int win = 0;
struct uniform_info {
@@ -177,6 +178,7 @@ key(unsigned char k, int x, int y)
EyeDist = 90;
break;
case 27:
glutDestroyWindow(win);
exit(0);
}
glutPostRedisplay();
@@ -554,7 +556,7 @@ main(int argc, char *argv[])
glutInit(&argc, argv);
glutInitWindowSize(500, 400);
glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
glutCreateWindow(Demo);
win = glutCreateWindow(Demo);
glutReshapeFunc(Reshape);
glutKeyboardFunc(key);
glutSpecialFunc(specialkey);
+6
View File
@@ -0,0 +1,6 @@
manytex
miniglxsample
miniglxtest
sample_server
sample_server2
texline
+8
View File
@@ -0,0 +1,8 @@
osdemo
osdemo16
osdemo32
ostest1
readtex.c
readtex.h
showbuffer.c
showbuffer.h
+17 -17
View File
@@ -1,24 +1,41 @@
.cvsignore
accum
anywin
bdemo
binfo
bitmap1
bitmap2
blendeq
blendxor
bugger
copy
cursor
demo
depth
eval
ffset
fog
font
font
incopy
line
logo
lthreads
lxdemo
lxgears
lxheads
lxinfo
lxpixmap
nurb
oglinfo
olympic
overlay
pend
point
prim
quad
readtex.c
readtex.h
select
shape
sphere
@@ -28,20 +45,3 @@ stretch
texture
tri
wave
bugger
pend
lthreads
lxdemo
lxgears
lxheads
lxinfo
lxpixmap
anywin
ffset
bdemo
binfo
incopy
demo
font
readtex.c
readtex.h
+3
View File
@@ -0,0 +1,3 @@
cltest
sotest
vstest
+31 -2
View File
@@ -1,48 +1,75 @@
.cvsignore
getproclist.h
afsmultiarb
antialias
arbfpspec
arbfptest1
arbfptexture
arbfptrig
arbnpot
arbnpot-mipmap
arbvptest1
arbvptest3
arbvptorus
arbvpwarpmesh
arraytexture
blendminmax
blendsquare
bufferobj
bug_3050
bug_3101
bug_3195
calibrate_rast
copypixrate
crossbar
cva
dinoshade
drawbuffers
extfuncs.h
fbotest1
fbotest2
fbotexture
fillrate
floattex
fog
fogcoord
fptest1
fptexture
getprocaddress
getproclist.h
interleave
invert
jkrahntest
manytex
minmag
mipmap_limits
mipmap_view
multipal
no_s3tc
packedpixels
pbo
prog_parameter
projtex
random
readrate
readtex.c
readtex.h
seccolor
sharedtex
stencil_wrap
stencilwrap
stencil_wrap
subtex
subtexrate
tex1d
texcmp
texcompress2
texfilt
texgenmix
texline
texobjshare
texrect
texwrap
vao-01
vao-02
vparray
vptest1
vptest2
@@ -51,4 +78,6 @@ vptorus
vpwarpmesh
yuvrect
yuvsquare
zcomp
zdrawpix
zreaddraw
+1
View File
@@ -0,0 +1 @@
gltrace.cc
+4
View File
@@ -14,6 +14,7 @@ fs-tri
line
line-clip
line-cull
line-smooth
line-stipple-wide
line-userclip
line-userclip-clip
@@ -33,6 +34,7 @@ point-clip
point-param
point-sprite
point-wide
point-wide-smooth
poly
poly-flat
poly-unfilled
@@ -77,6 +79,7 @@ tri-flat
tri-flat-clip
tri-fog
tri-mask-tri
tri-orig
tri-query
tri-scissor-tri
tri-stencil
@@ -84,6 +87,7 @@ tri-tex-3d
tri-tri
tri-unfilled
tri-unfilled-clip
tri-unfilled-edgeflag
tri-unfilled-smooth
tri-unfilled-userclip
tri-unfilled-userclip-stip
+5 -1
View File
@@ -31,6 +31,7 @@ static GLenum Target = GL_TEXTURE_2D;
static GLenum Filter = GL_NEAREST;
GLenum doubleBuffer;
static float Rot = 0;
static int win = 0;
static void Init(void)
{
@@ -88,6 +89,7 @@ static void Reshape(int width, int height)
glFrustum(-1, 1, -1, 1, 10, 20);
#endif
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTranslatef(0, 0, -15);
}
@@ -101,6 +103,7 @@ static void Key(unsigned char key, int x, int y)
Rot -= 10.0;
break;
case 27:
glutDestroyWindow(win);
exit(0);
default:
return;
@@ -170,7 +173,8 @@ int main(int argc, char **argv)
type |= (doubleBuffer) ? GLUT_DOUBLE : GLUT_SINGLE;
glutInitDisplayMode(type);
if (glutCreateWindow("First Tri") == GL_FALSE) {
win = glutCreateWindow("First Tri");
if (!win) {
exit(1);
}
+1
View File
@@ -0,0 +1 @@
vp-tris
+1
View File
@@ -13,6 +13,7 @@ offset
overlay
pbdemo
pbinfo
sharedtex
texture_from_pixmap
wincopy
xdemo
@@ -713,6 +713,11 @@ static void
aaline_destroy(struct draw_stage *stage)
{
struct aaline_stage *aaline = aaline_stage(stage);
uint i;
for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
pipe_texture_reference(&aaline->state.texture[i], NULL);
}
if (aaline->sampler_cso)
aaline->pipe->delete_sampler_state(aaline->pipe, aaline->sampler_cso);
@@ -836,6 +841,9 @@ aaline_set_sampler_textures(struct pipe_context *pipe,
for (i = 0; i < num; i++) {
pipe_texture_reference(&aaline->state.texture[i], texture[i]);
}
for ( ; i < PIPE_MAX_SAMPLERS; i++) {
pipe_texture_reference(&aaline->state.texture[i], NULL);
}
aaline->num_textures = num;
/* pass-through */
@@ -559,6 +559,11 @@ static void
pstip_destroy(struct draw_stage *stage)
{
struct pstip_stage *pstip = pstip_stage(stage);
uint i;
for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
pipe_texture_reference(&pstip->state.textures[i], NULL);
}
pstip->pipe->delete_sampler_state(pstip->pipe, pstip->sampler_cso);
+7 -4
View File
@@ -39,6 +39,7 @@
#include "draw_vs.h"
#include "tgsi/util/tgsi_parse.h"
#include "tgsi/util/tgsi_scan.h"
struct exec_vertex_shader {
@@ -165,21 +166,23 @@ draw_create_vs_exec(struct draw_context *draw,
const struct pipe_shader_state *state)
{
struct exec_vertex_shader *vs = CALLOC_STRUCT( exec_vertex_shader );
uint nt = tgsi_num_tokens(state->tokens);
if (vs == NULL)
return NULL;
/* we make a private copy of the tokens */
vs->base.state.tokens = mem_dup(state->tokens, nt * sizeof(state->tokens[0]));
tgsi_scan_shader(state->tokens, &vs->base.info);
vs->base.state.tokens = tgsi_dup_tokens(state->tokens);
if (!vs->base.state.tokens) {
FREE(vs);
return NULL;
}
tgsi_scan_shader(state->tokens, &vs->base.info);
vs->base.prepare = vs_exec_prepare;
vs->base.run_linear = vs_exec_run_linear;
vs->base.delete = vs_exec_delete;
vs->machine = &draw->machine;
return &vs->base;
}
+15 -50
View File
@@ -1,8 +1,8 @@
/**************************************************************************
*
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
@@ -10,11 +10,11 @@
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
@@ -22,7 +22,7 @@
* 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.
*
*
**************************************************************************/
/*
@@ -72,47 +72,9 @@ vs_llvm_run_linear( struct draw_vertex_shader *base,
struct draw_llvm_vertex_shader *shader =
(struct draw_llvm_vertex_shader *)base;
struct tgsi_exec_machine *machine = shader->machine;
unsigned int i, j;
unsigned slot;
for (i = 0; i < count; i += MAX_TGSI_VERTICES) {
unsigned int max_vertices = MIN2(MAX_TGSI_VERTICES, count - i);
/* Swizzle inputs.
*/
for (j = 0; j < max_vertices; j++) {
for (slot = 0; slot < base->info.num_inputs; slot++) {
machine->Inputs[slot].xyzw[0].f[j] = input[slot][0];
machine->Inputs[slot].xyzw[1].f[j] = input[slot][1];
machine->Inputs[slot].xyzw[2].f[j] = input[slot][2];
machine->Inputs[slot].xyzw[3].f[j] = input[slot][3];
}
input = (const float (*)[4])((const char *)input + input_stride);
}
/* run shader */
gallivm_cpu_vs_exec(shader->llvm_prog,
machine->Inputs,
machine->Outputs,
(float (*)[4]) constants,
machine->Temps);
/* Unswizzle all output results
*/
for (j = 0; j < max_vertices; j++) {
for (slot = 0; slot < base->info.num_outputs; slot++) {
output[slot][0] = machine->Outputs[slot].xyzw[0].f[j];
output[slot][1] = machine->Outputs[slot].xyzw[1].f[j];
output[slot][2] = machine->Outputs[slot].xyzw[2].f[j];
output[slot][3] = machine->Outputs[slot].xyzw[3].f[j];
}
output = (float (*)[4])((char *)output + output_stride);
}
}
gallivm_cpu_vs_exec(shader->llvm_prog, shader->machine,
input, base->info.num_inputs, output, base->info.num_outputs,
constants, count, input_stride, output_stride);
}
@@ -120,7 +82,7 @@ vs_llvm_run_linear( struct draw_vertex_shader *base,
static void
vs_llvm_delete( struct draw_vertex_shader *base )
{
struct draw_llvm_vertex_shader *shader =
struct draw_llvm_vertex_shader *shader =
(struct draw_llvm_vertex_shader *)base;
/* Do something to free compiled shader:
@@ -138,14 +100,17 @@ draw_create_vs_llvm(struct draw_context *draw,
const struct pipe_shader_state *templ)
{
struct draw_llvm_vertex_shader *vs;
uint nt = tgsi_num_tokens(templ->tokens);
vs = CALLOC_STRUCT( draw_llvm_vertex_shader );
if (vs == NULL)
if (vs == NULL)
return NULL;
/* we make a private copy of the tokens */
vs->base.state.tokens = mem_dup(templ->tokens, nt * sizeof(templ->tokens[0]));
vs->base.state.tokens = tgsi_dup_tokens(templ->tokens);
if (!vs->base.state.tokens) {
FREE(vs);
return NULL;
}
tgsi_scan_shader(vs->base.state.tokens, &vs->base.info);
+6 -2
View File
@@ -188,7 +188,6 @@ draw_create_vs_sse(struct draw_context *draw,
const struct pipe_shader_state *templ)
{
struct draw_sse_vertex_shader *vs;
uint nt = tgsi_num_tokens(templ->tokens);
if (!rtasm_cpu_has_sse2())
return NULL;
@@ -198,7 +197,9 @@ draw_create_vs_sse(struct draw_context *draw,
return NULL;
/* we make a private copy of the tokens */
vs->base.state.tokens = mem_dup(templ->tokens, nt * sizeof(templ->tokens[0]));
vs->base.state.tokens = tgsi_dup_tokens(templ->tokens);
if (!vs->base.state.tokens)
goto fail;
tgsi_scan_shader(templ->tokens, &vs->base.info);
@@ -214,6 +215,9 @@ draw_create_vs_sse(struct draw_context *draw,
goto fail;
vs->func = (codegen_function) x86_get_func( &vs->sse2_program );
if (!vs->func) {
goto fail;
}
return &vs->base;
+3 -6
View File
@@ -288,10 +288,7 @@ void gallivm_ir_fill_from_tgsi(struct gallivm_ir *ir,
std::cout << "Creating llvm from: " <<std::endl;
tgsi_dump(tokens, 0);
llvm::Module *mod = tgsi_to_llvmir(ir, tokens);
//llvm::Module *mod = tgsi_to_llvm(ir, tokens);
ir->module = mod;
gallivm_ir_dump(ir, 0);
}
@@ -306,11 +303,11 @@ struct gallivm_prog * gallivm_ir_compile(struct gallivm_ir *ir)
{
struct gallivm_prog *prog =
(struct gallivm_prog *)calloc(1, sizeof(struct gallivm_prog));
std::cout << "Before optimizations:"<<std::endl;
ir->module->dump();
std::cout<<"-------------------------------"<<std::endl;
PassManager veri;
veri.add(createVerifierPass());
veri.run(*ir->module);
@@ -318,7 +315,7 @@ struct gallivm_prog * gallivm_ir_compile(struct gallivm_ir *ir)
prog->num_consts = ir->num_consts;
memcpy(prog->interpolators, ir->interpolators, sizeof(prog->interpolators));
prog->num_interp = ir->num_interp;
/* Run optimization passes over it */
PassManager passes;
passes.add(new TargetData(mod));
+9 -4
View File
@@ -90,10 +90,15 @@ void gallivm_prog_dump(struct gallivm_prog *prog, const char *file_prefix);
struct gallivm_cpu_engine *gallivm_cpu_engine_create(struct gallivm_prog *prog);
struct gallivm_cpu_engine *gallivm_global_cpu_engine();
int gallivm_cpu_vs_exec(struct gallivm_prog *prog,
struct tgsi_exec_vector *inputs,
struct tgsi_exec_vector *dests,
float (*consts)[4],
struct tgsi_exec_vector *temps);
struct tgsi_exec_machine *machine,
const float (*input)[4],
unsigned num_inputs,
float (*output)[4],
unsigned num_outputs,
const float (*constants)[4],
unsigned count,
unsigned input_stride,
unsigned output_stride);
int gallivm_cpu_fs_exec(struct gallivm_prog *prog,
float x, float y,
float (*dests)[PIPE_MAX_SHADER_INPUTS][4],
+133 -134
View File
@@ -1,141 +1,140 @@
static const unsigned char llvm_builtins_data[] = {
0x42,0x43,0xc0,0xde,0x21,0x0c,0x00,0x00,0x2b,0x02,0x00,0x00,0x01,0x10,0x00,0x00,
0x42,0x43,0xc0,0xde,0x21,0x0c,0x00,0x00,0x29,0x02,0x00,0x00,0x01,0x10,0x00,0x00,
0x10,0x00,0x00,0x00,0x07,0x81,0x23,0x91,0x41,0xc8,0x04,0x49,0x06,0x10,0x32,0x39,
0x92,0x01,0x84,0x0c,0x25,0x05,0x08,0x19,0x1e,0x04,0x8b,0x62,0x80,0x14,0x45,0x02,
0x42,0x92,0x0b,0x42,0xa4,0x10,0x32,0x14,0x38,0x08,0x18,0x49,0x0a,0x32,0x44,0x24,
0x48,0x0a,0x90,0x21,0x23,0x44,0x72,0x80,0x8c,0x14,0x21,0x86,0x0a,0x8a,0x0a,0x64,
0x0c,0x1f,0x00,0x00,0x49,0x18,0x00,0x00,0x02,0x00,0x00,0x00,0x0b,0x04,0x00,0x0c,
0x00,0x00,0x00,0x00,0x51,0x20,0x00,0x00,0x13,0x00,0x00,0x00,0x32,0x22,0x48,0x09,
0x00,0x00,0x00,0x00,0x51,0x20,0x00,0x00,0x12,0x00,0x00,0x00,0x32,0x22,0x48,0x09,
0x20,0x65,0x82,0x84,0x00,0x26,0x45,0x48,0x05,0x09,0x26,0x45,0xc6,0x05,0x42,0x52,
0x26,0x08,0xb0,0x19,0x80,0x61,0x04,0x02,0x98,0x23,0x00,0x83,0x21,0x80,0x39,0x82,
0x60,0x0a,0x80,0x2e,0xd5,0x61,0x04,0x42,0x20,0x49,0x90,0x22,0x4d,0xa2,0x73,0x04,
0x08,0xb9,0x32,0x00,0x00,0x8a,0x10,0xc2,0x65,0xb8,0x42,0x84,0x10,0x42,0x0d,0x44,
0x11,0x00,0x18,0x01,0x28,0x82,0x08,0x00,0x13,0xa2,0x74,0xb0,0x03,0x3c,0xb0,0x83,
0x36,0x80,0x87,0x71,0x68,0x03,0x76,0x48,0x07,0x77,0xa8,0x07,0x7c,0x68,0x83,0x73,
0x70,0x87,0x7a,0xd8,0x70,0x0f,0xe5,0xd0,0x06,0xf0,0xa0,0x07,0x73,0x20,0x07,0x7a,
0x30,0x07,0x72,0xa0,0x07,0x73,0x20,0x07,0x6d,0x90,0x0e,0x71,0xa0,0x07,0x78,0xa0,
0x07,0x78,0xd0,0x06,0xe9,0x80,0x07,0x7a,0x80,0x07,0x7a,0x80,0x07,0x6d,0x90,0x0e,
0x71,0x60,0x07,0x7a,0x10,0x07,0x76,0xa0,0x07,0x71,0x60,0x07,0x6d,0x90,0x0e,0x73,
0x20,0x07,0x7a,0x30,0x07,0x72,0xa0,0x07,0x73,0x20,0x07,0x6d,0x90,0x0e,0x76,0x40,
0x07,0x7a,0x30,0x07,0x72,0xa0,0x07,0x76,0x40,0x07,0x6d,0x60,0x0e,0x73,0x20,0x07,
0x7a,0x30,0x07,0x72,0xa0,0x07,0x73,0x20,0x07,0x6d,0x60,0x0e,0x76,0x40,0x07,0x7a,
0x30,0x07,0x72,0xa0,0x07,0x76,0x40,0x07,0x6d,0x60,0x0f,0x76,0x40,0x07,0x7a,0x60,
0x07,0x74,0xa0,0x07,0x76,0x40,0x07,0x6d,0x60,0x0f,0x71,0x20,0x07,0x78,0xa0,0x07,
0x71,0x20,0x07,0x78,0xa0,0x07,0x71,0x20,0x07,0x78,0xd0,0x06,0xe1,0x00,0x07,0x7a,
0x00,0x07,0x7a,0x60,0x07,0x74,0xd0,0x06,0xe6,0x80,0x07,0x70,0xa0,0x07,0x71,0x20,
0x07,0x78,0xa0,0x07,0x71,0x20,0x07,0x78,0xa0,0xf3,0x40,0x88,0x04,0x32,0x32,0x02,
0x04,0x60,0x76,0xc6,0xfc,0x6c,0x48,0xa2,0x00,0x40,0x00,0x00,0x00,0x00,0x0c,0x49,
0x14,0x20,0x00,0x00,0x00,0x00,0x80,0x21,0xc9,0x02,0x00,0x01,0x00,0x00,0x00,0x30,
0x24,0x61,0x00,0x20,0x08,0x00,0x00,0x00,0x86,0x24,0x0b,0x00,0x04,0x00,0x00,0x00,
0xc0,0x90,0xa4,0x01,0x02,0x00,0x00,0x00,0x00,0x18,0x92,0x1c,0x40,0x00,0x00,0x00,
0x00,0x00,0x43,0x92,0x05,0x00,0x02,0x00,0x00,0x00,0x60,0x48,0x72,0x00,0x01,0x00,
0x00,0x00,0x00,0x0c,0x49,0x16,0x00,0x08,0x00,0x00,0x00,0x80,0x21,0x89,0x01,0x00,
0x41,0x00,0x00,0x00,0x90,0x05,0x02,0x00,0x10,0x00,0x00,0x00,0x32,0x1e,0x98,0x10,
0x19,0x11,0x4c,0x90,0x8c,0x09,0x26,0x47,0xc6,0x04,0x43,0x92,0x8a,0x59,0x8b,0x43,
0x50,0xd2,0x09,0x02,0x81,0xd2,0x73,0x50,0xc9,0x0c,0x2a,0x99,0x41,0x25,0x33,0xa8,
0x64,0x56,0x28,0x66,0x2d,0x0e,0x41,0xcf,0x2a,0x15,0x04,0x4a,0xcf,0x41,0x25,0x33,
0xa8,0x64,0x06,0x95,0xcc,0xa0,0x92,0x59,0x01,0x00,0x00,0x00,0x53,0x82,0x26,0x0c,
0x04,0x00,0x00,0x00,0x22,0x00,0x00,0x00,0x13,0x04,0x41,0x2c,0x10,0x00,0x00,0x00,
0x05,0x00,0x00,0x00,0x04,0xc6,0x08,0x40,0x10,0x04,0xe1,0x70,0x18,0x23,0x00,0x41,
0x10,0x84,0xc3,0x60,0x04,0x00,0x00,0x00,0x93,0x0c,0xce,0x43,0x4c,0x31,0x3c,0x8e,
0x34,0xc9,0x30,0x41,0xc2,0x14,0x03,0x34,0x51,0x93,0x0c,0x4d,0x44,0x4c,0x31,0x44,
0x8d,0x35,0x56,0x01,0x04,0xc3,0x55,0x21,0x16,0x0e,0x04,0x00,0x0f,0x00,0x00,0x00,
0x46,0x41,0x08,0xcc,0x73,0x9b,0x05,0x21,0x30,0xcf,0x6e,0x18,0x84,0x00,0x2c,0x8b,
0x35,0x04,0x80,0x39,0x04,0x81,0x5d,0x20,0x80,0x0f,0x0c,0x43,0xe4,0xd3,0x36,0x81,
0x04,0x3e,0x30,0x0c,0x91,0x4f,0x5b,0x05,0x12,0xf8,0xc0,0x30,0x44,0x7e,0x7d,0x00,
0x05,0xd1,0x4c,0x11,0x66,0x12,0x83,0xc0,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x61,0x20,0x00,0x00,0x2a,0x00,0x00,0x00,0x13,0x04,0x43,0x2c,0x10,0x00,0x00,0x00,
0x08,0x00,0x00,0x00,0x24,0x8a,0xa0,0x0c,0x46,0x00,0x4a,0x80,0xc2,0x1c,0x84,0x55,
0x55,0xd6,0x1c,0x84,0x45,0x51,0x16,0x81,0x19,0x80,0x11,0x80,0x31,0x02,0x10,0x04,
0x41,0xfc,0x03,0x00,0x63,0x08,0x0d,0x34,0xc9,0x70,0x55,0xc2,0x2c,0x43,0x20,0x60,
0x73,0x0c,0xd3,0x15,0x8d,0x21,0x34,0xd1,0x18,0x42,0xf3,0x8c,0x55,0x00,0x81,0xa0,
0x6d,0x73,0x0c,0x19,0xe7,0x60,0x87,0x52,0x38,0x10,0x00,0x00,0x13,0x00,0x00,0x00,
0x17,0x60,0x20,0xc5,0x74,0x10,0x8d,0x65,0x14,0x13,0xf3,0xd4,0xb4,0x6d,0x14,0x13,
0xf3,0xd4,0xb8,0x69,0x14,0x13,0xf3,0xd4,0xb6,0x75,0x14,0x13,0xf3,0xd4,0xba,0x35,
0x0c,0x13,0xf3,0x9c,0x80,0xe4,0x36,0x48,0x81,0x10,0xc3,0x4a,0x4c,0x54,0xd4,0x6c,
0x8b,0x23,0x28,0x76,0x41,0x4c,0xcc,0xa3,0x1b,0x07,0x21,0x00,0xcb,0x72,0x00,0x05,
0xd1,0x4c,0x11,0x66,0x18,0x83,0xc0,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x61,0x20,0x00,0x00,0x82,0x00,0x00,0x00,0x13,0x04,0x47,0x2c,0x10,0x00,0x00,0x00,
0x08,0x00,0x00,0x00,0x24,0x46,0x00,0x8a,0xa0,0x0c,0x4a,0xa0,0x14,0x8a,0xa1,0x1c,
0x68,0x8c,0x00,0x10,0x9a,0x83,0x80,0xa8,0x48,0x9a,0x83,0x80,0xa6,0x4a,0x9a,0x83,
0x80,0xa6,0xc8,0x02,0x63,0x08,0x0d,0x64,0xdb,0xc0,0x49,0x06,0xee,0x22,0xc6,0x10,
0x9a,0xc9,0xbc,0x81,0x93,0x0c,0xdf,0x45,0x4c,0x31,0x38,0x4f,0x37,0xcb,0x10,0x08,
0x60,0x30,0xc8,0x10,0x06,0x0e,0x36,0x86,0xd0,0x44,0x36,0x06,0x03,0x27,0x19,0xc8,
0xe0,0x22,0x66,0x19,0x06,0xa2,0x0c,0x06,0x19,0xc2,0xe0,0xc1,0xc6,0x10,0x9a,0xc8,
0xce,0x60,0xe0,0x24,0x03,0x1a,0x5c,0xc4,0x2c,0xc3,0x40,0xa4,0xc1,0x40,0x45,0x20,
0x06,0x81,0x19,0x08,0x83,0x0c,0x6a,0xe0,0x64,0x63,0x08,0x8d,0x64,0x6c,0x30,0x70,
0x92,0xa1,0x0d,0x2e,0x62,0x96,0xa1,0x30,0xdc,0x60,0xa0,0x22,0x10,0x83,0xc0,0x0c,
0x84,0x41,0x86,0x37,0x78,0xb2,0x31,0x84,0x46,0xb2,0x38,0x18,0x38,0xc9,0x20,0x07,
0x17,0x31,0xcb,0x50,0x18,0x73,0x30,0x50,0x11,0xac,0xc1,0x00,0x07,0xc4,0x20,0x03,
0x1d,0x38,0x1a,0xd6,0xc1,0x40,0x45,0xb0,0x06,0x03,0x1c,0x10,0x83,0x0c,0x76,0xf0,
0x68,0x78,0x07,0xe1,0x40,0x00,0x00,0x00,0x4c,0x00,0x00,0x00,0x56,0x62,0x08,0xcc,
0x63,0xef,0x3a,0xa9,0x00,0x19,0x7b,0x73,0x23,0x73,0xf9,0xa1,0x91,0x31,0x98,0x62,
0x62,0x9e,0x7b,0xb7,0x06,0x62,0x62,0x1e,0xda,0x1c,0x88,0x89,0x79,0x6a,0x7b,0x20,
0x26,0xe6,0xb1,0x6d,0x83,0x98,0x98,0xe7,0x36,0x92,0x43,0x70,0x9a,0xca,0xd6,0x73,
0xa3,0x79,0x26,0xe6,0xb9,0x77,0x3f,0x22,0x0c,0x9b,0x21,0x18,0x9f,0xb6,0x90,0x64,
0x62,0x9e,0xda,0x9f,0x98,0xc7,0x36,0x9b,0x67,0x62,0x9e,0x7b,0xf7,0x23,0xc2,0xb0,
0x19,0x82,0xf1,0x6b,0x53,0x79,0x26,0xe6,0xb1,0x6f,0x3f,0x22,0x0c,0x9b,0x21,0x18,
0x9f,0xb6,0x98,0x62,0x62,0x9e,0xbb,0xb7,0x97,0x67,0x62,0x1e,0xfb,0xf6,0x23,0xc2,
0xb0,0x19,0x82,0xf1,0x6b,0x43,0x31,0x04,0xa7,0xa9,0x6c,0xdd,0x66,0x0a,0x81,0x79,
0xf0,0xfa,0x08,0x16,0xc1,0x69,0x06,0x5f,0x70,0x9a,0xe9,0xc6,0x49,0x01,0xc8,0xd8,
0x9b,0x1b,0x99,0xcb,0x4f,0x0c,0x8d,0xad,0x18,0x13,0xf3,0xdc,0x3b,0x6f,0x35,0xc7,
0xc4,0x3c,0x79,0x5d,0xdf,0x06,0x52,0x08,0xcc,0x53,0xdf,0x26,0x62,0x4c,0xcc,0x63,
0xdf,0xb7,0xb9,0x1c,0x02,0xf3,0xe0,0x75,0x5d,0x5b,0xc7,0x20,0x30,0x8f,0x79,0x14,
0x13,0xf3,0xd4,0xf5,0x19,0x2c,0x82,0xd3,0x0c,0xbe,0xe0,0x34,0x13,0xce,0x5b,0x0b,
0x22,0x38,0x4d,0x85,0xd3,0x35,0x6d,0x37,0xc5,0xc4,0x3c,0x79,0x4d,0x1a,0x40,0xc6,
0xde,0xdc,0xc8,0x5c,0x7e,0x64,0x70,0x8c,0x83,0x10,0x9c,0xa6,0xb2,0x94,0x42,0x60,
0x1e,0x7b,0x37,0x19,0x43,0x70,0x9a,0x0a,0xa7,0xcd,0xa4,0x98,0x98,0xc7,0xbe,0x8d,
0xc5,0x98,0x98,0xe7,0xee,0x7b,0x3b,0x29,0x26,0xe6,0xb1,0xf3,0x13,0x58,0x04,0xa7,
0x19,0x7c,0xc1,0x69,0x26,0x9b,0xb6,0x0f,0x43,0x70,0x9a,0xaa,0xb6,0x6d,0xc4,0x98,
0x98,0xc7,0xce,0xf1,0x03,0x28,0x88,0x66,0x8a,0x30,0x00,0x00,0x00,0x00,0x00,0x00,
0x61,0x20,0x00,0x00,0x4a,0x00,0x00,0x00,0x13,0x04,0x41,0x2c,0x10,0x00,0x00,0x00,
0x07,0x00,0x00,0x00,0x24,0xca,0x60,0x04,0xa0,0x04,0x8a,0x80,0xc2,0x0c,0x00,0xbd,
0x61,0x8c,0x04,0x10,0x1e,0xe1,0x19,0xc6,0x48,0x02,0xe1,0x11,0x1e,0x00,0x00,0x00,
0x63,0x08,0xcd,0x63,0xd5,0xc0,0x31,0x84,0x06,0xb2,0x6b,0xe0,0x18,0x42,0x13,0x59,
0x36,0x70,0x0c,0xa1,0x71,0x6c,0x1b,0x38,0x16,0x02,0x04,0xc7,0x64,0x61,0x1a,0x37,
0x16,0x01,0x04,0x48,0x35,0xc7,0x20,0x79,0xcf,0x58,0x04,0x10,0x20,0xd5,0x1c,0xc3,
0x07,0x06,0xd0,0x58,0x04,0x10,0x20,0xd5,0x1c,0x43,0x18,0x88,0x41,0x34,0x16,0x01,
0x04,0x48,0x35,0xc7,0x30,0x06,0x64,0xe0,0x98,0x37,0xd0,0xc0,0x60,0xa0,0x89,0xc1,
0x40,0x23,0x83,0x81,0x63,0x21,0x40,0x70,0x50,0x66,0x70,0x06,0x68,0x90,0x06,0x58,
0x06,0xe1,0x40,0x00,0x25,0x00,0x00,0x00,0x56,0x52,0x4c,0xcc,0x73,0xd3,0x56,0x41,
0x4c,0xcc,0x53,0xdb,0x05,0x31,0x31,0xcf,0x6d,0x19,0xc4,0xc4,0x3c,0xba,0x6d,0x10,
0x13,0xf3,0xf4,0xd6,0x41,0x08,0xc0,0xb2,0x18,0x46,0x21,0x38,0x4d,0x85,0x9b,0x46,
0x21,0x38,0x4d,0xb5,0x9b,0x8a,0x21,0x00,0xcb,0x82,0xdf,0x66,0x62,0x08,0x4e,0x53,
0xdd,0xb7,0x9d,0x18,0x82,0xd3,0x54,0xb7,0x6e,0x28,0x86,0xe0,0x34,0xd5,0xdd,0xdb,
0x47,0x31,0x31,0x4f,0x9d,0x9b,0x87,0x21,0x00,0xcb,0x52,0xdf,0x06,0x62,0x08,0xc0,
0xb2,0xd4,0xbc,0x59,0x10,0x82,0xd3,0x54,0x96,0x62,0x08,0x4e,0x53,0xe1,0xb6,0x85,
0x14,0x13,0xf3,0xd8,0xb4,0x8d,0x14,0x13,0xf3,0xd8,0xb9,0x89,0x18,0x02,0xb0,0x2c,
0xf6,0x6d,0x24,0x86,0x00,0x2c,0x8b,0xcd,0x1b,0x87,0x21,0x38,0x4d,0x55,0xd3,0xd6,
0x30,0x54,0xc0,0x72,0x00,0x05,0xd1,0x4c,0x11,0x06,0x00,0x00,0x00,0x00,0x00,0x00,
0x61,0x20,0x00,0x00,0x19,0x00,0x00,0x00,0x13,0x04,0x41,0x2c,0x10,0x00,0x00,0x00,
0x03,0x00,0x00,0x00,0x24,0x4a,0x60,0x04,0x80,0xc2,0x0c,0x00,0x00,0x00,0x00,0x00,
0x63,0x08,0xcd,0x33,0x16,0x01,0x04,0x48,0x34,0xc7,0x00,0x49,0xcf,0x58,0x04,0x10,
0x28,0xd1,0x1c,0xc3,0x44,0x39,0x58,0x85,0x03,0x01,0x00,0x00,0x0a,0x00,0x00,0x00,
0x16,0x41,0x4c,0xcc,0x63,0xdb,0x04,0x31,0x31,0x4f,0x6e,0x0d,0x43,0x05,0x2c,0x07,
0x50,0x10,0xcd,0x14,0x61,0x56,0x41,0x4c,0xcc,0xd3,0x1b,0x45,0x21,0x00,0xcb,0xb2,
0x9b,0x04,0x21,0x00,0xcb,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x20,0x00,0x00,
0x1b,0x00,0x00,0x00,0x13,0x04,0x41,0x2c,0x10,0x00,0x00,0x00,0x03,0x00,0x00,0x00,
0x24,0xca,0x60,0x04,0xa0,0x04,0x8a,0x80,0xc2,0x0c,0x00,0x00,0x63,0x08,0xcd,0x33,
0x16,0x01,0x04,0xca,0x34,0xc7,0x20,0x51,0xcf,0x1c,0x43,0x45,0x41,0x73,0x0c,0x16,
0x15,0xcd,0x31,0x5c,0x94,0x83,0x58,0x38,0x10,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,
0x86,0x51,0x4c,0xcc,0x53,0xe7,0x76,0x51,0x4c,0xcc,0x53,0xdb,0x36,0x41,0x4c,0xcc,
0x63,0x5b,0x05,0x31,0x31,0x8f,0x6e,0x0d,0x43,0x05,0x2c,0x66,0x41,0x4c,0xcc,0xd3,
0x1f,0x40,0x41,0x34,0x53,0x84,0x19,0x05,0x21,0x00,0xcb,0x02,0x00,0x00,0x00,0x00,
0x61,0x20,0x00,0x00,0x2f,0x00,0x00,0x00,0x13,0x04,0x45,0x2c,0x10,0x00,0x00,0x00,
0x03,0x00,0x00,0x00,0x24,0xca,0xa0,0x04,0x46,0x00,0x8a,0x80,0xc0,0x08,0x00,0x00,
0x63,0x08,0x0d,0x34,0xc9,0x30,0x49,0xc4,0x2c,0x03,0x11,0x50,0x63,0x08,0xcd,0x33,
0xc9,0x50,0x49,0xc4,0x2c,0x03,0x21,0x58,0x63,0x08,0x4d,0x34,0xc9,0x70,0x49,0xc4,
0x2c,0x03,0x31,0x60,0x63,0x08,0x8d,0x33,0xc9,0x90,0x49,0x84,0x69,0x22,0x70,0xc3,
0x27,0x1c,0x08,0x00,0x1a,0x00,0x00,0x00,0x96,0x51,0x4c,0xcc,0x53,0xdf,0x66,0x41,
0x08,0xcc,0x83,0xdb,0x04,0x31,0x31,0x4f,0x6d,0x15,0xc4,0xc4,0x3c,0xb7,0x61,0x10,
0x02,0xf3,0xf0,0x47,0x20,0xb9,0x0d,0x52,0x20,0xc4,0xb0,0x12,0x13,0x15,0x35,0xdb,
0xe2,0x08,0x8a,0x5d,0x10,0x13,0xf3,0xec,0x37,0x90,0x2c,0x4e,0xf4,0x47,0x87,0x54,
0xd7,0x17,0x70,0x2c,0x4e,0xf4,0x47,0x87,0x74,0x02,0xc8,0xe2,0x44,0x7f,0x74,0x48,
0xb9,0x69,0x14,0x02,0xf3,0xd4,0xb8,0x6d,0x18,0x11,0x31,0x55,0xc0,0x62,0x0d,0x43,
0x05,0x2c,0x07,0x50,0x10,0xcd,0x14,0x61,0x46,0x31,0x08,0xcc,0x03,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x71,0x20,0x00,0x00,0x12,0x00,0x00,0x00,0x66,0x40,0x54,0x82,
0x23,0x59,0xc2,0x20,0x09,0x92,0x1d,0x18,0x4f,0x84,0x34,0x53,0x61,0x03,0xc4,0xe3,
0x58,0x85,0x05,0x14,0xbe,0x34,0x45,0xb5,0x21,0x10,0x82,0x23,0x15,0x46,0x30,0x2c,
0xc8,0x64,0x02,0x06,0xf0,0x3c,0x91,0x73,0x19,0x00,0xe1,0x4b,0x53,0x64,0x0a,0x84,
0x84,0x34,0x85,0x31,0x10,0x0a,0xb2,0x3c,0x56,0x30,0x08,0xcc,0x63,0x0b,0x44,0x25,
0x21,0x0d,0x00,0x00,0x00,0x00,0x00,0x00};
0x26,0x08,0xae,0x19,0x80,0x61,0x04,0x02,0x98,0x23,0x00,0x83,0x29,0x80,0x21,0x00,
0xb2,0x73,0x04,0x01,0x51,0x8a,0xf4,0x08,0x92,0xa4,0x39,0x47,0x80,0x50,0x2b,0x03,
0x00,0xa0,0x08,0x21,0x5c,0x46,0x2b,0x44,0x08,0x21,0xd4,0x40,0x14,0x01,0x80,0x11,
0x80,0x22,0x88,0x00,0x13,0xa2,0x74,0xb0,0x03,0x3c,0xb0,0x83,0x36,0x80,0x87,0x71,
0x68,0x03,0x76,0x48,0x07,0x77,0xa8,0x07,0x7c,0x68,0x83,0x73,0x70,0x87,0x7a,0xd8,
0x70,0x0f,0xe5,0xd0,0x06,0xf0,0xa0,0x07,0x73,0x20,0x07,0x7a,0x30,0x07,0x72,0xa0,
0x07,0x73,0x20,0x07,0x6d,0x90,0x0e,0x71,0xa0,0x07,0x78,0xa0,0x07,0x78,0xd0,0x06,
0xe9,0x80,0x07,0x7a,0x80,0x07,0x7a,0x80,0x07,0x6d,0x90,0x0e,0x71,0x60,0x07,0x7a,
0x10,0x07,0x76,0xa0,0x07,0x71,0x60,0x07,0x6d,0x90,0x0e,0x73,0x20,0x07,0x7a,0x30,
0x07,0x72,0xa0,0x07,0x73,0x20,0x07,0x6d,0x90,0x0e,0x76,0x40,0x07,0x7a,0x30,0x07,
0x72,0xa0,0x07,0x76,0x40,0x07,0x6d,0x60,0x0e,0x73,0x20,0x07,0x7a,0x30,0x07,0x72,
0xa0,0x07,0x73,0x20,0x07,0x6d,0x60,0x0e,0x76,0x40,0x07,0x7a,0x30,0x07,0x72,0xa0,
0x07,0x76,0x40,0x07,0x6d,0x60,0x0f,0x76,0x40,0x07,0x7a,0x60,0x07,0x74,0xa0,0x07,
0x76,0x40,0x07,0x6d,0x60,0x0f,0x71,0x20,0x07,0x78,0xa0,0x07,0x71,0x20,0x07,0x78,
0xa0,0x07,0x71,0x20,0x07,0x78,0xd0,0x06,0xe1,0x00,0x07,0x7a,0x00,0x07,0x7a,0x60,
0x07,0x74,0xd0,0x06,0xe6,0x80,0x07,0x70,0xa0,0x07,0x71,0x20,0x07,0x78,0xa0,0x07,
0x71,0x20,0x07,0x78,0xa0,0xf3,0x40,0x88,0x04,0x32,0x32,0x02,0x04,0x20,0x76,0x46,
0xfc,0x6c,0x48,0x92,0x00,0x40,0x00,0x00,0x00,0x00,0x0c,0x49,0x12,0x20,0x00,0x00,
0x00,0x00,0x80,0x21,0x89,0x02,0x00,0x01,0x00,0x00,0x00,0x30,0x24,0x59,0x00,0x20,
0x08,0x00,0x00,0x00,0x86,0x24,0x0a,0x00,0x04,0x00,0x00,0x00,0xc0,0x90,0x84,0x01,
0x02,0x00,0x00,0x00,0x00,0x18,0x92,0x1c,0x40,0x00,0x00,0x00,0x00,0x00,0x43,0x12,
0x05,0x00,0x02,0x00,0x00,0x00,0x60,0x48,0x72,0x00,0x01,0x00,0x00,0x00,0x00,0x0c,
0x49,0x14,0x00,0x08,0x00,0x00,0x00,0x80,0x21,0x49,0x01,0x00,0x41,0x00,0x00,0x00,
0x90,0x05,0x02,0x00,0x10,0x00,0x00,0x00,0x32,0x1e,0x98,0x10,0x19,0x11,0x4c,0x90,
0x8c,0x09,0x26,0x47,0xc6,0x04,0x43,0x8a,0x8a,0x59,0x8b,0x43,0x50,0xd2,0x09,0x02,
0x81,0xd2,0x73,0x50,0xc9,0x0c,0x2a,0x99,0x41,0x25,0x33,0xa8,0x64,0x56,0x28,0x66,
0x2d,0x0e,0x41,0xcf,0x2a,0x15,0x04,0x4a,0xcf,0x41,0x25,0x33,0xa8,0x64,0x06,0x95,
0xcc,0xa0,0x92,0x59,0x01,0x00,0x00,0x00,0x53,0x82,0x26,0x0c,0x04,0x00,0x00,0x00,
0x22,0x00,0x00,0x00,0x13,0x04,0x41,0x2c,0x10,0x00,0x00,0x00,0x05,0x00,0x00,0x00,
0x04,0xc6,0x08,0x40,0x10,0x04,0xe1,0x70,0x18,0x23,0x00,0x41,0x10,0x84,0xc3,0x60,
0x04,0x00,0x00,0x00,0x93,0x0c,0xce,0x43,0x4c,0x31,0x3c,0x8e,0x34,0xc9,0x30,0x41,
0xc2,0x14,0x03,0x34,0x51,0x93,0x0c,0x4d,0x44,0x4c,0x31,0x44,0x8d,0x35,0x56,0x01,
0x04,0xc3,0x55,0x21,0x16,0x0e,0x04,0x00,0x0f,0x00,0x00,0x00,0x46,0x41,0x08,0xcc,
0x73,0x9b,0x05,0x21,0x30,0xcf,0x6e,0x18,0x84,0x00,0x2c,0x8b,0x35,0x04,0x80,0x39,
0x04,0x81,0x5d,0x20,0x80,0x0f,0x0c,0x43,0xe4,0xd3,0x36,0x81,0x04,0x3e,0x30,0x0c,
0x91,0x4f,0x5b,0x05,0x12,0xf8,0xc0,0x30,0x44,0x7e,0x7d,0x00,0x05,0xd1,0x4c,0x11,
0x66,0x12,0x83,0xc0,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x20,0x00,0x00,
0x2a,0x00,0x00,0x00,0x13,0x04,0x43,0x2c,0x10,0x00,0x00,0x00,0x08,0x00,0x00,0x00,
0x24,0x8a,0xa0,0x0c,0x46,0x00,0x4a,0x80,0xc2,0x1c,0x84,0x55,0x55,0xd6,0x1c,0x84,
0x45,0x51,0x16,0x81,0x19,0x80,0x11,0x80,0x31,0x02,0x10,0x04,0x41,0xfc,0x03,0x00,
0x63,0x08,0x0d,0x34,0xc9,0x70,0x55,0xc2,0x2c,0x43,0x20,0x60,0x73,0x0c,0xd3,0x15,
0x8d,0x21,0x34,0xd1,0x18,0x42,0xf3,0x8c,0x55,0x00,0x81,0xa0,0x6d,0x73,0x0c,0x19,
0xe7,0x60,0x87,0x52,0x38,0x10,0x00,0x00,0x13,0x00,0x00,0x00,0x17,0x60,0x20,0xc5,
0x74,0x10,0x8d,0x65,0x14,0x13,0xf3,0xd4,0xb4,0x6d,0x14,0x13,0xf3,0xd4,0xb8,0x69,
0x14,0x13,0xf3,0xd4,0xb6,0x75,0x14,0x13,0xf3,0xd4,0xba,0x35,0x0c,0x13,0xf3,0x9c,
0x80,0xe4,0x36,0x48,0x81,0x10,0xc3,0x4a,0x4c,0x54,0xd4,0x6c,0x8b,0x23,0x28,0x76,
0x41,0x4c,0xcc,0xa3,0x1b,0x07,0x21,0x00,0xcb,0x72,0x00,0x05,0xd1,0x4c,0x11,0x66,
0x18,0x83,0xc0,0x3c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x20,0x00,0x00,
0x81,0x00,0x00,0x00,0x13,0x04,0x4d,0x2c,0x10,0x00,0x00,0x00,0x04,0x00,0x00,0x00,
0x24,0xca,0x60,0x04,0xa0,0x04,0x8a,0x80,0xc2,0x0c,0x00,0x91,0x11,0x00,0x00,0x00,
0x63,0x08,0x4d,0x64,0x16,0xc1,0x49,0x86,0xab,0x22,0x66,0x19,0x02,0x01,0x1b,0x43,
0x70,0xa2,0x59,0x82,0x61,0x0c,0xe1,0x89,0x66,0x09,0x86,0x81,0x0a,0x20,0x0b,0x34,
0x61,0x8e,0x81,0xda,0xa2,0x31,0x84,0x46,0xb2,0x8e,0xe0,0x24,0x83,0x57,0x11,0xb3,
0x0c,0x44,0xf1,0x8d,0x21,0x38,0xd2,0x2c,0x81,0x31,0x86,0xf0,0x48,0xb3,0x04,0xc6,
0x40,0x05,0x00,0x06,0x44,0x18,0x14,0x73,0x0c,0x9c,0x18,0x48,0x63,0x08,0xcd,0x64,
0x64,0x40,0x70,0x92,0xa1,0x0c,0x2a,0x62,0x96,0xe1,0x40,0xcc,0x60,0x0c,0xc1,0x99,
0x66,0x09,0x92,0x31,0x84,0x67,0x9a,0x25,0x48,0x06,0x2a,0x80,0x33,0x38,0xd0,0x00,
0x99,0x63,0x18,0x83,0x34,0x98,0xc6,0x10,0x1a,0xc8,0xd6,0x80,0xe0,0x24,0x03,0x1b,
0x54,0xc4,0x2c,0x83,0xb2,0xb4,0xc1,0x18,0x82,0x03,0xcd,0x12,0x30,0x63,0x08,0x0f,
0x34,0x4b,0xc0,0x0c,0x54,0x00,0x6e,0xa0,0xbc,0xc1,0x32,0xc7,0xa0,0x06,0x70,0x00,
0x61,0x1c,0x84,0x03,0x01,0x00,0x00,0x00,0x4e,0x00,0x00,0x00,0x76,0x52,0x4c,0xcc,
0x73,0xd3,0x24,0x05,0x64,0xec,0xcd,0x8d,0xcc,0xe5,0x87,0x46,0xc6,0x50,0x8a,0x89,
0x79,0xee,0xdb,0x54,0x8a,0x89,0x79,0xee,0xdd,0x1a,0x88,0x89,0x79,0x68,0x73,0x20,
0x26,0xe6,0xa9,0xed,0x81,0x98,0x98,0xc7,0x36,0x0b,0x62,0x62,0x9e,0xdb,0x32,0x88,
0x89,0x79,0x72,0xd3,0x20,0x26,0xe6,0xd9,0x8d,0x83,0x98,0x98,0xa7,0xb7,0x95,0x62,
0x62,0x9e,0xbb,0x27,0x2d,0x20,0x63,0x6f,0x6e,0x64,0x2e,0x3a,0x34,0x35,0x56,0x62,
0x08,0x4e,0x53,0xd9,0xba,0xb5,0x14,0x02,0xf3,0xe0,0xf5,0x25,0x2c,0x82,0xd3,0x0c,
0xbe,0xe0,0x34,0xd3,0x8d,0x9b,0x88,0x21,0x38,0xcd,0x60,0xd7,0x24,0x01,0x63,0xec,
0xcd,0x8d,0xcc,0x45,0x87,0x44,0x80,0x8c,0xbd,0xb9,0x91,0xb9,0xfc,0xc4,0xd0,0x90,
0x02,0x8c,0xb1,0x37,0x37,0x32,0x97,0x1f,0x73,0x29,0x26,0xe6,0xc1,0x71,0x7b,0x29,
0x26,0xe6,0xc1,0x77,0xfb,0x28,0x04,0xe6,0xa9,0x6f,0x52,0x01,0x32,0xf6,0xe6,0x46,
0xe6,0xa2,0x13,0x73,0x63,0x18,0x83,0xc0,0x3c,0xb6,0x41,0x08,0x4e,0x33,0x58,0x47,
0x31,0x31,0x4f,0x5d,0x1f,0xc3,0x22,0x38,0xcd,0xe0,0x0b,0x4e,0x33,0xe1,0xbc,0xa5,
0x18,0x82,0xd3,0x0c,0x77,0x6e,0x20,0xc5,0xc4,0x3c,0xb5,0x4e,0x3a,0x40,0xc6,0xde,
0xdc,0xc8,0x5c,0x7e,0x64,0x70,0x2c,0xa4,0x98,0x98,0xa7,0xee,0xed,0x82,0x10,0x9c,
0xa6,0xba,0x81,0x44,0x70,0x9a,0xc1,0x17,0x9c,0x66,0x32,0x93,0x42,0x60,0x1e,0x7b,
0xb7,0x98,0x62,0x62,0x9e,0xbc,0x36,0x16,0x43,0x70,0x9a,0x0a,0xa7,0x6d,0xa4,0x98,
0x98,0xc7,0xbe,0x8d,0xa4,0x98,0x98,0xc7,0xce,0x0d,0xc6,0x10,0x9c,0x66,0xc0,0x7b,
0x12,0x02,0x32,0xf6,0xe6,0x46,0xe6,0xa2,0x33,0x13,0x73,0x06,0x8b,0xe0,0x34,0x83,
0x2f,0x38,0xcd,0x64,0xd3,0xe6,0x61,0x08,0x4e,0x53,0xd5,0xf6,0x01,0x14,0x44,0x33,
0x45,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x20,0x00,0x00,0x4a,0x00,0x00,0x00,
0x13,0x04,0x41,0x2c,0x10,0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x24,0xca,0x60,0x04,
0xa0,0x04,0x8a,0x80,0xc2,0x0c,0x00,0xb9,0x61,0x0c,0x04,0x10,0x1e,0xe1,0x19,0xc6,
0x40,0x02,0xe1,0x11,0x1e,0x00,0x00,0x00,0x63,0x08,0xcd,0x63,0x15,0xc1,0x31,0x84,
0x06,0xb2,0x8b,0xe0,0x18,0x42,0x13,0x59,0x46,0x70,0x0c,0xa1,0x71,0x6c,0x23,0x38,
0x16,0x02,0x04,0xc7,0x64,0x61,0x1a,0x37,0x16,0x01,0x04,0x48,0x35,0xc7,0x20,0x79,
0xcf,0x58,0x04,0x10,0x20,0xd5,0x1c,0xc3,0x07,0x06,0xd0,0x58,0x04,0x10,0x20,0xd5,
0x1c,0x43,0x18,0x88,0x41,0x34,0x16,0x01,0x04,0x48,0x35,0xc7,0x30,0x06,0x64,0xe0,
0x98,0x47,0xd0,0xc0,0x80,0xa0,0x89,0x01,0x41,0x23,0x03,0x82,0x63,0x21,0x40,0x70,
0x50,0x66,0x70,0x06,0x68,0x90,0x06,0x58,0x06,0xe1,0x40,0x00,0x25,0x00,0x00,0x00,
0x56,0x52,0x4c,0xcc,0x73,0xd3,0x56,0x41,0x4c,0xcc,0x53,0xdb,0x05,0x31,0x31,0xcf,
0x6d,0x19,0xc4,0xc4,0x3c,0xba,0x6d,0x10,0x13,0xf3,0xf4,0xd6,0x41,0x08,0xc0,0xb2,
0x18,0x46,0x21,0x38,0x4d,0x85,0x9b,0x46,0x21,0x38,0x4d,0xb5,0x9b,0x8a,0x21,0x00,
0xcb,0x82,0xdf,0x66,0x62,0x08,0x4e,0x53,0xdd,0xb7,0x9d,0x18,0x82,0xd3,0x54,0xb7,
0x6e,0x28,0x86,0xe0,0x34,0xd5,0xdd,0xdb,0x47,0x31,0x31,0x4f,0x9d,0x9b,0x87,0x21,
0x00,0xcb,0x52,0xdf,0x06,0x62,0x08,0xc0,0xb2,0xd4,0xbc,0x59,0x10,0x82,0xd3,0x54,
0x96,0x62,0x08,0x4e,0x53,0xe1,0xb6,0x85,0x14,0x13,0xf3,0xd8,0xb4,0x8d,0x14,0x13,
0xf3,0xd8,0xb9,0x89,0x18,0x02,0xb0,0x2c,0xf6,0x6d,0x24,0x86,0x00,0x2c,0x8b,0xcd,
0x1b,0x87,0x21,0x38,0x4d,0x55,0xd3,0xd6,0x30,0x54,0xc0,0x72,0x00,0x05,0xd1,0x4c,
0x11,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x61,0x20,0x00,0x00,0x19,0x00,0x00,0x00,
0x13,0x04,0x41,0x2c,0x10,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x24,0x4a,0x60,0x04,
0x80,0xc2,0x0c,0x00,0x00,0x00,0x00,0x00,0x63,0x08,0xcd,0x33,0x16,0x01,0x04,0x48,
0x34,0xc7,0x00,0x49,0xcf,0x58,0x04,0x10,0x28,0xd1,0x1c,0xc3,0x44,0x39,0x58,0x85,
0x03,0x01,0x00,0x00,0x0a,0x00,0x00,0x00,0x16,0x41,0x4c,0xcc,0x63,0xdb,0x04,0x31,
0x31,0x4f,0x6e,0x0d,0x43,0x05,0x2c,0x07,0x50,0x10,0xcd,0x14,0x61,0x56,0x41,0x4c,
0xcc,0xd3,0x1b,0x45,0x21,0x00,0xcb,0xb2,0x9b,0x04,0x21,0x00,0xcb,0x02,0x00,0x00,
0x00,0x00,0x00,0x00,0x61,0x20,0x00,0x00,0x1b,0x00,0x00,0x00,0x13,0x04,0x41,0x2c,
0x10,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x24,0xca,0x60,0x04,0xa0,0x04,0x8a,0x80,
0xc2,0x0c,0x00,0x00,0x63,0x08,0xcd,0x33,0x16,0x01,0x04,0xca,0x34,0xc7,0x20,0x51,
0xcf,0x1c,0x43,0x45,0x41,0x73,0x0c,0x16,0x15,0xcd,0x31,0x5c,0x94,0x83,0x58,0x38,
0x10,0x00,0x00,0x00,0x0b,0x00,0x00,0x00,0x86,0x51,0x4c,0xcc,0x53,0xe7,0x76,0x51,
0x4c,0xcc,0x53,0xdb,0x36,0x41,0x4c,0xcc,0x63,0x5b,0x05,0x31,0x31,0x8f,0x6e,0x0d,
0x43,0x05,0x2c,0x66,0x41,0x4c,0xcc,0xd3,0x1f,0x40,0x41,0x34,0x53,0x84,0x19,0x05,
0x21,0x00,0xcb,0x02,0x00,0x00,0x00,0x00,0x61,0x20,0x00,0x00,0x2f,0x00,0x00,0x00,
0x13,0x04,0x45,0x2c,0x10,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x24,0xca,0xa0,0x04,
0x46,0x00,0x8a,0x80,0xc0,0x08,0x00,0x00,0x63,0x08,0x0d,0x34,0xc9,0x30,0x49,0xc4,
0x2c,0x03,0x11,0x50,0x63,0x08,0xcd,0x33,0xc9,0x50,0x49,0xc4,0x2c,0x03,0x21,0x58,
0x63,0x08,0x4d,0x34,0xc9,0x70,0x49,0xc4,0x2c,0x03,0x31,0x60,0x63,0x08,0x8d,0x33,
0xc9,0x90,0x49,0x84,0x69,0x22,0x70,0xc3,0x27,0x1c,0x08,0x00,0x1a,0x00,0x00,0x00,
0x96,0x51,0x4c,0xcc,0x53,0xdf,0x66,0x41,0x08,0xcc,0x83,0xdb,0x04,0x31,0x31,0x4f,
0x6d,0x15,0xc4,0xc4,0x3c,0xb7,0x61,0x10,0x02,0xf3,0xf0,0x47,0x20,0xb9,0x0d,0x52,
0x20,0xc4,0xb0,0x12,0x13,0x15,0x35,0xdb,0xe2,0x08,0x8a,0x5d,0x10,0x13,0xf3,0xec,
0x37,0x90,0x2c,0x4e,0xf4,0x47,0x87,0x54,0xd7,0x17,0x70,0x2c,0x4e,0xf4,0x47,0x87,
0x74,0x02,0xc8,0xe2,0x44,0x7f,0x74,0x48,0xb9,0x69,0x14,0x02,0xf3,0xd4,0xb8,0x6d,
0x18,0x11,0x31,0x55,0xc0,0x62,0x0d,0x43,0x05,0x2c,0x07,0x50,0x10,0xcd,0x14,0x61,
0x46,0x31,0x08,0xcc,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x71,0x20,0x00,0x00,
0x12,0x00,0x00,0x00,0x66,0x40,0x54,0x82,0x23,0x59,0xc2,0x20,0x09,0x92,0x1d,0x18,
0x4f,0x84,0x34,0x53,0x61,0x03,0xc4,0xe3,0x58,0x85,0x05,0x14,0xbe,0x34,0x45,0xb5,
0x21,0x10,0x82,0x23,0x15,0x46,0x30,0x2c,0xc8,0x64,0x02,0x06,0xf0,0x3c,0x91,0x73,
0x19,0x00,0xe1,0x4b,0x53,0x64,0x0a,0x84,0x84,0x34,0x85,0x31,0x10,0x0a,0xb2,0x3c,
0x56,0x30,0x08,0xcc,0x63,0x0b,0x44,0x25,0x21,0x0d,0x00,0x00,0x00,0x00,0x00,0x00};
+49 -7
View File
@@ -41,6 +41,7 @@
#include "pipe/p_context.h"
#include "pipe/p_shader_tokens.h"
#include "pipe/p_util.h"
#include "tgsi/exec/tgsi_exec.h"
#include "tgsi/util/tgsi_dump.h"
@@ -179,22 +180,63 @@ typedef void (*vertex_shader_runner)(void *ainputs,
float (*aconsts)[4],
void *temps);
#define MAX_TGSI_VERTICES 4
/*!
This function is used to execute the gallivm_prog in software. Before calling
this function the gallivm_prog has to be JIT compiled with the gallivm_cpu_jit_compile
function.
*/
int gallivm_cpu_vs_exec(struct gallivm_prog *prog,
struct tgsi_exec_vector *inputs,
struct tgsi_exec_vector *dests,
float (*consts)[4],
struct tgsi_exec_vector *temps)
struct tgsi_exec_machine *machine,
const float (*input)[4],
unsigned num_inputs,
float (*output)[4],
unsigned num_outputs,
const float (*constants)[4],
unsigned count,
unsigned input_stride,
unsigned output_stride )
{
unsigned int i, j;
unsigned slot;
vertex_shader_runner runner = reinterpret_cast<vertex_shader_runner>(prog->function);
assert(runner);
/*FIXME*/
runner(inputs, dests, consts, temps);
for (i = 0; i < count; i += MAX_TGSI_VERTICES) {
unsigned int max_vertices = MIN2(MAX_TGSI_VERTICES, count - i);
/* Swizzle inputs.
*/
for (j = 0; j < max_vertices; j++) {
for (slot = 0; slot < num_inputs; slot++) {
machine->Inputs[slot].xyzw[0].f[j] = input[slot][0];
machine->Inputs[slot].xyzw[1].f[j] = input[slot][1];
machine->Inputs[slot].xyzw[2].f[j] = input[slot][2];
machine->Inputs[slot].xyzw[3].f[j] = input[slot][3];
}
input = (const float (*)[4])((const char *)input + input_stride);
}
/* run shader */
runner(machine->Inputs,
machine->Outputs,
(float (*)[4]) constants,
machine->Temps);
/* Unswizzle all output results
*/
for (j = 0; j < max_vertices; j++) {
for (slot = 0; slot < num_outputs; slot++) {
output[slot][0] = machine->Outputs[slot].xyzw[0].f[j];
output[slot][1] = machine->Outputs[slot].xyzw[1].f[j];
output[slot][2] = machine->Outputs[slot].xyzw[2].f[j];
output[slot][3] = machine->Outputs[slot].xyzw[3].f[j];
}
output = (float (*)[4])((char *)output + output_stride);
}
}
return 0;
}
+104 -10
View File
@@ -38,7 +38,6 @@
#include <llvm/Instructions.h>
#include <llvm/Transforms/Utils/Cloning.h>
#include <llvm/ParameterAttributes.h>
//#include <llvm/ParamAttrsList.h>
#include <llvm/Support/MemoryBuffer.h>
#include <llvm/Bitcode/ReaderWriter.h>
@@ -174,16 +173,56 @@ std::vector<llvm::Value*> InstructionsSoa::extractVector(llvm::Value *vector)
void InstructionsSoa::createFunctionMap()
{
m_functionsMap[TGSI_OPCODE_ABS] = "abs";
m_functionsMap[TGSI_OPCODE_DP3] = "dp3";
m_functionsMap[TGSI_OPCODE_DP4] = "dp4";
m_functionsMap[TGSI_OPCODE_MIN] = "min";
m_functionsMap[TGSI_OPCODE_MAX] = "max";
m_functionsMap[TGSI_OPCODE_POWER] = "pow";
m_functionsMap[TGSI_OPCODE_LIT] = "lit";
m_functionsMap[TGSI_OPCODE_RSQ] = "rsq";
}
void InstructionsSoa::createDependencies()
{
std::vector<std::string> powDeps(1);
powDeps[0] = "powf";
m_builtinDependencies["pow"] = powDeps;
{
std::vector<std::string> powDeps(2);
powDeps[0] = "powf";
powDeps[1] = "powvec";
m_builtinDependencies["pow"] = powDeps;
}
{
std::vector<std::string> absDeps(2);
absDeps[0] = "fabsf";
absDeps[1] = "absvec";
m_builtinDependencies["abs"] = absDeps;
}
{
std::vector<std::string> maxDeps(1);
maxDeps[0] = "maxvec";
m_builtinDependencies["max"] = maxDeps;
}
{
std::vector<std::string> minDeps(1);
minDeps[0] = "minvec";
m_builtinDependencies["min"] = minDeps;
}
{
std::vector<std::string> litDeps(4);
litDeps[0] = "minvec";
litDeps[1] = "maxvec";
litDeps[2] = "powf";
litDeps[3] = "powvec";
m_builtinDependencies["lit"] = litDeps;
}
{
std::vector<std::string> rsqDeps(4);
rsqDeps[0] = "sqrtf";
rsqDeps[1] = "sqrtvec";
rsqDeps[2] = "fabsf";
rsqDeps[3] = "absvec";
m_builtinDependencies["rsq"] = rsqDeps;
}
}
llvm::Function * InstructionsSoa::function(int op)
@@ -193,9 +232,13 @@ llvm::Function * InstructionsSoa::function(int op)
std::string name = m_functionsMap[op];
std::cout <<"For op = "<<op<<", func is '"<<name<<"'"<<std::endl;
std::vector<std::string> deps = m_builtinDependencies[name];
for (unsigned int i = 0; i < deps.size(); ++i) {
injectFunction(m_builtins->getFunction(deps[i]));
llvm::Function *func = m_builtins->getFunction(deps[i]);
std::cout <<"\tinjecting dep = '"<<func->getName()<<"'"<<std::endl;
injectFunction(func);
}
llvm::Function *originalFunc = m_builtins->getFunction(name);
@@ -216,11 +259,20 @@ void InstructionsSoa::createBuiltins()
{
MemoryBuffer *buffer = MemoryBuffer::getMemBuffer(
(const char*)&soabuiltins_data[0],
(const char*)&soabuiltins_data[Elements(soabuiltins_data)-1]);
(const char*)&soabuiltins_data[Elements(soabuiltins_data)]);
m_builtins = ParseBitcodeFile(buffer);
std::cout<<"Builtins created at "<<m_builtins<<std::endl;
assert(m_builtins);
createDependencies();
}
std::vector<llvm::Value*> InstructionsSoa::abs(const std::vector<llvm::Value*> in1)
{
llvm::Function *func = function(TGSI_OPCODE_ABS);
return callBuiltin(func, in1);
}
std::vector<llvm::Value*> InstructionsSoa::dp3(const std::vector<llvm::Value*> in1,
const std::vector<llvm::Value*> in2)
{
@@ -354,6 +406,21 @@ std::vector<llvm::Value*> InstructionsSoa::pow(const std::vector<llvm::Value*> i
return callBuiltin(func, in1, in2);
}
std::vector<llvm::Value*> InstructionsSoa::min(const std::vector<llvm::Value*> in1,
const std::vector<llvm::Value*> in2)
{
llvm::Function *func = function(TGSI_OPCODE_MIN);
return callBuiltin(func, in1, in2);
}
std::vector<llvm::Value*> InstructionsSoa::max(const std::vector<llvm::Value*> in1,
const std::vector<llvm::Value*> in2)
{
llvm::Function *func = function(TGSI_OPCODE_MAX);
return callBuiltin(func, in1, in2);
}
void checkFunction(Function *func)
{
for (Function::const_iterator BI = func->begin(), BE = func->end();
@@ -388,7 +455,6 @@ void InstructionsSoa::injectFunction(llvm::Function *originalFunc, int op)
}
llvm::Function *func = 0;
if (originalFunc->isDeclaration()) {
std::cout << "function decleration" <<std::endl;
func = Function::Create(originalFunc->getFunctionType(), GlobalValue::ExternalLinkage,
originalFunc->getName(), currentModule());
func->setCallingConv(CallingConv::C);
@@ -397,20 +463,48 @@ void InstructionsSoa::injectFunction(llvm::Function *originalFunc, int op)
currentModule()->dump();
} else {
DenseMap<const Value*, Value *> val;
val[m_builtins->getFunction("fabsf")] = currentModule()->getFunction("fabsf");
val[m_builtins->getFunction("powf")] = currentModule()->getFunction("powf");
val[m_builtins->getFunction("sqrtf")] = currentModule()->getFunction("sqrtf");
func = CloneFunction(originalFunc, val);
#if 0
std::cout <<" replacing "<<m_builtins->getFunction("powf")
<<", with " <<currentModule()->getFunction("powf")<<std::endl;
func = CloneFunction(originalFunc, val);
std::cout<<"1111-------------------------------"<<std::endl;
checkFunction(originalFunc);
std::cout<<"2222-------------------------------"<<std::endl;
checkFunction(func);
std::cout <<"XXXX = " <<val[m_builtins->getFunction("powf")]<<std::endl;
#endif
currentModule()->getFunctionList().push_back(func);
std::cout << "Func parent is "<<func->getParent()
<<", cur is "<<currentModule() <<std::endl;
}
if (op != TGSI_OPCODE_LAST) {
m_functions[op] = func;
}
}
std::vector<llvm::Value*> InstructionsSoa::sub(const std::vector<llvm::Value*> in1,
const std::vector<llvm::Value*> in2)
{
std::vector<llvm::Value*> res(4);
res[0] = m_builder.CreateSub(in1[0], in2[0], name("subx"));
res[1] = m_builder.CreateSub(in1[1], in2[1], name("suby"));
res[2] = m_builder.CreateSub(in1[2], in2[2], name("subz"));
res[3] = m_builder.CreateSub(in1[3], in2[3], name("subw"));
return res;
}
std::vector<llvm::Value*> InstructionsSoa::lit(const std::vector<llvm::Value*> in)
{
llvm::Function *func = function(TGSI_OPCODE_LIT);
return callBuiltin(func, in);
}
std::vector<llvm::Value*> InstructionsSoa::rsq(const std::vector<llvm::Value*> in)
{
llvm::Function *func = function(TGSI_OPCODE_RSQ);
return callBuiltin(func, in);
}
@@ -48,6 +48,7 @@ public:
InstructionsSoa(llvm::Module *mod, llvm::Function *func,
llvm::BasicBlock *block, StorageSoa *storage);
std::vector<llvm::Value*> abs(const std::vector<llvm::Value*> in1);
std::vector<llvm::Value*> arl(const std::vector<llvm::Value*> in);
std::vector<llvm::Value*> add(const std::vector<llvm::Value*> in1,
const std::vector<llvm::Value*> in2);
@@ -55,13 +56,21 @@ public:
const std::vector<llvm::Value*> in2);
std::vector<llvm::Value*> dp4(const std::vector<llvm::Value*> in1,
const std::vector<llvm::Value*> in2);
std::vector<llvm::Value*> lit(const std::vector<llvm::Value*> in);
std::vector<llvm::Value*> madd(const std::vector<llvm::Value*> in1,
const std::vector<llvm::Value*> in2,
const std::vector<llvm::Value*> in3);
std::vector<llvm::Value*> max(const std::vector<llvm::Value*> in1,
const std::vector<llvm::Value*> in2);
std::vector<llvm::Value*> min(const std::vector<llvm::Value*> in1,
const std::vector<llvm::Value*> in2);
std::vector<llvm::Value*> mul(const std::vector<llvm::Value*> in1,
const std::vector<llvm::Value*> in2);
std::vector<llvm::Value*> pow(const std::vector<llvm::Value*> in1,
const std::vector<llvm::Value*> in2);
std::vector<llvm::Value*> rsq(const std::vector<llvm::Value*> in1);
std::vector<llvm::Value*> sub(const std::vector<llvm::Value*> in1,
const std::vector<llvm::Value*> in2);
void end();
std::vector<llvm::Value*> extractVector(llvm::Value *vector);
@@ -1,4 +1,3 @@
/*clang --emit-llvm llvm_builtins.c |llvm-as|opt -std-compile-opts|llvm2cpp -gen-contents -o=gallivm_builtins.cpp -f -for=shader -funcname=createGallivmBuiltins*/
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+115 -18
View File
@@ -33,6 +33,29 @@
*/
typedef __attribute__(( ext_vector_type(4) )) float float4;
extern float fabsf(float val);
float4 absvec(float4 vec)
{
float4 res;
res.x = fabsf(vec.x);
res.y = fabsf(vec.y);
res.z = fabsf(vec.z);
res.w = fabsf(vec.w);
return res;
}
void abs(float4 *res,
float4 tmp0x, float4 tmp0y, float4 tmp0z, float4 tmp0w)
{
res[0] = absvec(tmp0x);
res[1] = absvec(tmp0y);
res[2] = absvec(tmp0z);
res[3] = absvec(tmp0w);
}
void dp3(float4 *res,
float4 tmp0x, float4 tmp0y, float4 tmp0z, float4 tmp0w,
float4 tmp1x, float4 tmp1y, float4 tmp1z, float4 tmp1w)
@@ -61,30 +84,104 @@ void dp4(float4 *res,
}
extern float powf(float num, float p);
extern float sqrtf(float x);
float4 powvec(float4 vec, float4 q)
{
float4 p;
p.x = powf(vec.x, q.x);
p.y = powf(vec.y, q.y);
p.z = powf(vec.z, q.z);
p.w = powf(vec.w, q.w);
return p;
}
void pow(float4 *res,
float4 tmp0x, float4 tmp0y, float4 tmp0z, float4 tmp0w,
float4 tmp1x, float4 tmp1y, float4 tmp1z, float4 tmp1w)
{
float4 p;
p.x = powf(tmp0x.x, tmp1x.x);
p.y = powf(tmp0x.y, tmp1x.y);
p.z = powf(tmp0x.z, tmp1x.z);
p.w = powf(tmp0x.w, tmp1x.w);
res[0] = p;
res[1] = p;
res[2] = p;
res[3] = p;
res[0] = powvec(tmp0x, tmp1x);
res[1] = res[0];
res[2] = res[0];
res[3] = res[0];
}
#if 0
void yo(float4 *out, float4 *in)
float4 minvec(float4 a, float4 b)
{
float4 res[4];
dp3(res, in[0], in[1], in[2], in[3],
in[4], in[5], in[6], in[7]);
out[1] = res[1];
return (float4){(a.x < b.x) ? a.x : b.x,
(a.y < b.y) ? a.y : b.y,
(a.z < b.z) ? a.z : b.z,
(a.w < b.w) ? a.w : b.w};
}
void min(float4 *res,
float4 tmp0x, float4 tmp0y, float4 tmp0z, float4 tmp0w,
float4 tmp1x, float4 tmp1y, float4 tmp1z, float4 tmp1w)
{
res[0] = minvec(tmp0x, tmp1x);
res[1] = minvec(tmp0y, tmp1y);
res[2] = minvec(tmp0z, tmp1z);
res[3] = minvec(tmp0w, tmp1w);
}
float4 maxvec(float4 a, float4 b)
{
return (float4){(a.x > b.x) ? a.x : b.x,
(a.y > b.y) ? a.y : b.y,
(a.z > b.z) ? a.z : b.z,
(a.w > b.w) ? a.w : b.w};
}
void max(float4 *res,
float4 tmp0x, float4 tmp0y, float4 tmp0z, float4 tmp0w,
float4 tmp1x, float4 tmp1y, float4 tmp1z, float4 tmp1w)
{
res[0] = maxvec(tmp0x, tmp1x);
res[1] = maxvec(tmp0y, tmp1y);
res[2] = maxvec(tmp0z, tmp1z);
res[3] = maxvec(tmp0w, tmp1w);
}
void lit(float4 *res,
float4 tmp0x, float4 tmp0y, float4 tmp0z, float4 tmp0w)
{
const float4 zerovec = (float4) {0.0, 0.0, 0.0, 0.0};
const float4 min128 = (float4) {-128.f, -128.f, -128.f, -128.f};
const float4 plus128 = (float4) {128.f, 128.f, 128.f, 128.f};
res[0] = (float4){1.0, 1.0, 1.0, 1.0};
if (tmp0x.x > 0) {
float4 tmpy = maxvec(tmp0y, zerovec);
float4 tmpw = minvec(tmp0w, plus128);
tmpw = maxvec(tmpw, min128);
res[1] = tmp0x;
res[2] = powvec(tmpy, tmpw);
} else {
res[1] = zerovec;
res[2] = zerovec;
}
res[3] = (float4){1.0, 1.0, 1.0, 1.0};
}
float4 sqrtvec(float4 vec)
{
float4 p;
p.x = sqrtf(vec.x);
p.y = sqrtf(vec.y);
p.z = sqrtf(vec.z);
p.w = sqrtf(vec.w);
return p;
}
void rsq(float4 *res,
float4 tmp0x, float4 tmp0y, float4 tmp0z, float4 tmp0w)
{
const float4 onevec = (float4) {1., 1., 1., 1.};
res[0] = onevec/sqrtvec(absvec(tmp0x));
res[1] = onevec/sqrtvec(absvec(tmp0y));
res[2] = onevec/sqrtvec(absvec(tmp0z));
res[3] = onevec/sqrtvec(absvec(tmp0w));
}
#endif
@@ -692,12 +692,14 @@ translate_instructionir(llvm::Module *module,
}
break;
case TGSI_OPCODE_LIT: {
out = instr->lit(inputs[0]);
}
break;
case TGSI_OPCODE_RCP: {
}
break;
case TGSI_OPCODE_RSQ: {
out = instr->rsq(inputs[0]);
}
break;
case TGSI_OPCODE_EXP:
@@ -724,9 +726,11 @@ translate_instructionir(llvm::Module *module,
}
break;
case TGSI_OPCODE_MIN: {
out = instr->min(inputs[0], inputs[1]);
}
break;
case TGSI_OPCODE_MAX: {
out = instr->max(inputs[0], inputs[1]);
}
break;
case TGSI_OPCODE_SLT: {
@@ -740,6 +744,7 @@ translate_instructionir(llvm::Module *module,
}
break;
case TGSI_OPCODE_SUB: {
out = instr->sub(inputs[0], inputs[1]);
}
break;
case TGSI_OPCODE_LERP: {
@@ -781,6 +786,7 @@ translate_instructionir(llvm::Module *module,
case TGSI_OPCODE_MULTIPLYMATRIX:
break;
case TGSI_OPCODE_ABS: {
out = instr->abs(inputs[0]);
}
break;
case TGSI_OPCODE_RCC:
@@ -330,3 +330,18 @@ tgsi_num_tokens(const struct tgsi_token *tokens)
}
return 0;
}
/**
* Make a new copy of a token array.
*/
struct tgsi_token *
tgsi_dup_tokens(const struct tgsi_token *tokens)
{
unsigned n = tgsi_num_tokens(tokens);
unsigned bytes = n * sizeof(struct tgsi_token);
struct tgsi_token *new_tokens = (struct tgsi_token *) MALLOC(bytes);
if (new_tokens)
memcpy(new_tokens, tokens, bytes);
return new_tokens;
}
+30 -1
View File
@@ -1,4 +1,31 @@
#if !defined TGSI_PARSE_H
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef TGSI_PARSE_H
#define TGSI_PARSE_H
#include "pipe/p_shader_tokens.h"
@@ -118,6 +145,8 @@ tgsi_parse_token(
unsigned
tgsi_num_tokens(const struct tgsi_token *tokens);
struct tgsi_token *
tgsi_dup_tokens(const struct tgsi_token *tokens);
#if defined __cplusplus
}
@@ -30,33 +30,50 @@
#include "pipe/p_inlines.h"
#include "pipe/p_winsys.h"
#include "draw/draw_context.h"
#if 0
#include "pipe/p_shader_tokens.h"
#include "gallivm/gallivm.h"
#include "tgsi/util/tgsi_dump.h"
#include "tgsi/exec/tgsi_sse2.h"
#endif
#include "tgsi/util/tgsi_parse.h"
#include "cell_context.h"
#include "cell_state.h"
/** cast wrapper */
static INLINE struct cell_fragment_shader_state *
cell_fragment_shader_state(void *shader)
{
return (struct pipe_shader_state *) shader;
}
/** cast wrapper */
static INLINE struct cell_vertex_shader_state *
cell_vertex_shader_state(void *shader)
{
return (struct pipe_shader_state *) shader;
}
static void *
cell_create_fs_state(struct pipe_context *pipe,
const struct pipe_shader_state *templ)
{
/*struct cell_context *cell = cell_context(pipe);*/
struct cell_fragment_shader_state *state;
struct cell_fragment_shader_state *cfs;
state = CALLOC_STRUCT(cell_fragment_shader_state);
if (!state)
cfs = CALLOC_STRUCT(cell_fragment_shader_state);
if (!cfs)
return NULL;
state->shader = *templ;
cfs->shader.tokens = tgsi_dup_tokens(templ->tokens);
if (!cfs->shader.tokens) {
FREE(cfs);
return NULL;
}
tgsi_scan_shader(templ->tokens, &state->info);
tgsi_scan_shader(templ->tokens, &cfs->info);
return state;
return cfs;
}
@@ -65,7 +82,7 @@ cell_bind_fs_state(struct pipe_context *pipe, void *fs)
{
struct cell_context *cell = cell_context(pipe);
cell->fs = (struct cell_fragment_shader_state *) fs;
cell->fs = cell_fragment_shader_state(fs);
cell->dirty |= CELL_NEW_FS;
}
@@ -74,10 +91,10 @@ cell_bind_fs_state(struct pipe_context *pipe, void *fs)
static void
cell_delete_fs_state(struct pipe_context *pipe, void *fs)
{
struct cell_fragment_shader_state *state =
(struct cell_fragment_shader_state *) fs;
struct cell_fragment_shader_state *cfs = cell_fragment_shader_state(fs);
FREE( state );
FREE((void *) cfs->shader.tokens);
FREE(cfs);
}
@@ -86,22 +103,28 @@ cell_create_vs_state(struct pipe_context *pipe,
const struct pipe_shader_state *templ)
{
struct cell_context *cell = cell_context(pipe);
struct cell_vertex_shader_state *state;
struct cell_vertex_shader_state *cvs;
state = CALLOC_STRUCT(cell_vertex_shader_state);
if (!state)
cvs = CALLOC_STRUCT(cell_vertex_shader_state);
if (!cvs)
return NULL;
state->shader = *templ;
tgsi_scan_shader(templ->tokens, &state->info);
state->draw_data = draw_create_vertex_shader(cell->draw, &state->shader);
if (state->draw_data == NULL) {
FREE( state );
cvs->shader.tokens = tgsi_dup_tokens(templ->tokens);
if (!cvs->shader.tokens) {
FREE(cvs);
return NULL;
}
return state;
tgsi_scan_shader(templ->tokens, &cvs->info);
cvs->draw_data = draw_create_vertex_shader(cell->draw, &cvs->shader);
if (cvs->draw_data == NULL) {
FREE( (void *) cvs->shader.tokens );
FREE( cvs );
return NULL;
}
return cvs;
}
@@ -110,7 +133,7 @@ cell_bind_vs_state(struct pipe_context *pipe, void *vs)
{
struct cell_context *cell = cell_context(pipe);
cell->vs = (const struct cell_vertex_shader_state *) vs;
cell->vs = cell_vertex_shader_state(vs);
draw_bind_vertex_shader(cell->draw,
(cell->vs ? cell->vs->draw_data : NULL));
@@ -123,12 +146,11 @@ static void
cell_delete_vs_state(struct pipe_context *pipe, void *vs)
{
struct cell_context *cell = cell_context(pipe);
struct cell_vertex_shader_state *cvs = cell_vertex_shader_state(vs);
struct cell_vertex_shader_state *state =
(struct cell_vertex_shader_state *) vs;
draw_delete_vertex_shader(cell->draw, state->draw_data);
FREE( state );
draw_delete_vertex_shader(cell->draw, cvs->draw_data);
FREE( (void *) cvs->shader.tokens );
FREE( cvs );
}
+10 -1
View File
@@ -33,6 +33,7 @@
#include "pipe/p_winsys.h"
#include "pipe/p_util.h"
#include "pipe/p_inlines.h"
#include "tgsi/util/tgsi_parse.h"
#include "i915_context.h"
#include "i915_reg.h"
@@ -436,7 +437,7 @@ i915_create_fs_state(struct pipe_context *pipe,
if (!ifs)
return NULL;
ifs->state = *templ;
ifs->state.tokens = tgsi_dup_tokens(templ->tokens);
tgsi_scan_shader(templ->tokens, &ifs->info);
@@ -465,6 +466,8 @@ void i915_delete_fs_state(struct pipe_context *pipe, void *shader)
FREE(ifs->program);
ifs->program_len = 0;
FREE(ifs->state.tokens);
FREE(ifs);
}
@@ -714,10 +717,16 @@ static void i915_set_vertex_elements(struct pipe_context *pipe,
}
static void i915_set_edgeflags(struct pipe_context *pipe,
const unsigned *bitfield)
{
/* TODO do something here */
}
void
i915_init_state_functions( struct i915_context *i915 )
{
i915->pipe.set_edgeflags = i915_set_edgeflags;
i915->pipe.create_blend_state = i915_create_blend_state;
i915->pipe.bind_blend_state = i915_bind_blend_state;
i915->pipe.delete_blend_state = i915_delete_blend_state;
+11 -8
View File
@@ -35,6 +35,7 @@
#include "pipe/p_inlines.h"
#include "pipe/p_shader_tokens.h"
#include "tgsi/util/tgsi_dump.h"
#include "tgsi/util/tgsi_parse.h"
#include "brw_context.h"
#include "brw_defines.h"
@@ -182,9 +183,7 @@ static void * brw_create_fs_state(struct pipe_context *pipe,
{
struct brw_fragment_program *brw_fp = CALLOC_STRUCT(brw_fragment_program);
/* XXX: Do I have to duplicate the tokens as well??
*/
brw_fp->program = *shader;
brw_fp->program.tokens = tgsi_dup_tokens(shader->tokens);
brw_fp->id = brw_context(pipe)->program_id++;
tgsi_scan_shader(shader->tokens, &brw_fp->info);
@@ -210,7 +209,10 @@ static void brw_bind_fs_state(struct pipe_context *pipe, void *shader)
static void brw_delete_fs_state(struct pipe_context *pipe, void *shader)
{
FREE(shader);
struct brw_fragment_program *brw_fp = (struct brw_fragment_program *) shader;
FREE((void *) brw_fp->program.tokens);
FREE(brw_fp);
}
@@ -223,9 +225,7 @@ static void *brw_create_vs_state(struct pipe_context *pipe,
{
struct brw_vertex_program *brw_vp = CALLOC_STRUCT(brw_vertex_program);
/* XXX: Do I have to duplicate the tokens as well??
*/
brw_vp->program = *shader;
brw_vp->program.tokens = tgsi_dup_tokens(shader->tokens);
brw_vp->id = brw_context(pipe)->program_id++;
tgsi_scan_shader(shader->tokens, &brw_vp->info);
@@ -251,7 +251,10 @@ static void brw_bind_vs_state(struct pipe_context *pipe, void *vs)
static void brw_delete_vs_state(struct pipe_context *pipe, void *shader)
{
FREE(shader);
struct brw_vertex_program *brw_vp = (struct brw_vertex_program *) shader;
FREE((void *) brw_vp->program.tokens);
FREE(brw_vp);
}
+4 -1
View File
@@ -37,6 +37,7 @@
#include "pipe/p_util.h"
#include "pipe/p_inlines.h"
#include "tgsi/exec/tgsi_exec.h"
#include "tgsi/util/tgsi_parse.h"
struct sp_exec_fragment_shader {
struct sp_fragment_shader base;
@@ -116,6 +117,7 @@ exec_run( const struct sp_fragment_shader *base,
static void
exec_delete( struct sp_fragment_shader *base )
{
FREE((void *) base->shader.tokens);
FREE(base);
}
@@ -137,7 +139,8 @@ softpipe_create_fs_exec(struct softpipe_context *softpipe,
if (!shader)
return NULL;
shader->base.shader = *templ;
/* we need to keep a local copy of the tokens */
shader->base.shader.tokens = tgsi_dup_tokens(templ->tokens);
shader->base.prepare = exec_prepare;
shader->base.run = exec_run;
shader->base.delete = exec_delete;
+5 -1
View File
@@ -139,7 +139,11 @@ softpipe_create_fs_sse(struct softpipe_context *softpipe,
}
shader->func = (codegen_function) x86_get_func( &shader->sse2_program );
assert(shader->func);
if (!shader->func) {
x86_release_func( &shader->sse2_program );
FREE(shader);
return NULL;
}
shader->base.shader = *templ;
shader->base.prepare = fs_sse_prepare;
+4 -3
View File
@@ -54,9 +54,11 @@
struct tgsi_sampler;
struct tgsi_exec_machine;
struct vertex_info;
/** Subclass of pipe_shader_state (though it doesn't really need to be).
/**
* Subclass of pipe_shader_state (though it doesn't really need to be).
*
* This is starting to look an awful lot like a quad pipeline stage...
*/
@@ -80,11 +82,10 @@ struct sp_fragment_shader {
void (*delete)( struct sp_fragment_shader * );
};
struct vertex_info;
/** Subclass of pipe_shader_state */
struct sp_vertex_shader {
struct pipe_shader_state shader;
struct pipe_shader_state shader; /* Note: this field not actually used */
struct draw_vertex_shader *draw_data;
};
+1 -4
View File
@@ -102,10 +102,7 @@ softpipe_create_vs_state(struct pipe_context *pipe,
return NULL;
}
state->shader = *templ;
state->draw_data = draw_create_vertex_shader(softpipe->draw,
&state->shader);
state->draw_data = draw_create_vertex_shader(softpipe->draw, templ);
if (state->draw_data == NULL) {
FREE( state );
return NULL;
-8
View File
@@ -327,14 +327,6 @@ enum pipe_format {
};
/** XXX remove these deprecated names */
#define PIPE_FORMAT_U_L8 PIPE_FORMAT_L8_UNORM
#define PIPE_FORMAT_U_A8 PIPE_FORMAT_A8_UNORM
#define PIPE_FORMAT_U_I8 PIPE_FORMAT_I8_UNORM
#define PIPE_FORMAT_U_A8_L8 PIPE_FORMAT_A8L8_UNORM
#define PIPE_FORMAT_U_S8 PIPE_FORMAT_S8_UNORM
/**
* Builds pipe format name from format token.
*/
+3
View File
@@ -204,7 +204,10 @@ mem_dup(const void *src, uint size)
#define MIN2( A, B ) ( (A)<(B) ? (A) : (B) )
#define MAX2( A, B ) ( (A)>(B) ? (A) : (B) )
/* JB stop warnings */
#ifndef Elements
#define Elements(x) (sizeof(x)/sizeof((x)[0]))
#endif
#define Offset(TYPE, MEMBER) ((unsigned)&(((TYPE *)NULL)->MEMBER))
/**
+6 -3
View File
@@ -2,7 +2,7 @@
TOP = ../../../../..
include $(TOP)/configs/current
LIBNAME = i915tex_dri.so
LIBNAME = i915_dri.so
MINIGLX_SOURCES = server/intel_dri.c
@@ -19,11 +19,14 @@ DRIVER_SOURCES = \
intel_context.c \
intel_lock.c \
intel_screen.c \
intel_batchpool.c
ws_dri_bufmgr.c \
ws_dri_drmpool.c \
ws_dri_fencemgr.c \
ws_dri_mallocpool.c \
ws_dri_slabpool.c
C_SOURCES = \
$(COMMON_GALLIUM_SOURCES) \
$(COMMON_BM_SOURCES) \
$(DRIVER_SOURCES)
ASM_SOURCES =
+295 -193
View File
@@ -25,108 +25,95 @@
*
**************************************************************************/
#include <errno.h>
#include <stdio.h>
#include "intel_batchbuffer.h"
#include "intel_context.h"
#include "intel_screen.h"
#include "intel_reg.h"
#include "drm.h"
/* Relocations in kernel space:
* - pass dma buffer seperately
* - memory manager knows how to patch
* - pass list of dependent buffers
* - pass relocation list
*
* Either:
* - get back an offset for buffer to fire
* - memory manager knows how to fire buffer
*
* Really want the buffer to be AGP and pinned.
*
*/
/* Cliprect fence: The highest fence protecting a dma buffer
* containing explicit cliprect information. Like the old drawable
* lock but irq-driven. X server must wait for this fence to expire
* before changing cliprects [and then doing sw rendering?]. For
* other dma buffers, the scheduler will grab current cliprect info
* and mix into buffer. X server must hold the lock while changing
* cliprects??? Make per-drawable. Need cliprects in shared memory
* -- beats storing them with every cmd buffer in the queue.
*
* ==> X server must wait for this fence to expire before touching the
* framebuffer with new cliprects.
*
* ==> Cliprect-dependent buffers associated with a
* cliprect-timestamp. All of the buffers associated with a timestamp
* must go to hardware before any buffer with a newer timestamp.
*
* ==> Dma should be queued per-drawable for correct X/GL
* synchronization. Or can fences be used for this?
*
* Applies to: Blit operations, metaops, X server operations -- X
* server automatically waits on its own dma to complete before
* modifying cliprects ???
*/
#include <errno.h>
#if 0
static void
intel_dump_batchbuffer(uint offset, uint * ptr, uint count)
intel_dump_batchbuffer(GLuint offset, GLuint * ptr, GLuint count)
{
int i;
printf("\n\n\nSTART BATCH (%d dwords):\n", count / 4);
for (i = 0; i < count / 4; i += 1)
printf("\t0x%08x\n", ptr[i]);
printf("END BATCH\n\n\n");
fprintf(stderr, "\n\n\nSTART BATCH (%d dwords):\n", count / 4);
for (i = 0; i < count / 4; i += 4)
fprintf(stderr, "0x%x:\t0x%08x 0x%08x 0x%08x 0x%08x\n",
offset + i * 4, ptr[i], ptr[i + 1], ptr[i + 2], ptr[i + 3]);
fprintf(stderr, "END BATCH\n\n\n");
}
#endif
static void
intel_realloc_relocs(struct intel_batchbuffer *batch, int num_relocs)
{
unsigned long size = num_relocs * I915_RELOC0_STRIDE + I915_RELOC_HEADER;
size *= sizeof(uint32_t);
batch->reloc = realloc(batch->reloc, size);
batch->reloc_size = num_relocs;
}
void
intel_batchbuffer_reset(struct intel_batchbuffer *batch)
{
int i;
if (batch->map) {
driBOUnmap(batch->buffer);
batch->map = NULL;
}
/*
* Get a new, free batchbuffer.
*/
batch->size = BATCH_SZ;
driBOData(batch->buffer, batch->size, NULL, 0);
drmBO *bo;
struct drm_bo_info_req *req;
driBOUnrefUserList(batch->list);
driBOResetList(batch->list);
driBOResetList(&batch->list);
batch->size = 4 * 4096; // ZZZ JB batch->intel->intelScreen->maxBatchSize;
driBOData(batch->buffer, batch->size, NULL, NULL, 0);
/*
* Unreference buffers previously on the relocation list.
* Add the batchbuffer to the validate list.
*/
for (i = 0; i < batch->nr_relocs; i++) {
struct buffer_reloc *r = &batch->reloc[i];
driBOUnReference(r->buf);
}
batch->list_count = 0;
batch->nr_relocs = 0;
batch->flags = 0;
driBOAddListItem(batch->list, batch->buffer,
DRM_BO_FLAG_EXE | DRM_BO_FLAG_MEM_TT,
DRM_BO_FLAG_EXE | DRM_BO_MASK_MEM,
&batch->dest_location, &batch->node);
req = &batch->node->bo_arg.d.req.bo_req;
/*
* We don't refcount the batchbuffer itself since we can't destroy it
* while it's on the list.
* Set up information needed for us to make relocations
* relative to the underlying drm buffer objects.
*/
driBOAddListItem(&batch->list, batch->buffer,
DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_EXE,
DRM_BO_MASK_MEM | DRM_BO_FLAG_EXE);
driReadLockKernelBO();
bo = driBOKernel(batch->buffer);
req->presumed_offset = (uint64_t) bo->offset;
req->hint = DRM_BO_HINT_PRESUMED_OFFSET;
batch->drmBOVirtual = (uint8_t *) bo->virtual;
driReadUnlockKernelBO();
/*
* Adjust the relocation buffer size.
*/
if (batch->reloc_size > INTEL_MAX_RELOCS ||
batch->reloc == NULL)
intel_realloc_relocs(batch, INTEL_DEFAULT_RELOCS);
assert(batch->reloc != NULL);
batch->reloc[0] = 0; /* No relocs yet. */
batch->reloc[1] = 1; /* Reloc type 1 */
batch->reloc[2] = 0; /* Only a single relocation list. */
batch->reloc[3] = 0; /* Only a single relocation list. */
batch->map = driBOMap(batch->buffer, DRM_BO_FLAG_WRITE, 0);
batch->poolOffset = driBOPoolOffset(batch->buffer);
batch->ptr = batch->map;
batch->dirty_state = ~0;
batch->nr_relocs = 0;
batch->flags = 0;
batch->id = 0;//batch->intel->intelScreen->batch_id++;
}
/*======================================================================
* Public functions
*/
@@ -141,121 +128,253 @@ intel_batchbuffer_alloc(struct intel_context *intel)
&batch->buffer, 4096,
DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_EXE, 0);
batch->last_fence = NULL;
driBOCreateList(20, &batch->list);
batch->list = driBOCreateList(20);
batch->reloc = NULL;
intel_batchbuffer_reset(batch);
return batch;
}
void
intel_batchbuffer_free(struct intel_batchbuffer *batch)
{
if (batch->last_fence) {
driFenceFinish(batch->last_fence,
DRM_FENCE_TYPE_EXE | DRM_I915_FENCE_TYPE_RW,
GL_FALSE);
driFenceUnReference(batch->last_fence);
batch->last_fence = NULL;
DRM_FENCE_TYPE_EXE, GL_FALSE);
driFenceUnReference(&batch->last_fence);
}
if (batch->map) {
driBOUnmap(batch->buffer);
batch->map = NULL;
}
driBOUnReference(batch->buffer);
driBOFreeList(batch->list);
if (batch->reloc)
free(batch->reloc);
batch->buffer = NULL;
free(batch);
}
static void
intel_batch_ioctl(struct intel_context *intel,
uint start_offset, uint used, boolean allow_unlock)
void
intel_offset_relocation(struct intel_batchbuffer *batch,
unsigned pre_add,
struct _DriBufferObject *driBO,
uint64_t val_flags,
uint64_t val_mask)
{
drmI830BatchBuffer batch;
int itemLoc;
struct _drmBONode *node;
uint32_t *reloc;
struct drm_bo_info_req *req;
driBOAddListItem(batch->list, driBO, val_flags, val_mask,
&itemLoc, &node);
req = &node->bo_arg.d.req.bo_req;
batch.start = start_offset;
batch.used = used;
batch.cliprects = NULL; /* unused */
batch.num_cliprects = 0;
batch.DR1 = 0;
batch.DR4 = 0; /* still need this ? */
if (!(req->hint & DRM_BO_HINT_PRESUMED_OFFSET)) {
DBG(IOCTL, "%s: 0x%x..0x%x DR4: %x cliprects: %d\n",
__FUNCTION__,
batch.start,
batch.start + batch.used * 4, batch.DR4, batch.num_cliprects);
/*
* Stop other threads from tampering with the underlying
* drmBO while we're reading its offset.
*/
if (drmCommandWrite(intel->driFd, DRM_I830_BATCHBUFFER, &batch,
sizeof(batch))) {
printf("DRM_I830_BATCHBUFFER: %d\n", -errno);
UNLOCK_HARDWARE(intel);
exit(1);
}
driReadLockKernelBO();
req->presumed_offset = (uint64_t) driBOKernel(driBO)->offset;
driReadUnlockKernelBO();
req->hint = DRM_BO_HINT_PRESUMED_OFFSET;
}
pre_add += driBOPoolOffset(driBO);
if (batch->nr_relocs == batch->reloc_size)
intel_realloc_relocs(batch, batch->reloc_size * 2);
reloc = batch->reloc +
(I915_RELOC_HEADER + batch->nr_relocs * I915_RELOC0_STRIDE);
reloc[0] = ((uint8_t *)batch->ptr - batch->drmBOVirtual);
intel_batchbuffer_emit_dword(batch, req->presumed_offset + pre_add);
reloc[1] = pre_add;
reloc[2] = itemLoc;
reloc[3] = batch->dest_location;
batch->nr_relocs++;
}
static void
i915_drm_copy_reply(const struct drm_bo_info_rep * rep, drmBO * buf)
{
buf->handle = rep->handle;
buf->flags = rep->flags;
buf->size = rep->size;
buf->offset = rep->offset;
buf->mapHandle = rep->arg_handle;
buf->proposedFlags = rep->proposed_flags;
buf->start = rep->buffer_start;
buf->fenceFlags = rep->fence_flags;
buf->replyFlags = rep->rep_flags;
buf->pageAlignment = rep->page_alignment;
}
static int
i915_execbuf(struct intel_batchbuffer *batch,
GLuint used,
GLboolean ignore_cliprects,
drmBOList *list,
struct drm_i915_execbuffer *ea)
{
struct intel_context *intel = batch->intel;
drmBONode *node;
drmMMListHead *l;
struct drm_i915_op_arg *arg, *first;
struct drm_bo_op_req *req;
struct drm_bo_info_rep *rep;
uint64_t *prevNext = NULL;
drmBO *buf;
int ret = 0;
uint32_t count = 0;
first = NULL;
for (l = list->list.next; l != &list->list; l = l->next) {
node = DRMLISTENTRY(drmBONode, l, head);
arg = &node->bo_arg;
req = &arg->d.req;
if (!first)
first = arg;
if (prevNext)
*prevNext = (unsigned long)arg;
prevNext = &arg->next;
req->bo_req.handle = node->buf->handle;
req->op = drm_bo_validate;
req->bo_req.flags = node->arg0;
req->bo_req.mask = node->arg1;
req->bo_req.hint |= 0;
count++;
}
memset(ea, 0, sizeof(*ea));
ea->num_buffers = count;
ea->batch.start = batch->poolOffset;
ea->batch.used = used;
#if 0 /* ZZZ JB: no cliprects used */
ea->batch.cliprects = intel->pClipRects;
ea->batch.num_cliprects = ignore_cliprects ? 0 : intel->numClipRects;
ea->batch.DR1 = 0;
ea->batch.DR4 = 0;((((GLuint) intel->drawX) & 0xffff) |
(((GLuint) intel->drawY) << 16));
#else
ea->batch.cliprects = NULL;
ea->batch.num_cliprects = 0;
ea->batch.DR1 = 0;
ea->batch.DR4 = 0;
#endif
ea->fence_arg.flags = DRM_I915_FENCE_FLAG_FLUSHED;
ea->ops_list = (unsigned long) first;
first->reloc_ptr = (unsigned long) batch->reloc;
batch->reloc[0] = batch->nr_relocs;
//return -EFAULT;
do {
ret = drmCommandWriteRead(intel->driFd, DRM_I915_EXECBUFFER, ea,
sizeof(*ea));
} while (ret == -EAGAIN);
if (ret != 0)
return ret;
for (l = list->list.next; l != &list->list; l = l->next) {
node = DRMLISTENTRY(drmBONode, l, head);
arg = &node->bo_arg;
rep = &arg->d.rep.bo_info;
if (!arg->handled) {
return -EFAULT;
}
if (arg->d.rep.ret)
return arg->d.rep.ret;
buf = node->buf;
i915_drm_copy_reply(rep, buf);
}
return 0;
}
/* TODO: Push this whole function into bufmgr.
*/
static void
static struct _DriFenceObject *
do_flush_locked(struct intel_batchbuffer *batch,
uint used, boolean allow_unlock)
GLuint used,
GLboolean ignore_cliprects, GLboolean allow_unlock)
{
uint *ptr;
uint i, fenceFlags;
struct intel_context *intel = batch->intel;
struct _DriFenceObject *fo;
drmFence fence;
drmBOList *boList;
struct drm_i915_execbuffer ea;
int ret = 0;
driBOValidateList(batch->intel->driFd, &batch->list);
driBOValidateUserList(batch->list);
boList = driGetdrmBOList(batch->list);
/* Apply the relocations. This nasty map indicates to me that the
* whole task should be done internally by the memory manager, and
* that dma buffers probably need to be pinned within agp space.
*/
ptr = (uint *) driBOMap(batch->buffer, DRM_BO_FLAG_WRITE,
DRM_BO_HINT_ALLOW_UNFENCED_MAP);
for (i = 0; i < batch->nr_relocs; i++) {
struct buffer_reloc *r = &batch->reloc[i];
ptr[r->offset / 4] = driBOOffset(r->buf) + r->delta;
#if 0 /* ZZZ JB Allways run */
if (!(intel->numClipRects == 0 && !ignore_cliprects)) {
#else
if (1) {
#endif
ret = i915_execbuf(batch, used, ignore_cliprects, boList, &ea);
} else {
driPutdrmBOList(batch->list);
fo = NULL;
goto out;
}
driPutdrmBOList(batch->list);
if (ret)
abort();
if (0)
intel_dump_batchbuffer(0, ptr, used);
if (ea.fence_arg.error != 0) {
driBOUnmap(batch->buffer);
batch->map = NULL;
intel_batch_ioctl(batch->intel,
driBOOffset(batch->buffer),
used, allow_unlock);
/*
* Kernel fencing. The flags tells the kernel that we've
* programmed an MI_FLUSH.
*/
fenceFlags = DRM_I915_FENCE_FLAG_FLUSHED;
fo = driFenceBuffers(batch->intel->driFd, "Batch fence", fenceFlags);
/*
* User space fencing.
*/
driBOFence(batch->buffer, fo);
if (driFenceType(fo) == DRM_FENCE_TYPE_EXE) {
/*
* Oops. We only validated a batch buffer. This means we
* didn't do any proper rendering. Discard this fence object.
* The hardware has been idled by the kernel.
* Don't fence the driBOs.
*/
driFenceUnReference(fo);
}
else {
driFenceUnReference(batch->last_fence);
batch->last_fence = fo;
for (i = 0; i < batch->nr_relocs; i++) {
struct buffer_reloc *r = &batch->reloc[i];
driBOFence(r->buf, fo);
}
if (batch->last_fence)
driFenceUnReference(&batch->last_fence);
#if 0 /* ZZZ JB: no _mesa_* funcs in gallium */
_mesa_printf("fence error\n");
#endif
batch->last_fence = NULL;
fo = NULL;
goto out;
}
fence.handle = ea.fence_arg.handle;
fence.fence_class = ea.fence_arg.fence_class;
fence.type = ea.fence_arg.type;
fence.flags = ea.fence_arg.flags;
fence.signaled = ea.fence_arg.signaled;
fo = driBOFenceUserList(batch->intel->intelScreen->mgr, batch->list,
"SuperFence", &fence);
if (driFenceType(fo) & DRM_I915_FENCE_TYPE_RW) {
if (batch->last_fence)
driFenceUnReference(&batch->last_fence);
/*
* FIXME: Context last fence??
*/
batch->last_fence = fo;
driFenceReference(fo);
}
out:
#if 0 /* ZZZ JB: fix this */
intel->vtbl.lost_hardware(intel);
#else
(void)intel;
#endif
return fo;
}
@@ -263,29 +382,43 @@ struct _DriFenceObject *
intel_batchbuffer_flush(struct intel_batchbuffer *batch)
{
struct intel_context *intel = batch->intel;
uint used = batch->ptr - batch->map;
const boolean was_locked = intel->locked;
GLuint used = batch->ptr - batch->map;
GLboolean was_locked = intel->locked;
struct _DriFenceObject *fence;
if (used == 0)
if (used == 0) {
driFenceReference(batch->last_fence);
return batch->last_fence;
#define MI_FLUSH ((0 << 29) | (4 << 23))
}
/* Add the MI_BATCH_BUFFER_END. Always add an MI_FLUSH - this is a
* performance drain that we would like to avoid.
*/
#if 0 /* ZZZ JB: what should we do here? */
if (used & 4) {
((int *) batch->ptr)[0] = MI_FLUSH;
((int *) batch->ptr)[0] = intel->vtbl.flush_cmd();
((int *) batch->ptr)[1] = 0;
((int *) batch->ptr)[2] = MI_BATCH_BUFFER_END;
used += 12;
}
else {
((int *) batch->ptr)[0] = MI_FLUSH;
((int *) batch->ptr)[0] = intel->vtbl.flush_cmd();
((int *) batch->ptr)[1] = MI_BATCH_BUFFER_END;
used += 8;
}
#else
if (used & 4) {
((int *) batch->ptr)[0] = ((0<<29)|(4<<23)); // MI_FLUSH;
((int *) batch->ptr)[1] = 0;
((int *) batch->ptr)[2] = (0xA<<23); // MI_BATCH_BUFFER_END;
used += 12;
}
else {
((int *) batch->ptr)[0] = ((0<<29)|(4<<23)); // MI_FLUSH;
((int *) batch->ptr)[1] = (0xA<<23); // MI_BATCH_BUFFER_END;
used += 8;
}
#endif
driBOUnmap(batch->buffer);
batch->ptr = NULL;
batch->map = NULL;
@@ -296,7 +429,8 @@ intel_batchbuffer_flush(struct intel_batchbuffer *batch)
if (!was_locked)
LOCK_HARDWARE(intel);
do_flush_locked(batch, used, GL_FALSE);
fence = do_flush_locked(batch, used, !(batch->flags & INTEL_BATCH_CLIPRECTS),
GL_FALSE);
if (!was_locked)
UNLOCK_HARDWARE(intel);
@@ -304,52 +438,20 @@ intel_batchbuffer_flush(struct intel_batchbuffer *batch)
/* Reset the buffer:
*/
intel_batchbuffer_reset(batch);
return batch->last_fence;
return fence;
}
void
intel_batchbuffer_finish(struct intel_batchbuffer *batch)
{
struct _DriFenceObject *fence = intel_batchbuffer_flush(batch);
if (fence) {
driFenceReference(fence);
driFenceFinish(fence,
DRM_FENCE_TYPE_EXE | DRM_I915_FENCE_TYPE_RW,
GL_FALSE);
driFenceUnReference(fence);
}
driFenceFinish(fence, driFenceType(fence), GL_FALSE);
driFenceUnReference(&fence);
}
/* This is the only way buffers get added to the validate list.
*/
boolean
intel_batchbuffer_emit_reloc(struct intel_batchbuffer *batch,
struct _DriBufferObject *buffer,
uint flags, uint mask, uint delta)
{
assert(batch->nr_relocs < MAX_RELOCS);
driBOAddListItem(&batch->list, buffer, flags, mask);
{
struct buffer_reloc *r = &batch->reloc[batch->nr_relocs++];
driBOReference(buffer);
r->buf = buffer;
r->offset = batch->ptr - batch->map;
r->delta = delta;
*(uint *) batch->ptr = 0x12345678;
}
batch->ptr += 4;
return GL_TRUE;
}
void
intel_batchbuffer_data(struct intel_batchbuffer *batch,
const void *data, uint bytes, uint flags)
const void *data, GLuint bytes, GLuint flags)
{
assert((bytes & 3) == 0);
intel_batchbuffer_require_space(batch, bytes, flags);
@@ -1,54 +1,20 @@
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#ifndef INTEL_BATCHBUFFER_H
#define INTEL_BATCHBUFFER_H
#include "pipe/p_debug.h"
#include "pipe/p_compiler.h"
#include "dri_bufmgr.h"
#include "mtypes.h"
#include "ws_dri_bufmgr.h"
struct intel_context;
#define BATCH_SZ 16384
#define BATCH_RESERVED 16
#define MAX_RELOCS 4096
#define INTEL_DEFAULT_RELOCS 100
#define INTEL_MAX_RELOCS 400
#define INTEL_BATCH_NO_CLIPRECTS 0x1
#define INTEL_BATCH_CLIPRECTS 0x2
struct buffer_reloc
{
struct _DriBufferObject *buf;
uint offset;
uint delta; /* not needed? */
};
struct intel_batchbuffer
{
struct bufmgr *bm;
@@ -56,19 +22,30 @@ struct intel_batchbuffer
struct _DriBufferObject *buffer;
struct _DriFenceObject *last_fence;
uint flags;
GLuint flags;
drmBOList list;
uint list_count;
ubyte *map;
ubyte *ptr;
struct _DriBufferList *list;
GLuint list_count;
GLubyte *map;
GLubyte *ptr;
struct buffer_reloc reloc[MAX_RELOCS];
uint nr_relocs;
uint size;
uint32_t *reloc;
GLuint reloc_size;
GLuint nr_relocs;
GLuint size;
GLuint dirty_state;
GLuint id;
uint32_t poolOffset;
uint8_t *drmBOVirtual;
struct _drmBONode *node; /* Validation list node for this buffer */
int dest_location; /* Validation list sequence for this buffer */
};
struct intel_batchbuffer *intel_batchbuffer_alloc(struct intel_context *intel);
struct intel_batchbuffer *intel_batchbuffer_alloc(struct intel_context
*intel);
void intel_batchbuffer_free(struct intel_batchbuffer *batch);
@@ -82,26 +59,28 @@ void intel_batchbuffer_reset(struct intel_batchbuffer *batch);
/* Unlike bmBufferData, this currently requires the buffer be mapped.
* Consider it a convenience function wrapping multiple
* Consider it a convenience function wrapping multple
* intel_buffer_dword() calls.
*/
void intel_batchbuffer_data(struct intel_batchbuffer *batch,
const void *data, uint bytes, uint flags);
const void *data, GLuint bytes, GLuint flags);
void intel_batchbuffer_release_space(struct intel_batchbuffer *batch,
uint bytes);
GLuint bytes);
boolean intel_batchbuffer_emit_reloc(struct intel_batchbuffer *batch,
struct _DriBufferObject *buffer,
uint flags,
uint mask, uint offset);
void
intel_offset_relocation(struct intel_batchbuffer *batch,
unsigned pre_add,
struct _DriBufferObject *driBO,
uint64_t val_flags,
uint64_t val_mask);
/* Inline functions - might actually be better off with these
* non-inlined. Certainly better off switching all command packets to
* be passed as structs rather than dwords, but that's a little bit of
* work...
*/
static INLINE uint
static INLINE GLuint
intel_batchbuffer_space(struct intel_batchbuffer *batch)
{
return (batch->size - BATCH_RESERVED) - (batch->ptr - batch->map);
@@ -109,22 +88,26 @@ intel_batchbuffer_space(struct intel_batchbuffer *batch)
static INLINE void
intel_batchbuffer_emit_dword(struct intel_batchbuffer *batch, uint dword)
intel_batchbuffer_emit_dword(struct intel_batchbuffer *batch, GLuint dword)
{
assert(batch->map);
assert(intel_batchbuffer_space(batch) >= 4);
*(uint *) (batch->ptr) = dword;
*(GLuint *) (batch->ptr) = dword;
batch->ptr += 4;
}
static INLINE void
intel_batchbuffer_require_space(struct intel_batchbuffer *batch,
uint sz, uint flags)
GLuint sz, GLuint flags)
{
struct _DriFenceObject *fence;
assert(sz < batch->size - 8);
if (intel_batchbuffer_space(batch) < sz ||
(batch->flags != 0 && flags != 0 && batch->flags != flags))
intel_batchbuffer_flush(batch);
(batch->flags != 0 && flags != 0 && batch->flags != flags)) {
fence = intel_batchbuffer_flush(batch);
driFenceUnReference(&fence);
}
batch->flags |= flags;
}
@@ -134,14 +117,15 @@ intel_batchbuffer_require_space(struct intel_batchbuffer *batch,
#define BATCH_LOCALS
#define BEGIN_BATCH(n, flags) do { \
assert(!intel->prim.flush); \
intel_batchbuffer_require_space(intel->batch, (n)*4, flags); \
} while (0)
#define OUT_BATCH(d) intel_batchbuffer_emit_dword(intel->batch, d)
#define OUT_RELOC(buf,flags,mask,delta) do { \
assert((delta) >= 0); \
intel_batchbuffer_emit_reloc(intel->batch, buf, flags, mask, delta); \
assert((delta) >= 0); \
intel_offset_relocation(intel->batch, delta, buf, flags, mask); \
} while (0)
#define ADVANCE_BATCH() do { } while(0)
@@ -1,427 +0,0 @@
/**************************************************************************
*
* 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: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
*/
/**
* XXX NOTE: there are no intel dependencies in this file.
* Rename to dri_batchpool.c?
*/
#include <xf86drm.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include "pipe/p_compiler.h"
#include "pipe/p_thread.h"
#include "dri_bufpool.h"
#include "dri_bufmgr.h"
#include "intel_batchpool.h"
typedef struct
{
drmMMListHead head;
struct _BPool *parent;
struct _DriFenceObject *fence;
unsigned long start;
int unfenced;
int mapped;
} BBuf;
typedef struct _BPool
{
_glthread_Mutex mutex;
unsigned long bufSize;
unsigned poolSize;
unsigned numFree;
unsigned numTot;
unsigned numDelayed;
unsigned checkDelayed;
drmMMListHead free;
drmMMListHead delayed;
drmMMListHead head;
drmBO kernelBO;
void *virtual;
BBuf *bufs;
} BPool;
static BPool *
createBPool(int fd, unsigned long bufSize, unsigned numBufs, unsigned flags,
unsigned checkDelayed)
{
BPool *p = (BPool *) malloc(sizeof(*p));
BBuf *buf;
int i;
if (!p)
return NULL;
p->bufs = (BBuf *) malloc(numBufs * sizeof(*p->bufs));
if (!p->bufs) {
free(p);
return NULL;
}
DRMINITLISTHEAD(&p->free);
DRMINITLISTHEAD(&p->head);
DRMINITLISTHEAD(&p->delayed);
p->numTot = numBufs;
p->numFree = numBufs;
p->bufSize = bufSize;
p->numDelayed = 0;
p->checkDelayed = checkDelayed;
_glthread_INIT_MUTEX(p->mutex);
if (drmBOCreate(fd, 0, numBufs * bufSize, 0, NULL, drm_bo_type_dc,
flags, DRM_BO_HINT_DONT_FENCE, &p->kernelBO)) {
free(p->bufs);
free(p);
return NULL;
}
if (drmBOMap(fd, &p->kernelBO, DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0,
&p->virtual)) {
drmBODestroy(fd, &p->kernelBO);
free(p->bufs);
free(p);
return NULL;
}
/*
* We unmap the buffer so that we can validate it later. Note that this is
* just a synchronizing operation. The buffer will have a virtual mapping
* until it is destroyed.
*/
drmBOUnmap(fd, &p->kernelBO);
buf = p->bufs;
for (i = 0; i < numBufs; ++i) {
buf->parent = p;
buf->fence = NULL;
buf->start = i * bufSize;
buf->mapped = 0;
buf->unfenced = 0;
DRMLISTADDTAIL(&buf->head, &p->free);
buf++;
}
return p;
}
static void
pool_checkFree(BPool * p, int wait)
{
drmMMListHead *list, *prev;
BBuf *buf;
int signaled = 0;
int i;
list = p->delayed.next;
if (p->numDelayed > 3) {
for (i = 0; i < p->numDelayed; i += 3) {
list = list->next;
}
}
prev = list->prev;
for (; list != &p->delayed; list = prev, prev = list->prev) {
buf = DRMLISTENTRY(BBuf, list, head);
if (!signaled) {
if (wait) {
driFenceFinish(buf->fence, DRM_FENCE_TYPE_EXE, 1);
signaled = 1;
}
else {
signaled = driFenceSignaled(buf->fence, DRM_FENCE_TYPE_EXE);
}
}
if (!signaled)
break;
driFenceUnReference(buf->fence);
buf->fence = NULL;
DRMLISTDEL(list);
p->numDelayed--;
DRMLISTADD(list, &p->free);
p->numFree++;
}
}
static void *
pool_create(struct _DriBufferPool *pool,
unsigned long size, unsigned flags, unsigned hint,
unsigned alignment)
{
BPool *p = (BPool *) pool->data;
drmMMListHead *item;
if (alignment && (alignment != 4096))
return NULL;
_glthread_LOCK_MUTEX(p->mutex);
if (p->numFree == 0)
pool_checkFree(p, TRUE);
if (p->numFree == 0) {
fprintf(stderr, "Out of fixed size buffer objects\n");
BM_CKFATAL(-ENOMEM);
}
item = p->free.next;
if (item == &p->free) {
fprintf(stderr, "Fixed size buffer pool corruption\n");
}
DRMLISTDEL(item);
--p->numFree;
_glthread_UNLOCK_MUTEX(p->mutex);
return (void *) DRMLISTENTRY(BBuf, item, head);
}
static int
pool_destroy(struct _DriBufferPool *pool, void *private)
{
BBuf *buf = (BBuf *) private;
BPool *p = buf->parent;
_glthread_LOCK_MUTEX(p->mutex);
if (buf->fence) {
DRMLISTADDTAIL(&buf->head, &p->delayed);
p->numDelayed++;
}
else {
buf->unfenced = 0;
DRMLISTADD(&buf->head, &p->free);
p->numFree++;
}
if ((p->numDelayed % p->checkDelayed) == 0)
pool_checkFree(p, 0);
_glthread_UNLOCK_MUTEX(p->mutex);
return 0;
}
static int
pool_map(struct _DriBufferPool *pool, void *private, unsigned flags,
int hint, void **virtual)
{
BBuf *buf = (BBuf *) private;
BPool *p = buf->parent;
_glthread_LOCK_MUTEX(p->mutex);
/*
* Currently Mesa doesn't have any condition variables to resolve this
* cleanly in a multithreading environment.
* We bail out instead.
*/
if (buf->mapped) {
fprintf(stderr, "Trying to map already mapped buffer object\n");
BM_CKFATAL(-EINVAL);
}
#if 0
if (buf->unfenced && !(hint & DRM_BO_HINT_ALLOW_UNFENCED_MAP)) {
fprintf(stderr, "Trying to map an unfenced buffer object 0x%08x"
" 0x%08x %d\n", hint, flags, buf->start);
BM_CKFATAL(-EINVAL);
}
#endif
if (buf->fence) {
_glthread_UNLOCK_MUTEX(p->mutex);
return -EBUSY;
}
buf->mapped = TRUE;
*virtual = (unsigned char *) p->virtual + buf->start;
_glthread_UNLOCK_MUTEX(p->mutex);
return 0;
}
static int
pool_waitIdle(struct _DriBufferPool *pool, void *private, int lazy)
{
BBuf *buf = (BBuf *) private;
driFenceFinish(buf->fence, 0x0, lazy);
return 0;
}
static int
pool_unmap(struct _DriBufferPool *pool, void *private)
{
BBuf *buf = (BBuf *) private;
buf->mapped = 0;
return 0;
}
static unsigned long
pool_offset(struct _DriBufferPool *pool, void *private)
{
BBuf *buf = (BBuf *) private;
BPool *p = buf->parent;
return p->kernelBO.offset + buf->start;
}
static unsigned
pool_flags(struct _DriBufferPool *pool, void *private)
{
BPool *p = (BPool *) pool->data;
return p->kernelBO.flags;
}
static unsigned long
pool_size(struct _DriBufferPool *pool, void *private)
{
BPool *p = (BPool *) pool->data;
return p->bufSize;
}
static int
pool_fence(struct _DriBufferPool *pool, void *private,
struct _DriFenceObject *fence)
{
BBuf *buf = (BBuf *) private;
BPool *p = buf->parent;
_glthread_LOCK_MUTEX(p->mutex);
if (buf->fence) {
driFenceUnReference(buf->fence);
}
buf->fence = fence;
buf->unfenced = 0;
driFenceReference(buf->fence);
_glthread_UNLOCK_MUTEX(p->mutex);
return 0;
}
static drmBO *
pool_kernel(struct _DriBufferPool *pool, void *private)
{
BBuf *buf = (BBuf *) private;
BPool *p = buf->parent;
return &p->kernelBO;
}
static int
pool_validate(struct _DriBufferPool *pool, void *private)
{
BBuf *buf = (BBuf *) private;
BPool *p = buf->parent;
_glthread_LOCK_MUTEX(p->mutex);
buf->unfenced = TRUE;
_glthread_UNLOCK_MUTEX(p->mutex);
return 0;
}
static void
pool_takedown(struct _DriBufferPool *pool)
{
BPool *p = (BPool *) pool->data;
/*
* Wait on outstanding fences.
*/
_glthread_LOCK_MUTEX(p->mutex);
while ((p->numFree < p->numTot) && p->numDelayed) {
_glthread_UNLOCK_MUTEX(p->mutex);
sched_yield();
pool_checkFree(p, TRUE);
_glthread_LOCK_MUTEX(p->mutex);
}
drmBODestroy(pool->fd, &p->kernelBO);
free(p->bufs);
_glthread_UNLOCK_MUTEX(p->mutex);
free(p);
free(pool);
}
struct _DriBufferPool *
driBatchPoolInit(int fd, unsigned flags,
unsigned long bufSize,
unsigned numBufs, unsigned checkDelayed)
{
struct _DriBufferPool *pool;
pool = (struct _DriBufferPool *) malloc(sizeof(*pool));
if (!pool)
return NULL;
pool->data = createBPool(fd, bufSize, numBufs, flags, checkDelayed);
if (!pool->data)
return NULL;
pool->fd = fd;
pool->map = &pool_map;
pool->unmap = &pool_unmap;
pool->destroy = &pool_destroy;
pool->offset = &pool_offset;
pool->flags = &pool_flags;
pool->size = &pool_size;
pool->create = &pool_create;
pool->fence = &pool_fence;
pool->kernel = &pool_kernel;
pool->validate = &pool_validate;
pool->waitIdle = &pool_waitIdle;
pool->setstatic = NULL;
pool->takeDown = &pool_takedown;
return pool;
}
+3 -2
View File
@@ -162,6 +162,7 @@ intelCreateContext(const __GLcontextModes * visual,
* memory pools
*/
DRM_LIGHT_LOCK(sPriv->fd, &sPriv->pSAREA->lock, driContextPriv->hHWContext);
// ZZZ JB should be per screen and not be done per context
havePools = intelCreatePools(sPriv);
DRM_UNLOCK(sPriv->fd, &sPriv->pSAREA->lock, driContextPriv->hHWContext);
if (!havePools)
@@ -234,12 +235,12 @@ intelDestroyContext(__DRIcontextPrivate * driContextPriv)
if (intel->last_swap_fence) {
driFenceFinish(intel->last_swap_fence, DRM_FENCE_TYPE_EXE, GL_TRUE);
driFenceUnReference(intel->last_swap_fence);
driFenceUnReference(&intel->last_swap_fence);
intel->last_swap_fence = NULL;
}
if (intel->first_swap_fence) {
driFenceFinish(intel->first_swap_fence, DRM_FENCE_TYPE_EXE, GL_TRUE);
driFenceUnReference(intel->first_swap_fence);
driFenceUnReference(&intel->first_swap_fence);
intel->first_swap_fence = NULL;
}
+1 -1
View File
@@ -28,7 +28,7 @@
#ifndef INTEL_CONTEXT_H
#define INTEL_CONTEXT_H
#include <stdint.h>
#include "drm.h"
#include "pipe/p_debug.h"
+47 -6
View File
@@ -32,12 +32,12 @@
#include "intel_context.h"
#include "intel_screen.h"
#include "intel_batchbuffer.h"
#include "intel_batchpool.h"
//#include "intel_batchpool.h"
#include "intel_swapbuffers.h"
#include "intel_winsys.h"
#include "i830_dri.h"
#include "dri_bufpool.h"
#include "ws_dri_bufpool.h"
#include "pipe/p_context.h"
#include "state_tracker/st_public.h"
@@ -132,6 +132,7 @@ intelUpdateScreenRotation(__DRIscreenPrivate * sPriv, drmI830Sarea * sarea)
assert( sarea->front_size >=
intelScreen->front.pitch * intelScreen->front.height );
#if 0 /* JB not important */
if (!sarea->front_handle)
return;
@@ -142,30 +143,41 @@ intelUpdateScreenRotation(__DRIscreenPrivate * sPriv, drmI830Sarea * sarea)
fprintf(stderr, "drmMap(frontbuffer) failed!\n");
return;
}
#endif
#if 0 /* JB */
if (intelScreen->staticPool) {
driGenBuffers(intelScreen->staticPool, "static region", 1,
&intelScreen->front.buffer, 64,
DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_NO_MOVE |
DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0);
driBOSetStatic(intelScreen->front.buffer,
intelScreen->front.offset,
intelScreen->front.pitch * intelScreen->front.height,
intelScreen->front.map, 0);
}
#else
if (intelScreen->staticPool) {
if (intelScreen->front.buffer)
driBOUnReference(intelScreen->front.buffer);
driGenBuffers(intelScreen->staticPool, "front", 1, &intelScreen->front.buffer, 0, 0, 0);
driBOSetReferenced(intelScreen->front.buffer, sarea->front_bo_handle);
}
#endif
}
boolean
intelCreatePools(__DRIscreenPrivate * sPriv)
{
unsigned batchPoolSize = 1024*1024;
//unsigned batchPoolSize = 1024*1024;
struct intel_screen *intelScreen = intel_screen(sPriv);
if (intelScreen->havePools)
return GL_TRUE;
#if 0 /* ZZZ JB fix this */
intelScreen->staticPool = driDRMStaticPoolInit(sPriv->fd);
if (!intelScreen->staticPool)
return GL_FALSE;
@@ -181,7 +193,17 @@ intelCreatePools(__DRIscreenPrivate * sPriv)
fprintf(stderr, "Failed to initialize batch pool - possible incorrect agpgart installed\n");
return GL_FALSE;
}
#else
intelScreen->staticPool = driDRMPoolInit(sPriv->fd);
intelScreen->batchPool = driSlabPoolInit(sPriv->fd,
DRM_BO_FLAG_EXE |
DRM_BO_FLAG_MEM_TT,
DRM_BO_FLAG_EXE |
DRM_BO_FLAG_MEM_TT,
4 * 4096, //intelScreen->maxBatchSize,
1, 40, 16*16384, 0,
intelScreen->fMan);
#endif
intelScreen->havePools = GL_TRUE;
intelUpdateScreenRotation(sPriv, intelScreen->sarea);
@@ -240,7 +262,26 @@ intelInitDriver(__DRIscreenPrivate * sPriv)
(*glx_enable_extension) (psc, "GLX_SGI_make_current_read");
}
intelScreen->winsys = intel_create_pipe_winsys(sPriv->fd);
#if 1 // ZZZ JB
intelScreen->mgr = driFenceMgrTTMInit(sPriv->fd);
if (!intelScreen->mgr) {
fprintf(stderr, "Failed to create fence manager.\n");
return GL_FALSE;
}
intelScreen->fMan = driInitFreeSlabManager(10, 10);
if (!intelScreen->fMan) {
fprintf(stderr, "Failed to create free slab manager.\n");
return GL_FALSE;
}
if (!intelCreatePools(sPriv))
return GL_FALSE;
#endif
intelScreen->winsys = intel_create_pipe_winsys(sPriv->fd, intelScreen->fMan);
return GL_TRUE;
}
+8 -1
View File
@@ -31,7 +31,7 @@
#include "dri_util.h"
#include "i830_common.h"
#include "xmlconfig.h"
#include "dri_bufpool.h"
#include "ws_dri_bufpool.h"
#include "pipe/p_compiler.h"
@@ -74,6 +74,13 @@ struct intel_screen
*/
struct intel_context *dummyContext;
/*
* New stuff form the i915tex integration
*/
struct _DriFenceMgr *mgr;
struct _DriFreeSlabManager *fMan;
unsigned batch_id;
struct pipe_winsys *winsys;
};
@@ -63,7 +63,7 @@ intelDisplaySurface(__DRIdrawablePrivate *dPriv,
if (intel->last_swap_fence) {
driFenceFinish(intel->last_swap_fence, DRM_FENCE_TYPE_EXE, TRUE);
driFenceUnReference(intel->last_swap_fence);
driFenceUnReference(&intel->last_swap_fence);
intel->last_swap_fence = NULL;
}
intel->last_swap_fence = intel->first_swap_fence;
@@ -178,9 +178,8 @@ intelDisplaySurface(__DRIdrawablePrivate *dPriv,
}
if (intel->first_swap_fence)
driFenceUnReference(intel->first_swap_fence);
driFenceUnReference(&intel->first_swap_fence);
intel->first_swap_fence = intel_batchbuffer_flush(intel->batch);
driFenceReference(intel->first_swap_fence);
}
UNLOCK_HARDWARE(intel);
+2 -2
View File
@@ -37,7 +37,7 @@ struct pipe_buffer;
struct _DriBufferObject;
struct pipe_winsys *
intel_create_pipe_winsys( int fd );
intel_create_pipe_winsys( int fd, struct _DriFreeSlabManager *fMan );
void
intel_destroy_pipe_winsys( struct pipe_winsys *winsys );
@@ -53,6 +53,7 @@ intel_create_i915simple( struct intel_context *intel,
struct intel_buffer {
struct pipe_buffer base;
struct _DriBufferPool *pool;
struct _DriBufferObject *driBO;
};
@@ -69,5 +70,4 @@ dri_bo( struct pipe_buffer *buf )
}
#endif
@@ -31,8 +31,8 @@
#include <stdlib.h>
#include <xf86drm.h>
#include "dri_bufpool.h"
#include "dri_bufmgr.h"
#include "ws_dri_bufpool.h"
#include "ws_dri_bufmgr.h"
#include "intel_context.h"
#include "intel_batchbuffer.h"
@@ -106,10 +106,18 @@ static void intel_i915_batch_reloc( struct i915_winsys *sws,
mask |= DRM_BO_FLAG_READ;
}
intel_batchbuffer_emit_reloc( intel->batch,
#if 0 /* JB old */
intel_batchbuffer_emit_reloc( intel->batch,
dri_bo( buf ),
flags, mask,
flags, mask,
delta );
#else /* new */
intel_offset_relocation( intel->batch,
delta,
dri_bo( buf ),
flags,
mask );
#endif
}
@@ -124,12 +132,24 @@ static void intel_i915_batch_flush( struct i915_winsys *sws,
struct pipe_fence_handle *pipe;
} fu;
if (fence)
assert(!*fence);
fu.dri = intel_batchbuffer_flush( intel->batch );
if (fu.dri)
iws->pws->fence_reference(iws->pws, fence, fu.pipe);
if (!fu.dri) {
assert(0);
*fence = NULL;
return;
}
if (fu.dri) {
if (fence)
*fence = fu.pipe;
else
driFenceUnReference(&fu.dri);
}
// if (0) intel_i915_batch_wait_idle( sws );
}
@@ -31,8 +31,8 @@
#include <stdlib.h>
#include <xf86drm.h>
#include "dri_bufpool.h"
#include "dri_bufmgr.h"
//#include "dri_bufpool.h"
//#include "dri_bufmgr.h"
#include "intel_context.h"
#include "intel_winsys.h"
@@ -50,6 +50,9 @@
struct intel_pipe_winsys {
struct pipe_winsys winsys;
struct _DriBufferPool *regionPool;
struct _DriBufferPool *mallocPool;
struct _DriBufferPool *vertexPool;
struct _DriFreeSlabManager *fMan; /** shared between all pipes */
};
@@ -92,6 +95,7 @@ intel_buffer_destroy(struct pipe_winsys *winsys,
struct pipe_buffer *buf)
{
driBOUnReference( dri_bo(buf) );
FREE(buf);
}
@@ -108,16 +112,23 @@ intel_buffer_create(struct pipe_winsys *winsys,
struct intel_buffer *buffer = CALLOC_STRUCT( intel_buffer );
struct intel_pipe_winsys *iws = intel_pipe_winsys(winsys);
unsigned flags = 0;
struct _DriBufferPool *pool;
buffer->base.refcount = 1;
buffer->base.alignment = alignment;
buffer->base.usage = usage;
buffer->base.size = size;
if (usage & (PIPE_BUFFER_USAGE_VERTEX /*| IWS_BUFFER_USAGE_LOCAL*/)) {
if (usage & (PIPE_BUFFER_USAGE_VERTEX | PIPE_BUFFER_USAGE_CONSTANT)) {
flags |= DRM_BO_FLAG_MEM_LOCAL | DRM_BO_FLAG_CACHED;
pool = iws->mallocPool;
} else if (usage & PIPE_BUFFER_USAGE_CUSTOM) {
/* For vertex buffers */
flags |= DRM_BO_FLAG_MEM_VRAM | DRM_BO_FLAG_MEM_TT;
pool = iws->vertexPool;
} else {
flags |= DRM_BO_FLAG_MEM_VRAM | DRM_BO_FLAG_MEM_TT;
pool = iws->regionPool;
}
if (usage & PIPE_BUFFER_USAGE_GPU_READ)
@@ -139,10 +150,11 @@ intel_buffer_create(struct pipe_winsys *winsys,
flags |= DRM_BO_FLAG_CACHED;
#endif
driGenBuffers( iws->regionPool,
buffer->pool = pool;
driGenBuffers( buffer->pool,
"pipe buffer", 1, &buffer->driBO, alignment, flags, 0 );
driBOData( buffer->driBO, size, NULL, 0 );
driBOData( buffer->driBO, size, NULL, buffer->pool, 0 );
return &buffer->base;
}
@@ -155,7 +167,9 @@ intel_user_buffer_create(struct pipe_winsys *winsys, void *ptr, unsigned bytes)
struct intel_pipe_winsys *iws = intel_pipe_winsys(winsys);
driGenUserBuffer( iws->regionPool,
"pipe user buffer", &buffer->driBO, ptr, bytes);
"pipe user buffer", &buffer->driBO, ptr, bytes );
buffer->base.refcount = 1;
return &buffer->base;
}
@@ -209,7 +223,7 @@ intel_i915_surface_alloc_storage(struct pipe_winsys *winsys,
unsigned flags)
{
const unsigned alignment = 64;
int ret;
//int ret;
surf->width = width;
surf->height = height;
@@ -249,9 +263,36 @@ intel_get_name( struct pipe_winsys *winsys )
return "Intel/DRI/ttm";
}
static void
intel_fence_reference( struct pipe_winsys *sws,
struct pipe_fence_handle **ptr,
struct pipe_fence_handle *fence )
{
if (*ptr)
driFenceUnReference((struct _DriFenceObject **)ptr);
if (fence)
*ptr = (struct pipe_fence_handle *)driFenceReference((struct _DriFenceObject *)fence);
}
static int
intel_fence_signalled( struct pipe_winsys *sws,
struct pipe_fence_handle *fence,
unsigned flag )
{
return driFenceSignaled((struct _DriFenceObject *)fence, flag);
}
static int
intel_fence_finish( struct pipe_winsys *sws,
struct pipe_fence_handle *fence,
unsigned flag )
{
return driFenceFinish((struct _DriFenceObject *)fence, flag, 0);
}
struct pipe_winsys *
intel_create_pipe_winsys( int fd )
intel_create_pipe_winsys( int fd, struct _DriFreeSlabManager *fMan )
{
struct intel_pipe_winsys *iws = CALLOC_STRUCT( intel_pipe_winsys );
@@ -273,8 +314,25 @@ intel_create_pipe_winsys( int fd )
iws->winsys.surface_alloc_storage = intel_i915_surface_alloc_storage;
iws->winsys.surface_release = intel_i915_surface_release;
if (fd)
iws->regionPool = driDRMPoolInit(fd);
iws->winsys.fence_reference = intel_fence_reference;
iws->winsys.fence_signalled = intel_fence_signalled;
iws->winsys.fence_finish = intel_fence_finish;
if (fd) {
iws->regionPool = driDRMPoolInit(fd);
iws->vertexPool = driSlabPoolInit(fd,
DRM_BO_FLAG_READ |
DRM_BO_FLAG_WRITE |
DRM_BO_FLAG_MEM_TT,
DRM_BO_FLAG_READ |
DRM_BO_FLAG_WRITE |
DRM_BO_FLAG_MEM_TT,
32 * 4096,
1, 40, 32 * 4096 * 2, 0,
fMan);
}
iws->mallocPool = driMallocPoolInit();
return &iws->winsys;
}
@@ -287,6 +345,9 @@ intel_destroy_pipe_winsys( struct pipe_winsys *winsys )
if (iws->regionPool) {
driPoolTakeDown(iws->regionPool);
}
if (iws->mallocPool) {
driPoolTakeDown(iws->mallocPool);
}
free(iws);
}
@@ -54,6 +54,7 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#define DRM_I830_DESTROY_HEAP 0x0c
#define DRM_I830_SET_VBLANK_PIPE 0x0d
#define DRM_I830_GET_VBLANK_PIPE 0x0e
#define DRM_I830_MMIO 0x10
typedef struct {
enum {
@@ -85,6 +86,7 @@ typedef struct {
int last_enqueue; /* last time a buffer was enqueued */
int last_dispatch; /* age of the most recently dispatched buffer */
int ctxOwner; /* last context to upload state */
/** Last context that used the buffer manager. */
int texAge;
int pf_enabled; /* is pageflipping allowed? */
int pf_active;
@@ -121,20 +123,29 @@ typedef struct {
unsigned int rotated_tiled;
unsigned int rotated2_tiled;
int pipeA_x;
int pipeA_y;
int pipeA_w;
int pipeA_h;
int pipeB_x;
int pipeB_y;
int pipeB_w;
int pipeB_h;
int planeA_x;
int planeA_y;
int planeA_w;
int planeA_h;
int planeB_x;
int planeB_y;
int planeB_w;
int planeB_h;
/* Triple buffering */
drm_handle_t third_handle;
int third_offset;
int third_size;
unsigned int third_tiled;
/* buffer object handles for the static buffers. May change
* over the lifetime of the client, though it doesn't in our current
* implementation.
*/
unsigned int front_bo_handle;
unsigned int back_bo_handle;
unsigned int third_bo_handle;
unsigned int depth_bo_handle;
} drmI830Sarea;
/* Flags for perf_boxes
@@ -223,4 +234,23 @@ typedef struct {
int pipe;
} drmI830VBlankPipe;
#define MMIO_READ 0
#define MMIO_WRITE 1
#define MMIO_REGS_IA_PRIMATIVES_COUNT 0
#define MMIO_REGS_IA_VERTICES_COUNT 1
#define MMIO_REGS_VS_INVOCATION_COUNT 2
#define MMIO_REGS_GS_PRIMITIVES_COUNT 3
#define MMIO_REGS_GS_INVOCATION_COUNT 4
#define MMIO_REGS_CL_PRIMITIVES_COUNT 5
#define MMIO_REGS_CL_INVOCATION_COUNT 6
#define MMIO_REGS_PS_INVOCATION_COUNT 7
#define MMIO_REGS_PS_DEPTH_COUNT 8
typedef struct {
unsigned int read_write:1;
unsigned int reg:31;
void __user *data;
} drmI830MMIO;
#endif /* _I830_DRM_H_ */
@@ -0,0 +1,953 @@
/**************************************************************************
*
* 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: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
* Keith Whitwell <keithw-at-tungstengraphics-dot-com>
*/
#include <xf86drm.h>
#include <stdlib.h>
#include "glthread.h"
#include "errno.h"
#include "ws_dri_bufmgr.h"
#include "string.h"
#include "imports.h"
#include "ws_dri_bufpool.h"
#include "ws_dri_fencemgr.h"
/*
* This lock is here to protect drmBO structs changing underneath us during a
* validate list call, since validatelist cannot take individiual locks for
* each drmBO. Validatelist takes this lock in write mode. Any access to an
* individual drmBO should take this lock in read mode, since in that case, the
* driBufferObject mutex will protect the access. Locking order is
* driBufferObject mutex - > this rw lock.
*/
_glthread_DECLARE_STATIC_MUTEX(bmMutex);
_glthread_DECLARE_STATIC_COND(bmCond);
static int kernelReaders = 0;
static int num_buffers = 0;
static int num_user_buffers = 0;
static drmBO *drmBOListBuf(void *iterator)
{
drmBONode *node;
drmMMListHead *l = (drmMMListHead *) iterator;
node = DRMLISTENTRY(drmBONode, l, head);
return node->buf;
}
static void *drmBOListIterator(drmBOList *list)
{
void *ret = list->list.next;
if (ret == &list->list)
return NULL;
return ret;
}
static void *drmBOListNext(drmBOList *list, void *iterator)
{
void *ret;
drmMMListHead *l = (drmMMListHead *) iterator;
ret = l->next;
if (ret == &list->list)
return NULL;
return ret;
}
static drmBONode *drmAddListItem(drmBOList *list, drmBO *item,
uint64_t arg0,
uint64_t arg1)
{
drmBONode *node;
drmMMListHead *l;
l = list->free.next;
if (l == &list->free) {
node = (drmBONode *) malloc(sizeof(*node));
if (!node) {
return NULL;
}
list->numCurrent++;
}
else {
DRMLISTDEL(l);
node = DRMLISTENTRY(drmBONode, l, head);
}
node->buf = item;
node->arg0 = arg0;
node->arg1 = arg1;
DRMLISTADD(&node->head, &list->list);
list->numOnList++;
return node;
}
static int drmAddValidateItem(drmBOList *list, drmBO *buf, uint64_t flags,
uint64_t mask, int *newItem)
{
drmBONode *node, *cur;
drmMMListHead *l;
*newItem = 0;
cur = NULL;
for (l = list->list.next; l != &list->list; l = l->next) {
node = DRMLISTENTRY(drmBONode, l, head);
if (node->buf == buf) {
cur = node;
break;
}
}
if (!cur) {
cur = drmAddListItem(list, buf, flags, mask);
if (!cur) {
return -ENOMEM;
}
*newItem = 1;
cur->arg0 = flags;
cur->arg1 = mask;
}
else {
uint64_t memFlags = cur->arg0 & flags & DRM_BO_MASK_MEM;
uint64_t accFlags = (cur->arg0 | flags) & ~DRM_BO_MASK_MEM;
if (mask & cur->arg1 & ~DRM_BO_MASK_MEM & (cur->arg0 ^ flags)) {
return -EINVAL;
}
cur->arg1 |= mask;
cur->arg0 = (cur->arg0 & ~mask) | ((memFlags | accFlags) & mask);
if (((cur->arg1 & DRM_BO_MASK_MEM) != 0) &&
(cur->arg0 & DRM_BO_MASK_MEM) == 0) {
return -EINVAL;
}
}
return 0;
}
static void drmBOFreeList(drmBOList *list)
{
drmBONode *node;
drmMMListHead *l;
l = list->list.next;
while(l != &list->list) {
DRMLISTDEL(l);
node = DRMLISTENTRY(drmBONode, l, head);
free(node);
l = list->list.next;
list->numCurrent--;
list->numOnList--;
}
l = list->free.next;
while(l != &list->free) {
DRMLISTDEL(l);
node = DRMLISTENTRY(drmBONode, l, head);
free(node);
l = list->free.next;
list->numCurrent--;
}
}
static int drmAdjustListNodes(drmBOList *list)
{
drmBONode *node;
drmMMListHead *l;
int ret = 0;
while(list->numCurrent < list->numTarget) {
node = (drmBONode *) malloc(sizeof(*node));
if (!node) {
ret = -ENOMEM;
break;
}
list->numCurrent++;
DRMLISTADD(&node->head, &list->free);
}
while(list->numCurrent > list->numTarget) {
l = list->free.next;
if (l == &list->free)
break;
DRMLISTDEL(l);
node = DRMLISTENTRY(drmBONode, l, head);
free(node);
list->numCurrent--;
}
return ret;
}
static int drmBOCreateList(int numTarget, drmBOList *list)
{
DRMINITLISTHEAD(&list->list);
DRMINITLISTHEAD(&list->free);
list->numTarget = numTarget;
list->numCurrent = 0;
list->numOnList = 0;
return drmAdjustListNodes(list);
}
static int drmBOResetList(drmBOList *list)
{
drmMMListHead *l;
int ret;
ret = drmAdjustListNodes(list);
if (ret)
return ret;
l = list->list.next;
while (l != &list->list) {
DRMLISTDEL(l);
DRMLISTADD(l, &list->free);
list->numOnList--;
l = list->list.next;
}
return drmAdjustListNodes(list);
}
void driWriteLockKernelBO(void)
{
_glthread_LOCK_MUTEX(bmMutex);
while(kernelReaders != 0)
_glthread_COND_WAIT(bmCond, bmMutex);
}
void driWriteUnlockKernelBO(void)
{
_glthread_UNLOCK_MUTEX(bmMutex);
}
void driReadLockKernelBO(void)
{
_glthread_LOCK_MUTEX(bmMutex);
kernelReaders++;
_glthread_UNLOCK_MUTEX(bmMutex);
}
void driReadUnlockKernelBO(void)
{
_glthread_LOCK_MUTEX(bmMutex);
if (--kernelReaders == 0)
_glthread_COND_BROADCAST(bmCond);
_glthread_UNLOCK_MUTEX(bmMutex);
}
/*
* TODO: Introduce fence pools in the same way as
* buffer object pools.
*/
typedef struct _DriBufferObject
{
DriBufferPool *pool;
_glthread_Mutex mutex;
int refCount;
const char *name;
uint64_t flags;
unsigned hint;
unsigned alignment;
unsigned createdByReference;
void *private;
/* user-space buffer: */
unsigned userBuffer;
void *userData;
unsigned userSize;
} DriBufferObject;
typedef struct _DriBufferList {
drmBOList drmBuffers; /* List of kernel buffers needing validation */
drmBOList driBuffers; /* List of user-space buffers needing validation */
} DriBufferList;
void
bmError(int val, const char *file, const char *function, int line)
{
_mesa_printf("Fatal video memory manager error \"%s\".\n"
"Check kernel logs or set the LIBGL_DEBUG\n"
"environment variable to \"verbose\" for more info.\n"
"Detected in file %s, line %d, function %s.\n",
strerror(-val), file, line, function);
#ifndef NDEBUG
abort();
#else
abort();
#endif
}
extern drmBO *
driBOKernel(struct _DriBufferObject *buf)
{
drmBO *ret;
driReadLockKernelBO();
_glthread_LOCK_MUTEX(buf->mutex);
assert(buf->private != NULL);
ret = buf->pool->kernel(buf->pool, buf->private);
if (!ret)
BM_CKFATAL(-EINVAL);
_glthread_UNLOCK_MUTEX(buf->mutex);
driReadUnlockKernelBO();
return ret;
}
void
driBOWaitIdle(struct _DriBufferObject *buf, int lazy)
{
/*
* This function may block. Is it sane to keep the mutex held during
* that time??
*/
_glthread_LOCK_MUTEX(buf->mutex);
BM_CKFATAL(buf->pool->waitIdle(buf->pool, buf->private, &buf->mutex, lazy));
_glthread_UNLOCK_MUTEX(buf->mutex);
}
void *
driBOMap(struct _DriBufferObject *buf, unsigned flags, unsigned hint)
{
void *virtual;
int retval;
if (buf->userBuffer) {
return buf->userData;
}
_glthread_LOCK_MUTEX(buf->mutex);
assert(buf->private != NULL);
retval = buf->pool->map(buf->pool, buf->private, flags, hint,
&buf->mutex, &virtual);
_glthread_UNLOCK_MUTEX(buf->mutex);
return retval == 0 ? virtual : NULL;
}
void
driBOUnmap(struct _DriBufferObject *buf)
{
if (buf->userBuffer)
return;
assert(buf->private != NULL);
_glthread_LOCK_MUTEX(buf->mutex);
BM_CKFATAL(buf->pool->unmap(buf->pool, buf->private));
_glthread_UNLOCK_MUTEX(buf->mutex);
}
unsigned long
driBOOffset(struct _DriBufferObject *buf)
{
unsigned long ret;
assert(buf->private != NULL);
_glthread_LOCK_MUTEX(buf->mutex);
ret = buf->pool->offset(buf->pool, buf->private);
_glthread_UNLOCK_MUTEX(buf->mutex);
return ret;
}
unsigned long
driBOPoolOffset(struct _DriBufferObject *buf)
{
unsigned long ret;
assert(buf->private != NULL);
_glthread_LOCK_MUTEX(buf->mutex);
ret = buf->pool->poolOffset(buf->pool, buf->private);
_glthread_UNLOCK_MUTEX(buf->mutex);
return ret;
}
uint64_t
driBOFlags(struct _DriBufferObject *buf)
{
uint64_t ret;
assert(buf->private != NULL);
driReadLockKernelBO();
_glthread_LOCK_MUTEX(buf->mutex);
ret = buf->pool->flags(buf->pool, buf->private);
_glthread_UNLOCK_MUTEX(buf->mutex);
driReadUnlockKernelBO();
return ret;
}
struct _DriBufferObject *
driBOReference(struct _DriBufferObject *buf)
{
_glthread_LOCK_MUTEX(buf->mutex);
if (++buf->refCount == 1) {
_glthread_UNLOCK_MUTEX(buf->mutex);
BM_CKFATAL(-EINVAL);
}
_glthread_UNLOCK_MUTEX(buf->mutex);
return buf;
}
void
driBOUnReference(struct _DriBufferObject *buf)
{
int tmp;
if (!buf)
return;
_glthread_LOCK_MUTEX(buf->mutex);
tmp = --buf->refCount;
if (!tmp) {
_glthread_UNLOCK_MUTEX(buf->mutex);
if (buf->private) {
if (buf->createdByReference)
buf->pool->unreference(buf->pool, buf->private);
else
buf->pool->destroy(buf->pool, buf->private);
}
if (buf->userBuffer)
num_user_buffers--;
else
num_buffers--;
free(buf);
} else
_glthread_UNLOCK_MUTEX(buf->mutex);
}
int
driBOData(struct _DriBufferObject *buf,
unsigned size, const void *data,
DriBufferPool *newPool,
uint64_t flags)
{
void *virtual = NULL;
int newBuffer;
int retval = 0;
struct _DriBufferPool *pool;
assert(!buf->userBuffer); /* XXX just do a memcpy? */
_glthread_LOCK_MUTEX(buf->mutex);
pool = buf->pool;
if (pool == NULL && newPool != NULL) {
buf->pool = newPool;
pool = newPool;
}
if (newPool == NULL)
newPool = pool;
if (!pool->create) {
_mesa_error(NULL, GL_INVALID_OPERATION,
"driBOData called on invalid buffer\n");
BM_CKFATAL(-EINVAL);
}
newBuffer = (!buf->private || pool != newPool ||
pool->size(pool, buf->private) < size);
if (!flags)
flags = buf->flags;
if (newBuffer) {
if (buf->createdByReference) {
_mesa_error(NULL, GL_INVALID_OPERATION,
"driBOData requiring resizing called on "
"shared buffer.\n");
BM_CKFATAL(-EINVAL);
}
if (buf->private)
buf->pool->destroy(buf->pool, buf->private);
pool = newPool;
buf->pool = newPool;
buf->private = pool->create(pool, size, flags, DRM_BO_HINT_DONT_FENCE,
buf->alignment);
if (!buf->private)
retval = -ENOMEM;
if (retval == 0)
retval = pool->map(pool, buf->private,
DRM_BO_FLAG_WRITE,
DRM_BO_HINT_DONT_BLOCK, &buf->mutex, &virtual);
} else if (pool->map(pool, buf->private, DRM_BO_FLAG_WRITE,
DRM_BO_HINT_DONT_BLOCK, &buf->mutex, &virtual)) {
/*
* Buffer is busy. need to create a new one.
*/
void *newBuf;
newBuf = pool->create(pool, size, flags, DRM_BO_HINT_DONT_FENCE,
buf->alignment);
if (newBuf) {
buf->pool->destroy(buf->pool, buf->private);
buf->private = newBuf;
}
retval = pool->map(pool, buf->private,
DRM_BO_FLAG_WRITE, 0, &buf->mutex, &virtual);
} else {
uint64_t flag_diff = flags ^ buf->flags;
/*
* We might need to change buffer flags.
*/
if (flag_diff){
assert(pool->setStatus != NULL);
BM_CKFATAL(pool->unmap(pool, buf->private));
BM_CKFATAL(pool->setStatus(pool, buf->private, flag_diff,
buf->flags));
if (!data)
goto out;
retval = pool->map(pool, buf->private,
DRM_BO_FLAG_WRITE, 0, &buf->mutex, &virtual);
}
}
if (retval == 0) {
if (data)
memcpy(virtual, data, size);
BM_CKFATAL(pool->unmap(pool, buf->private));
}
out:
_glthread_UNLOCK_MUTEX(buf->mutex);
return retval;
}
void
driBOSubData(struct _DriBufferObject *buf,
unsigned long offset, unsigned long size, const void *data)
{
void *virtual;
assert(!buf->userBuffer); /* XXX just do a memcpy? */
_glthread_LOCK_MUTEX(buf->mutex);
if (size && data) {
BM_CKFATAL(buf->pool->map(buf->pool, buf->private,
DRM_BO_FLAG_WRITE, 0, &buf->mutex,
&virtual));
memcpy((unsigned char *) virtual + offset, data, size);
BM_CKFATAL(buf->pool->unmap(buf->pool, buf->private));
}
_glthread_UNLOCK_MUTEX(buf->mutex);
}
void
driBOGetSubData(struct _DriBufferObject *buf,
unsigned long offset, unsigned long size, void *data)
{
void *virtual;
assert(!buf->userBuffer); /* XXX just do a memcpy? */
_glthread_LOCK_MUTEX(buf->mutex);
if (size && data) {
BM_CKFATAL(buf->pool->map(buf->pool, buf->private,
DRM_BO_FLAG_READ, 0, &buf->mutex, &virtual));
memcpy(data, (unsigned char *) virtual + offset, size);
BM_CKFATAL(buf->pool->unmap(buf->pool, buf->private));
}
_glthread_UNLOCK_MUTEX(buf->mutex);
}
void
driBOSetReferenced(struct _DriBufferObject *buf,
unsigned long handle)
{
_glthread_LOCK_MUTEX(buf->mutex);
if (buf->private != NULL) {
_mesa_error(NULL, GL_INVALID_OPERATION,
"Invalid buffer for setReferenced\n");
BM_CKFATAL(-EINVAL);
}
if (buf->pool->reference == NULL) {
_mesa_error(NULL, GL_INVALID_OPERATION,
"Invalid buffer pool for setReferenced\n");
BM_CKFATAL(-EINVAL);
}
buf->private = buf->pool->reference(buf->pool, handle);
if (!buf->private) {
_mesa_error(NULL, GL_OUT_OF_MEMORY,
"Invalid buffer pool for setStatic\n");
BM_CKFATAL(-ENOMEM);
}
buf->createdByReference = GL_TRUE;
buf->flags = buf->pool->kernel(buf->pool, buf->private)->flags;
_glthread_UNLOCK_MUTEX(buf->mutex);
}
int
driGenBuffers(struct _DriBufferPool *pool,
const char *name,
unsigned n,
struct _DriBufferObject *buffers[],
unsigned alignment, uint64_t flags, unsigned hint)
{
struct _DriBufferObject *buf;
int i;
flags = (flags) ? flags : DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_MEM_VRAM |
DRM_BO_FLAG_MEM_LOCAL | DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE;
++num_buffers;
assert(pool);
for (i = 0; i < n; ++i) {
buf = (struct _DriBufferObject *) calloc(1, sizeof(*buf));
if (!buf)
return -ENOMEM;
_glthread_INIT_MUTEX(buf->mutex);
_glthread_LOCK_MUTEX(buf->mutex);
buf->refCount = 1;
buf->flags = flags;
buf->hint = hint;
buf->name = name;
buf->alignment = alignment;
buf->pool = pool;
buf->createdByReference = 0;
_glthread_UNLOCK_MUTEX(buf->mutex);
buffers[i] = buf;
}
return 0;
}
void
driGenUserBuffer(struct _DriBufferPool *pool,
const char *name,
struct _DriBufferObject **buffers,
void *ptr, unsigned bytes)
{
const unsigned alignment = 1, flags = 0, hint = 0;
--num_buffers; /* JB: is inced in GenBuffes */
driGenBuffers(pool, name, 1, buffers, alignment, flags, hint);
++num_user_buffers;
(*buffers)->userBuffer = 1;
(*buffers)->userData = ptr;
(*buffers)->userSize = bytes;
}
void
driDeleteBuffers(unsigned n, struct _DriBufferObject *buffers[])
{
int i;
for (i = 0; i < n; ++i) {
driBOUnReference(buffers[i]);
}
}
void
driInitBufMgr(int fd)
{
;
}
/*
* Note that lists are per-context and don't need mutex protection.
*/
struct _DriBufferList *
driBOCreateList(int target)
{
struct _DriBufferList *list = calloc(sizeof(*list), 1);
BM_CKFATAL(drmBOCreateList(target, &list->drmBuffers));
BM_CKFATAL(drmBOCreateList(target, &list->driBuffers));
return list;
}
int
driBOResetList(struct _DriBufferList * list)
{
int ret;
ret = drmBOResetList(&list->drmBuffers);
if (ret)
return ret;
ret = drmBOResetList(&list->driBuffers);
return ret;
}
void
driBOFreeList(struct _DriBufferList * list)
{
drmBOFreeList(&list->drmBuffers);
drmBOFreeList(&list->driBuffers);
free(list);
}
/*
* Copied from libdrm, because it is needed by driAddValidateItem.
*/
static drmBONode *
driAddListItem(drmBOList * list, drmBO * item,
uint64_t arg0, uint64_t arg1)
{
drmBONode *node;
drmMMListHead *l;
l = list->free.next;
if (l == &list->free) {
node = (drmBONode *) malloc(sizeof(*node));
if (!node) {
return NULL;
}
list->numCurrent++;
} else {
DRMLISTDEL(l);
node = DRMLISTENTRY(drmBONode, l, head);
}
memset(&node->bo_arg, 0, sizeof(node->bo_arg));
node->buf = item;
node->arg0 = arg0;
node->arg1 = arg1;
DRMLISTADDTAIL(&node->head, &list->list);
list->numOnList++;
return node;
}
/*
* Slightly modified version compared to the libdrm version.
* This one returns the list index of the buffer put on the list.
*/
static int
driAddValidateItem(drmBOList * list, drmBO * buf, uint64_t flags,
uint64_t mask, int *itemLoc,
struct _drmBONode **pnode)
{
drmBONode *node, *cur;
drmMMListHead *l;
int count = 0;
cur = NULL;
for (l = list->list.next; l != &list->list; l = l->next) {
node = DRMLISTENTRY(drmBONode, l, head);
if (node->buf == buf) {
cur = node;
break;
}
count++;
}
if (!cur) {
cur = driAddListItem(list, buf, flags, mask);
if (!cur)
return -ENOMEM;
cur->arg0 = flags;
cur->arg1 = mask;
} else {
uint64_t memFlags = cur->arg0 & flags & DRM_BO_MASK_MEM;
uint64_t accFlags = (cur->arg0 | flags) & ~DRM_BO_MASK_MEM;
if (mask & cur->arg1 & ~DRM_BO_MASK_MEM & (cur->arg0 ^ flags)) {
return -EINVAL;
}
cur->arg1 |= mask;
cur->arg0 = (cur->arg0 & ~mask) | ((memFlags | accFlags) & mask);
if (((cur->arg1 & DRM_BO_MASK_MEM) != 0) &&
(cur->arg0 & DRM_BO_MASK_MEM) == 0) {
return -EINVAL;
}
}
*itemLoc = count;
*pnode = cur;
return 0;
}
void
driBOAddListItem(struct _DriBufferList * list, struct _DriBufferObject *buf,
uint64_t flags, uint64_t mask, int *itemLoc,
struct _drmBONode **node)
{
int newItem;
_glthread_LOCK_MUTEX(buf->mutex);
BM_CKFATAL(driAddValidateItem(&list->drmBuffers,
buf->pool->kernel(buf->pool, buf->private),
flags, mask, itemLoc, node));
BM_CKFATAL(drmAddValidateItem(&list->driBuffers, (drmBO *) buf,
flags, mask, &newItem));
if (newItem)
buf->refCount++;
_glthread_UNLOCK_MUTEX(buf->mutex);
}
drmBOList *driGetdrmBOList(struct _DriBufferList *list)
{
driWriteLockKernelBO();
return &list->drmBuffers;
}
void driPutdrmBOList(struct _DriBufferList *list)
{
driWriteUnlockKernelBO();
}
void
driBOFence(struct _DriBufferObject *buf, struct _DriFenceObject *fence)
{
_glthread_LOCK_MUTEX(buf->mutex);
if (buf->pool->fence)
BM_CKFATAL(buf->pool->fence(buf->pool, buf->private, fence));
_glthread_UNLOCK_MUTEX(buf->mutex);
}
void
driBOUnrefUserList(struct _DriBufferList *list)
{
struct _DriBufferObject *buf;
void *curBuf;
curBuf = drmBOListIterator(&list->driBuffers);
while (curBuf) {
buf = (struct _DriBufferObject *)drmBOListBuf(curBuf);
driBOUnReference(buf);
curBuf = drmBOListNext(&list->driBuffers, curBuf);
}
}
struct _DriFenceObject *
driBOFenceUserList(struct _DriFenceMgr *mgr,
struct _DriBufferList *list, const char *name,
drmFence *kFence)
{
struct _DriFenceObject *fence;
struct _DriBufferObject *buf;
void *curBuf;
fence = driFenceCreate(mgr, kFence->fence_class, kFence->type,
kFence, sizeof(*kFence));
curBuf = drmBOListIterator(&list->driBuffers);
/*
* User-space fencing callbacks.
*/
while (curBuf) {
buf = (struct _DriBufferObject *) drmBOListBuf(curBuf);
driBOFence(buf, fence);
driBOUnReference(buf);
curBuf = drmBOListNext(&list->driBuffers, curBuf);
}
driBOResetList(list);
return fence;
}
void
driBOValidateUserList(struct _DriBufferList * list)
{
void *curBuf;
struct _DriBufferObject *buf;
curBuf = drmBOListIterator(&list->driBuffers);
/*
* User-space validation callbacks.
*/
while (curBuf) {
buf = (struct _DriBufferObject *) drmBOListBuf(curBuf);
_glthread_LOCK_MUTEX(buf->mutex);
if (buf->pool->validate)
BM_CKFATAL(buf->pool->validate(buf->pool, buf->private, &buf->mutex));
_glthread_UNLOCK_MUTEX(buf->mutex);
curBuf = drmBOListNext(&list->driBuffers, curBuf);
}
}
void
driPoolTakeDown(struct _DriBufferPool *pool)
{
pool->takeDown(pool);
}
unsigned long
driBOSize(struct _DriBufferObject *buf)
{
unsigned long size;
_glthread_LOCK_MUTEX(buf->mutex);
size = buf->pool->size(buf->pool, buf->private);
_glthread_UNLOCK_MUTEX(buf->mutex);
return size;
}
drmBOList *driBOGetDRMBuffers(struct _DriBufferList *list)
{
return &list->drmBuffers;
}
drmBOList *driBOGetDRIBuffers(struct _DriBufferList *list)
{
return &list->driBuffers;
}
@@ -0,0 +1,138 @@
/**************************************************************************
*
* 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: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
* Keith Whitwell <keithw-at-tungstengraphics-dot-com>
*/
#ifndef _PSB_BUFMGR_H_
#define _PSB_BUFMGR_H_
#include <xf86mm.h>
#include "i915_drm.h"
#include "ws_dri_fencemgr.h"
typedef struct _drmBONode
{
drmMMListHead head;
drmBO *buf;
struct drm_i915_op_arg bo_arg;
uint64_t arg0;
uint64_t arg1;
} drmBONode;
typedef struct _drmBOList {
unsigned numTarget;
unsigned numCurrent;
unsigned numOnList;
drmMMListHead list;
drmMMListHead free;
} drmBOList;
struct _DriFenceObject;
struct _DriBufferObject;
struct _DriBufferPool;
struct _DriBufferList;
/*
* Return a pointer to the libdrm buffer object this DriBufferObject
* uses.
*/
extern drmBO *driBOKernel(struct _DriBufferObject *buf);
extern void *driBOMap(struct _DriBufferObject *buf, unsigned flags,
unsigned hint);
extern void driBOUnmap(struct _DriBufferObject *buf);
extern unsigned long driBOOffset(struct _DriBufferObject *buf);
extern unsigned long driBOPoolOffset(struct _DriBufferObject *buf);
extern uint64_t driBOFlags(struct _DriBufferObject *buf);
extern struct _DriBufferObject *driBOReference(struct _DriBufferObject *buf);
extern void driBOUnReference(struct _DriBufferObject *buf);
extern int driBOData(struct _DriBufferObject *r_buf,
unsigned size, const void *data,
struct _DriBufferPool *pool, uint64_t flags);
extern void driBOSubData(struct _DriBufferObject *buf,
unsigned long offset, unsigned long size,
const void *data);
extern void driBOGetSubData(struct _DriBufferObject *buf,
unsigned long offset, unsigned long size,
void *data);
extern int driGenBuffers(struct _DriBufferPool *pool,
const char *name,
unsigned n,
struct _DriBufferObject *buffers[],
unsigned alignment, uint64_t flags, unsigned hint);
extern void driGenUserBuffer(struct _DriBufferPool *pool,
const char *name,
struct _DriBufferObject *buffers[],
void *ptr, unsigned bytes);
extern void driDeleteBuffers(unsigned n, struct _DriBufferObject *buffers[]);
extern void driInitBufMgr(int fd);
extern struct _DriBufferList *driBOCreateList(int target);
extern int driBOResetList(struct _DriBufferList * list);
extern void driBOAddListItem(struct _DriBufferList * list,
struct _DriBufferObject *buf,
uint64_t flags, uint64_t mask, int *itemLoc,
struct _drmBONode **node);
extern void driBOValidateList(int fd, struct _DriBufferList * list);
extern void driBOFreeList(struct _DriBufferList * list);
extern struct _DriFenceObject *driBOFenceUserList(struct _DriFenceMgr *mgr,
struct _DriBufferList *list,
const char *name,
drmFence *kFence);
extern void driBOUnrefUserList(struct _DriBufferList *list);
extern void driBOValidateUserList(struct _DriBufferList * list);
extern drmBOList *driGetdrmBOList(struct _DriBufferList *list);
extern void driPutdrmBOList(struct _DriBufferList *list);
extern void driBOFence(struct _DriBufferObject *buf,
struct _DriFenceObject *fence);
extern void driPoolTakeDown(struct _DriBufferPool *pool);
extern void driBOSetReferenced(struct _DriBufferObject *buf,
unsigned long handle);
unsigned long driBOSize(struct _DriBufferObject *buf);
extern void driBOWaitIdle(struct _DriBufferObject *buf, int lazy);
extern void driPoolTakeDown(struct _DriBufferPool *pool);
extern void driReadLockKernelBO(void);
extern void driReadUnlockKernelBO(void);
extern void driWriteLockKernelBO(void);
extern void driWriteUnlockKernelBO(void);
/*
* For debugging purposes.
*/
extern drmBOList *driBOGetDRMBuffers(struct _DriBufferList *list);
extern drmBOList *driBOGetDRIBuffers(struct _DriBufferList *list);
#endif
@@ -0,0 +1,102 @@
/**************************************************************************
*
* 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: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
*/
#ifndef _PSB_BUFPOOL_H_
#define _PSB_BUFPOOL_H_
#include <xf86drm.h>
#include <glthread.h>
struct _DriFenceObject;
typedef struct _DriBufferPool
{
int fd;
int (*map) (struct _DriBufferPool * pool, void *private,
unsigned flags, int hint, _glthread_Mutex *mutex,
void **virtual);
int (*unmap) (struct _DriBufferPool * pool, void *private);
int (*destroy) (struct _DriBufferPool * pool, void *private);
unsigned long (*offset) (struct _DriBufferPool * pool, void *private);
unsigned long (*poolOffset) (struct _DriBufferPool * pool, void *private);
uint64_t (*flags) (struct _DriBufferPool * pool, void *private);
unsigned long (*size) (struct _DriBufferPool * pool, void *private);
void *(*create) (struct _DriBufferPool * pool, unsigned long size,
uint64_t flags, unsigned hint, unsigned alignment);
void *(*reference) (struct _DriBufferPool * pool, unsigned handle);
int (*unreference) (struct _DriBufferPool * pool, void *private);
int (*fence) (struct _DriBufferPool * pool, void *private,
struct _DriFenceObject * fence);
drmBO *(*kernel) (struct _DriBufferPool * pool, void *private);
int (*validate) (struct _DriBufferPool * pool, void *private, _glthread_Mutex *mutex);
int (*waitIdle) (struct _DriBufferPool *pool, void *private, _glthread_Mutex *mutex,
int lazy);
int (*setStatus) (struct _DriBufferPool *pool, void *private,
uint64_t flag_diff, uint64_t old_flags);
void (*takeDown) (struct _DriBufferPool * pool);
void *data;
} DriBufferPool;
extern void bmError(int val, const char *file, const char *function,
int line);
#define BM_CKFATAL(val) \
do{ \
int tstVal = (val); \
if (tstVal) \
bmError(tstVal, __FILE__, __FUNCTION__, __LINE__); \
} while(0);
/*
* Builtin pools.
*/
/*
* Kernel buffer objects. Size in multiples of page size. Page size aligned.
*/
extern struct _DriBufferPool *driDRMPoolInit(int fd);
extern struct _DriBufferPool *driMallocPoolInit(void);
struct _DriFreeSlabManager;
extern struct _DriBufferPool * driSlabPoolInit(int fd, uint64_t flags,
uint64_t validMask,
uint32_t smallestSize,
uint32_t numSizes,
uint32_t desiredNumBuffers,
uint32_t maxSlabSize,
uint32_t pageAlignment,
struct _DriFreeSlabManager *fMan);
extern void driFinishFreeSlabManager(struct _DriFreeSlabManager *fMan);
extern struct _DriFreeSlabManager *
driInitFreeSlabManager(uint32_t checkIntervalMsec, uint32_t slabTimeoutMsec);
#endif
@@ -0,0 +1,268 @@
/**************************************************************************
*
* 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: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
*/
#include <xf86drm.h>
#include <stdlib.h>
#include <unistd.h>
#include "ws_dri_bufpool.h"
#include "ws_dri_bufmgr.h"
#include "assert.h"
/*
* Buffer pool implementation using DRM buffer objects as DRI buffer objects.
*/
static void *
pool_create(struct _DriBufferPool *pool,
unsigned long size, uint64_t flags, unsigned hint,
unsigned alignment)
{
drmBO *buf = (drmBO *) malloc(sizeof(*buf));
int ret;
unsigned pageSize = getpagesize();
if (!buf)
return NULL;
if ((alignment > pageSize) && (alignment % pageSize)) {
free(buf);
return NULL;
}
ret = drmBOCreate(pool->fd, size, alignment / pageSize,
NULL,
flags, hint, buf);
if (ret) {
free(buf);
return NULL;
}
return (void *) buf;
}
static void *
pool_reference(struct _DriBufferPool *pool, unsigned handle)
{
drmBO *buf = (drmBO *) malloc(sizeof(*buf));
int ret;
if (!buf)
return NULL;
ret = drmBOReference(pool->fd, handle, buf);
if (ret) {
free(buf);
return NULL;
}
return (void *) buf;
}
static int
pool_destroy(struct _DriBufferPool *pool, void *private)
{
int ret;
drmBO *buf = (drmBO *) private;
driReadLockKernelBO();
ret = drmBOUnreference(pool->fd, buf);
free(buf);
driReadUnlockKernelBO();
return ret;
}
static int
pool_unreference(struct _DriBufferPool *pool, void *private)
{
int ret;
drmBO *buf = (drmBO *) private;
driReadLockKernelBO();
ret = drmBOUnreference(pool->fd, buf);
free(buf);
driReadUnlockKernelBO();
return ret;
}
static int
pool_map(struct _DriBufferPool *pool, void *private, unsigned flags,
int hint, _glthread_Mutex *mutex, void **virtual)
{
drmBO *buf = (drmBO *) private;
int ret;
driReadLockKernelBO();
ret = drmBOMap(pool->fd, buf, flags, hint, virtual);
driReadUnlockKernelBO();
return ret;
}
static int
pool_unmap(struct _DriBufferPool *pool, void *private)
{
drmBO *buf = (drmBO *) private;
int ret;
driReadLockKernelBO();
ret = drmBOUnmap(pool->fd, buf);
driReadUnlockKernelBO();
return ret;
}
static unsigned long
pool_offset(struct _DriBufferPool *pool, void *private)
{
drmBO *buf = (drmBO *) private;
unsigned long offset;
driReadLockKernelBO();
assert(buf->flags & DRM_BO_FLAG_NO_MOVE);
offset = buf->offset;
driReadUnlockKernelBO();
return buf->offset;
}
static unsigned long
pool_poolOffset(struct _DriBufferPool *pool, void *private)
{
return 0;
}
static uint64_t
pool_flags(struct _DriBufferPool *pool, void *private)
{
drmBO *buf = (drmBO *) private;
uint64_t flags;
driReadLockKernelBO();
flags = buf->flags;
driReadUnlockKernelBO();
return flags;
}
static unsigned long
pool_size(struct _DriBufferPool *pool, void *private)
{
drmBO *buf = (drmBO *) private;
unsigned long size;
driReadLockKernelBO();
size = buf->size;
driReadUnlockKernelBO();
return buf->size;
}
static int
pool_fence(struct _DriBufferPool *pool, void *private,
struct _DriFenceObject *fence)
{
/*
* Noop. The kernel handles all fencing.
*/
return 0;
}
static drmBO *
pool_kernel(struct _DriBufferPool *pool, void *private)
{
return (drmBO *) private;
}
static int
pool_waitIdle(struct _DriBufferPool *pool, void *private, _glthread_Mutex *mutex,
int lazy)
{
drmBO *buf = (drmBO *) private;
int ret;
driReadLockKernelBO();
ret = drmBOWaitIdle(pool->fd, buf, (lazy) ? DRM_BO_HINT_WAIT_LAZY:0);
driReadUnlockKernelBO();
return ret;
}
static void
pool_takedown(struct _DriBufferPool *pool)
{
free(pool);
}
/*static int
pool_setStatus(struct _DriBufferPool *pool, void *private,
uint64_t flag_diff, uint64_t old_flags)
{
drmBO *buf = (drmBO *) private;
uint64_t new_flags = old_flags ^ flag_diff;
int ret;
driReadLockKernelBO();
ret = drmBOSetStatus(pool->fd, buf, new_flags, flag_diff,
0, 0, 0);
driReadUnlockKernelBO();
return ret;
}*/
struct _DriBufferPool *
driDRMPoolInit(int fd)
{
struct _DriBufferPool *pool;
pool = (struct _DriBufferPool *) malloc(sizeof(*pool));
if (!pool)
return NULL;
pool->fd = fd;
pool->map = &pool_map;
pool->unmap = &pool_unmap;
pool->destroy = &pool_destroy;
pool->offset = &pool_offset;
pool->poolOffset = &pool_poolOffset;
pool->flags = &pool_flags;
pool->size = &pool_size;
pool->create = &pool_create;
pool->fence = &pool_fence;
pool->kernel = &pool_kernel;
pool->validate = NULL;
pool->waitIdle = &pool_waitIdle;
pool->takeDown = &pool_takedown;
pool->reference = &pool_reference;
pool->unreference = &pool_unreference;
pool->data = NULL;
return pool;
}
@@ -0,0 +1,377 @@
#include "ws_dri_fencemgr.h"
#include "glthread.h"
#include <xf86mm.h>
#include <string.h>
#include <unistd.h>
/*
* Note: Locking order is
* _DriFenceObject::mutex
* _DriFenceMgr::mutex
*/
struct _DriFenceMgr {
/*
* Constant members. Need no mutex protection.
*/
struct _DriFenceMgrCreateInfo info;
void *private;
/*
* These members are protected by this->mutex
*/
_glthread_Mutex mutex;
int refCount;
drmMMListHead *heads;
int num_fences;
};
struct _DriFenceObject {
/*
* These members are constant and need no mutex protection.
*/
struct _DriFenceMgr *mgr;
uint32_t fence_class;
uint32_t fence_type;
/*
* These members are protected by mgr->mutex.
*/
drmMMListHead head;
int refCount;
/*
* These members are protected by this->mutex.
*/
_glthread_Mutex mutex;
uint32_t signaled_type;
void *private;
};
uint32_t
driFenceType(struct _DriFenceObject *fence)
{
return fence->fence_type;
}
struct _DriFenceMgr *
driFenceMgrCreate(const struct _DriFenceMgrCreateInfo *info)
{
struct _DriFenceMgr *tmp;
uint32_t i;
tmp = calloc(1, sizeof(*tmp));
if (!tmp)
return NULL;
_glthread_INIT_MUTEX(tmp->mutex);
_glthread_LOCK_MUTEX(tmp->mutex);
tmp->refCount = 1;
tmp->info = *info;
tmp->num_fences = 0;
tmp->heads = calloc(tmp->info.num_classes, sizeof(*tmp->heads));
if (!tmp->heads)
goto out_err;
for (i=0; i<tmp->info.num_classes; ++i) {
DRMINITLISTHEAD(&tmp->heads[i]);
}
_glthread_UNLOCK_MUTEX(tmp->mutex);
return tmp;
out_err:
if (tmp)
free(tmp);
return NULL;
}
static void
driFenceMgrUnrefUnlock(struct _DriFenceMgr **pMgr)
{
struct _DriFenceMgr *mgr = *pMgr;
*pMgr = NULL;
if (--mgr->refCount == 0)
free(mgr);
else
_glthread_UNLOCK_MUTEX(mgr->mutex);
}
void
driFenceMgrUnReference(struct _DriFenceMgr **pMgr)
{
_glthread_LOCK_MUTEX((*pMgr)->mutex);
driFenceMgrUnrefUnlock(pMgr);
}
static void
driFenceUnReferenceLocked(struct _DriFenceObject **pFence)
{
struct _DriFenceObject *fence = *pFence;
struct _DriFenceMgr *mgr = fence->mgr;
*pFence = NULL;
if (--fence->refCount == 0) {
DRMLISTDELINIT(&fence->head);
if (fence->private)
mgr->info.unreference(mgr, &fence->private);
--mgr->num_fences;
fence->mgr = NULL;
--mgr->refCount;
free(fence);
}
}
static void
driSignalPreviousFencesLocked(struct _DriFenceMgr *mgr,
drmMMListHead *list,
uint32_t fence_class,
uint32_t fence_type)
{
struct _DriFenceObject *entry;
drmMMListHead *prev;
while(list != &mgr->heads[fence_class]) {
entry = DRMLISTENTRY(struct _DriFenceObject, list, head);
/*
* Up refcount so that entry doesn't disappear from under us
* when we unlock-relock mgr to get the correct locking order.
*/
++entry->refCount;
_glthread_UNLOCK_MUTEX(mgr->mutex);
_glthread_LOCK_MUTEX(entry->mutex);
_glthread_LOCK_MUTEX(mgr->mutex);
prev = list->prev;
if (list->prev == list) {
/*
* Somebody else removed the entry from the list.
*/
_glthread_UNLOCK_MUTEX(entry->mutex);
driFenceUnReferenceLocked(&entry);
return;
}
entry->signaled_type |= (fence_type & entry->fence_type);
if (entry->signaled_type == entry->fence_type) {
DRMLISTDELINIT(list);
mgr->info.unreference(mgr, &entry->private);
}
_glthread_UNLOCK_MUTEX(entry->mutex);
driFenceUnReferenceLocked(&entry);
list = prev;
}
}
int
driFenceFinish(struct _DriFenceObject *fence, uint32_t fence_type,
int lazy_hint)
{
struct _DriFenceMgr *mgr = fence->mgr;
int ret = 0;
_glthread_LOCK_MUTEX(fence->mutex);
if ((fence->signaled_type & fence_type) == fence_type)
goto out0;
ret = mgr->info.finish(mgr, fence->private, fence_type, lazy_hint);
if (ret)
goto out0;
_glthread_LOCK_MUTEX(mgr->mutex);
_glthread_UNLOCK_MUTEX(fence->mutex);
driSignalPreviousFencesLocked(mgr, &fence->head, fence->fence_class,
fence_type);
_glthread_UNLOCK_MUTEX(mgr->mutex);
return 0;
out0:
_glthread_UNLOCK_MUTEX(fence->mutex);
return ret;
}
uint32_t driFenceSignaledTypeCached(struct _DriFenceObject *fence)
{
uint32_t ret;
_glthread_LOCK_MUTEX(fence->mutex);
ret = fence->signaled_type;
_glthread_UNLOCK_MUTEX(fence->mutex);
return ret;
}
int
driFenceSignaledType(struct _DriFenceObject *fence, uint32_t flush_type,
uint32_t *signaled)
{
int ret = 0;
struct _DriFenceMgr *mgr;
_glthread_LOCK_MUTEX(fence->mutex);
mgr = fence->mgr;
*signaled = fence->signaled_type;
if ((fence->signaled_type & flush_type) == flush_type)
goto out0;
ret = mgr->info.signaled(mgr, fence->private, flush_type, signaled);
if (ret) {
*signaled = fence->signaled_type;
goto out0;
}
if ((fence->signaled_type | *signaled) == fence->signaled_type)
goto out0;
_glthread_LOCK_MUTEX(mgr->mutex);
_glthread_UNLOCK_MUTEX(fence->mutex);
driSignalPreviousFencesLocked(mgr, &fence->head, fence->fence_class,
*signaled);
_glthread_UNLOCK_MUTEX(mgr->mutex);
return 0;
out0:
_glthread_UNLOCK_MUTEX(fence->mutex);
return ret;
}
struct _DriFenceObject *
driFenceReference(struct _DriFenceObject *fence)
{
_glthread_LOCK_MUTEX(fence->mgr->mutex);
++fence->refCount;
_glthread_UNLOCK_MUTEX(fence->mgr->mutex);
return fence;
}
void
driFenceUnReference(struct _DriFenceObject **pFence)
{
struct _DriFenceMgr *mgr;
if (*pFence == NULL)
return;
mgr = (*pFence)->mgr;
_glthread_LOCK_MUTEX(mgr->mutex);
++mgr->refCount;
driFenceUnReferenceLocked(pFence);
driFenceMgrUnrefUnlock(&mgr);
}
struct _DriFenceObject
*driFenceCreate(struct _DriFenceMgr *mgr, uint32_t fence_class,
uint32_t fence_type, void *private, size_t private_size)
{
struct _DriFenceObject *fence;
size_t fence_size = sizeof(*fence);
if (private_size)
fence_size = ((fence_size + 15) & ~15);
fence = calloc(1, fence_size + private_size);
if (!fence) {
int ret = mgr->info.finish(mgr, private, fence_type, 0);
if (ret)
usleep(10000000);
return NULL;
}
_glthread_INIT_MUTEX(fence->mutex);
_glthread_LOCK_MUTEX(fence->mutex);
_glthread_LOCK_MUTEX(mgr->mutex);
fence->refCount = 1;
DRMLISTADDTAIL(&fence->head, &mgr->heads[fence_class]);
fence->mgr = mgr;
++mgr->refCount;
++mgr->num_fences;
_glthread_UNLOCK_MUTEX(mgr->mutex);
fence->fence_class = fence_class;
fence->fence_type = fence_type;
fence->signaled_type = 0;
fence->private = private;
if (private_size) {
fence->private = (void *)(((uint8_t *) fence) + fence_size);
memcpy(fence->private, private, private_size);
}
_glthread_UNLOCK_MUTEX(fence->mutex);
return fence;
}
static int
tSignaled(struct _DriFenceMgr *mgr, void *private, uint32_t flush_type,
uint32_t *signaled_type)
{
long fd = (long) mgr->private;
int dummy;
drmFence *fence = (drmFence *) private;
int ret;
*signaled_type = 0;
ret = drmFenceSignaled((int) fd, fence, flush_type, &dummy);
if (ret)
return ret;
*signaled_type = fence->signaled;
return 0;
}
static int
tFinish(struct _DriFenceMgr *mgr, void *private, uint32_t fence_type,
int lazy_hint)
{
long fd = (long) mgr->private;
unsigned flags = lazy_hint ? DRM_FENCE_FLAG_WAIT_LAZY : 0;
return drmFenceWait((int)fd, flags, (drmFence *) private, fence_type);
}
static int
tUnref(struct _DriFenceMgr *mgr, void **private)
{
long fd = (long) mgr->private;
drmFence *fence = (drmFence *) *private;
*private = NULL;
return drmFenceUnreference(fd, fence);
}
struct _DriFenceMgr *driFenceMgrTTMInit(int fd)
{
struct _DriFenceMgrCreateInfo info;
struct _DriFenceMgr *mgr;
info.flags = DRI_FENCE_CLASS_ORDERED;
info.num_classes = 4;
info.signaled = tSignaled;
info.finish = tFinish;
info.unreference = tUnref;
mgr = driFenceMgrCreate(&info);
if (mgr == NULL)
return NULL;
mgr->private = (void *) (long) fd;
return mgr;
}
@@ -0,0 +1,115 @@
#ifndef DRI_FENCEMGR_H
#define DRI_FENCEMGR_H
#include <stdint.h>
#include <stdlib.h>
struct _DriFenceObject;
struct _DriFenceMgr;
/*
* Do a quick check to see if the fence manager has registered the fence
* object as signaled. Note that this function may return a false negative
* answer.
*/
extern uint32_t driFenceSignaledTypeCached(struct _DriFenceObject *fence);
/*
* Check if the fence object is signaled. This function can be substantially
* more expensive to call than the above function, but will not return a false
* negative answer. The argument "flush_type" sets the types that the
* underlying mechanism must make sure will eventually signal.
*/
extern int driFenceSignaledType(struct _DriFenceObject *fence,
uint32_t flush_type, uint32_t *signaled);
/*
* Convenience functions.
*/
static inline int driFenceSignaled(struct _DriFenceObject *fence,
uint32_t flush_type)
{
uint32_t signaled_types;
int ret = driFenceSignaledType(fence, flush_type, &signaled_types);
if (ret)
return 0;
return ((signaled_types & flush_type) == flush_type);
}
static inline int driFenceSignaledCached(struct _DriFenceObject *fence,
uint32_t flush_type)
{
uint32_t signaled_types =
driFenceSignaledTypeCached(fence);
return ((signaled_types & flush_type) == flush_type);
}
/*
* Reference a fence object.
*/
extern struct _DriFenceObject *driFenceReference(struct _DriFenceObject *fence);
/*
* Unreference a fence object. The fence object pointer will be reset to NULL.
*/
extern void driFenceUnReference(struct _DriFenceObject **pFence);
/*
* Wait for a fence to signal the indicated fence_type.
* If "lazy_hint" is true, it indicates that the wait may sleep to avoid
* busy-wait polling.
*/
extern int driFenceFinish(struct _DriFenceObject *fence, uint32_t fence_type,
int lazy_hint);
/*
* Create a DriFenceObject for manager "mgr".
*
* "private" is a pointer that should be used for the callbacks in
* struct _DriFenceMgrCreateInfo.
*
* if private_size is nonzero, then the info stored at *private, with size
* private size will be copied and the fence manager will instead use a
* pointer to the copied data for the callbacks in
* struct _DriFenceMgrCreateInfo. In that case, the object pointed to by
* "private" may be destroyed after the call to driFenceCreate.
*/
extern struct _DriFenceObject *driFenceCreate(struct _DriFenceMgr *mgr,
uint32_t fence_class,
uint32_t fence_type,
void *private,
size_t private_size);
extern uint32_t driFenceType(struct _DriFenceObject *fence);
/*
* Fence creations are ordered. If a fence signals a fence_type,
* it is safe to assume that all fences of the same class that was
* created before that fence has signaled the same type.
*/
#define DRI_FENCE_CLASS_ORDERED (1 << 0)
struct _DriFenceMgrCreateInfo {
uint32_t flags;
uint32_t num_classes;
int (*signaled) (struct _DriFenceMgr *mgr, void *private, uint32_t flush_type,
uint32_t *signaled_type);
int (*finish) (struct _DriFenceMgr *mgr, void *private, uint32_t fence_type, int lazy_hint);
int (*unreference) (struct _DriFenceMgr *mgr, void **private);
};
extern struct _DriFenceMgr *
driFenceMgrCreate(const struct _DriFenceMgrCreateInfo *info);
void
driFenceMgrUnReference(struct _DriFenceMgr **pMgr);
extern struct _DriFenceMgr *
driFenceMgrTTMInit(int fd);
#endif
@@ -0,0 +1,162 @@
/**************************************************************************
*
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, TX., 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: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
*/
#include <xf86drm.h>
#include <stdlib.h>
#include <errno.h>
#include "imports.h"
#include "glthread.h"
#include "ws_dri_bufpool.h"
#include "ws_dri_bufmgr.h"
#include "intel_screen.h"
static void *
pool_create(struct _DriBufferPool *pool,
unsigned long size, uint64_t flags, unsigned hint,
unsigned alignment)
{
unsigned long *private = malloc(size + 2*sizeof(unsigned long));
if ((flags & DRM_BO_MASK_MEM) != DRM_BO_FLAG_MEM_LOCAL)
abort();
*private = size;
return (void *)private;
}
static int
pool_destroy(struct _DriBufferPool *pool, void *private)
{
free(private);
return 0;
}
static int
pool_waitIdle(struct _DriBufferPool *pool, void *private,
_glthread_Mutex *mutex, int lazy)
{
return 0;
}
static int
pool_map(struct _DriBufferPool *pool, void *private, unsigned flags,
int hint, _glthread_Mutex *mutex, void **virtual)
{
*virtual = (void *)((unsigned long *)private + 2);
return 0;
}
static int
pool_unmap(struct _DriBufferPool *pool, void *private)
{
return 0;
}
static unsigned long
pool_offset(struct _DriBufferPool *pool, void *private)
{
/*
* BUG
*/
abort();
return 0UL;
}
static unsigned long
pool_poolOffset(struct _DriBufferPool *pool, void *private)
{
/*
* BUG
*/
abort();
}
static uint64_t
pool_flags(struct _DriBufferPool *pool, void *private)
{
return DRM_BO_FLAG_MEM_LOCAL | DRM_BO_FLAG_CACHED;
}
static unsigned long
pool_size(struct _DriBufferPool *pool, void *private)
{
return *(unsigned long *) private;
}
static int
pool_fence(struct _DriBufferPool *pool, void *private,
struct _DriFenceObject *fence)
{
abort();
return 0UL;
}
static drmBO *
pool_kernel(struct _DriBufferPool *pool, void *private)
{
abort();
return NULL;
}
static void
pool_takedown(struct _DriBufferPool *pool)
{
free(pool);
}
struct _DriBufferPool *
driMallocPoolInit(void)
{
struct _DriBufferPool *pool;
pool = (struct _DriBufferPool *) malloc(sizeof(*pool));
if (!pool)
return NULL;
pool->data = NULL;
pool->fd = -1;
pool->map = &pool_map;
pool->unmap = &pool_unmap;
pool->destroy = &pool_destroy;
pool->offset = &pool_offset;
pool->poolOffset = &pool_poolOffset;
pool->flags = &pool_flags;
pool->size = &pool_size;
pool->create = &pool_create;
pool->fence = &pool_fence;
pool->kernel = &pool_kernel;
pool->validate = NULL;
pool->waitIdle = &pool_waitIdle;
pool->takeDown = &pool_takedown;
return pool;
}
@@ -0,0 +1,968 @@
/**************************************************************************
*
* Copyright 2006-2008 Tungsten Graphics, Inc., Cedar Park, TX., 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: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
*/
#include <stdint.h>
#include <sys/time.h>
#include <errno.h>
#include <unistd.h>
#include <assert.h>
#include "ws_dri_bufpool.h"
#include "ws_dri_fencemgr.h"
#include "ws_dri_bufmgr.h"
#include "glthread.h"
#define DRI_SLABPOOL_ALLOC_RETRIES 100
struct _DriSlab;
struct _DriSlabBuffer {
int isSlabBuffer;
drmBO *bo;
struct _DriFenceObject *fence;
struct _DriSlab *parent;
drmMMListHead head;
uint32_t mapCount;
uint32_t start;
uint32_t fenceType;
int unFenced;
_glthread_Cond event;
};
struct _DriKernelBO {
int fd;
drmBO bo;
drmMMListHead timeoutHead;
drmMMListHead head;
struct timeval timeFreed;
uint32_t pageAlignment;
void *virtual;
};
struct _DriSlab{
drmMMListHead head;
drmMMListHead freeBuffers;
uint32_t numBuffers;
uint32_t numFree;
struct _DriSlabBuffer *buffers;
struct _DriSlabSizeHeader *header;
struct _DriKernelBO *kbo;
};
struct _DriSlabSizeHeader {
drmMMListHead slabs;
drmMMListHead freeSlabs;
drmMMListHead delayedBuffers;
uint32_t numDelayed;
struct _DriSlabPool *slabPool;
uint32_t bufSize;
_glthread_Mutex mutex;
};
struct _DriFreeSlabManager {
struct timeval slabTimeout;
struct timeval checkInterval;
struct timeval nextCheck;
drmMMListHead timeoutList;
drmMMListHead unCached;
drmMMListHead cached;
_glthread_Mutex mutex;
};
struct _DriSlabPool {
/*
* The data of this structure remains constant after
* initialization and thus needs no mutex protection.
*/
struct _DriFreeSlabManager *fMan;
uint64_t proposedFlags;
uint64_t validMask;
uint32_t *bucketSizes;
uint32_t numBuckets;
uint32_t pageSize;
int fd;
int pageAlignment;
int maxSlabSize;
int desiredNumBuffers;
struct _DriSlabSizeHeader *headers;
};
/*
* FIXME: Perhaps arrange timeout slabs in size buckets for fast
* retreival??
*/
static inline int
driTimeAfterEq(struct timeval *arg1, struct timeval *arg2)
{
return ((arg1->tv_sec > arg2->tv_sec) ||
((arg1->tv_sec == arg2->tv_sec) &&
(arg1->tv_usec > arg2->tv_usec)));
}
static inline void
driTimeAdd(struct timeval *arg, struct timeval *add)
{
unsigned int sec;
arg->tv_sec += add->tv_sec;
arg->tv_usec += add->tv_usec;
sec = arg->tv_usec / 1000000;
arg->tv_sec += sec;
arg->tv_usec -= sec*1000000;
}
static void
driFreeKernelBO(struct _DriKernelBO *kbo)
{
if (!kbo)
return;
(void) drmBOUnreference(kbo->fd, &kbo->bo);
free(kbo);
}
static void
driFreeTimeoutKBOsLocked(struct _DriFreeSlabManager *fMan,
struct timeval *time)
{
drmMMListHead *list, *next;
struct _DriKernelBO *kbo;
if (!driTimeAfterEq(time, &fMan->nextCheck))
return;
for (list = fMan->timeoutList.next, next = list->next;
list != &fMan->timeoutList;
list = next, next = list->next) {
kbo = DRMLISTENTRY(struct _DriKernelBO, list, timeoutHead);
if (!driTimeAfterEq(time, &kbo->timeFreed))
break;
DRMLISTDELINIT(&kbo->timeoutHead);
DRMLISTDELINIT(&kbo->head);
driFreeKernelBO(kbo);
}
fMan->nextCheck = *time;
driTimeAdd(&fMan->nextCheck, &fMan->checkInterval);
}
/*
* Add a _DriKernelBO to the free slab manager.
* This means that it is available for reuse, but if it's not
* reused in a while, it will be freed.
*/
static void
driSetKernelBOFree(struct _DriFreeSlabManager *fMan,
struct _DriKernelBO *kbo)
{
struct timeval time;
_glthread_LOCK_MUTEX(fMan->mutex);
gettimeofday(&time, NULL);
driTimeAdd(&time, &fMan->slabTimeout);
kbo->timeFreed = time;
if (kbo->bo.flags & DRM_BO_FLAG_CACHED)
DRMLISTADD(&kbo->head, &fMan->cached);
else
DRMLISTADD(&kbo->head, &fMan->unCached);
DRMLISTADDTAIL(&kbo->timeoutHead, &fMan->timeoutList);
driFreeTimeoutKBOsLocked(fMan, &time);
_glthread_UNLOCK_MUTEX(fMan->mutex);
}
/*
* Get a _DriKernelBO for us to use as storage for a slab.
*
*/
static struct _DriKernelBO *
driAllocKernelBO(struct _DriSlabSizeHeader *header)
{
struct _DriSlabPool *slabPool = header->slabPool;
struct _DriFreeSlabManager *fMan = slabPool->fMan;
drmMMListHead *list, *next, *head;
uint32_t size = header->bufSize * slabPool->desiredNumBuffers;
struct _DriKernelBO *kbo;
struct _DriKernelBO *kboTmp;
int ret;
/*
* FIXME: We should perhaps allow some variation in slabsize in order
* to efficiently reuse slabs.
*/
size = (size <= slabPool->maxSlabSize) ? size : slabPool->maxSlabSize;
size = (size + slabPool->pageSize - 1) & ~(slabPool->pageSize - 1);
_glthread_LOCK_MUTEX(fMan->mutex);
kbo = NULL;
retry:
head = (slabPool->proposedFlags & DRM_BO_FLAG_CACHED) ?
&fMan->cached : &fMan->unCached;
for (list = head->next, next = list->next;
list != head;
list = next, next = list->next) {
kboTmp = DRMLISTENTRY(struct _DriKernelBO, list, head);
if ((kboTmp->bo.size == size) &&
(slabPool->pageAlignment == 0 ||
(kboTmp->pageAlignment % slabPool->pageAlignment) == 0)) {
if (!kbo)
kbo = kboTmp;
if ((kbo->bo.proposedFlags ^ slabPool->proposedFlags) == 0)
break;
}
}
if (kbo) {
DRMLISTDELINIT(&kbo->head);
DRMLISTDELINIT(&kbo->timeoutHead);
}
_glthread_UNLOCK_MUTEX(fMan->mutex);
if (kbo) {
uint64_t new_mask = kbo->bo.proposedFlags ^ slabPool->proposedFlags;
ret = 0;
if (new_mask) {
ret = drmBOSetStatus(kbo->fd, &kbo->bo, slabPool->proposedFlags,
new_mask, DRM_BO_HINT_DONT_FENCE, 0, 0);
}
if (ret == 0)
return kbo;
driFreeKernelBO(kbo);
kbo = NULL;
goto retry;
}
kbo = calloc(1, sizeof(struct _DriKernelBO));
if (!kbo)
return NULL;
kbo->fd = slabPool->fd;
DRMINITLISTHEAD(&kbo->head);
DRMINITLISTHEAD(&kbo->timeoutHead);
ret = drmBOCreate(kbo->fd, size, slabPool->pageAlignment, NULL,
slabPool->proposedFlags,
DRM_BO_HINT_DONT_FENCE, &kbo->bo);
if (ret)
goto out_err0;
ret = drmBOMap(kbo->fd, &kbo->bo,
DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE,
0, &kbo->virtual);
if (ret)
goto out_err1;
ret = drmBOUnmap(kbo->fd, &kbo->bo);
if (ret)
goto out_err1;
return kbo;
out_err1:
drmBOUnreference(kbo->fd, &kbo->bo);
out_err0:
free(kbo);
return NULL;
}
static int
driAllocSlab(struct _DriSlabSizeHeader *header)
{
struct _DriSlab *slab;
struct _DriSlabBuffer *buf;
uint32_t numBuffers;
int ret;
int i;
slab = calloc(1, sizeof(*slab));
if (!slab)
return -ENOMEM;
slab->kbo = driAllocKernelBO(header);
if (!slab->kbo) {
ret = -ENOMEM;
goto out_err0;
}
numBuffers = slab->kbo->bo.size / header->bufSize;
slab->buffers = calloc(numBuffers, sizeof(*slab->buffers));
if (!slab->buffers) {
ret = -ENOMEM;
goto out_err1;
}
DRMINITLISTHEAD(&slab->head);
DRMINITLISTHEAD(&slab->freeBuffers);
slab->numBuffers = numBuffers;
slab->numFree = 0;
slab->header = header;
buf = slab->buffers;
for (i=0; i < numBuffers; ++i) {
buf->parent = slab;
buf->start = i* header->bufSize;
buf->mapCount = 0;
buf->isSlabBuffer = 1;
_glthread_INIT_COND(buf->event);
DRMLISTADDTAIL(&buf->head, &slab->freeBuffers);
slab->numFree++;
buf++;
}
DRMLISTADDTAIL(&slab->head, &header->slabs);
return 0;
out_err1:
driSetKernelBOFree(header->slabPool->fMan, slab->kbo);
free(slab->buffers);
out_err0:
free(slab);
return ret;
}
/*
* Delete a buffer from the slab header delayed list and put
* it on the slab free list.
*/
static void
driSlabFreeBufferLocked(struct _DriSlabBuffer *buf)
{
struct _DriSlab *slab = buf->parent;
struct _DriSlabSizeHeader *header = slab->header;
drmMMListHead *list = &buf->head;
DRMLISTDEL(list);
DRMLISTADDTAIL(list, &slab->freeBuffers);
slab->numFree++;
if (slab->head.next == &slab->head)
DRMLISTADDTAIL(&slab->head, &header->slabs);
if (slab->numFree == slab->numBuffers) {
list = &slab->head;
DRMLISTDEL(list);
DRMLISTADDTAIL(list, &header->freeSlabs);
}
if (header->slabs.next == &header->slabs ||
slab->numFree != slab->numBuffers) {
drmMMListHead *next;
struct _DriFreeSlabManager *fMan = header->slabPool->fMan;
for (list = header->freeSlabs.next, next = list->next;
list != &header->freeSlabs;
list = next, next = list->next) {
slab = DRMLISTENTRY(struct _DriSlab, list, head);
DRMLISTDELINIT(list);
driSetKernelBOFree(fMan, slab->kbo);
free(slab->buffers);
free(slab);
}
}
}
static void
driSlabCheckFreeLocked(struct _DriSlabSizeHeader *header, int wait)
{
drmMMListHead *list, *prev, *first;
struct _DriSlabBuffer *buf;
struct _DriSlab *slab;
int firstWasSignaled = 1;
int signaled;
int i;
int ret;
/*
* Rerun the freeing test if the youngest tested buffer
* was signaled, since there might be more idle buffers
* in the delay list.
*/
while (firstWasSignaled) {
firstWasSignaled = 0;
signaled = 0;
first = header->delayedBuffers.next;
/* Only examine the oldest 1/3 of delayed buffers:
*/
if (header->numDelayed > 3) {
for (i = 0; i < header->numDelayed; i += 3) {
first = first->next;
}
}
for (list = first, prev = list->prev;
list != &header->delayedBuffers;
list = prev, prev = list->prev) {
buf = DRMLISTENTRY(struct _DriSlabBuffer, list, head);
slab = buf->parent;
if (!signaled) {
if (wait) {
ret = driFenceFinish(buf->fence, buf->fenceType, 0);
if (ret)
break;
signaled = 1;
wait = 0;
} else {
signaled = driFenceSignaled(buf->fence, buf->fenceType);
}
if (signaled) {
if (list == first)
firstWasSignaled = 1;
driFenceUnReference(&buf->fence);
header->numDelayed--;
driSlabFreeBufferLocked(buf);
}
} else if (driFenceSignaledCached(buf->fence, buf->fenceType)) {
driFenceUnReference(&buf->fence);
header->numDelayed--;
driSlabFreeBufferLocked(buf);
}
}
}
}
static struct _DriSlabBuffer *
driSlabAllocBuffer(struct _DriSlabSizeHeader *header)
{
static struct _DriSlabBuffer *buf;
struct _DriSlab *slab;
drmMMListHead *list;
int count = DRI_SLABPOOL_ALLOC_RETRIES;
_glthread_LOCK_MUTEX(header->mutex);
while(header->slabs.next == &header->slabs && count > 0) {
driSlabCheckFreeLocked(header, 0);
if (header->slabs.next != &header->slabs)
break;
_glthread_UNLOCK_MUTEX(header->mutex);
if (count != DRI_SLABPOOL_ALLOC_RETRIES)
usleep(1);
_glthread_LOCK_MUTEX(header->mutex);
(void) driAllocSlab(header);
count--;
}
list = header->slabs.next;
if (list == &header->slabs) {
_glthread_UNLOCK_MUTEX(header->mutex);
return NULL;
}
slab = DRMLISTENTRY(struct _DriSlab, list, head);
if (--slab->numFree == 0)
DRMLISTDELINIT(list);
list = slab->freeBuffers.next;
DRMLISTDELINIT(list);
_glthread_UNLOCK_MUTEX(header->mutex);
buf = DRMLISTENTRY(struct _DriSlabBuffer, list, head);
return buf;
}
static void *
pool_create(struct _DriBufferPool *driPool, unsigned long size,
uint64_t flags, unsigned hint, unsigned alignment)
{
struct _DriSlabPool *pool = (struct _DriSlabPool *) driPool->data;
struct _DriSlabSizeHeader *header;
struct _DriSlabBuffer *buf;
void *dummy;
int i;
int ret;
/*
* FIXME: Check for compatibility.
*/
header = pool->headers;
for (i=0; i<pool->numBuckets; ++i) {
if (header->bufSize >= size)
break;
header++;
}
if (i < pool->numBuckets)
return driSlabAllocBuffer(header);
/*
* Fall back to allocate a buffer object directly from DRM.
* and wrap it in a driBO structure.
*/
buf = calloc(1, sizeof(*buf));
if (!buf)
return NULL;
buf->bo = calloc(1, sizeof(*buf->bo));
if (!buf->bo)
goto out_err0;
if (alignment) {
if ((alignment < pool->pageSize) && (pool->pageSize % alignment))
goto out_err1;
if ((alignment > pool->pageSize) && (alignment % pool->pageSize))
goto out_err1;
}
ret = drmBOCreate(pool->fd, size, alignment / pool->pageSize, NULL,
flags, hint, buf->bo);
if (ret)
goto out_err1;
ret = drmBOMap(pool->fd, buf->bo, DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE,
0, &dummy);
if (ret)
goto out_err2;
ret = drmBOUnmap(pool->fd, buf->bo);
if (ret)
goto out_err2;
return buf;
out_err2:
drmBOUnreference(pool->fd, buf->bo);
out_err1:
free(buf->bo);
out_err0:
free(buf);
return NULL;
}
static int
pool_destroy(struct _DriBufferPool *driPool, void *private)
{
struct _DriSlabBuffer *buf =
(struct _DriSlabBuffer *) private;
struct _DriSlab *slab;
struct _DriSlabSizeHeader *header;
if (!buf->isSlabBuffer) {
struct _DriSlabPool *pool = (struct _DriSlabPool *) driPool->data;
int ret;
ret = drmBOUnreference(pool->fd, buf->bo);
free(buf->bo);
free(buf);
return ret;
}
slab = buf->parent;
header = slab->header;
_glthread_LOCK_MUTEX(header->mutex);
buf->unFenced = 0;
buf->mapCount = 0;
if (buf->fence && !driFenceSignaledCached(buf->fence, buf->fenceType)) {
DRMLISTADDTAIL(&buf->head, &header->delayedBuffers);
header->numDelayed++;
} else {
if (buf->fence)
driFenceUnReference(&buf->fence);
driSlabFreeBufferLocked(buf);
}
_glthread_UNLOCK_MUTEX(header->mutex);
return 0;
}
static int
pool_waitIdle(struct _DriBufferPool *driPool, void *private,
_glthread_Mutex *mutex, int lazy)
{
struct _DriSlabBuffer *buf = (struct _DriSlabBuffer *) private;
while(buf->unFenced)
_glthread_COND_WAIT(buf->event, *mutex);
if (!buf->fence)
return 0;
driFenceFinish(buf->fence, buf->fenceType, lazy);
driFenceUnReference(&buf->fence);
return 0;
}
static int
pool_map(struct _DriBufferPool *pool, void *private, unsigned flags,
int hint, _glthread_Mutex *mutex, void **virtual)
{
struct _DriSlabBuffer *buf = (struct _DriSlabBuffer *) private;
int busy;
if (buf->isSlabBuffer)
busy = buf->unFenced || (buf->fence && !driFenceSignaledCached(buf->fence, buf->fenceType));
else
busy = buf->fence && !driFenceSignaled(buf->fence, buf->fenceType);
if (busy) {
if (hint & DRM_BO_HINT_DONT_BLOCK)
return -EBUSY;
else {
(void) pool_waitIdle(pool, private, mutex, 0);
}
}
++buf->mapCount;
*virtual = (buf->isSlabBuffer) ?
(void *) ((uint8_t *) buf->parent->kbo->virtual + buf->start) :
(void *) buf->bo->virtual;
return 0;
}
static int
pool_unmap(struct _DriBufferPool *pool, void *private)
{
struct _DriSlabBuffer *buf = (struct _DriSlabBuffer *) private;
--buf->mapCount;
if (buf->mapCount == 0 && buf->isSlabBuffer)
_glthread_COND_BROADCAST(buf->event);
return 0;
}
static unsigned long
pool_offset(struct _DriBufferPool *pool, void *private)
{
struct _DriSlabBuffer *buf = (struct _DriSlabBuffer *) private;
struct _DriSlab *slab;
struct _DriSlabSizeHeader *header;
if (!buf->isSlabBuffer) {
assert(buf->bo->proposedFlags & DRM_BO_FLAG_NO_MOVE);
return buf->bo->offset;
}
slab = buf->parent;
header = slab->header;
(void) header;
assert(header->slabPool->proposedFlags & DRM_BO_FLAG_NO_MOVE);
return slab->kbo->bo.offset + buf->start;
}
static unsigned long
pool_poolOffset(struct _DriBufferPool *pool, void *private)
{
struct _DriSlabBuffer *buf = (struct _DriSlabBuffer *) private;
return buf->start;
}
static uint64_t
pool_flags(struct _DriBufferPool *pool, void *private)
{
struct _DriSlabBuffer *buf = (struct _DriSlabBuffer *) private;
if (!buf->isSlabBuffer)
return buf->bo->flags;
return buf->parent->kbo->bo.flags;
}
static unsigned long
pool_size(struct _DriBufferPool *pool, void *private)
{
struct _DriSlabBuffer *buf = (struct _DriSlabBuffer *) private;
if (!buf->isSlabBuffer)
return buf->bo->size;
return buf->parent->header->bufSize;
}
static int
pool_fence(struct _DriBufferPool *pool, void *private,
struct _DriFenceObject *fence)
{
struct _DriSlabBuffer *buf = (struct _DriSlabBuffer *) private;
drmBO *bo;
if (buf->fence)
driFenceUnReference(&buf->fence);
buf->fence = driFenceReference(fence);
bo = (buf->isSlabBuffer) ?
&buf->parent->kbo->bo:
buf->bo;
buf->fenceType = bo->fenceFlags;
buf->unFenced = 0;
_glthread_COND_BROADCAST(buf->event);
return 0;
}
static drmBO *
pool_kernel(struct _DriBufferPool *pool, void *private)
{
struct _DriSlabBuffer *buf = (struct _DriSlabBuffer *) private;
return (buf->isSlabBuffer) ? &buf->parent->kbo->bo : buf->bo;
}
static int
pool_validate(struct _DriBufferPool *pool, void *private,
_glthread_Mutex *mutex)
{
struct _DriSlabBuffer *buf = (struct _DriSlabBuffer *) private;
if (!buf->isSlabBuffer)
return 0;
while(buf->mapCount != 0)
_glthread_COND_WAIT(buf->event, *mutex);
buf->unFenced = 1;
return 0;
}
struct _DriFreeSlabManager *
driInitFreeSlabManager(uint32_t checkIntervalMsec, uint32_t slabTimeoutMsec)
{
struct _DriFreeSlabManager *tmp;
tmp = calloc(1, sizeof(*tmp));
if (!tmp)
return NULL;
_glthread_INIT_MUTEX(tmp->mutex);
_glthread_LOCK_MUTEX(tmp->mutex);
tmp->slabTimeout.tv_usec = slabTimeoutMsec*1000;
tmp->slabTimeout.tv_sec = tmp->slabTimeout.tv_usec / 1000000;
tmp->slabTimeout.tv_usec -= tmp->slabTimeout.tv_sec*1000000;
tmp->checkInterval.tv_usec = checkIntervalMsec*1000;
tmp->checkInterval.tv_sec = tmp->checkInterval.tv_usec / 1000000;
tmp->checkInterval.tv_usec -= tmp->checkInterval.tv_sec*1000000;
gettimeofday(&tmp->nextCheck, NULL);
driTimeAdd(&tmp->nextCheck, &tmp->checkInterval);
DRMINITLISTHEAD(&tmp->timeoutList);
DRMINITLISTHEAD(&tmp->unCached);
DRMINITLISTHEAD(&tmp->cached);
_glthread_UNLOCK_MUTEX(tmp->mutex);
return tmp;
}
void
driFinishFreeSlabManager(struct _DriFreeSlabManager *fMan)
{
struct timeval time;
time = fMan->nextCheck;
driTimeAdd(&time, &fMan->checkInterval);
_glthread_LOCK_MUTEX(fMan->mutex);
driFreeTimeoutKBOsLocked(fMan, &time);
_glthread_UNLOCK_MUTEX(fMan->mutex);
assert(fMan->timeoutList.next == &fMan->timeoutList);
assert(fMan->unCached.next == &fMan->unCached);
assert(fMan->cached.next == &fMan->cached);
free(fMan);
}
static void
driInitSizeHeader(struct _DriSlabPool *pool, uint32_t size,
struct _DriSlabSizeHeader *header)
{
_glthread_INIT_MUTEX(header->mutex);
_glthread_LOCK_MUTEX(header->mutex);
DRMINITLISTHEAD(&header->slabs);
DRMINITLISTHEAD(&header->freeSlabs);
DRMINITLISTHEAD(&header->delayedBuffers);
header->numDelayed = 0;
header->slabPool = pool;
header->bufSize = size;
_glthread_UNLOCK_MUTEX(header->mutex);
}
static void
driFinishSizeHeader(struct _DriSlabSizeHeader *header)
{
drmMMListHead *list, *next;
struct _DriSlabBuffer *buf;
_glthread_LOCK_MUTEX(header->mutex);
for (list = header->delayedBuffers.next, next = list->next;
list != &header->delayedBuffers;
list = next, next = list->next) {
buf = DRMLISTENTRY(struct _DriSlabBuffer, list , head);
if (buf->fence) {
(void) driFenceFinish(buf->fence, buf->fenceType, 0);
driFenceUnReference(&buf->fence);
}
header->numDelayed--;
driSlabFreeBufferLocked(buf);
}
_glthread_UNLOCK_MUTEX(header->mutex);
}
static void
pool_takedown(struct _DriBufferPool *driPool)
{
struct _DriSlabPool *pool = driPool->data;
int i;
for (i=0; i<pool->numBuckets; ++i) {
driFinishSizeHeader(&pool->headers[i]);
}
free(pool->headers);
free(pool->bucketSizes);
free(pool);
free(driPool);
}
struct _DriBufferPool *
driSlabPoolInit(int fd, uint64_t flags,
uint64_t validMask,
uint32_t smallestSize,
uint32_t numSizes,
uint32_t desiredNumBuffers,
uint32_t maxSlabSize,
uint32_t pageAlignment,
struct _DriFreeSlabManager *fMan)
{
struct _DriBufferPool *driPool;
struct _DriSlabPool *pool;
uint32_t i;
driPool = calloc(1, sizeof(*driPool));
if (!driPool)
return NULL;
pool = calloc(1, sizeof(*pool));
if (!pool)
goto out_err0;
pool->bucketSizes = calloc(numSizes, sizeof(*pool->bucketSizes));
if (!pool->bucketSizes)
goto out_err1;
pool->headers = calloc(numSizes, sizeof(*pool->headers));
if (!pool->headers)
goto out_err2;
pool->fMan = fMan;
pool->proposedFlags = flags;
pool->validMask = validMask;
pool->numBuckets = numSizes;
pool->pageSize = getpagesize();
pool->fd = fd;
pool->pageAlignment = pageAlignment;
pool->maxSlabSize = maxSlabSize;
pool->desiredNumBuffers = desiredNumBuffers;
for (i=0; i<pool->numBuckets; ++i) {
pool->bucketSizes[i] = (smallestSize << i);
driInitSizeHeader(pool, pool->bucketSizes[i],
&pool->headers[i]);
}
driPool->data = (void *) pool;
driPool->map = &pool_map;
driPool->unmap = &pool_unmap;
driPool->destroy = &pool_destroy;
driPool->offset = &pool_offset;
driPool->poolOffset = &pool_poolOffset;
driPool->flags = &pool_flags;
driPool->size = &pool_size;
driPool->create = &pool_create;
driPool->fence = &pool_fence;
driPool->kernel = &pool_kernel;
driPool->validate = &pool_validate;
driPool->waitIdle = &pool_waitIdle;
driPool->takeDown = &pool_takedown;
return driPool;
out_err2:
free(pool->bucketSizes);
out_err1:
free(pool);
out_err0:
free(driPool);
return NULL;
}
+38
View File
@@ -0,0 +1,38 @@
# src/mesa/drivers/egl_drm/Makefile
TOP = ../../../..
include $(TOP)/configs/current
default: $(TOP)/$(LIB_DIR) subdirs
$(TOP)/$(LIB_DIR):
-mkdir $(TOP)/$(LIB_DIR)
subdirs:
@for dir in $(DRI_DIRS) ; do \
if [ -d $$dir ] ; then \
(cd $$dir && $(MAKE)) || exit 1 ; \
fi \
done
install:
@for dir in $(DRI_DIRS) ; do \
if [ -d $$dir ] ; then \
(cd $$dir && $(MAKE) install) || exit 1 ; \
fi \
done
clean:
@for dir in $(DRI_DIRS) ; do \
if [ -d $$dir ] ; then \
(cd $$dir && $(MAKE) clean) ; \
fi \
done
-rm -f common/*.o
@@ -0,0 +1,116 @@
# -*-makefile-*-
MESA_MODULES = \
$(TOP)/src/mesa/libmesa.a \
$(GALLIUM_AUXILIARIES)
COMMON_GALLIUM_SOURCES = \
$(TOP)/src/mesa/drivers/dri/common/utils.c \
$(TOP)/src/mesa/drivers/dri/common/vblank.c \
$(TOP)/src/mesa/drivers/dri/common/dri_util.c \
$(TOP)/src/mesa/drivers/dri/common/xmlconfig.c
COMMON_SOURCES = $(COMMON_GALLIUM_SOURCES) \
$(TOP)/src/mesa/drivers/common/driverfuncs.c \
$(TOP)/src/mesa/drivers/dri/common/texmem.c \
$(TOP)/src/mesa/drivers/dri/common/drirenderbuffer.c
COMMON_BM_SOURCES = \
$(TOP)/src/mesa/drivers/dri/common/dri_bufmgr.c \
$(TOP)/src/mesa/drivers/dri/common/dri_drmpool.c
ifeq ($(WINDOW_SYSTEM),dri)
WINOBJ=
WINLIB=
INCLUDES = $(SHARED_INCLUDES) $(EXPAT_INCLUDES)
OBJECTS = \
$(C_SOURCES:.c=.o) \
$(ASM_SOURCES:.S=.o)
else
# miniglx
WINOBJ=
WINLIB=-L$(MESA)/src/glx/mini
MINIGLX_INCLUDES = -I$(TOP)/src/glx/mini
INCLUDES = $(MINIGLX_INCLUDES) \
$(SHARED_INCLUDES) \
$(PCIACCESS_CFLAGS)
OBJECTS = $(C_SOURCES:.c=.o) \
$(MINIGLX_SOURCES:.c=.o) \
$(ASM_SOURCES:.S=.o)
endif
### Include directories
SHARED_INCLUDES = \
-I. \
-I$(TOP)/src/mesa/drivers/dri/common \
-Iserver \
-I$(TOP)/include \
-I$(TOP)/include/GL/internal \
-I$(TOP)/src/gallium/include \
-I$(TOP)/src/gallium/auxiliary \
-I$(TOP)/src/gallium/drivers \
-I$(TOP)/src/mesa \
-I$(TOP)/src/mesa/main \
-I$(TOP)/src/mesa/glapi \
-I$(TOP)/src/mesa/math \
-I$(TOP)/src/mesa/transform \
-I$(TOP)/src/mesa/shader \
-I$(TOP)/src/mesa/swrast \
-I$(TOP)/src/mesa/swrast_setup \
-I$(TOP)/src/egl/main \
-I$(TOP)/src/egl/drivers/dri \
$(LIBDRM_CFLAGS)
##### RULES #####
.c.o:
$(CC) -c $(INCLUDES) $(CFLAGS) $(DRIVER_DEFINES) $< -o $@
.S.o:
$(CC) -c $(INCLUDES) $(CFLAGS) $(DRIVER_DEFINES) $< -o $@
##### TARGETS #####
default: depend symlinks $(LIBNAME) $(TOP)/$(LIB_DIR)/$(LIBNAME)
$(LIBNAME): $(OBJECTS) $(MESA_MODULES) $(PIPE_DRIVERS) $(WINOBJ) Makefile $(TOP)/src/mesa/drivers/dri/Makefile.template
$(TOP)/bin/mklib -noprefix -o $@ \
$(OBJECTS) $(PIPE_DRIVERS) $(MESA_MODULES) $(WINOBJ) $(DRI_LIB_DEPS)
$(TOP)/$(LIB_DIR)/$(LIBNAME): $(LIBNAME)
$(INSTALL) $(LIBNAME) $(TOP)/$(LIB_DIR)
depend: $(C_SOURCES) $(ASM_SOURCES) $(SYMLINKS)
rm -f depend
touch depend
$(MKDEP) $(MKDEP_OPTIONS) $(DRIVER_DEFINES) $(INCLUDES) $(C_SOURCES) \
$(ASM_SOURCES) 2> /dev/null
# Emacs tags
tags:
etags `find . -name \*.[ch]` `find ../include`
# Remove .o and backup files
clean:
-rm -f *.o */*.o *~ *.so *~ server/*.o $(SYMLINKS)
-rm -f depend depend.bak
install: $(LIBNAME)
$(INSTALL) -d $(DRI_DRIVER_INSTALL_DIR)
$(INSTALL) -m 755 $(LIBNAME) $(DRI_DRIVER_INSTALL_DIR)
include depend
+40
View File
@@ -0,0 +1,40 @@
TOP = ../../../../..
include $(TOP)/configs/current
LIBNAME = EGL_i915.so
PIPE_DRIVERS = \
$(TOP)/src/gallium/drivers/softpipe/libsoftpipe.a \
$(TOP)/src/gallium/drivers/i915simple/libi915simple.a
DRIVER_SOURCES = \
intel_winsys_pipe.c \
intel_winsys_softpipe.c \
intel_winsys_i915.c \
intel_batchbuffer.c \
intel_swapbuffers.c \
intel_context.c \
intel_lock.c \
intel_screen.c \
ws_dri_bufmgr.c \
ws_dri_drmpool.c \
ws_dri_fencemgr.c \
ws_dri_mallocpool.c \
ws_dri_slabpool.c \
intel_egl.c
C_SOURCES = \
$(COMMON_GALLIUM_SOURCES) \
$(DRIVER_SOURCES)
ASM_SOURCES =
DRIVER_DEFINES = -I$(TOP)/src/mesa/drivers/dri/intel $(shell pkg-config libdrm --atleast-version=2.3.1 \
&& echo "-DDRM_VBLANK_FLIP=DRM_VBLANK_FLIP")
include ../Makefile.template
intel_tex_layout.o: $(TOP)/src/mesa/drivers/dri/intel/intel_tex_layout.c
symlinks:
@@ -0,0 +1,39 @@
Import('*')
env = drienv.Clone()
env.Append(CPPPATH = [
'../intel',
'server'
])
#MINIGLX_SOURCES = server/intel_dri.c
DRIVER_SOURCES = [
'intel_winsys_pipe.c',
'intel_winsys_softpipe.c',
'intel_winsys_i915.c',
'intel_batchbuffer.c',
'intel_swapbuffers.c',
'intel_context.c',
'intel_lock.c',
'intel_screen.c',
'intel_batchpool.c',
]
sources = \
COMMON_GALLIUM_SOURCES + \
COMMON_BM_SOURCES + \
DRIVER_SOURCES
drivers = [
softpipe,
i915simple
]
# TODO: write a wrapper function http://www.scons.org/wiki/WrapperFunctions
env.SharedLibrary(
target ='i915tex_dri.so',
source = sources,
LIBS = drivers + mesa + auxiliaries + env['LIBS'],
)
@@ -0,0 +1,465 @@
/**************************************************************************
*
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "intel_batchbuffer.h"
#include "intel_context.h"
#include "intel_egl.h"
#include <errno.h>
#if 0
static void
intel_dump_batchbuffer(GLuint offset, GLuint * ptr, GLuint count)
{
int i;
fprintf(stderr, "\n\n\nSTART BATCH (%d dwords):\n", count / 4);
for (i = 0; i < count / 4; i += 4)
fprintf(stderr, "0x%x:\t0x%08x 0x%08x 0x%08x 0x%08x\n",
offset + i * 4, ptr[i], ptr[i + 1], ptr[i + 2], ptr[i + 3]);
fprintf(stderr, "END BATCH\n\n\n");
}
#endif
static void
intel_realloc_relocs(struct intel_batchbuffer *batch, int num_relocs)
{
unsigned long size = num_relocs * I915_RELOC0_STRIDE + I915_RELOC_HEADER;
size *= sizeof(uint32_t);
batch->reloc = realloc(batch->reloc, size);
batch->reloc_size = num_relocs;
}
void
intel_batchbuffer_reset(struct intel_batchbuffer *batch)
{
/*
* Get a new, free batchbuffer.
*/
drmBO *bo;
struct drm_bo_info_req *req;
int ret;
driBOUnrefUserList(batch->list);
driBOResetList(batch->list);
batch->size = 4096; // ZZZ JB batch->intel->intelScreen->maxBatchSize;
ret = driBOData(batch->buffer, batch->size, NULL, NULL, 0);
assert(!ret);
/*
* Add the batchbuffer to the validate list.
*/
driBOAddListItem(batch->list, batch->buffer,
DRM_BO_FLAG_EXE | DRM_BO_FLAG_MEM_TT,
DRM_BO_FLAG_EXE | DRM_BO_MASK_MEM,
&batch->dest_location, &batch->node);
req = &batch->node->bo_arg.d.req.bo_req;
/*
* Set up information needed for us to make relocations
* relative to the underlying drm buffer objects.
*/
driReadLockKernelBO();
bo = driBOKernel(batch->buffer);
req->presumed_offset = (uint64_t) bo->offset;
req->hint = DRM_BO_HINT_PRESUMED_OFFSET;
batch->drmBOVirtual = (uint8_t *) bo->virtual;
driReadUnlockKernelBO();
/*
* Adjust the relocation buffer size.
*/
if (batch->reloc_size > INTEL_MAX_RELOCS ||
batch->reloc == NULL)
intel_realloc_relocs(batch, INTEL_DEFAULT_RELOCS);
assert(batch->reloc != NULL);
batch->reloc[0] = 0; /* No relocs yet. */
batch->reloc[1] = 1; /* Reloc type 1 */
batch->reloc[2] = 0; /* Only a single relocation list. */
batch->reloc[3] = 0; /* Only a single relocation list. */
batch->map = driBOMap(batch->buffer, DRM_BO_FLAG_WRITE, 0);
batch->poolOffset = driBOPoolOffset(batch->buffer);
batch->ptr = batch->map;
batch->dirty_state = ~0;
batch->nr_relocs = 0;
batch->flags = 0;
batch->id = 0;//batch->intel->intelScreen->batch_id++;
}
/*======================================================================
* Public functions
*/
struct intel_batchbuffer *
intel_batchbuffer_alloc(struct intel_screen *intel_screen)
{
struct intel_batchbuffer *batch = calloc(sizeof(*batch), 1);
batch->intel_screen = intel_screen;
driGenBuffers(intel_screen->batchPool, "batchbuffer", 1,
&batch->buffer, 4096,
DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_EXE, 0);
batch->last_fence = NULL;
batch->list = driBOCreateList(20);
batch->reloc = NULL;
intel_batchbuffer_reset(batch);
return batch;
}
void
intel_batchbuffer_free(struct intel_batchbuffer *batch)
{
if (batch->last_fence) {
driFenceFinish(batch->last_fence,
DRM_FENCE_TYPE_EXE, GL_FALSE);
driFenceUnReference(&batch->last_fence);
}
if (batch->map) {
driBOUnmap(batch->buffer);
batch->map = NULL;
}
driBOUnReference(batch->buffer);
driBOFreeList(batch->list);
if (batch->reloc)
free(batch->reloc);
batch->buffer = NULL;
free(batch);
}
void
intel_offset_relocation(struct intel_batchbuffer *batch,
unsigned pre_add,
struct _DriBufferObject *driBO,
uint64_t val_flags,
uint64_t val_mask)
{
int itemLoc;
struct _drmBONode *node;
uint32_t *reloc;
struct drm_bo_info_req *req;
driBOAddListItem(batch->list, driBO, val_flags, val_mask,
&itemLoc, &node);
req = &node->bo_arg.d.req.bo_req;
if (!(req->hint & DRM_BO_HINT_PRESUMED_OFFSET)) {
/*
* Stop other threads from tampering with the underlying
* drmBO while we're reading its offset.
*/
driReadLockKernelBO();
req->presumed_offset = (uint64_t) driBOKernel(driBO)->offset;
driReadUnlockKernelBO();
req->hint = DRM_BO_HINT_PRESUMED_OFFSET;
}
pre_add += driBOPoolOffset(driBO);
if (batch->nr_relocs == batch->reloc_size)
intel_realloc_relocs(batch, batch->reloc_size * 2);
reloc = batch->reloc +
(I915_RELOC_HEADER + batch->nr_relocs * I915_RELOC0_STRIDE);
reloc[0] = ((uint8_t *)batch->ptr - batch->drmBOVirtual);
intel_batchbuffer_emit_dword(batch, req->presumed_offset + pre_add);
reloc[1] = pre_add;
reloc[2] = itemLoc;
reloc[3] = batch->dest_location;
batch->nr_relocs++;
}
static void
i915_drm_copy_reply(const struct drm_bo_info_rep * rep, drmBO * buf)
{
buf->handle = rep->handle;
buf->flags = rep->flags;
buf->size = rep->size;
buf->offset = rep->offset;
buf->mapHandle = rep->arg_handle;
buf->proposedFlags = rep->proposed_flags;
buf->start = rep->buffer_start;
buf->fenceFlags = rep->fence_flags;
buf->replyFlags = rep->rep_flags;
buf->pageAlignment = rep->page_alignment;
}
static int
i915_execbuf(struct intel_batchbuffer *batch,
GLuint used,
GLboolean ignore_cliprects,
drmBOList *list,
struct drm_i915_execbuffer *ea)
{
struct intel_screen *intel_screen = batch->intel_screen;
drmBONode *node;
drmMMListHead *l;
struct drm_i915_op_arg *arg, *first;
struct drm_bo_op_req *req;
struct drm_bo_info_rep *rep;
uint64_t *prevNext = NULL;
drmBO *buf;
int ret = 0;
uint32_t count = 0;
first = NULL;
for (l = list->list.next; l != &list->list; l = l->next) {
node = DRMLISTENTRY(drmBONode, l, head);
arg = &node->bo_arg;
req = &arg->d.req;
if (!first)
first = arg;
if (prevNext)
*prevNext = (unsigned long)arg;
prevNext = &arg->next;
req->bo_req.handle = node->buf->handle;
req->op = drm_bo_validate;
req->bo_req.flags = node->arg0;
req->bo_req.mask = node->arg1;
req->bo_req.hint |= 0;
count++;
}
memset(ea, 0, sizeof(*ea));
ea->num_buffers = count;
ea->batch.start = batch->poolOffset;
ea->batch.used = used;
#if 0 /* ZZZ JB: no cliprects used */
ea->batch.cliprects = intel->pClipRects;
ea->batch.num_cliprects = ignore_cliprects ? 0 : intel->numClipRects;
ea->batch.DR1 = 0;
ea->batch.DR4 = 0;((((GLuint) intel->drawX) & 0xffff) |
(((GLuint) intel->drawY) << 16));
#else
ea->batch.cliprects = NULL;
ea->batch.num_cliprects = 0;
ea->batch.DR1 = 0;
ea->batch.DR4 = 0;
#endif
ea->fence_arg.flags = DRM_I915_FENCE_FLAG_FLUSHED;
ea->ops_list = (unsigned long) first;
first->reloc_ptr = (unsigned long) batch->reloc;
batch->reloc[0] = batch->nr_relocs;
//return -EFAULT;
do {
ret = drmCommandWriteRead(intel_screen->device->drmFD, DRM_I915_EXECBUFFER, ea,
sizeof(*ea));
} while (ret == -EAGAIN);
if (ret != 0) {
printf("%s somebody set us up the bomb\n", __FUNCTION__);
return ret;
}
for (l = list->list.next; l != &list->list; l = l->next) {
node = DRMLISTENTRY(drmBONode, l, head);
arg = &node->bo_arg;
rep = &arg->d.rep.bo_info;
if (!arg->handled) {
return -EFAULT;
}
if (arg->d.rep.ret)
return arg->d.rep.ret;
buf = node->buf;
i915_drm_copy_reply(rep, buf);
}
return 0;
}
/* TODO: Push this whole function into bufmgr.
*/
static struct _DriFenceObject *
do_flush_locked(struct intel_batchbuffer *batch,
GLuint used,
GLboolean ignore_cliprects, GLboolean allow_unlock)
{
struct intel_screen *intel_screen = batch->intel_screen;
struct _DriFenceObject *fo;
drmFence fence;
drmBOList *boList;
struct drm_i915_execbuffer ea;
int ret = 0;
driBOValidateUserList(batch->list);
boList = driGetdrmBOList(batch->list);
#if 0 /* ZZZ JB Allways run */
if (!(intel->numClipRects == 0 && !ignore_cliprects)) {
#else
if (1) {
#endif
ret = i915_execbuf(batch, used, ignore_cliprects, boList, &ea);
} else {
driPutdrmBOList(batch->list);
fo = NULL;
goto out;
}
driPutdrmBOList(batch->list);
if (ret)
abort();
if (ea.fence_arg.error != 0) {
/*
* The hardware has been idled by the kernel.
* Don't fence the driBOs.
*/
if (batch->last_fence)
driFenceUnReference(&batch->last_fence);
#if 0 /* ZZZ JB: no _mesa_* funcs in gallium */
_mesa_printf("fence error\n");
#endif
batch->last_fence = NULL;
fo = NULL;
goto out;
}
fence.handle = ea.fence_arg.handle;
fence.fence_class = ea.fence_arg.fence_class;
fence.type = ea.fence_arg.type;
fence.flags = ea.fence_arg.flags;
fence.signaled = ea.fence_arg.signaled;
fo = driBOFenceUserList(intel_screen->mgr, batch->list,
"SuperFence", &fence);
if (driFenceType(fo) & DRM_I915_FENCE_TYPE_RW) {
if (batch->last_fence)
driFenceUnReference(&batch->last_fence);
/*
* FIXME: Context last fence??
*/
batch->last_fence = fo;
driFenceReference(fo);
}
out:
#if 0 /* ZZZ JB: fix this */
intel->vtbl.lost_hardware(intel);
#else
#endif
return fo;
}
struct _DriFenceObject *
intel_batchbuffer_flush(struct intel_batchbuffer *batch)
{
//struct intel_context *intel = batch->intel;
GLuint used = batch->ptr - batch->map;
//GLboolean was_locked = 1;
struct _DriFenceObject *fence;
if (used == 0) {
driFenceReference(batch->last_fence);
return batch->last_fence;
}
/* Add the MI_BATCH_BUFFER_END. Always add an MI_FLUSH - this is a
* performance drain that we would like to avoid.
*/
#if 0 /* ZZZ JB: what should we do here? */
if (used & 4) {
((int *) batch->ptr)[0] = intel->vtbl.flush_cmd();
((int *) batch->ptr)[1] = 0;
((int *) batch->ptr)[2] = MI_BATCH_BUFFER_END;
used += 12;
}
else {
((int *) batch->ptr)[0] = intel->vtbl.flush_cmd();
((int *) batch->ptr)[1] = MI_BATCH_BUFFER_END;
used += 8;
}
#else
if (used & 4) {
((int *) batch->ptr)[0] = ((0<<29)|(4<<23)); // MI_FLUSH;
((int *) batch->ptr)[1] = 0;
((int *) batch->ptr)[2] = (0xA<<23); // MI_BATCH_BUFFER_END;
used += 12;
}
else {
((int *) batch->ptr)[0] = ((0<<29)|(4<<23)); // MI_FLUSH;
((int *) batch->ptr)[1] = (0xA<<23); // MI_BATCH_BUFFER_END;
used += 8;
}
#endif
driBOUnmap(batch->buffer);
batch->ptr = NULL;
batch->map = NULL;
/* TODO: Just pass the relocation list and dma buffer up to the
* kernel.
*/
/* if (!was_locked)
LOCK_HARDWARE(intel);*/
fence = do_flush_locked(batch, used, !(batch->flags & INTEL_BATCH_CLIPRECTS),
GL_FALSE);
/* if (!was_locked)
UNLOCK_HARDWARE(intel);*/
/* Reset the buffer:
*/
intel_batchbuffer_reset(batch);
return fence;
}
void
intel_batchbuffer_finish(struct intel_batchbuffer *batch)
{
struct _DriFenceObject *fence = intel_batchbuffer_flush(batch);
driFenceFinish(fence, driFenceType(fence), GL_FALSE);
driFenceUnReference(&fence);
}
void
intel_batchbuffer_data(struct intel_batchbuffer *batch,
const void *data, GLuint bytes, GLuint flags)
{
assert((bytes & 3) == 0);
intel_batchbuffer_require_space(batch, bytes, flags);
memcpy(batch->ptr, data, bytes);
batch->ptr += bytes;
}
@@ -0,0 +1,133 @@
#ifndef INTEL_BATCHBUFFER_H
#define INTEL_BATCHBUFFER_H
#include "mtypes.h"
#include "ws_dri_bufmgr.h"
struct intel_screen;
#define BATCH_SZ 16384
#define BATCH_RESERVED 16
#define INTEL_DEFAULT_RELOCS 100
#define INTEL_MAX_RELOCS 400
#define INTEL_BATCH_NO_CLIPRECTS 0x1
#define INTEL_BATCH_CLIPRECTS 0x2
struct intel_batchbuffer
{
struct bufmgr *bm;
struct intel_screen *intel_screen;
struct _DriBufferObject *buffer;
struct _DriFenceObject *last_fence;
GLuint flags;
struct _DriBufferList *list;
GLuint list_count;
GLubyte *map;
GLubyte *ptr;
uint32_t *reloc;
GLuint reloc_size;
GLuint nr_relocs;
GLuint size;
GLuint dirty_state;
GLuint id;
uint32_t poolOffset;
uint8_t *drmBOVirtual;
struct _drmBONode *node; /* Validation list node for this buffer */
int dest_location; /* Validation list sequence for this buffer */
};
struct intel_batchbuffer *intel_batchbuffer_alloc(struct intel_screen
*intel);
void intel_batchbuffer_free(struct intel_batchbuffer *batch);
void intel_batchbuffer_finish(struct intel_batchbuffer *batch);
struct _DriFenceObject *intel_batchbuffer_flush(struct intel_batchbuffer
*batch);
void intel_batchbuffer_reset(struct intel_batchbuffer *batch);
/* Unlike bmBufferData, this currently requires the buffer be mapped.
* Consider it a convenience function wrapping multple
* intel_buffer_dword() calls.
*/
void intel_batchbuffer_data(struct intel_batchbuffer *batch,
const void *data, GLuint bytes, GLuint flags);
void intel_batchbuffer_release_space(struct intel_batchbuffer *batch,
GLuint bytes);
void
intel_offset_relocation(struct intel_batchbuffer *batch,
unsigned pre_add,
struct _DriBufferObject *driBO,
uint64_t val_flags,
uint64_t val_mask);
/* Inline functions - might actually be better off with these
* non-inlined. Certainly better off switching all command packets to
* be passed as structs rather than dwords, but that's a little bit of
* work...
*/
static INLINE GLuint
intel_batchbuffer_space(struct intel_batchbuffer *batch)
{
return (batch->size - BATCH_RESERVED) - (batch->ptr - batch->map);
}
static INLINE void
intel_batchbuffer_emit_dword(struct intel_batchbuffer *batch, GLuint dword)
{
assert(batch->map);
assert(intel_batchbuffer_space(batch) >= 4);
*(GLuint *) (batch->ptr) = dword;
batch->ptr += 4;
}
static INLINE void
intel_batchbuffer_require_space(struct intel_batchbuffer *batch,
GLuint sz, GLuint flags)
{
struct _DriFenceObject *fence;
assert(sz < batch->size - 8);
if (intel_batchbuffer_space(batch) < sz ||
(batch->flags != 0 && flags != 0 && batch->flags != flags)) {
fence = intel_batchbuffer_flush(batch);
driFenceUnReference(&fence);
}
batch->flags |= flags;
}
/* Here are the crusty old macros, to be removed:
*/
#define BATCH_LOCALS
#define BEGIN_BATCH(n, flags) do { \
assert(!intel->prim.flush); \
intel_batchbuffer_require_space(intel->batch, (n)*4, flags); \
} while (0)
#define OUT_BATCH(d) intel_batchbuffer_emit_dword(intel->batch, d)
#define OUT_RELOC(buf,flags,mask,delta) do { \
assert((delta) >= 0); \
intel_offset_relocation(intel->batch, delta, buf, flags, mask); \
} while (0)
#define ADVANCE_BATCH() do { } while(0)
#endif
@@ -0,0 +1,366 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "intel_screen.h"
#include "intel_context.h"
#include "intel_swapbuffers.h"
#include "intel_winsys.h"
#include "intel_batchbuffer.h"
#include "state_tracker/st_public.h"
#include "pipe/p_defines.h"
#include "pipe/p_context.h"
#include "intel_egl.h"
#include "utils.h"
#ifdef DEBUG
int __intel_debug = 0;
#endif
#define need_GL_ARB_multisample
#define need_GL_ARB_point_parameters
#define need_GL_ARB_texture_compression
#define need_GL_ARB_vertex_buffer_object
#define need_GL_ARB_vertex_program
#define need_GL_ARB_window_pos
#define need_GL_EXT_blend_color
#define need_GL_EXT_blend_equation_separate
#define need_GL_EXT_blend_func_separate
#define need_GL_EXT_blend_minmax
#define need_GL_EXT_cull_vertex
#define need_GL_EXT_fog_coord
#define need_GL_EXT_framebuffer_object
#define need_GL_EXT_multi_draw_arrays
#define need_GL_EXT_secondary_color
#define need_GL_NV_vertex_program
#include "extension_helper.h"
/**
* Extension strings exported by the intel driver.
*
* \note
* It appears that ARB_texture_env_crossbar has "disappeared" compared to the
* old i830-specific driver.
*/
const struct dri_extension card_extensions[] = {
{"GL_ARB_multisample", GL_ARB_multisample_functions},
{"GL_ARB_multitexture", NULL},
{"GL_ARB_point_parameters", GL_ARB_point_parameters_functions},
{"GL_ARB_texture_border_clamp", NULL},
{"GL_ARB_texture_compression", GL_ARB_texture_compression_functions},
{"GL_ARB_texture_cube_map", NULL},
{"GL_ARB_texture_env_add", NULL},
{"GL_ARB_texture_env_combine", NULL},
{"GL_ARB_texture_env_dot3", NULL},
{"GL_ARB_texture_mirrored_repeat", NULL},
{"GL_ARB_texture_rectangle", NULL},
{"GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions},
{"GL_ARB_pixel_buffer_object", NULL},
{"GL_ARB_vertex_program", GL_ARB_vertex_program_functions},
{"GL_ARB_window_pos", GL_ARB_window_pos_functions},
{"GL_EXT_blend_color", GL_EXT_blend_color_functions},
{"GL_EXT_blend_equation_separate", GL_EXT_blend_equation_separate_functions},
{"GL_EXT_blend_func_separate", GL_EXT_blend_func_separate_functions},
{"GL_EXT_blend_minmax", GL_EXT_blend_minmax_functions},
{"GL_EXT_blend_subtract", NULL},
{"GL_EXT_cull_vertex", GL_EXT_cull_vertex_functions},
{"GL_EXT_fog_coord", GL_EXT_fog_coord_functions},
{"GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions},
{"GL_EXT_multi_draw_arrays", GL_EXT_multi_draw_arrays_functions},
{"GL_EXT_packed_depth_stencil", NULL},
{"GL_EXT_pixel_buffer_object", NULL},
{"GL_EXT_secondary_color", GL_EXT_secondary_color_functions},
{"GL_EXT_stencil_wrap", NULL},
{"GL_EXT_texture_edge_clamp", NULL},
{"GL_EXT_texture_env_combine", NULL},
{"GL_EXT_texture_env_dot3", NULL},
{"GL_EXT_texture_filter_anisotropic", NULL},
{"GL_EXT_texture_lod_bias", NULL},
{"GL_3DFX_texture_compression_FXT1", NULL},
{"GL_APPLE_client_storage", NULL},
{"GL_MESA_pack_invert", NULL},
{"GL_MESA_ycbcr_texture", NULL},
{"GL_NV_blend_square", NULL},
{"GL_NV_vertex_program", GL_NV_vertex_program_functions},
{"GL_NV_vertex_program1_1", NULL},
{"GL_SGIS_generate_mipmap", NULL },
{NULL, NULL}
};
int
intel_create_context(struct egl_drm_context *eglCon, const __GLcontextModes *visual, void *sharedContextPrivate)
{
struct intel_context *iCon = CALLOC_STRUCT(intel_context);
struct intel_screen *iScrn = (struct intel_screen *)eglCon->device->priv;
struct pipe_context *pipe;
struct st_context *st_share = NULL;
eglCon->priv = iCon;
iCon->intel_screen = iScrn;
iCon->egl_context = eglCon;
iCon->egl_device = eglCon->device;
iCon->batch = intel_batchbuffer_alloc(iScrn);
iCon->last_swap_fence = NULL;
iCon->first_swap_fence = NULL;
pipe = intel_create_i915simple(iCon, iScrn->winsys);
// pipe = intel_create_softpipe(iCon, iScrn->winsys);
pipe->priv = iCon;
iCon->st = st_create_context(pipe, visual, st_share);
return TRUE;
}
void
intel_make_current(struct egl_drm_context *context, struct egl_drm_drawable *draw, struct egl_drm_drawable *read)
{
if (context) {
struct intel_context *intel = (struct intel_context *)context->priv;
struct intel_framebuffer *draw_fb = (struct intel_framebuffer *)draw->priv;
struct intel_framebuffer *read_fb = (struct intel_framebuffer *)read->priv;
assert(draw_fb->stfb);
assert(read_fb->stfb);
st_make_current(intel->st, draw_fb->stfb, read_fb->stfb);
intel->egl_drawable = draw;
st_resize_framebuffer(draw_fb->stfb, draw->w, draw->h);
if (draw != read)
st_resize_framebuffer(read_fb->stfb, read->w, read->h);
//intelUpdateWindowSize(driDrawPriv);
} else {
st_make_current(NULL, NULL, NULL);
}
}
void
intel_bind_frontbuffer(struct egl_drm_drawable *draw, struct egl_drm_frontbuffer *front)
{
struct intel_screen *intelScreen = (struct intel_screen *)draw->device->priv;
struct intel_framebuffer *draw_fb = (struct intel_framebuffer *)draw->priv;
driBOUnReference(draw_fb->front_buffer);
draw_fb->front_buffer = NULL;
draw_fb->front = NULL;
/* to unbind just call this function with front == NULL */
if (!front)
return;
draw_fb->front = front;
driGenBuffers(intelScreen->staticPool, "front", 1, &draw_fb->front_buffer, 0, 0, 0);
driBOSetReferenced(draw_fb->front_buffer, front->handle);
st_resize_framebuffer(draw_fb->stfb, draw->w, draw->h);
}
#if 0
GLboolean
intelCreateContext(const __GLcontextModes * visual,
__DRIcontextPrivate * driContextPriv,
void *sharedContextPrivate)
{
struct intel_context *intel = CALLOC_STRUCT(intel_context);
__DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
struct intel_screen *intelScreen = intel_screen(sPriv);
drmI830Sarea *saPriv = intelScreen->sarea;
int fthrottle_mode;
GLboolean havePools;
struct pipe_context *pipe;
struct st_context *st_share = NULL;
if (sharedContextPrivate) {
st_share = ((struct intel_context *) sharedContextPrivate)->st;
}
driContextPriv->driverPrivate = intel;
intel->intelScreen = intelScreen;
intel->driScreen = sPriv;
intel->sarea = saPriv;
driParseConfigFiles(&intel->optionCache, &intelScreen->optionCache,
intel->driScreen->myNum, "i915");
/*
* memory pools
*/
DRM_LIGHT_LOCK(sPriv->fd, &sPriv->pSAREA->lock, driContextPriv->hHWContext);
// ZZZ JB should be per screen and not be done per context
havePools = intelCreatePools(sPriv);
DRM_UNLOCK(sPriv->fd, &sPriv->pSAREA->lock, driContextPriv->hHWContext);
if (!havePools)
return GL_FALSE;
/* Dri stuff */
intel->hHWContext = driContextPriv->hHWContext;
intel->driFd = sPriv->fd;
intel->driHwLock = (drmLock *) & sPriv->pSAREA->lock;
fthrottle_mode = driQueryOptioni(&intel->optionCache, "fthrottle_mode");
intel->iw.irq_seq = -1;
intel->irqsEmitted = 0;
intel->batch = intel_batchbuffer_alloc(intel);
intel->last_swap_fence = NULL;
intel->first_swap_fence = NULL;
#ifdef DEBUG
__intel_debug = driParseDebugString(getenv("INTEL_DEBUG"), debug_control);
#endif
/*
* Pipe-related setup
*/
if (getenv("INTEL_SP")) {
/* use softpipe driver instead of hw */
pipe = intel_create_softpipe( intel, intelScreen->winsys );
}
else {
switch (intel->intelScreen->deviceID) {
case PCI_CHIP_I945_G:
case PCI_CHIP_I945_GM:
case PCI_CHIP_I945_GME:
case PCI_CHIP_G33_G:
case PCI_CHIP_Q33_G:
case PCI_CHIP_Q35_G:
case PCI_CHIP_I915_G:
case PCI_CHIP_I915_GM:
pipe = intel_create_i915simple( intel, intelScreen->winsys );
break;
default:
fprintf(stderr, "Unknown PCIID %x in %s, using software driver\n",
intel->intelScreen->deviceID, __FUNCTION__);
pipe = intel_create_softpipe( intel, intelScreen->winsys );
break;
}
}
pipe->priv = intel;
intel->st = st_create_context(pipe, visual, st_share);
return GL_TRUE;
}
void
intelDestroyContext(__DRIcontextPrivate * driContextPriv)
{
struct intel_context *intel = intel_context(driContextPriv);
assert(intel); /* should never be null */
if (intel) {
st_finish(intel->st);
intel_batchbuffer_free(intel->batch);
if (intel->last_swap_fence) {
driFenceFinish(intel->last_swap_fence, DRM_FENCE_TYPE_EXE, GL_TRUE);
driFenceUnReference(&intel->last_swap_fence);
intel->last_swap_fence = NULL;
}
if (intel->first_swap_fence) {
driFenceFinish(intel->first_swap_fence, DRM_FENCE_TYPE_EXE, GL_TRUE);
driFenceUnReference(&intel->first_swap_fence);
intel->first_swap_fence = NULL;
}
if (intel->intelScreen->dummyContext == intel)
intel->intelScreen->dummyContext = NULL;
st_destroy_context(intel->st);
free(intel);
}
}
GLboolean
intelUnbindContext(__DRIcontextPrivate * driContextPriv)
{
struct intel_context *intel = intel_context(driContextPriv);
st_flush(intel->st, PIPE_FLUSH_RENDER_CACHE, NULL);
/* XXX make_current(NULL)? */
return GL_TRUE;
}
GLboolean
intelMakeCurrent(__DRIcontextPrivate * driContextPriv,
__DRIdrawablePrivate * driDrawPriv,
__DRIdrawablePrivate * driReadPriv)
{
if (driContextPriv) {
struct intel_context *intel = intel_context(driContextPriv);
struct intel_framebuffer *draw_fb = intel_framebuffer(driDrawPriv);
struct intel_framebuffer *read_fb = intel_framebuffer(driReadPriv);
assert(draw_fb->stfb);
assert(read_fb->stfb);
/* This is for situations in which we need a rendering context but
* there may not be any currently bound.
*/
intel->intelScreen->dummyContext = intel;
st_make_current(intel->st, draw_fb->stfb, read_fb->stfb);
if ((intel->driDrawable != driDrawPriv) ||
(intel->lastStamp != driDrawPriv->lastStamp)) {
intel->driDrawable = driDrawPriv;
intelUpdateWindowSize(driDrawPriv);
intel->lastStamp = driDrawPriv->lastStamp;
}
/* The size of the draw buffer will have been updated above.
* If the readbuffer is a different window, check/update its size now.
*/
if (driReadPriv != driDrawPriv) {
intelUpdateWindowSize(driReadPriv);
}
}
else {
st_make_current(NULL, NULL, NULL);
}
return GL_TRUE;
}
#endif
@@ -0,0 +1,162 @@
/**************************************************************************
*
* Copyright 2003 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.
*
**************************************************************************/
#ifndef INTEL_CONTEXT_H
#define INTEL_CONTEXT_H
#include <stdint.h>
#include "drm.h"
#include "pipe/p_debug.h"
#include "intel_screen.h"
#include "i915_drm.h"
struct pipe_context;
struct intel_context;
struct _DriBufferObject;
struct st_context;
struct egl_drm_device;
struct egl_drm_context;
struct egl_drm_frontbuffer;
#define INTEL_MAX_FIXUP 64
/**
* Intel rendering context, contains a state tracker and intel-specific info.
*/
struct intel_context
{
struct st_context *st;
struct _DriFenceObject *last_swap_fence;
struct _DriFenceObject *first_swap_fence;
struct intel_batchbuffer *batch;
#if 0
boolean locked;
char *prevLockFile;
int prevLockLine;
#endif
/* pick this up from the screen instead
int drmFd;
*/
struct intel_screen *intel_screen;
uint lastStamp;
/* new egl stuff */
struct egl_drm_device *egl_device;
struct egl_drm_context *egl_context;
struct egl_drm_drawable *egl_drawable;
};
/**
* Intel framebuffer.
*/
struct intel_framebuffer
{
struct st_framebuffer *stfb;
/* other fields TBD */
int other;
struct _DriBufferObject *front_buffer;
struct egl_drm_frontbuffer *front;
};
/* These are functions now:
*/
void LOCK_HARDWARE( struct intel_context *intel );
void UNLOCK_HARDWARE( struct intel_context *intel );
extern char *__progname;
/* ================================================================
* Debugging:
*/
#ifdef DEBUG
extern int __intel_debug;
#define DEBUG_SWAP 0x1
#define DEBUG_LOCK 0x2
#define DEBUG_IOCTL 0x4
#define DEBUG_BATCH 0x8
#define DBG(flag, ...) do { \
if (__intel_debug & (DEBUG_##flag)) \
printf(__VA_ARGS__); \
} while(0)
#else
#define DBG(flag, ...)
#endif
#define PCI_CHIP_845_G 0x2562
#define PCI_CHIP_I830_M 0x3577
#define PCI_CHIP_I855_GM 0x3582
#define PCI_CHIP_I865_G 0x2572
#define PCI_CHIP_I915_G 0x2582
#define PCI_CHIP_I915_GM 0x2592
#define PCI_CHIP_I945_G 0x2772
#define PCI_CHIP_I945_GM 0x27A2
#define PCI_CHIP_I945_GME 0x27AE
#define PCI_CHIP_G33_G 0x29C2
#define PCI_CHIP_Q35_G 0x29B2
#define PCI_CHIP_Q33_G 0x29D2
#if 0
/** Cast wrapper */
static INLINE struct intel_context *
intel_context(__DRIcontextPrivate *driContextPriv)
{
return (struct intel_context *) driContextPriv->driverPrivate;
}
/** Cast wrapper */
static INLINE struct intel_framebuffer *
intel_framebuffer(__DRIdrawablePrivate * driDrawPriv)
{
return (struct intel_framebuffer *) driDrawPriv->driverPrivate;
}
#endif
#endif
@@ -0,0 +1,617 @@
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "eglconfig.h"
#include "eglcontext.h"
#include "egldisplay.h"
#include "egldriver.h"
#include "eglglobals.h"
#include "eglmode.h"
#include "eglscreen.h"
#include "eglsurface.h"
#include "glapi.h"
#include "intel_egl.h"
#include "xf86drm.h"
#include "xf86drmMode.h"
#include "intel_context.h"
#include "ws_dri_bufmgr.h"
#include "intel_winsys.h"
#include "state_tracker/st_public.h"
struct egl_drm_device* egl_drm_create_device(int drmFD);
struct egl_drm_device*
egl_drm_create_device(int drmFD)
{
struct egl_drm_device *device = malloc(sizeof(*device));
memset(device, 0, sizeof(*device));
device->drmFD = drmFD;
if (!intel_init_driver(device)) {
printf("EGL: failed to initalize device\n");
free(device);
}
return device;
}
__GLcontextModes* _gl_context_modes_create( unsigned count, size_t minimum_size );
struct drm_driver
{
_EGLDriver base; /* base class/object */
drmModeResPtr res;
struct egl_drm_device *device;
};
struct drm_surface
{
_EGLSurface base; /* base class/object */
struct egl_drm_drawable *drawable;
};
struct drm_context
{
_EGLContext base; /* base class/object */
struct egl_drm_context *context;
};
struct drm_screen
{
_EGLScreen base;
/* backing buffer and crtc */
drmBO buffer;
drmModeFBPtr fb;
uint32_t fbID;
drmModeCrtcPtr crtc;
/* currently only support one output */
drmModeOutputPtr output;
uint32_t outputID;
struct drm_mode_modeinfo *mode;
/* geometry of the screen */
struct egl_drm_frontbuffer front;
};
static void
drm_update_res(struct drm_driver *drm_drv)
{
drmModeFreeResources(drm_drv->res);
drm_drv->res = drmModeGetResources(drm_drv->device->drmFD);
}
static void
drm_add_modes_from_output(_EGLScreen *screen, drmModeOutputPtr output)
{
struct drm_mode_modeinfo *m;
int i;
for (i = 0; i < output->count_modes; i++) {
m = &output->modes[i];
_eglAddNewMode(screen, m->hdisplay, m->vdisplay, m->vrefresh, m->name);
}
}
static EGLBoolean
drm_initialize(_EGLDriver *drv, EGLDisplay dpy, EGLint *major, EGLint *minor)
{
_EGLDisplay *disp = _eglLookupDisplay(dpy);
struct drm_driver *drm_drv = (struct drm_driver *)drv;
struct drm_screen *screen = NULL;
drmModeOutputPtr output = NULL;
drmModeResPtr res = NULL;
EGLint i;
int fd;
fd = drmOpen("i915", NULL);
if (fd < 0) {
return EGL_FALSE;
}
drm_drv->device = egl_drm_create_device(fd);
if (!drm_drv->device) {
drmClose(fd);
return EGL_FALSE;
}
drm_update_res(drm_drv);
res = drm_drv->res;
for(i = 0; i < res->count_outputs; i++) {
output = drmModeGetOutput(fd, res->outputs[i]);
if (!output)
continue;
if (output->connection == DRM_MODE_DISCONNECTED) {
drmModeFreeOutput(output);
continue;
}
screen = malloc(sizeof(struct drm_screen));
memset(screen, 0, sizeof(*screen));
screen->outputID = res->outputs[i];
screen->output = output;
_eglInitScreen(&screen->base);
_eglAddScreen(disp, &screen->base);
drm_add_modes_from_output(&screen->base, output);
}
/* for now we only have one config */
_EGLConfig config;
_eglInitConfig(&config, i + 1);
_eglSetConfigAttrib(&config, EGL_RED_SIZE, 8);
_eglSetConfigAttrib(&config, EGL_GREEN_SIZE, 8);
_eglSetConfigAttrib(&config, EGL_BLUE_SIZE, 8);
_eglSetConfigAttrib(&config, EGL_ALPHA_SIZE, 8);
_eglSetConfigAttrib(&config, EGL_BUFFER_SIZE, 32);
_eglSetConfigAttrib(&config, EGL_DEPTH_SIZE, 24);
_eglSetConfigAttrib(&config, EGL_STENCIL_SIZE, 8);
_eglSetConfigAttrib(&config, EGL_SURFACE_TYPE, EGL_PBUFFER_BIT);
_eglAddConfig(disp, &config);
drv->Initialized = EGL_TRUE;
*major = 1;
*minor = 0;
return EGL_TRUE;
}
static EGLBoolean
drm_terminate(_EGLDriver *drv, EGLDisplay dpy)
{
/* TODO: clean up */
free(drv);
return EGL_TRUE;
}
static struct drm_context *
lookup_drm_context(EGLContext context)
{
_EGLContext *c = _eglLookupContext(context);
return (struct drm_context *) c;
}
static struct drm_surface *
lookup_drm_surface(EGLSurface surface)
{
_EGLSurface *s = _eglLookupSurface(surface);
return (struct drm_surface *) s;
}
static struct drm_screen *
lookup_drm_screen(EGLDisplay dpy, EGLScreenMESA screen)
{
_EGLScreen *s = _eglLookupScreen(dpy, screen);
return (struct drm_screen *) s;
}
static __GLcontextModes*
visual_from_config(_EGLConfig *conf)
{
__GLcontextModes *visual;
(void)conf;
visual = _gl_context_modes_create(1, sizeof(*visual));
visual->redBits = 8;
visual->greenBits = 8;
visual->blueBits = 8;
visual->alphaBits = 8;
visual->rgbBits = 32;
visual->doubleBufferMode = 1;
visual->depthBits = 24;
visual->stencilBits = 8;
return visual;
}
static EGLContext
drm_create_context(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLContext share_list, const EGLint *attrib_list)
{
struct drm_driver *drm_drv = (struct drm_driver *)drv;
struct drm_context *c;
struct drm_egl_context *share = NULL;
_EGLConfig *conf;
int i;
int ret;
__GLcontextModes *visual;
struct egl_drm_context *context;
conf = _eglLookupConfig(drv, dpy, config);
if (!conf) {
_eglError(EGL_BAD_CONFIG, "eglCreateContext");
return EGL_NO_CONTEXT;
}
for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
switch (attrib_list[i]) {
/* no attribs defined for now */
default:
_eglError(EGL_BAD_ATTRIBUTE, "eglCreateContext");
return EGL_NO_CONTEXT;
}
}
c = (struct drm_context *) calloc(1, sizeof(struct drm_context));
if (!c)
return EGL_NO_CONTEXT;
_eglInitContext(drv, dpy, &c->base, config, attrib_list);
context = malloc(sizeof(*context));
memset(context, 0, sizeof(*context));
if (!context)
goto err_c;
context->device = drm_drv->device;
visual = visual_from_config(conf);
ret = intel_create_context(context, visual, share);
free(visual);
if (!ret)
goto err_gl;
c->context = context;
/* generate handle and insert into hash table */
_eglSaveContext(&c->base);
assert(c->base.Handle);
return c->base.Handle;
err_gl:
free(context);
err_c:
free(c);
return EGL_NO_CONTEXT;
}
static EGLBoolean
drm_destroy_context(_EGLDriver *drv, EGLDisplay dpy, EGLContext context)
{
struct drm_context *fc = lookup_drm_context(context);
_eglRemoveContext(&fc->base);
if (fc->base.IsBound) {
fc->base.DeletePending = EGL_TRUE;
} else {
free(fc);
}
return EGL_TRUE;
}
static EGLSurface
drm_create_window_surface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, NativeWindowType window, const EGLint *attrib_list)
{
return EGL_NO_SURFACE;
}
static EGLSurface
drm_create_pixmap_surface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, NativePixmapType pixmap, const EGLint *attrib_list)
{
return EGL_NO_SURFACE;
}
static EGLSurface
drm_create_pbuffer_surface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
const EGLint *attrib_list)
{
struct drm_driver *drm_drv = (struct drm_driver *)drv;
int i;
int ret;
int width = -1;
int height = -1;
struct drm_surface *surf = NULL;
struct egl_drm_drawable *drawable = NULL;
__GLcontextModes *visual;
_EGLConfig *conf;
conf = _eglLookupConfig(drv, dpy, config);
if (!conf) {
_eglError(EGL_BAD_CONFIG, "eglCreatePbufferSurface");
return EGL_NO_CONTEXT;
}
for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
switch (attrib_list[i]) {
case EGL_WIDTH:
width = attrib_list[++i];
break;
case EGL_HEIGHT:
height = attrib_list[++i];
break;
default:
_eglError(EGL_BAD_ATTRIBUTE, "eglCreatePbufferSurface");
return EGL_NO_SURFACE;
}
}
if (width < 1 || height < 1) {
_eglError(EGL_BAD_ATTRIBUTE, "eglCreatePbufferSurface");
return EGL_NO_SURFACE;
}
surf = (struct drm_surface *) calloc(1, sizeof(struct drm_surface));
if (!surf)
goto err;
if (!_eglInitSurface(drv, dpy, &surf->base, EGL_PBUFFER_BIT, config, attrib_list))
goto err_surf;
drawable = malloc(sizeof(*drawable));
memset(drawable, 0, sizeof(*drawable));
drawable->w = width;
drawable->h = height;
visual = visual_from_config(conf);
drawable->device = drm_drv->device;
ret = intel_create_drawable(drawable, visual);
free(visual);
if (!ret)
goto err_draw;
surf->drawable = drawable;
_eglSaveSurface(&surf->base);
return surf->base.Handle;
err_draw:
free(drawable);
err_surf:
free(surf);
err:
return EGL_NO_SURFACE;
}
static EGLSurface
drm_create_screen_surface_mesa(_EGLDriver *drv, EGLDisplay dpy, EGLConfig cfg,
const EGLint *attrib_list)
{
EGLSurface surf = drm_create_pbuffer_surface(drv, dpy, cfg, attrib_list);
return surf;
}
static struct drm_mode_modeinfo *
drm_find_mode(drmModeOutputPtr output, _EGLMode *mode)
{
int i;
struct drm_mode_modeinfo *m;
for (i = 0; i < output->count_modes; i++) {
m = &output->modes[i];
if (m->hdisplay == mode->Width && m->vdisplay == mode->Height && m->vrefresh == mode->RefreshRate)
break;
m = NULL;
}
return m;
}
static void
draw(size_t x, size_t y, size_t w, size_t h, size_t pitch, size_t v, unsigned int *ptr)
{
int i, j;
for (i = x; i < x + w; i++)
for(j = y; j < y + h; j++)
ptr[(i * pitch / 4) + j] = v;
}
static void
prettyColors(int fd, unsigned int handle, size_t pitch)
{
drmBO bo;
unsigned int *ptr;
int i;
drmBOReference(fd, handle, &bo);
drmBOMap(fd, &bo, DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0, (void**)&ptr);
for (i = 0; i < (bo.size / 4); i++)
ptr[i] = 0xFFFFFFFF;
for (i = 0; i < 4; i++)
draw(i * 40, i * 40, 40, 40, pitch, 0, ptr);
draw(200, 100, 40, 40, pitch, 0xff00ff, ptr);
draw(100, 200, 40, 40, pitch, 0xff00ff, ptr);
drmBOUnmap(fd, &bo);
}
static EGLBoolean
drm_show_screen_surface_mesa(_EGLDriver *drv, EGLDisplay dpy,
EGLScreenMESA screen,
EGLSurface surface, EGLModeMESA m)
{
struct drm_driver *drm_drv = (struct drm_driver *)drv;
struct drm_surface *surf = lookup_drm_surface(surface);
struct drm_screen *scrn = lookup_drm_screen(dpy, screen);
//struct intel_framebuffer *intel_fb = NULL;
//struct pipe_surface *front_surf = NULL;
_EGLMode *mode = _eglLookupMode(dpy, m);
size_t pitch = 2048 * 4;
size_t size = mode->Height * pitch;
int ret;
/* TODO if allready shown take down */
printf("setting mode to %i x %i\n", mode->Width, mode->Height);
ret = drmBOCreate(drm_drv->device->drmFD, size, 0, 0,
DRM_BO_FLAG_READ |
DRM_BO_FLAG_WRITE |
DRM_BO_FLAG_MEM_TT |
DRM_BO_FLAG_MEM_VRAM |
DRM_BO_FLAG_NO_EVICT,
DRM_BO_HINT_DONT_FENCE, &scrn->buffer);
prettyColors(drm_drv->device->drmFD, scrn->buffer.handle, pitch);
if (ret) {
printf("failed to create framebuffer (ret %d)\n", ret);
return EGL_FALSE;
}
ret = drmModeAddFB(drm_drv->device->drmFD, mode->Width, mode->Height,
32, 32, pitch,
scrn->buffer.handle,
&scrn->fbID);
if (ret)
goto err_bo;
scrn->fb = drmModeGetFB(drm_drv->device->drmFD, scrn->fbID);
if (!scrn->fb)
goto err_bo;
scrn->mode = drm_find_mode(scrn->output, mode);
if (!scrn->mode) {
printf("oh noes, no matching mode found\n");
goto err_fb;
}
ret = drmModeSetCrtc(
drm_drv->device->drmFD,
drm_drv->res->crtcs[1],
scrn->fbID,
0, 0,
&scrn->outputID, 1,
scrn->mode);
scrn->front.handle = scrn->buffer.handle;
scrn->front.pitch = pitch;
scrn->front.width = mode->Width;
scrn->front.height = mode->Height;
intel_bind_frontbuffer(surf->drawable, &scrn->front);
return EGL_TRUE;
err_fb:
/* TODO remove fb */
err_bo:
drmBOUnreference(drm_drv->device->drmFD, &scrn->buffer);
return EGL_FALSE;
}
static EGLBoolean
drm_destroy_surface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface)
{
struct drm_surface *fs = lookup_drm_surface(surface);
_eglRemoveSurface(&fs->base);
if (fs->base.IsBound) {
fs->base.DeletePending = EGL_TRUE;
} else {
free(fs);
}
return EGL_TRUE;
}
static EGLBoolean
drm_make_current(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext context)
{
struct drm_surface *readSurf = lookup_drm_surface(read);
struct drm_surface *drawSurf = lookup_drm_surface(draw);
struct drm_context *ctx = lookup_drm_context(context);
EGLBoolean b;
b = _eglMakeCurrent(drv, dpy, draw, read, context);
if (!b)
return EGL_FALSE;
/* XXX this is where we'd do the hardware context switch */
(void) drawSurf;
(void) readSurf;
(void) ctx;
intel_make_current(ctx->context, drawSurf->drawable, readSurf->drawable);
return EGL_TRUE;
}
static EGLBoolean
drm_swap_buffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw)
{
struct drm_surface *surf = lookup_drm_surface(draw);
if (!surf)
return EGL_FALSE;
/* error checking */
if (!_eglSwapBuffers(drv, dpy, draw))
return EGL_FALSE;
intel_swap_buffers(surf->drawable);
return EGL_TRUE;
}
/**
* The bootstrap function. Return a new drm_driver object and
* plug in API functions.
*/
_EGLDriver *
_eglMain(_EGLDisplay *dpy)
{
struct drm_driver *drm;
drm = (struct drm_driver *) calloc(1, sizeof(struct drm_driver));
if (!drm) {
return NULL;
}
/* First fill in the dispatch table with defaults */
_eglInitDriverFallbacks(&drm->base);
/* then plug in our Drm-specific functions */
drm->base.API.Initialize = drm_initialize;
drm->base.API.Terminate = drm_terminate;
drm->base.API.CreateContext = drm_create_context;
drm->base.API.MakeCurrent = drm_make_current;
drm->base.API.CreateWindowSurface = drm_create_window_surface;
drm->base.API.CreatePixmapSurface = drm_create_pixmap_surface;
drm->base.API.CreatePbufferSurface = drm_create_pbuffer_surface;
drm->base.API.DestroySurface = drm_destroy_surface;
drm->base.API.DestroyContext = drm_destroy_context;
drm->base.API.CreateScreenSurfaceMESA = drm_create_screen_surface_mesa;
drm->base.API.ShowScreenSurfaceMESA = drm_show_screen_surface_mesa;
drm->base.API.SwapBuffers = drm_swap_buffers;
/* enable supported extensions */
drm->base.Extensions.MESA_screen_surface = EGL_TRUE;
drm->base.Extensions.MESA_copy_context = EGL_TRUE;
return &drm->base;
}
@@ -0,0 +1,42 @@
#ifndef _INTEL_EGL_H_
#define _INTEL_EGL_H_
struct egl_drm_device
{
void *priv;
int drmFD;
};
struct egl_drm_context
{
void *priv;
struct egl_drm_device *device;
};
struct egl_drm_drawable
{
void *priv;
struct egl_drm_device *device;
size_t h;
size_t w;
};
struct egl_drm_frontbuffer
{
uint32_t handle;
uint32_t pitch;
uint32_t width;
uint32_t height;
};
#include "GL/internal/glcore.h"
int intel_init_driver(struct egl_drm_device *device);
int intel_create_context(struct egl_drm_context *context, const __GLcontextModes *visual, void *sharedContextPrivate);
int intel_create_drawable(struct egl_drm_drawable *drawable, const __GLcontextModes * visual);
void intel_make_current(struct egl_drm_context *context, struct egl_drm_drawable *draw, struct egl_drm_drawable *read);
void intel_swap_buffers(struct egl_drm_drawable *draw);
void intel_bind_frontbuffer(struct egl_drm_drawable *draw, struct egl_drm_frontbuffer *front);
#endif
@@ -0,0 +1,102 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "main/glheader.h"
#include "glapi/glthread.h"
#include <GL/internal/glcore.h>
#include "state_tracker/st_public.h"
#include "intel_context.h"
#if 0
_glthread_DECLARE_STATIC_MUTEX( lockMutex );
static void
intelContendedLock(struct intel_context *intel, uint flags)
{
__DRIdrawablePrivate *dPriv = intel->driDrawable;
__DRIscreenPrivate *sPriv = intel->driScreen;
struct intel_screen *intelScreen = intel_screen(sPriv);
drmI830Sarea *sarea = intel->sarea;
drmGetLock(intel->driFd, intel->hHWContext, flags);
DBG(LOCK, "%s - got contended lock\n", __progname);
/* If the window moved, may need to set a new cliprect now.
*
* NOTE: This releases and regains the hw lock, so all state
* checking must be done *after* this call:
*/
if (dPriv)
DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv);
if (sarea->width != intelScreen->front.width ||
sarea->height != intelScreen->front.height) {
intelUpdateScreenRotation(sPriv, sarea);
}
}
/* Lock the hardware and validate our state.
*/
void LOCK_HARDWARE( struct intel_context *intel )
{
char __ret = 0;
_glthread_LOCK_MUTEX(lockMutex);
assert(!intel->locked);
DRM_CAS(intel->driHwLock, intel->hHWContext,
(DRM_LOCK_HELD|intel->hHWContext), __ret);
if (__ret)
intelContendedLock( intel, 0 );
DBG(LOCK, "%s - locked\n", __progname);
intel->locked = 1;
}
/* Unlock the hardware using the global current context
*/
void UNLOCK_HARDWARE( struct intel_context *intel )
{
assert(intel->locked);
intel->locked = 0;
DRM_UNLOCK(intel->driFd, intel->driHwLock, intel->hHWContext);
_glthread_UNLOCK_MUTEX(lockMutex);
DBG(LOCK, "%s - unlocked\n", __progname);
}
#endif
@@ -0,0 +1,53 @@
/**************************************************************************
*
* Copyright 2003 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.
*
**************************************************************************/
#ifndef _INTEL_REG_H_
#define _INTEL_REG_H_
#define BR00_BITBLT_CLIENT 0x40000000
#define BR00_OP_COLOR_BLT 0x10000000
#define BR00_OP_SRC_COPY_BLT 0x10C00000
#define BR13_SOLID_PATTERN 0x80000000
#define XY_COLOR_BLT_CMD ((2<<29)|(0x50<<22)|0x4)
#define XY_COLOR_BLT_WRITE_ALPHA (1<<21)
#define XY_COLOR_BLT_WRITE_RGB (1<<20)
#define XY_SRC_COPY_BLT_CMD ((2<<29)|(0x53<<22)|6)
#define XY_SRC_COPY_BLT_WRITE_ALPHA (1<<21)
#define XY_SRC_COPY_BLT_WRITE_RGB (1<<20)
#define MI_WAIT_FOR_EVENT ((0x3<<23))
#define MI_WAIT_FOR_PLANE_B_FLIP (1<<6)
#define MI_WAIT_FOR_PLANE_A_FLIP (1<<2)
#define MI_BATCH_BUFFER_END (0xA<<23)
#endif
@@ -0,0 +1,680 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "utils.h"
#include "vblank.h"
#include "xmlpool.h"
#include "intel_context.h"
#include "intel_screen.h"
#include "intel_batchbuffer.h"
//#include "intel_batchpool.h"
#include "intel_swapbuffers.h"
#include "intel_winsys.h"
#include "ws_dri_bufpool.h"
#include "pipe/p_context.h"
#include "state_tracker/st_public.h"
#include "state_tracker/st_cb_fbo.h"
#include "intel_egl.h"
static boolean
intel_create_pools(struct intel_screen *intel_screen)
{
if (intel_screen->havePools)
return GL_TRUE;
intel_screen->mgr = driFenceMgrTTMInit(intel_screen->device->drmFD);
if (!intel_screen->mgr) {
fprintf(stderr, "Failed to create fence manager.\n");
return FALSE;
}
intel_screen->fMan = driInitFreeSlabManager(10, 10);
if (!intel_screen->fMan) {
fprintf(stderr, "Failed to create free slab manager.\n");
return FALSE;
}
intel_screen->staticPool = driDRMPoolInit(intel_screen->device->drmFD);
intel_screen->batchPool = driSlabPoolInit(intel_screen->device->drmFD,
DRM_BO_FLAG_EXE |
DRM_BO_FLAG_MEM_TT,
DRM_BO_FLAG_EXE |
DRM_BO_FLAG_MEM_TT,
4096, //intelScreen->maxBatchSize,
1, 40, 16*16384, 0,
intel_screen->fMan);
intel_screen->havePools = GL_TRUE;
return GL_TRUE;
}
extern const struct dri_extension card_extensions[];
int
intel_init_driver(struct egl_drm_device *device)
{
struct intel_screen *intel_screen;
/* Allocate the private area */
intel_screen = CALLOC_STRUCT(intel_screen);
if (!intel_screen)
return FALSE;
device->priv = (void *)intel_screen;
intel_screen->device = device;
if (!intel_create_pools(intel_screen))
return FALSE;
intel_screen->batch = intel_batchbuffer_alloc(intel_screen);
intel_screen->winsys = intel_create_pipe_winsys(device->drmFD, intel_screen->fMan);
/* hack */
driInitExtensions(NULL, card_extensions, GL_FALSE);
return TRUE;
}
int
intel_create_drawable(struct egl_drm_drawable *drawable,
const __GLcontextModes * visual)
{
enum pipe_format colorFormat, depthFormat, stencilFormat;
struct intel_framebuffer *intelfb = CALLOC_STRUCT(intel_framebuffer);
if (!intelfb)
return GL_FALSE;
if (visual->redBits == 5)
colorFormat = PIPE_FORMAT_R5G6B5_UNORM;
else
colorFormat = PIPE_FORMAT_A8R8G8B8_UNORM;
if (visual->depthBits == 16)
depthFormat = PIPE_FORMAT_Z16_UNORM;
else if (visual->depthBits == 24)
depthFormat = PIPE_FORMAT_S8Z24_UNORM;
else
depthFormat = PIPE_FORMAT_NONE;
if (visual->stencilBits == 8)
stencilFormat = PIPE_FORMAT_S8Z24_UNORM;
else
stencilFormat = PIPE_FORMAT_NONE;
intelfb->stfb = st_create_framebuffer(visual,
colorFormat,
depthFormat,
stencilFormat,
drawable->w,
drawable->h,
(void*) intelfb);
if (!intelfb->stfb) {
free(intelfb);
return GL_FALSE;
}
drawable->priv = (void *) intelfb;
return GL_TRUE;
}
#if 0
PUBLIC const char __driConfigOptions[] =
DRI_CONF_BEGIN DRI_CONF_SECTION_PERFORMANCE
DRI_CONF_FTHROTTLE_MODE(DRI_CONF_FTHROTTLE_IRQS)
DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0)
DRI_CONF_SECTION_END DRI_CONF_SECTION_QUALITY
DRI_CONF_FORCE_S3TC_ENABLE(false)
DRI_CONF_ALLOW_LARGE_TEXTURES(1)
DRI_CONF_SECTION_END DRI_CONF_END;
const uint __driNConfigOptions = 4;
#ifdef USE_NEW_INTERFACE
static PFNGLXCREATECONTEXTMODES create_context_modes = NULL;
#endif /*USE_NEW_INTERFACE */
extern const struct dri_extension card_extensions[];
static void
intelPrintDRIInfo(struct intel_screen * intelScreen,
__DRIscreenPrivate * sPriv, I830DRIPtr gDRIPriv)
{
fprintf(stderr, "*** Front size: 0x%x offset: 0x%x pitch: %d\n",
intelScreen->front.size, intelScreen->front.offset,
intelScreen->front.pitch);
fprintf(stderr, "*** Memory : 0x%x\n", gDRIPriv->mem);
}
static void
intelPrintSAREA(const drmI830Sarea * sarea)
{
fprintf(stderr, "SAREA: sarea width %d height %d\n", sarea->width,
sarea->height);
fprintf(stderr, "SAREA: pitch: %d\n", sarea->pitch);
fprintf(stderr,
"SAREA: front offset: 0x%08x size: 0x%x handle: 0x%x\n",
sarea->front_offset, sarea->front_size,
(unsigned) sarea->front_handle);
fprintf(stderr,
"SAREA: back offset: 0x%08x size: 0x%x handle: 0x%x\n",
sarea->back_offset, sarea->back_size,
(unsigned) sarea->back_handle);
fprintf(stderr, "SAREA: depth offset: 0x%08x size: 0x%x handle: 0x%x\n",
sarea->depth_offset, sarea->depth_size,
(unsigned) sarea->depth_handle);
fprintf(stderr, "SAREA: tex offset: 0x%08x size: 0x%x handle: 0x%x\n",
sarea->tex_offset, sarea->tex_size, (unsigned) sarea->tex_handle);
fprintf(stderr, "SAREA: rotation: %d\n", sarea->rotation);
fprintf(stderr,
"SAREA: rotated offset: 0x%08x size: 0x%x\n",
sarea->rotated_offset, sarea->rotated_size);
fprintf(stderr, "SAREA: rotated pitch: %d\n", sarea->rotated_pitch);
}
/**
* Use the information in the sarea to update the screen parameters
* related to screen rotation. Needs to be called locked.
*/
void
intelUpdateScreenRotation(__DRIscreenPrivate * sPriv, drmI830Sarea * sarea)
{
struct intel_screen *intelScreen = intel_screen(sPriv);
if (intelScreen->front.map) {
drmUnmap(intelScreen->front.map, intelScreen->front.size);
intelScreen->front.map = NULL;
}
if (intelScreen->front.buffer)
driDeleteBuffers(1, &intelScreen->front.buffer);
intelScreen->front.width = sarea->width;
intelScreen->front.height = sarea->height;
intelScreen->front.offset = sarea->front_offset;
intelScreen->front.pitch = sarea->pitch * intelScreen->front.cpp;
intelScreen->front.size = sarea->front_size;
intelScreen->front.handle = sarea->front_handle;
assert( sarea->front_size >=
intelScreen->front.pitch * intelScreen->front.height );
#if 0 /* JB not important */
if (!sarea->front_handle)
return;
if (drmMap(sPriv->fd,
sarea->front_handle,
intelScreen->front.size,
(drmAddress *) & intelScreen->front.map) != 0) {
fprintf(stderr, "drmMap(frontbuffer) failed!\n");
return;
}
#endif
#if 0 /* JB */
if (intelScreen->staticPool) {
driGenBuffers(intelScreen->staticPool, "static region", 1,
&intelScreen->front.buffer, 64,
DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_NO_MOVE |
DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE, 0);
driBOSetStatic(intelScreen->front.buffer,
intelScreen->front.offset,
intelScreen->front.pitch * intelScreen->front.height,
intelScreen->front.map, 0);
}
#else
if (intelScreen->staticPool) {
if (intelScreen->front.buffer)
driBOUnReference(intelScreen->front.buffer);
driGenBuffers(intelScreen->staticPool, "front", 1, &intelScreen->front.buffer, 0, 0, 0);
driBOSetReferenced(intelScreen->front.buffer, sarea->front_bo_handle);
}
#endif
}
boolean
intelCreatePools(__DRIscreenPrivate * sPriv)
{
//unsigned batchPoolSize = 1024*1024;
struct intel_screen *intelScreen = intel_screen(sPriv);
if (intelScreen->havePools)
return GL_TRUE;
#if 0 /* ZZZ JB fix this */
intelScreen->staticPool = driDRMStaticPoolInit(sPriv->fd);
if (!intelScreen->staticPool)
return GL_FALSE;
batchPoolSize /= BATCH_SZ;
intelScreen->batchPool = driBatchPoolInit(sPriv->fd,
DRM_BO_FLAG_EXE |
DRM_BO_FLAG_MEM_TT |
DRM_BO_FLAG_MEM_LOCAL,
BATCH_SZ,
batchPoolSize, 5);
if (!intelScreen->batchPool) {
fprintf(stderr, "Failed to initialize batch pool - possible incorrect agpgart installed\n");
return GL_FALSE;
}
#else
intelScreen->staticPool = driDRMPoolInit(sPriv->fd);
intelScreen->batchPool = driSlabPoolInit(sPriv->fd,
DRM_BO_FLAG_EXE |
DRM_BO_FLAG_MEM_TT,
DRM_BO_FLAG_EXE |
DRM_BO_FLAG_MEM_TT,
4096, //intelScreen->maxBatchSize,
1, 40, 16*16384, 0,
intelScreen->fMan);
#endif
intelScreen->havePools = GL_TRUE;
//intelUpdateScreenRotation(sPriv, intelScreen->sarea);
return GL_TRUE;
}
static boolean
intelInitDriver(__DRIscreenPrivate * sPriv)
{
struct intel_screen *intelScreen;
I830DRIPtr gDRIPriv = (I830DRIPtr) sPriv->pDevPriv;
PFNGLXSCRENABLEEXTENSIONPROC glx_enable_extension =
(PFNGLXSCRENABLEEXTENSIONPROC) (*dri_interface->
getProcAddress("glxEnableExtension"));
void *const psc = sPriv->psc->screenConfigs;
if (sPriv->devPrivSize != sizeof(I830DRIRec)) {
fprintf(stderr,
"\nERROR! sizeof(I830DRIRec) does not match passed size from device driver\n");
return GL_FALSE;
}
/* Allocate the private area */
intelScreen = CALLOC_STRUCT(intel_screen);
if (!intelScreen)
return GL_FALSE;
/* parse information in __driConfigOptions */
driParseOptionInfo(&intelScreen->optionCache,
__driConfigOptions, __driNConfigOptions);
sPriv->private = (void *) intelScreen;
intelScreen->sarea = (drmI830Sarea *) (((GLubyte *) sPriv->pSAREA) +
gDRIPriv->sarea_priv_offset);
intelScreen->deviceID = gDRIPriv->deviceID;
intelScreen->front.cpp = gDRIPriv->cpp;
intelScreen->drmMinor = sPriv->drmMinor;
assert(gDRIPriv->bitsPerPixel == 16 ||
gDRIPriv->bitsPerPixel == 32);
intelUpdateScreenRotation(sPriv, intelScreen->sarea);
if (0)
intelPrintDRIInfo(intelScreen, sPriv, gDRIPriv);
if (glx_enable_extension != NULL) {
(*glx_enable_extension) (psc, "GLX_SGI_swap_control");
(*glx_enable_extension) (psc, "GLX_SGI_video_sync");
(*glx_enable_extension) (psc, "GLX_MESA_swap_control");
(*glx_enable_extension) (psc, "GLX_MESA_swap_frame_usage");
(*glx_enable_extension) (psc, "GLX_SGI_make_current_read");
}
#if 1 // ZZZ JB
intelScreen->mgr = driFenceMgrTTMInit(sPriv->fd);
if (!intelScreen->mgr) {
fprintf(stderr, "Failed to create fence manager.\n");
return GL_FALSE;
}
intelScreen->fMan = driInitFreeSlabManager(10, 10);
if (!intelScreen->fMan) {
fprintf(stderr, "Failed to create free slab manager.\n");
return GL_FALSE;
}
if (!intelCreatePools(sPriv))
return GL_FALSE;
#endif
intelScreen->winsys = intel_create_pipe_winsys(sPriv->fd, intelScreen->fMan);
return GL_TRUE;
}
static void
intelDestroyScreen(__DRIscreenPrivate * sPriv)
{
struct intel_screen *intelScreen = intel_screen(sPriv);
/* intelUnmapScreenRegions(intelScreen); */
if (intelScreen->havePools) {
driPoolTakeDown(intelScreen->staticPool);
driPoolTakeDown(intelScreen->batchPool);
}
FREE(intelScreen);
sPriv->private = NULL;
}
/**
* This is called when we need to set up GL rendering to a new X window.
*/
static boolean
intelCreateBuffer(__DRIscreenPrivate * driScrnPriv,
__DRIdrawablePrivate * driDrawPriv,
const __GLcontextModes * visual, boolean isPixmap)
{
if (isPixmap) {
return GL_FALSE; /* not implemented */
}
else {
enum pipe_format colorFormat, depthFormat, stencilFormat;
struct intel_framebuffer *intelfb = CALLOC_STRUCT(intel_framebuffer);
if (!intelfb)
return GL_FALSE;
if (visual->redBits == 5)
colorFormat = PIPE_FORMAT_R5G6B5_UNORM;
else
colorFormat = PIPE_FORMAT_A8R8G8B8_UNORM;
if (visual->depthBits == 16)
depthFormat = PIPE_FORMAT_Z16_UNORM;
else if (visual->depthBits == 24)
depthFormat = PIPE_FORMAT_S8Z24_UNORM;
else
depthFormat = PIPE_FORMAT_NONE;
if (visual->stencilBits == 8)
stencilFormat = PIPE_FORMAT_S8Z24_UNORM;
else
stencilFormat = PIPE_FORMAT_NONE;
intelfb->stfb = st_create_framebuffer(visual,
colorFormat,
depthFormat,
stencilFormat,
driDrawPriv->w,
driDrawPriv->h,
(void*) intelfb);
if (!intelfb->stfb) {
free(intelfb);
return GL_FALSE;
}
driDrawPriv->driverPrivate = (void *) intelfb;
return GL_TRUE;
}
}
static void
intelDestroyBuffer(__DRIdrawablePrivate * driDrawPriv)
{
struct intel_framebuffer *intelfb = intel_framebuffer(driDrawPriv);
assert(intelfb->stfb);
st_unreference_framebuffer(&intelfb->stfb);
free(intelfb);
}
/**
* Get information about previous buffer swaps.
*/
static int
intelGetSwapInfo(__DRIdrawablePrivate * dPriv, __DRIswapInfo * sInfo)
{
if ((dPriv == NULL) || (dPriv->driverPrivate == NULL)
|| (sInfo == NULL)) {
return -1;
}
return 0;
}
static void
intelSetTexOffset(__DRIcontext *pDRICtx, int texname,
unsigned long long offset, int depth, uint pitch)
{
abort();
#if 0
struct intel_context *intel = (struct intel_context*)
((__DRIcontextPrivate*)pDRICtx->private)->driverPrivate;
struct gl_texture_object *tObj = _mesa_lookup_texture(&intel->ctx, texname);
struct st_texture_object *stObj = st_texture_object(tObj);
if (!stObj)
return;
if (stObj->pt)
st->pipe->texture_release(intel->st->pipe, &stObj->pt);
stObj->imageOverride = GL_TRUE;
stObj->depthOverride = depth;
stObj->pitchOverride = pitch;
if (offset)
stObj->textureOffset = offset;
#endif
}
static const struct __DriverAPIRec intelAPI = {
.InitDriver = intelInitDriver,
.DestroyScreen = intelDestroyScreen,
.CreateContext = intelCreateContext,
.DestroyContext = intelDestroyContext,
.CreateBuffer = intelCreateBuffer,
.DestroyBuffer = intelDestroyBuffer,
.SwapBuffers = intelSwapBuffers,
.MakeCurrent = intelMakeCurrent,
.UnbindContext = intelUnbindContext,
.GetSwapInfo = intelGetSwapInfo,
.GetMSC = driGetMSC32,
.WaitForMSC = driWaitForMSC32,
.WaitForSBC = NULL,
.SwapBuffersMSC = NULL,
.CopySubBuffer = intelCopySubBuffer,
.setTexOffset = intelSetTexOffset,
};
static __GLcontextModes *
intelFillInModes(unsigned pixel_bits, unsigned depth_bits,
unsigned stencil_bits, boolean have_back_buffer)
{
__GLcontextModes *modes;
__GLcontextModes *m;
unsigned num_modes;
unsigned depth_buffer_factor;
unsigned back_buffer_factor;
GLenum fb_format;
GLenum fb_type;
/* GLX_SWAP_COPY_OML is only supported because the Intel driver doesn't
* support pageflipping at all.
*/
static const GLenum back_buffer_modes[] = {
GLX_NONE, GLX_SWAP_UNDEFINED_OML, GLX_SWAP_COPY_OML
};
u_int8_t depth_bits_array[3];
u_int8_t stencil_bits_array[3];
depth_bits_array[0] = 0;
depth_bits_array[1] = depth_bits;
depth_bits_array[2] = depth_bits;
/* Just like with the accumulation buffer, always provide some modes
* with a stencil buffer. It will be a sw fallback, but some apps won't
* care about that.
*/
stencil_bits_array[0] = 0;
stencil_bits_array[1] = 0;
if (depth_bits == 24)
stencil_bits_array[1] = (stencil_bits == 0) ? 8 : stencil_bits;
stencil_bits_array[2] = (stencil_bits == 0) ? 8 : stencil_bits;
depth_buffer_factor = ((depth_bits != 0) || (stencil_bits != 0)) ? 3 : 1;
back_buffer_factor = (have_back_buffer) ? 3 : 1;
num_modes = depth_buffer_factor * back_buffer_factor * 4;
if (pixel_bits == 16) {
fb_format = GL_RGB;
fb_type = GL_UNSIGNED_SHORT_5_6_5;
}
else {
fb_format = GL_BGRA;
fb_type = GL_UNSIGNED_INT_8_8_8_8_REV;
}
modes =
(*dri_interface->createContextModes) (num_modes,
sizeof(__GLcontextModes));
m = modes;
if (!driFillInModes(&m, fb_format, fb_type,
depth_bits_array, stencil_bits_array,
depth_buffer_factor, back_buffer_modes,
back_buffer_factor, GLX_TRUE_COLOR)) {
fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
__LINE__);
return NULL;
}
if (!driFillInModes(&m, fb_format, fb_type,
depth_bits_array, stencil_bits_array,
depth_buffer_factor, back_buffer_modes,
back_buffer_factor, GLX_DIRECT_COLOR)) {
fprintf(stderr, "[%s:%u] Error creating FBConfig!\n", __func__,
__LINE__);
return NULL;
}
/* Mark the visual as slow if there are "fake" stencil bits.
*/
for (m = modes; m != NULL; m = m->next) {
if ((m->stencilBits != 0) && (m->stencilBits != stencil_bits)) {
m->visualRating = GLX_SLOW_CONFIG;
}
}
return modes;
}
/**
* This is the bootstrap function for the driver. libGL supplies all of the
* requisite information about the system, and the driver initializes itself.
* This routine also fills in the linked list pointed to by \c driver_modes
* with the \c __GLcontextModes that the driver can support for windows or
* pbuffers.
*
* \return A pointer to a \c __DRIscreenPrivate on success, or \c NULL on
* failure.
*/
PUBLIC void *
__driCreateNewScreen_20050727(__DRInativeDisplay * dpy, int scrn,
__DRIscreen * psc,
const __GLcontextModes * modes,
const __DRIversion * ddx_version,
const __DRIversion * dri_version,
const __DRIversion * drm_version,
const __DRIframebuffer * frame_buffer,
drmAddress pSAREA, int fd,
int internal_api_version,
const __DRIinterfaceMethods * interface,
__GLcontextModes ** driver_modes)
{
__DRIscreenPrivate *psp;
static const __DRIversion ddx_expected = { 1, 7, 0 };
static const __DRIversion dri_expected = { 4, 0, 0 };
static const __DRIversion drm_expected = { 1, 7, 0 };
dri_interface = interface;
if (!driCheckDriDdxDrmVersions2("i915",
dri_version, &dri_expected,
ddx_version, &ddx_expected,
drm_version, &drm_expected)) {
return NULL;
}
psp = __driUtilCreateNewScreen(dpy, scrn, psc, NULL,
ddx_version, dri_version, drm_version,
frame_buffer, pSAREA, fd,
internal_api_version, &intelAPI);
if (psp != NULL) {
I830DRIPtr dri_priv = (I830DRIPtr) psp->pDevPriv;
*driver_modes = intelFillInModes(dri_priv->cpp * 8,
(dri_priv->cpp == 2) ? 16 : 24,
(dri_priv->cpp == 2) ? 0 : 8, 1);
/* Calling driInitExtensions here, with a NULL context pointer,
* does not actually enable the extensions. It just makes sure
* that all the dispatch offsets for all the extensions that
* *might* be enables are known. This is needed because the
* dispatch offsets need to be known when _mesa_context_create
* is called, but we can't enable the extensions until we have a
* context pointer.
*
* Hello chicken. Hello egg. How are you two today?
*/
driInitExtensions(NULL, card_extensions, GL_FALSE);
}
return (void *) psp;
}
#endif
@@ -0,0 +1,133 @@
/**************************************************************************
*
* Copyright 2003 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.
*
**************************************************************************/
#ifndef _INTEL_SCREEN_H_
#define _INTEL_SCREEN_H_
#include "ws_dri_bufpool.h"
#include "pipe/p_compiler.h"
struct egl_drm_device *device;
struct intel_screen
{
#if 0
struct {
drm_handle_t handle;
/* We create a static dri buffer for the frontbuffer.
*/
struct _DriBufferObject *buffer;
char *map; /* memory map */
int offset; /* from start of video mem, in bytes */
int pitch; /* row stride, in bytes */
int width;
int height;
int size;
int cpp; /* for front and back buffers */
} front;
#endif
int drmFB;
#if 0
int deviceID;
int drmMinor;
drmI830Sarea *sarea;*/
/**
* Configuration cache with default values for all contexts
*/
driOptionCache optionCache;
#endif
struct _DriBufferPool *batchPool;
struct _DriBufferPool *staticPool; /** for the X screen/framebuffer */
boolean havePools;
#if 0
/**
* Temporary(?) context to use for SwapBuffers or other situations in
* which we need a rendering context, but none is currently bound.
*/
struct intel_context *dummyContext;
#endif
/*
* New stuff form the i915tex integration
*/
struct _DriFenceMgr *mgr;
struct _DriFreeSlabManager *fMan;
unsigned batch_id;
struct pipe_winsys *winsys;
struct egl_drm_device *device;
/* batch buffer used for swap buffers */
struct intel_batchbuffer *batch;
};
/** cast wrapper */
#if 0
static INLINE struct intel_screen *
intel_screen(__DRIscreenPrivate *sPriv)
{
return (struct intel_screen *) sPriv->private;
}
extern void
intelUpdateScreenRotation(__DRIscreenPrivate * sPriv, drmI830Sarea * sarea);
extern void intelDestroyContext(__DRIcontextPrivate * driContextPriv);
extern boolean intelUnbindContext(__DRIcontextPrivate * driContextPriv);
extern boolean
intelMakeCurrent(__DRIcontextPrivate * driContextPriv,
__DRIdrawablePrivate * driDrawPriv,
__DRIdrawablePrivate * driReadPriv);
extern boolean
intelCreatePools(__DRIscreenPrivate *sPriv);
extern boolean
intelCreateContext(const __GLcontextModes * visual,
__DRIcontextPrivate * driContextPriv,
void *sharedContextPrivate);
#endif
#endif
@@ -0,0 +1,327 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
**************************************************************************/
#include "intel_screen.h"
#include "intel_context.h"
#include "intel_swapbuffers.h"
#include "intel_batchbuffer.h"
#include "intel_reg.h"
#include "intel_winsys.h"
#include "pipe/p_context.h"
#include "state_tracker/st_public.h"
#include "state_tracker/st_context.h"
#include "state_tracker/st_cb_fbo.h"
#include "intel_egl.h"
static void
intel_display_surface(struct egl_drm_drawable *draw,
struct pipe_surface *surf);
void intel_swap_buffers(struct egl_drm_drawable *draw)
{
struct intel_framebuffer *intel_fb = (struct intel_framebuffer *)draw->priv;
struct pipe_surface *back_surf;
assert(intel_fb);
assert(intel_fb->stfb);
back_surf = st_get_framebuffer_surface(intel_fb->stfb, ST_SURFACE_BACK_LEFT);
if (back_surf) {
st_notify_swapbuffers(intel_fb->stfb);
intel_display_surface(draw, back_surf);
st_notify_swapbuffers_complete(intel_fb->stfb);
}
}
static void
intel_display_surface(struct egl_drm_drawable *draw,
struct pipe_surface *surf)
{
struct intel_screen *intel = (struct intel_screen *)draw->device->priv;
struct intel_framebuffer *intel_fb = (struct intel_framebuffer *)draw->priv;
struct _DriFenceObject *fence;
//const int srcWidth = surf->width;
//const int srcHeight = surf->height;
const int srcPitch = surf->pitch;
const int dstWidth = intel_fb->front->width;
const int dstHeight = intel_fb->front->height;
const int dstPitch = intel_fb->front->pitch / 4;//draw->front.cpp;
const int cpp = 4;//intel_fb->front->cpp;
int BR13, CMD;
//int i;
BR13 = (dstPitch * cpp) | (0xCC << 16) | (1 << 24) | (1 << 25);
CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
XY_SRC_COPY_BLT_WRITE_RGB);
printf("srcPitch: %u, dstWidth: %u, dstHeight: %u, dstPitch: %u, cpp: %u\n", srcPitch, dstWidth, dstHeight, dstPitch, cpp);
BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS);
OUT_BATCH(CMD);
OUT_BATCH(BR13);
OUT_BATCH((0 << 16) | 0);
OUT_BATCH((dstHeight << 16) | dstWidth);
OUT_RELOC(intel_fb->front_buffer,
DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,
DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, 0);
OUT_BATCH((0 << 16) | 0);
OUT_BATCH((srcPitch * cpp) & 0xffff);
OUT_RELOC(dri_bo(surf->buffer),
DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, 0);
ADVANCE_BATCH();
fence = intel_batchbuffer_flush(intel->batch);
driFenceUnReference(&fence);
intel_batchbuffer_finish(intel->batch);
}
#if 0
/**
* Display a colorbuffer surface in an X window.
* Used for SwapBuffers and flushing front buffer rendering.
*
* \param dPriv the window/drawable to display into
* \param surf the surface to display
* \param rect optional subrect of surface to display (may be NULL).
*/
void
intelDisplaySurface(__DRIdrawablePrivate *dPriv,
struct pipe_surface *surf,
const drm_clip_rect_t *rect)
{
struct intel_screen *intelScreen = intel_screen(dPriv->driScreenPriv);
//struct intel_context *intel = intelScreen->dummyContext;
DBG(SWAP, "%s\n", __FUNCTION__);
#if 0
if (!intel) {
/* XXX this is where some kind of extra/meta context could be useful */
return;
}
#endif
if (intel->last_swap_fence) {
driFenceFinish(intel->last_swap_fence, DRM_FENCE_TYPE_EXE, TRUE);
driFenceUnReference(&intel->last_swap_fence);
intel->last_swap_fence = NULL;
}
intel->last_swap_fence = intel->first_swap_fence;
intel->first_swap_fence = NULL;
/* The LOCK_HARDWARE is required for the cliprects. Buffer offsets
* should work regardless.
*/
LOCK_HARDWARE(intel);
/* if this drawable isn't currently bound the LOCK_HARDWARE done on the
* current context (which is what intelScreenContext should return) might
* not get a contended lock and thus cliprects not updated (tests/manywin)
*/
if (intel_context(dPriv->driContextPriv) != intel)
DRI_VALIDATE_DRAWABLE_INFO(intel->driScreen, dPriv);
if (dPriv && dPriv->numClipRects) {
const int srcWidth = surf->width;
const int srcHeight = surf->height;
const int nbox = dPriv->numClipRects;
const drm_clip_rect_t *pbox = dPriv->pClipRects;
const int pitch = intelScreen->front.pitch / intelScreen->front.cpp;
const int cpp = intelScreen->front.cpp;
const int srcpitch = surf->pitch;
int BR13, CMD;
int i;
ASSERT(surf->buffer);
ASSERT(surf->cpp == cpp);
DBG(SWAP, "screen pitch %d src surface pitch %d\n",
pitch, surf->pitch);
if (cpp == 2) {
BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24);
CMD = XY_SRC_COPY_BLT_CMD;
}
else {
BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24) | (1 << 25);
CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
XY_SRC_COPY_BLT_WRITE_RGB);
}
for (i = 0; i < nbox; i++, pbox++) {
drm_clip_rect_t box;
drm_clip_rect_t sbox;
if (pbox->x1 > pbox->x2 ||
pbox->y1 > pbox->y2 ||
pbox->x2 > intelScreen->front.width ||
pbox->y2 > intelScreen->front.height) {
/* invalid cliprect, skip it */
continue;
}
box = *pbox;
if (rect) {
/* intersect cliprect with user-provided src rect */
drm_clip_rect_t rrect;
rrect.x1 = dPriv->x + rect->x1;
rrect.y1 = (dPriv->h - rect->y1 - rect->y2) + dPriv->y;
rrect.x2 = rect->x2 + rrect.x1;
rrect.y2 = rect->y2 + rrect.y1;
if (rrect.x1 > box.x1)
box.x1 = rrect.x1;
if (rrect.y1 > box.y1)
box.y1 = rrect.y1;
if (rrect.x2 < box.x2)
box.x2 = rrect.x2;
if (rrect.y2 < box.y2)
box.y2 = rrect.y2;
if (box.x1 > box.x2 || box.y1 > box.y2)
continue;
}
/* restrict blit to size of actually rendered area */
if (box.x2 - box.x1 > srcWidth)
box.x2 = srcWidth + box.x1;
if (box.y2 - box.y1 > srcHeight)
box.y2 = srcHeight + box.y1;
DBG(SWAP, "box x1 x2 y1 y2 %d %d %d %d\n",
box.x1, box.x2, box.y1, box.y2);
sbox.x1 = box.x1 - dPriv->x;
sbox.y1 = box.y1 - dPriv->y;
assert(box.x1 < box.x2);
assert(box.y1 < box.y2);
/* XXX this could be done with pipe->surface_copy() */
BEGIN_BATCH(8, INTEL_BATCH_NO_CLIPRECTS);
OUT_BATCH(CMD);
OUT_BATCH(BR13);
OUT_BATCH((box.y1 << 16) | box.x1);
OUT_BATCH((box.y2 << 16) | box.x2);
OUT_RELOC(intelScreen->front.buffer,
DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_WRITE,
DRM_BO_MASK_MEM | DRM_BO_FLAG_WRITE, 0);
OUT_BATCH((sbox.y1 << 16) | sbox.x1);
OUT_BATCH((srcpitch * cpp) & 0xffff);
OUT_RELOC(dri_bo(surf->buffer),
DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
DRM_BO_MASK_MEM | DRM_BO_FLAG_READ, 0);
ADVANCE_BATCH();
}
if (intel->first_swap_fence)
driFenceUnReference(&intel->first_swap_fence);
intel->first_swap_fence = intel_batchbuffer_flush(intel->batch);
}
UNLOCK_HARDWARE(intel);
if (intel->lastStamp != dPriv->lastStamp) {
intelUpdateWindowSize(dPriv);
intel->lastStamp = dPriv->lastStamp;
}
}
/**
* This will be called whenever the currently bound window is moved/resized.
*/
void
intelUpdateWindowSize(__DRIdrawablePrivate *dPriv)
{
struct intel_framebuffer *intelfb = intel_framebuffer(dPriv);
assert(intelfb->stfb);
st_resize_framebuffer(intelfb->stfb, dPriv->w, dPriv->h);
}
void
intelSwapBuffers(__DRIdrawablePrivate * dPriv)
{
struct intel_framebuffer *intel_fb = intel_framebuffer(dPriv);
struct pipe_surface *back_surf;
assert(intel_fb);
assert(intel_fb->stfb);
back_surf = st_get_framebuffer_surface(intel_fb->stfb,
ST_SURFACE_BACK_LEFT);
if (back_surf) {
st_notify_swapbuffers(intel_fb->stfb);
intelDisplaySurface(dPriv, back_surf, NULL);
st_notify_swapbuffers_complete(intel_fb->stfb);
}
}
/**
* Called via glXCopySubBufferMESA() to copy a subrect of the back
* buffer to the front buffer/screen.
*/
void
intelCopySubBuffer(__DRIdrawablePrivate * dPriv, int x, int y, int w, int h)
{
struct intel_framebuffer *intel_fb = intel_framebuffer(dPriv);
struct pipe_surface *back_surf;
assert(intel_fb);
assert(intel_fb->stfb);
back_surf = st_get_framebuffer_surface(intel_fb->stfb,
ST_SURFACE_BACK_LEFT);
if (back_surf) {
drm_clip_rect_t rect;
rect.x1 = x;
rect.y1 = y;
rect.x2 = w;
rect.y2 = h;
st_notify_swapbuffers(intel_fb->stfb);
intelDisplaySurface(dPriv, back_surf, &rect);
}
}
#endif
@@ -1,6 +1,6 @@
/**************************************************************************
*
* Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
* Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
@@ -25,13 +25,23 @@
*
**************************************************************************/
#ifndef INTEL_BATCHPOOL_H
#define INTEL_BATCHPOOL_H
extern struct _DriBufferPool *driBatchPoolInit(int fd, unsigned flags,
unsigned long bufSize,
unsigned numBufs,
unsigned checkDelayed);
#ifndef INTEL_SWAPBUFFERS_H
#define INTEL_SWAPBUFFERS_H
#endif /* INTEL_BATCHPOOL_H */
struct pipe_surface;
#if 0
extern void intelDisplaySurface(__DRIdrawablePrivate * dPriv,
struct pipe_surface *surf,
const drm_clip_rect_t * rect);
extern void intelSwapBuffers(__DRIdrawablePrivate * dPriv);
extern void intelCopySubBuffer(__DRIdrawablePrivate * dPriv,
int x, int y, int w, int h);
extern void intelUpdateWindowSize(__DRIdrawablePrivate *dPriv);
#endif
#endif /* INTEL_SWAPBUFFERS_H */
@@ -0,0 +1,73 @@
/**************************************************************************
*
* Copyright 2006 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.
*
**************************************************************************/
#ifndef INTEL_WINSYS_H
#define INTEL_WINSYS_H
#include "pipe/p_state.h"
struct intel_context;
struct pipe_context;
struct pipe_winsys;
struct pipe_buffer;
struct _DriBufferObject;
struct pipe_winsys *
intel_create_pipe_winsys( int fd, struct _DriFreeSlabManager *fMan );
void
intel_destroy_pipe_winsys( struct pipe_winsys *winsys );
struct pipe_context *
intel_create_softpipe( struct intel_context *intel,
struct pipe_winsys *winsys );
struct pipe_context *
intel_create_i915simple( struct intel_context *intel,
struct pipe_winsys *winsys );
struct intel_buffer {
struct pipe_buffer base;
struct _DriBufferObject *driBO;
};
static INLINE struct intel_buffer *
intel_buffer( struct pipe_buffer *buf )
{
return (struct intel_buffer *)buf;
}
static INLINE struct _DriBufferObject *
dri_bo( struct pipe_buffer *buf )
{
return intel_buffer(buf)->driBO;
}
#endif
@@ -0,0 +1,184 @@
/**************************************************************************
*
* 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 <stdlib.h>
#include <xf86drm.h>
#include "ws_dri_bufpool.h"
#include "ws_dri_bufmgr.h"
#include "intel_context.h"
#include "intel_batchbuffer.h"
#include "intel_winsys.h"
#include "pipe/p_util.h"
#include "pipe/p_winsys.h"
#include "i915simple/i915_winsys.h"
#include "i915simple/i915_screen.h"
struct intel_i915_winsys {
struct i915_winsys winsys; /**< batch buffer funcs */
struct pipe_winsys *pws;
struct intel_context *intel;
};
/* Turn a i915simple winsys into an intel/i915simple winsys:
*/
static inline struct intel_i915_winsys *
intel_i915_winsys( struct i915_winsys *sws )
{
return (struct intel_i915_winsys *)sws;
}
/* Simple batchbuffer interface:
*/
static unsigned *intel_i915_batch_start( struct i915_winsys *sws,
unsigned dwords,
unsigned relocs )
{
struct intel_context *intel = intel_i915_winsys(sws)->intel;
/* XXX: check relocs.
*/
if (intel_batchbuffer_space( intel->batch ) >= dwords * 4) {
/* XXX: Hmm, the driver can't really do much with this pointer:
*/
return (unsigned *)intel->batch->ptr;
}
else
return NULL;
}
static void intel_i915_batch_dword( struct i915_winsys *sws,
unsigned dword )
{
struct intel_context *intel = intel_i915_winsys(sws)->intel;
intel_batchbuffer_emit_dword( intel->batch, dword );
}
static void intel_i915_batch_reloc( struct i915_winsys *sws,
struct pipe_buffer *buf,
unsigned access_flags,
unsigned delta )
{
struct intel_context *intel = intel_i915_winsys(sws)->intel;
unsigned flags = DRM_BO_FLAG_MEM_TT;
unsigned mask = DRM_BO_MASK_MEM;
if (access_flags & I915_BUFFER_ACCESS_WRITE) {
flags |= DRM_BO_FLAG_WRITE;
mask |= DRM_BO_FLAG_WRITE;
}
if (access_flags & I915_BUFFER_ACCESS_READ) {
flags |= DRM_BO_FLAG_READ;
mask |= DRM_BO_FLAG_READ;
}
#if 0 /* JB old */
intel_batchbuffer_emit_reloc( intel->batch,
dri_bo( buf ),
flags, mask,
delta );
#else /* new */
intel_offset_relocation( intel->batch,
delta,
dri_bo( buf ),
flags,
mask );
#endif
}
static void intel_i915_batch_flush( struct i915_winsys *sws,
struct pipe_fence_handle **fence )
{
struct intel_i915_winsys *iws = intel_i915_winsys(sws);
struct intel_context *intel = iws->intel;
union {
struct _DriFenceObject *dri;
struct pipe_fence_handle *pipe;
} fu;
if (fence)
assert(!*fence);
fu.dri = intel_batchbuffer_flush( intel->batch );
if (!fu.dri) {
assert(0);
*fence = NULL;
return;
}
if (fu.dri) {
if (fence)
*fence = fu.pipe;
else
driFenceUnReference(&fu.dri);
}
}
/**
* Create i915 hardware rendering context.
*/
struct pipe_context *
intel_create_i915simple( struct intel_context *intel,
struct pipe_winsys *winsys )
{
struct intel_i915_winsys *iws = CALLOC_STRUCT( intel_i915_winsys );
struct pipe_screen *screen;
/* Fill in this struct with callbacks that i915simple will need to
* communicate with the window system, buffer manager, etc.
*/
iws->winsys.batch_start = intel_i915_batch_start;
iws->winsys.batch_dword = intel_i915_batch_dword;
iws->winsys.batch_reloc = intel_i915_batch_reloc;
iws->winsys.batch_flush = intel_i915_batch_flush;
iws->pws = winsys;
iws->intel = intel;
screen = i915_create_screen(winsys, PCI_CHIP_I945_GM);
assert(screen);
/* Create the i915simple context:
*/
return i915_create_context( screen,
winsys,
&iws->winsys );
}
@@ -0,0 +1,338 @@
/**************************************************************************
*
* 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 <stdlib.h>
#include <xf86drm.h>
//#include "dri_bufpool.h"
//#include "dri_bufmgr.h"
#include "intel_context.h"
#include "intel_winsys.h"
#include "intel_swapbuffers.h"
#include "intel_batchbuffer.h"
#include "pipe/p_winsys.h"
#include "pipe/p_defines.h"
#include "pipe/p_state.h"
#include "pipe/p_util.h"
#include "pipe/p_inlines.h"
struct intel_pipe_winsys {
struct pipe_winsys winsys;
struct _DriBufferPool *regionPool;
struct _DriFreeSlabManager *fMan;
};
/* Turn a pipe winsys into an intel/pipe winsys:
*/
static inline struct intel_pipe_winsys *
intel_pipe_winsys( struct pipe_winsys *winsys )
{
return (struct intel_pipe_winsys *)winsys;
}
/* Most callbacks map direcly onto dri_bufmgr operations:
*/
static void *intel_buffer_map(struct pipe_winsys *winsys,
struct pipe_buffer *buf,
unsigned flags )
{
unsigned drm_flags = 0;
if (flags & PIPE_BUFFER_USAGE_CPU_WRITE)
drm_flags |= DRM_BO_FLAG_WRITE;
if (flags & PIPE_BUFFER_USAGE_CPU_READ)
drm_flags |= DRM_BO_FLAG_READ;
return driBOMap( dri_bo(buf), drm_flags, 0 );
}
static void intel_buffer_unmap(struct pipe_winsys *winsys,
struct pipe_buffer *buf)
{
driBOUnmap( dri_bo(buf) );
}
static void
intel_buffer_destroy(struct pipe_winsys *winsys,
struct pipe_buffer *buf)
{
driBOUnReference( dri_bo(buf) );
FREE(buf);
}
/* Pipe has no concept of pools. We choose the tex/region pool
* for all buffers.
* Grabs the hardware lock!
*/
static struct pipe_buffer *
intel_buffer_create(struct pipe_winsys *winsys,
unsigned alignment,
unsigned usage,
unsigned size )
{
struct intel_buffer *buffer = CALLOC_STRUCT( intel_buffer );
struct intel_pipe_winsys *iws = intel_pipe_winsys(winsys);
unsigned flags = 0;
buffer->base.refcount = 1;
buffer->base.alignment = alignment;
buffer->base.usage = usage;
buffer->base.size = size;
if (usage & (PIPE_BUFFER_USAGE_VERTEX /*| IWS_BUFFER_USAGE_LOCAL*/)) {
flags |= DRM_BO_FLAG_MEM_LOCAL | DRM_BO_FLAG_CACHED;
} else {
flags |= DRM_BO_FLAG_MEM_VRAM | DRM_BO_FLAG_MEM_TT;
}
if (usage & PIPE_BUFFER_USAGE_GPU_READ)
flags |= DRM_BO_FLAG_READ;
if (usage & PIPE_BUFFER_USAGE_GPU_WRITE)
flags |= DRM_BO_FLAG_WRITE;
/* drm complains if we don't set any read/write flags.
*/
if ((flags & (DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE)) == 0)
flags |= DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE;
#if 0
if (flags & IWS_BUFFER_USAGE_EXE)
flags |= DRM_BO_FLAG_EXE;
if (usage & IWS_BUFFER_USAGE_CACHED)
flags |= DRM_BO_FLAG_CACHED;
#endif
driGenBuffers( iws->regionPool,
"pipe buffer", 1, &buffer->driBO, alignment, flags, 0 );
driBOData( buffer->driBO, size, NULL, iws->regionPool, 0 );
return &buffer->base;
}
static struct pipe_buffer *
intel_user_buffer_create(struct pipe_winsys *winsys, void *ptr, unsigned bytes)
{
struct intel_buffer *buffer = CALLOC_STRUCT( intel_buffer );
struct intel_pipe_winsys *iws = intel_pipe_winsys(winsys);
driGenUserBuffer( iws->regionPool,
"pipe user buffer", &buffer->driBO, ptr, bytes );
buffer->base.refcount = 1;
return &buffer->base;
}
/* The state tracker (should!) keep track of whether the fake
* frontbuffer has been touched by any rendering since the last time
* we copied its contents to the real frontbuffer. Our task is easy:
*/
static void
intel_flush_frontbuffer( struct pipe_winsys *winsys,
struct pipe_surface *surf,
void *context_private)
{
#if 0
struct intel_context *intel = (struct intel_context *) context_private;
__DRIdrawablePrivate *dPriv = intel->driDrawable;
intelDisplaySurface(dPriv, surf, NULL);
#endif
}
static struct pipe_surface *
intel_i915_surface_alloc(struct pipe_winsys *winsys)
{
struct pipe_surface *surf = CALLOC_STRUCT(pipe_surface);
if (surf) {
surf->refcount = 1;
surf->winsys = winsys;
}
return surf;
}
/**
* Round n up to next multiple.
*/
static INLINE unsigned
round_up(unsigned n, unsigned multiple)
{
return (n + multiple - 1) & ~(multiple - 1);
}
/**
* Copied from xm_winsys.c
*/
static int
intel_i915_surface_alloc_storage(struct pipe_winsys *winsys,
struct pipe_surface *surf,
unsigned width, unsigned height,
enum pipe_format format,
unsigned flags)
{
const unsigned alignment = 64;
//int ret;
surf->width = width;
surf->height = height;
surf->format = format;
surf->cpp = pf_get_size(format);
surf->pitch = round_up(width, alignment / surf->cpp);
assert(!surf->buffer);
surf->buffer = winsys->buffer_create(winsys, alignment,
PIPE_BUFFER_USAGE_PIXEL,
surf->pitch * surf->cpp * height);
if(!surf->buffer)
return -1;
return 0;
}
static void
intel_i915_surface_release(struct pipe_winsys *winsys, struct pipe_surface **s)
{
struct pipe_surface *surf = *s;
surf->refcount--;
if (surf->refcount == 0) {
if (surf->buffer)
pipe_buffer_reference(winsys, &surf->buffer, NULL);
free(surf);
}
*s = NULL;
}
static const char *
intel_get_name( struct pipe_winsys *winsys )
{
return "Intel/EGL/ttm";
}
static void
intel_fence_reference( struct pipe_winsys *sws,
struct pipe_fence_handle **ptr,
struct pipe_fence_handle *fence )
{
if (*ptr)
driFenceUnReference((struct _DriFenceObject **)ptr);
if (fence)
*ptr = (struct pipe_fence_handle *)driFenceReference((struct _DriFenceObject *)fence);
}
static int
intel_fence_signalled( struct pipe_winsys *sws,
struct pipe_fence_handle *fence,
unsigned flag )
{
return driFenceSignaled((struct _DriFenceObject *)fence, flag);
}
static int
intel_fence_finish( struct pipe_winsys *sws,
struct pipe_fence_handle *fence,
unsigned flag )
{
/* JB: Lets allways lazy wait */
return driFenceFinish((struct _DriFenceObject *)fence, flag, 1);
}
struct pipe_winsys *
intel_create_pipe_winsys( int fd, struct _DriFreeSlabManager *fMan )
{
struct intel_pipe_winsys *iws = CALLOC_STRUCT( intel_pipe_winsys );
/* Fill in this struct with callbacks that pipe will need to
* communicate with the window system, buffer manager, etc.
*
* Pipe would be happy with a malloc based memory manager, but
* the SwapBuffers implementation in this winsys driver requires
* that rendering be done to an appropriate _DriBufferObject.
*/
iws->winsys.buffer_create = intel_buffer_create;
iws->winsys.user_buffer_create = intel_user_buffer_create;
iws->winsys.buffer_map = intel_buffer_map;
iws->winsys.buffer_unmap = intel_buffer_unmap;
iws->winsys.buffer_destroy = intel_buffer_destroy;
iws->winsys.flush_frontbuffer = intel_flush_frontbuffer;
iws->winsys.get_name = intel_get_name;
iws->winsys.surface_alloc = intel_i915_surface_alloc;
iws->winsys.surface_alloc_storage = intel_i915_surface_alloc_storage;
iws->winsys.surface_release = intel_i915_surface_release;
iws->winsys.fence_reference = intel_fence_reference;
iws->winsys.fence_signalled = intel_fence_signalled;
iws->winsys.fence_finish = intel_fence_finish;
if (fd)
iws->regionPool = driSlabPoolInit(fd,
DRM_BO_FLAG_READ |
DRM_BO_FLAG_WRITE |
DRM_BO_FLAG_MEM_TT,
DRM_BO_FLAG_READ |
DRM_BO_FLAG_WRITE |
DRM_BO_FLAG_MEM_TT,
64, 6, 16, 4096, 0,
fMan);
return &iws->winsys;
}
void
intel_destroy_pipe_winsys( struct pipe_winsys *winsys )
{
struct intel_pipe_winsys *iws = intel_pipe_winsys(winsys);
if (iws->regionPool) {
driPoolTakeDown(iws->regionPool);
}
free(iws);
}
@@ -0,0 +1,82 @@
/**************************************************************************
*
* 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 "intel_context.h"
#include "intel_winsys.h"
#include "pipe/p_defines.h"
#include "pipe/p_util.h"
#include "pipe/p_format.h"
#include "softpipe/sp_winsys.h"
struct intel_softpipe_winsys {
struct softpipe_winsys sws;
struct intel_context *intel;
};
/**
* Return list of surface formats supported by this driver.
*/
static boolean
intel_is_format_supported(struct softpipe_winsys *sws,
enum pipe_format format)
{
switch(format) {
case PIPE_FORMAT_A8R8G8B8_UNORM:
case PIPE_FORMAT_R5G6B5_UNORM:
case PIPE_FORMAT_S8Z24_UNORM:
return TRUE;
default:
return FALSE;
}
}
/**
* Create rendering context which uses software rendering.
*/
struct pipe_context *
intel_create_softpipe( struct intel_context *intel,
struct pipe_winsys *winsys )
{
struct intel_softpipe_winsys *isws = CALLOC_STRUCT( intel_softpipe_winsys );
struct pipe_screen *screen = softpipe_create_screen(winsys);
/* Fill in this struct with callbacks that softpipe will need to
* communicate with the window system, buffer manager, etc.
*/
isws->sws.is_format_supported = intel_is_format_supported;
isws->intel = intel;
/* Create the softpipe context:
*/
return softpipe_create( screen, winsys, &isws->sws );
}
@@ -0,0 +1,953 @@
/**************************************************************************
*
* 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: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
* Keith Whitwell <keithw-at-tungstengraphics-dot-com>
*/
#include <xf86drm.h>
#include <stdlib.h>
#include "glthread.h"
#include "errno.h"
#include "ws_dri_bufmgr.h"
#include "string.h"
#include "imports.h"
#include "ws_dri_bufpool.h"
#include "ws_dri_fencemgr.h"
/*
* This lock is here to protect drmBO structs changing underneath us during a
* validate list call, since validatelist cannot take individiual locks for
* each drmBO. Validatelist takes this lock in write mode. Any access to an
* individual drmBO should take this lock in read mode, since in that case, the
* driBufferObject mutex will protect the access. Locking order is
* driBufferObject mutex - > this rw lock.
*/
_glthread_DECLARE_STATIC_MUTEX(bmMutex);
_glthread_DECLARE_STATIC_COND(bmCond);
static int kernelReaders = 0;
static int num_buffers = 0;
static int num_user_buffers = 0;
static drmBO *drmBOListBuf(void *iterator)
{
drmBONode *node;
drmMMListHead *l = (drmMMListHead *) iterator;
node = DRMLISTENTRY(drmBONode, l, head);
return node->buf;
}
static void *drmBOListIterator(drmBOList *list)
{
void *ret = list->list.next;
if (ret == &list->list)
return NULL;
return ret;
}
static void *drmBOListNext(drmBOList *list, void *iterator)
{
void *ret;
drmMMListHead *l = (drmMMListHead *) iterator;
ret = l->next;
if (ret == &list->list)
return NULL;
return ret;
}
static drmBONode *drmAddListItem(drmBOList *list, drmBO *item,
uint64_t arg0,
uint64_t arg1)
{
drmBONode *node;
drmMMListHead *l;
l = list->free.next;
if (l == &list->free) {
node = (drmBONode *) malloc(sizeof(*node));
if (!node) {
return NULL;
}
list->numCurrent++;
}
else {
DRMLISTDEL(l);
node = DRMLISTENTRY(drmBONode, l, head);
}
node->buf = item;
node->arg0 = arg0;
node->arg1 = arg1;
DRMLISTADD(&node->head, &list->list);
list->numOnList++;
return node;
}
static int drmAddValidateItem(drmBOList *list, drmBO *buf, uint64_t flags,
uint64_t mask, int *newItem)
{
drmBONode *node, *cur;
drmMMListHead *l;
*newItem = 0;
cur = NULL;
for (l = list->list.next; l != &list->list; l = l->next) {
node = DRMLISTENTRY(drmBONode, l, head);
if (node->buf == buf) {
cur = node;
break;
}
}
if (!cur) {
cur = drmAddListItem(list, buf, flags, mask);
if (!cur) {
return -ENOMEM;
}
*newItem = 1;
cur->arg0 = flags;
cur->arg1 = mask;
}
else {
uint64_t memFlags = cur->arg0 & flags & DRM_BO_MASK_MEM;
uint64_t accFlags = (cur->arg0 | flags) & ~DRM_BO_MASK_MEM;
if (mask & cur->arg1 & ~DRM_BO_MASK_MEM & (cur->arg0 ^ flags)) {
return -EINVAL;
}
cur->arg1 |= mask;
cur->arg0 = (cur->arg0 & ~mask) | ((memFlags | accFlags) & mask);
if (((cur->arg1 & DRM_BO_MASK_MEM) != 0) &&
(cur->arg0 & DRM_BO_MASK_MEM) == 0) {
return -EINVAL;
}
}
return 0;
}
static void drmBOFreeList(drmBOList *list)
{
drmBONode *node;
drmMMListHead *l;
l = list->list.next;
while(l != &list->list) {
DRMLISTDEL(l);
node = DRMLISTENTRY(drmBONode, l, head);
free(node);
l = list->list.next;
list->numCurrent--;
list->numOnList--;
}
l = list->free.next;
while(l != &list->free) {
DRMLISTDEL(l);
node = DRMLISTENTRY(drmBONode, l, head);
free(node);
l = list->free.next;
list->numCurrent--;
}
}
static int drmAdjustListNodes(drmBOList *list)
{
drmBONode *node;
drmMMListHead *l;
int ret = 0;
while(list->numCurrent < list->numTarget) {
node = (drmBONode *) malloc(sizeof(*node));
if (!node) {
ret = -ENOMEM;
break;
}
list->numCurrent++;
DRMLISTADD(&node->head, &list->free);
}
while(list->numCurrent > list->numTarget) {
l = list->free.next;
if (l == &list->free)
break;
DRMLISTDEL(l);
node = DRMLISTENTRY(drmBONode, l, head);
free(node);
list->numCurrent--;
}
return ret;
}
static int drmBOCreateList(int numTarget, drmBOList *list)
{
DRMINITLISTHEAD(&list->list);
DRMINITLISTHEAD(&list->free);
list->numTarget = numTarget;
list->numCurrent = 0;
list->numOnList = 0;
return drmAdjustListNodes(list);
}
static int drmBOResetList(drmBOList *list)
{
drmMMListHead *l;
int ret;
ret = drmAdjustListNodes(list);
if (ret)
return ret;
l = list->list.next;
while (l != &list->list) {
DRMLISTDEL(l);
DRMLISTADD(l, &list->free);
list->numOnList--;
l = list->list.next;
}
return drmAdjustListNodes(list);
}
void driWriteLockKernelBO(void)
{
_glthread_LOCK_MUTEX(bmMutex);
while(kernelReaders != 0)
_glthread_COND_WAIT(bmCond, bmMutex);
}
void driWriteUnlockKernelBO(void)
{
_glthread_UNLOCK_MUTEX(bmMutex);
}
void driReadLockKernelBO(void)
{
_glthread_LOCK_MUTEX(bmMutex);
kernelReaders++;
_glthread_UNLOCK_MUTEX(bmMutex);
}
void driReadUnlockKernelBO(void)
{
_glthread_LOCK_MUTEX(bmMutex);
if (--kernelReaders == 0)
_glthread_COND_BROADCAST(bmCond);
_glthread_UNLOCK_MUTEX(bmMutex);
}
/*
* TODO: Introduce fence pools in the same way as
* buffer object pools.
*/
typedef struct _DriBufferObject
{
DriBufferPool *pool;
_glthread_Mutex mutex;
int refCount;
const char *name;
uint64_t flags;
unsigned hint;
unsigned alignment;
unsigned createdByReference;
void *private;
/* user-space buffer: */
unsigned userBuffer;
void *userData;
unsigned userSize;
} DriBufferObject;
typedef struct _DriBufferList {
drmBOList drmBuffers; /* List of kernel buffers needing validation */
drmBOList driBuffers; /* List of user-space buffers needing validation */
} DriBufferList;
void
bmError(int val, const char *file, const char *function, int line)
{
_mesa_printf("Fatal video memory manager error \"%s\".\n"
"Check kernel logs or set the LIBGL_DEBUG\n"
"environment variable to \"verbose\" for more info.\n"
"Detected in file %s, line %d, function %s.\n",
strerror(-val), file, line, function);
#ifndef NDEBUG
abort();
#else
abort();
#endif
}
extern drmBO *
driBOKernel(struct _DriBufferObject *buf)
{
drmBO *ret;
driReadLockKernelBO();
_glthread_LOCK_MUTEX(buf->mutex);
assert(buf->private != NULL);
ret = buf->pool->kernel(buf->pool, buf->private);
if (!ret)
BM_CKFATAL(-EINVAL);
_glthread_UNLOCK_MUTEX(buf->mutex);
driReadUnlockKernelBO();
return ret;
}
void
driBOWaitIdle(struct _DriBufferObject *buf, int lazy)
{
/*
* This function may block. Is it sane to keep the mutex held during
* that time??
*/
_glthread_LOCK_MUTEX(buf->mutex);
BM_CKFATAL(buf->pool->waitIdle(buf->pool, buf->private, &buf->mutex, lazy));
_glthread_UNLOCK_MUTEX(buf->mutex);
}
void *
driBOMap(struct _DriBufferObject *buf, unsigned flags, unsigned hint)
{
void *virtual;
int retval;
if (buf->userBuffer) {
return buf->userData;
}
_glthread_LOCK_MUTEX(buf->mutex);
assert(buf->private != NULL);
retval = buf->pool->map(buf->pool, buf->private, flags, hint,
&buf->mutex, &virtual);
_glthread_UNLOCK_MUTEX(buf->mutex);
return retval == 0 ? virtual : NULL;
}
void
driBOUnmap(struct _DriBufferObject *buf)
{
if (buf->userBuffer)
return;
assert(buf->private != NULL);
_glthread_LOCK_MUTEX(buf->mutex);
BM_CKFATAL(buf->pool->unmap(buf->pool, buf->private));
_glthread_UNLOCK_MUTEX(buf->mutex);
}
unsigned long
driBOOffset(struct _DriBufferObject *buf)
{
unsigned long ret;
assert(buf->private != NULL);
_glthread_LOCK_MUTEX(buf->mutex);
ret = buf->pool->offset(buf->pool, buf->private);
_glthread_UNLOCK_MUTEX(buf->mutex);
return ret;
}
unsigned long
driBOPoolOffset(struct _DriBufferObject *buf)
{
unsigned long ret;
assert(buf->private != NULL);
_glthread_LOCK_MUTEX(buf->mutex);
ret = buf->pool->poolOffset(buf->pool, buf->private);
_glthread_UNLOCK_MUTEX(buf->mutex);
return ret;
}
uint64_t
driBOFlags(struct _DriBufferObject *buf)
{
uint64_t ret;
assert(buf->private != NULL);
driReadLockKernelBO();
_glthread_LOCK_MUTEX(buf->mutex);
ret = buf->pool->flags(buf->pool, buf->private);
_glthread_UNLOCK_MUTEX(buf->mutex);
driReadUnlockKernelBO();
return ret;
}
struct _DriBufferObject *
driBOReference(struct _DriBufferObject *buf)
{
_glthread_LOCK_MUTEX(buf->mutex);
if (++buf->refCount == 1) {
_glthread_UNLOCK_MUTEX(buf->mutex);
BM_CKFATAL(-EINVAL);
}
_glthread_UNLOCK_MUTEX(buf->mutex);
return buf;
}
void
driBOUnReference(struct _DriBufferObject *buf)
{
int tmp;
if (!buf)
return;
_glthread_LOCK_MUTEX(buf->mutex);
tmp = --buf->refCount;
if (!tmp) {
_glthread_UNLOCK_MUTEX(buf->mutex);
if (buf->private) {
if (buf->createdByReference)
buf->pool->unreference(buf->pool, buf->private);
else
buf->pool->destroy(buf->pool, buf->private);
}
if (buf->userBuffer)
num_user_buffers--;
else
num_buffers--;
free(buf);
} else
_glthread_UNLOCK_MUTEX(buf->mutex);
}
int
driBOData(struct _DriBufferObject *buf,
unsigned size, const void *data,
DriBufferPool *newPool,
uint64_t flags)
{
void *virtual = NULL;
int newBuffer;
int retval = 0;
struct _DriBufferPool *pool;
assert(!buf->userBuffer); /* XXX just do a memcpy? */
_glthread_LOCK_MUTEX(buf->mutex);
pool = buf->pool;
if (pool == NULL && newPool != NULL) {
buf->pool = newPool;
pool = newPool;
}
if (newPool == NULL)
newPool = pool;
if (!pool->create) {
_mesa_error(NULL, GL_INVALID_OPERATION,
"driBOData called on invalid buffer\n");
BM_CKFATAL(-EINVAL);
}
newBuffer = (!buf->private || pool != newPool ||
pool->size(pool, buf->private) < size);
if (!flags)
flags = buf->flags;
if (newBuffer) {
if (buf->createdByReference) {
_mesa_error(NULL, GL_INVALID_OPERATION,
"driBOData requiring resizing called on "
"shared buffer.\n");
BM_CKFATAL(-EINVAL);
}
if (buf->private)
buf->pool->destroy(buf->pool, buf->private);
pool = newPool;
buf->pool = newPool;
buf->private = pool->create(pool, size, flags, DRM_BO_HINT_DONT_FENCE,
buf->alignment);
if (!buf->private)
retval = -ENOMEM;
if (retval == 0)
retval = pool->map(pool, buf->private,
DRM_BO_FLAG_WRITE,
DRM_BO_HINT_DONT_BLOCK, &buf->mutex, &virtual);
} else if (pool->map(pool, buf->private, DRM_BO_FLAG_WRITE,
DRM_BO_HINT_DONT_BLOCK, &buf->mutex, &virtual)) {
/*
* Buffer is busy. need to create a new one.
*/
void *newBuf;
newBuf = pool->create(pool, size, flags, DRM_BO_HINT_DONT_FENCE,
buf->alignment);
if (newBuf) {
buf->pool->destroy(buf->pool, buf->private);
buf->private = newBuf;
}
retval = pool->map(pool, buf->private,
DRM_BO_FLAG_WRITE, 0, &buf->mutex, &virtual);
} else {
uint64_t flag_diff = flags ^ buf->flags;
/*
* We might need to change buffer flags.
*/
if (flag_diff){
assert(pool->setStatus != NULL);
BM_CKFATAL(pool->unmap(pool, buf->private));
BM_CKFATAL(pool->setStatus(pool, buf->private, flag_diff,
buf->flags));
if (!data)
goto out;
retval = pool->map(pool, buf->private,
DRM_BO_FLAG_WRITE, 0, &buf->mutex, &virtual);
}
}
if (retval == 0) {
if (data)
memcpy(virtual, data, size);
BM_CKFATAL(pool->unmap(pool, buf->private));
}
out:
_glthread_UNLOCK_MUTEX(buf->mutex);
return retval;
}
void
driBOSubData(struct _DriBufferObject *buf,
unsigned long offset, unsigned long size, const void *data)
{
void *virtual;
assert(!buf->userBuffer); /* XXX just do a memcpy? */
_glthread_LOCK_MUTEX(buf->mutex);
if (size && data) {
BM_CKFATAL(buf->pool->map(buf->pool, buf->private,
DRM_BO_FLAG_WRITE, 0, &buf->mutex,
&virtual));
memcpy((unsigned char *) virtual + offset, data, size);
BM_CKFATAL(buf->pool->unmap(buf->pool, buf->private));
}
_glthread_UNLOCK_MUTEX(buf->mutex);
}
void
driBOGetSubData(struct _DriBufferObject *buf,
unsigned long offset, unsigned long size, void *data)
{
void *virtual;
assert(!buf->userBuffer); /* XXX just do a memcpy? */
_glthread_LOCK_MUTEX(buf->mutex);
if (size && data) {
BM_CKFATAL(buf->pool->map(buf->pool, buf->private,
DRM_BO_FLAG_READ, 0, &buf->mutex, &virtual));
memcpy(data, (unsigned char *) virtual + offset, size);
BM_CKFATAL(buf->pool->unmap(buf->pool, buf->private));
}
_glthread_UNLOCK_MUTEX(buf->mutex);
}
void
driBOSetReferenced(struct _DriBufferObject *buf,
unsigned long handle)
{
_glthread_LOCK_MUTEX(buf->mutex);
if (buf->private != NULL) {
_mesa_error(NULL, GL_INVALID_OPERATION,
"Invalid buffer for setReferenced\n");
BM_CKFATAL(-EINVAL);
}
if (buf->pool->reference == NULL) {
_mesa_error(NULL, GL_INVALID_OPERATION,
"Invalid buffer pool for setReferenced\n");
BM_CKFATAL(-EINVAL);
}
buf->private = buf->pool->reference(buf->pool, handle);
if (!buf->private) {
_mesa_error(NULL, GL_OUT_OF_MEMORY,
"Invalid buffer pool for setStatic\n");
BM_CKFATAL(-ENOMEM);
}
buf->createdByReference = GL_TRUE;
buf->flags = buf->pool->kernel(buf->pool, buf->private)->flags;
_glthread_UNLOCK_MUTEX(buf->mutex);
}
int
driGenBuffers(struct _DriBufferPool *pool,
const char *name,
unsigned n,
struct _DriBufferObject *buffers[],
unsigned alignment, uint64_t flags, unsigned hint)
{
struct _DriBufferObject *buf;
int i;
flags = (flags) ? flags : DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_MEM_VRAM |
DRM_BO_FLAG_MEM_LOCAL | DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE;
++num_buffers;
assert(pool);
for (i = 0; i < n; ++i) {
buf = (struct _DriBufferObject *) calloc(1, sizeof(*buf));
if (!buf)
return -ENOMEM;
_glthread_INIT_MUTEX(buf->mutex);
_glthread_LOCK_MUTEX(buf->mutex);
buf->refCount = 1;
buf->flags = flags;
buf->hint = hint;
buf->name = name;
buf->alignment = alignment;
buf->pool = pool;
buf->createdByReference = 0;
_glthread_UNLOCK_MUTEX(buf->mutex);
buffers[i] = buf;
}
return 0;
}
void
driGenUserBuffer(struct _DriBufferPool *pool,
const char *name,
struct _DriBufferObject **buffers,
void *ptr, unsigned bytes)
{
const unsigned alignment = 1, flags = 0, hint = 0;
--num_buffers; /* JB: is inced in GenBuffes */
driGenBuffers(pool, name, 1, buffers, alignment, flags, hint);
++num_user_buffers;
(*buffers)->userBuffer = 1;
(*buffers)->userData = ptr;
(*buffers)->userSize = bytes;
}
void
driDeleteBuffers(unsigned n, struct _DriBufferObject *buffers[])
{
int i;
for (i = 0; i < n; ++i) {
driBOUnReference(buffers[i]);
}
}
void
driInitBufMgr(int fd)
{
;
}
/*
* Note that lists are per-context and don't need mutex protection.
*/
struct _DriBufferList *
driBOCreateList(int target)
{
struct _DriBufferList *list = calloc(sizeof(*list), 1);
BM_CKFATAL(drmBOCreateList(target, &list->drmBuffers));
BM_CKFATAL(drmBOCreateList(target, &list->driBuffers));
return list;
}
int
driBOResetList(struct _DriBufferList * list)
{
int ret;
ret = drmBOResetList(&list->drmBuffers);
if (ret)
return ret;
ret = drmBOResetList(&list->driBuffers);
return ret;
}
void
driBOFreeList(struct _DriBufferList * list)
{
drmBOFreeList(&list->drmBuffers);
drmBOFreeList(&list->driBuffers);
free(list);
}
/*
* Copied from libdrm, because it is needed by driAddValidateItem.
*/
static drmBONode *
driAddListItem(drmBOList * list, drmBO * item,
uint64_t arg0, uint64_t arg1)
{
drmBONode *node;
drmMMListHead *l;
l = list->free.next;
if (l == &list->free) {
node = (drmBONode *) malloc(sizeof(*node));
if (!node) {
return NULL;
}
list->numCurrent++;
} else {
DRMLISTDEL(l);
node = DRMLISTENTRY(drmBONode, l, head);
}
memset(&node->bo_arg, 0, sizeof(node->bo_arg));
node->buf = item;
node->arg0 = arg0;
node->arg1 = arg1;
DRMLISTADDTAIL(&node->head, &list->list);
list->numOnList++;
return node;
}
/*
* Slightly modified version compared to the libdrm version.
* This one returns the list index of the buffer put on the list.
*/
static int
driAddValidateItem(drmBOList * list, drmBO * buf, uint64_t flags,
uint64_t mask, int *itemLoc,
struct _drmBONode **pnode)
{
drmBONode *node, *cur;
drmMMListHead *l;
int count = 0;
cur = NULL;
for (l = list->list.next; l != &list->list; l = l->next) {
node = DRMLISTENTRY(drmBONode, l, head);
if (node->buf == buf) {
cur = node;
break;
}
count++;
}
if (!cur) {
cur = driAddListItem(list, buf, flags, mask);
if (!cur)
return -ENOMEM;
cur->arg0 = flags;
cur->arg1 = mask;
} else {
uint64_t memFlags = cur->arg0 & flags & DRM_BO_MASK_MEM;
uint64_t accFlags = (cur->arg0 | flags) & ~DRM_BO_MASK_MEM;
if (mask & cur->arg1 & ~DRM_BO_MASK_MEM & (cur->arg0 ^ flags)) {
return -EINVAL;
}
cur->arg1 |= mask;
cur->arg0 = (cur->arg0 & ~mask) | ((memFlags | accFlags) & mask);
if (((cur->arg1 & DRM_BO_MASK_MEM) != 0) &&
(cur->arg0 & DRM_BO_MASK_MEM) == 0) {
return -EINVAL;
}
}
*itemLoc = count;
*pnode = cur;
return 0;
}
void
driBOAddListItem(struct _DriBufferList * list, struct _DriBufferObject *buf,
uint64_t flags, uint64_t mask, int *itemLoc,
struct _drmBONode **node)
{
int newItem;
_glthread_LOCK_MUTEX(buf->mutex);
BM_CKFATAL(driAddValidateItem(&list->drmBuffers,
buf->pool->kernel(buf->pool, buf->private),
flags, mask, itemLoc, node));
BM_CKFATAL(drmAddValidateItem(&list->driBuffers, (drmBO *) buf,
flags, mask, &newItem));
if (newItem)
buf->refCount++;
_glthread_UNLOCK_MUTEX(buf->mutex);
}
drmBOList *driGetdrmBOList(struct _DriBufferList *list)
{
driWriteLockKernelBO();
return &list->drmBuffers;
}
void driPutdrmBOList(struct _DriBufferList *list)
{
driWriteUnlockKernelBO();
}
void
driBOFence(struct _DriBufferObject *buf, struct _DriFenceObject *fence)
{
_glthread_LOCK_MUTEX(buf->mutex);
if (buf->pool->fence)
BM_CKFATAL(buf->pool->fence(buf->pool, buf->private, fence));
_glthread_UNLOCK_MUTEX(buf->mutex);
}
void
driBOUnrefUserList(struct _DriBufferList *list)
{
struct _DriBufferObject *buf;
void *curBuf;
curBuf = drmBOListIterator(&list->driBuffers);
while (curBuf) {
buf = (struct _DriBufferObject *)drmBOListBuf(curBuf);
driBOUnReference(buf);
curBuf = drmBOListNext(&list->driBuffers, curBuf);
}
}
struct _DriFenceObject *
driBOFenceUserList(struct _DriFenceMgr *mgr,
struct _DriBufferList *list, const char *name,
drmFence *kFence)
{
struct _DriFenceObject *fence;
struct _DriBufferObject *buf;
void *curBuf;
fence = driFenceCreate(mgr, kFence->fence_class, kFence->type,
kFence, sizeof(*kFence));
curBuf = drmBOListIterator(&list->driBuffers);
/*
* User-space fencing callbacks.
*/
while (curBuf) {
buf = (struct _DriBufferObject *) drmBOListBuf(curBuf);
driBOFence(buf, fence);
driBOUnReference(buf);
curBuf = drmBOListNext(&list->driBuffers, curBuf);
}
driBOResetList(list);
return fence;
}
void
driBOValidateUserList(struct _DriBufferList * list)
{
void *curBuf;
struct _DriBufferObject *buf;
curBuf = drmBOListIterator(&list->driBuffers);
/*
* User-space validation callbacks.
*/
while (curBuf) {
buf = (struct _DriBufferObject *) drmBOListBuf(curBuf);
_glthread_LOCK_MUTEX(buf->mutex);
if (buf->pool->validate)
BM_CKFATAL(buf->pool->validate(buf->pool, buf->private, &buf->mutex));
_glthread_UNLOCK_MUTEX(buf->mutex);
curBuf = drmBOListNext(&list->driBuffers, curBuf);
}
}
void
driPoolTakeDown(struct _DriBufferPool *pool)
{
pool->takeDown(pool);
}
unsigned long
driBOSize(struct _DriBufferObject *buf)
{
unsigned long size;
_glthread_LOCK_MUTEX(buf->mutex);
size = buf->pool->size(buf->pool, buf->private);
_glthread_UNLOCK_MUTEX(buf->mutex);
return size;
}
drmBOList *driBOGetDRMBuffers(struct _DriBufferList *list)
{
return &list->drmBuffers;
}
drmBOList *driBOGetDRIBuffers(struct _DriBufferList *list)
{
return &list->driBuffers;
}
@@ -0,0 +1,138 @@
/**************************************************************************
*
* 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: Thomas Hellström <thomas-at-tungstengraphics-dot-com>
* Keith Whitwell <keithw-at-tungstengraphics-dot-com>
*/
#ifndef _PSB_BUFMGR_H_
#define _PSB_BUFMGR_H_
#include <xf86mm.h>
#include "i915_drm.h"
#include "ws_dri_fencemgr.h"
typedef struct _drmBONode
{
drmMMListHead head;
drmBO *buf;
struct drm_i915_op_arg bo_arg;
uint64_t arg0;
uint64_t arg1;
} drmBONode;
typedef struct _drmBOList {
unsigned numTarget;
unsigned numCurrent;
unsigned numOnList;
drmMMListHead list;
drmMMListHead free;
} drmBOList;
struct _DriFenceObject;
struct _DriBufferObject;
struct _DriBufferPool;
struct _DriBufferList;
/*
* Return a pointer to the libdrm buffer object this DriBufferObject
* uses.
*/
extern drmBO *driBOKernel(struct _DriBufferObject *buf);
extern void *driBOMap(struct _DriBufferObject *buf, unsigned flags,
unsigned hint);
extern void driBOUnmap(struct _DriBufferObject *buf);
extern unsigned long driBOOffset(struct _DriBufferObject *buf);
extern unsigned long driBOPoolOffset(struct _DriBufferObject *buf);
extern uint64_t driBOFlags(struct _DriBufferObject *buf);
extern struct _DriBufferObject *driBOReference(struct _DriBufferObject *buf);
extern void driBOUnReference(struct _DriBufferObject *buf);
extern int driBOData(struct _DriBufferObject *r_buf,
unsigned size, const void *data,
struct _DriBufferPool *pool, uint64_t flags);
extern void driBOSubData(struct _DriBufferObject *buf,
unsigned long offset, unsigned long size,
const void *data);
extern void driBOGetSubData(struct _DriBufferObject *buf,
unsigned long offset, unsigned long size,
void *data);
extern int driGenBuffers(struct _DriBufferPool *pool,
const char *name,
unsigned n,
struct _DriBufferObject *buffers[],
unsigned alignment, uint64_t flags, unsigned hint);
extern void driGenUserBuffer(struct _DriBufferPool *pool,
const char *name,
struct _DriBufferObject *buffers[],
void *ptr, unsigned bytes);
extern void driDeleteBuffers(unsigned n, struct _DriBufferObject *buffers[]);
extern void driInitBufMgr(int fd);
extern struct _DriBufferList *driBOCreateList(int target);
extern int driBOResetList(struct _DriBufferList * list);
extern void driBOAddListItem(struct _DriBufferList * list,
struct _DriBufferObject *buf,
uint64_t flags, uint64_t mask, int *itemLoc,
struct _drmBONode **node);
extern void driBOValidateList(int fd, struct _DriBufferList * list);
extern void driBOFreeList(struct _DriBufferList * list);
extern struct _DriFenceObject *driBOFenceUserList(struct _DriFenceMgr *mgr,
struct _DriBufferList *list,
const char *name,
drmFence *kFence);
extern void driBOUnrefUserList(struct _DriBufferList *list);
extern void driBOValidateUserList(struct _DriBufferList * list);
extern drmBOList *driGetdrmBOList(struct _DriBufferList *list);
extern void driPutdrmBOList(struct _DriBufferList *list);
extern void driBOFence(struct _DriBufferObject *buf,
struct _DriFenceObject *fence);
extern void driPoolTakeDown(struct _DriBufferPool *pool);
extern void driBOSetReferenced(struct _DriBufferObject *buf,
unsigned long handle);
unsigned long driBOSize(struct _DriBufferObject *buf);
extern void driBOWaitIdle(struct _DriBufferObject *buf, int lazy);
extern void driPoolTakeDown(struct _DriBufferPool *pool);
extern void driReadLockKernelBO(void);
extern void driReadUnlockKernelBO(void);
extern void driWriteLockKernelBO(void);
extern void driWriteUnlockKernelBO(void);
/*
* For debugging purposes.
*/
extern drmBOList *driBOGetDRMBuffers(struct _DriBufferList *list);
extern drmBOList *driBOGetDRIBuffers(struct _DriBufferList *list);
#endif

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