patch to import Jon Smirl's work from Bitkeeper
This commit is contained in:
parent
1a84876d79
commit
5df82c82bd
16
Make-config
16
Make-config
|
@ -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
|
||||
|
|
31
Makefile.X11
31
Makefile.X11
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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 */
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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)
|
||||
{
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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) ();
|
||||
}
|
|
@ -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
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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))
|
||||
{
|
||||
}
|
|
@ -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)
|
||||
{
|
||||
}
|
|
@ -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;
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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
|
|
@ -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)
|
||||
{
|
||||
}
|
|
@ -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 */
|
|
@ -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)
|
||||
{
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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 */
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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.
|
||||
|
||||
|
||||
|
|
@ -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 */
|
|
@ -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_ */
|
|
@ -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;
|
||||
}
|
||||
|
||||
/*@}*/
|
|
@ -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_ */
|
|
@ -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_ */
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -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
|
File diff suppressed because it is too large
Load Diff
|
@ -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_ */
|
|
@ -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 );
|
||||
}
|
|
@ -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
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
|
@ -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,6 +321,8 @@ 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.
|
||||
|
@ -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
|
||||
|
|
|
@ -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 =
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -32,6 +32,5 @@
|
|||
#include "context.h"
|
||||
|
||||
void mgaDDInitDriverFuncs( GLcontext *ctx );
|
||||
void mgaDDExtensionsInit( GLcontext *ctx );
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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_ */
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
@ -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
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -146,7 +146,7 @@ typedef struct {
|
|||
|
||||
typedef struct {
|
||||
int param;
|
||||
int *value;
|
||||
void *value;
|
||||
} drmMGAGetParam;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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__ */
|
|
@ -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;
|
||||
}
|
|
@ -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
|
|
@ -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;
|
||||
}
|
|
@ -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__ */
|
|
@ -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] );
|
||||
}
|
||||
}
|
|
@ -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__ */
|
|
@ -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
|
|
@ -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__ */
|
|
@ -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;
|
||||
}
|
|
@ -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
|
@ -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
|
|
@ -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 );
|
||||
}
|
|
@ -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__ */
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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_ */
|
|
@ -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 );
|
||||
}
|
|
@ -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 ); */
|
||||
}
|
|
@ -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__ */
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
@ -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
|
|
@ -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
|
@ -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
Loading…
Reference in New Issue