patch to import Jon Smirl's work from Bitkeeper

This commit is contained in:
Brian Paul 2003-08-22 20:11:43 +00:00
parent 1a84876d79
commit 5df82c82bd
171 changed files with 57644 additions and 2518 deletions

View File

@ -664,6 +664,22 @@ linux-osmesa32:
"GL_LIB_DEPS = -lm -lpthread" \
"APP_LIB_DEPS = -lOSMesa32 -lGL"
# standalone Mesa -- embedded
# change -g to -O3 for non-debug
linux-solo:
$(MAKE) $(MFLAGS) -f Makefile.X11 targets \
"LIBMESA = mesa.a" \
"GLU_LIB = libGLU.so" \
"GLUT_LIB = libglut.so" \
"CC = gcc" \
"CXX = g++" \
"CFLAGS = -g -std=c99 -pedantic -fPIC -ffast-math -D_POSIX_SOURCE -D_POSIX_C_SOURCE=199309L -D_SVID_SOURCE -D_BSD_SOURCE" \
"CXXFLAGS = $(CFLAGS)" \
"GL_LIB_DEPS = -lm -lpthread" \
"GLU_LIB_DEPS = -L$(TOP)/lib -lGL -lm -Wl,-rpath,$(TOP)/lib" \
"GLUT_LIB_DEPS = -L$(TOP)/lib -lGLU -lGL -lm -Wl,-rpath,$(TOP)/lib" \
"APP_LIB_DEPS = -L$(TOP)/lib -lglut -lGLU -lGL -lm -lpthread -Wl,-rpath,$(TOP)/lib"
# May want to add these CFLAGS for better performance under LynxOS and GCC:
# -fPIC -O2 -ansi -pedantic -mieee-fp -DUSE_XSHM -funroll-loops
# -fexpensive-optimizations -fomit-frame-pointer -ffast-math

View File

@ -1,4 +1,4 @@
# $Id: Makefile.X11,v 1.79 2003/08/22 18:06:59 brianp Exp $
# $Id: Makefile.X11,v 1.80 2003/08/22 20:11:43 brianp Exp $
# Mesa 3-D graphics library
# Version: 5.1
@ -73,6 +73,7 @@ default:
@echo " make linux-sparc-ultra for Linux with UltraSparc optimizations"
@echo " make linux-osmesa16 for 16-bit/channel OSMesa"
@echo " make linux-osmesa32 for 32-bit/channel OSMesa"
@echo " make linux-solo for Linux standalone with dri drivers"
@echo " make linux-icc for Linux with the Intel C/C++ compiler"
@echo " make lynxos for LynxOS systems with GCC"
@echo " make mklinux for Linux on Power Macintosh"
@ -227,21 +228,47 @@ linux-osmesa16 linux-osmesa32:
if [ -d src ] ; then touch src/depend ; fi
if [ -d src ] ; then cd src ; $(MAKE) -f Makefile.OSMesa16 $@ ; fi
linux-solo:
-mkdir lib
if [ -d src/mesa ] ; then touch src/mesa/depend ; fi
if [ -d src/glx/mini ] ; then touch src/glx/mini/depend ; fi
if [ -d src/glu/mini ] ; then touch src/glu/mini/depend ; fi
if [ -d src/glut/mini ] ; then touch src/glut/mini/depend ; fi
if [ -d src/mesa ] ; then cd src/mesa ; $(MAKE) -f Makefile.X11 $@ ; fi
if [ -d src/mesa/drivers/dri/r200 ] ; then cd src/mesa/drivers/dri/r200 ; $(MAKE) -f Makefile.X11 $@ ; fi
if [ -d src/mesa/drivers/dri/r128 ] ; then cd src/mesa/drivers/dri/r128 ; $(MAKE) -f Makefile.X11 $@ ; fi
if [ -d src/mesa/drivers/dri/radeon ] ; then cd src/mesa/drivers/dri/radeon ; $(MAKE) -f Makefile.X11 $@ ; fi
if [ -d src/mesa/drivers/dri/mga ] ; then cd src/mesa/drivers/dri/mga ; $(MAKE) -f Makefile.X11 $@ ; fi
if [ -d src/mesa/drivers/dri/fb ] ; then cd src/mesa/drivers/dri/fb ; $(MAKE) -f Makefile.X11 $@ ; fi
if [ -d src/glx/mini ] ; then cd src/glx/mini ; $(MAKE) -f Makefile.X11 $@ ; fi
if [ -d src/glu/mini ] ; then cd src/glu/mini ; $(MAKE) -f Makefile.X11 $@ ; fi
if [ -d src/glut/mini ] ; then cd src/glut/mini ; $(MAKE) -f Makefile.X11 $@ ; fi
if [ -d progs/demos ] ; then cd progs/miniglx ; $(MAKE) -f Makefile.X11 $@ ; fi
if [ -d progs/demos ] ; then cd progs/tests ; $(MAKE) -f Makefile.X11 $@ ; fi
if [ -d progs/demos ] ; then cd progs/demos ; $(MAKE) -f Makefile.X11 $@ ; fi
if [ -d progs/xdemos ] ; then cd progs/xdemos ; $(MAKE) -f Makefile.X11 $@ ; fi
if [ -d progs/samples ] ; then cd progs/samples ; $(MAKE) -f Makefile.X11 $@ ; fi
if [ -d progs/redbook ] ; then cd progs/redbook ; $(MAKE) -f Makefile.X11 $@ ; fi
# Remove .o files, emacs backup files, etc.
clean:
-rm -f src/mesa/*/*.o
-rm -f src/mesa/drivers/*/*.o
-rm -f src/mesa/drivers/*/*.o
-rm -f src/mesa/drivers/*/*/*.o
-rm -f src/mesa/drivers/*/*/*/*.o
-rm -f include/*~
-rm -f include/GL/*~
-rm -f src/glu/mesa/*.o src/glu/mesa/*~ src-glu/*.a
-rm -f src/glu/sgi/*/*.o src/glu/sgi/*/*/*.o
-rm -f src/glut/glx/*.o
-rm -f src/miniglx/*.o
-rm -f src/miniglu/*.o
-rm -f src/miniglut/*.o
-rm -f progs/demos/*.o
-rm -f progs/redbook/*.o progs/redbook/*~
-rm -f progs/xdemos/*.o progs/xdemos/*~
-rm -f progs/samples/*.o progs/samples/*~
-rm -f progs/tests/*.o progs/tests/*~
-rm -f src/glw/*.o
# Remove everything that can be remade

65
src/glu/mini/Makefile.X11 Normal file
View File

@ -0,0 +1,65 @@
TOP = ../../..
default: linux-solo
LIBDIR = $(TOP)/lib
INCLUDES = -I$(TOP)/include
CFLAGS = -c -g $(INCLUDES) -MD
SOURCES = glu.c \
mipmap.c \
nurbs.c \
polytest.c \
project.c \
quadric.c \
tess.c \
tesselat.c
OBJS = $(SOURCES:.c=.o)
LIBS=-L$(TOP)/lib -lGL -lm
##### RULES #####
.c.o:
$(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
.S.o:
$(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
##### TARGETS #####
targets: depend libGLU.so.1.1 install
libGLU.so.1.1: $(OBJS) Makefile.X11
gcc -shared -Wl,-soname,libGLU.so -Wl,-Bsymbolic $(OBJS) $(LIBS) -o $@
install:
rm -f $(TOP)/lib/libGLU.so*
install -D libGLU.so.1.1 $(TOP)/lib/libGLU.so.1.1
ln -s libGLU.so.1.1 $(TOP)/lib/libGLU.so.1
ln -s libGLU.so.1 $(TOP)/lib/libGLU.so
# Run 'make -f Makefile.X11 dep' to update the dependencies if you change
# what's included by any source file.
depend: $(SOURCES)
makedepend -fdepend -Y $(INCLUDES) \
$(SOURCES)
# Emacs tags
tags:
etags `find . -name \*.[ch]` `find ../include`
# Remove .o and backup files
clean:
-rm -f *.o *~ *.o *~ *.so
include $(TOP)/Make-config
include depend

55
src/glu/mini/all.h Normal file
View File

@ -0,0 +1,55 @@
/* $Id: all.h,v 1.2 2003/08/22 20:11:43 brianp Exp $ */
/*
* Mesa 3-D graphics library
* Version: 3.3
* Copyright (C) 1995-2000 Brian Paul
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* This file includes all .h files needed for the GLU source code for
* the purpose of precompiled headers.
*
* If the preprocessor symbol PCH is defined at compile time then each
* of the .c files will #include "all.h" only, instead of a bunch of
* individual .h files.
*/
#ifndef GLU_ALL_H
#define GLU_ALL_H
#ifndef PC_HEADER
This is an error. all.h should be included only if PCH is defined.
#endif
#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "GL/gl.h"
#include "GL/glu.h"
#include "gluP.h"
#include "nurbs.h"
#include "tess.h"
#endif /*GLU_ALL_H */

417
src/glu/mini/glu.c Normal file
View File

@ -0,0 +1,417 @@
/* $Id: glu.c,v 1.2 2003/08/22 20:11:43 brianp Exp $ */
/*
* Mesa 3-D graphics library
* Version: 3.5
* Copyright (C) 1995-2001 Brian Paul
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifdef PC_HEADER
#include "all.h"
#else
#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "gluP.h"
#endif
/*
* Miscellaneous utility functions
*/
#ifndef M_PI
#define M_PI 3.1415926536
#endif
#define EPS 0.00001
#ifndef GLU_INCOMPATIBLE_GL_VERSION
#define GLU_INCOMPATIBLE_GL_VERSION 100903
#endif
void GLAPIENTRY
gluLookAt(GLdouble eyex, GLdouble eyey, GLdouble eyez,
GLdouble centerx, GLdouble centery, GLdouble centerz,
GLdouble upx, GLdouble upy, GLdouble upz)
{
GLfloat m[16];
GLfloat x[3], y[3], z[3];
GLfloat mag;
/* Make rotation matrix */
/* Z vector */
z[0] = eyex - centerx;
z[1] = eyey - centery;
z[2] = eyez - centerz;
mag = sqrt(z[0] * z[0] + z[1] * z[1] + z[2] * z[2]);
if (mag) { /* mpichler, 19950515 */
z[0] /= mag;
z[1] /= mag;
z[2] /= mag;
}
/* Y vector */
y[0] = upx;
y[1] = upy;
y[2] = upz;
/* X vector = Y cross Z */
x[0] = y[1] * z[2] - y[2] * z[1];
x[1] = -y[0] * z[2] + y[2] * z[0];
x[2] = y[0] * z[1] - y[1] * z[0];
/* Recompute Y = Z cross X */
y[0] = z[1] * x[2] - z[2] * x[1];
y[1] = -z[0] * x[2] + z[2] * x[0];
y[2] = z[0] * x[1] - z[1] * x[0];
/* mpichler, 19950515 */
/* cross product gives area of parallelogram, which is < 1.0 for
* non-perpendicular unit-length vectors; so normalize x, y here
*/
mag = sqrt(x[0] * x[0] + x[1] * x[1] + x[2] * x[2]);
if (mag) {
x[0] /= mag;
x[1] /= mag;
x[2] /= mag;
}
mag = sqrt(y[0] * y[0] + y[1] * y[1] + y[2] * y[2]);
if (mag) {
y[0] /= mag;
y[1] /= mag;
y[2] /= mag;
}
#define M(row,col) m[col*4+row]
M(0, 0) = x[0];
M(0, 1) = x[1];
M(0, 2) = x[2];
M(0, 3) = 0.0;
M(1, 0) = y[0];
M(1, 1) = y[1];
M(1, 2) = y[2];
M(1, 3) = 0.0;
M(2, 0) = z[0];
M(2, 1) = z[1];
M(2, 2) = z[2];
M(2, 3) = 0.0;
M(3, 0) = 0.0;
M(3, 1) = 0.0;
M(3, 2) = 0.0;
M(3, 3) = 1.0;
#undef M
glMultMatrixf(m);
/* Translate Eye to Origin */
glTranslatef(-eyex, -eyey, -eyez);
}
void GLAPIENTRY
gluOrtho2D(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top)
{
glOrtho(left, right, bottom, top, -1.0, 1.0);
}
static void
frustum(GLfloat left, GLfloat right,
GLfloat bottom, GLfloat top,
GLfloat nearval, GLfloat farval)
{
GLfloat x, y, a, b, c, d;
GLfloat m[16];
x = (2.0 * nearval) / (right - left);
y = (2.0 * nearval) / (top - bottom);
a = (right + left) / (right - left);
b = (top + bottom) / (top - bottom);
c = -(farval + nearval) / ( farval - nearval);
d = -(2.0 * farval * nearval) / (farval - nearval);
#define M(row,col) m[col*4+row]
M(0,0) = x; M(0,1) = 0.0F; M(0,2) = a; M(0,3) = 0.0F;
M(1,0) = 0.0F; M(1,1) = y; M(1,2) = b; M(1,3) = 0.0F;
M(2,0) = 0.0F; M(2,1) = 0.0F; M(2,2) = c; M(2,3) = d;
M(3,0) = 0.0F; M(3,1) = 0.0F; M(3,2) = -1.0F; M(3,3) = 0.0F;
#undef M
glMultMatrixf(m);
}
void GLAPIENTRY
gluPerspective(GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar)
{
GLfloat xmin, xmax, ymin, ymax;
ymax = zNear * tan(fovy * M_PI / 360.0);
ymin = -ymax;
xmin = ymin * aspect;
xmax = ymax * aspect;
/* don't call glFrustum() because of error semantics (covglu) */
frustum(xmin, xmax, ymin, ymax, zNear, zFar);
}
void GLAPIENTRY
gluPickMatrix(GLdouble x, GLdouble y,
GLdouble width, GLdouble height, GLint viewport[4])
{
GLfloat m[16];
GLfloat sx, sy;
GLfloat tx, ty;
sx = viewport[2] / width;
sy = viewport[3] / height;
tx = (viewport[2] + 2.0 * (viewport[0] - x)) / width;
ty = (viewport[3] + 2.0 * (viewport[1] - y)) / height;
#define M(row,col) m[col*4+row]
M(0, 0) = sx;
M(0, 1) = 0.0;
M(0, 2) = 0.0;
M(0, 3) = tx;
M(1, 0) = 0.0;
M(1, 1) = sy;
M(1, 2) = 0.0;
M(1, 3) = ty;
M(2, 0) = 0.0;
M(2, 1) = 0.0;
M(2, 2) = 1.0;
M(2, 3) = 0.0;
M(3, 0) = 0.0;
M(3, 1) = 0.0;
M(3, 2) = 0.0;
M(3, 3) = 1.0;
#undef M
glMultMatrixf(m);
}
const GLubyte *GLAPIENTRY
gluErrorString(GLenum errorCode)
{
static char *tess_error[] = {
"missing gluBeginPolygon",
"missing gluBeginContour",
"missing gluEndPolygon",
"missing gluEndContour",
"misoriented or self-intersecting loops",
"coincident vertices",
"colinear vertices",
"FIST recovery process fatal error"
};
static char *nurbs_error[] = {
"spline order un-supported",
"too few knots",
"valid knot range is empty",
"decreasing knot sequence knot",
"knot multiplicity greater than order of spline",
"endcurve() must follow bgncurve()",
"bgncurve() must precede endcurve()",
"missing or extra geometric data",
"can't draw pwlcurves",
"missing bgncurve()",
"missing bgnsurface()",
"endtrim() must precede endsurface()",
"bgnsurface() must precede endsurface()",
"curve of improper type passed as trim curve",
"bgnsurface() must precede bgntrim()",
"endtrim() must follow bgntrim()",
"bgntrim() must precede endtrim()",
"invalid or missing trim curve",
"bgntrim() must precede pwlcurve()",
"pwlcurve referenced twice",
"pwlcurve and nurbscurve mixed",
"improper usage of trim data type",
"nurbscurve referenced twice",
"nurbscurve and pwlcurve mixed",
"nurbssurface referenced twice",
"invalid property",
"endsurface() must follow bgnsurface()",
"misoriented trim curves",
"intersecting trim curves",
"UNUSED",
"unconnected trim curves",
"unknown knot error",
"negative vertex count encountered",
"negative byte-stride encountered",
"unknown type descriptor",
"null control array or knot vector",
"duplicate point on pwlcurve"
};
/* GL Errors */
if (errorCode == GL_NO_ERROR) {
return (GLubyte *) "no error";
}
else if (errorCode == GL_INVALID_VALUE) {
return (GLubyte *) "invalid value";
}
else if (errorCode == GL_INVALID_ENUM) {
return (GLubyte *) "invalid enum";
}
else if (errorCode == GL_INVALID_OPERATION) {
return (GLubyte *) "invalid operation";
}
else if (errorCode == GL_STACK_OVERFLOW) {
return (GLubyte *) "stack overflow";
}
else if (errorCode == GL_STACK_UNDERFLOW) {
return (GLubyte *) "stack underflow";
}
else if (errorCode == GL_OUT_OF_MEMORY) {
return (GLubyte *) "out of memory";
}
/* GLU Errors */
else if (errorCode == GLU_NO_ERROR) {
return (GLubyte *) "no error";
}
else if (errorCode == GLU_INVALID_ENUM) {
return (GLubyte *) "invalid enum";
}
else if (errorCode == GLU_INVALID_VALUE) {
return (GLubyte *) "invalid value";
}
else if (errorCode == GLU_OUT_OF_MEMORY) {
return (GLubyte *) "out of memory";
}
else if (errorCode == GLU_INCOMPATIBLE_GL_VERSION) {
return (GLubyte *) "incompatible GL version";
}
else if (errorCode >= GLU_TESS_ERROR1 && errorCode <= GLU_TESS_ERROR8) {
return (GLubyte *) tess_error[errorCode - GLU_TESS_ERROR1];
}
else if (errorCode >= GLU_NURBS_ERROR1 && errorCode <= GLU_NURBS_ERROR37) {
return (GLubyte *) nurbs_error[errorCode - GLU_NURBS_ERROR1];
}
else {
return NULL;
}
}
/*
* New in GLU 1.1
*/
const GLubyte *GLAPIENTRY
gluGetString(GLenum name)
{
static char *extensions = "GL_EXT_abgr";
static char *version = "1.1 Mesa 3.5";
switch (name) {
case GLU_EXTENSIONS:
return (GLubyte *) extensions;
case GLU_VERSION:
return (GLubyte *) version;
default:
return NULL;
}
}
#if 0 /* gluGetProcAddressEXT not finalized yet! */
#ifdef __cplusplus
/* for BeOS R4.5 */
void GLAPIENTRY(*gluGetProcAddressEXT(const GLubyte * procName)) (...)
#else
void (GLAPIENTRY * gluGetProcAddressEXT(const GLubyte * procName)) ()
#endif
{
struct proc
{
const char *name;
void *address;
};
static struct proc procTable[] = {
{"gluGetProcAddressEXT", (void *) gluGetProcAddressEXT}, /* me! */
/* new 1.1 functions */
{"gluGetString", (void *) gluGetString},
/* new 1.2 functions */
{"gluTessBeginPolygon", (void *) gluTessBeginPolygon},
{"gluTessBeginContour", (void *) gluTessBeginContour},
{"gluTessEndContour", (void *) gluTessEndContour},
{"gluTessEndPolygon", (void *) gluTessEndPolygon},
{"gluGetTessProperty", (void *) gluGetTessProperty},
/* new 1.3 functions */
{NULL, NULL}
};
GLuint i;
for (i = 0; procTable[i].address; i++) {
if (strcmp((const char *) procName, procTable[i].name) == 0)
return (void (GLAPIENTRY *) ()) procTable[i].address;
}
return NULL;
}
#endif
/*
* New in GLU 1.3
*/
#ifdef GLU_VERSION_1_3
GLboolean GLAPIENTRY
gluCheckExtension(const GLubyte *extName, const GLubyte * extString)
{
assert(extName);
assert(extString);
{
const int len = strlen((const char *) extName);
const char *start = (const char *) extString;
while (1) {
const char *c = strstr(start, (const char *) extName);
if (!c)
return GL_FALSE;
if ((c == start || c[-1] == ' ') && (c[len] == ' ' || c[len] == 0))
return GL_TRUE;
start = c + len;
}
}
}
#endif

142
src/glu/mini/gluP.h Normal file
View File

@ -0,0 +1,142 @@
/* $Id: gluP.h,v 1.2 2003/08/22 20:11:43 brianp Exp $ */
/*
* Mesa 3-D graphics library
* Version: 3.3
* Copyright (C) 1995-2000 Brian Paul
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* This file allows the GLU code to be compiled either with the Mesa
* headers or with the real OpenGL headers.
*/
#ifndef GLUP_H
#define GLUP_H
#include <GL/gl.h>
#include <GL/glu.h>
#include <string.h>
#if defined(_WIN32) && !defined(__WIN32__)
# define __WIN32__
#endif
#if !defined(OPENSTEP) && (defined(__WIN32__) || defined(__CYGWIN__))
# pragma warning( disable : 4068 ) /* unknown pragma */
# pragma warning( disable : 4710 ) /* function 'foo' not inlined */
# pragma warning( disable : 4711 ) /* function 'foo' selected for automatic inline expansion */
# pragma warning( disable : 4127 ) /* conditional expression is constant */
# if defined(MESA_MINWARN)
# pragma warning( disable : 4244 ) /* '=' : conversion from 'const double ' to 'float ', possible loss of data */
# pragma warning( disable : 4018 ) /* '<' : signed/unsigned mismatch */
# pragma warning( disable : 4305 ) /* '=' : truncation from 'const double ' to 'float ' */
# pragma warning( disable : 4550 ) /* 'function' undefined; assuming extern returning int */
# pragma warning( disable : 4761 ) /* integral size mismatch in argument; conversion supplied */
# endif
# if defined(_MSC_VER) && defined(BUILD_GL32) /* tag specify we're building mesa as a DLL */
# define GLAPI __declspec(dllexport)
# define WGLAPI __declspec(dllexport)
# elif defined(_MSC_VER) && defined(_DLL) /* tag specifying we're building for DLL runtime support */
# define GLAPI __declspec(dllimport)
# define WGLAPI __declspec(dllimport)
# else /* for use with static link lib build of Win32 edition only */
# define GLAPI extern
# define WGLAPI __declspec(dllimport)
# endif /* _STATIC_MESA support */
# define GLAPIENTRY __stdcall
# define GLAPIENTRYP __stdcall *
# define GLCALLBACK __stdcall
# define GLCALLBACKP __stdcall *
# if defined(__CYGWIN__)
# define GLCALLBACKPCAST *
# else
# define GLCALLBACKPCAST __stdcall *
# endif
# define GLWINAPI __stdcall
# define GLWINAPIV __cdecl
#else
/* non-Windows compilation */
# define GLAPI extern
# define GLAPIENTRY
# define GLAPIENTRYP *
# define GLCALLBACK
# define GLCALLBACKP *
# define GLCALLBACKPCAST *
# define GLWINAPI
# define GLWINAPIV
#endif /* WIN32 / CYGWIN bracket */
/* compatibility guard so we don't need to change client code */
#if defined(_WIN32) && !defined(_WINDEF_) && !defined(_GNU_H_WINDOWS32_BASE) && !defined(OPENSTEP)
# define CALLBACK GLCALLBACK
typedef int (GLAPIENTRY *PROC)();
typedef void *HGLRC;
typedef void *HDC;
typedef unsigned long COLORREF;
#endif
#if defined(_WIN32) && !defined(_WINGDI_) && !defined(_GNU_H_WINDOWS32_DEFINES) && !defined(OPENSTEP)
# define WGL_FONT_LINES 0
# define WGL_FONT_POLYGONS 1
#ifndef _GNU_H_WINDOWS32_FUNCTIONS
# ifdef UNICODE
# define wglUseFontBitmaps wglUseFontBitmapsW
# define wglUseFontOutlines wglUseFontOutlinesW
# else
# define wglUseFontBitmaps wglUseFontBitmapsA
# define wglUseFontOutlines wglUseFontOutlinesA
# endif /* !UNICODE */
#endif /* _GNU_H_WINDOWS32_FUNCTIONS */
typedef struct tagLAYERPLANEDESCRIPTOR LAYERPLANEDESCRIPTOR, *PLAYERPLANEDESCRIPTOR, *LPLAYERPLANEDESCRIPTOR;
typedef struct _GLYPHMETRICSFLOAT GLYPHMETRICSFLOAT, *PGLYPHMETRICSFLOAT, *LPGLYPHMETRICSFLOAT;
typedef struct tagPIXELFORMATDESCRIPTOR PIXELFORMATDESCRIPTOR, *PPIXELFORMATDESCRIPTOR, *LPPIXELFORMATDESCRIPTOR;
#include <gl/mesa_wgl.h>
#endif
#ifndef GLU_TESS_ERROR9
/* If we're using the real OpenGL header files... */
# define GLU_TESS_ERROR9 100159
#endif
#define GLU_NO_ERROR GL_NO_ERROR
/* for Sun: */
#ifdef SUNOS4
#define MEMCPY( DST, SRC, BYTES) \
memcpy( (char *) (DST), (char *) (SRC), (int) (BYTES) )
#else
#define MEMCPY( DST, SRC, BYTES) \
memcpy( (void *) (DST), (void *) (SRC), (size_t) (BYTES) )
#endif
#ifndef NULL
# define NULL 0
#endif
#endif

764
src/glu/mini/mipmap.c Normal file
View File

@ -0,0 +1,764 @@
/* $Id: mipmap.c,v 1.2 2003/08/22 20:11:43 brianp Exp $ */
/*
* Mesa 3-D graphics library
* Version: 3.4
* Copyright (C) 1995-2000 Brian Paul
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifdef PC_HEADER
#include "all.h"
#else
#include <assert.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include "gluP.h"
#endif
/*
* Compute ceiling of integer quotient of A divided by B:
*/
#define CEILING( A, B ) ( (A) % (B) == 0 ? (A)/(B) : (A)/(B)+1 )
#ifdef EPSILON
#undef EPSILON
#endif
#define EPSILON 0.001
/* To work around optimizer bug in MSVC4.1 */
#if defined(__WIN32__) && !defined(OPENSTEP)
void
dummy(GLuint j, GLuint k)
{
}
#else
#define dummy(J, K)
#endif
GLint GLAPIENTRY
gluScaleImage(GLenum format,
GLsizei widthin, GLsizei heightin,
GLenum typein, const void *datain,
GLsizei widthout, GLsizei heightout,
GLenum typeout, void *dataout)
{
GLint components, i, j, k;
GLfloat *tempin, *tempout, f;
GLfloat sx, sy;
GLint unpackrowlength, unpackalignment, unpackskiprows, unpackskippixels;
GLint packrowlength, packalignment, packskiprows, packskippixels;
GLint sizein, sizeout;
GLint rowstride, rowlen;
/* Determine number of components per pixel */
switch (format) {
case GL_COLOR_INDEX:
case GL_STENCIL_INDEX:
case GL_DEPTH_COMPONENT:
case GL_RED:
case GL_GREEN:
case GL_BLUE:
case GL_ALPHA:
case GL_LUMINANCE:
components = 1;
break;
case GL_LUMINANCE_ALPHA:
components = 2;
break;
case GL_RGB:
case GL_BGR:
components = 3;
break;
case GL_RGBA:
case GL_BGRA:
#ifdef GL_EXT_abgr
case GL_ABGR_EXT:
#endif
components = 4;
break;
default:
return GLU_INVALID_ENUM;
}
/* Determine bytes per input datum */
switch (typein) {
case GL_UNSIGNED_BYTE:
sizein = sizeof(GLubyte);
break;
case GL_BYTE:
sizein = sizeof(GLbyte);
break;
case GL_UNSIGNED_SHORT:
sizein = sizeof(GLushort);
break;
case GL_SHORT:
sizein = sizeof(GLshort);
break;
case GL_UNSIGNED_INT:
sizein = sizeof(GLuint);
break;
case GL_INT:
sizein = sizeof(GLint);
break;
case GL_FLOAT:
sizein = sizeof(GLfloat);
break;
case GL_BITMAP:
/* not implemented yet */
default:
return GL_INVALID_ENUM;
}
/* Determine bytes per output datum */
switch (typeout) {
case GL_UNSIGNED_BYTE:
sizeout = sizeof(GLubyte);
break;
case GL_BYTE:
sizeout = sizeof(GLbyte);
break;
case GL_UNSIGNED_SHORT:
sizeout = sizeof(GLushort);
break;
case GL_SHORT:
sizeout = sizeof(GLshort);
break;
case GL_UNSIGNED_INT:
sizeout = sizeof(GLuint);
break;
case GL_INT:
sizeout = sizeof(GLint);
break;
case GL_FLOAT:
sizeout = sizeof(GLfloat);
break;
case GL_BITMAP:
/* not implemented yet */
default:
return GL_INVALID_ENUM;
}
/* Get glPixelStore state */
glGetFloatv(GL_UNPACK_ROW_LENGTH, &f); unpackrowlength = (int)f;
glGetFloatv(GL_UNPACK_ALIGNMENT, &f); unpackalignment = (int)f;
glGetFloatv(GL_UNPACK_SKIP_ROWS, &f); unpackskiprows = (int)f;
glGetFloatv(GL_UNPACK_SKIP_PIXELS, &f); unpackskippixels = (int)f;
glGetFloatv(GL_PACK_ROW_LENGTH, &f); packrowlength = (int)f;
glGetFloatv(GL_PACK_ALIGNMENT, &f); packalignment = (int)f;
glGetFloatv(GL_PACK_SKIP_ROWS, &f); packskiprows = (int)f;
glGetFloatv(GL_PACK_SKIP_PIXELS, &f); packskippixels = (int)f;
/* Allocate storage for intermediate images */
tempin = (GLfloat *) malloc(widthin * heightin
* components * sizeof(GLfloat));
if (!tempin) {
return GLU_OUT_OF_MEMORY;
}
tempout = (GLfloat *) malloc(widthout * heightout
* components * sizeof(GLfloat));
if (!tempout) {
free(tempin);
return GLU_OUT_OF_MEMORY;
}
/*
* Unpack the pixel data and convert to floating point
*/
if (unpackrowlength > 0) {
rowlen = unpackrowlength;
}
else {
rowlen = widthin;
}
if (sizein >= unpackalignment) {
rowstride = components * rowlen;
}
else {
rowstride = unpackalignment / sizein
* CEILING(components * rowlen * sizein, unpackalignment);
}
switch (typein) {
case GL_UNSIGNED_BYTE:
k = 0;
for (i = 0; i < heightin; i++) {
GLubyte *ubptr = (GLubyte *) datain
+ i * rowstride
+ unpackskiprows * rowstride + unpackskippixels * components;
for (j = 0; j < widthin * components; j++) {
dummy(j, k);
tempin[k++] = (GLfloat) * ubptr++;
}
}
break;
case GL_BYTE:
k = 0;
for (i = 0; i < heightin; i++) {
GLbyte *bptr = (GLbyte *) datain
+ i * rowstride
+ unpackskiprows * rowstride + unpackskippixels * components;
for (j = 0; j < widthin * components; j++) {
dummy(j, k);
tempin[k++] = (GLfloat) * bptr++;
}
}
break;
case GL_UNSIGNED_SHORT:
k = 0;
for (i = 0; i < heightin; i++) {
GLushort *usptr = (GLushort *) datain
+ i * rowstride
+ unpackskiprows * rowstride + unpackskippixels * components;
for (j = 0; j < widthin * components; j++) {
dummy(j, k);
tempin[k++] = (GLfloat) * usptr++;
}
}
break;
case GL_SHORT:
k = 0;
for (i = 0; i < heightin; i++) {
GLshort *sptr = (GLshort *) datain
+ i * rowstride
+ unpackskiprows * rowstride + unpackskippixels * components;
for (j = 0; j < widthin * components; j++) {
dummy(j, k);
tempin[k++] = (GLfloat) * sptr++;
}
}
break;
case GL_UNSIGNED_INT:
k = 0;
for (i = 0; i < heightin; i++) {
GLuint *uiptr = (GLuint *) datain
+ i * rowstride
+ unpackskiprows * rowstride + unpackskippixels * components;
for (j = 0; j < widthin * components; j++) {
dummy(j, k);
tempin[k++] = (GLfloat) * uiptr++;
}
}
break;
case GL_INT:
k = 0;
for (i = 0; i < heightin; i++) {
GLint *iptr = (GLint *) datain
+ i * rowstride
+ unpackskiprows * rowstride + unpackskippixels * components;
for (j = 0; j < widthin * components; j++) {
dummy(j, k);
tempin[k++] = (GLfloat) * iptr++;
}
}
break;
case GL_FLOAT:
k = 0;
for (i = 0; i < heightin; i++) {
GLfloat *fptr = (GLfloat *) datain
+ i * rowstride
+ unpackskiprows * rowstride + unpackskippixels * components;
for (j = 0; j < widthin * components; j++) {
dummy(j, k);
tempin[k++] = *fptr++;
}
}
break;
default:
return GLU_INVALID_ENUM;
}
/*
* Scale the image!
*/
if (widthout > 1)
sx = (GLfloat) (widthin - 1) / (GLfloat) (widthout - 1);
else
sx = (GLfloat) (widthin - 1);
if (heightout > 1)
sy = (GLfloat) (heightin - 1) / (GLfloat) (heightout - 1);
else
sy = (GLfloat) (heightin - 1);
/*#define POINT_SAMPLE*/
#ifdef POINT_SAMPLE
for (i = 0; i < heightout; i++) {
GLint ii = i * sy;
for (j = 0; j < widthout; j++) {
GLint jj = j * sx;
GLfloat *src = tempin + (ii * widthin + jj) * components;
GLfloat *dst = tempout + (i * widthout + j) * components;
for (k = 0; k < components; k++) {
*dst++ = *src++;
}
}
}
#else
if (sx < 1.0 && sy < 1.0) {
/* magnify both width and height: use weighted sample of 4 pixels */
GLint i0, i1, j0, j1;
GLfloat alpha, beta;
GLfloat *src00, *src01, *src10, *src11;
GLfloat s1, s2;
GLfloat *dst;
for (i = 0; i < heightout; i++) {
i0 = i * sy;
i1 = i0 + 1;
if (i1 >= heightin)
i1 = heightin - 1;
/* i1 = (i+1) * sy - EPSILON;*/
alpha = i * sy - i0;
for (j = 0; j < widthout; j++) {
j0 = j * sx;
j1 = j0 + 1;
if (j1 >= widthin)
j1 = widthin - 1;
/* j1 = (j+1) * sx - EPSILON; */
beta = j * sx - j0;
/* compute weighted average of pixels in rect (i0,j0)-(i1,j1) */
src00 = tempin + (i0 * widthin + j0) * components;
src01 = tempin + (i0 * widthin + j1) * components;
src10 = tempin + (i1 * widthin + j0) * components;
src11 = tempin + (i1 * widthin + j1) * components;
dst = tempout + (i * widthout + j) * components;
for (k = 0; k < components; k++) {
s1 = *src00++ * (1.0 - beta) + *src01++ * beta;
s2 = *src10++ * (1.0 - beta) + *src11++ * beta;
*dst++ = s1 * (1.0 - alpha) + s2 * alpha;
}
}
}
}
else {
/* shrink width and/or height: use an unweighted box filter */
GLint i0, i1;
GLint j0, j1;
GLint ii, jj;
GLfloat sum, *dst;
for (i = 0; i < heightout; i++) {
i0 = i * sy;
i1 = i0 + 1;
if (i1 >= heightin)
i1 = heightin - 1;
/* i1 = (i+1) * sy - EPSILON; */
for (j = 0; j < widthout; j++) {
j0 = j * sx;
j1 = j0 + 1;
if (j1 >= widthin)
j1 = widthin - 1;
/* j1 = (j+1) * sx - EPSILON; */
dst = tempout + (i * widthout + j) * components;
/* compute average of pixels in the rectangle (i0,j0)-(i1,j1) */
for (k = 0; k < components; k++) {
sum = 0.0;
for (ii = i0; ii <= i1; ii++) {
for (jj = j0; jj <= j1; jj++) {
sum += *(tempin + (ii * widthin + jj) * components + k);
}
}
sum /= (j1 - j0 + 1) * (i1 - i0 + 1);
*dst++ = sum;
}
}
}
}
#endif
/*
* Return output image
*/
if (packrowlength > 0) {
rowlen = packrowlength;
}
else {
rowlen = widthout;
}
if (sizeout >= packalignment) {
rowstride = components * rowlen;
}
else {
rowstride = packalignment / sizeout
* CEILING(components * rowlen * sizeout, packalignment);
}
switch (typeout) {
case GL_UNSIGNED_BYTE:
k = 0;
for (i = 0; i < heightout; i++) {
GLubyte *ubptr = (GLubyte *) dataout
+ i * rowstride
+ packskiprows * rowstride + packskippixels * components;
for (j = 0; j < widthout * components; j++) {
dummy(j, k + i);
*ubptr++ = (GLubyte) tempout[k++];
}
}
break;
case GL_BYTE:
k = 0;
for (i = 0; i < heightout; i++) {
GLbyte *bptr = (GLbyte *) dataout
+ i * rowstride
+ packskiprows * rowstride + packskippixels * components;
for (j = 0; j < widthout * components; j++) {
dummy(j, k + i);
*bptr++ = (GLbyte) tempout[k++];
}
}
break;
case GL_UNSIGNED_SHORT:
k = 0;
for (i = 0; i < heightout; i++) {
GLushort *usptr = (GLushort *) dataout
+ i * rowstride
+ packskiprows * rowstride + packskippixels * components;
for (j = 0; j < widthout * components; j++) {
dummy(j, k + i);
*usptr++ = (GLushort) tempout[k++];
}
}
break;
case GL_SHORT:
k = 0;
for (i = 0; i < heightout; i++) {
GLshort *sptr = (GLshort *) dataout
+ i * rowstride
+ packskiprows * rowstride + packskippixels * components;
for (j = 0; j < widthout * components; j++) {
dummy(j, k + i);
*sptr++ = (GLshort) tempout[k++];
}
}
break;
case GL_UNSIGNED_INT:
k = 0;
for (i = 0; i < heightout; i++) {
GLuint *uiptr = (GLuint *) dataout
+ i * rowstride
+ packskiprows * rowstride + packskippixels * components;
for (j = 0; j < widthout * components; j++) {
dummy(j, k + i);
*uiptr++ = (GLuint) tempout[k++];
}
}
break;
case GL_INT:
k = 0;
for (i = 0; i < heightout; i++) {
GLint *iptr = (GLint *) dataout
+ i * rowstride
+ packskiprows * rowstride + packskippixels * components;
for (j = 0; j < widthout * components; j++) {
dummy(j, k + i);
*iptr++ = (GLint) tempout[k++];
}
}
break;
case GL_FLOAT:
k = 0;
for (i = 0; i < heightout; i++) {
GLfloat *fptr = (GLfloat *) dataout
+ i * rowstride
+ packskiprows * rowstride + packskippixels * components;
for (j = 0; j < widthout * components; j++) {
dummy(j, k + i);
*fptr++ = tempout[k++];
}
}
break;
default:
return GLU_INVALID_ENUM;
}
/* free temporary image storage */
free(tempin);
free(tempout);
return 0;
}
/*
* Return the largest k such that 2^k <= n.
*/
static GLint
ilog2(GLint n)
{
GLint k;
if (n <= 0)
return 0;
for (k = 0; n >>= 1; k++);
return k;
}
/*
* Find the value nearest to n which is also a power of two.
*/
static GLint
round2(GLint n)
{
GLint m;
for (m = 1; m < n; m *= 2);
/* m>=n */
if (m - n <= n - m / 2) {
return m;
}
else {
return m / 2;
}
}
/*
* Given an pixel format and data type, return the number of bytes to
* store one pixel.
*/
static GLint
bytes_per_pixel(GLenum format, GLenum type)
{
GLint n, m;
switch (format) {
case GL_COLOR_INDEX:
case GL_STENCIL_INDEX:
case GL_DEPTH_COMPONENT:
case GL_RED:
case GL_GREEN:
case GL_BLUE:
case GL_ALPHA:
case GL_LUMINANCE:
n = 1;
break;
case GL_LUMINANCE_ALPHA:
n = 2;
break;
case GL_RGB:
case GL_BGR:
n = 3;
break;
case GL_RGBA:
case GL_BGRA:
#ifdef GL_EXT_abgr
case GL_ABGR_EXT:
#endif
n = 4;
break;
default:
n = 0;
}
switch (type) {
case GL_UNSIGNED_BYTE:
m = sizeof(GLubyte);
break;
case GL_BYTE:
m = sizeof(GLbyte);
break;
case GL_BITMAP:
m = 1;
break;
case GL_UNSIGNED_SHORT:
m = sizeof(GLushort);
break;
case GL_SHORT:
m = sizeof(GLshort);
break;
case GL_UNSIGNED_INT:
m = sizeof(GLuint);
break;
case GL_INT:
m = sizeof(GLint);
break;
case GL_FLOAT:
m = sizeof(GLfloat);
break;
default:
m = 0;
}
return n * m;
}
/*
* WARNING: This function isn't finished and has never been tested!!!!
*/
GLint GLAPIENTRY
gluBuild1DMipmaps(GLenum target, GLint components,
GLsizei width, GLenum format, GLenum type, const void *data)
{
return 0;
}
GLint GLAPIENTRY
gluBuild2DMipmaps(GLenum target, GLint components,
GLsizei width, GLsizei height, GLenum format,
GLenum type, const void *data)
{
GLint w, h;
GLint maxsize;
void *image, *newimage;
GLint neww, newh, level, bpp;
int error;
GLboolean done;
GLint retval = 0;
GLint unpackrowlength, unpackalignment, unpackskiprows, unpackskippixels;
GLint packrowlength, packalignment, packskiprows, packskippixels;
GLfloat f;
if (width < 1 || height < 1)
return GLU_INVALID_VALUE;
glGetFloatv(GL_MAX_TEXTURE_SIZE, &f); maxsize = (int)f;
w = round2(width);
if (w > maxsize) {
w = maxsize;
}
h = round2(height);
if (h > maxsize) {
h = maxsize;
}
bpp = bytes_per_pixel(format, type);
if (bpp == 0) {
/* probably a bad format or type enum */
return GLU_INVALID_ENUM;
}
/* Get current glPixelStore values */
glGetFloatv(GL_UNPACK_ROW_LENGTH, &f); unpackrowlength = (int)f;
glGetFloatv(GL_UNPACK_ALIGNMENT, &f); unpackalignment = (int)f;
glGetFloatv(GL_UNPACK_SKIP_ROWS, &f); unpackskiprows = (int)f;
glGetFloatv(GL_UNPACK_SKIP_PIXELS, &f); unpackskippixels = (int)f;
glGetFloatv(GL_PACK_ROW_LENGTH, &f); packrowlength = (int)f;
glGetFloatv(GL_PACK_ALIGNMENT, &f); packalignment = (int)f;
glGetFloatv(GL_PACK_SKIP_ROWS, &f); packskiprows = (int)f;
glGetFloatv(GL_PACK_SKIP_PIXELS, &f); packskippixels = (int)f;
/* set pixel packing */
glPixelStorei(GL_PACK_ROW_LENGTH, 0);
glPixelStorei(GL_PACK_ALIGNMENT, 1);
glPixelStorei(GL_PACK_SKIP_ROWS, 0);
glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
done = GL_FALSE;
if (w != width || h != height) {
/* must rescale image to get "top" mipmap texture image */
image = malloc((w + 4) * h * bpp);
if (!image) {
return GLU_OUT_OF_MEMORY;
}
error = gluScaleImage(format, width, height, type, data,
w, h, type, image);
if (error) {
retval = error;
done = GL_TRUE;
}
}
else {
image = (void *) data;
}
level = 0;
while (!done) {
if (image != data) {
/* set pixel unpacking */
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
}
glTexImage2D(target, level, components, w, h, 0, format, type, image);
if (w == 1 && h == 1)
break;
neww = (w < 2) ? 1 : w / 2;
newh = (h < 2) ? 1 : h / 2;
newimage = malloc((neww + 4) * newh * bpp);
if (!newimage) {
return GLU_OUT_OF_MEMORY;
}
error = gluScaleImage(format, w, h, type, image,
neww, newh, type, newimage);
if (error) {
retval = error;
done = GL_TRUE;
}
if (image != data) {
free(image);
}
image = newimage;
w = neww;
h = newh;
level++;
}
if (image != data) {
free(image);
}
/* Restore original glPixelStore state */
glPixelStorei(GL_UNPACK_ROW_LENGTH, unpackrowlength);
glPixelStorei(GL_UNPACK_ALIGNMENT, unpackalignment);
glPixelStorei(GL_UNPACK_SKIP_ROWS, unpackskiprows);
glPixelStorei(GL_UNPACK_SKIP_PIXELS, unpackskippixels);
glPixelStorei(GL_PACK_ROW_LENGTH, packrowlength);
glPixelStorei(GL_PACK_ALIGNMENT, packalignment);
glPixelStorei(GL_PACK_SKIP_ROWS, packskiprows);
glPixelStorei(GL_PACK_SKIP_PIXELS, packskippixels);
return retval;
}

158
src/glu/mini/nurbs.c Normal file
View File

@ -0,0 +1,158 @@
/* $Id: nurbs.c,v 1.2 2003/08/22 20:11:43 brianp Exp $ */
/*
* Mesa 3-D graphics library
* Version: 3.3
* Copyright (C) 1995-2000 Brian Paul
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* NURBS implementation written by Bogdan Sikorski (bogdan@cira.it)
* See README2 for more info.
*/
#ifdef PC_HEADER
#include "all.h"
#else
#include <stdio.h>
#include <stdlib.h>
#include "gluP.h"
#include "nurbs.h"
#endif
void
call_user_error(GLUnurbsObj * nobj, GLenum error)
{
nobj->error = error;
if (nobj->error_callback != NULL) {
(*(nobj->error_callback)) (error);
}
else {
printf("NURBS error %d %s\n", error, (char *) gluErrorString(error));
}
}
GLUnurbsObj *GLAPIENTRY
gluNewNurbsRenderer(void)
{
GLUnurbsObj *n;
GLfloat tmp_viewport[4];
GLint i, j;
n = (GLUnurbsObj *) malloc(sizeof(GLUnurbsObj));
return n;
}
void GLAPIENTRY
gluDeleteNurbsRenderer(GLUnurbsObj * nobj)
{
if (nobj) {
free(nobj);
}
}
void GLAPIENTRY
gluLoadSamplingMatrices(GLUnurbsObj * nobj,
const GLfloat modelMatrix[16],
const GLfloat projMatrix[16], const GLint viewport[4])
{
}
void GLAPIENTRY
gluNurbsProperty(GLUnurbsObj * nobj, GLenum property, GLfloat value)
{
}
void GLAPIENTRY
gluGetNurbsProperty(GLUnurbsObj * nobj, GLenum property, GLfloat * value)
{
}
void GLAPIENTRY
gluBeginCurve(GLUnurbsObj * nobj)
{
}
void GLAPIENTRY
gluEndCurve(GLUnurbsObj * nobj)
{
}
void GLAPIENTRY
gluNurbsCurve(GLUnurbsObj * nobj, GLint nknots, GLfloat * knot,
GLint stride, GLfloat * ctlarray, GLint order, GLenum type)
{
}
void GLAPIENTRY
gluBeginSurface(GLUnurbsObj * nobj)
{
}
void GLAPIENTRY
gluEndSurface(GLUnurbsObj * nobj)
{
}
void GLAPIENTRY
gluNurbsSurface(GLUnurbsObj * nobj,
GLint sknot_count, GLfloat * sknot,
GLint tknot_count, GLfloat * tknot,
GLint s_stride, GLint t_stride,
GLfloat * ctrlarray, GLint sorder, GLint torder, GLenum type)
{
}
void GLAPIENTRY
gluNurbsCallback(GLUnurbsObj * nobj, GLenum which, void (GLCALLBACK * fn) ())
{
}
void GLAPIENTRY
gluBeginTrim(GLUnurbsObj * nobj)
{
}
void GLAPIENTRY
gluPwlCurve(GLUnurbsObj * nobj, GLint count, GLfloat * array, GLint stride,
GLenum type)
{
}
void GLAPIENTRY
gluEndTrim(GLUnurbsObj * nobj)
{
}

253
src/glu/mini/nurbs.h Normal file
View File

@ -0,0 +1,253 @@
/* $Id: nurbs.h,v 1.2 2003/08/22 20:11:43 brianp Exp $ */
/*
* Mesa 3-D graphics library
* Version: 3.3
* Copyright (C) 1995-2000 Brian Paul
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* NURBS implementation written by Bogdan Sikorski (bogdan@cira.it)
* See README2 for more info.
*/
#ifndef NURBS_H
#define NURBS_H
#define EPSILON 1e-06 /* epsilon for double precision compares */
typedef enum
{
GLU_NURBS_CURVE, GLU_NURBS_SURFACE, GLU_NURBS_TRIM, GLU_NURBS_NO_TRIM,
GLU_NURBS_TRIM_DONE, GLU_NURBS_NONE
}
GLU_nurbs_enum;
typedef enum
{
GLU_TRIM_NURBS, GLU_TRIM_PWL
}
GLU_trim_enum;
typedef struct
{
GLint sknot_count;
GLfloat *sknot;
GLint tknot_count;
GLfloat *tknot;
GLint s_stride;
GLint t_stride;
GLfloat *ctrlarray;
GLint sorder;
GLint torder;
GLint dim;
GLenum type;
}
surface_attribs;
typedef struct
{
surface_attribs geom;
surface_attribs color;
surface_attribs texture;
surface_attribs normal;
}
nurbs_surface;
typedef struct
{
GLint knot_count;
GLfloat *knot;
GLint stride;
GLfloat *ctrlarray;
GLint order;
GLint dim;
GLenum type;
}
curve_attribs;
typedef struct
{
GLint pt_count;
GLfloat *ctrlarray;
GLint stride;
GLint dim;
GLenum type;
}
pwl_curve_attribs;
typedef struct
{
curve_attribs geom;
curve_attribs color;
curve_attribs texture;
curve_attribs normal;
}
nurbs_curve;
typedef struct trim_list_str
{
GLU_trim_enum trim_type;
union
{
pwl_curve_attribs pwl_curve;
curve_attribs nurbs_curve;
}
curve;
struct trim_list_str *next;
}
trim_list;
typedef struct seg_trim_str
{
GLfloat *points;
GLint pt_cnt, seg_array_len;
struct seg_trim_str *next;
}
trim_segments;
typedef struct nurbs_trim_str
{
trim_list *trim_loop;
trim_segments *segments;
struct nurbs_trim_str *next;
}
nurbs_trim;
typedef struct
{
GLfloat model[16], proj[16], viewport[4];
}
culling_and_sampling_str;
struct GLUnurbs
{
GLboolean culling;
GLenum error;
void (GLCALLBACK * error_callback) (GLenum err);
GLenum display_mode;
GLU_nurbs_enum nurbs_type;
GLboolean auto_load_matrix;
culling_and_sampling_str sampling_matrices;
GLenum sampling_method;
GLfloat sampling_tolerance;
GLfloat parametric_tolerance;
GLint u_step, v_step;
nurbs_surface surface;
nurbs_curve curve;
nurbs_trim *trim;
};
typedef struct
{
GLfloat *knot;
GLint nknots;
GLfloat *unified_knot;
GLint unified_nknots;
GLint order;
GLint t_min, t_max;
GLint delta_nknots;
GLboolean open_at_begin, open_at_end;
GLfloat *new_knot;
GLfloat *alpha;
}
knot_str_type;
typedef struct
{
GLfloat *geom_ctrl;
GLint geom_s_stride, geom_t_stride;
GLfloat **geom_offsets;
GLint geom_s_pt_cnt, geom_t_pt_cnt;
GLfloat *color_ctrl;
GLint color_s_stride, color_t_stride;
GLfloat **color_offsets;
GLint color_s_pt_cnt, color_t_pt_cnt;
GLfloat *normal_ctrl;
GLint normal_s_stride, normal_t_stride;
GLfloat **normal_offsets;
GLint normal_s_pt_cnt, normal_t_pt_cnt;
GLfloat *texture_ctrl;
GLint texture_s_stride, texture_t_stride;
GLfloat **texture_offsets;
GLint texture_s_pt_cnt, texture_t_pt_cnt;
GLint s_bezier_cnt, t_bezier_cnt;
}
new_ctrl_type;
extern void call_user_error(GLUnurbsObj * nobj, GLenum error);
extern GLenum test_knot(GLint nknots, GLfloat * knot, GLint order);
extern GLenum explode_knot(knot_str_type * the_knot);
extern GLenum calc_alphas(knot_str_type * the_knot);
extern GLenum calc_new_ctrl_pts(GLfloat * ctrl, GLint stride,
knot_str_type * the_knot, GLint dim,
GLfloat ** new_ctrl, GLint * ncontrol);
extern GLenum glu_do_sampling_crv(GLUnurbsObj * nobj, GLfloat * new_ctrl,
GLint n_ctrl, GLint order, GLint dim,
GLint ** factors);
extern GLenum glu_do_sampling_3D(GLUnurbsObj * nobj, new_ctrl_type * new_ctrl,
int **sfactors, GLint ** tfactors);
extern GLenum glu_do_sampling_uv(GLUnurbsObj * nobj, new_ctrl_type * new_ctrl,
int **sfactors, GLint ** tfactors);
extern GLenum glu_do_sampling_param_3D(GLUnurbsObj * nobj,
new_ctrl_type * new_ctrl,
int **sfactors, GLint ** tfactors);
extern GLboolean fine_culling_test_2D(GLUnurbsObj * nobj, GLfloat * ctrl,
GLint n_ctrl, GLint stride, GLint dim);
extern GLboolean fine_culling_test_3D(GLUnurbsObj * nobj, GLfloat * ctrl,
GLint s_n_ctrl, GLint t_n_ctrl,
GLint s_stride, GLint t_stride,
GLint dim);
extern void do_nurbs_curve(GLUnurbsObj * nobj);
extern void do_nurbs_surface(GLUnurbsObj * nobj);
extern GLenum patch_trimming(GLUnurbsObj * nobj, new_ctrl_type * new_ctrl,
GLint * sfactors, GLint * tfactors);
extern void collect_unified_knot(knot_str_type * dest, knot_str_type * src,
GLfloat maximal_min_knot,
GLfloat minimal_max_knot);
extern GLenum select_knot_working_range(GLUnurbsObj * nobj,
knot_str_type * geom_knot,
knot_str_type * color_knot,
knot_str_type * normal_knot,
knot_str_type * texture_knot);
extern void free_unified_knots(knot_str_type * geom_knot,
knot_str_type * color_knot,
knot_str_type * normal_knot,
knot_str_type * texture_knot);
#endif

133
src/glu/mini/nurbscrv.c Normal file
View File

@ -0,0 +1,133 @@
/* $Id: nurbscrv.c,v 1.2 2003/08/22 20:11:43 brianp Exp $ */
/*
* Mesa 3-D graphics library
* Version: 3.3
* Copyright (C) 1995-2000 Brian Paul
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* NURBS implementation written by Bogdan Sikorski (bogdan@cira.it)
* See README2 for more info.
*/
#ifdef PC_HEADER
#include "all.h"
#else
#include <math.h>
#include <stdlib.h>
#include "gluP.h"
#include "nurbs.h"
#endif
/* main NURBS curve procedure */
void
do_nurbs_curve(GLUnurbsObj * nobj)
{
GLint geom_order, color_order = 0, normal_order = 0, texture_order = 0;
GLenum geom_type;
GLint n_ctrl;
GLfloat *new_geom_ctrl, *new_color_ctrl, *new_normal_ctrl,
*new_texture_ctrl;
GLfloat *geom_ctrl = 0, *color_ctrl = 0, *normal_ctrl = 0, *texture_ctrl = 0;
GLint *factors;
GLint i, j;
GLint geom_dim, color_dim = 0, normal_dim = 0, texture_dim = 0;
/* test the user supplied data */
if (test_nurbs_curves(nobj) != GLU_NO_ERROR)
return;
if (convert_curves(nobj, &new_geom_ctrl, &n_ctrl, &new_color_ctrl,
&new_normal_ctrl, &new_texture_ctrl) != GLU_NO_ERROR)
return;
geom_order = nobj->curve.geom.order;
geom_type = nobj->curve.geom.type;
geom_dim = nobj->curve.geom.dim;
if (glu_do_sampling_crv(nobj, new_geom_ctrl, n_ctrl, geom_order, geom_dim,
&factors) != GLU_NO_ERROR) {
free(new_geom_ctrl);
if (new_color_ctrl)
free(new_color_ctrl);
if (new_normal_ctrl)
free(new_normal_ctrl);
if (new_texture_ctrl)
free(new_texture_ctrl);
return;
}
glEnable(geom_type);
if (new_color_ctrl) {
glEnable(nobj->curve.color.type);
color_dim = nobj->curve.color.dim;
color_ctrl = new_color_ctrl;
color_order = nobj->curve.color.order;
}
if (new_normal_ctrl) {
glEnable(nobj->curve.normal.type);
normal_dim = nobj->curve.normal.dim;
normal_ctrl = new_normal_ctrl;
normal_order = nobj->curve.normal.order;
}
if (new_texture_ctrl) {
glEnable(nobj->curve.texture.type);
texture_dim = nobj->curve.texture.dim;
texture_ctrl = new_texture_ctrl;
texture_order = nobj->curve.texture.order;
}
for (i = 0, j = 0, geom_ctrl = new_geom_ctrl;
i < n_ctrl; i += geom_order, j++, geom_ctrl += geom_order * geom_dim) {
if (fine_culling_test_2D
(nobj, geom_ctrl, geom_order, geom_dim, geom_dim)) {
color_ctrl += color_order * color_dim;
normal_ctrl += normal_order * normal_dim;
texture_ctrl += texture_order * texture_dim;
continue;
}
glMap1f(geom_type, 0.0, 1.0, geom_dim, geom_order, geom_ctrl);
if (new_color_ctrl) {
glMap1f(nobj->curve.color.type, 0.0, 1.0, color_dim,
color_order, color_ctrl);
color_ctrl += color_order * color_dim;
}
if (new_normal_ctrl) {
glMap1f(nobj->curve.normal.type, 0.0, 1.0, normal_dim,
normal_order, normal_ctrl);
normal_ctrl += normal_order * normal_dim;
}
if (new_texture_ctrl) {
glMap1f(nobj->curve.texture.type, 0.0, 1.0, texture_dim,
texture_order, texture_ctrl);
texture_ctrl += texture_order * texture_dim;
}
glMapGrid1f(factors[j], 0.0, 1.0);
glEvalMesh1(GL_LINE, 0, factors[j]);
}
free(new_geom_ctrl);
free(factors);
if (new_color_ctrl)
free(new_color_ctrl);
if (new_normal_ctrl)
free(new_normal_ctrl);
if (new_texture_ctrl)
free(new_texture_ctrl);
}

938
src/glu/mini/polytest.c Normal file
View File

@ -0,0 +1,938 @@
/* $Id: polytest.c,v 1.2 2003/08/22 20:11:43 brianp Exp $ */
/*
* Mesa 3-D graphics library
* Version: 3.3
* Copyright (C) 1995-2000 Brian Paul
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* This file is part of the polygon tesselation code contributed by
* Bogdan Sikorski
*/
#ifdef PC_HEADER
#include "all.h"
#else
#include <math.h>
#include <stdlib.h>
#include "gluP.h"
#include "tess.h"
#endif
static GLenum store_polygon_as_contour(GLUtriangulatorObj *);
static void free_current_polygon(tess_polygon *);
static void prepare_projection_info(GLUtriangulatorObj *);
static GLdouble twice_the_polygon_area(tess_vertex *, tess_vertex *);
static GLenum verify_edge_vertex_intersections(GLUtriangulatorObj *);
void tess_find_contour_hierarchies(GLUtriangulatorObj *);
static GLenum test_for_overlapping_contours(GLUtriangulatorObj *);
static GLenum contours_overlap(tess_contour *, tess_polygon *);
static GLenum is_contour_contained_in(tess_contour *, tess_contour *);
static void add_new_exterior(GLUtriangulatorObj *, tess_contour *);
static void add_new_interior(GLUtriangulatorObj *, tess_contour *,
tess_contour *);
static void add_interior_with_hierarchy_check(GLUtriangulatorObj *,
tess_contour *, tess_contour *);
static void reverse_hierarchy_and_add_exterior(GLUtriangulatorObj *,
tess_contour *,
tess_contour *);
static GLboolean point_in_polygon(tess_contour *, GLdouble, GLdouble);
static void shift_interior_to_exterior(GLUtriangulatorObj *, tess_contour *);
static void add_exterior_with_check(GLUtriangulatorObj *, tess_contour *,
tess_contour *);
static GLenum cut_out_hole(GLUtriangulatorObj *, tess_contour *,
tess_contour *);
static GLenum merge_hole_with_contour(GLUtriangulatorObj *,
tess_contour *, tess_contour *,
tess_vertex *, tess_vertex *);
static GLenum
find_normal(GLUtriangulatorObj * tobj)
{
tess_polygon *polygon = tobj->current_polygon;
tess_vertex *va, *vb, *vc;
GLdouble A, B, C;
GLdouble A0, A1, A2, B0, B1, B2;
va = polygon->vertices;
vb = va->next;
A0 = vb->location[0] - va->location[0];
A1 = vb->location[1] - va->location[1];
A2 = vb->location[2] - va->location[2];
for (vc = vb->next; vc != va; vc = vc->next) {
B0 = vc->location[0] - va->location[0];
B1 = vc->location[1] - va->location[1];
B2 = vc->location[2] - va->location[2];
A = A1 * B2 - A2 * B1;
B = A2 * B0 - A0 * B2;
C = A0 * B1 - A1 * B0;
if (fabs(A) > EPSILON || fabs(B) > EPSILON || fabs(C) > EPSILON) {
polygon->A = A;
polygon->B = B;
polygon->C = C;
polygon->D =
-A * va->location[0] - B * va->location[1] - C * va->location[2];
return GLU_NO_ERROR;
}
}
tess_call_user_error(tobj, GLU_TESS_ERROR7);
return GLU_ERROR;
}
void
tess_test_polygon(GLUtriangulatorObj * tobj)
{
tess_polygon *polygon = tobj->current_polygon;
/* any vertices defined? */
if (polygon->vertex_cnt < 3) {
free_current_polygon(polygon);
return;
}
/* wrap pointers */
polygon->last_vertex->next = polygon->vertices;
polygon->vertices->previous = polygon->last_vertex;
/* determine the normal */
if (find_normal(tobj) == GLU_ERROR)
return;
/* compare the normals of previously defined contours and this one */
/* first contour define ? */
if (tobj->contours == NULL) {
tobj->A = polygon->A;
tobj->B = polygon->B;
tobj->C = polygon->C;
tobj->D = polygon->D;
/* determine the best projection to use */
if (fabs(polygon->A) > fabs(polygon->B))
if (fabs(polygon->A) > fabs(polygon->C))
tobj->projection = OYZ;
else
tobj->projection = OXY;
else if (fabs(polygon->B) > fabs(polygon->C))
tobj->projection = OXZ;
else
tobj->projection = OXY;
}
else {
GLdouble a[3], b[3];
tess_vertex *vertex = polygon->vertices;
a[0] = tobj->A;
a[1] = tobj->B;
a[2] = tobj->C;
b[0] = polygon->A;
b[1] = polygon->B;
b[2] = polygon->C;
/* compare the normals */
if (fabs(a[1] * b[2] - a[2] * b[1]) > EPSILON ||
fabs(a[2] * b[0] - a[0] * b[2]) > EPSILON ||
fabs(a[0] * b[1] - a[1] * b[0]) > EPSILON) {
/* not coplanar */
tess_call_user_error(tobj, GLU_TESS_ERROR9);
return;
}
/* the normals are parallel - test for plane equation */
if (fabs(a[0] * vertex->location[0] + a[1] * vertex->location[1] +
a[2] * vertex->location[2] + tobj->D) > EPSILON) {
/* not the same plane */
tess_call_user_error(tobj, GLU_TESS_ERROR9);
return;
}
}
prepare_projection_info(tobj);
if (verify_edge_vertex_intersections(tobj) == GLU_ERROR)
return;
if (test_for_overlapping_contours(tobj) == GLU_ERROR)
return;
if (store_polygon_as_contour(tobj) == GLU_ERROR)
return;
}
static GLenum
test_for_overlapping_contours(GLUtriangulatorObj * tobj)
{
tess_contour *contour;
tess_polygon *polygon;
polygon = tobj->current_polygon;
for (contour = tobj->contours; contour != NULL; contour = contour->next)
if (contours_overlap(contour, polygon) != GLU_NO_ERROR) {
tess_call_user_error(tobj, GLU_TESS_ERROR5);
return GLU_ERROR;
}
return GLU_NO_ERROR;
}
static GLenum
store_polygon_as_contour(GLUtriangulatorObj * tobj)
{
tess_polygon *polygon = tobj->current_polygon;
tess_contour *contour = tobj->contours;
/* the first contour defined */
if (contour == NULL) {
if ((contour = (tess_contour *) malloc(sizeof(tess_contour))) == NULL) {
tess_call_user_error(tobj, GLU_OUT_OF_MEMORY);
free_current_polygon(polygon);
return GLU_ERROR;
}
tobj->contours = tobj->last_contour = contour;
contour->next = contour->previous = NULL;
}
else {
if ((contour = (tess_contour *) malloc(sizeof(tess_contour))) == NULL) {
tess_call_user_error(tobj, GLU_OUT_OF_MEMORY);
free_current_polygon(polygon);
return GLU_ERROR;
}
contour->previous = tobj->last_contour;
tobj->last_contour->next = contour;
tobj->last_contour = contour;
contour->next = NULL;
}
/* mark all vertices in new contour as not special */
/* and all are boundary edges */
{
tess_vertex *vertex;
GLuint vertex_cnt, i;
for (vertex = polygon->vertices, i = 0, vertex_cnt =
polygon->vertex_cnt; i < vertex_cnt; vertex = vertex->next, i++) {
vertex->shadow_vertex = NULL;
vertex->edge_flag = GL_TRUE;
}
}
contour->vertex_cnt = polygon->vertex_cnt;
contour->area = polygon->area;
contour->orientation = polygon->orientation;
contour->type = GLU_UNKNOWN;
contour->vertices = polygon->vertices;
contour->last_vertex = polygon->last_vertex;
polygon->vertices = polygon->last_vertex = NULL;
polygon->vertex_cnt = 0;
++(tobj->contour_cnt);
return GLU_NO_ERROR;
}
static void
free_current_polygon(tess_polygon * polygon)
{
tess_vertex *vertex, *vertex_tmp;
GLuint i;
/* free current_polygon structures */
for (vertex = polygon->vertices, i = 0; i < polygon->vertex_cnt; i++) {
vertex_tmp = vertex->next;
free(vertex);
vertex = vertex_tmp;
}
polygon->vertices = polygon->last_vertex = NULL;
polygon->vertex_cnt = 0;
}
static void
prepare_projection_info(GLUtriangulatorObj * tobj)
{
tess_polygon *polygon = tobj->current_polygon;
tess_vertex *vertex, *last_vertex_ptr;
GLdouble area;
last_vertex_ptr = polygon->last_vertex;
switch (tobj->projection) {
case OXY:
for (vertex = polygon->vertices; vertex != last_vertex_ptr;
vertex = vertex->next) {
vertex->x = vertex->location[0];
vertex->y = vertex->location[1];
}
last_vertex_ptr->x = last_vertex_ptr->location[0];
last_vertex_ptr->y = last_vertex_ptr->location[1];
break;
case OXZ:
for (vertex = polygon->vertices; vertex != last_vertex_ptr;
vertex = vertex->next) {
vertex->x = vertex->location[0];
vertex->y = vertex->location[2];
}
last_vertex_ptr->x = last_vertex_ptr->location[0];
last_vertex_ptr->y = last_vertex_ptr->location[2];
break;
case OYZ:
for (vertex = polygon->vertices; vertex != last_vertex_ptr;
vertex = vertex->next) {
vertex->x = vertex->location[1];
vertex->y = vertex->location[2];
}
last_vertex_ptr->x = last_vertex_ptr->location[1];
last_vertex_ptr->y = last_vertex_ptr->location[2];
break;
}
area = twice_the_polygon_area(polygon->vertices, polygon->last_vertex);
if (area >= 0.0) {
polygon->orientation = GLU_CCW;
polygon->area = area;
}
else {
polygon->orientation = GLU_CW;
polygon->area = -area;
}
}
static GLdouble
twice_the_polygon_area(tess_vertex * vertex, tess_vertex * last_vertex)
{
tess_vertex *next;
GLdouble area, x, y;
area = 0.0;
x = vertex->x;
y = vertex->y;
vertex = vertex->next;
for (; vertex != last_vertex; vertex = vertex->next) {
next = vertex->next;
area +=
(vertex->x - x) * (next->y - y) - (vertex->y - y) * (next->x - x);
}
return area;
}
/* test if edges ab and cd intersect */
/* if not return GLU_NO_ERROR, else if cross return GLU_TESS_ERROR8, */
/* else if adjacent return GLU_TESS_ERROR4 */
static GLenum
edge_edge_intersect(tess_vertex * a,
tess_vertex * b, tess_vertex * c, tess_vertex * d)
{
GLdouble denom, r, s;
GLdouble xba, ydc, yba, xdc, yac, xac;
xba = b->x - a->x;
yba = b->y - a->y;
xdc = d->x - c->x;
ydc = d->y - c->y;
xac = a->x - c->x;
yac = a->y - c->y;
denom = xba * ydc - yba * xdc;
r = yac * xdc - xac * ydc;
/* parallel? */
if (fabs(denom) < EPSILON) {
if (fabs(r) < EPSILON) {
/* colinear */
if (fabs(xba) < EPSILON) {
/* compare the Y coordinate */
if (yba > 0.0) {
if (
(fabs(a->y - c->y) < EPSILON
&& fabs(c->y - b->y) < EPSILON)
|| (fabs(a->y - d->y) < EPSILON
&& fabs(d->y - b->y) <
EPSILON)) return GLU_TESS_ERROR4;
}
else {
if (
(fabs(b->y - c->y) < EPSILON
&& fabs(c->y - a->y) < EPSILON)
|| (fabs(b->y - d->y) < EPSILON
&& fabs(d->y - a->y) <
EPSILON)) return GLU_TESS_ERROR4;
}
}
else {
/* compare the X coordinate */
if (xba > 0.0) {
if (
(fabs(a->x - c->x) < EPSILON
&& fabs(c->x - b->x) < EPSILON)
|| (fabs(a->x - d->x) < EPSILON
&& fabs(d->x - b->x) <
EPSILON)) return GLU_TESS_ERROR4;
}
else {
if (
(fabs(b->x - c->x) < EPSILON
&& fabs(c->x - a->x) < EPSILON)
|| (fabs(b->x - d->x) < EPSILON
&& fabs(d->x - a->x) <
EPSILON)) return GLU_TESS_ERROR4;
}
}
}
return GLU_NO_ERROR;
}
r /= denom;
s = (yac * xba - xac * yba) / denom;
/* test if one vertex lies on other edge */
if (((fabs(r) < EPSILON || (r < 1.0 + EPSILON && r > 1.0 - EPSILON)) &&
s > -EPSILON && s < 1.0 + EPSILON) ||
((fabs(s) < EPSILON || (s < 1.0 + EPSILON && s > 1.0 - EPSILON)) &&
r > -EPSILON && r < 1.0 + EPSILON)) {
return GLU_TESS_ERROR4;
}
/* test for crossing */
if (r > -EPSILON && r < 1.0 + EPSILON && s > -EPSILON && s < 1.0 + EPSILON) {
return GLU_TESS_ERROR8;
}
return GLU_NO_ERROR;
}
static GLenum
verify_edge_vertex_intersections(GLUtriangulatorObj * tobj)
{
tess_polygon *polygon = tobj->current_polygon;
tess_vertex *vertex1, *last_vertex, *vertex2;
GLenum test;
last_vertex = polygon->last_vertex;
vertex1 = last_vertex;
for (vertex2 = vertex1->next->next;
vertex2->next != last_vertex; vertex2 = vertex2->next) {
test = edge_edge_intersect(vertex1, vertex1->next, vertex2,
vertex2->next);
if (test != GLU_NO_ERROR) {
tess_call_user_error(tobj, test);
return GLU_ERROR;
}
}
for (vertex1 = polygon->vertices;
vertex1->next->next != last_vertex; vertex1 = vertex1->next) {
for (vertex2 = vertex1->next->next;
vertex2 != last_vertex; vertex2 = vertex2->next) {
test = edge_edge_intersect(vertex1, vertex1->next, vertex2,
vertex2->next);
if (test != GLU_NO_ERROR) {
tess_call_user_error(tobj, test);
return GLU_ERROR;
}
}
}
return GLU_NO_ERROR;
}
static int
#ifdef WIN32
__cdecl
#endif
area_compare(const void *a, const void *b)
{
GLdouble area1, area2;
area1 = (*((tess_contour **) a))->area;
area2 = (*((tess_contour **) b))->area;
if (area1 < area2)
return 1;
if (area1 > area2)
return -1;
return 0;
}
void
tess_find_contour_hierarchies(GLUtriangulatorObj * tobj)
{
tess_contour **contours; /* dinamic array of pointers */
tess_contour *tmp_contour_ptr = tobj->contours;
GLuint cnt, i;
GLenum result;
GLboolean hierarchy_changed;
/* any contours? */
if (tobj->contour_cnt < 2) {
tobj->contours->type = GLU_EXTERIOR;
return;
}
if ((contours = (tess_contour **)
malloc(sizeof(tess_contour *) * (tobj->contour_cnt))) == NULL) {
tess_call_user_error(tobj, GLU_OUT_OF_MEMORY);
return;
}
for (tmp_contour_ptr = tobj->contours, cnt = 0;
tmp_contour_ptr != NULL; tmp_contour_ptr = tmp_contour_ptr->next)
contours[cnt++] = tmp_contour_ptr;
/* now sort the contours in decreasing area size order */
qsort((void *) contours, (size_t) cnt, (size_t) sizeof(tess_contour *),
area_compare);
/* we leave just the first contour - remove others from list */
tobj->contours = contours[0];
tobj->contours->next = tobj->contours->previous = NULL;
tobj->last_contour = tobj->contours;
tobj->contour_cnt = 1;
/* first contour is the one with greatest area */
/* must be EXTERIOR */
tobj->contours->type = GLU_EXTERIOR;
tmp_contour_ptr = tobj->contours;
/* now we play! */
for (i = 1; i < cnt; i++) {
hierarchy_changed = GL_FALSE;
for (tmp_contour_ptr = tobj->contours;
tmp_contour_ptr != NULL; tmp_contour_ptr = tmp_contour_ptr->next) {
if (tmp_contour_ptr->type == GLU_EXTERIOR) {
/* check if contour completely contained in EXTERIOR */
result = is_contour_contained_in(tmp_contour_ptr, contours[i]);
switch (result) {
case GLU_INTERIOR:
/* now we have to check if contour is inside interiors */
/* or not */
/* any interiors? */
if (tmp_contour_ptr->next != NULL &&
tmp_contour_ptr->next->type == GLU_INTERIOR) {
/* for all interior, check if inside any of them */
/* if not inside any of interiors, its another */
/* interior */
/* or it may contain some interiors, then change */
/* the contained interiors to exterior ones */
add_interior_with_hierarchy_check(tobj,
tmp_contour_ptr,
contours[i]);
}
else {
/* not in interior, add as new interior contour */
add_new_interior(tobj, tmp_contour_ptr, contours[i]);
}
hierarchy_changed = GL_TRUE;
break;
case GLU_EXTERIOR:
/* ooops, the marked as EXTERIOR (contours[i]) is */
/* actually an interior of tmp_contour_ptr */
/* reverse the local hierarchy */
reverse_hierarchy_and_add_exterior(tobj, tmp_contour_ptr,
contours[i]);
hierarchy_changed = GL_TRUE;
break;
case GLU_NO_ERROR:
break;
default:
abort();
}
}
if (hierarchy_changed)
break; /* break from for loop */
}
if (hierarchy_changed == GL_FALSE) {
/* disjoint with all contours, add to contour list */
add_new_exterior(tobj, contours[i]);
}
}
free(contours);
}
/* returns GLU_INTERIOR if inner is completey enclosed within outer */
/* returns GLU_EXTERIOR if outer is completely enclosed within inner */
/* returns GLU_NO_ERROR if contours are disjoint */
static GLenum
is_contour_contained_in(tess_contour * outer, tess_contour * inner)
{
GLenum relation_flag;
/* set relation_flag to relation of containment of first inner vertex */
/* regarding outer contour */
if (point_in_polygon(outer, inner->vertices->x, inner->vertices->y))
relation_flag = GLU_INTERIOR;
else
relation_flag = GLU_EXTERIOR;
if (relation_flag == GLU_INTERIOR)
return GLU_INTERIOR;
if (point_in_polygon(inner, outer->vertices->x, outer->vertices->y))
return GLU_EXTERIOR;
return GLU_NO_ERROR;
}
static GLboolean
point_in_polygon(tess_contour * contour, GLdouble x, GLdouble y)
{
tess_vertex *v1, *v2;
GLuint i, vertex_cnt;
GLdouble xp1, yp1, xp2, yp2;
GLboolean tst;
tst = GL_FALSE;
v1 = contour->vertices;
v2 = contour->vertices->previous;
for (i = 0, vertex_cnt = contour->vertex_cnt; i < vertex_cnt; i++) {
xp1 = v1->x;
yp1 = v1->y;
xp2 = v2->x;
yp2 = v2->y;
if ((((yp1 <= y) && (y < yp2)) || ((yp2 <= y) && (y < yp1))) &&
(x < (xp2 - xp1) * (y - yp1) / (yp2 - yp1) + xp1))
tst = (tst == GL_FALSE ? GL_TRUE : GL_FALSE);
v2 = v1;
v1 = v1->next;
}
return tst;
}
static GLenum
contours_overlap(tess_contour * contour, tess_polygon * polygon)
{
tess_vertex *vertex1, *vertex2;
GLuint vertex1_cnt, vertex2_cnt, i, j;
GLenum test;
vertex1 = contour->vertices;
vertex2 = polygon->vertices;
vertex1_cnt = contour->vertex_cnt;
vertex2_cnt = polygon->vertex_cnt;
for (i = 0; i < vertex1_cnt; vertex1 = vertex1->next, i++) {
for (j = 0; j < vertex2_cnt; vertex2 = vertex2->next, j++)
if ((test = edge_edge_intersect(vertex1, vertex1->next, vertex2,
vertex2->next)) != GLU_NO_ERROR)
return test;
}
return GLU_NO_ERROR;
}
static void
add_new_exterior(GLUtriangulatorObj * tobj, tess_contour * contour)
{
contour->type = GLU_EXTERIOR;
contour->next = NULL;
contour->previous = tobj->last_contour;
tobj->last_contour->next = contour;
tobj->last_contour = contour;
}
static void
add_new_interior(GLUtriangulatorObj * tobj,
tess_contour * outer, tess_contour * contour)
{
contour->type = GLU_INTERIOR;
contour->next = outer->next;
contour->previous = outer;
if (outer->next != NULL)
outer->next->previous = contour;
outer->next = contour;
if (tobj->last_contour == outer)
tobj->last_contour = contour;
}
static void
add_interior_with_hierarchy_check(GLUtriangulatorObj * tobj,
tess_contour * outer,
tess_contour * contour)
{
tess_contour *ptr;
/* for all interiors of outer check if they are interior of contour */
/* if so, change that interior to exterior and move it of of the */
/* interior sequence */
if (outer->next != NULL && outer->next->type == GLU_INTERIOR) {
GLenum test;
for (ptr = outer->next; ptr != NULL && ptr->type == GLU_INTERIOR;
ptr = ptr->next) {
test = is_contour_contained_in(ptr, contour);
switch (test) {
case GLU_INTERIOR:
/* contour is contained in one of the interiors */
/* check if possibly contained in other exteriors */
/* move ptr to first EXTERIOR */
for (; ptr != NULL && ptr->type == GLU_INTERIOR; ptr = ptr->next);
if (ptr == NULL)
/* another exterior */
add_new_exterior(tobj, contour);
else
add_exterior_with_check(tobj, ptr, contour);
return;
case GLU_EXTERIOR:
/* one of the interiors is contained in the contour */
/* change it to EXTERIOR, and shift it away from the */
/* interior sequence */
shift_interior_to_exterior(tobj, ptr);
break;
case GLU_NO_ERROR:
/* disjoint */
break;
default:
abort();
}
}
}
/* add contour to the interior sequence */
add_new_interior(tobj, outer, contour);
}
static void
reverse_hierarchy_and_add_exterior(GLUtriangulatorObj * tobj,
tess_contour * outer,
tess_contour * contour)
{
tess_contour *ptr;
/* reverse INTERIORS to EXTERIORS */
/* any INTERIORS? */
if (outer->next != NULL && outer->next->type == GLU_INTERIOR)
for (ptr = outer->next; ptr != NULL && ptr->type == GLU_INTERIOR;
ptr = ptr->next) ptr->type = GLU_EXTERIOR;
/* the outer now becomes inner */
outer->type = GLU_INTERIOR;
/* contour is the EXTERIOR */
contour->next = outer;
if (tobj->contours == outer) {
/* first contour beeing reversed */
contour->previous = NULL;
tobj->contours = contour;
}
else {
outer->previous->next = contour;
contour->previous = outer->previous;
}
outer->previous = contour;
}
static void
shift_interior_to_exterior(GLUtriangulatorObj * tobj, tess_contour * contour)
{
contour->previous->next = contour->next;
if (contour->next != NULL)
contour->next->previous = contour->previous;
else
tobj->last_contour = contour->previous;
}
static void
add_exterior_with_check(GLUtriangulatorObj * tobj,
tess_contour * outer, tess_contour * contour)
{
GLenum test;
/* this contour might be interior to further exteriors - check */
/* if not, just add as a new exterior */
for (; outer != NULL && outer->type == GLU_EXTERIOR; outer = outer->next) {
test = is_contour_contained_in(outer, contour);
switch (test) {
case GLU_INTERIOR:
/* now we have to check if contour is inside interiors */
/* or not */
/* any interiors? */
if (outer->next != NULL && outer->next->type == GLU_INTERIOR) {
/* for all interior, check if inside any of them */
/* if not inside any of interiors, its another */
/* interior */
/* or it may contain some interiors, then change */
/* the contained interiors to exterior ones */
add_interior_with_hierarchy_check(tobj, outer, contour);
}
else {
/* not in interior, add as new interior contour */
add_new_interior(tobj, outer, contour);
}
return;
case GLU_NO_ERROR:
/* disjoint */
break;
default:
abort();
}
}
/* add contour to the exterior sequence */
add_new_exterior(tobj, contour);
}
void
tess_handle_holes(GLUtriangulatorObj * tobj)
{
tess_contour *contour, *hole;
GLenum exterior_orientation;
/* verify hole orientation */
for (contour = tobj->contours; contour != NULL;) {
exterior_orientation = contour->orientation;
for (contour = contour->next;
contour != NULL && contour->type == GLU_INTERIOR;
contour = contour->next) {
if (contour->orientation == exterior_orientation) {
tess_call_user_error(tobj, GLU_TESS_ERROR5);
return;
}
}
}
/* now cut-out holes */
for (contour = tobj->contours; contour != NULL;) {
hole = contour->next;
while (hole != NULL && hole->type == GLU_INTERIOR) {
if (cut_out_hole(tobj, contour, hole) == GLU_ERROR)
return;
hole = contour->next;
}
contour = contour->next;
}
}
static GLenum
cut_out_hole(GLUtriangulatorObj * tobj,
tess_contour * contour, tess_contour * hole)
{
tess_contour *tmp_hole;
tess_vertex *v1, *v2, *tmp_vertex;
GLuint vertex1_cnt, vertex2_cnt, tmp_vertex_cnt;
GLuint i, j, k;
GLenum test = 0;
/* find an edge connecting contour and hole not intersecting any other */
/* edge belonging to either the contour or any of the other holes */
for (v1 = contour->vertices, vertex1_cnt = contour->vertex_cnt, i = 0;
i < vertex1_cnt; i++, v1 = v1->next) {
for (v2 = hole->vertices, vertex2_cnt = hole->vertex_cnt, j = 0;
j < vertex2_cnt; j++, v2 = v2->next) {
/* does edge (v1,v2) intersect any edge of contour */
for (tmp_vertex = contour->vertices, tmp_vertex_cnt =
contour->vertex_cnt, k = 0; k < tmp_vertex_cnt;
tmp_vertex = tmp_vertex->next, k++) {
/* skip edge tests for edges directly connected */
if (v1 == tmp_vertex || v1 == tmp_vertex->next)
continue;
test = edge_edge_intersect(v1, v2, tmp_vertex, tmp_vertex->next);
if (test != GLU_NO_ERROR)
break;
}
if (test == GLU_NO_ERROR) {
/* does edge (v1,v2) intersect any edge of hole */
for (tmp_vertex = hole->vertices,
tmp_vertex_cnt = hole->vertex_cnt, k = 0;
k < tmp_vertex_cnt; tmp_vertex = tmp_vertex->next, k++) {
/* skip edge tests for edges directly connected */
if (v2 == tmp_vertex || v2 == tmp_vertex->next)
continue;
test =
edge_edge_intersect(v1, v2, tmp_vertex, tmp_vertex->next);
if (test != GLU_NO_ERROR)
break;
}
if (test == GLU_NO_ERROR) {
/* does edge (v1,v2) intersect any other hole? */
for (tmp_hole = hole->next;
tmp_hole != NULL && tmp_hole->type == GLU_INTERIOR;
tmp_hole = tmp_hole->next) {
/* does edge (v1,v2) intersect any edge of hole */
for (tmp_vertex = tmp_hole->vertices,
tmp_vertex_cnt = tmp_hole->vertex_cnt, k = 0;
k < tmp_vertex_cnt; tmp_vertex = tmp_vertex->next, k++) {
test = edge_edge_intersect(v1, v2, tmp_vertex,
tmp_vertex->next);
if (test != GLU_NO_ERROR)
break;
}
if (test != GLU_NO_ERROR)
break;
}
}
}
if (test == GLU_NO_ERROR) {
/* edge (v1,v2) is good for eliminating the hole */
if (merge_hole_with_contour(tobj, contour, hole, v1, v2)
== GLU_NO_ERROR)
return GLU_NO_ERROR;
else
return GLU_ERROR;
}
}
}
/* other holes are blocking all possible connections of hole */
/* with contour, we shift this hole as the last hole and retry */
for (tmp_hole = hole;
tmp_hole != NULL && tmp_hole->type == GLU_INTERIOR;
tmp_hole = tmp_hole->next);
contour->next = hole->next;
hole->next->previous = contour;
if (tmp_hole == NULL) {
/* last EXTERIOR contour, shift hole as last contour */
hole->next = NULL;
hole->previous = tobj->last_contour;
tobj->last_contour->next = hole;
tobj->last_contour = hole;
}
else {
tmp_hole->previous->next = hole;
hole->previous = tmp_hole->previous;
tmp_hole->previous = hole;
hole->next = tmp_hole;
}
hole = contour->next;
/* try once again - recurse */
return cut_out_hole(tobj, contour, hole);
}
static GLenum
merge_hole_with_contour(GLUtriangulatorObj * tobj,
tess_contour * contour,
tess_contour * hole,
tess_vertex * v1, tess_vertex * v2)
{
tess_vertex *v1_new, *v2_new;
/* make copies of v1 and v2, place them respectively after their originals */
if ((v1_new = (tess_vertex *) malloc(sizeof(tess_vertex))) == NULL) {
tess_call_user_error(tobj, GLU_OUT_OF_MEMORY);
return GLU_ERROR;
}
if ((v2_new = (tess_vertex *) malloc(sizeof(tess_vertex))) == NULL) {
tess_call_user_error(tobj, GLU_OUT_OF_MEMORY);
return GLU_ERROR;
}
v1_new->edge_flag = GL_TRUE;
v1_new->data = v1->data;
v1_new->location[0] = v1->location[0];
v1_new->location[1] = v1->location[1];
v1_new->location[2] = v1->location[2];
v1_new->x = v1->x;
v1_new->y = v1->y;
v1_new->shadow_vertex = v1;
v1->shadow_vertex = v1_new;
v1_new->next = v1->next;
v1_new->previous = v1;
v1->next->previous = v1_new;
v1->next = v1_new;
v2_new->edge_flag = GL_TRUE;
v2_new->data = v2->data;
v2_new->location[0] = v2->location[0];
v2_new->location[1] = v2->location[1];
v2_new->location[2] = v2->location[2];
v2_new->x = v2->x;
v2_new->y = v2->y;
v2_new->shadow_vertex = v2;
v2->shadow_vertex = v2_new;
v2_new->next = v2->next;
v2_new->previous = v2;
v2->next->previous = v2_new;
v2->next = v2_new;
/* link together the two lists */
v1->next = v2_new;
v2_new->previous = v1;
v2->next = v1_new;
v1_new->previous = v2;
/* update the vertex count of the contour */
contour->vertex_cnt += hole->vertex_cnt + 2;
/* remove the INTERIOR contour */
contour->next = hole->next;
if (hole->next != NULL)
hole->next->previous = contour;
free(hole);
/* update tobj structure */
--(tobj->contour_cnt);
if (contour->last_vertex == v1)
contour->last_vertex = v1_new;
/* mark two vertices with edge_flag */
v2->edge_flag = GL_FALSE;
v1->edge_flag = GL_FALSE;
return GLU_NO_ERROR;
}

402
src/glu/mini/project.c Normal file
View File

@ -0,0 +1,402 @@
/* $Id: project.c,v 1.2 2003/08/22 20:11:43 brianp Exp $ */
/*
* Mesa 3-D graphics library
* Version: 3.3
* Copyright (C) 1995-2000 Brian Paul
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifdef PC_HEADER
#include "all.h"
#else
#include <stdio.h>
#include <string.h>
#include <math.h>
#include "gluP.h"
#endif
/*
* This code was contributed by Marc Buffat (buffat@mecaflu.ec-lyon.fr).
* Thanks Marc!!!
*/
/* implementation de gluProject et gluUnproject */
/* M. Buffat 17/2/95 */
/*
* Transform a point (column vector) by a 4x4 matrix. I.e. out = m * in
* Input: m - the 4x4 matrix
* in - the 4x1 vector
* Output: out - the resulting 4x1 vector.
*/
static void
transform_point(GLdouble out[4], const GLdouble m[16], const GLdouble in[4])
{
#define M(row,col) m[col*4+row]
out[0] =
M(0, 0) * in[0] + M(0, 1) * in[1] + M(0, 2) * in[2] + M(0, 3) * in[3];
out[1] =
M(1, 0) * in[0] + M(1, 1) * in[1] + M(1, 2) * in[2] + M(1, 3) * in[3];
out[2] =
M(2, 0) * in[0] + M(2, 1) * in[1] + M(2, 2) * in[2] + M(2, 3) * in[3];
out[3] =
M(3, 0) * in[0] + M(3, 1) * in[1] + M(3, 2) * in[2] + M(3, 3) * in[3];
#undef M
}
/*
* Perform a 4x4 matrix multiplication (product = a x b).
* Input: a, b - matrices to multiply
* Output: product - product of a and b
*/
static void
matmul(GLdouble * product, const GLdouble * a, const GLdouble * b)
{
/* This matmul was contributed by Thomas Malik */
GLdouble temp[16];
GLint i;
#define A(row,col) a[(col<<2)+row]
#define B(row,col) b[(col<<2)+row]
#define T(row,col) temp[(col<<2)+row]
/* i-te Zeile */
for (i = 0; i < 4; i++) {
T(i, 0) =
A(i, 0) * B(0, 0) + A(i, 1) * B(1, 0) + A(i, 2) * B(2, 0) + A(i,
3) *
B(3, 0);
T(i, 1) =
A(i, 0) * B(0, 1) + A(i, 1) * B(1, 1) + A(i, 2) * B(2, 1) + A(i,
3) *
B(3, 1);
T(i, 2) =
A(i, 0) * B(0, 2) + A(i, 1) * B(1, 2) + A(i, 2) * B(2, 2) + A(i,
3) *
B(3, 2);
T(i, 3) =
A(i, 0) * B(0, 3) + A(i, 1) * B(1, 3) + A(i, 2) * B(2, 3) + A(i,
3) *
B(3, 3);
}
#undef A
#undef B
#undef T
MEMCPY(product, temp, 16 * sizeof(GLdouble));
}
/*
* Compute inverse of 4x4 transformation matrix.
* Code contributed by Jacques Leroy jle@star.be
* Return GL_TRUE for success, GL_FALSE for failure (singular matrix)
*/
static GLboolean
invert_matrix(const GLdouble * m, GLdouble * out)
{
/* NB. OpenGL Matrices are COLUMN major. */
#define SWAP_ROWS(a, b) { GLdouble *_tmp = a; (a)=(b); (b)=_tmp; }
#define MAT(m,r,c) (m)[(c)*4+(r)]
GLdouble wtmp[4][8];
GLdouble m0, m1, m2, m3, s;
GLdouble *r0, *r1, *r2, *r3;
r0 = wtmp[0], r1 = wtmp[1], r2 = wtmp[2], r3 = wtmp[3];
r0[0] = MAT(m, 0, 0), r0[1] = MAT(m, 0, 1),
r0[2] = MAT(m, 0, 2), r0[3] = MAT(m, 0, 3),
r0[4] = 1.0, r0[5] = r0[6] = r0[7] = 0.0,
r1[0] = MAT(m, 1, 0), r1[1] = MAT(m, 1, 1),
r1[2] = MAT(m, 1, 2), r1[3] = MAT(m, 1, 3),
r1[5] = 1.0, r1[4] = r1[6] = r1[7] = 0.0,
r2[0] = MAT(m, 2, 0), r2[1] = MAT(m, 2, 1),
r2[2] = MAT(m, 2, 2), r2[3] = MAT(m, 2, 3),
r2[6] = 1.0, r2[4] = r2[5] = r2[7] = 0.0,
r3[0] = MAT(m, 3, 0), r3[1] = MAT(m, 3, 1),
r3[2] = MAT(m, 3, 2), r3[3] = MAT(m, 3, 3),
r3[7] = 1.0, r3[4] = r3[5] = r3[6] = 0.0;
/* choose pivot - or die */
if (fabs(r3[0]) > fabs(r2[0]))
SWAP_ROWS(r3, r2);
if (fabs(r2[0]) > fabs(r1[0]))
SWAP_ROWS(r2, r1);
if (fabs(r1[0]) > fabs(r0[0]))
SWAP_ROWS(r1, r0);
if (0.0 == r0[0])
return GL_FALSE;
/* eliminate first variable */
m1 = r1[0] / r0[0];
m2 = r2[0] / r0[0];
m3 = r3[0] / r0[0];
s = r0[1];
r1[1] -= m1 * s;
r2[1] -= m2 * s;
r3[1] -= m3 * s;
s = r0[2];
r1[2] -= m1 * s;
r2[2] -= m2 * s;
r3[2] -= m3 * s;
s = r0[3];
r1[3] -= m1 * s;
r2[3] -= m2 * s;
r3[3] -= m3 * s;
s = r0[4];
if (s != 0.0) {
r1[4] -= m1 * s;
r2[4] -= m2 * s;
r3[4] -= m3 * s;
}
s = r0[5];
if (s != 0.0) {
r1[5] -= m1 * s;
r2[5] -= m2 * s;
r3[5] -= m3 * s;
}
s = r0[6];
if (s != 0.0) {
r1[6] -= m1 * s;
r2[6] -= m2 * s;
r3[6] -= m3 * s;
}
s = r0[7];
if (s != 0.0) {
r1[7] -= m1 * s;
r2[7] -= m2 * s;
r3[7] -= m3 * s;
}
/* choose pivot - or die */
if (fabs(r3[1]) > fabs(r2[1]))
SWAP_ROWS(r3, r2);
if (fabs(r2[1]) > fabs(r1[1]))
SWAP_ROWS(r2, r1);
if (0.0 == r1[1])
return GL_FALSE;
/* eliminate second variable */
m2 = r2[1] / r1[1];
m3 = r3[1] / r1[1];
r2[2] -= m2 * r1[2];
r3[2] -= m3 * r1[2];
r2[3] -= m2 * r1[3];
r3[3] -= m3 * r1[3];
s = r1[4];
if (0.0 != s) {
r2[4] -= m2 * s;
r3[4] -= m3 * s;
}
s = r1[5];
if (0.0 != s) {
r2[5] -= m2 * s;
r3[5] -= m3 * s;
}
s = r1[6];
if (0.0 != s) {
r2[6] -= m2 * s;
r3[6] -= m3 * s;
}
s = r1[7];
if (0.0 != s) {
r2[7] -= m2 * s;
r3[7] -= m3 * s;
}
/* choose pivot - or die */
if (fabs(r3[2]) > fabs(r2[2]))
SWAP_ROWS(r3, r2);
if (0.0 == r2[2])
return GL_FALSE;
/* eliminate third variable */
m3 = r3[2] / r2[2];
r3[3] -= m3 * r2[3], r3[4] -= m3 * r2[4],
r3[5] -= m3 * r2[5], r3[6] -= m3 * r2[6], r3[7] -= m3 * r2[7];
/* last check */
if (0.0 == r3[3])
return GL_FALSE;
s = 1.0 / r3[3]; /* now back substitute row 3 */
r3[4] *= s;
r3[5] *= s;
r3[6] *= s;
r3[7] *= s;
m2 = r2[3]; /* now back substitute row 2 */
s = 1.0 / r2[2];
r2[4] = s * (r2[4] - r3[4] * m2), r2[5] = s * (r2[5] - r3[5] * m2),
r2[6] = s * (r2[6] - r3[6] * m2), r2[7] = s * (r2[7] - r3[7] * m2);
m1 = r1[3];
r1[4] -= r3[4] * m1, r1[5] -= r3[5] * m1,
r1[6] -= r3[6] * m1, r1[7] -= r3[7] * m1;
m0 = r0[3];
r0[4] -= r3[4] * m0, r0[5] -= r3[5] * m0,
r0[6] -= r3[6] * m0, r0[7] -= r3[7] * m0;
m1 = r1[2]; /* now back substitute row 1 */
s = 1.0 / r1[1];
r1[4] = s * (r1[4] - r2[4] * m1), r1[5] = s * (r1[5] - r2[5] * m1),
r1[6] = s * (r1[6] - r2[6] * m1), r1[7] = s * (r1[7] - r2[7] * m1);
m0 = r0[2];
r0[4] -= r2[4] * m0, r0[5] -= r2[5] * m0,
r0[6] -= r2[6] * m0, r0[7] -= r2[7] * m0;
m0 = r0[1]; /* now back substitute row 0 */
s = 1.0 / r0[0];
r0[4] = s * (r0[4] - r1[4] * m0), r0[5] = s * (r0[5] - r1[5] * m0),
r0[6] = s * (r0[6] - r1[6] * m0), r0[7] = s * (r0[7] - r1[7] * m0);
MAT(out, 0, 0) = r0[4];
MAT(out, 0, 1) = r0[5], MAT(out, 0, 2) = r0[6];
MAT(out, 0, 3) = r0[7], MAT(out, 1, 0) = r1[4];
MAT(out, 1, 1) = r1[5], MAT(out, 1, 2) = r1[6];
MAT(out, 1, 3) = r1[7], MAT(out, 2, 0) = r2[4];
MAT(out, 2, 1) = r2[5], MAT(out, 2, 2) = r2[6];
MAT(out, 2, 3) = r2[7], MAT(out, 3, 0) = r3[4];
MAT(out, 3, 1) = r3[5], MAT(out, 3, 2) = r3[6];
MAT(out, 3, 3) = r3[7];
return GL_TRUE;
#undef MAT
#undef SWAP_ROWS
}
/* projection du point (objx,objy,obz) sur l'ecran (winx,winy,winz) */
GLint GLAPIENTRY
gluProject(GLdouble objx, GLdouble objy, GLdouble objz,
const GLdouble model[16], const GLdouble proj[16],
const GLint viewport[4],
GLdouble * winx, GLdouble * winy, GLdouble * winz)
{
/* matrice de transformation */
GLdouble in[4], out[4];
/* initilise la matrice et le vecteur a transformer */
in[0] = objx;
in[1] = objy;
in[2] = objz;
in[3] = 1.0;
transform_point(out, model, in);
transform_point(in, proj, out);
/* d'ou le resultat normalise entre -1 et 1 */
if (in[3] == 0.0)
return GL_FALSE;
in[0] /= in[3];
in[1] /= in[3];
in[2] /= in[3];
/* en coordonnees ecran */
*winx = viewport[0] + (1 + in[0]) * viewport[2] / 2;
*winy = viewport[1] + (1 + in[1]) * viewport[3] / 2;
/* entre 0 et 1 suivant z */
*winz = (1 + in[2]) / 2;
return GL_TRUE;
}
/* transformation du point ecran (winx,winy,winz) en point objet */
GLint GLAPIENTRY
gluUnProject(GLdouble winx, GLdouble winy, GLdouble winz,
const GLdouble model[16], const GLdouble proj[16],
const GLint viewport[4],
GLdouble * objx, GLdouble * objy, GLdouble * objz)
{
/* matrice de transformation */
GLdouble m[16], A[16];
GLdouble in[4], out[4];
/* transformation coordonnees normalisees entre -1 et 1 */
in[0] = (winx - viewport[0]) * 2 / viewport[2] - 1.0;
in[1] = (winy - viewport[1]) * 2 / viewport[3] - 1.0;
in[2] = 2 * winz - 1.0;
in[3] = 1.0;
/* calcul transformation inverse */
matmul(A, proj, model);
invert_matrix(A, m);
/* d'ou les coordonnees objets */
transform_point(out, m, in);
if (out[3] == 0.0)
return GL_FALSE;
*objx = out[0] / out[3];
*objy = out[1] / out[3];
*objz = out[2] / out[3];
return GL_TRUE;
}
/*
* New in GLU 1.3
* This is like gluUnProject but also takes near and far DepthRange values.
*/
#ifdef GLU_VERSION_1_3
GLint GLAPIENTRY
gluUnProject4(GLdouble winx, GLdouble winy, GLdouble winz, GLdouble clipw,
const GLdouble modelMatrix[16],
const GLdouble projMatrix[16],
const GLint viewport[4],
GLclampd nearZ, GLclampd farZ,
GLdouble * objx, GLdouble * objy, GLdouble * objz,
GLdouble * objw)
{
/* matrice de transformation */
GLdouble m[16], A[16];
GLdouble in[4], out[4];
GLdouble z = nearZ + winz * (farZ - nearZ);
/* transformation coordonnees normalisees entre -1 et 1 */
in[0] = (winx - viewport[0]) * 2 / viewport[2] - 1.0;
in[1] = (winy - viewport[1]) * 2 / viewport[3] - 1.0;
in[2] = 2.0 * z - 1.0;
in[3] = clipw;
/* calcul transformation inverse */
matmul(A, projMatrix, modelMatrix);
invert_matrix(A, m);
/* d'ou les coordonnees objets */
transform_point(out, m, in);
if (out[3] == 0.0)
return GL_FALSE;
*objx = out[0] / out[3];
*objy = out[1] / out[3];
*objz = out[2] / out[3];
*objw = out[3];
return GL_TRUE;
}
#endif

774
src/glu/mini/quadric.c Normal file
View File

@ -0,0 +1,774 @@
/* $Id: quadric.c,v 1.2 2003/08/22 20:11:43 brianp Exp $ */
/*
* Mesa 3-D graphics library
* Version: 3.3
* Copyright (C) 1999-2000 Brian Paul
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* TODO:
* texture coordinate support
* flip normals according to orientation
* there's still some inside/outside orientation bugs in possibly all
* but the sphere function
*/
#ifdef PC_HEADER
#include "all.h"
#else
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include "gluP.h"
#endif
#ifndef M_PI
# define M_PI (3.1415926)
#endif
/*
* Convert degrees to radians:
*/
#define DEG_TO_RAD(A) ((A)*(M_PI/180.0))
/*
* Sin and Cos for degree angles:
*/
#define SIND( A ) sin( (A)*(M_PI/180.0) )
#define COSD( A) cos( (A)*(M_PI/180.0) )
/*
* Texture coordinates if texture flag is set
*/
#define TXTR_COORD(x,y) if (qobj->TextureFlag) glTexCoord2f(x,y);
struct GLUquadric
{
GLenum DrawStyle; /* GLU_FILL, LINE, SILHOUETTE, or POINT */
GLenum Orientation; /* GLU_INSIDE or GLU_OUTSIDE */
GLboolean TextureFlag; /* Generate texture coords? */
GLenum Normals; /* GLU_NONE, GLU_FLAT, or GLU_SMOOTH */
void (GLCALLBACK * ErrorFunc) (GLenum err); /* Error handler callback function */
};
/*
* Process a GLU error.
*/
static void
quadric_error(GLUquadricObj * qobj, GLenum error, const char *msg)
{
/* Call the error call back function if any */
if (qobj->ErrorFunc) {
(*qobj->ErrorFunc) (error);
}
/* Print a message to stdout if MESA_DEBUG variable is defined */
if (getenv("MESA_DEBUG")) {
fprintf(stderr, "GLUError: %s: %s\n", (char *) gluErrorString(error),
msg);
}
}
GLUquadricObj *GLAPIENTRY
gluNewQuadric(void)
{
GLUquadricObj *q;
q = (GLUquadricObj *) malloc(sizeof(struct GLUquadric));
if (q) {
q->DrawStyle = GLU_FILL;
q->Orientation = GLU_OUTSIDE;
q->TextureFlag = GL_FALSE;
q->Normals = GLU_SMOOTH;
q->ErrorFunc = NULL;
}
return q;
}
void GLAPIENTRY
gluDeleteQuadric(GLUquadricObj * state)
{
if (state) {
free((void *) state);
}
}
/*
* Set the drawing style to be GLU_FILL, GLU_LINE, GLU_SILHOUETTE,
* or GLU_POINT.
*/
void GLAPIENTRY
gluQuadricDrawStyle(GLUquadricObj * quadObject, GLenum drawStyle)
{
if (quadObject && (drawStyle == GLU_FILL || drawStyle == GLU_LINE
|| drawStyle == GLU_SILHOUETTE
|| drawStyle == GLU_POINT)) {
quadObject->DrawStyle = drawStyle;
}
else {
quadric_error(quadObject, GLU_INVALID_ENUM, "qluQuadricDrawStyle");
}
}
/*
* Set the orientation to GLU_INSIDE or GLU_OUTSIDE.
*/
void GLAPIENTRY
gluQuadricOrientation(GLUquadricObj * quadObject, GLenum orientation)
{
if (quadObject
&& (orientation == GLU_INSIDE || orientation == GLU_OUTSIDE)) {
quadObject->Orientation = orientation;
}
else {
quadric_error(quadObject, GLU_INVALID_ENUM, "qluQuadricOrientation");
}
}
/*
* Set the error handler callback function.
*/
void GLAPIENTRY
gluQuadricCallback(GLUquadricObj * qobj,
GLenum which, void (GLCALLBACK * fn) ())
{
/*
* UGH, this is a mess! I thought ANSI was a standard.
*/
if (qobj && which == GLU_ERROR) {
#ifdef __CYGWIN32__
qobj->ErrorFunc = (void (GLCALLBACKPCAST) (GLenum)) fn;
#elif defined(OPENSTEP)
qobj->ErrorFunc = (void (*)(GLenum)) fn;
#elif defined(_WIN32)
qobj->ErrorFunc = (void (GLCALLBACK *) (int)) fn;
#elif defined(__STORM__)
qobj->ErrorFunc = (void (GLCALLBACK *) (GLenum)) fn;
#elif defined(__BEOS__)
qobj->ErrorFunc = (void (*)(GLenum)) fn;
#else
qobj->ErrorFunc = (void (GLCALLBACK *) ()) fn;
#endif
}
}
void GLAPIENTRY
gluQuadricNormals(GLUquadricObj * quadObject, GLenum normals)
{
if (quadObject
&& (normals == GLU_NONE || normals == GLU_FLAT
|| normals == GLU_SMOOTH)) {
quadObject->Normals = normals;
}
}
void GLAPIENTRY
gluQuadricTexture(GLUquadricObj * quadObject, GLboolean textureCoords)
{
if (quadObject) {
quadObject->TextureFlag = textureCoords;
}
}
/*
* Call glNormal3f after scaling normal to unit length.
*/
static void
normal3f(GLfloat x, GLfloat y, GLfloat z)
{
}
void GLAPIENTRY
gluCylinder(GLUquadricObj * qobj,
GLdouble baseRadius, GLdouble topRadius,
GLdouble height, GLint slices, GLint stacks)
{
GLdouble da, r, dr, dz;
GLfloat x, y, z, nz, nsign;
GLint i, j;
if (qobj->Orientation == GLU_INSIDE) {
nsign = -1.0;
}
else {
nsign = 1.0;
}
da = 2.0 * M_PI / slices;
dr = (topRadius - baseRadius) / stacks;
dz = height / stacks;
nz = (baseRadius - topRadius) / height; /* Z component of normal vectors */
if (qobj->DrawStyle == GLU_POINT) {
glBegin(GL_POINTS);
for (i = 0; i < slices; i++) {
x = cos(i * da);
y = sin(i * da);
normal3f(x * nsign, y * nsign, nz * nsign);
z = 0.0;
r = baseRadius;
for (j = 0; j <= stacks; j++) {
glVertex3f(x * r, y * r, z);
z += dz;
r += dr;
}
}
glEnd();
}
else if (qobj->DrawStyle == GLU_LINE || qobj->DrawStyle == GLU_SILHOUETTE) {
/* Draw rings */
if (qobj->DrawStyle == GLU_LINE) {
z = 0.0;
r = baseRadius;
for (j = 0; j <= stacks; j++) {
glBegin(GL_LINE_LOOP);
for (i = 0; i < slices; i++) {
x = cos(i * da);
y = sin(i * da);
normal3f(x * nsign, y * nsign, nz * nsign);
glVertex3f(x * r, y * r, z);
}
glEnd();
z += dz;
r += dr;
}
}
else {
/* draw one ring at each end */
if (baseRadius != 0.0) {
glBegin(GL_LINE_LOOP);
for (i = 0; i < slices; i++) {
x = cos(i * da);
y = sin(i * da);
normal3f(x * nsign, y * nsign, nz * nsign);
glVertex3f(x * baseRadius, y * baseRadius, 0.0);
}
glEnd();
glBegin(GL_LINE_LOOP);
for (i = 0; i < slices; i++) {
x = cos(i * da);
y = sin(i * da);
normal3f(x * nsign, y * nsign, nz * nsign);
glVertex3f(x * topRadius, y * topRadius, height);
}
glEnd();
}
}
/* draw length lines */
glBegin(GL_LINES);
for (i = 0; i < slices; i++) {
x = cos(i * da);
y = sin(i * da);
normal3f(x * nsign, y * nsign, nz * nsign);
glVertex3f(x * baseRadius, y * baseRadius, 0.0);
glVertex3f(x * topRadius, y * topRadius, height);
}
glEnd();
}
else if (qobj->DrawStyle == GLU_FILL) {
GLfloat ds = 1.0 / slices;
GLfloat dt = 1.0 / stacks;
GLfloat t = 0.0;
z = 0.0;
r = baseRadius;
for (j = 0; j < stacks; j++) {
GLfloat s = 0.0;
glBegin(GL_QUAD_STRIP);
for (i = 0; i <= slices; i++) {
GLfloat x, y;
if (i == slices) {
x = sin(0.0);
y = cos(0.0);
}
else {
x = sin(i * da);
y = cos(i * da);
}
if (nsign == 1.0) {
normal3f(x * nsign, y * nsign, nz * nsign);
TXTR_COORD(s, t);
glVertex3f(x * r, y * r, z);
normal3f(x * nsign, y * nsign, nz * nsign);
TXTR_COORD(s, t + dt);
glVertex3f(x * (r + dr), y * (r + dr), z + dz);
}
else {
normal3f(x * nsign, y * nsign, nz * nsign);
TXTR_COORD(s, t);
glVertex3f(x * r, y * r, z);
normal3f(x * nsign, y * nsign, nz * nsign);
TXTR_COORD(s, t + dt);
glVertex3f(x * (r + dr), y * (r + dr), z + dz);
}
s += ds;
} /* for slices */
glEnd();
r += dr;
t += dt;
z += dz;
} /* for stacks */
}
}
void GLAPIENTRY
gluSphere(GLUquadricObj * qobj, GLdouble radius, GLint slices, GLint stacks)
{
GLfloat rho, drho, theta, dtheta;
GLfloat x, y, z;
GLfloat s, t, ds, dt;
GLint i, j, imin, imax;
GLboolean normals;
GLfloat nsign;
if (qobj->Normals == GLU_NONE) {
normals = GL_FALSE;
}
else {
normals = GL_TRUE;
}
if (qobj->Orientation == GLU_INSIDE) {
nsign = -1.0;
}
else {
nsign = 1.0;
}
drho = M_PI / (GLfloat) stacks;
dtheta = 2.0 * M_PI / (GLfloat) slices;
/* texturing: s goes from 0.0/0.25/0.5/0.75/1.0 at +y/+x/-y/-x/+y axis */
/* t goes from -1.0/+1.0 at z = -radius/+radius (linear along longitudes) */
/* cannot use triangle fan on texturing (s coord. at top/bottom tip varies) */
if (qobj->DrawStyle == GLU_FILL) {
if (!qobj->TextureFlag) {
/* draw +Z end as a triangle fan */
glBegin(GL_TRIANGLE_FAN);
/* glNormal3f(0.0, 0.0, 1.0); */
glVertex3f(0.0, 0.0, nsign * radius);
for (j = 0; j <= slices; j++) {
theta = (j == slices) ? 0.0 : j * dtheta;
x = -sin(theta) * sin(drho);
y = cos(theta) * sin(drho);
z = nsign * cos(drho);
glVertex3f(x * radius, y * radius, z * radius);
}
glEnd();
}
ds = 1.0 / slices;
dt = 1.0 / stacks;
t = 1.0; /* because loop now runs from 0 */
if (qobj->TextureFlag) {
imin = 0;
imax = stacks;
}
else {
imin = 1;
imax = stacks - 1;
}
/* draw intermediate stacks as quad strips */
for (i = imin; i < imax; i++) {
rho = i * drho;
glBegin(GL_QUAD_STRIP);
s = 0.0;
for (j = 0; j <= slices; j++) {
theta = (j == slices) ? 0.0 : j * dtheta;
x = -sin(theta) * sin(rho);
y = cos(theta) * sin(rho);
z = nsign * cos(rho);
TXTR_COORD(s, t);
glVertex3f(x * radius, y * radius, z * radius);
x = -sin(theta) * sin(rho + drho);
y = cos(theta) * sin(rho + drho);
z = nsign * cos(rho + drho);
TXTR_COORD(s, t - dt);
s += ds;
glVertex3f(x * radius, y * radius, z * radius);
}
glEnd();
t -= dt;
}
if (!qobj->TextureFlag) {
/* draw -Z end as a triangle fan */
glBegin(GL_TRIANGLE_FAN);
glVertex3f(0.0, 0.0, -radius * nsign);
rho = M_PI - drho;
s = 1.0;
t = dt;
for (j = slices; j >= 0; j--) {
theta = (j == slices) ? 0.0 : j * dtheta;
x = -sin(theta) * sin(rho);
y = cos(theta) * sin(rho);
z = nsign * cos(rho);
s -= ds;
glVertex3f(x * radius, y * radius, z * radius);
}
glEnd();
}
}
else if (qobj->DrawStyle == GLU_LINE || qobj->DrawStyle == GLU_SILHOUETTE) {
/* draw stack lines */
for (i = 1; i < stacks; i++) { /* stack line at i==stacks-1 was missing here */
rho = i * drho;
glBegin(GL_LINE_LOOP);
for (j = 0; j < slices; j++) {
theta = j * dtheta;
x = cos(theta) * sin(rho);
y = sin(theta) * sin(rho);
z = cos(rho);
glVertex3f(x * radius, y * radius, z * radius);
}
glEnd();
}
/* draw slice lines */
for (j = 0; j < slices; j++) {
theta = j * dtheta;
glBegin(GL_LINE_STRIP);
for (i = 0; i <= stacks; i++) {
rho = i * drho;
x = cos(theta) * sin(rho);
y = sin(theta) * sin(rho);
z = cos(rho);
glVertex3f(x * radius, y * radius, z * radius);
}
glEnd();
}
}
else if (qobj->DrawStyle == GLU_POINT) {
/* top and bottom-most points */
glBegin(GL_POINTS);
glVertex3f(0.0, 0.0, radius);
glVertex3f(0.0, 0.0, -radius);
/* loop over stacks */
for (i = 1; i < stacks - 1; i++) {
rho = i * drho;
for (j = 0; j < slices; j++) {
theta = j * dtheta;
x = cos(theta) * sin(rho);
y = sin(theta) * sin(rho);
z = cos(rho);
glVertex3f(x * radius, y * radius, z * radius);
}
}
glEnd();
}
}
void GLAPIENTRY
gluDisk(GLUquadricObj * qobj,
GLdouble innerRadius, GLdouble outerRadius, GLint slices, GLint loops)
{
GLfloat da, dr;
#if 0
GLdouble a, da;
GLfloat r, dr;
GLfloat x, y;
GLfloat r1, r2, dtc;
GLint s, l;
#endif
da = 2.0 * M_PI / slices;
dr = (outerRadius - innerRadius) / (GLfloat) loops;
switch (qobj->DrawStyle) {
case GLU_FILL:
{
/* texture of a gluDisk is a cut out of the texture unit square
* x, y in [-outerRadius, +outerRadius]; s, t in [0, 1]
* (linear mapping)
*/
GLfloat dtc = 2.0f * outerRadius;
GLfloat sa, ca;
GLfloat r1 = innerRadius;
GLint l;
for (l = 0; l < loops; l++) {
GLfloat r2 = r1 + dr;
if (qobj->Orientation == GLU_OUTSIDE) {
GLint s;
glBegin(GL_QUAD_STRIP);
for (s = 0; s <= slices; s++) {
GLfloat a;
if (s == slices)
a = 0.0;
else
a = s * da;
sa = sin(a);
ca = cos(a);
TXTR_COORD(0.5 + sa * r2 / dtc, 0.5 + ca * r2 / dtc);
glVertex2f(r2 * sa, r2 * ca);
TXTR_COORD(0.5 + sa * r1 / dtc, 0.5 + ca * r1 / dtc);
glVertex2f(r1 * sa, r1 * ca);
}
glEnd();
}
else {
GLint s;
glBegin(GL_QUAD_STRIP);
for (s = slices; s >= 0; s--) {
GLfloat a;
if (s == slices)
a = 0.0;
else
a = s * da;
sa = sin(a);
ca = cos(a);
TXTR_COORD(0.5 - sa * r2 / dtc, 0.5 + ca * r2 / dtc);
glVertex2f(r2 * sa, r2 * ca);
TXTR_COORD(0.5 - sa * r1 / dtc, 0.5 + ca * r1 / dtc);
glVertex2f(r1 * sa, r1 * ca);
}
glEnd();
}
r1 = r2;
}
break;
}
case GLU_LINE:
{
GLint l, s;
/* draw loops */
for (l = 0; l <= loops; l++) {
GLfloat r = innerRadius + l * dr;
glBegin(GL_LINE_LOOP);
for (s = 0; s < slices; s++) {
GLfloat a = s * da;
glVertex2f(r * sin(a), r * cos(a));
}
glEnd();
}
/* draw spokes */
for (s = 0; s < slices; s++) {
GLfloat a = s * da;
GLfloat x = sin(a);
GLfloat y = cos(a);
glBegin(GL_LINE_STRIP);
for (l = 0; l <= loops; l++) {
GLfloat r = innerRadius + l * dr;
glVertex2f(r * x, r * y);
}
glEnd();
}
break;
}
case GLU_POINT:
{
GLint s;
glBegin(GL_POINTS);
for (s = 0; s < slices; s++) {
GLfloat a = s * da;
GLfloat x = sin(a);
GLfloat y = cos(a);
GLint l;
for (l = 0; l <= loops; l++) {
GLfloat r = innerRadius * l * dr;
glVertex2f(r * x, r * y);
}
}
glEnd();
break;
}
case GLU_SILHOUETTE:
{
if (innerRadius != 0.0) {
GLfloat a;
glBegin(GL_LINE_LOOP);
for (a = 0.0; a < 2.0 * M_PI; a += da) {
GLfloat x = innerRadius * sin(a);
GLfloat y = innerRadius * cos(a);
glVertex2f(x, y);
}
glEnd();
}
{
GLfloat a;
glBegin(GL_LINE_LOOP);
for (a = 0; a < 2.0 * M_PI; a += da) {
GLfloat x = outerRadius * sin(a);
GLfloat y = outerRadius * cos(a);
glVertex2f(x, y);
}
glEnd();
}
break;
}
default:
abort();
}
}
void GLAPIENTRY
gluPartialDisk(GLUquadricObj * qobj, GLdouble innerRadius,
GLdouble outerRadius, GLint slices, GLint loops,
GLdouble startAngle, GLdouble sweepAngle)
{
if (qobj->DrawStyle == GLU_POINT) {
GLint loop, slice;
GLdouble radius, delta_radius;
GLdouble angle, delta_angle;
delta_radius = (outerRadius - innerRadius) / (loops - 1);
delta_angle = DEG_TO_RAD((sweepAngle) / (slices - 1));
glBegin(GL_POINTS);
radius = innerRadius;
for (loop = 0; loop < loops; loop++) {
angle = DEG_TO_RAD(startAngle);
for (slice = 0; slice < slices; slice++) {
glVertex2f(radius * sin(angle), radius * cos(angle));
angle += delta_angle;
}
radius += delta_radius;
}
glEnd();
}
else if (qobj->DrawStyle == GLU_LINE) {
GLint loop, slice;
GLdouble radius, delta_radius;
GLdouble angle, delta_angle;
delta_radius = (outerRadius - innerRadius) / loops;
delta_angle = DEG_TO_RAD(sweepAngle / slices);
/* draw rings */
radius = innerRadius;
for (loop = 0; loop < loops; loop++) {
angle = DEG_TO_RAD(startAngle);
glBegin(GL_LINE_STRIP);
for (slice = 0; slice <= slices; slice++) {
glVertex2f(radius * sin(angle), radius * cos(angle));
angle += delta_angle;
}
glEnd();
radius += delta_radius;
}
/* draw spokes */
angle = DEG_TO_RAD(startAngle);
for (slice = 0; slice <= slices; slice++) {
radius = innerRadius;
glBegin(GL_LINE_STRIP);
for (loop = 0; loop < loops; loop++) {
glVertex2f(radius * sin(angle), radius * cos(angle));
radius += delta_radius;
}
glEnd();
angle += delta_angle;
}
}
else if (qobj->DrawStyle == GLU_SILHOUETTE) {
GLint slice;
GLdouble angle, delta_angle;
delta_angle = DEG_TO_RAD(sweepAngle / slices);
/* draw outer ring */
glBegin(GL_LINE_STRIP);
angle = DEG_TO_RAD(startAngle);
for (slice = 0; slice <= slices; slice++) {
glVertex2f(outerRadius * sin(angle), outerRadius * cos(angle));
angle += delta_angle;
}
glEnd();
/* draw inner ring */
if (innerRadius > 0.0) {
glBegin(GL_LINE_STRIP);
angle = DEG_TO_RAD(startAngle);
for (slice = 0; slice < slices; slice++) {
glVertex2f(innerRadius * sin(angle), innerRadius * cos(angle));
angle += delta_angle;
}
glEnd();
}
/* draw spokes */
if (sweepAngle < 360.0) {
GLdouble stopAngle = startAngle + sweepAngle;
glBegin(GL_LINES);
glVertex2f(innerRadius * SIND(startAngle),
innerRadius * COSD(startAngle));
glVertex2f(outerRadius * SIND(startAngle),
outerRadius * COSD(startAngle));
glVertex2f(innerRadius * SIND(stopAngle),
innerRadius * COSD(stopAngle));
glVertex2f(outerRadius * SIND(stopAngle),
outerRadius * COSD(stopAngle));
glEnd();
}
}
else if (qobj->DrawStyle == GLU_FILL) {
GLint loop, slice;
GLdouble radius, delta_radius;
GLdouble angle, delta_angle;
delta_radius = (outerRadius - innerRadius) / loops;
delta_angle = DEG_TO_RAD(sweepAngle / slices);
radius = innerRadius;
for (loop = 0; loop < loops; loop++) {
glBegin(GL_QUAD_STRIP);
angle = DEG_TO_RAD(startAngle);
for (slice = 0; slice <= slices; slice++) {
if (qobj->Orientation == GLU_OUTSIDE) {
glVertex2f((radius + delta_radius) * sin(angle),
(radius + delta_radius) * cos(angle));
glVertex2f(radius * sin(angle), radius * cos(angle));
}
else {
glVertex2f(radius * sin(angle), radius * cos(angle));
glVertex2f((radius + delta_radius) * sin(angle),
(radius + delta_radius) * cos(angle));
}
angle += delta_angle;
}
glEnd();
radius += delta_radius;
}
}
}

328
src/glu/mini/tess.c Normal file
View File

@ -0,0 +1,328 @@
/* $Id: tess.c,v 1.2 2003/08/22 20:11:43 brianp Exp $ */
/*
* Mesa 3-D graphics library
* Version: 3.3
* Copyright (C) 1995-2000 Brian Paul
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* This file is part of the polygon tesselation code contributed by
* Bogdan Sikorski
*/
#ifdef PC_HEADER
#include "all.h"
#else
#include <math.h>
#include <stdlib.h>
#include "tess.h"
#endif
/*
* This is ugly, but seems the easiest way to do things to make the
* code work under YellowBox for Windows
*/
#if defined(OPENSTEP) && defined(CALLBACK)
#undef CALLBACK
#define CALLBACK
#endif
static void delete_contours(GLUtriangulatorObj *);
#ifdef __CYGWIN32__
#define _CALLBACK
#else
#define _CALLBACK GLCALLBACK
#endif
static void
init_callbacks(tess_callbacks * callbacks)
{
callbacks->begin = (void (_CALLBACK *) (GLenum)) 0;
callbacks->edgeFlag = (void (_CALLBACK *) (GLboolean)) 0;
callbacks->vertex = (void (_CALLBACK *) (void *)) 0;
callbacks->end = (void (_CALLBACK *) (void)) 0;
callbacks->error = (void (_CALLBACK *) (GLenum)) 0;
}
void
tess_call_user_error(GLUtriangulatorObj * tobj, GLenum gluerr)
{
if (tobj->error == GLU_NO_ERROR)
tobj->error = gluerr;
if (tobj->callbacks.error != NULL)
(tobj->callbacks.error) (gluerr);
}
GLUtriangulatorObj *GLAPIENTRY
gluNewTess(void)
{
GLUtriangulatorObj *tobj;
if ((tobj = (GLUtriangulatorObj *)
malloc(sizeof(struct GLUtesselator))) == NULL)
return NULL;
tobj->contours = tobj->last_contour = NULL;
init_callbacks(&tobj->callbacks);
tobj->error = GLU_NO_ERROR;
tobj->current_polygon = NULL;
tobj->contour_cnt = 0;
return tobj;
}
void GLAPIENTRY
gluTessCallback(GLUtriangulatorObj * tobj, GLenum which,
void (GLCALLBACK * fn) ())
{
switch (which) {
case GLU_BEGIN:
tobj->callbacks.begin = (void (_CALLBACK *) (GLenum)) fn;
break;
case GLU_EDGE_FLAG:
tobj->callbacks.edgeFlag = (void (_CALLBACK *) (GLboolean)) fn;
break;
case GLU_VERTEX:
tobj->callbacks.vertex = (void (_CALLBACK *) (void *)) fn;
break;
case GLU_END:
tobj->callbacks.end = (void (_CALLBACK *) (void)) fn;
break;
case GLU_ERROR:
tobj->callbacks.error = (void (_CALLBACK *) (GLenum)) fn;
break;
default:
tobj->error = GLU_INVALID_ENUM;
break;
}
}
void GLAPIENTRY
gluDeleteTess(GLUtriangulatorObj * tobj)
{
if (tobj->error == GLU_NO_ERROR && tobj->contour_cnt)
/* was gluEndPolygon called? */
tess_call_user_error(tobj, GLU_TESS_ERROR1);
/* delete all internal structures */
delete_contours(tobj);
free(tobj);
}
void GLAPIENTRY
gluBeginPolygon(GLUtriangulatorObj * tobj)
{
/*
if(tobj->error!=GLU_NO_ERROR)
return;
*/
tobj->error = GLU_NO_ERROR;
if (tobj->current_polygon != NULL) {
/* gluEndPolygon was not called */
tess_call_user_error(tobj, GLU_TESS_ERROR1);
/* delete all internal structures */
delete_contours(tobj);
}
else {
if ((tobj->current_polygon =
(tess_polygon *) malloc(sizeof(tess_polygon))) == NULL) {
tess_call_user_error(tobj, GLU_OUT_OF_MEMORY);
return;
}
tobj->current_polygon->vertex_cnt = 0;
tobj->current_polygon->vertices =
tobj->current_polygon->last_vertex = NULL;
}
}
void GLAPIENTRY
gluEndPolygon(GLUtriangulatorObj * tobj)
{
/*tess_contour *contour_ptr; */
/* there was an error */
if (tobj->error != GLU_NO_ERROR)
goto end;
/* check if gluBeginPolygon was called */
if (tobj->current_polygon == NULL) {
tess_call_user_error(tobj, GLU_TESS_ERROR2);
return;
}
tess_test_polygon(tobj);
/* there was an error */
if (tobj->error != GLU_NO_ERROR)
goto end;
/* any real contours? */
if (tobj->contour_cnt == 0) {
/* delete all internal structures */
delete_contours(tobj);
return;
}
tess_find_contour_hierarchies(tobj);
/* there was an error */
if (tobj->error != GLU_NO_ERROR)
goto end;
tess_handle_holes(tobj);
/* there was an error */
if (tobj->error != GLU_NO_ERROR)
goto end;
/* if no callbacks, nothing to do */
if (tobj->callbacks.begin != NULL && tobj->callbacks.vertex != NULL &&
tobj->callbacks.end != NULL) {
if (tobj->callbacks.edgeFlag == NULL)
tess_tesselate(tobj);
else
tess_tesselate_with_edge_flag(tobj);
}
end:
/* delete all internal structures */
delete_contours(tobj);
}
void GLAPIENTRY
gluNextContour(GLUtriangulatorObj * tobj, GLenum type)
{
if (tobj->error != GLU_NO_ERROR)
return;
if (tobj->current_polygon == NULL) {
tess_call_user_error(tobj, GLU_TESS_ERROR2);
return;
}
/* first contour? */
if (tobj->current_polygon->vertex_cnt)
tess_test_polygon(tobj);
}
void GLAPIENTRY
gluTessVertex(GLUtriangulatorObj * tobj, GLdouble v[3], void *data)
{
tess_polygon *polygon = tobj->current_polygon;
tess_vertex *last_vertex_ptr;
if (tobj->error != GLU_NO_ERROR)
return;
if (polygon == NULL) {
tess_call_user_error(tobj, GLU_TESS_ERROR2);
return;
}
last_vertex_ptr = polygon->last_vertex;
if (last_vertex_ptr == NULL) {
if ((last_vertex_ptr = (tess_vertex *)
malloc(sizeof(tess_vertex))) == NULL) {
tess_call_user_error(tobj, GLU_OUT_OF_MEMORY);
return;
}
polygon->vertices = last_vertex_ptr;
polygon->last_vertex = last_vertex_ptr;
last_vertex_ptr->data = data;
last_vertex_ptr->location[0] = v[0];
last_vertex_ptr->location[1] = v[1];
last_vertex_ptr->location[2] = v[2];
last_vertex_ptr->next = NULL;
last_vertex_ptr->previous = NULL;
++(polygon->vertex_cnt);
}
else {
tess_vertex *vertex_ptr;
/* same point twice? */
if (fabs(last_vertex_ptr->location[0] - v[0]) < EPSILON &&
fabs(last_vertex_ptr->location[1] - v[1]) < EPSILON &&
fabs(last_vertex_ptr->location[2] - v[2]) < EPSILON) {
tess_call_user_error(tobj, GLU_TESS_ERROR6);
return;
}
if ((vertex_ptr = (tess_vertex *)
malloc(sizeof(tess_vertex))) == NULL) {
tess_call_user_error(tobj, GLU_OUT_OF_MEMORY);
return;
}
vertex_ptr->data = data;
vertex_ptr->location[0] = v[0];
vertex_ptr->location[1] = v[1];
vertex_ptr->location[2] = v[2];
vertex_ptr->next = NULL;
vertex_ptr->previous = last_vertex_ptr;
++(polygon->vertex_cnt);
last_vertex_ptr->next = vertex_ptr;
polygon->last_vertex = vertex_ptr;
}
}
static void
delete_contours(GLUtriangulatorObj * tobj)
{
tess_polygon *polygon = tobj->current_polygon;
tess_contour *contour, *contour_tmp;
tess_vertex *vertex, *vertex_tmp;
/* remove current_polygon list - if exists due to detected error */
if (polygon != NULL) {
if (polygon->vertices) {
for (vertex = polygon->vertices; vertex != polygon->last_vertex;) {
vertex_tmp = vertex->next;
free(vertex);
vertex = vertex_tmp;
}
free(vertex);
}
free(polygon);
tobj->current_polygon = NULL;
}
/* remove all contour data */
for (contour = tobj->contours; contour != NULL;) {
for (vertex = contour->vertices; vertex != contour->last_vertex;) {
vertex_tmp = vertex->next;
free(vertex);
vertex = vertex_tmp;
}
free(vertex);
contour_tmp = contour->next;
free(contour);
contour = contour_tmp;
}
tobj->contours = tobj->last_contour = NULL;
tobj->contour_cnt = 0;
}
void GLAPIENTRY
gluTessNormal(GLUtesselator *tess, GLdouble valueX, GLdouble valueY, GLdouble valueZ)
{
/* dummy function */
(void) tess;
(void) valueX;
(void) valueY;
(void) valueZ;
}

108
src/glu/mini/tess.h Normal file
View File

@ -0,0 +1,108 @@
/* $Id: tess.h,v 1.2 2003/08/22 20:11:43 brianp Exp $ */
/*
* Mesa 3-D graphics library
* Version: 3.3
* Copyright (C) 1995-2000 Brian Paul
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* This file is part of the polygon tesselation code contributed by
* Bogdan Sikorski
*/
#ifndef TESS_H
#define TESS_H
#include "gluP.h"
#define EPSILON 1e-06 /* epsilon for double precision compares */
typedef enum
{
OXY,
OYZ,
OXZ
}
projection_type;
typedef struct callbacks_str
{
void (GLCALLBACK * begin) (GLenum mode);
void (GLCALLBACK * edgeFlag) (GLboolean flag);
void (GLCALLBACK * vertex) (GLvoid * v);
void (GLCALLBACK * end) (void);
void (GLCALLBACK * error) (GLenum err);
}
tess_callbacks;
typedef struct vertex_str
{
void *data;
GLdouble location[3];
GLdouble x, y;
GLboolean edge_flag;
struct vertex_str *shadow_vertex;
struct vertex_str *next, *previous;
}
tess_vertex;
typedef struct contour_str
{
GLenum type;
GLuint vertex_cnt;
GLdouble area;
GLenum orientation;
struct vertex_str *vertices, *last_vertex;
struct contour_str *next, *previous;
}
tess_contour;
typedef struct polygon_str
{
GLuint vertex_cnt;
GLdouble A, B, C, D;
GLdouble area;
GLenum orientation;
struct vertex_str *vertices, *last_vertex;
}
tess_polygon;
struct GLUtesselator
{
tess_contour *contours, *last_contour;
GLuint contour_cnt;
tess_callbacks callbacks;
tess_polygon *current_polygon;
GLenum error;
GLdouble A, B, C, D;
projection_type projection;
};
extern void tess_call_user_error(GLUtriangulatorObj *, GLenum);
extern void tess_test_polygon(GLUtriangulatorObj *);
extern void tess_find_contour_hierarchies(GLUtriangulatorObj *);
extern void tess_handle_holes(GLUtriangulatorObj *);
extern void tess_tesselate(GLUtriangulatorObj *);
extern void tess_tesselate_with_edge_flag(GLUtriangulatorObj *);
#endif

407
src/glu/mini/tesselat.c Normal file
View File

@ -0,0 +1,407 @@
/* $Id: tesselat.c,v 1.2 2003/08/22 20:11:43 brianp Exp $ */
/*
* Mesa 3-D graphics library
* Version: 3.3
* Copyright (C) 1995-2000 Brian Paul
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* This file is part of the polygon tesselation code contributed by
* Bogdan Sikorski
*/
#ifdef PC_HEADER
#include "all.h"
#else
#include <stdlib.h>
#include <math.h>
#include "tess.h"
#endif
static GLboolean edge_flag;
static void emit_triangle(GLUtriangulatorObj *, tess_vertex *,
tess_vertex *, tess_vertex *);
static void emit_triangle_with_edge_flag(GLUtriangulatorObj *,
tess_vertex *, GLboolean,
tess_vertex *, GLboolean,
tess_vertex *, GLboolean);
static GLdouble
twice_the_triangle_area(tess_vertex * va, tess_vertex * vb, tess_vertex * vc)
{
return (vb->x - va->x) * (vc->y - va->y) - (vb->y - va->y) * (vc->x -
va->x);
}
static GLboolean
left(GLdouble A, GLdouble B, GLdouble C, GLdouble x, GLdouble y)
{
if (A * x + B * y + C > -EPSILON)
return GL_TRUE;
else
return GL_FALSE;
}
static GLboolean
right(GLdouble A, GLdouble B, GLdouble C, GLdouble x, GLdouble y)
{
if (A * x + B * y + C < EPSILON)
return GL_TRUE;
else
return GL_FALSE;
}
static GLint
convex_ccw(tess_vertex * va,
tess_vertex * vb, tess_vertex * vc, GLUtriangulatorObj * tobj)
{
GLdouble d;
d = twice_the_triangle_area(va, vb, vc);
if (d > EPSILON) {
return 1;
}
else if (d < -EPSILON) {
return 0;
}
else {
return -1;
}
}
static GLint
convex_cw(tess_vertex * va,
tess_vertex * vb, tess_vertex * vc, GLUtriangulatorObj * tobj)
{
GLdouble d;
d = twice_the_triangle_area(va, vb, vc);
if (d < -EPSILON) {
return 1;
}
else if (d > EPSILON) {
return 0;
}
else {
return -1;
}
}
static GLboolean
diagonal_ccw(tess_vertex * va,
tess_vertex * vb,
GLUtriangulatorObj * tobj, tess_contour * contour)
{
tess_vertex *vc = va->next, *vertex, *shadow_vertex;
struct
{
GLdouble A, B, C;
}
ac, cb, ba;
GLdouble x, y;
GLint res = convex_ccw(va, vc, vb, tobj);
if (res == 0)
return GL_FALSE;
if (res == -1)
return GL_TRUE;
ba.A = vb->y - va->y;
ba.B = va->x - vb->x;
ba.C = -ba.A * va->x - ba.B * va->y;
ac.A = va->y - vc->y;
ac.B = vc->x - va->x;
ac.C = -ac.A * vc->x - ac.B * vc->y;
cb.A = vc->y - vb->y;
cb.B = vb->x - vc->x;
cb.C = -cb.A * vb->x - cb.B * vb->y;
for (vertex = vb->next; vertex != va; vertex = vertex->next) {
shadow_vertex = vertex->shadow_vertex;
if (shadow_vertex != NULL &&
(shadow_vertex == va || shadow_vertex == vb || shadow_vertex == vc))
continue;
x = vertex->x;
y = vertex->y;
if (left(ba.A, ba.B, ba.C, x, y) &&
left(ac.A, ac.B, ac.C, x, y) && left(cb.A, cb.B, cb.C, x, y))
return GL_FALSE;
}
return GL_TRUE;
}
static GLboolean
diagonal_cw(tess_vertex * va,
tess_vertex * vb,
GLUtriangulatorObj * tobj, tess_contour * contour)
{
tess_vertex *vc = va->next, *vertex, *shadow_vertex;
struct
{
GLdouble A, B, C;
}
ac, cb, ba;
GLdouble x, y;
GLint res = convex_cw(va, vc, vb, tobj);
if (res == 0)
return GL_FALSE;
if (res == -1)
return GL_TRUE;
ba.A = vb->y - va->y;
ba.B = va->x - vb->x;
ba.C = -ba.A * va->x - ba.B * va->y;
ac.A = va->y - vc->y;
ac.B = vc->x - va->x;
ac.C = -ac.A * vc->x - ac.B * vc->y;
cb.A = vc->y - vb->y;
cb.B = vb->x - vc->x;
cb.C = -cb.A * vb->x - cb.B * vb->y;
for (vertex = vb->next; vertex != va; vertex = vertex->next) {
shadow_vertex = vertex->shadow_vertex;
if (shadow_vertex != NULL &&
(shadow_vertex == va || shadow_vertex == vb || shadow_vertex == vc))
continue;
x = vertex->x;
y = vertex->y;
if (right(ba.A, ba.B, ba.C, x, y) &&
right(ac.A, ac.B, ac.C, x, y) && right(cb.A, cb.B, cb.C, x, y))
return GL_FALSE;
}
return GL_TRUE;
}
static void
clip_ear(GLUtriangulatorObj * tobj, tess_vertex * v, tess_contour * contour)
{
emit_triangle(tobj, v->previous, v, v->next);
/* the first in the list */
if (contour->vertices == v) {
contour->vertices = v->next;
contour->last_vertex->next = v->next;
v->next->previous = contour->last_vertex;
}
else
/* the last ? */
if (contour->last_vertex == v) {
contour->vertices->previous = v->previous;
v->previous->next = v->next;
contour->last_vertex = v->previous;
}
else {
v->next->previous = v->previous;
v->previous->next = v->next;
}
free(v);
--(contour->vertex_cnt);
}
static void
clip_ear_with_edge_flag(GLUtriangulatorObj * tobj,
tess_vertex * v, tess_contour * contour)
{
emit_triangle_with_edge_flag(tobj, v->previous, v->previous->edge_flag,
v, v->edge_flag, v->next, GL_FALSE);
v->previous->edge_flag = GL_FALSE;
/* the first in the list */
if (contour->vertices == v) {
contour->vertices = v->next;
contour->last_vertex->next = v->next;
v->next->previous = contour->last_vertex;
}
else
/* the last ? */
if (contour->last_vertex == v) {
contour->vertices->previous = v->previous;
v->previous->next = v->next;
contour->last_vertex = v->previous;
}
else {
v->next->previous = v->previous;
v->previous->next = v->next;
}
free(v);
--(contour->vertex_cnt);
}
static void
triangulate_ccw(GLUtriangulatorObj * tobj, tess_contour * contour)
{
tess_vertex *vertex;
GLuint vertex_cnt = contour->vertex_cnt;
while (vertex_cnt > 3) {
vertex = contour->vertices;
while (diagonal_ccw(vertex, vertex->next->next, tobj, contour) ==
GL_FALSE && tobj->error == GLU_NO_ERROR)
vertex = vertex->next;
if (tobj->error != GLU_NO_ERROR)
return;
clip_ear(tobj, vertex->next, contour);
--vertex_cnt;
}
}
static void
triangulate_cw(GLUtriangulatorObj * tobj, tess_contour * contour)
{
tess_vertex *vertex;
GLuint vertex_cnt = contour->vertex_cnt;
while (vertex_cnt > 3) {
vertex = contour->vertices;
while (diagonal_cw(vertex, vertex->next->next, tobj, contour) ==
GL_FALSE && tobj->error == GLU_NO_ERROR)
vertex = vertex->next;
if (tobj->error != GLU_NO_ERROR)
return;
clip_ear(tobj, vertex->next, contour);
--vertex_cnt;
}
}
static void
triangulate_ccw_with_edge_flag(GLUtriangulatorObj * tobj,
tess_contour * contour)
{
tess_vertex *vertex;
GLuint vertex_cnt = contour->vertex_cnt;
while (vertex_cnt > 3) {
vertex = contour->vertices;
while (diagonal_ccw(vertex, vertex->next->next, tobj, contour) ==
GL_FALSE && tobj->error == GLU_NO_ERROR)
vertex = vertex->next;
if (tobj->error != GLU_NO_ERROR)
return;
clip_ear_with_edge_flag(tobj, vertex->next, contour);
--vertex_cnt;
}
}
static void
triangulate_cw_with_edge_flag(GLUtriangulatorObj * tobj,
tess_contour * contour)
{
tess_vertex *vertex;
GLuint vertex_cnt = contour->vertex_cnt;
while (vertex_cnt > 3) {
vertex = contour->vertices;
while (diagonal_cw(vertex, vertex->next->next, tobj, contour) ==
GL_FALSE && tobj->error == GLU_NO_ERROR)
vertex = vertex->next;
if (tobj->error != GLU_NO_ERROR)
return;
clip_ear_with_edge_flag(tobj, vertex->next, contour);
--vertex_cnt;
}
}
void
tess_tesselate(GLUtriangulatorObj * tobj)
{
tess_contour *contour;
for (contour = tobj->contours; contour != NULL; contour = contour->next) {
if (contour->orientation == GLU_CCW) {
triangulate_ccw(tobj, contour);
}
else {
triangulate_cw(tobj, contour);
}
if (tobj->error != GLU_NO_ERROR)
return;
/* emit the last triangle */
emit_triangle(tobj, contour->vertices, contour->vertices->next,
contour->vertices->next->next);
}
}
void
tess_tesselate_with_edge_flag(GLUtriangulatorObj * tobj)
{
tess_contour *contour;
edge_flag = GL_TRUE;
/* first callback with edgeFlag set to GL_TRUE */
(tobj->callbacks.edgeFlag) (GL_TRUE);
for (contour = tobj->contours; contour != NULL; contour = contour->next) {
if (contour->orientation == GLU_CCW)
triangulate_ccw_with_edge_flag(tobj, contour);
else
triangulate_cw_with_edge_flag(tobj, contour);
if (tobj->error != GLU_NO_ERROR)
return;
/* emit the last triangle */
emit_triangle_with_edge_flag(tobj, contour->vertices,
contour->vertices->edge_flag,
contour->vertices->next,
contour->vertices->next->edge_flag,
contour->vertices->next->next,
contour->vertices->next->next->edge_flag);
}
}
static void
emit_triangle(GLUtriangulatorObj * tobj,
tess_vertex * v1, tess_vertex * v2, tess_vertex * v3)
{
(tobj->callbacks.begin) (GL_TRIANGLES);
(tobj->callbacks.vertex) (v1->data);
(tobj->callbacks.vertex) (v2->data);
(tobj->callbacks.vertex) (v3->data);
(tobj->callbacks.end) ();
}
static void
emit_triangle_with_edge_flag(GLUtriangulatorObj * tobj,
tess_vertex * v1,
GLboolean edge_flag1,
tess_vertex * v2,
GLboolean edge_flag2,
tess_vertex * v3, GLboolean edge_flag3)
{
(tobj->callbacks.begin) (GL_TRIANGLES);
if (edge_flag1 != edge_flag) {
edge_flag = (edge_flag == GL_TRUE ? GL_FALSE : GL_TRUE);
(tobj->callbacks.edgeFlag) (edge_flag);
}
(tobj->callbacks.vertex) (v1->data);
if (edge_flag2 != edge_flag) {
edge_flag = (edge_flag == GL_TRUE ? GL_FALSE : GL_TRUE);
(tobj->callbacks.edgeFlag) (edge_flag);
}
(tobj->callbacks.vertex) (v2->data);
if (edge_flag3 != edge_flag) {
edge_flag = (edge_flag == GL_TRUE ? GL_FALSE : GL_TRUE);
(tobj->callbacks.edgeFlag) (edge_flag);
}
(tobj->callbacks.vertex) (v3->data);
(tobj->callbacks.end) ();
}

View File

@ -0,0 +1,78 @@
TOP = ../../..
default: linux-solo
MARK = $(TOP)/src/glut/glx
INCLUDES = -I$(TOP)/include -I$(MARK)
CORE_SOURCES = \
bitmap.c \
callback.c \
color.c \
globals.c \
init.c \
menu.c \
models.c \
overlay.c \
state.c \
teapot.c \
window.c
MARK_SOURCES = \
$(MARK)/glut_8x13.c \
$(MARK)/glut_9x15.c \
$(MARK)/glut_hel10.c \
$(MARK)/glut_hel12.c \
$(MARK)/glut_hel18.c \
$(MARK)/glut_tr10.c \
$(MARK)/glut_tr24.c
SOURCES = $(CORE_SOURCES) $(MARK_SOURCES)
OBJS = $(SOURCES:.c=.o)
LIBS = -L$(TOP)/lib -lGL -lGLU -lm
##### RULES #####
.c.o:
$(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
.S.o:
$(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
##### TARGETS #####
targets: depend libglut.so.3.7 install
libglut.so.3.7: $(OBJS) Makefile.X11
gcc -shared -Wl,-soname,libglut.so -Wl,-Bsymbolic $(OBJS) $(LIBS) -o $@
install:
rm -f $(TOP)/lib/libglut.so*
install -D libglut.so.3.7 $(TOP)/lib/libglut.so.3.7
ln -s libglut.so.3.7 $(TOP)/lib/libglut.so.3
ln -s libglut.so.3 $(TOP)/lib/libglut.so
# Run 'make -f Makefile.X11 dep' to update the dependencies if you change
# what's included by any source file.
depend: $(SOURCES)
makedepend -fdepend -Y $(INCLUDES) \
$(SOURCES)
# Emacs tags
tags:
etags `find . -name \*.[ch]` `find ../include`
# Remove .o and backup files
clean:
-rm -f *.o *~ *.o *~ *.so
include $(TOP)/Make-config
include depend

56
src/glut/mini/bitmap.c Normal file
View File

@ -0,0 +1,56 @@
/* Copyright (c) Mark J. Kilgard, 1994. */
/* This program is freely distributable without licensing fees
and is provided without guarantee or warrantee expressed or
implied. This program is -not- in the public domain. */
#include "glutbitmap.h"
void APIENTRY
glutBitmapCharacter(GLUTbitmapFont font, int c)
{
const BitmapCharRec *ch;
BitmapFontPtr fontinfo;
GLfloat swapbytes, lsbfirst, rowlength;
GLfloat skiprows, skippixels, alignment;
#if defined(_WIN32)
fontinfo = (BitmapFontPtr) __glutFont(font);
#else
fontinfo = (BitmapFontPtr) font;
#endif
if (c < fontinfo->first ||
c >= fontinfo->first + fontinfo->num_chars)
return;
ch = fontinfo->ch[c - fontinfo->first];
if (ch) {
/* Save current modes. */
/* glGetFloatv(GL_UNPACK_SWAP_BYTES, &swapbytes); */
/* glGetFloatv(GL_UNPACK_LSB_FIRST, &lsbfirst); */
/* glGetFloatv(GL_UNPACK_ROW_LENGTH, &rowlength); */
/* glGetFloatv(GL_UNPACK_SKIP_ROWS, &skiprows); */
/* glGetFloatv(GL_UNPACK_SKIP_PIXELS, &skippixels); */
glGetFloatv(GL_UNPACK_ALIGNMENT, &alignment);
/* Little endian machines (DEC Alpha for example) could
benefit from setting GL_UNPACK_LSB_FIRST to GL_TRUE
instead of GL_FALSE, but this would require changing the
generated bitmaps too. */
/* glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); */
/* glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE); */
/* glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); */
/* glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); */
/* glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); */
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glBitmap(ch->width, ch->height, ch->xorig, ch->yorig,
ch->advance, 0, ch->bitmap);
/* Restore saved modes. */
/* glPixelStorei(GL_UNPACK_SWAP_BYTES, swapbytes); */
/* glPixelStorei(GL_UNPACK_LSB_FIRST, (int)lsbfirst); */
/* glPixelStorei(GL_UNPACK_ROW_LENGTH, (int)rowlength); */
/* glPixelStorei(GL_UNPACK_SKIP_ROWS, skiprows); */
/* glPixelStorei(GL_UNPACK_SKIP_PIXELS, skippixels); */
glPixelStorei(GL_UNPACK_ALIGNMENT, (int)alignment);
}
}

152
src/glut/mini/callback.c Normal file
View File

@ -0,0 +1,152 @@
/*
* Mesa 3-D graphics library
* Version: 3.4
* Copyright (C) 1995-1998 Brian Paul
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* DOS/DJGPP glut driver v1.0 for Mesa 4.0
*
* Copyright (C) 2002 - Borca Daniel
* Email : dborca@yahoo.com
* Web : http://www.geocities.com/dborca
*/
#include "GL/glut.h"
#include "internal.h"
void APIENTRY glutDisplayFunc (void (GLUTCALLBACK *func) (void))
{
display_func = func;
}
void APIENTRY glutReshapeFunc (void (GLUTCALLBACK *func) (int width, int height))
{
reshape_func = func;
}
void APIENTRY glutKeyboardFunc (void (GLUTCALLBACK *func) (unsigned char key, int x, int y))
{
keyboard_func = func;
}
void APIENTRY glutMouseFunc (void (GLUTCALLBACK *func) (int button, int state, int x, int y))
{
mouse_func = func;
}
void APIENTRY glutMotionFunc (void (GLUTCALLBACK *func) (int x, int y))
{
motion_func = func;
}
void APIENTRY glutPassiveMotionFunc (void (GLUTCALLBACK *func) (int x, int y))
{
passive_motion_func = func;
}
void APIENTRY glutEntryFunc (void (GLUTCALLBACK *func) (int state))
{
entry_func = func;
}
void APIENTRY glutVisibilityFunc (void (GLUTCALLBACK *func) (int state))
{
visibility_func = func;
}
void APIENTRY glutIdleFunc (void (GLUTCALLBACK *func) (void))
{
idle_func = func;
}
void APIENTRY glutTimerFunc (unsigned int millis, void (GLUTCALLBACK *func) (int value), int value)
{
}
void APIENTRY glutMenuStateFunc (void (GLUTCALLBACK *func) (int state))
{
menu_state_func = func;
}
void APIENTRY glutSpecialFunc (void (GLUTCALLBACK *func) (int key, int x, int y))
{
special_func = func;
}
void APIENTRY glutSpaceballMotionFunc (void (GLUTCALLBACK *func) (int x, int y, int z))
{
}
void APIENTRY glutSpaceballRotateFunc (void (GLUTCALLBACK *func) (int x, int y, int z))
{
}
void APIENTRY glutSpaceballButtonFunc (void (GLUTCALLBACK *func) (int button, int state))
{
}
void APIENTRY glutButtonBoxFunc (void (GLUTCALLBACK *func) (int button, int state))
{
}
void APIENTRY glutDialsFunc (void (GLUTCALLBACK *func) (int dial, int value))
{
}
void APIENTRY glutTabletMotionFunc (void (GLUTCALLBACK *func) (int x, int y))
{
}
void APIENTRY glutTabletButtonFunc (void (GLUTCALLBACK *func) (int button, int state, int x, int y))
{
}
void APIENTRY glutMenuStatusFunc (void (GLUTCALLBACK *func) (int status, int x, int y))
{
}
void APIENTRY glutOverlayDisplayFunc (void (GLUTCALLBACK *func) (void))
{
}
void APIENTRY glutWindowStatusFunc (void (GLUTCALLBACK *func) (int state))
{
}

46
src/glut/mini/color.c Normal file
View File

@ -0,0 +1,46 @@
/*
* Mesa 3-D graphics library
* Version: 3.4
* Copyright (C) 1995-1998 Brian Paul
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* DOS/DJGPP glut driver v1.0 for Mesa 4.0
*
* Copyright (C) 2002 - Borca Daniel
* Email : dborca@yahoo.com
* Web : http://www.geocities.com/dborca
*/
#include "GL/glut.h"
void APIENTRY glutSetColor (int ndx, GLfloat red, GLfloat green, GLfloat blue)
{
}
GLfloat APIENTRY glutGetColor (int ndx, int component)
{
return 0.0;
}
void APIENTRY glutCopyColormap (int win)
{
}

61
src/glut/mini/globals.c Normal file
View File

@ -0,0 +1,61 @@
/*
* Mesa 3-D graphics library
* Version: 3.4
* Copyright (C) 1995-1998 Brian Paul
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* DOS/DJGPP glut driver v1.0 for Mesa 4.0
*
* Copyright (C) 2002 - Borca Daniel
* Email : dborca@yahoo.com
* Web : http://www.geocities.com/dborca
*/
#include "GL/glut.h"
#include "internal.h"
GLenum g_display_mode = 0;
GLuint g_width = DEFAULT_WIDTH;
GLuint g_height = DEFAULT_HEIGHT;
GLint g_mouse = GL_FALSE;
GLboolean g_redisplay = GL_FALSE;
GLint g_xpos = 0;
GLint g_ypos = 0;
void (GLUTCALLBACK *display_func) (void) = 0;
void (GLUTCALLBACK *reshape_func) (int width, int height) = 0;
void (GLUTCALLBACK *keyboard_func) (unsigned char key, int x, int y) = 0;
void (GLUTCALLBACK *mouse_func) (int button, int state, int x, int y) = 0;
void (GLUTCALLBACK *motion_func) (int x, int y) = 0;
void (GLUTCALLBACK *passive_motion_func) (int x, int y) = 0;
void (GLUTCALLBACK *entry_func) (int state) = 0;
void (GLUTCALLBACK *visibility_func) (int state) = 0;
void (GLUTCALLBACK *idle_func) (void) = 0;
void (GLUTCALLBACK *menu_state_func) (int state) = 0;
void (GLUTCALLBACK *special_func) (int key, int x, int y) = 0;
void (GLUTCALLBACK *spaceball_motion_func) (int x, int y, int z) = 0;
void (GLUTCALLBACK *spaceball_rotate_func) (int x, int y, int z) = 0;
void (GLUTCALLBACK *spaceball_button_func) (int button, int state) = 0;
void (GLUTCALLBACK *button_box_func) (int button, int state) = 0;
void (GLUTCALLBACK *dials_func) (int dial, int value) = 0;
void (GLUTCALLBACK *tablet_motion_func) (int x, int y) = 0;
void (GLUTCALLBACK *tabled_button_func) (int button, int state, int x, int y) = 0;
void (GLUTCALLBACK *menu_status_func) (int status, int x, int y) = 0;
void (GLUTCALLBACK *overlay_display_func) (void) = 0;
void (GLUTCALLBACK *window_status_func) (int state) = 0;

59
src/glut/mini/init.c Normal file
View File

@ -0,0 +1,59 @@
/*
* Mesa 3-D graphics library
* Version: 4.0
* Copyright (C) 1995-1998 Brian Paul
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* DOS/DJGPP glut driver v1.0 for Mesa 4.0
*
* Copyright (C) 2002 - Borca Daniel
* Email : dborca@yahoo.com
* Web : http://www.geocities.com/dborca
*/
#include "GL/glut.h"
#include "internal.h"
void APIENTRY glutInit (int *argcp, char **argv)
{
glutGet(GLUT_ELAPSED_TIME);
}
void APIENTRY glutInitDisplayMode (unsigned int mode)
{
g_display_mode = mode;
}
void APIENTRY glutInitWindowPosition (int x, int y)
{
g_xpos = x;
g_ypos = y;
}
void APIENTRY glutInitWindowSize (int width, int height)
{
g_width = width;
g_height = height;
}

78
src/glut/mini/internal.h Normal file
View File

@ -0,0 +1,78 @@
/*
* Mesa 3-D graphics library
* Version: 4.0
* Copyright (C) 1995-1998 Brian Paul
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* DOS/DJGPP glut driver v1.0 for Mesa 4.0
*
* Copyright (C) 2002 - Borca Daniel
* Email : dborca@yahoo.com
* Web : http://www.geocities.com/dborca
*/
#ifndef INTERNAL_H_included
#define INTERNAL_H_included
#include "GL/glut.h"
/* #include "pc_hw/pc_hw.h" */
#define MAX_WINDOWS 4
#define DEFAULT_WIDTH 640
#define DEFAULT_HEIGHT 480
#define DEFAULT_BPP 16
#define DEPTH_SIZE 16
#define STENCIL_SIZE 8
#define ACCUM_SIZE 16
extern GLenum g_display_mode;
extern GLuint g_width;
extern GLuint g_height;
extern GLint g_mouse;
extern GLboolean g_redisplay;
extern GLint g_xpos;
extern GLint g_ypos;
extern void (GLUTCALLBACK *display_func) (void);
extern void (GLUTCALLBACK *reshape_func) (int width, int height);
extern void (GLUTCALLBACK *keyboard_func) (unsigned char key, int x, int y);
extern void (GLUTCALLBACK *mouse_func) (int button, int state, int x, int y);
extern void (GLUTCALLBACK *motion_func) (int x, int y);
extern void (GLUTCALLBACK *passive_motion_func) (int x, int y);
extern void (GLUTCALLBACK *entry_func) (int state);
extern void (GLUTCALLBACK *visibility_func) (int state);
extern void (GLUTCALLBACK *idle_func) (void);
extern void (GLUTCALLBACK *menu_state_func) (int state);
extern void (GLUTCALLBACK *special_func) (int key, int x, int y);
extern void (GLUTCALLBACK *spaceball_motion_func) (int x, int y, int z);
extern void (GLUTCALLBACK *spaceball_rotate_func) (int x, int y, int z);
extern void (GLUTCALLBACK *spaceball_button_func) (int button, int state);
extern void (GLUTCALLBACK *button_box_func) (int button, int state);
extern void (GLUTCALLBACK *dials_func) (int dial, int value);
extern void (GLUTCALLBACK *tablet_motion_func) (int x, int y);
extern void (GLUTCALLBACK *tabled_button_func) (int button, int state, int x, int y);
extern void (GLUTCALLBACK *menu_status_func) (int status, int x, int y);
extern void (GLUTCALLBACK *overlay_display_func) (void);
extern void (GLUTCALLBACK *window_status_func) (int state);
#endif

86
src/glut/mini/menu.c Normal file
View File

@ -0,0 +1,86 @@
/*
* Mesa 3-D graphics library
* Version: 3.4
* Copyright (C) 1995-1998 Brian Paul
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* DOS/DJGPP glut driver v1.0 for Mesa 4.0
*
* Copyright (C) 2002 - Borca Daniel
* Email : dborca@yahoo.com
* Web : http://www.geocities.com/dborca
*/
#include "GL/glut.h"
int APIENTRY glutCreateMenu (void (GLUTCALLBACK *func) (int))
{
return 0;
}
void APIENTRY glutDestroyMenu (int menu)
{
}
int APIENTRY glutGetMenu (void)
{
return 0;
}
void APIENTRY glutSetMenu (int menu)
{
}
void APIENTRY glutAddMenuEntry (const char *label, int value)
{
}
void APIENTRY glutAddSubMenu (const char *label, int submenu)
{
}
void APIENTRY glutChangeToMenuEntry (int item, const char *label, int value)
{
}
void APIENTRY glutChangeToSubMenu (int item, const char *label, int submenu)
{
}
void APIENTRY glutRemoveMenuItem (int item)
{
}
void APIENTRY glutAttachMenu (int button)
{
}
void APIENTRY glutDetachMenu (int button)
{
}

598
src/glut/mini/models.c Normal file
View File

@ -0,0 +1,598 @@
/* Copyright (c) Mark J. Kilgard, 1994, 1997. */
/**
(c) Copyright 1993, Silicon Graphics, Inc.
ALL RIGHTS RESERVED
Permission to use, copy, modify, and distribute this software
for any purpose and without fee is hereby granted, provided
that the above copyright notice appear in all copies and that
both the copyright notice and this permission notice appear in
supporting documentation, and that the name of Silicon
Graphics, Inc. not be used in advertising or publicity
pertaining to distribution of the software without specific,
written prior permission.
THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU
"AS-IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR
OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. IN NO
EVENT SHALL SILICON GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE
ELSE FOR ANY DIRECT, SPECIAL, INCIDENTAL, INDIRECT OR
CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER,
INCLUDING WITHOUT LIMITATION, LOSS OF PROFIT, LOSS OF USE,
SAVINGS OR REVENUE, OR THE CLAIMS OF THIRD PARTIES, WHETHER OR
NOT SILICON GRAPHICS, INC. HAS BEEN ADVISED OF THE POSSIBILITY
OF SUCH LOSS, HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
ARISING OUT OF OR IN CONNECTION WITH THE POSSESSION, USE OR
PERFORMANCE OF THIS SOFTWARE.
US Government Users Restricted Rights
Use, duplication, or disclosure by the Government is subject to
restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
(c)(1)(ii) of the Rights in Technical Data and Computer
Software clause at DFARS 252.227-7013 and/or in similar or
successor clauses in the FAR or the DOD or NASA FAR
Supplement. Unpublished-- rights reserved under the copyright
laws of the United States. Contractor/manufacturer is Silicon
Graphics, Inc., 2011 N. Shoreline Blvd., Mountain View, CA
94039-7311.
OpenGL(TM) is a trademark of Silicon Graphics, Inc.
*/
#include <math.h>
#include <GL/gl.h>
#include <GL/glu.h>
#include "GL/glut.h"
/* Some <math.h> files do not define M_PI... */
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
static GLUquadricObj *quadObj;
#define QUAD_OBJ_INIT() { if(!quadObj) initQuadObj(); }
static void
initQuadObj(void)
{
quadObj = gluNewQuadric();
/* if (!quadObj)
__glutFatalError("out of memory."); */
}
/* CENTRY */
void APIENTRY
glutWireSphere(GLdouble radius, GLint slices, GLint stacks)
{
QUAD_OBJ_INIT();
gluQuadricDrawStyle(quadObj, GLU_LINE);
gluQuadricNormals(quadObj, GLU_SMOOTH);
/* If we ever changed/used the texture or orientation state
of quadObj, we'd need to change it to the defaults here
with gluQuadricTexture and/or gluQuadricOrientation. */
gluSphere(quadObj, radius, slices, stacks);
}
void APIENTRY
glutSolidSphere(GLdouble radius, GLint slices, GLint stacks)
{
QUAD_OBJ_INIT();
gluQuadricDrawStyle(quadObj, GLU_FILL);
gluQuadricNormals(quadObj, GLU_SMOOTH);
/* If we ever changed/used the texture or orientation state
of quadObj, we'd need to change it to the defaults here
with gluQuadricTexture and/or gluQuadricOrientation. */
gluSphere(quadObj, radius, slices, stacks);
}
void APIENTRY
glutWireCone(GLdouble base, GLdouble height,
GLint slices, GLint stacks)
{
QUAD_OBJ_INIT();
gluQuadricDrawStyle(quadObj, GLU_LINE);
gluQuadricNormals(quadObj, GLU_SMOOTH);
/* If we ever changed/used the texture or orientation state
of quadObj, we'd need to change it to the defaults here
with gluQuadricTexture and/or gluQuadricOrientation. */
gluCylinder(quadObj, base, 0.0, height, slices, stacks);
}
void APIENTRY
glutSolidCone(GLdouble base, GLdouble height,
GLint slices, GLint stacks)
{
QUAD_OBJ_INIT();
gluQuadricDrawStyle(quadObj, GLU_FILL);
gluQuadricNormals(quadObj, GLU_SMOOTH);
/* If we ever changed/used the texture or orientation state
of quadObj, we'd need to change it to the defaults here
with gluQuadricTexture and/or gluQuadricOrientation. */
gluCylinder(quadObj, base, 0.0, height, slices, stacks);
}
/* ENDCENTRY */
static void
drawBox(GLfloat size, GLenum type)
{
static GLfloat n[6][3] =
{
{-1.0, 0.0, 0.0},
{0.0, 1.0, 0.0},
{1.0, 0.0, 0.0},
{0.0, -1.0, 0.0},
{0.0, 0.0, 1.0},
{0.0, 0.0, -1.0}
};
static GLint faces[6][4] =
{
{0, 1, 2, 3},
{3, 2, 6, 7},
{7, 6, 5, 4},
{4, 5, 1, 0},
{5, 6, 2, 1},
{7, 4, 0, 3}
};
GLfloat v[8][3];
GLint i;
v[0][0] = v[1][0] = v[2][0] = v[3][0] = -size / 2;
v[4][0] = v[5][0] = v[6][0] = v[7][0] = size / 2;
v[0][1] = v[1][1] = v[4][1] = v[5][1] = -size / 2;
v[2][1] = v[3][1] = v[6][1] = v[7][1] = size / 2;
v[0][2] = v[3][2] = v[4][2] = v[7][2] = -size / 2;
v[1][2] = v[2][2] = v[5][2] = v[6][2] = size / 2;
for (i = 5; i >= 0; i--) {
glBegin(type);
/* glNormal3fv(&n[i][0]); */
glVertex3fv(&v[faces[i][0]][0]);
glVertex3fv(&v[faces[i][1]][0]);
glVertex3fv(&v[faces[i][2]][0]);
glVertex3fv(&v[faces[i][3]][0]);
glEnd();
}
}
/* CENTRY */
void APIENTRY
glutWireCube(GLdouble size)
{
drawBox(size, GL_LINE_LOOP);
}
void APIENTRY
glutSolidCube(GLdouble size)
{
drawBox(size, GL_QUADS);
}
/* ENDCENTRY */
static void
doughnut(GLfloat r, GLfloat R, GLint nsides, GLint rings)
{
int i, j;
GLfloat theta, phi, theta1;
GLfloat cosTheta, sinTheta;
GLfloat cosTheta1, sinTheta1;
GLfloat ringDelta, sideDelta;
ringDelta = 2.0 * M_PI / rings;
sideDelta = 2.0 * M_PI / nsides;
theta = 0.0;
cosTheta = 1.0;
sinTheta = 0.0;
for (i = rings - 1; i >= 0; i--) {
theta1 = theta + ringDelta;
cosTheta1 = cos(theta1);
sinTheta1 = sin(theta1);
glBegin(GL_QUAD_STRIP);
phi = 0.0;
for (j = nsides; j >= 0; j--) {
GLfloat cosPhi, sinPhi, dist;
phi += sideDelta;
cosPhi = cos(phi);
sinPhi = sin(phi);
dist = R + r * cosPhi;
/* glNormal3f(cosTheta1 * cosPhi, -sinTheta1 * cosPhi, sinPhi); */
glVertex3f(cosTheta1 * dist, -sinTheta1 * dist, r * sinPhi);
/* glNormal3f(cosTheta * cosPhi, -sinTheta * cosPhi, sinPhi); */
glVertex3f(cosTheta * dist, -sinTheta * dist, r * sinPhi);
}
glEnd();
theta = theta1;
cosTheta = cosTheta1;
sinTheta = sinTheta1;
}
}
/* CENTRY */
void APIENTRY
glutWireTorus(GLdouble innerRadius, GLdouble outerRadius,
GLint nsides, GLint rings)
{
/* glPushAttrib(GL_POLYGON_BIT); */
/* glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); */
doughnut(innerRadius, outerRadius, nsides, rings);
/* glPopAttrib(); */
}
void APIENTRY
glutSolidTorus(GLdouble innerRadius, GLdouble outerRadius,
GLint nsides, GLint rings)
{
doughnut(innerRadius, outerRadius, nsides, rings);
}
/* ENDCENTRY */
static GLfloat dodec[20][3];
static void
initDodecahedron(void)
{
GLfloat alpha, beta;
alpha = sqrt(2.0 / (3.0 + sqrt(5.0)));
beta = 1.0 + sqrt(6.0 / (3.0 + sqrt(5.0)) -
2.0 + 2.0 * sqrt(2.0 / (3.0 + sqrt(5.0))));
/* *INDENT-OFF* */
dodec[0][0] = -alpha; dodec[0][1] = 0; dodec[0][2] = beta;
dodec[1][0] = alpha; dodec[1][1] = 0; dodec[1][2] = beta;
dodec[2][0] = -1; dodec[2][1] = -1; dodec[2][2] = -1;
dodec[3][0] = -1; dodec[3][1] = -1; dodec[3][2] = 1;
dodec[4][0] = -1; dodec[4][1] = 1; dodec[4][2] = -1;
dodec[5][0] = -1; dodec[5][1] = 1; dodec[5][2] = 1;
dodec[6][0] = 1; dodec[6][1] = -1; dodec[6][2] = -1;
dodec[7][0] = 1; dodec[7][1] = -1; dodec[7][2] = 1;
dodec[8][0] = 1; dodec[8][1] = 1; dodec[8][2] = -1;
dodec[9][0] = 1; dodec[9][1] = 1; dodec[9][2] = 1;
dodec[10][0] = beta; dodec[10][1] = alpha; dodec[10][2] = 0;
dodec[11][0] = beta; dodec[11][1] = -alpha; dodec[11][2] = 0;
dodec[12][0] = -beta; dodec[12][1] = alpha; dodec[12][2] = 0;
dodec[13][0] = -beta; dodec[13][1] = -alpha; dodec[13][2] = 0;
dodec[14][0] = -alpha; dodec[14][1] = 0; dodec[14][2] = -beta;
dodec[15][0] = alpha; dodec[15][1] = 0; dodec[15][2] = -beta;
dodec[16][0] = 0; dodec[16][1] = beta; dodec[16][2] = alpha;
dodec[17][0] = 0; dodec[17][1] = beta; dodec[17][2] = -alpha;
dodec[18][0] = 0; dodec[18][1] = -beta; dodec[18][2] = alpha;
dodec[19][0] = 0; dodec[19][1] = -beta; dodec[19][2] = -alpha;
/* *INDENT-ON* */
}
#define DIFF3(_a,_b,_c) { \
(_c)[0] = (_a)[0] - (_b)[0]; \
(_c)[1] = (_a)[1] - (_b)[1]; \
(_c)[2] = (_a)[2] - (_b)[2]; \
}
static void
crossprod(GLfloat v1[3], GLfloat v2[3], GLfloat prod[3])
{
GLfloat p[3]; /* in case prod == v1 or v2 */
p[0] = v1[1] * v2[2] - v2[1] * v1[2];
p[1] = v1[2] * v2[0] - v2[2] * v1[0];
p[2] = v1[0] * v2[1] - v2[0] * v1[1];
prod[0] = p[0];
prod[1] = p[1];
prod[2] = p[2];
}
static void
normalize(GLfloat v[3])
{
GLfloat d;
d = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
if (d == 0.0) {
/* __glutWarning("normalize: zero length vector"); */
v[0] = d = 1.0;
}
d = 1 / d;
v[0] *= d;
v[1] *= d;
v[2] *= d;
}
static void
pentagon(int a, int b, int c, int d, int e, GLenum shadeType)
{
GLfloat n0[3], d1[3], d2[3];
DIFF3(dodec[a], dodec[b], d1);
DIFF3(dodec[b], dodec[c], d2);
crossprod(d1, d2, n0);
normalize(n0);
glBegin(shadeType);
/* glNormal3fv(n0); */
glVertex3fv(&dodec[a][0]);
glVertex3fv(&dodec[b][0]);
glVertex3fv(&dodec[c][0]);
glVertex3fv(&dodec[d][0]);
glVertex3fv(&dodec[e][0]);
glEnd();
}
static void
dodecahedron(GLenum type)
{
static int inited = 0;
if (inited == 0) {
inited = 1;
initDodecahedron();
}
pentagon(0, 1, 9, 16, 5, type);
pentagon(1, 0, 3, 18, 7, type);
pentagon(1, 7, 11, 10, 9, type);
pentagon(11, 7, 18, 19, 6, type);
pentagon(8, 17, 16, 9, 10, type);
pentagon(2, 14, 15, 6, 19, type);
pentagon(2, 13, 12, 4, 14, type);
pentagon(2, 19, 18, 3, 13, type);
pentagon(3, 0, 5, 12, 13, type);
pentagon(6, 15, 8, 10, 11, type);
pentagon(4, 17, 8, 15, 14, type);
pentagon(4, 12, 5, 16, 17, type);
}
/* CENTRY */
void APIENTRY
glutWireDodecahedron(void)
{
dodecahedron(GL_LINE_LOOP);
}
void APIENTRY
glutSolidDodecahedron(void)
{
dodecahedron(GL_TRIANGLE_FAN);
}
/* ENDCENTRY */
static void
recorditem(GLfloat * n1, GLfloat * n2, GLfloat * n3,
GLenum shadeType)
{
GLfloat q0[3], q1[3];
DIFF3(n1, n2, q0);
DIFF3(n2, n3, q1);
crossprod(q0, q1, q1);
normalize(q1);
glBegin(shadeType);
/* glNormal3fv(q1); */
glVertex3fv(n1);
glVertex3fv(n2);
glVertex3fv(n3);
glEnd();
}
static void
subdivide(GLfloat * v0, GLfloat * v1, GLfloat * v2,
GLenum shadeType)
{
int depth;
GLfloat w0[3], w1[3], w2[3];
GLfloat l;
int i, j, k, n;
depth = 1;
for (i = 0; i < depth; i++) {
for (j = 0; i + j < depth; j++) {
k = depth - i - j;
for (n = 0; n < 3; n++) {
w0[n] = (i * v0[n] + j * v1[n] + k * v2[n]) / depth;
w1[n] = ((i + 1) * v0[n] + j * v1[n] + (k - 1) * v2[n])
/ depth;
w2[n] = (i * v0[n] + (j + 1) * v1[n] + (k - 1) * v2[n])
/ depth;
}
l = sqrt(w0[0] * w0[0] + w0[1] * w0[1] + w0[2] * w0[2]);
w0[0] /= l;
w0[1] /= l;
w0[2] /= l;
l = sqrt(w1[0] * w1[0] + w1[1] * w1[1] + w1[2] * w1[2]);
w1[0] /= l;
w1[1] /= l;
w1[2] /= l;
l = sqrt(w2[0] * w2[0] + w2[1] * w2[1] + w2[2] * w2[2]);
w2[0] /= l;
w2[1] /= l;
w2[2] /= l;
recorditem(w1, w0, w2, shadeType);
}
}
}
static void
drawtriangle(int i, GLfloat data[][3], int ndx[][3],
GLenum shadeType)
{
GLfloat *x0, *x1, *x2;
x0 = data[ndx[i][0]];
x1 = data[ndx[i][1]];
x2 = data[ndx[i][2]];
subdivide(x0, x1, x2, shadeType);
}
/* octahedron data: The octahedron produced is centered at the
origin and has radius 1.0 */
static GLfloat odata[6][3] =
{
{1.0, 0.0, 0.0},
{-1.0, 0.0, 0.0},
{0.0, 1.0, 0.0},
{0.0, -1.0, 0.0},
{0.0, 0.0, 1.0},
{0.0, 0.0, -1.0}
};
static int ondex[8][3] =
{
{0, 4, 2},
{1, 2, 4},
{0, 3, 4},
{1, 4, 3},
{0, 2, 5},
{1, 5, 2},
{0, 5, 3},
{1, 3, 5}
};
static void
octahedron(GLenum shadeType)
{
int i;
for (i = 7; i >= 0; i--) {
drawtriangle(i, odata, ondex, shadeType);
}
}
/* CENTRY */
void APIENTRY
glutWireOctahedron(void)
{
octahedron(GL_LINE_LOOP);
}
void APIENTRY
glutSolidOctahedron(void)
{
octahedron(GL_TRIANGLES);
}
/* ENDCENTRY */
/* icosahedron data: These numbers are rigged to make an
icosahedron of radius 1.0 */
#define X .525731112119133606
#define Z .850650808352039932
static GLfloat idata[12][3] =
{
{-X, 0, Z},
{X, 0, Z},
{-X, 0, -Z},
{X, 0, -Z},
{0, Z, X},
{0, Z, -X},
{0, -Z, X},
{0, -Z, -X},
{Z, X, 0},
{-Z, X, 0},
{Z, -X, 0},
{-Z, -X, 0}
};
static int index[20][3] =
{
{0, 4, 1},
{0, 9, 4},
{9, 5, 4},
{4, 5, 8},
{4, 8, 1},
{8, 10, 1},
{8, 3, 10},
{5, 3, 8},
{5, 2, 3},
{2, 7, 3},
{7, 10, 3},
{7, 6, 10},
{7, 11, 6},
{11, 0, 6},
{0, 1, 6},
{6, 1, 10},
{9, 0, 11},
{9, 11, 2},
{9, 2, 5},
{7, 2, 11},
};
static void
icosahedron(GLenum shadeType)
{
int i;
for (i = 19; i >= 0; i--) {
drawtriangle(i, idata, index, shadeType);
}
}
/* CENTRY */
void APIENTRY
glutWireIcosahedron(void)
{
icosahedron(GL_LINE_LOOP);
}
void APIENTRY
glutSolidIcosahedron(void)
{
icosahedron(GL_TRIANGLES);
}
/* ENDCENTRY */
/* tetrahedron data: */
#define T 1.73205080756887729
static GLfloat tdata[4][3] =
{
{T, T, T},
{T, -T, -T},
{-T, T, -T},
{-T, -T, T}
};
static int tndex[4][3] =
{
{0, 1, 3},
{2, 1, 0},
{3, 2, 0},
{1, 2, 3}
};
static void
tetrahedron(GLenum shadeType)
{
int i;
for (i = 3; i >= 0; i--)
drawtriangle(i, tdata, tndex, shadeType);
}
/* CENTRY */
void APIENTRY
glutWireTetrahedron(void)
{
tetrahedron(GL_LINE_LOOP);
}
void APIENTRY
glutSolidTetrahedron(void)
{
tetrahedron(GL_TRIANGLES);
}
/* ENDCENTRY */

60
src/glut/mini/overlay.c Normal file
View File

@ -0,0 +1,60 @@
/*
* Mesa 3-D graphics library
* Version: 3.4
* Copyright (C) 1995-1998 Brian Paul
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* DOS/DJGPP glut driver v1.0 for Mesa 4.0
*
* Copyright (C) 2002 - Borca Daniel
* Email : dborca@yahoo.com
* Web : http://www.geocities.com/dborca
*/
#include "GL/glut.h"
void APIENTRY glutEstablishOverlay (void)
{
}
void APIENTRY glutRemoveOverlay (void)
{
}
void APIENTRY glutUseLayer (GLenum layer)
{
}
void APIENTRY glutPostOverlayRedisplay (void)
{
}
void APIENTRY glutShowOverlay (void)
{
}
void APIENTRY glutHideOverlay (void)
{
}

70
src/glut/mini/state.c Normal file
View File

@ -0,0 +1,70 @@
/*
* Mesa 3-D graphics library
* Version: 3.4
* Copyright (C) 1995-1998 Brian Paul
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* DOS/DJGPP glut driver v1.0 for Mesa 4.0
*
* Copyright (C) 2002 - Borca Daniel
* Email : dborca@yahoo.com
* Web : http://www.geocities.com/dborca
*/
#include "GL/glut.h"
#include <sys/time.h>
#define TIMEDELTA(dest, src1, src2) { \
if(((dest).tv_usec = (src1).tv_usec - (src2).tv_usec) < 0) { \
(dest).tv_usec += 1000000; \
(dest).tv_sec = (src1).tv_sec - (src2).tv_sec - 1; \
} else { \
(dest).tv_sec = (src1).tv_sec - (src2).tv_sec; \
} \
}
int APIENTRY glutGet (GLenum type)
{
switch (type) {
case GLUT_WINDOW_RGBA:
return 1;
case GLUT_ELAPSED_TIME: {
static int inited = 0;
static struct timeval elapsed, beginning, now;
if (!inited) {
gettimeofday(&beginning, 0);
inited = 1;
}
gettimeofday(&now, 0);
TIMEDELTA(elapsed, now, beginning);
/* Return elapsed milliseconds. */
return (int) ((elapsed.tv_sec * 1000) + (elapsed.tv_usec / 1000));
}
default:
return 0;
}
}
int APIENTRY glutDeviceGet (GLenum type)
{
return 0;
}

214
src/glut/mini/teapot.c Normal file
View File

@ -0,0 +1,214 @@
/* Copyright (c) Mark J. Kilgard, 1994. */
/**
(c) Copyright 1993, Silicon Graphics, Inc.
ALL RIGHTS RESERVED
Permission to use, copy, modify, and distribute this software
for any purpose and without fee is hereby granted, provided
that the above copyright notice appear in all copies and that
both the copyright notice and this permission notice appear in
supporting documentation, and that the name of Silicon
Graphics, Inc. not be used in advertising or publicity
pertaining to distribution of the software without specific,
written prior permission.
THE MATERIAL EMBODIED ON THIS SOFTWARE IS PROVIDED TO YOU
"AS-IS" AND WITHOUT WARRANTY OF ANY KIND, EXPRESS, IMPLIED OR
OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. IN NO
EVENT SHALL SILICON GRAPHICS, INC. BE LIABLE TO YOU OR ANYONE
ELSE FOR ANY DIRECT, SPECIAL, INCIDENTAL, INDIRECT OR
CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER,
INCLUDING WITHOUT LIMITATION, LOSS OF PROFIT, LOSS OF USE,
SAVINGS OR REVENUE, OR THE CLAIMS OF THIRD PARTIES, WHETHER OR
NOT SILICON GRAPHICS, INC. HAS BEEN ADVISED OF THE POSSIBILITY
OF SUCH LOSS, HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
ARISING OUT OF OR IN CONNECTION WITH THE POSSESSION, USE OR
PERFORMANCE OF THIS SOFTWARE.
US Government Users Restricted Rights
Use, duplication, or disclosure by the Government is subject to
restrictions set forth in FAR 52.227.19(c)(2) or subparagraph
(c)(1)(ii) of the Rights in Technical Data and Computer
Software clause at DFARS 252.227-7013 and/or in similar or
successor clauses in the FAR or the DOD or NASA FAR
Supplement. Unpublished-- rights reserved under the copyright
laws of the United States. Contractor/manufacturer is Silicon
Graphics, Inc., 2011 N. Shoreline Blvd., Mountain View, CA
94039-7311.
OpenGL(TM) is a trademark of Silicon Graphics, Inc.
*/
#include <GL/gl.h>
#include <GL/glu.h>
#include "GL/glut.h"
/* Rim, body, lid, and bottom data must be reflected in x and
y; handle and spout data across the y axis only. */
static int patchdata[][16] =
{
/* rim */
{102, 103, 104, 105, 4, 5, 6, 7, 8, 9, 10, 11,
12, 13, 14, 15},
/* body */
{12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
24, 25, 26, 27},
{24, 25, 26, 27, 29, 30, 31, 32, 33, 34, 35, 36,
37, 38, 39, 40},
/* lid */
{96, 96, 96, 96, 97, 98, 99, 100, 101, 101, 101,
101, 0, 1, 2, 3,},
{0, 1, 2, 3, 106, 107, 108, 109, 110, 111, 112,
113, 114, 115, 116, 117},
/* bottom */
{118, 118, 118, 118, 124, 122, 119, 121, 123, 126,
125, 120, 40, 39, 38, 37},
/* handle */
{41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
53, 54, 55, 56},
{53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
28, 65, 66, 67},
/* spout */
{68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
80, 81, 82, 83},
{80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
92, 93, 94, 95}
};
/* *INDENT-OFF* */
static float cpdata[][3] =
{
{0.2, 0, 2.7}, {0.2, -0.112, 2.7}, {0.112, -0.2, 2.7}, {0,
-0.2, 2.7}, {1.3375, 0, 2.53125}, {1.3375, -0.749, 2.53125},
{0.749, -1.3375, 2.53125}, {0, -1.3375, 2.53125}, {1.4375,
0, 2.53125}, {1.4375, -0.805, 2.53125}, {0.805, -1.4375,
2.53125}, {0, -1.4375, 2.53125}, {1.5, 0, 2.4}, {1.5, -0.84,
2.4}, {0.84, -1.5, 2.4}, {0, -1.5, 2.4}, {1.75, 0, 1.875},
{1.75, -0.98, 1.875}, {0.98, -1.75, 1.875}, {0, -1.75,
1.875}, {2, 0, 1.35}, {2, -1.12, 1.35}, {1.12, -2, 1.35},
{0, -2, 1.35}, {2, 0, 0.9}, {2, -1.12, 0.9}, {1.12, -2,
0.9}, {0, -2, 0.9}, {-2, 0, 0.9}, {2, 0, 0.45}, {2, -1.12,
0.45}, {1.12, -2, 0.45}, {0, -2, 0.45}, {1.5, 0, 0.225},
{1.5, -0.84, 0.225}, {0.84, -1.5, 0.225}, {0, -1.5, 0.225},
{1.5, 0, 0.15}, {1.5, -0.84, 0.15}, {0.84, -1.5, 0.15}, {0,
-1.5, 0.15}, {-1.6, 0, 2.025}, {-1.6, -0.3, 2.025}, {-1.5,
-0.3, 2.25}, {-1.5, 0, 2.25}, {-2.3, 0, 2.025}, {-2.3, -0.3,
2.025}, {-2.5, -0.3, 2.25}, {-2.5, 0, 2.25}, {-2.7, 0,
2.025}, {-2.7, -0.3, 2.025}, {-3, -0.3, 2.25}, {-3, 0,
2.25}, {-2.7, 0, 1.8}, {-2.7, -0.3, 1.8}, {-3, -0.3, 1.8},
{-3, 0, 1.8}, {-2.7, 0, 1.575}, {-2.7, -0.3, 1.575}, {-3,
-0.3, 1.35}, {-3, 0, 1.35}, {-2.5, 0, 1.125}, {-2.5, -0.3,
1.125}, {-2.65, -0.3, 0.9375}, {-2.65, 0, 0.9375}, {-2,
-0.3, 0.9}, {-1.9, -0.3, 0.6}, {-1.9, 0, 0.6}, {1.7, 0,
1.425}, {1.7, -0.66, 1.425}, {1.7, -0.66, 0.6}, {1.7, 0,
0.6}, {2.6, 0, 1.425}, {2.6, -0.66, 1.425}, {3.1, -0.66,
0.825}, {3.1, 0, 0.825}, {2.3, 0, 2.1}, {2.3, -0.25, 2.1},
{2.4, -0.25, 2.025}, {2.4, 0, 2.025}, {2.7, 0, 2.4}, {2.7,
-0.25, 2.4}, {3.3, -0.25, 2.4}, {3.3, 0, 2.4}, {2.8, 0,
2.475}, {2.8, -0.25, 2.475}, {3.525, -0.25, 2.49375},
{3.525, 0, 2.49375}, {2.9, 0, 2.475}, {2.9, -0.15, 2.475},
{3.45, -0.15, 2.5125}, {3.45, 0, 2.5125}, {2.8, 0, 2.4},
{2.8, -0.15, 2.4}, {3.2, -0.15, 2.4}, {3.2, 0, 2.4}, {0, 0,
3.15}, {0.8, 0, 3.15}, {0.8, -0.45, 3.15}, {0.45, -0.8,
3.15}, {0, -0.8, 3.15}, {0, 0, 2.85}, {1.4, 0, 2.4}, {1.4,
-0.784, 2.4}, {0.784, -1.4, 2.4}, {0, -1.4, 2.4}, {0.4, 0,
2.55}, {0.4, -0.224, 2.55}, {0.224, -0.4, 2.55}, {0, -0.4,
2.55}, {1.3, 0, 2.55}, {1.3, -0.728, 2.55}, {0.728, -1.3,
2.55}, {0, -1.3, 2.55}, {1.3, 0, 2.4}, {1.3, -0.728, 2.4},
{0.728, -1.3, 2.4}, {0, -1.3, 2.4}, {0, 0, 0}, {1.425,
-0.798, 0}, {1.5, 0, 0.075}, {1.425, 0, 0}, {0.798, -1.425,
0}, {0, -1.5, 0.075}, {0, -1.425, 0}, {1.5, -0.84, 0.075},
{0.84, -1.5, 0.075}
};
static float tex[2][2][2] =
{
{ {0, 0},
{1, 0}},
{ {0, 1},
{1, 1}}
};
/* *INDENT-ON* */
static void
teapot(GLint grid, GLdouble scale, GLenum type)
{
float p[4][4][3], q[4][4][3], r[4][4][3], s[4][4][3];
long i, j, k, l;
#if 0
glPushAttrib(GL_ENABLE_BIT | GL_EVAL_BIT);
glEnable(GL_AUTO_NORMAL);
glEnable(GL_NORMALIZE);
glEnable(GL_MAP2_VERTEX_3);
glEnable(GL_MAP2_TEXTURE_COORD_2);
glPushMatrix();
glRotatef(270.0, 1.0, 0.0, 0.0);
glScalef(0.5 * scale, 0.5 * scale, 0.5 * scale);
glTranslatef(0.0, 0.0, -1.5);
for (i = 0; i < 10; i++) {
for (j = 0; j < 4; j++) {
for (k = 0; k < 4; k++) {
for (l = 0; l < 3; l++) {
p[j][k][l] = cpdata[patchdata[i][j * 4 + k]][l];
q[j][k][l] = cpdata[patchdata[i][j * 4 + (3 - k)]][l];
if (l == 1)
q[j][k][l] *= -1.0;
if (i < 6) {
r[j][k][l] =
cpdata[patchdata[i][j * 4 + (3 - k)]][l];
if (l == 0)
r[j][k][l] *= -1.0;
s[j][k][l] = cpdata[patchdata[i][j * 4 + k]][l];
if (l == 0)
s[j][k][l] *= -1.0;
if (l == 1)
s[j][k][l] *= -1.0;
}
}
}
}
glMap2f(GL_MAP2_TEXTURE_COORD_2, 0, 1, 2, 2, 0, 1, 4, 2,
&tex[0][0][0]);
glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4,
&p[0][0][0]);
glMapGrid2f(grid, 0.0, 1.0, grid, 0.0, 1.0);
glEvalMesh2(type, 0, grid, 0, grid);
glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4,
&q[0][0][0]);
glEvalMesh2(type, 0, grid, 0, grid);
if (i < 6) {
glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4,
&r[0][0][0]);
glEvalMesh2(type, 0, grid, 0, grid);
glMap2f(GL_MAP2_VERTEX_3, 0, 1, 3, 4, 0, 1, 12, 4,
&s[0][0][0]);
glEvalMesh2(type, 0, grid, 0, grid);
}
}
glPopMatrix();
glPopAttrib();
#endif
}
/* CENTRY */
void APIENTRY
glutSolidTeapot(GLdouble scale)
{
teapot(7, scale, GL_FILL);
}
void APIENTRY
glutWireTeapot(GLdouble scale)
{
teapot(10, scale, GL_LINE);
}
/* ENDCENTRY */

273
src/glut/mini/window.c Normal file
View File

@ -0,0 +1,273 @@
/*
* Mesa 3-D graphics library
* Version: 4.1
* Copyright (C) 1995-1998 Brian Paul
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/*
* DOS/DJGPP glut driver v1.2 for Mesa 4.1
*
* Copyright (C) 2002 - Borca Daniel
* Email : dborca@yahoo.com
* Web : http://www.geocities.com/dborca
*/
#include <stdio.h>
#include <GL/gl.h>
#include "GL/glut.h"
#include "internal.h"
#define USE_MINI_GLX 1
#if USE_MINI_GLX
#include "GL/miniglx.h"
#else
#include <GL/glx.h>
#endif
static GLXContext context = 0;
static Window win;
static XVisualInfo *visinfo = 0;
static Display *dpy = 0;
int APIENTRY glutCreateWindow (const char *title)
{
XSetWindowAttributes attr;
unsigned long mask;
GLXContext ctx;
int scrnum = 0;
Window root = RootWindow( dpy, scrnum );
if (win)
return 0;
if (!dpy) {
dpy = XOpenDisplay(NULL);
if (!dpy) {
printf("Error: XOpenDisplay failed\n");
exit(1);
}
}
if (!visinfo) {
int attrib[] = {GLX_RGBA,
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
GLX_DEPTH_SIZE, 1,
GLX_DOUBLEBUFFER,
None };
visinfo = glXChooseVisual( dpy, scrnum, attrib );
if (!visinfo) {
printf("Error: couldn't get an RGB, Double-buffered visual\n");
exit(1);
}
}
/* window attributes */
attr.background_pixel = 0;
attr.border_pixel = 0;
attr.colormap = XCreateColormap( dpy, root, visinfo->visual, AllocNone);
attr.event_mask = StructureNotifyMask | ExposureMask;
mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
win = XCreateWindow( dpy, root, 0, 0, g_width, g_height,
0, visinfo->depth, InputOutput,
visinfo->visual, mask, &attr );
if (!win) {
printf("Error: XCreateWindow failed\n");
exit(1);
}
ctx = glXCreateContext( dpy, visinfo, NULL, True );
if (!ctx) {
printf("Error: glXCreateContext failed\n");
exit(1);
}
if (!glXMakeCurrent( dpy, win, ctx )) {
printf("Error: glXMakeCurrent failed\n");
exit(1);
}
if (!(g_display_mode & GLUT_DOUBLE))
glDrawBuffer( GL_FRONT );
XMapWindow( dpy, win );
#if !USE_MINI_GLX
{
XEvent e;
while (1) {
XNextEvent( dpy, &e );
if (e.type == MapNotify && e.xmap.window == win) {
break;
}
}
}
#endif
return 1;
}
int APIENTRY glutCreateSubWindow (int win, int x, int y, int width, int height)
{
return GL_FALSE;
}
void APIENTRY glutDestroyWindow (int idx)
{
if (dpy && win)
XDestroyWindow( dpy, win );
if (dpy)
XCloseDisplay( dpy );
win = 0;
dpy = 0;
}
void APIENTRY glutPostRedisplay (void)
{
g_redisplay = GL_TRUE;
}
void APIENTRY glutSwapBuffers (void)
{
/* if (g_mouse) pc_scare_mouse(); */
if (dpy && win) glXSwapBuffers( dpy, win );
/* if (g_mouse) pc_unscare_mouse(); */
}
int APIENTRY glutGetWindow (void)
{
return 0;
}
void APIENTRY glutSetWindow (int win)
{
}
void APIENTRY glutSetWindowTitle (const char *title)
{
}
void APIENTRY glutSetIconTitle (const char *title)
{
}
void APIENTRY glutPositionWindow (int x, int y)
{
}
void APIENTRY glutReshapeWindow (int width, int height)
{
}
void APIENTRY glutPopWindow (void)
{
}
void APIENTRY glutPushWindow (void)
{
}
void APIENTRY glutIconifyWindow (void)
{
}
void APIENTRY glutShowWindow (void)
{
}
void APIENTRY glutHideWindow (void)
{
}
void APIENTRY glutMainLoop (void)
{
GLboolean idle;
GLboolean have_event;
XEvent evt;
int visible = 0;
glutPostRedisplay();
if (reshape_func) reshape_func(g_width, g_height);
while (GL_TRUE) {
idle = GL_TRUE;
if (visible && idle_func)
have_event = XCheckMaskEvent( dpy, ~0, &evt );
else
have_event = XNextEvent( dpy, &evt );
if (have_event) {
idle = GL_FALSE;
switch(evt.type) {
case MapNotify:
if (visibility_func) {
visibility_func(GLUT_VISIBLE);
}
visible = 1;
break;
case UnmapNotify:
if (visibility_func) {
visibility_func(GLUT_NOT_VISIBLE);
}
visible = 0;
break;
case Expose:
g_redisplay = 1;
break;
}
}
if (visible && g_redisplay && display_func) {
idle = GL_FALSE;
g_redisplay = GL_FALSE;
display_func();
}
if (visible && idle && idle_func) {
idle_func();
}
}
}

79
src/glx/mini/Makefile.X11 Normal file
View File

@ -0,0 +1,79 @@
# Build a subset DRI-based libGL.so library.
# Indirect rendering not supported, etc.
TOP = ../../..
default: linux-solo
C_SOURCES = dispatch.c \
dri_util.c \
../../mesa/glapi/glapi.c \
../../mesa/glapi/glthread.c \
miniglx.c \
miniglx_events.c \
xf86drm.c
OBJECTS = $(C_SOURCES:.c=.o)
INCLUDES = -I. $(INCLUDE_DIRS)
LIBS = -ldl
### Include directories
INCLUDE_DIRS = \
-I$(TOP)/include \
-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/swrast \
-I$(TOP)/src/mesa/swrast_setup
##### RULES #####
.c.o:
$(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
.S.o:
$(CC) -c $(INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
##### TARGETS #####
targets: depend libGL.so.1.2
libGL.so.1.2: $(OBJECTS) Makefile.X11
rm -f $@ && gcc -shared -Wl,-soname,libGL.so -Wl,-Bsymbolic $(OBJECTS) $(LIBS) -o $@
rm -f $(TOP)/lib/libGL.so*
rm -f $(TOP)/lib/miniglx.conf
install -D libGL.so.1.2 $(TOP)/lib/libGL.so.1.2
ln -s libGL.so.1.2 $(TOP)/lib/libGL.so.1
ln -s libGL.so.1 $(TOP)/lib/libGL.so
install example.miniglx.conf $(TOP)/lib/miniglx.conf
drmtest: xf86drm.o drmtest.o
rm -f drmtest && $(CC) -o drmtest xf86drm.o drmtest.o
# Run 'make -f Makefile.X11 dep' to update the dependencies if you change
# what's included by any source file.
depend: $(C_SOURCES) $(ASM_SOURCES)
makedepend -fdepend -Y $(INCLUDES) \
$(C_SOURCES) $(ASM_SOURCES)
# Emacs tags
tags:
etags `find . -name \*.[ch]` `find ../include`
# Remove .o and backup files
clean:
-rm -f drmtest $(TOP)/lib/libGL.so*
-rm -f */*.o */*~ */*.o */*~
include $(TOP)/Make-config
include depend

115
src/glx/mini/NOTES Normal file
View File

@ -0,0 +1,115 @@
Getting MiniGLX up and running
------------------------------
It's necessary to do a bit of work to set up an environment to run miniglx.
For the radeon driver, it's necessary to get the right set of kernel
modules installed before attempting to run any programs:
rmmod radeon agpgart;
insmod agpgart;
insmod $(MESA)/src/kernel/radeonfb/radeonfb.o;
insmod $(MESA)/src/kernel/radeon/radeon.o;
For all drivers, its necessary to reach the compiled libraries, and
tell MiniGLX where to find it's configuration file:
export LD_LIBRARY_PATH=$(MESA)/lib;
export MINIGLX_CONF=$(MESA)/lib/miniglx.conf
------------------------------------------------------------
MiniGLX Example Programs
------------------------
The following programs will work with miniglx:
$(MESA)/tests/miniglx
$(MESA)/xdemos/glxgears
Thanks to the miniglut stub library, most of the mesa glut demos will
work. In particular, the following have been tested. (Note there is
no keyboard or mouse interaction with these demos).
$(MESA)/demos/gears
$(MESA)/demos/geartrain
$(MESA)/demos/morph3d
$(MESA)/demos/isosurf
$(MESA)/demos/texobj
$(MESA)/demos/texcyl
$(MESA)/demos/gloss
$(MESA)/demos/fire
$(MESA)/demos/tunnel
$(MESA)/demos/teapot
$(MESA)/samples/prim
$(MESA)/samples/olympic
$(MESA)/samples/star
$(MESA)/samples/wave
...etc
In fact most of the glut demos seem to work within the constraints of
having no keyboard/mouse interactivity. Furthermore, the use of the
glut wrapper means that these programs don't require recompilation to
run under MiniGLX -- the same binary works with both regular GLX and
MiniGLX.
------------------------------------------------------------
Porting GLX apps to MiniGLX
---------------------------
A quick list of issues encountered in porting existing GLX apps to
MiniGLX. Listed in no particular order.
1) No input events
MiniGLX doesn't provide an input layer, so any X11 input event
handling in the existing app will have to be redone for whatever
input devices exist on the target.
2) No configuration, expose events
Many GLX and Xlib programs wait on an event to ensure the window has
become visible after being mapped. MiniGLX provides no equivalent
facility.
3) Different headers
X11/Xlib.h, GL/GLX.h, etc must not be used if the program is being
compiled against MiniGLX.
The equivalent header is GL/MiniGLX.h.
4) Different library
It may be necessary to link directly against the minGLX libGL.so.
5) Reduced number of Xlib and GLX entrypoints.
By definition (MiniGLX is a subset of GLX), many Xlib and GLX
entrypoints, structures and macros are not present in MiniGLX. It
will be necessary to find and eliminate all references to
non-supported entrypoints.
---------------------------------------------------------------
Bugs in radeonfb.o -- the radeon framebuffer driver.
----------------------------------------------------
Several bugs have been found in the radeonfb.o framebuffer driver.
Most of these are resolved in the version included in the MiniGLX
sources, but some remain:
1) Occasionally, after entering graphics mode, colors appear 'shifted'
or 'translated', particularly in higher resolution modes. This is
definitely a bug in radeonfb.o as this can be provoked even when using
the software dri driver (fb_dri.so). Importance: High. Workaround:
Use 800x600 as it seems to be less frequent at this resolution,
otherwise, restart the application.

64
src/glx/mini/dispatch.c Normal file
View File

@ -0,0 +1,64 @@
/**
* \file miniglx/dispatch.c
*
* \brief C-based dispatch of the OpenGL entry points (glAccum(), glBegin(),
* etc).
*
* \author Brian Paul <brian@precisioninsight.com>
*
* \note This code IS NOT USED if we're compiling on an x86 system and using
* the glapi_x86.S assembly code.
*/
/*
* Copyright 1998-1999 Precision Insight, 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 PRECISION INSIGHT 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 <GL/gl.h>
#include "glapi.h"
#include "glapitable.h"
#if !(defined(USE_X86_ASM) || defined(USE_SPARC_ASM))
#define KEYWORD1
#define KEYWORD2
#define NAME(func) gl##func
#define DISPATCH(func, args, msg) \
const struct _glapi_table *dispatch; \
dispatch = _glapi_Dispatch ? _glapi_Dispatch : _glapi_get_dispatch();\
(dispatch->func) args
#define RETURN_DISPATCH(func, args, msg) \
const struct _glapi_table *dispatch; \
dispatch = _glapi_Dispatch ? _glapi_Dispatch : _glapi_get_dispatch();\
return (dispatch->func) args
#include "glapitemp.h"
#endif /* USE_X86_ASM */

124
src/glx/mini/dri.h Normal file
View File

@ -0,0 +1,124 @@
/**
* \file miniglxP.h
* \brief Define replacements for some X data types and define the DRI-related
* data structures.
*
* \note Cut down version of glxclient.h.
*
*/
#ifndef _dri_h_
#define _dri_h_
#include "driver.h"
typedef struct __DRIscreenRec __DRIscreen; /**< \copydoc __DRIscreenRec */
typedef struct __DRIcontextRec __DRIcontext; /**< \copydoc __DRIcontextRec */
typedef struct __DRIdrawableRec __DRIdrawable; /**< \copydoc __DRIdrawableRec */
/**
* \brief Screen dependent methods.
*
* This structure is initialized during the MiniGLXDisplayRec::createScreen
* call.
*/
struct __DRIscreenRec {
/**
* \brief Method to destroy the private DRI screen data.
*/
void (*destroyScreen)(__DRIscreen *screen);
/**
* \brief Method to create the private DRI context data and initialize the
* context dependent methods.
*/
void *(*createContext)(__DRIscreen *screen, const __GLcontextModes *glVisual,
void *sharedPrivate);
/**
* \brief Method to create the private DRI drawable data and initialize the
* drawable dependent methods.
*/
void *(*createDrawable)(__DRIscreen *screen,
int width, int height, int index,
const __GLcontextModes *glVisual);
/*
* XXX in the future, implement this:
void *(*createPBuffer)(Display *dpy, int scrn, GLXPbuffer pbuffer,
GLXFBConfig config, __DRIdrawable *pdraw);
*/
/**
* \brief Opaque pointer to private per screen direct rendering data.
*
* \c NULL if direct rendering is not supported on this screen. Never
* dereferenced in libGL.
*/
};
/**
* \brief Context dependent methods.
*
* This structure is initialized during the __DRIscreenRec::createContext call.
*/
struct __DRIcontextRec {
/**
* \brief Method to destroy the private DRI context data.
*/
void (*destroyContext)(__DRIcontext *context);
/**
* \brief Method to bind a DRI drawable to a DRI graphics context.
*
* \todo XXX in the future, also pass a 'read' GLXDrawable for
* glXMakeCurrentReadSGI() and GLX 1.3's glXMakeContextCurrent().
*/
GLboolean (*bindContext)(__DRIscreen *screen, __DRIdrawable *drawable, __DRIcontext *context);
/**
* \brief Method to unbind a DRI drawable to a DRI graphics context.
*/
GLboolean (*unbindContext)(__DRIdrawable *drawable, __DRIcontext *context);
/**
* \brief Opaque pointer to private per context direct rendering data.
*
* NULL if direct rendering is not supported on the display or
* screen used to create this context. Never dereferenced in libGL.
*/
};
/**
* \brief Drawable dependent methods.
*
* This structure is initialized during the __DRIscreenRec::createDrawable call.
*
* __DRIscreenRec::createDrawable is not called by libGL at this time. It's
* currently used via the dri_util.c utility code instead.
*/
struct __DRIdrawableRec {
/**
* \brief Method to destroy the private DRI drawable data.
*/
void (*destroyDrawable)(__DRIdrawable *drawable);
/**
* \brief Method to swap the front and back buffers.
*/
void (*swapBuffers)(__DRIdrawable *drawable);
/**
* \brief Opaque pointer to private per drawable direct rendering data.
*
* \c NULL if direct rendering is not supported on the display or
* screen used to create this drawable. Never dereferenced in libGL.
*/
};
typedef void *(driCreateScreenFunc)(struct DRIDriverRec *driver,
struct DRIDriverContextRec *driverContext);
/** This must be implemented in each driver */
extern driCreateScreenFunc __driCreateScreen;
#endif /* _dri_h_ */

715
src/glx/mini/dri_util.c Normal file
View File

@ -0,0 +1,715 @@
/**
* \file dri_util.c
* \brief DRI utility functions.
*
* This module acts as glue between GLX and the actual hardware driver. A DRI
* driver doesn't really \e have to use any of this - it's optional. But, some
* useful stuff is done here that otherwise would have to be duplicated in most
* drivers.
*
* Basically, these utility functions take care of some of the dirty details of
* screen initialization, context creation, context binding, DRM setup, etc.
*
* These functions are compiled into each DRI driver so libGL.so knows nothing
* about them.
*
*/
#include <assert.h>
#include <fcntl.h>
#include <stdarg.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <linux/fb.h>
#include <linux/vt.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/shm.h>
#include "sarea.h"
#include "dri_util.h"
/**
* \brief Print message to \c stderr if the \c LIBGL_DEBUG environment variable
* is set.
*
* Is called from the drivers.
*
* \param f \e printf like format.
*
* \internal
* This function is a wrapper around vfprintf().
*/
void
__driUtilMessage(const char *f, ...)
{
va_list args;
if (getenv("LIBGL_DEBUG")) {
fprintf(stderr, "libGL error: \n");
va_start(args, f);
vfprintf(stderr, f, args);
va_end(args);
fprintf(stderr, "\n");
}
}
/*****************************************************************/
/** \name Visual utility functions */
/*****************************************************************/
/*@{*/
/*@}*/
/*****************************************************************/
/** \name Context (un)binding functions */
/*****************************************************************/
/*@{*/
/**
* \brief Unbind context.
*
* \param drawable __DRIdrawable
* \param context __DRIcontext
* \param will_rebind not used.
*
* \return GL_TRUE on success, or GL_FALSE on failure.
*
* \internal
* This function calls __DriverAPIRec::UnbindContext, and then decrements
* __DRIdrawablePrivateRec::refcount which must be non-zero for a successful
* return.
*
* While casting the opaque private pointers associated with the parameters into their
* respective real types it also assures they are not null.
*/
static GLboolean driUnbindContext(__DRIdrawable *drawable,
__DRIcontext *context)
{
__DRIdrawablePrivate *pdp = (__DRIdrawablePrivate *)drawable;
__DRIcontextPrivate *pcp = (__DRIcontextPrivate *)context;
__DRIscreenPrivate *psp;
if (pdp == NULL || pcp == NULL)
return GL_FALSE;
if (!(psp = (__DRIscreenPrivate *)pdp->driScreenPriv))
return GL_FALSE;
/* Let driver unbind drawable from context */
(*psp->DriverAPI.UnbindContext)(pcp);
if (pdp->refcount == 0)
return GL_FALSE;
--pdp->refcount;
return GL_TRUE;
}
/**
* \brief Unbind context.
*
* \param pDRIScreen __DRIscreen
* \param drawable __DRIdrawable
* \param context __DRIcontext
*
* \internal
* This function and increments __DRIdrawablePrivateRec::refcount and calls
* __DriverAPIRec::MakeCurrent to binds the drawable.
*
* While casting the opaque private pointers into their
* respective real types it also assures they are not null.
*/
static GLboolean driBindContext(__DRIscreen *screen, __DRIdrawable *drawable,
__DRIcontext *context)
{
__DRIscreenPrivate *psp = (__DRIscreenPrivate *)screen;
__DRIdrawablePrivate *pdp = (__DRIdrawablePrivate *)drawable;
__DRIcontextPrivate *pcp = (__DRIcontextPrivate *)context;
if (psp == NULL)
return GL_FALSE;
if (pdp == NULL || pcp == NULL) {
(*psp->DriverAPI.MakeCurrent)(0, 0, 0);
return GL_TRUE;
}
/* Bind the drawable to the context */
pcp->driDrawablePriv = pdp;
pdp->driContextPriv = pcp;
pdp->refcount++;
/* Call device-specific MakeCurrent */
(*psp->DriverAPI.MakeCurrent)(pcp, pdp, pdp);
return GL_TRUE;
}
/*@}*/
/*****************************************************************/
/** \name Drawable handling functions */
/*****************************************************************/
/*@{*/
/**
* \brief Update private drawable information.
*
* \param pdp pointer to the private drawable information to update.
*
* \internal
* This function is a no-op. Should never be called but is referenced as an
* external symbol from client drivers.
*/
void __driUtilUpdateDrawableInfo(__DRIdrawablePrivate *pdp)
{
__DRIscreenPrivate *psp = pdp->driScreenPriv;
pdp->numClipRects = psp->pSAREA->drawableTable[pdp->index].flags ? 1 : 0;
pdp->lastStamp = *(pdp->pStamp);
}
/**
* \brief Swap buffers.
*
* \param pDRIscreen __DRIscreen
* \param drawablePrivate opaque pointer to the per-drawable private info.
*
* \internal
* This function calls __DRIdrawablePrivate::swapBuffers.
*
* Is called directly from glXSwapBuffers().
*/
static void driSwapBuffers(__DRIdrawable *drawable)
{
__DRIdrawablePrivate *pdp = (__DRIdrawablePrivate *)drawable;
if (pdp)
pdp->swapBuffers(pdp);
}
/**
* \brief Destroy per-drawable private information.
*
* \param pDRIscreen __DRIscreen
* \param drawablePrivate opaque pointer to the per-drawable private info.
*
* \internal
* This function calls __DriverAPIRec::DestroyBuffer on \p drawablePrivate,
* frees the clip rects if any, and finally frees \p drawablePrivate itself.
*/
static void driDestroyDrawable(__DRIdrawable *drawable)
{
__DRIdrawablePrivate *pdp = (__DRIdrawablePrivate *)drawable;
__DRIscreenPrivate *psp;
if (pdp) {
psp = pdp->driScreenPriv;
(*psp->DriverAPI.DestroyBuffer)(pdp);
if (pdp->pClipRects)
free(pdp->pClipRects);
free(pdp);
}
}
/**
* \brief Create the per-drawable private driver information.
*
* \param dpy the display handle.
* \param scrn the screen number.
* \param draw the GLX drawable info.
* \param vid visual ID.
* \param pdraw will receive the drawable dependent methods.
*
*
* \returns a opaque pointer to the per-drawable private info on success, or NULL
* on failure.
*
* \internal
* This function allocates and fills a __DRIdrawablePrivateRec structure,
* initializing the invariant window dimensions and clip rects. It obtains the
* visual config, converts it into a __GLcontextModesRec and passes it to
* __DriverAPIRec::CreateBuffer to create a buffer.
*/
static void *driCreateDrawable(__DRIscreen *screen,
int width, int height, int index,
const __GLcontextModes *glVisual)
{
__DRIscreenPrivate *psp = (__DRIscreenPrivate *)screen;
__DRIdrawablePrivate *pdp;
if (!psp)
return NULL;
if (!(pdp = (__DRIdrawablePrivate *)malloc(sizeof(__DRIdrawablePrivate))))
return NULL;
pdp->index = index;
pdp->refcount = 0;
pdp->lastStamp = -1;
pdp->numBackClipRects = 0;
pdp->pBackClipRects = NULL;
/* Initialize with the invariant window dimensions and clip rects here.
*/
pdp->x = 0;
pdp->y = 0;
pdp->w = width;
pdp->h = height;
pdp->numClipRects = 0;
pdp->pClipRects = (XF86DRIClipRectPtr) malloc(sizeof(XF86DRIClipRectRec));
(pdp->pClipRects)[0].x1 = 0;
(pdp->pClipRects)[0].y1 = 0;
(pdp->pClipRects)[0].x2 = width;
(pdp->pClipRects)[0].y2 = height;
pdp->driScreenPriv = psp;
pdp->driContextPriv = 0;
pdp->frontBuffer = psp->pFB;
pdp->currentBuffer = pdp->frontBuffer;
pdp->currentPitch = psp->fbStride;
pdp->backBuffer = psp->pFB + psp->fbStride * psp->fbHeight;
if (!(*psp->DriverAPI.CreateBuffer)(psp, pdp, glVisual, GL_FALSE)) {
free(pdp);
return NULL;
}
pdp->entry.destroyDrawable = driDestroyDrawable;
pdp->entry.swapBuffers = driSwapBuffers; /* called by glXSwapBuffers() */
pdp->swapBuffers = psp->DriverAPI.SwapBuffers;
pdp->pStamp = &(psp->pSAREA->drawableTable[pdp->index].stamp);
return (void *) pdp;
}
/*@}*/
/*****************************************************************/
/** \name Context handling functions */
/*****************************************************************/
/*@{*/
/**
* \brief Destroy the per-context private information.
*
* \param contextPrivate opaque pointer to the per-drawable private info.
*
* \internal
* This function calls __DriverAPIRec::DestroyContext on \p contextPrivate, calls
* drmDestroyContext(), and finally frees \p contextPrivate.
*/
static void driDestroyContext(__DRIcontext *context)
{
__DRIcontextPrivate *pcp = (__DRIcontextPrivate *)context;
__DRIscreenPrivate *psp = NULL;
if (pcp) {
(*pcp->driScreenPriv->DriverAPI.DestroyContext)(pcp);
psp = pcp->driDrawablePriv->driScreenPriv;
if (psp->fd) {
printf(">>> drmDestroyContext(0x%x)\n", (int) pcp->hHWContext);
drmDestroyContext(psp->fd, pcp->hHWContext);
}
free(pcp);
}
}
/**
* \brief Create the per-drawable private driver information.
*
* \param dpy the display handle.
* \param vis the visual information.
* \param sharedPrivate the shared context dependent methods or NULL if non-existent.
* \param pctx will receive the context dependent methods.
*
* \returns a opaque pointer to the per-context private information on success, or NULL
* on failure.
*
* \internal
* This function allocates and fills a __DRIcontextPrivateRec structure. It
* gets the visual, converts it into a __GLcontextModesRec and passes it
* to __DriverAPIRec::CreateContext to create the context.
*/
static void *driCreateContext(__DRIscreen *screen,
const __GLcontextModes *glVisual,
void *sharedPrivate)
{
__DRIscreenPrivate *psp = (__DRIscreenPrivate *)screen;
__DRIcontextPrivate *pcp;
__DRIcontextPrivate *pshare = (__DRIcontextPrivate *) sharedPrivate;
void *shareCtx;
if (!psp)
return NULL;
if (!(pcp = (__DRIcontextPrivate *)malloc(sizeof(__DRIcontextPrivate))))
return NULL;
pcp->driScreenPriv = psp;
pcp->driDrawablePriv = NULL;
if (psp->fd) {
if (drmCreateContext(psp->fd, &pcp->hHWContext)) {
fprintf(stderr, ">>> drmCreateContext failed\n");
free(pcp);
return NULL;
}
}
shareCtx = pshare ? pshare->driverPrivate : NULL;
if (!(*psp->DriverAPI.CreateContext)(glVisual, pcp, shareCtx)) {
if (psp->fd)
(void) drmDestroyContext(psp->fd, pcp->hHWContext);
free(pcp);
return NULL;
}
pcp->entry.destroyContext = driDestroyContext;
pcp->entry.bindContext = driBindContext;
pcp->entry.unbindContext = driUnbindContext;
return pcp;
}
/*@}*/
/*****************************************************************/
/** \name Screen handling functions */
/*****************************************************************/
/*@{*/
/**
* \brief Destroy the per-screen private information.
*
* \param pDRIscreen __DRIscreen
*
* \internal
* This function calls __DriverAPIRec::DestroyScreen on \p screenPrivate, calls
* drmClose(), and finally frees \p screenPrivate.
*/
static void driDestroyScreen(__DRIscreen *screen)
{
__DRIscreenPrivate *psp = (__DRIscreenPrivate *)screen;
if (psp) {
if (psp->DriverAPI.DestroyScreen)
(*psp->DriverAPI.DestroyScreen)(psp);
if (psp->fd)
(void)drmClose(psp->fd);
free(psp->pDevPriv);
free(psp);
}
}
/**
* \brief Create the per-screen private information.
*
* \param dpy the display handle.
* \param scrn the screen number.
* \param psc will receive the screen dependent methods.
* \param numConfigs number of visuals.
* \param config visuals.
* \param driverAPI driver callbacks structure.
*
* \return a pointer to the per-screen private information.
*
* \internal
* This function allocates and fills a __DRIscreenPrivateRec structure. It
* opens the DRM device verifying that the exported version matches the
* expected. It copies the driver callback functions and calls
* __DriverAPIRec::InitDriver.
*
* If a client maps the framebuffer and SAREA regions.
*/
__DRIscreenPrivate *
__driUtilCreateScreen(struct DRIDriverRec *driver,
struct DRIDriverContextRec *driverContext,
const struct __DriverAPIRec *driverAPI)
{
__DRIscreenPrivate *psp;
if(!(psp = (__DRIscreenPrivate *)malloc(sizeof(__DRIscreenPrivate))))
return NULL;
psp->fd = drmOpen(NULL, driverContext->pciBusID);
if (psp->fd < 0) {
fprintf(stderr, "libGL error: failed to open DRM: %s\n",
strerror(-psp->fd));
free(psp);
return NULL;
}
{
drmVersionPtr version = drmGetVersion(psp->fd);
if (version) {
psp->drmMajor = version->version_major;
psp->drmMinor = version->version_minor;
psp->drmPatch = version->version_patchlevel;
drmFreeVersion(version);
}
else {
fprintf(stderr, "libGL error: failed to get drm version: %s\n",
strerror(-psp->fd));
free(psp);
return NULL;
}
}
/*
* Fake various version numbers.
*/
psp->ddxMajor = 4;
psp->ddxMinor = 0;
psp->ddxPatch = 1;
psp->driMajor = 4;
psp->driMinor = 1;
psp->driPatch = 0;
/* install driver's callback functions */
psp->DriverAPI = *driverAPI;
/*
* Get device-specific info. pDevPriv will point to a struct
* (such as DRIRADEONRec in xfree86/driver/ati/radeon_dri.h)
* that has information about the screen size, depth, pitch,
* ancilliary buffers, DRM mmap handles, etc.
*/
psp->fbOrigin = driverContext->shared.fbOrigin;
psp->fbSize = driverContext->shared.fbSize;
psp->fbStride = driverContext->shared.fbStride;
psp->devPrivSize = driverContext->driverClientMsgSize;
psp->pDevPriv = driverContext->driverClientMsg;
psp->fbWidth = driverContext->shared.virtualWidth;
psp->fbHeight = driverContext->shared.virtualHeight;
psp->fbBPP = driverContext->bpp;
if ((driverContext->FBAddress != NULL) && (driverContext->pSAREA != NULL)) {
/* Already mapped in server */
psp->pFB = driverContext->FBAddress;
psp->pSAREA = driverContext->pSAREA;
} else {
/*
* Map the framebuffer region.
*/
if (drmMap(psp->fd, driverContext->shared.hFrameBuffer, psp->fbSize,
(drmAddressPtr)&psp->pFB)) {
fprintf(stderr, "libGL error: drmMap of framebuffer failed\n");
(void)drmClose(psp->fd);
free(psp);
return NULL;
}
/*
* Map the SAREA region. Further mmap regions may be setup in
* each DRI driver's "createScreen" function.
*/
if (drmMap(psp->fd, driverContext->shared.hSAREA,
driverContext->shared.SAREASize,
(drmAddressPtr)&psp->pSAREA)) {
fprintf(stderr, "libGL error: drmMap of sarea failed\n");
(void)drmUnmap((drmAddress)psp->pFB, psp->fbSize);
(void)drmClose(psp->fd);
free(psp);
return NULL;
}
#ifdef _EMBEDDED
mprotect(psp->pSAREA, driverContext->shared.SAREASize, PROT_READ);
#endif
}
/* Initialize the screen specific GLX driver */
if (psp->DriverAPI.InitDriver) {
if (!(*psp->DriverAPI.InitDriver)(psp)) {
fprintf(stderr, "libGL error: InitDriver failed\n");
free(psp->pDevPriv);
(void)drmClose(psp->fd);
free(psp);
return NULL;
}
}
psp->entry.destroyScreen = driDestroyScreen;
psp->entry.createContext = driCreateContext;
psp->entry.createDrawable = driCreateDrawable;
return psp;
}
/**
* \brief Create the per-screen private information.
*
* Version for drivers without a DRM module.
*
* \param dpy the display handle.
* \param scrn the screen number.
* \param numConfigs number of visuals.
* \param config visuals.
* \param driverAPI driver callbacks structure.
*
* \internal
* Same as __driUtilCreateScreen() but without opening the DRM device.
*/
__DRIscreenPrivate *
__driUtilCreateScreenNoDRM(struct DRIDriverRec *driver,
struct DRIDriverContextRec *driverContext,
const struct __DriverAPIRec *driverAPI)
{
__DRIscreenPrivate *psp;
psp = (__DRIscreenPrivate *)calloc(1, sizeof(__DRIscreenPrivate));
if (!psp)
return NULL;
psp->ddxMajor = 4;
psp->ddxMinor = 0;
psp->ddxPatch = 1;
psp->driMajor = 4;
psp->driMinor = 1;
psp->driPatch = 0;
psp->fd = 0;
psp->fbOrigin = driverContext->shared.fbOrigin;
psp->fbSize = driverContext->shared.fbSize;
psp->fbStride = driverContext->shared.fbStride;
psp->devPrivSize = driverContext->driverClientMsgSize;
psp->pDevPriv = driverContext->driverClientMsg;
psp->fbWidth = driverContext->shared.virtualWidth;
psp->fbHeight = driverContext->shared.virtualHeight;
psp->fbBPP = driverContext->bpp;
psp->pFB = driverContext->FBAddress;
/* install driver's callback functions */
psp->DriverAPI = *driverAPI;
if ((driverContext->FBAddress != NULL) && (driverContext->pSAREA != NULL)) {
/* Already mapped in server */
psp->pFB = driverContext->FBAddress;
psp->pSAREA = driverContext->pSAREA;
} else {
psp->fd = open("/dev/mem", O_RDWR, 0);
/*
* Map the framebuffer region.
*/
if (drmMap(psp->fd, driverContext->shared.hFrameBuffer, psp->fbSize,
(drmAddressPtr)&psp->pFB)) {
fprintf(stderr, "libGL error: drmMap of framebuffer failed\n");
(void)drmClose(psp->fd);
free(psp);
return NULL;
}
driverContext->FBAddress = psp->pFB;
/*
* Map the SAREA region. Non-DRM drivers use a shmem SAREA
*/
int id;
id = shmget(driverContext->shared.hSAREA, driverContext->shared.SAREASize, 0);
driverContext->pSAREA = shmat(id, NULL, 0);
if (!driverContext->pSAREA) {
fprintf(stderr, "libGL error: shmget of sarea failed\n");
(void)drmUnmap((drmAddress)psp->pFB, psp->fbSize);
(void)drmClose(psp->fd);
free(psp);
return NULL;
}
close(psp->fd);
psp->fd = 0;
}
/* Initialize the screen specific GLX driver */
if (psp->DriverAPI.InitDriver) {
if (!(*psp->DriverAPI.InitDriver)(psp)) {
fprintf(stderr, "libGL error: InitDriver failed\n");
free(psp->pDevPriv);
free(psp);
return NULL;
}
}
psp->entry.destroyScreen = driDestroyScreen;
psp->entry.createContext = driCreateContext;
psp->entry.createDrawable = driCreateDrawable;
return psp;
}
/**
* Calculate amount of swap interval used between GLX buffer swaps.
*
* The usage value, on the range [0,max], is the fraction of total swap
* interval time used between GLX buffer swaps is calculated.
*
* \f$p = t_d / (i * t_r)\f$
*
* Where \f$t_d\$f is the time since the last GLX buffer swap, \f$i\f$ is the
* swap interval (as set by \c glXSwapIntervalSGI), and \f$t_r\f$ time
* required for a single vertical refresh period (as returned by \c
* glXGetMscRateOML).
*
* See the documentation for the GLX_MESA_swap_frame_usage extension for more
* details.
*
* \param dPriv Pointer to the private drawable structure.
* \return If less than a single swap interval time period was required
* between GLX buffer swaps, a number greater than 0 and less than
* 1.0 is returned. If exactly one swap interval time period is
* required, 1.0 is returned, and if more than one is required then
* a number greater than 1.0 will be returned.
*
* \sa glXSwapIntervalSGI(), glXGetMscRateOML().
*/
float
driCalculateSwapUsage( __DRIdrawablePrivate *dPriv, int64_t last_swap_ust,
int64_t current_ust )
{
return 0.0f;
}
/**
* Compare the current GLX API version with a driver supplied required version.
*
* The minimum required version is compared with the API version exported by
* the \c __glXGetInternalVersion function (in libGL.so).
*
* \param required_version Minimum required internal GLX API version.
* \return A tri-value return, as from strcmp is returned. A value less
* than, equal to, or greater than zero will be returned if the
* internal GLX API version is less than, equal to, or greater
* than \c required_version.
*
* \sa __glXGetInternalVersion().
*/
int driCompareGLXAPIVersion( GLuint required_version )
{
return 0;
}
/*@}*/

523
src/glx/mini/dri_util.h Normal file
View File

@ -0,0 +1,523 @@
/**
* \file dri_util.h
* \brief DRI utility functions definitions.
*
* This module acts as glue between GLX and the actual hardware driver. A DRI
* driver doesn't really \e have to use any of this - it's optional. But, some
* useful stuff is done here that otherwise would have to be duplicated in most
* drivers.
*
* Basically, these utility functions take care of some of the dirty details of
* screen initialization, context creation, context binding, DRM setup, etc.
*
* These functions are compiled into each DRI driver so libGL.so knows nothing
* about them.
*
* Look for more comments in the dri_util.c file.
*
* \author Kevin E. Martin <kevin@precisioninsight.com>
* \author Brian Paul <brian@precisioninsight.com>
*/
/*
* Copyright 1998-1999 Precision Insight, 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 PRECISION INSIGHT 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 _DRI_UTIL_H_
#define _DRI_UTIL_H_
#include <inttypes.h>
#include "dri.h" /* public entry points */
#include "sarea.h" /* for XF86DRISAREAPtr */
#define _SOLO
typedef unsigned long CARD32;
typedef int (* PFNGLXGETUSTPROC) ( uint64_t * ust );
typedef struct __DRIdisplayPrivateRec __DRIdisplayPrivate; /**< \brief Alias for __DRIdisplayPrivateRec */
typedef struct __DRIscreenPrivateRec __DRIscreenPrivate; /**< \brief Alias for __DRIscreenPrivateRec */
typedef struct __DRIcontextPrivateRec __DRIcontextPrivate; /**< \brief Alias for __DRIcontextPrivateRec */
typedef struct __DRIdrawablePrivateRec __DRIdrawablePrivate; /**< \brief Alias for __DRIdrawablePrivateRec */
typedef struct __DRIswapInfoRec __DRIswapInfo; /**< \brief Alias for __DRIswapInfoPrivateRec */
/**
* Used by DRI_VALIDATE_DRAWABLE_INFO
*/
#define DRI_VALIDATE_DRAWABLE_INFO_ONCE(pDrawPriv) \
do { \
if (*(pDrawPriv->pStamp) != pDrawPriv->lastStamp) { \
__driUtilUpdateDrawableInfo(pDrawPriv); \
} \
} while (0)
/**
* \brief Utility macro to validate the drawable information.
*
* See __DRIdrawablePrivateRec::pStamp and __DRIdrawablePrivateRec::lastStamp.
*/
#define DRI_VALIDATE_DRAWABLE_INFO(psp, pdp) \
do { \
DRI_VALIDATE_DRAWABLE_INFO_ONCE(pdp); \
} while (0)
/**
* Driver callback functions.
*
* Each DRI driver must have one of these structures with all the pointers set
* to appropriate functions within the driver.
*
* When glXCreateContext() is called, for example, it'll call a helper function
* dri_util.c which in turn will jump through the \a CreateContext pointer in
* this structure.
*/
struct __DriverAPIRec {
/**
* Driver initialization callback
*/
GLboolean (*InitDriver)(__DRIscreenPrivate *driScrnPriv);
/**
* Screen destruction callback
*/
void (*DestroyScreen)(__DRIscreenPrivate *driScrnPriv);
/**
* Context creation callback
*/
GLboolean (*CreateContext)(const __GLcontextModes *glVis,
__DRIcontextPrivate *driContextPriv,
void *sharedContextPrivate);
/**
* Context destruction callback
*/
void (*DestroyContext)(__DRIcontextPrivate *driContextPriv);
/**
* Buffer (drawable) creation callback
*/
GLboolean (*CreateBuffer)(__DRIscreenPrivate *driScrnPriv,
__DRIdrawablePrivate *driDrawPriv,
const __GLcontextModes *glVis,
GLboolean pixmapBuffer);
/**
* Buffer (drawable) destruction callback
*/
void (*DestroyBuffer)(__DRIdrawablePrivate *driDrawPriv);
/**
* Buffer swapping callback
*/
void (*SwapBuffers)(__DRIdrawablePrivate *driDrawPriv);
/**
* Context activation callback
*/
GLboolean (*MakeCurrent)(__DRIcontextPrivate *driContextPriv,
__DRIdrawablePrivate *driDrawPriv,
__DRIdrawablePrivate *driReadPriv);
/**
* Context unbinding callback
*/
GLboolean (*UnbindContext)(__DRIcontextPrivate *driContextPriv);
/**
* Full screen mode opening callback.
*
* \deprecated Full screen functionality is no longer used by DRI.
* Drivers should simply install a function returning
* \c GL_TRUE for backwards compatability.
*/
GLboolean (*OpenFullScreen)(__DRIcontextPrivate *driContextPriv);
/**
* Full screen mode closing callback.
*
* \deprecated Full screen functionality is no longer used by DRI.
* Drivers should simply install a function returning
* \c GL_TRUE for backwards compatability.
*/
GLboolean (*CloseFullScreen)(__DRIcontextPrivate *driContextPriv);
/* Retrieves statistics about buffer swap operations. Required if
* GLX_OML_sync_control or GLX_MESA_swap_frame_usage is supported.
*/
int (*GetSwapInfo)( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo );
/* Required if GLX_SGI_video_sync or GLX_OML_sync_control is
* supported.
*/
int (*GetMSC)( __DRIscreenPrivate * priv, int64_t * count );
/**
* These are required if GLX_OML_sync_control is supported.
*/
/*@{*/
int (*WaitForMSC)( __DRIdrawablePrivate *priv, int64_t target_msc,
int64_t divisor, int64_t remainder,
int64_t * msc );
int (*WaitForSBC)( __DRIdrawablePrivate *priv, int64_t target_sbc,
int64_t * msc, int64_t * sbc );
int64_t (*SwapBuffersMSC)( __DRIdrawablePrivate *priv, int64_t target_msc,
int64_t divisor, int64_t remainder );
/*@}*/
};
struct __DRIswapInfoRec {
/**
* Number of swapBuffers operations that have been *completed*.
*/
uint64_t swap_count;
/*
* Unadjusted system time of the last buffer swap. This is the time
* when the swap completed, not the time when swapBuffers was called.
*/
int64_t swap_ust;
/*
* Number of swap operations that occurred after the swap deadline. That
* is if a swap happens more than swap_interval frames after the previous
* swap, it has missed its deadline. If swap_interval is 0, then the
* swap deadline is 1 frame after the previous swap.
*/
uint64_t swap_missed_count;
/*
* Amount of time used by the last swap that missed its deadline. This
* is calculated as (__glXGetUST() - swap_ust) / (swap_interval *
* time_for_single_vrefresh)). If the actual value of swap_interval is
* 0, then 1 is used instead. If swap_missed_count is non-zero, this
* should be greater-than 1.0.
*/
float swap_missed_usage;
};
/**
* \brief Per-drawable private DRI driver information.
*
*/
struct __DRIdrawablePrivateRec {
/**
* \brief Public entry points
*/
__DRIdrawable entry;
/**
* \brief Kernel drawable handle
*
* \note Not currently used.
*/
drmDrawable hHWDrawable;
/**
* \brief Driver's private drawable information.
*
* This structure is opaque.
*/
void *driverPrivate;
/**
* \brief Reference count for number of context's currently bound to this
* drawable.
*
* Once it reaches zero, the drawable can be destroyed.
*
* \note This behavior will change with GLX 1.3.
*/
int refcount;
/**
* \brief Index of this drawable information in the SAREA.
*/
unsigned int index;
/**
* \brief Pointer to the "drawable has changed ID" stamp in the SAREA.
*/
unsigned int *pStamp;
/**
* \brief Last value of the stamp.
*
* If this differs from the value stored at
* __DRIdrawablePrivateRec::pStamp, then the drawable information has been
* modified by the X server, and the drawable information (below) should be
* retrieved from the X server.
*/
unsigned int lastStamp;
/**
* \name Drawable
* Drawable information used in software fallbacks.
*/
/*@{*/
int x;
int y;
int w;
int h;
int numClipRects;
XF86DRIClipRectPtr pClipRects;
/*@}*/
/**
* \name Back and depthbuffer
* Information about the back and depthbuffer where different from above.
*/
/*@{*/
int backX;
int backY;
int backClipRectType;
int numBackClipRects;
XF86DRIClipRectPtr pBackClipRects;
/*@}*/
/**
* \brief Pointer to context to which this drawable is currently bound.
*/
__DRIcontextPrivate *driContextPriv;
/**
* \brief Pointer to screen on which this drawable was created.
*/
__DRIscreenPrivate *driScreenPriv;
int cpp;
void *frontBuffer;
void *backBuffer;
void *currentBuffer;
int currentPitch;
int depthCpp;
void *depthBuffer;
int depthPitch;
/**
* \brief Called via glXSwapBuffers().
*/
void (*swapBuffers)( __DRIdrawablePrivate *dPriv );
};
/**
* \brief Per-context private driver information.
*/
struct __DRIcontextPrivateRec {
/**
* \brief Public entry points
*/
__DRIcontext entry;
/**
* \brief Kernel context handle used to access the device lock.
*/
drmContext hHWContext;
/**
* \brief Device driver's private context data. This structure is opaque.
*/
void *driverPrivate;
/**
* \brief Pointer to drawable currently bound to this context.
*/
__DRIdrawablePrivate *driDrawablePriv;
/**
* \brief Pointer to screen on which this context was created.
*/
__DRIscreenPrivate *driScreenPriv;
};
/**
* \brief Per-screen private driver information.
*/
struct __DRIscreenPrivateRec {
/**
* \brief Public entry points
*/
__DRIscreen entry;
/**
* \brief Callback functions into the hardware-specific DRI driver code.
*/
struct __DriverAPIRec DriverAPI;
/**
* \name DDX version
* DDX / 2D driver version information.
*/
/*@{*/
int ddxMajor;
int ddxMinor;
int ddxPatch;
/*@}*/
/**
* \name DRI version
* DRI X extension version information.
*/
/*@{*/
int driMajor;
int driMinor;
int driPatch;
/*@}*/
/**
* \name DRM version
* DRM (kernel module) version information.
*/
/*@{*/
int drmMajor;
int drmMinor;
int drmPatch;
/*@}*/
/**
* \brief ID used when the client sets the drawable lock.
*
* The X server uses this value to detect if the client has died while
* holding the drawable lock.
*/
int drawLockID;
/**
* \brief File descriptor returned when the kernel device driver is opened.
*
* Used to:
* - authenticate client to kernel
* - map the frame buffer, SAREA, etc.
* - close the kernel device driver
*/
int fd;
/**
* \brief SAREA pointer
*
* Used to access:
* - the device lock
* - the device-independent per-drawable and per-context(?) information
*/
XF86DRISAREAPtr pSAREA;
/**
* \name Direct frame buffer access information
* Used for software fallbacks.
*/
/*@{*/
unsigned char *pFB;
int fbSize;
int fbOrigin;
int fbStride;
int fbWidth;
int fbHeight;
int fbBPP;
/*@}*/
/**
* \name Device-dependent private information (stored in the SAREA).
*
* This data is accessed by the client driver only.
*/
/*@{*/
void *pDevPriv;
int devPrivSize;
/*@}*/
/**
* \brief Dummy context to which drawables are bound when not bound to any
* other context.
*
* A dummy hHWContext is created for this context, and is used by the GL
* core when a hardware lock is required but the drawable is not currently
* bound (e.g., potentially during a SwapBuffers request). The dummy
* context is created when the first "real" context is created on this
* screen.
*/
__DRIcontextPrivate dummyContextPriv;
/**
* \brief Hash table to hold the drawable information for this screen.
*/
void *drawHash;
/**
* \brief Device-dependent private information (not stored in the SAREA).
*
* This pointer is never touched by the DRI layer.
*/
void *private;
/**
* \brief Full screen mode.
*
* If we're in full screen mode (via DRIOpenFullScreen()), this points to
* the drawable that was bound. Otherwise, this is NULL.
*/
__DRIdrawablePrivate *fullscreen;
};
extern void
__driUtilMessage(const char *f, ...);
extern void
__driUtilUpdateDrawableInfo(__DRIdrawablePrivate *pdp);
extern __DRIscreenPrivate *
__driUtilCreateScreen(struct DRIDriverRec *driver,
struct DRIDriverContextRec *driverContext,
const struct __DriverAPIRec *driverAPI);
__DRIscreenPrivate *
__driUtilCreateScreenNoDRM(struct DRIDriverRec *driver,
struct DRIDriverContextRec *driverContext,
const struct __DriverAPIRec *driverAPI);
extern float
driCalculateSwapUsage( __DRIdrawablePrivate *dPriv,
int64_t last_swap_ust, int64_t current_ust );
/* Test the version of the internal GLX API. Returns a value like strcmp. */
extern int
driCompareGLXAPIVersion( GLuint required_version );
/** This is optionally implemented in each driver */
extern void
__driRegisterExtensions( void );
#endif /* _DRI_UTIL_H_ */

177
src/glx/mini/driver.h Normal file
View File

@ -0,0 +1,177 @@
/**
* \file driver.h
* \brief DRI utility functions definitions.
*
* This module acts as glue between GLX and the actual hardware driver. A DRI
* driver doesn't really \e have to use any of this - it's optional. But, some
* useful stuff is done here that otherwise would have to be duplicated in most
* drivers.
*
* Basically, these utility functions take care of some of the dirty details of
* screen initialization, context creation, context binding, DRM setup, etc.
*
* These functions are compiled into each DRI driver so libGL.so knows nothing
* about them.
*
* Look for more comments in the dri_util.c file.
*
* \author Kevin E. Martin <kevin@precisioninsight.com>
* \author Brian Paul <brian@precisioninsight.com>
*/
/*
* Copyright 1998-1999 Precision Insight, 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 PRECISION INSIGHT 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 _driver_H_
#define _driver_H_
#define CAPI /* XXX this should be globally defined somewhere */
#include "GL/gl.h"
#include "GL/internal/glcore.h"
/**
* \brief Clip rectangle definition.
*/
typedef struct _XF86DRIClipRect {
unsigned short x1; /**< \brief Upper: inclusive */
unsigned short y1; /**< \brief Left: inclusive */
unsigned short x2; /**< \brief Lower: exclusive */
unsigned short y2; /**< \brief Right: exclusive */
} XF86DRIClipRectRec, *XF86DRIClipRectPtr;
/**
* \brief DRIDriverContext type.
*/
typedef struct DRIDriverContextRec {
const char *pciBusID;
int pciBus;
int pciDevice;
int pciFunc;
int chipset;
int bpp;
int cpp;
unsigned long FBStart; /**< \brief physical address of the framebuffer */
unsigned long MMIOStart; /**< \brief physical address of the MMIO region */
int FBSize; /**< \brief size of the mmap'd framebuffer in bytes */
int MMIOSize; /**< \brief size of the mmap'd MMIO region in bytes */
void *FBAddress; /**< \brief start of the mmap'd framebuffer */
void *MMIOAddress; /**< \brief start of the mmap'd MMIO region */
/**
* \brief Client configuration details
*
* These are computed on the server and sent to clients as part of
* the initial handshaking.
*/
struct {
unsigned long hSAREA;
int SAREASize;
unsigned long hFrameBuffer;
int fbOrigin;
int fbSize;
int fbStride;
int virtualWidth;
int virtualHeight;
} shared;
/**
* \name From DRIInfoRec
*/
/*@{*/
int drmFD; /**< \brief DRM device file descriptor */
struct _XF86DRISAREA *pSAREA;
unsigned int serverContext; /**< \brief DRM context only active on server */
/*@}*/
/**
* \name Driver private
*
* Populated by __driInitFBDev()
*/
/*@{*/
void *driverPrivate;
void *driverClientMsg;
int driverClientMsgSize;
/*@}*/
} DRIDriverContext;
/**
* \brief Interface to the DRI driver.
*
* This structure is retrieved from the loadable driver by the \e
* __driDriver symbol to access the Mini GLX specific hardware
* initialization and take down routines.
*/
typedef struct DRIDriverRec {
/**
* \brief Get the list of supported gl context modes.
*/
int (*initContextModes)( const DRIDriverContext *context,
int *numModes, const __GLcontextModes **modes );
/**
* \brief Validate the framebuffer device mode
*/
int (*validateMode)( const DRIDriverContext *context );
/**
* \brief Examine mode returned by fbdev (may differ from the one
* requested), restore any hw regs clobbered by fbdev.
*/
int (*postValidateMode)( const DRIDriverContext *context );
/**
* \brief Initialize the framebuffer device.
*/
int (*initFBDev)( DRIDriverContext *context );
/**
* \brief Halt the framebuffer device.
*/
void (*haltFBDev)( DRIDriverContext *context );
/**
* \brief Idle and shutdown hardware in preparation for a VT switch.
*/
int (*shutdownHardware)( const DRIDriverContext *context );
/**
* \brief Restore hardware state after regaining the VT.
*/
int (*restoreHardware)( const DRIDriverContext *context );
/**
* \brief Notify hardware driver of gain/loose focus. May be zero
* as this is of limited utility for most drivers.
*/
void (*notifyFocus)( int have_focus );
} DRIDriver;
#endif /* _driver_H_ */

657
src/glx/mini/drm.h Normal file
View File

@ -0,0 +1,657 @@
/**
* \file drm.h
* \brief Header for the Direct Rendering Manager
*
* This file defines the DRM device ioctls and the strucutre of respective user
* arguments.
*
* \sa xf86drm.h and xf86drm.c for an user-friendlier interface.
*
* \author Rickard E. (Rik) Faith <faith@valinux.com>
*
* \par Acknowledgements:
* Dec 1999, Richard Henderson <rth@twiddle.net>, move to generic \c cmpxchg.
*/
/*
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* VA LINUX SYSTEMS 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 _DRM_H_
#define _DRM_H_
#if defined(__linux__)
#include <linux/config.h>
#include <asm/ioctl.h> /* For _IO* macros */
#define DRM_IOCTL_NR(n) _IOC_NR(n)
#define DRM_IOC_VOID _IOC_NONE
#define DRM_IOC_READ _IOC_READ
#define DRM_IOC_WRITE _IOC_WRITE
#define DRM_IOC_READWRITE _IOC_READ|_IOC_WRITE
#define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size)
#elif defined(__FreeBSD__) || defined(__NetBSD__)
#if defined(__FreeBSD__) && defined(XFree86Server)
/* Prevent name collision when including sys/ioccom.h */
#undef ioctl
#include <sys/ioccom.h>
#define ioctl(a,b,c) xf86ioctl(a,b,c)
#else
#include <sys/ioccom.h>
#endif /* __FreeBSD__ && xf86ioctl */
#define DRM_IOCTL_NR(n) ((n) & 0xff)
#define DRM_IOC_VOID IOC_VOID
#define DRM_IOC_READ IOC_OUT
#define DRM_IOC_WRITE IOC_IN
#define DRM_IOC_READWRITE IOC_INOUT
#define DRM_IOC(dir, group, nr, size) _IOC(dir, group, nr, size)
#endif
#define XFREE86_VERSION(major,minor,patch,snap) \
((major << 16) | (minor << 8) | patch)
#ifndef CONFIG_XFREE86_VERSION
#define CONFIG_XFREE86_VERSION XFREE86_VERSION(4,1,0,0)
#endif
#if CONFIG_XFREE86_VERSION < XFREE86_VERSION(4,1,0,0)
#define DRM_PROC_DEVICES "/proc/devices"
#define DRM_PROC_MISC "/proc/misc"
#define DRM_PROC_DRM "/proc/drm"
#define DRM_DEV_DRM "/dev/drm"
#define DRM_DEV_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP)
#define DRM_DEV_UID 0
#define DRM_DEV_GID 0
#endif
#if CONFIG_XFREE86_VERSION >= XFREE86_VERSION(4,1,0,0)
#define DRM_MAJOR 226
#define DRM_MAX_MINOR 15
#endif
#define DRM_NAME "drm" /**< Name in kernel, /dev, and /proc */
#define DRM_MIN_ORDER 5 /**< At least 2^5 bytes = 32 bytes */
#define DRM_MAX_ORDER 22 /**< Up to 2^22 bytes = 4MB */
#define DRM_RAM_PERCENT 10 /**< How much system ram can we lock? */
#define _DRM_LOCK_HELD 0x80000000 /**< Hardware lock is held */
#define _DRM_LOCK_CONT 0x40000000 /**< Hardware lock is contended */
#define _DRM_LOCK_IS_HELD(lock) ((lock) & _DRM_LOCK_HELD)
#define _DRM_LOCK_IS_CONT(lock) ((lock) & _DRM_LOCK_CONT)
#define _DRM_LOCKING_CONTEXT(lock) ((lock) & ~(_DRM_LOCK_HELD|_DRM_LOCK_CONT))
typedef unsigned long drm_handle_t;
typedef unsigned int drm_context_t;
typedef unsigned int drm_drawable_t;
typedef unsigned int drm_magic_t;
/**
* Cliprect.
*
* \warning: If you change this structure, make sure you change
* XF86DRIClipRectRec in the server as well
*
* \note KW: Actually it's illegal to change either for
* backwards-compatibility reasons.
*/
typedef struct drm_clip_rect {
unsigned short x1;
unsigned short y1;
unsigned short x2;
unsigned short y2;
} drm_clip_rect_t;
/**
* Texture region,
*/
typedef struct drm_tex_region {
unsigned char next;
unsigned char prev;
unsigned char in_use;
unsigned char padding;
unsigned int age;
} drm_tex_region_t;
/**
* \brief DRM_IOCTL_VERSION ioctl argument type.
*
* \sa drmGetVersion().
*/
typedef struct drm_version {
int version_major; /**< Major version */
int version_minor; /**< Minor version */
int version_patchlevel;/**< Patch level */
size_t name_len; /**< Length of name buffer */
char *name; /**< Name of driver */
size_t date_len; /**< Length of date buffer */
char *date; /**< User-space buffer to hold date */
size_t desc_len; /**< Length of desc buffer */
char *desc; /**< User-space buffer to hold desc */
} drm_version_t;
/**
* \brief DRM_IOCTL_GET_UNIQUE ioctl argument type.
*
* \sa drmGetBusid() and drmSetBusId().
*/
typedef struct drm_unique {
size_t unique_len; /**< Length of unique */
char *unique; /**< Unique name for driver instantiation */
} drm_unique_t;
typedef struct drm_list {
int count; /**< Length of user-space structures */
drm_version_t *version;
} drm_list_t;
typedef struct drm_block {
int unused;
} drm_block_t;
/**
* \brief DRM_IOCTL_CONTROL ioctl argument type.
*
* \sa drmCtlInstHandler() and drmCtlUninstHandler().
*/
typedef struct drm_control {
enum {
DRM_ADD_COMMAND,
DRM_RM_COMMAND,
DRM_INST_HANDLER,
DRM_UNINST_HANDLER
} func;
int irq;
} drm_control_t;
/**
* \brief Type of memory to map.
*/
typedef enum drm_map_type {
_DRM_FRAME_BUFFER = 0, /**< WC (no caching), no core dump */
_DRM_REGISTERS = 1, /**< no caching, no core dump */
_DRM_SHM = 2, /**< shared, cached */
_DRM_AGP = 3, /**< AGP/GART */
_DRM_SCATTER_GATHER = 4 /**< Scatter/gather memory for PCI DMA */
} drm_map_type_t;
/**
* \brief Memory mapping flags.
*/
typedef enum drm_map_flags {
_DRM_RESTRICTED = 0x01, /**< Cannot be mapped to user-virtual */
_DRM_READ_ONLY = 0x02,
_DRM_LOCKED = 0x04, /**< shared, cached, locked */
_DRM_KERNEL = 0x08, /**< kernel requires access */
_DRM_WRITE_COMBINING = 0x10, /**< use write-combining if available */
_DRM_CONTAINS_LOCK = 0x20, /**< SHM page that contains lock */
_DRM_REMOVABLE = 0x40 /**< Removable mapping */
} drm_map_flags_t;
typedef struct drm_ctx_priv_map {
unsigned int ctx_id; /**< Context requesting private mapping */
void *handle; /**< Handle of map */
} drm_ctx_priv_map_t;
/**
* \brief DRM_IOCTL_GET_MAP, DRM_IOCTL_ADD_MAP and DRM_IOCTL_RM_MAP ioctls
* argument type.
*
* \sa drmAddMap().
*/
typedef struct drm_map {
unsigned long offset; /**< Requested physical address (0 for SAREA)*/
unsigned long size; /**< Requested physical size (bytes) */
drm_map_type_t type; /**< Type of memory to map */
drm_map_flags_t flags; /**< Flags */
void *handle; /**< User-space: "Handle" to pass to mmap() */
/**< Kernel-space: kernel-virtual address */
int mtrr; /**< MTRR slot used */
/* Private data */
} drm_map_t;
/**
* \brief DRM_IOCTL_GET_CLIENT ioctl argument type.
*/
typedef struct drm_client {
int idx; /**< Which client desired? */
int auth; /**< Is client authenticated? */
unsigned long pid; /**< Process ID */
unsigned long uid; /**< User ID */
unsigned long magic; /**< Magic */
unsigned long iocs; /**< Ioctl count */
} drm_client_t;
typedef enum {
_DRM_STAT_LOCK,
_DRM_STAT_OPENS,
_DRM_STAT_CLOSES,
_DRM_STAT_IOCTLS,
_DRM_STAT_LOCKS,
_DRM_STAT_UNLOCKS,
_DRM_STAT_VALUE, /**< Generic value */
_DRM_STAT_BYTE, /**< Generic byte counter (1024bytes/K) */
_DRM_STAT_COUNT, /**< Generic non-byte counter (1000/k) */
_DRM_STAT_IRQ, /**< IRQ */
_DRM_STAT_PRIMARY, /**< Primary DMA bytes */
_DRM_STAT_SECONDARY, /**< Secondary DMA bytes */
_DRM_STAT_DMA, /**< DMA */
_DRM_STAT_SPECIAL, /**< Special DMA (e.g., priority or polled) */
_DRM_STAT_MISSED /**< Missed DMA opportunity */
/* Add to the *END* of the list */
} drm_stat_type_t;
/**
* \brief DRM_IOCTL_GET_STATS ioctl argument type.
*/
typedef struct drm_stats {
unsigned long count;
struct {
unsigned long value;
drm_stat_type_t type;
} data[15];
} drm_stats_t;
/**
* \brief Hardware locking flags.
*/
typedef enum drm_lock_flags {
_DRM_LOCK_READY = 0x01, /**< Wait until hardware is ready for DMA */
_DRM_LOCK_QUIESCENT = 0x02, /**< Wait until hardware quiescent */
_DRM_LOCK_FLUSH = 0x04, /**< Flush this context's DMA queue first */
_DRM_LOCK_FLUSH_ALL = 0x08, /**< Flush all DMA queues first */
/* These *HALT* flags aren't supported yet
-- they will be used to support the
full-screen DGA-like mode. */
_DRM_HALT_ALL_QUEUES = 0x10, /**< Halt all current and future queues */
_DRM_HALT_CUR_QUEUES = 0x20 /**< Halt all current queues */
} drm_lock_flags_t;
/**
* \brief DRM_IOCTL_LOCK, DRM_IOCTL_UNLOCK and DRM_IOCTL_FINISH ioctl argument type.
*
* \sa drmGetLock() and drmUnlock().
*/
typedef struct drm_lock {
int context;
drm_lock_flags_t flags;
} drm_lock_t;
/**
* \brief DMA flags
*
* \warning
* These values \e must match xf86drm.h.
*
* \sa drm_dma.
*/
typedef enum drm_dma_flags {
/* Flags for DMA buffer dispatch */
_DRM_DMA_BLOCK = 0x01, /**<
* Block until buffer dispatched.
*
* \note The buffer may not yet have
* been processed by the hardware --
* getting a hardware lock with the
* hardware quiescent will ensure
* that the buffer has been
* processed.
*/
_DRM_DMA_WHILE_LOCKED = 0x02, /**< Dispatch while lock held */
_DRM_DMA_PRIORITY = 0x04, /**< High priority dispatch */
/* Flags for DMA buffer request */
_DRM_DMA_WAIT = 0x10, /**< Wait for free buffers */
_DRM_DMA_SMALLER_OK = 0x20, /**< Smaller-than-requested buffers OK */
_DRM_DMA_LARGER_OK = 0x40 /**< Larger-than-requested buffers OK */
} drm_dma_flags_t;
/**
* \brief DRM_IOCTL_ADD_BUFS and DRM_IOCTL_MARK_BUFS ioctl argument type.
*
* \sa drmAddBufs().
*/
typedef struct drm_buf_desc {
int count; /**< Number of buffers of this size */
int size; /**< Size in bytes */
int low_mark; /**< Low water mark */
int high_mark; /**< High water mark */
enum {
_DRM_PAGE_ALIGN = 0x01, /**< Align on page boundaries for DMA */
_DRM_AGP_BUFFER = 0x02, /**< Buffer is in AGP space */
_DRM_SG_BUFFER = 0x04 /**< Scatter/gather memory buffer */
} flags;
unsigned long agp_start; /**<
* Start address of where the AGP buffers are
* in the AGP aperture
*/
} drm_buf_desc_t;
/**
* \brief DRM_IOCTL_INFO_BUFS ioctl argument type.
*/
typedef struct drm_buf_info {
int count; /**< Entries in list */
drm_buf_desc_t *list;
} drm_buf_info_t;
/**
* \brief DRM_IOCTL_FREE_BUFS ioctl argument type.
*/
typedef struct drm_buf_free {
int count;
int *list;
} drm_buf_free_t;
/**
* \brief Buffer information
*
* \sa drm_buf_map.
*/
typedef struct drm_buf_pub {
int idx; /**< Index into the master buffer list */
int total; /**< Buffer size */
int used; /**< Amount of buffer in use (for DMA) */
void *address; /**< Address of buffer */
} drm_buf_pub_t;
/**
* \brief DRM_IOCTL_MAP_BUFS ioctl argument type.
*/
typedef struct drm_buf_map {
int count; /**< Length of the buffer list */
void *virtual; /**< Mmap'd area in user-virtual */
drm_buf_pub_t *list; /**< Buffer information */
} drm_buf_map_t;
/**
* \brief DRM_IOCTL_DMA ioctl argument type.
*
* Indices here refer to the offset into the buffer list in drm_buf_get.
*
* \sa drmDMA().
*/
typedef struct drm_dma {
int context; /**< Context handle */
int send_count; /**< Number of buffers to send */
int *send_indices; /**< List of handles to buffers */
int *send_sizes; /**< Lengths of data to send */
drm_dma_flags_t flags; /**< Flags */
int request_count; /**< Number of buffers requested */
int request_size; /**< Desired size for buffers */
int *request_indices; /**< Buffer information */
int *request_sizes;
int granted_count; /**< Number of buffers granted */
} drm_dma_t;
typedef enum {
_DRM_CONTEXT_PRESERVED = 0x01,
_DRM_CONTEXT_2DONLY = 0x02
} drm_ctx_flags_t;
/**
* \brief DRM_IOCTL_ADD_CTX ioctl argument type.
*
* \sa drmCreateContext() and drmDestroyContext().
*/
typedef struct drm_ctx {
drm_context_t handle;
drm_ctx_flags_t flags;
} drm_ctx_t;
/**
* \brief DRM_IOCTL_RES_CTX ioctl argument type.
*/
typedef struct drm_ctx_res {
int count;
drm_ctx_t *contexts;
} drm_ctx_res_t;
/**
* \brief DRM_IOCTL_ADD_DRAW and DRM_IOCTL_RM_DRAW ioctl argument type.
*/
typedef struct drm_draw {
drm_drawable_t handle;
} drm_draw_t;
/**
* \brief DRM_IOCTL_GET_MAGIC and DRM_IOCTL_AUTH_MAGIC ioctl argument type.
*/
typedef struct drm_auth {
drm_magic_t magic;
} drm_auth_t;
/**
* \brief DRM_IOCTL_IRQ_BUSID ioctl argument type.
*
* \sa drmGetInterruptFromBusID().
*/
typedef struct drm_irq_busid {
int irq; /**< IRQ number */
int busnum; /**< bus number */
int devnum; /**< device number */
int funcnum; /**< function number */
} drm_irq_busid_t;
typedef enum {
_DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */
_DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */
_DRM_VBLANK_SIGNAL = 0x8000 /**< Send signal instead of blocking */
} drm_vblank_seq_type_t;
#define _DRM_VBLANK_FLAGS_MASK _DRM_VBLANK_SIGNAL
struct drm_wait_vblank_request {
drm_vblank_seq_type_t type;
unsigned int sequence;
unsigned long signal;
};
struct drm_wait_vblank_reply {
drm_vblank_seq_type_t type;
unsigned int sequence;
long tval_sec;
long tval_usec;
};
/**
* \brief DRM_IOCTL_WAIT_VBLANK ioctl argument type.
*
* \sa drmWaitVBlank().
*/
typedef union drm_wait_vblank {
struct drm_wait_vblank_request request;
struct drm_wait_vblank_reply reply;
} drm_wait_vblank_t;
/**
* \brief DRM_IOCTL_AGP_ENABLE ioctl argument type.
*
* \sa drmAgpEnable().
*/
typedef struct drm_agp_mode {
unsigned long mode; /**< AGP mode */
} drm_agp_mode_t;
/**
* \brief DRM_IOCTL_AGP_ALLOC and DRM_IOCTL_AGP_FREE ioctls argument type.
*
* \sa drmAgpAlloc() and drmAgpFree().
*/
typedef struct drm_agp_buffer {
unsigned long size; /**< In bytes -- will round to page boundary */
unsigned long handle; /**< Used for binding / unbinding */
unsigned long type; /**< Type of memory to allocate */
unsigned long physical; /**< Physical used by i810 */
} drm_agp_buffer_t;
/**
* \brief DRM_IOCTL_AGP_BIND and DRM_IOCTL_AGP_UNBIND ioctls argument type.
*
* \sa drmAgpBind() and drmAgpUnbind().
*/
typedef struct drm_agp_binding {
unsigned long handle; /**< From drm_agp_buffer */
unsigned long offset; /**< In bytes -- will round to page boundary */
} drm_agp_binding_t;
/**
* \brief DRM_IOCTL_AGP_INFO ioctl argument type.
*
* \sa drmAgpVersionMajor(), drmAgpVersionMinor(), drmAgpGetMode(),
* drmAgpBase(), drmAgpSize(), drmAgpMemoryUsed(), drmAgpMemoryAvail(),
* drmAgpVendorId() and drmAgpDeviceId().
*/
typedef struct drm_agp_info {
int agp_version_major;
int agp_version_minor;
unsigned long mode;
unsigned long aperture_base; /* physical address */
unsigned long aperture_size; /* bytes */
unsigned long memory_allowed; /* bytes */
unsigned long memory_used;
/* PCI information */
unsigned short id_vendor;
unsigned short id_device;
} drm_agp_info_t;
/**
* \brief DRM_IOCTL_SG_ALLOC ioctl argument type.
*/
typedef struct drm_scatter_gather {
unsigned long size; /**< In bytes -- will round to page boundary */
unsigned long handle; /**< Used for mapping / unmapping */
} drm_scatter_gather_t;
#define DRM_IOCTL_BASE 'd'
#define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr)
#define DRM_IOR(nr,type) _IOR(DRM_IOCTL_BASE,nr,type)
#define DRM_IOW(nr,type) _IOW(DRM_IOCTL_BASE,nr,type)
#define DRM_IOWR(nr,type) _IOWR(DRM_IOCTL_BASE,nr,type)
#define DRM_IOCTL_VERSION DRM_IOWR(0x00, drm_version_t)
#define DRM_IOCTL_GET_UNIQUE DRM_IOWR(0x01, drm_unique_t)
#define DRM_IOCTL_GET_MAGIC DRM_IOR( 0x02, drm_auth_t)
#define DRM_IOCTL_IRQ_BUSID DRM_IOWR(0x03, drm_irq_busid_t)
#define DRM_IOCTL_GET_MAP DRM_IOWR(0x04, drm_map_t)
#define DRM_IOCTL_GET_CLIENT DRM_IOWR(0x05, drm_client_t)
#define DRM_IOCTL_GET_STATS DRM_IOR( 0x06, drm_stats_t)
#define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, drm_unique_t)
#define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, drm_auth_t)
#define DRM_IOCTL_BLOCK DRM_IOWR(0x12, drm_block_t)
#define DRM_IOCTL_UNBLOCK DRM_IOWR(0x13, drm_block_t)
#define DRM_IOCTL_CONTROL DRM_IOW( 0x14, drm_control_t)
#define DRM_IOCTL_ADD_MAP DRM_IOWR(0x15, drm_map_t)
#define DRM_IOCTL_ADD_BUFS DRM_IOWR(0x16, drm_buf_desc_t)
#define DRM_IOCTL_MARK_BUFS DRM_IOW( 0x17, drm_buf_desc_t)
#define DRM_IOCTL_INFO_BUFS DRM_IOWR(0x18, drm_buf_info_t)
#define DRM_IOCTL_MAP_BUFS DRM_IOWR(0x19, drm_buf_map_t)
#define DRM_IOCTL_FREE_BUFS DRM_IOW( 0x1a, drm_buf_free_t)
#define DRM_IOCTL_RM_MAP DRM_IOW( 0x1b, drm_map_t)
#define DRM_IOCTL_SET_SAREA_CTX DRM_IOW( 0x1c, drm_ctx_priv_map_t)
#define DRM_IOCTL_GET_SAREA_CTX DRM_IOWR(0x1d, drm_ctx_priv_map_t)
#define DRM_IOCTL_ADD_CTX DRM_IOWR(0x20, drm_ctx_t)
#define DRM_IOCTL_RM_CTX DRM_IOWR(0x21, drm_ctx_t)
#define DRM_IOCTL_MOD_CTX DRM_IOW( 0x22, drm_ctx_t)
#define DRM_IOCTL_GET_CTX DRM_IOWR(0x23, drm_ctx_t)
#define DRM_IOCTL_SWITCH_CTX DRM_IOW( 0x24, drm_ctx_t)
#define DRM_IOCTL_NEW_CTX DRM_IOW( 0x25, drm_ctx_t)
#define DRM_IOCTL_RES_CTX DRM_IOWR(0x26, drm_ctx_res_t)
#define DRM_IOCTL_ADD_DRAW DRM_IOWR(0x27, drm_draw_t)
#define DRM_IOCTL_RM_DRAW DRM_IOWR(0x28, drm_draw_t)
#define DRM_IOCTL_DMA DRM_IOWR(0x29, drm_dma_t)
#define DRM_IOCTL_LOCK DRM_IOW( 0x2a, drm_lock_t)
#define DRM_IOCTL_UNLOCK DRM_IOW( 0x2b, drm_lock_t)
#define DRM_IOCTL_FINISH DRM_IOW( 0x2c, drm_lock_t)
#define DRM_IOCTL_AGP_ACQUIRE DRM_IO( 0x30)
#define DRM_IOCTL_AGP_RELEASE DRM_IO( 0x31)
#define DRM_IOCTL_AGP_ENABLE DRM_IOW( 0x32, drm_agp_mode_t)
#define DRM_IOCTL_AGP_INFO DRM_IOR( 0x33, drm_agp_info_t)
#define DRM_IOCTL_AGP_ALLOC DRM_IOWR(0x34, drm_agp_buffer_t)
#define DRM_IOCTL_AGP_FREE DRM_IOW( 0x35, drm_agp_buffer_t)
#define DRM_IOCTL_AGP_BIND DRM_IOW( 0x36, drm_agp_binding_t)
#define DRM_IOCTL_AGP_UNBIND DRM_IOW( 0x37, drm_agp_binding_t)
#define DRM_IOCTL_SG_ALLOC DRM_IOW( 0x38, drm_scatter_gather_t)
#define DRM_IOCTL_SG_FREE DRM_IOW( 0x39, drm_scatter_gather_t)
#define DRM_IOCTL_WAIT_VBLANK DRM_IOWR(0x3a, drm_wait_vblank_t)
/**
* Device specific ioctls should only be in their respective headers
* The device specific ioctl range is from 0x40 to 0x79.
*
* \sa drmCommandNone(), drmCommandRead(), drmCommandWrite(), and
* drmCommandReadWrite().
*/
#define DRM_COMMAND_BASE 0x40
#endif

140
src/glx/mini/drmtest.c Normal file
View File

@ -0,0 +1,140 @@
#include <assert.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include "xf86drm.h"
char *pciBusID = "PCI:1:0:0";
#define DRM_PAGE_SIZE 4096
void *pSAREA;
static int client( void )
{
int fd, ret, err;
drmContext clientContext;
fprintf(stderr, "Opening client drm\n");
fd = drmOpen(NULL,pciBusID);
if (fd < 0) {
fprintf(stderr, "failed to open DRM: %s\n", strerror(-fd));
return 1;
}
fprintf(stderr, "Create server context\n");
if ((err = drmCreateContext(fd, &clientContext)) != 0) {
fprintf(stderr, "%s: drmCreateContext failed %d\n", __FUNCTION__, err);
return 0;
}
fprintf(stderr, "DRM_LOCK( %d %p %d )\n", fd, pSAREA, clientContext);
DRM_LOCK(fd, pSAREA, clientContext, 0);
fprintf(stderr, "locked\n");
DRM_UNLOCK(fd, pSAREA, clientContext);
fprintf(stderr, "DRM_UNLOCK finished\n");
fprintf(stderr, "Closing client drm: %d\n", fd);
ret = drmClose(fd);
fprintf(stderr, "done %d\n", ret);
return ret;
}
int main( int argc, char *argv[] )
{
char *drmModuleName = "radeon";
int drmFD;
int err;
int SAREASize;
drmHandle hSAREA;
drmContext serverContext;
/* Note that drmOpen will try to load the kernel module, if needed. */
drmFD = drmOpen(drmModuleName, NULL );
if (drmFD < 0) {
/* failed to open DRM */
fprintf(stderr, "[drm] drmOpen failed\n");
return 0;
}
if ((err = drmSetBusid(drmFD, pciBusID)) < 0) {
drmClose(drmFD);
fprintf(stderr, "[drm] drmSetBusid failed (%d, %s), %s\n",
drmFD, pciBusID, strerror(-err));
return 0;
}
SAREASize = DRM_PAGE_SIZE;
if (drmAddMap( drmFD,
0,
SAREASize,
DRM_SHM,
DRM_CONTAINS_LOCK,
&hSAREA) < 0)
{
drmClose(drmFD);
fprintf(stderr, "[drm] drmAddMap failed\n");
return 0;
}
fprintf(stderr, "[drm] added %d byte SAREA at 0x%08lx\n",
SAREASize, hSAREA);
if (drmMap( drmFD,
hSAREA,
SAREASize,
(drmAddressPtr)(&pSAREA)) < 0)
{
drmClose(drmFD);
fprintf(stderr, "[drm] drmMap failed\n");
return 0;
}
memset(pSAREA, 0, SAREASize);
fprintf(stderr, "[drm] mapped SAREA 0x%08lx to %p, size %d\n",
hSAREA, pSAREA, SAREASize);
fprintf(stderr, "Create server context\n");
if ((err = drmCreateContext(drmFD, &serverContext)) != 0) {
fprintf(stderr, "%s: drmCreateContext failed %d\n", __FUNCTION__, err);
return 0;
}
fprintf(stderr, "DRM_LOCK( %d %p %d )\n", drmFD, pSAREA, serverContext);
DRM_LOCK(drmFD, pSAREA, serverContext, 0);
fprintf(stderr, "locked\n");
DRM_UNLOCK(drmFD, pSAREA, serverContext);
fprintf(stderr, "DRM_UNLOCK finished\n");
client();
fprintf(stderr, "DRM_LOCK( %d %p %d )\n", drmFD, pSAREA, serverContext);
DRM_LOCK(drmFD, pSAREA, serverContext, 0);
fprintf(stderr, "locked\n");
DRM_UNLOCK(drmFD, pSAREA, serverContext);
fprintf(stderr, "DRM_UNLOCK finished\n");
drmUnmap(pSAREA, SAREASize);
fprintf(stderr, "[drm] unmapped SAREA 0x%08lx from %p, size %d\n",
hSAREA, pSAREA, SAREASize);
pSAREA = 0;
fprintf(stderr, "%s: Closing DRM fd\n", __FUNCTION__);
(void)drmClose(drmFD);
return 0;
}

View File

@ -0,0 +1,26 @@
# Example miniglx configuration file (/etc/miniglx.conf)
#
# Framebuffer device to open: Might need to change this on dual-head
# systems.
fbdevDevice=/dev/fb0
# Which driver?
# radeon_dri.so -- HW accelerated radeon driver
# fb_dri.so -- Software rasterizer
clientDriverName=radeon_dri.so
# The pci bus id of the video card. Find this with scanpci, lspci or
# look in /proc/pci.
pciBusID=PCI:1:0:0
# Virtual screen dimensions. Can reduce this to save videocard memory
# at the expense of maximum window size available.
virtualWidth=1280
virtualHeight=1024
# Screen depth. Only 16 & 32bpp supported.
bpp=32
# Rotated monitor? -- NOTE: only works with subsetted radeon driver!
rotateMode=0

1975
src/glx/mini/miniglx.c Normal file

File diff suppressed because it is too large Load Diff

194
src/glx/mini/miniglxP.h Normal file
View File

@ -0,0 +1,194 @@
/**
* \file miniglxP.h
* \brief Define replacements for some X data types and define the DRI-related
* data structures.
*
* \note Cut down version of glxclient.h.
*
*/
#ifndef _mini_GLX_client_h_
#define _mini_GLX_client_h_
#include <signal.h>
#include <linux/fb.h>
#include <GL/miniglx.h>
#include "glheader.h"
#include "mtypes.h"
#include "driver.h"
#include "dri.h"
/**
* \brief Supported pixel formats.
*/
enum PixelFormat {
PF_B8G8R8, /**< \brief 24-bit BGR */
PF_B8G8R8A8, /**< \brief 32-bit BGRA */
PF_B5G6R5, /**< \brief 16-bit BGR */
PF_B5G5R5, /**< \brief 15-bit BGR */
PF_CI8 /**< \brief 8-bit color index */
};
/**
* \brief X Visual type.
*
* \sa ::Visual, \ref datatypes.
*/
struct MiniGLXVisualRec {
/** \brief GLX visual information */
const __GLcontextModes *mode;
/** \brief pointer back to corresponding ::XVisualInfo */
XVisualInfo *visInfo;
/** \brief display handle */
Display *dpy;
/** \brief pixel format */
enum PixelFormat pixelFormat;
};
/**
* \brief X Window type.
*
* \sa ::Window, \ref datatypes.
*/
struct MiniGLXWindowRec {
Visual *visual;
/** \brief position (always 0,0) */
int x, y;
/** \brief size */
unsigned int w, h;
void *frontStart; /**< \brief start of front color buffer */
void *backStart; /**< \brief start of back color buffer */
size_t size; /**< \brief color buffer size, in bytes */
GLuint bytesPerPixel;
GLuint rowStride; /**< \brief in bytes */
GLubyte *frontBottom; /**< \brief pointer to last row */
GLubyte *backBottom; /**< \brief pointer to last row */
GLubyte *curBottom; /**< = frontBottom or backBottom */
__DRIdrawable *driDrawable;
GLuint ismapped;
};
/**
* \brief GLXContext type.
*
* \sa ::GLXContext, \ref datatypes.
*/
struct MiniGLXContextRec {
Window drawBuffer; /**< \brief drawing buffer */
Window curBuffer; /**< \brief current buffer */
VisualID vid; /**< \brief visual ID */
__DRIcontext *driContext; /**< \brief context dependent methods */
};
#define MINIGLX_BUF_SIZE 512
#define MINIGLX_MAX_SERVER_FDS 10
#define MINIGLX_MAX_CLIENT_FDS 1
#define MINIGLX_EVENT_QUEUE_SZ 16
#define MINIGLX_EVENT_QUEUE_MASK (MINIGLX_EVENT_QUEUE_SZ-1)
/**
* A connection to/from the server
*
* All information is to/from the server is buffered and then dispatched by
* __miniglx_Select() to avoid blocking the server.
*/
struct MiniGLXConnection {
int fd; /**< \brief file descriptor */
char readbuf[MINIGLX_BUF_SIZE]; /**< \brief read buffer */
char writebuf[MINIGLX_BUF_SIZE]; /**< \brief write buffer */
int readbuf_count; /**< \brief count of bytes waiting to be read */
int writebuf_count; /**< \brief count of bytes waiting to be written */
};
/**
* \brief X Display type
*
* \sa ::Display, \ref datatypes.
*/
struct MiniGLXDisplayRec {
/** \brief fixed framebuffer screen info */
struct fb_fix_screeninfo FixedInfo;
/** \brief original and current variable framebuffer screen info */
struct fb_var_screeninfo OrigVarInfo, VarInfo;
struct sigaction OrigSigUsr1;
struct sigaction OrigSigUsr2;
int OriginalVT;
int ConsoleFD; /**< \brief console TTY device file descriptor */
int FrameBufferFD; /**< \brief framebuffer device file descriptor */
int NumWindows; /**< \brief number of open windows */
Window TheWindow; /**< \brief open window - only allow one window for now */
int rotateMode;
volatile int vtSignalFlag;
volatile int haveVT; /**< \brief whether the VT is hold */
int hwActive; /**< \brief whether the hardware is active -- mimics
the variations of MiniGLXDisplayRec::haveVT */
int IsClient; /**< \brief whether it's a client or the server */
int clientID;
int nrFds; /**< \brief number of connections (usually just one for the clients) */
struct MiniGLXConnection *fd; /**< \brief connections */
struct {
int nr, head, tail;
XEvent queue[MINIGLX_EVENT_QUEUE_SZ];
} eventqueue;
/**
* \name Visuals
*
* Visuals (configs) in this screen.
*/
/*@{*/
int numModes; /**< \brief Number of modes. */
const __GLcontextModes *modes; /**< \brief Modes list pointer. */
/*@}*/
/**
* \name From __GLXdisplayPrivate
*/
/*@{*/
driCreateScreenFunc *createScreen; /**< \brief \e __driCreateScreen hook */
__DRIscreen *driScreen; /**< \brief Screen dependent methods */
void *dlHandle; /**<
* \brief handle to the client dynamic
* library
*/
/*@}*/
/**
* \brief Mini GLX specific driver hooks
*/
struct DRIDriverRec *driver;
struct DRIDriverContextRec driverContext;
/**
* \name Configuration details
*
* They are read from a configuration file by __read_config_file().
*/
/*@{*/
const char *fbdevDevice;
const char *clientDriverName;
/*@}*/
};
extern __DRIscreen *__glXFindDRIScreen(Display *dpy, int scrn);
extern Bool __glXWindowExists(Display *dpy, GLXDrawable draw);
extern int __miniglx_open_connections( Display *dpy );
extern void __miniglx_close_connections( Display *dpy );
#endif /* !_mini_GLX_client_h_ */

View File

@ -0,0 +1,962 @@
/**
* \file miniglx_events.c
* \brief Mini GLX client/server communication functions.
* \author Keith Whitwell
*
* The Mini GLX interface is a subset of the GLX interface, plus a
* minimal set of Xlib functions. This file adds interfaces to
* arbitrate a single cliprect between multiple direct rendering
* clients.
*
* A fairly complete client/server non-blocking communication
* mechanism. Probably overkill given that none of our messages
* currently exceed 1 byte in length and take place over the
* relatively benign channel provided by a Unix domain socket.
*/
/*
* Mesa 3-D graphics library
* Version: 5.0
*
* Copyright (C) 1999-2003 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/* $Id: miniglx_events.c,v 1.1 2003/08/22 20:11:43 brianp Exp $ */
#include <assert.h>
#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/stat.h>
#include <linux/kd.h>
#include <linux/vt.h>
#include "miniglxP.h"
#include "xf86drm.h"
#include "sarea.h"
#define MINIGLX_FIFO_NAME "/tmp/miniglx.fifo"
/** Character messages. */
enum msgs {
_CanIHaveFocus,
_IDontWantFocus,
_YouveGotFocus,
_YouveLostFocus,
_RepaintPlease,
};
/**
* \brief Allocate an XEvent structure on the event queue.
*
* \param dpy the display handle.
*
* \return Pointer to the queued event structure or NULL on failure.
*
* \internal
* If there is space on the XEvent queue, return a pointer
* to the next free event and increment the eventqueue tail value.
* Otherwise return null.
*/
static XEvent *queue_event( Display *dpy )
{
int incr = (dpy->eventqueue.tail + 1) & MINIGLX_EVENT_QUEUE_MASK;
if (incr == dpy->eventqueue.head) {
return 0;
}
else {
XEvent *ev = &dpy->eventqueue.queue[dpy->eventqueue.tail];
dpy->eventqueue.tail = incr;
return ev;
}
}
/**
* \brief Dequeue an XEvent and copy it into provided storage.
*
* \param dpy the display handle.
* \param event_return pointer to copy the queued event to.
*
* \return True or False depending on success.
*
* \internal
* If there is a queued XEvent on the queue, copy it to the provided
* pointer and increment the eventqueue head value. Otherwise return
* null.
*/
static int dequeue_event( Display *dpy, XEvent *event_return )
{
if (dpy->eventqueue.tail == dpy->eventqueue.head) {
return False;
}
else {
*event_return = dpy->eventqueue.queue[dpy->eventqueue.head];
dpy->eventqueue.head += 1;
dpy->eventqueue.head &= MINIGLX_EVENT_QUEUE_MASK;
return True;
}
}
/**
* \brief Shutdown a socket connection.
*
* \param dpy the display handle.
* \param i the index in dpy->fd of the socket connection.
*
* \internal
* Shutdown and close the file descriptor. If this is the special
* connection in fd[0], issue an error message and exit - there's been
* some sort of failure somewhere. Otherwise, let the application
* know about whats happened by issuing a DestroyNotify event.
*/
static void shut_fd( Display *dpy, int i )
{
if (dpy->fd[i].fd < 0)
return;
shutdown (dpy->fd[i].fd, SHUT_RDWR);
close (dpy->fd[i].fd);
dpy->fd[i].fd = -1;
dpy->fd[i].readbuf_count = 0;
dpy->fd[i].writebuf_count = 0;
if (i == 0) {
fprintf(stderr, "server connection lost\n");
exit(1);
}
else {
/* Pass this to the application as a DestroyNotify event.
*/
XEvent *er = queue_event(dpy);
if (!er) return;
er->xdestroywindow.type = DestroyNotify;
er->xdestroywindow.serial = 0;
er->xdestroywindow.send_event = 0;
er->xdestroywindow.display = dpy;
er->xdestroywindow.window = (Window)i;
}
}
/**
* \brief Send a message to a socket connection.
*
* \param dpy the display handle.
* \param i the index in dpy->fd of the socket connection.
* \param msg the message to send.
* \param sz the size of the message
*
* \internal
* Copy the message to the write buffer for the nominated connection.
* This will be actually sent to that file descriptor from
* __miniglx_Select().
*/
static int send_msg( Display *dpy, int i,
const void *msg, size_t sz )
{
int cnt = dpy->fd[i].writebuf_count;
if (MINIGLX_BUF_SIZE - cnt < sz) {
fprintf(stderr, "client %d: writebuf overflow\n", i);
return False;
}
memcpy( dpy->fd[i].writebuf + cnt, msg, sz ); cnt += sz;
dpy->fd[i].writebuf_count = cnt;
return True;
}
/**
* \brief Send a message to a socket connection.
*
* \param dpy the display handle.
* \param i the index in dpy->fd of the socket connection.
* \param msg the message to send.
*
* \internal
* Use send_msg() to send a one-byte message to a socket.
*/
static int send_char_msg( Display *dpy, int i, char msg )
{
return send_msg( dpy, i, &msg, sizeof(char));
}
/**
* \brief Block and receive a message from a socket connection.
*
* \param dpy the display handle.
* \param connection the index in dpy->fd of the socket connection.
* \param msg storage for the received message.
* \param msg_size the number of bytes to read.
*
* \internal
* Block and read from the connection's file descriptor
* until msg_size bytes have been received.
*
* Only called from welcome_message_part().
*/
static int blocking_read( Display *dpy, int connection,
char *msg, size_t msg_size )
{
int i, r;
for (i = 0 ; i < msg_size ; i += r) {
r = read(dpy->fd[connection].fd, msg + i, msg_size - i);
if (r < 1) {
fprintf(stderr, "blocking_read: %d %s\n", r, strerror(errno));
shut_fd(dpy,connection);
return False;
}
}
return True;
}
/**
* \brief Send/receive a part of the welcome message.
*
* \param dpy the display handle.
* \param i the index in dpy->fd of the socket connection.
* \param msg storage for the sent/received message.
* \param sz the number of bytes to write/read.
*
* \return True on success, or False on failure.
*
* This function is called by welcome_message_part(), to either send or receive
* (via blocking_read()) part of the welcome message, according to whether
* Display::IsClient is set.
*
* Each part of the welcome message on the wire consists of a count and then the
* actual message data with that number of bytes.
*/
static int welcome_message_part( Display *dpy, int i, void **msg, int sz )
{
if (dpy->IsClient) {
int sz;
if (!blocking_read( dpy, i, (char *)&sz, sizeof(sz))) return False;
if (!*msg) *msg = malloc(sz);
if (!*msg) return False;
if (!blocking_read( dpy, i, *msg, sz )) return False;
}
else {
if (!send_msg( dpy, i, &sz, sizeof(sz))) return False;
if (!send_msg( dpy, i, *msg, sz )) return False;
}
return True;
}
/**
* \brief Send/receive the welcome message.
*
* \param dpy the display handle.
* \param i the index in dpy->fd of the socket connection.
*
* \return True on success, or False on failure.
*
* Using welcome_message_part(), sends/receives the client ID, the client
* configuration details in DRIDriverContext::shared, and the driver private
* message in DRIDriverContext::driverClientMsg.
*/
static int welcome_message( Display *dpy, int i )
{
void *tmp = &dpy->driverContext.shared;
int *clientid = dpy->IsClient ? &dpy->clientID : &i;
if (!welcome_message_part( dpy, i, (void **)&clientid, sizeof(*clientid)))
return False;
if (!welcome_message_part( dpy, i, &tmp, sizeof(dpy->driverContext.shared)))
return False;
if (!welcome_message_part( dpy, i,
(void **)&dpy->driverContext.driverClientMsg,
dpy->driverContext.driverClientMsgSize ))
return False;
return True;
}
/**
* \brief Handle a new client connection.
*
* \param dpy the display handle.
*
* \return True on success or False on failure.
*
* Accepts the connection, sets it in non-blocking operation, and finds a free
* slot in Display::fd for it.
*/
static int handle_new_client( Display *dpy )
{
struct sockaddr_un client_address;
unsigned int l = sizeof(client_address);
int r, i;
r = accept(dpy->fd[0].fd, (struct sockaddr *) &client_address, &l);
if (r < 0) {
perror ("accept()");
shut_fd(dpy,0);
return False;
}
if (fcntl(r, F_SETFL, O_NONBLOCK) != 0) {
perror("fcntl");
close(r);
return False;
}
/* Some rough & ready adaption of the XEvent semantics.
*/
for (i = 1 ; i < dpy->nrFds ; i++) {
if (dpy->fd[i].fd < 0) {
XEvent *er = queue_event(dpy);
if (!er) {
close(r);
return False;
}
dpy->fd[i].fd = r;
er->xcreatewindow.type = CreateNotify;
er->xcreatewindow.serial = 0;
er->xcreatewindow.send_event = 0;
er->xcreatewindow.display = dpy;
er->xcreatewindow.window = (Window)i; /* fd slot == window, now? */
/* Send the driver client message - this is expected as the
* first message on a new connection. The recpient already
* knows the size of the message.
*/
welcome_message( dpy, i );
return True;
}
}
fprintf(stderr, "[miniglx] %s: Max nr clients exceeded\n", __FUNCTION__);
close(r);
return False;
}
/**
* This routine "puffs out" the very basic communications between
* client and server to full-sized X Events that can be handled by the
* application.
*
* \param dpy the display handle.
* \param i the index in dpy->fd of the socket connection.
*
* \return True on success or False on failure.
*
* \internal
* Interprets the message (see msg) into a XEvent and advances the file FIFO
* buffer.
*/
static int
handle_fifo_read( Display *dpy, int i )
{
while (dpy->fd[i].readbuf_count) {
char id = dpy->fd[i].readbuf[0];
XEvent *er;
int count = 1;
if (dpy->IsClient) {
switch (id) {
/* The server has called XMapWindow on a client window */
case _YouveGotFocus:
er = queue_event(dpy);
if (!er) return False;
er->xmap.type = MapNotify;
er->xmap.serial = 0;
er->xmap.send_event = False;
er->xmap.display = dpy;
er->xmap.event = dpy->TheWindow;
er->xmap.window = dpy->TheWindow;
er->xmap.override_redirect = False;
if (dpy->driver->notifyFocus)
dpy->driver->notifyFocus( 1 );
break;
/* The server has called XMapWindow on a client window */
case _RepaintPlease:
er = queue_event(dpy);
if (!er) return False;
er->xexpose.type = Expose;
er->xexpose.serial = 0;
er->xexpose.send_event = False;
er->xexpose.display = dpy;
er->xexpose.window = dpy->TheWindow;
if (dpy->rotateMode) {
er->xexpose.x = dpy->TheWindow->y;
er->xexpose.y = dpy->TheWindow->x;
er->xexpose.width = dpy->TheWindow->h;
er->xexpose.height = dpy->TheWindow->w;
}
else {
er->xexpose.x = dpy->TheWindow->x;
er->xexpose.y = dpy->TheWindow->y;
er->xexpose.width = dpy->TheWindow->w;
er->xexpose.height = dpy->TheWindow->h;
}
er->xexpose.count = 0;
break;
/* The server has called 'XUnmapWindow' on a client
* window.
*/
case _YouveLostFocus:
er = queue_event(dpy);
if (!er) return False;
er->xunmap.type = UnmapNotify;
er->xunmap.serial = 0;
er->xunmap.send_event = False;
er->xunmap.display = dpy;
er->xunmap.event = dpy->TheWindow;
er->xunmap.window = dpy->TheWindow;
er->xunmap.from_configure = False;
if (dpy->driver->notifyFocus)
dpy->driver->notifyFocus( 0 );
break;
default:
fprintf(stderr, "Client received unhandled message type %d\n", id);
shut_fd(dpy, i); /* Actually shuts down the client */
return False;
}
}
else {
switch (id) {
/* Lets the server know that the client is ready to render
* (having called 'XMapWindow' locally).
*/
case _CanIHaveFocus:
er = queue_event(dpy);
if (!er) return False;
er->xmaprequest.type = MapRequest;
er->xmaprequest.serial = 0;
er->xmaprequest.send_event = False;
er->xmaprequest.display = dpy;
er->xmaprequest.parent = 0;
er->xmaprequest.window = (Window)i;
break;
/* Both _YouveLostFocus and _IDontWantFocus generate unmap
* events. The idea is that _YouveLostFocus lets the client
* know that it has had focus revoked by the server, whereas
* _IDontWantFocus lets the server know that the client has
* unmapped its own window.
*/
case _IDontWantFocus:
er = queue_event(dpy);
if (!er) return False;
er->xunmap.type = UnmapNotify;
er->xunmap.serial = 0;
er->xunmap.send_event = False;
er->xunmap.display = dpy;
er->xunmap.event = (Window)i;
er->xunmap.window = (Window)i;
er->xunmap.from_configure = False;
break;
default:
fprintf(stderr, "Server received unhandled message type %d\n", id);
shut_fd(dpy, i); /* Generates DestroyNotify event */
return False;
}
}
dpy->fd[i].readbuf_count -= count;
if (dpy->fd[i].readbuf_count) {
memmove(dpy->fd[i].readbuf,
dpy->fd[i].readbuf + count,
dpy->fd[i].readbuf_count);
}
}
return True;
}
/**
* Handle a VT signal
*
* \param dpy display handle.
*
* The VT switches is detected by comparing Display::haveVT and
* Display::hwActive. When loosing the VT the hardware lock is acquired, the
* hardware is shutdown via a call to DRIDriverRec::shutdownHardware(), and the
* VT released. When acquiring the VT back the hardware state is restored via a
* call to DRIDriverRec::restoreHardware() and the hardware lock released.
*/
static void __driHandleVtSignals( Display *dpy )
{
dpy->vtSignalFlag = 0;
fprintf(stderr, "%s: haveVT %d hwActive %d\n", __FUNCTION__,
dpy->haveVT, dpy->hwActive);
if (!dpy->haveVT && dpy->hwActive) {
/* Need to get lock and shutdown hardware */
DRM_LIGHT_LOCK( dpy->driverContext.drmFD,
dpy->driverContext.pSAREA,
dpy->driverContext.serverContext );
dpy->driver->shutdownHardware( &dpy->driverContext );
/* Can now give up control of the VT */
ioctl( dpy->ConsoleFD, VT_RELDISP, 1 );
dpy->hwActive = 0;
}
else if (dpy->haveVT && !dpy->hwActive) {
/* Get VT (wait??) */
ioctl( dpy->ConsoleFD, VT_RELDISP, VT_ACTIVATE );
/* restore HW state, release lock */
dpy->driver->restoreHardware( &dpy->driverContext );
DRM_UNLOCK( dpy->driverContext.drmFD,
dpy->driverContext.pSAREA,
dpy->driverContext.serverContext );
dpy->hwActive = 1;
}
}
#undef max
#define max(x,y) ((x) > (y) ? (x) : (y))
/**
* Logic for the select() call.
*
* \param dpy display handle.
* \param n highest fd in any set plus one.
* \param rfds fd set to be watched for reading, or NULL to create one.
* \param wfds fd set to be watched for writing, or NULL to create one.
* \param xfds fd set to be watched for exceptions or error, or NULL to create one.
* \param tv timeout value, or NULL for no timeout.
*
* \return number of file descriptors contained in the sets, or a negative number on failure.
*
* \note
* This all looks pretty complex, but is necessary especially on the
* server side to prevent a poorly-behaved client from causing the
* server to block in a read or write and hence not service the other
* clients.
*
* \sa
* See select_tut in the Linux manual pages for more discussion.
*
* \internal
* Creates and initializes the file descriptor sets by inspecting Display::fd
* if these aren't passed in the function call. Calls select() and fulfill the
* demands by trying to fill MiniGLXConnection::readbuf and draining
* MiniGLXConnection::writebuf.
* The server fd[0] is handled specially for new connections, by calling
* handle_new_client().
*
*/
int
__miniglx_Select( Display *dpy, int n, fd_set *rfds, fd_set *wfds, fd_set *xfds,
struct timeval *tv )
{
int i;
int retval;
fd_set my_rfds, my_wfds;
struct timeval my_tv;
if (!rfds) {
rfds = &my_rfds;
FD_ZERO(rfds);
}
if (!wfds) {
wfds = &my_wfds;
FD_ZERO(wfds);
}
/* Don't block if there are events queued. Review this if the
* flush in XMapWindow is changed to blocking. (Test case:
* miniglxtest).
*/
if (dpy->eventqueue.head != dpy->eventqueue.tail) {
my_tv.tv_sec = my_tv.tv_usec = 0;
tv = &my_tv;
}
for (i = 0 ; i < dpy->nrFds; i++) {
if (dpy->fd[i].fd < 0)
continue;
if (dpy->fd[i].writebuf_count)
FD_SET(dpy->fd[i].fd, wfds);
if (dpy->fd[i].readbuf_count < MINIGLX_BUF_SIZE)
FD_SET(dpy->fd[i].fd, rfds);
n = max(n, dpy->fd[i].fd + 1);
}
if (dpy->vtSignalFlag)
__driHandleVtSignals( dpy );
retval = select( n, rfds, wfds, xfds, tv );
if (dpy->vtSignalFlag) {
int tmp = errno;
__driHandleVtSignals( dpy );
errno = tmp;
}
if (retval < 0) {
FD_ZERO(rfds);
FD_ZERO(wfds);
return retval;
}
/* Handle server fd[0] specially on the server - accept new client
* connections.
*/
if (!dpy->IsClient) {
if (FD_ISSET(dpy->fd[0].fd, rfds)) {
FD_CLR(dpy->fd[0].fd, rfds);
handle_new_client( dpy );
}
}
/* Otherwise, try and fill readbuffer and drain writebuffer:
*/
for (i = 0 ; i < dpy->nrFds ; i++) {
if (dpy->fd[i].fd < 0)
continue;
/* If there aren't any event slots left, don't examine
* any more file events. This will prevent lost events.
*/
if (dpy->eventqueue.head ==
((dpy->eventqueue.tail + 1) & MINIGLX_EVENT_QUEUE_MASK)) {
fprintf(stderr, "leaving event loop as event queue is full\n");
return retval;
}
if (FD_ISSET(dpy->fd[i].fd, wfds)) {
int r = write(dpy->fd[i].fd,
dpy->fd[i].writebuf,
dpy->fd[i].writebuf_count);
if (r < 1)
shut_fd(dpy,i);
else {
dpy->fd[i].writebuf_count -= r;
if (dpy->fd[i].writebuf_count) {
memmove(dpy->fd[i].writebuf,
dpy->fd[i].writebuf + r,
dpy->fd[i].writebuf_count);
}
}
}
if (FD_ISSET(dpy->fd[i].fd, rfds)) {
int r = read(dpy->fd[i].fd,
dpy->fd[i].readbuf + dpy->fd[i].readbuf_count,
MINIGLX_BUF_SIZE - dpy->fd[i].readbuf_count);
if (r < 1)
shut_fd(dpy,i);
else {
dpy->fd[i].readbuf_count += r;
handle_fifo_read( dpy, i );
}
}
}
return retval;
}
/**
* \brief Handle socket events.
*
* \param dpy the display handle.
* \param nonblock whether to return immediately or wait for an event.
*
* \return True on success, False on failure. Aborts on critical error.
*
* \internal
* This function is the select() main loop.
*/
static int handle_fd_events( Display *dpy, int nonblock )
{
while (1) {
struct timeval tv = {0, 0};
int r = __miniglx_Select( dpy, 0, 0, 0, 0, nonblock ? &tv : 0 );
if (r >= 0)
return True;
if (errno == EINTR || errno == EAGAIN)
continue;
perror ("select()");
exit (1);
}
}
/**
* Initializes the connections.
*
* \param dpy the display handle.
*
* \return True on success or False on failure.
*
* Allocates and initializes the Display::fd array and create a Unix socket on
* the first entry. For a server binds the socket to a filename and listen for
* connections. For a client connects to the server and waits for a welcome
* message. Sets the socket in nonblocking mode.
*/
int __miniglx_open_connections( Display *dpy )
{
struct sockaddr_un sa;
int i;
dpy->nrFds = dpy->IsClient ? 1 : MINIGLX_MAX_SERVER_FDS;
dpy->fd = calloc(1, dpy->nrFds * sizeof(struct MiniGLXConnection));
if (!dpy->fd)
return False;
for (i = 0 ; i < dpy->nrFds ; i++)
dpy->fd[i].fd = -1;
if (!dpy->IsClient) {
if (unlink(MINIGLX_FIFO_NAME) != 0 && errno != ENOENT) {
perror("unlink " MINIGLX_FIFO_NAME);
return False;
}
}
/* Create a Unix socket -- Note this is *not* a network connection!
*/
dpy->fd[0].fd = socket(PF_UNIX, SOCK_STREAM, 0);
if (dpy->fd[0].fd < 0) {
perror("socket " MINIGLX_FIFO_NAME);
return False;
}
memset(&sa, 0, sizeof(sa));
sa.sun_family = AF_UNIX;
strcpy(sa.sun_path, MINIGLX_FIFO_NAME);
if (dpy->IsClient) {
/* Connect to server
*/
if (connect(dpy->fd[0].fd, (struct sockaddr *)&sa, sizeof(sa)) != 0) {
perror("connect");
shut_fd(dpy,0);
return False;
}
/* Wait for configuration messages from the server.
*/
welcome_message( dpy, 0 );
}
else {
mode_t tmp = umask( 0000 ); /* open to everybody ? */
/* Bind socket to our filename
*/
if (bind(dpy->fd[0].fd, (struct sockaddr *)&sa, sizeof(sa)) != 0) {
perror("bind");
shut_fd(dpy,0);
return False;
}
umask( tmp );
/* Listen for connections
*/
if (listen(dpy->fd[0].fd, 5) != 0) {
perror("listen");
shut_fd(dpy,0);
return False;
}
}
if (fcntl(dpy->fd[0].fd, F_SETFL, O_NONBLOCK) != 0) {
perror("fcntl");
shut_fd(dpy,0);
return False;
}
return True;
}
/**
* Frees the connections initialized by __miniglx_open_connections().
*
* \param dpy the display handle.
*/
void __miniglx_close_connections( Display *dpy )
{
int i;
for (i = 0 ; i < dpy->nrFds ; i++) {
if (dpy->fd[i].fd >= 0) {
shutdown (dpy->fd[i].fd, SHUT_RDWR);
close (dpy->fd[i].fd);
}
}
dpy->nrFds = 0;
free(dpy->fd);
}
/**
* Set a drawable flag.
*
* \param dpy the display handle.
* \param w drawable (window).
* \param flag flag.
*
* Sets the specified drawable flag in the SAREA and increment its stamp while
* holding the light hardware lock.
*/
static void set_drawable_flag( Display *dpy, int w, int flag )
{
if (dpy->driverContext.pSAREA) {
if (dpy->hwActive)
DRM_LIGHT_LOCK( dpy->driverContext.drmFD,
dpy->driverContext.pSAREA,
dpy->driverContext.serverContext );
dpy->driverContext.pSAREA->drawableTable[w].stamp++;
dpy->driverContext.pSAREA->drawableTable[w].flags = flag;
if (dpy->hwActive)
DRM_UNLOCK( dpy->driverContext.drmFD,
dpy->driverContext.pSAREA,
dpy->driverContext.serverContext );
}
}
/**
* \brief Map Window.
*
* \param dpy the display handle as returned by XOpenDisplay().
* \param w the window handle.
*
* If called by a client, sends a request for focus to the server. If
* called by the server, will generate a MapNotify and Expose event at
* the client.
*
*/
void
XMapWindow( Display *dpy, Window w )
{
if (dpy->IsClient)
send_char_msg( dpy, 0, _CanIHaveFocus );
else {
set_drawable_flag( dpy, (int)w, 1 );
send_char_msg( dpy, (int)w, _YouveGotFocus );
send_char_msg( dpy, (int)w, _RepaintPlease );
dpy->TheWindow = w;
}
handle_fd_events( dpy, 0 ); /* flush write queue */
}
/**
* \brief Unmap Window.
*
* \param dpy the display handle as returned by XOpenDisplay().
* \param w the window handle.
*
* Called from the client: Lets the server know that the window won't
* be updated anymore.
*
* Called from the server: Tells the specified client that it no longer
* holds the focus.
*/
void
XUnmapWindow( Display *dpy, Window w )
{
if (dpy->IsClient) {
send_char_msg( dpy, 0, _IDontWantFocus );
}
else {
dpy->TheWindow = 0;
set_drawable_flag( dpy, (int)w, 0 );
send_char_msg( dpy, (int)w, _YouveLostFocus );
}
handle_fd_events( dpy, 0 ); /* flush write queue */
}
/**
* \brief Block and wait for next X event.
*
* \param dpy the display handle as returned by XOpenDisplay().
* \param event_return a pointer to an XEvent structure for the returned data.
*
* Wait until there is a new XEvent pending.
*/
int XNextEvent(Display *dpy, XEvent *event_return)
{
for (;;) {
if ( dpy->eventqueue.head != dpy->eventqueue.tail )
return dequeue_event( dpy, event_return );
handle_fd_events( dpy, 0 );
}
}
/**
* \brief Non-blocking check for next X event.
*
* \param dpy the display handle as returned by XOpenDisplay().
* \param event_mask ignored.
* \param event_return a pointer to an XEvent structure for the returned data.
*
* Check if there is a new XEvent pending. Note that event_mask is
* ignored and any pending event will be returned.
*/
Bool XCheckMaskEvent(Display *dpy, long event_mask, XEvent *event_return)
{
if ( dpy->eventqueue.head != dpy->eventqueue.tail )
return dequeue_event( dpy, event_return );
handle_fd_events( dpy, 1 );
return dequeue_event( dpy, event_return );
}

96
src/glx/mini/sarea.h Normal file
View File

@ -0,0 +1,96 @@
/**
* \file sarea.h
* \brief SAREA definitions.
*
* The SAREA is a memory region is shared by the DRM device, the X server and
* the clients.
*
* This file defines its layout in user space.
*
* \author Kevin E. Martin <kevin@precisioninsight.com>
* \author Jens Owen <jens@tungstengraphics.com>
* \author Rickard E. (Rik) Faith <faith@valinux.com>
*/
/*
* Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000 VA Linux Systems, Inc.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sub license, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
* IN NO EVENT SHALL PRECISION INSIGHT 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 _SAREA_H_
#define _SAREA_H_
#include "xf86drm.h"
/* SAREA area needs to be at least a page */
#if defined(__alpha__)
#define SAREA_MAX 0x2000
#elif defined(__ia64__)
#define SAREA_MAX 0x10000 /* 64kB */
#else
/* Intel 830M driver needs at least 8k SAREA */
#define SAREA_MAX 0x2000
#endif
#define SAREA_MAX_DRAWABLES 256
#define SAREA_DRAWABLE_CLAIMED_ENTRY 0x80000000
/**
* \brief SAREA per drawable information.
*
* \sa _XF86DRISAREA.
*/
typedef struct _XF86DRISAREADrawable {
unsigned int stamp;
unsigned int flags;
} XF86DRISAREADrawableRec, *XF86DRISAREADrawablePtr;
/**
* \brief SAREA frame information.
*
* \sa _XF86DRISAREA.
*/
typedef struct _XF86DRISAREAFrame {
unsigned int x;
unsigned int y;
unsigned int width;
unsigned int height;
unsigned int fullscreen;
} XF86DRISAREAFrameRec, *XF86DRISAREAFramePtr;
/**
* \brief SAREA definition.
*/
typedef struct _XF86DRISAREA {
/** first thing is always the DRM locking structure */
drmLock lock;
/** \todo Use readers/writer lock for drawable_lock */
drmLock drawable_lock;
XF86DRISAREADrawableRec drawableTable[SAREA_MAX_DRAWABLES];
XF86DRISAREAFrameRec frame;
drmContext dummy_context;
} XF86DRISAREARec, *XF86DRISAREAPtr;
#endif

1587
src/glx/mini/xf86drm.c Normal file

File diff suppressed because it is too large Load Diff

609
src/glx/mini/xf86drm.h Normal file
View File

@ -0,0 +1,609 @@
/* xf86drm.h -- OS-independent header for DRM user-level library interface
* Created: Tue Jan 5 08:17:23 1999 by faith@precisioninsight.com
*
* Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* PRECISION INSIGHT 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.
*
* Author: Rickard E. (Rik) Faith <faith@valinux.com>
*
* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/xf86drm.h,v 1.22 2003/06/12 14:12:35 eich Exp $
*
*/
#ifndef _XF86DRM_H_
#define _XF86DRM_H_
/* Defaults, if nothing set in xf86config */
#define DRM_DEV_UID 0
#define DRM_DEV_GID 0
/* Default /dev/dri directory permissions 0755 */
#define DRM_DEV_DIRMODE \
(S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH)
#define DRM_DEV_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP)
#define DRM_DIR_NAME "/dev/dri"
#define DRM_DEV_NAME "%s/card%d"
#define DRM_PROC_NAME "/proc/dri/" /* For backware Linux compatibility */
#define DRM_ERR_NO_DEVICE (-1001)
#define DRM_ERR_NO_ACCESS (-1002)
#define DRM_ERR_NOT_ROOT (-1003)
#define DRM_ERR_INVALID (-1004)
#define DRM_ERR_NO_FD (-1005)
#define DRM_AGP_NO_HANDLE 0
typedef unsigned long drmHandle, *drmHandlePtr; /* To mapped regions */
typedef unsigned int drmSize, *drmSizePtr; /* For mapped regions */
typedef void *drmAddress, **drmAddressPtr; /* For mapped regions */
typedef unsigned int drmContext, *drmContextPtr; /* GLXContext handle */
typedef unsigned int drmDrawable, *drmDrawablePtr; /* Unused */
typedef unsigned int drmMagic, *drmMagicPtr; /* Magic for auth */
typedef struct _drmVersion {
int version_major; /* Major version */
int version_minor; /* Minor version */
int version_patchlevel; /* Patch level */
int name_len; /* Length of name buffer */
char *name; /* Name of driver */
int date_len; /* Length of date buffer */
char *date; /* User-space buffer to hold date */
int desc_len; /* Length of desc buffer */
char *desc; /* User-space buffer to hold desc */
} drmVersion, *drmVersionPtr;
typedef struct _drmStats {
unsigned long count; /* Number of data */
struct {
unsigned long value; /* Value from kernel */
const char *long_format; /* Suggested format for long_name */
const char *long_name; /* Long name for value */
const char *rate_format; /* Suggested format for rate_name */
const char *rate_name; /* Short name for value per second */
int isvalue; /* True if value (vs. counter) */
const char *mult_names; /* Multiplier names (e.g., "KGM") */
int mult; /* Multiplier value (e.g., 1024) */
int verbose; /* Suggest only in verbose output */
} data[15];
} drmStatsT;
/* All of these enums *MUST* match with the
kernel implementation -- so do *NOT*
change them! (The drmlib implementation
will just copy the flags instead of
translating them.) */
typedef enum {
DRM_FRAME_BUFFER = 0, /* WC, no caching, no core dump */
DRM_REGISTERS = 1, /* no caching, no core dump */
DRM_SHM = 2, /* shared, cached */
DRM_AGP = 3, /* AGP/GART */
DRM_SCATTER_GATHER = 4 /* PCI scatter/gather */
} drmMapType;
typedef enum {
DRM_RESTRICTED = 0x0001, /* Cannot be mapped to client-virtual */
DRM_READ_ONLY = 0x0002, /* Read-only in client-virtual */
DRM_LOCKED = 0x0004, /* Physical pages locked */
DRM_KERNEL = 0x0008, /* Kernel requires access */
DRM_WRITE_COMBINING = 0x0010, /* Use write-combining, if available */
DRM_CONTAINS_LOCK = 0x0020, /* SHM page that contains lock */
DRM_REMOVABLE = 0x0040 /* Removable mapping */
} drmMapFlags;
typedef enum { /* These values *MUST* match drm.h */
/* Flags for DMA buffer dispatch */
DRM_DMA_BLOCK = 0x01, /* Block until buffer dispatched. Note,
the buffer may not yet have been
processed by the hardware -- getting a
hardware lock with the hardware
quiescent will ensure that the buffer
has been processed. */
DRM_DMA_WHILE_LOCKED = 0x02, /* Dispatch while lock held */
DRM_DMA_PRIORITY = 0x04, /* High priority dispatch */
/* Flags for DMA buffer request */
DRM_DMA_WAIT = 0x10, /* Wait for free buffers */
DRM_DMA_SMALLER_OK = 0x20, /* Smaller-than-requested buffers ok */
DRM_DMA_LARGER_OK = 0x40 /* Larger-than-requested buffers ok */
} drmDMAFlags;
typedef enum {
DRM_PAGE_ALIGN = 0x01,
DRM_AGP_BUFFER = 0x02,
DRM_SG_BUFFER = 0x04
} drmBufDescFlags;
typedef enum {
DRM_LOCK_READY = 0x01, /* Wait until hardware is ready for DMA */
DRM_LOCK_QUIESCENT = 0x02, /* Wait until hardware quiescent */
DRM_LOCK_FLUSH = 0x04, /* Flush this context's DMA queue first */
DRM_LOCK_FLUSH_ALL = 0x08, /* Flush all DMA queues first */
/* These *HALT* flags aren't supported yet
-- they will be used to support the
full-screen DGA-like mode. */
DRM_HALT_ALL_QUEUES = 0x10, /* Halt all current and future queues */
DRM_HALT_CUR_QUEUES = 0x20 /* Halt all current queues */
} drmLockFlags;
typedef enum {
DRM_CONTEXT_PRESERVED = 0x01, /* This context is preserved and
never swapped. */
DRM_CONTEXT_2DONLY = 0x02 /* This context is for 2D rendering only. */
} drmContextFlags, *drmContextFlagsPtr;
typedef struct _drmBufDesc {
int count; /* Number of buffers of this size */
int size; /* Size in bytes */
int low_mark; /* Low water mark */
int high_mark; /* High water mark */
} drmBufDesc, *drmBufDescPtr;
typedef struct _drmBufInfo {
int count; /* Number of buffers described in list */
drmBufDescPtr list; /* List of buffer descriptions */
} drmBufInfo, *drmBufInfoPtr;
typedef struct _drmBuf {
int idx; /* Index into master buflist */
int total; /* Buffer size */
int used; /* Amount of buffer in use (for DMA) */
drmAddress address; /* Address */
} drmBuf, *drmBufPtr;
typedef struct _drmBufMap {
int count; /* Number of buffers mapped */
drmBufPtr list; /* Buffers */
} drmBufMap, *drmBufMapPtr;
typedef struct _drmLock {
volatile unsigned int lock;
char padding[60];
/* This is big enough for most current (and future?) architectures:
DEC Alpha: 32 bytes
Intel Merced: ?
Intel P5/PPro/PII/PIII: 32 bytes
Intel StrongARM: 32 bytes
Intel i386/i486: 16 bytes
MIPS: 32 bytes (?)
Motorola 68k: 16 bytes
Motorola PowerPC: 32 bytes
Sun SPARC: 32 bytes
*/
} drmLock, *drmLockPtr;
typedef struct _drmDMAReq {
/* Indices here refer to the offset into
list in drmBufInfo */
drmContext context; /* Context handle */
int send_count; /* Number of buffers to send */
int *send_list; /* List of handles to buffers */
int *send_sizes; /* Lengths of data to send, in bytes */
drmDMAFlags flags; /* Flags */
int request_count; /* Number of buffers requested */
int request_size; /* Desired size of buffers requested */
int *request_list; /* Buffer information */
int *request_sizes; /* Minimum acceptable sizes */
int granted_count; /* Number of buffers granted at this size */
} drmDMAReq, *drmDMAReqPtr;
typedef struct _drmRegion {
drmHandle handle;
unsigned int offset;
drmSize size;
drmAddress map;
} drmRegion, *drmRegionPtr;
typedef struct _drmTextureRegion {
unsigned char next;
unsigned char prev;
unsigned char in_use;
unsigned char padding; /* Explicitly pad this out */
unsigned int age;
} drmTextureRegion, *drmTextureRegionPtr;
typedef struct _drmClipRect {
unsigned short x1; /* Upper left: inclusive */
unsigned short y1;
unsigned short x2; /* Lower right: exclusive */
unsigned short y2;
} drmClipRect, *drmClipRectPtr;
typedef enum {
DRM_VBLANK_ABSOLUTE = 0x0, /* Wait for specific vblank sequence number */
DRM_VBLANK_RELATIVE = 0x1, /* Wait for given number of vblanks */
DRM_VBLANK_SIGNAL = 0x40000000 /* Send signal instead of blocking */
} drmVBlankSeqType;
typedef struct _drmVBlankReq {
drmVBlankSeqType type;
unsigned int sequence;
unsigned long signal;
} drmVBlankReq, *drmVBlankReqPtr;
typedef struct _drmVBlankReply {
drmVBlankSeqType type;
unsigned int sequence;
long tval_sec;
long tval_usec;
} drmVBlankReply, *drmVBlankReplyPtr;
typedef union _drmVBlank {
drmVBlankReq request;
drmVBlankReply reply;
} drmVBlank, *drmVBlankPtr;
#define __drm_dummy_lock(lock) (*(__volatile__ unsigned int *)lock)
#define DRM_LOCK_HELD 0x80000000 /* Hardware lock is held */
#define DRM_LOCK_CONT 0x40000000 /* Hardware lock is contended */
#if defined(__GNUC__) && (__GNUC__ >= 2)
# if defined(__i386) || defined(__AMD64__)
/* Reflect changes here to drmP.h */
#define DRM_CAS(lock,old,new,__ret) \
do { \
int __dummy; /* Can't mark eax as clobbered */ \
__asm__ __volatile__( \
"lock ; cmpxchg %4,%1\n\t" \
"setnz %0" \
: "=d" (__ret), \
"=m" (__drm_dummy_lock(lock)), \
"=a" (__dummy) \
: "2" (old), \
"r" (new)); \
} while (0)
#elif defined(__alpha__)
#define DRM_CAS(lock, old, new, ret) \
do { \
int old32; \
int cur32; \
__asm__ __volatile__( \
" mb\n" \
" zap %4, 0xF0, %0\n" \
" ldl_l %1, %2\n" \
" zap %1, 0xF0, %1\n" \
" cmpeq %0, %1, %1\n" \
" beq %1, 1f\n" \
" bis %5, %5, %1\n" \
" stl_c %1, %2\n" \
"1: xor %1, 1, %1\n" \
" stl %1, %3" \
: "+r" (old32), \
"+&r" (cur32), \
"=m" (__drm_dummy_lock(lock)),\
"=m" (ret) \
: "r" (old), \
"r" (new)); \
} while(0)
#elif defined(__sparc__)
#define DRM_CAS(lock,old,new,__ret) \
do { register unsigned int __old __asm("o0"); \
register unsigned int __new __asm("o1"); \
register volatile unsigned int *__lock __asm("o2"); \
__old = old; \
__new = new; \
__lock = (volatile unsigned int *)lock; \
__asm__ __volatile__( \
/*"cas [%2], %3, %0"*/ \
".word 0xd3e29008\n\t" \
/*"membar #StoreStore | #StoreLoad"*/ \
".word 0x8143e00a" \
: "=&r" (__new) \
: "0" (__new), \
"r" (__lock), \
"r" (__old) \
: "memory"); \
__ret = (__new != __old); \
} while(0)
#elif defined(__ia64__)
#if 0
/* this currently generates bad code (missing stop bits)... */
#include <ia64intrin.h>
#define DRM_CAS(lock,old,new,__ret) \
do { \
__ret = (__sync_val_compare_and_swap(&__drm_dummy_lock(lock), \
(old), (new)) \
!= (old)); \
} while (0)
#else
#define DRM_CAS(lock,old,new,__ret) \
do { \
unsigned int __result, __old = (old); \
__asm__ __volatile__( \
"mf\n" \
"mov ar.ccv=%2\n" \
";;\n" \
"cmpxchg4.acq %0=%1,%3,ar.ccv" \
: "=r" (__result), "=m" (__drm_dummy_lock(lock)) \
: "r" (__old), "r" (new) \
: "memory"); \
__ret = (__result) != (__old); \
} while (0)
#endif
#elif defined(__powerpc__)
#define DRM_CAS(lock,old,new,__ret) \
do { \
__asm__ __volatile__( \
"sync;" \
"0: lwarx %0,0,%1;" \
" xor. %0,%3,%0;" \
" bne 1f;" \
" stwcx. %2,0,%1;" \
" bne- 0b;" \
"1: " \
"sync;" \
: "=&r"(__ret) \
: "r"(lock), "r"(new), "r"(old) \
: "cr0", "memory"); \
} while (0)
#endif /* architecture */
#endif /* __GNUC__ >= 2 */
#ifndef DRM_CAS
#define DRM_CAS(lock,old,new,ret) do { ret=1; } while (0) /* FAST LOCK FAILS */
#endif
#if defined(__alpha__) || defined(__powerpc__)
#define DRM_CAS_RESULT(_result) int _result
#else
#define DRM_CAS_RESULT(_result) char _result
#endif
#define DRM_LIGHT_LOCK(fd,lock,context) \
do { \
DRM_CAS_RESULT(__ret); \
DRM_CAS(lock,context,DRM_LOCK_HELD|context,__ret); \
if (__ret) drmGetLock(fd,context,0); \
} while(0)
/* This one counts fast locks -- for
benchmarking only. */
#define DRM_LIGHT_LOCK_COUNT(fd,lock,context,count) \
do { \
DRM_CAS_RESULT(__ret); \
DRM_CAS(lock,context,DRM_LOCK_HELD|context,__ret); \
if (__ret) drmGetLock(fd,context,0); \
else ++count; \
} while(0)
#define DRM_LOCK(fd,lock,context,flags) \
do { \
if (flags) drmGetLock(fd,context,flags); \
else DRM_LIGHT_LOCK(fd,lock,context); \
} while(0)
#define DRM_UNLOCK(fd,lock,context) \
do { \
DRM_CAS_RESULT(__ret); \
DRM_CAS(lock,DRM_LOCK_HELD|context,context,__ret); \
if (__ret) drmUnlock(fd,context); \
} while(0)
/* Simple spin locks */
#define DRM_SPINLOCK(spin,val) \
do { \
DRM_CAS_RESULT(__ret); \
do { \
DRM_CAS(spin,0,val,__ret); \
if (__ret) while ((spin)->lock); \
} while (__ret); \
} while(0)
#define DRM_SPINLOCK_TAKE(spin,val) \
do { \
DRM_CAS_RESULT(__ret); \
int cur; \
do { \
cur = (*spin).lock; \
DRM_CAS(spin,cur,val,__ret); \
} while (__ret); \
} while(0)
#define DRM_SPINLOCK_COUNT(spin,val,count,__ret) \
do { \
int __i; \
__ret = 1; \
for (__i = 0; __ret && __i < count; __i++) { \
DRM_CAS(spin,0,val,__ret); \
if (__ret) for (;__i < count && (spin)->lock; __i++); \
} \
} while(0)
#define DRM_SPINUNLOCK(spin,val) \
do { \
DRM_CAS_RESULT(__ret); \
if ((*spin).lock == val) { /* else server stole lock */ \
do { \
DRM_CAS(spin,val,0,__ret); \
} while (__ret); \
} \
} while(0)
/* General user-level programmer's API: unprivileged */
extern int drmAvailable(void);
extern int drmOpen(const char *name, const char *busid);
extern int drmClose(int fd);
extern drmVersionPtr drmGetVersion(int fd);
extern drmVersionPtr drmGetLibVersion(int fd);
extern void drmFreeVersion(drmVersionPtr);
extern int drmGetMagic(int fd, drmMagicPtr magic);
extern char *drmGetBusid(int fd);
extern int drmGetInterruptFromBusID(int fd, int busnum, int devnum,
int funcnum);
extern int drmGetMap(int fd, int idx, drmHandle *offset,
drmSize *size, drmMapType *type,
drmMapFlags *flags, drmHandle *handle,
int *mtrr);
extern int drmGetClient(int fd, int idx, int *auth, int *pid,
int *uid, unsigned long *magic,
unsigned long *iocs);
extern int drmGetStats(int fd, drmStatsT *stats);
extern int drmCommandNone(int fd, unsigned long drmCommandIndex);
extern int drmCommandRead(int fd, unsigned long drmCommandIndex,
void *data, unsigned long size);
extern int drmCommandWrite(int fd, unsigned long drmCommandIndex,
void *data, unsigned long size);
extern int drmCommandWriteRead(int fd, unsigned long drmCommandIndex,
void *data, unsigned long size);
/* General user-level programmer's API: X server (root) only */
extern void drmFreeBusid(const char *busid);
extern int drmSetBusid(int fd, const char *busid);
extern int drmAuthMagic(int fd, drmMagic magic);
extern int drmAddMap(int fd,
drmHandle offset,
drmSize size,
drmMapType type,
drmMapFlags flags,
drmHandlePtr handle);
extern int drmRmMap(int fd, drmHandle handle);
extern int drmAddContextPrivateMapping(int fd, drmContext ctx_id,
drmHandle handle);
extern int drmAddBufs(int fd, int count, int size,
drmBufDescFlags flags,
int agp_offset);
extern int drmMarkBufs(int fd, double low, double high);
extern int drmCreateContext(int fd, drmContextPtr handle);
extern int drmSetContextFlags(int fd, drmContext context,
drmContextFlags flags);
extern int drmGetContextFlags(int fd, drmContext context,
drmContextFlagsPtr flags);
extern int drmAddContextTag(int fd, drmContext context, void *tag);
extern int drmDelContextTag(int fd, drmContext context);
extern void *drmGetContextTag(int fd, drmContext context);
extern drmContextPtr drmGetReservedContextList(int fd, int *count);
extern void drmFreeReservedContextList(drmContextPtr);
extern int drmSwitchToContext(int fd, drmContext context);
extern int drmDestroyContext(int fd, drmContext handle);
extern int drmCreateDrawable(int fd, drmDrawablePtr handle);
extern int drmDestroyDrawable(int fd, drmDrawable handle);
extern int drmCtlInstHandler(int fd, int irq);
extern int drmCtlUninstHandler(int fd);
extern int drmInstallSIGIOHandler(int fd,
void (*f)(int fd,
void *oldctx,
void *newctx));
extern int drmRemoveSIGIOHandler(int fd);
/* General user-level programmer's API: authenticated client and/or X */
extern int drmMap(int fd,
drmHandle handle,
drmSize size,
drmAddressPtr address);
extern int drmUnmap(drmAddress address, drmSize size);
extern drmBufInfoPtr drmGetBufInfo(int fd);
extern drmBufMapPtr drmMapBufs(int fd);
extern int drmUnmapBufs(drmBufMapPtr bufs);
extern int drmDMA(int fd, drmDMAReqPtr request);
extern int drmFreeBufs(int fd, int count, int *list);
extern int drmGetLock(int fd,
drmContext context,
drmLockFlags flags);
extern int drmUnlock(int fd, drmContext context);
extern int drmFinish(int fd, int context, drmLockFlags flags);
extern int drmGetContextPrivateMapping(int fd, drmContext ctx_id,
drmHandlePtr handle);
/* AGP/GART support: X server (root) only */
extern int drmAgpAcquire(int fd);
extern int drmAgpRelease(int fd);
extern int drmAgpEnable(int fd, unsigned long mode);
extern int drmAgpAlloc(int fd, unsigned long size,
unsigned long type, unsigned long *address,
unsigned long *handle);
extern int drmAgpFree(int fd, unsigned long handle);
extern int drmAgpBind(int fd, unsigned long handle,
unsigned long offset);
extern int drmAgpUnbind(int fd, unsigned long handle);
/* AGP/GART info: authenticated client and/or X */
extern int drmAgpVersionMajor(int fd);
extern int drmAgpVersionMinor(int fd);
extern unsigned long drmAgpGetMode(int fd);
extern unsigned long drmAgpBase(int fd); /* Physical location */
extern unsigned long drmAgpSize(int fd); /* Bytes */
extern unsigned long drmAgpMemoryUsed(int fd);
extern unsigned long drmAgpMemoryAvail(int fd);
extern unsigned int drmAgpVendorId(int fd);
extern unsigned int drmAgpDeviceId(int fd);
/* PCI scatter/gather support: X server (root) only */
extern int drmScatterGatherAlloc(int fd, unsigned long size,
unsigned long *handle);
extern int drmScatterGatherFree(int fd, unsigned long handle);
extern int drmWaitVBlank(int fd, drmVBlankPtr vbl);
/* Support routines */
extern int drmError(int err, const char *label);
extern void *drmMalloc(int size);
extern void drmFree(void *pt);
/* Hash table routines */
extern void *drmHashCreate(void);
extern int drmHashDestroy(void *t);
extern int drmHashLookup(void *t, unsigned long key, void **value);
extern int drmHashInsert(void *t, unsigned long key, void *value);
extern int drmHashDelete(void *t, unsigned long key);
extern int drmHashFirst(void *t, unsigned long *key, void **value);
extern int drmHashNext(void *t, unsigned long *key, void **value);
/* PRNG routines */
extern void *drmRandomCreate(unsigned long seed);
extern int drmRandomDestroy(void *state);
extern unsigned long drmRandom(void *state);
extern double drmRandomDouble(void *state);
/* Skip list routines */
extern void *drmSLCreate(void);
extern int drmSLDestroy(void *l);
extern int drmSLLookup(void *l, unsigned long key, void **value);
extern int drmSLInsert(void *l, unsigned long key, void *value);
extern int drmSLDelete(void *l, unsigned long key);
extern int drmSLNext(void *l, unsigned long *key, void **value);
extern int drmSLFirst(void *l, unsigned long *key, void **value);
extern void drmSLDump(void *l);
extern int drmSLLookupNeighbors(void *l, unsigned long key,
unsigned long *prev_key, void **prev_value,
unsigned long *next_key, void **next_value);
#endif

View File

@ -296,7 +296,7 @@ default:
@echo "Specify a target configuration"
targets: $(LIBDIR)/$(GL_LIB) $(LIBDIR)/$(OSMESA_LIB)
targets: $(LIBDIR)/$(GL_LIB) $(LIBDIR)/$(OSMESA_LIB) $(LIBMESA)
# Make the GL library
@ -321,7 +321,9 @@ libmesa: $(LIBDIR)/$(MESA_LIB)
$(LIBDIR)/$(MESA_LIB): $(CORE_OBJECTS)
mesa.a: $(CORE_OBJECTS)
rm -f $@ && ar rcv $@ $(CORE_OBJECTS) && ranlib $@
# Run 'make -f Makefile.X11 dep' to update the dependencies if you change
# what's included by any source file.
dep: $(CORE_SOURCES) $(DRIVER_SOURCES) $(OSMESA_DRIVER_SOURCES) $(ASM_SOURCES)
@ -336,9 +338,9 @@ tags:
# Remove .o and backup files
clean:
-rm *.a
-rm -f */*.o */*~ */*.o */*~
-rm -f drivers/*/*.o
-rm -f drivers/dri/*/*.o
include $(TOP)/Make-config

View File

@ -0,0 +1,234 @@
# Doxyfile 1.3.3-Gideon
#---------------------------------------------------------------------------
# General configuration options
#---------------------------------------------------------------------------
PROJECT_NAME = mga
PROJECT_NUMBER = $VERSION$
OUTPUT_DIRECTORY =
OUTPUT_LANGUAGE = English
USE_WINDOWS_ENCODING = NO
EXTRACT_ALL = NO
EXTRACT_PRIVATE = NO
EXTRACT_STATIC = NO
EXTRACT_LOCAL_CLASSES = YES
HIDE_UNDOC_MEMBERS = NO
HIDE_UNDOC_CLASSES = NO
HIDE_FRIEND_COMPOUNDS = NO
HIDE_IN_BODY_DOCS = NO
BRIEF_MEMBER_DESC = YES
REPEAT_BRIEF = YES
ALWAYS_DETAILED_SEC = NO
INLINE_INHERITED_MEMB = NO
FULL_PATH_NAMES = NO
STRIP_FROM_PATH =
INTERNAL_DOCS = NO
CASE_SENSE_NAMES = YES
SHORT_NAMES = NO
HIDE_SCOPE_NAMES = NO
SHOW_INCLUDE_FILES = YES
JAVADOC_AUTOBRIEF = NO
MULTILINE_CPP_IS_BRIEF = NO
DETAILS_AT_TOP = NO
INHERIT_DOCS = YES
INLINE_INFO = YES
SORT_MEMBER_DOCS = YES
DISTRIBUTE_GROUP_DOC = NO
TAB_SIZE = 8
GENERATE_TODOLIST = YES
GENERATE_TESTLIST = YES
GENERATE_BUGLIST = YES
GENERATE_DEPRECATEDLIST= YES
ALIASES =
ENABLED_SECTIONS =
MAX_INITIALIZER_LINES = 30
OPTIMIZE_OUTPUT_FOR_C = NO
OPTIMIZE_OUTPUT_JAVA = NO
SHOW_USED_FILES = YES
SUBGROUPING = YES
#---------------------------------------------------------------------------
# configuration options related to warning and progress messages
#---------------------------------------------------------------------------
QUIET = NO
WARNINGS = YES
WARN_IF_UNDOCUMENTED = YES
WARN_IF_DOC_ERROR = YES
WARN_FORMAT = "$file:$line: $text"
WARN_LOGFILE =
#---------------------------------------------------------------------------
# configuration options related to the input files
#---------------------------------------------------------------------------
INPUT = /home/newtree/temp/src/mesa/drivers/dri/mga
FILE_PATTERNS = *.c \
*.cc \
*.cxx \
*.cpp \
*.c++ \
*.java \
*.ii \
*.ixx \
*.ipp \
*.i++ \
*.inl \
*.h \
*.hh \
*.hxx \
*.hpp \
*.h++ \
*.idl \
*.odl \
*.cs \
*.C \
*.H \
*.tlh \
*.diff \
*.patch \
*.moc \
*.xpm \
*.dox
RECURSIVE = yes
EXCLUDE =
EXCLUDE_SYMLINKS = NO
EXCLUDE_PATTERNS =
EXAMPLE_PATH =
EXAMPLE_PATTERNS = *
EXAMPLE_RECURSIVE = NO
IMAGE_PATH =
INPUT_FILTER =
FILTER_SOURCE_FILES = NO
#---------------------------------------------------------------------------
# configuration options related to source browsing
#---------------------------------------------------------------------------
SOURCE_BROWSER = NO
INLINE_SOURCES = NO
STRIP_CODE_COMMENTS = YES
REFERENCED_BY_RELATION = YES
REFERENCES_RELATION = YES
VERBATIM_HEADERS = YES
#---------------------------------------------------------------------------
# configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
ALPHABETICAL_INDEX = NO
COLS_IN_ALPHA_INDEX = 5
IGNORE_PREFIX =
#---------------------------------------------------------------------------
# configuration options related to the HTML output
#---------------------------------------------------------------------------
GENERATE_HTML = YES
HTML_OUTPUT = html
HTML_FILE_EXTENSION = .html
HTML_HEADER =
HTML_FOOTER =
HTML_STYLESHEET =
HTML_ALIGN_MEMBERS = YES
GENERATE_HTMLHELP = NO
CHM_FILE =
HHC_LOCATION =
GENERATE_CHI = NO
BINARY_TOC = NO
TOC_EXPAND = NO
DISABLE_INDEX = NO
ENUM_VALUES_PER_LINE = 4
GENERATE_TREEVIEW = NO
TREEVIEW_WIDTH = 250
#---------------------------------------------------------------------------
# configuration options related to the LaTeX output
#---------------------------------------------------------------------------
GENERATE_LATEX = YES
LATEX_OUTPUT = latex
LATEX_CMD_NAME = latex
MAKEINDEX_CMD_NAME = makeindex
COMPACT_LATEX = NO
PAPER_TYPE = a4wide
EXTRA_PACKAGES =
LATEX_HEADER =
PDF_HYPERLINKS = NO
USE_PDFLATEX = NO
LATEX_BATCHMODE = NO
LATEX_HIDE_INDICES = NO
#---------------------------------------------------------------------------
# configuration options related to the RTF output
#---------------------------------------------------------------------------
GENERATE_RTF = NO
RTF_OUTPUT = rtf
COMPACT_RTF = NO
RTF_HYPERLINKS = NO
RTF_STYLESHEET_FILE =
RTF_EXTENSIONS_FILE =
#---------------------------------------------------------------------------
# configuration options related to the man page output
#---------------------------------------------------------------------------
GENERATE_MAN = NO
MAN_OUTPUT = man
MAN_EXTENSION = .3
MAN_LINKS = NO
#---------------------------------------------------------------------------
# configuration options related to the XML output
#---------------------------------------------------------------------------
GENERATE_XML = yes
XML_OUTPUT = xml
XML_SCHEMA =
XML_DTD =
#---------------------------------------------------------------------------
# configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
# configuration options related to the Perl module output
#---------------------------------------------------------------------------
GENERATE_PERLMOD = NO
PERLMOD_LATEX = NO
PERLMOD_PRETTY = YES
PERLMOD_MAKEVAR_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
ENABLE_PREPROCESSING = YES
MACRO_EXPANSION = NO
EXPAND_ONLY_PREDEF = NO
SEARCH_INCLUDES = YES
INCLUDE_PATH =
INCLUDE_FILE_PATTERNS =
PREDEFINED =
EXPAND_AS_DEFINED =
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration::addtions related to external references
#---------------------------------------------------------------------------
TAGFILES =
GENERATE_TAGFILE =
ALLEXTERNALS = NO
EXTERNAL_GROUPS = YES
PERL_PATH = /usr/bin/perl
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
CLASS_DIAGRAMS = YES
HIDE_UNDOC_RELATIONS = YES
HAVE_DOT = NO
CLASS_GRAPH = YES
COLLABORATION_GRAPH = YES
UML_LOOK = NO
TEMPLATE_RELATIONS = NO
INCLUDE_GRAPH = YES
INCLUDED_BY_GRAPH = YES
CALL_GRAPH = NO
GRAPHICAL_HIERARCHY = YES
DOT_IMAGE_FORMAT = png
DOT_PATH =
DOTFILE_DIRS =
MAX_DOT_GRAPH_WIDTH = 1024
MAX_DOT_GRAPH_HEIGHT = 1024
MAX_DOT_GRAPH_DEPTH = 1000
GENERATE_LEGEND = YES
DOT_CLEANUP = YES
#---------------------------------------------------------------------------
# Configuration::addtions related to the search engine
#---------------------------------------------------------------------------
SEARCHENGINE = NO
CGI_NAME = search.cgi
CGI_URL =
DOC_URL =
DOC_ABSPATH =
BIN_ABSPATH = /usr/local/bin/
EXT_DOC_PATHS =

View File

@ -1,4 +1,4 @@
# $Id: Makefile.X11,v 1.1 2003/08/06 18:01:13 keithw Exp $
# $Id: Makefile.X11,v 1.2 2003/08/22 20:11:44 brianp Exp $
# Mesa 3-D graphics library
# Version: 5.0
@ -6,8 +6,10 @@
TOP = ../../../../..
default: linux-solo
SHARED_INCLUDES = $(INCLUDE_DIRS) -I. -I../common -Iserver
MINIGLX_INCLUDES = -I$(TOP)/src/miniglx
MINIGLX_INCLUDES = -I$(TOP)/src/glx/mini
DEFINES += \
-D_HAVE_SWRAST=1 \
@ -16,24 +18,27 @@ DEFINES += \
-D_HAVE_CODEGEN=1 \
-D_HAVE_LIGHTING=1 \
-D_HAVE_TEXGEN=1 \
-D_HAVE_USERCLIP=1
-D_HAVE_USERCLIP=1 \
-DGLX_DIRECT_RENDERING
MINIGLX_SOURCES = server/mga_dri.c
DRIVER_SOURCES = mgabuffers.c \
mgadd.c \
DRIVER_SOURCES = mgadd.c \
mgaioctl.c \
mgarender.c \
mgastate.c \
mgatris.c \
../common/mm.c
../common/mm.c \
../common/utils.c \
../common/texmem.c \
../common/vblank.c
FULL_DRIVER_SOURCES = \
mgapixel.c \
mgaspan.c \
mgatex.c \
mgatexcnv.c \
mgatexmem.c \
mga_texstate.c \
mgavb.c \
mga_xmesa.c
@ -54,7 +59,7 @@ WINOBJ=$(MESABUILDDIR)/dri/dri.a
WINLIB=
else
WINOBJ=
WINLIB=-L$(MESA)/src/miniglx
WINLIB=-L$(MESA)/src/glx/mini
endif
ASM_SOURCES =
@ -87,7 +92,7 @@ INCLUDE_DIRS = \
##### TARGETS #####
targets: mga_dri.so
targets: depend mga_dri.so
mga_dri.so: $(OBJECTS) $(MESA_MODULES) $(WINOBJ) Makefile.X11
rm -f $@ && gcc -o $@ -shared $(OBJECTS) $(MESA_MODULES) $(WINOBJ) $(WINLIB) -lc -lm
@ -96,7 +101,7 @@ mga_dri.so: $(OBJECTS) $(MESA_MODULES) $(WINOBJ) Makefile.X11
# Run 'make -f Makefile.X11 dep' to update the dependencies if you change
# what's included by any source file.
dep: $(C_SOURCES) $(ASM_SOURCES)
depend: $(C_SOURCES) $(ASM_SOURCES)
makedepend -fdepend -Y $(SHARED_INCLUDES) \
$(C_SOURCES) $(ASM_SOURCES)
@ -108,7 +113,7 @@ tags:
# Remove .o and backup files
clean:
-rm -f *.o *~ *.o *~ *.so
-rm -f *.o *~ *.o *~ *.so server/*.o
include $(TOP)/Make-config

View File

@ -0,0 +1,747 @@
/*
* Copyright 2000-2001 VA Linux Systems, Inc.
* (c) Copyright IBM Corporation 2002
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* on the rights to use, copy, modify, merge, publish, distribute, sub
* license, and/or sell copies of the Software, and to permit persons to whom
* the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
* VA LINUX SYSTEMS, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
* USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Ian Romanick <idr@us.ibm.com>
* Keith Whitwell <keithw@tungstengraphics.com>
*/
/* $XFree86:$ */
#include "mm.h"
#include "mgacontext.h"
#include "mgatex.h"
#include "mgaregs.h"
#include "mgatris.h"
#include "mgaioctl.h"
#include "context.h"
#include "enums.h"
#include "macros.h"
#include "imports.h"
#include "simple_list.h"
#include "texformat.h"
#define MGA_USE_TABLE_FOR_FORMAT
#ifdef MGA_USE_TABLE_FOR_FORMAT
#define TMC_nr_tformat (MESA_FORMAT_YCBCR_REV + 1)
static const unsigned TMC_tformat[ TMC_nr_tformat ] =
{
[MESA_FORMAT_ARGB8888] = TMC_tformat_tw32 | TMC_takey_1 | TMC_tamask_0,
[MESA_FORMAT_RGB565] = TMC_tformat_tw16 | TMC_takey_1 | TMC_tamask_0,
[MESA_FORMAT_ARGB4444] = TMC_tformat_tw12 | TMC_takey_1 | TMC_tamask_0,
[MESA_FORMAT_ARGB1555] = TMC_tformat_tw15 | TMC_takey_1 | TMC_tamask_0,
[MESA_FORMAT_CI8] = TMC_tformat_tw8 | TMC_takey_1 | TMC_tamask_0,
[MESA_FORMAT_YCBCR] = TMC_tformat_tw422uyvy | TMC_takey_1 | TMC_tamask_0,
[MESA_FORMAT_YCBCR_REV] = TMC_tformat_tw422 | TMC_takey_1 | TMC_tamask_0,
};
#endif
static void
mgaSetTexImages( mgaContextPtr mmesa,
const struct gl_texture_object * tObj )
{
mgaTextureObjectPtr t = (mgaTextureObjectPtr) tObj->DriverData;
struct gl_texture_image *baseImage = tObj->Image[ tObj->BaseLevel ];
GLint totalSize;
GLint width, height;
GLint i;
GLint firstLevel, lastLevel, numLevels;
GLint log2Width, log2Height;
GLuint txformat = 0;
GLint ofs;
/* Set the hardware texture format
*/
#ifndef MGA_USE_TABLE_FOR_FORMAT
switch (baseImage->TexFormat->MesaFormat) {
case MESA_FORMAT_ARGB8888: txformat = TMC_tformat_tw32; break;
case MESA_FORMAT_RGB565: txformat = TMC_tformat_tw16; break;
case MESA_FORMAT_ARGB4444: txformat = TMC_tformat_tw12; break;
case MESA_FORMAT_ARGB1555: txformat = TMC_tformat_tw15; break;
case MESA_FORMAT_CI8: txformat = TMC_tformat_tw8; break;
case MESA_FORMAT_YCBCR: txformat = TMC_tformat_tw422uyvy; break;
case MESA_FORMAT_YCBCR_REV: txformat = TMC_tformat_tw422; break;
default:
_mesa_problem(NULL, "unexpected texture format in %s", __FUNCTION__);
return;
}
#else
if ( (baseImage->TexFormat->MesaFormat >= TMC_nr_tformat)
|| (TMC_tformat[ baseImage->TexFormat->MesaFormat ] == 0) )
{
_mesa_problem(NULL, "unexpected texture format in %s", __FUNCTION__);
return;
}
txformat = TMC_tformat[ baseImage->TexFormat->MesaFormat ];
#endif /* MGA_USE_TABLE_FOR_FORMAT */
if (tObj->MinFilter == GL_NEAREST || tObj->MinFilter == GL_LINEAR) {
/* GL_NEAREST and GL_LINEAR only care about GL_TEXTURE_BASE_LEVEL.
*/
firstLevel = lastLevel = tObj->BaseLevel;
} else {
/* Compute which mipmap levels we really want to send to the hardware.
* This depends on the base image size, GL_TEXTURE_MIN_LOD,
* GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL.
* Yes, this looks overly complicated, but it's all needed.
*/
firstLevel = tObj->BaseLevel + (GLint)(tObj->MinLod + 0.5);
firstLevel = MAX2(firstLevel, tObj->BaseLevel);
lastLevel = tObj->BaseLevel + (GLint)(tObj->MaxLod + 0.5);
lastLevel = MAX2(lastLevel, tObj->BaseLevel);
lastLevel = MIN2(lastLevel, tObj->BaseLevel + baseImage->MaxLog2);
lastLevel = MIN2(lastLevel, tObj->MaxLevel);
lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */
}
log2Width = tObj->Image[firstLevel]->WidthLog2;
log2Height = tObj->Image[firstLevel]->HeightLog2;
width = tObj->Image[firstLevel]->Width;
height = tObj->Image[firstLevel]->Height;
numLevels = MIN2( lastLevel - firstLevel + 1,
MGA_IS_G200(mmesa) ? G200_TEX_MAXLEVELS : G400_TEX_MAXLEVELS);
totalSize = 0;
for ( i = 0 ; i < numLevels ; i++ ) {
const struct gl_texture_image * const texImage = tObj->Image[i+firstLevel];
if ( (texImage == NULL)
|| ((i != 0)
&& ((texImage->Width < 8) || (texImage->Height < 8))) ) {
break;
}
t->offsets[i] = totalSize;
t->base.dirty_images[0] |= (1<<i);
totalSize += ((MAX2( texImage->Width, 8 ) *
MAX2( texImage->Height, 8 ) *
baseImage->TexFormat->TexelBytes) + 31) & ~31;
}
numLevels = i;
lastLevel = firstLevel + numLevels - 1;
/* save these values */
t->base.firstLevel = firstLevel;
t->base.lastLevel = lastLevel;
t->base.totalSize = totalSize;
/* setup hardware register values */
t->setup.texctl &= (TMC_tformat_MASK & TMC_tpitch_MASK
& TMC_tpitchext_MASK);
t->setup.texctl |= txformat;
/* Set the texture width. In order to support non-power of 2 textures and
* textures larger than 1024 texels wide, "linear" pitch must be used. For
* the linear pitch, if the width is 2048, a value of zero is used.
*/
t->setup.texctl |= TMC_tpitchlin_enable;
t->setup.texctl |= (width & (2048 - 1)) << TMC_tpitchext_SHIFT;
/* G400 specifies the number of mip levels in a strange way. Since there
* are up to 12 levels, it requires 4 bits. Three of the bits are at the
* high end of TEXFILTER. The other bit is in the middle. Weird.
*/
t->setup.texfilter &= TF_mapnb_MASK & TF_mapnbhigh_MASK & TF_reserved_MASK;
t->setup.texfilter |= (((numLevels-1) & 0x07) << (TF_mapnb_SHIFT));
t->setup.texfilter |= (((numLevels-1) & 0x08) << (TF_mapnbhigh_SHIFT - 3));
/* warp texture registers */
ofs = MGA_IS_G200(mmesa) ? 28 : 11;
t->setup.texwidth = (MGA_FIELD(TW_twmask, width - 1) |
MGA_FIELD(TW_rfw, (10 - log2Width - 8) & 63 ) |
MGA_FIELD(TW_tw, (log2Width + ofs ) | 0x40 ));
t->setup.texheight = (MGA_FIELD(TH_thmask, height - 1) |
MGA_FIELD(TH_rfh, (10 - log2Height - 8) & 63 ) |
MGA_FIELD(TH_th, (log2Height + ofs ) | 0x40 ));
mgaUploadTexImages( mmesa, t );
}
/* ================================================================
* Texture unit state management
*/
static void mgaUpdateTextureEnvG200( GLcontext *ctx, GLuint unit )
{
struct gl_texture_object *tObj = ctx->Texture.Unit[0]._Current;
mgaTextureObjectPtr t;
if (!tObj || !tObj->DriverData)
return;
t = (mgaTextureObjectPtr)tObj->DriverData;
t->setup.texctl2 &= ~TMC_decalblend_enable;
switch (ctx->Texture.Unit[0].EnvMode) {
case GL_REPLACE:
t->setup.texctl &= ~TMC_tmodulate_enable;
break;
case GL_MODULATE:
t->setup.texctl |= TMC_tmodulate_enable;
break;
case GL_DECAL:
t->setup.texctl &= ~TMC_tmodulate_enable;
t->setup.texctl2 |= TMC_decalblend_enable;
break;
case GL_BLEND:
FALLBACK( ctx, MGA_FALLBACK_TEXTURE, GL_TRUE );
break;
default:
break;
}
}
#define MGA_DISABLE 0
#define MGA_REPLACE 1
#define MGA_MODULATE 2
#define MGA_DECAL 3
#define MGA_BLEND 4
#define MGA_ADD 5
#define MGA_MAX_COMBFUNC 6
static const GLuint g400_color_combine[][MGA_MAX_COMBFUNC] =
{
/* Unit 0:
*/
{
/* Disable combiner stage
*/
(0),
/* GL_REPLACE
*/
(TD0_color_sel_arg1 |
TD0_alpha_arg2_diffuse |
TD0_alpha_sel_arg2 ),
/* GL_MODULATE
*/
(TD0_color_arg2_diffuse |
TD0_color_sel_mul |
TD0_alpha_arg2_diffuse |
TD0_alpha_sel_mul),
/* GL_DECAL
*/
(TD0_color_sel_arg1 |
TD0_alpha_arg2_diffuse |
TD0_alpha_sel_arg2),
/* GL_BLEND
*/
(0),
/* GL_ADD
*/
(TD0_color_arg2_diffuse |
TD0_color_add_add |
TD0_color_sel_add |
TD0_alpha_arg2_diffuse |
TD0_alpha_sel_mul),
},
/* Unit 1:
*/
{
/* Disable combiner stage
*/
(0),
/* GL_REPLACE
*/
(TD0_color_sel_arg1 |
TD0_alpha_arg2_diffuse |
TD0_alpha_sel_arg2 ),
/* GL_MODULATE
*/
(TD0_color_arg2_prevstage |
TD0_color_alpha_prevstage |
TD0_color_sel_mul |
TD0_alpha_arg2_prevstage |
TD0_alpha_sel_mul),
/* GL_DECAL
*/
(TD0_color_sel_arg1 |
TD0_alpha_arg2_prevstage |
TD0_alpha_sel_arg2 ),
/* GL_BLEND
*/
(0),
/* GL_ADD
*/
(TD0_color_arg2_prevstage |
TD0_color_alpha_prevstage |
TD0_color_add_add |
TD0_color_sel_add |
TD0_alpha_arg2_prevstage |
TD0_alpha_sel_mul),
},
};
static const GLuint g400_alpha_combine[][MGA_MAX_COMBFUNC] =
{
/* Unit 0:
*/
{
/* Disable combiner stage
*/
(0),
/* GL_REPLACE
*/
(TD0_color_sel_arg2 |
TD0_color_arg2_diffuse |
TD0_alpha_sel_arg1 ),
/* GL_MODULATE
* FIXME: Is this correct?
*/
(TD0_color_arg2_diffuse |
TD0_color_sel_mul |
TD0_alpha_arg2_diffuse |
TD0_alpha_sel_mul),
/* GL_DECAL
*/
(TD0_color_arg2_diffuse |
TD0_color_sel_arg2 |
TD0_alpha_arg2_diffuse |
TD0_alpha_sel_arg2),
/* GL_BLEND
*/
(TD0_color_arg2_diffuse |
TD0_color_sel_mul |
TD0_alpha_arg2_diffuse |
TD0_alpha_sel_mul),
/* GL_ADD
*/
(TD0_color_arg2_diffuse |
TD0_color_sel_mul |
TD0_alpha_arg2_diffuse |
TD0_alpha_sel_mul),
},
/* Unit 1:
*/
{
/* Disable combiner stage
*/
(0),
/* GL_REPLACE
*/
(TD0_color_sel_arg2 |
TD0_color_arg2_diffuse |
TD0_alpha_sel_arg1 ),
/* GL_MODULATE
* FIXME: Is this correct?
*/
(TD0_color_arg2_prevstage |
TD0_color_alpha_prevstage |
TD0_color_sel_mul |
TD0_alpha_arg2_prevstage |
TD0_alpha_sel_mul),
/* GL_DECAL
*/
(TD0_color_arg2_prevstage |
TD0_color_sel_arg2 |
TD0_alpha_arg2_prevstage |
TD0_alpha_sel_arg2),
/* GL_BLEND
*/
(TD0_color_arg2_diffuse |
TD0_color_sel_mul |
TD0_alpha_arg2_diffuse |
TD0_alpha_sel_mul),
/* GL_ADD
*/
(TD0_color_arg2_prevstage |
TD0_color_sel_mul |
TD0_alpha_arg2_prevstage |
TD0_alpha_sel_mul),
},
};
static void mgaUpdateTextureEnvG400( GLcontext *ctx, GLuint unit )
{
mgaContextPtr mmesa = MGA_CONTEXT( ctx );
const int source = mmesa->tmu_source[unit];
const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
const struct gl_texture_object *tObj = texUnit->_Current;
GLuint *reg = ((GLuint *)&mmesa->setup.tdualstage0 + unit);
GLenum format;
if ( tObj != ctx->Texture.Unit[source].Current2D || !tObj )
return;
format = tObj->Image[tObj->BaseLevel]->Format;
switch (ctx->Texture.Unit[source].EnvMode) {
case GL_REPLACE:
if (format == GL_RGB || format == GL_LUMINANCE) {
*reg = g400_color_combine[unit][MGA_REPLACE];
}
else if (format == GL_ALPHA) {
*reg = g400_alpha_combine[unit][MGA_REPLACE];
}
else {
*reg = (TD0_color_sel_arg1 |
TD0_alpha_sel_arg1 );
}
break;
case GL_MODULATE:
*reg = g400_color_combine[unit][MGA_MODULATE];
break;
case GL_DECAL:
if (format == GL_RGB) {
*reg = g400_color_combine[unit][MGA_DECAL];
}
else if ( format == GL_RGBA ) {
#if 0
if (unit == 0) {
/* this doesn't work */
*reg = (TD0_color_arg2_diffuse |
TD0_color_alpha_currtex |
TD0_color_alpha2inv_enable |
TD0_color_arg2mul_alpha2 |
TD0_color_arg1mul_alpha1 |
TD0_color_blend_enable |
TD0_color_arg1add_mulout |
TD0_color_arg2add_mulout |
TD0_color_add_add |
TD0_color_sel_mul |
TD0_alpha_arg2_diffuse |
TD0_alpha_sel_arg2 );
}
else {
*reg = (TD0_color_arg2_prevstage |
TD0_color_alpha_currtex |
TD0_color_alpha2inv_enable |
TD0_color_arg2mul_alpha2 |
TD0_color_arg1mul_alpha1 |
TD0_color_add_add |
TD0_color_sel_add |
TD0_alpha_arg2_prevstage |
TD0_alpha_sel_arg2 );
}
#else
/* s/w fallback, pretty sure we can't do in h/w */
FALLBACK( ctx, MGA_FALLBACK_TEXTURE, GL_TRUE );
if ( MGA_DEBUG & DEBUG_VERBOSE_FALLBACK )
fprintf( stderr, "FALLBACK: GL_DECAL RGBA texture, unit=%d\n",
unit );
#endif
}
else {
*reg = g400_alpha_combine[unit][MGA_DECAL];
}
break;
case GL_ADD:
if (format == GL_INTENSITY) {
if (unit == 0) {
*reg = ( TD0_color_arg2_diffuse |
TD0_color_add_add |
TD0_color_sel_add |
TD0_alpha_arg2_diffuse |
TD0_alpha_add_enable |
TD0_alpha_sel_add);
}
else {
*reg = ( TD0_color_arg2_prevstage |
TD0_color_add_add |
TD0_color_sel_add |
TD0_alpha_arg2_prevstage |
TD0_alpha_add_enable |
TD0_alpha_sel_add);
}
}
else if (format == GL_ALPHA) {
*reg = g400_alpha_combine[unit][MGA_ADD];
}
else {
*reg = g400_color_combine[unit][MGA_ADD];
}
break;
case GL_BLEND:
if (format == GL_ALPHA) {
*reg = g400_alpha_combine[unit][MGA_BLEND];
}
else {
FALLBACK( ctx, MGA_FALLBACK_TEXTURE, GL_TRUE );
if ( MGA_DEBUG & DEBUG_VERBOSE_FALLBACK )
fprintf( stderr, "FALLBACK: GL_BLEND envcolor=0x%08x\n",
mmesa->envcolor );
/* Do singletexture GL_BLEND with 'all ones' env-color
* by using both texture units. Multitexture gl_blend
* is a fallback.
*/
if (unit == 0) {
/* Part 1: R1 = Rf ( 1 - Rt )
* A1 = Af At
*/
*reg = ( TD0_color_arg2_diffuse |
TD0_color_arg1_inv_enable |
TD0_color_sel_mul |
TD0_alpha_arg2_diffuse |
TD0_alpha_sel_arg1);
} else {
/* Part 2: R2 = R1 + Rt
* A2 = A1
*/
*reg = ( TD0_color_arg2_prevstage |
TD0_color_add_add |
TD0_color_sel_add |
TD0_alpha_arg2_prevstage |
TD0_alpha_sel_arg2);
}
}
break;
default:
break;
}
}
static void disable_tex( GLcontext *ctx, int unit )
{
mgaContextPtr mmesa = MGA_CONTEXT( ctx );
/* Texture unit disabled */
if ( mmesa->CurrentTexObj[unit] != NULL ) {
/* The old texture is no longer bound to this texture unit.
* Mark it as such.
*/
mmesa->CurrentTexObj[unit]->base.bound &= ~(1UL << unit);
mmesa->CurrentTexObj[unit] = NULL;
}
if ( unit != 0 ) {
mmesa->setup.tdualstage1 = mmesa->setup.tdualstage0;
}
if ( ctx->Texture._EnabledUnits == 0 ) {
mmesa->setup.dwgctl &= DC_opcod_MASK;
mmesa->setup.dwgctl |= DC_opcod_trap;
mmesa->hw.alpha_sel = AC_alphasel_diffused;
}
mmesa->dirty |= MGA_UPLOAD_CONTEXT | (MGA_UPLOAD_TEX0 << unit);
}
static GLboolean enable_tex_2d( GLcontext *ctx, int unit )
{
mgaContextPtr mmesa = MGA_CONTEXT(ctx);
const int source = mmesa->tmu_source[unit];
const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
const struct gl_texture_object *tObj = texUnit->_Current;
mgaTextureObjectPtr t = (mgaTextureObjectPtr) tObj->DriverData;
/* Upload teximages (not pipelined)
*/
if (t->base.dirty_images[0]) {
FLUSH_BATCH( mmesa );
mgaSetTexImages( mmesa, tObj );
if ( t->base.memBlock == NULL ) {
return GL_FALSE;
}
}
return GL_TRUE;
}
static GLboolean update_tex_common( GLcontext *ctx, int unit )
{
mgaContextPtr mmesa = MGA_CONTEXT(ctx);
const int source = mmesa->tmu_source[unit];
const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
struct gl_texture_object *tObj = texUnit->_Current;
mgaTextureObjectPtr t = (mgaTextureObjectPtr) tObj->DriverData;
/* Fallback if there's a texture border */
if ( tObj->Image[tObj->BaseLevel]->Border > 0 ) {
return GL_FALSE;
}
/* Update state if this is a different texture object to last
* time.
*/
if ( mmesa->CurrentTexObj[unit] != t ) {
if ( mmesa->CurrentTexObj[unit] != NULL ) {
/* The old texture is no longer bound to this texture unit.
* Mark it as such.
*/
mmesa->CurrentTexObj[unit]->base.bound &= ~(1UL << unit);
}
mmesa->CurrentTexObj[unit] = t;
t->base.bound |= (1UL << unit);
driUpdateTextureLRU( (driTextureObject *) t ); /* done too often */
}
/* register setup */
if ( unit == 1 ) {
mmesa->setup.tdualstage1 = mmesa->setup.tdualstage0;
}
t->setup.texctl2 &= TMC_dualtex_MASK;
if (ctx->Texture._EnabledUnits == 0x03) {
t->setup.texctl2 |= TMC_dualtex_enable;
}
/* FIXME: The Radeon has some cached state so that it can avoid calling
* FIXME: UpdateTextureEnv in some cases. Is that possible here?
*/
if (MGA_IS_G400(mmesa)) {
/* G400: Regardless of texture env mode, we use the alpha from the
* texture unit (AC_alphasel_fromtex) since it will have already
* been modulated by the incoming fragment color, if needed.
* We don't want (AC_alphasel_modulate) since that'll effectively
* do the modulation twice.
*/
mmesa->hw.alpha_sel = AC_alphasel_fromtex;
mgaUpdateTextureEnvG400( ctx, unit );
} else {
mmesa->hw.alpha_sel = 0;
switch (ctx->Texture.Unit[0].EnvMode) {
case GL_DECAL:
mmesa->hw.alpha_sel |= AC_alphasel_diffused;
case GL_REPLACE:
mmesa->hw.alpha_sel |= AC_alphasel_fromtex;
break;
case GL_BLEND:
case GL_MODULATE:
mmesa->hw.alpha_sel |= AC_alphasel_modulated;
break;
default:
break;
}
mgaUpdateTextureEnvG200( ctx, unit );
}
mmesa->setup.dwgctl &= DC_opcod_MASK;
mmesa->setup.dwgctl |= DC_opcod_texture_trap;
mmesa->dirty |= MGA_UPLOAD_CONTEXT | (MGA_UPLOAD_TEX0 << unit);
FALLBACK( ctx, MGA_FALLBACK_BORDER_MODE, t->border_fallback );
return !t->border_fallback;
}
static GLboolean updateTextureUnit( GLcontext *ctx, int unit )
{
mgaContextPtr mmesa = MGA_CONTEXT( ctx );
const int source = mmesa->tmu_source[unit];
const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
if ( texUnit->_ReallyEnabled == TEXTURE_2D_BIT) {
return(enable_tex_2d( ctx, unit ) &&
update_tex_common( ctx, unit ));
}
else if ( texUnit->_ReallyEnabled ) {
return GL_FALSE;
}
else {
disable_tex( ctx, unit );
return GL_TRUE;
}
}
/* The G400 is now programmed quite differently wrt texture environment.
*/
void mgaUpdateTextureState( GLcontext *ctx )
{
mgaContextPtr mmesa = MGA_CONTEXT( ctx );
GLboolean ok;
unsigned i;
/* This works around a quirk with the MGA hardware. If only OpenGL
* TEXTURE1 is enabled, then the hardware TEXTURE0 must be used. The
* hardware TEXTURE1 can ONLY be used when hardware TEXTURE0 is also used.
*/
mmesa->tmu_source[0] = 0;
mmesa->tmu_source[1] = 1;
if ((ctx->Texture._EnabledUnits & 0x03) == 0x02) {
/* only texture 1 enabled */
mmesa->tmu_source[0] = 1;
mmesa->tmu_source[1] = 0;
}
for ( i = 0, ok = GL_TRUE
; (i < ctx->Const.MaxTextureUnits) && ok
; i++ ) {
ok = updateTextureUnit( ctx, i );
}
FALLBACK( ctx, MGA_FALLBACK_TEXTURE, !ok );
/* FIXME: I believe that ChooseVertexState should be called here instead of
* FIXME: in mgaDDValidateState.
*/
}

View File

@ -1,4 +1,4 @@
/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mga_xmesa.c,v 1.19 2003/03/26 20:43:49 tsi Exp $ */
/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mga_xmesa.c,v 1.18 2002/12/16 16:18:52 dawes Exp $ */
/*
* Copyright 2000-2001 VA Linux Systems, Inc.
* All Rights Reserved.
@ -26,15 +26,14 @@
* Keith Whitwell <keith@tungstengraphics.com>
*/
#include <stdio.h>
#ifdef GLX_DIRECT_RENDERING
#include "mga_common.h"
#include "mga_xmesa.h"
#include "context.h"
#include "matrix.h"
/*#include "mmath.h"*/
#include "simple_list.h"
/*#include "mem.h"*/
#include "imports.h"
#include "swrast/swrast.h"
#include "swrast_setup/swrast_setup.h"
@ -50,26 +49,23 @@
#include "mgaioctl.h"
#include "mgatris.h"
#include "mgavb.h"
#include "mgabuffers.h"
#include "mgapixel.h"
#include "mga_xmesa.h"
#include "mga_dri.h"
#ifndef MGA_DEBUG
int MGA_DEBUG = (0
/* | DEBUG_ALWAYS_SYNC */
/* | DEBUG_VERBOSE_MSG */
/* | DEBUG_VERBOSE_LRU */
/* | DEBUG_VERBOSE_DRI */
/* | DEBUG_VERBOSE_IOCTL */
/* | DEBUG_VERBOSE_2D */
/* | DEBUG_VERBOSE_FALLBACK */
);
#include "utils.h"
#include "vblank.h"
#include "dri_util.h"
#ifndef _SOLO
#include "glxextensions.h"
#endif
#ifndef MGA_DEBUG
int MGA_DEBUG = 0;
#endif
static int getSwapInfo( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo );
static GLboolean
mgaInitDriver(__DRIscreenPrivate *sPriv)
@ -77,16 +73,8 @@ mgaInitDriver(__DRIscreenPrivate *sPriv)
mgaScreenPrivate *mgaScreen;
MGADRIPtr serverInfo = (MGADRIPtr)sPriv->pDevPriv;
if (MGA_DEBUG&DEBUG_VERBOSE_DRI)
fprintf(stderr, "mgaInitDriver\n");
/* Check that the DRM driver version is compatible */
if (sPriv->drmMajor != 3 ||
sPriv->drmMinor < 0) {
__driUtilMessage("MGA DRI driver expected DRM driver version 3.0.x but got version %d.%d.%d", sPriv->drmMajor, sPriv->drmMinor, sPriv->drmPatch);
if ( ! driCheckDriDdxDrmVersions( sPriv, "MGA", 4, 0, 1, 0, 3, 0 ) )
return GL_FALSE;
}
/* Allocate the private area */
mgaScreen = (mgaScreenPrivate *)MALLOC(sizeof(mgaScreenPrivate));
@ -103,21 +91,37 @@ mgaInitDriver(__DRIscreenPrivate *sPriv)
drmMGAGetParam gp;
gp.param = MGA_PARAM_IRQ_NR;
gp.value = (int *) &mgaScreen->irq;
gp.value = &mgaScreen->irq;
ret = drmCommandWriteRead( sPriv->fd, DRM_MGA_GETPARAM,
&gp, sizeof(gp));
if (ret) {
fprintf(stderr, "drmMgaGetParam (MGA_PARAM_IRQ_NR): %d\n", ret);
FREE(mgaScreen);
free(mgaScreen);
sPriv->private = NULL;
return GL_FALSE;
}
}
mgaScreen->linecomp_sane = (sPriv->ddxMajor > 1) || (sPriv->ddxMinor > 1)
|| ((sPriv->ddxMinor == 1) && (sPriv->ddxPatch > 0));
#ifndef _SOLO
if ( ! mgaScreen->linecomp_sane ) {
PFNGLXDISABLEEXTENSIONPROC glx_disable_extension;
glx_disable_extension = (PFNGLXDISABLEEXTENSIONPROC)
glXGetProcAddress( "__glXDisableExtension" );
if ( glx_disable_extension != NULL ) {
(*glx_disable_extension)( "GLX_SGI_swap_control" );
(*glx_disable_extension)( "GLX_SGI_video_sync" );
(*glx_disable_extension)( "GLX_MESA_swap_control" );
}
}
#endif
if (serverInfo->chipset != MGA_CARD_TYPE_G200 &&
serverInfo->chipset != MGA_CARD_TYPE_G400) {
FREE(mgaScreen);
free(mgaScreen);
sPriv->private = NULL;
__driUtilMessage("Unrecognized chipset");
return GL_FALSE;
@ -164,7 +168,7 @@ mgaInitDriver(__DRIscreenPrivate *sPriv)
mgaScreen->agp.size,
(drmAddress *)&mgaScreen->agp.map) != 0)
{
Xfree(mgaScreen);
free(mgaScreen);
sPriv->private = NULL;
__driUtilMessage("Couldn't map agp region");
return GL_FALSE;
@ -210,7 +214,7 @@ mgaInitDriver(__DRIscreenPrivate *sPriv)
mgaScreen->bufs = drmMapBufs(sPriv->fd);
if (!mgaScreen->bufs) {
/*drmUnmap(mgaScreen->agp_tex.map, mgaScreen->agp_tex.size);*/
FREE(mgaScreen);
free(mgaScreen);
sPriv->private = NULL;
__driUtilMessage("Couldn't map dma buffers");
return GL_FALSE;
@ -254,12 +258,63 @@ static const struct gl_pipeline_stage *mga_pipeline[] = {
};
static const char * const g400_extensions[] =
{
"GL_ARB_multitexture",
"GL_ARB_texture_env_add",
"GL_EXT_texture_env_add",
"GL_EXT_texture_edge_clamp",
"GL_SGIS_texture_edge_clamp",
#if defined (MESA_packed_depth_stencil)
"GL_MESA_packed_depth_stencil",
#endif
NULL
};
static const char * const card_extensions[] =
{
"GL_ARB_multisample",
"GL_ARB_texture_compression",
"GL_EXT_fog_coord",
/* paletted_textures currently doesn't work, but we could fix them later */
#if 0
"GL_EXT_shared_texture_palette",
"GL_EXT_paletted_texture",
#endif
"GL_EXT_secondary_color",
"GL_EXT_stencil_wrap",
"GL_MESA_ycbcr_texture",
"GL_SGIS_generate_mipmap",
"GL_SGIS_texture_lod",
NULL
};
static const struct dri_debug_control debug_control[] =
{
{ "fall", DEBUG_VERBOSE_FALLBACK },
{ "tex", DEBUG_VERBOSE_TEXTURE },
{ "ioctl", DEBUG_VERBOSE_IOCTL },
{ "verb", DEBUG_VERBOSE_MSG },
{ "dri", DEBUG_VERBOSE_DRI },
{ NULL, 0 }
};
static int
get_ust_nop( uint64_t * ust )
{
*ust = 1;
return 0;
}
static GLboolean
mgaCreateContext( const __GLcontextModes *mesaVis,
__DRIcontextPrivate *driContextPriv,
void *sharedContextPrivate )
{
int i;
unsigned maxlevels;
GLcontext *ctx, *shareCtx;
mgaContextPtr mmesa;
__DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
@ -281,7 +336,7 @@ mgaCreateContext( const __GLcontextModes *mesaVis,
shareCtx = ((mgaContextPtr) sharedContextPrivate)->glCtx;
else
shareCtx = NULL;
mmesa->glCtx = _mesa_create_context(mesaVis, shareCtx, mmesa, GL_TRUE);
mmesa->glCtx = _mesa_create_context(mesaVis, shareCtx, (void *) mmesa, GL_TRUE);
if (!mmesa->glCtx) {
FREE(mmesa);
return GL_FALSE;
@ -298,13 +353,20 @@ mgaCreateContext( const __GLcontextModes *mesaVis,
mmesa->sarea = (void *)saPriv;
mmesa->glBuffer = NULL;
make_empty_list(&mmesa->SwappedOut);
(void) memset( mmesa->texture_heaps, 0, sizeof( mmesa->texture_heaps ) );
make_empty_list( & mmesa->swapped );
mmesa->lastTexHeap = mgaScreen->texVirtual[MGA_AGP_HEAP] ? 2 : 1;
for (i = 0 ; i < mmesa->lastTexHeap ; i++) {
mmesa->texHeap[i] = mmInit( 0, mgaScreen->textureSize[i]);
make_empty_list(&mmesa->TexObjList[i]);
mmesa->nr_heaps = mgaScreen->texVirtual[MGA_AGP_HEAP] ? 2 : 1;
for ( i = 0 ; i < mmesa->nr_heaps ; i++ ) {
mmesa->texture_heaps[i] = driCreateTextureHeap( i, mmesa,
mgaScreen->textureSize[i],
6,
MGA_NR_TEX_REGIONS,
mmesa->sarea->texList[i],
& mmesa->sarea->texAge[i],
& mmesa->swapped,
sizeof( mgaTextureObject_t ),
(destroy_texture_object_t *) mgaDestroyTexObj );
}
/* Set the maximum texture size small enough that we can guarentee
@ -312,22 +374,26 @@ mgaCreateContext( const __GLcontextModes *mesaVis,
* on the card at once.
*/
ctx = mmesa->glCtx;
{
int nr = 2;
if ( mgaScreen->chipset == MGA_CARD_TYPE_G200 ) {
ctx->Const.MaxTextureUnits = 1;
maxlevels = G200_TEX_MAXLEVELS;
if (mgaScreen->chipset == MGA_CARD_TYPE_G200)
nr = 1;
if (mgaScreen->textureSize[0] < nr*1024*1024) {
ctx->Const.MaxTextureLevels = 9;
} else if (mgaScreen->textureSize[0] < nr*4*1024*1024) {
ctx->Const.MaxTextureLevels = 10;
} else {
ctx->Const.MaxTextureLevels = 11;
}
ctx->Const.MaxTextureUnits = nr;
}
else {
ctx->Const.MaxTextureUnits = 2;
maxlevels = G400_TEX_MAXLEVELS;
}
driCalculateMaxTextureLevels( mmesa->texture_heaps,
mmesa->nr_heaps,
& ctx->Const,
4,
11, /* max 2D texture size is 1024x1024 */
0, /* 3D textures unsupported. */
0, /* cube textures unsupported. */
0, /* texture rectangles unsupported. */
maxlevels,
GL_FALSE );
ctx->Const.MinLineWidth = 1.0;
ctx->Const.MinLineWidthAA = 1.0;
@ -335,6 +401,7 @@ mgaCreateContext( const __GLcontextModes *mesaVis,
ctx->Const.MaxLineWidthAA = 10.0;
ctx->Const.LineWidthGranularity = 1.0;
mmesa->default32BitTextures = (mesaVis->rgbBits >= 24);
mmesa->hw_stencil = mesaVis->stencilBits && mesaVis->depthBits == 24;
switch (mesaVis->depthBits) {
@ -361,7 +428,6 @@ mgaCreateContext( const __GLcontextModes *mesaVis,
mmesa->haveHwStipple = GL_FALSE;
mmesa->RenderIndex = -1; /* impossible value */
mmesa->new_state = ~0;
mmesa->dirty = ~0;
mmesa->vertex_format = 0;
mmesa->CurrentTexObj[0] = 0;
@ -395,7 +461,11 @@ mgaCreateContext( const __GLcontextModes *mesaVis,
ctx->DriverCtx = (void *) mmesa;
mmesa->glCtx = ctx;
mgaDDExtensionsInit( ctx );
driInitExtensions( ctx, card_extensions, GL_FALSE );
if (MGA_IS_G400(MGA_CONTEXT(ctx))) {
driInitExtensions( ctx, g400_extensions, GL_FALSE );
}
mgaDDInitStateFuncs( ctx );
mgaDDInitTextureFuncs( ctx );
@ -410,6 +480,24 @@ mgaCreateContext( const __GLcontextModes *mesaVis,
driContextPriv->driverPrivate = (void *) mmesa;
#if DO_DEBUG
MGA_DEBUG = driParseDebugString( getenv( "MGA_DEBUG" ),
debug_control );
#endif
mmesa->vblank_flags = ((mmesa->mgaScreen->irq == 0)
|| !mmesa->mgaScreen->linecomp_sane)
? VBLANK_FLAG_NO_IRQ : driGetDefaultVBlankFlags();
#ifndef _SOLO
mmesa->get_ust = (PFNGLXGETUSTPROC) glXGetProcAddress( "__glXGetUST" );
if ( mmesa->get_ust == NULL )
#endif
{
mmesa->get_ust = get_ust_nop;
}
(*mmesa->get_ust)( & mmesa->swap_ust );
return GL_TRUE;
}
@ -419,10 +507,15 @@ mgaDestroyContext(__DRIcontextPrivate *driContextPriv)
mgaContextPtr mmesa = (mgaContextPtr) driContextPriv->driverPrivate;
if (MGA_DEBUG&DEBUG_VERBOSE_DRI)
fprintf(stderr, "mgaDestroyContext\n");
fprintf( stderr, "[%s:%d] mgaDestroyContext start\n",
__FILE__, __LINE__ );
assert(mmesa); /* should never be null */
if (mmesa) {
GLboolean release_texture_heaps;
release_texture_heaps = (mmesa->glCtx->Shared->RefCount == 1);
_swsetup_DestroyContext( mmesa->glCtx );
_tnl_DestroyContext( mmesa->glCtx );
_ac_DestroyContext( mmesa->glCtx );
@ -433,9 +526,27 @@ mgaDestroyContext(__DRIcontextPrivate *driContextPriv)
/* free the Mesa context */
mmesa->glCtx->DriverCtx = NULL;
_mesa_destroy_context(mmesa->glCtx);
/* free the mga context */
if ( release_texture_heaps ) {
/* This share group is about to go away, free our private
* texture object data.
*/
int i;
assert( is_empty_list( & mmesa->swapped ) );
for ( i = 0 ; i < mmesa->nr_heaps ; i++ ) {
driDestroyTextureHeap( mmesa->texture_heaps[ i ] );
mmesa->texture_heaps[ i ] = NULL;
}
}
FREE(mmesa);
}
if (MGA_DEBUG&DEBUG_VERBOSE_DRI)
fprintf( stderr, "[%s:%d] mgaDestroyContext done\n",
__FILE__, __LINE__ );
}
@ -482,13 +593,7 @@ mgaUnbindContext(__DRIcontextPrivate *driContextPriv)
}
static GLboolean
mgaOpenFullScreen(__DRIcontextPrivate *driContextPriv)
{
return GL_TRUE;
}
static GLboolean
mgaCloseFullScreen(__DRIcontextPrivate *driContextPriv)
mgaOpenCloseFullScreen(__DRIcontextPrivate *driContextPriv)
{
return GL_TRUE;
}
@ -505,8 +610,6 @@ mgaMakeCurrent(__DRIcontextPrivate *driContextPriv,
__DRIdrawablePrivate *driDrawPriv,
__DRIdrawablePrivate *driReadPriv)
{
fprintf(stderr, "%s\n", __FUNCTION__);
if (driContextPriv) {
mgaContextPtr mmesa = (mgaContextPtr) driContextPriv->driverPrivate;
@ -532,6 +635,7 @@ mgaMakeCurrent(__DRIcontextPrivate *driContextPriv,
return GL_TRUE;
}
void mgaGetLock( mgaContextPtr mmesa, GLuint flags )
{
__DRIdrawablePrivate *dPriv = mmesa->driDrawable;
@ -539,29 +643,10 @@ void mgaGetLock( mgaContextPtr mmesa, GLuint flags )
int me = mmesa->hHWContext;
int i;
fprintf(stderr, "%s\n", __FUNCTION__);
drmGetLock(mmesa->driFd, mmesa->hHWContext, flags);
fprintf(stderr,
"mmesa->lastStamp %d dpriv->lastStamp %d *(dpriv->pStamp) %d\n",
mmesa->lastStamp,
dPriv->lastStamp,
*(dPriv->pStamp));
/* The window might have moved, so we might need to get new clip
* rects.
*
* NOTE: This releases and regrabs the hw lock to allow the X server
* to respond to the DRI protocol request for new drawable info.
* Since the hardware state depends on having the latest drawable
* clip rects, all state checking must be done _after_ this call.
*/
DRI_VALIDATE_DRAWABLE_INFO( sPriv, dPriv );
if ( mmesa->lastStamp == 0 ||
mmesa->lastStamp != dPriv->lastStamp ) {
mmesa->lastStamp = dPriv->lastStamp;
if (*(dPriv->pStamp) != mmesa->lastStamp) {
mmesa->lastStamp = *(dPriv->pStamp);
mmesa->SetupNewInputs |= VERT_BIT_CLIP;
mmesa->dirty_cliprects = (MGA_FRONT|MGA_BACK);
mgaUpdateRects( mmesa, (MGA_FRONT|MGA_BACK) );
@ -569,7 +654,7 @@ void mgaGetLock( mgaContextPtr mmesa, GLuint flags )
mmesa->dirty |= MGA_UPLOAD_CONTEXT | MGA_UPLOAD_CLIPRECTS;
mmesa->sarea->dirty |= MGA_UPLOAD_CONTEXT;
mmesa->sarea->dirty |= MGA_UPLOAD_CONTEXT;
if (sarea->ctxOwner != me) {
mmesa->dirty |= (MGA_UPLOAD_CONTEXT | MGA_UPLOAD_TEX0 |
@ -577,36 +662,48 @@ void mgaGetLock( mgaContextPtr mmesa, GLuint flags )
sarea->ctxOwner=me;
}
for (i = 0 ; i < mmesa->lastTexHeap ; i++)
if (sarea->texAge[i] != mmesa->texAge[i])
mgaAgeTextures( mmesa, i );
for ( i = 0 ; i < mmesa->nr_heaps ; i++ ) {
DRI_AGE_TEXTURES( mmesa->texture_heaps[ i ] );
}
sarea->last_quiescent = -1; /* just kill it for now */
}
static const struct __DriverAPIRec mgaAPI = {
mgaInitDriver,
mgaDestroyScreen,
mgaCreateContext,
mgaDestroyContext,
mgaCreateBuffer,
mgaDestroyBuffer,
mgaSwapBuffers,
mgaMakeCurrent,
mgaUnbindContext,
mgaOpenFullScreen,
mgaCloseFullScreen
.InitDriver = mgaInitDriver,
.DestroyScreen = mgaDestroyScreen,
.CreateContext = mgaCreateContext,
.DestroyContext = mgaDestroyContext,
.CreateBuffer = mgaCreateBuffer,
.DestroyBuffer = mgaDestroyBuffer,
.SwapBuffers = mgaSwapBuffers,
.MakeCurrent = mgaMakeCurrent,
.UnbindContext = mgaUnbindContext,
.OpenFullScreen = mgaOpenCloseFullScreen,
.CloseFullScreen = mgaOpenCloseFullScreen,
.GetSwapInfo = getSwapInfo,
.GetMSC = driGetMSC32,
.WaitForMSC = driWaitForMSC32,
.WaitForSBC = NULL,
.SwapBuffersMSC = NULL
};
/*
* This is the bootstrap function for the driver.
* The __driCreateScreen name is the symbol that libGL.so fetches.
* Return: pointer to a __DRIscreenPrivate.
*/
#ifndef _SOLO
void *__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
int numConfigs, __GLXvisualConfig *config)
{
__DRIscreenPrivate *psp;
psp = __driUtilCreateScreen(dpy, scrn, psc, numConfigs, config, &mgaAPI);
return (void *) psp;
}
#else
void *__driCreateScreen(struct DRIDriverRec *driver,
struct DRIDriverContextRec *driverContext)
{
@ -614,3 +711,56 @@ void *__driCreateScreen(struct DRIDriverRec *driver,
psp = __driUtilCreateScreen(driver, driverContext, &mgaAPI);
return (void *) psp;
}
#endif
#ifndef _SOLO
/* This function is called by libGL.so as soon as libGL.so is loaded.
* This is where we'd register new extension functions with the dispatcher.
*/
void
__driRegisterExtensions( void )
{
PFNGLXENABLEEXTENSIONPROC glx_enable_extension;
if ( driCompareGLXAPIVersion( 20030317 ) >= 0 ) {
glx_enable_extension = (PFNGLXENABLEEXTENSIONPROC)
glXGetProcAddress( "__glXEnableExtension" );
if ( glx_enable_extension != NULL ) {
(*glx_enable_extension)( "GLX_SGI_swap_control", GL_FALSE );
(*glx_enable_extension)( "GLX_SGI_video_sync", GL_FALSE );
(*glx_enable_extension)( "GLX_MESA_swap_control", GL_FALSE );
(*glx_enable_extension)( "GLX_MESA_swap_frame_usage", GL_FALSE );
}
}
}
#endif
/**
* Get information about previous buffer swaps.
*/
static int
getSwapInfo( __DRIdrawablePrivate *dPriv, __DRIswapInfo * sInfo )
{
mgaContextPtr mmesa;
if ( (dPriv == NULL) || (dPriv->driContextPriv == NULL)
|| (dPriv->driContextPriv->driverPrivate == NULL)
|| (sInfo == NULL) ) {
return -1;
}
mmesa = (mgaContextPtr) dPriv->driContextPriv->driverPrivate;
sInfo->swap_count = mmesa->swap_count;
sInfo->swap_ust = mmesa->swap_ust;
sInfo->swap_missed_count = mmesa->swap_missed_count;
sInfo->swap_missed_usage = (sInfo->swap_missed_count != 0)
? driCalculateSwapUsage( dPriv, 0, mmesa->swap_missed_ust )
: 0.0;
return 0;
}
#endif

View File

@ -29,8 +29,9 @@
#ifndef _MGA_INIT_H_
#define _MGA_INIT_H_
#ifdef GLX_DIRECT_RENDERING
#include <sys/time.h>
#include <linux/types.h>
#include "dri_util.h"
#include "mtypes.h"
#include "mgaregs.h"
@ -46,6 +47,9 @@ typedef struct mga_screen_private_s {
int cpp; /* for front and back buffers */
GLint agpMode;
unsigned int irq; /* IRQ number (0 means none) */
GLboolean linecomp_sane; /* GL_TRUE if line comp. programmed correctly
* by the DDX driver.
*/
unsigned int mAccess;
@ -136,8 +140,9 @@ do { \
#define MGA_BASE( reg ) ((unsigned long)(mmesa->mgaScreen->mmio.map))
#define MGA_ADDR( reg ) (MGA_BASE(reg) + reg)
#define MGA_DEREF( reg ) *(volatile __u32 *)MGA_ADDR( reg )
#define MGA_DEREF( reg ) *(volatile CARD32 *)MGA_ADDR( reg )
#define MGA_READ( reg ) MGA_DEREF( reg )
#define MGA_WRITE( reg, val ) do { MGA_DEREF( reg ) = val; } while (0)
#endif
#endif

View File

@ -29,14 +29,15 @@
#ifndef MGALIB_INC
#define MGALIB_INC
/*#include <X11/Xlibint.h>*/
#include <inttypes.h>
#include "dri_util.h"
#include "mtypes.h"
#include "colormac.h"
#include "xf86drm.h"
#include "mm.h"
/*#include "mem.h"*/
#include "mga_sarea.h"
#include "texmem.h"
#include "macros.h"
#define MGA_SET_FIELD(reg,mask,val) reg = ((reg) & (mask)) | ((val) & ~(mask))
#define MGA_FIELD(field,val) (((val) << (field ## _SHIFT)) & ~(field ## _MASK))
@ -59,19 +60,9 @@
#define MGA_FALLBACK_RENDERMODE 0x10
#define MGA_FALLBACK_STENCIL 0x20
#define MGA_FALLBACK_DEPTH 0x40
#define MGA_FALLBACK_BORDER_MODE 0x80
/* For mgaCtx->new_state.
*/
#define MGA_NEW_DEPTH 0x1
#define MGA_NEW_ALPHA 0x2
#define MGA_NEW_CLIP 0x8
#define MGA_NEW_TEXTURE 0x20
#define MGA_NEW_CULL 0x40
#define MGA_NEW_WARP 0x80
#define MGA_NEW_STENCIL 0x100
#define MGA_NEW_CONTEXT 0x200
/* Use the templated vertex formats:
*/
#define TAG(x) mga##x
@ -96,43 +87,103 @@ typedef void (*mga_point_func)( mgaContextPtr, mgaVertex * );
struct mga_texture_object_s;
struct mga_screen_private_s;
#define MGA_TEX_MAXLEVELS 5
#define G200_TEX_MAXLEVELS 5
#define G400_TEX_MAXLEVELS 11
typedef struct mga_texture_object_s
{
struct mga_texture_object_s *next;
struct mga_texture_object_s *prev;
struct gl_texture_object *tObj;
struct mga_context_t *ctx;
PMemBlock MemBlock;
GLuint offsets[MGA_TEX_MAXLEVELS];
int lastLevel;
GLuint dirty_images;
GLuint totalSize;
int texelBytes;
GLuint age;
int bound;
int heap; /* agp or card */
driTextureObject base;
/* The G200 only has the ability to use 5 mipmap levels (including the
* base level). The G400 does not have this restriction, but it still
* only has 5 offset pointers in the hardware. The trick on the G400 is
* upto the first 4 offset pointers point to mipmap levels. The last
* offset pointer tells how large the preceeding mipmap is. This value is
* then used to determine where the remaining mipmaps are.
*
* For example, if the first offsets[0] through offsets[2] are used as
* pointers, then offset[3] will be the size of the mipmap pointed to by
* offsets[2]. So mipmap level 3 will be at (offsets[2]+offsets[3]). For
* each successive mipmap level, offsets[3] is divided by 4 and added to
* the previous address. So mipmap level 4 will be at
* (offsets[2]+offsets[3]+(offsets[3] / 4)).
*
* The last pointer is selected by setting TO_texorgoffsetsel in its
* pointer. In the previous example, offset[2] would have
* TO_texorgoffsetsel or'ed in before writing it to the hardware.
*
* In the current driver all of the mipmaps are packed together linearly
* with mipmap level 0. Therefore offsets[0] points to the base of the
* texture (and has TO_texorgoffsetsel or'ed in), and offsets[1] is the
* size of the base texture.
*
* There is a possible optimization available here. At times the driver
* may not be able to allocate a single block of memory for the complete
* texture without ejecting some other textures from memory. It may be
* possible to put some of the lower mipmap levels (i.e., the larger
* mipmaps) in memory separate from the higher levels.
*
* The implementation should be fairly obvious, but getting "right" would
* likely be non-trivial. A first allocation for the entire texture would
* be attempted with a flag that says "don't eject other textures." If
* that failed, an additional allocation would be attmpted for just the
* base map. The process would repeat with the block of lower maps. The
* tricky parts would be in detecting when some of the levels had been
* ejected from texture memory by other textures and preventing the
* 4th allocation (for all the smallest mipmap levels) from kicking out
* any of the first three.
*
* This array holds G400_TEX_MAXLEVELS pointers to remove an if-statement
* in a loop in mgaSetTexImages. Values past G200_TEX_MAXLEVELS are not
* used.
*/
GLuint offsets[G400_TEX_MAXLEVELS];
int texelBytes;
GLuint age;
mga_texture_regs_t setup;
/* If one texture dimension wraps with GL_CLAMP and the other with
* GL_CLAMP_TO_EDGE, we have to fallback to software. We would also have
* to fallback for GL_CLAMP_TO_BORDER.
*/
GLboolean border_fallback;
} mgaTextureObject_t;
struct mga_hw_state {
GLuint specen;
GLuint cull;
GLuint cull_dualtex;
GLuint stencil;
GLuint stencilctl;
GLuint stencil_enable;
GLuint zmode;
GLuint rop;
GLuint alpha_func;
GLuint alpha_func_enable;
GLuint blend_func;
GLuint blend_func_enable;
GLuint alpha_sel;
};
struct mga_context_t {
GLcontext *glCtx;
unsigned int lastStamp; /* fullscreen breaks dpriv->laststamp,
* need to shadow it here. */
unsigned int lastStamp; /* fullscreen breaks dpriv->laststamp,
* need to shadow it here. */
/* Hardware state management
*/
struct mga_hw_state hw;
/* Bookkeeping for texturing
*/
int lastTexHeap;
struct mga_texture_object_s TexObjList[MGA_NR_TEX_HEAPS];
struct mga_texture_object_s SwappedOut;
unsigned nr_heaps;
driTexHeap * texture_heaps[ MGA_NR_TEX_HEAPS ];
driTextureObject swapped;
struct mga_texture_object_s *CurrentTexObj[2];
memHeap_t *texHeap[MGA_NR_TEX_HEAPS];
int c_texupload;
int c_texusage;
int tex_thrash;
/* Map GL texture units onto hardware.
@ -166,7 +217,7 @@ struct mga_context_t {
GLenum raster_primitive;
GLenum render_primitive;
char *verts;
GLubyte *verts;
GLint vertex_stride_shift;
GLuint vertex_format;
GLuint vertex_size;
@ -180,8 +231,7 @@ struct mga_context_t {
/* Manage driver and hardware state
*/
GLuint new_gl_state;
GLuint new_state;
GLuint NewGLState;
GLuint dirty;
mga_context_regs_t setup;
@ -205,13 +255,21 @@ struct mga_context_t {
/* VBI
*/
GLuint vbl_seq;
GLuint vblank_flags;
uint64_t swap_ust;
uint64_t swap_missed_ust;
GLuint swap_count;
GLuint swap_missed_count;
PFNGLXGETUSTPROC get_ust;
/* Drawable, cliprect and scissor information
*/
int dirty_cliprects; /* which sets of cliprects are uptodate? */
int draw_buffer; /* which buffer are we rendering to */
unsigned int drawOffset; /* draw buffer address in space */
int read_buffer;
int readOffset;
int drawX, drawY; /* origin of drawable in draw buffer */
int lastX, lastY; /* detect DSTORG bug */
@ -245,51 +303,38 @@ struct mga_context_t {
#define MGA_CONTEXT(ctx) ((mgaContextPtr)(ctx->DriverCtx))
#define MGAPACKCOLOR555(r,g,b,a) \
((((r) & 0xf8) << 7) | (((g) & 0xf8) << 2) | (((b) & 0xf8) >> 3) | \
((a) ? 0x8000 : 0))
#define MGAPACKCOLOR565(r,g,b) \
((((r) & 0xf8) << 8) | (((g) & 0xfc) << 3) | (((b) & 0xf8) >> 3))
#define MGAPACKCOLOR88(l, a) \
(((l) << 8) | (a))
#define MGAPACKCOLOR888(r,g,b) \
(((r) << 16) | ((g) << 8) | (b))
#define MGAPACKCOLOR8888(r,g,b,a) \
(((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
#define MGAPACKCOLOR4444(r,g,b,a) \
((((a) & 0xf0) << 8) | (((r) & 0xf0) << 4) | ((g) & 0xf0) | ((b) >> 4))
#define MGA_DEBUG 0
#ifndef MGA_DEBUG
/* ================================================================
* Debugging:
*/
#define DO_DEBUG 1
#if DO_DEBUG
extern int MGA_DEBUG;
#else
#define MGA_DEBUG 0
#endif
#define DEBUG_ALWAYS_SYNC 0x1
#define DEBUG_VERBOSE_MSG 0x2
#define DEBUG_VERBOSE_LRU 0x4
#define DEBUG_VERBOSE_DRI 0x8
#define DEBUG_VERBOSE_IOCTL 0x10
#define DEBUG_VERBOSE_2D 0x20
#define DEBUG_VERBOSE_FALLBACK 0x40
#define DEBUG_VERBOSE_MSG 0x01
#define DEBUG_VERBOSE_DRI 0x02
#define DEBUG_VERBOSE_IOCTL 0x04
#define DEBUG_VERBOSE_TEXTURE 0x08
#define DEBUG_VERBOSE_FALLBACK 0x10
static __inline__ GLuint mgaPackColor(GLuint cpp,
GLubyte r, GLubyte g,
GLubyte b, GLubyte a)
{
switch (cpp) {
case 2:
return MGAPACKCOLOR565(r,g,b);
case 4:
return MGAPACKCOLOR8888(r,g,b,a);
default:
return 0;
}
switch (cpp) {
case 2:
return PACK_COLOR_565( r, g, b );
case 4:
return PACK_COLOR_8888( a, r, g, b );
default:
return 0;
}
}

View File

@ -29,10 +29,6 @@
#include "mtypes.h"
#include <stdio.h>
#include <stdlib.h>
#include "mm.h"
#include "mgacontext.h"
#include "mgadd.h"
@ -42,12 +38,9 @@
#include "mgatris.h"
#include "mgavb.h"
#include "mga_xmesa.h"
#include "extensions.h"
#if defined(USE_X86_ASM)
#include "X86/common_x86_asm.h"
#endif
#include "utils.h"
#define MGA_DATE "20020221"
#define DRIVER_DATE "20030328"
/***************************************
@ -59,52 +52,19 @@ static const GLubyte *mgaDDGetString( GLcontext *ctx, GLenum name )
{
mgaContextPtr mmesa = MGA_CONTEXT( ctx );
static char buffer[128];
unsigned offset;
switch ( name ) {
case GL_VENDOR:
return (GLubyte *) "VA Linux Systems Inc.";
case GL_RENDERER:
sprintf( buffer, "Mesa DRI %s " MGA_DATE,
MGA_IS_G400(mmesa) ? "G400" :
MGA_IS_G200(mmesa) ? "G200" : "MGA" );
offset = driGetRendererString( buffer,
MGA_IS_G400(mmesa) ? "G400" :
MGA_IS_G200(mmesa) ? "G200" : "MGA",
DRIVER_DATE,
mmesa->mgaScreen->agpMode );
/* Append any AGP-specific information.
*/
switch ( mmesa->mgaScreen->agpMode ) {
case 1:
strncat( buffer, " AGP 1x", 7 );
break;
case 2:
strncat( buffer, " AGP 2x", 7 );
break;
case 4:
strncat( buffer, " AGP 4x", 7 );
break;
}
/* Append any CPU-specific information.
*/
#ifdef USE_X86_ASM
if ( _mesa_x86_cpu_features ) {
strncat( buffer, " x86", 4 );
}
#endif
#ifdef USE_MMX_ASM
if ( cpu_has_mmx ) {
strncat( buffer, "/MMX", 4 );
}
#endif
#ifdef USE_3DNOW_ASM
if ( cpu_has_3dnow ) {
strncat( buffer, "/3DNow!", 7 );
}
#endif
#ifdef USE_SSE_ASM
if ( cpu_has_xmm ) {
strncat( buffer, "/SSE", 4 );
}
#endif
return (GLubyte *)buffer;
default:
@ -129,40 +89,6 @@ static void mgaBufferSize(GLframebuffer *buffer, GLuint *width, GLuint *height)
UNLOCK_HARDWARE( mmesa );
}
void mgaDDExtensionsInit( GLcontext *ctx )
{
/* paletted_textures currently doesn't work, but we could fix them later */
/*
_mesa_enable_extension( ctx, "GL_EXT_shared_texture_palette" );
_mesa_enable_extension( ctx, "GL_EXT_paletted_texture" );
*/
_mesa_enable_extension( ctx, "GL_ARB_texture_compression" );
_mesa_enable_extension( ctx, "GL_ARB_multisample" );
_mesa_enable_extension( ctx, "GL_SGIS_generate_mipmap" );
/* Turn on multitexture and texenv_add for the G400.
*/
if (MGA_IS_G400(MGA_CONTEXT(ctx))) {
_mesa_enable_extension( ctx, "GL_ARB_multitexture" );
_mesa_enable_extension( ctx, "GL_ARB_texture_env_add" );
_mesa_enable_extension( ctx, "GL_EXT_texture_env_add" );
#if defined (MESA_packed_depth_stencil)
_mesa_enable_extension( ctx, "GL_MESA_packed_depth_stencil" );
#endif
#if defined (MESA_experimetal_agp_allocator)
if (!getenv("MGA_DISABLE_AGP_ALLOCATOR"))
_mesa_enable_extension( ctx, "GL_MESA_experimental_agp_allocator" );
#endif
}
}
void mgaDDInitDriverFuncs( GLcontext *ctx )
{
ctx->Driver.GetBufferSize = mgaBufferSize;

View File

@ -32,6 +32,5 @@
#include "context.h"
void mgaDDInitDriverFuncs( GLcontext *ctx );
void mgaDDExtensionsInit( GLcontext *ctx );
#endif

View File

@ -27,7 +27,7 @@
*/
/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgaioctl.c,v 1.16 2002/12/16 16:18:52 dawes Exp $ */
#include <stdio.h>
#include <sched.h>
#include <errno.h>
#include "mtypes.h"
@ -43,12 +43,11 @@
#include "mgavb.h"
#include "mgaioctl.h"
#include "mgatris.h"
#include "mgabuffers.h"
#include "xf86drm.h"
#include "mga_common.h"
#include "vblank.h"
static void mga_iload_dma_ioctl(mgaContextPtr mmesa,
unsigned long dest,
int length)
@ -61,6 +60,13 @@ static void mga_iload_dma_ioctl(mgaContextPtr mmesa,
fprintf(stderr, "DRM_IOCTL_MGA_ILOAD idx %d dst %x length %d\n",
buf->idx, (int) dest, length);
if ( (length & MGA_ILOAD_MASK) != 0 ) {
UNLOCK_HARDWARE( mmesa );
fprintf( stderr, "%s: Invalid ILOAD datasize (%d), must be "
"multiple of %u.\n", __FUNCTION__, length, MGA_ILOAD_ALIGN );
exit( 1 );
}
iload.idx = buf->idx;
iload.dstorg = dest;
iload.length = length;
@ -278,65 +284,11 @@ mgaDDClear( GLcontext *ctx, GLbitfield mask, GLboolean all,
}
int nrswaps;
void mgaWaitForVBlank( mgaContextPtr mmesa )
static void mgaWaitForFrameCompletion( mgaContextPtr mmesa )
{
#if 0
drmVBlank vbl;
int ret;
if ( !mmesa->mgaScreen->irq )
return;
if ( getenv("LIBGL_SYNC_REFRESH") ) {
/* Wait for until the next vertical blank */
vbl.request.type = DRM_VBLANK_RELATIVE;
vbl.request.sequence = 1;
} else if ( getenv("LIBGL_THROTTLE_REFRESH") ) {
/* Wait for at least one vertical blank since the last call */
vbl.request.type = DRM_VBLANK_ABSOLUTE;
vbl.request.sequence = mmesa->vbl_seq + 1;
} else {
return;
}
if ((ret = drmWaitVBlank( mmesa->driFd, &vbl ))) {
fprintf(stderr, "%s: drmWaitVBlank returned %d, IRQs don't seem to be"
" working correctly.\nTry running with LIBGL_THROTTLE_REFRESH"
" and LIBL_SYNC_REFRESH unset.\n", __FUNCTION__, ret);
exit(1);
}
mmesa->vbl_seq = vbl.reply.sequence;
#endif
}
/*
* Copy the back buffer to the front buffer.
*/
void mgaSwapBuffers(__DRIdrawablePrivate *dPriv)
{
mgaContextPtr mmesa;
XF86DRIClipRectPtr pbox;
GLint nbox;
GLint ret, wait = 0;
GLint i;
unsigned wait = 0;
GLuint last_frame, last_wrap;
assert(dPriv);
assert(dPriv->driContextPriv);
assert(dPriv->driContextPriv->driverPrivate);
mmesa = (mgaContextPtr) dPriv->driContextPriv->driverPrivate;
FLUSH_BATCH( mmesa );
mgaWaitForVBlank( mmesa );
LOCK_HARDWARE( mmesa );
last_frame = mmesa->sarea->last_frame.head;
last_wrap = mmesa->sarea->last_frame.wrap;
@ -360,12 +312,46 @@ void mgaSwapBuffers(__DRIdrawablePrivate *dPriv)
}
UPDATE_LOCK( mmesa, DRM_LOCK_FLUSH );
for ( i = 0 ; i < 1024 ; i++ ) {
/* Don't just hammer the register... */
}
UNLOCK_HARDWARE( mmesa );
DO_USLEEP( 1 );
LOCK_HARDWARE( mmesa );
}
if ( wait )
fprintf( stderr, "\n" );
}
/*
* Copy the back buffer to the front buffer.
*/
void mgaSwapBuffers( __DRIdrawablePrivate *dPriv )
{
mgaContextPtr mmesa;
XF86DRIClipRectPtr pbox;
GLint nbox;
GLint ret;
GLint i;
GLboolean missed_target;
assert(dPriv);
assert(dPriv->driContextPriv);
assert(dPriv->driContextPriv->driverPrivate);
mmesa = (mgaContextPtr) dPriv->driContextPriv->driverPrivate;
FLUSH_BATCH( mmesa );
LOCK_HARDWARE( mmesa );
mgaWaitForFrameCompletion( mmesa );
UNLOCK_HARDWARE( mmesa );
driWaitForVBlank( dPriv, & mmesa->vbl_seq, mmesa->vblank_flags,
& missed_target );
if ( missed_target ) {
mmesa->swap_missed_count++;
(void) (*mmesa->get_ust)( & mmesa->swap_missed_ust );
}
LOCK_HARDWARE( mmesa );
/* Use the frontbuffer cliprects
*/
@ -399,6 +385,8 @@ void mgaSwapBuffers(__DRIdrawablePrivate *dPriv)
UNLOCK_HARDWARE( mmesa );
mmesa->dirty |= MGA_UPLOAD_CLIPRECTS;
mmesa->swap_count++;
(void) (*mmesa->get_ust)( & mmesa->swap_ust );
}
@ -442,18 +430,17 @@ void mgaWaitAge( mgaContextPtr mmesa, int age )
}
static int intersect_rect( XF86DRIClipRectPtr out,
XF86DRIClipRectPtr a,
XF86DRIClipRectPtr b )
static GLboolean intersect_rect( XF86DRIClipRectPtr out,
const XF86DRIClipRectPtr a,
const XF86DRIClipRectPtr b )
{
*out = *a;
if (b->x1 > out->x1) out->x1 = b->x1;
if (b->y1 > out->y1) out->y1 = b->y1;
if (b->x2 < out->x2) out->x2 = b->x2;
if (b->y2 < out->y2) out->y2 = b->y2;
if (out->x1 > out->x2) return 0;
if (out->y1 > out->y2) return 0;
return 1;
return ((out->x1 < out->x2) && (out->y1 < out->y2));
}
@ -559,7 +546,7 @@ void mgaFlushVerticesLocked( mgaContextPtr mmesa )
vertex.idx = buffer->idx;
vertex.used = buffer->used;
vertex.discard = discard;
drmCommandWrite( mmesa->driFd, DRM_MGA_VERTEX,
drmCommandWrite( mmesa->driFd, DRM_MGA_VERTEX,
&vertex, sizeof(drmMGAVertex) );
age_mmesa(mmesa, mmesa->sarea->last_enqueue);

View File

@ -34,6 +34,7 @@
#include "mga_xmesa.h"
void mgaSwapBuffers( __DRIdrawablePrivate *dPriv );
void mgaWaitForVBlank( mgaContextPtr mmesa );
GLuint *mgaAllocVertexDwords( mgaContextPtr mmesa, int dwords );
@ -41,7 +42,6 @@ GLuint *mgaAllocVertexDwords( mgaContextPtr mmesa, int dwords );
void mgaGetILoadBufferLocked( mgaContextPtr mmesa );
drmBufPtr mgaGetBufferLocked( mgaContextPtr mmesa );
void mgaWaitForVBlank( mgaContextPtr mmesa );
void mgaFireILoadLocked( mgaContextPtr mmesa,
GLuint offset, GLuint length );
@ -104,8 +104,9 @@ do { \
if ( ret < 0 ) { \
drmCommandNone( mmesa->driFd, DRM_MGA_RESET ); \
UNLOCK_HARDWARE( mmesa ); \
fprintf( stderr, "%s: flush ret=%d\n", __FUNCTION__, ret ); \
/*fprintf( stderr, "drmMGAFlushDMA: return = %d\n", ret );*/ \
fprintf( stderr, "%s: flush return = %s (%d), flags = 0x%08x\n", \
__FUNCTION__, strerror( -ret ), -ret, \
(unsigned)(flags) ); \
exit( 1 ); \
} \
} while (0)

View File

@ -35,12 +35,12 @@
#include "mgacontext.h"
#include "mgaioctl.h"
#include "mgapixel.h"
#include "mgabuffers.h"
#include "mgastate.h"
#include "xf86drm.h"
#include "mga_common.h"
#include "swrast/swrast.h"
#include "imports.h"
#define IS_AGP_MEM( mmesa, p ) \
((unsigned long)mmesa->mgaScreen->buffers.map <= ((unsigned long)p) && \
@ -134,7 +134,7 @@ check_color_per_fragment_ops( const GLcontext *ctx )
!ctx->Color.ColorMask[2] ||
!ctx->Color.ColorMask[3] ||
ctx->Color.ColorLogicOpEnabled ||
ctx->Texture.Unit[0]._ReallyEnabled ||
ctx->Texture._EnabledUnits ||
ctx->Depth.OcclusionTest
) &&
ctx->Current.RasterPosValid &&
@ -596,7 +596,7 @@ mgaTryDrawPixels( GLcontext *ctx,
}
}
#else
memcpy( address, pixels, rows*bufferpitch );
MEMCPY( address, pixels, rows*bufferpitch );
#endif
do_draw_pix( ctx, x, y, width, rows,
@ -639,42 +639,8 @@ mgaDDDrawPixels( GLcontext *ctx,
* the same block of agp space which isn't used for anything else at
* present.
*/
#if defined(MESA_hacked_agp_allocator)
static void mgaDDFreeAgpMemory( GLcontext *ctx, void *ptr )
{
(void) ptr;
}
static void *mgaDDAllocateAgpMemory( GLcontext *ctx, GLsizei size )
{
mgaContextPtr mmesa = MGA_CONTEXT(ctx);
if (size < mmesa->mgaScreen->textureSize[MGA_AGP_HEAP])
return mmesa->mgaScreen->texVirtual[MGA_AGP_HEAP];
else
return 0;
}
static GLint mgaDDGetAgpOffset( GLcontext *ctx, const void *ptr )
{
mgaContextPtr mmesa = MGA_CONTEXT(ctx);
if (!IS_AGP_MEM(mmesa, ptr))
return -1;
return AGP_OFFSET(mmesa, ptr);
}
#endif
void mgaDDInitPixelFuncs( GLcontext *ctx )
{
#if defined (MESA_experimetal_agp_allocator)
ctx->Driver.AllocateAgpMemory = mgaDDAllocateAgpMemory;
ctx->Driver.GetAgpOffset = mgaDDGetAgpOffset;
ctx->Driver.FreeAgpMemory = mgaDDFreeAgpMemory;
#endif
/* Pixel path fallbacks.
*/
ctx->Driver.Accum = _swrast_Accum;

View File

@ -1052,6 +1052,7 @@
# define TMC_tformat_tw8a 0x7 /* val 7, shift 0 */
# define TMC_tformat_tw8al 0x8 /* val 8, shift 0 */
# define TMC_tformat_tw422 0xa /* val 10, shift 0 */
# define TMC_tformat_tw422uyvy 0xb /* val 11, shift 0 */
# define TMC_tpitchlin_MASK 0xfffffeff /* bit 8 */
# define TMC_tpitchlin_disable 0x0
# define TMC_tpitchlin_enable 0x100
@ -1137,6 +1138,13 @@
# define TF_magfilter_nrst 0x0 /* val 0, shift 4 */
# define TF_magfilter_bilin 0x20 /* val 2, shift 4 */
# define TF_magfilter_cnst 0x30 /* val 3, shift 4 */
# define TF_uvoffset_SHIFT 17
# define TF_uvoffset_OGL (0U << TF_uvoffset_SHIFT)
# define TF_uvoffset_D3D (1U << TF_uvoffset_SHIFT)
# define TF_uvoffset_MASK (~(1U << TF_uvoffset_SHIFT))
# define TF_reserved_MASK (~0x1ff00) /* bits 8-16 */
# define TF_mapnbhigh_SHIFT 18
# define TF_mapnbhigh_MASK (~(1U << TF_mapnbhigh_SHIFT))
# define TF_avgstride_MASK 0xfff7ffff /* bit 19 */
# define TF_avgstride_disable 0x0
# define TF_avgstride_enable 0x80000
@ -1377,5 +1385,11 @@
/**************** (END) AUTOMATICLY GENERATED REGISTER FILE ******************/
/* Copied from mga_drv.h kernel file.
*/
#define MGA_ILOAD_ALIGN 64
#define MGA_ILOAD_MASK (MGA_ILOAD_ALIGN - 1)
#endif /* _MGAREGS_H_ */

View File

@ -42,9 +42,8 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "glheader.h"
#include "context.h"
#include "macros.h"
/*//#include "mem.h"*/
#include "imports.h"
#include "mtypes.h"
/*#include "mmath.h" */
#include "tnl/t_context.h"
@ -165,7 +164,7 @@ static GLboolean mga_run_render( GLcontext *ctx,
static void mga_check_render( GLcontext *ctx, struct gl_pipeline_stage *stage )
{
GLuint inputs = VERT_BIT_POS | VERT_BIT_CLIP | VERT_BIT_COLOR0;
GLuint inputs = VERT_BIT_CLIP | VERT_BIT_COLOR0;
if (ctx->RenderMode == GL_RENDER) {
if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR)

View File

@ -116,7 +116,7 @@
#undef INIT_MONO_PIXEL
#define INIT_MONO_PIXEL(p, color) \
p = MGAPACKCOLOR565( color[0], color[1], color[2] )
p = PACK_COLOR_565( color[0], color[1], color[2] )
#define WRITE_RGBA( _x, _y, r, g, b, a ) \
@ -148,7 +148,7 @@ do { \
#undef INIT_MONO_PIXEL
#define INIT_MONO_PIXEL(p, color) \
p = MGAPACKCOLOR8888( color[0], color[1], color[2], color[3] )
p = PACK_COLOR_8888( color[3], color[0], color[1], color[2] )
#define WRITE_RGBA(_x, _y, r, g, b, a) \
@ -233,11 +233,38 @@ do { \
/*
* This function is called to specify which buffer to read and write
* for software rasterization (swrast) fallbacks. This doesn't necessarily
* correspond to glDrawBuffer() or glReadBuffer() calls.
*/
static void mgaDDSetBuffer(GLcontext *ctx, GLframebuffer *buffer,
GLuint bufferBit)
{
mgaContextPtr mmesa = MGA_CONTEXT(ctx);
if (bufferBit == FRONT_LEFT_BIT)
{
mmesa->drawOffset = mmesa->mgaScreen->frontOffset;
mmesa->readOffset = mmesa->mgaScreen->frontOffset;
}
else if (bufferBit == BACK_LEFT_BIT)
{
mmesa->drawOffset = mmesa->mgaScreen->backOffset;
mmesa->readOffset = mmesa->mgaScreen->backOffset;
}
else {
assert(0);
}
}
void mgaDDInitSpanFuncs( GLcontext *ctx )
{
mgaContextPtr mmesa = MGA_CONTEXT(ctx);
struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference(ctx);
swdd->SetBuffer = mgaDDSetBuffer;
switch (mmesa->mgaScreen->cpp) {
case 2:
swdd->WriteRGBASpan = mgaWriteRGBASpan_565;

File diff suppressed because it is too large Load Diff

View File

@ -29,14 +29,11 @@
#ifndef _MGA_STATE_H
#define _MGA_STATE_H
extern void mgaInitState( mgaContextPtr mmesa );
extern void mgaDDInitStateFuncs(GLcontext *ctx);
extern void mgaDDUpdateHwState( GLcontext *ctx );
extern void mgaUpdateClipping(const GLcontext *ctx);
extern void mgaUpdateCull( GLcontext *ctx );
extern void mgaCalcViewport( GLcontext *ctx );
extern void mgaUpdateRects( mgaContextPtr mmesa, GLuint buffers );
#endif

File diff suppressed because it is too large Load Diff

View File

@ -40,23 +40,10 @@ typedef struct mga_texture_object_s *mgaTextureObjectPtr;
*/
void mgaUpdateTextureState( GLcontext *ctx );
void mgaConvertTexture( GLuint *dest, int texelBytes,
struct gl_texture_image *image,
int x, int y, int width, int height );
void mgaUploadSubImageLocked( mgaContextPtr mmesa,
mgaTextureObjectPtr t,
int level,
int x, int y, int width, int height );
int mgaUploadTexImages( mgaContextPtr mmesa, mgaTextureObjectPtr t );
void mgaDestroyTexObj( mgaContextPtr mmesa, mgaTextureObjectPtr t );
void mgaAgeTextures( mgaContextPtr mmesa, int heap );
void mgaDDInitTextureFuncs( GLcontext *ctx );
#endif

View File

@ -26,539 +26,257 @@
*/
/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgatexmem.c,v 1.7 2002/10/30 12:51:36 alanh Exp $ */
#include <stdlib.h>
#include <stdio.h>
#include <GL/gl.h>
#include "glheader.h"
#include "mm.h"
#include "mgacontext.h"
#include "mgatex.h"
#include "mgaregs.h"
#include "mgaioctl.h"
#include "mga_xmesa.h"
/*#include "mem.h" */
#include "imports.h"
#include "simple_list.h"
static void
mgaSwapOutTexObj(mgaContextPtr mmesa, mgaTextureObjectPtr t)
{
if (t->MemBlock) {
mmFreeMem(t->MemBlock);
t->MemBlock = 0;
if (t->age > mmesa->dirtyAge)
mmesa->dirtyAge = t->age;
}
t->dirty_images = ~0;
move_to_tail(&(mmesa->SwappedOut), t);
}
static void
mgaPrintLocalLRU( mgaContextPtr mmesa, int heap )
{
mgaTextureObjectPtr t;
int sz = 1 << (mmesa->mgaScreen->logTextureGranularity[heap]);
fprintf(stderr, "\nLocal LRU, heap %d:\n", heap);
foreach( t, &(mmesa->TexObjList[heap]) ) {
if (!t->tObj)
fprintf(stderr, "Placeholder %d at %x sz %x\n",
t->MemBlock->ofs / sz,
t->MemBlock->ofs,
t->MemBlock->size);
else
fprintf(stderr, "Texture (bound %d) at %x sz %x\n",
t->bound,
t->MemBlock->ofs,
t->MemBlock->size);
}
fprintf(stderr, "\n\n");
}
static void
mgaPrintGlobalLRU( mgaContextPtr mmesa, int heap )
{
int i, j;
drmTextureRegion *list = mmesa->sarea->texList[heap];
fprintf(stderr, "\nGlobal LRU, heap %d list %p:\n", heap, list);
for (i = 0, j = MGA_NR_TEX_REGIONS ; i < MGA_NR_TEX_REGIONS ; i++) {
fprintf(stderr, "list[%d] age %d next %d prev %d\n",
j, list[j].age, list[j].next, list[j].prev);
j = list[j].next;
if (j == MGA_NR_TEX_REGIONS) break;
}
if (j != MGA_NR_TEX_REGIONS) {
fprintf(stderr, "Loop detected in global LRU\n\n\n");
for (i = 0 ; i < MGA_NR_TEX_REGIONS ; i++) {
fprintf(stderr, "list[%d] age %d next %d prev %d\n",
i, list[i].age, list[i].next, list[i].prev);
}
}
fprintf(stderr, "\n\n");
}
static void mgaResetGlobalLRU( mgaContextPtr mmesa, GLuint heap )
{
drmTextureRegion *list = mmesa->sarea->texList[heap];
int sz = 1 << mmesa->mgaScreen->logTextureGranularity[heap];
int i;
mmesa->texAge[heap] = ++mmesa->sarea->texAge[heap];
if (0) fprintf(stderr, "mgaResetGlobalLRU %d\n", (int)heap);
/* (Re)initialize the global circular LRU list. The last element
* in the array (MGA_NR_TEX_REGIONS) is the sentinal. Keeping it
* at the end of the array allows it to be addressed rationally
* when looking up objects at a particular location in texture
* memory.
*/
for (i = 0 ; (i+1) * sz <= mmesa->mgaScreen->textureSize[heap] ; i++) {
list[i].prev = i-1;
list[i].next = i+1;
list[i].age = mmesa->sarea->texAge[heap];
}
i--;
list[0].prev = MGA_NR_TEX_REGIONS;
list[i].prev = i-1;
list[i].next = MGA_NR_TEX_REGIONS;
list[MGA_NR_TEX_REGIONS].prev = i;
list[MGA_NR_TEX_REGIONS].next = 0;
}
static void mgaUpdateTexLRU( mgaContextPtr mmesa, mgaTextureObjectPtr t )
{
int i;
int heap = t->heap;
int logsz = mmesa->mgaScreen->logTextureGranularity[heap];
int start = t->MemBlock->ofs >> logsz;
int end = (t->MemBlock->ofs + t->MemBlock->size - 1) >> logsz;
drmTextureRegion *list = mmesa->sarea->texList[heap];
mmesa->texAge[heap] = ++mmesa->sarea->texAge[heap];
if (!t->MemBlock) {
fprintf(stderr, "no memblock\n\n");
return;
}
/* Update our local LRU
*/
move_to_head( &(mmesa->TexObjList[heap]), t );
if (0)
fprintf(stderr, "mgaUpdateTexLRU heap %d list %p\n", heap, list);
/* Update the global LRU
*/
for (i = start ; i <= end ; i++) {
list[i].in_use = 1;
list[i].age = mmesa->texAge[heap];
/* remove_from_list(i)
*/
list[(unsigned)list[i].next].prev = list[i].prev;
list[(unsigned)list[i].prev].next = list[i].next;
/* insert_at_head(list, i)
*/
list[i].prev = MGA_NR_TEX_REGIONS;
list[i].next = list[MGA_NR_TEX_REGIONS].next;
list[(unsigned)list[MGA_NR_TEX_REGIONS].next].prev = i;
list[MGA_NR_TEX_REGIONS].next = i;
}
if (0) {
mgaPrintGlobalLRU(mmesa, t->heap);
mgaPrintLocalLRU(mmesa, t->heap);
}
}
/* Called for every shared texture region which has increased in age
* since we last held the lock.
*
* Figures out which of our textures have been ejected by other clients,
* and pushes a placeholder texture onto the LRU list to represent
* the other client's textures.
/**
* Destroy any device-dependent state associated with the texture. This may
* include NULLing out hardware state that points to the texture.
*/
static void mgaTexturesGone( mgaContextPtr mmesa,
GLuint heap,
GLuint offset,
GLuint size,
GLuint in_use )
void
mgaDestroyTexObj( mgaContextPtr mmesa, mgaTextureObjectPtr t )
{
mgaTextureObjectPtr t, tmp;
unsigned i;
/* See if it was the driver's current object.
*/
foreach_s ( t, tmp, &(mmesa->TexObjList[heap]) ) {
if ( mmesa != NULL )
{
if ( t->age > mmesa->dirtyAge )
mmesa->dirtyAge = t->age;
if (t->MemBlock->ofs >= offset + size ||
t->MemBlock->ofs + t->MemBlock->size <= offset)
continue;
/* It overlaps - kick it off. Need to hold onto the currently bound
* objects, however.
*/
if (t->bound)
mgaSwapOutTexObj( mmesa, t );
else
mgaDestroyTexObj( mmesa, t );
}
if (in_use) {
t = (mgaTextureObjectPtr) calloc(1, sizeof(*t));
if (!t) return;
t->heap = heap;
t->MemBlock = mmAllocMem( mmesa->texHeap[heap], size, 0, offset);
if (!t->MemBlock) {
fprintf(stderr, "Couldn't alloc placeholder sz %x ofs %x\n",
(int)size, (int)offset);
mmDumpMemInfo( mmesa->texHeap[heap]);
return;
}
insert_at_head( &(mmesa->TexObjList[heap]), t );
}
for ( i = 0 ; i < mmesa->glCtx->Const.MaxTextureUnits ; i++ )
{
if ( t == mmesa->CurrentTexObj[ i ] ) {
mmesa->CurrentTexObj[ i ] = NULL;
}
}
}
}
void mgaAgeTextures( mgaContextPtr mmesa, int heap )
{
MGASAREAPrivPtr sarea = mmesa->sarea;
int sz = 1 << (mmesa->mgaScreen->logTextureGranularity[heap]);
int idx, nr = 0;
/* Have to go right round from the back to ensure stuff ends up
* LRU in our local list... Fix with a cursor pointer.
*/
for (idx = sarea->texList[heap][MGA_NR_TEX_REGIONS].prev ;
idx != MGA_NR_TEX_REGIONS && nr < MGA_NR_TEX_REGIONS ;
idx = sarea->texList[heap][idx].prev, nr++)
{
/* If switching texturing schemes, then the SAREA might not
* have been properly cleared, so we need to reset the
* global texture LRU.
*/
if ( idx * sz > mmesa->mgaScreen->textureSize[heap] ) {
nr = MGA_NR_TEX_REGIONS;
break;
}
if (sarea->texList[heap][idx].age > mmesa->texAge[heap]) {
mgaTexturesGone(mmesa, heap, idx * sz, sz,
sarea->texList[heap][idx].in_use);
}
}
if (nr == MGA_NR_TEX_REGIONS) {
mgaTexturesGone(mmesa, heap, 0,
mmesa->mgaScreen->textureSize[heap], 0);
mgaResetGlobalLRU( mmesa, heap );
}
if (0) {
mgaPrintGlobalLRU( mmesa, heap );
mgaPrintLocalLRU( mmesa, heap );
}
mmesa->texAge[heap] = sarea->texAge[heap];
mmesa->dirty |= MGA_UPLOAD_TEX0IMAGE | MGA_UPLOAD_TEX1IMAGE;
}
/*
* mgaUploadSubImageLocked
*
* Perform an iload based update of a resident buffer. This is used for
* both initial loading of the entire image, and texSubImage updates.
/**
* Upload a texture image from system memory to either on-card or AGP
* memory. Uploads to on-card memory are performed using an ILOAD operation.
* This is used for both initial loading of the entire image, and texSubImage
* updates.
*
* Performed with the hardware lock held.
*
* Even though this function is named "upload subimage," the entire image
* is uploaded.
*
* \param mmesa Driver context.
* \param t Texture to be uploaded.
* \param hwlevel Mipmap level of the texture to be uploaded.
*
* \bug As mentioned above, this fuction actually copies the entier mipmap
* level. There should be a version of this function that performs
* sub-rectangle uploads. This will perform quite a bit better if only
* a small portion of a larger texture has been updated. Care would
* need to be take with such an implementation once glCopyTexImage has
* been hardware accelerated.
*/
void mgaUploadSubImageLocked( mgaContextPtr mmesa,
mgaTextureObjectPtr t,
int level,
int x, int y, int width, int height )
static void mgaUploadSubImage( mgaContextPtr mmesa,
mgaTextureObjectPtr t, GLint hwlevel )
{
int x2;
int dwords;
int offset;
struct gl_texture_image *image;
int texelBytes, texelsPerDword, texelMaccess, length;
struct gl_texture_image * texImage;
unsigned offset;
unsigned texelBytes;
unsigned length;
const int level = hwlevel + t->base.firstLevel;
if ( level < 0 || level >= MGA_TEX_MAXLEVELS )
if ( (hwlevel < 0)
|| (hwlevel >= (MGA_IS_G200(mmesa)
? G200_TEX_MAXLEVELS : G400_TEX_MAXLEVELS)) ) {
fprintf( stderr, "[%s:%d] level = %d\n", __FILE__, __LINE__, level );
return;
}
image = t->tObj->Image[level];
if ( !image ) return;
texImage = t->base.tObj->Image[level];
if ( texImage == NULL ) {
fprintf( stderr, "[%s:%d] Image[%d] = NULL\n", __FILE__, __LINE__,
level );
return;
}
if (image->Data == 0) {
if (texImage->Data == NULL) {
fprintf(stderr, "null texture image data tObj %p level %d\n",
t->tObj, level);
t->base.tObj, level);
return;
}
/* find the proper destination offset for this level */
offset = (t->MemBlock->ofs +
t->offsets[level]);
texelBytes = t->texelBytes;
switch( texelBytes ) {
case 1:
texelsPerDword = 4;
texelMaccess = 0;
break;
case 2:
texelsPerDword = 2;
texelMaccess = 1;
break;
case 4:
texelsPerDword = 1;
texelMaccess = 2;
break;
default:
return;
if ( MGA_IS_G200(mmesa) ) {
offset = (t->base.memBlock->ofs + t->offsets[hwlevel]);
}
else {
unsigned i;
/* We can't do a subimage update if pitch is < 32 texels due
* to hardware XY addressing limits, so we will need to
* linearly upload all modified rows.
*/
if ( image->Width < 32 ) {
x = 0;
width = image->Width * height;
height = 1;
/* Assume that 1x1 textures aren't going to cause a
* bus error if we read up to four texels from that
* location:
*/
/* if ( width < texelsPerDword ) { */
/* width = texelsPerDword; */
/* } */
} else {
/* pad the size out to dwords. The image is a pointer
to the entire image, so we can safely reference
outside the x,y,width,height bounds if we need to */
x2 = x + width;
x2 = (x2 + (texelsPerDword-1)) & ~(texelsPerDword-1);
x = (x + (texelsPerDword-1)) & ~(texelsPerDword-1);
width = x2 - x;
}
/* we may not be able to upload the entire texture in one
batch due to register limits or dma buffer limits.
Recursively split it up. */
while ( 1 ) {
dwords = height * width / texelsPerDword;
if ( dwords * 4 <= MGA_BUFFER_SIZE ) {
break;
offset = t->base.memBlock->ofs;
for ( i = 0 ; i < hwlevel ; i++ ) {
offset += (t->offsets[1] >> (i * 2));
}
mgaUploadSubImageLocked( mmesa, t, level, x, y,
width, height >> 1 );
y += ( height >> 1 );
height -= ( height >> 1 );
/* Each mipmap must be DWORD aligned.
*/
offset &= ~0x03;
}
length = dwords * 4;
/* Fill in the secondary buffer with properly converted texels
* from the mesa buffer. */
/* FIXME: the sync for direct copy reduces speed.. */
if(t->heap == MGA_CARD_HEAP ) {
mgaGetILoadBufferLocked( mmesa );
mgaConvertTexture( (GLuint *)mmesa->iload_buffer->address,
texelBytes, image, x, y, width, height );
if(length < 64) length = 64;
/* Copy the texture from system memory to a memory space that can be
* directly used by the hardware for texturing.
*/
if (0)
fprintf(stderr, "TexelBytes : %d, offset: %d, length : %d\n",
texelBytes,
mmesa->mgaScreen->textureOffset[t->heap] +
offset +
y * width * 4/texelsPerDword,
length);
texelBytes = texImage->TexFormat->TexelBytes;
length = texImage->Width * texImage->Height * texelBytes;
if ( t->base.heap->heapId == MGA_CARD_HEAP ) {
unsigned tex_offset = 0;
unsigned to_copy;
mgaFireILoadLocked( mmesa,
mmesa->mgaScreen->textureOffset[t->heap] +
offset +
y * width * 4/texelsPerDword,
length);
/* We may not be able to upload the entire texture in one batch due to
* register limits or dma buffer limits. Split the copy up into maximum
* sized chunks.
*/
offset += mmesa->mgaScreen->textureOffset[ t->base.heap->heapId ];
while ( length != 0 ) {
mgaGetILoadBufferLocked( mmesa );
/* The kernel ILOAD ioctl requires that the lenght be an even multiple
* of MGA_ILOAD_ALIGN.
*/
length = ((length) + MGA_ILOAD_MASK) & ~MGA_ILOAD_MASK;
to_copy = MIN2( length, MGA_BUFFER_SIZE );
(void) memcpy( mmesa->iload_buffer->address,
(GLubyte *) texImage->Data + tex_offset, to_copy );
if ( MGA_DEBUG & DEBUG_VERBOSE_TEXTURE )
fprintf(stderr, "[%s:%d] address/size = 0x%08lx/%d\n",
__FILE__, __LINE__,
(long) (offset + tex_offset),
to_copy );
mgaFireILoadLocked( mmesa, offset + tex_offset, to_copy );
tex_offset += to_copy;
length -= to_copy;
}
} else {
/* FIXME: the sync for direct copy reduces speed.. */
/* This works, is slower for uploads to card space and needs
* additional synchronization with the dma stream.
*/
UPDATE_LOCK(mmesa, DRM_LOCK_FLUSH | DRM_LOCK_QUIESCENT);
mgaConvertTexture( (GLuint *)
(mmesa->mgaScreen->texVirtual[t->heap] +
offset +
y * width * 4/texelsPerDword),
texelBytes, image, x, y, width, height );
memcpy( mmesa->mgaScreen->texVirtual[t->base.heap->heapId] + offset,
texImage->Data, length );
if ( MGA_DEBUG & DEBUG_VERBOSE_TEXTURE )
fprintf(stderr, "[%s:%d] address/size = 0x%08lx/%d\n",
__FILE__, __LINE__,
(long) (mmesa->mgaScreen->texVirtual[t->base.heap->heapId]
+ offset),
length);
}
}
static void mgaUploadTexLevel( mgaContextPtr mmesa,
mgaTextureObjectPtr t,
int l )
{
mgaUploadSubImageLocked( mmesa,
t,
l,
0, 0,
t->tObj->Image[l]->Width,
t->tObj->Image[l]->Height);
}
#if 0
static void mgaMigrateTexture( mgaContextPtr mmesa, mgaTextureObjectPtr t )
{
/* NOT DONE */
}
#endif
static int mgaChooseTexHeap( mgaContextPtr mmesa, mgaTextureObjectPtr t )
{
int freeagp, freecard;
int fitincard, fitinagp;
int totalcard, totalagp;
TMemBlock *b;
totalcard = totalagp = fitincard = fitinagp = freeagp = freecard = 0;
b = mmesa->texHeap[0];
while(b)
{
totalcard += b->size;
if(b->free) if(t->totalSize <= b->size)fitincard = 1;
b = b->next;
}
b = mmesa->texHeap[1];
while(b)
{
totalagp += b->size;
if(b->free) if(t->totalSize <= b->size)fitinagp = 1;
b = b->next;
}
if(fitincard)return 0;
if(fitinagp)return 1;
if(totalcard && totalagp)
{
int ages;
int ratio = (totalcard > totalagp) ? totalcard / totalagp : totalagp / totalcard;
ages = mmesa->sarea->texAge[0] + mmesa->sarea->texAge[1];
if( (ages % ratio) == 0)return totalcard > totalagp ? 1 : 0;
else return totalcard > totalagp ? 0 : 1;
}
if(totalagp) return 1;
return 0;
}
/**
* Upload the texture images associated with texture \a t. This might
* require the allocation of texture memory.
*
* \param mmesa Context pointer
* \param t Texture to be uploaded
*/
int mgaUploadTexImages( mgaContextPtr mmesa, mgaTextureObjectPtr t )
{
int heap;
int i;
int ofs;
heap = t->heap = mgaChooseTexHeap( mmesa, t );
/* Do we need to eject LRU texture objects?
*/
if (!t->MemBlock) {
while (1)
{
mgaTextureObjectPtr tmp = mmesa->TexObjList[heap].prev;
if ( (t == NULL) || (t->base.totalSize == 0) )
return 0;
t->MemBlock = mmAllocMem( mmesa->texHeap[heap],
t->totalSize,
6, 0 );
if (t->MemBlock)
break;
LOCK_HARDWARE( mmesa );
if (mmesa->TexObjList[heap].prev->bound) {
fprintf(stderr, "Hit bound texture in upload\n");
return -1;
}
if (t->base.memBlock == NULL ) {
int heap;
if (mmesa->TexObjList[heap].prev ==
&(mmesa->TexObjList[heap]))
{
fprintf(stderr, "Failed to upload texture, sz %d\n", t->totalSize);
mmDumpMemInfo( mmesa->texHeap[heap] );
return -1;
}
mgaDestroyTexObj( mmesa, tmp );
heap = driAllocateTexture( mmesa->texture_heaps, mmesa->nr_heaps,
(driTextureObject *) t );
if ( heap == -1 ) {
UNLOCK_HARDWARE( mmesa );
return -1;
}
ofs = t->MemBlock->ofs
+ mmesa->mgaScreen->textureOffset[heap]
;
ofs = mmesa->mgaScreen->textureOffset[ heap ]
+ t->base.memBlock->ofs;
t->setup.texorg = ofs;
t->setup.texorg1 = ofs + t->offsets[1];
t->setup.texorg2 = ofs + t->offsets[2];
t->setup.texorg3 = ofs + t->offsets[3];
t->setup.texorg4 = ofs + t->offsets[4];
if ( MGA_IS_G200(mmesa) ) {
t->setup.texorg = ofs;
t->setup.texorg1 = ofs + t->offsets[1];
t->setup.texorg2 = ofs + t->offsets[2];
t->setup.texorg3 = ofs + t->offsets[3];
t->setup.texorg4 = ofs + t->offsets[4];
}
else {
t->setup.texorg = ofs | TO_texorgoffsetsel;
t->setup.texorg1 = t->offsets[1];
t->setup.texorg2 = 0;
t->setup.texorg3 = 0;
t->setup.texorg4 = 0;
}
mmesa->dirty |= MGA_UPLOAD_CONTEXT;
}
/* Let the world know we've used this memory recently.
*/
mgaUpdateTexLRU( mmesa, t );
driUpdateTextureLRU( (driTextureObject *) t );
if (MGA_DEBUG&DEBUG_VERBOSE_LRU)
fprintf(stderr, "dispatch age: %d age freed memory: %d\n",
if (MGA_DEBUG&DEBUG_VERBOSE_TEXTURE)
fprintf(stderr, "[%s:%d] dispatch age: %d age freed memory: %d\n",
__FILE__, __LINE__,
GET_DISPATCH_AGE(mmesa), mmesa->dirtyAge);
if (mmesa->dirtyAge >= GET_DISPATCH_AGE(mmesa))
mgaWaitAgeLocked( mmesa, mmesa->dirtyAge );
if (t->dirty_images) {
if (MGA_DEBUG&DEBUG_VERBOSE_LRU)
fprintf(stderr, "*");
if (t->base.dirty_images[0]) {
const int numLevels = t->base.lastLevel - t->base.firstLevel + 1;
for (i = 0 ; i <= t->lastLevel ; i++)
if (t->dirty_images & (1<<i))
mgaUploadTexLevel( mmesa, t, i );
if (MGA_DEBUG&DEBUG_VERBOSE_TEXTURE)
fprintf(stderr, "[%s:%d] dirty_images[0] = 0x%04x\n",
__FILE__, __LINE__, t->base.dirty_images[0] );
for (i = 0 ; i < numLevels ; i++) {
if ( (t->base.dirty_images[0] & (1U << i)) != 0 ) {
mgaUploadSubImage( mmesa, t, i );
}
}
t->base.dirty_images[0] = 0;
}
t->dirty_images = 0;
UNLOCK_HARDWARE( mmesa );
return 0;
}

View File

@ -26,9 +26,6 @@
*/
/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgatris.c,v 1.10 2002/10/30 12:51:36 alanh Exp $ */
#include <stdio.h>
#include <math.h>
#include "mtypes.h"
#include "macros.h"
#include "colormac.h"
@ -676,15 +673,6 @@ static void mgaFastRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
/**********************************************************************/
#define _MGA_NEW_RENDERSTATE (_DD_NEW_LINE_STIPPLE | \
_DD_NEW_TRI_UNFILLED | \
_DD_NEW_TRI_LIGHT_TWOSIDE | \
_DD_NEW_TRI_OFFSET | \
_DD_NEW_TRI_STIPPLE | \
_NEW_POLYGONSTIPPLE)
#define POINT_FALLBACK (DD_POINT_SMOOTH)
#define LINE_FALLBACK (DD_LINE_SMOOTH | DD_LINE_STIPPLE)
#define TRI_FALLBACK (DD_TRI_SMOOTH | DD_TRI_UNFILLED)
@ -693,7 +681,7 @@ static void mgaFastRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
#define ANY_RASTER_FLAGS (DD_FLATSHADE|DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET| \
DD_TRI_UNFILLED)
static void mgaChooseRenderState(GLcontext *ctx)
void mgaChooseRenderState(GLcontext *ctx)
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
mgaContextPtr mmesa = MGA_CONTEXT(ctx);
@ -759,36 +747,6 @@ static void mgaChooseRenderState(GLcontext *ctx)
/**********************************************************************/
static void mgaRunPipeline( GLcontext *ctx )
{
mgaContextPtr mmesa = MGA_CONTEXT(ctx);
if (mmesa->new_state) {
mgaDDUpdateHwState( ctx );
}
if (!mmesa->Fallback && mmesa->new_gl_state) {
if (mmesa->new_gl_state & _MGA_NEW_RASTERSETUP)
mgaChooseVertexState( ctx );
if (mmesa->new_gl_state & _MGA_NEW_RENDERSTATE)
mgaChooseRenderState( ctx );
mmesa->new_gl_state = 0;
/* Circularity: mgaDDUpdateHwState can affect mmesa->Fallback,
* but mgaChooseVertexState can affect mmesa->new_state. Hence
* the second check. (Fix this...)
*/
if (mmesa->new_state) {
mgaDDUpdateHwState( ctx );
}
}
_tnl_run_pipeline( ctx );
}
static GLenum reduced_prim[GL_POLYGON+1] = {
GL_POINTS,
GL_LINES,
@ -812,10 +770,14 @@ void mgaRasterPrimitive( GLcontext *ctx, GLenum prim, GLuint hwprim )
mgaContextPtr mmesa = MGA_CONTEXT( ctx );
FLUSH_BATCH( mmesa );
/* Update culling */
if (mmesa->raster_primitive != prim)
mmesa->dirty |= MGA_UPLOAD_CONTEXT;
mmesa->raster_primitive = prim;
/* mmesa->hw_primitive = hwprim; */
mmesa->hw_primitive = MGA_WA_TRIANGLES; /* disable mgarender.c for now */
mgaUpdateCull(ctx);
if (ctx->Polygon.StippleFlag && mmesa->haveHwStipple)
{
@ -864,6 +826,28 @@ static void mgaRenderFinish( GLcontext *ctx )
/* Manage total rasterization fallbacks */
/**********************************************************************/
static const char * const fallbackStrings[] = {
"Texture mode",
"glDrawBuffer(GL_FRONT_AND_BACK)",
"read buffer",
"LogicOp != GL_COPY",
"glRenderMode(selection or feedback)",
"No hardware stencil",
"glDepthFunc( GL_NEVER )",
"Mixing GL_CLAMP_TO_EDGE and GL_CLAMP"
};
static const char *getFallbackString(GLuint bit)
{
int i = 0;
while (bit > 1) {
i++;
bit >>= 1;
}
return fallbackStrings[i];
}
void mgaFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
@ -876,6 +860,10 @@ void mgaFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
FLUSH_BATCH(mmesa);
_swsetup_Wakeup( ctx );
mmesa->RenderIndex = ~0;
if (MGA_DEBUG & DEBUG_VERBOSE_FALLBACK) {
fprintf(stderr, "MGA begin rasterization fallback: 0x%x %s\n",
bit, getFallbackString(bit));
}
}
}
else {
@ -886,8 +874,12 @@ void mgaFallback( GLcontext *ctx, GLuint bit, GLboolean mode )
tnl->Driver.Render.PrimitiveNotify = mgaRenderPrimitive;
tnl->Driver.Render.Finish = mgaRenderFinish;
tnl->Driver.Render.BuildVertices = mgaBuildVertices;
mmesa->new_gl_state |= (_MGA_NEW_RENDERSTATE |
_MGA_NEW_RASTERSETUP);
mmesa->NewGLState |= (_MGA_NEW_RENDERSTATE |
_MGA_NEW_RASTERSETUP);
if (MGA_DEBUG & DEBUG_VERBOSE_FALLBACK) {
fprintf(stderr, "MGA end rasterization fallback: 0x%x %s\n",
bit, getFallbackString(bit));
}
}
}
}
@ -905,7 +897,6 @@ void mgaDDInitTriFuncs( GLcontext *ctx )
mmesa->RenderIndex = ~0;
tnl->Driver.RunPipeline = mgaRunPipeline;
tnl->Driver.Render.Start = mgaCheckTexSizes;
tnl->Driver.Render.Finish = mgaRenderFinish;
tnl->Driver.Render.PrimitiveNotify = mgaRenderPrimitive;

View File

@ -32,12 +32,17 @@
#include "mtypes.h"
extern void mgaDDInitTriFuncs( GLcontext *ctx );
extern void mgaChooseRenderState( GLcontext *ctx );
extern void mgaRasterPrimitive( GLcontext *ctx, GLenum prim, GLuint hwprim );
extern void mgaFallback( GLcontext *ctx, GLuint bit, GLboolean mode );
#define FALLBACK( ctx, bit, mode ) mgaFallback( ctx, bit, mode )
#define _MGA_NEW_RENDERSTATE (_DD_NEW_LINE_STIPPLE | \
_DD_NEW_TRI_UNFILLED | \
_DD_NEW_TRI_LIGHT_TWOSIDE | \
_DD_NEW_TRI_OFFSET | \
_DD_NEW_TRI_STIPPLE | \
_NEW_POLYGONSTIPPLE)
#endif

View File

@ -24,7 +24,7 @@
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgavb.c,v 1.15 2003/03/26 20:43:49 tsi Exp $ */
/* $XFree86: xc/lib/GL/mesa/src/drv/mga/mgavb.c,v 1.14 2002/10/30 12:51:36 alanh Exp $ */
#include "mgacontext.h"
#include "mgavb.h"
@ -34,18 +34,14 @@
#include "glheader.h"
#include "mtypes.h"
/*#include "mem.h" */
#include "imports.h"
#include "macros.h"
#include "colormac.h"
/*#include "mmath.h"*/
#include "tnl/t_context.h"
#include "swrast_setup/swrast_setup.h"
#include "swrast/swrast.h"
#include <stdio.h>
#include <stdlib.h>
#define MGA_TEX1_BIT 0x1
#define MGA_TEX0_BIT 0x2
@ -93,7 +89,7 @@ static struct {
#define GET_VIEWPORT_MAT() mmesa->hw_viewport
#define GET_TEXSOURCE(n) mmesa->tmu_source[n]
#define GET_VERTEX_FORMAT() mmesa->vertex_format
#define GET_VERTEX_STORE() ((GLubyte *)mmesa->verts)
#define GET_VERTEX_STORE() mmesa->verts
#define GET_VERTEX_STRIDE_SHIFT() mmesa->vertex_stride_shift
#define GET_UBYTE_COLOR_STORE() &mmesa->UbyteColor
#define GET_UBYTE_SPEC_COLOR_STORE() &mmesa->UbyteSecondaryColor
@ -407,15 +403,18 @@ void mgaChooseVertexState( GLcontext *ctx )
if (ctx->Fog.Enabled)
ind |= MGA_FOG_BIT;
if (ctx->Texture.Unit[1]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT)) {
if (ctx->Texture.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT)) {
if (ctx->Texture._EnabledUnits & 0x2) {
/* unit 1 enabled */
if (ctx->Texture._EnabledUnits & 0x1) {
/* unit 0 enabled */
ind |= MGA_TEX1_BIT|MGA_TEX0_BIT;
}
else {
ind |= MGA_TEX0_BIT;
}
}
else if (ctx->Texture.Unit[0]._ReallyEnabled & (TEXTURE_1D_BIT|TEXTURE_2D_BIT)) {
else if (ctx->Texture._EnabledUnits & 0x1) {
/* unit 0 enabled */
ind |= MGA_TEX0_BIT;
}
@ -431,7 +430,6 @@ void mgaChooseVertexState( GLcontext *ctx )
if (setup_tab[ind].vertex_format != mmesa->vertex_format) {
FLUSH_BATCH(mmesa);
mmesa->new_state |= MGA_NEW_WARP;
mmesa->dirty |= MGA_UPLOAD_PIPE;
mmesa->vertex_format = setup_tab[ind].vertex_format;
mmesa->vertex_size = setup_tab[ind].vertex_size;
@ -458,7 +456,7 @@ void mgaInitVB( GLcontext *ctx )
mgaContextPtr mmesa = MGA_CONTEXT(ctx);
GLuint size = TNL_CONTEXT(ctx)->vb.Size;
mmesa->verts = (char *)ALIGN_MALLOC(size * sizeof(mgaVertex), 32);
mmesa->verts = ALIGN_MALLOC(size * sizeof(mgaVertex), 32);
{
static int firsttime = 1;
@ -468,7 +466,6 @@ void mgaInitVB( GLcontext *ctx )
}
}
mmesa->new_state |= MGA_NEW_WARP;
mmesa->dirty |= MGA_UPLOAD_PIPE;
mmesa->vertex_format = setup_tab[0].vertex_format;
mmesa->vertex_size = setup_tab[0].vertex_size;

View File

@ -146,7 +146,7 @@ typedef struct {
typedef struct {
int param;
int *value;
void *value;
} drmMGAGetParam;
#endif

View File

@ -0,0 +1,116 @@
# $Id: Makefile.X11,v 1.1 2003/08/22 20:11:44 brianp Exp $
# Mesa 3-D graphics library
# Version: 5.0
# Copyright (C) 1995-2002 Brian Paul
TOP = ../../../../..
default: linux-solo
SHARED_INCLUDES = $(INCLUDE_DIRS) -I. -I../common -Iserver
MINIGLX_INCLUDES = -I$(TOP)/src/glx/mini
DEFINES += \
-D_HAVE_SWRAST=1 \
-D_HAVE_SWTNL=1 \
-D_HAVE_SANITY=1 \
-D_HAVE_CODEGEN=1 \
-D_HAVE_LIGHTING=1 \
-D_HAVE_TEXGEN=1 \
-D_HAVE_USERCLIP=1 \
-DGLX_DIRECT_RENDERING
MINIGLX_SOURCES = server/r128_dri.c
DRIVER_SOURCES = \
r128_context.c \
r128_lock.c \
r128_state.c \
r128_texstate.c \
r128_dd.c \
r128_screen.c \
r128_tex.c \
r128_tris.c \
r128_ioctl.c \
r128_span.c \
r128_texmem.c \
r128_vb.c \
../common/mm.c \
../common/utils.c \
../common/texmem.c \
../common/vblank.c
INCLUDES = $(MINIGLX_INCLUDES) \
$(SHARED_INCLUDES)
C_SOURCES = $(DRIVER_SOURCES) \
$(MINIGLX_SOURCES)
MESA_MODULES = $(TOP)/src/mesa/mesa.a
ifeq ($(WINDOW_SYSTEM),dri)
WINOBJ=$(MESABUILDDIR)/dri/dri.a
WINLIB=
else
WINOBJ=
WINLIB=-L$(MESA)/src/glx/mini
endif
ASM_SOURCES =
OBJECTS = $(C_SOURCES:.c=.o) \
$(ASM_SOURCES:.S=.o)
### Include directories
INCLUDE_DIRS = \
-I$(TOP)/include \
-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/swrast \
-I$(TOP)/src/mesa/swrast_setup
##### RULES #####
.c.o:
$(CC) -c $(SHARED_INCLUDES) $(MINIGLX_INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
.S.o:
$(CC) -c $(SHARED_INCLUDES) $(MINIGLX_INCLUDES) $(CFLAGS) $(DEFINES) $< -o $@
##### TARGETS #####
targets: depend r128_dri.so
r128_dri.so: $(OBJECTS) $(MESA_MODULES) $(WINOBJ) Makefile.X11
rm -f $@ && gcc -o $@ -shared $(OBJECTS) $(MESA_MODULES) $(WINOBJ) $(WINLIB) -lc $(GL_LIB_DEPS)
rm -f $(TOP)/lib/r128_dri.so && \
install r128_dri.so $(TOP)/lib/r128_dri.so
# Run 'make -f Makefile.X11 dep' to update the dependencies if you change
# what's included by any source file.
depend: $(C_SOURCES) $(ASM_SOURCES)
makedepend -fdepend -Y $(SHARED_INCLUDES) $(MINIGLX_INCLUDES) \
$(C_SOURCES) $(ASM_SOURCES)
# Emacs tags
tags:
etags `find . -name \*.[ch]` `find ../include`
# Remove .o and backup files
clean:
-rm -f *.o */*.o *~ *.o *~ *.so server/*.o
include $(TOP)/Make-config
include depend

View File

@ -0,0 +1,335 @@
/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_context.c,v 1.8 2002/10/30 12:51:38 alanh Exp $ */
/**************************************************************************
Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
Cedar Park, Texas.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Kevin E. Martin <martin@valinux.com>
* Gareth Hughes <gareth@valinux.com>
*
*/
#include "glheader.h"
#include "context.h"
#include "simple_list.h"
#include "imports.h"
#include "matrix.h"
#include "extensions.h"
#include "swrast/swrast.h"
#include "swrast_setup/swrast_setup.h"
#include "array_cache/acache.h"
#include "tnl/tnl.h"
#include "tnl/t_pipeline.h"
#include "r128_context.h"
#include "r128_ioctl.h"
#include "r128_dd.h"
#include "r128_state.h"
#include "r128_span.h"
#include "r128_tex.h"
#include "r128_tris.h"
#include "r128_vb.h"
#include "vblank.h"
#include "utils.h"
#include "texmem.h"
#ifndef R128_DEBUG
int R128_DEBUG = 0;
#endif
static const char * const card_extensions[] =
{
"GL_ARB_multitexture",
"GL_ARB_texture_env_add",
"GL_ARB_texture_mirrored_repeat",
"GL_EXT_texture_edge_clamp",
"GL_EXT_texture_env_add",
"GL_IBM_texture_mirrored_repeat",
"GL_SGIS_generate_mipmap",
"GL_SGIS_texture_edge_clamp",
NULL
};
static const struct dri_debug_control debug_control[] =
{
{ "ioctl", DEBUG_VERBOSE_IOCTL },
{ "verb", DEBUG_VERBOSE_MSG },
{ "dri", DEBUG_VERBOSE_DRI },
{ "2d", DEBUG_VERBOSE_2D },
{ "sync", DEBUG_ALWAYS_SYNC },
{ "api", DEBUG_VERBOSE_API },
{ NULL, 0 }
};
/* Create the device specific context.
*/
GLboolean r128CreateContext( const __GLcontextModes *glVisual,
__DRIcontextPrivate *driContextPriv,
void *sharedContextPrivate )
{
GLcontext *ctx, *shareCtx;
__DRIscreenPrivate *sPriv = driContextPriv->driScreenPriv;
r128ContextPtr rmesa;
r128ScreenPtr r128scrn;
int i;
/* Allocate the r128 context */
rmesa = (r128ContextPtr) CALLOC( sizeof(*rmesa) );
if ( !rmesa )
return GL_FALSE;
/* Allocate the Mesa context */
if (sharedContextPrivate)
shareCtx = ((r128ContextPtr) sharedContextPrivate)->glCtx;
else
shareCtx = NULL;
rmesa->glCtx = _mesa_create_context(glVisual, shareCtx, (void *) rmesa, GL_TRUE);
if (!rmesa->glCtx) {
FREE(rmesa);
return GL_FALSE;
}
driContextPriv->driverPrivate = rmesa;
ctx = rmesa->glCtx;
rmesa->driContext = driContextPriv;
rmesa->driScreen = sPriv;
rmesa->driDrawable = NULL;
rmesa->hHWContext = driContextPriv->hHWContext;
rmesa->driHwLock = &sPriv->pSAREA->lock;
rmesa->driFd = sPriv->fd;
r128scrn = rmesa->r128Screen = (r128ScreenPtr)(sPriv->private);
rmesa->sarea = (R128SAREAPrivPtr)((char *)sPriv->pSAREA +
r128scrn->sarea_priv_offset);
rmesa->CurrentTexObj[0] = NULL;
rmesa->CurrentTexObj[1] = NULL;
(void) memset( rmesa->texture_heaps, 0, sizeof( rmesa->texture_heaps ) );
make_empty_list( & rmesa->swapped );
rmesa->nr_heaps = r128scrn->numTexHeaps;
for ( i = 0 ; i < rmesa->nr_heaps ; i++ ) {
rmesa->texture_heaps[i] = driCreateTextureHeap( i, rmesa,
r128scrn->texSize[i],
12,
R128_NR_TEX_REGIONS,
rmesa->sarea->texList[i],
& rmesa->sarea->texAge[i],
& rmesa->swapped,
sizeof( r128TexObj ),
(destroy_texture_object_t *) r128DestroyTexObj );
driSetTextureSwapCounterLocation( rmesa->texture_heaps[i],
& rmesa->c_textureSwaps );
}
rmesa->RenderIndex = -1; /* Impossible value */
rmesa->vert_buf = NULL;
rmesa->num_verts = 0;
/* Set the maximum texture size small enough that we can guarentee that
* all texture units can bind a maximal texture and have them both in
* texturable memory at once.
*/
ctx->Const.MaxTextureUnits = 2;
driCalculateMaxTextureLevels( rmesa->texture_heaps,
rmesa->nr_heaps,
& ctx->Const,
4,
10, /* max 2D texture size is 1024x1024 */
0, /* 3D textures unsupported. */
0, /* cube textures unsupported. */
0, /* texture rectangles unsupported. */
11,
GL_FALSE );
/* No wide points.
*/
ctx->Const.MinPointSize = 1.0;
ctx->Const.MinPointSizeAA = 1.0;
ctx->Const.MaxPointSize = 1.0;
ctx->Const.MaxPointSizeAA = 1.0;
/* No wide lines.
*/
ctx->Const.MinLineWidth = 1.0;
ctx->Const.MinLineWidthAA = 1.0;
ctx->Const.MaxLineWidth = 1.0;
ctx->Const.MaxLineWidthAA = 1.0;
ctx->Const.LineWidthGranularity = 1.0;
#if ENABLE_PERF_BOXES
rmesa->boxes = (getenv( "LIBGL_PERFORMANCE_BOXES" ) != NULL);
#endif
/* Initialize the software rasterizer and helper modules.
*/
_swrast_CreateContext( ctx );
_ac_CreateContext( ctx );
_tnl_CreateContext( ctx );
_swsetup_CreateContext( ctx );
/* Install the customized pipeline:
*/
/* _tnl_destroy_pipeline( ctx ); */
/* _tnl_install_pipeline( ctx, r128_pipeline ); */
/* Configure swrast to match hardware characteristics:
*/
_swrast_allow_pixel_fog( ctx, GL_FALSE );
_swrast_allow_vertex_fog( ctx, GL_TRUE );
driInitExtensions( ctx, card_extensions, GL_TRUE );
if (sPriv->drmMinor >= 4)
_mesa_enable_extension( ctx, "GL_MESA_ycbcr_texture" );
r128InitVB( ctx );
r128InitTriFuncs( ctx );
r128DDInitDriverFuncs( ctx );
r128DDInitIoctlFuncs( ctx );
r128DDInitStateFuncs( ctx );
r128DDInitSpanFuncs( ctx );
r128DDInitTextureFuncs( ctx );
r128DDInitState( rmesa );
rmesa->do_irqs = (rmesa->r128Screen->irq && !getenv("R128_NO_IRQS"));
rmesa->vblank_flags = (rmesa->do_irqs)
? driGetDefaultVBlankFlags() : VBLANK_FLAG_NO_IRQ;
driContextPriv->driverPrivate = (void *)rmesa;
#if DO_DEBUG
R128_DEBUG = driParseDebugString( getenv( "R128_DEBUG" ),
debug_control );
#endif
return GL_TRUE;
}
/* Destroy the device specific context.
*/
void r128DestroyContext( __DRIcontextPrivate *driContextPriv )
{
r128ContextPtr rmesa = (r128ContextPtr) driContextPriv->driverPrivate;
assert(rmesa); /* should never be null */
if ( rmesa ) {
GLboolean release_texture_heaps;
release_texture_heaps = (rmesa->glCtx->Shared->RefCount == 1);
_swsetup_DestroyContext( rmesa->glCtx );
_tnl_DestroyContext( rmesa->glCtx );
_ac_DestroyContext( rmesa->glCtx );
_swrast_DestroyContext( rmesa->glCtx );
r128FreeVB( rmesa->glCtx );
/* free the Mesa context */
rmesa->glCtx->DriverCtx = NULL;
_mesa_destroy_context(rmesa->glCtx);
if ( release_texture_heaps ) {
/* This share group is about to go away, free our private
* texture object data.
*/
int i;
assert( is_empty_list( & rmesa->swapped ) );
for ( i = 0 ; i < rmesa->nr_heaps ; i++ ) {
driDestroyTextureHeap( rmesa->texture_heaps[ i ] );
rmesa->texture_heaps[ i ] = NULL;
}
}
FREE( rmesa );
}
#if 0
/* Use this to force shared object profiling. */
glx_fini_prof();
#endif
}
/* Force the context `c' to be the current context and associate with it
* buffer `b'.
*/
GLboolean
r128MakeCurrent( __DRIcontextPrivate *driContextPriv,
__DRIdrawablePrivate *driDrawPriv,
__DRIdrawablePrivate *driReadPriv )
{
if ( driContextPriv ) {
GET_CURRENT_CONTEXT(ctx);
r128ContextPtr oldR128Ctx = ctx ? R128_CONTEXT(ctx) : NULL;
r128ContextPtr newR128Ctx = (r128ContextPtr) driContextPriv->driverPrivate;
if ( newR128Ctx != oldR128Ctx ) {
newR128Ctx->new_state |= R128_NEW_CONTEXT;
newR128Ctx->dirty = R128_UPLOAD_ALL;
}
newR128Ctx->driDrawable = driDrawPriv;
_mesa_make_current2( newR128Ctx->glCtx,
(GLframebuffer *) driDrawPriv->driverPrivate,
(GLframebuffer *) driReadPriv->driverPrivate );
newR128Ctx->new_state |= R128_NEW_WINDOW | R128_NEW_CLIP;
if ( !newR128Ctx->glCtx->Viewport.Width ) {
_mesa_set_viewport(newR128Ctx->glCtx, 0, 0,
driDrawPriv->w, driDrawPriv->h);
}
} else {
_mesa_make_current( 0, 0 );
}
return GL_TRUE;
}
/* Force the context `c' to be unbound from its buffer.
*/
GLboolean
r128UnbindContext( __DRIcontextPrivate *driContextPriv )
{
return GL_TRUE;
}

View File

@ -0,0 +1,270 @@
/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_context.h,v 1.12 2002/12/16 16:18:52 dawes Exp $ */
/**************************************************************************
Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
Cedar Park, Texas.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Kevin E. Martin <martin@valinux.com>
* Gareth Hughes <gareth@valinux.com>
*
*/
#ifndef __R128_CONTEXT_H__
#define __R128_CONTEXT_H__
#ifdef GLX_DIRECT_RENDERING
#include "dri_util.h"
#include "xf86drm.h"
#include "r128_common.h"
#include "mtypes.h"
#include "r128_reg.h"
#include "texmem.h"
struct r128_context;
typedef struct r128_context r128ContextRec;
typedef struct r128_context *r128ContextPtr;
#include "r128_lock.h"
#include "r128_texobj.h"
#include "r128_screen.h"
/* Flags for what context state needs to be updated:
*/
#define R128_NEW_ALPHA 0x0001
#define R128_NEW_DEPTH 0x0002
#define R128_NEW_FOG 0x0004
#define R128_NEW_CLIP 0x0008
#define R128_NEW_CULL 0x0010
#define R128_NEW_MASKS 0x0020
#define R128_NEW_RENDER_NOT 0x0040
#define R128_NEW_WINDOW 0x0080
#define R128_NEW_CONTEXT 0x0100
#define R128_NEW_ALL 0x01ff
/* Flags for software fallback cases:
*/
#define R128_FALLBACK_TEXTURE 0x0001
#define R128_FALLBACK_DRAW_BUFFER 0x0002
#define R128_FALLBACK_READ_BUFFER 0x0004
#define R128_FALLBACK_STENCIL 0x0008
#define R128_FALLBACK_RENDER_MODE 0x0010
#define R128_FALLBACK_MULTIDRAW 0x0020
#define R128_FALLBACK_LOGICOP 0x0040
#define R128_FALLBACK_SEP_SPECULAR 0x0080
#define R128_FALLBACK_BLEND_EQ 0x0100
#define R128_FALLBACK_BLEND_FUNC 0x0200
/* Use the templated vertex format:
*/
#define TAG(x) r128##x
#include "tnl_dd/t_dd_vertex.h"
#undef TAG
/* Reasons why the GL_BLEND fallback mightn't work:
*/
#define R128_BLEND_ENV_COLOR 0x1
#define R128_BLEND_MULTITEX 0x2
/* Subpixel offsets for window coordinates (triangles):
*/
#define SUBPIXEL_X (0.0F)
#define SUBPIXEL_Y (0.125F)
typedef void (*r128_tri_func)( r128ContextPtr,
r128Vertex *,
r128Vertex *,
r128Vertex * );
typedef void (*r128_line_func)( r128ContextPtr,
r128Vertex *,
r128Vertex * );
typedef void (*r128_point_func)( r128ContextPtr,
r128Vertex * );
struct r128_context {
GLcontext *glCtx; /* Mesa context */
/* Driver and hardware state management
*/
GLuint new_state;
GLuint dirty; /* Hardware state to be updated */
r128_context_regs_t setup;
/* Temporaries for translating away float colors:
*/
struct gl_client_array UbyteColor;
struct gl_client_array UbyteSecondaryColor;
GLuint NewGLState;
GLuint Fallback;
GLuint SetupIndex;
GLuint SetupNewInputs;
GLuint RenderIndex;
GLfloat hw_viewport[16];
GLfloat depth_scale;
GLuint vertex_size;
GLuint vertex_stride_shift;
GLuint vertex_format;
GLuint num_verts;
GLubyte *verts;
CARD32 ClearColor; /* Color used to clear color buffer */
CARD32 ClearDepth; /* Value used to clear depth buffer */
CARD32 ClearStencil; /* Value used to clear stencil */
/* Map GL texture units onto hardware
*/
GLint multitex;
GLint tmu_source[2];
GLuint tex_combine[2];
GLuint blend_flags;
GLuint env_color;
/* Texture object bookkeeping
*/
unsigned nr_heaps;
driTexHeap * texture_heaps[ R128_NR_TEX_HEAPS ];
driTextureObject swapped;
r128TexObjPtr CurrentTexObj[2];
/* Fallback rasterization functions
*/
r128_point_func draw_point;
r128_line_func draw_line;
r128_tri_func draw_tri;
/* Vertex buffers
*/
drmBufPtr vert_buf;
GLuint hw_primitive;
GLenum render_primitive;
/* Page flipping
*/
GLuint doPageFlip;
/* Busy waiting
*/
GLuint do_irqs;
/* Drawable, cliprect and scissor information
*/
GLint drawOffset, drawPitch;
GLint readOffset, readPitch;
GLuint numClipRects; /* Cliprects for the draw buffer */
XF86DRIClipRectPtr pClipRects;
GLuint scissor;
XF86DRIClipRectRec ScissorRect; /* Current software scissor */
/* Mirrors of some DRI state
*/
__DRIcontextPrivate *driContext; /* DRI context */
__DRIscreenPrivate *driScreen; /* DRI screen */
__DRIdrawablePrivate *driDrawable; /* DRI drawable bound to this ctx */
unsigned int lastStamp; /* mirror driDrawable->lastStamp */
drmContext hHWContext;
drmLock *driHwLock;
int driFd;
r128ScreenPtr r128Screen; /* Screen private DRI data */
R128SAREAPrivPtr sarea; /* Private SAREA data */
/* Performance counters
*/
GLuint boxes; /* Draw performance boxes */
GLuint hardwareWentIdle;
GLuint c_clears;
GLuint c_drawWaits;
GLuint c_textureSwaps;
GLuint c_textureBytes;
GLuint c_vertexBuffers;
/* VBI
*/
GLuint vbl_seq;
GLuint vblank_flags;
};
#define R128_CONTEXT(ctx) ((r128ContextPtr)(ctx->DriverCtx))
#define R128_IS_PLAIN( rmesa ) \
(rmesa->r128Screen->chipset == R128_CARD_TYPE_R128)
#define R128_IS_PRO( rmesa ) \
(rmesa->r128Screen->chipset == R128_CARD_TYPE_R128_PRO)
#define R128_IS_MOBILITY( rmesa ) \
(rmesa->r128Screen->chipset == R128_CARD_TYPE_R128_MOBILITY)
extern GLboolean r128CreateContext( const __GLcontextModes *glVisual,
__DRIcontextPrivate *driContextPriv,
void *sharedContextPrivate );
extern void r128DestroyContext( __DRIcontextPrivate * );
extern GLboolean r128MakeCurrent( __DRIcontextPrivate *driContextPriv,
__DRIdrawablePrivate *driDrawPriv,
__DRIdrawablePrivate *driReadPriv );
extern GLboolean r128UnbindContext( __DRIcontextPrivate *driContextPriv );
/* ================================================================
* Debugging:
*/
#define DO_DEBUG 0
#define ENABLE_PERF_BOXES 0
#if DO_DEBUG
extern int R128_DEBUG;
#else
#define R128_DEBUG 0
#endif
#define DEBUG_ALWAYS_SYNC 0x01
#define DEBUG_VERBOSE_API 0x02
#define DEBUG_VERBOSE_MSG 0x04
#define DEBUG_VERBOSE_LRU 0x08
#define DEBUG_VERBOSE_DRI 0x10
#define DEBUG_VERBOSE_IOCTL 0x20
#define DEBUG_VERBOSE_2D 0x40
#endif
#endif /* __R128_CONTEXT_H__ */

View File

@ -0,0 +1,148 @@
/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_dd.c,v 1.15 2002/10/30 12:51:38 alanh Exp $ */
/**************************************************************************
Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
Cedar Park, Texas.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Gareth Hughes <gareth@valinux.com>
* Kevin E. Martin <martin@valinux.com>
*
*/
#include "r128_context.h"
#include "r128_ioctl.h"
#include "r128_state.h"
#include "r128_vb.h"
#include "r128_dd.h"
#include "context.h"
#include "utils.h"
#define DRIVER_DATE "20030328"
/* Return the width and height of the current color buffer.
*/
static void r128DDGetBufferSize( GLframebuffer *buffer,
GLuint *width, GLuint *height )
{
GET_CURRENT_CONTEXT(ctx);
r128ContextPtr rmesa = R128_CONTEXT(ctx);
LOCK_HARDWARE( rmesa );
*width = rmesa->driDrawable->w;
*height = rmesa->driDrawable->h;
UNLOCK_HARDWARE( rmesa );
}
/* Return various strings for glGetString().
*/
static const GLubyte *r128DDGetString( GLcontext *ctx, GLenum name )
{
r128ContextPtr rmesa = R128_CONTEXT(ctx);
static char buffer[128];
unsigned offset;
const char * card_name = "Rage 128";
GLuint agp_mode = rmesa->r128Screen->IsPCI ? 0 :
rmesa->r128Screen->AGPMode;
switch ( name ) {
case GL_VENDOR:
return (GLubyte *)"VA Linux Systems, Inc.";
case GL_RENDERER:
/* Select the spefic chipset.
*/
if ( R128_IS_PRO( rmesa ) ) {
card_name = "Rage 128 Pro";
}
else if ( R128_IS_MOBILITY( rmesa ) ) {
card_name = "Rage 128 Mobility";
}
offset = driGetRendererString( buffer, card_name, DRIVER_DATE,
agp_mode );
return (GLubyte *)buffer;
default:
return NULL;
}
}
/* Send all commands to the hardware. If vertex buffers or indirect
* buffers are in use, then we need to make sure they are sent to the
* hardware. All commands that are normally sent to the ring are
* already considered `flushed'.
*/
static void r128DDFlush( GLcontext *ctx )
{
r128ContextPtr rmesa = R128_CONTEXT(ctx);
FLUSH_BATCH( rmesa );
#if ENABLE_PERF_BOXES
if ( rmesa->boxes ) {
LOCK_HARDWARE( rmesa );
r128PerformanceBoxesLocked( rmesa );
UNLOCK_HARDWARE( rmesa );
}
/* Log the performance counters if necessary */
r128PerformanceCounters( rmesa );
#endif
}
/* Make sure all commands have been sent to the hardware and have
* completed processing.
*/
static void r128DDFinish( GLcontext *ctx )
{
r128ContextPtr rmesa = R128_CONTEXT(ctx);
#if ENABLE_PERF_BOXES
/* Bump the performance counter */
rmesa->c_drawWaits++;
#endif
r128DDFlush( ctx );
r128WaitForIdle( rmesa );
}
/* Initialize the driver's misc functions.
*/
void r128DDInitDriverFuncs( GLcontext *ctx )
{
ctx->Driver.GetBufferSize = r128DDGetBufferSize;
ctx->Driver.ResizeBuffers = _swrast_alloc_buffers;
ctx->Driver.GetString = r128DDGetString;
ctx->Driver.Finish = r128DDFinish;
ctx->Driver.Flush = r128DDFlush;
ctx->Driver.Error = NULL;
}

View File

@ -0,0 +1,44 @@
/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_dd.h,v 1.3 2001/01/08 01:07:20 martin Exp $ */
/**************************************************************************
Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
Cedar Park, Texas.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Gareth Hughes <gareth@valinux.com>
* Kevin E. Martin <martin@valinux.com>
*
*/
#ifndef __R128_DD_H__
#define __R128_DD_H__
#ifdef GLX_DIRECT_RENDERING
extern void r128DDInitDriverFuncs( GLcontext *ctx );
#endif
#endif

View File

@ -0,0 +1,812 @@
/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_ioctl.c,v 1.10 2002/12/16 16:18:53 dawes Exp $ */
/**************************************************************************
Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
Cedar Park, Texas.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Gareth Hughes <gareth@valinux.com>
*
*/
#include <errno.h>
#include "r128_context.h"
#include "r128_state.h"
#include "r128_ioctl.h"
#include "r128_macros.h"
#include "imports.h"
#include "macros.h"
#include "swrast/swrast.h"
#include "vblank.h"
#define R128_TIMEOUT 2048
#define R128_IDLE_RETRY 32
/* =============================================================
* Hardware vertex buffer handling
*/
/* Get a new VB from the pool of vertex buffers in AGP space.
*/
drmBufPtr r128GetBufferLocked( r128ContextPtr rmesa )
{
int fd = rmesa->r128Screen->driScreen->fd;
int index = 0;
int size = 0;
drmDMAReq dma;
drmBufPtr buf = NULL;
int to = 0;
int ret;
dma.context = rmesa->hHWContext;
dma.send_count = 0;
dma.send_list = NULL;
dma.send_sizes = NULL;
dma.flags = 0;
dma.request_count = 1;
dma.request_size = R128_BUFFER_SIZE;
dma.request_list = &index;
dma.request_sizes = &size;
dma.granted_count = 0;
while ( !buf && ( to++ < R128_TIMEOUT ) ) {
ret = drmDMA( fd, &dma );
if ( ret == 0 ) {
buf = &rmesa->r128Screen->buffers->list[index];
buf->used = 0;
#if ENABLE_PERF_BOXES
/* Bump the performance counter */
rmesa->c_vertexBuffers++;
#endif
return buf;
}
}
if ( !buf ) {
drmCommandNone( fd, DRM_R128_CCE_RESET);
UNLOCK_HARDWARE( rmesa );
fprintf( stderr, "Error: Could not get new VB... exiting\n" );
exit( -1 );
}
return buf;
}
void r128FlushVerticesLocked( r128ContextPtr rmesa )
{
XF86DRIClipRectPtr pbox = rmesa->pClipRects;
int nbox = rmesa->numClipRects;
drmBufPtr buffer = rmesa->vert_buf;
int count = rmesa->num_verts;
int prim = rmesa->hw_primitive;
int fd = rmesa->driScreen->fd;
drmR128Vertex vertex;
int i;
rmesa->num_verts = 0;
rmesa->vert_buf = NULL;
if ( !buffer )
return;
if ( rmesa->dirty & ~R128_UPLOAD_CLIPRECTS )
r128EmitHwStateLocked( rmesa );
if ( !nbox )
count = 0;
if ( nbox >= R128_NR_SAREA_CLIPRECTS )
rmesa->dirty |= R128_UPLOAD_CLIPRECTS;
if ( !count || !(rmesa->dirty & R128_UPLOAD_CLIPRECTS) )
{
if ( nbox < 3 ) {
rmesa->sarea->nbox = 0;
} else {
rmesa->sarea->nbox = nbox;
}
vertex.prim = prim;
vertex.idx = buffer->idx;
vertex.count = count;
vertex.discard = 1;
drmCommandWrite( fd, DRM_R128_VERTEX, &vertex, sizeof(drmR128Vertex) );
}
else
{
for ( i = 0 ; i < nbox ; ) {
int nr = MIN2( i + R128_NR_SAREA_CLIPRECTS, nbox );
XF86DRIClipRectPtr b = rmesa->sarea->boxes;
int discard = 0;
rmesa->sarea->nbox = nr - i;
for ( ; i < nr ; i++ ) {
*b++ = pbox[i];
}
/* Finished with the buffer?
*/
if ( nr == nbox ) {
discard = 1;
}
rmesa->sarea->dirty |= R128_UPLOAD_CLIPRECTS;
vertex.prim = prim;
vertex.idx = buffer->idx;
vertex.count = count;
vertex.discard = discard;
drmCommandWrite( fd, DRM_R128_VERTEX, &vertex, sizeof(drmR128Vertex) );
}
}
rmesa->dirty &= ~R128_UPLOAD_CLIPRECTS;
}
/* ================================================================
* Texture uploads
*/
void r128FireBlitLocked( r128ContextPtr rmesa, drmBufPtr buffer,
GLint offset, GLint pitch, GLint format,
GLint x, GLint y, GLint width, GLint height )
{
drmR128Blit blit;
GLint ret;
blit.idx = buffer->idx;
blit.offset = offset;
blit.pitch = pitch;
blit.format = format;
blit.x = x;
blit.y = y;
blit.width = width;
blit.height = height;
ret = drmCommandWrite( rmesa->driFd, DRM_R128_BLIT,
&blit, sizeof(drmR128Blit) );
if ( ret ) {
UNLOCK_HARDWARE( rmesa );
fprintf( stderr, "DRM_R128_BLIT: return = %d\n", ret );
exit( 1 );
}
}
/* ================================================================
* SwapBuffers with client-side throttling
*/
static void delay( void ) {
/* Prevent an optimizing compiler from removing a spin loop */
}
#define R128_MAX_OUTSTANDING 2
/* Throttle the frame rate -- only allow one pending swap buffers
* request at a time.
* GH: We probably don't want a timeout here, as we can wait as
* long as we want for a frame to complete. If it never does, then
* the card has locked.
*/
static int r128WaitForFrameCompletion( r128ContextPtr rmesa )
{
unsigned char *R128MMIO = rmesa->r128Screen->mmio.map;
CARD32 frame;
int i;
int wait = 0;
while ( 1 ) {
frame = INREG( R128_LAST_FRAME_REG );
if ( rmesa->sarea->last_frame - frame <= R128_MAX_OUTSTANDING ) {
break;
}
/* Spin in place a bit so we aren't hammering the register */
wait++;
for ( i = 0 ; i < 1024 ; i++ ) {
delay();
}
}
return wait;
}
/* Copy the back color buffer to the front color buffer.
*/
void r128CopyBuffer( const __DRIdrawablePrivate *dPriv )
{
r128ContextPtr rmesa;
GLint nbox, i, ret;
GLboolean missed_target;
assert(dPriv);
assert(dPriv->driContextPriv);
assert(dPriv->driContextPriv->driverPrivate);
rmesa = (r128ContextPtr) dPriv->driContextPriv->driverPrivate;
if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
fprintf( stderr, "\n********************************\n" );
fprintf( stderr, "\n%s( %p )\n\n",
__FUNCTION__, rmesa->glCtx );
fflush( stderr );
}
FLUSH_BATCH( rmesa );
LOCK_HARDWARE( rmesa );
/* Throttle the frame rate -- only allow one pending swap buffers
* request at a time.
*/
if ( !r128WaitForFrameCompletion( rmesa ) ) {
rmesa->hardwareWentIdle = 1;
} else {
rmesa->hardwareWentIdle = 0;
}
UNLOCK_HARDWARE( rmesa );
driWaitForVBlank( dPriv, &rmesa->vbl_seq, rmesa->vblank_flags, &missed_target );
LOCK_HARDWARE( rmesa );
nbox = dPriv->numClipRects; /* must be in locked region */
for ( i = 0 ; i < nbox ; ) {
GLint nr = MIN2( i + R128_NR_SAREA_CLIPRECTS , nbox );
XF86DRIClipRectPtr box = dPriv->pClipRects;
XF86DRIClipRectPtr b = rmesa->sarea->boxes;
GLint n = 0;
for ( ; i < nr ; i++ ) {
*b++ = *(XF86DRIClipRectRec *)&box[i];
n++;
}
rmesa->sarea->nbox = n;
ret = drmCommandNone( rmesa->driFd, DRM_R128_SWAP );
if ( ret ) {
UNLOCK_HARDWARE( rmesa );
fprintf( stderr, "DRM_R128_SWAP: return = %d\n", ret );
exit( 1 );
}
}
if ( R128_DEBUG & DEBUG_ALWAYS_SYNC ) {
i = 0;
do {
ret = drmCommandNone(rmesa->driFd, DRM_R128_CCE_IDLE);
} while ( ret && errno == EBUSY && i++ < R128_IDLE_RETRY );
}
UNLOCK_HARDWARE( rmesa );
rmesa->new_state |= R128_NEW_CONTEXT;
rmesa->dirty |= (R128_UPLOAD_CONTEXT |
R128_UPLOAD_MASKS |
R128_UPLOAD_CLIPRECTS);
#if ENABLE_PERF_BOXES
/* Log the performance counters if necessary */
r128PerformanceCounters( rmesa );
#endif
}
void r128PageFlip( const __DRIdrawablePrivate *dPriv )
{
r128ContextPtr rmesa;
GLint ret;
GLboolean missed_target;
assert(dPriv);
assert(dPriv->driContextPriv);
assert(dPriv->driContextPriv->driverPrivate);
rmesa = (r128ContextPtr) dPriv->driContextPriv->driverPrivate;
if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
fprintf( stderr, "\n%s( %p ): page=%d\n\n",
__FUNCTION__, rmesa->glCtx, rmesa->sarea->pfCurrentPage );
}
FLUSH_BATCH( rmesa );
LOCK_HARDWARE( rmesa );
/* Throttle the frame rate -- only allow one pending swap buffers
* request at a time.
*/
if ( !r128WaitForFrameCompletion( rmesa ) ) {
rmesa->hardwareWentIdle = 1;
} else {
rmesa->hardwareWentIdle = 0;
}
UNLOCK_HARDWARE( rmesa );
driWaitForVBlank( dPriv, &rmesa->vbl_seq, rmesa->vblank_flags, &missed_target );
LOCK_HARDWARE( rmesa );
/* The kernel will have been initialized to perform page flipping
* on a swapbuffers ioctl.
*/
ret = drmCommandNone( rmesa->driFd, DRM_R128_FLIP );
UNLOCK_HARDWARE( rmesa );
if ( ret ) {
fprintf( stderr, "DRM_R128_FLIP: return = %d\n", ret );
exit( 1 );
}
if ( rmesa->sarea->pfCurrentPage == 1 ) {
rmesa->drawOffset = rmesa->r128Screen->frontOffset;
rmesa->drawPitch = rmesa->r128Screen->frontPitch;
} else {
rmesa->drawOffset = rmesa->r128Screen->backOffset;
rmesa->drawPitch = rmesa->r128Screen->backPitch;
}
rmesa->setup.dst_pitch_offset_c = (((rmesa->drawPitch/8) << 21) |
(rmesa->drawOffset >> 5));
rmesa->new_state |= R128_NEW_WINDOW;
/* FIXME: Do we need this anymore? */
rmesa->new_state |= R128_NEW_CONTEXT;
rmesa->dirty |= (R128_UPLOAD_CONTEXT |
R128_UPLOAD_MASKS |
R128_UPLOAD_CLIPRECTS);
#if ENABLE_PERF_BOXES
/* Log the performance counters if necessary */
r128PerformanceCounters( rmesa );
#endif
}
/* ================================================================
* Buffer clear
*/
static void r128DDClear( GLcontext *ctx, GLbitfield mask, GLboolean all,
GLint cx, GLint cy, GLint cw, GLint ch )
{
r128ContextPtr rmesa = R128_CONTEXT(ctx);
__DRIdrawablePrivate *dPriv = rmesa->driDrawable;
drmR128Clear clear;
GLuint flags = 0;
GLint i;
GLint ret;
if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
fprintf( stderr, "%s:\n", __FUNCTION__ );
}
FLUSH_BATCH( rmesa );
/* The only state change we care about here is the RGBA colormask
* We'll just update that state, if needed. If we do more then
* there's some strange side-effects that the conformance tests find.
*/
if ( rmesa->new_state & R128_NEW_MASKS) {
const GLuint save_state = rmesa->new_state;
rmesa->new_state = R128_NEW_MASKS;
r128DDUpdateHWState( ctx );
rmesa->new_state = save_state & ~R128_NEW_MASKS;
}
if ( mask & DD_FRONT_LEFT_BIT ) {
flags |= DRM_R128_FRONT_BUFFER;
mask &= ~DD_FRONT_LEFT_BIT;
}
if ( mask & DD_BACK_LEFT_BIT ) {
flags |= DRM_R128_BACK_BUFFER;
mask &= ~DD_BACK_LEFT_BIT;
}
if ( ( mask & DD_DEPTH_BIT ) && ctx->Depth.Mask ) {
flags |= DRM_R128_DEPTH_BUFFER;
mask &= ~DD_DEPTH_BIT;
}
#if 0
/* FIXME: Add stencil support */
if ( mask & DD_STENCIL_BIT ) {
flags |= DRM_R128_DEPTH_BUFFER;
mask &= ~DD_STENCIL_BIT;
}
#endif
if ( flags ) {
/* Flip top to bottom */
cx += dPriv->x;
cy = dPriv->y + dPriv->h - cy - ch;
LOCK_HARDWARE( rmesa );
/* FIXME: Do we actually need this?
*/
if ( rmesa->dirty & ~R128_UPLOAD_CLIPRECTS ) {
r128EmitHwStateLocked( rmesa );
}
for ( i = 0 ; i < rmesa->numClipRects ; ) {
GLint nr = MIN2( i + R128_NR_SAREA_CLIPRECTS , rmesa->numClipRects );
XF86DRIClipRectPtr box = rmesa->pClipRects;
XF86DRIClipRectPtr b = rmesa->sarea->boxes;
GLint n = 0;
if ( !all ) {
for ( ; i < nr ; i++ ) {
GLint x = box[i].x1;
GLint y = box[i].y1;
GLint w = box[i].x2 - x;
GLint h = box[i].y2 - y;
if ( x < cx ) w -= cx - x, x = cx;
if ( y < cy ) h -= cy - y, y = cy;
if ( x + w > cx + cw ) w = cx + cw - x;
if ( y + h > cy + ch ) h = cy + ch - y;
if ( w <= 0 ) continue;
if ( h <= 0 ) continue;
b->x1 = x;
b->y1 = y;
b->x2 = x + w;
b->y2 = y + h;
b++;
n++;
}
} else {
for ( ; i < nr ; i++ ) {
*b++ = *(XF86DRIClipRectPtr)&box[i];
n++;
}
}
rmesa->sarea->nbox = n;
if ( R128_DEBUG & DEBUG_VERBOSE_IOCTL ) {
fprintf( stderr,
"DRM_R128_CLEAR: flag 0x%x color %x depth %x nbox %d\n",
flags,
(GLuint)rmesa->ClearColor,
(GLuint)rmesa->ClearDepth,
rmesa->sarea->nbox );
}
clear.flags = flags;
clear.clear_color = rmesa->ClearColor;
clear.clear_depth = rmesa->ClearDepth;
clear.color_mask = rmesa->setup.plane_3d_mask_c;
clear.depth_mask = ~0;
ret = drmCommandWrite( rmesa->driFd, DRM_R128_CLEAR,
&clear, sizeof(drmR128Clear) );
if ( ret ) {
UNLOCK_HARDWARE( rmesa );
fprintf( stderr, "DRM_R128_CLEAR: return = %d\n", ret );
exit( 1 );
}
}
UNLOCK_HARDWARE( rmesa );
rmesa->dirty |= R128_UPLOAD_CLIPRECTS;
}
if ( mask )
_swrast_Clear( ctx, mask, all, cx, cy, cw, ch );
}
/* ================================================================
* Depth spans, pixels
*/
void r128WriteDepthSpanLocked( r128ContextPtr rmesa,
GLuint n, GLint x, GLint y,
const GLdepth depth[],
const GLubyte mask[] )
{
XF86DRIClipRectPtr pbox = rmesa->pClipRects;
drmR128Depth d;
int nbox = rmesa->numClipRects;
int fd = rmesa->driScreen->fd;
int i;
if ( !nbox || !n ) {
return;
}
if ( nbox >= R128_NR_SAREA_CLIPRECTS ) {
rmesa->dirty |= R128_UPLOAD_CLIPRECTS;
}
if ( !(rmesa->dirty & R128_UPLOAD_CLIPRECTS) )
{
if ( nbox < 3 ) {
rmesa->sarea->nbox = 0;
} else {
rmesa->sarea->nbox = nbox;
}
d.func = DRM_R128_WRITE_SPAN;
d.n = n;
d.x = (int*)&x;
d.y = (int*)&y;
d.buffer = (unsigned int *)depth;
d.mask = (unsigned char *)mask;
drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(drmR128Depth));
}
else
{
for (i = 0 ; i < nbox ; ) {
int nr = MIN2( i + R128_NR_SAREA_CLIPRECTS, nbox );
XF86DRIClipRectPtr b = rmesa->sarea->boxes;
rmesa->sarea->nbox = nr - i;
for ( ; i < nr ; i++) {
*b++ = pbox[i];
}
rmesa->sarea->dirty |= R128_UPLOAD_CLIPRECTS;
d.func = DRM_R128_WRITE_SPAN;
d.n = n;
d.x = (int*)&x;
d.y = (int*)&y;
d.buffer = (unsigned int *)depth;
d.mask = (unsigned char *)mask;
drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(drmR128Depth));
}
}
rmesa->dirty &= ~R128_UPLOAD_CLIPRECTS;
}
void r128WriteDepthPixelsLocked( r128ContextPtr rmesa, GLuint n,
const GLint x[], const GLint y[],
const GLdepth depth[],
const GLubyte mask[] )
{
XF86DRIClipRectPtr pbox = rmesa->pClipRects;
drmR128Depth d;
int nbox = rmesa->numClipRects;
int fd = rmesa->driScreen->fd;
int i;
if ( !nbox || !n ) {
return;
}
if ( nbox >= R128_NR_SAREA_CLIPRECTS ) {
rmesa->dirty |= R128_UPLOAD_CLIPRECTS;
}
if ( !(rmesa->dirty & R128_UPLOAD_CLIPRECTS) )
{
if ( nbox < 3 ) {
rmesa->sarea->nbox = 0;
} else {
rmesa->sarea->nbox = nbox;
}
d.func = DRM_R128_WRITE_PIXELS;
d.n = n;
d.x = (int*)&x;
d.y = (int*)&y;
d.buffer = (unsigned int *)depth;
d.mask = (unsigned char *)mask;
drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(drmR128Depth));
}
else
{
for (i = 0 ; i < nbox ; ) {
int nr = MIN2( i + R128_NR_SAREA_CLIPRECTS, nbox );
XF86DRIClipRectPtr b = rmesa->sarea->boxes;
rmesa->sarea->nbox = nr - i;
for ( ; i < nr ; i++) {
*b++ = pbox[i];
}
rmesa->sarea->dirty |= R128_UPLOAD_CLIPRECTS;
d.func = DRM_R128_WRITE_PIXELS;
d.n = n;
d.x = (int*)&x;
d.y = (int*)&y;
d.buffer = (unsigned int *)depth;
d.mask = (unsigned char *)mask;
drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(drmR128Depth));
}
}
rmesa->dirty &= ~R128_UPLOAD_CLIPRECTS;
}
void r128ReadDepthSpanLocked( r128ContextPtr rmesa,
GLuint n, GLint x, GLint y )
{
XF86DRIClipRectPtr pbox = rmesa->pClipRects;
drmR128Depth d;
int nbox = rmesa->numClipRects;
int fd = rmesa->driScreen->fd;
int i;
if ( !nbox || !n ) {
return;
}
if ( nbox >= R128_NR_SAREA_CLIPRECTS ) {
rmesa->dirty |= R128_UPLOAD_CLIPRECTS;
}
if ( !(rmesa->dirty & R128_UPLOAD_CLIPRECTS) )
{
if ( nbox < 3 ) {
rmesa->sarea->nbox = 0;
} else {
rmesa->sarea->nbox = nbox;
}
d.func = DRM_R128_READ_SPAN;
d.n = n;
d.x = (int*)&x;
d.y = (int*)&y;
d.buffer = NULL;
d.mask = NULL;
drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(drmR128Depth));
}
else
{
for (i = 0 ; i < nbox ; ) {
int nr = MIN2( i + R128_NR_SAREA_CLIPRECTS, nbox );
XF86DRIClipRectPtr b = rmesa->sarea->boxes;
rmesa->sarea->nbox = nr - i;
for ( ; i < nr ; i++) {
*b++ = pbox[i];
}
rmesa->sarea->dirty |= R128_UPLOAD_CLIPRECTS;
d.func = DRM_R128_READ_SPAN;
d.n = n;
d.x = (int*)&x;
d.y = (int*)&y;
d.buffer = NULL;
d.mask = NULL;
drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(drmR128Depth));
}
}
rmesa->dirty &= ~R128_UPLOAD_CLIPRECTS;
}
void r128ReadDepthPixelsLocked( r128ContextPtr rmesa, GLuint n,
const GLint x[], const GLint y[] )
{
XF86DRIClipRectPtr pbox = rmesa->pClipRects;
drmR128Depth d;
int nbox = rmesa->numClipRects;
int fd = rmesa->driScreen->fd;
int i;
if ( !nbox || !n ) {
return;
}
if ( nbox >= R128_NR_SAREA_CLIPRECTS ) {
rmesa->dirty |= R128_UPLOAD_CLIPRECTS;
}
if ( !(rmesa->dirty & R128_UPLOAD_CLIPRECTS) )
{
if ( nbox < 3 ) {
rmesa->sarea->nbox = 0;
} else {
rmesa->sarea->nbox = nbox;
}
d.func = DRM_R128_READ_PIXELS;
d.n = n;
d.x = (int*)&x;
d.y = (int*)&y;
d.buffer = NULL;
d.mask = NULL;
drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(drmR128Depth));
}
else
{
for (i = 0 ; i < nbox ; ) {
int nr = MIN2( i + R128_NR_SAREA_CLIPRECTS, nbox );
XF86DRIClipRectPtr b = rmesa->sarea->boxes;
rmesa->sarea->nbox = nr - i;
for ( ; i < nr ; i++) {
*b++ = pbox[i];
}
rmesa->sarea->dirty |= R128_UPLOAD_CLIPRECTS;
d.func = DRM_R128_READ_PIXELS;
d.n = n;
d.x = (int*)&x;
d.y = (int*)&y;
d.buffer = NULL;
d.mask = NULL;
drmCommandWrite( fd, DRM_R128_DEPTH, &d, sizeof(drmR128Depth));
}
}
rmesa->dirty &= ~R128_UPLOAD_CLIPRECTS;
}
void r128WaitForIdleLocked( r128ContextPtr rmesa )
{
int fd = rmesa->r128Screen->driScreen->fd;
int to = 0;
int ret, i;
do {
i = 0;
do {
ret = drmCommandNone( fd, DRM_R128_CCE_IDLE);
} while ( ret && errno == EBUSY && i++ < R128_IDLE_RETRY );
} while ( ( ret == -EBUSY ) && ( to++ < R128_TIMEOUT ) );
if ( ret < 0 ) {
drmCommandNone( fd, DRM_R128_CCE_RESET);
UNLOCK_HARDWARE( rmesa );
fprintf( stderr, "Error: Rage 128 timed out... exiting\n" );
exit( -1 );
}
}
void r128DDInitIoctlFuncs( GLcontext *ctx )
{
ctx->Driver.Clear = r128DDClear;
}

View File

@ -0,0 +1,146 @@
/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_ioctl.h,v 1.6 2002/12/16 16:18:53 dawes Exp $ */
/**************************************************************************
Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
Cedar Park, Texas.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Gareth Hughes <gareth@valinux.com>
*
*/
#ifndef __R128_IOCTL_H__
#define __R128_IOCTL_H__
#ifdef GLX_DIRECT_RENDERING
#include "r128_dri.h"
#include "r128_reg.h"
#include "r128_lock.h"
#include "xf86drm.h"
#include "r128_common.h"
#define R128_BUFFER_MAX_DWORDS (R128_BUFFER_SIZE / sizeof(CARD32))
extern drmBufPtr r128GetBufferLocked( r128ContextPtr rmesa );
extern void r128FlushVerticesLocked( r128ContextPtr rmesa );
static __inline void *r128AllocDmaLow( r128ContextPtr rmesa, int bytes )
{
CARD32 *head;
if ( !rmesa->vert_buf ) {
LOCK_HARDWARE( rmesa );
rmesa->vert_buf = r128GetBufferLocked( rmesa );
UNLOCK_HARDWARE( rmesa );
} else if ( rmesa->vert_buf->used + bytes > rmesa->vert_buf->total ) {
LOCK_HARDWARE( rmesa );
r128FlushVerticesLocked( rmesa );
rmesa->vert_buf = r128GetBufferLocked( rmesa );
UNLOCK_HARDWARE( rmesa );
}
head = (CARD32 *)((char *)rmesa->vert_buf->address + rmesa->vert_buf->used);
rmesa->vert_buf->used += bytes;
return head;
}
extern void r128FireBlitLocked( r128ContextPtr rmesa, drmBufPtr buffer,
GLint offset, GLint pitch, GLint format,
GLint x, GLint y, GLint width, GLint height );
extern void r128WriteDepthSpanLocked( r128ContextPtr rmesa,
GLuint n, GLint x, GLint y,
const GLdepth depth[],
const GLubyte mask[] );
extern void r128WriteDepthPixelsLocked( r128ContextPtr rmesa, GLuint n,
const GLint x[], const GLint y[],
const GLdepth depth[],
const GLubyte mask[] );
extern void r128ReadDepthSpanLocked( r128ContextPtr rmesa,
GLuint n, GLint x, GLint y );
extern void r128ReadDepthPixelsLocked( r128ContextPtr rmesa, GLuint n,
const GLint x[], const GLint y[] );
extern void r128CopyBuffer( const __DRIdrawablePrivate *dPriv );
extern void r128PageFlip( const __DRIdrawablePrivate *dPriv );
void r128WaitForVBlank( r128ContextPtr rmesa );
extern void r128WaitForIdleLocked( r128ContextPtr rmesa );
extern void r128DDInitIoctlFuncs( GLcontext *ctx );
/* ================================================================
* Helper macros:
*/
#define FLUSH_BATCH( rmesa ) \
do { \
if ( R128_DEBUG & DEBUG_VERBOSE_IOCTL ) \
fprintf( stderr, "FLUSH_BATCH in %s\n", __FUNCTION__ ); \
if ( rmesa->vert_buf ) { \
r128FlushVertices( rmesa ); \
} \
} while (0)
/* 64-bit align the next element address, and then make room for the
* next indexed prim packet header.
*/
#define ALIGN_NEXT_ELT( rmesa ) \
do { \
rmesa->next_elt = (GLushort *) \
(((GLuint)rmesa->next_elt + 7) & ~0x7); \
rmesa->next_elt = (GLushort *) \
((GLubyte *)rmesa->next_elt + R128_INDEX_PRIM_OFFSET); \
} while (0)
#define r128FlushVertices( rmesa ) \
do { \
LOCK_HARDWARE( rmesa ); \
r128FlushVerticesLocked( rmesa ); \
UNLOCK_HARDWARE( rmesa ); \
} while (0)
#define r128FlushElts( rmesa ) \
do { \
LOCK_HARDWARE( rmesa ); \
r128FlushEltsLocked( rmesa ); \
UNLOCK_HARDWARE( rmesa ); \
} while (0)
#define r128WaitForIdle( rmesa ) \
do { \
LOCK_HARDWARE( rmesa ); \
r128WaitForIdleLocked( rmesa ); \
UNLOCK_HARDWARE( rmesa ); \
} while (0)
#endif
#endif /* __R128_IOCTL_H__ */

View File

@ -0,0 +1,123 @@
/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_lock.c,v 1.5 2002/10/30 12:51:38 alanh Exp $ */
/**************************************************************************
Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
Cedar Park, Texas.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Gareth Hughes <gareth@valinux.com>
*
*/
#include "r128_context.h"
#include "r128_lock.h"
#include "r128_tex.h"
#include "r128_state.h"
#if DEBUG_LOCKING
char *prevLockFile = NULL;
int prevLockLine = 0;
#endif
/* Turn on/off page flipping according to the flags in the sarea:
*/
static void
r128UpdatePageFlipping( r128ContextPtr rmesa )
{
int use_back;
rmesa->doPageFlip = rmesa->sarea->pfAllowPageFlip;
use_back = (rmesa->glCtx->Color._DrawDestMask == BACK_LEFT_BIT);
use_back ^= (rmesa->sarea->pfCurrentPage == 1);
if ( R128_DEBUG & DEBUG_VERBOSE_API )
fprintf(stderr, "%s allow %d current %d\n", __FUNCTION__,
rmesa->doPageFlip,
rmesa->sarea->pfCurrentPage );
if ( use_back ) {
rmesa->drawOffset = rmesa->r128Screen->backOffset;
rmesa->drawPitch = rmesa->r128Screen->backPitch;
} else {
rmesa->drawOffset = rmesa->r128Screen->frontOffset;
rmesa->drawPitch = rmesa->r128Screen->frontPitch;
}
rmesa->setup.dst_pitch_offset_c = (((rmesa->drawPitch/8) << 21) |
(rmesa->drawOffset >> 5));
rmesa->new_state |= R128_NEW_WINDOW;
}
/* Update the hardware state. This is called if another context has
* grabbed the hardware lock, which includes the X server. This
* function also updates the driver's window state after the X server
* moves, resizes or restacks a window -- the change will be reflected
* in the drawable position and clip rects. Since the X server grabs
* the hardware lock when it changes the window state, this routine will
* automatically be called after such a change.
*/
void r128GetLock( r128ContextPtr rmesa, GLuint flags )
{
__DRIdrawablePrivate *dPriv = rmesa->driDrawable;
__DRIscreenPrivate *sPriv = rmesa->driScreen;
R128SAREAPrivPtr sarea = rmesa->sarea;
int i;
drmGetLock( rmesa->driFd, rmesa->hHWContext, flags );
/* The window might have moved, so we might need to get new clip
* rects.
*
* NOTE: This releases and regrabs the hw lock to allow the X server
* to respond to the DRI protocol request for new drawable info.
* Since the hardware state depends on having the latest drawable
* clip rects, all state checking must be done _after_ this call.
*/
DRI_VALIDATE_DRAWABLE_INFO( sPriv, dPriv );
if ( rmesa->lastStamp != dPriv->lastStamp ) {
r128UpdatePageFlipping( rmesa );
rmesa->lastStamp = dPriv->lastStamp;
rmesa->new_state |= R128_NEW_CLIP;
rmesa->SetupNewInputs = ~0;
}
rmesa->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_CLIPRECTS;
rmesa->numClipRects = dPriv->numClipRects;
rmesa->pClipRects = dPriv->pClipRects;
if ( sarea->ctxOwner != rmesa->hHWContext ) {
sarea->ctxOwner = rmesa->hHWContext;
rmesa->dirty = R128_UPLOAD_ALL;
}
for ( i = 0 ; i < rmesa->nr_heaps ; i++ ) {
DRI_AGE_TEXTURES( rmesa->texture_heaps[i] );
}
}

View File

@ -0,0 +1,111 @@
/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_lock.h,v 1.4 2001/01/08 01:07:21 martin Exp $ */
/**************************************************************************
Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
Cedar Park, Texas.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Kevin E. Martin <martin@valinux.com>
* Gareth Hughes <gareth@valinux.com>
*
*/
#ifndef __R128_LOCK_H__
#define __R128_LOCK_H__
#ifdef GLX_DIRECT_RENDERING
extern void r128GetLock( r128ContextPtr rmesa, GLuint flags );
/* Turn DEBUG_LOCKING on to find locking conflicts.
*/
#define DEBUG_LOCKING 0
#if DEBUG_LOCKING
extern char *prevLockFile;
extern int prevLockLine;
#define DEBUG_LOCK() \
do { \
prevLockFile = (__FILE__); \
prevLockLine = (__LINE__); \
} while (0)
#define DEBUG_RESET() \
do { \
prevLockFile = 0; \
prevLockLine = 0; \
} while (0)
#define DEBUG_CHECK_LOCK() \
do { \
if ( prevLockFile ) { \
fprintf( stderr, \
"LOCK SET!\n\tPrevious %s:%d\n\tCurrent: %s:%d\n", \
prevLockFile, prevLockLine, __FILE__, __LINE__ ); \
exit( 1 ); \
} \
} while (0)
#else
#define DEBUG_LOCK()
#define DEBUG_RESET()
#define DEBUG_CHECK_LOCK()
#endif
/*
* !!! We may want to separate locks from locks with validation. This
* could be used to improve performance for those things commands that
* do not do any drawing !!!
*/
/* Lock the hardware and validate our state.
*/
#define LOCK_HARDWARE( rmesa ) \
do { \
char __ret = 0; \
DEBUG_CHECK_LOCK(); \
DRM_CAS( rmesa->driHwLock, rmesa->hHWContext, \
(DRM_LOCK_HELD | rmesa->hHWContext), __ret ); \
if ( __ret ) \
r128GetLock( rmesa, 0 ); \
DEBUG_LOCK(); \
} while (0)
/* Unlock the hardware.
*/
#define UNLOCK_HARDWARE( rmesa ) \
do { \
DRM_UNLOCK( rmesa->driFd, \
rmesa->driHwLock, \
rmesa->hHWContext ); \
DEBUG_RESET(); \
} while (0)
#endif
#endif /* __R128_LOCK_H__ */

View File

@ -0,0 +1,357 @@
/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_screen.c,v 1.8 2002/12/16 16:18:53 dawes Exp $ */
/**************************************************************************
Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
Cedar Park, Texas.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Gareth Hughes <gareth@valinux.com>
* Kevin E. Martin <martin@valinux.com>
*
*/
#include "r128_dri.h"
#include "r128_context.h"
#include "r128_ioctl.h"
#include "r128_tris.h"
#include "r128_vb.h"
#include "context.h"
#include "imports.h"
#include "utils.h"
#include "vblank.h"
#ifndef _SOLO
#include "glxextensions.h"
#endif
#if 1
/* Including xf86PciInfo.h introduces a bunch of errors...
*/
#define PCI_CHIP_RAGE128LE 0x4C45
#define PCI_CHIP_RAGE128LF 0x4C46
#define PCI_CHIP_RAGE128PD 0x5044
#define PCI_CHIP_RAGE128PF 0x5046
#define PCI_CHIP_RAGE128PR 0x5052
#define PCI_CHIP_RAGE128RE 0x5245
#define PCI_CHIP_RAGE128RF 0x5246
#define PCI_CHIP_RAGE128RK 0x524B
#define PCI_CHIP_RAGE128RL 0x524C
#endif
/* Create the device specific screen private data struct.
*/
static r128ScreenPtr
r128CreateScreen( __DRIscreenPrivate *sPriv )
{
r128ScreenPtr r128Screen;
R128DRIPtr r128DRIPriv = (R128DRIPtr)sPriv->pDevPriv;
if ( ! driCheckDriDdxDrmVersions( sPriv, "Rage128", 4, 0, 4, 0, 2, 2 ) )
return NULL;
/* Allocate the private area */
r128Screen = (r128ScreenPtr) CALLOC( sizeof(*r128Screen) );
if ( !r128Screen ) return NULL;
/* This is first since which regions we map depends on whether or
* not we are using a PCI card.
*/
r128Screen->IsPCI = r128DRIPriv->IsPCI;
r128Screen->sarea_priv_offset = r128DRIPriv->sarea_priv_offset;
if (sPriv->drmMinor >= 3) {
drmR128GetParam gp;
int ret;
gp.param = R128_PARAM_IRQ_NR;
gp.value = &r128Screen->irq;
ret = drmCommandWriteRead( sPriv->fd, DRM_R128_GETPARAM,
&gp, sizeof(gp));
if (ret) {
fprintf(stderr, "drmR128GetParam (R128_PARAM_IRQ_NR): %d\n", ret);
FREE( r128Screen );
return NULL;
}
}
r128Screen->mmio.handle = r128DRIPriv->registerHandle;
r128Screen->mmio.size = r128DRIPriv->registerSize;
if ( drmMap( sPriv->fd,
r128Screen->mmio.handle,
r128Screen->mmio.size,
(drmAddressPtr)&r128Screen->mmio.map ) ) {
FREE( r128Screen );
return NULL;
}
r128Screen->buffers = drmMapBufs( sPriv->fd );
if ( !r128Screen->buffers ) {
drmUnmap( (drmAddress)r128Screen->mmio.map, r128Screen->mmio.size );
FREE( r128Screen );
return NULL;
}
if ( !r128Screen->IsPCI ) {
r128Screen->agpTextures.handle = r128DRIPriv->agpTexHandle;
r128Screen->agpTextures.size = r128DRIPriv->agpTexMapSize;
if ( drmMap( sPriv->fd,
r128Screen->agpTextures.handle,
r128Screen->agpTextures.size,
(drmAddressPtr)&r128Screen->agpTextures.map ) ) {
drmUnmapBufs( r128Screen->buffers );
drmUnmap( (drmAddress)r128Screen->mmio.map, r128Screen->mmio.size );
FREE( r128Screen );
return NULL;
}
}
switch ( r128DRIPriv->deviceID ) {
case PCI_CHIP_RAGE128RE:
case PCI_CHIP_RAGE128RF:
case PCI_CHIP_RAGE128RK:
case PCI_CHIP_RAGE128RL:
r128Screen->chipset = R128_CARD_TYPE_R128;
break;
case PCI_CHIP_RAGE128PD:
case PCI_CHIP_RAGE128PF:
r128Screen->chipset = R128_CARD_TYPE_R128_PRO;
break;
case PCI_CHIP_RAGE128LE:
case PCI_CHIP_RAGE128LF:
r128Screen->chipset = R128_CARD_TYPE_R128_MOBILITY;
break;
default:
r128Screen->chipset = R128_CARD_TYPE_R128;
break;
}
r128Screen->cpp = r128DRIPriv->bpp / 8;
r128Screen->AGPMode = r128DRIPriv->AGPMode;
r128Screen->frontOffset = r128DRIPriv->frontOffset;
r128Screen->frontPitch = r128DRIPriv->frontPitch;
r128Screen->backOffset = r128DRIPriv->backOffset;
r128Screen->backPitch = r128DRIPriv->backPitch;
r128Screen->depthOffset = r128DRIPriv->depthOffset;
r128Screen->depthPitch = r128DRIPriv->depthPitch;
r128Screen->spanOffset = r128DRIPriv->spanOffset;
r128Screen->texOffset[R128_CARD_HEAP] = r128DRIPriv->textureOffset;
r128Screen->texSize[R128_CARD_HEAP] = r128DRIPriv->textureSize;
r128Screen->logTexGranularity[R128_CARD_HEAP] = r128DRIPriv->log2TexGran;
if ( r128Screen->IsPCI ) {
r128Screen->numTexHeaps = R128_NR_TEX_HEAPS - 1;
r128Screen->texOffset[R128_AGP_HEAP] = 0;
r128Screen->texSize[R128_AGP_HEAP] = 0;
r128Screen->logTexGranularity[R128_AGP_HEAP] = 0;
} else {
r128Screen->numTexHeaps = R128_NR_TEX_HEAPS;
r128Screen->texOffset[R128_AGP_HEAP] =
r128DRIPriv->agpTexOffset + R128_AGP_TEX_OFFSET;
r128Screen->texSize[R128_AGP_HEAP] = r128DRIPriv->agpTexMapSize;
r128Screen->logTexGranularity[R128_AGP_HEAP] =
r128DRIPriv->log2AGPTexGran;
}
r128Screen->driScreen = sPriv;
return r128Screen;
}
/* Destroy the device specific screen private data struct.
*/
static void
r128DestroyScreen( __DRIscreenPrivate *sPriv )
{
r128ScreenPtr r128Screen = (r128ScreenPtr)sPriv->private;
if ( !r128Screen )
return;
if ( !r128Screen->IsPCI ) {
drmUnmap( (drmAddress)r128Screen->agpTextures.map,
r128Screen->agpTextures.size );
}
drmUnmapBufs( r128Screen->buffers );
drmUnmap( (drmAddress)r128Screen->mmio.map, r128Screen->mmio.size );
FREE( r128Screen );
sPriv->private = NULL;
}
/* Initialize the fullscreen mode.
*/
static GLboolean
r128OpenCloseFullScreen( __DRIcontextPrivate *driContextPriv )
{
return GL_TRUE;
}
/* Create and initialize the Mesa and driver specific pixmap buffer
* data.
*/
static GLboolean
r128CreateBuffer( __DRIscreenPrivate *driScrnPriv,
__DRIdrawablePrivate *driDrawPriv,
const __GLcontextModes *mesaVis,
GLboolean isPixmap )
{
if (isPixmap) {
return GL_FALSE; /* not implemented */
}
else {
driDrawPriv->driverPrivate = (void *)
_mesa_create_framebuffer( mesaVis,
GL_FALSE, /* software depth buffer? */
mesaVis->stencilBits > 0,
mesaVis->accumRedBits > 0,
mesaVis->alphaBits > 0 );
return (driDrawPriv->driverPrivate != NULL);
}
}
static void
r128DestroyBuffer(__DRIdrawablePrivate *driDrawPriv)
{
_mesa_destroy_framebuffer((GLframebuffer *) (driDrawPriv->driverPrivate));
}
/* Copy the back color buffer to the front color buffer */
static void
r128SwapBuffers(__DRIdrawablePrivate *dPriv)
{
if (dPriv->driContextPriv && dPriv->driContextPriv->driverPrivate) {
r128ContextPtr rmesa;
GLcontext *ctx;
rmesa = (r128ContextPtr) dPriv->driContextPriv->driverPrivate;
ctx = rmesa->glCtx;
if (ctx->Visual.doubleBufferMode) {
_mesa_notifySwapBuffers( ctx ); /* flush pending rendering comands */
if ( rmesa->doPageFlip ) {
r128PageFlip( dPriv );
}
else {
r128CopyBuffer( dPriv );
}
}
}
else {
/* XXX this shouldn't be an error but we can't handle it for now */
_mesa_problem(NULL, "%s: drawable has no context!", __FUNCTION__);
}
}
/* Initialize the driver specific screen private data.
*/
static GLboolean
r128InitDriver( __DRIscreenPrivate *sPriv )
{
sPriv->private = (void *) r128CreateScreen( sPriv );
if ( !sPriv->private ) {
r128DestroyScreen( sPriv );
return GL_FALSE;
}
return GL_TRUE;
}
#ifndef _SOLO
/* This function is called by libGL.so as soon as libGL.so is loaded.
* This is where we register new extension functions with the dispatcher.
*/
void __driRegisterExtensions( void )
{
PFNGLXENABLEEXTENSIONPROC glx_enable_extension;
if ( driCompareGLXAPIVersion( 20030317 ) >= 0 ) {
glx_enable_extension = (PFNGLXENABLEEXTENSIONPROC)
glXGetProcAddress( "__glXEnableExtension" );
if ( glx_enable_extension != NULL ) {
glx_enable_extension( "GLX_SGI_swap_control", GL_FALSE );
glx_enable_extension( "GLX_SGI_video_sync", GL_FALSE );
glx_enable_extension( "GLX_MESA_swap_control", GL_FALSE );
}
}
}
#endif
static struct __DriverAPIRec r128API = {
.InitDriver = r128InitDriver,
.DestroyScreen = r128DestroyScreen,
.CreateContext = r128CreateContext,
.DestroyContext = r128DestroyContext,
.CreateBuffer = r128CreateBuffer,
.DestroyBuffer = r128DestroyBuffer,
.SwapBuffers = r128SwapBuffers,
.MakeCurrent = r128MakeCurrent,
.UnbindContext = r128UnbindContext,
.OpenFullScreen = r128OpenCloseFullScreen,
.CloseFullScreen = r128OpenCloseFullScreen,
.GetSwapInfo = NULL,
.GetMSC = driGetMSC32,
.WaitForMSC = driWaitForMSC32,
.WaitForSBC = NULL,
.SwapBuffersMSC = NULL
};
/*
* This is the bootstrap function for the driver.
* The __driCreateScreen name is the symbol that libGL.so fetches.
* Return: pointer to a __DRIscreenPrivate.
*/
#ifndef _SOLO
void *__driCreateScreen(Display *dpy, int scrn, __DRIscreen *psc,
int numConfigs, __GLXvisualConfig *config)
{
__DRIscreenPrivate *psp;
psp = __driUtilCreateScreen(dpy, scrn, psc, numConfigs, config, &r128API);
return (void *) psp;
}
#else
void *__driCreateScreen(struct DRIDriverRec *driver,
struct DRIDriverContextRec *driverContext)
{
__DRIscreenPrivate *psp;
psp = __driUtilCreateScreen(driver, driverContext, &r128API);
return (void *) psp;
}
#endif

View File

@ -0,0 +1,84 @@
/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_screen.h,v 1.7 2002/12/16 16:18:53 dawes Exp $ */
/**************************************************************************
Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
Cedar Park, Texas.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Gareth Hughes <gareth@valinux.com>
* Kevin E. Martin <martin@valinux.com>
*
*/
#ifndef __R128_SCREEN_H__
#define __R128_SCREEN_H__
#ifdef GLX_DIRECT_RENDERING
#include "r128_sarea.h"
typedef struct {
drmHandle handle; /* Handle to the DRM region */
drmSize size; /* Size of the DRM region */
unsigned char *map; /* Mapping of the DRM region */
} r128RegionRec, *r128RegionPtr;
typedef struct {
GLint chipset;
GLint cpp;
GLint IsPCI; /* Current card is a PCI card */
GLint AGPMode;
unsigned int irq; /* IRQ number (0 means none) */
GLuint frontOffset;
GLuint frontPitch;
GLuint backOffset;
GLuint backPitch;
GLuint depthOffset;
GLuint depthPitch;
GLuint spanOffset;
/* Shared texture data */
GLint numTexHeaps;
GLint texOffset[R128_NR_TEX_HEAPS];
GLint texSize[R128_NR_TEX_HEAPS];
GLint logTexGranularity[R128_NR_TEX_HEAPS];
r128RegionRec mmio;
r128RegionRec agpTextures;
drmBufMapPtr buffers;
__DRIscreenPrivate *driScreen;
unsigned int sarea_priv_offset;
} r128ScreenRec, *r128ScreenPtr;
#endif
#endif /* __R128_SCREEN_H__ */

View File

@ -0,0 +1,475 @@
/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_span.c,v 1.8 2002/10/30 12:51:39 alanh Exp $ */
/**************************************************************************
Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
Cedar Park, Texas.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Gareth Hughes <gareth@valinux.com>
* Keith Whitwell <keith@tungstengraphics.com>
* Kevin E. Martin <martin@valinux.com>
*
*/
#include "r128_context.h"
#include "r128_ioctl.h"
#include "r128_state.h"
#include "r128_span.h"
#include "r128_tex.h"
#include "swrast/swrast.h"
#define DBG 0
#define HAVE_HW_DEPTH_SPANS 1
#define HAVE_HW_DEPTH_PIXELS 1
#define LOCAL_VARS \
r128ContextPtr rmesa = R128_CONTEXT(ctx); \
r128ScreenPtr r128scrn = rmesa->r128Screen; \
__DRIscreenPrivate *sPriv = rmesa->driScreen; \
__DRIdrawablePrivate *dPriv = rmesa->driDrawable; \
GLuint pitch = r128scrn->frontPitch * r128scrn->cpp; \
GLuint height = dPriv->h; \
char *buf = (char *)(sPriv->pFB + \
rmesa->drawOffset + \
(dPriv->x * r128scrn->cpp) + \
(dPriv->y * pitch)); \
char *read_buf = (char *)(sPriv->pFB + \
rmesa->readOffset + \
(dPriv->x * r128scrn->cpp) + \
(dPriv->y * pitch)); \
GLuint p; \
(void) read_buf; (void) buf; (void) p
#define LOCAL_DEPTH_VARS \
r128ContextPtr rmesa = R128_CONTEXT(ctx); \
r128ScreenPtr r128scrn = rmesa->r128Screen; \
__DRIscreenPrivate *sPriv = rmesa->driScreen; \
__DRIdrawablePrivate *dPriv = rmesa->driDrawable; \
GLuint height = dPriv->h; \
(void) r128scrn; (void) sPriv; (void) height
#define LOCAL_STENCIL_VARS LOCAL_DEPTH_VARS
#define CLIPPIXEL( _x, _y ) \
((_x >= minx) && (_x < maxx) && (_y >= miny) && (_y < maxy))
#define CLIPSPAN( _x, _y, _n, _x1, _n1, _i ) \
if ( _y < miny || _y >= maxy ) { \
_n1 = 0, _x1 = x; \
} else { \
_n1 = _n; \
_x1 = _x; \
if ( _x1 < minx ) _i += (minx-_x1), n1 -= (minx-_x1), _x1 = minx; \
if ( _x1 + _n1 >= maxx ) n1 -= (_x1 + n1 - maxx); \
}
#define Y_FLIP( _y ) (height - _y - 1)
#define HW_LOCK() \
r128ContextPtr rmesa = R128_CONTEXT(ctx); \
FLUSH_BATCH( rmesa ); \
LOCK_HARDWARE( rmesa ); \
r128WaitForIdleLocked( rmesa );
#define HW_CLIPLOOP() \
do { \
__DRIdrawablePrivate *dPriv = rmesa->driDrawable; \
int _nc = dPriv->numClipRects; \
\
while ( _nc-- ) { \
int minx = dPriv->pClipRects[_nc].x1 - dPriv->x; \
int miny = dPriv->pClipRects[_nc].y1 - dPriv->y; \
int maxx = dPriv->pClipRects[_nc].x2 - dPriv->x; \
int maxy = dPriv->pClipRects[_nc].y2 - dPriv->y;
#define HW_ENDCLIPLOOP() \
} \
} while (0)
#define HW_UNLOCK() \
UNLOCK_HARDWARE( rmesa )
/* ================================================================
* Color buffer
*/
/* 16 bit, RGB565 color spanline and pixel functions
*/
#undef INIT_MONO_PIXEL
#define INIT_MONO_PIXEL(p, color) \
p = R128PACKCOLOR565( color[0], color[1], color[2] )
#define WRITE_RGBA( _x, _y, r, g, b, a ) \
*(GLushort *)(buf + _x*2 + _y*pitch) = ((((int)r & 0xf8) << 8) | \
(((int)g & 0xfc) << 3) | \
(((int)b & 0xf8) >> 3))
#define WRITE_PIXEL( _x, _y, p ) \
*(GLushort *)(buf + _x*2 + _y*pitch) = p
#define READ_RGBA( rgba, _x, _y ) \
do { \
GLushort p = *(GLushort *)(read_buf + _x*2 + _y*pitch); \
rgba[0] = (p >> 8) & 0xf8; \
rgba[1] = (p >> 3) & 0xfc; \
rgba[2] = (p << 3) & 0xf8; \
rgba[3] = 0xff; \
if ( rgba[0] & 0x08 ) rgba[0] |= 0x07; \
if ( rgba[1] & 0x04 ) rgba[1] |= 0x03; \
if ( rgba[2] & 0x08 ) rgba[2] |= 0x07; \
} while (0)
#define TAG(x) r128##x##_RGB565
#include "spantmp.h"
#define READ_DEPTH(d, _x, _y) \
d = *(GLushort *)(buf + _x*2 + _y*pitch)
/* 32 bit, ARGB8888 color spanline and pixel functions
*/
#undef INIT_MONO_PIXEL
#define INIT_MONO_PIXEL(p, color) \
p = R128PACKCOLOR8888( color[0], color[1], color[2], color[3] )
#define WRITE_RGBA( _x, _y, r, g, b, a ) \
*(GLuint *)(buf + _x*4 + _y*pitch) = ((b << 0) | \
(g << 8) | \
(r << 16) | \
(a << 24) )
#define WRITE_PIXEL( _x, _y, p ) \
*(GLuint *)(buf + _x*4 + _y*pitch) = p
#define READ_RGBA( rgba, _x, _y ) \
do { \
GLuint p = *(GLuint *)(read_buf + _x*4 + _y*pitch); \
rgba[0] = (p >> 16) & 0xff; \
rgba[1] = (p >> 8) & 0xff; \
rgba[2] = (p >> 0) & 0xff; \
rgba[3] = 0xff;/*(p >> 24) & 0xff;*/ \
} while (0)
#define TAG(x) r128##x##_ARGB8888
#include "spantmp.h"
/* 24 bit, RGB888 color spanline and pixel functions */
#undef INIT_MONO_PIXEL
#define INIT_MONO_PIXEL(p, color) \
p = R128PACKCOLOR888( color[0], color[1], color[2] )
#define WRITE_RGBA(_x, _y, r, g, b, a) \
*(GLuint *)(buf + _x*3 + _y*pitch) = ((r << 16) | \
(g << 8) | \
(b << 0))
#define WRITE_PIXEL(_x, _y, p) \
*(GLuint *)(buf + _x*3 + _y*pitch) = p
#define READ_RGBA(rgba, _x, _y) \
do { \
GLuint p = *(GLuint *)(read_buf + _x*3 + _y*pitch); \
rgba[0] = (p >> 16) & 0xff; \
rgba[1] = (p >> 8) & 0xff; \
rgba[2] = (p >> 0) & 0xff; \
rgba[3] = 0xff; \
} while (0)
/* ================================================================
* Depth buffer
*/
/* 16-bit depth buffer functions
*/
#define WRITE_DEPTH_SPAN() \
r128WriteDepthSpanLocked( rmesa, n, \
x + dPriv->x, \
y + dPriv->y, \
depth, mask );
#define WRITE_DEPTH_PIXELS() \
do { \
GLint ox[MAX_WIDTH]; \
GLint oy[MAX_WIDTH]; \
for ( i = 0 ; i < n ; i++ ) { \
ox[i] = x[i] + dPriv->x; \
} \
for ( i = 0 ; i < n ; i++ ) { \
oy[i] = Y_FLIP( y[i] ) + dPriv->y; \
} \
r128WriteDepthPixelsLocked( rmesa, n, ox, oy, depth, mask ); \
} while (0)
#define READ_DEPTH_SPAN() \
do { \
GLushort *buf = (GLushort *)((GLubyte *)sPriv->pFB + \
r128scrn->spanOffset); \
GLint i; \
\
r128ReadDepthSpanLocked( rmesa, n, \
x + dPriv->x, \
y + dPriv->y ); \
r128WaitForIdleLocked( rmesa ); \
\
for ( i = 0 ; i < n ; i++ ) { \
depth[i] = buf[i]; \
} \
} while (0)
#define READ_DEPTH_PIXELS() \
do { \
GLushort *buf = (GLushort *)((GLubyte *)sPriv->pFB + \
r128scrn->spanOffset); \
GLint i, remaining = n; \
\
while ( remaining > 0 ) { \
GLint ox[MAX_WIDTH]; \
GLint oy[MAX_WIDTH]; \
GLint count; \
\
if ( remaining <= 128 ) { \
count = remaining; \
} else { \
count = 128; \
} \
for ( i = 0 ; i < count ; i++ ) { \
ox[i] = x[i] + dPriv->x; \
} \
for ( i = 0 ; i < count ; i++ ) { \
oy[i] = Y_FLIP( y[i] ) + dPriv->y; \
} \
\
r128ReadDepthPixelsLocked( rmesa, count, ox, oy ); \
r128WaitForIdleLocked( rmesa ); \
\
for ( i = 0 ; i < count ; i++ ) { \
depth[i] = buf[i]; \
} \
depth += count; \
x += count; \
y += count; \
remaining -= count; \
} \
} while (0)
#define TAG(x) r128##x##_16
#include "depthtmp.h"
/* 24-bit depth, 8-bit stencil buffer functions
*/
#define WRITE_DEPTH_SPAN() \
r128WriteDepthSpanLocked( rmesa, n, \
x + dPriv->x, \
y + dPriv->y, \
depth, mask );
#define WRITE_DEPTH_PIXELS() \
do { \
GLint ox[MAX_WIDTH]; \
GLint oy[MAX_WIDTH]; \
for ( i = 0 ; i < n ; i++ ) { \
ox[i] = x[i] + dPriv->x; \
} \
for ( i = 0 ; i < n ; i++ ) { \
oy[i] = Y_FLIP( y[i] ) + dPriv->y; \
} \
r128WriteDepthPixelsLocked( rmesa, n, ox, oy, depth, mask ); \
} while (0)
#define READ_DEPTH_SPAN() \
do { \
GLuint *buf = (GLuint *)((GLubyte *)sPriv->pFB + \
r128scrn->spanOffset); \
GLint i; \
\
r128ReadDepthSpanLocked( rmesa, n, \
x + dPriv->x, \
y + dPriv->y ); \
r128WaitForIdleLocked( rmesa ); \
\
for ( i = 0 ; i < n ; i++ ) { \
depth[i] = buf[i] & 0x00ffffff; \
} \
} while (0)
#define READ_DEPTH_PIXELS() \
do { \
GLuint *buf = (GLuint *)((GLubyte *)sPriv->pFB + \
r128scrn->spanOffset); \
GLint i, remaining = n; \
\
while ( remaining > 0 ) { \
GLint ox[MAX_WIDTH]; \
GLint oy[MAX_WIDTH]; \
GLint count; \
\
if ( remaining <= 128 ) { \
count = remaining; \
} else { \
count = 128; \
} \
for ( i = 0 ; i < count ; i++ ) { \
ox[i] = x[i] + dPriv->x; \
} \
for ( i = 0 ; i < count ; i++ ) { \
oy[i] = Y_FLIP( y[i] ) + dPriv->y; \
} \
\
r128ReadDepthPixelsLocked( rmesa, count, ox, oy ); \
r128WaitForIdleLocked( rmesa ); \
\
for ( i = 0 ; i < count ; i++ ) { \
depth[i] = buf[i] & 0x00ffffff; \
} \
depth += count; \
x += count; \
y += count; \
remaining -= count; \
} \
} while (0)
#define TAG(x) r128##x##_24_8
#include "depthtmp.h"
/* ================================================================
* Stencil buffer
*/
/* FIXME: Add support for hardware stencil buffers.
*/
/* 32 bit depthbuffer functions */
#define WRITE_DEPTH(_x, _y, d) \
*(GLuint *)(buf + _x*4 + _y*pitch) = d
/*
* This function is called to specify which buffer to read and write
* for software rasterization (swrast) fallbacks. This doesn't necessarily
* correspond to glDrawBuffer() or glReadBuffer() calls.
*/
static void r128DDSetBuffer( GLcontext *ctx,
GLframebuffer *colorBuffer,
GLuint bufferBit )
{
r128ContextPtr rmesa = R128_CONTEXT(ctx);
switch ( bufferBit ) {
case FRONT_LEFT_BIT:
if ( rmesa->sarea->pfCurrentPage == 1 ) {
rmesa->drawOffset = rmesa->readOffset = rmesa->r128Screen->backOffset;
rmesa->drawPitch = rmesa->readPitch = rmesa->r128Screen->backPitch;
} else {
rmesa->drawOffset = rmesa->readOffset = rmesa->r128Screen->frontOffset;
rmesa->drawPitch = rmesa->readPitch = rmesa->r128Screen->frontPitch;
}
break;
case BACK_LEFT_BIT:
if ( rmesa->sarea->pfCurrentPage == 1 ) {
rmesa->drawOffset = rmesa->readOffset = rmesa->r128Screen->frontOffset;
rmesa->drawPitch = rmesa->readPitch = rmesa->r128Screen->frontPitch;
} else {
rmesa->drawOffset = rmesa->readOffset = rmesa->r128Screen->backOffset;
rmesa->drawPitch = rmesa->readPitch = rmesa->r128Screen->backPitch;
}
break;
default:
break;
}
}
void r128DDInitSpanFuncs( GLcontext *ctx )
{
r128ContextPtr rmesa = R128_CONTEXT(ctx);
struct swrast_device_driver *swdd = _swrast_GetDeviceDriverReference(ctx);
swdd->SetBuffer = r128DDSetBuffer;
switch ( rmesa->r128Screen->cpp ) {
case 2:
swdd->WriteRGBASpan = r128WriteRGBASpan_RGB565;
swdd->WriteRGBSpan = r128WriteRGBSpan_RGB565;
swdd->WriteMonoRGBASpan = r128WriteMonoRGBASpan_RGB565;
swdd->WriteRGBAPixels = r128WriteRGBAPixels_RGB565;
swdd->WriteMonoRGBAPixels = r128WriteMonoRGBAPixels_RGB565;
swdd->ReadRGBASpan = r128ReadRGBASpan_RGB565;
swdd->ReadRGBAPixels = r128ReadRGBAPixels_RGB565;
break;
case 4:
swdd->WriteRGBASpan = r128WriteRGBASpan_ARGB8888;
swdd->WriteRGBSpan = r128WriteRGBSpan_ARGB8888;
swdd->WriteMonoRGBASpan = r128WriteMonoRGBASpan_ARGB8888;
swdd->WriteRGBAPixels = r128WriteRGBAPixels_ARGB8888;
swdd->WriteMonoRGBAPixels = r128WriteMonoRGBAPixels_ARGB8888;
swdd->ReadRGBASpan = r128ReadRGBASpan_ARGB8888;
swdd->ReadRGBAPixels = r128ReadRGBAPixels_ARGB8888;
break;
default:
break;
}
switch ( rmesa->glCtx->Visual.depthBits ) {
case 16:
swdd->ReadDepthSpan = r128ReadDepthSpan_16;
swdd->WriteDepthSpan = r128WriteDepthSpan_16;
swdd->ReadDepthPixels = r128ReadDepthPixels_16;
swdd->WriteDepthPixels = r128WriteDepthPixels_16;
break;
case 24:
swdd->ReadDepthSpan = r128ReadDepthSpan_24_8;
swdd->WriteDepthSpan = r128WriteDepthSpan_24_8;
swdd->ReadDepthPixels = r128ReadDepthPixels_24_8;
swdd->WriteDepthPixels = r128WriteDepthPixels_24_8;
break;
default:
break;
}
swdd->WriteCI8Span = NULL;
swdd->WriteCI32Span = NULL;
swdd->WriteMonoCISpan = NULL;
swdd->WriteCI32Pixels = NULL;
swdd->WriteMonoCIPixels = NULL;
swdd->ReadCI32Span = NULL;
swdd->ReadCI32Pixels = NULL;
}

View File

@ -0,0 +1,44 @@
/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_span.h,v 1.3 2001/01/08 01:07:21 martin Exp $ */
/**************************************************************************
Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
Cedar Park, Texas.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Gareth Hughes <gareth@valinux.com>
* Kevin E. Martin <martin@valinux.com>
*
*/
#ifndef __R128_SPAN_H__
#define __R128_SPAN_H__
#ifdef GLX_DIRECT_RENDERING
extern void r128DDInitSpanFuncs( GLcontext *ctx );
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,54 @@
/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_state.h,v 1.3 2001/01/08 01:07:21 martin Exp $ */
/**************************************************************************
Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
Cedar Park, Texas.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Gareth Hughes <gareth@valinux.com>
* Kevin E. Martin <martin@valinux.com>
*
*/
#ifndef __R128_STATE_H__
#define __R128_STATE_H__
#ifdef GLX_DIRECT_RENDERING
#include "r128_context.h"
extern void r128DDInitState( r128ContextPtr rmesa );
extern void r128DDInitStateFuncs( GLcontext *ctx );
extern void r128DDUpdateState( GLcontext *ctx );
extern void r128DDUpdateHWState( GLcontext *ctx );
extern void r128UpdateWindow( GLcontext *ctx );
extern void r128EmitHwStateLocked( r128ContextPtr rmesa );
#endif
#endif

View File

@ -0,0 +1,598 @@
/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_tex.c,v 1.14 2002/11/05 17:46:08 tsi Exp $ */
/**************************************************************************
Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
Cedar Park, Texas.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Gareth Hughes <gareth@valinux.com>
* Kevin E. Martin <martin@valinux.com>
* Brian Paul <brianp@valinux.com>
*/
#include "r128_context.h"
#include "r128_state.h"
#include "r128_ioctl.h"
#include "r128_vb.h"
#include "r128_tris.h"
#include "r128_tex.h"
#include "r128_texobj.h"
#include "context.h"
#include "macros.h"
#include "simple_list.h"
#include "enums.h"
#include "texstore.h"
#include "texformat.h"
#include "teximage.h"
#include "imports.h"
#include "colormac.h"
#define TEX_0 1
#define TEX_1 2
static void r128SetTexWrap( r128TexObjPtr t, GLenum swrap, GLenum twrap )
{
t->setup.tex_cntl &= ~(R128_TEX_CLAMP_S_MASK | R128_TEX_CLAMP_T_MASK);
switch ( swrap ) {
case GL_CLAMP:
t->setup.tex_cntl |= R128_TEX_CLAMP_S_BORDER_COLOR;
break;
case GL_CLAMP_TO_EDGE:
t->setup.tex_cntl |= R128_TEX_CLAMP_S_CLAMP;
break;
case GL_REPEAT:
t->setup.tex_cntl |= R128_TEX_CLAMP_S_WRAP;
break;
case GL_CLAMP_TO_BORDER:
t->setup.tex_cntl |= R128_TEX_CLAMP_S_BORDER_COLOR;
break;
case GL_MIRRORED_REPEAT:
t->setup.tex_cntl |= R128_TEX_CLAMP_S_MIRROR;
break;
}
switch ( twrap ) {
case GL_CLAMP:
t->setup.tex_cntl |= R128_TEX_CLAMP_T_BORDER_COLOR;
break;
case GL_CLAMP_TO_EDGE:
t->setup.tex_cntl |= R128_TEX_CLAMP_T_CLAMP;
break;
case GL_REPEAT:
t->setup.tex_cntl |= R128_TEX_CLAMP_T_WRAP;
break;
case GL_CLAMP_TO_BORDER:
t->setup.tex_cntl |= R128_TEX_CLAMP_T_BORDER_COLOR;
break;
case GL_MIRRORED_REPEAT:
t->setup.tex_cntl |= R128_TEX_CLAMP_T_MIRROR;
break;
}
}
static void r128SetTexFilter( r128TexObjPtr t, GLenum minf, GLenum magf )
{
t->setup.tex_cntl &= ~(R128_MIN_BLEND_MASK | R128_MAG_BLEND_MASK);
switch ( minf ) {
case GL_NEAREST:
t->setup.tex_cntl |= R128_MIN_BLEND_NEAREST;
break;
case GL_LINEAR:
t->setup.tex_cntl |= R128_MIN_BLEND_LINEAR;
break;
case GL_NEAREST_MIPMAP_NEAREST:
t->setup.tex_cntl |= R128_MIN_BLEND_MIPNEAREST;
break;
case GL_LINEAR_MIPMAP_NEAREST:
t->setup.tex_cntl |= R128_MIN_BLEND_MIPLINEAR;
break;
case GL_NEAREST_MIPMAP_LINEAR:
t->setup.tex_cntl |= R128_MIN_BLEND_LINEARMIPNEAREST;
break;
case GL_LINEAR_MIPMAP_LINEAR:
t->setup.tex_cntl |= R128_MIN_BLEND_LINEARMIPLINEAR;
break;
}
switch ( magf ) {
case GL_NEAREST:
t->setup.tex_cntl |= R128_MAG_BLEND_NEAREST;
break;
case GL_LINEAR:
t->setup.tex_cntl |= R128_MAG_BLEND_LINEAR;
break;
}
}
static void r128SetTexBorderColor( r128TexObjPtr t, GLubyte c[4] )
{
t->setup.tex_border_color = r128PackColor( 4, c[0], c[1], c[2], c[3] );
}
static r128TexObjPtr r128AllocTexObj( struct gl_texture_object *texObj )
{
r128TexObjPtr t;
if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
fprintf( stderr, "%s( %p )\n", __FUNCTION__, texObj );
}
t = (r128TexObjPtr) CALLOC_STRUCT( r128_tex_obj );
texObj->DriverData = t;
if ( t != NULL ) {
/* Initialize non-image-dependent parts of the state:
*/
t->base.tObj = texObj;
/* FIXME Something here to set initial values for other parts of
* FIXME t->setup?
*/
make_empty_list( (driTextureObject *) t );
r128SetTexWrap( t, texObj->WrapS, texObj->WrapT );
r128SetTexFilter( t, texObj->MinFilter, texObj->MagFilter );
r128SetTexBorderColor( t, texObj->_BorderChan );
}
return t;
}
/* Called by the _mesa_store_teximage[123]d() functions. */
static const struct gl_texture_format *
r128ChooseTextureFormat( GLcontext *ctx, GLint internalFormat,
GLenum format, GLenum type )
{
r128ContextPtr rmesa = R128_CONTEXT(ctx);
(void) format;
(void) type;
switch ( internalFormat ) {
case GL_ALPHA:
case GL_ALPHA4:
case GL_ALPHA8:
case GL_ALPHA12:
case GL_ALPHA16:
case GL_COMPRESSED_ALPHA:
case 2:
case GL_LUMINANCE_ALPHA:
case GL_LUMINANCE4_ALPHA4:
case GL_LUMINANCE6_ALPHA2:
case GL_LUMINANCE8_ALPHA8:
case GL_LUMINANCE12_ALPHA4:
case GL_LUMINANCE12_ALPHA12:
case GL_LUMINANCE16_ALPHA16:
case GL_COMPRESSED_LUMINANCE_ALPHA:
case 4:
case GL_RGBA:
case GL_COMPRESSED_RGBA:
case GL_RGBA2:
case GL_RGB5_A1:
case GL_RGBA8:
case GL_RGB10_A2:
case GL_RGBA12:
case GL_RGBA16:
if (rmesa->r128Screen->cpp == 4)
return &_mesa_texformat_argb8888;
else
return &_mesa_texformat_argb4444;
case GL_RGBA4:
return &_mesa_texformat_argb4444;
case 3:
case GL_RGB:
case GL_COMPRESSED_RGB:
case GL_R3_G3_B2:
case GL_RGB4:
case GL_RGB5:
case GL_RGB8:
case GL_RGB10:
case GL_RGB12:
case GL_RGB16:
if (rmesa->r128Screen->cpp == 4)
return &_mesa_texformat_argb8888;
else
return &_mesa_texformat_rgb565;
case 1:
case GL_LUMINANCE:
case GL_LUMINANCE4:
case GL_LUMINANCE8:
case GL_LUMINANCE12:
case GL_LUMINANCE16:
case GL_COMPRESSED_LUMINANCE:
if (rmesa->r128Screen->cpp == 4)
return &_mesa_texformat_argb8888; /* inefficient but accurate */
else
return &_mesa_texformat_rgb565;
case GL_INTENSITY4:
return &_mesa_texformat_argb4444;
case GL_INTENSITY:
case GL_INTENSITY8:
case GL_INTENSITY12:
case GL_INTENSITY16:
case GL_COMPRESSED_INTENSITY:
if (rmesa->r128Screen->cpp == 4)
return &_mesa_texformat_argb8888; /* inefficient but accurate */
else
return &_mesa_texformat_argb4444;
case GL_COLOR_INDEX:
case GL_COLOR_INDEX1_EXT:
case GL_COLOR_INDEX2_EXT:
case GL_COLOR_INDEX4_EXT:
case GL_COLOR_INDEX8_EXT:
case GL_COLOR_INDEX12_EXT:
case GL_COLOR_INDEX16_EXT:
return &_mesa_texformat_ci8;
case GL_YCBCR_MESA:
if (type == GL_UNSIGNED_SHORT_8_8_APPLE ||
type == GL_UNSIGNED_BYTE)
return &_mesa_texformat_ycbcr;
else
return &_mesa_texformat_ycbcr_rev;
default:
_mesa_problem( ctx, "unexpected format in %s", __FUNCTION__ );
return NULL;
}
}
static void r128TexImage1D( GLcontext *ctx, GLenum target, GLint level,
GLint internalFormat,
GLint width, GLint border,
GLenum format, GLenum type, const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage )
{
driTextureObject * t = (driTextureObject *) texObj->DriverData;
if ( t ) {
driSwapOutTextureObject( t );
}
else {
t = (driTextureObject *) r128AllocTexObj(texObj);
if (!t) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage1D");
return;
}
}
/* Note, this will call r128ChooseTextureFormat */
_mesa_store_teximage1d( ctx, target, level, internalFormat,
width, border, format, type,
pixels, packing, texObj, texImage );
t->dirty_images[0] |= (1 << level);
}
static void r128TexSubImage1D( GLcontext *ctx,
GLenum target,
GLint level,
GLint xoffset,
GLsizei width,
GLenum format, GLenum type,
const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage )
{
driTextureObject * t = (driTextureObject *) texObj->DriverData;
assert( t ); /* this _should_ be true */
if ( t ) {
driSwapOutTextureObject( t );
}
else {
t = (driTextureObject *) r128AllocTexObj(texObj);
if (!t) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage1D");
return;
}
}
_mesa_store_texsubimage1d(ctx, target, level, xoffset, width,
format, type, pixels, packing, texObj,
texImage);
t->dirty_images[0] |= (1 << level);
}
static void r128TexImage2D( GLcontext *ctx, GLenum target, GLint level,
GLint internalFormat,
GLint width, GLint height, GLint border,
GLenum format, GLenum type, const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage )
{
driTextureObject * t = (driTextureObject *) texObj->DriverData;
if ( t ) {
driSwapOutTextureObject( (driTextureObject *) t );
}
else {
t = (driTextureObject *) r128AllocTexObj(texObj);
if (!t) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
return;
}
}
/* Note, this will call r128ChooseTextureFormat */
_mesa_store_teximage2d(ctx, target, level, internalFormat,
width, height, border, format, type, pixels,
&ctx->Unpack, texObj, texImage);
t->dirty_images[0] |= (1 << level);
}
static void r128TexSubImage2D( GLcontext *ctx,
GLenum target,
GLint level,
GLint xoffset, GLint yoffset,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage )
{
driTextureObject * t = (driTextureObject *) texObj->DriverData;
assert( t ); /* this _should_ be true */
if ( t ) {
driSwapOutTextureObject( t );
}
else {
t = (driTextureObject *) r128AllocTexObj(texObj);
if (!t) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage2D");
return;
}
}
_mesa_store_texsubimage2d(ctx, target, level, xoffset, yoffset, width,
height, format, type, pixels, packing, texObj,
texImage);
t->dirty_images[0] |= (1 << level);
}
static void r128DDTexEnv( GLcontext *ctx, GLenum target,
GLenum pname, const GLfloat *param )
{
r128ContextPtr rmesa = R128_CONTEXT(ctx);
struct gl_texture_unit *texUnit;
GLubyte c[4];
if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
fprintf( stderr, "%s( %s )\n",
__FUNCTION__, _mesa_lookup_enum_by_nr( pname ) );
}
switch ( pname ) {
case GL_TEXTURE_ENV_MODE:
FLUSH_BATCH( rmesa );
rmesa->new_state |= R128_NEW_ALPHA;
break;
case GL_TEXTURE_ENV_COLOR:
texUnit = &ctx->Texture.Unit[ctx->Texture.CurrentUnit];
CLAMPED_FLOAT_TO_UBYTE( c[0], texUnit->EnvColor[0] );
CLAMPED_FLOAT_TO_UBYTE( c[1], texUnit->EnvColor[1] );
CLAMPED_FLOAT_TO_UBYTE( c[2], texUnit->EnvColor[2] );
CLAMPED_FLOAT_TO_UBYTE( c[3], texUnit->EnvColor[3] );
rmesa->env_color = r128PackColor( 4, c[0], c[1], c[2], c[3] );
if ( rmesa->setup.constant_color_c != rmesa->env_color ) {
FLUSH_BATCH( rmesa );
rmesa->setup.constant_color_c = rmesa->env_color;
/* More complex multitexture/multipass fallbacks for GL_BLEND
* can be done later, but this allows a single pass GL_BLEND
* in some cases (ie. Performer town demo). This is only
* applicable to the regular Rage 128, as the Pro and M3 can
* handle true single-pass GL_BLEND texturing.
*/
rmesa->blend_flags &= ~R128_BLEND_ENV_COLOR;
if ( R128_IS_PLAIN( rmesa ) &&
rmesa->env_color != 0x00000000 &&
rmesa->env_color != 0xff000000 &&
rmesa->env_color != 0x00ffffff &&
rmesa->env_color != 0xffffffff ) {
rmesa->blend_flags |= R128_BLEND_ENV_COLOR;
}
}
break;
case GL_TEXTURE_LOD_BIAS_EXT:
do {
CARD32 t = rmesa->setup.tex_cntl_c;
GLint bias;
CARD32 b;
/* GTH: This isn't exactly correct, but gives good results up to a
* certain point. It is better than completely ignoring the LOD
* bias. Unfortunately there isn't much range in the bias, the
* spec mentions strides that vary between 0.5 and 2.0 but these
* numbers don't seem to relate the the GL LOD bias value at all.
*/
if ( param[0] >= 1.0 ) {
bias = -128;
} else if ( param[0] >= 0.5 ) {
bias = -64;
} else if ( param[0] >= 0.25 ) {
bias = 0;
} else if ( param[0] >= 0.0 ) {
bias = 63;
} else {
bias = 127;
}
b = (CARD32)bias & 0xff;
t &= ~R128_LOD_BIAS_MASK;
t |= (b << R128_LOD_BIAS_SHIFT);
if ( rmesa->setup.tex_cntl_c != t ) {
FLUSH_BATCH( rmesa );
rmesa->setup.tex_cntl_c = t;
rmesa->dirty |= R128_UPLOAD_CONTEXT;
}
} while (0);
break;
default:
return;
}
}
static void r128DDTexParameter( GLcontext *ctx, GLenum target,
struct gl_texture_object *tObj,
GLenum pname, const GLfloat *params )
{
r128ContextPtr rmesa = R128_CONTEXT(ctx);
r128TexObjPtr t = (r128TexObjPtr)tObj->DriverData;
if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
fprintf( stderr, "%s( %s )\n",
__FUNCTION__, _mesa_lookup_enum_by_nr( pname ) );
}
if ( ( target != GL_TEXTURE_2D ) && ( target != GL_TEXTURE_1D ) )
return;
switch ( pname ) {
case GL_TEXTURE_MIN_FILTER:
case GL_TEXTURE_MAG_FILTER:
if ( t->base.bound ) FLUSH_BATCH( rmesa );
r128SetTexFilter( t, tObj->MinFilter, tObj->MagFilter );
break;
case GL_TEXTURE_WRAP_S:
case GL_TEXTURE_WRAP_T:
if ( t->base.bound ) FLUSH_BATCH( rmesa );
r128SetTexWrap( t, tObj->WrapS, tObj->WrapT );
break;
case GL_TEXTURE_BORDER_COLOR:
if ( t->base.bound ) FLUSH_BATCH( rmesa );
r128SetTexBorderColor( t, tObj->_BorderChan );
break;
case GL_TEXTURE_BASE_LEVEL:
case GL_TEXTURE_MAX_LEVEL:
case GL_TEXTURE_MIN_LOD:
case GL_TEXTURE_MAX_LOD:
/* This isn't the most efficient solution but there doesn't appear to
* be a nice alternative for R128. Since there's no LOD clamping,
* we just have to rely on loading the right subset of mipmap levels
* to simulate a clamped LOD.
*/
if ( t->base.bound ) FLUSH_BATCH( rmesa );
driSwapOutTextureObject( (driTextureObject *) t );
break;
default:
return;
}
}
static void r128DDBindTexture( GLcontext *ctx, GLenum target,
struct gl_texture_object *tObj )
{
if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
fprintf( stderr, "%s( %p ) unit=%d\n", __FUNCTION__, tObj,
ctx->Texture.CurrentUnit );
}
if ( target == GL_TEXTURE_2D || target == GL_TEXTURE_1D ) {
if ( tObj->DriverData == NULL ) {
r128AllocTexObj( tObj );
}
}
}
static void r128DDDeleteTexture( GLcontext *ctx,
struct gl_texture_object *tObj )
{
r128ContextPtr rmesa = R128_CONTEXT(ctx);
driTextureObject * t = (driTextureObject *) tObj->DriverData;
if ( t ) {
if ( t->bound && rmesa ) {
FLUSH_BATCH( rmesa );
}
driDestroyTextureObject( t );
}
}
void r128DDInitTextureFuncs( GLcontext *ctx )
{
r128ContextPtr rmesa = R128_CONTEXT(ctx);
ctx->Driver.TexEnv = r128DDTexEnv;
ctx->Driver.ChooseTextureFormat = r128ChooseTextureFormat;
ctx->Driver.TexImage1D = r128TexImage1D;
ctx->Driver.TexSubImage1D = r128TexSubImage1D;
ctx->Driver.TexImage2D = r128TexImage2D;
ctx->Driver.TexSubImage2D = r128TexSubImage2D;
ctx->Driver.TexImage3D = _mesa_store_teximage3d;
ctx->Driver.TexSubImage3D = _mesa_store_texsubimage3d;
ctx->Driver.CopyTexImage1D = _swrast_copy_teximage1d;
ctx->Driver.CopyTexImage2D = _swrast_copy_teximage2d;
ctx->Driver.CopyTexSubImage1D = _swrast_copy_texsubimage1d;
ctx->Driver.CopyTexSubImage2D = _swrast_copy_texsubimage2d;
ctx->Driver.CopyTexSubImage3D = _swrast_copy_texsubimage3d;
ctx->Driver.TestProxyTexImage = _mesa_test_proxy_teximage;
ctx->Driver.TexParameter = r128DDTexParameter;
ctx->Driver.BindTexture = r128DDBindTexture;
ctx->Driver.DeleteTexture = r128DDDeleteTexture;
ctx->Driver.UpdateTexturePalette = NULL;
ctx->Driver.ActiveTexture = NULL;
ctx->Driver.IsTextureResident = driIsTextureResident;
ctx->Driver.PrioritizeTexture = NULL;
driInitTextureObjects( ctx, & rmesa->swapped,
DRI_TEXMGR_DO_TEXTURE_1D
| DRI_TEXMGR_DO_TEXTURE_2D );
}

View File

@ -0,0 +1,88 @@
/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_tex.h,v 1.7 2002/02/22 21:44:58 dawes Exp $ */
/**************************************************************************
Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
Cedar Park, Texas.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Gareth Hughes <gareth@valinux.com>
* Kevin E. Martin <martin@valinux.com>
*
*/
#ifndef __R128_TEX_H__
#define __R128_TEX_H__
#ifdef GLX_DIRECT_RENDERING
extern void r128UpdateTextureState( GLcontext *ctx );
extern void r128UploadTexImages( r128ContextPtr rmesa, r128TexObjPtr t );
extern void r128DestroyTexObj( r128ContextPtr rmesa, r128TexObjPtr t );
extern void r128DDInitTextureFuncs( GLcontext *ctx );
/* ================================================================
* Color conversion macros:
*/
#define R128PACKCOLOR332( r, g, b ) \
(((r) & 0xe0) | (((g) & 0xe0) >> 3) | (((b) & 0xc0) >> 6))
#define R128PACKCOLOR1555( r, g, b, a ) \
((((r) & 0xf8) << 7) | (((g) & 0xf8) << 2) | (((b) & 0xf8) >> 3) | \
((a) ? 0x8000 : 0))
#define R128PACKCOLOR565( r, g, b ) \
((((r) & 0xf8) << 8) | (((g) & 0xfc) << 3) | (((b) & 0xf8) >> 3))
#define R128PACKCOLOR888( r, g, b ) \
(((r) << 16) | ((g) << 8) | (b))
#define R128PACKCOLOR8888( r, g, b, a ) \
(((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
#define R128PACKCOLOR4444( r, g, b, a ) \
((((a) & 0xf0) << 8) | (((r) & 0xf0) << 4) | ((g) & 0xf0) | ((b) >> 4))
static __inline__ CARD32 r128PackColor( GLuint cpp,
GLubyte r, GLubyte g,
GLubyte b, GLubyte a )
{
switch ( cpp ) {
case 2:
return R128PACKCOLOR565( r, g, b );
case 4:
return R128PACKCOLOR8888( r, g, b, a );
default:
return 0;
}
}
#endif
#endif /* __R128_TEX_H__ */

View File

@ -0,0 +1,302 @@
/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_tex.c,v 1.7 2001/01/08 01:07:21 martin Exp $ */
/**************************************************************************
Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
Cedar Park, Texas.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Gareth Hughes <gareth@valinux.com>
* Kevin E. Martin <martin@valinux.com>
* Brian Paul <brianp@valinux.com>
*/
#include "r128_context.h"
#include "r128_state.h"
#include "r128_ioctl.h"
#include "r128_vb.h"
#include "r128_tris.h"
#include "r128_tex.h"
#include "context.h"
#include "macros.h"
#include "simple_list.h"
#include "texformat.h"
#include "imports.h"
#define TEX_0 1
#define TEX_1 2
/* Destroy hardware state associated with texture `t'.
*/
void r128DestroyTexObj( r128ContextPtr rmesa, r128TexObjPtr t )
{
unsigned i;
/* See if it was the driver's current object.
*/
if ( rmesa != NULL )
{
for ( i = 0 ; i < rmesa->glCtx->Const.MaxTextureUnits ; i++ )
{
if ( t == rmesa->CurrentTexObj[ i ] ) {
assert( t->base.bound & (1 << i) );
rmesa->CurrentTexObj[ i ] = NULL;
}
}
}
}
/**
* Upload the texture image associated with texture \a t at the specified
* level at the address relative to \a start.
*/
static void uploadSubImage( r128ContextPtr rmesa, r128TexObjPtr t,
GLint level,
GLint x, GLint y, GLint width, GLint height )
{
struct gl_texture_image *image;
int texelsPerDword = 0;
int imageWidth, imageHeight;
int remaining, rows;
int format, dwords;
CARD32 pitch, offset;
int i;
/* Ensure we have a valid texture to upload */
if ( ( level < 0 ) || ( level > R128_MAX_TEXTURE_LEVELS ) )
return;
image = t->base.tObj->Image[level];
if ( !image )
return;
switch ( image->TexFormat->TexelBytes ) {
case 1: texelsPerDword = 4; break;
case 2: texelsPerDword = 2; break;
case 4: texelsPerDword = 1; break;
}
#if 1
/* FIXME: The subimage index calcs are wrong... */
x = 0;
y = 0;
width = image->Width;
height = image->Height;
#endif
imageWidth = image->Width;
imageHeight = image->Height;
format = t->textureFormat >> 16;
/* The texel upload routines have a minimum width, so force the size
* if needed.
*/
if ( imageWidth < texelsPerDword ) {
int factor;
factor = texelsPerDword / imageWidth;
imageWidth = texelsPerDword;
imageHeight /= factor;
if ( imageHeight == 0 ) {
/* In this case, the texel converter will actually walk a
* texel or two off the end of the image, but normal malloc
* alignment should prevent it from ever causing a fault.
*/
imageHeight = 1;
}
}
/* We can't upload to a pitch less than 8 texels so we will need to
* linearly upload all modified rows for textures smaller than this.
* This makes the x/y/width/height different for the blitter and the
* texture walker.
*/
if ( imageWidth >= 8 ) {
/* The texture walker and the blitter look identical */
pitch = imageWidth >> 3;
} else {
int factor;
int y2;
int start, end;
start = (y * imageWidth) & ~7;
end = (y + height) * imageWidth;
if ( end - start < 8 ) {
/* Handle the case where the total number of texels
* uploaded is < 8.
*/
x = 0;
y = start / 8;
width = end - start;
height = 1;
} else {
/* Upload some number of full 8 texel blit rows */
factor = 8 / imageWidth;
y2 = y + height - 1;
y /= factor;
y2 /= factor;
x = 0;
width = 8;
height = y2 - y + 1;
}
/* Fixed pitch of 8 */
pitch = 1;
}
dwords = width * height / texelsPerDword;
offset = t->bufAddr + t->image[level - t->base.firstLevel].offset;
#if ENABLE_PERF_BOXES
/* Bump the performace counter */
rmesa->c_textureBytes += (dwords << 2);
#endif
if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
fprintf( stderr, "r128UploadSubImage: %d,%d of %d,%d at %d,%d\n",
width, height, image->Width, image->Height, x, y );
fprintf( stderr, " blit ofs: 0x%07x pitch: 0x%x dwords: %d "
"level: %d format: %x\n",
(GLuint)offset, (GLuint)pitch, dwords, level, format );
}
/* Subdivide the texture if required */
if ( dwords <= R128_BUFFER_MAX_DWORDS / 2 ) {
rows = height;
} else {
rows = (R128_BUFFER_MAX_DWORDS * texelsPerDword) / (2 * width);
}
for ( i = 0, remaining = height ;
remaining > 0 ;
remaining -= rows, y += rows, i++ )
{
CARD32 *dst;
drmBufPtr buffer;
assert(image->Data);
height = MIN2(remaining, rows);
/* Grab the indirect buffer for the texture blit */
LOCK_HARDWARE( rmesa );
buffer = r128GetBufferLocked( rmesa );
dst = (CARD32 *)((char *)buffer->address + R128_HOSTDATA_BLIT_OFFSET);
/* Copy the next chunck of the texture image into the blit buffer */
{
const GLubyte *src = (const GLubyte *) image->Data +
(y * image->Width + x) * image->TexFormat->TexelBytes;
const GLuint bytes = width * height * image->TexFormat->TexelBytes;
memcpy(dst, src, bytes);
}
r128FireBlitLocked( rmesa, buffer,
offset, pitch, format,
x, y, width, height );
UNLOCK_HARDWARE( rmesa );
}
rmesa->new_state |= R128_NEW_CONTEXT;
rmesa->dirty |= R128_UPLOAD_CONTEXT | R128_UPLOAD_MASKS;
}
/* Upload the texture images associated with texture `t'. This might
* require removing our own and/or other client's texture objects to
* make room for these images.
*/
void r128UploadTexImages( r128ContextPtr rmesa, r128TexObjPtr t )
{
const GLint numLevels = t->base.lastLevel - t->base.firstLevel + 1;
GLint i;
if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
fprintf( stderr, "%s( %p, %p )\n",
__FUNCTION__, rmesa->glCtx, t );
}
assert(t);
LOCK_HARDWARE( rmesa );
if ( !t->base.memBlock ) {
int heap;
heap = driAllocateTexture( rmesa->texture_heaps, rmesa->nr_heaps,
(driTextureObject *) t );
if ( heap == -1 ) {
UNLOCK_HARDWARE( rmesa );
return;
}
/* Set the base offset of the texture image */
t->bufAddr = rmesa->r128Screen->texOffset[heap]
+ t->base.memBlock->ofs;
/* Set texture offsets for each mipmap level */
if ( t->setup.tex_cntl & R128_MIP_MAP_DISABLE ) {
for ( i = 0 ; i < R128_MAX_TEXTURE_LEVELS ; i++ ) {
t->setup.tex_offset[i] = t->bufAddr;
}
} else {
for ( i = 0; i < numLevels; i++ ) {
const int j = numLevels - i - 1;
t->setup.tex_offset[j] = t->bufAddr + t->image[i].offset;
}
}
}
/* Let the world know we've used this memory recently.
*/
driUpdateTextureLRU( (driTextureObject *) t );
UNLOCK_HARDWARE( rmesa );
/* Upload any images that are new */
if ( t->base.dirty_images[0] ) {
for ( i = 0 ; i < numLevels; i++ ) {
const GLint j = t->base.firstLevel + i; /* the texObj's level */
if ( t->base.dirty_images[0] & (1 << j) ) {
uploadSubImage( rmesa, t, j, 0, 0,
t->image[i].width, t->image[i].height );
}
}
rmesa->setup.tex_cntl_c |= R128_TEX_CACHE_FLUSH;
rmesa->dirty |= R128_UPLOAD_CONTEXT;
t->base.dirty_images[0] = 0;
}
}

View File

@ -0,0 +1,69 @@
/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_texobj.h,v 1.5 2002/02/22 21:44:58 dawes Exp $ */
/**************************************************************************
Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
Cedar Park, Texas.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Kevin E. Martin <martin@valinux.com>
* Gareth Hughes <gareth@valinux.com>
*
*/
#ifndef _R128_TEXOBJ_H_
#define _R128_TEXOBJ_H_
#include "r128_sarea.h"
#include "mm.h"
/* Individual texture image information.
*/
typedef struct {
GLuint offset; /* Relative to local texture space */
GLuint width;
GLuint height;
} r128TexImage;
typedef struct r128_tex_obj r128TexObj, *r128TexObjPtr;
/* Texture object in locally shared texture space.
*/
struct r128_tex_obj {
driTextureObject base;
CARD32 bufAddr; /* Offset to start of locally
shared texture block */
GLuint age;
r128TexImage image[R128_MAX_TEXTURE_LEVELS]; /* Image data for all
mipmap levels */
CARD32 textureFormat; /* Actual hardware format */
r128_texture_regs_t setup; /* Setup regs for texture */
};
#endif /* _R128_TEXOBJ_H_ */

View File

@ -0,0 +1,652 @@
/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_tex.c,v 1.7 2001/01/08 01:07:21 martin Exp $ */
/**************************************************************************
Copyright 1999, 2000 ATI Technologies Inc. and Precision Insight, Inc.,
Cedar Park, Texas.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ATI, PRECISION INSIGHT AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Gareth Hughes <gareth@valinux.com>
* Kevin E. Martin <martin@valinux.com>
* Brian Paul <brianp@valinux.com>
*/
#include "glheader.h"
#include "imports.h"
#include "context.h"
#include "macros.h"
#include "texformat.h"
#include "r128_context.h"
#include "r128_state.h"
#include "r128_ioctl.h"
#include "r128_vb.h"
#include "r128_tris.h"
#include "r128_tex.h"
static void r128SetTexImages( r128ContextPtr rmesa,
const struct gl_texture_object *tObj )
{
r128TexObjPtr t = (r128TexObjPtr) tObj->DriverData;
struct gl_texture_image *baseImage = tObj->Image[tObj->BaseLevel];
int log2Pitch, log2Height, log2Size, log2MinSize;
int totalSize;
int i;
GLint firstLevel, lastLevel;
assert(t);
assert(baseImage);
if ( R128_DEBUG & DEBUG_VERBOSE_API )
fprintf( stderr, "%s( %p )\n", __FUNCTION__, tObj );
switch (baseImage->TexFormat->MesaFormat) {
case MESA_FORMAT_ARGB8888:
t->textureFormat = R128_DATATYPE_ARGB8888;
break;
case MESA_FORMAT_ARGB4444:
t->textureFormat = R128_DATATYPE_ARGB4444;
break;
case MESA_FORMAT_RGB565:
t->textureFormat = R128_DATATYPE_RGB565;
break;
case MESA_FORMAT_RGB332:
t->textureFormat = R128_DATATYPE_RGB8;
break;
case MESA_FORMAT_CI8:
t->textureFormat = R128_DATATYPE_CI8;
break;
case MESA_FORMAT_YCBCR:
t->textureFormat = R128_DATATYPE_YVYU422;
break;
case MESA_FORMAT_YCBCR_REV:
t->textureFormat = R128_DATATYPE_VYUY422;
break;
default:
_mesa_problem(rmesa->glCtx, "Bad texture format in %s", __FUNCTION__);
};
/* Compute which mipmap levels we really want to send to the hardware.
* This depends on the base image size, GL_TEXTURE_MIN_LOD,
* GL_TEXTURE_MAX_LOD, GL_TEXTURE_BASE_LEVEL, and GL_TEXTURE_MAX_LEVEL.
* Yes, this looks overly complicated, but it's all needed.
*/
firstLevel = tObj->BaseLevel + (GLint) (tObj->MinLod + 0.5);
firstLevel = MAX2(firstLevel, tObj->BaseLevel);
lastLevel = tObj->BaseLevel + (GLint) (tObj->MaxLod + 0.5);
lastLevel = MAX2(lastLevel, tObj->BaseLevel);
lastLevel = MIN2(lastLevel, tObj->BaseLevel + baseImage->MaxLog2);
lastLevel = MIN2(lastLevel, tObj->MaxLevel);
lastLevel = MAX2(firstLevel, lastLevel); /* need at least one level */
log2Pitch = tObj->Image[firstLevel]->WidthLog2;
log2Height = tObj->Image[firstLevel]->HeightLog2;
log2Size = MAX2(log2Pitch, log2Height);
log2MinSize = log2Size;
t->base.dirty_images[0] = 0;
totalSize = 0;
for ( i = firstLevel; i <= lastLevel; i++ ) {
const struct gl_texture_image *texImage;
texImage = tObj->Image[i];
if ( !texImage || !texImage->Data ) {
lastLevel = i - 1;
break;
}
log2MinSize = texImage->MaxLog2;
t->image[i - firstLevel].offset = totalSize;
t->image[i - firstLevel].width = tObj->Image[i]->Width;
t->image[i - firstLevel].height = tObj->Image[i]->Height;
t->base.dirty_images[0] |= (1 << i);
totalSize += (tObj->Image[i]->Height *
tObj->Image[i]->Width *
tObj->Image[i]->TexFormat->TexelBytes);
/* Offsets must be 32-byte aligned for host data blits and tiling */
totalSize = (totalSize + 31) & ~31;
}
t->base.totalSize = totalSize;
t->base.firstLevel = firstLevel;
t->base.lastLevel = lastLevel;
/* Set the texture format */
t->setup.tex_cntl &= ~(0xf << 16);
t->setup.tex_cntl |= t->textureFormat;
t->setup.tex_combine_cntl = 0x00000000; /* XXX is this right? */
t->setup.tex_size_pitch = ((log2Pitch << R128_TEX_PITCH_SHIFT) |
(log2Size << R128_TEX_SIZE_SHIFT) |
(log2Height << R128_TEX_HEIGHT_SHIFT) |
(log2MinSize << R128_TEX_MIN_SIZE_SHIFT));
for ( i = 0 ; i < R128_MAX_TEXTURE_LEVELS ; i++ ) {
t->setup.tex_offset[i] = 0x00000000;
}
if (firstLevel == lastLevel)
t->setup.tex_cntl |= R128_MIP_MAP_DISABLE;
else
t->setup.tex_cntl &= ~R128_MIP_MAP_DISABLE;
/* FYI: r128UploadTexImages( rmesa, t ); used to be called here */
}
/* ================================================================
* Texture combine functions
*/
#define COLOR_COMB_DISABLE (R128_COMB_DIS | \
R128_COLOR_FACTOR_TEX)
#define COLOR_COMB_COPY_INPUT (R128_COMB_COPY_INP | \
R128_COLOR_FACTOR_TEX)
#define COLOR_COMB_MODULATE (R128_COMB_MODULATE | \
R128_COLOR_FACTOR_TEX)
#define COLOR_COMB_MODULATE_NTEX (R128_COMB_MODULATE | \
R128_COLOR_FACTOR_NTEX)
#define COLOR_COMB_ADD (R128_COMB_ADD | \
R128_COLOR_FACTOR_TEX)
#define COLOR_COMB_BLEND_TEX (R128_COMB_BLEND_TEXTURE | \
R128_COLOR_FACTOR_TEX)
/* Rage 128 Pro/M3 only! */
#define COLOR_COMB_BLEND_COLOR (R128_COMB_MODULATE2X | \
R128_COMB_FCN_MSB | \
R128_COLOR_FACTOR_CONST_COLOR)
#define ALPHA_COMB_DISABLE (R128_COMB_ALPHA_DIS | \
R128_ALPHA_FACTOR_TEX_ALPHA)
#define ALPHA_COMB_COPY_INPUT (R128_COMB_ALPHA_COPY_INP | \
R128_ALPHA_FACTOR_TEX_ALPHA)
#define ALPHA_COMB_MODULATE (R128_COMB_ALPHA_MODULATE | \
R128_ALPHA_FACTOR_TEX_ALPHA)
#define ALPHA_COMB_MODULATE_NTEX (R128_COMB_ALPHA_MODULATE | \
R128_ALPHA_FACTOR_NTEX_ALPHA)
#define ALPHA_COMB_ADD (R128_COMB_ALPHA_ADD | \
R128_ALPHA_FACTOR_TEX_ALPHA)
#define INPUT_INTERP (R128_INPUT_FACTOR_INT_COLOR | \
R128_INP_FACTOR_A_INT_ALPHA)
#define INPUT_PREVIOUS (R128_INPUT_FACTOR_PREV_COLOR | \
R128_INP_FACTOR_A_PREV_ALPHA)
static GLboolean r128UpdateTextureEnv( GLcontext *ctx, int unit )
{
r128ContextPtr rmesa = R128_CONTEXT(ctx);
GLint source = rmesa->tmu_source[unit];
const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
const struct gl_texture_object *tObj = texUnit->_Current;
const GLenum format = tObj->Image[tObj->BaseLevel]->Format;
GLuint combine;
if ( R128_DEBUG & DEBUG_VERBOSE_API ) {
fprintf( stderr, "%s( %p, %d )\n",
__FUNCTION__, ctx, unit );
}
if ( unit == 0 ) {
combine = INPUT_INTERP;
} else {
combine = INPUT_PREVIOUS;
}
/* Set the texture environment state */
switch ( texUnit->EnvMode ) {
case GL_REPLACE:
switch ( format ) {
case GL_RGBA:
case GL_LUMINANCE_ALPHA:
case GL_INTENSITY:
combine |= (COLOR_COMB_DISABLE | /* C = Ct */
ALPHA_COMB_DISABLE); /* A = At */
break;
case GL_RGB:
case GL_LUMINANCE:
combine |= (COLOR_COMB_DISABLE | /* C = Ct */
ALPHA_COMB_COPY_INPUT); /* A = Af */
break;
case GL_ALPHA:
combine |= (COLOR_COMB_COPY_INPUT | /* C = Cf */
ALPHA_COMB_DISABLE); /* A = At */
break;
case GL_COLOR_INDEX:
default:
return GL_FALSE;
}
break;
case GL_MODULATE:
switch ( format ) {
case GL_RGBA:
case GL_LUMINANCE_ALPHA:
case GL_INTENSITY:
combine |= (COLOR_COMB_MODULATE | /* C = CfCt */
ALPHA_COMB_MODULATE); /* A = AfAt */
break;
case GL_RGB:
case GL_LUMINANCE:
combine |= (COLOR_COMB_MODULATE | /* C = CfCt */
ALPHA_COMB_COPY_INPUT); /* A = Af */
break;
case GL_ALPHA:
combine |= (COLOR_COMB_COPY_INPUT | /* C = Cf */
ALPHA_COMB_MODULATE); /* A = AfAt */
break;
case GL_COLOR_INDEX:
default:
return GL_FALSE;
}
break;
case GL_DECAL:
switch ( format ) {
case GL_RGBA:
combine |= (COLOR_COMB_BLEND_TEX | /* C = Cf(1-At)+CtAt */
ALPHA_COMB_COPY_INPUT); /* A = Af */
break;
case GL_RGB:
combine |= (COLOR_COMB_DISABLE | /* C = Ct */
ALPHA_COMB_COPY_INPUT); /* A = Af */
break;
case GL_ALPHA:
case GL_LUMINANCE:
case GL_LUMINANCE_ALPHA:
case GL_INTENSITY:
/* Undefined behaviour - just copy the incoming fragment */
combine |= (COLOR_COMB_COPY_INPUT | /* C = undefined */
ALPHA_COMB_COPY_INPUT); /* A = undefined */
break;
case GL_COLOR_INDEX:
default:
return GL_FALSE;
}
break;
case GL_BLEND:
/* Rage 128 Pro and M3 can handle GL_BLEND texturing.
*/
if ( !R128_IS_PLAIN( rmesa ) ) {
/* XXX this hasn't been fully tested, I don't have a Pro card. -BP */
switch ( format ) {
case GL_RGBA:
case GL_LUMINANCE_ALPHA:
combine |= (COLOR_COMB_BLEND_COLOR | /* C = Cf(1-Ct)+CcCt */
ALPHA_COMB_MODULATE); /* A = AfAt */
break;
case GL_RGB:
case GL_LUMINANCE:
combine |= (COLOR_COMB_BLEND_COLOR | /* C = Cf(1-Ct)+CcCt */
ALPHA_COMB_COPY_INPUT); /* A = Af */
break;
case GL_ALPHA:
combine |= (COLOR_COMB_COPY_INPUT | /* C = Cf */
ALPHA_COMB_MODULATE); /* A = AfAt */
break;
case GL_INTENSITY:
/* GH: We could be smarter about this... */
switch ( rmesa->env_color & 0xff000000 ) {
case 0x00000000:
combine |= (COLOR_COMB_BLEND_COLOR | /* C = Cf(1-It)+CcIt */
ALPHA_COMB_MODULATE_NTEX); /* A = Af(1-It) */
default:
combine |= (COLOR_COMB_MODULATE | /* C = fallback */
ALPHA_COMB_MODULATE); /* A = fallback */
return GL_FALSE;
}
break;
case GL_COLOR_INDEX:
default:
return GL_FALSE;
}
break;
}
/* Rage 128 has to fake some cases of GL_BLEND, otherwise fallback
* to software rendering.
*/
if ( rmesa->blend_flags ) {
return GL_FALSE;
}
switch ( format ) {
case GL_RGBA:
case GL_LUMINANCE_ALPHA:
switch ( rmesa->env_color & 0x00ffffff ) {
case 0x00000000:
combine |= (COLOR_COMB_MODULATE_NTEX | /* C = Cf(1-Ct) */
ALPHA_COMB_MODULATE); /* A = AfAt */
break;
#if 0
/* This isn't right - BP */
case 0x00ffffff:
if ( unit == 0 ) {
combine |= (COLOR_COMB_MODULATE_NTEX | /* C = Cf(1-Ct) */
ALPHA_COMB_MODULATE); /* A = AfAt */
} else {
combine |= (COLOR_COMB_ADD | /* C = Cf+Ct */
ALPHA_COMB_COPY_INPUT); /* A = Af */
}
break;
#endif
default:
combine |= (COLOR_COMB_MODULATE | /* C = fallback */
ALPHA_COMB_MODULATE); /* A = fallback */
return GL_FALSE;
}
break;
case GL_RGB:
case GL_LUMINANCE:
switch ( rmesa->env_color & 0x00ffffff ) {
case 0x00000000:
combine |= (COLOR_COMB_MODULATE_NTEX | /* C = Cf(1-Ct) */
ALPHA_COMB_COPY_INPUT); /* A = Af */
break;
#if 0
/* This isn't right - BP */
case 0x00ffffff:
if ( unit == 0 ) {
combine |= (COLOR_COMB_MODULATE_NTEX | /* C = Cf(1-Ct) */
ALPHA_COMB_COPY_INPUT); /* A = Af */
} else {
combine |= (COLOR_COMB_ADD | /* C = Cf+Ct */
ALPHA_COMB_COPY_INPUT); /* A = Af */
}
break;
#endif
default:
combine |= (COLOR_COMB_MODULATE | /* C = fallback */
ALPHA_COMB_COPY_INPUT); /* A = fallback */
return GL_FALSE;
}
break;
case GL_ALPHA:
if ( unit == 0 ) {
combine |= (COLOR_COMB_COPY_INPUT | /* C = Cf */
ALPHA_COMB_MODULATE); /* A = AfAt */
} else {
combine |= (COLOR_COMB_COPY_INPUT | /* C = Cf */
ALPHA_COMB_COPY_INPUT); /* A = Af */
}
break;
case GL_INTENSITY:
switch ( rmesa->env_color & 0x00ffffff ) {
case 0x00000000:
combine |= COLOR_COMB_MODULATE_NTEX; /* C = Cf(1-It) */
break;
#if 0
/* This isn't right - BP */
case 0x00ffffff:
if ( unit == 0 ) {
combine |= COLOR_COMB_MODULATE_NTEX; /* C = Cf(1-It) */
} else {
combine |= COLOR_COMB_ADD; /* C = Cf+It */
}
break;
#endif
default:
combine |= (COLOR_COMB_MODULATE | /* C = fallback */
ALPHA_COMB_MODULATE); /* A = fallback */
return GL_FALSE;
}
switch ( rmesa->env_color & 0xff000000 ) {
case 0x00000000:
combine |= ALPHA_COMB_MODULATE_NTEX; /* A = Af(1-It) */
break;
#if 0
/* This isn't right - BP */
case 0xff000000:
if ( unit == 0 ) {
combine |= ALPHA_COMB_MODULATE_NTEX; /* A = Af(1-It) */
} else {
combine |= ALPHA_COMB_ADD; /* A = Af+It */
}
break;
#endif
default:
combine |= (COLOR_COMB_MODULATE | /* C = fallback */
ALPHA_COMB_MODULATE); /* A = fallback */
return GL_FALSE;
}
break;
case GL_COLOR_INDEX:
default:
return GL_FALSE;
}
break;
case GL_ADD:
switch ( format ) {
case GL_RGBA:
case GL_LUMINANCE_ALPHA:
combine |= (COLOR_COMB_ADD | /* C = Cf+Ct */
ALPHA_COMB_MODULATE); /* A = AfAt */
break;
case GL_RGB:
case GL_LUMINANCE:
combine |= (COLOR_COMB_ADD | /* C = Cf+Ct */
ALPHA_COMB_COPY_INPUT); /* A = Af */
break;
case GL_ALPHA:
combine |= (COLOR_COMB_COPY_INPUT | /* C = Cf */
ALPHA_COMB_MODULATE); /* A = AfAt */
break;
case GL_INTENSITY:
combine |= (COLOR_COMB_ADD | /* C = Cf+Ct */
ALPHA_COMB_ADD); /* A = Af+At */
break;
case GL_COLOR_INDEX:
default:
return GL_FALSE;
}
break;
default:
return GL_FALSE;
}
if ( rmesa->tex_combine[unit] != combine ) {
rmesa->tex_combine[unit] = combine;
rmesa->dirty |= R128_UPLOAD_TEX0 << unit;
}
return GL_TRUE;
}
static void disable_tex( GLcontext *ctx, int unit )
{
r128ContextPtr rmesa = R128_CONTEXT(ctx);
FLUSH_BATCH( rmesa );
if ( rmesa->CurrentTexObj[unit] ) {
rmesa->CurrentTexObj[unit]->base.bound &= ~(1 << unit);
rmesa->CurrentTexObj[unit] = NULL;
}
rmesa->setup.tex_cntl_c &= ~(R128_TEXMAP_ENABLE << unit);
rmesa->setup.tex_size_pitch_c &= ~(R128_TEX_SIZE_PITCH_MASK <<
(R128_SEC_TEX_SIZE_PITCH_SHIFT * unit));
rmesa->dirty |= R128_UPLOAD_CONTEXT;
/* If either texture unit is disabled, then multitexturing is not
* happening.
*/
rmesa->blend_flags &= ~R128_BLEND_MULTITEX;
}
static GLboolean enable_tex_2d( GLcontext *ctx, int unit )
{
r128ContextPtr rmesa = R128_CONTEXT(ctx);
const int source = rmesa->tmu_source[unit];
const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
const struct gl_texture_object *tObj = texUnit->_Current;
r128TexObjPtr t = (r128TexObjPtr) tObj->DriverData;
/* Need to load the 2d images associated with this unit.
*/
if ( t->base.dirty_images[0] ) {
/* FIXME: For Radeon, RADEON_FIREVERTICES is called here. Should
* FIXME: something similar be done for R128?
*/
/* FLUSH_BATCH( rmesa ); */
r128SetTexImages( rmesa, tObj );
r128UploadTexImages( rmesa, t );
if ( !t->base.memBlock )
return GL_FALSE;
}
return GL_TRUE;
}
static GLboolean update_tex_common( GLcontext *ctx, int unit )
{
r128ContextPtr rmesa = R128_CONTEXT(ctx);
const int source = rmesa->tmu_source[unit];
const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
const struct gl_texture_object *tObj = texUnit->_Current;
r128TexObjPtr t = (r128TexObjPtr) tObj->DriverData;
/* Fallback if there's a texture border */
if ( tObj->Image[tObj->BaseLevel]->Border > 0 ) {
return GL_FALSE;
}
/* Update state if this is a different texture object to last
* time.
*/
if ( rmesa->CurrentTexObj[unit] != t ) {
if ( rmesa->CurrentTexObj[unit] != NULL ) {
/* The old texture is no longer bound to this texture unit.
* Mark it as such.
*/
rmesa->CurrentTexObj[unit]->base.bound &=
~(1UL << unit);
}
rmesa->CurrentTexObj[unit] = t;
t->base.bound |= (1UL << unit);
rmesa->dirty |= R128_UPLOAD_TEX0 << unit;
driUpdateTextureLRU( (driTextureObject *) t ); /* XXX: should be locked! */
}
/* FIXME: We need to update the texture unit if any texture parameters have
* changed, but this texture was already bound. This could be changed to
* work like the Radeon driver where the texture object has it's own
* dirty state flags
*/
rmesa->dirty |= R128_UPLOAD_TEX0 << unit;
/* register setup */
rmesa->setup.tex_size_pitch_c &= ~(R128_TEX_SIZE_PITCH_MASK <<
(R128_SEC_TEX_SIZE_PITCH_SHIFT * unit));
if ( unit == 0 ) {
rmesa->setup.tex_cntl_c |= R128_TEXMAP_ENABLE;
rmesa->setup.tex_size_pitch_c |= t->setup.tex_size_pitch << 0;
rmesa->setup.scale_3d_cntl &= ~R128_TEX_CACHE_SPLIT;
t->setup.tex_cntl &= ~R128_SEC_SELECT_SEC_ST;
}
else {
rmesa->setup.tex_cntl_c |= R128_SEC_TEXMAP_ENABLE;
rmesa->setup.tex_size_pitch_c |= t->setup.tex_size_pitch << 16;
rmesa->setup.scale_3d_cntl |= R128_TEX_CACHE_SPLIT;
t->setup.tex_cntl |= R128_SEC_SELECT_SEC_ST;
/* If the second TMU is enabled, then multitexturing is happening.
*/
if ( R128_IS_PLAIN( rmesa ) )
rmesa->blend_flags |= R128_BLEND_MULTITEX;
}
rmesa->dirty |= R128_UPLOAD_CONTEXT;
/* FIXME: The Radeon has some cached state so that it can avoid calling
* FIXME: UpdateTextureEnv in some cases. Is that possible here?
*/
return r128UpdateTextureEnv( ctx, unit );
}
static GLboolean updateTextureUnit( GLcontext *ctx, int unit )
{
r128ContextPtr rmesa = R128_CONTEXT(ctx);
const int source = rmesa->tmu_source[unit];
const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[source];
if (texUnit->_ReallyEnabled & (TEXTURE_1D_BIT | TEXTURE_2D_BIT)) {
return (enable_tex_2d( ctx, unit ) &&
update_tex_common( ctx, unit ));
}
else if ( texUnit->_ReallyEnabled ) {
return GL_FALSE;
}
else {
disable_tex( ctx, unit );
return GL_TRUE;
}
}
void r128UpdateTextureState( GLcontext *ctx )
{
r128ContextPtr rmesa = R128_CONTEXT(ctx);
GLboolean ok;
/* This works around a quirk with the R128 hardware. If only OpenGL
* TEXTURE1 is enabled, then the hardware TEXTURE0 must be used. The
* hardware TEXTURE1 can ONLY be used when hardware TEXTURE0 is also used.
*/
rmesa->tmu_source[0] = 0;
rmesa->tmu_source[1] = 1;
if ((ctx->Texture._EnabledUnits & 0x03) == 0x02) {
/* only texture 1 enabled */
rmesa->tmu_source[0] = 1;
rmesa->tmu_source[1] = 0;
}
ok = (updateTextureUnit( ctx, 0 ) &&
updateTextureUnit( ctx, 1 ));
FALLBACK( rmesa, R128_FALLBACK_TEXTURE, !ok );
}

View File

@ -0,0 +1,721 @@
/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_tris.c,v 1.8 2002/10/30 12:51:43 alanh Exp $ */ /* -*- c-basic-offset: 3 -*- */
/**************************************************************************
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
VA Linux Systems Inc., Fremont, California.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*
*/
#include "glheader.h"
#include "mtypes.h"
#include "colormac.h"
#include "macros.h"
#include "swrast/swrast.h"
#include "swrast_setup/swrast_setup.h"
#include "tnl/tnl.h"
#include "tnl/t_context.h"
#include "tnl/t_pipeline.h"
#include "r128_tris.h"
#include "r128_state.h"
#include "r128_tex.h"
#include "r128_vb.h"
#include "r128_ioctl.h"
static const GLuint hw_prim[GL_POLYGON+1] = {
R128_CCE_VC_CNTL_PRIM_TYPE_POINT,
R128_CCE_VC_CNTL_PRIM_TYPE_LINE,
R128_CCE_VC_CNTL_PRIM_TYPE_LINE,
R128_CCE_VC_CNTL_PRIM_TYPE_LINE,
R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST,
R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST,
R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST,
R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST,
R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST,
R128_CCE_VC_CNTL_PRIM_TYPE_TRI_LIST,
};
static void r128RasterPrimitive( GLcontext *ctx, GLuint hwprim );
static void r128RenderPrimitive( GLcontext *ctx, GLenum prim );
/***********************************************************************
* Emit primitives as inline vertices *
***********************************************************************/
#if defined(USE_X86_ASM)
#define COPY_DWORDS( j, vb, vertsize, v ) \
do { \
int __tmp; \
__asm__ __volatile__( "rep ; movsl" \
: "=%c" (j), "=D" (vb), "=S" (__tmp) \
: "0" (vertsize), \
"D" ((long)vb), \
"S" ((long)v) ); \
} while (0)
#else
#define COPY_DWORDS( j, vb, vertsize, v ) \
do { \
for ( j = 0 ; j < vertsize ; j++ ) \
vb[j] = CPU_TO_LE32(((GLuint *)v)[j]); \
vb += vertsize; \
} while (0)
#endif
static __inline void r128_draw_quad( r128ContextPtr rmesa,
r128VertexPtr v0,
r128VertexPtr v1,
r128VertexPtr v2,
r128VertexPtr v3 )
{
GLuint vertsize = rmesa->vertex_size;
GLuint *vb = (GLuint *)r128AllocDmaLow( rmesa, 6 * vertsize * 4 );
GLuint j;
rmesa->num_verts += 6;
COPY_DWORDS( j, vb, vertsize, v0 );
COPY_DWORDS( j, vb, vertsize, v1 );
COPY_DWORDS( j, vb, vertsize, v3 );
COPY_DWORDS( j, vb, vertsize, v1 );
COPY_DWORDS( j, vb, vertsize, v2 );
COPY_DWORDS( j, vb, vertsize, v3 );
}
static __inline void r128_draw_triangle( r128ContextPtr rmesa,
r128VertexPtr v0,
r128VertexPtr v1,
r128VertexPtr v2 )
{
GLuint vertsize = rmesa->vertex_size;
GLuint *vb = (GLuint *)r128AllocDmaLow( rmesa, 3 * vertsize * 4 );
GLuint j;
rmesa->num_verts += 3;
COPY_DWORDS( j, vb, vertsize, v0 );
COPY_DWORDS( j, vb, vertsize, v1 );
COPY_DWORDS( j, vb, vertsize, v2 );
}
static __inline void r128_draw_line( r128ContextPtr rmesa,
r128VertexPtr v0,
r128VertexPtr v1 )
{
GLuint vertsize = rmesa->vertex_size;
GLuint *vb = (GLuint *)r128AllocDmaLow( rmesa, 2 * vertsize * 4 );
GLuint j;
rmesa->num_verts += 2;
COPY_DWORDS( j, vb, vertsize, v0 );
COPY_DWORDS( j, vb, vertsize, v1 );
}
static __inline void r128_draw_point( r128ContextPtr rmesa,
r128VertexPtr v0 )
{
int vertsize = rmesa->vertex_size;
GLuint *vb = (GLuint *)r128AllocDmaLow( rmesa, vertsize * 4 );
int j;
rmesa->num_verts += 1;
COPY_DWORDS( j, vb, vertsize, v0 );
}
/***********************************************************************
* Macros for t_dd_tritmp.h to draw basic primitives *
***********************************************************************/
#define TRI( a, b, c ) \
do { \
if (DO_FALLBACK) \
rmesa->draw_tri( rmesa, a, b, c ); \
else \
r128_draw_triangle( rmesa, a, b, c ); \
} while (0)
#define QUAD( a, b, c, d ) \
do { \
if (DO_FALLBACK) { \
rmesa->draw_tri( rmesa, a, b, d ); \
rmesa->draw_tri( rmesa, b, c, d ); \
} else \
r128_draw_quad( rmesa, a, b, c, d ); \
} while (0)
#define LINE( v0, v1 ) \
do { \
if (DO_FALLBACK) \
rmesa->draw_line( rmesa, v0, v1 ); \
else \
r128_draw_line( rmesa, v0, v1 ); \
} while (0)
#define POINT( v0 ) \
do { \
if (DO_FALLBACK) \
rmesa->draw_point( rmesa, v0 ); \
else \
r128_draw_point( rmesa, v0 ); \
} while (0)
/***********************************************************************
* Build render functions from dd templates *
***********************************************************************/
#define R128_OFFSET_BIT 0x01
#define R128_TWOSIDE_BIT 0x02
#define R128_UNFILLED_BIT 0x04
#define R128_FALLBACK_BIT 0x08
#define R128_MAX_TRIFUNC 0x10
static struct {
points_func points;
line_func line;
triangle_func triangle;
quad_func quad;
} rast_tab[R128_MAX_TRIFUNC];
#define DO_FALLBACK (IND & R128_FALLBACK_BIT)
#define DO_OFFSET (IND & R128_OFFSET_BIT)
#define DO_UNFILLED (IND & R128_UNFILLED_BIT)
#define DO_TWOSIDE (IND & R128_TWOSIDE_BIT)
#define DO_FLAT 0
#define DO_TRI 1
#define DO_QUAD 1
#define DO_LINE 1
#define DO_POINTS 1
#define DO_FULL_QUAD 1
#define HAVE_RGBA 1
#define HAVE_SPEC 1
#define HAVE_BACK_COLORS 0
#define HAVE_HW_FLATSHADE 1
#define VERTEX r128Vertex
#define TAB rast_tab
#define DEPTH_SCALE 1.0
#define UNFILLED_TRI unfilled_tri
#define UNFILLED_QUAD unfilled_quad
#define VERT_X(_v) _v->v.x
#define VERT_Y(_v) _v->v.y
#define VERT_Z(_v) _v->v.z
#define AREA_IS_CCW( a ) (a > 0)
#define GET_VERTEX(e) (rmesa->verts + (e<<rmesa->vertex_stride_shift))
#define VERT_SET_RGBA( v, c ) do { \
r128_color_t *vc = (r128_color_t *)&(v)->ui[coloroffset]; \
vc->blue = (c)[2]; \
vc->green = (c)[1]; \
vc->red = (c)[0]; \
vc->alpha = (c)[3]; \
} while (0)
#define VERT_COPY_RGBA( v0, v1 ) v0->ui[coloroffset] = v1->ui[coloroffset]
#define VERT_SAVE_RGBA( idx ) color[idx] = v[idx]->ui[coloroffset]
#define VERT_RESTORE_RGBA( idx ) v[idx]->ui[coloroffset] = color[idx]
#define VERT_SET_SPEC( v0, c ) if (havespec) { \
(v0)->v.specular.red = (c)[0];\
(v0)->v.specular.green = (c)[1];\
(v0)->v.specular.blue = (c)[2]; }
#define VERT_COPY_SPEC( v0, v1 ) if (havespec) { \
(v0)->v.specular.red = v1->v.specular.red; \
(v0)->v.specular.green = v1->v.specular.green; \
(v0)->v.specular.blue = v1->v.specular.blue; }
#define VERT_SAVE_SPEC( idx ) if (havespec) spec[idx] = v[idx]->ui[5]
#define VERT_RESTORE_SPEC( idx ) if (havespec) v[idx]->ui[5] = spec[idx]
#define LOCAL_VARS(n) \
r128ContextPtr rmesa = R128_CONTEXT(ctx); \
GLuint color[n], spec[n]; \
GLuint coloroffset = (rmesa->vertex_size == 4 ? 3 : 4); \
GLboolean havespec = (rmesa->vertex_size == 4 ? 0 : 1); \
(void) color; (void) spec; (void) coloroffset; (void) havespec;
/***********************************************************************
* Helpers for rendering unfilled primitives *
***********************************************************************/
#define RASTERIZE(x) if (rmesa->hw_primitive != hw_prim[x]) \
r128RasterPrimitive( ctx, hw_prim[x] )
#define RENDER_PRIMITIVE rmesa->render_primitive
#define IND R128_FALLBACK_BIT
#define TAG(x) x
#include "tnl_dd/t_dd_unfilled.h"
#undef IND
/***********************************************************************
* Generate GL render functions *
***********************************************************************/
#define IND (0)
#define TAG(x) x
#include "tnl_dd/t_dd_tritmp.h"
#define IND (R128_OFFSET_BIT)
#define TAG(x) x##_offset
#include "tnl_dd/t_dd_tritmp.h"
#define IND (R128_TWOSIDE_BIT)
#define TAG(x) x##_twoside
#include "tnl_dd/t_dd_tritmp.h"
#define IND (R128_TWOSIDE_BIT|R128_OFFSET_BIT)
#define TAG(x) x##_twoside_offset
#include "tnl_dd/t_dd_tritmp.h"
#define IND (R128_UNFILLED_BIT)
#define TAG(x) x##_unfilled
#include "tnl_dd/t_dd_tritmp.h"
#define IND (R128_OFFSET_BIT|R128_UNFILLED_BIT)
#define TAG(x) x##_offset_unfilled
#include "tnl_dd/t_dd_tritmp.h"
#define IND (R128_TWOSIDE_BIT|R128_UNFILLED_BIT)
#define TAG(x) x##_twoside_unfilled
#include "tnl_dd/t_dd_tritmp.h"
#define IND (R128_TWOSIDE_BIT|R128_OFFSET_BIT|R128_UNFILLED_BIT)
#define TAG(x) x##_twoside_offset_unfilled
#include "tnl_dd/t_dd_tritmp.h"
#define IND (R128_FALLBACK_BIT)
#define TAG(x) x##_fallback
#include "tnl_dd/t_dd_tritmp.h"
#define IND (R128_OFFSET_BIT|R128_FALLBACK_BIT)
#define TAG(x) x##_offset_fallback
#include "tnl_dd/t_dd_tritmp.h"
#define IND (R128_TWOSIDE_BIT|R128_FALLBACK_BIT)
#define TAG(x) x##_twoside_fallback
#include "tnl_dd/t_dd_tritmp.h"
#define IND (R128_TWOSIDE_BIT|R128_OFFSET_BIT|R128_FALLBACK_BIT)
#define TAG(x) x##_twoside_offset_fallback
#include "tnl_dd/t_dd_tritmp.h"
#define IND (R128_UNFILLED_BIT|R128_FALLBACK_BIT)
#define TAG(x) x##_unfilled_fallback
#include "tnl_dd/t_dd_tritmp.h"
#define IND (R128_OFFSET_BIT|R128_UNFILLED_BIT|R128_FALLBACK_BIT)
#define TAG(x) x##_offset_unfilled_fallback
#include "tnl_dd/t_dd_tritmp.h"
#define IND (R128_TWOSIDE_BIT|R128_UNFILLED_BIT|R128_FALLBACK_BIT)
#define TAG(x) x##_twoside_unfilled_fallback
#include "tnl_dd/t_dd_tritmp.h"
#define IND (R128_TWOSIDE_BIT|R128_OFFSET_BIT|R128_UNFILLED_BIT| \
R128_FALLBACK_BIT)
#define TAG(x) x##_twoside_offset_unfilled_fallback
#include "tnl_dd/t_dd_tritmp.h"
static void init_rast_tab( void )
{
init();
init_offset();
init_twoside();
init_twoside_offset();
init_unfilled();
init_offset_unfilled();
init_twoside_unfilled();
init_twoside_offset_unfilled();
init_fallback();
init_offset_fallback();
init_twoside_fallback();
init_twoside_offset_fallback();
init_unfilled_fallback();
init_offset_unfilled_fallback();
init_twoside_unfilled_fallback();
init_twoside_offset_unfilled_fallback();
}
/***********************************************************************
* Rasterization fallback helpers *
***********************************************************************/
/* This code is hit only when a mix of accelerated and unaccelerated
* primitives are being drawn, and only for the unaccelerated
* primitives.
*/
static void
r128_fallback_tri( r128ContextPtr rmesa,
r128Vertex *v0,
r128Vertex *v1,
r128Vertex *v2 )
{
GLcontext *ctx = rmesa->glCtx;
SWvertex v[3];
r128_translate_vertex( ctx, v0, &v[0] );
r128_translate_vertex( ctx, v1, &v[1] );
r128_translate_vertex( ctx, v2, &v[2] );
_swrast_Triangle( ctx, &v[0], &v[1], &v[2] );
}
static void
r128_fallback_line( r128ContextPtr rmesa,
r128Vertex *v0,
r128Vertex *v1 )
{
GLcontext *ctx = rmesa->glCtx;
SWvertex v[2];
r128_translate_vertex( ctx, v0, &v[0] );
r128_translate_vertex( ctx, v1, &v[1] );
_swrast_Line( ctx, &v[0], &v[1] );
}
static void
r128_fallback_point( r128ContextPtr rmesa,
r128Vertex *v0 )
{
GLcontext *ctx = rmesa->glCtx;
SWvertex v[1];
r128_translate_vertex( ctx, v0, &v[0] );
_swrast_Point( ctx, &v[0] );
}
/**********************************************************************/
/* Render unclipped begin/end objects */
/**********************************************************************/
#define VERT(x) (r128Vertex *)(r128verts + (x << shift))
#define RENDER_POINTS( start, count ) \
for ( ; start < count ; start++) \
r128_draw_point( rmesa, VERT(start) )
#define RENDER_LINE( v0, v1 ) \
r128_draw_line( rmesa, VERT(v0), VERT(v1) )
#define RENDER_TRI( v0, v1, v2 ) \
r128_draw_triangle( rmesa, VERT(v0), VERT(v1), VERT(v2) )
#define RENDER_QUAD( v0, v1, v2, v3 ) \
r128_draw_quad( rmesa, VERT(v0), VERT(v1), VERT(v2), VERT(v3) )
#define INIT(x) do { \
if (0) fprintf(stderr, "%s\n", __FUNCTION__); \
r128RenderPrimitive( ctx, x ); \
} while (0)
#undef LOCAL_VARS
#define LOCAL_VARS \
r128ContextPtr rmesa = R128_CONTEXT(ctx); \
const GLuint shift = rmesa->vertex_stride_shift; \
const char *r128verts = (char *)rmesa->verts; \
const GLuint * const elt = TNL_CONTEXT(ctx)->vb.Elts; \
(void) elt;
#define RESET_STIPPLE
#define RESET_OCCLUSION
#define PRESERVE_VB_DEFS
#define ELT(x) (x)
#define TAG(x) r128_##x##_verts
#include "tnl/t_vb_rendertmp.h"
#undef ELT
#undef TAG
#define TAG(x) r128_##x##_elts
#define ELT(x) elt[x]
#include "tnl/t_vb_rendertmp.h"
/**********************************************************************/
/* Render clipped primitives */
/**********************************************************************/
static void r128RenderClippedPoly( GLcontext *ctx, const GLuint *elts,
GLuint n )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
/* Render the new vertices as an unclipped polygon.
*/
{
GLuint *tmp = VB->Elts;
VB->Elts = (GLuint *)elts;
tnl->Driver.Render.PrimTabElts[GL_POLYGON]( ctx, 0, n, PRIM_BEGIN|PRIM_END );
VB->Elts = tmp;
}
}
static void r128RenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
tnl->Driver.Render.Line( ctx, ii, jj );
}
static void r128FastRenderClippedPoly( GLcontext *ctx, const GLuint *elts,
GLuint n )
{
r128ContextPtr rmesa = R128_CONTEXT( ctx );
GLuint vertsize = rmesa->vertex_size;
GLuint *vb = r128AllocDmaLow( rmesa, (n-2) * 3 * 4 * vertsize );
GLubyte *r128verts = (GLubyte *)rmesa->verts;
const GLuint shift = rmesa->vertex_stride_shift;
const GLuint *start = (const GLuint *)VERT(elts[0]);
int i,j;
rmesa->num_verts += (n-2) * 3;
for (i = 2 ; i < n ; i++) {
COPY_DWORDS( j, vb, vertsize, (r128VertexPtr) VERT(elts[i-1]) );
COPY_DWORDS( j, vb, vertsize, (r128VertexPtr) VERT(elts[i]) );
COPY_DWORDS( j, vb, vertsize, (r128VertexPtr) start );
}
}
/**********************************************************************/
/* Choose render functions */
/**********************************************************************/
#define _R128_NEW_RENDER_STATE (_DD_NEW_LINE_STIPPLE | \
_DD_NEW_LINE_SMOOTH | \
_DD_NEW_POINT_SMOOTH | \
_DD_NEW_TRI_SMOOTH | \
_DD_NEW_TRI_UNFILLED | \
_DD_NEW_TRI_LIGHT_TWOSIDE | \
_DD_NEW_TRI_OFFSET) \
#define POINT_FALLBACK (DD_POINT_SMOOTH)
#define LINE_FALLBACK (DD_LINE_STIPPLE|DD_LINE_SMOOTH)
#define TRI_FALLBACK (DD_TRI_SMOOTH)
#define ANY_FALLBACK_FLAGS (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)
#define ANY_RASTER_FLAGS (DD_TRI_LIGHT_TWOSIDE|DD_TRI_OFFSET|DD_TRI_UNFILLED)
static void r128ChooseRenderState(GLcontext *ctx)
{
r128ContextPtr rmesa = R128_CONTEXT(ctx);
GLuint flags = ctx->_TriangleCaps;
GLuint index = 0;
if (flags & (ANY_RASTER_FLAGS|ANY_FALLBACK_FLAGS)) {
rmesa->draw_point = r128_draw_point;
rmesa->draw_line = r128_draw_line;
rmesa->draw_tri = r128_draw_triangle;
if (flags & ANY_RASTER_FLAGS) {
if (flags & DD_TRI_LIGHT_TWOSIDE) index |= R128_TWOSIDE_BIT;
if (flags & DD_TRI_OFFSET) index |= R128_OFFSET_BIT;
if (flags & DD_TRI_UNFILLED) index |= R128_UNFILLED_BIT;
}
/* Hook in fallbacks for specific primitives.
*/
if (flags & (POINT_FALLBACK|LINE_FALLBACK|TRI_FALLBACK)) {
if (flags & POINT_FALLBACK) rmesa->draw_point = r128_fallback_point;
if (flags & LINE_FALLBACK) rmesa->draw_line = r128_fallback_line;
if (flags & TRI_FALLBACK) rmesa->draw_tri = r128_fallback_tri;
index |= R128_FALLBACK_BIT;
}
}
if (index != rmesa->RenderIndex) {
TNLcontext *tnl = TNL_CONTEXT(ctx);
tnl->Driver.Render.Points = rast_tab[index].points;
tnl->Driver.Render.Line = rast_tab[index].line;
tnl->Driver.Render.Triangle = rast_tab[index].triangle;
tnl->Driver.Render.Quad = rast_tab[index].quad;
if (index == 0) {
tnl->Driver.Render.PrimTabVerts = r128_render_tab_verts;
tnl->Driver.Render.PrimTabElts = r128_render_tab_elts;
tnl->Driver.Render.ClippedLine = rast_tab[index].line;
tnl->Driver.Render.ClippedPolygon = r128FastRenderClippedPoly;
} else {
tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
tnl->Driver.Render.ClippedLine = r128RenderClippedLine;
tnl->Driver.Render.ClippedPolygon = r128RenderClippedPoly;
}
rmesa->RenderIndex = index;
}
}
/**********************************************************************/
/* Validate state at pipeline start */
/**********************************************************************/
static void r128RunPipeline( GLcontext *ctx )
{
r128ContextPtr rmesa = R128_CONTEXT(ctx);
if (rmesa->new_state || rmesa->NewGLState & _NEW_TEXTURE)
r128DDUpdateHWState( ctx );
if (!rmesa->Fallback && rmesa->NewGLState) {
if (rmesa->NewGLState & _R128_NEW_VERTEX_STATE)
r128ChooseVertexState( ctx );
if (rmesa->NewGLState & _R128_NEW_RENDER_STATE)
r128ChooseRenderState( ctx );
rmesa->NewGLState = 0;
}
_tnl_run_pipeline( ctx );
}
/**********************************************************************/
/* High level hooks for t_vb_render.c */
/**********************************************************************/
/* This is called when Mesa switches between rendering triangle
* primitives (such as GL_POLYGON, GL_QUADS, GL_TRIANGLE_STRIP, etc),
* and lines, points and bitmaps.
*
* As the r128 uses triangles to render lines and points, it is
* necessary to turn off hardware culling when rendering these
* primitives.
*/
static void r128RasterPrimitive( GLcontext *ctx, GLuint hwprim )
{
r128ContextPtr rmesa = R128_CONTEXT(ctx);
rmesa->setup.dp_gui_master_cntl_c &= ~R128_GMC_BRUSH_NONE;
if ( ctx->Polygon.StippleFlag && hwprim == GL_TRIANGLES ) {
rmesa->setup.dp_gui_master_cntl_c |= R128_GMC_BRUSH_32x32_MONO_FG_LA;
}
else {
rmesa->setup.dp_gui_master_cntl_c |= R128_GMC_BRUSH_SOLID_COLOR;
}
rmesa->new_state |= R128_NEW_CONTEXT;
rmesa->dirty |= R128_UPLOAD_CONTEXT;
if (rmesa->hw_primitive != hwprim) {
FLUSH_BATCH( rmesa );
rmesa->hw_primitive = hwprim;
}
}
static void r128RenderPrimitive( GLcontext *ctx, GLenum prim )
{
r128ContextPtr rmesa = R128_CONTEXT(ctx);
GLuint hw = hw_prim[prim];
rmesa->render_primitive = prim;
if (prim >= GL_TRIANGLES && (ctx->_TriangleCaps & DD_TRI_UNFILLED))
return;
r128RasterPrimitive( ctx, hw );
}
static void r128RenderStart( GLcontext *ctx )
{
/* Check for projective texturing. Make sure all texcoord
* pointers point to something. (fix in mesa?)
*/
r128CheckTexSizes( ctx );
}
static void r128RenderFinish( GLcontext *ctx )
{
if (R128_CONTEXT(ctx)->RenderIndex & R128_FALLBACK_BIT)
_swrast_flush( ctx );
}
/**********************************************************************/
/* Transition to/from hardware rasterization. */
/**********************************************************************/
void r128Fallback( GLcontext *ctx, GLuint bit, GLboolean mode )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
r128ContextPtr rmesa = R128_CONTEXT(ctx);
GLuint oldfallback = rmesa->Fallback;
if (mode) {
rmesa->Fallback |= bit;
if (oldfallback == 0) {
FLUSH_BATCH( rmesa );
_swsetup_Wakeup( ctx );
rmesa->RenderIndex = ~0;
}
}
else {
rmesa->Fallback &= ~bit;
if (oldfallback == bit) {
_swrast_flush( ctx );
tnl->Driver.Render.Start = r128RenderStart;
tnl->Driver.Render.PrimitiveNotify = r128RenderPrimitive;
tnl->Driver.Render.Finish = r128RenderFinish;
tnl->Driver.Render.BuildVertices = r128BuildVertices;
rmesa->NewGLState |= (_R128_NEW_RENDER_STATE|
_R128_NEW_VERTEX_STATE);
}
}
}
/**********************************************************************/
/* Initialization. */
/**********************************************************************/
void r128InitTriFuncs( GLcontext *ctx )
{
r128ContextPtr rmesa = R128_CONTEXT(ctx);
TNLcontext *tnl = TNL_CONTEXT(ctx);
static int firsttime = 1;
if (firsttime) {
init_rast_tab();
firsttime = 0;
}
tnl->Driver.RunPipeline = r128RunPipeline;
tnl->Driver.Render.Start = r128RenderStart;
tnl->Driver.Render.Finish = r128RenderFinish;
tnl->Driver.Render.PrimitiveNotify = r128RenderPrimitive;
tnl->Driver.Render.ResetLineStipple = _swrast_ResetLineStipple;
tnl->Driver.Render.BuildVertices = r128BuildVertices;
rmesa->NewGLState |= (_R128_NEW_RENDER_STATE|
_R128_NEW_VERTEX_STATE);
/* r128Fallback( ctx, 0x100000, 1 ); */
}

View File

@ -0,0 +1,48 @@
/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_tris.h,v 1.8 2002/10/30 12:51:43 alanh Exp $ */
/**************************************************************************
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
VA Linux Systems Inc., Fremont, California.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*
*/
#ifndef __R128_TRIS_H__
#define __R128_TRIS_H__
#include "mtypes.h"
extern void r128InitTriFuncs( GLcontext *ctx );
extern void r128Fallback( GLcontext *ctx, GLuint bit, GLboolean mode );
#define FALLBACK( rmesa, bit, mode ) r128Fallback( rmesa->glCtx, bit, mode )
#endif /* __R128_TRIS_H__ */

View File

@ -0,0 +1,522 @@
/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_vb.c,v 1.15 2002/10/30 12:51:43 alanh Exp $ */
/**************************************************************************
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
VA Linux Systems Inc., Fremont, California.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*
*/
#include "glheader.h"
#include "mtypes.h"
#include "imports.h"
#include "macros.h"
#include "colormac.h"
#include "swrast_setup/swrast_setup.h"
#include "tnl/t_context.h"
#include "r128_context.h"
#include "r128_vb.h"
#include "r128_ioctl.h"
#include "r128_tris.h"
#include "r128_state.h"
#define R128_TEX1_BIT 0x1
#define R128_TEX0_BIT 0x2
#define R128_RGBA_BIT 0x4
#define R128_SPEC_BIT 0x8
#define R128_FOG_BIT 0x10
#define R128_XYZW_BIT 0x20
#define R128_PTEX_BIT 0x40
#define R128_MAX_SETUP 0x80
static struct {
void (*emit)( GLcontext *, GLuint, GLuint, void *, GLuint );
interp_func interp;
copy_pv_func copy_pv;
GLboolean (*check_tex_sizes)( GLcontext *ctx );
GLuint vertex_size;
GLuint vertex_stride_shift;
GLuint vertex_format;
} setup_tab[R128_MAX_SETUP];
#define TINY_VERTEX_FORMAT (R128_CCE_VC_FRMT_DIFFUSE_ARGB)
#define NOTEX_VERTEX_FORMAT (R128_CCE_VC_FRMT_RHW | \
R128_CCE_VC_FRMT_DIFFUSE_ARGB |\
R128_CCE_VC_FRMT_SPEC_FRGB)
#define TEX0_VERTEX_FORMAT (R128_CCE_VC_FRMT_RHW | \
R128_CCE_VC_FRMT_DIFFUSE_ARGB |\
R128_CCE_VC_FRMT_SPEC_FRGB | \
R128_CCE_VC_FRMT_S_T)
#define TEX1_VERTEX_FORMAT (R128_CCE_VC_FRMT_RHW | \
R128_CCE_VC_FRMT_DIFFUSE_ARGB |\
R128_CCE_VC_FRMT_SPEC_FRGB | \
R128_CCE_VC_FRMT_S_T | \
R128_CCE_VC_FRMT_S2_T2)
#define PROJ_TEX1_VERTEX_FORMAT 0
#define TEX2_VERTEX_FORMAT 0
#define TEX3_VERTEX_FORMAT 0
#define PROJ_TEX3_VERTEX_FORMAT 0
#define DO_XYZW (IND & R128_XYZW_BIT)
#define DO_RGBA (IND & R128_RGBA_BIT)
#define DO_SPEC (IND & R128_SPEC_BIT)
#define DO_FOG (IND & R128_FOG_BIT)
#define DO_TEX0 (IND & R128_TEX0_BIT)
#define DO_TEX1 (IND & R128_TEX1_BIT)
#define DO_TEX2 0
#define DO_TEX3 0
#define DO_PTEX (IND & R128_PTEX_BIT)
#define VERTEX r128Vertex
#define VERTEX_COLOR r128_color_t
#define LOCALVARS r128ContextPtr rmesa = R128_CONTEXT(ctx);
#define GET_VIEWPORT_MAT() rmesa->hw_viewport
#define GET_TEXSOURCE(n) rmesa->tmu_source[n]
#define GET_VERTEX_FORMAT() rmesa->vertex_format
#define GET_VERTEX_STORE() rmesa->verts
#define GET_VERTEX_STRIDE_SHIFT() rmesa->vertex_stride_shift
#define INVALIDATE_STORED_VERTICES()
#define GET_UBYTE_COLOR_STORE() &rmesa->UbyteColor
#define GET_UBYTE_SPEC_COLOR_STORE() &rmesa->UbyteSecondaryColor
#define HAVE_HW_VIEWPORT 0
#define HAVE_HW_DIVIDE 0
#define HAVE_RGBA_COLOR 0
#define HAVE_TINY_VERTICES 1
#define HAVE_NOTEX_VERTICES 1
#define HAVE_TEX0_VERTICES 1
#define HAVE_TEX1_VERTICES 1
#define HAVE_TEX2_VERTICES 0
#define HAVE_TEX3_VERTICES 0
#define HAVE_PTEX_VERTICES 0 /* r128 rhw2 not supported by template */
#define UNVIEWPORT_VARS GLfloat h = R128_CONTEXT(ctx)->driDrawable->h
#define UNVIEWPORT_X(x) x - SUBPIXEL_X
#define UNVIEWPORT_Y(y) - y + h + SUBPIXEL_Y
#define UNVIEWPORT_Z(z) z / rmesa->depth_scale
#define PTEX_FALLBACK() FALLBACK(R128_CONTEXT(ctx), R128_FALLBACK_TEXTURE, 1)
#define IMPORT_FLOAT_COLORS r128_import_float_colors
#define IMPORT_FLOAT_SPEC_COLORS r128_import_float_spec_colors
#define INTERP_VERTEX setup_tab[rmesa->SetupIndex].interp
#define COPY_PV_VERTEX setup_tab[rmesa->SetupIndex].copy_pv
/***********************************************************************
* Generate pv-copying and translation functions *
***********************************************************************/
#define TAG(x) r128_##x
#include "tnl_dd/t_dd_vb.c"
/***********************************************************************
* Generate vertex emit and interp functions *
***********************************************************************/
#define IND (R128_XYZW_BIT|R128_RGBA_BIT)
#define TAG(x) x##_wg
#include "tnl_dd/t_dd_vbtmp.h"
#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_SPEC_BIT)
#define TAG(x) x##_wgs
#include "tnl_dd/t_dd_vbtmp.h"
#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_TEX0_BIT)
#define TAG(x) x##_wgt0
#include "tnl_dd/t_dd_vbtmp.h"
#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_TEX0_BIT|R128_TEX1_BIT)
#define TAG(x) x##_wgt0t1
#include "tnl_dd/t_dd_vbtmp.h"
#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_TEX0_BIT|R128_PTEX_BIT)
#define TAG(x) x##_wgpt0
#include "tnl_dd/t_dd_vbtmp.h"
#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_SPEC_BIT|R128_TEX0_BIT)
#define TAG(x) x##_wgst0
#include "tnl_dd/t_dd_vbtmp.h"
#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_SPEC_BIT|R128_TEX0_BIT|\
R128_TEX1_BIT)
#define TAG(x) x##_wgst0t1
#include "tnl_dd/t_dd_vbtmp.h"
#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_SPEC_BIT|R128_TEX0_BIT|\
R128_PTEX_BIT)
#define TAG(x) x##_wgspt0
#include "tnl_dd/t_dd_vbtmp.h"
#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_FOG_BIT)
#define TAG(x) x##_wgf
#include "tnl_dd/t_dd_vbtmp.h"
#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT)
#define TAG(x) x##_wgfs
#include "tnl_dd/t_dd_vbtmp.h"
#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_FOG_BIT|R128_TEX0_BIT)
#define TAG(x) x##_wgft0
#include "tnl_dd/t_dd_vbtmp.h"
#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_FOG_BIT|R128_TEX0_BIT|\
R128_TEX1_BIT)
#define TAG(x) x##_wgft0t1
#include "tnl_dd/t_dd_vbtmp.h"
#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_FOG_BIT|R128_TEX0_BIT|\
R128_PTEX_BIT)
#define TAG(x) x##_wgfpt0
#include "tnl_dd/t_dd_vbtmp.h"
#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT|\
R128_TEX0_BIT)
#define TAG(x) x##_wgfst0
#include "tnl_dd/t_dd_vbtmp.h"
#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT|\
R128_TEX0_BIT|R128_TEX1_BIT)
#define TAG(x) x##_wgfst0t1
#include "tnl_dd/t_dd_vbtmp.h"
#define IND (R128_XYZW_BIT|R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT|\
R128_TEX0_BIT|R128_PTEX_BIT)
#define TAG(x) x##_wgfspt0
#include "tnl_dd/t_dd_vbtmp.h"
#define IND (R128_TEX0_BIT)
#define TAG(x) x##_t0
#include "tnl_dd/t_dd_vbtmp.h"
#define IND (R128_TEX0_BIT|R128_TEX1_BIT)
#define TAG(x) x##_t0t1
#include "tnl_dd/t_dd_vbtmp.h"
#define IND (R128_FOG_BIT)
#define TAG(x) x##_f
#include "tnl_dd/t_dd_vbtmp.h"
#define IND (R128_FOG_BIT|R128_TEX0_BIT)
#define TAG(x) x##_ft0
#include "tnl_dd/t_dd_vbtmp.h"
#define IND (R128_FOG_BIT|R128_TEX0_BIT|R128_TEX1_BIT)
#define TAG(x) x##_ft0t1
#include "tnl_dd/t_dd_vbtmp.h"
#define IND (R128_RGBA_BIT)
#define TAG(x) x##_g
#include "tnl_dd/t_dd_vbtmp.h"
#define IND (R128_RGBA_BIT|R128_SPEC_BIT)
#define TAG(x) x##_gs
#include "tnl_dd/t_dd_vbtmp.h"
#define IND (R128_RGBA_BIT|R128_TEX0_BIT)
#define TAG(x) x##_gt0
#include "tnl_dd/t_dd_vbtmp.h"
#define IND (R128_RGBA_BIT|R128_TEX0_BIT|R128_TEX1_BIT)
#define TAG(x) x##_gt0t1
#include "tnl_dd/t_dd_vbtmp.h"
#define IND (R128_RGBA_BIT|R128_SPEC_BIT|R128_TEX0_BIT)
#define TAG(x) x##_gst0
#include "tnl_dd/t_dd_vbtmp.h"
#define IND (R128_RGBA_BIT|R128_SPEC_BIT|R128_TEX0_BIT|R128_TEX1_BIT)
#define TAG(x) x##_gst0t1
#include "tnl_dd/t_dd_vbtmp.h"
#define IND (R128_RGBA_BIT|R128_FOG_BIT)
#define TAG(x) x##_gf
#include "tnl_dd/t_dd_vbtmp.h"
#define IND (R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT)
#define TAG(x) x##_gfs
#include "tnl_dd/t_dd_vbtmp.h"
#define IND (R128_RGBA_BIT|R128_FOG_BIT|R128_TEX0_BIT)
#define TAG(x) x##_gft0
#include "tnl_dd/t_dd_vbtmp.h"
#define IND (R128_RGBA_BIT|R128_FOG_BIT|R128_TEX0_BIT|R128_TEX1_BIT)
#define TAG(x) x##_gft0t1
#include "tnl_dd/t_dd_vbtmp.h"
#define IND (R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT|R128_TEX0_BIT)
#define TAG(x) x##_gfst0
#include "tnl_dd/t_dd_vbtmp.h"
#define IND (R128_RGBA_BIT|R128_FOG_BIT|R128_SPEC_BIT|R128_TEX0_BIT|\
R128_TEX1_BIT)
#define TAG(x) x##_gfst0t1
#include "tnl_dd/t_dd_vbtmp.h"
static void init_setup_tab( void )
{
init_wg();
init_wgs();
init_wgt0();
init_wgt0t1();
init_wgpt0();
init_wgst0();
init_wgst0t1();
init_wgspt0();
init_wgf();
init_wgfs();
init_wgft0();
init_wgft0t1();
init_wgfpt0();
init_wgfst0();
init_wgfst0t1();
init_wgfspt0();
init_t0();
init_t0t1();
init_f();
init_ft0();
init_ft0t1();
init_g();
init_gs();
init_gt0();
init_gt0t1();
init_gst0();
init_gst0t1();
init_gf();
init_gfs();
init_gft0();
init_gft0t1();
init_gfst0();
init_gfst0t1();
}
void r128PrintSetupFlags(char *msg, GLuint flags )
{
fprintf(stderr, "%s(%x): %s%s%s%s%s%s\n",
msg,
(int)flags,
(flags & R128_XYZW_BIT) ? " xyzw," : "",
(flags & R128_RGBA_BIT) ? " rgba," : "",
(flags & R128_SPEC_BIT) ? " spec," : "",
(flags & R128_FOG_BIT) ? " fog," : "",
(flags & R128_TEX0_BIT) ? " tex-0," : "",
(flags & R128_TEX1_BIT) ? " tex-1," : "");
}
void r128CheckTexSizes( GLcontext *ctx )
{
r128ContextPtr rmesa = R128_CONTEXT( ctx );
if (!setup_tab[rmesa->SetupIndex].check_tex_sizes(ctx)) {
TNLcontext *tnl = TNL_CONTEXT(ctx);
/* Invalidate stored verts
*/
rmesa->SetupNewInputs = ~0;
rmesa->SetupIndex |= R128_PTEX_BIT;
if (!rmesa->Fallback &&
!(ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) {
tnl->Driver.Render.Interp = setup_tab[rmesa->SetupIndex].interp;
tnl->Driver.Render.CopyPV = setup_tab[rmesa->SetupIndex].copy_pv;
}
}
}
void r128BuildVertices( GLcontext *ctx,
GLuint start,
GLuint count,
GLuint newinputs )
{
r128ContextPtr rmesa = R128_CONTEXT( ctx );
GLubyte *v = ((GLubyte *)rmesa->verts + (start<<rmesa->vertex_stride_shift));
GLuint stride = 1<<rmesa->vertex_stride_shift;
newinputs |= rmesa->SetupNewInputs;
rmesa->SetupNewInputs = 0;
if (!newinputs)
return;
if (newinputs & VERT_BIT_CLIP) {
setup_tab[rmesa->SetupIndex].emit( ctx, start, count, v, stride );
} else {
GLuint ind = 0;
if (newinputs & VERT_BIT_COLOR0)
ind |= R128_RGBA_BIT;
if (newinputs & VERT_BIT_COLOR1)
ind |= R128_SPEC_BIT;
if (newinputs & VERT_BIT_TEX0)
ind |= R128_TEX0_BIT;
if (newinputs & VERT_BIT_TEX1)
ind |= R128_TEX1_BIT;
if (newinputs & VERT_BIT_FOG)
ind |= R128_FOG_BIT;
if (rmesa->SetupIndex & R128_PTEX_BIT)
ind = ~0;
ind &= rmesa->SetupIndex;
if (ind) {
setup_tab[ind].emit( ctx, start, count, v, stride );
}
}
}
void r128ChooseVertexState( GLcontext *ctx )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
r128ContextPtr rmesa = R128_CONTEXT( ctx );
GLuint ind = R128_XYZW_BIT|R128_RGBA_BIT;
if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR)
ind |= R128_SPEC_BIT;
if (ctx->Fog.Enabled)
ind |= R128_FOG_BIT;
if (ctx->Texture._EnabledUnits) {
ind |= R128_TEX0_BIT;
if (ctx->Texture.Unit[0]._ReallyEnabled &&
ctx->Texture.Unit[1]._ReallyEnabled)
ind |= R128_TEX1_BIT;
}
rmesa->SetupIndex = ind;
if (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED)) {
tnl->Driver.Render.Interp = r128_interp_extras;
tnl->Driver.Render.CopyPV = r128_copy_pv_extras;
} else {
tnl->Driver.Render.Interp = setup_tab[ind].interp;
tnl->Driver.Render.CopyPV = setup_tab[ind].copy_pv;
}
if (setup_tab[ind].vertex_format != rmesa->vertex_format) {
FLUSH_BATCH(rmesa);
rmesa->vertex_format = setup_tab[ind].vertex_format;
rmesa->vertex_size = setup_tab[ind].vertex_size;
rmesa->vertex_stride_shift = setup_tab[ind].vertex_stride_shift;
}
}
void r128_emit_contiguous_verts( GLcontext *ctx,
GLuint start,
GLuint count )
{
r128ContextPtr rmesa = R128_CONTEXT(ctx);
GLuint vertex_size = rmesa->vertex_size * 4;
GLuint *dest = r128AllocDmaLow( rmesa, (count-start) * vertex_size);
setup_tab[rmesa->SetupIndex].emit( ctx, start, count, dest, vertex_size );
}
#if 0
void r128_emit_indexed_verts( GLcontext *ctx, GLuint start, GLuint count )
{
r128ContextPtr rmesa = R128_CONTEXT(ctx);
GLuint vertex_size = rmesa->vertex_size * 4;
GLuint bufsz = (count-start) * vertex_size;
CARD32 *dest;
rmesa->vertex_low = (rmesa->vertex_low + 63) & ~63; /* alignment */
rmesa->vertex_last_prim = rmesa->vertex_low;
dest = r128AllocDmaLow( rmesa, bufsz, __FUNCTION__);
setup_tab[rmesa->SetupIndex].emit( ctx, start, count, dest, vertex_size );
rmesa->retained_buffer = rmesa->vertex_buffer;
rmesa->vb_offset = (rmesa->vertex_buffer->idx * R128_BUFFER_SIZE +
rmesa->vertex_low - bufsz);
rmesa->vertex_low = (rmesa->vertex_low + 0x7) & ~0x7; /* alignment */
rmesa->vertex_last_prim = rmesa->vertex_low;
}
#endif
void r128InitVB( GLcontext *ctx )
{
r128ContextPtr rmesa = R128_CONTEXT(ctx);
GLuint size = TNL_CONTEXT(ctx)->vb.Size;
rmesa->verts = ALIGN_MALLOC(size * 4 * 16, 32);
{
static int firsttime = 1;
if (firsttime) {
init_setup_tab();
firsttime = 0;
}
}
}
void r128FreeVB( GLcontext *ctx )
{
r128ContextPtr rmesa = R128_CONTEXT(ctx);
if (rmesa->verts) {
ALIGN_FREE(rmesa->verts);
rmesa->verts = 0;
}
if (rmesa->UbyteSecondaryColor.Ptr) {
ALIGN_FREE(rmesa->UbyteSecondaryColor.Ptr);
rmesa->UbyteSecondaryColor.Ptr = 0;
}
if (rmesa->UbyteColor.Ptr) {
ALIGN_FREE(rmesa->UbyteColor.Ptr);
rmesa->UbyteColor.Ptr = 0;
}
}

View File

@ -0,0 +1,74 @@
/* $XFree86: xc/lib/GL/mesa/src/drv/r128/r128_vb.h,v 1.8 2002/10/30 12:51:46 alanh Exp $ */
/**************************************************************************
Copyright 2000, 2001 ATI Technologies Inc., Ontario, Canada, and
VA Linux Systems Inc., Fremont, California.
All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
on the rights to use, copy, modify, merge, publish, distribute, sub
license, and/or sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice (including the next
paragraph) shall be included in all copies or substantial portions of the
Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
ATI, VA LINUX SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
USE OR OTHER DEALINGS IN THE SOFTWARE.
**************************************************************************/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*
*/
#ifndef R128VB_INC
#define R128VB_INC
#include "mtypes.h"
#include "swrast/swrast.h"
#include "r128_context.h"
#define _R128_NEW_VERTEX_STATE (_DD_NEW_SEPARATE_SPECULAR | \
_DD_NEW_TRI_LIGHT_TWOSIDE | \
_DD_NEW_TRI_UNFILLED | \
_NEW_TEXTURE | \
_NEW_FOG)
extern void r128CheckTexSizes( GLcontext *ctx );
extern void r128ChooseVertexState( GLcontext *ctx );
extern void r128BuildVertices( GLcontext *ctx, GLuint start, GLuint count,
GLuint newinputs );
extern void r128PrintSetupFlags(char *msg, GLuint flags );
extern void r128InitVB( GLcontext *ctx );
extern void r128FreeVB( GLcontext *ctx );
extern void r128_emit_contiguous_verts( GLcontext *ctx,
GLuint start,
GLuint count );
extern void r128_emit_indexed_verts( GLcontext *ctx,
GLuint start,
GLuint count );
extern void r128_translate_vertex( GLcontext *ctx,
const r128Vertex *src,
SWvertex *dst );
extern void r128_print_vertex( GLcontext *ctx, const r128Vertex *v );
#endif

View File

@ -0,0 +1,566 @@
/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128.h,v 1.24 2002/12/16 16:19:10 dawes Exp $ */
/*
* Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario,
* Precision Insight, Inc., Cedar Park, Texas, and
* VA Linux Systems Inc., Fremont, California.
*
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation on the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NON-INFRINGEMENT. IN NO EVENT SHALL ATI, PRECISION INSIGHT, VA LINUX
* SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Authors:
* Rickard E. Faith <faith@valinux.com>
* Kevin E. Martin <martin@valinux.com>
*
*/
#ifndef _R128_H_
#define _R128_H_
#include "dri_util.h"
#ifndef _SOLO
#include "xf86str.h"
/* PCI support */
#include "xf86Pci.h"
/* XAA and Cursor Support */
#include "xaa.h"
#include "xf86Cursor.h"
/* DDC support */
#include "xf86DDC.h"
/* Xv support */
#include "xf86xv.h"
/* DRI support */
#ifdef XF86DRI
#define _XF86DRI_SERVER_
#include "r128_dripriv.h"
#include "dri.h"
#include "GL/glxint.h"
#endif
#endif
#ifdef _SOLO
#define XF86DRI
#endif
#define R128_DEBUG 0 /* Turn off debugging output */
#define R128_IDLE_RETRY 32 /* Fall out of idle loops after this count */
#define R128_TIMEOUT 2000000 /* Fall out of wait loops after this count */
#define R128_MMIOSIZE 0x4000
#define R128_VBIOS_SIZE 0x00010000
#if R128_DEBUG
#define R128TRACE(x) \
do { \
ErrorF("(**) %s(%d): ", R128_NAME, pScrn->scrnIndex); \
ErrorF x; \
} while (0);
#else
#define R128TRACE(x)
#endif
/* Other macros */
#define R128_ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
#define R128_ALIGN(x,bytes) (((x) + ((bytes) - 1)) & ~((bytes) - 1))
#define R128PTR(pScrn) ((R128InfoPtr)(pScrn)->driverPrivate)
/**
* \brief Chip families.
*/
typedef enum {
CHIP_FAMILY_UNKNOWN,
CHIP_FAMILY_R128_PCI,
CHIP_FAMILY_R128_AGP,
} R128ChipFamily;
typedef struct { /* All values in XCLKS */
int ML; /* Memory Read Latency */
int MB; /* Memory Burst Length */
int Trcd; /* RAS to CAS delay */
int Trp; /* RAS percentage */
int Twr; /* Write Recovery */
int CL; /* CAS Latency */
int Tr2w; /* Read to Write Delay */
int Rloop; /* Loop Latency */
int Rloop_fudge; /* Add to ML to get Rloop */
char *name;
} R128RAMRec, *R128RAMPtr;
typedef struct {
/* Common registers */
CARD32 ovr_clr;
CARD32 ovr_wid_left_right;
CARD32 ovr_wid_top_bottom;
CARD32 ov0_scale_cntl;
CARD32 mpp_tb_config;
CARD32 mpp_gp_config;
CARD32 subpic_cntl;
CARD32 viph_control;
CARD32 i2c_cntl_1;
CARD32 gen_int_cntl;
CARD32 cap0_trig_cntl;
CARD32 cap1_trig_cntl;
CARD32 bus_cntl;
CARD32 config_cntl;
/* Other registers to save for VT switches */
CARD32 dp_datatype;
CARD32 gen_reset_cntl;
CARD32 clock_cntl_index;
CARD32 amcgpio_en_reg;
CARD32 amcgpio_mask;
/* CRTC registers */
CARD32 crtc_gen_cntl;
CARD32 crtc_ext_cntl;
CARD32 dac_cntl;
CARD32 crtc_h_total_disp;
CARD32 crtc_h_sync_strt_wid;
CARD32 crtc_v_total_disp;
CARD32 crtc_v_sync_strt_wid;
CARD32 crtc_offset;
CARD32 crtc_offset_cntl;
CARD32 crtc_pitch;
/* CRTC2 registers */
CARD32 crtc2_gen_cntl;
/* Flat panel registers */
CARD32 fp_crtc_h_total_disp;
CARD32 fp_crtc_v_total_disp;
CARD32 fp_gen_cntl;
CARD32 fp_h_sync_strt_wid;
CARD32 fp_horz_stretch;
CARD32 fp_panel_cntl;
CARD32 fp_v_sync_strt_wid;
CARD32 fp_vert_stretch;
CARD32 lvds_gen_cntl;
CARD32 tmds_crc;
CARD32 tmds_transmitter_cntl;
/* Computed values for PLL */
CARD32 dot_clock_freq;
CARD32 pll_output_freq;
int feedback_div;
int post_div;
/* PLL registers */
CARD32 ppll_ref_div;
CARD32 ppll_div_3;
CARD32 htotal_cntl;
/* DDA register */
CARD32 dda_config;
CARD32 dda_on_off;
/* Pallet */
GLboolean palette_valid;
CARD32 palette[256];
} R128SaveRec, *R128SavePtr;
#ifndef _SOLO
typedef struct {
CARD16 reference_freq;
CARD16 reference_div;
CARD32 min_pll_freq;
CARD32 max_pll_freq;
CARD16 xclk;
} R128PLLRec, *R128PLLPtr;
typedef struct {
int bitsPerPixel;
int depth;
int displayWidth;
int pixel_code;
int pixel_bytes;
DisplayModePtr mode;
} R128FBLayout;
#endif
typedef struct {
#ifndef _SOLO
EntityInfoPtr pEnt;
pciVideoPtr PciInfo;
PCITAG PciTag;
#endif
int Chipset;
GLboolean Primary;
GLboolean FBDev;
unsigned long LinearAddr; /* Frame buffer physical address */
unsigned long BIOSAddr; /* BIOS physical address */
unsigned char *MMIO; /* Map of MMIO region */
unsigned char *FB; /* Map of frame buffer */
CARD32 MemCntl;
CARD32 BusCntl;
unsigned long FbMapSize; /* Size of frame buffer, in bytes */
int Flags; /* Saved copy of mode flags */
#ifndef _SOLO
CARD8 BIOSDisplay; /* Device the BIOS is set to display to */
GLboolean HasPanelRegs; /* Current chip can connect to a FP */
CARD8 *VBIOS; /* Video BIOS for mode validation on FPs */
int FPBIOSstart; /* Start of the flat panel info */
#endif
/* Computed values for FPs */
int PanelXRes;
int PanelYRes;
int HOverPlus;
int HSyncWidth;
int HBlank;
int VOverPlus;
int VSyncWidth;
int VBlank;
int PanelPwrDly;
#ifndef _SOLO
R128PLLRec pll;
R128RAMPtr ram;
R128SaveRec SavedReg; /* Original (text) mode */
R128SaveRec ModeReg; /* Current mode */
GLboolean (*CloseScreen)(int, ScreenPtr);
void (*BlockHandler)(int, pointer, pointer, pointer);
GLboolean PaletteSavedOnVT; /* Palette saved on last VT switch */
XAAInfoRecPtr accel;
GLboolean accelOn;
xf86CursorInfoPtr cursor;
#endif
unsigned long cursor_start;
unsigned long cursor_end;
/*
* XAAForceTransBlit is used to change the behavior of the XAA
* SetupForScreenToScreenCopy function, to make it DGA-friendly.
*/
GLboolean XAAForceTransBlit;
int fifo_slots; /* Free slots in the FIFO (64 max) */
int pix24bpp; /* Depth of pixmap for 24bpp framebuffer */
GLboolean dac6bits; /* Use 6 bit DAC? */
/* Computed values for Rage 128 */
int pitch;
int datatype;
CARD32 dp_gui_master_cntl;
/* Saved values for ScreenToScreenCopy */
int xdir;
int ydir;
/* ScanlineScreenToScreenColorExpand support */
unsigned char *scratch_buffer[1];
unsigned char *scratch_save;
int scanline_x;
int scanline_y;
int scanline_w;
int scanline_h;
#ifdef XF86DRI
int scanline_hpass;
int scanline_x1clip;
int scanline_x2clip;
int scanline_rop;
int scanline_fg;
int scanline_bg;
#endif /* XF86DRI */
int scanline_words;
int scanline_direct;
int scanline_bpp; /* Only used for ImageWrite */
#ifndef _SOLO
DGAModePtr DGAModes;
int numDGAModes;
GLboolean DGAactive;
int DGAViewportStatus;
DGAFunctionRec DGAFuncs;
R128FBLayout CurrentLayout;
#endif
#ifdef XF86DRI
drmContext drmCtx;
#ifndef _SOLO
DRIInfoPtr pDRIInfo;
int numVisualConfigs;
__GLXvisualConfig *pVisualConfigs;
R128ConfigPrivPtr pVisualConfigsPriv;
#endif
drmSize registerSize;
drmHandle registerHandle;
GLboolean IsPCI; /* Current card is a PCI card */
drmSize pciSize;
drmHandle pciMemHandle;
unsigned char *PCI; /* Map */
GLboolean allowPageFlip; /* Enable 3d page flipping */
GLboolean have3DWindows; /* Are there any 3d clients? */
int drmMinor;
drmSize agpSize;
drmHandle agpMemHandle; /* Handle from drmAgpAlloc */
unsigned long agpOffset;
unsigned char *AGP; /* Map */
int agpMode;
GLboolean CCEInUse; /* CCE is currently active */
int CCEMode; /* CCE mode that server/clients use */
int CCEFifoSize; /* Size of the CCE command FIFO */
GLboolean CCESecure; /* CCE security enabled */
int CCEusecTimeout; /* CCE timeout in usecs */
/* CCE ring buffer data */
unsigned long ringStart; /* Offset into AGP space */
drmHandle ringHandle; /* Handle from drmAddMap */
drmSize ringMapSize; /* Size of map */
int ringSize; /* Size of ring (in MB) */
unsigned char *ring; /* Map */
int ringSizeLog2QW;
unsigned long ringReadOffset; /* Offset into AGP space */
drmHandle ringReadPtrHandle; /* Handle from drmAddMap */
drmSize ringReadMapSize; /* Size of map */
unsigned char *ringReadPtr; /* Map */
/* CCE vertex/indirect buffer data */
unsigned long bufStart; /* Offset into AGP space */
drmHandle bufHandle; /* Handle from drmAddMap */
drmSize bufMapSize; /* Size of map */
int bufSize; /* Size of buffers (in MB) */
unsigned char *buf; /* Map */
int bufNumBufs; /* Number of buffers */
drmBufMapPtr buffers; /* Buffer map */
/* CCE AGP Texture data */
unsigned long agpTexStart; /* Offset into AGP space */
drmHandle agpTexHandle; /* Handle from drmAddMap */
drmSize agpTexMapSize; /* Size of map */
int agpTexSize; /* Size of AGP tex space (in MB) */
unsigned char *agpTex; /* Map */
int log2AGPTexGran;
/* CCE 2D accleration */
drmBufPtr indirectBuffer;
int indirectStart;
/* DRI screen private data */
int fbX;
int fbY;
int backX;
int backY;
int depthX;
int depthY;
int frontOffset;
int frontPitch;
int backOffset;
int backPitch;
int depthOffset;
int depthPitch;
int spanOffset;
int textureOffset;
int textureSize;
int log2TexGran;
/* Saved scissor values */
CARD32 sc_left;
CARD32 sc_right;
CARD32 sc_top;
CARD32 sc_bottom;
CARD32 re_top_left;
CARD32 re_width_height;
CARD32 aux_sc_cntl;
int irq;
CARD32 gen_int_cntl;
GLboolean DMAForXv;
#endif
#ifndef _SOLO
XF86VideoAdaptorPtr adaptor;
void (*VideoTimerCallback)(ScrnInfoPtr, Time);
int videoKey;
GLboolean showCache;
OptionInfoPtr Options;
GLboolean isDFP;
GLboolean isPro2;
I2CBusPtr pI2CBus;
CARD32 DDCReg;
#endif
} R128InfoRec, *R128InfoPtr;
#define R128WaitForFifo(pScrn, entries) \
do { \
if (info->fifo_slots < entries) R128WaitForFifoFunction(pScrn, entries); \
info->fifo_slots -= entries; \
} while (0)
extern void r128WaitForFifoFunction(const DRIDriverContext *ctx, int entries);
extern void r128WaitForIdle(const DRIDriverContext *ctx);
extern void r128WaitForVerticalSync(const DRIDriverContext *ctx);
extern GLboolean r128AccelInit(const DRIDriverContext *ctx);
extern void r128EngineInit(const DRIDriverContext *ctx);
extern GLboolean r128CursorInit(const DRIDriverContext *ctx);
extern GLboolean r128DGAInit(const DRIDriverContext *ctx);
extern void r128InitVideo(const DRIDriverContext *ctx);
extern GLboolean r128DRIScreenInit(const DRIDriverContext *ctx);
extern void r128DRICloseScreen(const DRIDriverContext *ctx);
extern GLboolean r128DRIFinishScreenInit(const DRIDriverContext *ctx);
#define R128CCE_START(ctx, info) \
do { \
int _ret = drmCommandNone(ctx->drmFD, DRM_R128_CCE_START); \
if (_ret) { \
fprintf(stderr, \
"%s: CCE start %d\n", __FUNCTION__, _ret); \
} \
} while (0)
#define R128CCE_STOP(ctx, info) \
do { \
int _ret = R128CCEStop(ctx); \
if (_ret) { \
fprintf(stderr, \
"%s: CCE stop %d\n", __FUNCTION__, _ret); \
} \
} while (0)
#define R128CCE_RESET(ctx, info) \
do { \
if (info->directRenderingEnabled \
&& R128CCE_USE_RING_BUFFER(info->CCEMode)) { \
int _ret = drmCommandNone(info->drmFD, DRM_R128_CCE_RESET); \
if (_ret) { \
fprintf(stderr, \
"%s: CCE reset %d\n", __FUNCTION__, _ret); \
} \
} \
} while (0)
#define CCE_PACKET0( reg, n ) \
(R128_CCE_PACKET0 | ((n) << 16) | ((reg) >> 2))
#define CCE_PACKET1( reg0, reg1 ) \
(R128_CCE_PACKET1 | (((reg1) >> 2) << 11) | ((reg0) >> 2))
#define CCE_PACKET2() \
(R128_CCE_PACKET2)
#define CCE_PACKET3( pkt, n ) \
(R128_CCE_PACKET3 | (pkt) | ((n) << 16))
#define R128_VERBOSE 0
#define RING_LOCALS CARD32 *__head; int __count;
#define R128CCE_REFRESH(pScrn, info) \
do { \
if ( R128_VERBOSE ) { \
fprintf(stderr, "REFRESH( %d ) in %s\n", \
!info->CCEInUse , __FUNCTION__ ); \
} \
if ( !info->CCEInUse ) { \
R128CCEWaitForIdle(pScrn); \
BEGIN_RING( 6 ); \
OUT_RING_REG( R128_RE_TOP_LEFT, info->re_top_left ); \
OUT_RING_REG( R128_RE_WIDTH_HEIGHT, info->re_width_height ); \
OUT_RING_REG( R128_AUX_SC_CNTL, info->aux_sc_cntl ); \
ADVANCE_RING(); \
info->CCEInUse = TRUE; \
} \
} while (0)
#define BEGIN_RING( n ) do { \
if ( R128_VERBOSE ) { \
fprintf(stderr, \
"BEGIN_RING( %d ) in %s\n", n, __FUNCTION__ ); \
} \
if ( !info->indirectBuffer ) { \
info->indirectBuffer = R128CCEGetBuffer( pScrn ); \
info->indirectStart = 0; \
} else if ( (info->indirectBuffer->used + 4*(n)) > \
info->indirectBuffer->total ) { \
R128CCEFlushIndirect( pScrn, 1 ); \
} \
__head = (pointer)((char *)info->indirectBuffer->address + \
info->indirectBuffer->used); \
__count = 0; \
} while (0)
#define ADVANCE_RING() do { \
if ( R128_VERBOSE ) { \
fprintf(stderr, \
"ADVANCE_RING() used: %d+%d=%d/%d\n", \
info->indirectBuffer->used - info->indirectStart, \
__count * sizeof(CARD32), \
info->indirectBuffer->used - info->indirectStart + \
__count * sizeof(CARD32), \
info->indirectBuffer->total - info->indirectStart ); \
} \
info->indirectBuffer->used += __count * (int)sizeof(CARD32); \
} while (0)
#define OUT_RING( x ) do { \
if ( R128_VERBOSE ) { \
fprintf(stderr, \
" OUT_RING( 0x%08x )\n", (unsigned int)(x) ); \
} \
MMIO_OUT32(&__head[__count++], 0, (x)); \
} while (0)
#define OUT_RING_REG( reg, val ) \
do { \
OUT_RING( CCE_PACKET0( reg, 0 ) ); \
OUT_RING( val ); \
} while (0)
#define FLUSH_RING() \
do { \
if ( R128_VERBOSE ) \
fprintf(stderr, \
"FLUSH_RING in %s\n", __FUNCTION__ ); \
if ( info->indirectBuffer ) { \
R128CCEFlushIndirect( pScrn, 0 ); \
} \
} while (0)
#endif

View File

@ -0,0 +1,169 @@
/* r128_common.h -- common header definitions for R128 2D/3D/DRM suite
* Created: Sun Apr 9 18:16:28 2000 by kevin@precisioninsight.com
*
* Copyright 1999, 2000 Precision Insight, Inc., Cedar Park, Texas.
* Copyright 2002 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, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* PRECISION INSIGHT 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.
*
* Author:
* Gareth Hughes <gareth@valinux.com>
* Kevin E. Martin <martin@valinux.com>
*
* Converted to common header format:
* Jens Owen <jens@tungstengraphics.com>
*
* $XFree86: xc/programs/Xserver/hw/xfree86/os-support/xf86drmR128.h,v 3.11 2001/04/16 15:02:13 tsi Exp $
*
*/
#ifndef _R128_COMMON_H_
#define _R128_COMMON_H_
/*
* WARNING: If you change any of these defines, make sure to change
* the kernel include file as well (r128_drm.h)
*/
/* Driver specific DRM command indices
* NOTE: these are not OS specific, but they are driver specific
*/
#define DRM_R128_INIT 0x00
#define DRM_R128_CCE_START 0x01
#define DRM_R128_CCE_STOP 0x02
#define DRM_R128_CCE_RESET 0x03
#define DRM_R128_CCE_IDLE 0x04
#define DRM_R128_UNDEFINED1 0x05
#define DRM_R128_RESET 0x06
#define DRM_R128_SWAP 0x07
#define DRM_R128_CLEAR 0x08
#define DRM_R128_VERTEX 0x09
#define DRM_R128_INDICES 0x0a
#define DRM_R128_BLIT 0x0b
#define DRM_R128_DEPTH 0x0c
#define DRM_R128_STIPPLE 0x0d
#define DRM_R128_UNDEFINED2 0x0e
#define DRM_R128_INDIRECT 0x0f
#define DRM_R128_FULLSCREEN 0x10
#define DRM_R128_CLEAR2 0x11
#define DRM_R128_GETPARAM 0x12
#define DRM_R128_FLIP 0x13
#define DRM_R128_FRONT_BUFFER 0x1
#define DRM_R128_BACK_BUFFER 0x2
#define DRM_R128_DEPTH_BUFFER 0x4
typedef struct {
enum {
DRM_R128_INIT_CCE = 0x01,
DRM_R128_CLEANUP_CCE = 0x02
} func;
unsigned long sarea_priv_offset;
int is_pci;
int cce_mode;
int cce_secure; /* FIXME: Deprecated, we should remove this */
int ring_size;
int usec_timeout;
unsigned int fb_bpp;
unsigned int front_offset, front_pitch;
unsigned int back_offset, back_pitch;
unsigned int depth_bpp;
unsigned int depth_offset, depth_pitch;
unsigned int span_offset;
unsigned long fb_offset;
unsigned long mmio_offset;
unsigned long ring_offset;
unsigned long ring_rptr_offset;
unsigned long buffers_offset;
unsigned long agp_textures_offset;
} drmR128Init;
typedef struct {
int flush;
int idle;
} drmR128CCEStop;
typedef struct {
int idx;
int start;
int end;
int discard;
} drmR128Indirect;
typedef struct {
int idx;
int pitch;
int offset;
int format;
unsigned short x, y;
unsigned short width, height;
} drmR128Blit;
typedef struct {
enum {
DRM_R128_WRITE_SPAN = 0x01,
DRM_R128_WRITE_PIXELS = 0x02,
DRM_R128_READ_SPAN = 0x03,
DRM_R128_READ_PIXELS = 0x04
} func;
int n;
int *x;
int *y;
unsigned int *buffer;
unsigned char *mask;
} drmR128Depth;
typedef struct {
int prim;
int idx; /* Index of vertex buffer */
int count; /* Number of vertices in buffer */
int discard; /* Client finished with buffer? */
} drmR128Vertex;
typedef struct {
unsigned int *mask;
} drmR128Stipple;
typedef struct {
unsigned int flags;
unsigned int clear_color;
unsigned int clear_depth;
unsigned int color_mask;
unsigned int depth_mask;
} drmR128Clear;
typedef struct {
enum {
DRM_R128_INIT_FULLSCREEN = 0x01,
DRM_R128_CLEANUP_FULLSCREEN = 0x02
} func;
} drmR128Fullscreen;
typedef struct drm_r128_getparam {
int param;
void *value;
} drmR128GetParam;
#define R128_PARAM_IRQ_NR 1
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,103 @@
/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_dri.h,v 1.7 2002/10/30 12:52:12 alanh Exp $ */
/*
* Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario,
* Precision Insight, Inc., Cedar Park, Texas, and
* VA Linux Systems Inc., Fremont, California.
*
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation on the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NON-INFRINGEMENT. IN NO EVENT SHALL ATI, PRECISION INSIGHT, VA LINUX
* SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Authors:
* Kevin E. Martin <martin@valinux.com>
* Rickard E. Faith <faith@valinux.com>
* Gareth Hughes <gareth@valinux.com>
*
*/
#ifndef _R128_DRI_
#define _R128_DRI_
#include "xf86drm.h"
#include "r128_common.h"
/* DRI Driver defaults */
#define R128_DEFAULT_CCE_PIO_MODE R128_PM4_64PIO_64VCBM_64INDBM
#define R128_DEFAULT_CCE_BM_MODE R128_PM4_64BM_64VCBM_64INDBM
#define R128_DEFAULT_AGP_MODE 1
#define R128_DEFAULT_AGP_SIZE 8 /* MB (must be a power of 2 and > 4MB) */
#define R128_DEFAULT_RING_SIZE 1 /* MB (must be page aligned) */
#define R128_DEFAULT_BUFFER_SIZE 2 /* MB (must be page aligned) */
#define R128_DEFAULT_AGP_TEX_SIZE 1 /* MB (must be page aligned) */
#define R128_DEFAULT_CCE_TIMEOUT 10000 /* usecs */
#define R128_AGP_MAX_MODE 4
#define R128_BUFFER_ALIGN 0x00000fff
#define R128_CARD_TYPE_R128 1
#define R128_CARD_TYPE_R128_PRO 2
#define R128_CARD_TYPE_R128_MOBILITY 3
#define R128CCE_USE_RING_BUFFER(m) \
(((m) == R128_PM4_192BM) || \
((m) == R128_PM4_128BM_64INDBM) || \
((m) == R128_PM4_64BM_128INDBM) || \
((m) == R128_PM4_64BM_64VCBM_64INDBM))
typedef struct {
/* DRI screen private data */
int deviceID; /* PCI device ID */
int width; /* Width in pixels of display */
int height; /* Height in scanlines of display */
int depth; /* Depth of display (8, 15, 16, 24) */
int bpp; /* Bit depth of display (8, 16, 24, 32) */
int IsPCI; /* Current card is a PCI card */
int AGPMode;
int frontOffset; /* Start of front buffer */
int frontPitch;
int backOffset; /* Start of shared back buffer */
int backPitch;
int depthOffset; /* Start of shared depth buffer */
int depthPitch;
int spanOffset; /* Start of scratch spanline */
int textureOffset;/* Start of texture data in frame buffer */
int textureSize;
int log2TexGran;
/* MMIO register data */
drmHandle registerHandle;
drmSize registerSize;
/* CCE AGP Texture data */
drmHandle agpTexHandle;
drmSize agpTexMapSize;
int log2AGPTexGran;
int agpTexOffset;
unsigned int sarea_priv_offset;
} R128DRIRec, *R128DRIPtr;
#endif

View File

@ -0,0 +1,135 @@
/**
* \file server/R128_macros.h
* \brief Macros for R128 MMIO operation.
*
* \authors Kevin E. Martin <martin@xfree86.org>
* \authors Rickard E. Faith <faith@valinux.com>
* \authors Alan Hourihane <alanh@fairlite.demon.co.uk>
*/
/*
* Copyright 2000 ATI Technologies Inc., Markham, Ontario, and
* VA Linux Systems Inc., Fremont, California.
*
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation on the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR
* THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/R128_reg.h,v 1.20 2002/10/12 01:38:07 martin Exp $ */
#ifndef _R128_MACROS_H_
#define _R128_MACROS_H_
# define MMIO_IN8(base, offset) \
*(volatile unsigned char *)(((unsigned char*)(base)) + (offset))
# define MMIO_IN16(base, offset) \
*(volatile unsigned short *)(void *)(((unsigned char*)(base)) + (offset))
# define MMIO_IN32(base, offset) \
*(volatile unsigned int *)(void *)(((unsigned char*)(base)) + (offset))
# define MMIO_OUT8(base, offset, val) \
*(volatile unsigned char *)(((unsigned char*)(base)) + (offset)) = (val)
# define MMIO_OUT16(base, offset, val) \
*(volatile unsigned short *)(void *)(((unsigned char*)(base)) + (offset)) = (val)
# define MMIO_OUT32(base, offset, val) \
*(volatile unsigned int *)(void *)(((unsigned char*)(base)) + (offset)) = (val)
/* Memory mapped register access macros */
#define INREG8(addr) MMIO_IN8(R128MMIO, addr)
#define INREG16(addr) MMIO_IN16(R128MMIO, addr)
#define INREG(addr) MMIO_IN32(R128MMIO, addr)
#define OUTREG8(addr, val) MMIO_OUT8(R128MMIO, addr, val)
#define OUTREG16(addr, val) MMIO_OUT16(R128MMIO, addr, val)
#define OUTREG(addr, val) MMIO_OUT32(R128MMIO, addr, val)
#define ADDRREG(addr) ((volatile GLuint *)(pointer)(R128MMIO + (addr)))
#define OUTREGP(addr, val, mask) \
do { \
GLuint tmp = INREG(addr); \
tmp &= (mask); \
tmp |= (val); \
OUTREG(addr, tmp); \
} while (0)
#define INPLL(dpy, addr) r128INPLL(dpy, addr)
#define OUTPLL(addr, val) \
do { \
OUTREG8(R128_CLOCK_CNTL_INDEX, (((addr) & 0x3f) | \
R128_PLL_WR_EN)); \
OUTREG(R128_CLOCK_CNTL_DATA, val); \
} while (0)
#define OUTPLLP(dpy, addr, val, mask) \
do { \
GLuint tmp = INPLL(dpy, addr); \
tmp &= (mask); \
tmp |= (val); \
OUTPLL(addr, tmp); \
} while (0)
#define OUTPAL_START(idx) \
do { \
OUTREG8(R128_PALETTE_INDEX, (idx)); \
} while (0)
#define OUTPAL_NEXT(r, g, b) \
do { \
OUTREG(R128_PALETTE_DATA, ((r) << 16) | ((g) << 8) | (b)); \
} while (0)
#define OUTPAL_NEXT_CARD32(v) \
do { \
OUTREG(R128_PALETTE_DATA, (v & 0x00ffffff)); \
} while (0)
#define OUTPAL(idx, r, g, b) \
do { \
OUTPAL_START((idx)); \
OUTPAL_NEXT((r), (g), (b)); \
} while (0)
#define INPAL_START(idx) \
do { \
OUTREG(R128_PALETTE_INDEX, (idx) << 16); \
} while (0)
#define INPAL_NEXT() INREG(R128_PALETTE_DATA)
#define PAL_SELECT(idx) \
do { \
if (!idx) { \
OUTREG(R128_DAC_CNTL2, INREG(R128_DAC_CNTL2) & \
(GLuint)~R128_DAC2_PALETTE_ACC_CTL); \
} else { \
OUTREG(R128_DAC_CNTL2, INREG(R128_DAC_CNTL2) | \
R128_DAC2_PALETTE_ACC_CTL); \
} \
} while (0)
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,195 @@
/* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_sarea.h,v 1.7 2002/02/16 21:26:35 herrb Exp $ */
/*
* Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario,
* Precision Insight, Inc., Cedar Park, Texas, and
* VA Linux Systems Inc., Fremont, California.
*
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation on the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software,
* and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial
* portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NON-INFRINGEMENT. IN NO EVENT SHALL ATI, PRECISION INSIGHT, VA LINUX
* SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Authors:
* Kevin E. Martin <martin@valinux.com>
* Gareth Hughes <gareth@valinux.com>
*
*/
#ifndef _R128_SAREA_H_
#define _R128_SAREA_H_
/* WARNING: If you change any of these defines, make sure to change the
* defines in the kernel file (r128_drm.h)
*/
#ifndef __R128_SAREA_DEFINES__
#define __R128_SAREA_DEFINES__
/* What needs to be changed for the current vertex buffer?
*/
#define R128_UPLOAD_CONTEXT 0x001
#define R128_UPLOAD_SETUP 0x002
#define R128_UPLOAD_TEX0 0x004
#define R128_UPLOAD_TEX1 0x008
#define R128_UPLOAD_TEX0IMAGES 0x010
#define R128_UPLOAD_TEX1IMAGES 0x020
#define R128_UPLOAD_CORE 0x040
#define R128_UPLOAD_MASKS 0x080
#define R128_UPLOAD_WINDOW 0x100
#define R128_UPLOAD_CLIPRECTS 0x200 /* handled client-side */
#define R128_REQUIRE_QUIESCENCE 0x400
#define R128_UPLOAD_ALL 0x7ff
#define R128_FRONT 0x1
#define R128_BACK 0x2
#define R128_DEPTH 0x4
/* Primitive types
*/
#define R128_POINTS 0x1
#define R128_LINES 0x2
#define R128_LINE_STRIP 0x3
#define R128_TRIANGLES 0x4
#define R128_TRIANGLE_FAN 0x5
#define R128_TRIANGLE_STRIP 0x6
/* Vertex/indirect buffer size
*/
#define R128_BUFFER_SIZE 16384
/* Byte offsets for indirect buffer data
*/
#define R128_INDEX_PRIM_OFFSET 20
#define R128_HOSTDATA_BLIT_OFFSET 32
/* Keep these small for testing
*/
#define R128_NR_SAREA_CLIPRECTS 12
/* There are 2 heaps (local/AGP). Each region within a heap is a
* minimum of 64k, and there are at most 64 of them per heap.
*/
#define R128_CARD_HEAP 0
#define R128_AGP_HEAP 1
#define R128_NR_TEX_HEAPS 2
#define R128_NR_TEX_REGIONS 64
#define R128_LOG_TEX_GRANULARITY 16
#define R128_NR_CONTEXT_REGS 12
#define R128_MAX_TEXTURE_LEVELS 11
#define R128_MAX_TEXTURE_UNITS 2
#endif /* __R128_SAREA_DEFINES__ */
typedef struct {
/* Context state - can be written in one large chunk */
unsigned int dst_pitch_offset_c;
unsigned int dp_gui_master_cntl_c;
unsigned int sc_top_left_c;
unsigned int sc_bottom_right_c;
unsigned int z_offset_c;
unsigned int z_pitch_c;
unsigned int z_sten_cntl_c;
unsigned int tex_cntl_c;
unsigned int misc_3d_state_cntl_reg;
unsigned int texture_clr_cmp_clr_c;
unsigned int texture_clr_cmp_msk_c;
unsigned int fog_color_c;
/* Texture state */
unsigned int tex_size_pitch_c;
unsigned int constant_color_c;
/* Setup state */
unsigned int pm4_vc_fpu_setup;
unsigned int setup_cntl;
/* Mask state */
unsigned int dp_write_mask;
unsigned int sten_ref_mask_c;
unsigned int plane_3d_mask_c;
/* Window state */
unsigned int window_xy_offset;
/* Core state */
unsigned int scale_3d_cntl;
} r128_context_regs_t;
/* Setup registers for each texture unit
*/
typedef struct {
unsigned int tex_cntl;
unsigned int tex_combine_cntl;
unsigned int tex_size_pitch;
unsigned int tex_offset[R128_MAX_TEXTURE_LEVELS];
unsigned int tex_border_color;
} r128_texture_regs_t;
typedef struct {
/* The channel for communication of state information to the kernel
* on firing a vertex buffer.
*/
r128_context_regs_t ContextState;
r128_texture_regs_t TexState[R128_MAX_TEXTURE_UNITS];
unsigned int dirty;
unsigned int vertsize;
unsigned int vc_format;
#if defined(XF86DRI) | defined(_SOLO)
/* The current cliprects, or a subset thereof.
*/
XF86DRIClipRectRec boxes[R128_NR_SAREA_CLIPRECTS];
unsigned int nbox;
#endif
/* Counters for throttling of rendering clients.
*/
unsigned int last_frame;
unsigned int last_dispatch;
/* Maintain an LRU of contiguous regions of texture space. If you
* think you own a region of texture memory, and it has an age
* different to the one you set, then you are mistaken and it has
* been stolen by another client. If global texAge hasn't changed,
* there is no need to walk the list.
*
* These regions can be used as a proxy for the fine-grained texture
* information of other clients - by maintaining them in the same
* lru which is used to age their own textures, clients have an
* approximate lru for the whole of global texture space, and can
* make informed decisions as to which areas to kick out. There is
* no need to choose whether to kick out your own texture or someone
* else's - simply eject them all in LRU order.
*/
/* Last elt is sentinal */
drmTextureRegion texList[R128_NR_TEX_HEAPS][R128_NR_TEX_REGIONS+1];
/* last time texture was uploaded */
unsigned int texAge[R128_NR_TEX_HEAPS];
int ctxOwner; /* last context to upload state */
int pfAllowPageFlip; /* set by the 2d driver, read by the client */
int pfCurrentPage; /* set by kernel, read by others */
} R128SAREAPriv, *R128SAREAPrivPtr;
#endif

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