Subversion Repositories shark

Compare Revisions

Ignore whitespace Rev 55 → Rev 56

/shark/trunk/ports/mesa/src-glut.dos/pc_hw/pc_hw.c
0,0 → 1,148
/*
* PC/HW routine collection v1.2 for DOS/DJGPP
*
* Copyright (C) 2002 - Borca Daniel
* Email : dborca@yahoo.com
* Web : http://www.geocities.com/dborca
*/
 
 
#include <dpmi.h>
#include <fcntl.h>
#include <sys/stat.h> /* for mode definitions */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
 
#include "pc_hw.h"
 
/*
* atexit
*/
#define MAX_ATEXIT 32
 
static volatile int atexitcnt;
static VFUNC atexittbl[MAX_ATEXIT];
 
static void __attribute__((destructor)) doexit (void)
{
while (atexitcnt) atexittbl[--atexitcnt]();
}
 
int pc_clexit (VFUNC f)
{
int i;
 
for (i=0;i<atexitcnt;i++) {
if (atexittbl[i]==f) {
for (atexitcnt--;i<atexitcnt;i++) atexittbl[i] = atexittbl[i+1];
atexittbl[i] = 0;
return 0;
}
}
return -1;
}
 
int pc_atexit (VFUNC f)
{
pc_clexit(f);
if (atexitcnt<MAX_ATEXIT) {
atexittbl[atexitcnt++] = f;
return 0;
}
return -1;
}
 
/*
* locked memory allocation
*/
void *pc_malloc (size_t size)
{
void *p = malloc(size);
 
if (p) {
if (_go32_dpmi_lock_data(p, size)) {
free(p);
return NULL;
}
}
 
return p;
}
 
/*
* standard redirection
*/
static int h_out, h_outbak, h_err, h_errbak;
 
int pc_open_stdout (void)
{
if ((h_out=open(tmpnam(NULL), O_WRONLY | O_CREAT | O_TRUNC | O_TEXT | O_TEMPORARY, S_IRUSR | S_IWUSR)) >= 0) {
if ((h_outbak=dup(1)) != -1) {
fflush(stdout);
if (dup2(h_out, 1) != -1) {
return 0;
}
close(h_outbak);
}
close(h_out);
}
return (h_out = -1);
}
 
void pc_close_stdout (void)
{
FILE *f;
char *line = alloca(512);
 
if (h_out >= 0) {
dup2(h_outbak, 1);
close(h_outbak);
 
if ((f=fdopen(h_out, "r")) != NULL) {
fseek(f, 0, SEEK_SET);
while (fgets(line, 512, f)) {
fputs(line, stdout);
}
fclose(f);
} else {
close(h_out);
}
}
}
 
int pc_open_stderr (void)
{
if ((h_err=open(tmpnam(NULL), O_WRONLY | O_CREAT | O_TRUNC | O_TEXT | O_TEMPORARY, S_IRUSR | S_IWUSR)) >= 0) {
if ((h_errbak=dup(2)) != -1) {
fflush(stderr);
if (dup2(h_err, 2) != -1) {
return 0;
}
close(h_errbak);
}
close(h_err);
}
return (h_err = -1);
}
 
void pc_close_stderr (void)
{
FILE *f;
char *line = alloca(512);
 
if (h_err >= 0) {
dup2(h_errbak, 2);
close(h_errbak);
 
if ((f=fdopen(h_err, "r")) != NULL) {
fseek(f, 0, SEEK_SET);
while (fgets(line, 512, f)) {
fputs(line, stderr);
}
fclose(f);
} else {
close(h_err);
}
}
}
/shark/trunk/ports/mesa/src-glut.dos/pc_hw/pc_timer.c
0,0 → 1,158
/*
* PC/HW routine collection v1.0 for DOS/DJGPP
*
* Copyright (C) 2002 - Borca Daniel
* Email : dborca@yahoo.com
* Web : http://www.geocities.com/dborca
*/
 
 
#include <pc.h>
 
#include "pc_hw.h"
 
#define TIMER_IRQ 0
 
#define MAX_TIMERS 8
 
#define PIT_FREQ 0x1234DD
 
#define unvolatile(__v, __t) __extension__ ({union { volatile __t __cp; __t __p; } __q; __q.__cp = __v; __q.__p;})
 
static int timer_installed;
 
typedef struct {
volatile unsigned int counter, clock_ticks, freq;
volatile PFUNC func;
volatile void *parm;
} TIMER;
 
TIMER timer_main, timer_func[MAX_TIMERS];
 
static int timer ()
{
int i;
 
for (i=0;i<MAX_TIMERS;i++) {
TIMER *t = &timer_func[i];
if (t->func) {
t->clock_ticks += t->counter;
if (t->clock_ticks>=timer_main.counter) {
t->clock_ticks -= timer_main.counter;
t->func(unvolatile(t->parm, void *));
}
}
}
 
timer_main.clock_ticks += timer_main.counter;
if (timer_main.clock_ticks>=0x10000) {
timer_main.clock_ticks -= 0x10000;
return 1;
} else {
outportb(0x20, 0x20);
return 0;
}
} ENDOFUNC(timer)
 
void pc_remove_timer (void)
{
if (timer_installed) {
timer_installed = FALSE;
pc_clexit(pc_remove_timer);
 
DISABLE();
outportb(0x43, 0x34);
outportb(0x40, 0);
outportb(0x40, 0);
ENABLE();
 
pc_remove_irq(TIMER_IRQ);
}
}
 
static int install_timer (void)
{
if (timer_installed||pc_install_irq(TIMER_IRQ, timer)) {
return -1;
} else {
LOCKDATA(timer_func);
LOCKDATA(timer_main);
LOCKFUNC(timer);
 
timer_main.counter = 0x10000;
 
DISABLE();
outportb(0x43, 0x34);
outportb(0x40, 0);
outportb(0x40, 0);
timer_main.clock_ticks = 0;
ENABLE();
 
pc_atexit(pc_remove_timer);
timer_installed = TRUE;
return 0;
}
}
 
static TIMER *find_slot (PFUNC func)
{
int i;
 
for (i=0;i<MAX_TIMERS;i++) {
if (timer_func[i].func==func) {
return &timer_func[i];
}
}
for (i=0;i<MAX_TIMERS;i++) {
if (!timer_func[i].func) {
return &timer_func[i];
}
}
 
return NULL;
}
 
int pc_install_int (PFUNC func, void *parm, unsigned int freq)
{
int i;
TIMER *t;
 
if (!timer_installed) {
if (install_timer()) {
return -1;
}
}
 
if ((t=find_slot(func))!=NULL) {
unsigned int new_counter = PIT_FREQ / freq;
 
DISABLE();
 
t->func = func;
t->parm = parm;
t->freq = freq;
t->clock_ticks = 0;
 
if (new_counter < timer_main.counter) {
for (i=0;i<MAX_TIMERS;i++) {
if (timer_func[i].func) {
timer_func[i].counter = new_counter * timer_func[i].freq / freq;
}
}
outportb(0x43, 0x34);
outportb(0x40, (unsigned char)new_counter);
outportb(0x40, (unsigned char)(new_counter>>8));
timer_main.clock_ticks = 0;
timer_main.counter = new_counter;
timer_main.freq = freq;
} else {
t->counter = PIT_FREQ * freq / (timer_main.freq * timer_main.freq);
}
 
ENABLE();
 
return 0;
}
return -1;
}
/shark/trunk/ports/mesa/src-glut.dos/pc_hw/pc_hw.h
0,0 → 1,225
/*
* PC/HW routine collection v1.2 for DOS/DJGPP
*
* Copyright (C) 2002 - Borca Daniel
* Email : dborca@yahoo.com
* Web : http://www.geocities.com/dborca
*/
 
 
#ifndef PC_HW_H_included
#define PC_HW_H_included
 
//#include <dpmi.h> //SHARK
#include <stdlib.h>
 
/*
* misc C definitions
*/
#define FALSE 0
#define TRUE !FALSE
 
#define MIN(x,y) (((x) < (y)) ? (x) : (y))
#define MAX(x,y) (((x) > (y)) ? (x) : (y))
#define MID(x,y,z) MAX((x), MIN((y), (z)))
 
typedef void (*VFUNC) (void);
typedef void (*PFUNC) (void *);
typedef void (*MFUNC) (int x, int y, int b);
 
/*
* atexit
*/
int pc_atexit (VFUNC f);
int pc_clexit (VFUNC f);
 
/*
* locked memory
*/
#define ENDOFUNC(x) static void x##_end() { }
#define LOCKFUNC(x) _go32_dpmi_lock_code((void *)x, (long)x##_end - (long)x)
#define LOCKDATA(x) _go32_dpmi_lock_data((void *)&x, sizeof(x))
 
void *pc_malloc (size_t size);
 
/*
* IRQ
*/
#define ENABLE() __asm __volatile ("sti")
#define DISABLE() __asm __volatile ("cli")
 
extern int pc_install_irq (int i, int (*handler) ());
extern int pc_remove_irq (int i);
 
/*
* keyboard
*/
#define KB_SHIFT_FLAG 0x0001
#define KB_CTRL_FLAG 0x0002
#define KB_ALT_FLAG 0x0004
#define KB_LWIN_FLAG 0x0008
#define KB_RWIN_FLAG 0x0010
#define KB_MENU_FLAG 0x0020
#define KB_SCROLOCK_FLAG 0x0100
#define KB_NUMLOCK_FLAG 0x0200
#define KB_CAPSLOCK_FLAG 0x0400
#define KB_INALTSEQ_FLAG 0x0800
#define KB_ACCENT1_FLAG 0x1000
#define KB_ACCENT2_FLAG 0x2000
#define KB_ACCENT3_FLAG 0x4000
#define KB_ACCENT4_FLAG 0x8000
 
#define KEY_A 1
#define KEY_B 2
#define KEY_C 3
#define KEY_D 4
#define KEY_E 5
#define KEY_F 6
#define KEY_G 7
#define KEY_H 8
#define KEY_I 9
#define KEY_J 10
#define KEY_K 11
#define KEY_L 12
#define KEY_M 13
#define KEY_N 14
#define KEY_O 15
#define KEY_P 16
#define KEY_Q 17
#define KEY_R 18
#define KEY_S 19
#define KEY_T 20
#define KEY_U 21
#define KEY_V 22
#define KEY_W 23
#define KEY_X 24
#define KEY_Y 25
#define KEY_Z 26
#define KEY_0 27
#define KEY_1 28
#define KEY_2 29
#define KEY_3 30
#define KEY_4 31
#define KEY_5 32
#define KEY_6 33
#define KEY_7 34
#define KEY_8 35
#define KEY_9 36
#define KEY_0_PAD 37
#define KEY_1_PAD 38
#define KEY_2_PAD 39
#define KEY_3_PAD 40
#define KEY_4_PAD 41
#define KEY_5_PAD 42
#define KEY_6_PAD 43
#define KEY_7_PAD 44
#define KEY_8_PAD 45
#define KEY_9_PAD 46
#define KEY_F1 47
#define KEY_F2 48
#define KEY_F3 49
#define KEY_F4 50
#define KEY_F5 51
#define KEY_F6 52
#define KEY_F7 53
#define KEY_F8 54
#define KEY_F9 55
#define KEY_F10 56
#define KEY_F11 57
#define KEY_F12 58
#define KEY_ESC 59
#define KEY_TILDE 60
#define KEY_MINUS 61
#define KEY_EQUALS 62
#define KEY_BACKSPACE 63
#define KEY_TAB 64
#define KEY_OPENBRACE 65
#define KEY_CLOSEBRACE 66
#define KEY_ENTER 67
#define KEY_COLON 68
#define KEY_QUOTE 69
#define KEY_BACKSLASH 70
#define KEY_BACKSLASH2 71
#define KEY_COMMA 72
#define KEY_STOP 73
#define KEY_SLASH 74
#define KEY_SPACE 75
#define KEY_INSERT 76
#define KEY_DEL 77
#define KEY_HOME 78
#define KEY_END 79
#define KEY_PGUP 80
#define KEY_PGDN 81
#define KEY_LEFT 82
#define KEY_RIGHT 83
#define KEY_UP 84
#define KEY_DOWN 85
#define KEY_SLASH_PAD 86
#define KEY_ASTERISK 87
#define KEY_MINUS_PAD 88
#define KEY_PLUS_PAD 89
#define KEY_DEL_PAD 90
#define KEY_ENTER_PAD 91
#define KEY_PRTSCR 92
#define KEY_PAUSE 93
#define KEY_ABNT_C1 94
#define KEY_YEN 95
#define KEY_KANA 96
#define KEY_CONVERT 97
#define KEY_NOCONVERT 98
#define KEY_AT 99
#define KEY_CIRCUMFLEX 100
#define KEY_COLON2 101
#define KEY_KANJI 102
 
#define KEY_MODIFIERS 103
 
#define KEY_LSHIFT 103
#define KEY_RSHIFT 104
#define KEY_LCONTROL 105
#define KEY_RCONTROL 106
#define KEY_ALT 107
#define KEY_ALTGR 108
#define KEY_LWIN 109
#define KEY_RWIN 110
#define KEY_MENU 111
#define KEY_SCRLOCK 112
#define KEY_NUMLOCK 113
#define KEY_CAPSLOCK 114
 
#define KEY_MAX 115
 
int pc_install_keyb (void);
void pc_remove_keyb (void);
int pc_keypressed (void);
int pc_readkey (void);
int pc_keydown (int code);
 
/*
* timer
*/
int pc_install_int (PFUNC func, void *parm, unsigned int freq);
void pc_remove_timer (void);
 
/*
* mouse
*/
int pc_install_mouse (void);
void pc_remove_mouse (void);
MFUNC pc_install_mouse_handler (MFUNC handler);
void pc_mouse_area (int x1, int y1, int x2, int y2);
void pc_mouse_speed (int xspeed, int yspeed);
int pc_query_mouse (int *x, int *y);
void pc_show_mouse (void);
void pc_scare_mouse (void);
void pc_unscare_mouse (void);
 
/*
* standard redirection
*/
int pc_open_stdout (void);
int pc_open_stderr (void);
void pc_close_stdout (void);
void pc_close_stderr (void);
 
#endif
/shark/trunk/ports/mesa/src-glut.dos/pc_hw/pc_mouse.c
0,0 → 1,258
/*
* PC/HW routine collection v1.2 for DOS/DJGPP
*
* Copyright (C) 2002 - Borca Daniel
* Email : dborca@yahoo.com
* Web : http://www.geocities.com/dborca
*/
 
 
#include <dpmi.h>
 
#include "pc_hw.h"
 
 
 
#define MOUSE_STACK_SIZE 16384
 
#define CLEAR_MICKEYS() \
do { \
__asm __volatile ("movw $0xb, %%ax; int $0x33":::"%eax", "%ecx", "%edx"); \
ox = oy = 0; \
} while (0)
 
extern void mouse_wrapper (void);
extern void mouse_wrapper_end (void);
 
static MFUNC mouse_func;
static void *mouse_stack;
static long mouse_callback;
static __dpmi_regs mouse_regs;
 
static volatile int pc_mouse_x, pc_mouse_y, pc_mouse_b;
 
static int minx = 0;
static int maxx = 319;
static int miny = 0;
static int maxy = 199;
 
static int sx = 2;
static int sy = 2;
 
static int emulat3 = FALSE;
 
static int ox, oy;
 
static void mouse (__dpmi_regs *r)
{
int nx = (signed short)r->x.si / sx;
int ny = (signed short)r->x.di / sy;
int dx = nx - ox;
int dy = ny - oy;
ox = nx;
oy = ny;
 
pc_mouse_b = r->x.bx;
pc_mouse_x = MID(minx, pc_mouse_x + dx, maxx);
pc_mouse_y = MID(miny, pc_mouse_y + dy, maxy);
 
if (emulat3) {
if ((pc_mouse_b&3)==3) {
pc_mouse_b = 4;
}
}
 
if (mouse_func) {
mouse_func(pc_mouse_x, pc_mouse_y, pc_mouse_b);
}
} ENDOFUNC(mouse)
 
void pc_remove_mouse (void)
{
if (mouse_callback) {
pc_clexit(pc_remove_mouse);
__asm("\n\
movl %%edx, %%ecx \n\
shrl $16, %%ecx \n\
movw $0x0304, %%ax \n\
int $0x31 \n\
movw $0x000c, %%ax \n\
xorl %%ecx, %%ecx \n\
int $0x33 \n\
"::"d"(mouse_callback):"%eax", "%ecx");
 
mouse_callback = 0;
 
free((void *)((unsigned long)mouse_stack-MOUSE_STACK_SIZE));
}
}
 
int pc_install_mouse (void)
{
int buttons;
 
/* fail if already call-backed */
if (mouse_callback) {
return 0;
}
 
/* reset mouse and get status */
__asm("\n\
xorl %%eax, %%eax \n\
int $0x33 \n\
andl %%ebx, %%eax \n\
movl %%eax, %0 \n\
":"=g" (buttons)::"%eax", "%ebx");
if (!buttons) {
return 0;
}
 
/* lock wrapper */
LOCKDATA(mouse_func);
LOCKDATA(mouse_stack);
LOCKDATA(mouse_callback);
LOCKDATA(mouse_regs);
LOCKDATA(pc_mouse_x);
LOCKDATA(pc_mouse_y);
LOCKDATA(pc_mouse_b);
LOCKDATA(minx);
LOCKDATA(maxx);
LOCKDATA(miny);
LOCKDATA(maxy);
LOCKDATA(sx);
LOCKDATA(sy);
LOCKDATA(emulat3);
LOCKDATA(ox);
LOCKDATA(oy);
LOCKFUNC(mouse);
LOCKFUNC(mouse_wrapper);
 
/* grab a locked stack */
if ((mouse_stack=pc_malloc(MOUSE_STACK_SIZE))==NULL) {
return 0;
}
 
/* try to hook a call-back */
__asm("\n\
pushl %%ds \n\
pushl %%es \n\
movw $0x0303, %%ax \n\
pushl %%ds \n\
pushl %%cs \n\
popl %%ds \n\
popl %%es \n\
int $0x31 \n\
popl %%es \n\
popl %%ds \n\
jc 0f \n\
shll $16, %%ecx \n\
movw %%dx, %%cx \n\
movl %%ecx, %0 \n\
0: \n\
":"=g"(mouse_callback)
:"S" (mouse_wrapper), "D"(&mouse_regs)
:"%eax", "%ecx", "%edx");
if (!mouse_callback) {
free(mouse_stack);
return 0;
}
 
/* adjust stack */
mouse_stack = (void *)((unsigned long)mouse_stack + MOUSE_STACK_SIZE);
 
/* install the handler */
mouse_regs.x.ax = 0x000c;
mouse_regs.x.cx = 0x007f;
mouse_regs.x.dx = mouse_callback&0xffff;
mouse_regs.x.es = mouse_callback>>16;
__dpmi_int(0x33, &mouse_regs);
 
CLEAR_MICKEYS();
 
emulat3 = buttons<3;
pc_atexit(pc_remove_mouse);
return buttons;
}
 
MFUNC pc_install_mouse_handler (MFUNC handler)
{
MFUNC old;
 
if (!mouse_callback && !pc_install_mouse()) {
return NULL;
}
 
old = mouse_func;
mouse_func = handler;
return old;
}
 
void pc_mouse_area (int x1, int y1, int x2, int y2)
{
minx = x1;
maxx = x2;
miny = y1;
maxy = y2;
}
 
void pc_mouse_speed (int xspeed, int yspeed)
{
DISABLE();
 
sx = MAX(1, xspeed);
sy = MAX(1, yspeed);
 
ENABLE();
}
 
int pc_query_mouse (int *x, int *y)
{
*x = pc_mouse_x;
*y = pc_mouse_y;
return pc_mouse_b;
}
 
void pc_show_mouse (void)
{
/* not implemented */
}
void pc_scare_mouse (void)
{
/* not implemented */
}
void pc_unscare_mouse (void)
{
/* not implemented */
}
 
__asm("\n\
.text \n\
.balign 4 \n\
.global _mouse_wrapper \n\
_mouse_wrapper: \n\
cld \n\
lodsl \n\
movl %eax, %es:42(%edi) \n\
addw $4, %es:46(%edi) \n\
pushl %es \n\
movl %ss, %ebx \n\
movl %esp, %esi \n\
movl %cs:___djgpp_ds_alias, %ss \n\
movl %cs:_mouse_stack, %esp \n\
pushl %ss \n\
pushl %ss \n\
popl %es \n\
popl %ds \n\
movl ___djgpp_dos_sel, %fs \n\
pushl %fs \n\
popl %gs \n\
pushl %edi \n\
call _mouse \n\
popl %edi \n\
movl %ebx, %ss \n\
movl %esi, %esp \n\
popl %es \n\
iret \n\
.balign 4 \n\
.global _mouse_wrapper_end \n\
_mouse_wrapper_end:");
/shark/trunk/ports/mesa/src-glut.dos/pc_hw/pc_keyb.c
0,0 → 1,541
/*
* PC/HW routine collection v1.1 for DOS/DJGPP
*
* Copyright (C) 2002 - Borca Daniel
* Email : dborca@yahoo.com
* Web : http://www.geocities.com/dborca
*/
 
 
#include <pc.h>
#include <sys/exceptn.h>
#include <sys/farptr.h>
 
#include "pc_hw.h"
 
 
 
#define KEYB_IRQ 1
 
#define KEY_BUFFER_SIZE 64
 
#define KB_MODIFIERS (KB_SHIFT_FLAG | KB_CTRL_FLAG | KB_ALT_FLAG | KB_LWIN_FLAG | KB_RWIN_FLAG | KB_MENU_FLAG)
#define KB_LED_FLAGS (KB_SCROLOCK_FLAG | KB_NUMLOCK_FLAG | KB_CAPSLOCK_FLAG)
 
static int keyboard_installed;
 
static volatile struct {
volatile int start, end;
volatile int key[KEY_BUFFER_SIZE];
} key_buffer;
 
static volatile int key_enhanced, key_pause_loop, key_shifts;
static int leds_ok = TRUE;
static int in_a_terrupt = FALSE;
static volatile char pc_key[KEY_MAX];
 
 
 
/* convert Allegro format scancodes into key_shifts flag bits */
static unsigned short modifier_table[KEY_MAX - KEY_MODIFIERS] =
{
KB_SHIFT_FLAG, KB_SHIFT_FLAG, KB_CTRL_FLAG,
KB_CTRL_FLAG, KB_ALT_FLAG, KB_ALT_FLAG,
KB_LWIN_FLAG, KB_RWIN_FLAG, KB_MENU_FLAG,
KB_SCROLOCK_FLAG, KB_NUMLOCK_FLAG, KB_CAPSLOCK_FLAG
};
 
 
 
/* lookup table for converting hardware scancodes into Allegro format */
static unsigned char hw_to_mycode[128] =
{
/* 0x00 */ 0, KEY_ESC, KEY_1, KEY_2,
/* 0x04 */ KEY_3, KEY_4, KEY_5, KEY_6,
/* 0x08 */ KEY_7, KEY_8, KEY_9, KEY_0,
/* 0x0C */ KEY_MINUS, KEY_EQUALS, KEY_BACKSPACE, KEY_TAB,
/* 0x10 */ KEY_Q, KEY_W, KEY_E, KEY_R,
/* 0x14 */ KEY_T, KEY_Y, KEY_U, KEY_I,
/* 0x18 */ KEY_O, KEY_P, KEY_OPENBRACE, KEY_CLOSEBRACE,
/* 0x1C */ KEY_ENTER, KEY_LCONTROL, KEY_A, KEY_S,
/* 0x20 */ KEY_D, KEY_F, KEY_G, KEY_H,
/* 0x24 */ KEY_J, KEY_K, KEY_L, KEY_COLON,
/* 0x28 */ KEY_QUOTE, KEY_TILDE, KEY_LSHIFT, KEY_BACKSLASH,
/* 0x2C */ KEY_Z, KEY_X, KEY_C, KEY_V,
/* 0x30 */ KEY_B, KEY_N, KEY_M, KEY_COMMA,
/* 0x34 */ KEY_STOP, KEY_SLASH, KEY_RSHIFT, KEY_ASTERISK,
/* 0x38 */ KEY_ALT, KEY_SPACE, KEY_CAPSLOCK, KEY_F1,
/* 0x3C */ KEY_F2, KEY_F3, KEY_F4, KEY_F5,
/* 0x40 */ KEY_F6, KEY_F7, KEY_F8, KEY_F9,
/* 0x44 */ KEY_F10, KEY_NUMLOCK, KEY_SCRLOCK, KEY_7_PAD,
/* 0x48 */ KEY_8_PAD, KEY_9_PAD, KEY_MINUS_PAD, KEY_4_PAD,
/* 0x4C */ KEY_5_PAD, KEY_6_PAD, KEY_PLUS_PAD, KEY_1_PAD,
/* 0x50 */ KEY_2_PAD, KEY_3_PAD, KEY_0_PAD, KEY_DEL_PAD,
/* 0x54 */ KEY_PRTSCR, 0, KEY_BACKSLASH2, KEY_F11,
/* 0x58 */ KEY_F12, 0, 0, KEY_LWIN,
/* 0x5C */ KEY_RWIN, KEY_MENU, 0, 0,
/* 0x60 */ 0, 0, 0, 0,
/* 0x64 */ 0, 0, 0, 0,
/* 0x68 */ 0, 0, 0, 0,
/* 0x6C */ 0, 0, 0, 0,
/* 0x70 */ KEY_KANA, 0, 0, KEY_ABNT_C1,
/* 0x74 */ 0, 0, 0, 0,
/* 0x78 */ 0, KEY_CONVERT, 0, KEY_NOCONVERT,
/* 0x7C */ 0, KEY_YEN, 0, 0
};
 
 
 
/* lookup table for converting extended hardware codes into Allegro format */
static unsigned char hw_to_mycode_ex[128] =
{
/* 0x00 */ 0, KEY_ESC, KEY_1, KEY_2,
/* 0x04 */ KEY_3, KEY_4, KEY_5, KEY_6,
/* 0x08 */ KEY_7, KEY_8, KEY_9, KEY_0,
/* 0x0C */ KEY_MINUS, KEY_EQUALS, KEY_BACKSPACE, KEY_TAB,
/* 0x10 */ KEY_CIRCUMFLEX, KEY_AT, KEY_COLON2, KEY_R,
/* 0x14 */ KEY_KANJI, KEY_Y, KEY_U, KEY_I,
/* 0x18 */ KEY_O, KEY_P, KEY_OPENBRACE, KEY_CLOSEBRACE,
/* 0x1C */ KEY_ENTER_PAD, KEY_RCONTROL, KEY_A, KEY_S,
/* 0x20 */ KEY_D, KEY_F, KEY_G, KEY_H,
/* 0x24 */ KEY_J, KEY_K, KEY_L, KEY_COLON,
/* 0x28 */ KEY_QUOTE, KEY_TILDE, 0, KEY_BACKSLASH,
/* 0x2C */ KEY_Z, KEY_X, KEY_C, KEY_V,
/* 0x30 */ KEY_B, KEY_N, KEY_M, KEY_COMMA,
/* 0x34 */ KEY_STOP, KEY_SLASH_PAD, 0, KEY_PRTSCR,
/* 0x38 */ KEY_ALTGR, KEY_SPACE, KEY_CAPSLOCK, KEY_F1,
/* 0x3C */ KEY_F2, KEY_F3, KEY_F4, KEY_F5,
/* 0x40 */ KEY_F6, KEY_F7, KEY_F8, KEY_F9,
/* 0x44 */ KEY_F10, KEY_NUMLOCK, KEY_PAUSE, KEY_HOME,
/* 0x48 */ KEY_UP, KEY_PGUP, KEY_MINUS_PAD, KEY_LEFT,
/* 0x4C */ KEY_5_PAD, KEY_RIGHT, KEY_PLUS_PAD, KEY_END,
/* 0x50 */ KEY_DOWN, KEY_PGDN, KEY_INSERT, KEY_DEL,
/* 0x54 */ KEY_PRTSCR, 0, KEY_BACKSLASH2, KEY_F11,
/* 0x58 */ KEY_F12, 0, 0, KEY_LWIN,
/* 0x5C */ KEY_RWIN, KEY_MENU, 0, 0,
/* 0x60 */ 0, 0, 0, 0,
/* 0x64 */ 0, 0, 0, 0,
/* 0x68 */ 0, 0, 0, 0,
/* 0x6C */ 0, 0, 0, 0,
/* 0x70 */ 0, 0, 0, 0,
/* 0x74 */ 0, 0, 0, 0,
/* 0x78 */ 0, 0, 0, 0,
/* 0x7C */ 0, 0, 0, 0
};
 
 
 
/* default mapping table for the US keyboard layout */
static unsigned short standard_key_ascii_table[KEY_MAX] =
{
/* start */ 0,
/* alphabet */ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
/* numbers */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
/* numpad */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
/* func keys */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
/* misc chars */ 27, '`', '-', '=', 8, 9, '[', ']', 13, ';', '\'', '\\', '\\', ',', '.', '/', ' ',
/* controls */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
/* numpad */ '/', '*', '-', '+', '.', 13,
/* modifiers */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
 
 
 
/* capslock mapping table for the US keyboard layout */
static unsigned short standard_key_capslock_table[KEY_MAX] =
{
/* start */ 0,
/* alphabet */ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
/* numbers */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
/* numpad */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
/* func keys */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
/* misc chars */ 27, '`', '-', '=', 8, 9, '[', ']', 13, ';', '\'', '\\', '\\', ',', '.', '/', ' ',
/* controls */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
/* numpad */ '/', '*', '-', '+', '.', 13,
/* modifiers */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
 
 
 
/* shifted mapping table for the US keyboard layout */
static unsigned short standard_key_shift_table[KEY_MAX] =
{
/* start */ 0,
/* alphabet */ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
/* numbers */ ')', '!', '@', '#', '$', '%', '^', '&', '*', '(',
/* numpad */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
/* func keys */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
/* misc chars */ 27, '~', '_', '+', 8, 9, '{', '}', 13, ':', '"', '|', '|', '<', '>', '?', ' ',
/* controls */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
/* numpad */ '/', '*', '-', '+', '.', 13,
/* modifiers */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
 
 
 
/* ctrl+key mapping table for the US keyboard layout */
static unsigned short standard_key_control_table[KEY_MAX] =
{
/* start */ 0,
/* alphabet */ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
/* numbers */ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
/* numpad */ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
/* func keys */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
/* misc chars */ 27, 2, 2, 2, 127, 127, 2, 2, 10, 2, 2, 2, 2, 2, 2, 2, 2,
/* controls */ 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF,
/* numpad */ 2, 2, 2, 2, 2, 10,
/* modifiers */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
 
 
 
/* convert numeric pad scancodes into arrow codes */
static unsigned char numlock_table[10] =
{
KEY_INSERT, KEY_END, KEY_DOWN, KEY_PGDN, KEY_LEFT,
KEY_5_PAD, KEY_RIGHT, KEY_HOME, KEY_UP, KEY_PGUP
};
 
 
 
/* kb_wait_for_write_ready:
* Wait for the keyboard controller to set the ready-for-write bit.
*/
static __inline int kb_wait_for_write_ready (void)
{
int timeout = 4096;
 
while ((timeout>0) && (inportb(0x64)&2)) timeout--;
 
return (timeout>0);
}
 
 
 
/* kb_wait_for_read_ready:
* Wait for the keyboard controller to set the ready-for-read bit.
*/
static __inline int kb_wait_for_read_ready (void)
{
int timeout = 16384;
 
while ((timeout>0) && (!(inportb(0x64)&1))) timeout--;
 
return (timeout>0);
}
 
 
 
/* kb_send_data:
* Sends a byte to the keyboard controller. Returns 1 if all OK.
*/
static __inline int kb_send_data (unsigned char data)
{
int resends = 4;
int timeout, temp;
 
do {
if (!kb_wait_for_write_ready())
return 0;
 
outportb(0x60, data);
timeout = 4096;
 
while (--timeout>0) {
if (!kb_wait_for_read_ready())
return 0;
 
temp = inportb(0x60);
 
if (temp == 0xFA)
return 1;
 
if (temp == 0xFE)
break;
}
} while ((resends-- > 0) && (timeout > 0));
 
return 0;
}
 
 
 
static void update_leds (int leds)
{
if (leds_ok) {
if (!in_a_terrupt)
DISABLE();
 
if (!kb_send_data(0xED)) {
kb_send_data(0xF4);
leds_ok = FALSE;
} else if (!kb_send_data((leds>>8)&7)) {
kb_send_data(0xF4);
leds_ok = FALSE;
}
 
if (!in_a_terrupt)
ENABLE();
}
} ENDOFUNC(update_leds)
 
 
 
static void inject_key (int scancode)
{
unsigned short *table;
 
if ((scancode >= KEY_0_PAD) && (scancode <= KEY_9_PAD)) {
if (((key_shifts & KB_NUMLOCK_FLAG) != 0) == ((key_shifts & KB_SHIFT_FLAG) != 0)) {
scancode = numlock_table[scancode - KEY_0_PAD];
}
table = standard_key_ascii_table;
} else if (key_shifts & KB_CTRL_FLAG) {
table = standard_key_control_table;
} else if (key_shifts & KB_SHIFT_FLAG) {
if (key_shifts & KB_CAPSLOCK_FLAG) {
if (standard_key_ascii_table[scancode]==standard_key_capslock_table[scancode]) {
table = standard_key_shift_table;
} else {
table = standard_key_ascii_table;
}
} else {
table = standard_key_shift_table;
}
} else if (key_shifts & KB_CAPSLOCK_FLAG) {
table = standard_key_capslock_table;
} else {
table = standard_key_ascii_table;
}
 
key_buffer.key[key_buffer.end++] = (scancode<<16)|table[scancode];
 
if (key_buffer.end>=KEY_BUFFER_SIZE)
key_buffer.end = 0;
if (key_buffer.end==key_buffer.start) {
key_buffer.start++;
if (key_buffer.start>=KEY_BUFFER_SIZE)
key_buffer.start = 0;
}
} ENDOFUNC(inject_key)
 
static void handle_code (int scancode, int keycode)
{
in_a_terrupt++;
 
if (keycode==0) { /* pause */
inject_key(scancode);
pc_key[KEY_PAUSE] ^= TRUE;
} else if (scancode) {
int flag;
if (scancode>=KEY_MODIFIERS) {
flag = modifier_table[scancode - KEY_MODIFIERS];
} else {
flag = 0;
}
if ((char)keycode<0) { /* release */
pc_key[scancode] = FALSE;
if (flag&KB_MODIFIERS) {
key_shifts &= ~flag;
}
} else { /* keypress */
pc_key[scancode] = TRUE;
if (flag&KB_MODIFIERS) {
key_shifts |= flag;
}
if (flag&KB_LED_FLAGS) {
key_shifts ^= flag;
update_leds(key_shifts);
}
if (scancode<KEY_MODIFIERS) {
inject_key(scancode);
}
}
}
 
in_a_terrupt--;
} ENDOFUNC(handle_code)
 
static __inline void satisfy (void)
{
__asm("\n\
inb $0x61, %%al \n\
movb %%al, %%ah \n\
orb $0x80, %%al \n\
outb %%al, $0x61 \n\
xchgb %%al, %%ah \n\
outb %%al, $0x61 \n\
movb $0x20, %%al \n\
outb %%al, $0x20 \n\
":::"%eax");
}
 
static int keyboard ()
{
unsigned char temp, scancode;
 
temp = inportb(0x60);
 
if (temp<=0xe1) {
if (key_pause_loop) {
if (!--key_pause_loop) handle_code(KEY_PAUSE, 0);
} else
switch (temp) {
case 0xe0:
key_enhanced = TRUE;
break;
case 0xe1:
key_pause_loop = 5;
break;
default:
if (key_enhanced) {
key_enhanced = FALSE;
scancode = hw_to_mycode_ex[temp&0x7f];
} else {
scancode = hw_to_mycode[temp&0x7f];
}
handle_code(scancode, temp);
}
}
 
if (((temp==0x4F)||(temp==0x53))&&(key_shifts&KB_CTRL_FLAG)&&(key_shifts&KB_ALT_FLAG)) {
/* Hack alert:
only SIGINT (but not Ctrl-Break)
calls the destructors and will safely clean up
*/
__asm("\n\
movb $0x79, %%al \n\
call ___djgpp_hw_exception \n\
":::"%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory");
}
 
satisfy();
return 0;
} ENDOFUNC(keyboard)
 
 
int pc_keypressed (void)
{
return (key_buffer.start!=key_buffer.end);
}
 
int pc_readkey (void)
{
if (keyboard_installed) {
int key;
 
do {
} while (key_buffer.start==key_buffer.end);
 
DISABLE();
key = key_buffer.key[key_buffer.start++];
if (key_buffer.start>=KEY_BUFFER_SIZE)
key_buffer.start = 0;
ENABLE();
 
return key;
} else {
return 0;
}
}
 
int pc_keydown (int code)
{
return pc_key[code];
}
 
void pc_remove_keyb (void)
{
if (keyboard_installed) {
int s1, s2, s3;
keyboard_installed = FALSE;
pc_clexit(pc_remove_keyb);
 
DISABLE();
_farsetsel(__djgpp_dos_sel);
_farnspokew(0x41c, _farnspeekw(0x41a));
 
s1 = _farnspeekb(0x417) & 0x80;
s2 = _farnspeekb(0x418) & 0xFC;
s3 = _farnspeekb(0x496) & 0xF3;
 
if (pc_key[KEY_RSHIFT]) { s1 |= 1; }
if (pc_key[KEY_LSHIFT]) { s1 |= 2; }
if (pc_key[KEY_LCONTROL]) { s2 |= 1; s1 |= 4; }
if (pc_key[KEY_ALT]) { s1 |= 8; s2 |= 2; }
if (pc_key[KEY_RCONTROL]) { s1 |= 4; s3 |= 4; }
if (pc_key[KEY_ALTGR]) { s1 |= 8; s3 |= 8; }
 
if (key_shifts&KB_SCROLOCK_FLAG) s1 |= 16;
if (key_shifts&KB_NUMLOCK_FLAG) s1 |= 32;
if (key_shifts&KB_CAPSLOCK_FLAG) s1 |= 64;
 
_farnspokeb(0x417, s1);
_farnspokeb(0x418, s2);
_farnspokeb(0x496, s3);
update_leds(key_shifts);
 
ENABLE();
pc_remove_irq(KEYB_IRQ);
}
}
 
int pc_install_keyb (void)
{
if (keyboard_installed||pc_install_irq(KEYB_IRQ, keyboard)) {
return -1;
} else {
int s1, s2, s3;
 
LOCKDATA(key_buffer);
LOCKDATA(key_enhanced);
LOCKDATA(key_pause_loop);
LOCKDATA(key_shifts);
LOCKDATA(leds_ok);
LOCKDATA(in_a_terrupt);
LOCKDATA(pc_key);
LOCKDATA(modifier_table);
LOCKDATA(hw_to_mycode);
LOCKDATA(hw_to_mycode_ex);
LOCKDATA(standard_key_ascii_table);
LOCKDATA(standard_key_capslock_table);
LOCKDATA(standard_key_shift_table);
LOCKDATA(standard_key_control_table);
LOCKDATA(numlock_table);
LOCKFUNC(update_leds);
LOCKFUNC(inject_key);
LOCKFUNC(handle_code);
LOCKFUNC(keyboard);
DISABLE();
_farsetsel(__djgpp_dos_sel);
_farnspokew(0x41c, _farnspeekw(0x41a));
 
key_shifts = 0;
s1 = _farnspeekb(0x417);
s2 = _farnspeekb(0x418);
s3 = _farnspeekb(0x496);
 
if (s1&1) { key_shifts |= KB_SHIFT_FLAG; pc_key[KEY_RSHIFT] = TRUE; }
if (s1&2) { key_shifts |= KB_SHIFT_FLAG; pc_key[KEY_LSHIFT] = TRUE; }
if (s2&1) { key_shifts |= KB_CTRL_FLAG; pc_key[KEY_LCONTROL] = TRUE; }
if (s2&2) { key_shifts |= KB_ALT_FLAG; pc_key[KEY_ALT] = TRUE; }
if (s3&4) { key_shifts |= KB_CTRL_FLAG; pc_key[KEY_RCONTROL] = TRUE; }
if (s3&8) { key_shifts |= KB_ALT_FLAG; pc_key[KEY_ALTGR] = TRUE; }
 
if (s1&16) key_shifts |= KB_SCROLOCK_FLAG;
if (s1&32) key_shifts |= KB_NUMLOCK_FLAG;
if (s1&64) key_shifts |= KB_CAPSLOCK_FLAG;
update_leds(key_shifts);
 
key_enhanced = key_pause_loop = 0;
key_buffer.start = key_buffer.end = 0;
ENABLE();
 
pc_atexit(pc_remove_keyb);
keyboard_installed = TRUE;
return 0;
}
}
/shark/trunk/ports/mesa/src-glut.dos/pc_hw/pc_irq.S
0,0 → 1,180
/*
* PC/HW routine collection v1.0 for DOS/DJGPP
*
* Copyright (C) 2002 - Borca Daniel
* Email : dborca@yahoo.com
* Web : http://www.geocities.com/dborca
*/
 
 
.file "pc_irq.S"
 
.text
 
#define IRQ_STACK_SIZE 16384
 
#define IRQ_WRAPPER_LEN (__irq_wrapper_1-__irq_wrapper_0)
#define IRQ_OLD (__irq_old_0-__irq_wrapper_0)
#define IRQ_HOOK (__irq_hook_0-__irq_wrapper_0)
#define IRQ_STACK (__irq_stack_0-__irq_wrapper_0)
 
.balign 4
common:
movw $0x0400, %ax
int $0x31
 
movl %ss:8(%ebp), %ebx
cmpl $15, %ebx
jbe 0f
fail:
orl $-1, %eax
popl %edi
popl %ebx
leave
ret
 
0:
movl %ebx, %edi
imull $IRQ_WRAPPER_LEN, %edi
addl $__irq_wrapper_0, %edi
 
cmpb $7, %bl
jbe 1f
movb %dl, %dh
subb $8, %dh
1:
addb %dh, %bl
ret
 
.balign 4
.global _pc_install_irq
_pc_install_irq:
pushl %ebp
movl %esp, %ebp
pushl %ebx
pushl %edi
 
call common
 
cmpl $0, IRQ_HOOK(%edi)
jne fail
 
pushl $IRQ_WRAPPER_LEN
pushl %edi
call __go32_dpmi_lock_code
addl $8, %esp
testl %eax, %eax
jnz fail
 
pushl $IRQ_STACK_SIZE
call _pc_malloc
popl %edx
testl %eax, %eax
jz fail
addl %edx, %eax
movl %eax, IRQ_STACK(%edi)
 
movl %ss:12(%ebp), %eax
movl %eax, IRQ_HOOK(%edi)
 
movw $0x0204, %ax
int $0x31
movl %edx, IRQ_OLD(%edi)
movw %cx, IRQ_OLD+4(%edi)
movw $0x0205, %ax
movl %edi, %edx
movl %cs, %ecx
int $0x31
 
done:
xorl %eax, %eax
popl %edi
popl %ebx
leave
ret
 
.balign 4
.global _pc_remove_irq
_pc_remove_irq:
pushl %ebp
movl %esp, %ebp
pushl %ebx
pushl %edi
 
call common
 
cmpl $0, IRQ_HOOK(%edi)
je fail
 
movl $0, IRQ_HOOK(%edi)
 
movw $0x0205, %ax
movl IRQ_OLD(%edi), %edx
movl IRQ_OLD+4(%edi), %ecx
int $0x31
 
movl IRQ_STACK(%edi), %eax
subl $IRQ_STACK_SIZE, %eax
pushl %eax
call _free
popl %eax
 
jmp done
 
#define WRAPPER(x) ; \
.balign 4 ; \
__irq_wrapper_##x: ; \
pushal ; \
pushl %ds ; \
pushl %es ; \
pushl %fs ; \
pushl %gs ; \
movl %ss, %ebx ; \
movl %esp, %esi ; \
movl %cs:___djgpp_ds_alias, %ss ; \
movl %cs:__irq_stack_##x, %esp ; \
pushl %ss ; \
pushl %ss ; \
popl %es ; \
popl %ds ; \
movl ___djgpp_dos_sel, %fs ; \
pushl %fs ; \
popl %gs ; \
call *__irq_hook_##x ; \
movl %ebx, %ss ; \
movl %esi, %esp ; \
testl %eax, %eax ; \
popl %gs ; \
popl %fs ; \
popl %es ; \
popl %ds ; \
popal ; \
jz __irq_ignore_##x ; \
__irq_bypass_##x: ; \
ljmp *%cs:__irq_old_##x ; \
__irq_ignore_##x: ; \
iret ; \
.balign 4 ; \
__irq_old_##x: ; \
.long 0, 0 ; \
__irq_hook_##x: ; \
.long 0 ; \
__irq_stack_##x: ; \
.long 0
 
WRAPPER(0);
WRAPPER(1);
WRAPPER(2);
WRAPPER(3);
WRAPPER(4);
WRAPPER(5);
WRAPPER(6);
WRAPPER(7);
WRAPPER(8);
WRAPPER(9);
WRAPPER(10);
WRAPPER(11);
WRAPPER(12);
WRAPPER(13);
WRAPPER(14);
WRAPPER(15);
/shark/trunk/ports/mesa/src-glut.dos/makefile
0,0 → 1,23
# The Frame Buffer Device
 
ifndef BASE
BASE=../../..
endif
 
include $(BASE)/config/config.mk
 
LIBRARY = glut
 
OBJS_PATH = $(BASE)/drivers/mesa/src-glut.dos/
 
GLUT = bitmap.o color.o globals.o models.o teapot.o\
window.o callback.o init.o menu.o overlay.o state.o
 
OBJS = $(GLUT)
 
C_OPT += -I../../../drivers/linuxc24/include -I../include -I. -I.. -D__KERNEL__ -D__i368__ \
-ffast-math -fexpensive-optimizations -fstrict-aliasing \
-malign-loops=2 -malign-jumps=2 -malign-functions=2 -D_REENTRANT -DUSE_MMX_ASM -DUSE_X86_ASM
 
include $(BASE)/config/lib.mk
 
/shark/trunk/ports/mesa/src/tnl/t_array_api.h
0,0 → 1,47
/* $Id: t_array_api.h,v 1.1 2003-02-28 11:48:06 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
#ifndef _T_VARRAY_H
#define _T_VARRAY_H
 
#include "mtypes.h"
#include "t_context.h"
 
 
extern void _tnl_DrawArrays(GLenum mode, GLint first, GLsizei count);
 
extern void _tnl_DrawElements(GLenum mode, GLsizei count, GLenum type,
const GLvoid *indices);
 
extern void _tnl_DrawRangeElements(GLenum mode, GLuint start,
GLuint end, GLsizei count, GLenum type,
const GLvoid *indices);
 
 
extern void _tnl_array_init( GLcontext *ctx );
extern void _tnl_array_destroy( GLcontext *ctx );
 
#endif
/shark/trunk/ports/mesa/src/tnl/t_eval_api.c
0,0 → 1,248
/* $Id: t_eval_api.c,v 1.1 2003-02-28 11:48:06 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 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.
*
* Authors:
* Keith Whitwell - original code
* Brian Paul - vertex program updates
*/
 
 
#include "glheader.h"
#include "colormac.h"
#include "context.h"
#include "macros.h"
#include "imports.h"
#include "mmath.h"
#include "mtypes.h"
#include "math/m_eval.h"
 
#include "t_eval_api.h"
#include "t_imm_api.h"
#include "t_imm_alloc.h"
#include "t_imm_exec.h"
 
 
/* KW: If are compiling, we don't know whether eval will produce a
* vertex when it is run in the future. If this is pure immediate
* mode, eval is a noop if neither vertex map is enabled.
*
* Thus we need to have a check in the display list code or
* elsewhere for eval(1,2) vertices in the case where
* map(1,2)_vertex is disabled, and to purge those vertices from
* the vb.
*/
void
_tnl_exec_EvalMesh1( GLenum mode, GLint i1, GLint i2 )
{
GET_CURRENT_CONTEXT(ctx);
GLint i;
GLfloat u, du;
GLenum prim;
ASSERT_OUTSIDE_BEGIN_END(ctx);
 
if (MESA_VERBOSE & VERBOSE_API)
_mesa_debug(ctx, "glEvalMesh1()");
 
switch (mode) {
case GL_POINT:
prim = GL_POINTS;
break;
case GL_LINE:
prim = GL_LINE_STRIP;
break;
default:
_mesa_error( ctx, GL_INVALID_ENUM, "glEvalMesh1(mode)" );
return;
}
 
/* No effect if vertex maps disabled.
*/
if (!ctx->Eval.Map1Vertex4 && !ctx->Eval.Map1Vertex3 &&
(!ctx->VertexProgram.Enabled || !ctx->Eval.Map1Attrib[VERT_ATTRIB_POS]))
return;
 
du = ctx->Eval.MapGrid1du;
u = ctx->Eval.MapGrid1u1 + i1 * du;
 
/* Need to turn off compilation -- this is already saved, and the
* coordinates generated and the test above depend on state that
* may change before the list is executed.
*
* TODO: Anaylse display lists to determine if this state is
* constant.
*
* State to watch:
* - enabled maps
* - map state for each enabled map, including control points
* - grid state
*
* Could alternatively cache individual maps in arrays, rather than
* building immediates.
*/
{
GLboolean compiling = ctx->CompileFlag;
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct immediate *im = TNL_CURRENT_IM(ctx);
GLboolean (*NotifyBegin)(GLcontext *ctx, GLenum p);
 
NotifyBegin = tnl->Driver.NotifyBegin;
tnl->Driver.NotifyBegin = 0;
 
if (compiling) {
struct immediate *tmp = _tnl_alloc_immediate( ctx );
FLUSH_VERTICES( ctx, 0 );
SET_IMMEDIATE( ctx, tmp );
TNL_CURRENT_IM(ctx)->ref_count++;
ctx->CompileFlag = GL_FALSE;
}
 
_tnl_Begin( prim );
for (i=i1;i<=i2;i++,u+=du) {
_tnl_eval_coord1f( ctx, u );
}
_tnl_end(ctx);
 
/* Need this for replay *and* compile:
*/
FLUSH_VERTICES( ctx, 0 );
tnl->Driver.NotifyBegin = NotifyBegin;
 
if (compiling) {
TNL_CURRENT_IM(ctx)->ref_count--;
ASSERT( TNL_CURRENT_IM(ctx)->ref_count == 0 );
_tnl_free_immediate( ctx, TNL_CURRENT_IM(ctx) );
SET_IMMEDIATE( ctx, im );
ctx->CompileFlag = GL_TRUE;
}
}
}
 
 
 
void
_tnl_exec_EvalMesh2( GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2 )
{
GET_CURRENT_CONTEXT(ctx);
GLint i, j;
GLfloat u, du, v, dv, v1, u1;
ASSERT_OUTSIDE_BEGIN_END(ctx);
 
if (MESA_VERBOSE & VERBOSE_API)
_mesa_debug(ctx, "glEvalMesh2()");
 
/* No effect if vertex maps disabled.
*/
if (!ctx->Eval.Map2Vertex4 && !ctx->Eval.Map2Vertex3 &&
(!ctx->VertexProgram.Enabled || !ctx->Eval.Map2Attrib[VERT_ATTRIB_POS]))
return;
 
du = ctx->Eval.MapGrid2du;
dv = ctx->Eval.MapGrid2dv;
v1 = ctx->Eval.MapGrid2v1 + j1 * dv;
u1 = ctx->Eval.MapGrid2u1 + i1 * du;
 
/* Need to turn off compilation -- this is already saved, and the
* coordinates generated and the test above depend on state that
* may change before the list is executed.
*/
{
GLboolean compiling = ctx->CompileFlag;
struct immediate *im = TNL_CURRENT_IM(ctx);
TNLcontext *tnl = TNL_CONTEXT(ctx);
GLboolean (*NotifyBegin)(GLcontext *ctx, GLenum p);
 
NotifyBegin = tnl->Driver.NotifyBegin;
tnl->Driver.NotifyBegin = 0;
 
if (compiling) {
struct immediate *tmp = _tnl_alloc_immediate( ctx );
FLUSH_VERTICES( ctx, 0 );
SET_IMMEDIATE( ctx, tmp );
TNL_CURRENT_IM(ctx)->ref_count++;
ctx->CompileFlag = GL_FALSE;
}
 
switch (mode) {
case GL_POINT:
_tnl_Begin( GL_POINTS );
for (v=v1,j=j1;j<=j2;j++,v+=dv) {
for (u=u1,i=i1;i<=i2;i++,u+=du) {
_tnl_eval_coord2f( ctx, u, v );
}
}
_tnl_end(ctx);
break;
case GL_LINE:
for (v=v1,j=j1;j<=j2;j++,v+=dv) {
_tnl_Begin( GL_LINE_STRIP );
for (u=u1,i=i1;i<=i2;i++,u+=du) {
_tnl_eval_coord2f( ctx, u, v );
}
_tnl_end(ctx);
}
for (u=u1,i=i1;i<=i2;i++,u+=du) {
_tnl_Begin( GL_LINE_STRIP );
for (v=v1,j=j1;j<=j2;j++,v+=dv) {
_tnl_eval_coord2f( ctx, u, v );
}
_tnl_end(ctx);
}
break;
case GL_FILL:
for (v=v1,j=j1;j<j2;j++,v+=dv) {
_tnl_Begin( GL_TRIANGLE_STRIP );
for (u=u1,i=i1;i<=i2;i++,u+=du) {
_tnl_eval_coord2f( ctx, u, v );
_tnl_eval_coord2f( ctx, u, v+dv );
}
_tnl_end(ctx);
}
break;
default:
_mesa_error( ctx, GL_INVALID_ENUM, "glEvalMesh2(mode)" );
return;
}
 
/* Need this for replay *and* compile:
*/
FLUSH_VERTICES( ctx, 0 );
tnl->Driver.NotifyBegin = NotifyBegin;
if (compiling) {
TNL_CURRENT_IM(ctx)->ref_count--;
_tnl_free_immediate( ctx, TNL_CURRENT_IM( ctx ) );
SET_IMMEDIATE( ctx, im );
ctx->CompileFlag = GL_TRUE;
}
}
}
 
 
void _tnl_eval_init( GLcontext *ctx )
{
GLvertexformat *vfmt = &(TNL_CONTEXT(ctx)->vtxfmt);
vfmt->EvalMesh1 = _tnl_exec_EvalMesh1;
vfmt->EvalMesh2 = _tnl_exec_EvalMesh2;
}
/shark/trunk/ports/mesa/src/tnl/t_vtx_exec.c
0,0 → 1,632
/* $XFree86$ */
/**************************************************************************
 
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
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
TUNGSTEN GRAPHICS 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 "api_noop.h"
#include "api_arrayelt.h"
#include "context.h"
#include "imports.h"
#include "mmath.h"
#include "mtypes.h"
#include "enums.h"
#include "glapi.h"
#include "colormac.h"
#include "light.h"
#include "state.h"
#include "vtxfmt.h"
 
#include "tnl/tnl.h"
#include "tnl/t_context.h"
#include "tnl/t_array_api.h"
 
static void _tnl_FlushVertices( GLcontext *, GLuint );
 
 
void tnl_copy_to_current( GLcontext *ctx )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
GLuint flag = tnl->vertex_format;
GLint i;
 
assert(ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT);
 
for (i = 0 ; i < 16 ; i++)
if (flag & (1<<i))
COPY_4FV( ctx->Current.Attrib[i], tnl->attribptr[i] );
 
if (flag & VERT_BIT_INDEX)
ctx->Current.Index = tnl->indexptr[0];
 
if (flag & VERT_BIT_EDGEFLAG)
ctx->Current.EdgeFlag = tnl->edgeflagptr[0];
 
if (flag & VERT_BIT_MATERIAL) {
_mesa_update_material( ctx,
IM->Material[IM->LastMaterial],
IM->MaterialOrMask );
 
tnl->Driver.NotifyMaterialChange( ctx );
}
 
 
ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT;
}
 
static GLboolean discreet_gl_prim[GL_POLYGON+1] = {
1, /* 0 points */
1, /* 1 lines */
0, /* 2 line_strip */
0, /* 3 line_loop */
1, /* 4 tris */
0, /* 5 tri_fan */
0, /* 6 tri_strip */
1, /* 7 quads */
0, /* 8 quadstrip */
0, /* 9 poly */
};
 
/* Optimize the primitive list: ONLY FOR EXECUTE ATM
*/
static void optimize_prims( TNLcontext *tnl )
{
int i, j;
 
if (tnl->nrprims <= 1)
return;
 
for (j = 0, i = 1 ; i < tnl->nrprims; i++) {
int pj = tnl->primlist[j].prim & 0xf;
int pi = tnl->primlist[i].prim & 0xf;
if (pj == pi && discreet_gl_prim[pj] &&
tnl->primlist[i].start == tnl->primlist[j].end) {
tnl->primlist[j].end = tnl->primlist[i].end;
}
else {
j++;
if (j != i) tnl->primlist[j] = tnl->primlist[i];
}
}
 
tnl->nrprims = j+1;
}
 
 
/* Bind vertex buffer pointers, run pipeline:
*/
static void flush_prims( TNLcontext *tnl )
{
int i,j;
 
tnl->dma.current.ptr = tnl->dma.current.start +=
(tnl->initial_counter - tnl->counter) * tnl->vertex_size * 4;
 
tnl->tcl.vertex_format = tnl->vertex_format;
tnl->tcl.aos_components[0] = &tmp;
tnl->tcl.nr_aos_components = 1;
tnl->dma.flush = 0;
 
tnl->Driver.RunPipeline( ... );
tnl->nrprims = 0;
}
 
 
static void start_prim( TNLcontext *tnl, GLuint mode )
{
if (MESA_VERBOSE & DEBUG_VFMT)
_mesa_debug(NULL, "%s %d\n", __FUNCTION__,
tnl->initial_counter - tnl->counter);
 
tnl->primlist[tnl->nrprims].start = tnl->initial_counter - tnl->counter;
tnl->primlist[tnl->nrprims].prim = mode;
}
 
static void note_last_prim( TNLcontext *tnl, GLuint flags )
{
if (MESA_VERBOSE & DEBUG_VFMT)
_mesa_debug(NULL, "%s %d\n", __FUNCTION__,
tnl->initial_counter - tnl->counter);
 
if (tnl->prim[0] != GL_POLYGON+1) {
tnl->primlist[tnl->nrprims].prim |= flags;
tnl->primlist[tnl->nrprims].end = tnl->initial_counter - tnl->counter;
 
if (++tnl->nrprims == TNL_MAX_PRIMS)
flush_prims( tnl );
}
}
 
 
static void copy_vertex( TNLcontext *tnl, GLuint n, GLfloat *dst )
{
GLuint i;
GLfloat *src = (GLfloat *)(tnl->dma.current.address +
tnl->dma.current.ptr +
(tnl->primlist[tnl->nrprims].start + n) *
tnl->vertex_size * 4);
 
if (MESA_VERBOSE & DEBUG_VFMT)
_mesa_debug(NULL, "copy_vertex %d\n",
tnl->primlist[tnl->nrprims].start + n);
 
for (i = 0 ; i < tnl->vertex_size; i++) {
dst[i] = src[i];
}
}
 
static GLuint copy_wrapped_verts( TNLcontext *tnl, GLfloat (*tmp)[15] )
{
GLuint ovf, i;
GLuint nr = (tnl->initial_counter - tnl->counter) - tnl->primlist[tnl->nrprims].start;
 
if (MESA_VERBOSE & DEBUG_VFMT)
_mesa_debug(NULL, "%s %d verts\n", __FUNCTION__, nr);
 
switch( tnl->prim[0] )
{
case GL_POINTS:
return 0;
case GL_LINES:
ovf = nr&1;
for (i = 0 ; i < ovf ; i++)
copy_vertex( tnl, nr-ovf+i, tmp[i] );
return i;
case GL_TRIANGLES:
ovf = nr%3;
for (i = 0 ; i < ovf ; i++)
copy_vertex( tnl, nr-ovf+i, tmp[i] );
return i;
case GL_QUADS:
ovf = nr&3;
for (i = 0 ; i < ovf ; i++)
copy_vertex( tnl, nr-ovf+i, tmp[i] );
return i;
case GL_LINE_STRIP:
if (nr == 0)
return 0;
copy_vertex( tnl, nr-1, tmp[0] );
return 1;
case GL_LINE_LOOP:
case GL_TRIANGLE_FAN:
case GL_POLYGON:
if (nr == 0)
return 0;
else if (nr == 1) {
copy_vertex( tnl, 0, tmp[0] );
return 1;
} else {
copy_vertex( tnl, 0, tmp[0] );
copy_vertex( tnl, nr-1, tmp[1] );
return 2;
}
case GL_TRIANGLE_STRIP:
ovf = MIN2( nr-1, 2 );
for (i = 0 ; i < ovf ; i++)
copy_vertex( tnl, nr-ovf+i, tmp[i] );
return i;
case GL_QUAD_STRIP:
ovf = MIN2( nr-1, 2 );
if (nr > 2) ovf += nr&1;
for (i = 0 ; i < ovf ; i++)
copy_vertex( tnl, nr-ovf+i, tmp[i] );
return i;
default:
assert(0);
return 0;
}
}
 
 
 
/* Extend for vertex-format changes on wrap:
*/
static void wrap_buffer( void )
{
TNLcontext *tnl = tnl->tnl;
GLfloat tmp[3][15];
GLuint i, nrverts;
 
if (MESA_VERBOSE & (DEBUG_VFMT|DEBUG_PRIMS))
_mesa_debug(NULL, "%s %d\n", __FUNCTION__,
tnl->initial_counter - tnl->counter);
 
/* Don't deal with parity. *** WONT WORK FOR COMPILE
*/
if ((((tnl->initial_counter - tnl->counter) -
tnl->primlist[tnl->nrprims].start) & 1)) {
tnl->counter++;
tnl->initial_counter++;
return;
}
 
/* Copy vertices out of dma:
*/
nrverts = copy_dma_verts( tnl, tmp );
 
if (MESA_VERBOSE & DEBUG_VFMT)
_mesa_debug(NULL, "%d vertices to copy\n", nrverts);
 
/* Finish the prim at this point:
*/
note_last_prim( tnl, 0 );
flush_prims( tnl );
 
/* Reset counter, dmaptr
*/
tnl->dmaptr = (int *)(tnl->dma.current.ptr + tnl->dma.current.address);
tnl->counter = (tnl->dma.current.end - tnl->dma.current.ptr) /
(tnl->vertex_size * 4);
tnl->counter--;
tnl->initial_counter = tnl->counter;
tnl->notify = wrap_buffer;
 
tnl->dma.flush = flush_prims;
start_prim( tnl, tnl->prim[0] );
 
 
/* Reemit saved vertices
* *** POSSIBLY IN NEW FORMAT
* --> Can't always extend at end of vertex?
*/
for (i = 0 ; i < nrverts; i++) {
if (MESA_VERBOSE & DEBUG_VERTS) {
int j;
_mesa_debug(NULL, "re-emit vertex %d to %p\n", i, tnl->dmaptr);
if (MESA_VERBOSE & DEBUG_VERBOSE)
for (j = 0 ; j < tnl->vertex_size; j++)
_mesa_debug(NULL, "\t%08x/%f\n", *(int*)&tmp[i][j], tmp[i][j]);
}
 
memcpy( tnl->dmaptr, tmp[i], tnl->vertex_size * 4 );
tnl->dmaptr += tnl->vertex_size;
tnl->counter--;
}
}
 
 
 
/* Always follow data, don't try to predict what's necessary.
*/
static GLboolean check_vtx_fmt( GLcontext *ctx )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
 
if (ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT)
ctx->Driver.FlushVertices( ctx, FLUSH_UPDATE_CURRENT );
 
TNL_NEWPRIM(tnl);
tnl->vertex_format = VERT_BIT_POS;
tnl->prim = &ctx->Driver.CurrentExecPrimitive;
 
 
/* Currently allow the full 4 components per attrib. Can use the
* mechanism from radeon driver color handling to reduce this (and
* also to store ubyte colors where these are incoming). This
* won't work for compile mode.
*
* Only adding components when they are first received eliminates
* the need for displaylist fixup, as there are no 'empty' slots
* at the start of buffers.
*/
for (i = 0 ; i < 16 ; i++) {
if (ind & (1<<i)) {
tnl->attribptr[i] = &tnl->vertex[tnl->vertex_size].f;
tnl->vertex_size += 4;
tnl->attribptr[i][0] = ctx->Current.Attrib[i][0];
tnl->attribptr[i][1] = ctx->Current.Attrib[i][1];
tnl->attribptr[i][2] = ctx->Current.Attrib[i][2];
tnl->attribptr[i][3] = ctx->Current.Attrib[i][3];
}
else
tnl->attribptr[i] = ctx->Current.Attrib[i];
}
 
/* Edgeflag, Index:
*/
for (i = 16 ; i < 18 ; i++)
;
 
/* Materials:
*/
for (i = 18 ; i < 28 ; i++)
;
 
/* Eval:
*/
for (i = 28 ; i < 29 ; i++)
;
 
if (tnl->installed_vertex_format != tnl->vertex_format) {
if (MESA_VERBOSE & DEBUG_VFMT)
_mesa_debug(NULL, "reinstall on vertex_format change\n");
_mesa_install_exec_vtxfmt( ctx, &tnl->vtxfmt );
tnl->installed_vertex_format = tnl->vertex_format;
}
 
return GL_TRUE;
}
 
 
void _tnl_InvalidateVtxfmt( GLcontext *ctx )
{
tnl->recheck = GL_TRUE;
tnl->fell_back = GL_FALSE;
}
 
 
 
 
static void _tnl_ValidateVtxfmt( GLcontext *ctx )
{
if (MESA_VERBOSE & DEBUG_VFMT)
_mesa_debug(NULL, "%s\n", __FUNCTION__);
 
if (ctx->Driver.NeedFlush)
ctx->Driver.FlushVertices( ctx, ctx->Driver.NeedFlush );
 
tnl->recheck = GL_FALSE;
 
if (check_vtx_fmt( ctx )) {
if (!tnl->installed) {
if (MESA_VERBOSE & DEBUG_VFMT)
_mesa_debug(NULL, "reinstall (new install)\n");
 
_mesa_install_exec_vtxfmt( ctx, &tnl->vtxfmt );
ctx->Driver.FlushVertices = _tnl_FlushVertices;
tnl->installed = GL_TRUE;
}
else
_mesa_debug(NULL, "%s: already installed", __FUNCTION__);
}
else {
if (MESA_VERBOSE & DEBUG_VFMT)
_mesa_debug(NULL, "%s: failed\n", __FUNCTION__);
 
if (tnl->installed) {
if (tnl->tnl->dma.flush)
tnl->tnl->dma.flush( tnl->tnl );
_tnl_wakeup_exec( ctx );
tnl->installed = GL_FALSE;
}
}
}
 
 
 
 
 
/* Begin/End
*/
static void _tnl_Begin( GLenum mode )
{
GLcontext *ctx = tnl->context;
TNLcontext *tnl = tnl->tnl;
if (MESA_VERBOSE & DEBUG_VFMT)
_mesa_debug(NULL, "%s\n", __FUNCTION__);
 
if (mode > GL_POLYGON) {
_mesa_error( ctx, GL_INVALID_ENUM, "glBegin" );
return;
}
 
if (tnl->prim[0] != GL_POLYGON+1) {
_mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" );
return;
}
if (ctx->NewState)
_mesa_update_state( ctx );
 
if (tnl->recheck)
_tnl_ValidateVtxfmt( ctx );
 
if (tnl->dma.flush && tnl->counter < 12) {
if (MESA_VERBOSE & DEBUG_VFMT)
_mesa_debug(NULL, "%s: flush almost-empty buffers\n", __FUNCTION__);
flush_prims( tnl );
}
 
if (!tnl->dma.flush) {
if (tnl->dma.current.ptr + 12*tnl->vertex_size*4 >
tnl->dma.current.end) {
TNL_NEWPRIM( tnl );
_tnl_RefillCurrentDmaRegion( tnl );
}
 
tnl->dmaptr = (int *)(tnl->dma.current.address + tnl->dma.current.ptr);
tnl->counter = (tnl->dma.current.end - tnl->dma.current.ptr) /
(tnl->vertex_size * 4);
tnl->counter--;
tnl->initial_counter = tnl->counter;
tnl->notify = wrap_buffer;
tnl->dma.flush = flush_prims;
tnl->context->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
}
tnl->prim[0] = mode;
start_prim( tnl, mode | PRIM_BEGIN );
}
 
 
 
 
 
static void _tnl_End( void )
{
TNLcontext *tnl = tnl->tnl;
GLcontext *ctx = tnl->context;
 
if (MESA_VERBOSE & DEBUG_VFMT)
_mesa_debug(NULL, "%s\n", __FUNCTION__);
 
if (tnl->prim[0] == GL_POLYGON+1) {
_mesa_error( ctx, GL_INVALID_OPERATION, "glEnd" );
return;
}
note_last_prim( tnl, PRIM_END );
tnl->prim[0] = GL_POLYGON+1;
}
 
 
static void _tnl_FlushVertices( GLcontext *ctx, GLuint flags )
{
if (MESA_VERBOSE & DEBUG_VFMT)
_mesa_debug(NULL, "%s\n", __FUNCTION__);
 
assert(tnl->installed);
 
if (flags & FLUSH_UPDATE_CURRENT) {
_tnl_copy_to_current( ctx );
if (MESA_VERBOSE & DEBUG_VFMT)
_mesa_debug(NULL, "reinstall on update_current\n");
_mesa_install_exec_vtxfmt( ctx, &tnl->vtxfmt );
ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT;
}
 
if (flags & FLUSH_STORED_VERTICES) {
TNLcontext *tnl = TNL_CONTEXT( ctx );
assert (tnl->dma.flush == 0 ||
tnl->dma.flush == flush_prims);
if (tnl->dma.flush == flush_prims)
flush_prims( TNL_CONTEXT( ctx ) );
ctx->Driver.NeedFlush &= ~FLUSH_STORED_VERTICES;
}
}
 
 
 
/* At this point, don't expect very many versions of each function to
* be generated, so not concerned about freeing them?
*/
 
 
static void _tnl_InitVtxfmt( GLcontext *ctx )
{
GLvertexformat *vfmt = &(tnl->vtxfmt);
 
MEMSET( vfmt, 0, sizeof(GLvertexformat) );
 
/* Hook in chooser functions for codegen, etc:
*/
_tnl_InitVtxfmtChoosers( vfmt );
 
/* Handled fully in supported states, but no codegen:
*/
vfmt->ArrayElement = _ae_loopback_array_elt; /* generic helper */
vfmt->Rectf = _mesa_noop_Rectf; /* generic helper */
vfmt->Begin = _tnl_Begin;
vfmt->End = _tnl_End;
tnl->context = ctx;
tnl->tnl = TNL_CONTEXT(ctx);
tnl->prim = &ctx->Driver.CurrentExecPrimitive;
tnl->primflags = 0;
 
make_empty_list( &tnl->dfn_cache.Vertex2f );
make_empty_list( &tnl->dfn_cache.Vertex2fv );
make_empty_list( &tnl->dfn_cache.Vertex3f );
make_empty_list( &tnl->dfn_cache.Vertex3fv );
make_empty_list( &tnl->dfn_cache.Color4ub );
make_empty_list( &tnl->dfn_cache.Color4ubv );
make_empty_list( &tnl->dfn_cache.Color3ub );
make_empty_list( &tnl->dfn_cache.Color3ubv );
make_empty_list( &tnl->dfn_cache.Color4f );
make_empty_list( &tnl->dfn_cache.Color4fv );
make_empty_list( &tnl->dfn_cache.Color3f );
make_empty_list( &tnl->dfn_cache.Color3fv );
make_empty_list( &tnl->dfn_cache.SecondaryColor3fEXT );
make_empty_list( &tnl->dfn_cache.SecondaryColor3fvEXT );
make_empty_list( &tnl->dfn_cache.SecondaryColor3ubEXT );
make_empty_list( &tnl->dfn_cache.SecondaryColor3ubvEXT );
make_empty_list( &tnl->dfn_cache.Normal3f );
make_empty_list( &tnl->dfn_cache.Normal3fv );
make_empty_list( &tnl->dfn_cache.TexCoord2f );
make_empty_list( &tnl->dfn_cache.TexCoord2fv );
make_empty_list( &tnl->dfn_cache.TexCoord1f );
make_empty_list( &tnl->dfn_cache.TexCoord1fv );
make_empty_list( &tnl->dfn_cache.MultiTexCoord2fARB );
make_empty_list( &tnl->dfn_cache.MultiTexCoord2fvARB );
make_empty_list( &tnl->dfn_cache.MultiTexCoord1fARB );
make_empty_list( &tnl->dfn_cache.MultiTexCoord1fvARB );
 
_tnl_InitCodegen( &tnl->codegen );
}
 
static void free_funcs( struct dynfn *l )
{
struct dynfn *f, *tmp;
foreach_s (f, tmp, l) {
remove_from_list( f );
ALIGN_FREE( f->code );
FREE( f );
}
}
 
 
static void _tnl_DestroyVtxfmt( GLcontext *ctx )
{
count_funcs();
free_funcs( &tnl->dfn_cache.Vertex2f );
free_funcs( &tnl->dfn_cache.Vertex2fv );
free_funcs( &tnl->dfn_cache.Vertex3f );
free_funcs( &tnl->dfn_cache.Vertex3fv );
free_funcs( &tnl->dfn_cache.Color4ub );
free_funcs( &tnl->dfn_cache.Color4ubv );
free_funcs( &tnl->dfn_cache.Color3ub );
free_funcs( &tnl->dfn_cache.Color3ubv );
free_funcs( &tnl->dfn_cache.Color4f );
free_funcs( &tnl->dfn_cache.Color4fv );
free_funcs( &tnl->dfn_cache.Color3f );
free_funcs( &tnl->dfn_cache.Color3fv );
free_funcs( &tnl->dfn_cache.SecondaryColor3ubEXT );
free_funcs( &tnl->dfn_cache.SecondaryColor3ubvEXT );
free_funcs( &tnl->dfn_cache.SecondaryColor3fEXT );
free_funcs( &tnl->dfn_cache.SecondaryColor3fvEXT );
free_funcs( &tnl->dfn_cache.Normal3f );
free_funcs( &tnl->dfn_cache.Normal3fv );
free_funcs( &tnl->dfn_cache.TexCoord2f );
free_funcs( &tnl->dfn_cache.TexCoord2fv );
free_funcs( &tnl->dfn_cache.TexCoord1f );
free_funcs( &tnl->dfn_cache.TexCoord1fv );
free_funcs( &tnl->dfn_cache.MultiTexCoord2fARB );
free_funcs( &tnl->dfn_cache.MultiTexCoord2fvARB );
free_funcs( &tnl->dfn_cache.MultiTexCoord1fARB );
free_funcs( &tnl->dfn_cache.MultiTexCoord1fvARB );
}
 
/shark/trunk/ports/mesa/src/tnl/t_eval_api.h
0,0 → 1,44
/* $Id: t_eval_api.h,v 1.1 2003-02-28 11:48:06 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
 
#ifndef _T_EVAL_H
#define _T_EVAL_H
 
 
#include "mtypes.h"
#include "t_context.h"
 
/* Use _mesa_save_EvalMesh{1,2} to save these to display lists.
*/
extern void _tnl_exec_EvalMesh1( GLenum mode, GLint i1, GLint i2 );
 
extern void _tnl_exec_EvalMesh2( GLenum mode, GLint i1, GLint i2,
GLint j1, GLint j2 );
 
void _tnl_eval_init( GLcontext *ctx );
 
#endif
/shark/trunk/ports/mesa/src/tnl/t_vtx_x86.c
0,0 → 1,705
/* $XFree86$ */
/**************************************************************************
 
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
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
TUNGSTEN GRAPHICS 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 "imports.h"
#include "mmath.h"
#include "simple_list.h"
#include "tnl_vtxfmt.h"
 
#if defined(USE_X86_ASM)
 
 
struct dynfn *tnl_makeX86Vertex2f( TNLcontext *tnl, int key )
{
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
 
if (RADEON_DEBUG & DEBUG_CODEGEN)
_mesa_debug(NULL, "%s 0x%08x\n", __FUNCTION__, key );
 
switch (tnl->vertex_size) {
default: {
/* Repz convenient as it's possible to emit code for any size
* vertex with little tweaking. Might as well read vertsize
* though, and have only one of these.
*/
static char temp[] = {
0x57, /* push %edi */
0x56, /* push %esi */
0xbe, 0, 0, 0, 0, /* mov $VERTEX+2,%esi */
0x8b, 0x3d, 0, 0, 0, 0, /* mov DMAPTR,%edi */
0x8b, 0x44, 0x24, 0x0c, /* mov 0x0c(%esp,1),%eax */
0x8b, 0x54, 0x24, 0x10, /* mov 0x10(%esp,1),%edx */
0x89, 0x07, /* mov %eax,(%edi) */
0x89, 0x57, 0x04, /* mov %edx,0x4(%edi) */
0x83, 0xc7, 0x08, /* add $0x8,%edi */
0xb9, 0, 0, 0, 0, /* mov $VERTSIZE-2,%ecx */
0xf3, 0xa5, /* repz movsl %ds:(%esi),%es:(%edi)*/
0xa1, 0, 0, 0, 0, /* mov COUNTER,%eax */
0x89, 0x3d, 0, 0, 0, 0, /* mov %edi,DMAPTR */
0x48, /* dec %eax */
0xa3, 0, 0, 0, 0, /* mov %eax,COUNTER */
0x5e, /* pop %esi */
0x5f, /* pop %edi */
0x74, 0x01, /* je +1 */
0xc3, /* ret */
0xff, 0x25, 0, 0, 0, 0 /* jmp NOTIFY */
};
 
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
memcpy (dfn->code, temp, sizeof(temp));
FIXUP(dfn->code, 3, 0x0, (int)&tnl->vertex[2]);
FIXUP(dfn->code, 9, 0x0, (int)&tnl->dmaptr);
FIXUP(dfn->code, 37, 0x0, tnl->vertex_size-2);
FIXUP(dfn->code, 44, 0x0, (int)&tnl->counter);
FIXUP(dfn->code, 50, 0x0, (int)&tnl->dmaptr);
FIXUP(dfn->code, 56, 0x0, (int)&tnl->counter);
FIXUP(dfn->code, 67, 0x0, (int)&tnl->notify);
break;
}
}
 
insert_at_head( &tnl->dfn_cache.Vertex3f, dfn );
dfn->key = key;
return dfn;
}
 
/* Build specialized versions of the immediate calls on the fly for
* the current state. Generic x86 versions.
*/
 
struct dynfn *tnl_makeX86Vertex3f( TNLcontext *tnl, int key )
{
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
 
if (RADEON_DEBUG & DEBUG_CODEGEN)
_mesa_debug(NULL, "%s 0x%08x\n", __FUNCTION__, key );
 
switch (tnl->vertex_size) {
case 4: {
static char temp[] = {
0x8b, 0x0d, 0,0,0,0, /* mov DMAPTR,%ecx */
0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */
0x8b, 0x54, 0x24, 0x08, /* mov 0x8(%esp,1),%edx */
0x89, 0x01, /* mov %eax,(%ecx) */
0x89, 0x51, 0x04, /* mov %edx,0x4(%ecx) */
0x8b, 0x44, 0x24, 0x0c, /* mov 0xc(%esp,1),%eax */
0x8b, 0x15, 0,0,0,0, /* mov VERTEX[3],%edx */
0x89, 0x41, 0x08, /* mov %eax,0x8(%ecx) */
0x89, 0x51, 0x0c, /* mov %edx,0xc(%ecx) */
0xa1, 0, 0, 0, 0, /* mov COUNTER,%eax */
0x83, 0xc1, 0x10, /* add $0x10,%ecx */
0x48, /* dec %eax */
0x89, 0x0d, 0,0,0,0, /* mov %ecx,DMAPTR */
0xa3, 0, 0, 0, 0, /* mov %eax,COUNTER */
0x74, 0x01, /* je +1 */
0xc3, /* ret */
0xff, 0x25, 0,0,0,0 /* jmp *NOTIFY */
};
 
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
memcpy (dfn->code, temp, sizeof(temp));
FIXUP(dfn->code, 2, 0x0, (int)&tnl->dmaptr);
FIXUP(dfn->code, 25, 0x0, (int)&tnl->vertex[3]);
FIXUP(dfn->code, 36, 0x0, (int)&tnl->counter);
FIXUP(dfn->code, 46, 0x0, (int)&tnl->dmaptr);
FIXUP(dfn->code, 51, 0x0, (int)&tnl->counter);
FIXUP(dfn->code, 60, 0x0, (int)&tnl->notify);
break;
}
case 6: {
static char temp[] = {
0x57, /* push %edi */
0x8b, 0x3d, 0, 0, 0, 0, /* mov DMAPTR,%edi */
0x8b, 0x44, 0x24, 0x8, /* mov 0x8(%esp,1),%eax */
0x8b, 0x54, 0x24, 0xc, /* mov 0xc(%esp,1),%edx */
0x8b, 0x4c, 0x24, 0x10, /* mov 0x10(%esp,1),%ecx */
0x89, 0x07, /* mov %eax,(%edi) */
0x89, 0x57, 0x04, /* mov %edx,0x4(%edi) */
0x89, 0x4f, 0x08, /* mov %ecx,0x8(%edi) */
0xa1, 0, 0, 0, 0, /* mov VERTEX[3],%eax */
0x8b, 0x15, 0, 0, 0, 0, /* mov VERTEX[4],%edx */
0x8b, 0x0d, 0, 0, 0, 0, /* mov VERTEX[5],%ecx */
0x89, 0x47, 0x0c, /* mov %eax,0xc(%edi) */
0x89, 0x57, 0x10, /* mov %edx,0x10(%edi) */
0x89, 0x4f, 0x14, /* mov %ecx,0x14(%edi) */
0x83, 0xc7, 0x18, /* add $0x18,%edi */
0xa1, 0, 0, 0, 0, /* mov COUNTER,%eax */
0x89, 0x3d, 0, 0, 0, 0, /* mov %edi,DMAPTR */
0x48, /* dec %eax */
0x5f, /* pop %edi */
0xa3, 0, 0, 0, 0, /* mov %eax,COUNTER */
0x74, 0x01, /* je +1 */
0xc3, /* ret */
0xff, 0x25, 0,0,0,0, /* jmp *NOTIFY */
};
 
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
memcpy (dfn->code, temp, sizeof(temp));
FIXUP(dfn->code, 3, 0x0, (int)&tnl->dmaptr);
FIXUP(dfn->code, 28, 0x0, (int)&tnl->vertex[3]);
FIXUP(dfn->code, 34, 0x0, (int)&tnl->vertex[4]);
FIXUP(dfn->code, 40, 0x0, (int)&tnl->vertex[5]);
FIXUP(dfn->code, 57, 0x0, (int)&tnl->counter);
FIXUP(dfn->code, 63, 0x0, (int)&tnl->dmaptr);
FIXUP(dfn->code, 70, 0x0, (int)&tnl->counter);
FIXUP(dfn->code, 79, 0x0, (int)&tnl->notify);
break;
}
default: {
/* Repz convenient as it's possible to emit code for any size
* vertex with little tweaking. Might as well read vertsize
* though, and have only one of these.
*/
static char temp[] = {
0x57, /* push %edi */
0x56, /* push %esi */
0xbe, 0, 0, 0, 0, /* mov $VERTEX+3,%esi */
0x8b, 0x3d, 0, 0, 0, 0, /* mov DMAPTR,%edi */
0x8b, 0x44, 0x24, 0x0c, /* mov 0x0c(%esp,1),%eax */
0x8b, 0x54, 0x24, 0x10, /* mov 0x10(%esp,1),%edx */
0x8b, 0x4c, 0x24, 0x14, /* mov 0x14(%esp,1),%ecx */
0x89, 0x07, /* mov %eax,(%edi) */
0x89, 0x57, 0x04, /* mov %edx,0x4(%edi) */
0x89, 0x4f, 0x08, /* mov %ecx,0x8(%edi) */
0x83, 0xc7, 0x0c, /* add $0xc,%edi */
0xb9, 0, 0, 0, 0, /* mov $VERTSIZE-3,%ecx */
0xf3, 0xa5, /* repz movsl %ds:(%esi),%es:(%edi)*/
0xa1, 0, 0, 0, 0, /* mov COUNTER,%eax */
0x89, 0x3d, 0, 0, 0, 0, /* mov %edi,DMAPTR */
0x48, /* dec %eax */
0xa3, 0, 0, 0, 0, /* mov %eax,COUNTER */
0x5e, /* pop %esi */
0x5f, /* pop %edi */
0x74, 0x01, /* je +1 */
0xc3, /* ret */
0xff, 0x25, 0, 0, 0, 0 /* jmp NOTIFY */
};
 
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
memcpy (dfn->code, temp, sizeof(temp));
FIXUP(dfn->code, 3, 0x0, (int)&tnl->vertex[3]);
FIXUP(dfn->code, 9, 0x0, (int)&tnl->dmaptr);
FIXUP(dfn->code, 37, 0x0, tnl->vertex_size-3);
FIXUP(dfn->code, 44, 0x0, (int)&tnl->counter);
FIXUP(dfn->code, 50, 0x0, (int)&tnl->dmaptr);
FIXUP(dfn->code, 56, 0x0, (int)&tnl->counter);
FIXUP(dfn->code, 67, 0x0, (int)&tnl->notify);
break;
}
}
 
insert_at_head( &tnl->dfn_cache.Vertex3f, dfn );
dfn->key = key;
return dfn;
}
 
 
 
struct dynfn *tnl_makeX86Vertex3fv( TNLcontext *tnl, int key )
{
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
 
if (TNL_DEBUG & DEBUG_CODEGEN)
_mesa_debug(NULL, "%s 0x%08x\n", __FUNCTION__, key );
 
switch (tnl->vertex_size) {
case 6: {
static char temp[] = {
0xa1, 0x00, 0x00, 0, 0, /* mov 0x0,%eax */
0x8b, 0x4c, 0x24, 0x04, /* mov 0x4(%esp,1),%ecx */
0x8b, 0x11, /* mov (%ecx),%edx */
0x89, 0x10, /* mov %edx,(%eax) */
0x8b, 0x51, 0x04, /* mov 0x4(%ecx),%edx */
0x8b, 0x49, 0x08, /* mov 0x8(%ecx),%ecx */
0x89, 0x50, 0x04, /* mov %edx,0x4(%eax) */
0x89, 0x48, 0x08, /* mov %ecx,0x8(%eax) */
0x8b, 0x15, 0x1c, 0, 0, 0, /* mov 0x1c,%edx */
0x8b, 0x0d, 0x20, 0, 0, 0, /* mov 0x20,%ecx */
0x89, 0x50, 0x0c, /* mov %edx,0xc(%eax) */
0x89, 0x48, 0x10, /* mov %ecx,0x10(%eax) */
0x8b, 0x15, 0x24, 0, 0, 0, /* mov 0x24,%edx */
0x89, 0x50, 0x14, /* mov %edx,0x14(%eax) */
0x83, 0xc0, 0x18, /* add $0x18,%eax */
0xa3, 0x00, 0x00, 0, 0, /* mov %eax,0x0 */
0xa1, 0x04, 0x00, 0, 0, /* mov 0x4,%eax */
0x48, /* dec %eax */
0xa3, 0x04, 0x00, 0, 0, /* mov %eax,0x4 */
0x74, 0x01, /* je 2a4 <.f11> */
0xc3, /* ret */
0xff, 0x25, 0x08, 0, 0, 0, /* jmp *0x8 */
};
 
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
memcpy (dfn->code, temp, sizeof(temp));
FIXUP(dfn->code, 1, 0x00000000, (int)&tnl->dmaptr);
FIXUP(dfn->code, 27, 0x0000001c, (int)&tnl->vertex[3]);
FIXUP(dfn->code, 33, 0x00000020, (int)&tnl->vertex[4]);
FIXUP(dfn->code, 45, 0x00000024, (int)&tnl->vertex[5]);
FIXUP(dfn->code, 56, 0x00000000, (int)&tnl->dmaptr);
FIXUP(dfn->code, 61, 0x00000004, (int)&tnl->counter);
FIXUP(dfn->code, 67, 0x00000004, (int)&tnl->counter);
FIXUP(dfn->code, 76, 0x00000008, (int)&tnl->notify);
break;
}
 
case 8: {
static char temp[] = {
0xa1, 0x00, 0x00, 0, 0, /* mov 0x0,%eax */
0x8b, 0x4c, 0x24, 0x04, /* mov 0x4(%esp,1),%ecx */
0x8b, 0x11, /* mov (%ecx),%edx */
0x89, 0x10, /* mov %edx,(%eax) */
0x8b, 0x51, 0x04, /* mov 0x4(%ecx),%edx */
0x8b, 0x49, 0x08, /* mov 0x8(%ecx),%ecx */
0x89, 0x50, 0x04, /* mov %edx,0x4(%eax) */
0x89, 0x48, 0x08, /* mov %ecx,0x8(%eax) */
0x8b, 0x15, 0x1c, 0, 0, 0, /* mov 0x1c,%edx */
0x8b, 0x0d, 0x20, 0, 0, 0, /* mov 0x20,%ecx */
0x89, 0x50, 0x0c, /* mov %edx,0xc(%eax) */
0x89, 0x48, 0x10, /* mov %ecx,0x10(%eax) */
0x8b, 0x15, 0x1c, 0, 0, 0, /* mov 0x1c,%edx */
0x8b, 0x0d, 0x20, 0, 0, 0, /* mov 0x20,%ecx */
0x89, 0x50, 0x14, /* mov %edx,0x14(%eax) */
0x89, 0x48, 0x18, /* mov %ecx,0x18(%eax) */
0x8b, 0x15, 0x24, 0, 0, 0, /* mov 0x24,%edx */
0x89, 0x50, 0x1c, /* mov %edx,0x1c(%eax) */
0x83, 0xc0, 0x20, /* add $0x20,%eax */
0xa3, 0x00, 0x00, 0, 0, /* mov %eax,0x0 */
0xa1, 0x04, 0x00, 0, 0, /* mov 0x4,%eax */
0x48, /* dec %eax */
0xa3, 0x04, 0x00, 0, 0, /* mov %eax,0x4 */
0x74, 0x01, /* je 2a4 <.f11> */
0xc3, /* ret */
0xff, 0x25, 0x08, 0, 0, 0, /* jmp *0x8 */
};
 
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
memcpy (dfn->code, temp, sizeof(temp));
FIXUP(dfn->code, 1, 0x00000000, (int)&tnl->dmaptr);
FIXUP(dfn->code, 27, 0x0000001c, (int)&tnl->vertex[3]);
FIXUP(dfn->code, 33, 0x00000020, (int)&tnl->vertex[4]);
FIXUP(dfn->code, 45, 0x0000001c, (int)&tnl->vertex[5]);
FIXUP(dfn->code, 51, 0x00000020, (int)&tnl->vertex[6]);
FIXUP(dfn->code, 63, 0x00000024, (int)&tnl->vertex[7]);
FIXUP(dfn->code, 74, 0x00000000, (int)&tnl->dmaptr);
FIXUP(dfn->code, 79, 0x00000004, (int)&tnl->counter);
FIXUP(dfn->code, 85, 0x00000004, (int)&tnl->counter);
FIXUP(dfn->code, 94, 0x00000008, (int)&tnl->notify);
break;
}
 
 
default: {
/* Repz convenient as it's possible to emit code for any size
* vertex with little tweaking. Might as well read vertsize
* though, and have only one of these.
*/
static char temp[] = {
0x8b, 0x54, 0x24, 0x04, /* mov 0x4(%esp,1),%edx */
0x57, /* push %edi */
0x56, /* push %esi */
0x8b, 0x3d, 1,1,1,1, /* mov DMAPTR,%edi */
0x8b, 0x02, /* mov (%edx),%eax */
0x8b, 0x4a, 0x04, /* mov 0x4(%edx),%ecx */
0x8b, 0x72, 0x08, /* mov 0x8(%edx),%esi */
0x89, 0x07, /* mov %eax,(%edi) */
0x89, 0x4f, 0x04, /* mov %ecx,0x4(%edi) */
0x89, 0x77, 0x08, /* mov %esi,0x8(%edi) */
0x83, 0xc7, 0x0c, /* add $0xc,%edi */
0xb9, 0x06, 0x00, 0x00, 0x00, /* mov $VERTSIZE-3,%ecx */
0xbe, 0x58, 0x00, 0x00, 0x00, /* mov $VERTEX[3],%esi */
0xf3, 0xa5, /* repz movsl %ds:(%esi),%es:(%edi)*/
0x89, 0x3d, 1, 1, 1, 1, /* mov %edi,DMAPTR */
0xa1, 2, 2, 2, 2, /* mov COUNTER,%eax */
0x5e, /* pop %esi */
0x5f, /* pop %edi */
0x48, /* dec %eax */
0xa3, 2, 2, 2, 2, /* mov %eax,COUNTER */
0x74, 0x01, /* je +1 */
0xc3, /* ret */
0xff, 0x25, 0, 0, 0, 0 /* jmp NOTIFY */
};
 
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
memcpy (dfn->code, temp, sizeof(temp));
FIXUP(dfn->code, 8, 0x01010101, (int)&tnl->dmaptr);
FIXUP(dfn->code, 32, 0x00000006, tnl->vertex_size-3);
FIXUP(dfn->code, 37, 0x00000058, (int)&tnl->vertex[3]);
FIXUP(dfn->code, 45, 0x01010101, (int)&tnl->dmaptr);
FIXUP(dfn->code, 50, 0x02020202, (int)&tnl->counter);
FIXUP(dfn->code, 58, 0x02020202, (int)&tnl->counter);
FIXUP(dfn->code, 67, 0x0, (int)&tnl->notify);
break;
}
}
 
insert_at_head( &tnl->dfn_cache.Vertex3fv, dfn );
dfn->key = key;
return dfn;
}
 
 
struct dynfn *tnl_makeX86Attr4fv( TNLcontext *tnl, int key )
{
static char temp[] = {
0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */
0xba, 0, 0, 0, 0, /* mov $DEST,%edx */
0x8b, 0x08, /* mov (%eax),%ecx */
0x89, 0x0a, /* mov %ecx,(%edx) */
0x8b, 0x48, 0x04, /* mov 0x4(%eax),%ecx */
0x89, 0x4a, 0x04, /* mov %ecx,0x4(%edx) */
0x8b, 0x48, 0x08, /* mov 0x8(%eax),%ecx */
0x89, 0x4a, 0x08, /* mov %ecx,0x8(%edx) */
0x8b, 0x48, 0x0a, /* mov 0xa(%eax),%ecx */
0x89, 0x4a, 0x0a, /* mov %ecx,0xa(%edx) */
0xc3, /* ret */
};
 
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
 
if (TNL_DEBUG & DEBUG_CODEGEN)
_mesa_debug(NULL, "%s 0x%08x\n", __FUNCTION__, key );
 
insert_at_head( &tnl->dfn_cache.Normal3fv, dfn );
dfn->key = key;
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
memcpy (dfn->code, temp, sizeof(temp));
FIXUP(dfn->code, 5, 0x0, (int)tnl->normalptr);
return dfn;
}
 
struct dynfn *tnl_makeX86Attr4f( TNLcontext *tnl, int key )
{
static char temp[] = {
0xba, 0x78, 0x56, 0x34, 0x12, /* mov $DEST,%edx */
0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */
0x89, 0x02, /* mov %eax,(%edx) */
0x8b, 0x44, 0x24, 0x08, /* mov 0x8(%esp,1),%eax */
0x89, 0x42, 0x04, /* mov %eax,0x4(%edx) */
0x8b, 0x44, 0x24, 0x0c, /* mov 0xc(%esp,1),%eax */
0x89, 0x42, 0x08, /* mov %eax,0x8(%edx) */
0x8b, 0x44, 0x24, 0x10, /* mov 0x10(%esp,1),%eax */
0x89, 0x42, 0x0a, /* mov %eax,0xa(%edx) */
0xc3, /* ret */
};
 
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
 
if (TNL_DEBUG & DEBUG_CODEGEN)
_mesa_debug(NULL, "%s 0x%08x\n", __FUNCTION__, key );
 
insert_at_head( &tnl->dfn_cache.Normal3f, dfn );
dfn->key = key;
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
memcpy (dfn->code, temp, sizeof(temp));
FIXUP(dfn->code, 1, 0x12345678, (int)tnl->normalptr);
return dfn;
}
 
 
struct dynfn *tnl_makeX86Attr3fv( TNLcontext *tnl, int key )
{
static char temp[] = {
0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */
0xba, 0, 0, 0, 0, /* mov $DEST,%edx */
0x8b, 0x08, /* mov (%eax),%ecx */
0x89, 0x0a, /* mov %ecx,(%edx) */
0x8b, 0x48, 0x04, /* mov 0x4(%eax),%ecx */
0x89, 0x4a, 0x04, /* mov %ecx,0x4(%edx) */
0x8b, 0x48, 0x08, /* mov 0x8(%eax),%ecx */
0x89, 0x4a, 0x08, /* mov %ecx,0x8(%edx) */
0xc3, /* ret */
};
 
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
 
if (TNL_DEBUG & DEBUG_CODEGEN)
_mesa_debug(NULL, "%s 0x%08x\n", __FUNCTION__, key );
 
insert_at_head( &tnl->dfn_cache.Normal3fv, dfn );
dfn->key = key;
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
memcpy (dfn->code, temp, sizeof(temp));
FIXUP(dfn->code, 5, 0x0, (int)tnl->normalptr);
return dfn;
}
 
struct dynfn *tnl_makeX86Attr3f( TNLcontext *tnl, int key )
{
static char temp[] = {
0xba, 0x78, 0x56, 0x34, 0x12, /* mov $DEST,%edx */
0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */
0x89, 0x02, /* mov %eax,(%edx) */
0x8b, 0x44, 0x24, 0x08, /* mov 0x8(%esp,1),%eax */
0x89, 0x42, 0x04, /* mov %eax,0x4(%edx) */
0x8b, 0x44, 0x24, 0x0c, /* mov 0xc(%esp,1),%eax */
0x89, 0x42, 0x08, /* mov %eax,0x8(%edx) */
0xc3, /* ret */
};
 
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
 
if (TNL_DEBUG & DEBUG_CODEGEN)
_mesa_debug(NULL, "%s 0x%08x\n", __FUNCTION__, key );
 
insert_at_head( &tnl->dfn_cache.Normal3f, dfn );
dfn->key = key;
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
memcpy (dfn->code, temp, sizeof(temp));
FIXUP(dfn->code, 1, 0x12345678, (int)tnl->normalptr);
return dfn;
}
 
struct dynfn *tnl_makeX86Attr4ubv( TNLcontext *tnl, int key )
{
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
insert_at_head( &tnl->dfn_cache.Color4ubv, dfn );
dfn->key = key;
 
if (TNL_DEBUG & DEBUG_CODEGEN)
_mesa_debug(NULL, "%s 0x%08x\n", __FUNCTION__, key );
 
if (key & TNL_CP_VC_FRMT_PKCOLOR) {
static char temp[] = {
0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */
0xba, 0x78, 0x56, 0x34, 0x12, /* mov $DEST,%edx */
0x8b, 0x00, /* mov (%eax),%eax */
0x89, 0x02, /* mov %eax,(%edx) */
0xc3, /* ret */
};
 
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
memcpy (dfn->code, temp, sizeof(temp));
FIXUP(dfn->code, 5, 0x12345678, (int)tnl->ubytecolorptr);
return dfn;
}
else {
static char temp[] = {
0x53, /* push %ebx */
0xba, 0x00, 0x00, 0x00, 0x00, /* mov $0x0,%edx */
0x31, 0xc0, /* xor %eax,%eax */
0x31, 0xc9, /* xor %ecx,%ecx */
0x8b, 0x5c, 0x24, 0x08, /* mov 0x8(%esp,1), %ebx */
0x8b, 0x1b, /* mov (%ebx), %ebx */
0x88, 0xd8, /* mov %bl, %al */
0x88, 0xf9, /* mov %bh, %cl */
0x8b, 0x04, 0x82, /* mov (%edx,%eax,4),%eax */
0x8b, 0x0c, 0x8a, /* mov (%edx,%ecx,4),%ecx */
0xa3, 0xaf, 0xbe, 0xad, 0xde, /* mov %eax,0xdeadbeaf */
0x89, 0x0d, 0xaf, 0xbe, 0xad, 0xde, /* mov %ecx,0xdeadbeaf */
0x31, 0xc0, /* xor %eax,%eax */
0x31, 0xc9, /* xor %ecx,%ecx */
0xc1, 0xeb, 0x10, /* shr $0x10, %ebx */
0x88, 0xd8, /* mov %bl, %al */
0x88, 0xf9, /* mov %bh, %cl */
0x8b, 0x04, 0x82, /* mov (%edx,%eax,4),%eax */
0x8b, 0x0c, 0x8a, /* mov (%edx,%ecx,4),%ecx */
0xa3, 0xaf, 0xbe, 0xad, 0xde, /* mov %eax,0xdeadbeaf */
0x89, 0x0d, 0xaf, 0xbe, 0xad, 0xde, /* mov %ecx,0xdeadbeaf */
0x5b, /* pop %ebx */
0xc3, /* ret */
};
 
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
memcpy (dfn->code, temp, sizeof(temp));
FIXUP(dfn->code, 2, 0x00000000, (int)_mesa_ubyte_to_float_color_tab);
FIXUP(dfn->code, 27, 0xdeadbeaf, (int)tnl->floatcolorptr);
FIXUP(dfn->code, 33, 0xdeadbeaf, (int)tnl->floatcolorptr+4);
FIXUP(dfn->code, 55, 0xdeadbeaf, (int)tnl->floatcolorptr+8);
FIXUP(dfn->code, 61, 0xdeadbeaf, (int)tnl->floatcolorptr+12);
return dfn;
}
}
 
struct dynfn *tnl_makeX86Attr4ub( TNLcontext *tnl, int key )
{
if (TNL_DEBUG & DEBUG_CODEGEN)
_mesa_debug(NULL, "%s 0x%08x\n", __FUNCTION__, key );
 
if (key & TNL_CP_VC_FRMT_PKCOLOR) {
/* XXX push/pop */
static char temp[] = {
0x53, /* push %ebx */
0x8b, 0x44, 0x24, 0x08, /* mov 0x8(%esp,1),%eax */
0x8b, 0x54, 0x24, 0x0c, /* mov 0xc(%esp,1),%edx */
0x8b, 0x4c, 0x24, 0x10, /* mov 0x10(%esp,1),%ecx */
0x8b, 0x5c, 0x24, 0x14, /* mov 0x14(%esp,1),%ebx */
0xa2, 0, 0, 0, 0, /* mov %al,DEST */
0x88, 0x15, 0, 0, 0, 0, /* mov %dl,DEST+1 */
0x88, 0x0d, 0, 0, 0, 0, /* mov %cl,DEST+2 */
0x88, 0x1d, 0, 0, 0, 0, /* mov %bl,DEST+3 */
0x5b, /* pop %ebx */
0xc3, /* ret */
};
 
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
insert_at_head( &tnl->dfn_cache.Color4ub, dfn );
dfn->key = key;
 
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
memcpy (dfn->code, temp, sizeof(temp));
FIXUP(dfn->code, 18, 0x0, (int)tnl->ubytecolorptr);
FIXUP(dfn->code, 24, 0x0, (int)tnl->ubytecolorptr+1);
FIXUP(dfn->code, 30, 0x0, (int)tnl->ubytecolorptr+2);
FIXUP(dfn->code, 36, 0x0, (int)tnl->ubytecolorptr+3);
return dfn;
}
else
return 0;
}
 
 
 
struct dynfn *tnl_makeX86Attr2fv( TNLcontext *tnl, int key )
{
static char temp[] = {
0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */
0xba, 0x78, 0x56, 0x34, 0x12, /* mov $DEST,%edx */
0x8b, 0x08, /* mov (%eax),%ecx */
0x8b, 0x40, 0x04, /* mov 0x4(%eax),%eax */
0x89, 0x0a, /* mov %ecx,(%edx) */
0x89, 0x42, 0x04, /* mov %eax,0x4(%edx) */
0xc3, /* ret */
};
 
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
 
if (TNL_DEBUG & DEBUG_CODEGEN)
_mesa_debug(NULL, "%s 0x%08x\n", __FUNCTION__, key );
 
insert_at_head( &tnl->dfn_cache.TexCoord2fv, dfn );
dfn->key = key;
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
memcpy (dfn->code, temp, sizeof(temp));
FIXUP(dfn->code, 5, 0x12345678, (int)tnl->texcoordptr[0]);
return dfn;
}
 
struct dynfn *tnl_makeX86Attr2f( TNLcontext *tnl, int key )
{
static char temp[] = {
0xba, 0x78, 0x56, 0x34, 0x12, /* mov $DEST,%edx */
0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */
0x8b, 0x4c, 0x24, 0x08, /* mov 0x8(%esp,1),%ecx */
0x89, 0x02, /* mov %eax,(%edx) */
0x89, 0x4a, 0x04, /* mov %ecx,0x4(%edx) */
0xc3, /* ret */
};
 
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
 
if (TNL_DEBUG & DEBUG_CODEGEN)
_mesa_debug(NULL, "%s 0x%08x\n", __FUNCTION__, key );
 
insert_at_head( &tnl->dfn_cache.TexCoord2f, dfn );
dfn->key = key;
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
memcpy (dfn->code, temp, sizeof(temp));
FIXUP(dfn->code, 1, 0x12345678, (int)tnl->texcoordptr[0]);
return dfn;
}
 
 
struct dynfn *tnl_makeX86Attr1fv( TNLcontext *tnl, int key )
{
static char temp[] = {
0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */
0xba, 0x78, 0x56, 0x34, 0x12, /* mov $DEST,%edx */
0x8b, 0x08, /* mov (%eax),%ecx */
0x89, 0x0a, /* mov %ecx,(%edx) */
0xc3, /* ret */
};
 
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
 
if (TNL_DEBUG & DEBUG_CODEGEN)
_mesa_debug(NULL, "%s 0x%08x\n", __FUNCTION__, key );
 
insert_at_head( &tnl->dfn_cache.TexCoord2fv, dfn );
dfn->key = key;
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
memcpy (dfn->code, temp, sizeof(temp));
FIXUP(dfn->code, 5, 0x12345678, (int)tnl->texcoordptr[0]);
return dfn;
}
 
struct dynfn *tnl_makeX86Attr1f( TNLcontext *tnl, int key )
{
static char temp[] = {
0xba, 0x78, 0x56, 0x34, 0x12, /* mov $DEST,%edx */
0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */
0x89, 0x02, /* mov %eax,(%edx) */
0xc3, /* ret */
};
 
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
 
if (TNL_DEBUG & DEBUG_CODEGEN)
_mesa_debug(NULL, "%s 0x%08x\n", __FUNCTION__, key );
 
insert_at_head( &tnl->dfn_cache.TexCoord2f, dfn );
dfn->key = key;
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
memcpy (dfn->code, temp, sizeof(temp));
FIXUP(dfn->code, 1, 0x12345678, (int)tnl->texcoordptr[0]);
return dfn;
}
 
 
 
void _tnl_InitX86Codegen( struct dfn_generators *gen )
{
gen->Attr1f = tnl_makeX86Attr1f;
gen->Attr1fv = tnl_makeX86Attr1fv;
gen->Attr2f = tnl_makeX86Attr2f;
gen->Attr2fv = tnl_makeX86Attr2fv;
gen->Attr3f = tnl_makeX86Attr3f;
gen->Attr3fv = tnl_makeX86Attr3fv;
gen->Attr4f = tnl_makeX86Attr4f;
gen->Attr4fv = tnl_makeX86Attr4fv;
gen->Attr4ub = tnl_makeX86Attr4ub;
gen->Attr4ubv = tnl_makeX86Attr4ubv;
gen->Vertex3f = tnl_makeX86Vertex3f;
gen->Vertex3fv = tnl_makeX86Vertex3fv;
}
 
 
#else
 
void _tnl_InitX86Codegen( struct dfn_generators *gen )
{
(void) gen;
}
 
#endif
/shark/trunk/ports/mesa/src/tnl/t_vtx_sse.c
0,0 → 1,91
/* $XFree86$ */
/**************************************************************************
 
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
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
TUNGSTEN GRAPHICS 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 "imports.h"
#include "simple_list.h"
#include "t_vtx_api.h"
 
#if defined(USE_SSE_ASM)
 
/* Build specialized versions of the immediate calls on the fly for
* the current state. ???P4 SSE2 versions???
*/
 
 
static struct dynfn *makeSSENormal3fv( struct _vb *vb, int key )
{
/* Requires P4 (sse2?)
*/
static unsigned char temp[] = {
0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */
0xba, 0x78, 0x56, 0x34, 0x12, /* mov $0x12345678,%edx */
0xf3, 0x0f, 0x7e, 0x00, /* movq (%eax),%xmm0 */
0x66, 0x0f, 0x6e, 0x48, 0x08, /* movd 0x8(%eax),%xmm1 */
0x66, 0x0f, 0xd6, 0x42, 0x0c, /* movq %xmm0,0xc(%edx) */
0x66, 0x0f, 0x7e, 0x4a, 0x14, /* movd %xmm1,0x14(%edx) */
0xc3, /* ret */
};
 
 
struct dynfn *dfn = MALLOC_STRUCT( dynfn );
insert_at_head( &vb->dfn_cache.Normal3fv, dfn );
dfn->key = key;
 
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 );
memcpy (dfn->code, temp, sizeof(temp));
FIXUP(dfn->code, 5, 0x0, (int)vb->normalptr);
return dfn;
}
 
void _tnl_InitSSECodegen( struct dfn_generators *gen )
{
/* Need to:
* - check kernel sse support
* - check p4/sse2
*/
(void) makeSSENormal3fv;
}
 
 
#else
 
void _tnl_InitSSECodegen( struct dfn_generators *gen )
{
(void) gen;
}
 
#endif
 
 
 
 
/shark/trunk/ports/mesa/src/tnl/t_imm_alloc.c
0,0 → 1,124
/* $Id: t_imm_alloc.c,v 1.1 2003-02-28 11:48:06 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 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.
*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
#include "glheader.h"
#include "imports.h"
#include "mtypes.h"
 
#include "t_imm_alloc.h"
 
 
static int id = 0; /* give each struct immediate a unique ID number */
 
static struct immediate *real_alloc_immediate( GLcontext *ctx )
{
struct immediate *IM = ALIGN_CALLOC_STRUCT( immediate, 32 );
 
if (!IM)
return 0;
 
/* memset(IM, 0, sizeof(*IM)); */
 
IM->id = id++;
IM->ref_count = 0;
IM->FlushElt = 0;
IM->LastPrimitive = IMM_MAX_COPIED_VERTS;
IM->Count = IMM_MAX_COPIED_VERTS;
IM->Start = IMM_MAX_COPIED_VERTS;
IM->Material = 0;
IM->MaterialMask = 0;
IM->MaxTextureUnits = ctx->Const.MaxTextureUnits;
IM->TexSize = 0;
IM->NormalLengthPtr = 0;
 
IM->CopyTexSize = 0;
IM->CopyStart = IM->Start;
 
return IM;
}
 
 
static void real_free_immediate( struct immediate *IM )
{
static int freed = 0;
 
if (IM->Material) {
FREE( IM->Material );
FREE( IM->MaterialMask );
IM->Material = 0;
IM->MaterialMask = 0;
}
 
if (IM->NormalLengthPtr)
ALIGN_FREE( IM->NormalLengthPtr );
 
ALIGN_FREE( IM );
freed++;
/* printf("outstanding %d\n", id - freed); */
}
 
 
/* Cache a single allocated immediate struct.
*/
struct immediate *_tnl_alloc_immediate( GLcontext *ctx )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct immediate *tmp = tnl->freed_immediate;
if (tmp) {
tnl->freed_immediate = 0;
return tmp;
}
else
return real_alloc_immediate( ctx );
}
 
/* May be called after tnl is destroyed.
*/
void _tnl_free_immediate( GLcontext *ctx, struct immediate *IM )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
 
ASSERT(IM->ref_count == 0);
 
if (IM->NormalLengthPtr) {
ALIGN_FREE(IM->NormalLengthPtr);
IM->NormalLengthPtr = NULL;
}
 
if (!tnl) {
real_free_immediate( IM );
}
else {
if (tnl->freed_immediate)
real_free_immediate( tnl->freed_immediate );
tnl->freed_immediate = IM;
}
}
/shark/trunk/ports/mesa/src/tnl/t_vb_rendertmp.h
0,0 → 1,445
/* $Id: t_vb_rendertmp.h,v 1.1 2003-02-28 11:48:08 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
 
#ifndef POSTFIX
#define POSTFIX
#endif
 
#ifndef INIT
#define INIT(x)
#endif
 
#ifndef NEED_EDGEFLAG_SETUP
#define NEED_EDGEFLAG_SETUP 0
#define EDGEFLAG_GET(a) 0
#define EDGEFLAG_SET(a,b) (void)b
#endif
 
#ifndef RESET_STIPPLE
#define RESET_STIPPLE
#endif
 
#ifndef RESET_OCCLUSION
#define RESET_OCCLUSION
#endif
 
#ifndef TEST_PRIM_END
#define TEST_PRIM_END(flags) (flags & PRIM_END)
#define TEST_PRIM_BEGIN(flags) (flags & PRIM_BEGIN)
#define TEST_PRIM_PARITY(flags) (flags & PRIM_PARITY)
#endif
 
#ifndef ELT
#define ELT(x) x
#endif
 
#ifndef RENDER_TAB_QUALIFIER
#define RENDER_TAB_QUALIFIER static
#endif
 
static void TAG(render_points)( GLcontext *ctx,
GLuint start,
GLuint count,
GLuint flags )
{
LOCAL_VARS;
(void) flags;
 
RESET_OCCLUSION;
INIT(GL_POINTS);
RENDER_POINTS( start, count );
POSTFIX;
}
 
static void TAG(render_lines)( GLcontext *ctx,
GLuint start,
GLuint count,
GLuint flags )
{
GLuint j;
LOCAL_VARS;
(void) flags;
 
RESET_OCCLUSION;
INIT(GL_LINES);
for (j=start+1; j<count; j+=2 ) {
RESET_STIPPLE;
RENDER_LINE( ELT(j-1), ELT(j) );
}
POSTFIX;
}
 
 
static void TAG(render_line_strip)( GLcontext *ctx,
GLuint start,
GLuint count,
GLuint flags )
{
GLuint j;
LOCAL_VARS;
(void) flags;
 
RESET_OCCLUSION;
INIT(GL_LINE_STRIP);
 
if (TEST_PRIM_BEGIN(flags)) {
RESET_STIPPLE;
}
 
for (j=start+1; j<count; j++ )
RENDER_LINE( ELT(j-1), ELT(j) );
 
POSTFIX;
}
 
 
static void TAG(render_line_loop)( GLcontext *ctx,
GLuint start,
GLuint count,
GLuint flags )
{
GLuint i;
LOCAL_VARS;
 
(void) flags;
 
RESET_OCCLUSION;
INIT(GL_LINE_LOOP);
 
if (start+1 < count) {
if (TEST_PRIM_BEGIN(flags)) {
RESET_STIPPLE;
RENDER_LINE( ELT(start), ELT(start+1) );
}
 
for ( i = start+2 ; i < count ; i++) {
RENDER_LINE( ELT(i-1), ELT(i) );
}
 
if ( TEST_PRIM_END(flags)) {
RENDER_LINE( ELT(count-1), ELT(start) );
}
}
 
POSTFIX;
}
 
 
static void TAG(render_triangles)( GLcontext *ctx,
GLuint start,
GLuint count,
GLuint flags )
{
GLuint j;
LOCAL_VARS;
(void) flags;
 
INIT(GL_TRIANGLES);
if (NEED_EDGEFLAG_SETUP) {
for (j=start+2; j<count; j+=3) {
/* Leave the edgeflags as supplied by the user.
*/
RESET_STIPPLE;
RENDER_TRI( ELT(j-2), ELT(j-1), ELT(j) );
}
} else {
for (j=start+2; j<count; j+=3) {
RENDER_TRI( ELT(j-2), ELT(j-1), ELT(j) );
}
}
POSTFIX;
}
 
 
 
static void TAG(render_tri_strip)( GLcontext *ctx,
GLuint start,
GLuint count,
GLuint flags )
{
GLuint j;
GLuint parity = 0;
LOCAL_VARS;
 
if (TEST_PRIM_PARITY(flags))
parity = 1;
 
INIT(GL_TRIANGLE_STRIP);
if (NEED_EDGEFLAG_SETUP) {
for (j=start+2;j<count;j++,parity^=1) {
GLuint ej2 = ELT(j-2+parity);
GLuint ej1 = ELT(j-1-parity);
GLuint ej = ELT(j);
GLboolean ef2 = EDGEFLAG_GET( ej2 );
GLboolean ef1 = EDGEFLAG_GET( ej1 );
GLboolean ef = EDGEFLAG_GET( ej );
if (TEST_PRIM_BEGIN(flags)) {
RESET_STIPPLE;
}
EDGEFLAG_SET( ej2, GL_TRUE );
EDGEFLAG_SET( ej1, GL_TRUE );
EDGEFLAG_SET( ej, GL_TRUE );
RENDER_TRI( ej2, ej1, ej );
EDGEFLAG_SET( ej2, ef2 );
EDGEFLAG_SET( ej1, ef1 );
EDGEFLAG_SET( ej, ef );
}
} else {
for (j=start+2; j<count ; j++, parity^=1) {
RENDER_TRI( ELT(j-2+parity), ELT(j-1-parity), ELT(j) );
}
}
POSTFIX;
}
 
 
static void TAG(render_tri_fan)( GLcontext *ctx,
GLuint start,
GLuint count,
GLuint flags )
{
GLuint j;
LOCAL_VARS;
(void) flags;
 
INIT(GL_TRIANGLE_FAN);
if (NEED_EDGEFLAG_SETUP) {
for (j=start+2;j<count;j++) {
/* For trifans, all edges are boundary.
*/
GLuint ejs = ELT(start);
GLuint ej1 = ELT(j-1);
GLuint ej = ELT(j);
GLboolean efs = EDGEFLAG_GET( ejs );
GLboolean ef1 = EDGEFLAG_GET( ej1 );
GLboolean ef = EDGEFLAG_GET( ej );
if (TEST_PRIM_BEGIN(flags)) {
RESET_STIPPLE;
}
EDGEFLAG_SET( ejs, GL_TRUE );
EDGEFLAG_SET( ej1, GL_TRUE );
EDGEFLAG_SET( ej, GL_TRUE );
RENDER_TRI( ejs, ej1, ej);
EDGEFLAG_SET( ejs, efs );
EDGEFLAG_SET( ej1, ef1 );
EDGEFLAG_SET( ej, ef );
}
} else {
for (j=start+2;j<count;j++) {
RENDER_TRI( ELT(start), ELT(j-1), ELT(j) );
}
}
 
POSTFIX;
}
 
 
static void TAG(render_poly)( GLcontext *ctx,
GLuint start,
GLuint count,
GLuint flags )
{
GLuint j = start+2;
LOCAL_VARS;
(void) flags;
 
INIT(GL_POLYGON);
if (NEED_EDGEFLAG_SETUP) {
GLboolean efstart = EDGEFLAG_GET( ELT(start) );
GLboolean efcount = EDGEFLAG_GET( ELT(count-1) );
 
/* If the primitive does not begin here, the first edge
* is non-boundary.
*/
if (!TEST_PRIM_BEGIN(flags))
EDGEFLAG_SET( ELT(start), GL_FALSE );
else {
RESET_STIPPLE;
}
 
/* If the primitive does not end here, the final edge is
* non-boundary.
*/
if (!TEST_PRIM_END(flags))
EDGEFLAG_SET( ELT(count-1), GL_FALSE );
 
/* Draw the first triangles (possibly zero)
*/
if (j+1<count) {
GLboolean ef = EDGEFLAG_GET( ELT(j) );
EDGEFLAG_SET( ELT(j), GL_FALSE );
RENDER_TRI( ELT(j-1), ELT(j), ELT(start) );
EDGEFLAG_SET( ELT(j), ef );
j++;
 
/* Don't render the first edge again:
*/
EDGEFLAG_SET( ELT(start), GL_FALSE );
 
for (;j+1<count;j++) {
GLboolean efj = EDGEFLAG_GET( ELT(j) );
EDGEFLAG_SET( ELT(j), GL_FALSE );
RENDER_TRI( ELT(j-1), ELT(j), ELT(start) );
EDGEFLAG_SET( ELT(j), efj );
}
}
 
/* Draw the last or only triangle
*/
if (j < count)
RENDER_TRI( ELT(j-1), ELT(j), ELT(start) );
 
/* Restore the first and last edgeflags:
*/
EDGEFLAG_SET( ELT(count-1), efcount );
EDGEFLAG_SET( ELT(start), efstart );
 
}
else {
for (j=start+2;j<count;j++) {
RENDER_TRI( ELT(j-1), ELT(j), ELT(start) );
}
}
POSTFIX;
}
 
static void TAG(render_quads)( GLcontext *ctx,
GLuint start,
GLuint count,
GLuint flags )
{
GLuint j;
LOCAL_VARS;
(void) flags;
 
INIT(GL_QUADS);
if (NEED_EDGEFLAG_SETUP) {
for (j=start+3; j<count; j+=4) {
/* Use user-specified edgeflags for quads.
*/
RESET_STIPPLE;
RENDER_QUAD( ELT(j-3), ELT(j-2), ELT(j-1), ELT(j) );
}
} else {
for (j=start+3; j<count; j+=4) {
RENDER_QUAD( ELT(j-3), ELT(j-2), ELT(j-1), ELT(j) );
}
}
POSTFIX;
}
 
static void TAG(render_quad_strip)( GLcontext *ctx,
GLuint start,
GLuint count,
GLuint flags )
{
GLuint j;
LOCAL_VARS;
(void) flags;
 
INIT(GL_QUAD_STRIP);
if (NEED_EDGEFLAG_SETUP) {
for (j=start+3;j<count;j+=2) {
/* All edges are boundary. Set edgeflags to 1, draw the
* quad, and restore them to the original values.
*/
GLboolean ef3 = EDGEFLAG_GET( ELT(j-3) );
GLboolean ef2 = EDGEFLAG_GET( ELT(j-2) );
GLboolean ef1 = EDGEFLAG_GET( ELT(j-1) );
GLboolean ef = EDGEFLAG_GET( ELT(j) );
if (TEST_PRIM_BEGIN(flags)) {
RESET_STIPPLE;
}
EDGEFLAG_SET( ELT(j-3), GL_TRUE );
EDGEFLAG_SET( ELT(j-2), GL_TRUE );
EDGEFLAG_SET( ELT(j-1), GL_TRUE );
EDGEFLAG_SET( ELT(j), GL_TRUE );
RENDER_QUAD( ELT(j-1), ELT(j-3), ELT(j-2), ELT(j) );
EDGEFLAG_SET( ELT(j-3), ef3 );
EDGEFLAG_SET( ELT(j-2), ef2 );
EDGEFLAG_SET( ELT(j-1), ef1 );
EDGEFLAG_SET( ELT(j), ef );
}
} else {
for (j=start+3;j<count;j+=2) {
RENDER_QUAD( ELT(j-1), ELT(j-3), ELT(j-2), ELT(j) );
}
}
POSTFIX;
}
 
static void TAG(render_noop)( GLcontext *ctx,
GLuint start,
GLuint count,
GLuint flags )
{
(void)(ctx && start && count && flags);
}
 
RENDER_TAB_QUALIFIER void (*TAG(render_tab)[GL_POLYGON+2])(GLcontext *,
GLuint,
GLuint,
GLuint) =
{
TAG(render_points),
TAG(render_lines),
TAG(render_line_loop),
TAG(render_line_strip),
TAG(render_triangles),
TAG(render_tri_strip),
TAG(render_tri_fan),
TAG(render_quads),
TAG(render_quad_strip),
TAG(render_poly),
TAG(render_noop),
};
 
 
 
#ifndef PRESERVE_VB_DEFS
#undef RENDER_TRI
#undef RENDER_QUAD
#undef RENDER_LINE
#undef RENDER_POINTS
#undef LOCAL_VARS
#undef INIT
#undef POSTFIX
#undef RESET_STIPPLE
#undef DBG
#undef ELT
#undef RENDER_TAB_QUALIFIER
#endif
 
#ifndef PRESERVE_TAG
#undef TAG
#endif
 
#undef PRESERVE_VB_DEFS
#undef PRESERVE_TAG
/shark/trunk/ports/mesa/src/tnl/t_imm_fixup.c
0,0 → 1,871
/* $Id: t_imm_fixup.c,v 1.1 2003-02-28 11:48:07 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 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.
*/
 
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
 
#include "glheader.h"
#include "context.h"
#include "enums.h"
#include "dlist.h"
#include "colormac.h"
#include "light.h"
#include "macros.h"
#include "imports.h"
#include "mmath.h"
#include "state.h"
#include "mtypes.h"
 
#include "math/m_matrix.h"
#include "math/m_xform.h"
 
#include "t_context.h"
#include "t_imm_alloc.h"
#include "t_imm_debug.h"
#include "t_imm_elt.h"
#include "t_imm_fixup.h"
#include "t_imm_exec.h"
#include "t_pipeline.h"
 
 
static const GLuint increment[GL_POLYGON+2] = { 1,2,1,1,3,1,1,4,2,1,1 };
static const GLuint intro[GL_POLYGON+2] = { 0,0,2,2,0,2,2,0,2,2,0 };
 
void
_tnl_fixup_4f( GLfloat data[][4], GLuint flag[], GLuint start, GLuint match )
{
GLuint i = start;
 
for (;;) {
if ((flag[++i] & match) == 0) {
COPY_4FV(data[i], data[i-1]);
if (flag[i] & VERT_BIT_END_VB) break;
}
}
}
 
void
_tnl_fixup_3f( float data[][3], GLuint flag[], GLuint start, GLuint match )
{
GLuint i = start;
 
 
for (;;) {
if ((flag[++i] & match) == 0) {
/* _mesa_debug(NULL, "_tnl_fixup_3f copy to %p values %f %f %f\n", */
/* data[i], */
/* data[i-1][0], */
/* data[i-1][1], */
/* data[i-1][2]); */
COPY_3V(data[i], data[i-1]);
if (flag[i] & VERT_BIT_END_VB) break;
}
}
}
 
 
void
_tnl_fixup_1ui( GLuint *data, GLuint flag[], GLuint start, GLuint match )
{
GLuint i = start;
 
for (;;) {
if ((flag[++i] & match) == 0) {
data[i] = data[i-1];
if (flag[i] & VERT_BIT_END_VB) break;
}
}
flag[i] |= match;
}
 
 
void
_tnl_fixup_1f( GLfloat *data, GLuint flag[], GLuint start, GLuint match )
{
GLuint i = start;
 
for (;;) {
if ((flag[++i] & match) == 0) {
data[i] = data[i-1];
if (flag[i] & VERT_BIT_END_VB) break;
}
}
flag[i] |= match;
}
 
void
_tnl_fixup_1ub( GLubyte *data, GLuint flag[], GLuint start, GLuint match )
{
GLuint i = start;
 
for (;;) {
if ((flag[++i] & match) == 0) {
data[i] = data[i-1];
if (flag[i] & VERT_BIT_END_VB) break;
}
}
flag[i] |= match;
}
 
 
static void
fixup_first_4f( GLfloat data[][4], GLuint flag[], GLuint match,
GLuint start, GLfloat *dflt )
{
GLuint i = start-1;
match |= VERT_BIT_END_VB;
 
while ((flag[++i]&match) == 0)
COPY_4FV(data[i], dflt);
}
 
#if 0
static void
fixup_first_3f( GLfloat data[][3], GLuint flag[], GLuint match,
GLuint start, GLfloat *dflt )
{
GLuint i = start-1;
match |= VERT_BIT_END_VB;
 
/* _mesa_debug(NULL, "fixup_first_3f default: %f %f %f start: %d\n", */
/* dflt[0], dflt[1], dflt[2], start); */
 
while ((flag[++i]&match) == 0)
COPY_3FV(data[i], dflt);
}
#endif
 
static void
fixup_first_1ui( GLuint data[], GLuint flag[], GLuint match,
GLuint start, GLuint dflt )
{
GLuint i = start-1;
match |= VERT_BIT_END_VB;
 
while ((flag[++i]&match) == 0)
data[i] = dflt;
}
 
#if 00
static void
fixup_first_1f( GLfloat data[], GLuint flag[], GLuint match,
GLuint start, GLfloat dflt )
{
GLuint i = start-1;
match |= VERT_BIT_END_VB;
 
while ((flag[++i]&match) == 0)
data[i] = dflt;
}
#endif
 
static void
fixup_first_1ub( GLubyte data[], GLuint flag[], GLuint match,
GLuint start, GLubyte dflt )
{
GLuint i = start-1;
match |= VERT_BIT_END_VB;
 
while ((flag[++i]&match) == 0)
data[i] = dflt;
}
 
/*
* Copy vertex attributes from the ctx->Current group into the immediate
* struct at the given position according to copyMask.
*/
static void copy_from_current( GLcontext *ctx, struct immediate *IM,
GLuint pos, GLuint copyMask )
{
GLuint attrib, attribBit;
 
if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
_tnl_print_vert_flags("copy from current", copyMask);
 
#if 0
if (copyMask & VERT_BIT_NORMAL) {
COPY_4V(IM->Attrib[VERT_ATTRIB_NORMAL][pos],
ctx->Current.Attrib[VERT_ATTRIB_NORMAL]);
}
 
if (copyMask & VERT_BIT_COLOR0) {
COPY_4FV( IM->Attrib[VERT_ATTRIB_COLOR0][pos],
ctx->Current.Attrib[VERT_ATTRIB_COLOR0]);
}
 
if (copyMask & VERT_BIT_COLOR1)
COPY_4FV( IM->Attrib[VERT_ATTRIB_COLOR1][pos],
ctx->Current.Attrib[VERT_ATTRIB_COLOR1]);
 
if (copyMask & VERT_BIT_FOG)
IM->Attrib[VERT_ATTRIB_FOG][pos][0] = ctx->Current.Attrib[VERT_ATTRIB_FOG][0];
 
if (copyMask & VERT_BITS_TEX_ANY) {
GLuint i;
for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) {
if (copyMask & VERT_BIT_TEX(i))
COPY_4FV(IM->Attrib[VERT_ATTRIB_TEX0 + i][pos],
ctx->Current.Attrib[VERT_ATTRIB_TEX0 + i]);
}
}
#else
for (attrib = 0, attribBit = 1; attrib < 16; attrib++, attribBit <<= 1) {
if (copyMask & attribBit) {
COPY_4FV( IM->Attrib[attrib][pos], ctx->Current.Attrib[attrib]);
}
}
#endif
 
if (copyMask & VERT_BIT_INDEX)
IM->Index[pos] = ctx->Current.Index;
 
if (copyMask & VERT_BIT_EDGEFLAG)
IM->EdgeFlag[pos] = ctx->Current.EdgeFlag;
}
 
 
void _tnl_fixup_input( GLcontext *ctx, struct immediate *IM )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
GLuint start = IM->CopyStart;
GLuint andflag = IM->CopyAndFlag;
GLuint orflag = IM->CopyOrFlag | IM->Evaluated;
GLuint fixup;
 
IM->CopyTexSize = IM->TexSize;
 
/* _mesa_debug(ctx, "Fixup input, Start: %u Count: %u LastData: %u\n", */
/* IM->Start, IM->Count, IM->LastData); */
/* _tnl_print_vert_flags("Orflag", orflag); */
/* _tnl_print_vert_flags("Andflag", andflag); */
 
 
fixup = ~andflag & VERT_BITS_FIXUP;
 
if (!ctx->CompileFlag)
fixup &= tnl->pipeline.inputs;
 
if (!ctx->ExecuteFlag)
fixup &= orflag;
 
if ((orflag & (VERT_BIT_POS|VERT_BITS_EVAL_ANY)) == 0)
fixup = 0;
 
if (fixup) {
GLuint copy = fixup & ~IM->Flag[start];
 
 
/* Equivalent to a lazy copy-from-current when setting up the
* immediate.
*/
if (ctx->ExecuteFlag && copy)
copy_from_current( ctx, IM, start, copy );
 
if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
_tnl_print_vert_flags("fixup", fixup);
 
/* XXX replace these conditionals with a loop over the 16
* vertex attributes.
*/
 
if (fixup & VERT_BITS_TEX_ANY) {
GLuint i;
for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) {
if (fixup & VERT_BIT_TEX(i)) {
if (orflag & VERT_BIT_TEX(i))
_tnl_fixup_4f( IM->Attrib[VERT_ATTRIB_TEX0 + i], IM->Flag,
start, VERT_BIT_TEX(i) );
else
fixup_first_4f( IM->Attrib[VERT_ATTRIB_TEX0 + i], IM->Flag,
VERT_BIT_END_VB, start,
IM->Attrib[VERT_ATTRIB_TEX0 + i][start]);
}
}
}
 
if (fixup & VERT_BIT_EDGEFLAG) {
if (orflag & VERT_BIT_EDGEFLAG)
_tnl_fixup_1ub( IM->EdgeFlag, IM->Flag, start, VERT_BIT_EDGEFLAG );
else
fixup_first_1ub( IM->EdgeFlag, IM->Flag, VERT_BIT_END_VB, start,
IM->EdgeFlag[start] );
}
 
if (fixup & VERT_BIT_INDEX) {
if (orflag & VERT_BIT_INDEX)
_tnl_fixup_1ui( IM->Index, IM->Flag, start, VERT_BIT_INDEX );
else
fixup_first_1ui( IM->Index, IM->Flag, VERT_BIT_END_VB, start,
IM->Index[start] );
}
 
if (fixup & VERT_BIT_COLOR0) {
if (orflag & VERT_BIT_COLOR0)
_tnl_fixup_4f( IM->Attrib[VERT_ATTRIB_COLOR0], IM->Flag, start,
VERT_BIT_COLOR0 );
/* No need for else case as the drivers understand stride
* zero here. (TODO - propogate this)
*/
}
if (fixup & VERT_BIT_COLOR1) {
if (orflag & VERT_BIT_COLOR1)
_tnl_fixup_4f( IM->Attrib[VERT_ATTRIB_COLOR1], IM->Flag, start,
VERT_BIT_COLOR1 );
else
fixup_first_4f( IM->Attrib[VERT_ATTRIB_COLOR1], IM->Flag, VERT_BIT_END_VB, start,
IM->Attrib[VERT_ATTRIB_COLOR1][start] );
}
if (fixup & VERT_BIT_FOG) {
if (orflag & VERT_BIT_FOG)
_tnl_fixup_4f( IM->Attrib[VERT_ATTRIB_FOG], IM->Flag,
start, VERT_BIT_FOG );
else
fixup_first_4f( IM->Attrib[VERT_ATTRIB_FOG], IM->Flag, VERT_BIT_END_VB,
start, IM->Attrib[VERT_ATTRIB_FOG][start] );
}
 
if (fixup & VERT_BIT_NORMAL) {
if (orflag & VERT_BIT_NORMAL)
_tnl_fixup_4f( IM->Attrib[VERT_ATTRIB_NORMAL], IM->Flag, start,
VERT_BIT_NORMAL );
else
fixup_first_4f( IM->Attrib[VERT_ATTRIB_NORMAL], IM->Flag,
VERT_BIT_END_VB, start,
IM->Attrib[VERT_ATTRIB_NORMAL][start] );
}
}
/* Prune possible half-filled slot.
*/
IM->Flag[IM->LastData+1] &= ~VERT_BIT_END_VB;
IM->Flag[IM->Count] |= VERT_BIT_END_VB;
 
 
/* Materials:
*/
if (IM->MaterialOrMask & ~IM->MaterialAndMask) {
GLuint vulnerable = IM->MaterialOrMask;
GLuint i = IM->Start;
 
do {
while (!(IM->Flag[i] & VERT_BIT_MATERIAL))
i++;
 
vulnerable &= ~IM->MaterialMask[i];
_mesa_copy_material_pairs( IM->Material[i],
ctx->Light.Material,
vulnerable );
 
 
++i;
} while (vulnerable);
}
}
 
 
static void
copy_material( struct immediate *next,
struct immediate *prev,
GLuint dst, GLuint src )
{
/* _mesa_debug(NULL, "%s\n", __FUNCTION__); */
 
if (next->Material == 0) {
next->Material = (struct gl_material (*)[2])
MALLOC( sizeof(struct gl_material) * IMM_SIZE * 2 );
next->MaterialMask = (GLuint *) MALLOC( sizeof(GLuint) * IMM_SIZE );
}
 
next->MaterialMask[dst] = prev->MaterialOrMask;
MEMCPY(next->Material[dst], prev->Material[src],
2 * sizeof(struct gl_material));
}
 
 
 
static GLboolean is_fan_like[GL_POLYGON+1] = {
GL_FALSE,
GL_FALSE,
GL_TRUE, /* line loop */
GL_FALSE,
GL_FALSE,
GL_FALSE,
GL_TRUE, /* tri fan */
GL_FALSE,
GL_FALSE,
GL_TRUE /* polygon */
};
 
 
/* Copy the untransformed data from the shared vertices of a primitive
* that wraps over two immediate structs. This is done prior to
* set_immediate so that prev and next may point to the same
* structure. In general it's difficult to avoid this copy on long
* primitives.
*
* Have to be careful with the transitions between display list
* replay, compile and normal execute modes.
*/
void _tnl_copy_immediate_vertices( GLcontext *ctx, struct immediate *next )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct immediate *prev = tnl->ExecCopySource;
struct vertex_arrays *inputs = &tnl->imm_inputs;
GLuint count = tnl->ExecCopyCount;
GLuint *elts = tnl->ExecCopyElts;
GLuint offset = IMM_MAX_COPIED_VERTS - count;
GLuint i;
 
if (!prev) {
ASSERT(tnl->ExecCopyCount == 0);
return;
}
 
next->CopyStart = next->Start - count;
 
if ((prev->CopyOrFlag & VERT_BITS_DATA) == VERT_BIT_ELT &&
ctx->Array.LockCount &&
ctx->Array.Vertex.Enabled)
{
/* Copy Elt values only
*/
for (i = 0 ; i < count ; i++)
{
GLuint src = elts[i+offset];
GLuint dst = next->CopyStart+i;
next->Elt[dst] = prev->Elt[src];
next->Flag[dst] = VERT_BIT_ELT;
elts[i+offset] = dst;
}
/* _mesa_debug(ctx, "ADDING VERT_BIT_ELT!\n"); */
next->CopyOrFlag |= VERT_BIT_ELT;
next->CopyAndFlag &= VERT_BIT_ELT;
}
else {
GLuint copy = tnl->pipeline.inputs & (prev->CopyOrFlag|prev->Evaluated);
GLuint flag;
 
if (is_fan_like[ctx->Driver.CurrentExecPrimitive]) {
flag = ((prev->CopyOrFlag|prev->Evaluated) & VERT_BITS_FIXUP);
next->CopyOrFlag |= flag;
}
else {
/* Don't let an early 'glColor', etc. poison the elt path.
*/
flag = ((prev->OrFlag|prev->Evaluated) & VERT_BITS_FIXUP);
}
 
next->TexSize |= tnl->ExecCopyTexSize;
next->CopyAndFlag &= flag;
 
/* _tnl_print_vert_flags("copy vertex components", copy); */
/* _tnl_print_vert_flags("prev copyorflag", prev->CopyOrFlag); */
/* _tnl_print_vert_flags("flag", flag); */
 
/* Copy whole vertices
*/
for (i = 0 ; i < count ; i++)
{
GLuint src = elts[i+offset];
GLuint isrc = src - prev->CopyStart;
GLuint dst = next->CopyStart+i;
 
/* Values subject to eval must be copied out of the 'inputs'
* struct. (Copied rows should not be evaluated twice).
*
* Note these pointers are null when inactive.
*/
COPY_4FV( next->Attrib[VERT_ATTRIB_POS][dst],
inputs->Obj.data[isrc] );
 
if (copy & VERT_BIT_NORMAL) {
/* _mesa_debug(ctx, "copy vert norm %d to %d (%p): %f %f %f\n", */
/* isrc, dst, */
/* next->Normal[dst], */
/* inputs->Normal.data[isrc][0], */
/* inputs->Normal.data[isrc][1], */
/* inputs->Normal.data[isrc][2]); */
COPY_3FV( next->Attrib[VERT_ATTRIB_NORMAL][dst], inputs->Normal.data[isrc] );
}
 
if (copy & VERT_BIT_COLOR0)
COPY_4FV( next->Attrib[VERT_ATTRIB_COLOR0][dst],
((GLfloat (*)[4])inputs->Color.Ptr)[isrc] );
 
if (copy & VERT_BIT_INDEX)
next->Index[dst] = inputs->Index.data[isrc];
 
if (copy & VERT_BITS_TEX_ANY) {
GLuint i;
for (i = 0 ; i < prev->MaxTextureUnits ; i++) {
if (copy & VERT_BIT_TEX(i))
COPY_4FV( next->Attrib[VERT_ATTRIB_TEX0 + i][dst],
inputs->TexCoord[i].data[isrc] );
}
}
 
/* Remaining values should be the same in the 'input' struct and the
* original immediate.
*/
if (copy & (VERT_BIT_ELT|VERT_BIT_EDGEFLAG|VERT_BIT_COLOR1|VERT_BIT_FOG|
VERT_BIT_MATERIAL)) {
 
if (prev->Flag[src] & VERT_BIT_MATERIAL)
copy_material(next, prev, dst, src);
 
next->Elt[dst] = prev->Elt[src];
next->EdgeFlag[dst] = prev->EdgeFlag[src];
COPY_4FV( next->Attrib[VERT_ATTRIB_COLOR1][dst],
prev->Attrib[VERT_ATTRIB_COLOR1][src] );
COPY_4FV( next->Attrib[VERT_ATTRIB_FOG][dst],
prev->Attrib[VERT_ATTRIB_FOG][src] );
}
 
next->Flag[dst] = flag;
next->CopyOrFlag |= prev->Flag[src] & (VERT_BITS_FIXUP|
VERT_BIT_MATERIAL|
VERT_BIT_POS);
elts[i+offset] = dst;
}
}
 
if (--tnl->ExecCopySource->ref_count == 0)
_tnl_free_immediate( ctx, tnl->ExecCopySource );
tnl->ExecCopySource = next; next->ref_count++;
}
 
 
 
/* Revive a compiled immediate struct - propogate new 'Current'
* values. Often this is redundant because the current values were
* known and fixed up at compile time (or in the first execution of
* the cassette).
*/
void _tnl_fixup_compiled_cassette( GLcontext *ctx, struct immediate *IM )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
GLuint fixup;
GLuint start = IM->Start;
 
/* _mesa_debug(ctx, "%s\n", __FUNCTION__); */
 
IM->Evaluated = 0;
IM->CopyOrFlag = IM->OrFlag;
IM->CopyAndFlag = IM->AndFlag;
IM->CopyTexSize = IM->TexSize | tnl->ExecCopyTexSize;
 
_tnl_copy_immediate_vertices( ctx, IM );
 
if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) {
ASSERT(IM->CopyStart == IM->Start);
}
 
/* Naked array elements can be copied into the first cassette in a
* display list. Need to translate them away:
*/
if (IM->CopyOrFlag & VERT_BIT_ELT) {
GLuint copy = tnl->pipeline.inputs & ~ctx->Array._Enabled;
GLuint i;
 
ASSERT(IM->CopyStart < IM->Start);
 
_tnl_translate_array_elts( ctx, IM, IM->CopyStart, IM->Start );
 
for (i = IM->CopyStart ; i < IM->Start ; i++)
copy_from_current( ctx, IM, i, copy );
 
_tnl_copy_to_current( ctx, IM, ctx->Array._Enabled, IM->Start );
}
 
fixup = tnl->pipeline.inputs & ~IM->Flag[start] & VERT_BITS_FIXUP;
 
/* _tnl_print_vert_flags("fixup compiled", fixup); */
 
if (fixup) {
 
/* XXX try to replace this code with a loop over the 16 vertex
* attributes.
*/
 
if (fixup & VERT_BIT_NORMAL) {
fixup_first_4f(IM->Attrib[VERT_ATTRIB_NORMAL], IM->Flag,
VERT_BIT_NORMAL, start,
ctx->Current.Attrib[VERT_ATTRIB_NORMAL] );
}
 
if (fixup & VERT_BIT_COLOR0) {
if (IM->CopyOrFlag & VERT_BIT_COLOR0)
fixup_first_4f(IM->Attrib[VERT_ATTRIB_COLOR0], IM->Flag,
VERT_BIT_COLOR0, start,
ctx->Current.Attrib[VERT_ATTRIB_COLOR0] );
else
fixup &= ~VERT_BIT_COLOR0;
}
 
if (fixup & VERT_BIT_COLOR1)
fixup_first_4f(IM->Attrib[VERT_ATTRIB_COLOR1], IM->Flag,
VERT_BIT_COLOR1, start,
ctx->Current.Attrib[VERT_ATTRIB_COLOR1] );
 
if (fixup & VERT_BIT_FOG)
fixup_first_4f( IM->Attrib[VERT_ATTRIB_FOG], IM->Flag,
VERT_BIT_FOG, start,
ctx->Current.Attrib[VERT_ATTRIB_FOG] );
 
if (fixup & VERT_BITS_TEX_ANY) {
GLuint i;
for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) {
if (fixup & VERT_BIT_TEX(i))
fixup_first_4f( IM->Attrib[VERT_ATTRIB_TEX0 + i], IM->Flag,
VERT_BIT_TEX(i), start,
ctx->Current.Attrib[VERT_ATTRIB_TEX0 + i] );
}
}
 
if (fixup & VERT_BIT_EDGEFLAG)
fixup_first_1ub(IM->EdgeFlag, IM->Flag, VERT_BIT_EDGEFLAG, start,
ctx->Current.EdgeFlag );
 
if (fixup & VERT_BIT_INDEX)
fixup_first_1ui(IM->Index, IM->Flag, VERT_BIT_INDEX, start,
ctx->Current.Index );
 
IM->CopyOrFlag |= fixup;
}
 
/* Materials:
*/
if (IM->MaterialOrMask & ~IM->MaterialAndMask) {
GLuint vulnerable = IM->MaterialOrMask;
GLuint i = IM->Start;
 
do {
while (!(IM->Flag[i] & VERT_BIT_MATERIAL))
i++;
 
vulnerable &= ~IM->MaterialMask[i];
_mesa_copy_material_pairs( IM->Material[i],
ctx->Light.Material,
vulnerable );
 
 
++i;
} while (vulnerable);
}
}
 
 
 
 
 
 
static void copy_none( TNLcontext *tnl, GLuint start, GLuint count, GLuint ovf)
{
(void) (start && ovf && tnl && count);
}
 
static void copy_last( TNLcontext *tnl, GLuint start, GLuint count, GLuint ovf)
{
(void) start; (void) ovf;
tnl->ExecCopyCount = 1;
tnl->ExecCopyElts[2] = count-1;
}
 
static void copy_first_and_last( TNLcontext *tnl, GLuint start, GLuint count,
GLuint ovf)
{
(void) ovf;
tnl->ExecCopyCount = 2;
tnl->ExecCopyElts[1] = start;
tnl->ExecCopyElts[2] = count-1;
}
 
static void copy_last_two( TNLcontext *tnl, GLuint start, GLuint count,
GLuint ovf )
{
(void) start;
tnl->ExecCopyCount = 2+ovf;
tnl->ExecCopyElts[0] = count-3;
tnl->ExecCopyElts[1] = count-2;
tnl->ExecCopyElts[2] = count-1;
}
 
static void copy_overflow( TNLcontext *tnl, GLuint start, GLuint count,
GLuint ovf )
{
(void) start;
tnl->ExecCopyCount = ovf;
tnl->ExecCopyElts[0] = count-3;
tnl->ExecCopyElts[1] = count-2;
tnl->ExecCopyElts[2] = count-1;
}
 
 
typedef void (*copy_func)( TNLcontext *tnl, GLuint start, GLuint count,
GLuint ovf );
 
static copy_func copy_tab[GL_POLYGON+2] =
{
copy_none,
copy_overflow,
copy_first_and_last,
copy_last,
copy_overflow,
copy_last_two,
copy_first_and_last,
copy_overflow,
copy_last_two,
copy_first_and_last,
copy_none
};
 
 
 
 
 
/* Figure out what vertices need to be copied next time.
*/
void
_tnl_get_exec_copy_verts( GLcontext *ctx, struct immediate *IM )
{
 
TNLcontext *tnl = TNL_CONTEXT(ctx);
GLuint last = IM->LastPrimitive;
GLuint prim = ctx->Driver.CurrentExecPrimitive;
GLuint pincr = increment[prim];
GLuint pintro = intro[prim];
GLuint ovf = 0;
 
/* _mesa_debug(ctx, "_tnl_get_exec_copy_verts %s\n", */
/* _mesa_lookup_enum_by_nr(prim)); */
 
if (tnl->ExecCopySource)
if (--tnl->ExecCopySource->ref_count == 0)
_tnl_free_immediate( ctx, tnl->ExecCopySource );
 
if (prim == GL_POLYGON+1) {
tnl->ExecCopySource = 0;
tnl->ExecCopyCount = 0;
tnl->ExecCopyTexSize = 0;
tnl->ExecParity = 0;
} else {
/* Remember this immediate as the one to copy from.
*/
tnl->ExecCopySource = IM; IM->ref_count++;
tnl->ExecCopyCount = 0;
tnl->ExecCopyTexSize = IM->CopyTexSize;
 
if (IM->LastPrimitive != IM->CopyStart)
tnl->ExecParity = 0;
tnl->ExecParity ^= IM->PrimitiveLength[IM->LastPrimitive] & 1;
 
 
if (pincr != 1 && (IM->Count - last - pintro))
ovf = (IM->Count - last - pintro) % pincr;
 
if (last < IM->Count)
copy_tab[prim]( tnl, last, IM->Count, ovf );
}
}
 
 
/* Recalculate ExecCopyElts, ExecParity, etc.
*/
void
_tnl_get_purged_copy_verts( GLcontext *ctx, struct immediate *IM )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
 
if (ctx->Driver.CurrentExecPrimitive != GL_POLYGON+1) {
GLuint last = IM->LastPrimitive;
GLenum prim = IM->Primitive[last];
GLuint pincr = increment[prim];
GLuint pintro = intro[prim];
GLuint ovf = 0, i;
 
tnl->ExecCopyCount = 0;
if (IM->LastPrimitive != IM->CopyStart)
tnl->ExecParity = 0;
tnl->ExecParity ^= IM->PrimitiveLength[IM->LastPrimitive] & 1;
 
if (pincr != 1 && (IM->Count - last - pintro))
ovf = (IM->Count - last - pintro) % pincr;
 
if (last < IM->Count)
copy_tab[prim]( tnl, last, IM->Count, ovf );
 
for (i = 0 ; i < tnl->ExecCopyCount ; i++)
tnl->ExecCopyElts[i] = IM->Elt[tnl->ExecCopyElts[i]];
}
}
 
 
void _tnl_upgrade_current_data( GLcontext *ctx,
GLuint required,
GLuint flags )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
struct immediate *IM = (struct immediate *)VB->import_source;
 
ASSERT(IM);
 
/* _tnl_print_vert_flags("_tnl_upgrade_client_data", required); */
 
if ((required & VERT_BIT_COLOR0) && (VB->ColorPtr[0]->Flags & CA_CLIENT_DATA)) {
struct gl_client_array *tmp = &tnl->imm_inputs.Color;
GLuint start = IM->CopyStart;
 
tmp->Ptr = IM->Attrib[VERT_ATTRIB_COLOR0] + start;
tmp->StrideB = 4 * sizeof(GLfloat);
tmp->Flags = 0;
 
COPY_4FV( IM->Attrib[VERT_ATTRIB_COLOR0][start],
ctx->Current.Attrib[VERT_ATTRIB_COLOR0]);
 
/*
ASSERT(IM->Flag[IM->LastData+1] & VERT_BIT_END_VB);
*/
 
fixup_first_4f( IM->Attrib[VERT_ATTRIB_COLOR0], IM->Flag,
VERT_BIT_END_VB,
start, IM->Attrib[VERT_ATTRIB_COLOR0][start] );
 
VB->importable_data &= ~VERT_BIT_COLOR0;
}
}
/shark/trunk/ports/mesa/src/tnl/t_imm_alloc.h
0,0 → 1,40
/* $Id: t_imm_alloc.h,v 1.1 2003-02-28 11:48:06 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
 
#ifndef _T_IMM_ALLOC_H
#define _T_IMM_ALLOC_H
 
#include "mtypes.h"
#include "t_context.h"
 
 
extern struct immediate *_tnl_alloc_immediate( GLcontext *ctx );
 
extern void _tnl_free_immediate( GLcontext *ctx, struct immediate *im );
 
 
#endif
/shark/trunk/ports/mesa/src/tnl/t_imm_fixup.h
0,0 → 1,64
/* $Id: t_imm_fixup.h,v 1.1 2003-02-28 11:48:07 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
 
#ifndef _T_IMM_FIXUP_H
#define _T_IMM_FIXUP_H
 
#include "mtypes.h"
#include "t_context.h"
 
extern void _tnl_fixup_1ub( GLubyte *data, GLuint flag[],
GLuint start, GLuint match );
 
extern void _tnl_fixup_1f( GLfloat *data, GLuint flag[],
GLuint start, GLuint match );
 
extern void _tnl_fixup_1ui( GLuint *data, GLuint flag[],
GLuint start, GLuint match );
 
extern void _tnl_fixup_3f( float data[][3], GLuint flag[],
GLuint start, GLuint match );
 
extern void _tnl_fixup_4f( GLfloat data[][4], GLuint flag[],
GLuint start, GLuint match );
 
extern void _tnl_fixup_input( GLcontext *ctx, struct immediate *IM );
 
extern void _tnl_fixup_compiled_cassette( GLcontext *ctx,
struct immediate *IM );
 
extern void _tnl_copy_immediate_vertices( GLcontext *ctx,
struct immediate *IM );
 
extern void _tnl_get_purged_copy_verts( GLcontext *ctx, struct immediate *IM );
 
extern void _tnl_get_exec_copy_verts( GLcontext *ctx, struct immediate *IM );
 
extern void _tnl_upgrade_current_data( GLcontext *ctx, GLuint required,
GLuint flags );
 
#endif
/shark/trunk/ports/mesa/src/tnl/t_vb_fog.c
0,0 → 1,254
/* $Id: t_vb_fog.c,v 1.1 2003-02-28 11:48:07 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 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.
*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
 
#include "glheader.h"
#include "colormac.h"
#include "context.h"
#include "macros.h"
#include "imports.h"
#include "mmath.h"
#include "mtypes.h"
 
#include "math/m_xform.h"
 
#include "t_context.h"
#include "t_pipeline.h"
 
 
struct fog_stage_data {
GLvector4f fogcoord; /* has actual storage allocated */
GLvector4f input; /* points into VB->EyePtr Z values */
};
 
#define FOG_STAGE_DATA(stage) ((struct fog_stage_data *)stage->privatePtr)
 
#define FOG_EXP_TABLE_SIZE 256
#define FOG_MAX (10.0)
#define EXP_FOG_MAX .0006595
#define FOG_INCR (FOG_MAX/FOG_EXP_TABLE_SIZE)
static GLfloat exp_table[FOG_EXP_TABLE_SIZE];
static GLfloat inited = 0;
 
#if 1
#define NEG_EXP( result, narg ) \
do { \
GLfloat f = (GLfloat) (narg * (1.0/FOG_INCR)); \
GLint k = (GLint) f; \
if (k > FOG_EXP_TABLE_SIZE-2) \
result = (GLfloat) EXP_FOG_MAX; \
else \
result = exp_table[k] + (f-k)*(exp_table[k+1]-exp_table[k]); \
} while (0)
#else
#define NEG_EXP( result, narg ) \
do { \
result = exp(-narg); \
} while (0)
#endif
 
 
static void init_static_data( void )
{
GLfloat f = 0.0F;
GLint i = 0;
for ( ; i < FOG_EXP_TABLE_SIZE ; i++, f += FOG_INCR) {
exp_table[i] = (GLfloat) exp(-f);
}
inited = 1;
}
 
 
static void make_win_fog_coords( GLcontext *ctx, GLvector4f *out,
const GLvector4f *in )
{
GLfloat end = ctx->Fog.End;
GLfloat *v = in->start;
GLuint stride = in->stride;
GLuint n = in->count;
GLfloat (*data)[4] = out->data;
GLfloat d;
GLuint i;
 
out->count = in->count;
 
switch (ctx->Fog.Mode) {
case GL_LINEAR:
if (ctx->Fog.Start == ctx->Fog.End)
d = 1.0F;
else
d = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
for ( i = 0 ; i < n ; i++, STRIDE_F(v, stride)) {
GLfloat f = (end - ABSF(*v)) * d;
data[i][0] = CLAMP(f, 0.0F, 1.0F);
}
break;
case GL_EXP:
d = ctx->Fog.Density;
for ( i = 0 ; i < n ; i++, STRIDE_F(v,stride))
NEG_EXP( data[i][0], d * ABSF(*v) );
break;
case GL_EXP2:
d = ctx->Fog.Density*ctx->Fog.Density;
for ( i = 0 ; i < n ; i++, STRIDE_F(v, stride)) {
GLfloat z = *v;
NEG_EXP( data[i][0], d * z * z );
}
break;
default:
_mesa_problem(ctx, "Bad fog mode in make_fog_coord");
return;
}
}
 
 
static GLboolean run_fog_stage( GLcontext *ctx,
struct gl_pipeline_stage *stage )
{
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
struct fog_stage_data *store = FOG_STAGE_DATA(stage);
GLvector4f *input;
 
if (stage->changed_inputs == 0)
return GL_TRUE;
 
if (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH_EXT) {
/* fog computed from Z depth */
/* source = VB->ObjPtr or VB->EyePtr coords */
/* dest = VB->FogCoordPtr = fog stage private storage */
VB->FogCoordPtr = &store->fogcoord;
 
if (!ctx->_NeedEyeCoords) {
const GLfloat *m = ctx->ModelviewMatrixStack.Top->m;
GLfloat plane[4];
 
/* Use this to store calculated eye z values:
*/
input = &store->fogcoord;
 
plane[0] = m[2];
plane[1] = m[6];
plane[2] = m[10];
plane[3] = m[14];
 
/* Full eye coords weren't required, just calculate the
* eye Z values.
*/
_mesa_dotprod_tab[VB->ObjPtr->size]( (GLfloat *) input->data,
4 * sizeof(GLfloat),
VB->ObjPtr, plane );
 
input->count = VB->ObjPtr->count;
}
else {
input = &store->input;
 
if (VB->EyePtr->size < 2)
_mesa_vector4f_clean_elem( VB->EyePtr, VB->Count, 2 );
 
input->data = (GLfloat (*)[4]) &(VB->EyePtr->data[0][2]);
input->start = VB->EyePtr->start+2;
input->stride = VB->EyePtr->stride;
input->count = VB->EyePtr->count;
}
}
else {
/* use glFogCoord() coordinates */
/* source = VB->FogCoordPtr */
input = VB->FogCoordPtr;
/* dest = fog stage private storage */
VB->FogCoordPtr = &store->fogcoord;
}
 
make_win_fog_coords( ctx, VB->FogCoordPtr, input );
return GL_TRUE;
}
 
 
static void check_fog_stage( GLcontext *ctx, struct gl_pipeline_stage *stage )
{
stage->active = ctx->Fog.Enabled && !ctx->VertexProgram.Enabled;
 
if (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH_EXT)
stage->inputs = VERT_BIT_EYE;
else
stage->inputs = VERT_BIT_FOG;
}
 
 
/* Called the first time stage->run() is invoked.
*/
static GLboolean alloc_fog_data( GLcontext *ctx,
struct gl_pipeline_stage *stage )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct fog_stage_data *store;
stage->privatePtr = MALLOC(sizeof(*store));
store = FOG_STAGE_DATA(stage);
if (!store)
return GL_FALSE;
 
_mesa_vector4f_alloc( &store->fogcoord, 0, tnl->vb.Size, 32 );
_mesa_vector4f_init( &store->input, 0, 0 );
 
if (!inited)
init_static_data();
 
/* Now run the stage.
*/
stage->run = run_fog_stage;
return stage->run( ctx, stage );
}
 
 
static void free_fog_data( struct gl_pipeline_stage *stage )
{
struct fog_stage_data *store = FOG_STAGE_DATA(stage);
if (store) {
_mesa_vector4f_free( &store->fogcoord );
FREE( store );
stage->privatePtr = NULL;
}
}
 
 
const struct gl_pipeline_stage _tnl_fog_coordinate_stage =
{
"build fog coordinates", /* name */
_NEW_FOG, /* check_state */
_NEW_FOG, /* run_state */
GL_FALSE, /* active? */
0, /* inputs */
VERT_BIT_FOG, /* outputs */
0, /* changed_inputs */
NULL, /* private_data */
free_fog_data, /* dtr */
check_fog_stage, /* check */
alloc_fog_data /* run -- initially set to init. */
};
/shark/trunk/ports/mesa/src/tnl/t_vb_cliptmp.h
0,0 → 1,271
/* $Id: t_vb_cliptmp.h,v 1.1 2003-02-28 11:48:07 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
 
#define CLIP_DOTPROD(K, A, B, C, D) X(K)*A + Y(K)*B + Z(K)*C + W(K)*D
 
#define POLY_CLIP( PLANE, A, B, C, D ) \
do { \
if (mask & PLANE) { \
GLuint idxPrev = inlist[0]; \
GLfloat dpPrev = CLIP_DOTPROD(idxPrev, A, B, C, D ); \
GLuint outcount = 0; \
GLuint i; \
\
inlist[n] = inlist[0]; /* prevent rotation of vertices */ \
for (i = 1; i <= n; i++) { \
GLuint idx = inlist[i]; \
GLfloat dp = CLIP_DOTPROD(idx, A, B, C, D ); \
\
clipmask[idxPrev] |= PLANE; \
if (!NEGATIVE(dpPrev)) { \
outlist[outcount++] = idxPrev; \
clipmask[idxPrev] &= ~PLANE; \
} \
\
if (DIFFERENT_SIGNS(dp, dpPrev)) { \
GLuint newvert = VB->LastClipped++; \
VB->ClipMask[newvert] = 0; \
outlist[outcount++] = newvert; \
if (NEGATIVE(dp)) { \
/* Going out of bounds. Avoid division by zero as we \
* know dp != dpPrev from DIFFERENT_SIGNS, above. \
*/ \
GLfloat t = dp / (dp - dpPrev); \
INTERP_4F( t, coord[newvert], coord[idx], coord[idxPrev]); \
interp( ctx, t, newvert, idx, idxPrev, GL_TRUE ); \
} else { \
/* Coming back in. \
*/ \
GLfloat t = dpPrev / (dpPrev - dp); \
INTERP_4F( t, coord[newvert], coord[idxPrev], coord[idx]); \
interp( ctx, t, newvert, idxPrev, idx, GL_FALSE ); \
} \
} \
\
idxPrev = idx; \
dpPrev = dp; \
} \
\
if (outcount < 3) \
return; \
\
{ \
GLuint *tmp = inlist; \
inlist = outlist; \
outlist = tmp; \
n = outcount; \
} \
} \
} while (0)
 
 
#define LINE_CLIP(PLANE, A, B, C, D ) \
do { \
if (mask & PLANE) { \
GLfloat dpI = CLIP_DOTPROD( ii, A, B, C, D ); \
GLfloat dpJ = CLIP_DOTPROD( jj, A, B, C, D ); \
\
if (DIFFERENT_SIGNS(dpI, dpJ)) { \
GLuint newvert = VB->LastClipped++; \
VB->ClipMask[newvert] = 0; \
if (NEGATIVE(dpJ)) { \
GLfloat t = dpI / (dpI - dpJ); \
VB->ClipMask[jj] |= PLANE; \
INTERP_4F( t, coord[newvert], coord[ii], coord[jj] ); \
interp( ctx, t, newvert, ii, jj, GL_FALSE ); \
jj = newvert; \
} else { \
GLfloat t = dpJ / (dpJ - dpI); \
VB->ClipMask[ii] |= PLANE; \
INTERP_4F( t, coord[newvert], coord[jj], coord[ii] ); \
interp( ctx, t, newvert, jj, ii, GL_FALSE ); \
ii = newvert; \
} \
} \
else if (NEGATIVE(dpI)) \
return; \
} \
} while (0)
 
 
 
/* Clip a line against the viewport and user clip planes.
*/
static INLINE void
TAG(clip_line)( GLcontext *ctx, GLuint i, GLuint j, GLubyte mask )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
interp_func interp = tnl->Driver.Render.Interp;
GLfloat (*coord)[4] = VB->ClipPtr->data;
GLuint ii = i, jj = j, p;
 
VB->LastClipped = VB->FirstClipped;
 
if (mask & 0x3f) {
LINE_CLIP( CLIP_RIGHT_BIT, -1, 0, 0, 1 );
LINE_CLIP( CLIP_LEFT_BIT, 1, 0, 0, 1 );
LINE_CLIP( CLIP_TOP_BIT, 0, -1, 0, 1 );
LINE_CLIP( CLIP_BOTTOM_BIT, 0, 1, 0, 1 );
LINE_CLIP( CLIP_FAR_BIT, 0, 0, -1, 1 );
LINE_CLIP( CLIP_NEAR_BIT, 0, 0, 1, 1 );
}
 
if (mask & CLIP_USER_BIT) {
for (p=0;p<MAX_CLIP_PLANES;p++) {
if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {
const GLfloat a = ctx->Transform._ClipUserPlane[p][0];
const GLfloat b = ctx->Transform._ClipUserPlane[p][1];
const GLfloat c = ctx->Transform._ClipUserPlane[p][2];
const GLfloat d = ctx->Transform._ClipUserPlane[p][3];
LINE_CLIP( CLIP_USER_BIT, a, b, c, d );
}
}
}
 
if ((ctx->_TriangleCaps & DD_FLATSHADE) && j != jj)
tnl->Driver.Render.CopyPV( ctx, jj, j );
 
tnl->Driver.Render.ClippedLine( ctx, ii, jj );
}
 
 
/* Clip a triangle against the viewport and user clip planes.
*/
static INLINE void
TAG(clip_tri)( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLubyte mask )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
interp_func interp = tnl->Driver.Render.Interp;
GLfloat (*coord)[4] = VB->ClipPtr->data;
GLuint pv = v2;
GLuint vlist[2][MAX_CLIPPED_VERTICES];
GLuint *inlist = vlist[0], *outlist = vlist[1];
GLuint p;
GLubyte *clipmask = VB->ClipMask;
GLuint n = 3;
 
ASSIGN_3V(inlist, v2, v0, v1 ); /* pv rotated to slot zero */
 
VB->LastClipped = VB->FirstClipped;
 
if (mask & 0x3f) {
POLY_CLIP( CLIP_RIGHT_BIT, -1, 0, 0, 1 );
POLY_CLIP( CLIP_LEFT_BIT, 1, 0, 0, 1 );
POLY_CLIP( CLIP_TOP_BIT, 0, -1, 0, 1 );
POLY_CLIP( CLIP_BOTTOM_BIT, 0, 1, 0, 1 );
POLY_CLIP( CLIP_FAR_BIT, 0, 0, -1, 1 );
POLY_CLIP( CLIP_NEAR_BIT, 0, 0, 1, 1 );
}
 
if (mask & CLIP_USER_BIT) {
for (p=0;p<MAX_CLIP_PLANES;p++) {
if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {
const GLfloat a = ctx->Transform._ClipUserPlane[p][0];
const GLfloat b = ctx->Transform._ClipUserPlane[p][1];
const GLfloat c = ctx->Transform._ClipUserPlane[p][2];
const GLfloat d = ctx->Transform._ClipUserPlane[p][3];
POLY_CLIP( CLIP_USER_BIT, a, b, c, d );
}
}
}
 
if (ctx->_TriangleCaps & DD_FLATSHADE) {
if (pv != inlist[0]) {
ASSERT( inlist[0] >= VB->FirstClipped );
tnl->Driver.Render.CopyPV( ctx, inlist[0], pv );
}
}
 
tnl->Driver.Render.ClippedPolygon( ctx, inlist, n );
}
 
 
/* Clip a quad against the viewport and user clip planes.
*/
static INLINE void
TAG(clip_quad)( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3,
GLubyte mask )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
interp_func interp = tnl->Driver.Render.Interp;
GLfloat (*coord)[4] = VB->ClipPtr->data;
GLuint pv = v3;
GLuint vlist[2][MAX_CLIPPED_VERTICES];
GLuint *inlist = vlist[0], *outlist = vlist[1];
GLuint p;
GLubyte *clipmask = VB->ClipMask;
GLuint n = 4;
 
ASSIGN_4V(inlist, v3, v0, v1, v2 ); /* pv rotated to slot zero */
 
VB->LastClipped = VB->FirstClipped;
 
if (mask & 0x3f) {
POLY_CLIP( CLIP_RIGHT_BIT, -1, 0, 0, 1 );
POLY_CLIP( CLIP_LEFT_BIT, 1, 0, 0, 1 );
POLY_CLIP( CLIP_TOP_BIT, 0, -1, 0, 1 );
POLY_CLIP( CLIP_BOTTOM_BIT, 0, 1, 0, 1 );
POLY_CLIP( CLIP_FAR_BIT, 0, 0, -1, 1 );
POLY_CLIP( CLIP_NEAR_BIT, 0, 0, 1, 1 );
}
 
if (mask & CLIP_USER_BIT) {
for (p=0;p<MAX_CLIP_PLANES;p++) {
if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {
const GLfloat a = ctx->Transform._ClipUserPlane[p][0];
const GLfloat b = ctx->Transform._ClipUserPlane[p][1];
const GLfloat c = ctx->Transform._ClipUserPlane[p][2];
const GLfloat d = ctx->Transform._ClipUserPlane[p][3];
POLY_CLIP( CLIP_USER_BIT, a, b, c, d );
}
}
}
 
if (ctx->_TriangleCaps & DD_FLATSHADE) {
if (pv != inlist[0]) {
ASSERT( inlist[0] >= VB->FirstClipped );
tnl->Driver.Render.CopyPV( ctx, inlist[0], pv );
}
}
 
tnl->Driver.Render.ClippedPolygon( ctx, inlist, n );
}
 
#undef W
#undef Z
#undef Y
#undef X
#undef SIZE
#undef TAG
#undef POLY_CLIP
#undef LINE_CLIP
/shark/trunk/ports/mesa/src/tnl/t_vb_render.c
0,0 → 1,425
/* $Id: t_vb_render.c,v 1.1 2003-02-28 11:48:07 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.0.1
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
 
/*
* Render whole vertex buffers, including projection of vertices from
* clip space and clipping of primitives.
*
* This file makes calls to project vertices and to the point, line
* and triangle rasterizers via the function pointers:
*
* context->Driver.Render.*
*
*/
 
 
#include "glheader.h"
#include "context.h"
#include "enums.h"
#include "macros.h"
#include "imports.h"
#include "mtypes.h"
#include "mmath.h"
 
#include "math/m_matrix.h"
#include "math/m_xform.h"
 
#include "t_pipeline.h"
 
 
 
/**********************************************************************/
/* Clip single primitives */
/**********************************************************************/
 
 
#if defined(USE_IEEE)
#define NEGATIVE(x) (GET_FLOAT_BITS(x) & (1<<31))
#define DIFFERENT_SIGNS(x,y) ((GET_FLOAT_BITS(x) ^ GET_FLOAT_BITS(y)) & (1<<31))
#else
#define NEGATIVE(x) (x < 0)
#define DIFFERENT_SIGNS(x,y) (x * y <= 0 && x - y != 0)
/* Could just use (x*y<0) except for the flatshading requirements.
* Maybe there's a better way?
*/
#endif
 
 
#define W(i) coord[i][3]
#define Z(i) coord[i][2]
#define Y(i) coord[i][1]
#define X(i) coord[i][0]
#define SIZE 4
#define TAG(x) x##_4
#include "t_vb_cliptmp.h"
 
 
 
/**********************************************************************/
/* Clip and render whole begin/end objects */
/**********************************************************************/
 
#define NEED_EDGEFLAG_SETUP (ctx->_TriangleCaps & DD_TRI_UNFILLED)
#define EDGEFLAG_GET(idx) VB->EdgeFlag[idx]
#define EDGEFLAG_SET(idx, val) VB->EdgeFlag[idx] = val
 
 
/* Vertices, with the possibility of clipping.
*/
#define RENDER_POINTS( start, count ) \
tnl->Driver.Render.Points( ctx, start, count )
 
#define RENDER_LINE( v1, v2 ) \
do { \
GLubyte c1 = mask[v1], c2 = mask[v2]; \
GLubyte ormask = c1|c2; \
if (!ormask) \
LineFunc( ctx, v1, v2 ); \
else if (!(c1 & c2 & 0x3f)) \
clip_line_4( ctx, v1, v2, ormask ); \
} while (0)
 
#define RENDER_TRI( v1, v2, v3 ) \
do { \
GLubyte c1 = mask[v1], c2 = mask[v2], c3 = mask[v3]; \
GLubyte ormask = c1|c2|c3; \
if (!ormask) \
TriangleFunc( ctx, v1, v2, v3 ); \
else if (!(c1 & c2 & c3 & 0x3f)) \
clip_tri_4( ctx, v1, v2, v3, ormask ); \
} while (0)
 
#define RENDER_QUAD( v1, v2, v3, v4 ) \
do { \
GLubyte c1 = mask[v1], c2 = mask[v2]; \
GLubyte c3 = mask[v3], c4 = mask[v4]; \
GLubyte ormask = c1|c2|c3|c4; \
if (!ormask) \
QuadFunc( ctx, v1, v2, v3, v4 ); \
else if (!(c1 & c2 & c3 & c4 & 0x3f)) \
clip_quad_4( ctx, v1, v2, v3, v4, ormask ); \
} while (0)
 
 
#define LOCAL_VARS \
TNLcontext *tnl = TNL_CONTEXT(ctx); \
struct vertex_buffer *VB = &tnl->vb; \
const GLuint * const elt = VB->Elts; \
const GLubyte *mask = VB->ClipMask; \
const GLuint sz = VB->ClipPtr->size; \
const line_func LineFunc = tnl->Driver.Render.Line; \
const triangle_func TriangleFunc = tnl->Driver.Render.Triangle; \
const quad_func QuadFunc = tnl->Driver.Render.Quad; \
const GLboolean stipple = ctx->Line.StippleFlag; \
(void) (LineFunc && TriangleFunc && QuadFunc); \
(void) elt; (void) mask; (void) sz; (void) stipple;
 
#define TAG(x) clip_##x##_verts
#define INIT(x) tnl->Driver.Render.PrimitiveNotify( ctx, x )
#define RESET_STIPPLE if (stipple) tnl->Driver.Render.ResetLineStipple( ctx )
#define RESET_OCCLUSION ctx->OcclusionResult = GL_TRUE
#define PRESERVE_VB_DEFS
#include "t_vb_rendertmp.h"
 
 
 
/* Elts, with the possibility of clipping.
*/
#undef ELT
#undef TAG
#define ELT(x) elt[x]
#define TAG(x) clip_##x##_elts
#include "t_vb_rendertmp.h"
 
/* TODO: do this for all primitives, verts and elts:
*/
static void clip_elt_triangles( GLcontext *ctx,
GLuint start,
GLuint count,
GLuint flags )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
render_func render_tris = tnl->Driver.Render.PrimTabElts[GL_TRIANGLES];
struct vertex_buffer *VB = &tnl->vb;
const GLuint * const elt = VB->Elts;
GLubyte *mask = VB->ClipMask;
GLuint last = count-2;
GLuint j;
(void) flags;
 
tnl->Driver.Render.PrimitiveNotify( ctx, GL_TRIANGLES );
 
for (j=start; j < last; j+=3 ) {
GLubyte c1 = mask[elt[j]];
GLubyte c2 = mask[elt[j+1]];
GLubyte c3 = mask[elt[j+2]];
GLubyte ormask = c1|c2|c3;
if (ormask) {
if (start < j)
render_tris( ctx, start, j, 0 );
if (!(c1&c2&c3&0x3f))
clip_tri_4( ctx, elt[j], elt[j+1], elt[j+2], ormask );
start = j+3;
}
}
 
if (start < j)
render_tris( ctx, start, j, 0 );
}
 
/**********************************************************************/
/* Render whole begin/end objects */
/**********************************************************************/
 
#define NEED_EDGEFLAG_SETUP (ctx->_TriangleCaps & DD_TRI_UNFILLED)
#define EDGEFLAG_GET(idx) VB->EdgeFlag[idx]
#define EDGEFLAG_SET(idx, val) VB->EdgeFlag[idx] = val
 
 
/* Vertices, no clipping.
*/
#define RENDER_POINTS( start, count ) \
tnl->Driver.Render.Points( ctx, start, count )
 
#define RENDER_LINE( v1, v2 ) \
LineFunc( ctx, v1, v2 )
 
#define RENDER_TRI( v1, v2, v3 ) \
TriangleFunc( ctx, v1, v2, v3 )
 
#define RENDER_QUAD( v1, v2, v3, v4 ) \
QuadFunc( ctx, v1, v2, v3, v4 )
 
#define TAG(x) _tnl_##x##_verts
 
#define LOCAL_VARS \
TNLcontext *tnl = TNL_CONTEXT(ctx); \
struct vertex_buffer *VB = &tnl->vb; \
const GLuint * const elt = VB->Elts; \
const line_func LineFunc = tnl->Driver.Render.Line; \
const triangle_func TriangleFunc = tnl->Driver.Render.Triangle; \
const quad_func QuadFunc = tnl->Driver.Render.Quad; \
const GLboolean stipple = ctx->Line.StippleFlag; \
(void) (LineFunc && TriangleFunc && QuadFunc); \
(void) elt; (void) stipple
 
#define RESET_STIPPLE if (stipple) tnl->Driver.Render.ResetLineStipple( ctx )
#define RESET_OCCLUSION ctx->OcclusionResult = GL_TRUE
#define INIT(x) tnl->Driver.Render.PrimitiveNotify( ctx, x )
#define RENDER_TAB_QUALIFIER
#define PRESERVE_VB_DEFS
#include "t_vb_rendertmp.h"
 
 
/* Elts, no clipping.
*/
#undef ELT
#define TAG(x) _tnl_##x##_elts
#define ELT(x) elt[x]
#include "t_vb_rendertmp.h"
 
 
/**********************************************************************/
/* Helper functions for drivers */
/**********************************************************************/
 
void _tnl_RenderClippedPolygon( GLcontext *ctx, const GLuint *elts, GLuint n )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
GLuint *tmp = VB->Elts;
 
VB->Elts = (GLuint *)elts;
tnl->Driver.Render.PrimTabElts[GL_POLYGON]( ctx, 0, n, PRIM_BEGIN|PRIM_END );
VB->Elts = tmp;
}
 
void _tnl_RenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
tnl->Driver.Render.Line( ctx, ii, jj );
}
 
 
 
/**********************************************************************/
/* Clip and render whole vertex buffers */
/**********************************************************************/
 
 
static GLboolean run_render( GLcontext *ctx,
struct gl_pipeline_stage *stage )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
GLuint new_inputs = stage->changed_inputs;
render_func *tab;
GLint pass = 0;
 
/* Allow the drivers to lock before projected verts are built so
* that window coordinates are guarenteed not to change before
* rendering.
*/
ASSERT(tnl->Driver.Render.Start);
 
tnl->Driver.Render.Start( ctx );
 
ASSERT(tnl->Driver.Render.BuildVertices);
ASSERT(tnl->Driver.Render.PrimitiveNotify);
ASSERT(tnl->Driver.Render.Points);
ASSERT(tnl->Driver.Render.Line);
ASSERT(tnl->Driver.Render.Triangle);
ASSERT(tnl->Driver.Render.Quad);
ASSERT(tnl->Driver.Render.ResetLineStipple);
ASSERT(tnl->Driver.Render.Interp);
ASSERT(tnl->Driver.Render.CopyPV);
ASSERT(tnl->Driver.Render.ClippedLine);
ASSERT(tnl->Driver.Render.ClippedPolygon);
ASSERT(tnl->Driver.Render.Finish);
 
tnl->Driver.Render.BuildVertices( ctx, 0, VB->Count, new_inputs );
 
if (VB->ClipOrMask) {
tab = VB->Elts ? clip_render_tab_elts : clip_render_tab_verts;
clip_render_tab_elts[GL_TRIANGLES] = clip_elt_triangles;
}
else {
tab = (VB->Elts ?
tnl->Driver.Render.PrimTabElts :
tnl->Driver.Render.PrimTabVerts);
}
 
do
{
GLuint i, length, flags = 0;
for (i = VB->FirstPrimitive ; !(flags & PRIM_LAST) ; i += length)
{
flags = VB->Primitive[i];
length= VB->PrimitiveLength[i];
ASSERT(length || (flags & PRIM_LAST));
ASSERT((flags & PRIM_MODE_MASK) <= GL_POLYGON+1);
 
if (MESA_VERBOSE & VERBOSE_PRIMS)
_mesa_debug(NULL, "MESA prim %s %d..%d\n",
_mesa_lookup_enum_by_nr(flags & PRIM_MODE_MASK),
i, i+length);
 
if (length)
tab[flags & PRIM_MODE_MASK]( ctx, i, i + length, flags );
}
} while (tnl->Driver.Render.Multipass &&
tnl->Driver.Render.Multipass( ctx, ++pass ));
 
 
tnl->Driver.Render.Finish( ctx );
/* _swrast_flush(ctx); */
/* usleep(1000000); */
return GL_FALSE; /* finished the pipe */
}
 
 
/**********************************************************************/
/* Render pipeline stage */
/**********************************************************************/
 
 
 
/* Quite a bit of work involved in finding out the inputs for the
* render stage.
*/
static void check_render( GLcontext *ctx, struct gl_pipeline_stage *stage )
{
GLuint inputs = VERT_BIT_CLIP;
GLuint i;
 
if (ctx->Visual.rgbMode) {
inputs |= VERT_BIT_COLOR0;
 
if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR)
inputs |= VERT_BIT_COLOR1;
 
if (ctx->Texture._EnabledUnits) {
for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) {
if (ctx->Texture.Unit[i]._ReallyEnabled)
inputs |= VERT_BIT_TEX(i);
}
}
}
else {
inputs |= VERT_BIT_INDEX;
}
 
if (ctx->Point._Attenuated)
inputs |= VERT_BIT_POINT_SIZE;
 
/* How do drivers turn this off?
*/
if (ctx->Fog.Enabled)
inputs |= VERT_BIT_FOG;
 
if (ctx->_TriangleCaps & DD_TRI_UNFILLED)
inputs |= VERT_BIT_EDGEFLAG;
 
if (ctx->RenderMode==GL_FEEDBACK)
inputs |= VERT_BITS_TEX_ANY;
 
stage->inputs = inputs;
}
 
 
 
 
static void dtr( struct gl_pipeline_stage *stage )
{
}
 
 
const struct gl_pipeline_stage _tnl_render_stage =
{
"render", /* name */
(_NEW_BUFFERS |
_DD_NEW_SEPARATE_SPECULAR |
_DD_NEW_FLATSHADE |
_NEW_TEXTURE|
_NEW_LIGHT|
_NEW_POINT|
_NEW_FOG|
_DD_NEW_TRI_UNFILLED |
_NEW_RENDERMODE), /* re-check (new inputs, interp function) */
0, /* re-run (always runs) */
GL_TRUE, /* active? */
0, /* inputs (set in check_render) */
0, /* outputs */
0, /* changed_inputs */
NULL, /* private data */
dtr, /* destructor */
check_render, /* check */
run_render /* run */
};
/shark/trunk/ports/mesa/src/tnl/t_array_import.c
0,0 → 1,432
/* $Id: t_array_import.c,v 1.1 2003-02-28 11:48:06 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 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.
*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
#include "glheader.h"
#include "context.h"
#include "macros.h"
#include "imports.h"
#include "mmath.h"
#include "state.h"
#include "mtypes.h"
 
#include "array_cache/acache.h"
#include "math/m_translate.h"
 
#include "t_array_import.h"
#include "t_context.h"
#include "t_imm_debug.h"
 
 
static void _tnl_import_vertex( GLcontext *ctx,
GLboolean writeable,
GLboolean stride )
{
struct gl_client_array *tmp;
GLboolean is_writeable = 0;
struct vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs;
 
tmp = _ac_import_vertex(ctx,
GL_FLOAT,
stride ? 4*sizeof(GLfloat) : 0,
0,
writeable,
&is_writeable);
 
inputs->Obj.data = (GLfloat (*)[4]) tmp->Ptr;
inputs->Obj.start = (GLfloat *) tmp->Ptr;
inputs->Obj.stride = tmp->StrideB;
inputs->Obj.size = tmp->Size;
inputs->Obj.flags &= ~(VEC_BAD_STRIDE|VEC_NOT_WRITEABLE);
if (inputs->Obj.stride != 4*sizeof(GLfloat))
inputs->Obj.flags |= VEC_BAD_STRIDE;
if (!is_writeable)
inputs->Obj.flags |= VEC_NOT_WRITEABLE;
}
 
static void _tnl_import_normal( GLcontext *ctx,
GLboolean writeable,
GLboolean stride )
{
struct gl_client_array *tmp;
GLboolean is_writeable = 0;
struct vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs;
 
tmp = _ac_import_normal(ctx, GL_FLOAT,
stride ? 3*sizeof(GLfloat) : 0, writeable,
&is_writeable);
 
inputs->Normal.data = (GLfloat (*)[4]) tmp->Ptr;
inputs->Normal.start = (GLfloat *) tmp->Ptr;
inputs->Normal.stride = tmp->StrideB;
inputs->Normal.flags &= ~(VEC_BAD_STRIDE|VEC_NOT_WRITEABLE);
if (inputs->Normal.stride != 3*sizeof(GLfloat))
inputs->Normal.flags |= VEC_BAD_STRIDE;
if (!is_writeable)
inputs->Normal.flags |= VEC_NOT_WRITEABLE;
}
 
 
static void _tnl_import_color( GLcontext *ctx,
GLenum type,
GLboolean writeable,
GLboolean stride )
{
struct gl_client_array *tmp;
GLboolean is_writeable = 0;
struct vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs;
 
tmp = _ac_import_color(ctx,
type,
stride ? 4*sizeof(GLfloat) : 0,
4,
writeable,
&is_writeable);
 
inputs->Color = *tmp;
}
 
 
static void _tnl_import_secondarycolor( GLcontext *ctx,
GLenum type,
GLboolean writeable,
GLboolean stride )
{
struct gl_client_array *tmp;
GLboolean is_writeable = 0;
struct vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs;
 
tmp = _ac_import_secondarycolor(ctx,
type,
stride ? 4*sizeof(GLfloat) : 0,
4,
writeable,
&is_writeable);
 
inputs->SecondaryColor = *tmp;
}
 
static void _tnl_import_fogcoord( GLcontext *ctx,
GLboolean writeable,
GLboolean stride )
{
struct vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs;
struct gl_client_array *tmp;
GLboolean is_writeable = 0;
 
tmp = _ac_import_fogcoord(ctx, GL_FLOAT,
stride ? sizeof(GLfloat) : 0, writeable,
&is_writeable);
 
inputs->FogCoord.data = (GLfloat (*)[4]) tmp->Ptr;
inputs->FogCoord.start = (GLfloat *) tmp->Ptr;
inputs->FogCoord.stride = tmp->StrideB;
inputs->FogCoord.flags &= ~(VEC_BAD_STRIDE|VEC_NOT_WRITEABLE);
if (inputs->FogCoord.stride != sizeof(GLfloat))
inputs->FogCoord.flags |= VEC_BAD_STRIDE;
if (!is_writeable)
inputs->FogCoord.flags |= VEC_NOT_WRITEABLE;
}
 
static void _tnl_import_index( GLcontext *ctx,
GLboolean writeable,
GLboolean stride )
{
struct vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs;
struct gl_client_array *tmp;
GLboolean is_writeable = 0;
 
tmp = _ac_import_index(ctx, GL_UNSIGNED_INT,
stride ? sizeof(GLuint) : 0, writeable,
&is_writeable);
 
inputs->Index.data = (GLuint *) tmp->Ptr;
inputs->Index.start = (GLuint *) tmp->Ptr;
inputs->Index.stride = tmp->StrideB;
inputs->Index.flags &= ~(VEC_BAD_STRIDE|VEC_NOT_WRITEABLE);
if (inputs->Index.stride != sizeof(GLuint))
inputs->Index.flags |= VEC_BAD_STRIDE;
if (!is_writeable)
inputs->Index.flags |= VEC_NOT_WRITEABLE;
}
 
 
static void _tnl_import_texcoord( GLcontext *ctx,
GLuint unit,
GLboolean writeable,
GLboolean stride )
{
struct vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs;
struct gl_client_array *tmp;
GLboolean is_writeable = 0;
 
tmp = _ac_import_texcoord(ctx, unit, GL_FLOAT,
stride ? 4 * sizeof(GLfloat) : 0,
0,
writeable,
&is_writeable);
 
inputs->TexCoord[unit].data = (GLfloat (*)[4]) tmp->Ptr;
inputs->TexCoord[unit].start = (GLfloat *) tmp->Ptr;
inputs->TexCoord[unit].stride = tmp->StrideB;
inputs->TexCoord[unit].size = tmp->Size;
inputs->TexCoord[unit].flags &= ~(VEC_BAD_STRIDE|VEC_NOT_WRITEABLE);
if (inputs->TexCoord[unit].stride != 4*sizeof(GLfloat))
inputs->TexCoord[unit].flags |= VEC_BAD_STRIDE;
if (!is_writeable)
inputs->TexCoord[unit].flags |= VEC_NOT_WRITEABLE;
}
 
 
static void _tnl_import_edgeflag( GLcontext *ctx,
GLboolean writeable,
GLboolean stride )
{
struct vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs;
struct gl_client_array *tmp;
GLboolean is_writeable = 0;
 
tmp = _ac_import_edgeflag(ctx, GL_UNSIGNED_BYTE,
stride ? sizeof(GLubyte) : 0,
0,
&is_writeable);
 
inputs->EdgeFlag.data = (GLubyte *) tmp->Ptr;
inputs->EdgeFlag.start = (GLubyte *) tmp->Ptr;
inputs->EdgeFlag.stride = tmp->StrideB;
inputs->EdgeFlag.flags &= ~(VEC_BAD_STRIDE|VEC_NOT_WRITEABLE);
if (inputs->EdgeFlag.stride != sizeof(GLubyte))
inputs->EdgeFlag.flags |= VEC_BAD_STRIDE;
if (!is_writeable)
inputs->EdgeFlag.flags |= VEC_NOT_WRITEABLE;
}
 
 
 
static void _tnl_import_attrib( GLcontext *ctx,
GLuint index,
GLboolean writeable,
GLboolean stride )
{
struct vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs;
struct gl_client_array *tmp;
GLboolean is_writeable = 0;
 
tmp = _ac_import_attrib(ctx, index, GL_FLOAT,
stride ? 4 * sizeof(GLfloat) : 0,
4, /* want GLfloat[4] */
writeable,
&is_writeable);
 
inputs->Attribs[index].data = (GLfloat (*)[4]) tmp->Ptr;
inputs->Attribs[index].start = (GLfloat *) tmp->Ptr;
inputs->Attribs[index].stride = tmp->StrideB;
inputs->Attribs[index].size = tmp->Size;
inputs->Attribs[index].flags &= ~(VEC_BAD_STRIDE|VEC_NOT_WRITEABLE);
if (inputs->Attribs[index].stride != 4 * sizeof(GLfloat))
inputs->Attribs[index].flags |= VEC_BAD_STRIDE;
if (!is_writeable)
inputs->Attribs[index].flags |= VEC_NOT_WRITEABLE;
}
 
 
 
/**
* Callback for VB stages that need to improve the quality of arrays
* bound to the VB. This is only necessary for client arrays which
* have not been transformed at any point in the pipeline.
* \param required - bitmask of VERT_*_BIT flags
* \param flags - bitmask of VEC_* flags (ex: VEC_NOT_WRITABLE)
*/
static void _tnl_upgrade_client_data( GLcontext *ctx,
GLuint required,
GLuint flags )
{
GLuint i;
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
GLboolean writeable = (flags & VEC_NOT_WRITEABLE) != 0;
GLboolean stride = (flags & VEC_BAD_STRIDE) != 0;
struct vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs;
GLuint ca_flags = 0;
(void) inputs;
 
if (writeable || stride) ca_flags |= CA_CLIENT_DATA;
 
if ((required & VERT_BIT_CLIP) && VB->ClipPtr == VB->ObjPtr)
required |= VERT_BIT_POS;
 
/* _tnl_print_vert_flags("_tnl_upgrade_client_data", required); */
 
if ((required & VERT_BIT_POS) && (VB->ObjPtr->flags & flags)) {
ASSERT(VB->ObjPtr == &inputs->Obj);
_tnl_import_vertex( ctx, writeable, stride );
VB->importable_data &= ~(VERT_BIT_POS|VERT_BIT_CLIP);
}
 
if ((required & VERT_BIT_NORMAL) && (VB->NormalPtr->flags & flags)) {
ASSERT(VB->NormalPtr == &inputs->Normal);
_tnl_import_normal( ctx, writeable, stride );
VB->importable_data &= ~VERT_BIT_NORMAL;
}
 
if ((required & VERT_BIT_COLOR0) && (VB->ColorPtr[0]->Flags & ca_flags)) {
ASSERT(VB->ColorPtr[0] == &inputs->Color);
_tnl_import_color( ctx, GL_FLOAT, writeable, stride );
VB->importable_data &= ~VERT_BIT_COLOR0;
}
 
if ((required & VERT_BIT_COLOR1) &&
(VB->SecondaryColorPtr[0]->Flags & ca_flags)) {
ASSERT(VB->SecondaryColorPtr[0] == &inputs->SecondaryColor);
_tnl_import_secondarycolor( ctx, GL_FLOAT, writeable, stride );
VB->importable_data &= ~VERT_BIT_COLOR1;
}
 
if ((required & VERT_BIT_FOG)
&& (VB->FogCoordPtr->flags & flags)) {
ASSERT(VB->FogCoordPtr == &inputs->FogCoord);
_tnl_import_fogcoord( ctx, writeable, stride );
VB->importable_data &= ~VERT_BIT_FOG;
}
 
if ((required & VERT_BIT_INDEX) && (VB->IndexPtr[0]->flags & flags)) {
ASSERT(VB->IndexPtr[0] == &inputs->Index);
_tnl_import_index( ctx, writeable, stride );
VB->importable_data &= ~VERT_BIT_INDEX;
}
 
if (required & VERT_BITS_TEX_ANY)
for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++)
if ((required & VERT_BIT_TEX(i)) && (VB->TexCoordPtr[i]->flags & flags)) {
ASSERT(VB->TexCoordPtr[i] == &inputs->TexCoord[i]);
_tnl_import_texcoord( ctx, i, writeable, stride );
VB->importable_data &= ~VERT_BIT_TEX(i);
}
 
/* XXX not sure what to do here for vertex program arrays */
}
 
 
 
void _tnl_vb_bind_arrays( GLcontext *ctx, GLint start, GLsizei count )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
GLuint inputs = tnl->pipeline.inputs;
struct vertex_arrays *tmp = &tnl->array_inputs;
 
/* _mesa_debug(ctx, "%s %d..%d // %d..%d\n", __FUNCTION__, */
/* start, count, ctx->Array.LockFirst, ctx->Array.LockCount); */
/* _tnl_print_vert_flags(" inputs", inputs); */
/* _tnl_print_vert_flags(" _Enabled", ctx->Array._Enabled); */
/* _tnl_print_vert_flags(" importable", inputs & VERT_BITS_FIXUP); */
 
VB->Count = count - start;
VB->FirstClipped = VB->Count;
VB->Elts = NULL;
VB->MaterialMask = NULL;
VB->Material = NULL;
VB->Flag = NULL;
VB->Primitive = tnl->tmp_primitive;
VB->PrimitiveLength = tnl->tmp_primitive_length;
VB->import_data = _tnl_upgrade_client_data;
VB->importable_data = inputs & VERT_BITS_FIXUP;
 
if (ctx->Array.LockCount) {
ASSERT(start == (GLint) ctx->Array.LockFirst);
ASSERT(count == (GLint) ctx->Array.LockCount);
}
 
_ac_import_range( ctx, start, count );
 
if (inputs & VERT_BIT_POS) {
_tnl_import_vertex( ctx, 0, 0 );
tmp->Obj.count = VB->Count;
VB->ObjPtr = &tmp->Obj;
}
 
if (inputs & VERT_BIT_NORMAL) {
_tnl_import_normal( ctx, 0, 0 );
tmp->Normal.count = VB->Count;
VB->NormalPtr = &tmp->Normal;
}
 
if (inputs & VERT_BIT_COLOR0) {
_tnl_import_color( ctx, 0, 0, 0 );
VB->ColorPtr[0] = &tmp->Color;
VB->ColorPtr[1] = 0;
}
 
if (inputs & VERT_BITS_TEX_ANY) {
GLuint unit;
for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) {
if (inputs & VERT_BIT_TEX(unit)) {
_tnl_import_texcoord( ctx, unit, GL_FALSE, GL_FALSE );
tmp->TexCoord[unit].count = VB->Count;
VB->TexCoordPtr[unit] = &tmp->TexCoord[unit];
}
}
}
 
if (inputs & (VERT_BIT_INDEX | VERT_BIT_FOG |
VERT_BIT_EDGEFLAG | VERT_BIT_COLOR1)) {
if (inputs & VERT_BIT_INDEX) {
_tnl_import_index( ctx, 0, 0 );
tmp->Index.count = VB->Count;
VB->IndexPtr[0] = &tmp->Index;
VB->IndexPtr[1] = 0;
}
 
if (inputs & VERT_BIT_FOG) {
_tnl_import_fogcoord( ctx, 0, 0 );
tmp->FogCoord.count = VB->Count;
VB->FogCoordPtr = &tmp->FogCoord;
}
 
if (inputs & VERT_BIT_EDGEFLAG) {
_tnl_import_edgeflag( ctx, GL_TRUE, sizeof(GLboolean) );
VB->EdgeFlag = (GLboolean *) tmp->EdgeFlag.data;
}
 
if (inputs & VERT_BIT_COLOR1) {
_tnl_import_secondarycolor( ctx, 0, 0, 0 );
VB->SecondaryColorPtr[0] = &tmp->SecondaryColor;
VB->SecondaryColorPtr[1] = 0;
}
}
 
/* XXX not 100% sure this is finished. Keith should probably inspect. */
if (ctx->VertexProgram.Enabled) {
GLuint index;
for (index = 0; index < VERT_ATTRIB_MAX; index++) {
/* XXX check program->InputsRead to reduce work here */
_tnl_import_attrib( ctx, index, GL_FALSE, GL_TRUE );
VB->AttribPtr[index] = &tmp->Attribs[index];
}
}
}
/shark/trunk/ports/mesa/src/tnl/t_vtx_api.c
0,0 → 1,808
/* $XFree86$ */
/**************************************************************************
 
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
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
TUNGSTEN GRAPHICS 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 "mtypes.h"
#include "colormac.h"
#include "simple_list.h"
#include "vtxfmt.h"
 
#include "tnl_vtx_api.h"
 
/* Fallback versions of all the entrypoints for situations where
* codegen isn't available. This is slowed significantly by all the
* gumph necessary to get to the tnl pointer.
*/
 
 
/* MultiTexcoord ends up with both of these branches, unfortunately
* (it may get its own version of the macro after size-tracking is
* working).
*
* Errors (VertexAttribNV when ATTR>15) are handled at a higher level.
*/
#define ATTRF( ATTR, N, A, B, C, D ) \
{ \
GET_CURRENT_CONTEXT( ctx ); \
TNLcontext *tnl = TNL_CONTEXT(ctx); \
\
if ((ATTR) == 0) { \
int i; \
\
if (N>0) tnl->vbptr[0].f = A; \
if (N>1) tnl->vbptr[1].f = B; \
if (N>2) tnl->vbptr[2].f = C; \
if (N>3) tnl->vbptr[3].f = D; \
\
for (i = N; i < tnl->vertex_size; i++) \
*tnl->vbptr[i].i = tnl->vertex[i].i; \
\
tnl->vbptr += tnl->vertex_size; \
\
if (--tnl->counter == 0) \
tnl->notify(); \
} \
else { \
GLfloat *dest = tnl->attrptr[ATTR]; \
if (N>0) dest[0] = A; \
if (N>1) dest[1] = B; \
if (N>2) dest[2] = C; \
if (N>3) dest[3] = D; \
} \
}
 
#define ATTR4F( ATTR, A, B, C, D ) ATTRF( ATTR, 4, A, B, C, D )
#define ATTR3F( ATTR, A, B, C, D ) ATTRF( ATTR, 3, A, B, C, 1 )
#define ATTR2F( ATTR, A, B, C, D ) ATTRF( ATTR, 2, A, B, 0, 1 )
#define ATTR1F( ATTR, A, B, C, D ) ATTRF( ATTR, 1, A, 0, 0, 1 )
 
#define ATTR3UB( ATTR, A, B, C ) \
ATTR3F( ATTR, \
UBYTE_TO_FLOAT(A), \
UBYTE_TO_FLOAT(B), \
UBYTE_TO_FLOAT(C))
 
 
#define ATTR4UB( ATTR, A, B, C, D ) \
ATTR4F( ATTR, \
UBYTE_TO_FLOAT(A), \
UBYTE_TO_FLOAT(B), \
UBYTE_TO_FLOAT(C), \
UBYTE_TO_FLOAT(D))
 
 
/* Vertex
*/
static void tnl_Vertex2f( GLfloat x, GLfloat y )
{
ATTR2F( VERT_ATTRIB_POS, x, y );
}
 
static void tnl_Vertex2fv( const GLfloat *v )
{
ATTR2F( VERT_ATTRIB_POS, v[0], v[1] );
}
 
static void tnl_Vertex3f( GLfloat x, GLfloat y, GLfloat z )
{
ATTR3F( VERT_ATTRIB_POS, x, y, z );
}
 
static void tnl_Vertex3fv( const GLfloat *v )
{
ATTR3F( VERT_ATTRIB_POS, v[0], v[1], v[2] );
}
 
static void tnl_Vertex4f( GLfloat x, GLfloat y, GLfloat z, GLfloat w )
{
ATTR4F( VERT_ATTRIB_POS, x, y, z, w );
}
 
static void tnl_Vertex4fv( const GLfloat *v )
{
ATTR4F( VERT_ATTRIB_POS, v[0], v[1], v[2], v[3] );
}
 
 
/* Color
*/
static void tnl_Color3ub( GLubyte r, GLubyte g, GLubyte b )
{
ATTR3UB( VERT_ATTRIB_COLOR0, r, g, b );
}
 
static void tnl_Color3ubv( const GLubyte *v )
{
ATTR3UB( VERT_ATTRIB_COLOR0, v[0], v[1], v[2] );
}
 
static void tnl_Color4ub( GLubyte r, GLubyte g, GLubyte b, GLubyte a )
{
ATTR4UB( VERT_ATTRIB_COLOR0, r, g, b, a );
}
 
static void tnl_Color4ubv( const GLubyte *v )
{
ATTR4UB( VERT_ATTRIB_COLOR0, v[0], v[1], v[2], v[3] );
}
 
static void tnl_Color3f( GLfloat r, GLfloat g, GLfloat b )
{
ATTR3F( VERT_ATTRIB_COLOR0, r, g, b );
}
 
static void tnl_Color3fv( const GLfloat *v )
{
ATTR3F( VERT_ATTRIB_COLOR0, v[0], v[1], v[2] );
}
 
static void tnl_Color4f( GLfloat r, GLfloat g, GLfloat b, GLfloat a )
{
ATTR4F( VERT_ATTRIB_COLOR0, r, g, b, a );
}
 
static void tnl_Color4fv( const GLfloat *v )
{
ATTR4F( VERT_ATTRIB_COLOR0, v[0], v[1], v[2], v[3] );
}
 
 
/* Secondary Color
*/
static void tnl_SecondaryColor3ubEXT( GLubyte r, GLubyte g, GLubyte b )
{
ATTR3UB( VERT_ATTRIB_COLOR1, r, g, b );
}
 
static void tnl_SecondaryColor3ubvEXT( const GLubyte *v )
{
ATTR3UB( VERT_ATTRIB_COLOR1, v[0], v[1], v[2] );
}
 
static void tnl_SecondaryColor3fEXT( GLfloat r, GLfloat g, GLfloat b )
{
ATTR3F( VERT_ATTRIB_COLOR1, r, g, b );
}
 
static void tnl_SecondaryColor3fvEXT( const GLfloat *v )
{
ATTR3F( VERT_ATTRIB_COLOR1, v[0], v[1], v[2] );
}
 
 
 
/* Fog Coord
*/
static void tnl_FogCoordfEXT( GLfloat f )
{
ATTR1F( VERT_ATTRIB_FOG, f );
}
 
static void tnl_FogCoordfvEXT( const GLfloat *v )
{
ATTR1F( VERT_ATTRIB_FOG, v[0] );
}
 
 
 
/* Normal
*/
static void tnl_Normal3f( GLfloat n0, GLfloat n1, GLfloat n2 )
{
ATTR3F( VERT_ATTRIB_NORMAL, n0, n1, n2 );
}
 
static void tnl_Normal3fv( const GLfloat *v )
{
ATTR3F( VERT_ATTRIB_COLOR1, v[0], v[1], v[2] );
}
 
 
/* TexCoord
*/
static void tnl_TexCoord1f( GLfloat s )
{
ATTR1F( VERT_ATTRIB_TEX0, s );
}
 
static void tnl_TexCoord1fv( const GLfloat *v )
{
ATTR1F( VERT_ATTRIB_TEX0, v[0] );
}
 
static void tnl_TexCoord2f( GLfloat s, GLfloat t )
{
ATTR2F( VERT_ATTRIB_TEX0, s, t );
}
 
static void tnl_TexCoord2fv( const GLfloat *v )
{
ATTR2F( VERT_ATTRIB_TEX0, v[0], v[1] );
}
 
static void tnl_TexCoord3f( GLfloat s, GLfloat t, GLfloat r )
{
ATTR3F( VERT_ATTRIB_TEX0, s, t, r );
}
 
static void tnl_TexCoord3fv( const GLfloat *v )
{
ATTR3F( VERT_ATTRIB_TEX0, v[0], v[1], v[2] );
}
 
static void tnl_TexCoord4f( GLfloat s, GLfloat t, GLfloat r, GLfloat q )
{
ATTR4F( VERT_ATTRIB_TEX0, s, t, r, q );
}
 
static void tnl_TexCoord4fv( const GLfloat *v )
{
ATTR4F( VERT_ATTRIB_TEX0, v[0], v[1], v[2], v[3] );
}
 
 
/* Miscellaneous:
*
* These don't alias NV attributes, but still need similar treatment.
* Basically these are attributes with numbers greater than 16.
*/
static void tnl_EdgeFlag( GLboolean flag )
{
GLfloat f = flag ? 1 : 0;
ATTR1F( VERT_ATTRIB_EDGEFLAG, f);
}
 
static void tnl_EdgeFlagv( const GLboolean *flag )
{
GLfloat f = flag[0] ? 1 : 0;
ATTR1F( VERT_ATTRIB_EDGEFLAG, f);
}
 
static void tnl_Indexi( GLint idx )
{
ATTR1F( VERT_ATTRIB_INDEX, idx );
}
 
static void tnl_Indexiv( const GLint *idx )
{
ATTR1F( VERT_ATTRIB_INDEX, idx );
}
 
/* Use dispatch switching to build 'ranges' of eval vertices for each
* type, avoiding need for flags. (Make
* evalcoords/evalpoints/vertices/attr0 mutually exclusive)
*/
static void _tnl_EvalCoord1f( GLfloat u )
{
ATTR1F( VERT_ATTRIB_POS, u );
}
 
static void _tnl_EvalCoord1fv( const GLfloat *v )
{
ATTR1F( VERT_ATTRIB_POS, v[0] );
}
 
static void _tnl_EvalCoord2f( GLfloat u, GLfloat v )
{
ATTR2F( VERT_ATTRIB_POS, u, v );
}
 
static void _tnl_EvalCoord2fv( const GLfloat *v )
{
ATTR2F( VERT_ATTRIB_POS, v[0], v[1] );
}
 
 
 
/* Second level dispatch table for MultiTexCoord, Material and
* VertexAttribNV.
*
* Need this because we want to track things like vertex attribute
* sizes, presence/otherwise of attribs in recorded vertices, etc, by
* manipulating the state of dispatch tables. Need therefore a
* dispatch slot for each value of 'index' or 'unit' in VertexAttribNV
* and MultiTexCoordARB. Also need a mechnism for keeping this data
* consistent with what's coming in via the Vertex/Normal/etc api
* above (where aliasing exists with the traditional entrypoints).
* Note that MultiTexCoordARB aliases with TexCoord when unit==0.
*
* Need presence tracking for material components, too, but not size
* tracking or help with aliasing. Could move material to seperate
* dispatch without the "*4" below, or even do the checks every time.
*/
struct attr_dispatch_tab {
void (*tab[32*4])( void );
void (*swapped[32*4])( void );
int swapcount;
int installed_sizes[32];
};
 
#define DISPATCH_ATTR1F( ATTR, N, )
tnl->vb.attr_dispatch
 
/* Result at the back end after second dispatch -- could further
* specialize for attr zero -- maybe just in the codegen version.
*/
static void tnl_Attr1f( GLint attr, GLfloat s )
{
ATTR1F( attr, s );
}
 
static void tnl_Attr1fv( GLint attr, const GLfloat *v )
{
ATTR1F( attr, v[0] );
}
 
static void tnl_Attr2f( GLint attr, GLfloat s, GLfloat t )
{
ATTR2F( attr, s, t );
}
 
static void tnl_Attr2fv( GLint attr, const GLfloat *v )
{
ATTR2F( attr, v[0], v[1] );
}
 
static void tnl_Attr3f( GLint attr, GLfloat s, GLfloat t, GLfloat r )
{
ATTR3F( attr, s, t, r );
}
 
static void tnl_Attr3fv( GLint attr, const GLfloat *v )
{
ATTR3F( attr, v[0], v[1], v[2] );
}
 
static void tnl_Attr4f( GLint attr, GLfloat s, GLfloat t, GLfloat r, GLfloat q )
{
ATTR4F( attr, s, t, r, q );
}
 
static void tnl_Attr4fv( GLint attr, const GLfloat *v )
{
ATTR4F( attr, v[0], v[1], v[2], v[3] );
}
 
 
/* MultiTexcoord: Send through second level dispatch.
*/
static void tnl_MultiTexCoord1fARB( GLenum target, GLfloat s )
{
GLuint attr = (target - GL_TEXTURE0_ARB) + VERT_ATTRIB_TEX0;
if (attr < MAX_VERT_ATTRS)
DISPATCH_ATTR1F( attr, s );
}
 
static void tnl_MultiTexCoord1fvARB( GLenum target, const GLfloat *v )
{
GLuint attr = (target - GL_TEXTURE0_ARB) + VERT_ATTRIB_TEX0;
if (attr < MAX_VERT_ATTRS)
DISPATCH_ATTR1F( attr, v[0] );
}
 
static void tnl_MultiTexCoord2fARB( GLenum target, GLfloat s, GLfloat t )
{
GLuint attr = (target - GL_TEXTURE0_ARB) + VERT_ATTRIB_TEX0;
if (attr < MAX_VERT_ATTRS)
DISPATCH_ATTR2F( attr, s, t );
}
 
static void tnl_MultiTexCoord2fvARB( GLenum target, const GLfloat *v )
{
GLuint attr = (target - GL_TEXTURE0_ARB) + VERT_ATTRIB_TEX0;
if (attr < MAX_VERT_ATTRS)
DISPATCH_ATTR2F( attr, v[0], v[1] );
}
 
static void tnl_MultiTexCoord3fARB( GLenum target, GLfloat s, GLfloat t,
GLfloat r)
{
GLuint attr = (target - GL_TEXTURE0_ARB) + VERT_ATTRIB_TEX0;
if (attr < MAX_VERT_ATTRS)
DISPATCH_ATTR3F( attr, s, t, r );
}
 
static void tnl_MultiTexCoord3fvARB( GLenum target, const GLfloat *v )
{
GLuint attr = (target - GL_TEXTURE0_ARB) + VERT_ATTRIB_TEX0;
if (attr < MAX_VERT_ATTRS)
DISPATCH_ATTR3F( attr, v[0], v[1], v[2] );
}
 
static void tnl_MultiTexCoord4fARB( GLenum target, GLfloat s, GLfloat t,
GLfloat r, GLfloat q )
{
GLuint attr = (target - GL_TEXTURE0_ARB) + VERT_ATTRIB_TEX0;
if (attr < MAX_VERT_ATTRS)
DISPATCH_ATTR4F( attr, s, t, r, q );
}
 
static void tnl_MultiTexCoord4fvARB( GLenum target, const GLfloat *v )
{
GLuint attr = (target - GL_TEXTURE0_ARB) + VERT_ATTRIB_TEX0;
if (attr < MAX_VERT_ATTRS)
DISPATCH_ATTR4F( attr, v[0], v[1], v[2], v[3] );
}
 
 
/* NV_vertex_program:
*
* Check for errors & reroute through second dispatch layer to get
* size tracking per-attribute.
*/
static void tnl_VertexAttrib1fNV( GLuint index, GLfloat s )
{
if (index < MAX_VERT_ATTRS)
DISPATCH_ATTR1F( index, s );
else
DISPATCH_ERROR;
}
 
static void tnl_VertexAttrib1fvNV( GLuint index, const GLfloat *v )
{
if (index < MAX_VERT_ATTRS)
DISPATCH_ATTR1F( index, v[0] );
else
DISPATCH_ERROR;
}
 
static void tnl_VertexAttrib2fNV( GLuint index, GLfloat s, GLfloat t )
{
if (index < MAX_VERT_ATTRS)
DISPATCH_ATTR2F( index, s, t );
else
DISPATCH_ERROR;
}
 
static void tnl_VertexAttrib2fvNV( GLuint index, const GLfloat *v )
{
if (index < MAX_VERT_ATTRS)
DISPATCH_ATTR2F( index, v[0], v[1] );
else
DISPATCH_ERROR;
}
 
static void tnl_VertexAttrib3fNV( GLuint index, GLfloat s, GLfloat t,
GLfloat r )
{
if (index < MAX_VERT_ATTRS)
DISPATCH_ATTR3F( index, s, t, r );
else
DISPATCH_ERROR;
}
 
static void tnl_VertexAttrib3fvNV( GLuint index, const GLfloat *v )
{
if (index < MAX_VERT_ATTRS)
DISPATCH_ATTR3F( index, v[0], v[1], v[2] );
else
DISPATCH_ERROR;
}
 
static void tnl_VertexAttrib4fNV( GLuint index, GLfloat s, GLfloat t,
GLfloat r, GLfloat q )
{
if (index < MAX_VERT_ATTRS)
DISPATCH_ATTR4F( index, s, t, r, q );
else
DISPATCH_ERROR;
}
 
static void tnl_VertexAttrib4fvNV( GLuint index, const GLfloat *v )
{
if (index < MAX_VERT_ATTRS)
DISPATCH_ATTR4F( index, v[0], v[1], v[2], v[3] );
else
DISPATCH_ERROR;
}
 
 
 
 
 
 
 
/* Materials:
*
* These are treated as per-vertex attributes, at indices above where
* the NV_vertex_program leaves off. There are a lot of good things
* about treating materials this way.
*
* *** Need a dispatch step (like VertexAttribute GLint attr, and MultiTexCoord)
* *** to expand vertex size, etc. Use the same second level dispatch
* *** (keyed by attr number) as above.
*/
#define MAT( ATTR, face, params ) \
do { \
if (face != GL_BACK) \
DISPATCH_ATTRF( ATTR, N, params ); \
if (face != GL_FRONT) \
DISPATCH_ATTRF( ATTR+7, N, params ); \
} while (0)
 
 
/* NOTE: Have to remove/dealwith colormaterial crossovers, probably
* later on - in the meantime just store everything.
*/
static void _tnl_Materialfv( GLenum face, GLenum pname,
const GLfloat *params )
{
switch (pname) {
case GL_EMISSION:
MAT( VERT_ATTRIB_FRONT_EMMISSION, 4, face, params );
break;
case GL_AMBIENT:
MAT( VERT_ATTRIB_FRONT_AMBIENT, 4, face, params );
break;
case GL_DIFFUSE:
MAT( VERT_ATTRIB_FRONT_DIFFUSE, 4, face, params );
break;
case GL_SPECULAR:
MAT( VERT_ATTRIB_FRONT_SPECULAR, 4, face, params );
break;
case GL_SHININESS:
MAT( VERT_ATTRIB_FRONT_SHININESS, 1, face, params );
break;
case GL_COLOR_INDEXES:
MAT( VERT_ATTRIB_FRONT_EMMISSION, 3, face, params );
break;
case GL_AMBIENT_AND_DIFFUSE:
MAT( VERT_ATTRIB_FRONT_AMBIENT, 4, face, params );
MAT( VERT_ATTRIB_FRONT_DIFFUSE, 4, face, params );
break;
default:
_mesa_error( ctx, GL_INVALID_ENUM, where );
return;
}
}
 
 
 
 
/* Codegen support
*/
static struct dynfn *lookup( struct dynfn *l, int key )
{
struct dynfn *f;
 
foreach( f, l ) {
if (f->key == key)
return f;
}
 
return 0;
}
 
/* Vertex descriptor
*/
struct _tnl_vertex_descriptor {
GLuint attr_bits[4];
};
 
 
/* Can't use the loopback template for this:
*/
#define CHOOSE(FN, FNTYPE, MASK, ACTIVE, ARGS1, ARGS2 ) \
static void choose_##FN ARGS1 \
{ \
int key = tnl->vertex_format & (MASK|ACTIVE); \
struct dynfn *dfn = lookup( &tnl->dfn_cache.FN, key ); \
\
if (dfn == 0) \
dfn = tnl->codegen.FN( &vb, key ); \
else if (MESA_VERBOSE & DEBUG_CODEGEN) \
_mesa_debug(NULL, "%s -- cached codegen\n", __FUNCTION__ ); \
\
if (dfn) \
tnl->context->Exec->FN = (FNTYPE)(dfn->code); \
else { \
if (MESA_VERBOSE & DEBUG_CODEGEN) \
_mesa_debug(NULL, "%s -- generic version\n", __FUNCTION__ ); \
tnl->context->Exec->FN = tnl_##FN; \
} \
\
tnl->context->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; \
tnl->context->Exec->FN ARGS2; \
}
 
 
 
CHOOSE(Normal3f, p3f, 3, VERT_ATTRIB_NORMAL,
(GLfloat a,GLfloat b,GLfloat c), (a,b,c))
CHOOSE(Normal3fv, pfv, 3, VERT_ATTRIB_NORMAL,
(const GLfloat *v), (v))
 
CHOOSE(Color4ub, p4ub, 4, VERT_ATTRIB_COLOR0,
(GLubyte a,GLubyte b, GLubyte c, GLubyte d), (a,b,c,d))
CHOOSE(Color4ubv, pubv, 4, VERT_ATTRIB_COLOR0,
(const GLubyte *v), (v))
CHOOSE(Color3ub, p3ub, 3, VERT_ATTRIB_COLOR0,
(GLubyte a,GLubyte b, GLubyte c), (a,b,c))
CHOOSE(Color3ubv, pubv, 3, VERT_ATTRIB_COLOR0,
(const GLubyte *v), (v))
 
CHOOSE(Color4f, p4f, 4, VERT_ATTRIB_COLOR0,
(GLfloat a,GLfloat b, GLfloat c, GLfloat d), (a,b,c,d))
CHOOSE(Color4fv, pfv, 4, VERT_ATTRIB_COLOR0,
(const GLfloat *v), (v))
CHOOSE(Color3f, p3f, 3, VERT_ATTRIB_COLOR0,
(GLfloat a,GLfloat b, GLfloat c), (a,b,c))
CHOOSE(Color3fv, pfv, 3, VERT_ATTRIB_COLOR0,
(const GLfloat *v), (v))
 
 
CHOOSE(SecondaryColor3ubEXT, p3ub, VERT_ATTRIB_COLOR1,
(GLubyte a,GLubyte b, GLubyte c), (a,b,c))
CHOOSE(SecondaryColor3ubvEXT, pubv, VERT_ATTRIB_COLOR1,
(const GLubyte *v), (v))
CHOOSE(SecondaryColor3fEXT, p3f, VERT_ATTRIB_COLOR1,
(GLfloat a,GLfloat b, GLfloat c), (a,b,c))
CHOOSE(SecondaryColor3fvEXT, pfv, VERT_ATTRIB_COLOR1,
(const GLfloat *v), (v))
 
CHOOSE(TexCoord2f, p2f, VERT_ATTRIB_TEX0,
(GLfloat a,GLfloat b), (a,b))
CHOOSE(TexCoord2fv, pfv, VERT_ATTRIB_TEX0,
(const GLfloat *v), (v))
CHOOSE(TexCoord1f, p1f, VERT_ATTRIB_TEX0,
(GLfloat a), (a))
CHOOSE(TexCoord1fv, pfv, VERT_ATTRIB_TEX0,
(const GLfloat *v), (v))
 
CHOOSE(MultiTexCoord2fARB, pe2f, VERT_ATTRIB_TEX0,
(GLenum u,GLfloat a,GLfloat b), (u,a,b))
CHOOSE(MultiTexCoord2fvARB, pefv, MASK_ST_ALL, ACTIVE_ST_ALL,
(GLenum u,const GLfloat *v), (u,v))
CHOOSE(MultiTexCoord1fARB, pe1f, MASK_ST_ALL, ACTIVE_ST_ALL,
(GLenum u,GLfloat a), (u,a))
CHOOSE(MultiTexCoord1fvARB, pefv, MASK_ST_ALL, ACTIVE_ST_ALL,
(GLenum u,const GLfloat *v), (u,v))
 
CHOOSE(Vertex3f, p3f, VERT_ATTRIB_POS,
(GLfloat a,GLfloat b,GLfloat c), (a,b,c))
CHOOSE(Vertex3fv, pfv, VERT_ATTRIB_POS,
(const GLfloat *v), (v))
CHOOSE(Vertex2f, p2f, VERT_ATTRIB_POS,
(GLfloat a,GLfloat b), (a,b))
CHOOSE(Vertex2fv, pfv, VERT_ATTRIB_POS,
(const GLfloat *v), (v))
 
 
 
 
 
void _tnl_InitVtxfmtChoosers( GLvertexformat *vfmt )
{
vfmt->Color3f = choose_Color3f;
vfmt->Color3fv = choose_Color3fv;
vfmt->Color3ub = choose_Color3ub;
vfmt->Color3ubv = choose_Color3ubv;
vfmt->Color4f = choose_Color4f;
vfmt->Color4fv = choose_Color4fv;
vfmt->Color4ub = choose_Color4ub;
vfmt->Color4ubv = choose_Color4ubv;
vfmt->SecondaryColor3fEXT = choose_SecondaryColor3fEXT;
vfmt->SecondaryColor3fvEXT = choose_SecondaryColor3fvEXT;
vfmt->SecondaryColor3ubEXT = choose_SecondaryColor3ubEXT;
vfmt->SecondaryColor3ubvEXT = choose_SecondaryColor3ubvEXT;
vfmt->MultiTexCoord1fARB = dd_MultiTexCoord1fARB;
vfmt->MultiTexCoord1fvARB = dd_MultiTexCoord1fvARB;
vfmt->MultiTexCoord2fARB = dd_MultiTexCoord2fARB;
vfmt->MultiTexCoord2fvARB = dd_MultiTexCoord2fvARB;
vfmt->MultiTexCoord3fARB = dd_MultiTexCoord3fARB;
vfmt->MultiTexCoord3fvARB = dd_MultiTexCoord3fvARB;
vfmt->MultiTexCoord4fARB = dd_MultiTexCoord4fARB;
vfmt->MultiTexCoord4fvARB = dd_MultiTexCoord4fvARB;
vfmt->Normal3f = choose_Normal3f;
vfmt->Normal3fv = choose_Normal3fv;
vfmt->TexCoord1f = choose_TexCoord1f;
vfmt->TexCoord1fv = choose_TexCoord1fv;
vfmt->TexCoord2f = choose_TexCoord2f;
vfmt->TexCoord2fv = choose_TexCoord2fv;
vfmt->TexCoord3f = choose_TexCoord3f;
vfmt->TexCoord3fv = choose_TexCoord3fv;
vfmt->TexCoord4f = choose_TexCoord4f;
vfmt->TexCoord4fv = choose_TexCoord4fv;
vfmt->Vertex2f = choose_Vertex2f;
vfmt->Vertex2fv = choose_Vertex2fv;
vfmt->Vertex3f = choose_Vertex3f;
vfmt->Vertex3fv = choose_Vertex3fv;
vfmt->Vertex4f = choose_Vertex4f;
vfmt->Vertex4fv = choose_Vertex4fv;
vfmt->FogCoordfvEXT = choose_FogCoordfvEXT;
vfmt->FogCoordfEXT = choose_FogCoordfEXT;
vfmt->EdgeFlag = choose_EdgeFlag;
vfmt->EdgeFlagv = choose_EdgeFlagv;
vfmt->Indexi = choose_Indexi;
vfmt->Indexiv = choose_Indexiv;
vfmt->EvalCoord1f = choose_EvalCoord1f;
vfmt->EvalCoord1fv = choose_EvalCoord1fv;
vfmt->EvalCoord2f = choose_EvalCoord2f;
vfmt->EvalCoord2fv = choose_EvalCoord2fv;
vfmt->Materialfv = dd_Materialfv;
}
 
 
static struct dynfn *codegen_noop( struct _vb *vb, int key )
{
(void) vb; (void) key;
return 0;
}
 
void _tnl_InitCodegen( struct dfn_generators *gen )
{
/* Generate an attribute or vertex command.
*/
gen->Attr1f = codegen_noop;
gen->Attr1fv = codegen_noop;
gen->Attr2f = codegen_noop;
gen->Attr2fv = codegen_noop;
gen->Attr3f = codegen_noop;
gen->Attr3fv = codegen_noop;
gen->Attr4f = codegen_noop;
gen->Attr4fv = codegen_noop;
/* Index is never zero for these...
*/
gen->Attr3ub = codegen_noop;
gen->Attr3ubv = codegen_noop;
gen->Attr4ub = codegen_noop;
gen->Attr4ubv = codegen_noop;
 
/* As above, but deal with the extra (redundant by now) index
* argument to the generated function.
*/
gen->NVAttr1f = codegen_noop;
gen->NVAttr1fv = codegen_noop;
gen->NVAttr2f = codegen_noop;
gen->NVAttr2fv = codegen_noop;
gen->NVAttr3f = codegen_noop;
gen->NVAttr3fv = codegen_noop;
gen->NVAttr4f = codegen_noop;
gen->NVAttr4fv = codegen_noop;
 
 
if (!getenv("MESA_NO_CODEGEN")) {
#if defined(USE_X86_ASM)
_tnl_InitX86Codegen( gen );
#endif
 
#if defined(USE_SSE_ASM)
_tnl_InitSSECodegen( gen );
#endif
 
#if defined(USE_3DNOW_ASM)
#endif
 
#if defined(USE_SPARC_ASM)
#endif
}
}
/shark/trunk/ports/mesa/src/tnl/t_imm_api.c
0,0 → 1,1368
/* $Id: t_imm_api.c,v 1.1 2003-02-28 11:48:06 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
 
 
#include "glheader.h"
#include "context.h"
#include "dlist.h"
#include "enums.h"
#include "light.h"
#include "imports.h"
#include "state.h"
#include "colormac.h"
#include "macros.h"
#include "vtxfmt.h"
 
#include "t_context.h"
#include "t_imm_api.h"
#include "t_imm_elt.h"
#include "t_imm_exec.h"
#include "t_imm_dlist.h"
 
 
/* A cassette is full or flushed on a statechange.
*/
void _tnl_flush_immediate( GLcontext *ctx, struct immediate *IM )
{
if (!ctx) {
/* We were called by glVertex, glEvalCoord, glArrayElement, etc.
* The current context is corresponds to the IM structure.
*/
GET_CURRENT_CONTEXT(context);
ctx = context;
}
 
if (MESA_VERBOSE & VERBOSE_IMMEDIATE)
_mesa_debug(ctx, "_tnl_flush_immediate IM: %d compiling: %d\n",
IM->id, ctx->CompileFlag);
 
if (IM->FlushElt == FLUSH_ELT_EAGER) {
_tnl_translate_array_elts( ctx, IM, IM->LastPrimitive, IM->Count );
}
 
/* Mark the last primitive:
*/
IM->PrimitiveLength[IM->LastPrimitive] = IM->Count - IM->LastPrimitive;
IM->Primitive[IM->LastPrimitive] |= PRIM_LAST;
 
if (ctx->CompileFlag)
_tnl_compile_cassette( ctx, IM );
else
_tnl_execute_cassette( ctx, IM );
}
 
 
/* Hook for ctx->Driver.FlushVertices:
*/
void _tnl_flush_vertices( GLcontext *ctx, GLuint flags )
{
struct immediate *IM = TNL_CURRENT_IM(ctx);
 
if (MESA_VERBOSE & VERBOSE_IMMEDIATE)
_mesa_debug(ctx,
"_tnl_flush_vertices flags %x IM(%d) %d..%d Flag[%d]: %x\n",
flags, IM->id, IM->Start, IM->Count, IM->Start,
IM->Flag[IM->Start]);
 
if (IM->Flag[IM->Start]) {
if ((flags & FLUSH_UPDATE_CURRENT) ||
IM->Count > IM->Start ||
(IM->Flag[IM->Start] & (VERT_BIT_BEGIN | VERT_BIT_END))) {
_tnl_flush_immediate( ctx, IM );
}
}
}
 
 
void
_tnl_save_Begin( GLenum mode )
{
GET_CURRENT_CONTEXT(ctx);
struct immediate *IM = TNL_CURRENT_IM(ctx);
GLuint inflags, state;
 
/* _mesa_debug(ctx, "%s: before: %x\n", __FUNCTION__, IM->BeginState); */
 
if (mode > GL_POLYGON) {
_mesa_compile_error( ctx, GL_INVALID_ENUM, "_tnl_Begin" );
return;
}
 
if (ctx->NewState)
_mesa_update_state(ctx);
 
#if 000
/* if only a very few slots left, might as well flush now
*/
if (IM->Count > IMM_MAXDATA-8) {
_tnl_flush_immediate( ctx, IM );
IM = TNL_CURRENT_IM(ctx);
}
#endif
 
/* Check for and flush buffered vertices from internal operations.
*/
if (IM->SavedBeginState) {
_tnl_flush_immediate( ctx, IM );
IM = TNL_CURRENT_IM(ctx);
IM->BeginState = IM->SavedBeginState;
IM->SavedBeginState = 0;
}
 
state = IM->BeginState;
inflags = state & (VERT_BEGIN_0|VERT_BEGIN_1);
state |= inflags << 2; /* set error conditions */
 
if (inflags != (VERT_BEGIN_0|VERT_BEGIN_1))
{
GLuint count = IM->Count;
GLuint last = IM->LastPrimitive;
 
state |= (VERT_BEGIN_0|VERT_BEGIN_1);
IM->Flag[count] |= VERT_BIT_BEGIN;
IM->Primitive[count] = mode | PRIM_BEGIN;
IM->PrimitiveLength[IM->LastPrimitive] = count - IM->LastPrimitive;
IM->LastPrimitive = count;
 
/* Not quite right. Need to use the fallback '_aa_ArrayElement'
* when not known to be inside begin/end and arrays are
* unlocked.
*/
if (IM->FlushElt == FLUSH_ELT_EAGER) {
_tnl_translate_array_elts( ctx, IM, last, count );
}
}
 
ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
IM->BeginState = state;
 
/* Update save_primitive now. Don't touch ExecPrimitive as this is
* updated in the replay of this cassette if we are in
* COMPILE_AND_EXECUTE mode.
*/
if (ctx->Driver.CurrentSavePrimitive == PRIM_UNKNOWN)
ctx->Driver.CurrentSavePrimitive = PRIM_INSIDE_UNKNOWN_PRIM;
else if (ctx->Driver.CurrentSavePrimitive == PRIM_OUTSIDE_BEGIN_END)
ctx->Driver.CurrentSavePrimitive = mode;
}
 
 
void
_tnl_Begin( GLenum mode )
{
GET_CURRENT_CONTEXT(ctx);
TNLcontext *tnl = TNL_CONTEXT(ctx);
ASSERT (!ctx->CompileFlag);
 
if (mode > GL_POLYGON) {
_mesa_error( ctx, GL_INVALID_ENUM, "_tnl_Begin(0x%x)", mode );
return;
}
 
if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) {
_mesa_error( ctx, GL_INVALID_OPERATION, "_tnl_Begin" );
return;
}
 
if (ctx->NewState)
_mesa_update_state(ctx);
 
{
struct immediate *IM = TNL_CURRENT_IM(ctx);
GLuint count = IM->Count;
GLuint last = IM->LastPrimitive;
 
if (IM->Start == IM->Count &&
tnl->Driver.NotifyBegin &&
tnl->Driver.NotifyBegin( ctx, mode )) {
return;
}
 
assert( IM->SavedBeginState == 0 );
assert( IM->BeginState == 0 );
 
/* Not quite right. Need to use the fallback '_aa_ArrayElement'
* when not known to be inside begin/end and arrays are
* unlocked.
*/
if (IM->FlushElt == FLUSH_ELT_EAGER) {
_tnl_translate_array_elts( ctx, IM, last, count );
}
 
IM->Flag[count] |= VERT_BIT_BEGIN;
IM->Primitive[count] = mode | PRIM_BEGIN;
IM->PrimitiveLength[last] = count - last;
IM->LastPrimitive = count;
IM->BeginState = (VERT_BEGIN_0|VERT_BEGIN_1);
 
/* _mesa_debug(ctx, "%s: %x\n", __FUNCTION__, IM->BeginState); */
 
ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
ctx->Driver.CurrentExecPrimitive = mode;
}
}
 
 
/* Function which allows operations like 'glRectf' to decompose to a
* begin/end object and vertices without worrying about what happens
* with display lists.
*/
GLboolean
_tnl_hard_begin( GLcontext *ctx, GLenum p )
{
/* _mesa_debug(ctx, "%s\n", __FUNCTION__); */
 
if (!ctx->CompileFlag) {
/* If not compiling, treat as a normal begin().
*/
/* _mesa_debug(ctx, "%s: treating as glBegin\n", __FUNCTION__); */
glBegin( p );
return GL_TRUE;
}
else {
/* Otherwise, need to do special processing to preserve the
* condition that these vertices will only be replayed outside
* future begin/end objects.
*/
struct immediate *IM = TNL_CURRENT_IM(ctx);
 
if (ctx->NewState)
_mesa_update_state(ctx);
 
if (IM->Count > IMM_MAXDATA-8) {
_tnl_flush_immediate( ctx, IM );
IM = TNL_CURRENT_IM(ctx);
}
 
/* A lot depends on the degree to which the display list has
* constrained the possible begin/end states at this point:
*/
switch (IM->BeginState & (VERT_BEGIN_0|VERT_BEGIN_1)) {
case VERT_BEGIN_0|VERT_BEGIN_1:
/* This is an immediate known to be inside a begin/end object.
*/
ASSERT(ctx->Driver.CurrentSavePrimitive <= GL_POLYGON);
IM->BeginState |= (VERT_ERROR_1|VERT_ERROR_0);
return GL_FALSE;
 
case VERT_BEGIN_0:
case VERT_BEGIN_1:
/* This is a display-list immediate in an unknown begin/end
* state. Assert it is empty and convert it to a 'hard' one.
*/
ASSERT(IM->SavedBeginState == 0);
ASSERT(ctx->Driver.CurrentSavePrimitive == PRIM_UNKNOWN);
 
/* Push current beginstate, to be restored later. Don't worry
* about raising errors.
*/
IM->SavedBeginState = IM->BeginState;
 
/* FALLTHROUGH */
 
case 0:
/* Unless we have fallen through, this is an immediate known to
* be outside begin/end objects.
*/
ASSERT(ctx->Driver.CurrentSavePrimitive == PRIM_UNKNOWN ||
ctx->Driver.CurrentSavePrimitive == PRIM_OUTSIDE_BEGIN_END);
ASSERT (IM->FlushElt != FLUSH_ELT_EAGER);
 
IM->BeginState |= VERT_BEGIN_0|VERT_BEGIN_1;
IM->Flag[IM->Count] |= VERT_BIT_BEGIN;
IM->Primitive[IM->Count] = p | PRIM_BEGIN;
IM->PrimitiveLength[IM->LastPrimitive] = IM->Count - IM->LastPrimitive;
IM->LastPrimitive = IM->Count;
 
/* This is necessary as this immediate will not be flushed in
* _tnl_end() -- we leave it active, hoping to pick up more
* vertices before the next state change.
*/
ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES;
return GL_TRUE;
 
default:
assert (0);
return GL_TRUE;
}
}
}
 
 
 
 
 
 
/* Both streams now outside begin/end.
*
* Leave SavedBeginState untouched -- attempt to gather several
* rects/arrays together in a single immediate struct.
*/
void
_tnl_end( GLcontext *ctx )
{
struct immediate *IM = TNL_CURRENT_IM(ctx);
GLuint state = IM->BeginState;
GLuint inflags = (~state) & (VERT_BEGIN_0|VERT_BEGIN_1);
 
assert( ctx->Driver.NeedFlush & FLUSH_STORED_VERTICES );
 
state |= inflags << 2; /* errors */
 
if (inflags != (VERT_BEGIN_0|VERT_BEGIN_1))
{
GLuint count = IM->Count;
GLuint last = IM->LastPrimitive;
 
state &= ~(VERT_BEGIN_0|VERT_BEGIN_1); /* update state */
IM->Flag[count] |= VERT_BIT_END;
IM->Primitive[last] |= PRIM_END;
IM->PrimitiveLength[last] = count - last;
IM->Primitive[count] = PRIM_OUTSIDE_BEGIN_END; /* removes PRIM_BEGIN
* flag if length == 0
*/
IM->LastPrimitive = count;
 
if (IM->FlushElt == FLUSH_ELT_EAGER) {
_tnl_translate_array_elts( ctx, IM, last, count );
}
}
 
IM->BeginState = state;
 
if (!ctx->CompileFlag) {
if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END)
_mesa_error( ctx, GL_INVALID_OPERATION, "_tnl_End" );
else
ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END;
}
 
/* You can set this flag to get the old 'flush_vb on glEnd()'
* behaviour.
*/
if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH)
_tnl_flush_immediate( ctx, IM );
}
 
void
_tnl_End(void)
{
GET_CURRENT_CONTEXT(ctx);
 
_tnl_end( ctx );
 
/* Need to keep save primitive uptodate in COMPILE and
* COMPILE_AND_EXEC modes, need to keep exec primitive uptodate
* otherwise.
*/
if (ctx->CompileFlag)
ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END;
}
 
 
#define COLOR( r, g, b, a ) \
{ \
GET_IMMEDIATE; \
GLuint count = IM->Count; \
GLfloat *color = IM->Attrib[VERT_ATTRIB_COLOR0][count]; \
IM->Flag[count] |= VERT_BIT_COLOR0; \
color[0] = r; \
color[1] = g; \
color[2] = b; \
color[3] = a; \
}
 
static void
_tnl_Color3f( GLfloat red, GLfloat green, GLfloat blue )
{
COLOR( red, green, blue, 1.0 );
}
 
static void
_tnl_Color3ub( GLubyte red, GLubyte green, GLubyte blue )
{
COLOR(UBYTE_TO_FLOAT(red),
UBYTE_TO_FLOAT(green),
UBYTE_TO_FLOAT(blue),
1.0);
}
 
static void
_tnl_Color4f( GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha )
{
COLOR( red, green, blue, alpha );
}
 
static void
_tnl_Color4ub( GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha )
{
COLOR(UBYTE_TO_FLOAT(red),
UBYTE_TO_FLOAT(green),
UBYTE_TO_FLOAT(blue),
UBYTE_TO_FLOAT(alpha));
}
 
static void
_tnl_Color3fv( const GLfloat *v )
{
COLOR( v[0], v[1], v[2], 1.0 );
}
 
static void
_tnl_Color3ubv( const GLubyte *v )
{
COLOR(UBYTE_TO_FLOAT(v[0]),
UBYTE_TO_FLOAT(v[1]),
UBYTE_TO_FLOAT(v[2]),
1.0 );
}
 
static void
_tnl_Color4fv( const GLfloat *v )
{
COLOR( v[0], v[1], v[2], v[3] );
}
 
static void
_tnl_Color4ubv( const GLubyte *v)
{
COLOR(UBYTE_TO_FLOAT(v[0]),
UBYTE_TO_FLOAT(v[1]),
UBYTE_TO_FLOAT(v[2]),
UBYTE_TO_FLOAT(v[3]));
}
 
 
 
 
#define SECONDARY_COLOR( r, g, b ) \
{ \
GLuint count; \
GET_IMMEDIATE; \
count = IM->Count; \
IM->Flag[count] |= VERT_BIT_COLOR1; \
IM->Attrib[VERT_ATTRIB_COLOR1][count][0] = r; \
IM->Attrib[VERT_ATTRIB_COLOR1][count][1] = g; \
IM->Attrib[VERT_ATTRIB_COLOR1][count][2] = b; \
}
 
static void
_tnl_SecondaryColor3fEXT( GLfloat red, GLfloat green, GLfloat blue )
{
SECONDARY_COLOR( red, green, blue );
}
 
static void
_tnl_SecondaryColor3ubEXT( GLubyte red, GLubyte green, GLubyte blue )
{
SECONDARY_COLOR(UBYTE_TO_FLOAT(red),
UBYTE_TO_FLOAT(green),
UBYTE_TO_FLOAT(blue));
}
 
static void
_tnl_SecondaryColor3fvEXT( const GLfloat *v )
{
SECONDARY_COLOR( v[0], v[1], v[2] );
}
 
static void
_tnl_SecondaryColor3ubvEXT( const GLubyte *v )
{
SECONDARY_COLOR(UBYTE_TO_FLOAT(v[0]),
UBYTE_TO_FLOAT(v[1]),
UBYTE_TO_FLOAT(v[2]));
}
 
 
static void
_tnl_EdgeFlag( GLboolean flag )
{
GLuint count;
GET_IMMEDIATE;
count = IM->Count;
IM->EdgeFlag[count] = flag;
IM->Flag[count] |= VERT_BIT_EDGEFLAG;
}
 
 
static void
_tnl_EdgeFlagv( const GLboolean *flag )
{
GLuint count;
GET_IMMEDIATE;
count = IM->Count;
IM->EdgeFlag[count] = *flag;
IM->Flag[count] |= VERT_BIT_EDGEFLAG;
}
 
 
static void
_tnl_FogCoordfEXT( GLfloat f )
{
GLuint count;
GET_IMMEDIATE;
count = IM->Count;
IM->Attrib[VERT_ATTRIB_FOG][count][0] = f; /*FogCoord[count] = f;*/
IM->Flag[count] |= VERT_BIT_FOG;
}
 
static void
_tnl_FogCoordfvEXT( const GLfloat *v )
{
GLuint count;
GET_IMMEDIATE;
count = IM->Count;
IM->Attrib[VERT_ATTRIB_FOG][count][0] = v[0]; /*FogCoord[count] = v[0];*/
IM->Flag[count] |= VERT_BIT_FOG;
}
 
 
static void
_tnl_Indexi( GLint c )
{
GLuint count;
GET_IMMEDIATE;
count = IM->Count;
IM->Index[count] = c;
IM->Flag[count] |= VERT_BIT_INDEX;
}
 
 
static void
_tnl_Indexiv( const GLint *c )
{
GLuint count;
GET_IMMEDIATE;
count = IM->Count;
IM->Index[count] = *c;
IM->Flag[count] |= VERT_BIT_INDEX;
}
 
 
#define NORMAL( x, y, z ) \
{ \
GLuint count; \
GLfloat *normal; \
GET_IMMEDIATE; \
count = IM->Count; \
IM->Flag[count] |= VERT_BIT_NORMAL; \
normal = IM->Attrib[VERT_ATTRIB_NORMAL][count]; \
ASSIGN_3V(normal, x,y,z); \
}
 
#if defined(USE_IEEE)
#define NORMALF( x, y, z ) \
{ \
GLuint count; \
fi_type *normal; \
GET_IMMEDIATE; \
count = IM->Count; \
IM->Flag[count] |= VERT_BIT_NORMAL; \
normal = (fi_type *)IM->Attrib[VERT_ATTRIB_NORMAL][count]; \
normal[0].i = ((fi_type *)&(x))->i; \
normal[1].i = ((fi_type *)&(y))->i; \
normal[2].i = ((fi_type *)&(z))->i; \
}
#else
#define NORMALF NORMAL
#endif
 
static void
_tnl_Normal3f( GLfloat nx, GLfloat ny, GLfloat nz )
{
NORMALF(nx, ny, nz);
}
 
 
static void
_tnl_Normal3fv( const GLfloat *v )
{
NORMALF( v[0], v[1], v[2] );
/* struct immediate *IM = (struct immediate *)(((GLcontext *) _glapi_Context)->swtnl_im); */
/* IM->Flag[IM->Count] = VERT_NORM; */
}
 
 
 
#define TEXCOORD1(s) \
{ \
GLuint count; \
GLfloat *tc; \
GET_IMMEDIATE; \
count = IM->Count; \
IM->Flag[count] |= VERT_BIT_TEX0; \
tc = IM->Attrib[VERT_ATTRIB_TEX0][count]; \
ASSIGN_4V(tc,s,0,0,1); \
}
 
#define TEXCOORD2(s, t) \
{ \
GLuint count; \
GLfloat *tc; \
GET_IMMEDIATE; \
count = IM->Count; \
IM->Flag[count] |= VERT_BIT_TEX0; \
tc = IM->Attrib[VERT_ATTRIB_TEX0][count]; \
ASSIGN_4V(tc, s, t, 0, 1); \
}
 
#define TEXCOORD3(s, t, u) \
{ \
GLuint count; \
GLfloat *tc; \
GET_IMMEDIATE; \
count = IM->Count; \
IM->Flag[count] |= VERT_BIT_TEX0; \
IM->TexSize |= TEX_0_SIZE_3; \
tc = IM->Attrib[VERT_ATTRIB_TEX0][count]; \
ASSIGN_4V(tc, s, t, u, 1); \
}
 
#define TEXCOORD4(s, t, u, v) \
{ \
GLuint count; \
GLfloat *tc; \
GET_IMMEDIATE; \
count = IM->Count; \
IM->Flag[count] |= VERT_BIT_TEX0; \
IM->TexSize |= TEX_0_SIZE_4; \
tc = IM->Attrib[VERT_ATTRIB_TEX0][count]; \
ASSIGN_4V(tc, s, t, u, v); \
}
 
#if defined(USE_IEEE)
#define TEXCOORD2F(s, t) \
{ \
GLuint count; \
fi_type *tc; \
GET_IMMEDIATE; \
count = IM->Count; \
IM->Flag[count] |= VERT_BIT_TEX0; \
tc = (fi_type *)IM->Attrib[VERT_ATTRIB_TEX0][count]; \
tc[0].i = ((fi_type *)&(s))->i; \
tc[1].i = ((fi_type *)&(t))->i; \
tc[2].i = 0; \
tc[3].i = IEEE_ONE; \
}
#else
#define TEXCOORD2F TEXCOORD2
#endif
 
static void
_tnl_TexCoord1f( GLfloat s )
{
TEXCOORD1(s);
}
 
 
static void
_tnl_TexCoord2f( GLfloat s, GLfloat t )
{
TEXCOORD2F(s, t);
}
 
 
static void
_tnl_TexCoord3f( GLfloat s, GLfloat t, GLfloat r )
{
TEXCOORD3(s, t, r);
}
 
static void
_tnl_TexCoord4f( GLfloat s, GLfloat t, GLfloat r, GLfloat q )
{
TEXCOORD4(s, t, r, q)
}
 
static void
_tnl_TexCoord1fv( const GLfloat *v )
{
TEXCOORD1(v[0]);
}
 
static void
_tnl_TexCoord2fv( const GLfloat *v )
{
TEXCOORD2F(v[0], v[1]);
}
 
static void
_tnl_TexCoord3fv( const GLfloat *v )
{
TEXCOORD3(v[0], v[1], v[2]);
}
 
static void
_tnl_TexCoord4fv( const GLfloat *v )
{
TEXCOORD4(v[0], v[1], v[2], v[3]);
}
 
 
 
/* KW: Run into bad problems in vertex copying if we don't fully pad
* the incoming vertices.
*/
#define VERTEX2(IM, x,y) \
{ \
GLuint count = IM->Count++; \
GLfloat *dest = IM->Attrib[VERT_ATTRIB_POS][count]; \
IM->Flag[count] |= VERT_BIT_POS; \
ASSIGN_4V(dest, x, y, 0, 1); \
/* ASSERT(IM->Flag[IM->Count]==0); */ \
if (count == IMM_MAXDATA - 1) \
_tnl_flush_immediate( NULL, IM ); \
}
 
#define VERTEX3(IM,x,y,z) \
{ \
GLuint count = IM->Count++; \
GLfloat *dest = IM->Attrib[VERT_ATTRIB_POS][count]; \
IM->Flag[count] |= VERT_BITS_OBJ_23; \
ASSIGN_4V(dest, x, y, z, 1); \
/* ASSERT(IM->Flag[IM->Count]==0); */ \
if (count == IMM_MAXDATA - 1) \
_tnl_flush_immediate( NULL, IM ); \
}
 
#define VERTEX4(IM, x,y,z,w) \
{ \
GLuint count = IM->Count++; \
GLfloat *dest = IM->Attrib[VERT_ATTRIB_POS][count]; \
IM->Flag[count] |= VERT_BITS_OBJ_234; \
ASSIGN_4V(dest, x, y, z, w); \
if (count == IMM_MAXDATA - 1) \
_tnl_flush_immediate( NULL, IM ); \
}
 
#if defined(USE_IEEE)
#define VERTEX2F(IM, x, y) \
{ \
GLuint count = IM->Count++; \
fi_type *dest = (fi_type *)IM->Attrib[VERT_ATTRIB_POS][count]; \
IM->Flag[count] |= VERT_BIT_POS; \
dest[0].i = ((fi_type *)&(x))->i; \
dest[1].i = ((fi_type *)&(y))->i; \
dest[2].i = 0; \
dest[3].i = IEEE_ONE; \
/* ASSERT(IM->Flag[IM->Count]==0); */ \
if (count == IMM_MAXDATA - 1) \
_tnl_flush_immediate( NULL, IM ); \
}
#else
#define VERTEX2F VERTEX2
#endif
 
#if defined(USE_IEEE)
#define VERTEX3F(IM, x, y, z) \
{ \
GLuint count = IM->Count++; \
fi_type *dest = (fi_type *)IM->Attrib[VERT_ATTRIB_POS][count]; \
IM->Flag[count] |= VERT_BITS_OBJ_23; \
dest[0].i = ((fi_type *)&(x))->i; \
dest[1].i = ((fi_type *)&(y))->i; \
dest[2].i = ((fi_type *)&(z))->i; \
dest[3].i = IEEE_ONE; \
/* ASSERT(IM->Flag[IM->Count]==0); */ \
if (count == IMM_MAXDATA - 1) \
_tnl_flush_immediate( NULL, IM ); \
}
#else
#define VERTEX3F VERTEX3
#endif
 
#if defined(USE_IEEE)
#define VERTEX4F(IM, x, y, z, w) \
{ \
GLuint count = IM->Count++; \
fi_type *dest = (fi_type *)IM->Attrib[VERT_ATTRIB_POS][count]; \
IM->Flag[count] |= VERT_BITS_OBJ_234; \
dest[0].i = ((fi_type *)&(x))->i; \
dest[1].i = ((fi_type *)&(y))->i; \
dest[2].i = ((fi_type *)&(z))->i; \
dest[3].i = ((fi_type *)&(w))->i; \
if (count == IMM_MAXDATA - 1) \
_tnl_flush_immediate( NULL, IM ); \
}
#else
#define VERTEX4F VERTEX4
#endif
 
 
 
static void
_tnl_Vertex2f( GLfloat x, GLfloat y )
{
GET_IMMEDIATE;
VERTEX2F( IM, x, y );
}
 
static void
_tnl_Vertex3f( GLfloat x, GLfloat y, GLfloat z )
{
GET_IMMEDIATE;
VERTEX3F( IM, x, y, z );
}
static void
_tnl_Vertex4f( GLfloat x, GLfloat y, GLfloat z, GLfloat w )
{
GET_IMMEDIATE;
VERTEX4F( IM, x, y, z, w );
}
 
static void
_tnl_Vertex2fv( const GLfloat *v )
{
GET_IMMEDIATE;
VERTEX2F( IM, v[0], v[1] );
}
 
static void
_tnl_Vertex3fv( const GLfloat *v )
{
GET_IMMEDIATE;
VERTEX3F( IM, v[0], v[1], v[2] );
}
 
static void
_tnl_Vertex4fv( const GLfloat *v )
{
GET_IMMEDIATE;
VERTEX4F( IM, v[0], v[1], v[2], v[3] );
}
 
 
 
 
/*
* GL_ARB_multitexture
*
* Note: the multitexture spec says that specifying an invalid target
* has undefined results and does not have to generate an error. Just
* don't crash. We no-op on invalid targets.
*/
 
#define MAX_TARGET (GL_TEXTURE0_ARB + MAX_TEXTURE_UNITS)
 
#define MULTI_TEXCOORD1(target, s) \
{ \
GET_IMMEDIATE; \
GLuint texunit = target - GL_TEXTURE0_ARB; \
if (texunit < IM->MaxTextureUnits) { \
GLuint count = IM->Count; \
GLfloat *tc = IM->Attrib[VERT_ATTRIB_TEX0 + texunit][count]; \
ASSIGN_4V(tc, s, 0.0F, 0.0F, 1.0F); \
IM->Flag[count] |= VERT_BIT_TEX(texunit); \
} \
}
 
#define MULTI_TEXCOORD2(target, s, t) \
{ \
GET_IMMEDIATE; \
GLuint texunit = target - GL_TEXTURE0_ARB; \
if (texunit < IM->MaxTextureUnits) { \
GLuint count = IM->Count; \
GLfloat *tc = IM->Attrib[VERT_ATTRIB_TEX0 + texunit][count]; \
ASSIGN_4V(tc, s, t, 0.0F, 1.0F); \
IM->Flag[count] |= VERT_BIT_TEX(texunit); \
} \
}
 
#define MULTI_TEXCOORD3(target, s, t, u) \
{ \
GET_IMMEDIATE; \
GLuint texunit = target - GL_TEXTURE0_ARB; \
if (texunit < IM->MaxTextureUnits) { \
GLuint count = IM->Count; \
GLfloat *tc = IM->Attrib[VERT_ATTRIB_TEX0 + texunit][count]; \
ASSIGN_4V(tc, s, t, u, 1.0F); \
IM->Flag[count] |= VERT_BIT_TEX(texunit); \
IM->TexSize |= TEX_SIZE_3(texunit); \
} \
}
 
#define MULTI_TEXCOORD4(target, s, t, u, v) \
{ \
GET_IMMEDIATE; \
GLuint texunit = target - GL_TEXTURE0_ARB; \
if (texunit < IM->MaxTextureUnits) { \
GLuint count = IM->Count; \
GLfloat *tc = IM->Attrib[VERT_ATTRIB_TEX0 + texunit][count]; \
ASSIGN_4V(tc, s, t, u, v); \
IM->Flag[count] |= VERT_BIT_TEX(texunit); \
IM->TexSize |= TEX_SIZE_4(texunit); \
} \
}
 
#if defined(USE_IEEE)
#define MULTI_TEXCOORD2F(target, s, t) \
{ \
GET_IMMEDIATE; \
GLuint texunit = target - GL_TEXTURE0_ARB; \
if (texunit < IM->MaxTextureUnits) { \
GLuint count = IM->Count; \
fi_type *tc = (fi_type *)IM->Attrib[VERT_ATTRIB_TEX0 + texunit][count];\
IM->Flag[count] |= VERT_BIT_TEX(texunit); \
tc[0].i = ((fi_type *)&(s))->i; \
tc[1].i = ((fi_type *)&(t))->i; \
tc[2].i = 0; \
tc[3].i = IEEE_ONE; \
} \
}
#else
#define MULTI_TEXCOORD2F MULTI_TEXCOORD2
#endif
 
static void
_tnl_MultiTexCoord1fARB(GLenum target, GLfloat s)
{
MULTI_TEXCOORD1( target, s );
}
 
static void
_tnl_MultiTexCoord1fvARB(GLenum target, const GLfloat *v)
{
MULTI_TEXCOORD1( target, v[0] );
}
 
static void
_tnl_MultiTexCoord2fARB(GLenum target, GLfloat s, GLfloat t)
{
MULTI_TEXCOORD2F( target, s, t );
}
 
static void
_tnl_MultiTexCoord2fvARB(GLenum target, const GLfloat *v)
{
MULTI_TEXCOORD2F( target, v[0], v[1] );
}
 
static void
_tnl_MultiTexCoord3fARB(GLenum target, GLfloat s, GLfloat t, GLfloat r)
{
MULTI_TEXCOORD3( target, s, t, r );
}
 
static void
_tnl_MultiTexCoord3fvARB(GLenum target, const GLfloat *v)
{
MULTI_TEXCOORD3( target, v[0], v[1], v[2] );
}
 
static void
_tnl_MultiTexCoord4fARB(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q)
{
MULTI_TEXCOORD4( target, s, t, r, q );
}
 
static void
_tnl_MultiTexCoord4fvARB(GLenum target, const GLfloat *v)
{
MULTI_TEXCOORD4( target, v[0], v[1], v[2], v[3] );
}
 
 
 
/* KW: Because the eval values don't become 'current', fixup will flow
* through these vertices, and then evaluation will write on top
* of the fixup results.
*
* Note: using Obj to hold eval coord data.
*/
#define EVALCOORD1(IM, x) \
{ \
GLuint count = IM->Count++; \
GLfloat *dest = IM->Attrib[VERT_ATTRIB_POS][count]; \
IM->Flag[count] |= VERT_BIT_EVAL_C1; \
ASSIGN_4V(dest, x, 0, 0, 1); \
if (count == IMM_MAXDATA-1) \
_tnl_flush_immediate( NULL, IM ); \
}
 
#define EVALCOORD2(IM, x, y) \
{ \
GLuint count = IM->Count++; \
GLfloat *dest = IM->Attrib[VERT_ATTRIB_POS][count]; \
IM->Flag[count] |= VERT_BIT_EVAL_C2; \
ASSIGN_4V(dest, x, y, 0, 1); \
if (count == IMM_MAXDATA-1) \
_tnl_flush_immediate( NULL, IM ); \
}
 
#define EVALPOINT1(IM, x) \
{ \
GLuint count = IM->Count++; \
GLfloat *dest = IM->Attrib[VERT_ATTRIB_POS][count]; \
IM->Flag[count] |= VERT_BIT_EVAL_P1; \
ASSIGN_4V(dest, x, 0, 0, 1); \
if (count == IMM_MAXDATA-1) \
_tnl_flush_immediate( NULL, IM ); \
}
 
#define EVALPOINT2(IM, x, y) \
{ \
GLuint count = IM->Count++; \
GLfloat *dest = IM->Attrib[VERT_ATTRIB_POS][count]; \
IM->Flag[count] |= VERT_BIT_EVAL_P2; \
ASSIGN_4V(dest, x, y, 0, 1); \
if (count == IMM_MAXDATA-1) \
_tnl_flush_immediate( NULL, IM ); \
}
 
static void
_tnl_EvalCoord1f( GLfloat u )
{
GET_IMMEDIATE;
EVALCOORD1( IM, u );
}
 
static void
_tnl_EvalCoord1fv( const GLfloat *u )
{
GET_IMMEDIATE;
EVALCOORD1( IM, (GLfloat) *u );
}
 
static void
_tnl_EvalCoord2f( GLfloat u, GLfloat v )
{
GET_IMMEDIATE;
EVALCOORD2( IM, u, v );
}
 
static void
_tnl_EvalCoord2fv( const GLfloat *u )
{
GET_IMMEDIATE;
EVALCOORD2( IM, u[0], u[1] );
}
 
 
static void
_tnl_EvalPoint1( GLint i )
{
GET_IMMEDIATE;
EVALPOINT1( IM, (GLfloat) i );
}
 
 
static void
_tnl_EvalPoint2( GLint i, GLint j )
{
GET_IMMEDIATE;
EVALPOINT2( IM, (GLfloat) i, (GLfloat) j );
}
 
 
/* Need to use the default array-elt outside begin/end for strict
* conformance.
*/
#define ARRAY_ELT( IM, i ) \
{ \
GLuint count = IM->Count; \
IM->Elt[count] = i; \
IM->Flag[count] &= IM->ArrayEltFlags; \
IM->Flag[count] |= VERT_BIT_ELT; \
IM->FlushElt = IM->ArrayEltFlush; \
IM->Count += IM->ArrayEltIncr; \
if (IM->Count == IMM_MAXDATA) \
_tnl_flush_immediate( NULL, IM ); \
}
 
 
static void
_tnl_ArrayElement( GLint i )
{
GET_IMMEDIATE;
ARRAY_ELT( IM, i );
}
 
 
/* Internal functions. These are safe to use providing either:
*
* - It is determined that a display list is not being compiled, or
* if so that these commands won't be compiled into the list (see
* t_eval.c for an example).
*
* - _tnl_hard_begin() is used instead of _tnl_[bB]egin, and tested
* for a GL_TRUE return value. See _tnl_Rectf, below.
*/
void
_tnl_eval_coord1f( GLcontext *CC, GLfloat u )
{
struct immediate *i = TNL_CURRENT_IM(CC);
EVALCOORD1( i, u );
}
 
void
_tnl_eval_coord2f( GLcontext *CC, GLfloat u, GLfloat v )
{
struct immediate *i = TNL_CURRENT_IM(CC);
EVALCOORD2( i, u, v );
}
 
 
 
 
/*
* NV_vertex_program
*/
 
static void
_tnl_VertexAttrib4fNV( GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w )
{
if (index < 16) {
GET_IMMEDIATE;
const GLuint count = IM->Count;
GLfloat *attrib = IM->Attrib[index][count];
ASSIGN_4V(attrib, x, y, z, w);
IM->Flag[count] |= (1 << index);
if (index == 0) {
IM->Count++;
if (count == IMM_MAXDATA - 1)
_tnl_flush_immediate( NULL, IM );
}
}
else {
GET_CURRENT_CONTEXT(ctx);
_mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribNV(index > 15)");
}
}
 
static void
_tnl_VertexAttrib4fvNV( GLuint index, const GLfloat *v )
{
if (index < 16) {
GET_IMMEDIATE;
const GLuint count = IM->Count;
GLfloat *attrib = IM->Attrib[index][count];
COPY_4V(attrib, v);
IM->Flag[count] |= (1 << index);
if (index == 0) {
IM->Count++;
if (count == IMM_MAXDATA - 1)
_tnl_flush_immediate( NULL, IM );
}
}
else {
GET_CURRENT_CONTEXT(ctx);
_mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribNV(index > 15)");
}
}
 
 
/* Execute a glRectf() function. _tnl_hard_begin() ensures the check
* on outside_begin_end is executed even in compiled lists. These
* vertices can now participate in the same immediate as regular ones,
* even in most display lists.
*/
static void
_tnl_Rectf( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 )
{
GET_CURRENT_CONTEXT(ctx);
 
if (_tnl_hard_begin( ctx, GL_QUADS )) {
glVertex2f( x1, y1 );
glVertex2f( x2, y1 );
glVertex2f( x2, y2 );
glVertex2f( x1, y2 );
glEnd();
}
}
 
static void
_tnl_Materialfv( GLenum face, GLenum pname, const GLfloat *params )
{
GET_CURRENT_CONTEXT(ctx);
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct immediate *IM = TNL_CURRENT_IM(ctx);
GLuint count = IM->Count;
struct gl_material *mat;
GLuint bitmask = _mesa_material_bitmask(ctx, face, pname, ~0, "Materialfv");
 
if (bitmask == 0)
return;
if (MESA_VERBOSE & VERBOSE_API)
_mesa_debug(ctx, "_tnl_Materialfv\n");
 
if (tnl->IsolateMaterials &&
!(IM->BeginState & VERT_BEGIN_1)) /* heuristic */
{
_tnl_flush_immediate( ctx, IM );
IM = TNL_CURRENT_IM(ctx);
count = IM->Count;
}
 
if (!(IM->Flag[count] & VERT_BIT_MATERIAL)) {
if (!IM->Material) {
IM->Material = (struct gl_material (*)[2])
MALLOC( sizeof(struct gl_material) * IMM_SIZE * 2 );
IM->MaterialMask = (GLuint *) MALLOC( sizeof(GLuint) * IMM_SIZE );
IM->MaterialMask[IM->LastMaterial] = 0;
}
else if (IM->MaterialOrMask & ~bitmask) {
_mesa_copy_material_pairs( IM->Material[count],
IM->Material[IM->LastMaterial],
IM->MaterialOrMask & ~bitmask );
}
 
IM->Flag[count] |= VERT_BIT_MATERIAL;
IM->MaterialMask[count] = 0;
IM->MaterialAndMask &= IM->MaterialMask[IM->LastMaterial];
IM->LastMaterial = count;
}
 
IM->MaterialOrMask |= bitmask;
IM->MaterialMask[count] |= bitmask;
mat = IM->Material[count];
 
if (bitmask & FRONT_AMBIENT_BIT) {
COPY_4FV( mat[0].Ambient, params );
}
if (bitmask & BACK_AMBIENT_BIT) {
COPY_4FV( mat[1].Ambient, params );
}
if (bitmask & FRONT_DIFFUSE_BIT) {
COPY_4FV( mat[0].Diffuse, params );
}
if (bitmask & BACK_DIFFUSE_BIT) {
COPY_4FV( mat[1].Diffuse, params );
}
if (bitmask & FRONT_SPECULAR_BIT) {
COPY_4FV( mat[0].Specular, params );
}
if (bitmask & BACK_SPECULAR_BIT) {
COPY_4FV( mat[1].Specular, params );
}
if (bitmask & FRONT_EMISSION_BIT) {
COPY_4FV( mat[0].Emission, params );
}
if (bitmask & BACK_EMISSION_BIT) {
COPY_4FV( mat[1].Emission, params );
}
if (bitmask & FRONT_SHININESS_BIT) {
GLfloat shininess = CLAMP( params[0], 0.0F, 128.0F );
mat[0].Shininess = shininess;
}
if (bitmask & BACK_SHININESS_BIT) {
GLfloat shininess = CLAMP( params[0], 0.0F, 128.0F );
mat[1].Shininess = shininess;
}
if (bitmask & FRONT_INDEXES_BIT) {
mat[0].AmbientIndex = params[0];
mat[0].DiffuseIndex = params[1];
mat[0].SpecularIndex = params[2];
}
if (bitmask & BACK_INDEXES_BIT) {
mat[1].AmbientIndex = params[0];
mat[1].DiffuseIndex = params[1];
mat[1].SpecularIndex = params[2];
}
 
if (tnl->IsolateMaterials &&
!(IM->BeginState & VERT_BEGIN_1)) /* heuristic */
{
_tnl_flush_immediate( ctx, IM );
}
}
 
void _tnl_imm_vtxfmt_init( GLcontext *ctx )
{
GLvertexformat *vfmt = &(TNL_CONTEXT(ctx)->vtxfmt);
 
/* All begin/end operations are handled by this vertex format:
*/
vfmt->ArrayElement = _tnl_ArrayElement;
vfmt->Begin = _tnl_Begin;
vfmt->Color3f = _tnl_Color3f;
vfmt->Color3fv = _tnl_Color3fv;
vfmt->Color3ub = _tnl_Color3ub;
vfmt->Color3ubv = _tnl_Color3ubv;
vfmt->Color4f = _tnl_Color4f;
vfmt->Color4fv = _tnl_Color4fv;
vfmt->Color4ub = _tnl_Color4ub;
vfmt->Color4ubv = _tnl_Color4ubv;
vfmt->EdgeFlag = _tnl_EdgeFlag;
vfmt->EdgeFlagv = _tnl_EdgeFlagv;
vfmt->End = _tnl_End;
vfmt->EvalCoord1f = _tnl_EvalCoord1f;
vfmt->EvalCoord1fv = _tnl_EvalCoord1fv;
vfmt->EvalCoord2f = _tnl_EvalCoord2f;
vfmt->EvalCoord2fv = _tnl_EvalCoord2fv;
vfmt->EvalPoint1 = _tnl_EvalPoint1;
vfmt->EvalPoint2 = _tnl_EvalPoint2;
vfmt->FogCoordfEXT = _tnl_FogCoordfEXT;
vfmt->FogCoordfvEXT = _tnl_FogCoordfvEXT;
vfmt->Indexi = _tnl_Indexi;
vfmt->Indexiv = _tnl_Indexiv;
vfmt->Materialfv = _tnl_Materialfv;
vfmt->MultiTexCoord1fARB = _tnl_MultiTexCoord1fARB;
vfmt->MultiTexCoord1fvARB = _tnl_MultiTexCoord1fvARB;
vfmt->MultiTexCoord2fARB = _tnl_MultiTexCoord2fARB;
vfmt->MultiTexCoord2fvARB = _tnl_MultiTexCoord2fvARB;
vfmt->MultiTexCoord3fARB = _tnl_MultiTexCoord3fARB;
vfmt->MultiTexCoord3fvARB = _tnl_MultiTexCoord3fvARB;
vfmt->MultiTexCoord4fARB = _tnl_MultiTexCoord4fARB;
vfmt->MultiTexCoord4fvARB = _tnl_MultiTexCoord4fvARB;
vfmt->Normal3f = _tnl_Normal3f;
vfmt->Normal3fv = _tnl_Normal3fv;
vfmt->SecondaryColor3fEXT = _tnl_SecondaryColor3fEXT;
vfmt->SecondaryColor3fvEXT = _tnl_SecondaryColor3fvEXT;
vfmt->SecondaryColor3ubEXT = _tnl_SecondaryColor3ubEXT;
vfmt->SecondaryColor3ubvEXT = _tnl_SecondaryColor3ubvEXT;
vfmt->TexCoord1f = _tnl_TexCoord1f;
vfmt->TexCoord1fv = _tnl_TexCoord1fv;
vfmt->TexCoord2f = _tnl_TexCoord2f;
vfmt->TexCoord2fv = _tnl_TexCoord2fv;
vfmt->TexCoord3f = _tnl_TexCoord3f;
vfmt->TexCoord3fv = _tnl_TexCoord3fv;
vfmt->TexCoord4f = _tnl_TexCoord4f;
vfmt->TexCoord4fv = _tnl_TexCoord4fv;
vfmt->Vertex2f = _tnl_Vertex2f;
vfmt->Vertex2fv = _tnl_Vertex2fv;
vfmt->Vertex3f = _tnl_Vertex3f;
vfmt->Vertex3fv = _tnl_Vertex3fv;
vfmt->Vertex4f = _tnl_Vertex4f;
vfmt->Vertex4fv = _tnl_Vertex4fv;
vfmt->VertexAttrib4fNV = _tnl_VertexAttrib4fNV;
vfmt->VertexAttrib4fvNV = _tnl_VertexAttrib4fvNV;
 
/* Outside begin/end functions (from t_varray.c, t_eval.c, ...):
*/
vfmt->Rectf = _tnl_Rectf;
 
/* Just use the core function:
*/
vfmt->CallList = _mesa_CallList;
 
vfmt->prefer_float_colors = GL_FALSE;
}
/shark/trunk/ports/mesa/src/tnl/t_array_import.h
0,0 → 1,37
/* $Id: t_array_import.h,v 1.1 2003-02-28 11:48:06 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
#ifndef _T_ARRAY_IMPORT_H
#define _T_ARRAY_IMPORT_H
 
#include "mtypes.h"
#include "t_context.h"
 
extern void _tnl_vb_bind_arrays( GLcontext *ctx, GLint start, GLsizei count );
 
extern void _tnl_array_import_init( GLcontext *ctx );
 
#endif
/shark/trunk/ports/mesa/src/tnl/tnl.h
0,0 → 1,78
/* $Id: tnl.h,v 1.1 2003-02-28 11:48:08 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
#ifndef _TNL_H
#define _TNL_H
 
#include "mtypes.h"
 
 
 
/* These are the public-access functions exported from tnl. (A few
* more are currently hooked into dispatch directly by the module
* itself.)
*/
extern GLboolean
_tnl_CreateContext( GLcontext *ctx );
 
extern void
_tnl_DestroyContext( GLcontext *ctx );
 
extern void
_tnl_InvalidateState( GLcontext *ctx, GLuint new_state );
 
/* Functions to revive the tnl module after being unhooked from
* dispatch and/or driver callbacks.
*/
 
/* Restore just the ctx->Exec table:
*/
extern void
_tnl_wakeup_exec( GLcontext *ctx );
 
/* Restore both ctx->Exec and ctx->Save:
*/
extern void
_tnl_wakeup_save_exec( GLcontext *ctx );
 
/* Driver configuration options:
*/
extern void
_tnl_need_projected_coords( GLcontext *ctx, GLboolean flag );
 
extern void
_tnl_need_dlist_loopback( GLcontext *ctx, GLboolean flag );
 
extern void
_tnl_need_dlist_norm_lengths( GLcontext *ctx, GLboolean flag );
 
extern void
_tnl_isolate_materials( GLcontext *ctx, GLboolean flag );
 
#endif
/shark/trunk/ports/mesa/src/tnl/t_vtx_api.h
0,0 → 1,234
/* $XFree86$ */
/**************************************************************************
 
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
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
TUNGSTEN GRAPHICS 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 __RADEON_VTXFMT_H__
#define __RADEON_VTXFMT_H__
 
#ifdef GLX_DIRECT_RENDERING
 
#include "_tnl__context.h"
 
extern void _tnl_UpdateVtxfmt( GLcontext *ctx );
extern void _tnl_InitVtxfmt( GLcontext *ctx );
extern void _tnl_InvalidateVtxfmt( GLcontext *ctx );
extern void _tnl_DestroyVtxfmt( GLcontext *ctx );
 
typedef void (*p4f)( GLfloat, GLfloat, GLfloat, GLfloat );
typedef void (*p3f)( GLfloat, GLfloat, GLfloat );
typedef void (*p2f)( GLfloat, GLfloat );
typedef void (*p1f)( GLfloat );
typedef void (*pe2f)( GLenum, GLfloat, GLfloat );
typedef void (*pe1f)( GLenum, GLfloat );
typedef void (*p4ub)( GLubyte, GLubyte, GLubyte, GLubyte );
typedef void (*p3ub)( GLubyte, GLubyte, GLubyte );
typedef void (*pfv)( const GLfloat * );
typedef void (*pefv)( GLenum, const GLfloat * );
typedef void (*pubv)( const GLubyte * );
 
/* Want to keep a cache of these around. Each is parameterized by
* only a single value which has only a small range. Only expect a
* few, so just rescan the list each time?
*/
struct dynfn {
struct dynfn *next, *prev;
int key;
char *code;
};
 
struct dfn_lists {
struct dynfn Vertex2f;
struct dynfn Vertex2fv;
struct dynfn Vertex3f;
struct dynfn Vertex3fv;
struct dynfn Color4ub;
struct dynfn Color4ubv;
struct dynfn Color3ub;
struct dynfn Color3ubv;
struct dynfn Color4f;
struct dynfn Color4fv;
struct dynfn Color3f;
struct dynfn Color3fv;
struct dynfn SecondaryColor3ubEXT;
struct dynfn SecondaryColor3ubvEXT;
struct dynfn SecondaryColor3fEXT;
struct dynfn SecondaryColor3fvEXT;
struct dynfn Normal3f;
struct dynfn Normal3fv;
struct dynfn TexCoord2f;
struct dynfn TexCoord2fv;
struct dynfn TexCoord1f;
struct dynfn TexCoord1fv;
struct dynfn MultiTexCoord2fARB;
struct dynfn MultiTexCoord2fvARB;
struct dynfn MultiTexCoord1fARB;
struct dynfn MultiTexCoord1fvARB;
};
 
struct _vb;
 
struct dfn_generators {
struct dynfn *(*Vertex2f)( struct _vb *, int );
struct dynfn *(*Vertex2fv)( struct _vb *, int );
struct dynfn *(*Vertex3f)( struct _vb *, int );
struct dynfn *(*Vertex3fv)( struct _vb *, int );
struct dynfn *(*Color4ub)( struct _vb *, int );
struct dynfn *(*Color4ubv)( struct _vb *, int );
struct dynfn *(*Color3ub)( struct _vb *, int );
struct dynfn *(*Color3ubv)( struct _vb *, int );
struct dynfn *(*Color4f)( struct _vb *, int );
struct dynfn *(*Color4fv)( struct _vb *, int );
struct dynfn *(*Color3f)( struct _vb *, int );
struct dynfn *(*Color3fv)( struct _vb *, int );
struct dynfn *(*SecondaryColor3ubEXT)( struct _vb *, int );
struct dynfn *(*SecondaryColor3ubvEXT)( struct _vb *, int );
struct dynfn *(*SecondaryColor3fEXT)( struct _vb *, int );
struct dynfn *(*SecondaryColor3fvEXT)( struct _vb *, int );
struct dynfn *(*Normal3f)( struct _vb *, int );
struct dynfn *(*Normal3fv)( struct _vb *, int );
struct dynfn *(*TexCoord2f)( struct _vb *, int );
struct dynfn *(*TexCoord2fv)( struct _vb *, int );
struct dynfn *(*TexCoord1f)( struct _vb *, int );
struct dynfn *(*TexCoord1fv)( struct _vb *, int );
struct dynfn *(*MultiTexCoord2fARB)( struct _vb *, int );
struct dynfn *(*MultiTexCoord2fvARB)( struct _vb *, int );
struct dynfn *(*MultiTexCoord1fARB)( struct _vb *, int );
struct dynfn *(*MultiTexCoord1fvARB)( struct _vb *, int );
};
 
struct prim {
GLuint start;
GLuint end;
GLuint prim;
};
 
#define _TNL__MAX_PRIMS 64
 
 
 
struct tnl_vbinfo {
/* Keep these first: referenced from codegen templates:
*/
GLint counter;
GLint *dmaptr;
void (*notify)( void );
union { float f; int i; GLubyte ub4[4]; } vertex[16*4];
 
GLfloat *attrptr[16];
GLuint size[16];
 
GLenum *prim; /* &ctx->Driver.CurrentExecPrimitive */
GLuint primflags;
 
GLboolean installed;
GLboolean recheck;
 
GLint vertex_size;
GLint initial_counter;
GLint nrverts;
GLuint vertex_format;
 
GLuint installed_vertex_format;
 
struct prim primlist[RADEON_MAX_PRIMS];
int nrprims;
 
struct dfn_lists dfn_cache;
struct dfn_generators codegen;
GLvertexformat vtxfmt;
};
 
 
extern void _tnl_InitVtxfmtChoosers( GLvertexformat *vfmt );
 
 
#define FIXUP( CODE, OFFSET, CHECKVAL, NEWVAL ) \
do { \
int *icode = (int *)(CODE+OFFSET); \
assert (*icode == CHECKVAL); \
*icode = (int)NEWVAL; \
} while (0)
 
 
/* Useful for figuring out the offsets:
*/
#define FIXUP2( CODE, OFFSET, CHECKVAL, NEWVAL ) \
do { \
while (*(int *)(CODE+OFFSET) != CHECKVAL) OFFSET++; \
fprintf(stderr, "%s/%d CVAL %x OFFSET %d\n", __FUNCTION__, \
__LINE__, CHECKVAL, OFFSET); \
*(int *)(CODE+OFFSET) = (int)NEWVAL; \
OFFSET += 4; \
} while (0)
 
/*
*/
void _tnl_InitCodegen( struct dfn_generators *gen );
void _tnl_InitX86Codegen( struct dfn_generators *gen );
void _tnl_InitSSECodegen( struct dfn_generators *gen );
 
void _tnl_copy_to_current( GLcontext *ctx );
 
 
/* Defined in tnl_vtxfmt_c.c.
*/
struct dynfn *tnl_makeX86Vertex2f( TNLcontext *, int );
struct dynfn *tnl_makeX86Vertex2fv( TNLcontext *, int );
struct dynfn *tnl_makeX86Vertex3f( TNLcontext *, int );
struct dynfn *tnl_makeX86Vertex3fv( TNLcontext *, int );
struct dynfn *tnl_makeX86Color4ub( TNLcontext *, int );
struct dynfn *tnl_makeX86Color4ubv( TNLcontext *, int );
struct dynfn *tnl_makeX86Color3ub( TNLcontext *, int );
struct dynfn *tnl_makeX86Color3ubv( TNLcontext *, int );
struct dynfn *tnl_makeX86Color4f( TNLcontext *, int );
struct dynfn *tnl_makeX86Color4fv( TNLcontext *, int );
struct dynfn *tnl_makeX86Color3f( TNLcontext *, int );
struct dynfn *tnl_makeX86Color3fv( TNLcontext *, int );
struct dynfn *tnl_makeX86SecondaryColor3ubEXT( TNLcontext *, int );
struct dynfn *tnl_makeX86SecondaryColor3ubvEXT( TNLcontext *, int );
struct dynfn *tnl_makeX86SecondaryColor3fEXT( TNLcontext *, int );
struct dynfn *tnl_makeX86SecondaryColor3fvEXT( TNLcontext *, int );
struct dynfn *tnl_makeX86Normal3f( TNLcontext *, int );
struct dynfn *tnl_makeX86Normal3fv( TNLcontext *, int );
struct dynfn *tnl_makeX86TexCoord2f( TNLcontext *, int );
struct dynfn *tnl_makeX86TexCoord2fv( TNLcontext *, int );
struct dynfn *tnl_makeX86TexCoord1f( TNLcontext *, int );
struct dynfn *tnl_makeX86TexCoord1fv( TNLcontext *, int );
struct dynfn *tnl_makeX86MultiTexCoord2fARB( TNLcontext *, int );
struct dynfn *tnl_makeX86MultiTexCoord2fvARB( TNLcontext *, int );
struct dynfn *tnl_makeX86MultiTexCoord1fARB( TNLcontext *, int );
struct dynfn *tnl_makeX86MultiTexCoord1fvARB( TNLcontext *, int );
 
 
#endif
#endif
/shark/trunk/ports/mesa/src/tnl/t_imm_api.h
0,0 → 1,57
/* $Id: t_imm_api.h,v 1.1 2003-02-28 11:48:06 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
 
#ifndef _T_VTXFMT_H
#define _T_VTXFMT_H
 
#include "mtypes.h"
#include "t_context.h"
 
 
extern void _tnl_save_Begin( GLenum mode );
extern void _tnl_Begin( GLenum mode );
 
extern void _tnl_Begin( GLenum mode );
 
extern void _tnl_End(void);
 
 
/* TNL-private internal functions for building higher-level operations:
*/
extern GLboolean _tnl_hard_begin( GLcontext *ctx, GLenum p );
extern void _tnl_end( GLcontext *ctx );
extern void _tnl_vertex2f( GLcontext *ctx, GLfloat x, GLfloat y );
extern void _tnl_eval_coord1f( GLcontext *CC, GLfloat u );
extern void _tnl_eval_coord2f( GLcontext *CC, GLfloat u, GLfloat v );
extern void _tnl_array_element( GLcontext *CC, GLint i );
 
/* Initialize our part of the vtxfmt struct:
*/
extern void _tnl_imm_vtxfmt_init( GLcontext *ctx );
 
 
#endif
/shark/trunk/ports/mesa/src/tnl/t_imm_dlist.c
0,0 → 1,656
/* $Id: t_imm_dlist.c,v 1.1 2003-02-28 11:48:06 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
 
#include "glheader.h"
#include "context.h"
#include "dlist.h"
#include "debug.h"
#include "mmath.h"
#include "imports.h"
#include "state.h"
 
#include "t_context.h"
#include "t_imm_api.h"
#include "t_imm_elt.h"
#include "t_imm_alloc.h"
#include "t_imm_dlist.h"
#include "t_imm_debug.h"
#include "t_imm_exec.h"
#include "t_imm_fixup.h"
#include "t_pipeline.h"
 
typedef struct {
struct immediate *IM;
GLuint Start;
GLuint Count;
GLuint BeginState;
GLuint SavedBeginState;
GLuint OrFlag;
GLuint AndFlag;
GLuint TexSize;
GLuint LastData;
GLuint LastPrimitive;
GLuint LastMaterial;
GLuint MaterialOrMask;
GLuint MaterialAndMask;
} TNLvertexcassette;
 
static void execute_compiled_cassette( GLcontext *ctx, void *data );
static void loopback_compiled_cassette( GLcontext *ctx, struct immediate *IM );
 
 
static void build_normal_lengths( struct immediate *IM )
{
GLuint i;
GLfloat len;
GLfloat (*data)[4] = IM->Attrib[VERT_ATTRIB_NORMAL] + IM->Start;
GLfloat *dest = IM->NormalLengthPtr;
GLuint *flags = IM->Flag + IM->Start;
GLuint count = IM->Count - IM->Start;
 
if (!dest) {
dest = IM->NormalLengthPtr = (GLfloat *) ALIGN_MALLOC( IMM_SIZE*sizeof(GLfloat), 32 );
if (!dest) return;
}
dest += IM->Start;
 
len = (GLfloat) LEN_3FV( data[0] );
if (len > 0.0F) len = 1.0F / len;
for (i = 0 ; i < count ; ) {
dest[i] = len;
if (flags[++i] & VERT_BIT_NORMAL) {
len = (GLfloat) LEN_3FV( data[i] );
if (len > 0.0F) len = 1.0F / len;
}
}
}
 
static void fixup_normal_lengths( struct immediate *IM )
{
GLuint i;
GLfloat len = 1.0F; /* just to silence warnings */
GLfloat (*data)[4] = IM->Attrib[VERT_ATTRIB_NORMAL];
GLfloat *dest = IM->NormalLengthPtr;
GLuint *flags = IM->Flag;
 
for (i = IM->CopyStart ; i <= IM->Start ; i++) {
len = (GLfloat) LEN_3FV( data[i] );
if (len > 0.0F) len = 1.0F / len;
dest[i] = len;
}
 
if (i < IM->Count) {
while (!(flags[i] & (VERT_BIT_NORMAL|VERT_BIT_END_VB))) {
dest[i] = len;
i++;
}
}
}
 
 
 
/* Insert the active immediate struct onto the display list currently
* being built.
*/
void
_tnl_compile_cassette( GLcontext *ctx, struct immediate *IM )
{
struct immediate *im = TNL_CURRENT_IM(ctx);
TNLcontext *tnl = TNL_CONTEXT(ctx);
TNLvertexcassette *node;
GLuint new_beginstate;
 
if (MESA_VERBOSE & VERBOSE_DISPLAY_LIST)
_mesa_debug(ctx, "_tnl_compiled_cassette IM: %d\n", IM->id);
 
if (IM->FlushElt) {
ASSERT (IM->FlushElt == FLUSH_ELT_LAZY);
_tnl_translate_array_elts( ctx, IM, IM->Start, IM->Count );
}
 
_tnl_compute_orflag( IM, IM->Start );
 
/* Need to clear this flag, or fixup gets confused. (The
* array-elements have been translated away by now, so it's ok to
* remove it.)
*/
IM->OrFlag &= ~VERT_BIT_ELT;
IM->AndFlag &= ~VERT_BIT_ELT;
 
_tnl_fixup_input( ctx, IM );
 
node = (TNLvertexcassette *)
_mesa_alloc_instruction(ctx,
tnl->opcode_vertex_cassette,
sizeof(TNLvertexcassette));
if (!node)
return;
 
node->IM = im; im->ref_count++;
node->Start = im->Start;
node->Count = im->Count;
node->BeginState = im->BeginState;
node->SavedBeginState = im->SavedBeginState;
node->OrFlag = im->OrFlag;
node->TexSize = im->TexSize;
node->AndFlag = im->AndFlag;
node->LastData = im->LastData;
node->LastPrimitive = im->LastPrimitive;
node->LastMaterial = im->LastMaterial;
node->MaterialOrMask = im->MaterialOrMask;
node->MaterialAndMask = im->MaterialAndMask;
if (tnl->CalcDListNormalLengths) {
build_normal_lengths( im );
}
 
if (ctx->ExecuteFlag) {
execute_compiled_cassette( ctx, (void *)node );
}
 
/* Discard any errors raised in the last cassette.
*/
new_beginstate = node->BeginState & (VERT_BEGIN_0|VERT_BEGIN_1);
 
/* Decide whether this immediate struct is full, or can be used for
* the next batch of vertices as well.
*/
if (im->Count > IMM_MAXDATA - 16) {
/* Call it full...
*/
struct immediate *new_im = _tnl_alloc_immediate(ctx);
new_im->ref_count++;
im->ref_count--; /* remove CURRENT_IM reference */
ASSERT(im->ref_count > 0); /* it is compiled into a display list */
SET_IMMEDIATE( ctx, new_im );
_tnl_reset_compile_input( ctx, IMM_MAX_COPIED_VERTS,
new_beginstate, node->SavedBeginState );
} else {
/* Still some room in the current immediate.
*/
_tnl_reset_compile_input( ctx, im->Count+1+IMM_MAX_COPIED_VERTS,
new_beginstate, node->SavedBeginState);
}
}
 
 
static void fixup_compiled_primitives( GLcontext *ctx, struct immediate *IM )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
 
/* Can potentially overwrite primitive details - need to save the
* first slot:
*/
tnl->DlistPrimitive = IM->Primitive[IM->Start];
tnl->DlistPrimitiveLength = IM->PrimitiveLength[IM->Start];
tnl->DlistLastPrimitive = IM->LastPrimitive;
 
/* The first primitive may be different from what was recorded in
* the immediate struct. Consider an immediate that starts with a
* glBegin, compiled in a display list, which is called from within
* an existing Begin/End object.
*/
if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) {
GLuint i;
 
if (IM->BeginState & VERT_ERROR_1)
_mesa_error( ctx, GL_INVALID_OPERATION, "glBegin/glEnd");
 
for (i = IM->Start ; i <= IM->Count ; i += IM->PrimitiveLength[i])
if (IM->Flag[i] & (VERT_BIT_BEGIN|VERT_BIT_END_VB))
break;
 
/* Would like to just ignore vertices upto this point. Can't
* set copystart because it might skip materials?
*/
ASSERT(IM->Start == IM->CopyStart);
if (i > IM->CopyStart || !(IM->Flag[IM->Start] & VERT_BIT_BEGIN)) {
IM->Primitive[IM->CopyStart] = GL_POLYGON+1;
IM->PrimitiveLength[IM->CopyStart] = i - IM->CopyStart;
if (IM->Flag[i] & VERT_BIT_END_VB) {
IM->Primitive[IM->CopyStart] |= PRIM_LAST;
IM->LastPrimitive = IM->CopyStart;
}
}
} else {
GLuint i;
 
if (IM->BeginState & VERT_ERROR_0)
_mesa_error( ctx, GL_INVALID_OPERATION, "glBegin/glEnd");
 
if (IM->CopyStart == IM->Start &&
IM->Flag[IM->Start] & (VERT_BIT_END | VERT_BIT_END_VB))
{
}
else
{
IM->Primitive[IM->CopyStart] = ctx->Driver.CurrentExecPrimitive;
if (tnl->ExecParity)
IM->Primitive[IM->CopyStart] |= PRIM_PARITY;
 
/* one of these should be true, else we'll be in an infinite loop
*/
ASSERT(IM->PrimitiveLength[IM->Start] > 0 ||
IM->Flag[IM->Start] & (VERT_BIT_END | VERT_BIT_END_VB));
 
for (i = IM->Start ; i <= IM->Count ; i += IM->PrimitiveLength[i])
if (IM->Flag[i] & (VERT_BIT_END | VERT_BIT_END_VB)) {
IM->PrimitiveLength[IM->CopyStart] = i - IM->CopyStart;
if (IM->Flag[i] & VERT_BIT_END_VB) {
IM->Primitive[IM->CopyStart] |= PRIM_LAST;
IM->LastPrimitive = IM->CopyStart;
}
if (IM->Flag[i] & VERT_BIT_END) {
IM->Primitive[IM->CopyStart] |= PRIM_END;
}
break;
}
}
}
}
 
/* Undo any changes potentially made to the immediate in the range
* IM->Start..IM->Count above.
*/
static void restore_compiled_primitives( GLcontext *ctx, struct immediate *IM )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
IM->Primitive[IM->Start] = tnl->DlistPrimitive;
IM->PrimitiveLength[IM->Start] = tnl->DlistPrimitiveLength;
}
 
 
 
static void
execute_compiled_cassette( GLcontext *ctx, void *data )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
TNLvertexcassette *node = (TNLvertexcassette *)data;
struct immediate *IM = node->IM;
 
/* _mesa_debug("%s\n", __FUNCTION__); */
 
IM->Start = node->Start;
IM->CopyStart = node->Start;
IM->Count = node->Count;
IM->BeginState = node->BeginState;
IM->SavedBeginState = node->SavedBeginState;
IM->OrFlag = node->OrFlag;
IM->TexSize = node->TexSize;
IM->AndFlag = node->AndFlag;
IM->LastData = node->LastData;
IM->LastPrimitive = node->LastPrimitive;
IM->LastMaterial = node->LastMaterial;
IM->MaterialOrMask = node->MaterialOrMask;
IM->MaterialAndMask = node->MaterialAndMask;
 
if ((MESA_VERBOSE & VERBOSE_DISPLAY_LIST) &&
(MESA_VERBOSE & VERBOSE_IMMEDIATE))
_tnl_print_cassette( IM );
 
if (MESA_VERBOSE & VERBOSE_DISPLAY_LIST) {
_mesa_debug(ctx, "Run cassette %d, rows %d..%d, beginstate %x ",
IM->id, IM->Start, IM->Count, IM->BeginState);
_tnl_print_vert_flags("orflag", IM->OrFlag);
}
 
 
/* Need to respect 'HardBeginEnd' even if the commands are looped
* back to a driver tnl module.
*/
if (IM->SavedBeginState) {
if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1)
tnl->ReplayHardBeginEnd = 1;
if (!tnl->ReplayHardBeginEnd) {
/* This is a user error. Whatever operation (like glRectf)
* decomposed to this hard begin/end pair is now being run
* inside a begin/end object -- illegally. Reject it and
* raise an error.
*/
_mesa_error(ctx, GL_INVALID_OPERATION, "hard replay");
return;
}
}
 
if (tnl->LoopbackDListCassettes) {
/* (tnl->IsolateMaterials && (IM->OrFlag & VERT_MATERIAL)) ) { */
fixup_compiled_primitives( ctx, IM );
loopback_compiled_cassette( ctx, IM );
restore_compiled_primitives( ctx, IM );
}
else {
if (ctx->NewState)
_mesa_update_state(ctx);
 
if (tnl->pipeline.build_state_changes)
_tnl_validate_pipeline( ctx );
 
_tnl_fixup_compiled_cassette( ctx, IM );
fixup_compiled_primitives( ctx, IM );
 
if (IM->Primitive[IM->LastPrimitive] & PRIM_END)
ctx->Driver.CurrentExecPrimitive = GL_POLYGON+1;
else if ((IM->Primitive[IM->LastPrimitive] & PRIM_BEGIN) ||
(IM->Primitive[IM->LastPrimitive] & PRIM_MODE_MASK) ==
PRIM_OUTSIDE_BEGIN_END) {
ctx->Driver.CurrentExecPrimitive =
IM->Primitive[IM->LastPrimitive] & PRIM_MODE_MASK;
}
 
_tnl_get_exec_copy_verts( ctx, IM );
 
if (IM->NormalLengthPtr)
fixup_normal_lengths( IM );
if (IM->Count == IM->Start)
_tnl_copy_to_current( ctx, IM, IM->OrFlag, IM->LastData );
else {
/* _tnl_print_cassette( IM ); */
_tnl_run_cassette( ctx, IM );
}
 
restore_compiled_primitives( ctx, IM );
}
 
if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1)
tnl->ReplayHardBeginEnd = 0;
}
 
static void
destroy_compiled_cassette( GLcontext *ctx, void *data )
{
TNLvertexcassette *node = (TNLvertexcassette *)data;
 
if ( --node->IM->ref_count == 0 )
_tnl_free_immediate( ctx, node->IM );
}
 
 
static void
print_compiled_cassette( GLcontext *ctx, void *data )
{
TNLvertexcassette *node = (TNLvertexcassette *)data;
struct immediate *IM = node->IM;
 
_mesa_debug(ctx, "TNL-VERTEX-CASSETTE, id %u, rows %u..%u\n",
node->IM->id, node->Start, node->Count);
 
IM->Start = node->Start;
IM->CopyStart = node->Start;
IM->Count = node->Count;
IM->BeginState = node->BeginState;
IM->OrFlag = node->OrFlag;
IM->TexSize = node->TexSize;
IM->AndFlag = node->AndFlag;
IM->LastData = node->LastData;
IM->LastPrimitive = node->LastPrimitive;
IM->LastMaterial = node->LastMaterial;
IM->MaterialOrMask = node->MaterialOrMask;
IM->MaterialAndMask = node->MaterialAndMask;
 
_tnl_print_cassette( node->IM );
}
 
void
_tnl_BeginCallList( GLcontext *ctx, GLuint list )
{
(void) ctx;
(void) list;
FLUSH_CURRENT(ctx, 0);
}
 
 
/* Called at the tail of a CallList. Make current immediate aware of
* any new to-be-copied vertices.
*/
void
_tnl_EndCallList( GLcontext *ctx )
{
GLuint beginstate = 0;
 
if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END)
beginstate = VERT_BEGIN_0|VERT_BEGIN_1;
 
_tnl_reset_exec_input( ctx, TNL_CURRENT_IM(ctx)->Start, beginstate, 0 );
}
 
 
void
_tnl_EndList( GLcontext *ctx )
{
struct immediate *IM = TNL_CURRENT_IM(ctx);
 
ctx->swtnl_im = 0;
IM->ref_count--;
 
/* outside begin/end, even in COMPILE_AND_EXEC,
* so no vertices to copy, right?
*/
ASSERT(TNL_CONTEXT(ctx)->ExecCopyCount == 0);
 
/* If this one isn't free, get a clean one. (Otherwise we'll be
* using one that's already half full).
*/
if (IM->ref_count != 0)
IM = _tnl_alloc_immediate( ctx );
 
ASSERT(IM->ref_count == 0);
 
SET_IMMEDIATE( ctx, IM );
IM->ref_count++;
 
_tnl_reset_exec_input( ctx, IMM_MAX_COPIED_VERTS, 0, 0 );
}
 
 
void
_tnl_NewList( GLcontext *ctx, GLuint list, GLenum mode )
{
struct immediate *IM = TNL_CURRENT_IM(ctx);
 
/* Use the installed immediate struct. No vertices in the current
* immediate, no copied vertices in the system.
*/
ASSERT(TNL_CURRENT_IM(ctx));
ASSERT(TNL_CURRENT_IM(ctx)->Start == IMM_MAX_COPIED_VERTS);
ASSERT(TNL_CURRENT_IM(ctx)->Start == TNL_CURRENT_IM(ctx)->Count);
ASSERT(TNL_CONTEXT(ctx)->ExecCopyCount == 0);
 
/* Set current Begin/End state to unknown:
*/
IM->BeginState = VERT_BEGIN_0;
ctx->Driver.CurrentSavePrimitive = PRIM_UNKNOWN;
}
 
 
void
_tnl_dlist_init( GLcontext *ctx )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
 
tnl->opcode_vertex_cassette =
_mesa_alloc_opcode( ctx,
sizeof(TNLvertexcassette),
execute_compiled_cassette,
destroy_compiled_cassette,
print_compiled_cassette );
}
 
 
static void emit_material( struct gl_material *src, GLuint bitmask )
{
if (bitmask & FRONT_EMISSION_BIT)
glMaterialfv( GL_FRONT, GL_EMISSION, src[0].Emission );
 
if (bitmask & BACK_EMISSION_BIT)
glMaterialfv( GL_BACK, GL_EMISSION, src[1].Emission );
 
if (bitmask & FRONT_AMBIENT_BIT)
glMaterialfv( GL_FRONT, GL_AMBIENT, src[0].Ambient );
 
if (bitmask & BACK_AMBIENT_BIT)
glMaterialfv( GL_BACK, GL_AMBIENT, src[1].Ambient );
 
if (bitmask & FRONT_DIFFUSE_BIT)
glMaterialfv( GL_FRONT, GL_DIFFUSE, src[0].Diffuse );
 
if (bitmask & BACK_DIFFUSE_BIT)
glMaterialfv( GL_BACK, GL_DIFFUSE, src[1].Diffuse );
 
if (bitmask & FRONT_SPECULAR_BIT)
glMaterialfv( GL_FRONT, GL_SPECULAR, src[0].Specular );
 
if (bitmask & BACK_SPECULAR_BIT)
glMaterialfv( GL_BACK, GL_SPECULAR, src[1].Specular );
 
if (bitmask & FRONT_SHININESS_BIT)
glMaterialfv( GL_FRONT, GL_SHININESS, &src[0].Shininess );
 
if (bitmask & BACK_SHININESS_BIT)
glMaterialfv( GL_BACK, GL_SHININESS, &src[1].Shininess );
 
if (bitmask & FRONT_INDEXES_BIT) {
GLfloat ind[3];
ind[0] = src[0].AmbientIndex;
ind[1] = src[0].DiffuseIndex;
ind[2] = src[0].SpecularIndex;
glMaterialfv( GL_FRONT, GL_COLOR_INDEXES, ind );
}
 
if (bitmask & BACK_INDEXES_BIT) {
GLfloat ind[3];
ind[0] = src[1].AmbientIndex;
ind[1] = src[1].DiffuseIndex;
ind[2] = src[1].SpecularIndex;
glMaterialfv( GL_BACK, GL_COLOR_INDEXES, ind );
}
}
 
 
/* Low-performance helper function to allow driver-supplied tnl
* modules to process tnl display lists. This is primarily supplied
* to avoid fallbacks if CallList is invoked inside a Begin/End pair.
* For higher performance, drivers should fallback to tnl (if outside
* begin/end), or (for tnl hardware) implement their own display list
* mechanism.
*/
static void loopback_compiled_cassette( GLcontext *ctx, struct immediate *IM )
{
GLuint i;
GLuint *flags = IM->Flag;
GLuint orflag = IM->OrFlag;
GLuint j;
void (GLAPIENTRY *vertex)( const GLfloat * );
void (GLAPIENTRY *texcoordfv[MAX_TEXTURE_UNITS])( GLenum, const GLfloat * );
GLuint maxtex = 0;
GLuint p, length, prim = 0;
if (orflag & VERT_BITS_OBJ_234)
vertex = (void (GLAPIENTRY *)(const GLfloat *)) glVertex4fv;
else
vertex = (void (GLAPIENTRY *)(const GLfloat *)) glVertex3fv;
if (orflag & VERT_BITS_TEX_ANY) {
for (j = 0 ; j < ctx->Const.MaxTextureUnits ; j++) {
if (orflag & VERT_BIT_TEX(j)) {
maxtex = j+1;
if ((IM->TexSize & TEX_SIZE_4(j)) == TEX_SIZE_4(j))
texcoordfv[j] = glMultiTexCoord4fvARB;
else if (IM->TexSize & TEX_SIZE_3(j))
texcoordfv[j] = glMultiTexCoord3fvARB;
else
texcoordfv[j] = glMultiTexCoord2fvARB;
}
}
}
 
for (p = IM->Start ; !(prim & PRIM_LAST) ; p += length)
{
prim = IM->Primitive[p];
length= IM->PrimitiveLength[p];
ASSERT(length || (prim & PRIM_LAST));
ASSERT((prim & PRIM_MODE_MASK) <= GL_POLYGON+1);
 
if (prim & PRIM_BEGIN) {
glBegin(prim & PRIM_MODE_MASK);
}
 
for ( i = p ; i <= p+length ; i++) {
if (flags[i] & VERT_BITS_TEX_ANY) {
GLuint k;
for (k = 0 ; k < maxtex ; k++) {
if (flags[i] & VERT_BIT_TEX(k)) {
texcoordfv[k]( GL_TEXTURE0_ARB + k,
IM->Attrib[VERT_ATTRIB_TEX0 + k][i] );
}
}
}
 
if (flags[i] & VERT_BIT_NORMAL)
glNormal3fv(IM->Attrib[VERT_ATTRIB_NORMAL][i]);
 
if (flags[i] & VERT_BIT_COLOR0)
glColor4fv( IM->Attrib[VERT_ATTRIB_COLOR0][i] );
 
if (flags[i] & VERT_BIT_COLOR1)
_glapi_Dispatch->SecondaryColor3fvEXT( IM->Attrib[VERT_ATTRIB_COLOR1][i] );
 
if (flags[i] & VERT_BIT_FOG)
_glapi_Dispatch->FogCoordfEXT( IM->Attrib[VERT_ATTRIB_FOG][i][0] );
 
if (flags[i] & VERT_BIT_INDEX)
glIndexi( IM->Index[i] );
 
if (flags[i] & VERT_BIT_EDGEFLAG)
glEdgeFlag( IM->EdgeFlag[i] );
 
if (flags[i] & VERT_BIT_MATERIAL)
emit_material( IM->Material[i], IM->MaterialMask[i] );
 
if (flags[i]&VERT_BITS_OBJ_234)
vertex( IM->Attrib[VERT_ATTRIB_POS][i] );
else if (flags[i] & VERT_BIT_EVAL_C1)
glEvalCoord1f( IM->Attrib[VERT_ATTRIB_POS][i][0] );
else if (flags[i] & VERT_BIT_EVAL_P1)
glEvalPoint1( (GLint) IM->Attrib[VERT_ATTRIB_POS][i][0] );
else if (flags[i] & VERT_BIT_EVAL_C2)
glEvalCoord2f( IM->Attrib[VERT_ATTRIB_POS][i][0],
IM->Attrib[VERT_ATTRIB_POS][i][1] );
else if (flags[i] & VERT_BIT_EVAL_P2)
glEvalPoint2( (GLint) IM->Attrib[VERT_ATTRIB_POS][i][0],
(GLint) IM->Attrib[VERT_ATTRIB_POS][i][1] );
}
 
if (prim & PRIM_END) {
glEnd();
}
}
}
/shark/trunk/ports/mesa/src/tnl/t_vb_texgen.c
0,0 → 1,692
/* $Id: t_vb_texgen.c,v 1.1 2003-02-28 11:48:08 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Brian Paul
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
 
#include "glheader.h"
#include "colormac.h"
#include "context.h"
#include "macros.h"
#include "mmath.h"
#include "imports.h"
#include "mtypes.h"
 
#include "math/m_xform.h"
 
#include "t_context.h"
#include "t_pipeline.h"
 
 
/***********************************************************************
* Automatic texture coordinate generation (texgen) code.
*/
 
 
struct texgen_stage_data;
 
typedef void (*texgen_func)( GLcontext *ctx,
struct texgen_stage_data *store,
GLuint unit);
 
 
struct texgen_stage_data {
 
/* Per-texunit derived state.
*/
GLuint TexgenSize[MAX_TEXTURE_UNITS];
GLuint TexgenHoles[MAX_TEXTURE_UNITS];
texgen_func TexgenFunc[MAX_TEXTURE_UNITS];
 
/* Temporary values used in texgen.
*/
GLfloat (*tmp_f)[3];
GLfloat *tmp_m;
 
/* Buffered outputs of the stage.
*/
GLvector4f texcoord[MAX_TEXTURE_UNITS];
};
 
 
#define TEXGEN_STAGE_DATA(stage) ((struct texgen_stage_data *)stage->privatePtr)
 
 
 
static GLuint all_bits[5] = {
0,
VEC_SIZE_1,
VEC_SIZE_2,
VEC_SIZE_3,
VEC_SIZE_4,
};
 
#define VEC_SIZE_FLAGS (VEC_SIZE_1|VEC_SIZE_2|VEC_SIZE_3|VEC_SIZE_4)
 
#define TEXGEN_NEED_M (TEXGEN_SPHERE_MAP)
#define TEXGEN_NEED_F (TEXGEN_SPHERE_MAP | \
TEXGEN_REFLECTION_MAP_NV)
 
 
 
static void build_m3( GLfloat f[][3], GLfloat m[],
const GLvector4f *normal,
const GLvector4f *eye )
{
GLuint stride = eye->stride;
GLfloat *coord = (GLfloat *)eye->start;
GLuint count = eye->count;
const GLfloat *norm = normal->start;
GLuint i;
 
for (i=0;i<count;i++,STRIDE_F(coord,stride),STRIDE_F(norm,normal->stride)) {
GLfloat u[3], two_nu, fx, fy, fz;
COPY_3V( u, coord );
NORMALIZE_3FV( u );
two_nu = 2.0F * DOT3(norm,u);
fx = f[i][0] = u[0] - norm[0] * two_nu;
fy = f[i][1] = u[1] - norm[1] * two_nu;
fz = f[i][2] = u[2] - norm[2] * two_nu;
m[i] = fx * fx + fy * fy + (fz + 1.0F) * (fz + 1.0F);
if (m[i] != 0.0F) {
m[i] = 0.5F / (GLfloat) GL_SQRT(m[i]);
}
}
}
 
 
 
static void build_m2( GLfloat f[][3], GLfloat m[],
const GLvector4f *normal,
const GLvector4f *eye )
{
GLuint stride = eye->stride;
GLfloat *coord = eye->start;
GLuint count = eye->count;
 
GLfloat *norm = normal->start;
GLuint i;
 
for (i=0;i<count;i++,STRIDE_F(coord,stride),STRIDE_F(norm,normal->stride)) {
GLfloat u[3], two_nu, fx, fy, fz;
COPY_2V( u, coord );
u[2] = 0;
NORMALIZE_3FV( u );
two_nu = 2.0F * DOT3(norm,u);
fx = f[i][0] = u[0] - norm[0] * two_nu;
fy = f[i][1] = u[1] - norm[1] * two_nu;
fz = f[i][2] = u[2] - norm[2] * two_nu;
m[i] = fx * fx + fy * fy + (fz + 1.0F) * (fz + 1.0F);
if (m[i] != 0.0F) {
m[i] = 0.5F / (GLfloat) GL_SQRT(m[i]);
}
}
}
 
 
 
typedef void (*build_m_func)( GLfloat f[][3],
GLfloat m[],
const GLvector4f *normal,
const GLvector4f *eye );
 
 
static build_m_func build_m_tab[5] = {
0,
0,
build_m2,
build_m3,
build_m3
};
 
 
/* This is unusual in that we respect the stride of the output vector
* (f). This allows us to pass in either a texcoord vector4f, or a
* temporary vector3f.
*/
static void build_f3( GLfloat *f,
GLuint fstride,
const GLvector4f *normal,
const GLvector4f *eye )
{
GLuint stride = eye->stride;
GLfloat *coord = eye->start;
GLuint count = eye->count;
 
GLfloat *norm = normal->start;
GLuint i;
 
for (i=0;i<count;i++) {
GLfloat u[3], two_nu;
COPY_3V( u, coord );
NORMALIZE_3FV( u );
two_nu = 2.0F * DOT3(norm,u);
f[0] = u[0] - norm[0] * two_nu;
f[1] = u[1] - norm[1] * two_nu;
f[2] = u[2] - norm[2] * two_nu;
STRIDE_F(coord,stride);
STRIDE_F(f,fstride);
STRIDE_F(norm, normal->stride);
}
}
 
 
static void build_f2( GLfloat *f,
GLuint fstride,
const GLvector4f *normal,
const GLvector4f *eye )
{
GLuint stride = eye->stride;
GLfloat *coord = eye->start;
GLuint count = eye->count;
GLfloat *norm = normal->start;
GLuint i;
 
for (i=0;i<count;i++) {
 
GLfloat u[3], two_nu;
COPY_2V( u, coord );
u[2] = 0;
NORMALIZE_3FV( u );
two_nu = 2.0F * DOT3(norm,u);
f[0] = u[0] - norm[0] * two_nu;
f[1] = u[1] - norm[1] * two_nu;
f[2] = u[2] - norm[2] * two_nu;
 
STRIDE_F(coord,stride);
STRIDE_F(f,fstride);
STRIDE_F(norm, normal->stride);
}
}
 
typedef void (*build_f_func)( GLfloat *f,
GLuint fstride,
const GLvector4f *normal_vec,
const GLvector4f *eye );
 
 
 
/* Just treat 4-vectors as 3-vectors.
*/
static build_f_func build_f_tab[5] = {
0,
0,
build_f2,
build_f3,
build_f3
};
 
 
/* Special case texgen functions.
*/
static void texgen_reflection_map_nv( GLcontext *ctx,
struct texgen_stage_data *store,
GLuint unit )
{
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
GLvector4f *in = VB->TexCoordPtr[unit];
GLvector4f *out = &store->texcoord[unit];
 
build_f_tab[VB->EyePtr->size]( out->start,
out->stride,
VB->NormalPtr,
VB->EyePtr );
 
if (in) {
out->flags |= (in->flags & VEC_SIZE_FLAGS) | VEC_SIZE_3;
out->count = in->count;
out->size = MAX2(in->size, 3);
if (in->size == 4)
_mesa_copy_tab[0x8]( out, in );
}
else {
out->flags |= VEC_SIZE_3;
out->size = 3;
out->count = in->count;
}
 
}
 
 
 
static void texgen_normal_map_nv( GLcontext *ctx,
struct texgen_stage_data *store,
GLuint unit )
{
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
GLvector4f *in = VB->TexCoordPtr[unit];
GLvector4f *out = &store->texcoord[unit];
GLvector4f *normal = VB->NormalPtr;
GLfloat (*texcoord)[4] = (GLfloat (*)[4])out->start;
GLuint count = VB->Count;
GLuint i;
const GLfloat *norm = normal->start;
 
for (i=0;i<count;i++, STRIDE_F(norm, normal->stride)) {
texcoord[i][0] = norm[0];
texcoord[i][1] = norm[1];
texcoord[i][2] = norm[2];
}
 
 
if (in) {
out->flags |= (in->flags & VEC_SIZE_FLAGS) | VEC_SIZE_3;
out->count = in->count;
out->size = MAX2(in->size, 3);
if (in->size == 4)
_mesa_copy_tab[0x8]( out, in );
}
else {
out->flags |= VEC_SIZE_3;
out->size = 3;
out->count = in->count;
}
}
 
 
static void texgen_sphere_map( GLcontext *ctx,
struct texgen_stage_data *store,
GLuint unit )
{
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
GLvector4f *in = VB->TexCoordPtr[unit];
GLvector4f *out = &store->texcoord[unit];
GLfloat (*texcoord)[4] = (GLfloat (*)[4]) out->start;
GLuint count = VB->Count;
GLuint i;
GLfloat (*f)[3] = store->tmp_f;
GLfloat *m = store->tmp_m;
 
/* _mesa_debug(NULL, "%s normstride %d eyestride %d\n", */
/* __FUNCTION__, VB->NormalPtr->stride, */
/* VB->EyePtr->stride); */
 
(build_m_tab[VB->EyePtr->size])( store->tmp_f,
store->tmp_m,
VB->NormalPtr,
VB->EyePtr );
 
for (i=0;i<count;i++) {
texcoord[i][0] = f[i][0] * m[i] + 0.5F;
texcoord[i][1] = f[i][1] * m[i] + 0.5F;
}
 
if (in) {
out->size = MAX2(in->size,2);
out->count = in->count;
out->flags |= (in->flags & VEC_SIZE_FLAGS) | VEC_SIZE_2;
if (in->size > 2)
_mesa_copy_tab[all_bits[in->size] & ~0x3]( out, in );
} else {
out->size = 2;
out->flags |= VEC_SIZE_2;
out->count = in->count;
}
}
 
 
 
static void texgen( GLcontext *ctx,
struct texgen_stage_data *store,
GLuint unit )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
GLvector4f *in = VB->TexCoordPtr[unit];
GLvector4f *out = &store->texcoord[unit];
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
const GLvector4f *obj = VB->ObjPtr;
const GLvector4f *eye = VB->EyePtr;
const GLvector4f *normal = VB->NormalPtr;
GLfloat (*texcoord)[4] = (GLfloat (*)[4])out->data;
GLfloat *indata;
GLuint count = VB->Count;
GLfloat (*f)[3] = store->tmp_f;
GLfloat *m = store->tmp_m;
GLuint holes = 0;
 
 
if (texUnit->_GenFlags & TEXGEN_NEED_M) {
build_m_tab[in->size]( store->tmp_f, store->tmp_m, normal, eye );
} else if (texUnit->_GenFlags & TEXGEN_NEED_F) {
build_f_tab[in->size]( (GLfloat *)store->tmp_f, 3, normal, eye );
}
 
if (!in) {
ASSERT(0);
in = out;
in->count = VB->Count;
 
out->size = store->TexgenSize[unit];
out->flags |= texUnit->TexGenEnabled;
out->count = VB->Count;
holes = store->TexgenHoles[unit];
}
else {
GLuint copy = (all_bits[in->size] & ~texUnit->TexGenEnabled);
if (copy)
_mesa_copy_tab[copy]( out, in );
 
out->size = MAX2(in->size, store->TexgenSize[unit]);
out->flags |= (in->flags & VEC_SIZE_FLAGS) | texUnit->TexGenEnabled;
out->count = in->count;
 
holes = ~all_bits[in->size] & store->TexgenHoles[unit];
}
 
if (holes) {
if (holes & VEC_DIRTY_2) _mesa_vector4f_clean_elem(out, count, 2);
if (holes & VEC_DIRTY_1) _mesa_vector4f_clean_elem(out, count, 1);
if (holes & VEC_DIRTY_0) _mesa_vector4f_clean_elem(out, count, 0);
}
 
if (texUnit->TexGenEnabled & S_BIT) {
GLuint i;
switch (texUnit->GenModeS) {
case GL_OBJECT_LINEAR:
_mesa_dotprod_tab[obj->size]( (GLfloat *)out->data,
sizeof(out->data[0]), obj,
texUnit->ObjectPlaneS );
break;
case GL_EYE_LINEAR:
_mesa_dotprod_tab[eye->size]( (GLfloat *)out->data,
sizeof(out->data[0]), eye,
texUnit->EyePlaneS );
break;
case GL_SPHERE_MAP:
for (indata=in->start,i=0 ; i<count ;i++, STRIDE_F(indata,in->stride))
texcoord[i][0] = indata[0] * m[i] + 0.5F;
break;
case GL_REFLECTION_MAP_NV:
for (i=0;i<count;i++)
texcoord[i][0] = f[i][0];
break;
case GL_NORMAL_MAP_NV: {
const GLfloat *norm = normal->start;
for (i=0;i<count;i++, STRIDE_F(norm, normal->stride)) {
texcoord[i][0] = norm[0];
}
break;
}
default:
_mesa_problem(ctx, "Bad S texgen");
}
}
 
if (texUnit->TexGenEnabled & T_BIT) {
GLuint i;
switch (texUnit->GenModeT) {
case GL_OBJECT_LINEAR:
_mesa_dotprod_tab[obj->size]( &(out->data[0][1]),
sizeof(out->data[0]), obj,
texUnit->ObjectPlaneT );
break;
case GL_EYE_LINEAR:
_mesa_dotprod_tab[eye->size]( &(out->data[0][1]),
sizeof(out->data[0]), eye,
texUnit->EyePlaneT );
break;
case GL_SPHERE_MAP:
for (indata=in->start,i=0; i<count ;i++,STRIDE_F(indata,in->stride))
texcoord[i][1] = indata[1] * m[i] + 0.5F;
break;
case GL_REFLECTION_MAP_NV:
for (i=0;i<count;i++)
texcoord[i][0] = f[i][0];
break;
case GL_NORMAL_MAP_NV: {
const GLfloat *norm = normal->start;
for (i=0;i<count;i++, STRIDE_F(norm, normal->stride)) {
texcoord[i][1] = norm[1];
}
break;
}
default:
_mesa_problem(ctx, "Bad T texgen");
}
}
 
if (texUnit->TexGenEnabled & R_BIT) {
GLuint i;
switch (texUnit->GenModeR) {
case GL_OBJECT_LINEAR:
_mesa_dotprod_tab[obj->size]( &(out->data[0][2]),
sizeof(out->data[0]), obj,
texUnit->ObjectPlaneR );
break;
case GL_EYE_LINEAR:
_mesa_dotprod_tab[eye->size]( &(out->data[0][2]),
sizeof(out->data[0]), eye,
texUnit->EyePlaneR );
break;
case GL_REFLECTION_MAP_NV:
for (i=0;i<count;i++)
texcoord[i][2] = f[i][2];
break;
case GL_NORMAL_MAP_NV: {
const GLfloat *norm = normal->start;
for (i=0;i<count;i++,STRIDE_F(norm, normal->stride)) {
texcoord[i][2] = norm[2];
}
break;
}
default:
_mesa_problem(ctx, "Bad R texgen");
}
}
 
if (texUnit->TexGenEnabled & Q_BIT) {
switch (texUnit->GenModeQ) {
case GL_OBJECT_LINEAR:
_mesa_dotprod_tab[obj->size]( &(out->data[0][3]),
sizeof(out->data[0]), obj,
texUnit->ObjectPlaneQ );
break;
case GL_EYE_LINEAR:
_mesa_dotprod_tab[eye->size]( &(out->data[0][3]),
sizeof(out->data[0]), eye,
texUnit->EyePlaneQ );
break;
default:
_mesa_problem(ctx, "Bad Q texgen");
}
}
}
 
 
 
static GLboolean run_texgen_stage( GLcontext *ctx,
struct gl_pipeline_stage *stage )
{
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
struct texgen_stage_data *store = TEXGEN_STAGE_DATA( stage );
GLuint i;
 
for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++)
if (ctx->Texture._TexGenEnabled & ENABLE_TEXGEN(i)) {
if (stage->changed_inputs & (VERT_BIT_EYE | VERT_BIT_NORMAL | VERT_BIT_TEX(i)))
store->TexgenFunc[i]( ctx, store, i );
 
VB->TexCoordPtr[i] = &store->texcoord[i];
}
 
return GL_TRUE;
}
 
 
 
 
static GLboolean run_validate_texgen_stage( GLcontext *ctx,
struct gl_pipeline_stage *stage )
{
struct texgen_stage_data *store = TEXGEN_STAGE_DATA(stage);
GLuint i;
 
for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) {
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
 
if (texUnit->TexGenEnabled) {
GLuint sz;
 
if (texUnit->TexGenEnabled & R_BIT)
sz = 4;
else if (texUnit->TexGenEnabled & Q_BIT)
sz = 3;
else if (texUnit->TexGenEnabled & T_BIT)
sz = 2;
else
sz = 1;
 
store->TexgenSize[i] = sz;
store->TexgenHoles[i] = (all_bits[sz] & ~texUnit->TexGenEnabled);
store->TexgenFunc[i] = texgen;
 
if (texUnit->TexGenEnabled == (S_BIT|T_BIT|R_BIT)) {
if (texUnit->_GenFlags == TEXGEN_REFLECTION_MAP_NV) {
store->TexgenFunc[i] = texgen_reflection_map_nv;
}
else if (texUnit->_GenFlags == TEXGEN_NORMAL_MAP_NV) {
store->TexgenFunc[i] = texgen_normal_map_nv;
}
}
else if (texUnit->TexGenEnabled == (S_BIT|T_BIT) &&
texUnit->_GenFlags == TEXGEN_SPHERE_MAP) {
store->TexgenFunc[i] = texgen_sphere_map;
}
}
}
 
stage->run = run_texgen_stage;
return stage->run( ctx, stage );
}
 
 
static void check_texgen( GLcontext *ctx, struct gl_pipeline_stage *stage )
{
GLuint i;
stage->active = 0;
 
if (ctx->Texture._TexGenEnabled && !ctx->VertexProgram.Enabled) {
GLuint inputs = 0;
GLuint outputs = 0;
 
if (ctx->Texture._GenFlags & TEXGEN_OBJ_LINEAR)
inputs |= VERT_BIT_POS;
 
if (ctx->Texture._GenFlags & TEXGEN_NEED_EYE_COORD)
inputs |= VERT_BIT_EYE;
 
if (ctx->Texture._GenFlags & TEXGEN_NEED_NORMALS)
inputs |= VERT_BIT_NORMAL;
 
for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++)
if (ctx->Texture._TexGenEnabled & ENABLE_TEXGEN(i))
{
outputs |= VERT_BIT_TEX(i);
 
/* Need the original input in case it contains a Q coord:
* (sigh)
*/
inputs |= VERT_BIT_TEX(i);
 
/* Something for Feedback? */
}
 
if (stage->privatePtr)
stage->run = run_validate_texgen_stage;
stage->active = 1;
stage->inputs = inputs;
stage->outputs = outputs;
}
}
 
 
 
 
/* Called the first time stage->run() is invoked.
*/
static GLboolean alloc_texgen_data( GLcontext *ctx,
struct gl_pipeline_stage *stage )
{
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
struct texgen_stage_data *store;
GLuint i;
 
stage->privatePtr = CALLOC(sizeof(*store));
store = TEXGEN_STAGE_DATA(stage);
if (!store)
return GL_FALSE;
 
for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++)
_mesa_vector4f_alloc( &store->texcoord[i], 0, VB->Size, 32 );
 
store->tmp_f = (GLfloat (*)[3]) MALLOC(VB->Size * sizeof(GLfloat) * 3);
store->tmp_m = (GLfloat *) MALLOC(VB->Size * sizeof(GLfloat));
 
/* Now validate and run the stage.
*/
stage->run = run_validate_texgen_stage;
return stage->run( ctx, stage );
}
 
 
static void free_texgen_data( struct gl_pipeline_stage *stage )
 
{
struct texgen_stage_data *store = TEXGEN_STAGE_DATA(stage);
GLuint i;
 
if (store) {
for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++)
if (store->texcoord[i].data)
_mesa_vector4f_free( &store->texcoord[i] );
 
 
if (store->tmp_f) FREE( store->tmp_f );
if (store->tmp_m) FREE( store->tmp_m );
FREE( store );
stage->privatePtr = NULL;
}
}
 
 
 
const struct gl_pipeline_stage _tnl_texgen_stage =
{
"texgen", /* name */
_NEW_TEXTURE, /* when to call check() */
_NEW_TEXTURE, /* when to invalidate stored data */
GL_FALSE, /* active? */
0, /* inputs */
0, /* outputs */
0, /* changed_inputs */
NULL, /* private data */
free_texgen_data, /* destructor */
check_texgen, /* check */
alloc_texgen_data /* run -- initially set to alloc data */
};
/shark/trunk/ports/mesa/src/tnl/t_vb_lighttmp.h
0,0 → 1,1003
/* $Id: t_vb_lighttmp.h,v 1.1 2003-02-28 11:48:07 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*
* Authors:
* Brian Paul
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
 
#if (IDX & LIGHT_FLAGS)
# define VSTRIDE (4 * sizeof(GLfloat))
# define NSTRIDE nstride /*(3 * sizeof(GLfloat))*/
# define CHECK_MATERIAL(x) (flags[x] & VERT_BIT_MATERIAL)
# define CHECK_END_VB(x) (flags[x] & VERT_BIT_END_VB)
# if (IDX & LIGHT_COLORMATERIAL)
# define CMSTRIDE STRIDE_F(CMcolor, CMstride)
# define CHECK_COLOR_MATERIAL(x) (flags[x] & VERT_BIT_COLOR0)
# define CHECK_VALIDATE(x) (flags[x] & (VERT_BIT_COLOR0|VERT_BIT_MATERIAL))
# define DO_ANOTHER_NORMAL(x) \
((flags[x] & (VERT_BIT_COLOR0|VERT_BIT_NORMAL|VERT_BIT_END_VB|VERT_BIT_MATERIAL)) == VERT_BIT_NORMAL)
# define REUSE_LIGHT_RESULTS(x) \
((flags[x] & (VERT_BIT_COLOR0|VERT_BIT_NORMAL|VERT_BIT_END_VB|VERT_BIT_MATERIAL)) == 0)
# else
# define CMSTRIDE (void)0
# define CHECK_COLOR_MATERIAL(x) 0
# define CHECK_VALIDATE(x) (flags[x] & (VERT_BIT_MATERIAL))
# define DO_ANOTHER_NORMAL(x) \
((flags[x] & (VERT_BIT_NORMAL|VERT_BIT_END_VB|VERT_BIT_MATERIAL)) == VERT_BIT_NORMAL)
# define REUSE_LIGHT_RESULTS(x) \
((flags[x] & (VERT_BIT_NORMAL|VERT_BIT_END_VB|VERT_BIT_MATERIAL)) == 0)
# endif
#else
# define VSTRIDE vstride
# define NSTRIDE nstride
# define CHECK_MATERIAL(x) 0 /* no materials on array paths */
# define CHECK_END_VB(XX) (XX >= nr)
# if (IDX & LIGHT_COLORMATERIAL)
# define CMSTRIDE STRIDE_F(CMcolor, CMstride)
# define CHECK_COLOR_MATERIAL(x) (x < nr) /* always have colormaterial */
# define CHECK_VALIDATE(x) (x < nr)
# define DO_ANOTHER_NORMAL(x) 0 /* always stop to recalc colormat */
# else
# define CMSTRIDE (void)0
# define CHECK_COLOR_MATERIAL(x) 0 /* no colormaterial */
# define CHECK_VALIDATE(x) (0)
# define DO_ANOTHER_NORMAL(XX) (XX < nr) /* keep going to end of vb */
# endif
# define REUSE_LIGHT_RESULTS(x) 0 /* always have a new normal */
#endif
 
 
 
#if (IDX & LIGHT_TWOSIDE)
# define NR_SIDES 2
#else
# define NR_SIDES 1
#endif
 
 
/* define TRACE if to trace lighting code */
 
 
/*
* ctx is the current context
* VB is the vertex buffer
* stage is the lighting stage-private data
* input is the vector of eye or object-space vertex coordinates
*/
static void TAG(light_rgba_spec)( GLcontext *ctx,
struct vertex_buffer *VB,
struct gl_pipeline_stage *stage,
GLvector4f *input )
{
struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
GLfloat (*base)[3] = ctx->Light._BaseColor;
GLchan sumA[2];
GLuint j;
 
const GLuint vstride = input->stride;
const GLfloat *vertex = (GLfloat *)input->data;
const GLuint nstride = VB->NormalPtr->stride;
const GLfloat *normal = (GLfloat *)VB->NormalPtr->data;
 
GLfloat *CMcolor;
GLuint CMstride;
 
GLchan (*Fcolor)[4] = (GLchan (*)[4]) store->LitColor[0].Ptr;
GLchan (*Bcolor)[4] = (GLchan (*)[4]) store->LitColor[1].Ptr;
GLchan (*Fspec)[4] = (GLchan (*)[4]) store->LitSecondary[0].Ptr;
GLchan (*Bspec)[4] = (GLchan (*)[4]) store->LitSecondary[1].Ptr;
 
const GLuint nr = VB->Count;
const GLuint *flags = VB->Flag;
struct gl_material (*new_material)[2] = VB->Material;
const GLuint *new_material_mask = VB->MaterialMask;
 
(void) flags;
(void) nstride;
(void) vstride;
 
#ifdef TRACE
fprintf(stderr, "%s\n", __FUNCTION__ );
#endif
 
if (IDX & LIGHT_COLORMATERIAL) {
if (VB->ColorPtr[0]->Type != GL_FLOAT ||
VB->ColorPtr[0]->Size != 4)
import_color_material( ctx, stage );
 
CMcolor = (GLfloat *) VB->ColorPtr[0]->Ptr;
CMstride = VB->ColorPtr[0]->StrideB;
}
 
VB->ColorPtr[0] = &store->LitColor[0];
VB->SecondaryColorPtr[0] = &store->LitSecondary[0];
UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material[0].Diffuse[3]);
 
if (IDX & LIGHT_TWOSIDE) {
VB->ColorPtr[1] = &store->LitColor[1];
VB->SecondaryColorPtr[1] = &store->LitSecondary[1];
UNCLAMPED_FLOAT_TO_CHAN(sumA[1], ctx->Light.Material[1].Diffuse[3]);
}
 
/* Side-effects done, can we finish now?
*/
if (stage->changed_inputs == 0)
return;
 
for ( j=0 ;
j<nr ;
j++,STRIDE_F(vertex,VSTRIDE),STRIDE_F(normal,NSTRIDE),CMSTRIDE)
{
GLfloat sum[2][3], spec[2][3];
struct gl_light *light;
 
if ( CHECK_COLOR_MATERIAL(j) )
_mesa_update_color_material( ctx, CMcolor );
 
if ( CHECK_MATERIAL(j) )
_mesa_update_material( ctx, new_material[j], new_material_mask[j] );
 
if ( CHECK_VALIDATE(j) ) {
TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx );
UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material[0].Diffuse[3]);
if (IDX & LIGHT_TWOSIDE)
UNCLAMPED_FLOAT_TO_CHAN(sumA[1], ctx->Light.Material[1].Diffuse[3]);
}
 
COPY_3V(sum[0], base[0]);
ZERO_3V(spec[0]);
 
if (IDX & LIGHT_TWOSIDE) {
COPY_3V(sum[1], base[1]);
ZERO_3V(spec[1]);
}
 
/* Add contribution from each enabled light source */
foreach (light, &ctx->Light.EnabledList) {
GLfloat n_dot_h;
GLfloat correction;
GLint side;
GLfloat contrib[3];
GLfloat attenuation;
GLfloat VP[3]; /* unit vector from vertex to light */
GLfloat n_dot_VP; /* n dot VP */
GLfloat *h;
 
/* compute VP and attenuation */
if (!(light->_Flags & LIGHT_POSITIONAL)) {
/* directional light */
COPY_3V(VP, light->_VP_inf_norm);
attenuation = light->_VP_inf_spot_attenuation;
}
else {
GLfloat d; /* distance from vertex to light */
 
SUB_3V(VP, light->_Position, vertex);
 
d = (GLfloat) LEN_3FV( VP );
 
if (d > 1e-6) {
GLfloat invd = 1.0F / d;
SELF_SCALE_SCALAR_3V(VP, invd);
}
 
attenuation = 1.0F / (light->ConstantAttenuation + d *
(light->LinearAttenuation + d *
light->QuadraticAttenuation));
 
/* spotlight attenuation */
if (light->_Flags & LIGHT_SPOT) {
GLfloat PV_dot_dir = - DOT3(VP, light->_NormDirection);
 
if (PV_dot_dir<light->_CosCutoff) {
continue; /* this light makes no contribution */
}
else {
GLdouble x = PV_dot_dir * (EXP_TABLE_SIZE-1);
GLint k = (GLint) x;
GLfloat spot = (GLfloat) (light->_SpotExpTable[k][0]
+ (x-k)*light->_SpotExpTable[k][1]);
attenuation *= spot;
}
}
}
 
if (attenuation < 1e-3)
continue; /* this light makes no contribution */
 
/* Compute dot product or normal and vector from V to light pos */
n_dot_VP = DOT3( normal, VP );
 
/* Which side gets the diffuse & specular terms? */
if (n_dot_VP < 0.0F) {
ACC_SCALE_SCALAR_3V(sum[0], attenuation, light->_MatAmbient[0]);
if (!(IDX & LIGHT_TWOSIDE)) {
continue;
}
side = 1;
correction = -1;
n_dot_VP = -n_dot_VP;
}
else {
if (IDX & LIGHT_TWOSIDE) {
ACC_SCALE_SCALAR_3V( sum[1], attenuation, light->_MatAmbient[1]);
}
side = 0;
correction = 1;
}
 
/* diffuse term */
COPY_3V(contrib, light->_MatAmbient[side]);
ACC_SCALE_SCALAR_3V(contrib, n_dot_VP, light->_MatDiffuse[side]);
ACC_SCALE_SCALAR_3V(sum[side], attenuation, contrib );
 
/* specular term - cannibalize VP... */
if (ctx->Light.Model.LocalViewer) {
GLfloat v[3];
COPY_3V(v, vertex);
NORMALIZE_3FV(v);
SUB_3V(VP, VP, v); /* h = VP + VPe */
h = VP;
NORMALIZE_3FV(h);
}
else if (light->_Flags & LIGHT_POSITIONAL) {
h = VP;
ACC_3V(h, ctx->_EyeZDir);
NORMALIZE_3FV(h);
}
else {
h = light->_h_inf_norm;
}
 
n_dot_h = correction * DOT3(normal, h);
 
if (n_dot_h > 0.0F) {
GLfloat spec_coef;
struct gl_shine_tab *tab = ctx->_ShineTable[side];
GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef );
 
if (spec_coef > 1.0e-10) {
spec_coef *= attenuation;
ACC_SCALE_SCALAR_3V( spec[side], spec_coef,
light->_MatSpecular[side]);
}
}
} /*loop over lights*/
 
UNCLAMPED_FLOAT_TO_RGB_CHAN( Fcolor[j], sum[0] );
UNCLAMPED_FLOAT_TO_RGB_CHAN( Fspec[j], spec[0] );
Fcolor[j][3] = sumA[0];
 
if (IDX & LIGHT_TWOSIDE) {
UNCLAMPED_FLOAT_TO_RGB_CHAN( Bcolor[j], sum[1] );
UNCLAMPED_FLOAT_TO_RGB_CHAN( Bspec[j], spec[1] );
Bcolor[j][3] = sumA[1];
}
}
}
 
 
static void TAG(light_rgba)( GLcontext *ctx,
struct vertex_buffer *VB,
struct gl_pipeline_stage *stage,
GLvector4f *input )
{
struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
GLuint j;
 
GLfloat (*base)[3] = ctx->Light._BaseColor;
GLchan sumA[2];
 
const GLuint vstride = input->stride;
const GLfloat *vertex = (GLfloat *) input->data;
const GLuint nstride = VB->NormalPtr->stride;
const GLfloat *normal = (GLfloat *)VB->NormalPtr->data;
 
GLfloat *CMcolor;
GLuint CMstride;
 
GLchan (*Fcolor)[4] = (GLchan (*)[4]) store->LitColor[0].Ptr;
GLchan (*Bcolor)[4] = (GLchan (*)[4]) store->LitColor[1].Ptr;
GLchan (*color[2])[4];
const GLuint *flags = VB->Flag;
 
struct gl_material (*new_material)[2] = VB->Material;
const GLuint *new_material_mask = VB->MaterialMask;
const GLuint nr = VB->Count;
 
#ifdef TRACE
fprintf(stderr, "%s\n", __FUNCTION__ );
#endif
 
(void) flags;
(void) nstride;
(void) vstride;
 
color[0] = Fcolor;
color[1] = Bcolor;
 
if (IDX & LIGHT_COLORMATERIAL) {
if (VB->ColorPtr[0]->Type != GL_FLOAT ||
VB->ColorPtr[0]->Size != 4)
import_color_material( ctx, stage );
 
CMcolor = (GLfloat *)VB->ColorPtr[0]->Ptr;
CMstride = VB->ColorPtr[0]->StrideB;
}
 
VB->ColorPtr[0] = &store->LitColor[0];
UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material[0].Diffuse[3]);
 
if (IDX & LIGHT_TWOSIDE) {
VB->ColorPtr[1] = &store->LitColor[1];
UNCLAMPED_FLOAT_TO_CHAN(sumA[1], ctx->Light.Material[1].Diffuse[3]);
}
 
if (stage->changed_inputs == 0)
return;
 
for ( j=0 ;
j<nr ;
j++,STRIDE_F(vertex,VSTRIDE), STRIDE_F(normal,NSTRIDE),CMSTRIDE)
{
GLfloat sum[2][3];
struct gl_light *light;
 
if ( CHECK_COLOR_MATERIAL(j) )
_mesa_update_color_material( ctx, CMcolor );
 
if ( CHECK_MATERIAL(j) )
_mesa_update_material( ctx, new_material[j], new_material_mask[j] );
 
if ( CHECK_VALIDATE(j) ) {
TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx );
UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material[0].Diffuse[3]);
if (IDX & LIGHT_TWOSIDE)
UNCLAMPED_FLOAT_TO_CHAN(sumA[1], ctx->Light.Material[1].Diffuse[3]);
}
 
COPY_3V(sum[0], base[0]);
 
if ( IDX & LIGHT_TWOSIDE )
COPY_3V(sum[1], base[1]);
 
/* Add contribution from each enabled light source */
foreach (light, &ctx->Light.EnabledList) {
 
GLfloat n_dot_h;
GLfloat correction;
GLint side;
GLfloat contrib[3];
GLfloat attenuation = 1.0;
GLfloat VP[3]; /* unit vector from vertex to light */
GLfloat n_dot_VP; /* n dot VP */
GLfloat *h;
 
/* compute VP and attenuation */
if (!(light->_Flags & LIGHT_POSITIONAL)) {
/* directional light */
COPY_3V(VP, light->_VP_inf_norm);
attenuation = light->_VP_inf_spot_attenuation;
}
else {
GLfloat d; /* distance from vertex to light */
 
 
SUB_3V(VP, light->_Position, vertex);
 
d = (GLfloat) LEN_3FV( VP );
 
if ( d > 1e-6) {
GLfloat invd = 1.0F / d;
SELF_SCALE_SCALAR_3V(VP, invd);
}
 
attenuation = 1.0F / (light->ConstantAttenuation + d *
(light->LinearAttenuation + d *
light->QuadraticAttenuation));
 
/* spotlight attenuation */
if (light->_Flags & LIGHT_SPOT) {
GLfloat PV_dot_dir = - DOT3(VP, light->_NormDirection);
 
if (PV_dot_dir<light->_CosCutoff) {
continue; /* this light makes no contribution */
}
else {
GLdouble x = PV_dot_dir * (EXP_TABLE_SIZE-1);
GLint k = (GLint) x;
GLfloat spot = (GLfloat) (light->_SpotExpTable[k][0]
+ (x-k)*light->_SpotExpTable[k][1]);
attenuation *= spot;
}
}
}
 
if (attenuation < 1e-3)
continue; /* this light makes no contribution */
 
/* Compute dot product or normal and vector from V to light pos */
n_dot_VP = DOT3( normal, VP );
 
/* which side are we lighting? */
if (n_dot_VP < 0.0F) {
ACC_SCALE_SCALAR_3V(sum[0], attenuation, light->_MatAmbient[0]);
 
if (!(IDX & LIGHT_TWOSIDE))
continue;
 
side = 1;
correction = -1;
n_dot_VP = -n_dot_VP;
}
else {
if (IDX & LIGHT_TWOSIDE) {
ACC_SCALE_SCALAR_3V( sum[1], attenuation, light->_MatAmbient[1]);
}
side = 0;
correction = 1;
}
 
COPY_3V(contrib, light->_MatAmbient[side]);
 
/* diffuse term */
ACC_SCALE_SCALAR_3V(contrib, n_dot_VP, light->_MatDiffuse[side]);
 
/* specular term - cannibalize VP... */
{
if (ctx->Light.Model.LocalViewer) {
GLfloat v[3];
COPY_3V(v, vertex);
NORMALIZE_3FV(v);
SUB_3V(VP, VP, v); /* h = VP + VPe */
h = VP;
NORMALIZE_3FV(h);
}
else if (light->_Flags & LIGHT_POSITIONAL) {
h = VP;
ACC_3V(h, ctx->_EyeZDir);
NORMALIZE_3FV(h);
}
else {
h = light->_h_inf_norm;
}
 
n_dot_h = correction * DOT3(normal, h);
 
if (n_dot_h > 0.0F)
{
GLfloat spec_coef;
struct gl_shine_tab *tab = ctx->_ShineTable[side];
 
GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef );
 
ACC_SCALE_SCALAR_3V( contrib, spec_coef,
light->_MatSpecular[side]);
}
}
 
ACC_SCALE_SCALAR_3V( sum[side], attenuation, contrib );
}
 
UNCLAMPED_FLOAT_TO_RGB_CHAN( Fcolor[j], sum[0] );
Fcolor[j][3] = sumA[0];
 
if (IDX & LIGHT_TWOSIDE) {
UNCLAMPED_FLOAT_TO_RGB_CHAN( Bcolor[j], sum[1] );
Bcolor[j][3] = sumA[1];
}
}
}
 
 
 
 
/* As below, but with just a single light.
*/
static void TAG(light_fast_rgba_single)( GLcontext *ctx,
struct vertex_buffer *VB,
struct gl_pipeline_stage *stage,
GLvector4f *input )
 
{
struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
const GLuint nstride = VB->NormalPtr->stride;
const GLfloat *normal = (GLfloat *)VB->NormalPtr->data;
GLfloat *CMcolor;
GLuint CMstride;
GLchan (*Fcolor)[4] = (GLchan (*)[4]) store->LitColor[0].Ptr;
GLchan (*Bcolor)[4] = (GLchan (*)[4]) store->LitColor[1].Ptr;
const struct gl_light *light = ctx->Light.EnabledList.next;
const GLuint *flags = VB->Flag;
GLchan basechan[2][4];
GLuint j = 0;
struct gl_material (*new_material)[2] = VB->Material;
const GLuint *new_material_mask = VB->MaterialMask;
GLfloat base[2][3];
const GLuint nr = VB->Count;
 
#ifdef TRACE
fprintf(stderr, "%s\n", __FUNCTION__ );
#endif
 
(void) input; /* doesn't refer to Eye or Obj */
(void) flags;
(void) nr;
(void) nstride;
 
if (IDX & LIGHT_COLORMATERIAL) {
if (VB->ColorPtr[0]->Type != GL_FLOAT ||
VB->ColorPtr[0]->Size != 4)
import_color_material( ctx, stage );
 
CMcolor = (GLfloat *)VB->ColorPtr[0]->Ptr;
CMstride = VB->ColorPtr[0]->StrideB;
}
 
VB->ColorPtr[0] = &store->LitColor[0];
if (IDX & LIGHT_TWOSIDE)
VB->ColorPtr[1] = &store->LitColor[1];
 
if (stage->changed_inputs == 0)
return;
 
do {
if ( CHECK_COLOR_MATERIAL(j) ) {
_mesa_update_color_material( ctx, CMcolor );
}
 
if ( CHECK_MATERIAL(j) )
_mesa_update_material( ctx, new_material[j], new_material_mask[j] );
 
if ( CHECK_VALIDATE(j) )
TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx );
 
 
/* No attenuation, so incoporate _MatAmbient into base color.
*/
COPY_3V(base[0], light->_MatAmbient[0]);
ACC_3V(base[0], ctx->Light._BaseColor[0] );
UNCLAMPED_FLOAT_TO_RGB_CHAN( basechan[0], base[0] );
UNCLAMPED_FLOAT_TO_CHAN(basechan[0][3],
ctx->Light.Material[0].Diffuse[3]);
 
if (IDX & LIGHT_TWOSIDE) {
COPY_3V(base[1], light->_MatAmbient[1]);
ACC_3V(base[1], ctx->Light._BaseColor[1]);
UNCLAMPED_FLOAT_TO_RGB_CHAN( basechan[1], base[1]);
UNCLAMPED_FLOAT_TO_CHAN(basechan[1][3],
ctx->Light.Material[1].Diffuse[3]);
}
 
do {
GLfloat n_dot_VP = DOT3(normal, light->_VP_inf_norm);
 
if (n_dot_VP < 0.0F) {
if (IDX & LIGHT_TWOSIDE) {
GLfloat n_dot_h = -DOT3(normal, light->_h_inf_norm);
GLfloat sum[3];
COPY_3V(sum, base[1]);
ACC_SCALE_SCALAR_3V(sum, -n_dot_VP, light->_MatDiffuse[1]);
if (n_dot_h > 0.0F) {
GLfloat spec;
GET_SHINE_TAB_ENTRY( ctx->_ShineTable[1], n_dot_h, spec );
ACC_SCALE_SCALAR_3V(sum, spec, light->_MatSpecular[1]);
}
UNCLAMPED_FLOAT_TO_RGB_CHAN(Bcolor[j], sum );
Bcolor[j][3] = basechan[1][3];
}
COPY_CHAN4(Fcolor[j], basechan[0]);
}
else {
GLfloat n_dot_h = DOT3(normal, light->_h_inf_norm);
GLfloat sum[3];
COPY_3V(sum, base[0]);
ACC_SCALE_SCALAR_3V(sum, n_dot_VP, light->_MatDiffuse[0]);
if (n_dot_h > 0.0F) {
GLfloat spec;
GET_SHINE_TAB_ENTRY( ctx->_ShineTable[0], n_dot_h, spec );
ACC_SCALE_SCALAR_3V(sum, spec, light->_MatSpecular[0]);
 
}
UNCLAMPED_FLOAT_TO_RGB_CHAN(Fcolor[j], sum );
Fcolor[j][3] = basechan[0][3];
if (IDX & LIGHT_TWOSIDE) COPY_CHAN4(Bcolor[j], basechan[1]);
}
 
j++;
CMSTRIDE;
STRIDE_F(normal, NSTRIDE);
} while (DO_ANOTHER_NORMAL(j));
 
 
for ( ; REUSE_LIGHT_RESULTS(j) ; j++, CMSTRIDE, STRIDE_F(normal,NSTRIDE))
{
COPY_CHAN4(Fcolor[j], Fcolor[j-1]);
if (IDX & LIGHT_TWOSIDE)
COPY_CHAN4(Bcolor[j], Bcolor[j-1]);
}
 
} while (!CHECK_END_VB(j));
}
 
 
/* Light infinite lights
*/
static void TAG(light_fast_rgba)( GLcontext *ctx,
struct vertex_buffer *VB,
struct gl_pipeline_stage *stage,
GLvector4f *input )
{
struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
GLchan sumA[2];
const GLuint nstride = VB->NormalPtr->stride;
const GLfloat *normal = (GLfloat *)VB->NormalPtr->data;
GLfloat *CMcolor;
GLuint CMstride;
GLchan (*Fcolor)[4] = (GLchan (*)[4]) store->LitColor[0].Ptr;
GLchan (*Bcolor)[4] = (GLchan (*)[4]) store->LitColor[1].Ptr;
const GLuint *flags = VB->Flag;
GLuint j = 0;
struct gl_material (*new_material)[2] = VB->Material;
GLuint *new_material_mask = VB->MaterialMask;
const GLuint nr = VB->Count;
const struct gl_light *light;
 
#ifdef TRACE
fprintf(stderr, "%s\n", __FUNCTION__ );
#endif
 
(void) flags;
(void) input;
(void) nr;
(void) nstride;
 
UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material[0].Diffuse[3]);
UNCLAMPED_FLOAT_TO_CHAN(sumA[1], ctx->Light.Material[1].Diffuse[3]);
 
if (IDX & LIGHT_COLORMATERIAL) {
if (VB->ColorPtr[0]->Type != GL_FLOAT ||
VB->ColorPtr[0]->Size != 4)
import_color_material( ctx, stage );
 
CMcolor = (GLfloat *)VB->ColorPtr[0]->Ptr;
CMstride = VB->ColorPtr[0]->StrideB;
}
 
VB->ColorPtr[0] = &store->LitColor[0];
if (IDX & LIGHT_TWOSIDE)
VB->ColorPtr[1] = &store->LitColor[1];
 
if (stage->changed_inputs == 0)
return;
 
do {
do {
GLfloat sum[2][3];
 
if ( CHECK_COLOR_MATERIAL(j) )
_mesa_update_color_material( ctx, CMcolor );
 
if ( CHECK_MATERIAL(j) )
_mesa_update_material( ctx, new_material[j], new_material_mask[j] );
 
if ( CHECK_VALIDATE(j) ) {
TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx );
UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material[0].Diffuse[3]);
if (IDX & LIGHT_TWOSIDE)
UNCLAMPED_FLOAT_TO_CHAN(sumA[1],
ctx->Light.Material[1].Diffuse[3]);
}
 
 
COPY_3V(sum[0], ctx->Light._BaseColor[0]);
if (IDX & LIGHT_TWOSIDE)
COPY_3V(sum[1], ctx->Light._BaseColor[1]);
 
foreach (light, &ctx->Light.EnabledList) {
GLfloat n_dot_h, n_dot_VP, spec;
 
ACC_3V(sum[0], light->_MatAmbient[0]);
if (IDX & LIGHT_TWOSIDE)
ACC_3V(sum[1], light->_MatAmbient[1]);
 
n_dot_VP = DOT3(normal, light->_VP_inf_norm);
 
if (n_dot_VP > 0.0F) {
ACC_SCALE_SCALAR_3V(sum[0], n_dot_VP, light->_MatDiffuse[0]);
n_dot_h = DOT3(normal, light->_h_inf_norm);
if (n_dot_h > 0.0F) {
struct gl_shine_tab *tab = ctx->_ShineTable[0];
GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec );
ACC_SCALE_SCALAR_3V( sum[0], spec,
light->_MatSpecular[0]);
}
}
else if (IDX & LIGHT_TWOSIDE) {
ACC_SCALE_SCALAR_3V(sum[1], -n_dot_VP, light->_MatDiffuse[1]);
n_dot_h = -DOT3(normal, light->_h_inf_norm);
if (n_dot_h > 0.0F) {
struct gl_shine_tab *tab = ctx->_ShineTable[1];
GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec );
ACC_SCALE_SCALAR_3V( sum[1], spec,
light->_MatSpecular[1]);
}
}
}
 
UNCLAMPED_FLOAT_TO_RGB_CHAN( Fcolor[j], sum[0] );
Fcolor[j][3] = sumA[0];
 
if (IDX & LIGHT_TWOSIDE) {
UNCLAMPED_FLOAT_TO_RGB_CHAN( Bcolor[j], sum[1] );
Bcolor[j][3] = sumA[1];
}
 
j++;
CMSTRIDE;
STRIDE_F(normal, NSTRIDE);
} while (DO_ANOTHER_NORMAL(j));
 
/* Reuse the shading results while there is no change to
* normal or material values.
*/
for ( ; REUSE_LIGHT_RESULTS(j) ; j++, CMSTRIDE, STRIDE_F(normal, NSTRIDE))
{
COPY_CHAN4(Fcolor[j], Fcolor[j-1]);
if (IDX & LIGHT_TWOSIDE)
COPY_CHAN4(Bcolor[j], Bcolor[j-1]);
}
 
} while (!CHECK_END_VB(j));
}
 
 
 
 
 
/*
* Use current lighting/material settings to compute the color indexes
* for an array of vertices.
* Input: n - number of vertices to light
* side - 0=use front material, 1=use back material
* vertex - array of [n] vertex position in eye coordinates
* normal - array of [n] surface normal vector
* Output: indexResult - resulting array of [n] color indexes
*/
static void TAG(light_ci)( GLcontext *ctx,
struct vertex_buffer *VB,
struct gl_pipeline_stage *stage,
GLvector4f *input )
{
struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
GLuint j;
const GLuint vstride = input->stride;
const GLfloat *vertex = (GLfloat *) input->data;
const GLuint nstride = VB->NormalPtr->stride;
const GLfloat *normal = (GLfloat *)VB->NormalPtr->data;
GLfloat *CMcolor;
GLuint CMstride;
const GLuint *flags = VB->Flag;
GLuint *indexResult[2];
struct gl_material (*new_material)[2] = VB->Material;
GLuint *new_material_mask = VB->MaterialMask;
const GLuint nr = VB->Count;
 
#ifdef TRACE
fprintf(stderr, "%s\n", __FUNCTION__ );
#endif
 
(void) flags;
(void) nstride;
(void) vstride;
 
VB->IndexPtr[0] = &store->LitIndex[0];
if (IDX & LIGHT_TWOSIDE)
VB->IndexPtr[1] = &store->LitIndex[1];
 
if (stage->changed_inputs == 0)
return;
 
indexResult[0] = VB->IndexPtr[0]->data;
if (IDX & LIGHT_TWOSIDE)
indexResult[1] = VB->IndexPtr[1]->data;
 
if (IDX & LIGHT_COLORMATERIAL) {
if (VB->ColorPtr[0]->Type != GL_FLOAT ||
VB->ColorPtr[0]->Size != 4)
import_color_material( ctx, stage );
 
CMcolor = (GLfloat *)VB->ColorPtr[0]->Ptr;
CMstride = VB->ColorPtr[0]->StrideB;
}
 
/* loop over vertices */
for ( j=0 ;
j<nr ;
j++,STRIDE_F(vertex,VSTRIDE),STRIDE_F(normal, NSTRIDE), CMSTRIDE)
{
GLfloat diffuse[2], specular[2];
GLuint side = 0;
struct gl_light *light;
 
if ( CHECK_COLOR_MATERIAL(j) )
_mesa_update_color_material( ctx, CMcolor );
 
if ( CHECK_MATERIAL(j) )
_mesa_update_material( ctx, new_material[j], new_material_mask[j] );
 
if ( CHECK_VALIDATE(j) )
TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx );
 
diffuse[0] = specular[0] = 0.0F;
 
if ( IDX & LIGHT_TWOSIDE ) {
diffuse[1] = specular[1] = 0.0F;
}
 
/* Accumulate diffuse and specular from each light source */
foreach (light, &ctx->Light.EnabledList) {
 
GLfloat attenuation = 1.0F;
GLfloat VP[3]; /* unit vector from vertex to light */
GLfloat n_dot_VP; /* dot product of l and n */
GLfloat *h, n_dot_h, correction = 1.0;
 
/* compute l and attenuation */
if (!(light->_Flags & LIGHT_POSITIONAL)) {
/* directional light */
COPY_3V(VP, light->_VP_inf_norm);
}
else {
GLfloat d; /* distance from vertex to light */
 
SUB_3V(VP, light->_Position, vertex);
 
d = (GLfloat) LEN_3FV( VP );
if ( d > 1e-6) {
GLfloat invd = 1.0F / d;
SELF_SCALE_SCALAR_3V(VP, invd);
}
 
attenuation = 1.0F / (light->ConstantAttenuation + d *
(light->LinearAttenuation + d *
light->QuadraticAttenuation));
 
/* spotlight attenuation */
if (light->_Flags & LIGHT_SPOT) {
GLfloat PV_dot_dir = - DOT3(VP, light->_NormDirection);
if (PV_dot_dir < light->_CosCutoff) {
continue; /* this light makes no contribution */
}
else {
GLdouble x = PV_dot_dir * (EXP_TABLE_SIZE-1);
GLint k = (GLint) x;
GLfloat spot = (GLfloat) (light->_SpotExpTable[k][0]
+ (x-k)*light->_SpotExpTable[k][1]);
attenuation *= spot;
}
}
}
 
if (attenuation < 1e-3)
continue; /* this light makes no contribution */
 
n_dot_VP = DOT3( normal, VP );
 
/* which side are we lighting? */
if (n_dot_VP < 0.0F) {
if (!(IDX & LIGHT_TWOSIDE))
continue;
side = 1;
correction = -1;
n_dot_VP = -n_dot_VP;
}
 
/* accumulate diffuse term */
diffuse[side] += n_dot_VP * light->_dli * attenuation;
 
/* specular term */
if (ctx->Light.Model.LocalViewer) {
GLfloat v[3];
COPY_3V(v, vertex);
NORMALIZE_3FV(v);
SUB_3V(VP, VP, v); /* h = VP + VPe */
h = VP;
NORMALIZE_3FV(h);
}
else if (light->_Flags & LIGHT_POSITIONAL) {
h = VP;
/* Strangely, disabling this addition fixes a conformance
* problem. If this code is enabled, l_sed.c fails.
*/
/*ACC_3V(h, ctx->_EyeZDir);*/
NORMALIZE_3FV(h);
}
else {
h = light->_h_inf_norm;
}
 
n_dot_h = correction * DOT3(normal, h);
if (n_dot_h > 0.0F) {
GLfloat spec_coef;
struct gl_shine_tab *tab = ctx->_ShineTable[side];
GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef);
specular[side] += spec_coef * light->_sli * attenuation;
}
} /*loop over lights*/
 
/* Now compute final color index */
for (side = 0 ; side < NR_SIDES ; side++) {
struct gl_material *mat = &ctx->Light.Material[side];
GLfloat index;
 
if (specular[side] > 1.0F) {
index = mat->SpecularIndex;
}
else {
GLfloat d_a = mat->DiffuseIndex - mat->AmbientIndex;
GLfloat s_a = mat->SpecularIndex - mat->AmbientIndex;
 
index = mat->AmbientIndex
+ diffuse[side] * (1.0F-specular[side]) * d_a
+ specular[side] * s_a;
 
if (index > mat->SpecularIndex) {
index = mat->SpecularIndex;
}
}
indexResult[side][j] = (GLuint) (GLint) index;
}
} /*for vertex*/
}
 
 
 
static void TAG(init_light_tab)( void )
{
_tnl_light_tab[IDX] = TAG(light_rgba);
_tnl_light_fast_tab[IDX] = TAG(light_fast_rgba);
_tnl_light_fast_single_tab[IDX] = TAG(light_fast_rgba_single);
_tnl_light_spec_tab[IDX] = TAG(light_rgba_spec);
_tnl_light_ci_tab[IDX] = TAG(light_ci);
}
 
 
#undef TAG
#undef IDX
#undef NR_SIDES
#undef NSTRIDE
#undef VSTRIDE
#undef CHECK_MATERIAL
#undef CHECK_END_VB
#undef DO_ANOTHER_NORMAL
#undef REUSE_LIGHT_RESULTS
#undef CMSTRIDE
#undef CHECK_COLOR_MATERIAL
#undef CHECK_VALIDATE
/shark/trunk/ports/mesa/src/tnl/t_context.c
0,0 → 1,244
/* $Id: t_context.c,v 1.1 2003-02-28 11:48:06 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
 
#include "glheader.h"
#include "imports.h"
#include "macros.h"
#include "mtypes.h"
#include "dlist.h"
#include "light.h"
#include "vtxfmt.h"
 
#include "t_context.h"
#include "t_array_api.h"
#include "t_eval_api.h"
#include "t_imm_alloc.h"
#include "t_imm_api.h"
#include "t_imm_exec.h"
#include "t_imm_dlist.h"
#include "t_pipeline.h"
#include "tnl.h"
 
#ifndef THREADS
struct immediate *_tnl_CurrentInput = NULL;
#endif
 
 
void
_tnl_MakeCurrent( GLcontext *ctx,
GLframebuffer *drawBuffer,
GLframebuffer *readBuffer )
{
#ifndef THREADS
SET_IMMEDIATE( ctx, TNL_CURRENT_IM(ctx) );
#endif
}
 
 
static void
install_driver_callbacks( GLcontext *ctx )
{
ctx->Driver.NewList = _tnl_NewList;
ctx->Driver.EndList = _tnl_EndList;
ctx->Driver.FlushVertices = _tnl_flush_vertices;
ctx->Driver.MakeCurrent = _tnl_MakeCurrent;
ctx->Driver.BeginCallList = _tnl_BeginCallList;
ctx->Driver.EndCallList = _tnl_EndCallList;
}
 
 
 
GLboolean
_tnl_CreateContext( GLcontext *ctx )
{
TNLcontext *tnl;
 
/* Create the TNLcontext structure
*/
ctx->swtnl_context = tnl = (TNLcontext *) CALLOC( sizeof(TNLcontext) );
 
if (!tnl) {
return GL_FALSE;
}
 
/* Initialize the VB.
*/
tnl->vb.Size = MAX2( IMM_SIZE,
ctx->Const.MaxArrayLockSize + MAX_CLIPPED_VERTICES);
 
 
/* Initialize tnl state and tnl->vtxfmt.
*/
_tnl_dlist_init( ctx );
_tnl_array_init( ctx );
_tnl_imm_init( ctx );
_tnl_eval_init( ctx );
_tnl_install_pipeline( ctx, _tnl_default_pipeline );
 
 
tnl->NeedNdcCoords = GL_TRUE;
tnl->LoopbackDListCassettes = GL_FALSE;
tnl->CalcDListNormalLengths = GL_TRUE;
 
/* Hook our functions into exec and compile dispatch tables.
*/
_mesa_install_exec_vtxfmt( ctx, &tnl->vtxfmt );
 
tnl->save_vtxfmt = tnl->vtxfmt;
tnl->save_vtxfmt.CallList = _mesa_save_CallList;
tnl->save_vtxfmt.EvalMesh1 = _mesa_save_EvalMesh1;
tnl->save_vtxfmt.EvalMesh2 = _mesa_save_EvalMesh2;
tnl->save_vtxfmt.Begin = _tnl_save_Begin;
 
_mesa_install_save_vtxfmt( ctx, &tnl->save_vtxfmt );
 
 
/* Set a few default values in the driver struct.
*/
install_driver_callbacks(ctx);
ctx->Driver.NeedFlush = FLUSH_UPDATE_CURRENT;
ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END;
ctx->Driver.CurrentSavePrimitive = PRIM_UNKNOWN;
 
tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
tnl->Driver.NotifyMaterialChange = _mesa_validate_all_lighting_tables;
 
 
return GL_TRUE;
}
 
 
void
_tnl_DestroyContext( GLcontext *ctx )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
 
_tnl_array_destroy( ctx );
_tnl_imm_destroy( ctx );
_tnl_destroy_pipeline( ctx );
_tnl_free_immediate( ctx, tnl->freed_immediate );
 
FREE(tnl);
ctx->swtnl_context = 0;
}
 
 
void
_tnl_InvalidateState( GLcontext *ctx, GLuint new_state )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
 
if (new_state & _NEW_ARRAY) {
struct immediate *IM = TNL_CURRENT_IM(ctx);
IM->ArrayEltFlags = ~ctx->Array._Enabled;
IM->ArrayEltFlush = (ctx->Array.LockCount
? FLUSH_ELT_LAZY : FLUSH_ELT_EAGER);
IM->ArrayEltIncr = ctx->Array.Vertex.Enabled ? 1 : 0;
tnl->pipeline.run_input_changes |= ctx->Array.NewState; /* overkill */
}
 
tnl->pipeline.run_state_changes |= new_state;
tnl->pipeline.build_state_changes |= (new_state &
tnl->pipeline.build_state_trigger);
 
tnl->eval.EvalNewState |= new_state;
}
 
 
void
_tnl_wakeup_exec( GLcontext *ctx )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
 
install_driver_callbacks(ctx);
ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT;
 
/* Hook our functions into exec and compile dispatch tables.
*/
_mesa_install_exec_vtxfmt( ctx, &tnl->vtxfmt );
 
/* Call all appropriate driver callbacks to revive state.
*/
_tnl_MakeCurrent( ctx, ctx->DrawBuffer, ctx->ReadBuffer );
 
/* Assume we haven't been getting state updates either:
*/
_tnl_InvalidateState( ctx, ~0 );
tnl->pipeline.run_input_changes = ~0;
 
if (ctx->Light.ColorMaterialEnabled) {
_mesa_update_color_material( ctx, ctx->Current.Attrib[VERT_ATTRIB_COLOR0] );
}
 
}
 
 
void
_tnl_wakeup_save_exec( GLcontext *ctx )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
 
_tnl_wakeup_exec( ctx );
_mesa_install_save_vtxfmt( ctx, &tnl->save_vtxfmt );
}
 
 
void
_tnl_need_projected_coords( GLcontext *ctx, GLboolean mode )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
if (tnl->NeedNdcCoords != mode) {
tnl->NeedNdcCoords = mode;
_tnl_InvalidateState( ctx, _NEW_PROJECTION );
}
}
 
void
_tnl_need_dlist_loopback( GLcontext *ctx, GLboolean mode )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
tnl->LoopbackDListCassettes = mode;
}
 
void
_tnl_need_dlist_norm_lengths( GLcontext *ctx, GLboolean mode )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
tnl->CalcDListNormalLengths = mode;
}
 
void
_tnl_isolate_materials( GLcontext *ctx, GLboolean mode )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
tnl->IsolateMaterials = mode;
}
/shark/trunk/ports/mesa/src/tnl/t_imm_dlist.h
0,0 → 1,45
/* $Id: t_imm_dlist.h,v 1.1 2003-02-28 11:48:06 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
#ifndef _T_DLIST_H
#define _T_DLIST_H
 
#include "mtypes.h"
#include "t_context.h"
 
extern void _tnl_dlist_init( GLcontext *ctx );
 
extern void _tnl_compile_cassette( GLcontext *ctx, struct immediate *IM );
extern void _tnl_EndList( GLcontext *ctx );
extern void _tnl_NewList( GLcontext *ctx, GLuint list, GLenum mode );
 
extern void _tnl_EndCallList( GLcontext *ctx );
extern void _tnl_BeginCallList( GLcontext *ctx, GLuint list );
 
#endif
/shark/trunk/ports/mesa/src/tnl/t_imm_elt.c
0,0 → 1,834
/* $Id: t_imm_elt.c,v 1.1 2003-02-28 11:48:06 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 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.
*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
#include "glheader.h"
#include "colormac.h"
#include "context.h"
#include "imports.h"
#include "mmath.h"
#include "mtypes.h"
 
#include "math/m_translate.h"
 
#include "t_context.h"
#include "t_imm_elt.h"
 
 
 
typedef void (*trans_elt_1f_func)(GLfloat *to,
CONST void *ptr,
GLuint stride,
GLuint *flags,
GLuint *elts,
GLuint match,
GLuint start,
GLuint n );
 
typedef void (*trans_elt_1ui_func)(GLuint *to,
CONST void *ptr,
GLuint stride,
GLuint *flags,
GLuint *elts,
GLuint match,
GLuint start,
GLuint n );
 
typedef void (*trans_elt_1ub_func)(GLubyte *to,
CONST void *ptr,
GLuint stride,
GLuint *flags,
GLuint *elts,
GLuint match,
GLuint start,
GLuint n );
 
typedef void (*trans_elt_4ub_func)(GLubyte (*to)[4],
CONST void *ptr,
GLuint stride,
GLuint *flags,
GLuint *elts,
GLuint match,
GLuint start,
GLuint n );
 
typedef void (*trans_elt_4us_func)(GLushort (*to)[4],
CONST void *ptr,
GLuint stride,
GLuint *flags,
GLuint *elts,
GLuint match,
GLuint start,
GLuint n );
 
typedef void (*trans_elt_4f_func)(GLfloat (*to)[4],
CONST void *ptr,
GLuint stride,
GLuint *flags,
GLuint *elts,
GLuint match,
GLuint start,
GLuint n );
 
typedef void (*trans_elt_3f_func)(GLfloat (*to)[3],
CONST void *ptr,
GLuint stride,
GLuint *flags,
GLuint *elts,
GLuint match,
GLuint start,
GLuint n );
 
 
 
 
static trans_elt_1f_func _tnl_trans_elt_1f_tab[MAX_TYPES];
static trans_elt_1ui_func _tnl_trans_elt_1ui_tab[MAX_TYPES];
static trans_elt_1ub_func _tnl_trans_elt_1ub_tab[MAX_TYPES];
static trans_elt_3f_func _tnl_trans_elt_3f_tab[MAX_TYPES];
static trans_elt_4ub_func _tnl_trans_elt_4ub_tab[5][MAX_TYPES];
static trans_elt_4us_func _tnl_trans_elt_4us_tab[5][MAX_TYPES];
static trans_elt_4f_func _tnl_trans_elt_4f_tab[5][MAX_TYPES];
 
 
#define PTR_ELT(ptr, elt) (((SRC *)ptr)[elt])
 
 
 
 
 
/* Code specific to array element implementation. There is a small
* subtlety in the bits CHECK() tests, and the way bits are set in
* glArrayElement which ensures that if, eg, in the case that the
* vertex array is disabled and normal array is enabled, and we get
* either sequence:
*
* ArrayElement() OR Normal()
* Normal() ArrayElement()
* Vertex() Vertex()
*
* That the correct value for normal is used.
*/
#define TAB(x) _tnl_trans_elt##x##_tab
#define ARGS GLuint *flags, GLuint *elts, GLuint match, \
GLuint start, GLuint n
#define SRC_START 0
#define DST_START start
#define CHECK if ((flags[i]&match) == VERT_BIT_ELT)
#define NEXT_F (void)1
#define NEXT_F2 f = first + elts[i] * stride;
 
 
/* GL_BYTE
*/
#define SRC GLbyte
#define SRC_IDX TYPE_IDX(GL_BYTE)
#define TRX_3F(f,n) BYTE_TO_FLOAT( PTR_ELT(f,n) )
#define TRX_4F(f,n) BYTE_TO_FLOAT( PTR_ELT(f,n) )
#define TRX_UB(ub, f,n) ub = BYTE_TO_UBYTE( PTR_ELT(f,n) )
#define TRX_US(us, f,n) us = BYTE_TO_USHORT( PTR_ELT(f,n) )
#define TRX_UI(f,n) (PTR_ELT(f,n) < 0 ? 0 : (GLuint) PTR_ELT(f,n))
 
 
#define SZ 4
#define INIT init_trans_4_GLbyte_elt
#define DEST_4F trans_4_GLbyte_4f_elt
#define DEST_4UB trans_4_GLbyte_4ub_elt
#define DEST_4US trans_4_GLbyte_4us_elt
#include "math/m_trans_tmp.h"
 
#define SZ 3
#define INIT init_trans_3_GLbyte_elt
#define DEST_4F trans_3_GLbyte_4f_elt
#define DEST_4UB trans_3_GLbyte_4ub_elt
#define DEST_4US trans_3_GLbyte_4us_elt
#define DEST_3F trans_3_GLbyte_3f_elt
#include "math/m_trans_tmp.h"
 
#define SZ 2
#define INIT init_trans_2_GLbyte_elt
#define DEST_4F trans_2_GLbyte_4f_elt
#include "math/m_trans_tmp.h"
 
#define SZ 1
#define INIT init_trans_1_GLbyte_elt
#define DEST_4F trans_1_GLbyte_4f_elt
#define DEST_1UB trans_1_GLbyte_1ub_elt
#define DEST_1UI trans_1_GLbyte_1ui_elt
#include "math/m_trans_tmp.h"
 
#undef SRC
#undef TRX_3F
#undef TRX_4F
#undef TRX_UB
#undef TRX_US
#undef TRX_UI
#undef SRC_IDX
 
/* GL_UNSIGNED_BYTE
*/
#define SRC GLubyte
#define SRC_IDX TYPE_IDX(GL_UNSIGNED_BYTE)
#define TRX_3F(f,n) UBYTE_TO_FLOAT( PTR_ELT(f,n) )
#define TRX_4F(f,n) UBYTE_TO_FLOAT( PTR_ELT(f,n) )
#define TRX_UB(ub, f,n) ub = PTR_ELT(f,n)
#define TRX_US(us, f,n) us = PTR_ELT(f,n)
#define TRX_UI(f,n) (GLuint)PTR_ELT(f,n)
 
/* 4ub->4ub handled in special case below.
*/
#define SZ 4
#define INIT init_trans_4_GLubyte_elt
#define DEST_4F trans_4_GLubyte_4f_elt
#define DEST_4US trans_4_GLubyte_4us_elt
#include "math/m_trans_tmp.h"
 
#define SZ 3
#define INIT init_trans_3_GLubyte_elt
#define DEST_4F trans_3_GLubyte_4f_elt
#define DEST_3F trans_3_GLubyte_3f_elt
#define DEST_4UB trans_3_GLubyte_4ub_elt
#define DEST_4US trans_3_GLubyte_4us_elt
#include "math/m_trans_tmp.h"
 
 
#define SZ 1
#define INIT init_trans_1_GLubyte_elt
#define DEST_1UI trans_1_GLubyte_1ui_elt
#define DEST_1UB trans_1_GLubyte_1ub_elt
#include "math/m_trans_tmp.h"
 
#undef SRC
#undef SRC_IDX
#undef TRX_3F
#undef TRX_4F
#undef TRX_UB
#undef TRX_US
#undef TRX_UI
 
 
/* GL_SHORT
*/
#define SRC GLshort
#define SRC_IDX TYPE_IDX(GL_SHORT)
#define TRX_3F(f,n) SHORT_TO_FLOAT( PTR_ELT(f,n) )
#define TRX_4F(f,n) (GLfloat)( PTR_ELT(f,n) )
#define TRX_UB(ub, f,n) ub = SHORT_TO_UBYTE(PTR_ELT(f,n))
#define TRX_US(us, f,n) us = SHORT_TO_USHORT(PTR_ELT(f,n))
#define TRX_UI(f,n) (PTR_ELT(f,n) < 0 ? 0 : (GLuint) PTR_ELT(f,n))
 
 
#define SZ 4
#define INIT init_trans_4_GLshort_elt
#define DEST_4F trans_4_GLshort_4f_elt
#define DEST_4UB trans_4_GLshort_4ub_elt
#define DEST_4US trans_4_GLshort_4us_elt
#include "math/m_trans_tmp.h"
 
#define SZ 3
#define INIT init_trans_3_GLshort_elt
#define DEST_4F trans_3_GLshort_4f_elt
#define DEST_4UB trans_3_GLshort_4ub_elt
#define DEST_4US trans_3_GLshort_4us_elt
#define DEST_3F trans_3_GLshort_3f_elt
#include "math/m_trans_tmp.h"
 
#define SZ 2
#define INIT init_trans_2_GLshort_elt
#define DEST_4F trans_2_GLshort_4f_elt
#include "math/m_trans_tmp.h"
 
#define SZ 1
#define INIT init_trans_1_GLshort_elt
#define DEST_4F trans_1_GLshort_4f_elt
#define DEST_1UB trans_1_GLshort_1ub_elt
#define DEST_1UI trans_1_GLshort_1ui_elt
#include "math/m_trans_tmp.h"
 
 
#undef SRC
#undef SRC_IDX
#undef TRX_3F
#undef TRX_4F
#undef TRX_UB
#undef TRX_US
#undef TRX_UI
 
 
/* GL_UNSIGNED_SHORT
*/
#define SRC GLushort
#define SRC_IDX TYPE_IDX(GL_UNSIGNED_SHORT)
#define TRX_3F(f,n) USHORT_TO_FLOAT( PTR_ELT(f,n) )
#define TRX_4F(f,n) (GLfloat)( PTR_ELT(f,n) )
#define TRX_UB(ub,f,n) ub = (GLubyte) (PTR_ELT(f,n) >> 8)
#define TRX_US(us,f,n) us = PTR_ELT(f,n)
#define TRX_UI(f,n) (GLuint) PTR_ELT(f,n)
 
 
#define SZ 4
#define INIT init_trans_4_GLushort_elt
#define DEST_4F trans_4_GLushort_4f_elt
#define DEST_4UB trans_4_GLushort_4ub_elt
#define DEST_4US trans_4_GLushort_4us_elt
#include "math/m_trans_tmp.h"
 
#define SZ 3
#define INIT init_trans_3_GLushort_elt
#define DEST_4F trans_3_GLushort_4f_elt
#define DEST_4UB trans_3_GLushort_4ub_elt
#define DEST_4US trans_3_GLushort_4us_elt
#define DEST_3F trans_3_GLushort_3f_elt
#include "math/m_trans_tmp.h"
 
#define SZ 2
#define INIT init_trans_2_GLushort_elt
#define DEST_4F trans_2_GLushort_4f_elt
#include "math/m_trans_tmp.h"
 
#define SZ 1
#define INIT init_trans_1_GLushort_elt
#define DEST_4F trans_1_GLushort_4f_elt
#define DEST_1UB trans_1_GLushort_1ub_elt
#define DEST_1UI trans_1_GLushort_1ui_elt
#include "math/m_trans_tmp.h"
 
#undef SRC
#undef SRC_IDX
#undef TRX_3F
#undef TRX_4F
#undef TRX_UB
#undef TRX_US
#undef TRX_UI
 
 
/* GL_INT
*/
#define SRC GLint
#define SRC_IDX TYPE_IDX(GL_INT)
#define TRX_3F(f,n) INT_TO_FLOAT( PTR_ELT(f,n) )
#define TRX_4F(f,n) (GLfloat)( PTR_ELT(f,n) )
#define TRX_UB(ub, f,n) ub = INT_TO_UBYTE(PTR_ELT(f,n))
#define TRX_US(us, f,n) us = INT_TO_USHORT(PTR_ELT(f,n))
#define TRX_UI(f,n) (PTR_ELT(f,n) < 0 ? 0 : (GLuint) PTR_ELT(f,n))
 
 
#define SZ 4
#define INIT init_trans_4_GLint_elt
#define DEST_4F trans_4_GLint_4f_elt
#define DEST_4UB trans_4_GLint_4ub_elt
#define DEST_4US trans_4_GLint_4us_elt
#include "math/m_trans_tmp.h"
 
#define SZ 3
#define INIT init_trans_3_GLint_elt
#define DEST_4F trans_3_GLint_4f_elt
#define DEST_4UB trans_3_GLint_4ub_elt
#define DEST_4US trans_3_GLint_4us_elt
#define DEST_3F trans_3_GLint_3f_elt
#include "math/m_trans_tmp.h"
 
#define SZ 2
#define INIT init_trans_2_GLint_elt
#define DEST_4F trans_2_GLint_4f_elt
#include "math/m_trans_tmp.h"
 
#define SZ 1
#define INIT init_trans_1_GLint_elt
#define DEST_4F trans_1_GLint_4f_elt
#define DEST_1UB trans_1_GLint_1ub_elt
#define DEST_1UI trans_1_GLint_1ui_elt
#include "math/m_trans_tmp.h"
 
 
#undef SRC
#undef SRC_IDX
#undef TRX_3F
#undef TRX_4F
#undef TRX_UB
#undef TRX_US
#undef TRX_UI
 
 
/* GL_UNSIGNED_INT
*/
#define SRC GLuint
#define SRC_IDX TYPE_IDX(GL_UNSIGNED_INT)
#define TRX_3F(f,n) UINT_TO_FLOAT( PTR_ELT(f,n) )
#define TRX_4F(f,n) (GLfloat)( PTR_ELT(f,n) )
#define TRX_UB(ub, f,n) ub = (GLubyte) (PTR_ELT(f,n) >> 24)
#define TRX_US(us, f,n) us = (GLushort) (PTR_ELT(f,n) >> 16)
#define TRX_UI(f,n) PTR_ELT(f,n)
 
 
#define SZ 4
#define INIT init_trans_4_GLuint_elt
#define DEST_4F trans_4_GLuint_4f_elt
#define DEST_4UB trans_4_GLuint_4ub_elt
#define DEST_4US trans_4_GLuint_4us_elt
#include "math/m_trans_tmp.h"
 
#define SZ 3
#define INIT init_trans_3_GLuint_elt
#define DEST_4F trans_3_GLuint_4f_elt
#define DEST_4UB trans_3_GLuint_4ub_elt
#define DEST_4US trans_3_GLuint_4us_elt
#define DEST_3F trans_3_GLuint_3f_elt
#include "math/m_trans_tmp.h"
 
#define SZ 2
#define INIT init_trans_2_GLuint_elt
#define DEST_4F trans_2_GLuint_4f_elt
#include "math/m_trans_tmp.h"
 
#define SZ 1
#define INIT init_trans_1_GLuint_elt
#define DEST_4F trans_1_GLuint_4f_elt
#define DEST_1UB trans_1_GLuint_1ub_elt
#define DEST_1UI trans_1_GLuint_1ui_elt
#include "math/m_trans_tmp.h"
 
#undef SRC
#undef SRC_IDX
#undef TRX_3F
#undef TRX_4F
#undef TRX_UB
#undef TRX_US
#undef TRX_UI
 
 
/* GL_DOUBLE
*/
#define SRC GLdouble
#define SRC_IDX TYPE_IDX(GL_DOUBLE)
#define TRX_3F(f,n) (GLfloat) PTR_ELT(f,n)
#define TRX_4F(f,n) (GLfloat) PTR_ELT(f,n)
#define TRX_UB(ub,f,n) UNCLAMPED_FLOAT_TO_UBYTE(ub, PTR_ELT(f,n))
#define TRX_US(us,f,n) UNCLAMPED_FLOAT_TO_USHORT(us, PTR_ELT(f,n))
#define TRX_UI(f,n) (GLuint) (GLint) PTR_ELT(f,n)
#define TRX_1F(f,n) (GLfloat) PTR_ELT(f,n)
 
 
#define SZ 4
#define INIT init_trans_4_GLdouble_elt
#define DEST_4F trans_4_GLdouble_4f_elt
#define DEST_4UB trans_4_GLdouble_4ub_elt
#define DEST_4US trans_4_GLdouble_4us_elt
#include "math/m_trans_tmp.h"
 
#define SZ 3
#define INIT init_trans_3_GLdouble_elt
#define DEST_4F trans_3_GLdouble_4f_elt
#define DEST_4UB trans_3_GLdouble_4ub_elt
#define DEST_4US trans_3_GLdouble_4us_elt
#define DEST_3F trans_3_GLdouble_3f_elt
#include "math/m_trans_tmp.h"
 
#define SZ 2
#define INIT init_trans_2_GLdouble_elt
#define DEST_4F trans_2_GLdouble_4f_elt
#include "math/m_trans_tmp.h"
 
#define SZ 1
#define INIT init_trans_1_GLdouble_elt
#define DEST_4F trans_1_GLdouble_4f_elt
#define DEST_1UB trans_1_GLdouble_1ub_elt
#define DEST_1UI trans_1_GLdouble_1ui_elt
#define DEST_1F trans_1_GLdouble_1f_elt
#include "math/m_trans_tmp.h"
 
#undef SRC
#undef SRC_IDX
 
/* GL_FLOAT
*/
#define SRC GLfloat
#define SRC_IDX TYPE_IDX(GL_FLOAT)
#define SZ 4
#define INIT init_trans_4_GLfloat_elt
#define DEST_4UB trans_4_GLfloat_4ub_elt
#define DEST_4US trans_4_GLfloat_4us_elt
#define DEST_4F trans_4_GLfloat_4f_elt
#include "math/m_trans_tmp.h"
 
#define SZ 3
#define INIT init_trans_3_GLfloat_elt
#define DEST_4F trans_3_GLfloat_4f_elt
#define DEST_4UB trans_3_GLfloat_4ub_elt
#define DEST_4US trans_3_GLfloat_4us_elt
#define DEST_3F trans_3_GLfloat_3f_elt
#include "math/m_trans_tmp.h"
 
#define SZ 2
#define INIT init_trans_2_GLfloat_elt
#define DEST_4F trans_2_GLfloat_4f_elt
#include "math/m_trans_tmp.h"
 
#define SZ 1
#define INIT init_trans_1_GLfloat_elt
#define DEST_4F trans_1_GLfloat_3f_elt
#define DEST_1UB trans_1_GLfloat_1ub_elt
#define DEST_1UI trans_1_GLfloat_1ui_elt
#define DEST_1F trans_1_GLfloat_1f_elt
#include "math/m_trans_tmp.h"
 
#undef SRC
#undef SRC_IDX
#undef TRX_3F
#undef TRX_4F
#undef TRX_UB
#undef TRX_US
#undef TRX_UI
 
 
static void trans_4_GLubyte_4ub(GLubyte (*t)[4],
CONST void *Ptr,
GLuint stride,
ARGS )
{
const GLubyte *f = (GLubyte *) Ptr + SRC_START * stride;
const GLubyte *first = f;
GLuint i;
(void) start;
if (((((long) f | (long) stride)) & 3L) == 0L) {
/* Aligned.
*/
for (i = DST_START ; i < n ; i++, NEXT_F) {
CHECK {
NEXT_F2;
COPY_4UBV( t[i], f );
}
}
} else {
for (i = DST_START ; i < n ; i++, NEXT_F) {
CHECK {
NEXT_F2;
t[i][0] = f[0];
t[i][1] = f[1];
t[i][2] = f[2];
t[i][3] = f[3];
}
}
}
}
 
 
static void init_translate_elt(void)
{
MEMSET( TAB(_1ui), 0, sizeof(TAB(_1ui)) );
MEMSET( TAB(_1ub), 0, sizeof(TAB(_1ub)) );
MEMSET( TAB(_3f), 0, sizeof(TAB(_3f)) );
MEMSET( TAB(_4ub), 0, sizeof(TAB(_4ub)) );
MEMSET( TAB(_4us), 0, sizeof(TAB(_4us)) );
MEMSET( TAB(_4f), 0, sizeof(TAB(_4f)) );
 
TAB(_4ub)[4][TYPE_IDX(GL_UNSIGNED_BYTE)] = trans_4_GLubyte_4ub;
 
init_trans_4_GLbyte_elt();
init_trans_3_GLbyte_elt();
init_trans_2_GLbyte_elt();
init_trans_1_GLbyte_elt();
init_trans_1_GLubyte_elt();
init_trans_3_GLubyte_elt();
init_trans_4_GLubyte_elt();
init_trans_4_GLshort_elt();
init_trans_3_GLshort_elt();
init_trans_2_GLshort_elt();
init_trans_1_GLshort_elt();
init_trans_4_GLushort_elt();
init_trans_3_GLushort_elt();
init_trans_2_GLushort_elt();
init_trans_1_GLushort_elt();
init_trans_4_GLint_elt();
init_trans_3_GLint_elt();
init_trans_2_GLint_elt();
init_trans_1_GLint_elt();
init_trans_4_GLuint_elt();
init_trans_3_GLuint_elt();
init_trans_2_GLuint_elt();
init_trans_1_GLuint_elt();
init_trans_4_GLdouble_elt();
init_trans_3_GLdouble_elt();
init_trans_2_GLdouble_elt();
init_trans_1_GLdouble_elt();
init_trans_4_GLfloat_elt();
init_trans_3_GLfloat_elt();
init_trans_2_GLfloat_elt();
init_trans_1_GLfloat_elt();
}
 
 
#undef TAB
#undef CLASS
#undef ARGS
#undef CHECK
#undef START
 
 
 
 
void _tnl_imm_elt_init( void )
{
init_translate_elt();
}
 
 
#if 00
static void _tnl_trans_elt_1f(GLfloat *to,
const struct gl_client_array *from,
GLuint *flags,
GLuint *elts,
GLuint match,
GLuint start,
GLuint n )
{
_tnl_trans_elt_1f_tab[TYPE_IDX(from->Type)]( to,
from->Ptr,
from->StrideB,
flags,
elts,
match,
start,
n );
 
}
#endif
 
static void _tnl_trans_elt_1ui(GLuint *to,
const struct gl_client_array *from,
GLuint *flags,
GLuint *elts,
GLuint match,
GLuint start,
GLuint n )
{
_tnl_trans_elt_1ui_tab[TYPE_IDX(from->Type)]( to,
from->Ptr,
from->StrideB,
flags,
elts,
match,
start,
n );
 
}
 
 
static void _tnl_trans_elt_1ub(GLubyte *to,
const struct gl_client_array *from,
GLuint *flags,
GLuint *elts,
GLuint match,
GLuint start,
GLuint n )
{
_tnl_trans_elt_1ub_tab[TYPE_IDX(from->Type)]( to,
from->Ptr,
from->StrideB,
flags,
elts,
match,
start,
n );
 
}
 
 
#if 0
static void _tnl_trans_elt_4ub(GLubyte (*to)[4],
const struct gl_client_array *from,
GLuint *flags,
GLuint *elts,
GLuint match,
GLuint start,
GLuint n )
{
_tnl_trans_elt_4ub_tab[from->Size][TYPE_IDX(from->Type)]( to,
from->Ptr,
from->StrideB,
flags,
elts,
match,
start,
n );
 
}
#endif
 
#if 0
static void _tnl_trans_elt_4us(GLushort (*to)[4],
const struct gl_client_array *from,
GLuint *flags,
GLuint *elts,
GLuint match,
GLuint start,
GLuint n )
{
_tnl_trans_elt_4us_tab[from->Size][TYPE_IDX(from->Type)]( to,
from->Ptr,
from->StrideB,
flags,
elts,
match,
start,
n );
 
}
#endif
 
static void _tnl_trans_elt_4f(GLfloat (*to)[4],
const struct gl_client_array *from,
GLuint *flags,
GLuint *elts,
GLuint match,
GLuint start,
GLuint n )
{
_tnl_trans_elt_4f_tab[from->Size][TYPE_IDX(from->Type)]( to,
from->Ptr,
from->StrideB,
flags,
elts,
match,
start,
n );
 
}
 
 
 
#if 0
static void _tnl_trans_elt_3f(GLfloat (*to)[3],
const struct gl_client_array *from,
GLuint *flags,
GLuint *elts,
GLuint match,
GLuint start,
GLuint n )
{
_tnl_trans_elt_3f_tab[TYPE_IDX(from->Type)]( to,
from->Ptr,
from->StrideB,
flags,
elts,
match,
start,
n );
}
#endif
 
 
 
/* Batch function to translate away all the array elements in the
* input buffer prior to transform. Done only the first time a vertex
* buffer is executed or compiled.
*
* KW: Have to do this after each glEnd if arrays aren't locked.
*/
void _tnl_translate_array_elts( GLcontext *ctx, struct immediate *IM,
GLuint start, GLuint count )
{
GLuint *flags = IM->Flag;
GLuint *elts = IM->Elt;
GLuint translate = ctx->Array._Enabled;
GLuint i;
 
if (MESA_VERBOSE & VERBOSE_IMMEDIATE)
_mesa_debug(ctx, "exec_array_elements %d .. %d\n", start, count);
 
if (translate & VERT_BIT_POS) {
_tnl_trans_elt_4f( IM->Attrib[VERT_ATTRIB_POS],
&ctx->Array.Vertex,
flags, elts, (VERT_BIT_ELT|VERT_BIT_POS),
start, count);
 
if (ctx->Array.Vertex.Size == 4)
translate |= VERT_BITS_OBJ_234;
else if (ctx->Array.Vertex.Size == 3)
translate |= VERT_BITS_OBJ_23;
}
 
 
if (translate & VERT_BIT_NORMAL)
_tnl_trans_elt_4f( IM->Attrib[VERT_ATTRIB_NORMAL],
&ctx->Array.Normal,
flags, elts, (VERT_BIT_ELT|VERT_BIT_NORMAL),
start, count);
 
if (translate & VERT_BIT_EDGEFLAG)
_tnl_trans_elt_1ub( IM->EdgeFlag,
&ctx->Array.EdgeFlag,
flags, elts, (VERT_BIT_ELT|VERT_BIT_EDGEFLAG),
start, count);
 
if (translate & VERT_BIT_COLOR0) {
_tnl_trans_elt_4f( IM->Attrib[VERT_ATTRIB_COLOR0],
&ctx->Array.Color,
flags, elts, (VERT_BIT_ELT|VERT_BIT_COLOR0),
start, count);
}
 
if (translate & VERT_BIT_COLOR1) {
_tnl_trans_elt_4f( IM->Attrib[VERT_ATTRIB_COLOR1],
&ctx->Array.SecondaryColor,
flags, elts, (VERT_BIT_ELT|VERT_BIT_COLOR1),
start, count);
}
 
if (translate & VERT_BIT_FOG)
_tnl_trans_elt_4f( IM->Attrib[VERT_ATTRIB_FOG],
&ctx->Array.FogCoord,
flags, elts, (VERT_BIT_ELT|VERT_BIT_FOG),
start, count);
 
if (translate & VERT_BIT_INDEX)
_tnl_trans_elt_1ui( IM->Index,
&ctx->Array.Index,
flags, elts, (VERT_BIT_ELT|VERT_BIT_INDEX),
start, count);
 
if (translate & VERT_BITS_TEX_ANY) {
for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++)
if (translate & VERT_BIT_TEX(i)) {
_tnl_trans_elt_4f( IM->Attrib[VERT_ATTRIB_TEX0 + i],
&ctx->Array.TexCoord[i],
flags, elts, (VERT_BIT_ELT|VERT_BIT_TEX(i)),
start, count);
 
if (ctx->Array.TexCoord[i].Size == 4)
IM->TexSize |= TEX_SIZE_4(i);
else if (ctx->Array.TexCoord[i].Size == 3)
IM->TexSize |= TEX_SIZE_3(i);
}
}
 
for (i = start ; i < count ; i++)
if (flags[i] & VERT_BIT_ELT) flags[i] |= translate;
 
IM->FlushElt = 0;
}
/shark/trunk/ports/mesa/src/tnl/t_imm_exec.c
0,0 → 1,598
/* $Id: t_imm_exec.c,v 1.1 2003-02-28 11:48:07 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
/**
* \file tnl/t_imm_exec.c
* \brief Setup to execute immediate-mode vertex data.
* \author Keith Whitwell
*/
 
#include "glheader.h"
#include "colormac.h"
#include "context.h"
#include "enums.h"
#include "dlist.h"
#include "macros.h"
#include "imports.h"
#include "mmath.h"
#include "light.h"
#include "state.h"
#include "mtypes.h"
 
#include "math/m_matrix.h"
#include "math/m_xform.h"
 
#include "t_context.h"
#include "t_array_import.h"
#include "t_imm_alloc.h"
#include "t_imm_api.h"
#include "t_imm_debug.h"
#include "t_imm_dlist.h"
#include "t_imm_eval.h"
#include "t_imm_elt.h"
#include "t_imm_exec.h"
#include "t_imm_fixup.h"
#include "t_pipeline.h"
 
 
 
static void reset_input( GLcontext *ctx,
GLuint start,
GLuint beginstate,
GLuint savedbeginstate )
{
struct immediate *IM = TNL_CURRENT_IM(ctx);
 
/* Clear the dirty part of the flag array.
*/
if (start < IM->Count+2)
MEMSET(IM->Flag + start, 0, sizeof(GLuint) * (IM->Count+2-start));
 
if (MESA_VERBOSE & VERBOSE_IMMEDIATE)
_mesa_debug(ctx, "reset_input: IM(%d) new %x\n", IM->id, beginstate);
 
IM->Start = start;
IM->Count = start;
IM->LastMaterial = start;
IM->BeginState = beginstate;
IM->SavedBeginState = savedbeginstate;
IM->TexSize = 0;
IM->MaterialOrMask = 0;
 
if (IM->MaterialMask)
IM->MaterialMask[IM->Start] = 0;
 
IM->ArrayEltFlags = ~ctx->Array._Enabled;
IM->ArrayEltIncr = ctx->Array.Vertex.Enabled ? 1 : 0;
IM->ArrayEltFlush = ctx->Array.LockCount ? FLUSH_ELT_LAZY : FLUSH_ELT_EAGER;
}
void _tnl_reset_exec_input( GLcontext *ctx,
GLuint start,
GLuint beginstate,
GLuint savedbeginstate )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct immediate *IM = TNL_CURRENT_IM(ctx);
 
reset_input( ctx, start, beginstate, savedbeginstate );
 
IM->CopyStart = start - tnl->ExecCopyCount;
 
IM->Primitive[IM->CopyStart] = ctx->Driver.CurrentExecPrimitive;
if (tnl->ExecParity)
IM->Primitive[IM->CopyStart] |= PRIM_PARITY;
 
IM->LastPrimitive = IM->CopyStart;
}
 
 
void _tnl_reset_compile_input( GLcontext *ctx,
GLuint start,
GLuint beginstate,
GLuint savedbeginstate )
{
struct immediate *IM = TNL_CURRENT_IM(ctx);
 
reset_input( ctx, start, beginstate, savedbeginstate );
IM->CopyStart = start;
IM->LastPrimitive = IM->Start;
}
 
/**
* Copy the last specified normal, color, texcoord, edge flag, etc
* from the immediate struct into the ctx->Current attribute group.
*/
void _tnl_copy_to_current( GLcontext *ctx, struct immediate *IM,
GLuint flag, GLuint count )
{
if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
_tnl_print_vert_flags("copy to current", flag);
 
/* XXX should be able to replace these conditions with a loop over
* the 16 vertex attributes.
*/
if (flag & VERT_BIT_NORMAL)
COPY_4FV( ctx->Current.Attrib[VERT_ATTRIB_NORMAL],
IM->Attrib[VERT_ATTRIB_NORMAL][count]);
 
if (flag & VERT_BIT_INDEX)
ctx->Current.Index = IM->Index[count];
 
if (flag & VERT_BIT_EDGEFLAG)
ctx->Current.EdgeFlag = IM->EdgeFlag[count];
 
if (flag & VERT_BIT_COLOR0) {
COPY_4FV(ctx->Current.Attrib[VERT_ATTRIB_COLOR0],
IM->Attrib[VERT_ATTRIB_COLOR0][count]);
if (ctx->Light.ColorMaterialEnabled) {
_mesa_update_color_material( ctx,
ctx->Current.Attrib[VERT_ATTRIB_COLOR0] );
TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx );
}
}
 
if (flag & VERT_BIT_COLOR1)
COPY_4FV(ctx->Current.Attrib[VERT_ATTRIB_COLOR1],
IM->Attrib[VERT_ATTRIB_COLOR1][count]);
 
if (flag & VERT_BIT_FOG)
ctx->Current.Attrib[VERT_ATTRIB_FOG][0] = IM->Attrib[VERT_ATTRIB_FOG][count][0];
 
if (flag & VERT_BITS_TEX_ANY) {
GLuint i;
for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) {
if (flag & VERT_BIT_TEX(i)) {
COPY_4FV( ctx->Current.Attrib[VERT_ATTRIB_TEX0 + i],
IM->Attrib[VERT_ATTRIB_TEX0 + i][count]);
}
}
}
 
if (flag & VERT_BIT_MATERIAL) {
_mesa_update_material( ctx,
IM->Material[IM->LastMaterial],
IM->MaterialOrMask );
 
TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx );
}
}
 
 
 
void _tnl_compute_orflag( struct immediate *IM, GLuint start )
{
GLuint count = IM->Count;
GLuint orflag = 0;
GLuint andflag = ~0U;
GLuint i;
 
IM->LastData = count-1;
 
 
/* Compute the flags for the whole buffer.
*/
for (i = start ; i < count ; i++) {
andflag &= IM->Flag[i];
orflag |= IM->Flag[i];
}
 
/* It is possible there will be data in the buffer arising from
* calls like 'glNormal', 'glMaterial' that occur after the final
* glVertex, glEval, etc. Additionally, a buffer can consist of
* eg. a single glMaterial call, in which case IM->Start ==
* IM->Count, but the buffer is definitely not empty.
*/
if (IM->Flag[i] & VERT_BITS_DATA) {
IM->LastData++;
orflag |= IM->Flag[i];
}
 
IM->Flag[IM->LastData+1] |= VERT_BIT_END_VB;
IM->CopyAndFlag = IM->AndFlag = andflag;
IM->OrFlag = orflag;
IM->CopyOrFlag = orflag;
IM->Evaluated = 0;
}
 
 
/**
* This is where the vertex data is transfered from the 'struct immediate
* into the 'struct vertex_buffer'.
*
* Note: The 'start' member of the GLvector structs is now redundant
* because we always re-transform copied vertices, and the vectors
* below are set up so that the first copied vertex (if any) appears
* at position zero.
*/
static void _tnl_vb_bind_immediate( GLcontext *ctx, struct immediate *IM )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
struct vertex_arrays *tmp = &tnl->imm_inputs;
GLuint inputs = tnl->pipeline.inputs; /* for copy-to-current */
const GLuint start = IM->CopyStart;
const GLuint count = IM->Count - start;
 
/* TODO: optimize the case where nothing has changed. (Just bind
* tmp to vb).
*/
 
/* Setup constant data in the VB.
*/
VB->Count = count;
VB->FirstClipped = IMM_MAXDATA - IM->CopyStart;
VB->import_data = NULL;
VB->importable_data = 0;
 
/* Need an IM->FirstPrimitive?
*/
VB->Primitive = IM->Primitive + IM->CopyStart;
VB->PrimitiveLength = IM->PrimitiveLength + IM->CopyStart;
VB->FirstPrimitive = 0;
 
VB->Flag = IM->Flag + start;
 
/* TexCoordPtr's are zeroed in loop below.
*/
VB->NormalPtr = NULL;
VB->NormalLengthPtr = NULL;
VB->EdgeFlag = NULL;
VB->IndexPtr[0] = NULL;
VB->IndexPtr[1] = NULL;
VB->ColorPtr[0] = NULL;
VB->ColorPtr[1] = NULL;
VB->SecondaryColorPtr[0] = NULL;
VB->SecondaryColorPtr[1] = NULL;
VB->Elts = NULL;
VB->MaterialMask = NULL;
VB->Material = NULL;
 
/* _tnl_print_vert_flags("copy-orflag", IM->CopyOrFlag); */
/* _tnl_print_vert_flags("orflag", IM->OrFlag); */
/* _tnl_print_vert_flags("inputs", inputs); */
 
/* Setup the initial values of array pointers in the vb.
*/
if (inputs & VERT_BIT_POS) {
tmp->Obj.data = IM->Attrib[VERT_ATTRIB_POS] + start;
tmp->Obj.start = (GLfloat *)(IM->Attrib[VERT_ATTRIB_POS] + start);
tmp->Obj.count = count;
VB->ObjPtr = &tmp->Obj;
if ((IM->CopyOrFlag & VERT_BITS_OBJ_234) == VERT_BITS_OBJ_234)
tmp->Obj.size = 4;
else if ((IM->CopyOrFlag & VERT_BITS_OBJ_234) == VERT_BITS_OBJ_23)
tmp->Obj.size = 3;
else
tmp->Obj.size = 2;
}
 
if (inputs & VERT_BIT_NORMAL) {
tmp->Normal.data = IM->Attrib[VERT_ATTRIB_NORMAL] + start;
tmp->Normal.start = (GLfloat *) (IM->Attrib[VERT_ATTRIB_NORMAL] + start);
tmp->Normal.count = count;
tmp->Normal.size = 3; /* just to be safe */
VB->NormalPtr = &tmp->Normal;
if (IM->NormalLengthPtr)
VB->NormalLengthPtr = IM->NormalLengthPtr + start;
}
 
if (inputs & VERT_BIT_INDEX) {
tmp->Index.count = count;
tmp->Index.data = IM->Index + start;
tmp->Index.start = IM->Index + start;
VB->IndexPtr[0] = &tmp->Index;
}
 
if (inputs & VERT_BIT_FOG) {
tmp->FogCoord.data = IM->Attrib[VERT_ATTRIB_FOG] + start;
tmp->FogCoord.start = (GLfloat *) (IM->Attrib[VERT_ATTRIB_FOG] + start);
tmp->FogCoord.count = count;
VB->FogCoordPtr = &tmp->FogCoord;
}
 
if (inputs & VERT_BIT_COLOR1) {
tmp->SecondaryColor.Ptr = IM->Attrib[VERT_ATTRIB_COLOR1] + start;
VB->SecondaryColorPtr[0] = &tmp->SecondaryColor;
}
 
if (inputs & VERT_BIT_EDGEFLAG) {
VB->EdgeFlag = IM->EdgeFlag + start;
}
 
if (inputs & VERT_BIT_COLOR0) {
if (IM->CopyOrFlag & VERT_BIT_COLOR0) {
tmp->Color.Ptr = IM->Attrib[VERT_ATTRIB_COLOR0] + start;
tmp->Color.StrideB = 4 * sizeof(GLfloat);
tmp->Color.Flags = 0;
}
else {
tmp->Color.Ptr = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
tmp->Color.StrideB = 0;
tmp->Color.Flags = CA_CLIENT_DATA; /* hack */
VB->import_source = IM;
VB->importable_data |= VERT_BIT_COLOR0;
VB->import_data = _tnl_upgrade_current_data;
}
VB->ColorPtr[0] = &tmp->Color;
}
 
if (inputs & VERT_BITS_TEX_ANY) {
GLuint i;
for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
VB->TexCoordPtr[i] = NULL;
if (inputs & VERT_BIT_TEX(i)) {
tmp->TexCoord[i].count = count;
tmp->TexCoord[i].data = IM->Attrib[VERT_ATTRIB_TEX0 + i] + start;
tmp->TexCoord[i].start = (GLfloat *)(IM->Attrib[VERT_ATTRIB_TEX0 + i] + start);
tmp->TexCoord[i].size = 2;
if (IM->TexSize & TEX_SIZE_3(i)) {
tmp->TexCoord[i].size = 3;
if (IM->TexSize & TEX_SIZE_4(i))
tmp->TexCoord[i].size = 4;
}
VB->TexCoordPtr[i] = &tmp->TexCoord[i];
}
}
}
 
if ((inputs & IM->OrFlag & VERT_BIT_MATERIAL) && IM->Material) {
VB->MaterialMask = IM->MaterialMask + start;
VB->Material = IM->Material + start;
}
 
/* GL_NV_vertex_program */
if (ctx->VertexProgram.Enabled) {
GLuint attr;
for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) {
tmp->Attribs[attr].count = count;
tmp->Attribs[attr].data = IM->Attrib[attr] + start;
tmp->Attribs[attr].start = (GLfloat *) (IM->Attrib[attr] + start);
tmp->Attribs[attr].size = 4;
VB->AttribPtr[attr] = &(tmp->Attribs[attr]);
}
}
}
 
 
 
 
/**
* Called by exec_vert_cassette, execute_compiled_cassette, but not
* exec_elt_cassette.
*/
void _tnl_run_cassette( GLcontext *ctx, struct immediate *IM )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
 
_tnl_vb_bind_immediate( ctx, IM );
 
if (IM->OrFlag & VERT_BITS_EVAL_ANY)
_tnl_eval_immediate( ctx, IM );
 
/* Invalidate all stored data before and after run:
*/
tnl->pipeline.run_input_changes |= tnl->pipeline.inputs;
tnl->Driver.RunPipeline( ctx );
tnl->pipeline.run_input_changes |= tnl->pipeline.inputs;
 
_tnl_copy_to_current( ctx, IM, IM->OrFlag, IM->LastData );
}
 
 
/**
* Called for regular vertex cassettes.
*/
static void exec_vert_cassette( GLcontext *ctx, struct immediate *IM )
{
if (IM->FlushElt) {
/* Orflag is computed twice, but only reach this code if app is
* using a mixture of glArrayElement() and glVertex() while
* arrays are locked (else would be in exec_elt_cassette now).
*/
ASSERT(ctx->Array.LockCount);
ASSERT(IM->FlushElt == FLUSH_ELT_LAZY);
_tnl_translate_array_elts( ctx, IM, IM->CopyStart, IM->Count );
_tnl_compute_orflag( IM, IM->CopyStart );
}
 
_tnl_fixup_input( ctx, IM );
/* _tnl_print_cassette( IM ); */
_tnl_run_cassette( ctx, IM );
}
 
 
/* Called for pure, locked VERT_BIT_ELT cassettes instead of
* _tnl_run_cassette.
*/
static void exec_elt_cassette( GLcontext *ctx, struct immediate *IM )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
 
_tnl_vb_bind_arrays( ctx, ctx->Array.LockFirst, ctx->Array.LockCount );
 
/* Take only elements and primitive information from the immediate:
*/
VB->Elts = IM->Elt + IM->CopyStart;
VB->Primitive = IM->Primitive + IM->CopyStart;
VB->PrimitiveLength = IM->PrimitiveLength + IM->CopyStart;
VB->FirstPrimitive = 0;
 
/* Run the pipeline. No input changes as a result of this action.
*/
tnl->Driver.RunPipeline( ctx );
 
/* Still need to update current values:
*/
if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) {
_tnl_translate_array_elts( ctx, IM, IM->LastData, IM->LastData );
_tnl_copy_to_current( ctx, IM, ctx->Array._Enabled, IM->LastData );
}
}
 
 
static void
exec_empty_cassette( GLcontext *ctx, struct immediate *IM )
{
if (IM->FlushElt)
_tnl_translate_array_elts( ctx, IM, IM->CopyStart, IM->CopyStart );
 
_tnl_copy_to_current( ctx, IM, IM->OrFlag, IM->LastData );
}
 
 
 
/**
* Called for all cassettes when not compiling or playing a display
* list.
*/
void _tnl_execute_cassette( GLcontext *ctx, struct immediate *IM )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
 
_tnl_compute_orflag( IM, IM->Start );
_tnl_copy_immediate_vertices( ctx, IM );
_tnl_get_exec_copy_verts( ctx, IM );
 
if (tnl->pipeline.build_state_changes)
_tnl_validate_pipeline( ctx );
 
if (IM->CopyStart == IM->Count) {
exec_empty_cassette( ctx, IM );
}
else if ((IM->CopyOrFlag & VERT_BITS_DATA) == VERT_BIT_ELT &&
ctx->Array.LockCount &&
ctx->Array.Vertex.Enabled) {
exec_elt_cassette( ctx, IM );
}
else {
exec_vert_cassette( ctx, IM );
}
 
/* Only reuse the immediate if there are no copied vertices living
* inside it:
*/
{
GLuint begin_state = IM->BeginState & (VERT_BEGIN_0|VERT_BEGIN_1);
GLuint saved_begin_state = IM->SavedBeginState;
 
if (--IM->ref_count != 0) {
IM = _tnl_alloc_immediate( ctx );
SET_IMMEDIATE( ctx, IM );
}
 
IM->ref_count++;
_tnl_reset_exec_input( ctx, IMM_MAX_COPIED_VERTS,
begin_state, saved_begin_state );
}
 
if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1)
ctx->Driver.NeedFlush &= ~FLUSH_STORED_VERTICES;
}
 
 
 
 
/**
* Setup vector pointers that will be used to bind immediates to VB's.
*/
void _tnl_imm_init( GLcontext *ctx )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_arrays *tmp = &tnl->imm_inputs;
GLuint i;
static int firsttime = 1;
 
if (firsttime) {
firsttime = 0;
_tnl_imm_elt_init();
}
 
ctx->swtnl_im = _tnl_alloc_immediate( ctx );
TNL_CURRENT_IM(ctx)->ref_count++;
 
tnl->ExecCopyTexSize = 0;
tnl->ExecCopyCount = 0;
tnl->ExecCopySource = 0;
 
TNL_CURRENT_IM(ctx)->CopyStart = IMM_MAX_COPIED_VERTS;
 
_mesa_vector4f_init( &tmp->Obj, 0, 0 );
_mesa_vector4f_init( &tmp->Normal, 0, 0 );
 
tmp->Color.Ptr = NULL;
tmp->Color.Type = GL_FLOAT;
tmp->Color.Size = 4;
tmp->Color.Stride = 0;
tmp->Color.StrideB = 4 * sizeof(GLfloat);
tmp->Color.Flags = 0;
 
tmp->SecondaryColor.Ptr = NULL;
tmp->SecondaryColor.Type = GL_FLOAT;
tmp->SecondaryColor.Size = 4;
tmp->SecondaryColor.Stride = 0;
tmp->SecondaryColor.StrideB = 4 * sizeof(GLfloat);
tmp->SecondaryColor.Flags = 0;
 
_mesa_vector4f_init( &tmp->FogCoord, 0, 0 );
_mesa_vector1ui_init( &tmp->Index, 0, 0 );
_mesa_vector1ub_init( &tmp->EdgeFlag, 0, 0 );
 
for (i = 0; i < ctx->Const.MaxTextureUnits; i++)
_mesa_vector4f_init( &tmp->TexCoord[i], 0, 0);
 
/* Install the first immediate. Intially outside begin/end.
*/
_tnl_reset_exec_input( ctx, IMM_MAX_COPIED_VERTS, 0, 0 );
tnl->ReplayHardBeginEnd = 0;
 
_tnl_imm_vtxfmt_init( ctx );
}
 
 
/**
* Deallocate the immediate-mode buffer for the given context, if
* its reference count goes to zero.
*/
void _tnl_imm_destroy( GLcontext *ctx )
{
if (TNL_CURRENT_IM(ctx)) {
TNL_CURRENT_IM(ctx)->ref_count--;
if (TNL_CURRENT_IM(ctx)->ref_count == 0)
_tnl_free_immediate( ctx, TNL_CURRENT_IM(ctx) );
/*
* Don't use SET_IMMEDIATE here, or else we'll whack the
* _tnl_CurrentInput pointer - not good when another
* context has already been made current.
* So we just set the context's own tnl immediate pointer
* to 0.
*/
ctx->swtnl_im = NULL;
}
}
/shark/trunk/ports/mesa/src/tnl/t_imm_debug.c
0,0 → 1,183
/* $Id: t_imm_debug.c,v 1.1 2003-02-28 11:48:06 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
#include "mtypes.h"
#include "context.h"
#include "imports.h"
#include "t_context.h"
#include "t_imm_debug.h"
 
 
void _tnl_print_vert_flags( const char *name, GLuint flags )
{
_mesa_debug(NULL,
"%s: (0x%x) %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
name,
flags,
(flags & VERT_BIT_CLIP) ? "clip/proj-clip/glend, " : "",
(flags & VERT_BIT_EDGEFLAG) ? "edgeflag, " : "",
(flags & VERT_BIT_ELT) ? "array-elt, " : "",
(flags & VERT_BIT_END_VB) ? "end-vb, " : "",
(flags & VERT_BITS_EVAL_ANY) ? "eval-coord, " : "",
(flags & VERT_BIT_EYE) ? "eye/glbegin, " : "",
(flags & VERT_BIT_FOG) ? "fog-coord, " : "",
(flags & VERT_BIT_INDEX) ? "index, " : "",
(flags & VERT_BIT_MATERIAL) ? "material, " : "",
(flags & VERT_BIT_NORMAL) ? "normals, " : "",
(flags & VERT_BIT_POS) ? "obj, " : "",
(flags & VERT_BIT_OBJ_3) ? "obj-3, " : "",
(flags & VERT_BIT_OBJ_4) ? "obj-4, " : "",
(flags & VERT_BIT_POINT_SIZE) ? "point-size, " : "",
(flags & VERT_BIT_COLOR0) ? "colors, " : "",
(flags & VERT_BIT_COLOR1) ? "specular, " : "",
(flags & VERT_BIT_TEX0) ? "texcoord0, " : "",
(flags & VERT_BIT_TEX1) ? "texcoord1, " : "",
(flags & VERT_BIT_TEX2) ? "texcoord2, " : "",
(flags & VERT_BIT_TEX3) ? "texcoord3, " : "",
(flags & VERT_BIT_TEX4) ? "texcoord4, " : "",
(flags & VERT_BIT_TEX5) ? "texcoord5, " : "",
(flags & VERT_BIT_TEX6) ? "texcoord6, " : "",
(flags & VERT_BIT_TEX7) ? "texcoord7, " : ""
);
}
 
void _tnl_print_cassette( struct immediate *IM )
{
GLuint i;
GLuint *flags = IM->Flag;
GLuint andflag = IM->CopyAndFlag;
GLuint orflag = (IM->CopyOrFlag|IM->Evaluated);
GLuint state = IM->BeginState;
GLuint req = ~0;
 
_mesa_debug(NULL, "Cassette id %d, %u rows.\n", IM->id,
IM->Count - IM->CopyStart);
 
_tnl_print_vert_flags("Contains at least one", orflag);
 
if (IM->Count != IM->CopyStart)
{
_tnl_print_vert_flags("Contains a full complement of", andflag);
 
_mesa_debug(NULL, "Final begin/end state %s/%s, errors %s/%s\n",
(state & VERT_BEGIN_0) ? "in" : "out",
(state & VERT_BEGIN_1) ? "in" : "out",
(state & VERT_ERROR_0) ? "y" : "n",
(state & VERT_ERROR_1) ? "y" : "n");
 
}
 
for (i = IM->CopyStart ; i <= IM->Count ; i++) {
_mesa_debug(NULL, "%u: ", i);
if (req & VERT_BITS_OBJ_234) {
if (flags[i] & VERT_BIT_EVAL_C1)
_mesa_debug(NULL, "EvalCoord %f ",
IM->Attrib[VERT_ATTRIB_POS][i][0]);
else if (flags[i] & VERT_BIT_EVAL_P1)
_mesa_debug(NULL, "EvalPoint %.0f ",
IM->Attrib[VERT_ATTRIB_POS][i][0]);
else if (flags[i] & VERT_BIT_EVAL_C2)
_mesa_debug(NULL, "EvalCoord %f %f ",
IM->Attrib[VERT_ATTRIB_POS][i][0],
IM->Attrib[VERT_ATTRIB_POS][i][1]);
else if (flags[i] & VERT_BIT_EVAL_P2)
_mesa_debug(NULL, "EvalPoint %.0f %.0f ",
IM->Attrib[VERT_ATTRIB_POS][i][0],
IM->Attrib[VERT_ATTRIB_POS][i][1]);
else if (i < IM->Count && (flags[i] & VERT_BITS_OBJ_234)) {
_mesa_debug(NULL, "Obj %f %f %f %f",
IM->Attrib[VERT_ATTRIB_POS][i][0],
IM->Attrib[VERT_ATTRIB_POS][i][1],
IM->Attrib[VERT_ATTRIB_POS][i][2],
IM->Attrib[VERT_ATTRIB_POS][i][3]);
}
}
 
if (req & flags[i] & VERT_BIT_ELT)
_mesa_debug(NULL, " Elt %u\t", IM->Elt[i]);
 
if (req & flags[i] & VERT_BIT_NORMAL)
_mesa_debug(NULL, " Norm %f %f %f ",
IM->Attrib[VERT_ATTRIB_NORMAL][i][0],
IM->Attrib[VERT_ATTRIB_NORMAL][i][1],
IM->Attrib[VERT_ATTRIB_NORMAL][i][2]);
 
if (req & flags[i] & VERT_BITS_TEX_ANY) {
GLuint j;
for (j = 0 ; j < MAX_TEXTURE_UNITS ; j++) {
if (req & flags[i] & VERT_BIT_TEX(j)) {
_mesa_debug(NULL, "TC%d %f %f %f %f", j,
IM->Attrib[VERT_ATTRIB_TEX0 + j][i][0],
IM->Attrib[VERT_ATTRIB_TEX0 + j][i][1],
IM->Attrib[VERT_ATTRIB_TEX0 + j][i][2],
IM->Attrib[VERT_ATTRIB_TEX0 + j][i][3]);
}
}
}
 
if (req & flags[i] & VERT_BIT_COLOR0)
_mesa_debug(NULL, " Rgba %f %f %f %f ",
IM->Attrib[VERT_ATTRIB_COLOR0][i][0],
IM->Attrib[VERT_ATTRIB_COLOR0][i][1],
IM->Attrib[VERT_ATTRIB_COLOR0][i][2],
IM->Attrib[VERT_ATTRIB_COLOR0][i][3]);
 
if (req & flags[i] & VERT_BIT_COLOR1)
_mesa_debug(NULL, " Spec %f %f %f ",
IM->Attrib[VERT_ATTRIB_COLOR1][i][0],
IM->Attrib[VERT_ATTRIB_COLOR1][i][1],
IM->Attrib[VERT_ATTRIB_COLOR1][i][2]);
 
if (req & flags[i] & VERT_BIT_FOG)
_mesa_debug(NULL, " Fog %f ", IM->Attrib[VERT_ATTRIB_FOG][i][0]);
 
if (req & flags[i] & VERT_BIT_INDEX)
_mesa_debug(NULL, " Index %u ", IM->Index[i]);
 
if (req & flags[i] & VERT_BIT_EDGEFLAG)
_mesa_debug(NULL, " Edgeflag %d ", IM->EdgeFlag[i]);
 
if (req & flags[i] & VERT_BIT_MATERIAL)
_mesa_debug(NULL, " Material ");
 
 
/* The order of these two is not easily knowable, but this is
* the usually correct way to look at them.
*/
if (req & flags[i] & VERT_BIT_END)
_mesa_debug(NULL, " END ");
 
if (req & flags[i] & VERT_BIT_BEGIN)
_mesa_debug(NULL, " BEGIN(%s) (%s%s%s%s)",
_mesa_prim_name[IM->Primitive[i] & PRIM_MODE_MASK],
(IM->Primitive[i] & PRIM_LAST) ? "LAST," : "",
(IM->Primitive[i] & PRIM_BEGIN) ? "BEGIN," : "",
(IM->Primitive[i] & PRIM_END) ? "END," : "",
(IM->Primitive[i] & PRIM_PARITY) ? "PARITY," : "");
 
_mesa_debug(NULL, "\n");
}
}
/shark/trunk/ports/mesa/src/tnl/t_context.h
0,0 → 1,582
/* $Id: t_context.h,v 1.1 2003-02-28 11:48:06 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
/**
* \file t_context.h
* \brief TnL module datatypes and definitions.
* \author Keith Whitwell
*/
 
#ifndef _T_CONTEXT_H
#define _T_CONTEXT_H
 
#include "glheader.h"
#include "mtypes.h"
 
#include "math/m_matrix.h"
#include "math/m_vector.h"
#include "math/m_xform.h"
 
 
#define MAX_PIPELINE_STAGES 30
 
 
/* Numbers for sizing immediate structs.
*/
#define IMM_MAX_COPIED_VERTS 3
#define IMM_MAXDATA (216 + IMM_MAX_COPIED_VERTS)
#define IMM_SIZE (IMM_MAXDATA + MAX_CLIPPED_VERTICES)
 
 
/* Values for IM->BeginState
*/
#define VERT_BEGIN_0 0x1 /* glBegin (if initially inside beg/end) */
#define VERT_BEGIN_1 0x2 /* glBegin (if initially outside beg/end) */
#define VERT_ERROR_0 0x4 /* invalid_operation in initial state 0 */
#define VERT_ERROR_1 0x8 /* invalid_operation in initial state 1 */
 
 
/* Flags to be added to the primitive enum in VB->Primitive.
*/
#define PRIM_MODE_MASK 0xff /* Extract the actual primitive */
#define PRIM_BEGIN 0x100 /* The prim starts here (not wrapped) */
#define PRIM_END 0x200 /* The prim ends in this VB (does not wrap) */
#define PRIM_PARITY 0x400 /* The prim wrapped on an odd number of verts */
#define PRIM_LAST 0x800 /* No more prims in the VB */
 
 
/**
* Flags that describe the inputs and outputs of pipeline stages, and
* the contents of a vertex-cassette. We reuse the VERT_BIT_* flags
* defined in mtypes.h and add a bunch of new ones.
*/
/* bits 0..5 defined in mtypes.h */
#define VERT_BIT_INDEX VERT_BIT_SIX /* a free vertex attrib bit */
#define VERT_BIT_EDGEFLAG VERT_BIT_SEVEN /* a free vertex attrib bit */
/* bits 8..15 defined in mtypes.h */
#define VERT_BIT_EVAL_C1 (1 << 16) /* imm only */
#define VERT_BIT_EVAL_C2 (1 << 17) /* imm only */
#define VERT_BIT_EVAL_P1 (1 << 18) /* imm only */
#define VERT_BIT_EVAL_P2 (1 << 19) /* imm only */
#define VERT_BIT_OBJ_3 (1 << 20) /* imm only */
#define VERT_BIT_OBJ_4 (1 << 21) /* imm only */
#define VERT_BIT_MATERIAL (1 << 22) /* imm only, but tested in vb code */
#define VERT_BIT_ELT (1 << 23) /* imm only */
#define VERT_BIT_BEGIN (1 << 24) /* imm only, but tested in vb code */
#define VERT_BIT_END (1 << 25) /* imm only, but tested in vb code */
#define VERT_BIT_END_VB (1 << 26) /* imm only, but tested in vb code */
#define VERT_BIT_POINT_SIZE (1 << 27) /* vb only, could reuse a bit */
#define VERT_BIT_EYE VERT_BIT_BEGIN /* vb only, reuse imm bit */
#define VERT_BIT_CLIP VERT_BIT_END /* vb only, reuse imm bit*/
 
 
/* Flags for IM->TexCoordSize. Enough flags for 16 units.
*/
#define TEX_0_SIZE_3 (unsigned)0x1
#define TEX_0_SIZE_4 (unsigned)0x10001
#define TEX_SIZE_3(unit) (TEX_0_SIZE_3 << (unit))
#define TEX_SIZE_4(unit) (TEX_0_SIZE_4 << (unit))
 
 
/* Shorthands.
*/
#define VERT_BITS_OBJ_23 (VERT_BIT_POS | VERT_BIT_OBJ_3)
#define VERT_BITS_OBJ_234 (VERT_BIT_POS | VERT_BIT_OBJ_3 | VERT_BIT_OBJ_4)
 
#define VERT_BITS_TEX_ANY (VERT_BIT_TEX0 | \
VERT_BIT_TEX1 | \
VERT_BIT_TEX2 | \
VERT_BIT_TEX3 | \
VERT_BIT_TEX4 | \
VERT_BIT_TEX5 | \
VERT_BIT_TEX6 | \
VERT_BIT_TEX7)
 
#define VERT_BITS_EVAL_ANY (VERT_BIT_EVAL_C1 | VERT_BIT_EVAL_P1 | \
VERT_BIT_EVAL_C2 | VERT_BIT_EVAL_P2)
 
#define VERT_BITS_FIXUP (VERT_BITS_TEX_ANY | \
VERT_BIT_COLOR0 | \
VERT_BIT_COLOR1 | \
VERT_BIT_FOG | \
VERT_BIT_INDEX | \
VERT_BIT_EDGEFLAG | \
VERT_BIT_NORMAL)
 
#define VERT_BITS_CURRENT_DATA (VERT_BITS_FIXUP | \
VERT_BIT_MATERIAL)
 
#define VERT_BITS_DATA (VERT_BITS_TEX_ANY | \
VERT_BIT_COLOR0 | \
VERT_BIT_COLOR1 | \
VERT_BIT_FOG | \
VERT_BIT_INDEX | \
VERT_BIT_EDGEFLAG | \
VERT_BIT_NORMAL | \
VERT_BIT_POS | \
VERT_BIT_MATERIAL | \
VERT_BIT_ELT | \
VERT_BITS_EVAL_ANY)
 
 
/**
* KW: Represents everything that can take place between a begin and
* end, and can represent multiple begin/end pairs. Can be used to
* losslessly encode this information in display lists.
*/
struct immediate
{
GLuint id, ref_count;
 
/* This must be saved when immediates are shared in display lists.
*/
GLuint CopyStart, Start, Count;
GLuint LastData; /* count or count+1 */
GLuint AndFlag, OrFlag;
GLuint TexSize; /* keep track of texcoord sizes */
GLuint BeginState, SavedBeginState;
GLuint LastPrimitive;
 
GLuint ArrayEltFlags; /* precalc'ed for glArrayElt */
GLuint ArrayEltIncr;
GLuint ArrayEltFlush;
 
#define FLUSH_ELT_EAGER 0x1
#define FLUSH_ELT_LAZY 0x2
GLuint FlushElt;
 
GLuint MaxTextureUnits; /* precalc'ed for glMultiTexCoordARB */
 
/* Temporary values created when vertices are copied into the
* first 3 slots of the struct:
*/
GLuint CopyOrFlag;
GLuint CopyAndFlag;
GLuint CopyTexSize;
GLuint Evaluated;
 
 
/* allocate storage for these on demand:
*/
struct gl_material (*Material)[2];
GLuint *MaterialMask;
GLuint LastMaterial;
GLuint MaterialOrMask;
GLuint MaterialAndMask;
 
GLuint Primitive[IMM_SIZE]; /* BEGIN/END */
GLuint PrimitiveLength[IMM_SIZE]; /* BEGIN/END */
GLuint Flag[IMM_SIZE]; /* VERT_BIT_* flags */
 
/* All vertex attributes (position, normal, color, secondary color,
* texcoords, fog coord) are stored in the Attrib[] arrays instead
* of individual arrays as we did prior to Mesa 4.1.
*
* XXX may need to use 32-byte aligned allocation for this!!!
*/
GLfloat Attrib[VERT_ATTRIB_MAX][IMM_SIZE][4]; /* GL_NV_vertex_program */
 
GLfloat *NormalLengthPtr; /* length of normal vectors (display list only) */
 
GLuint Elt[IMM_SIZE];
GLubyte EdgeFlag[IMM_SIZE];
GLuint Index[IMM_SIZE];
};
 
 
struct vertex_arrays
{
/* XXX move a bunch of these fields into the Attribs[] array??? */
GLvector4f Obj;
GLvector4f Normal;
struct gl_client_array Color;
struct gl_client_array SecondaryColor;
GLvector1ui Index;
GLvector1ub EdgeFlag;
GLvector4f TexCoord[MAX_TEXTURE_UNITS];
GLvector1ui Elt;
GLvector4f FogCoord;
GLvector4f Attribs[VERT_ATTRIB_MAX];
};
 
 
/**
* Contains the current state of a running pipeline.
*/
typedef struct vertex_buffer
{
/* Constant over life of the vertex_buffer.
*/
GLuint Size;
 
/* Constant over the pipeline.
*/
GLuint Count; /* for everything except Elts */
GLuint FirstClipped; /* temp verts for clipping */
GLuint FirstPrimitive; /* usually zero */
 
/* Pointers to current data.
*/
GLuint *Elts; /* VERT_BIT_ELT */
GLvector4f *ObjPtr; /* VERT_BIT_POS */
GLvector4f *EyePtr; /* VERT_BIT_EYE */
GLvector4f *ClipPtr; /* VERT_BIT_CLIP */
GLvector4f *NdcPtr; /* VERT_BIT_CLIP (2) */
GLubyte ClipOrMask; /* VERT_BIT_CLIP (3) */
GLubyte *ClipMask; /* VERT_BIT_CLIP (4) */
GLvector4f *NormalPtr; /* VERT_BIT_NORMAL */
GLfloat *NormalLengthPtr; /* VERT_BIT_NORMAL */
GLboolean *EdgeFlag; /* VERT_BIT_EDGEFLAG */
GLvector4f *TexCoordPtr[MAX_TEXTURE_UNITS]; /* VERT_TEX_0..n */
GLvector1ui *IndexPtr[2]; /* VERT_BIT_INDEX */
struct gl_client_array *ColorPtr[2]; /* VERT_BIT_COLOR0 */
struct gl_client_array *SecondaryColorPtr[2];/* VERT_BIT_COLOR1 */
GLvector4f *PointSizePtr; /* VERT_BIT_POINT_SIZE */
GLvector4f *FogCoordPtr; /* VERT_BIT_FOG */
struct gl_material (*Material)[2]; /* VERT_BIT_MATERIAL, optional */
GLuint *MaterialMask; /* VERT_BIT_MATERIAL, optional */
GLuint *Flag; /* VERT_BIT_* flags, optional */
GLuint *Primitive; /* GL_(mode)|PRIM_* flags */
GLuint *PrimitiveLength; /* integers */
 
/* Inputs to the vertex program stage */
GLvector4f *AttribPtr[VERT_ATTRIB_MAX]; /* GL_NV_vertex_program */
 
GLuint importable_data;
void *import_source;
void (*import_data)( GLcontext *ctx, GLuint flags, GLuint vecflags );
/* Callback to the provider of the untransformed input for the
* render stage (or other stages) to call if they need to write into
* write-protected arrays, or fixup the stride on input arrays.
*
* This is currently only necessary for client arrays that make it
* as far down the pipeline as the render stage.
*/
 
GLuint LastClipped;
/* Private data from _tnl_render_stage that has no business being
* in this struct.
*/
 
} TNLvertexbuffer;
 
 
 
/* Describes an individual operation on the pipeline.
*/
struct gl_pipeline_stage {
const char *name;
GLuint check_state; /* All state referenced in check() --
* When is the pipeline_stage struct
* itself invalidated? Must be
* constant.
*/
 
/* Usually constant or set by the 'check' callback:
*/
GLuint run_state; /* All state referenced in run() --
* When is the cached output of the
* stage invalidated?
*/
 
GLboolean active; /* True if runnable in current state */
GLuint inputs; /* VERT_* inputs to the stage */
GLuint outputs; /* VERT_* outputs of the stage */
 
/* Set in _tnl_run_pipeline():
*/
GLuint changed_inputs; /* Generated value -- inputs to the
* stage that have changed since last
* call to 'run'.
*/
 
/* Private data for the pipeline stage:
*/
void *privatePtr;
 
/* Free private data. May not be null.
*/
void (*destroy)( struct gl_pipeline_stage * );
 
/* Called from _tnl_validate_pipeline(). Must update all fields in
* the pipeline_stage struct for the current state.
*/
void (*check)( GLcontext *ctx, struct gl_pipeline_stage * );
 
/* Called from _tnl_run_pipeline(). The stage.changed_inputs value
* encodes all inputs to thee struct which have changed. If
* non-zero, recompute all affected outputs of the stage, otherwise
* execute any 'sideeffects' of the stage.
*
* Return value: GL_TRUE - keep going
* GL_FALSE - finished pipeline
*/
GLboolean (*run)( GLcontext *ctx, struct gl_pipeline_stage * );
};
 
 
struct gl_pipeline {
GLuint build_state_trigger; /* state changes which require build */
GLuint build_state_changes; /* state changes since last build */
GLuint run_state_changes; /* state changes since last run */
GLuint run_input_changes; /* VERT_* changes since last run */
GLuint inputs; /* VERT_* inputs to pipeline */
struct gl_pipeline_stage stages[MAX_PIPELINE_STAGES+1];
GLuint nr_stages;
};
 
 
struct tnl_eval_store {
GLuint EvalMap1Flags;
GLuint EvalMap2Flags;
GLuint EvalMap1AttribFlags; /* GL_NV_vertex_program */
GLuint EvalMap2AttribFlags; /* GL_NV_vertex_program */
GLuint EvalNewState;
struct immediate *im; /* used for temporary data */
};
 
 
typedef void (*points_func)( GLcontext *ctx, GLuint first, GLuint last );
typedef void (*line_func)( GLcontext *ctx, GLuint v1, GLuint v2 );
typedef void (*triangle_func)( GLcontext *ctx,
GLuint v1, GLuint v2, GLuint v3 );
typedef void (*quad_func)( GLcontext *ctx, GLuint v1, GLuint v2,
GLuint v3, GLuint v4 );
typedef void (*render_func)( GLcontext *ctx, GLuint start, GLuint count,
GLuint flags );
typedef void (*interp_func)( GLcontext *ctx,
GLfloat t, GLuint dst, GLuint out, GLuint in,
GLboolean force_boundary );
typedef void (*copy_pv_func)( GLcontext *ctx, GLuint dst, GLuint src );
typedef void (*setup_func)( GLcontext *ctx,
GLuint start, GLuint end,
GLuint new_inputs);
 
 
struct tnl_device_driver {
/***
*** TNL Pipeline
***/
 
void (*RunPipeline)(GLcontext *ctx);
/* Replaces PipelineStart/PipelineFinish -- intended to allow
* drivers to wrap _tnl_run_pipeline() with code to validate state
* and grab/release hardware locks.
*/
 
void (*NotifyMaterialChange)(GLcontext *ctx);
/* Alert tnl-aware drivers of changes to material.
*/
 
GLboolean (*NotifyBegin)(GLcontext *ctx, GLenum p);
/* Allow drivers to hook in optimized begin/end engines.
* Return value: GL_TRUE - driver handled the begin
* GL_FALSE - driver didn't handle the begin
*/
 
/***
*** Rendering -- These functions called only from t_vb_render.c
***/
struct {
void (*Start)(GLcontext *ctx);
void (*Finish)(GLcontext *ctx);
/* Called before and after all rendering operations, including DrawPixels,
* ReadPixels, Bitmap, span functions, and CopyTexImage, etc commands.
* These are a suitable place for grabbing/releasing hardware locks.
*/
 
void (*PrimitiveNotify)(GLcontext *ctx, GLenum mode);
/* Called between RenderStart() and RenderFinish() to indicate the
* type of primitive we're about to draw. Mode will be one of the
* modes accepted by glBegin().
*/
 
interp_func Interp;
/* The interp function is called by the clipping routines when we need
* to generate an interpolated vertex. All pertinant vertex ancilliary
* data should be computed by interpolating between the 'in' and 'out'
* vertices.
*/
 
copy_pv_func CopyPV;
/* The copy function is used to make a copy of a vertex. All pertinant
* vertex attributes should be copied.
*/
 
void (*ClippedPolygon)( GLcontext *ctx, const GLuint *elts, GLuint n );
/* Render a polygon with <n> vertices whose indexes are in the <elts>
* array.
*/
 
void (*ClippedLine)( GLcontext *ctx, GLuint v0, GLuint v1 );
/* Render a line between the two vertices given by indexes v0 and v1. */
 
points_func Points; /* must now respect vb->elts */
line_func Line;
triangle_func Triangle;
quad_func Quad;
/* These functions are called in order to render points, lines,
* triangles and quads. These are only called via the T&L module.
*/
 
render_func *PrimTabVerts;
render_func *PrimTabElts;
/* Render whole unclipped primitives (points, lines, linestrips,
* lineloops, etc). The tables are indexed by the GL enum of the
* primitive to be rendered. RenderTabVerts is used for non-indexed
* arrays of vertices. RenderTabElts is used for indexed arrays of
* vertices.
*/
 
void (*ResetLineStipple)( GLcontext *ctx );
/* Reset the hardware's line stipple counter.
*/
 
setup_func BuildVertices;
/* This function is called whenever new vertices are required for
* rendering. The vertices in question are those n such that start
* <= n < end. The new_inputs parameter indicates those fields of
* the vertex which need to be updated, if only a partial repair of
* the vertex is required.
*
* This function is called only from _tnl_render_stage in tnl/t_render.c.
*/
 
GLboolean (*Multipass)( GLcontext *ctx, GLuint passno );
/* Driver may request additional render passes by returning GL_TRUE
* when this function is called. This function will be called
* after the first pass, and passes will be made until the function
* returns GL_FALSE. If no function is registered, only one pass
* is made.
*
* This function will be first invoked with passno == 1.
*/
} Render;
};
 
typedef struct {
 
/* Driver interface.
*/
struct tnl_device_driver Driver;
 
/* Track whether the module is active.
*/
GLboolean bound_exec;
 
/* Display list extensions
*/
GLuint opcode_vertex_cassette;
 
/* Pipeline
*/
struct gl_pipeline pipeline;
struct vertex_buffer vb;
 
/* GLvectors for binding to vb:
*/
struct vertex_arrays imm_inputs;
struct vertex_arrays array_inputs;
GLuint *tmp_primitive;
GLuint *tmp_primitive_length;
 
/* Set when executing an internally generated begin/end object. If
* such an object is encountered in a display list, it will be
* replayed only if the list is outside any existing begin/end
* objects.
*/
GLboolean ReplayHardBeginEnd;
 
/* Note which vertices need copying over succesive immediates.
* Will add save versions to precompute vertex copying where
* possible.
*/
struct immediate *ExecCopySource;
GLuint ExecCopyCount;
GLuint ExecCopyElts[IMM_MAX_COPIED_VERTS];
GLuint ExecCopyTexSize;
GLuint ExecParity;
 
GLuint DlistPrimitive;
GLuint DlistPrimitiveLength;
GLuint DlistLastPrimitive;
 
/* Cache a single free immediate (refcount == 0)
*/
struct immediate *freed_immediate;
 
/* Probably need a better configuration mechanism:
*/
GLboolean NeedNdcCoords;
GLboolean LoopbackDListCassettes;
GLboolean CalcDListNormalLengths;
GLboolean IsolateMaterials;
 
/* Derived state and storage for _tnl_eval_vb:
*/
struct tnl_eval_store eval;
 
/* Functions to be plugged into dispatch when tnl is active.
*/
GLvertexformat vtxfmt;
GLvertexformat save_vtxfmt;
 
} TNLcontext;
 
 
 
#define TNL_CONTEXT(ctx) ((TNLcontext *)(ctx->swtnl_context))
#define TNL_CURRENT_IM(ctx) ((struct immediate *)(ctx->swtnl_im))
 
 
#define TYPE_IDX(t) ((t) & 0xf)
#define MAX_TYPES TYPE_IDX(GL_DOUBLE)+1 /* 0xa + 1 */
 
extern void _tnl_MakeCurrent( GLcontext *ctx,
GLframebuffer *drawBuffer,
GLframebuffer *readBuffer );
 
 
/*
* Macros for fetching current input buffer.
*/
#ifdef THREADS
#define GET_IMMEDIATE struct immediate *IM = TNL_CURRENT_IM(((GLcontext *) (_glapi_Context ? _glapi_Context : _glapi_get_context())))
#define SET_IMMEDIATE(ctx, im) ctx->swtnl_im = (void *)im
#else
extern struct immediate *_tnl_CurrentInput;
#define GET_IMMEDIATE struct immediate *IM = _tnl_CurrentInput
#define SET_IMMEDIATE(ctx, im) \
do { \
ctx->swtnl_im = (void *)im; \
_tnl_CurrentInput = im; \
} while (0)
#endif
 
 
#endif
/shark/trunk/ports/mesa/src/tnl/t_vb_texmat.c
0,0 → 1,152
/* $Id: t_vb_texmat.c,v 1.1 2003-02-28 11:48:08 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
 
#include "glheader.h"
#include "colormac.h"
#include "context.h"
#include "macros.h"
#include "imports.h"
#include "mmath.h"
#include "mtypes.h"
 
#include "math/m_xform.h"
 
#include "t_context.h"
#include "t_pipeline.h"
 
/* Is there any real benefit seperating texmat from texgen? It means
* we need two lots of intermediate storage. Any changes to
* _NEW_TEXTURE will invalidate both sets -- it's only on changes to
* *only* _NEW_TEXTURE_MATRIX that texgen survives but texmat doesn't.
*
* However, the seperation of this code from the complex texgen stuff
* is very appealing.
*/
struct texmat_stage_data {
GLvector4f texcoord[MAX_TEXTURE_UNITS];
};
 
#define TEXMAT_STAGE_DATA(stage) ((struct texmat_stage_data *)stage->privatePtr)
 
static void check_texmat( GLcontext *ctx, struct gl_pipeline_stage *stage )
{
GLuint i;
stage->active = 0;
 
if (ctx->Texture._TexMatEnabled && !ctx->VertexProgram.Enabled) {
GLuint flags = 0;
 
for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++)
if (ctx->Texture._TexMatEnabled & ENABLE_TEXMAT(i))
flags |= VERT_BIT_TEX(i);
 
stage->active = 1;
stage->inputs = flags;
stage->outputs = flags;
}
}
 
static GLboolean run_texmat_stage( GLcontext *ctx,
struct gl_pipeline_stage *stage )
{
struct texmat_stage_data *store = TEXMAT_STAGE_DATA(stage);
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
GLuint i;
 
/* ENABLE_TEXMAT implies that the texture matrix is not the
* identity, so we don't have to check that here.
*/
for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++)
if (ctx->Texture._TexMatEnabled & ENABLE_TEXMAT(i)) {
if (stage->changed_inputs & VERT_BIT_TEX(i))
(void) TransformRaw( &store->texcoord[i],
ctx->TextureMatrixStack[i].Top,
VB->TexCoordPtr[i]);
 
VB->TexCoordPtr[i] = &store->texcoord[i];
}
return GL_TRUE;
}
 
 
/* Called the first time stage->run() is invoked.
*/
static GLboolean alloc_texmat_data( GLcontext *ctx,
struct gl_pipeline_stage *stage )
{
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
struct texmat_stage_data *store;
GLuint i;
 
stage->privatePtr = CALLOC(sizeof(*store));
store = TEXMAT_STAGE_DATA(stage);
if (!store)
return GL_FALSE;
 
for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++)
_mesa_vector4f_alloc( &store->texcoord[i], 0, VB->Size, 32 );
 
/* Now run the stage.
*/
stage->run = run_texmat_stage;
return stage->run( ctx, stage );
}
 
 
static void free_texmat_data( struct gl_pipeline_stage *stage )
{
struct texmat_stage_data *store = TEXMAT_STAGE_DATA(stage);
GLuint i;
 
if (store) {
for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++)
if (store->texcoord[i].data)
_mesa_vector4f_free( &store->texcoord[i] );
FREE( store );
stage->privatePtr = 0;
}
}
 
 
 
const struct gl_pipeline_stage _tnl_texture_transform_stage =
{
"texture transform", /* name */
_NEW_TEXTURE|_NEW_TEXTURE_MATRIX, /* check_state */
_NEW_TEXTURE|_NEW_TEXTURE_MATRIX, /* run_state */
GL_FALSE, /* active? */
0, /* inputs */
0, /* outputs */
0, /* changed_inputs */
NULL, /* private data */
free_texmat_data, /* destructor */
check_texmat, /* check */
alloc_texmat_data, /* run -- initially set to init */
};
/shark/trunk/ports/mesa/src/tnl/t_imm_eval.c
0,0 → 1,854
/* $Id: t_imm_eval.c,v 1.1 2003-02-28 11:48:07 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 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.
*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
* Brian Paul - vertex program updates
*/
 
 
#include "glheader.h"
#include "colormac.h"
#include "context.h"
#include "macros.h"
#include "imports.h"
#include "mmath.h"
#include "mtypes.h"
#include "math/m_eval.h"
 
#include "t_context.h"
#include "t_imm_debug.h"
#include "t_imm_eval.h"
#include "t_imm_exec.h"
#include "t_imm_fixup.h"
#include "t_imm_alloc.h"
 
 
static void eval_points1( GLfloat outcoord[][4],
GLfloat coord[][4],
const GLuint *flags,
GLfloat du, GLfloat u1 )
{
GLuint i;
for (i = 0 ; !(flags[i] & VERT_BIT_END_VB) ; i++)
if (flags[i] & VERT_BITS_EVAL_ANY) {
outcoord[i][0] = coord[i][0];
outcoord[i][1] = coord[i][1];
if (flags[i] & VERT_BIT_EVAL_P1)
outcoord[i][0] = coord[i][0] * du + u1;
}
}
 
static void eval_points2( GLfloat outcoord[][4],
GLfloat coord[][4],
const GLuint *flags,
GLfloat du, GLfloat u1,
GLfloat dv, GLfloat v1 )
{
GLuint i;
for (i = 0 ; !(flags[i] & VERT_BIT_END_VB) ; i++) {
if (flags[i] & VERT_BITS_EVAL_ANY) {
outcoord[i][0] = coord[i][0];
outcoord[i][1] = coord[i][1];
if (flags[i] & VERT_BIT_EVAL_P2) {
outcoord[i][0] = coord[i][0] * du + u1;
outcoord[i][1] = coord[i][1] * dv + v1;
}
}
}
}
 
static const GLubyte dirty_flags[5] = {
0, /* not possible */
VEC_DIRTY_0,
VEC_DIRTY_1,
VEC_DIRTY_2,
VEC_DIRTY_3
};
 
 
static void eval1_4f( GLvector4f *dest,
GLfloat coord[][4],
const GLuint *flags,
GLuint dimension,
const struct gl_1d_map *map )
{
const GLfloat u1 = map->u1;
const GLfloat du = map->du;
GLfloat (*to)[4] = dest->data;
GLuint i;
 
for (i = 0 ; !(flags[i] & VERT_BIT_END_VB) ; i++)
if (flags[i] & (VERT_BIT_EVAL_C1|VERT_BIT_EVAL_P1)) {
GLfloat u = (coord[i][0] - u1) * du;
ASSIGN_4V(to[i], 0,0,0,1);
_math_horner_bezier_curve(map->Points, to[i], u,
dimension, map->Order);
}
 
dest->size = MAX2(dest->size, dimension);
dest->flags |= dirty_flags[dimension];
}
 
 
/* as above, but dest is a gl_client_array */
static void eval1_4f_ca( struct gl_client_array *dest,
GLfloat coord[][4],
const GLuint *flags,
GLuint dimension,
const struct gl_1d_map *map )
{
const GLfloat u1 = map->u1;
const GLfloat du = map->du;
GLfloat (*to)[4] = (GLfloat (*)[4])dest->Ptr;
GLuint i;
 
ASSERT(dest->Type == GL_FLOAT);
ASSERT(dest->StrideB == 4 * sizeof(GLfloat));
 
for (i = 0 ; !(flags[i] & VERT_BIT_END_VB) ; i++)
if (flags[i] & (VERT_BIT_EVAL_C1|VERT_BIT_EVAL_P1)) {
GLfloat u = (coord[i][0] - u1) * du;
ASSIGN_4V(to[i], 0,0,0,1);
_math_horner_bezier_curve(map->Points, to[i], u,
dimension, map->Order);
}
 
dest->Size = MAX2(dest->Size, (GLint) dimension);
}
 
 
static void eval1_1ui( GLvector1ui *dest,
GLfloat coord[][4],
const GLuint *flags,
const struct gl_1d_map *map )
{
const GLfloat u1 = map->u1;
const GLfloat du = map->du;
GLuint *to = dest->data;
GLuint i;
 
for (i = 0 ; !(flags[i] & VERT_BIT_END_VB) ; i++)
if (flags[i] & (VERT_BIT_EVAL_C1|VERT_BIT_EVAL_P1)) {
GLfloat u = (coord[i][0] - u1) * du;
GLfloat tmp;
_math_horner_bezier_curve(map->Points, &tmp, u, 1, map->Order);
to[i] = (GLuint) (GLint) tmp;
}
 
}
 
static void eval1_norm( GLvector4f *dest,
GLfloat coord[][4],
const GLuint *flags,
const struct gl_1d_map *map )
{
const GLfloat u1 = map->u1;
const GLfloat du = map->du;
GLfloat (*to)[4] = dest->data;
GLuint i;
 
for (i = 0 ; !(flags[i] & VERT_BIT_END_VB) ; i++)
if (flags[i] & (VERT_BIT_EVAL_C1|VERT_BIT_EVAL_P1)) {
GLfloat u = (coord[i][0] - u1) * du;
_math_horner_bezier_curve(map->Points, to[i], u, 3, map->Order);
}
}
 
 
static void eval2_obj_norm( GLvector4f *obj_ptr,
GLvector4f *norm_ptr,
GLfloat coord[][4],
GLuint *flags,
GLuint dimension,
const struct gl_2d_map *map )
{
const GLfloat u1 = map->u1;
const GLfloat du = map->du;
const GLfloat v1 = map->v1;
const GLfloat dv = map->dv;
GLfloat (*obj)[4] = obj_ptr->data;
GLfloat (*normal)[4] = norm_ptr->data;
GLuint i;
 
for (i = 0 ; !(flags[i] & VERT_BIT_END_VB) ; i++)
if (flags[i] & (VERT_BIT_EVAL_C2|VERT_BIT_EVAL_P2)) {
GLfloat u = (coord[i][0] - u1) * du;
GLfloat v = (coord[i][1] - v1) * dv;
GLfloat du[4], dv[4];
 
ASSIGN_4V(obj[i], 0,0,0,1);
_math_de_casteljau_surf(map->Points, obj[i], du, dv, u, v, dimension,
map->Uorder, map->Vorder);
 
if (dimension == 4) {
du[0] = du[0]*obj[i][3] - du[3]*obj[i][0];
du[1] = du[1]*obj[i][3] - du[3]*obj[i][1];
du[2] = du[2]*obj[i][3] - du[3]*obj[i][2];
dv[0] = dv[0]*obj[i][3] - dv[3]*obj[i][0];
dv[1] = dv[1]*obj[i][3] - dv[3]*obj[i][1];
dv[2] = dv[2]*obj[i][3] - dv[3]*obj[i][2];
}
 
CROSS3(normal[i], du, dv);
NORMALIZE_3FV(normal[i]);
}
 
obj_ptr->size = MAX2(obj_ptr->size, dimension);
obj_ptr->flags |= dirty_flags[dimension];
}
 
 
static void eval2_4f( GLvector4f *dest,
GLfloat coord[][4],
const GLuint *flags,
GLuint dimension,
const struct gl_2d_map *map )
{
const GLfloat u1 = map->u1;
const GLfloat du = map->du;
const GLfloat v1 = map->v1;
const GLfloat dv = map->dv;
GLfloat (*to)[4] = dest->data;
GLuint i;
 
for (i = 0 ; !(flags[i] & VERT_BIT_END_VB) ; i++)
if (flags[i] & (VERT_BIT_EVAL_C2|VERT_BIT_EVAL_P2)) {
GLfloat u = (coord[i][0] - u1) * du;
GLfloat v = (coord[i][1] - v1) * dv;
 
_math_horner_bezier_surf(map->Points, to[i], u, v, dimension,
map->Uorder, map->Vorder);
}
 
dest->size = MAX2(dest->size, dimension);
dest->flags |= dirty_flags[dimension];
}
 
 
/* as above, but dest is a gl_client_array */
static void eval2_4f_ca( struct gl_client_array *dest,
GLfloat coord[][4],
const GLuint *flags,
GLuint dimension,
const struct gl_2d_map *map )
{
const GLfloat u1 = map->u1;
const GLfloat du = map->du;
const GLfloat v1 = map->v1;
const GLfloat dv = map->dv;
GLfloat (*to)[4] = (GLfloat (*)[4])dest->Ptr;
GLuint i;
 
ASSERT(dest->Type == GL_FLOAT);
ASSERT(dest->StrideB == 4 * sizeof(GLfloat));
 
for (i = 0 ; !(flags[i] & VERT_BIT_END_VB) ; i++)
if (flags[i] & (VERT_BIT_EVAL_C2|VERT_BIT_EVAL_P2)) {
GLfloat u = (coord[i][0] - u1) * du;
GLfloat v = (coord[i][1] - v1) * dv;
_math_horner_bezier_surf(map->Points, to[i], u, v, dimension,
map->Uorder, map->Vorder);
}
 
dest->Size = MAX2(dest->Size, (GLint) dimension);
}
 
 
static void eval2_norm( GLvector4f *dest,
GLfloat coord[][4],
GLuint *flags,
const struct gl_2d_map *map )
{
const GLfloat u1 = map->u1;
const GLfloat du = map->du;
const GLfloat v1 = map->v1;
const GLfloat dv = map->dv;
GLfloat (*to)[4] = dest->data;
GLuint i;
 
for (i = 0 ; !(flags[i] & VERT_BIT_END_VB) ; i++) {
if (flags[i] & (VERT_BIT_EVAL_C2|VERT_BIT_EVAL_P2)) {
GLfloat u = (coord[i][0] - u1) * du;
GLfloat v = (coord[i][1] - v1) * dv;
_math_horner_bezier_surf(map->Points, to[i], u, v, 3,
map->Uorder, map->Vorder);
}
}
}
 
 
static void eval2_1ui( GLvector1ui *dest,
GLfloat coord[][4],
const GLuint *flags,
const struct gl_2d_map *map )
{
const GLfloat u1 = map->u1;
const GLfloat du = map->du;
const GLfloat v1 = map->v1;
const GLfloat dv = map->dv;
GLuint *to = dest->data;
GLuint i;
 
for (i = 0 ; !(flags[i] & VERT_BIT_END_VB) ; i++)
if (flags[i] & (VERT_BIT_EVAL_C2|VERT_BIT_EVAL_P2)) {
GLfloat u = (coord[i][0] - u1) * du;
GLfloat v = (coord[i][1] - v1) * dv;
GLfloat tmp;
_math_horner_bezier_surf(map->Points, &tmp, u, v, 1,
map->Uorder, map->Vorder);
 
to[i] = (GLuint) (GLint) tmp;
}
}
 
 
static void copy_4f( GLfloat to[][4], GLfloat from[][4], GLuint count )
{
MEMCPY( to, from, count * sizeof(to[0]));
}
 
static void copy_4f_stride( GLfloat to[][4], const GLfloat *from,
GLuint stride, GLuint count )
{
if (stride == 4 * sizeof(GLfloat))
MEMCPY( to, from, count * sizeof(to[0]));
else {
GLuint i;
for (i = 0 ; i < count ; i++, STRIDE_F(from, stride))
COPY_4FV( to[i], from );
}
}
 
static void copy_3f( GLfloat to[][4], GLfloat from[][4], GLuint count )
{
GLuint i;
for (i = 0 ; i < count ; i++) {
COPY_3FV(to[i], from[i]);
}
}
 
 
static void copy_1ui( GLuint to[], const GLuint from[], GLuint count )
{
MEMCPY( to, from, (count) * sizeof(to[0]));
}
 
 
 
/* Translate eval enabled flags to VERT_* flags.
*/
static void update_eval( GLcontext *ctx )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
GLuint eval1 = 0, eval2 = 0;
GLuint i;
 
if (ctx->Eval.Map1Index)
eval1 |= VERT_BIT_INDEX;
 
if (ctx->Eval.Map2Index)
eval2 |= VERT_BIT_INDEX;
 
if (ctx->Eval.Map1Color4)
eval1 |= VERT_BIT_COLOR0;
 
if (ctx->Eval.Map2Color4)
eval2 |= VERT_BIT_COLOR0;
 
if (ctx->Eval.Map1Normal)
eval1 |= VERT_BIT_NORMAL;
 
if (ctx->Eval.Map2Normal)
eval2 |= VERT_BIT_NORMAL;
 
if (ctx->Eval.Map1TextureCoord4 ||
ctx->Eval.Map1TextureCoord3 ||
ctx->Eval.Map1TextureCoord2 ||
ctx->Eval.Map1TextureCoord1)
eval1 |= VERT_BIT_TEX0;
 
if (ctx->Eval.Map2TextureCoord4 ||
ctx->Eval.Map2TextureCoord3 ||
ctx->Eval.Map2TextureCoord2 ||
ctx->Eval.Map2TextureCoord1)
eval2 |= VERT_BIT_TEX0;
 
if (ctx->Eval.Map1Vertex4)
eval1 |= VERT_BITS_OBJ_234;
 
if (ctx->Eval.Map1Vertex3)
eval1 |= VERT_BITS_OBJ_23;
 
if (ctx->Eval.Map2Vertex4) {
if (ctx->Eval.AutoNormal)
eval2 |= VERT_BITS_OBJ_234 | VERT_BIT_NORMAL;
else
eval2 |= VERT_BITS_OBJ_234;
}
else if (ctx->Eval.Map2Vertex3) {
if (ctx->Eval.AutoNormal)
eval2 |= VERT_BITS_OBJ_23 | VERT_BIT_NORMAL;
else
eval2 |= VERT_BITS_OBJ_23;
}
 
tnl->eval.EvalMap1Flags = eval1;
tnl->eval.EvalMap2Flags = eval2;
 
/* GL_NV_vertex_program evaluators */
eval1 = eval2 = 0;
for (i = 0; i < VERT_ATTRIB_MAX; i++) {
if (ctx->Eval.Map1Attrib[i])
eval1 |= (1 << i);
if (ctx->Eval.Map2Attrib[i])
eval2 |= (1 << i);
}
tnl->eval.EvalMap1AttribFlags = eval1;
tnl->eval.EvalMap2AttribFlags = eval2;
 
tnl->eval.EvalNewState = 0;
}
 
 
/* This looks a lot like a pipeline stage, but for various reasons is
* better handled outside the pipeline, and considered the final stage
* of fixing up an immediate struct for execution.
*
* Really want to cache the results of this function in display lists,
* at least for EvalMesh commands.
*/
void _tnl_eval_immediate( GLcontext *ctx, struct immediate *IM )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_arrays *tmp = &tnl->imm_inputs;
struct immediate *store = tnl->eval.im;
GLuint *flags = IM->Flag + IM->CopyStart;
GLuint copycount;
GLuint orflag = IM->OrFlag;
GLuint any_eval1 = orflag & (VERT_BIT_EVAL_C1|VERT_BIT_EVAL_P1);
GLuint any_eval2 = orflag & (VERT_BIT_EVAL_C2|VERT_BIT_EVAL_P2);
GLuint req = 0;
GLuint purge_flags = 0;
GLfloat (*coord)[4] = IM->Attrib[VERT_ATTRIB_POS] + IM->CopyStart;
 
if (IM->AndFlag & VERT_BITS_EVAL_ANY)
copycount = IM->Start - IM->CopyStart; /* just copy copied vertices */
else
copycount = IM->Count - IM->CopyStart; /* copy all vertices */
 
if (!store)
store = tnl->eval.im = _tnl_alloc_immediate( ctx );
 
if (tnl->eval.EvalNewState & _NEW_EVAL)
update_eval( ctx );
 
if (any_eval1) {
req |= tnl->pipeline.inputs
& (tnl->eval.EvalMap1Flags | tnl->eval.EvalMap1AttribFlags);
 
if (!ctx->Eval.Map1Vertex4 && !ctx->Eval.Map1Vertex3 &&
!ctx->Eval.Map1Attrib[0])
purge_flags = (VERT_BIT_EVAL_P1|VERT_BIT_EVAL_C1);
 
if (orflag & VERT_BIT_EVAL_P1) {
eval_points1( store->Attrib[VERT_ATTRIB_POS] + IM->CopyStart,
coord, flags,
ctx->Eval.MapGrid1du,
ctx->Eval.MapGrid1u1);
coord = store->Attrib[VERT_ATTRIB_POS] + IM->CopyStart;
}
}
 
if (any_eval2) {
req |= tnl->pipeline.inputs
& (tnl->eval.EvalMap2Flags | tnl->eval.EvalMap2AttribFlags);
 
if (!ctx->Eval.Map2Vertex4 && !ctx->Eval.Map2Vertex3 &&
!ctx->Eval.Map2Attrib[0])
purge_flags |= (VERT_BIT_EVAL_P2|VERT_BIT_EVAL_C2);
 
if (orflag & VERT_BIT_EVAL_P2) {
eval_points2( store->Attrib[VERT_ATTRIB_POS] + IM->CopyStart,
coord, flags,
ctx->Eval.MapGrid2du,
ctx->Eval.MapGrid2u1,
ctx->Eval.MapGrid2dv,
ctx->Eval.MapGrid2v1 );
 
coord = store->Attrib[VERT_ATTRIB_POS] + IM->CopyStart;
}
}
 
/* Perform the evaluations on active data elements.
*/
if (req & VERT_BIT_INDEX) {
GLuint generated = 0;
 
if (copycount)
copy_1ui( store->Index + IM->CopyStart, tmp->Index.data, copycount );
 
tmp->Index.data = store->Index + IM->CopyStart;
tmp->Index.start = store->Index + IM->CopyStart;
 
if (ctx->Eval.Map1Index && any_eval1) {
eval1_1ui( &tmp->Index, coord, flags, &ctx->EvalMap.Map1Index );
generated |= VERT_BIT_EVAL_C1|VERT_BIT_EVAL_P1;
}
 
if (ctx->Eval.Map2Index && any_eval2) {
eval2_1ui( &tmp->Index, coord, flags, &ctx->EvalMap.Map2Index );
generated |= VERT_BIT_EVAL_C2|VERT_BIT_EVAL_P2;
}
}
 
if (req & VERT_BIT_COLOR0) {
GLuint generated = 0;
 
if (copycount)
copy_4f_stride( store->Attrib[VERT_ATTRIB_COLOR0] + IM->CopyStart,
(GLfloat *)tmp->Color.Ptr,
tmp->Color.StrideB,
copycount );
 
tmp->Color.Ptr = store->Attrib[VERT_ATTRIB_COLOR0] + IM->CopyStart;
tmp->Color.StrideB = 4 * sizeof(GLfloat);
tmp->Color.Flags = 0;
tnl->vb.importable_data &= ~VERT_BIT_COLOR0;
 
if (ctx->VertexProgram.Enabled) {
tmp->Attribs[VERT_ATTRIB_COLOR0].data =
store->Attrib[VERT_ATTRIB_COLOR0] + IM->CopyStart;
tmp->Attribs[VERT_ATTRIB_COLOR0].start =
(GLfloat *) tmp->Attribs[VERT_ATTRIB_COLOR0].data;
tmp->Attribs[VERT_ATTRIB_COLOR0].size = 0;
}
 
/* Vertex program maps have priority over conventional attribs */
if (any_eval1) {
if (ctx->VertexProgram.Enabled
&& ctx->Eval.Map1Attrib[VERT_ATTRIB_COLOR0]) {
eval1_4f_ca( &tmp->Color, coord, flags, 4,
&ctx->EvalMap.Map1Attrib[VERT_ATTRIB_COLOR0] );
generated |= VERT_BIT_EVAL_C1|VERT_BIT_EVAL_P1;
}
else if (ctx->Eval.Map1Color4) {
eval1_4f_ca( &tmp->Color, coord, flags, 4,
&ctx->EvalMap.Map1Color4 );
generated |= VERT_BIT_EVAL_C1|VERT_BIT_EVAL_P1;
}
}
 
if (any_eval2) {
if (ctx->VertexProgram.Enabled
&& ctx->Eval.Map2Attrib[VERT_ATTRIB_COLOR0]) {
eval2_4f_ca( &tmp->Color, coord, flags, 4,
&ctx->EvalMap.Map2Attrib[VERT_ATTRIB_COLOR0] );
generated |= VERT_BIT_EVAL_C2|VERT_BIT_EVAL_P2;
}
else if (ctx->Eval.Map2Color4) {
eval2_4f_ca( &tmp->Color, coord, flags, 4,
&ctx->EvalMap.Map2Color4 );
generated |= VERT_BIT_EVAL_C2|VERT_BIT_EVAL_P2;
}
}
}
 
if (req & VERT_BIT_TEX0) {
GLuint generated = 0;
 
if (copycount)
copy_4f( store->Attrib[VERT_ATTRIB_TEX0] + IM->CopyStart,
tmp->TexCoord[0].data, copycount );
else
tmp->TexCoord[0].size = 0;
 
tmp->TexCoord[0].data = store->Attrib[VERT_ATTRIB_TEX0] + IM->CopyStart;
tmp->TexCoord[0].start = (GLfloat *)tmp->TexCoord[0].data;
 
if (ctx->VertexProgram.Enabled) {
tmp->Attribs[VERT_ATTRIB_TEX0].data =
store->Attrib[VERT_ATTRIB_TEX0] + IM->CopyStart;
tmp->Attribs[VERT_ATTRIB_TEX0].start =
(GLfloat *) tmp->Attribs[VERT_ATTRIB_TEX0].data;
tmp->Attribs[VERT_ATTRIB_TEX0].size = 0;
}
 
/* Vertex program maps have priority over conventional attribs */
if (any_eval1) {
if (ctx->VertexProgram.Enabled
&& ctx->Eval.Map1Attrib[VERT_ATTRIB_TEX0]) {
eval1_4f( &tmp->TexCoord[0], coord, flags, 4,
&ctx->EvalMap.Map1Attrib[VERT_ATTRIB_TEX0] );
generated |= VERT_BIT_EVAL_C1|VERT_BIT_EVAL_P1;
}
else if (ctx->Eval.Map1TextureCoord4) {
eval1_4f( &tmp->TexCoord[0], coord, flags, 4,
&ctx->EvalMap.Map1Texture4 );
generated |= VERT_BIT_EVAL_C1|VERT_BIT_EVAL_P1;
}
else if (ctx->Eval.Map1TextureCoord3) {
eval1_4f( &tmp->TexCoord[0], coord, flags, 3,
&ctx->EvalMap.Map1Texture3 );
generated |= VERT_BIT_EVAL_C1|VERT_BIT_EVAL_P1;
}
else if (ctx->Eval.Map1TextureCoord2) {
eval1_4f( &tmp->TexCoord[0], coord, flags, 2,
&ctx->EvalMap.Map1Texture2 );
generated |= VERT_BIT_EVAL_C1|VERT_BIT_EVAL_P1;
}
else if (ctx->Eval.Map1TextureCoord1) {
eval1_4f( &tmp->TexCoord[0], coord, flags, 1,
&ctx->EvalMap.Map1Texture1 );
generated |= VERT_BIT_EVAL_C1|VERT_BIT_EVAL_P1;
}
}
 
if (any_eval2) {
if (ctx->VertexProgram.Enabled
&& ctx->Eval.Map2Attrib[VERT_ATTRIB_TEX0]) {
eval2_4f( &tmp->TexCoord[0], coord, flags, 4,
&ctx->EvalMap.Map2Attrib[VERT_ATTRIB_TEX0] );
generated |= VERT_BIT_EVAL_C1|VERT_BIT_EVAL_P1;
}
else if (ctx->Eval.Map2TextureCoord4) {
eval2_4f( &tmp->TexCoord[0], coord, flags, 4,
&ctx->EvalMap.Map2Texture4 );
generated |= VERT_BIT_EVAL_C2|VERT_BIT_EVAL_P2;
}
else if (ctx->Eval.Map2TextureCoord3) {
eval2_4f( &tmp->TexCoord[0], coord, flags, 3,
&ctx->EvalMap.Map2Texture3 );
generated |= VERT_BIT_EVAL_C2|VERT_BIT_EVAL_P2;
}
else if (ctx->Eval.Map2TextureCoord2) {
eval2_4f( &tmp->TexCoord[0], coord, flags, 2,
&ctx->EvalMap.Map2Texture2 );
generated |= VERT_BIT_EVAL_C2|VERT_BIT_EVAL_P2;
}
else if (ctx->Eval.Map2TextureCoord1) {
eval2_4f( &tmp->TexCoord[0], coord, flags, 1,
&ctx->EvalMap.Map2Texture1 );
generated |= VERT_BIT_EVAL_C2|VERT_BIT_EVAL_P2;
}
}
}
 
if (req & VERT_BIT_NORMAL) {
GLuint generated = 0;
 
if (copycount) {
copy_3f( store->Attrib[VERT_ATTRIB_NORMAL] + IM->CopyStart,
tmp->Normal.data, copycount );
}
 
tmp->Normal.data = store->Attrib[VERT_ATTRIB_NORMAL] + IM->CopyStart;
tmp->Normal.start = (GLfloat *)tmp->Normal.data;
 
if (ctx->VertexProgram.Enabled) {
tmp->Attribs[VERT_ATTRIB_NORMAL].data =
store->Attrib[VERT_ATTRIB_NORMAL] + IM->CopyStart;
tmp->Attribs[VERT_ATTRIB_NORMAL].start =
(GLfloat *) tmp->Attribs[VERT_ATTRIB_NORMAL].data;
tmp->Attribs[VERT_ATTRIB_NORMAL].size = 0;
}
 
if (any_eval1) {
if (ctx->VertexProgram.Enabled &&
ctx->Eval.Map1Attrib[VERT_ATTRIB_NORMAL]) {
eval1_norm( &tmp->Normal, coord, flags,
&ctx->EvalMap.Map1Attrib[VERT_ATTRIB_NORMAL] );
generated |= VERT_BIT_EVAL_C1|VERT_BIT_EVAL_P1;
}
else if (ctx->Eval.Map1Normal) {
eval1_norm( &tmp->Normal, coord, flags, &ctx->EvalMap.Map1Normal );
generated |= VERT_BIT_EVAL_C1|VERT_BIT_EVAL_P1;
}
}
 
if (any_eval2) {
if (ctx->VertexProgram.Enabled &&
ctx->Eval.Map2Attrib[VERT_ATTRIB_NORMAL]) {
eval2_norm( &tmp->Normal, coord, flags,
&ctx->EvalMap.Map2Attrib[VERT_ATTRIB_NORMAL] );
generated |= VERT_BIT_EVAL_C2|VERT_BIT_EVAL_P2;
}
else if (ctx->Eval.Map2Normal) {
eval2_norm( &tmp->Normal, coord, flags, &ctx->EvalMap.Map2Normal );
generated |= VERT_BIT_EVAL_C2|VERT_BIT_EVAL_P2;
}
}
}
 
/* In the AutoNormal case, the copy and assignment of tmp->NormalPtr
* are done above.
*/
if (req & VERT_BIT_POS) {
if (copycount) {
/* This copy may already have occurred when eliminating
* glEvalPoint calls:
*/
if (coord != store->Attrib[VERT_ATTRIB_POS] + IM->CopyStart) {
copy_4f( store->Attrib[VERT_ATTRIB_POS] + IM->CopyStart,
tmp->Obj.data, copycount );
}
}
else {
tmp->Obj.size = 0;
}
 
tmp->Obj.data = store->Attrib[VERT_ATTRIB_POS] + IM->CopyStart;
tmp->Obj.start = (GLfloat *) tmp->Obj.data;
 
#if 1
/*tmp->Attribs[0].count = count;*/
tmp->Attribs[0].data = store->Attrib[0] + IM->CopyStart;
tmp->Attribs[0].start = (GLfloat *) tmp->Attribs[0].data;
tmp->Attribs[0].size = 0;
#endif
 
/* Note: Normal data is already prepared above.
*/
 
if (any_eval1) {
if (ctx->VertexProgram.Enabled &&
ctx->Eval.Map1Attrib[VERT_ATTRIB_POS]) {
eval1_4f( &tmp->Obj, coord, flags, 4,
&ctx->EvalMap.Map1Attrib[VERT_ATTRIB_POS] );
}
else if (ctx->Eval.Map1Vertex4) {
eval1_4f( &tmp->Obj, coord, flags, 4,
&ctx->EvalMap.Map1Vertex4 );
}
else if (ctx->Eval.Map1Vertex3) {
eval1_4f( &tmp->Obj, coord, flags, 3,
&ctx->EvalMap.Map1Vertex3 );
}
}
 
if (any_eval2) {
if (ctx->VertexProgram.Enabled &&
ctx->Eval.Map2Attrib[VERT_ATTRIB_POS]) {
if (ctx->Eval.AutoNormal && (req & VERT_BIT_NORMAL))
eval2_obj_norm( &tmp->Obj, &tmp->Normal, coord, flags, 4,
&ctx->EvalMap.Map2Attrib[VERT_ATTRIB_POS] );
else
eval2_4f( &tmp->Obj, coord, flags, 4,
&ctx->EvalMap.Map2Attrib[VERT_ATTRIB_POS] );
}
else if (ctx->Eval.Map2Vertex4) {
if (ctx->Eval.AutoNormal && (req & VERT_BIT_NORMAL))
eval2_obj_norm( &tmp->Obj, &tmp->Normal, coord, flags, 4,
&ctx->EvalMap.Map2Vertex4 );
else
eval2_4f( &tmp->Obj, coord, flags, 4,
&ctx->EvalMap.Map2Vertex4 );
}
else if (ctx->Eval.Map2Vertex3) {
if (ctx->Eval.AutoNormal && (req & VERT_BIT_NORMAL))
eval2_obj_norm( &tmp->Obj, &tmp->Normal, coord, flags, 3,
&ctx->EvalMap.Map2Vertex3 );
else
eval2_4f( &tmp->Obj, coord, flags, 3,
&ctx->EvalMap.Map2Vertex3 );
}
}
}
 
 
if (ctx->VertexProgram.Enabled) {
/* We already evaluated position, normal, color and texture 0 above.
* now evaluate any other generic attributes.
*/
const GLuint skipBits = (VERT_BIT_POS |
VERT_BIT_NORMAL |
VERT_BIT_COLOR0 |
VERT_BIT_TEX0);
GLuint generated = 0;
GLuint attr;
for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) {
if ((1 << attr) & req & ~skipBits) {
if (any_eval1 && ctx->Eval.Map1Attrib[attr]) {
/* evaluate 1-D vertex attrib map [i] */
eval1_4f( &tmp->Attribs[attr], coord, flags, 4,
&ctx->EvalMap.Map1Attrib[attr] );
generated |= VERT_BIT_EVAL_C1|VERT_BIT_EVAL_P1;
}
if (any_eval2 && ctx->Eval.Map2Attrib[attr]) {
/* evaluate 2-D vertex attrib map [i] */
eval2_4f( &tmp->Attribs[attr], coord, flags, 4,
&ctx->EvalMap.Map2Attrib[attr] );
generated |= VERT_BIT_EVAL_C1|VERT_BIT_EVAL_P1;
}
}
}
}
 
/* Calculate new IM->Elts, IM->Primitive, IM->PrimitiveLength for
* the case where vertex maps are not enabled for some received
* eval coordinates. In this case those slots in the immediate
* must be ignored.
*/
if (purge_flags) {
const GLuint vertex = VERT_BIT_POS|(VERT_BITS_EVAL_ANY & ~purge_flags);
GLuint last_new_prim = 0;
GLuint new_prim_length = 0;
GLuint next_old_prim = 0;
struct vertex_buffer *VB = &tnl->vb;
const GLuint count = VB->Count;
GLuint i, j;
 
for (i = 0, j = 0 ; i < count ; i++) {
if (flags[i] & vertex) {
store->Elt[j++] = i;
new_prim_length++;
}
if (i == next_old_prim) {
next_old_prim += VB->PrimitiveLength[i];
VB->PrimitiveLength[last_new_prim] = new_prim_length;
VB->Primitive[j] = VB->Primitive[i];
last_new_prim = j;
}
}
VB->Elts = store->Elt;
_tnl_get_purged_copy_verts( ctx, store );
}
 
/* Produce new flags array:
*/
{
const GLuint count = tnl->vb.Count + 1;
GLuint i;
 
copy_1ui( store->Flag, flags, count );
tnl->vb.Flag = store->Flag;
for (i = 0 ; i < count ; i++)
store->Flag[i] |= req;
IM->Evaluated = req; /* hack for copying. */
}
}
/shark/trunk/ports/mesa/src/tnl/t_imm_exec.h
0,0 → 1,70
/* $Id: t_imm_exec.h,v 1.1 2003-02-28 11:48:07 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
 
#ifndef _T_VBXFORM_H
#define _T_VBXFORM_H
 
#include "mtypes.h"
#include "t_context.h"
 
 
/* Hook for ctx->Driver.FlushVertices:
*/
extern void _tnl_flush_vertices( GLcontext *ctx, GLuint flush_flags );
 
/* Called from imm_api.c and _tnl_flush_vertices:
*/
extern void _tnl_flush_immediate( GLcontext *ctx, struct immediate *IM );
 
/* Called from imm_dlist.c and _tnl_flush_immediate:
*/
extern void _tnl_run_cassette( GLcontext *ctx, struct immediate *IM );
extern void _tnl_copy_to_current( GLcontext *ctx, struct immediate *IM,
GLuint flag, GLuint row );
 
/* Initialize some stuff:
*/
extern void _tnl_imm_init( GLcontext *ctx );
 
extern void _tnl_imm_destroy( GLcontext *ctx );
 
extern void _tnl_reset_exec_input( GLcontext *ctx,
GLuint start,
GLuint beginstate,
GLuint savedbeginstate );
 
extern void _tnl_reset_compile_input( GLcontext *ctx,
GLuint start,
GLuint beginstate,
GLuint savedbeginstate );
 
extern void _tnl_compute_orflag( struct immediate *IM, GLuint start );
extern void _tnl_execute_cassette( GLcontext *ctx, struct immediate *IM );
 
 
 
#endif
/shark/trunk/ports/mesa/src/tnl/t_imm_elt.h
0,0 → 1,46
/* $Id: t_imm_elt.h,v 1.1 2003-02-28 11:48:07 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
 
#ifndef _T_IMM_ELT_H_
#define _T_IMM_ELT_H_
 
#include "mtypes.h"
#include "t_context.h"
 
 
extern void _tnl_imm_elt_init( void );
 
extern void _tnl_translate_array_elts( GLcontext *ctx,
struct immediate *IM,
GLuint start,
GLuint end );
 
 
#endif
/shark/trunk/ports/mesa/src/tnl/t_imm_debug.h
0,0 → 1,39
/* $Id: t_imm_debug.h,v 1.1 2003-02-28 11:48:06 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
#ifndef _T_DEBUG_H
#define _T_DEBUG_H
 
#include "mtypes.h"
#include "t_context.h"
 
void _tnl_print_cassette( struct immediate *IM );
void _tnl_print_vert_flags( const char *name, GLuint flags );
 
#endif
/shark/trunk/ports/mesa/src/tnl/t_vb_light.c
0,0 → 1,350
/* $Id: t_vb_light.c,v 1.1 2003-02-28 11:48:07 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
 
 
#include "glheader.h"
#include "colormac.h"
#include "light.h"
#include "macros.h"
#include "imports.h"
#include "mmath.h"
#include "simple_list.h"
#include "mtypes.h"
 
#include "math/m_translate.h"
 
#include "t_context.h"
#include "t_pipeline.h"
 
#define LIGHT_FLAGS 0x1 /* must be first */
#define LIGHT_TWOSIDE 0x2
#define LIGHT_COLORMATERIAL 0x4
#define MAX_LIGHT_FUNC 0x8
 
typedef void (*light_func)( GLcontext *ctx,
struct vertex_buffer *VB,
struct gl_pipeline_stage *stage,
GLvector4f *input );
 
struct light_stage_data {
struct gl_client_array FloatColor;
struct gl_client_array LitColor[2];
struct gl_client_array LitSecondary[2];
GLvector1ui LitIndex[2];
light_func *light_func_tab;
};
 
 
#define LIGHT_STAGE_DATA(stage) ((struct light_stage_data *)(stage->privatePtr))
 
 
static void import_color_material( GLcontext *ctx,
struct gl_pipeline_stage *stage )
{
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
struct gl_client_array *to = &LIGHT_STAGE_DATA(stage)->FloatColor;
struct gl_client_array *from = VB->ColorPtr[0];
GLuint count = VB->Count;
 
if (!to->Ptr) {
to->Ptr = ALIGN_MALLOC( VB->Size * 4 * sizeof(GLfloat), 32 );
to->Type = GL_FLOAT;
}
 
/* No need to transform the same value 3000 times.
*/
if (!from->StrideB) {
to->StrideB = 0;
count = 1;
}
else
to->StrideB = 4 * sizeof(GLfloat);
_math_trans_4f( (GLfloat (*)[4]) to->Ptr,
from->Ptr,
from->StrideB,
from->Type,
from->Size,
0,
count);
 
VB->ColorPtr[0] = to;
}
 
 
/* Tables for all the shading functions.
*/
static light_func _tnl_light_tab[MAX_LIGHT_FUNC];
static light_func _tnl_light_fast_tab[MAX_LIGHT_FUNC];
static light_func _tnl_light_fast_single_tab[MAX_LIGHT_FUNC];
static light_func _tnl_light_spec_tab[MAX_LIGHT_FUNC];
static light_func _tnl_light_ci_tab[MAX_LIGHT_FUNC];
 
#define TAG(x) x
#define IDX (0)
#include "t_vb_lighttmp.h"
 
#define TAG(x) x##_tw
#define IDX (LIGHT_TWOSIDE)
#include "t_vb_lighttmp.h"
 
#define TAG(x) x##_fl
#define IDX (LIGHT_FLAGS)
#include "t_vb_lighttmp.h"
 
#define TAG(x) x##_tw_fl
#define IDX (LIGHT_FLAGS|LIGHT_TWOSIDE)
#include "t_vb_lighttmp.h"
 
#define TAG(x) x##_cm
#define IDX (LIGHT_COLORMATERIAL)
#include "t_vb_lighttmp.h"
 
#define TAG(x) x##_tw_cm
#define IDX (LIGHT_TWOSIDE|LIGHT_COLORMATERIAL)
#include "t_vb_lighttmp.h"
 
#define TAG(x) x##_fl_cm
#define IDX (LIGHT_FLAGS|LIGHT_COLORMATERIAL)
#include "t_vb_lighttmp.h"
 
#define TAG(x) x##_tw_fl_cm
#define IDX (LIGHT_FLAGS|LIGHT_TWOSIDE|LIGHT_COLORMATERIAL)
#include "t_vb_lighttmp.h"
 
 
static void init_lighting( void )
{
static int done;
 
if (!done) {
init_light_tab();
init_light_tab_tw();
init_light_tab_fl();
init_light_tab_tw_fl();
init_light_tab_cm();
init_light_tab_tw_cm();
init_light_tab_fl_cm();
init_light_tab_tw_fl_cm();
done = 1;
}
}
 
 
static GLboolean run_lighting( GLcontext *ctx, struct gl_pipeline_stage *stage )
{
struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
GLvector4f *input = ctx->_NeedEyeCoords ? VB->EyePtr : VB->ObjPtr;
GLuint ind;
 
/* _tnl_print_vert_flags( __FUNCTION__, stage->changed_inputs ); */
 
/* Make sure we can talk about elements 0..2 in the vector we are
* lighting.
*/
if (stage->changed_inputs & (VERT_BIT_EYE|VERT_BIT_POS)) {
if (input->size <= 2) {
if (input->flags & VEC_NOT_WRITEABLE) {
ASSERT(VB->importable_data & VERT_BIT_POS);
 
VB->import_data( ctx, VERT_BIT_POS, VEC_NOT_WRITEABLE );
input = ctx->_NeedEyeCoords ? VB->EyePtr : VB->ObjPtr;
 
ASSERT((input->flags & VEC_NOT_WRITEABLE) == 0);
}
 
_mesa_vector4f_clean_elem(input, VB->Count, 2);
}
}
 
if (VB->Flag)
ind = LIGHT_FLAGS;
else
ind = 0;
 
/* The individual functions know about replaying side-effects
* vs. full re-execution.
*/
store->light_func_tab[ind]( ctx, VB, stage, input );
 
return GL_TRUE;
}
 
 
/* Called in place of do_lighting when the light table may have changed.
*/
static GLboolean run_validate_lighting( GLcontext *ctx,
struct gl_pipeline_stage *stage )
{
GLuint ind = 0;
light_func *tab;
 
if (ctx->Visual.rgbMode) {
if (ctx->Light._NeedVertices) {
if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)
tab = _tnl_light_spec_tab;
else
tab = _tnl_light_tab;
}
else {
if (ctx->Light.EnabledList.next == ctx->Light.EnabledList.prev)
tab = _tnl_light_fast_single_tab;
else
tab = _tnl_light_fast_tab;
}
}
else
tab = _tnl_light_ci_tab;
 
if (ctx->Light.ColorMaterialEnabled)
ind |= LIGHT_COLORMATERIAL;
 
if (ctx->Light.Model.TwoSide)
ind |= LIGHT_TWOSIDE;
 
LIGHT_STAGE_DATA(stage)->light_func_tab = &tab[ind];
 
/* This and the above should only be done on _NEW_LIGHT:
*/
TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx );
 
/* Now run the stage...
*/
stage->run = run_lighting;
return stage->run( ctx, stage );
}
 
static void alloc_4chan( struct gl_client_array *a, GLuint sz )
{
a->Ptr = ALIGN_MALLOC( sz * sizeof(GLchan) * 4, 32 );
a->Size = 4;
a->Type = CHAN_TYPE;
a->Stride = 0;
a->StrideB = sizeof(GLchan) * 4;
a->Enabled = 0;
a->Flags = 0;
}
 
 
/* Called the first time stage->run is called. In effect, don't
* allocate data until the first time the stage is run.
*/
static GLboolean run_init_lighting( GLcontext *ctx,
struct gl_pipeline_stage *stage )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct light_stage_data *store;
GLuint size = tnl->vb.Size;
 
stage->privatePtr = MALLOC(sizeof(*store));
store = LIGHT_STAGE_DATA(stage);
if (!store)
return GL_FALSE;
 
/* Do onetime init.
*/
init_lighting();
 
store->FloatColor.Ptr = 0;
 
alloc_4chan( &store->LitColor[0], size );
alloc_4chan( &store->LitColor[1], size );
alloc_4chan( &store->LitSecondary[0], size );
alloc_4chan( &store->LitSecondary[1], size );
 
_mesa_vector1ui_alloc( &store->LitIndex[0], 0, size, 32 );
_mesa_vector1ui_alloc( &store->LitIndex[1], 0, size, 32 );
 
/* Now validate the stage derived data...
*/
stage->run = run_validate_lighting;
return stage->run( ctx, stage );
}
 
 
 
/*
* Check if lighting is enabled. If so, configure the pipeline stage's
* type, inputs, and outputs.
*/
static void check_lighting( GLcontext *ctx, struct gl_pipeline_stage *stage )
{
stage->active = ctx->Light.Enabled && !ctx->VertexProgram.Enabled;
if (stage->active) {
if (stage->privatePtr)
stage->run = run_validate_lighting;
stage->inputs = VERT_BIT_NORMAL|VERT_BIT_MATERIAL;
if (ctx->Light._NeedVertices)
stage->inputs |= VERT_BIT_EYE; /* effectively, even when lighting in obj */
if (ctx->Light.ColorMaterialEnabled)
stage->inputs |= VERT_BIT_COLOR0;
 
stage->outputs = VERT_BIT_COLOR0;
if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)
stage->outputs |= VERT_BIT_COLOR1;
}
}
 
 
static void dtr( struct gl_pipeline_stage *stage )
{
struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
 
if (store) {
ALIGN_FREE( store->LitColor[0].Ptr );
ALIGN_FREE( store->LitColor[1].Ptr );
ALIGN_FREE( store->LitSecondary[0].Ptr );
ALIGN_FREE( store->LitSecondary[1].Ptr );
 
if (store->FloatColor.Ptr)
ALIGN_FREE( store->FloatColor.Ptr );
 
_mesa_vector1ui_free( &store->LitIndex[0] );
_mesa_vector1ui_free( &store->LitIndex[1] );
FREE( store );
stage->privatePtr = 0;
}
}
 
const struct gl_pipeline_stage _tnl_lighting_stage =
{
"lighting", /* name */
_NEW_LIGHT, /* recheck */
_NEW_LIGHT|_NEW_MODELVIEW, /* recalc -- modelview dependency
* otherwise not captured by inputs
* (which may be VERT_BIT_POS) */
GL_FALSE, /* active? */
0, /* inputs */
0, /* outputs */
0, /* changed_inputs */
NULL, /* private_data */
dtr, /* destroy */
check_lighting, /* check */
run_init_lighting /* run -- initially set to ctr */
};
/shark/trunk/ports/mesa/src/tnl/t_imm_eval.h
0,0 → 1,39
/* $Id: t_imm_eval.h,v 1.1 2003-02-28 11:48:07 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
 
#ifndef _T_IMM_EVAL_H
#define _T_IMM_EVAL_H
 
 
#include "mtypes.h"
#include "t_context.h"
 
extern void _tnl_eval_init( void );
 
extern void _tnl_eval_immediate( GLcontext *ctx, struct immediate *IM );
 
#endif
/shark/trunk/ports/mesa/src/tnl/t_vb_program.c
0,0 → 1,477
/* $Id: t_vb_program.c,v 1.1 2003-02-28 11:48:07 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 5.0
*
* Copyright (C) 1999-2002 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.
*/
 
/*
* -------- Regarding NV_vertex_program --------
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* o Redistribution of the source code must contain a copyright notice
* and this list of conditions;
*
* o Redistribution in binary and source code form must contain the
* following Notice in the software and any documentation and/or other
* materials provided with the distribution; and
*
* o The name of Nvidia may not be used to promote or endorse software
* derived from the software.
*
* NOTICE: Nvidia hereby grants to each recipient a non-exclusive worldwide
* royalty free patent license under patent claims that are licensable by
* Nvidia and which are necessarily required and for which no commercially
* viable non infringing alternative exists to make, use, sell, offer to sell,
* import and otherwise transfer the vertex extension for the Mesa 3D Graphics
* Library as distributed in source code and object code form. No hardware or
* hardware implementation (including a semiconductor implementation and chips)
* are licensed hereunder. If a recipient makes a patent claim or institutes
* patent litigation against Nvidia or Nvidia's customers for use or sale of
* Nvidia products, then this license grant as to such recipient shall
* immediately terminate and recipient immediately agrees to cease use and
* distribution of the Mesa Program and derivatives thereof.
*
* THE MESA 3D GRAPHICS LIBRARY IS PROVIDED ON AN "AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING,
* WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-NFRINGEMENT
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
*
* NVIDIA SHALL NOT HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION
* LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE MESA 3D GRAPHICS
* LIBRARY OR EVIDENCE OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDR, EVEN
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* If you do not comply with this agreement, then Nvidia may cancel the license
* and rights granted herein.
* ---------------------------------------------
*/
 
/**
* \file tnl/t_vb_program.c
* \brief Pipeline stage for executing vertex programs
* \author Brian Paul, Keith Whitwell
*/
 
 
#include "glheader.h"
#include "api_noop.h"
#include "colormac.h"
#include "context.h"
#include "dlist.h"
#include "hash.h"
#include "light.h"
#include "macros.h"
#include "imports.h"
#include "mmath.h"
#include "simple_list.h"
#include "mtypes.h"
#include "vpexec.h"
 
#include "math/m_translate.h"
 
#include "t_context.h"
#include "t_pipeline.h"
#include "t_imm_api.h"
#include "t_imm_exec.h"
 
 
/**
* \warning These values _MUST_ match the values in the OutputRegisters[]
* array in vpparse.c!!!
*/
#define VERT_RESULT_HPOS 0
#define VERT_RESULT_COL0 1
#define VERT_RESULT_COL1 2
#define VERT_RESULT_BFC0 3
#define VERT_RESULT_BFC1 4
#define VERT_RESULT_FOGC 5
#define VERT_RESULT_PSIZ 6
#define VERT_RESULT_TEX0 7
#define VERT_RESULT_TEX1 8
#define VERT_RESULT_TEX2 9
#define VERT_RESULT_TEX3 10
#define VERT_RESULT_TEX4 11
#define VERT_RESULT_TEX5 12
#define VERT_RESULT_TEX6 13
#define VERT_RESULT_TEX7 14
 
 
/*!
* Private storage for the vertex program pipeline stage.
*/
struct vp_stage_data {
/** The results of running the vertex program go into these arrays. */
GLvector4f attribs[15];
 
/* These point to the attribs[VERT_RESULT_COL0, COL1, BFC0, BFC1] arrays */
struct gl_client_array color0[2]; /**< diffuse front and back */
struct gl_client_array color1[2]; /**< specular front and back */
 
GLvector4f ndcCoords; /**< normalized device coords */
GLubyte *clipmask; /**< clip flags */
GLubyte ormask, andmask; /**< for clipping */
};
 
 
#define VP_STAGE_DATA(stage) ((struct vp_stage_data *)(stage->privatePtr))
 
 
/**
* This function executes vertex programs
*/
static GLboolean run_vp( GLcontext *ctx, struct gl_pipeline_stage *stage )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vp_stage_data *store = VP_STAGE_DATA(stage);
struct vertex_buffer *VB = &tnl->vb;
struct vp_machine *machine = &(ctx->VertexProgram.Machine);
struct vp_program *program = ctx->VertexProgram.Current;
GLuint i;
 
_mesa_init_tracked_matrices(ctx); /* load registers with matrices */
_mesa_init_vp_registers(ctx); /* init temp and result regs */
 
for (i = 0; i < VB->Count; i++) {
GLuint attr;
 
#if 0
printf("Input %d: %f, %f, %f, %f\n", i,
VB->AttribPtr[0]->data[i][0],
VB->AttribPtr[0]->data[i][1],
VB->AttribPtr[0]->data[i][2],
VB->AttribPtr[0]->data[i][3]);
printf(" color: %f, %f, %f, %f\n",
VB->AttribPtr[3]->data[i][0],
VB->AttribPtr[3]->data[i][1],
VB->AttribPtr[3]->data[i][2],
VB->AttribPtr[3]->data[i][3]);
printf(" normal: %f, %f, %f, %f\n",
VB->AttribPtr[2]->data[i][0],
VB->AttribPtr[2]->data[i][1],
VB->AttribPtr[2]->data[i][2],
VB->AttribPtr[2]->data[i][3]);
#endif
 
/* load the input attribute registers */
if (VB->Flag) {
/* the traditional glBegin/glVertex/glEnd case */
for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) {
if (attr == 0 || (VB->Flag[i] & (1 << attr))) {
COPY_4V(machine->Registers[VP_INPUT_REG_START + attr],
VB->AttribPtr[attr]->data[i]);
}
}
}
else {
/* the vertex array case */
for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) {
if (program->InputsRead & (1 << attr)) {
const GLubyte *ptr = (const GLubyte*) VB->AttribPtr[attr]->data;
const GLuint stride = VB->AttribPtr[attr]->stride;
const GLfloat *data = (GLfloat *) (ptr + stride * i);
COPY_4V(machine->Registers[VP_INPUT_REG_START + attr], data);
/*ASSERT(VB->AttribPtr[attr]->size == 4);*/
ASSERT(stride == 4 * sizeof(GLfloat) || stride == 0);
}
}
}
 
/* execute the program */
ASSERT(program);
_mesa_exec_program(ctx, program);
 
#if 0
printf("Output %d: %f, %f, %f, %f\n", i,
machine->Registers[VP_OUTPUT_REG_START + 0][0],
machine->Registers[VP_OUTPUT_REG_START + 0][1],
machine->Registers[VP_OUTPUT_REG_START + 0][2],
machine->Registers[VP_OUTPUT_REG_START + 0][3]);
printf(" color: %f, %f, %f, %f\n",
machine->Registers[VP_OUTPUT_REG_START +_1][0],
machine->Registers[VP_OUTPUT_REG_START + 1][1],
machine->Registers[VP_OUTPUT_REG_START + 1][2],
machine->Registers[VP_OUTPUT_REG_START + 1][3]);
printf("PointSize[%d]: %g\n", i,
machine->Registers[VP_OUTPUT_REG_START + VERT_RESULT_PSIZ][0]);
#endif
 
/* Fixup fog an point size results if needed */
if (ctx->Fog.Enabled &&
(program->OutputsWritten & (1 << VERT_RESULT_FOGC)) == 0) {
machine->Registers[VP_OUTPUT_REG_START + VERT_RESULT_FOGC][0] = 1.0;
}
 
if (ctx->VertexProgram.PointSizeEnabled &&
(program->OutputsWritten & (1 << VERT_RESULT_PSIZ)) == 0) {
machine->Registers[VP_OUTPUT_REG_START + VERT_RESULT_PSIZ][0]
= ctx->Point.Size;
}
 
/* copy the output registers into the VB->attribs arrays */
/* XXX (optimize) could use a conditional and smaller loop limit here */
for (attr = 0; attr < 15; attr++) {
COPY_4V( store->attribs[attr].data[i],
machine->Registers[VP_OUTPUT_REG_START + attr] );
}
}
 
/* Setup the VB pointers so that the next pipeline stages get
* their data from the right place (the program output arrays).
*/
VB->ClipPtr = &store->attribs[VERT_RESULT_HPOS];
VB->ClipPtr->size = 4;
VB->ClipPtr->count = VB->Count;
VB->ColorPtr[0] = &store->color0[0];
VB->ColorPtr[1] = &store->color0[1];
VB->SecondaryColorPtr[0] = &store->color1[0];
VB->SecondaryColorPtr[1] = &store->color1[1];
VB->FogCoordPtr = &store->attribs[VERT_RESULT_FOGC];
VB->PointSizePtr = &store->attribs[VERT_RESULT_PSIZ];
for (i = 0; i < ctx->Const.MaxTextureUnits; i++)
VB->TexCoordPtr[i] = &store->attribs[VERT_RESULT_TEX0 + i];
 
/* Cliptest and perspective divide. Clip functions must clear
* the clipmask.
*/
store->ormask = 0;
store->andmask = CLIP_ALL_BITS;
 
if (tnl->NeedNdcCoords) {
VB->NdcPtr =
_mesa_clip_tab[VB->ClipPtr->size]( VB->ClipPtr,
&store->ndcCoords,
store->clipmask,
&store->ormask,
&store->andmask );
}
else {
VB->NdcPtr = 0;
_mesa_clip_np_tab[VB->ClipPtr->size]( VB->ClipPtr,
0,
store->clipmask,
&store->ormask,
&store->andmask );
}
 
if (store->andmask) /* All vertices are outside the frustum */
return GL_FALSE;
 
 
/* This is where we'd do clip testing against the user-defined
* clipping planes, but they're not supported by vertex programs.
*/
 
VB->ClipOrMask = store->ormask;
VB->ClipMask = store->clipmask;
 
/* XXXX what's this?
if (VB->ClipPtr == VB->ObjPtr && (VB->importable_data & VERT_BIT_POS))
VB->importable_data |= VERT_BIT_CLIP;
*/
 
return GL_TRUE;
}
 
 
/**
* This function validates stuff.
*/
static GLboolean run_validate_program( GLcontext *ctx,
struct gl_pipeline_stage *stage )
{
#if 000
/* XXX do we need any validation for vertex programs? */
GLuint ind = 0;
light_func *tab;
 
if (ctx->Visual.rgbMode) {
if (ctx->Light._NeedVertices) {
if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)
tab = _tnl_light_spec_tab;
else
tab = _tnl_light_tab;
}
else {
if (ctx->Light.EnabledList.next == ctx->Light.EnabledList.prev)
tab = _tnl_light_fast_single_tab;
else
tab = _tnl_light_fast_tab;
}
}
else
tab = _tnl_light_ci_tab;
 
if (ctx->Light.ColorMaterialEnabled)
ind |= LIGHT_COLORMATERIAL;
 
if (ctx->Light.Model.TwoSide)
ind |= LIGHT_TWOSIDE;
 
VP_STAGE_DATA(stage)->light_func_tab = &tab[ind];
 
/* This and the above should only be done on _NEW_LIGHT:
*/
_mesa_validate_all_lighting_tables( ctx );
#endif
 
/* Now run the stage...
*/
stage->run = run_vp;
return stage->run( ctx, stage );
}
 
 
/**
* Initialize a gl_client_array to point into a GLvector4f color vector.
*/
static void init_color_array( struct gl_client_array *a, GLvector4f *vec )
{
a->Ptr = vec->data;
a->Size = 4;
a->Type = GL_FLOAT;
a->Stride = 0;
a->StrideB = sizeof(GLfloat) * 4;
a->Enabled = 0;
a->Flags = 0;
}
 
 
/**
* Called the first time stage->run is called. In effect, don't
* allocate data until the first time the stage is run.
*/
static GLboolean run_init_vp( GLcontext *ctx,
struct gl_pipeline_stage *stage )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &(tnl->vb);
struct vp_stage_data *store;
const GLuint size = VB->Size;
GLuint i;
 
stage->privatePtr = MALLOC(sizeof(*store));
store = VP_STAGE_DATA(stage);
if (!store)
return GL_FALSE;
 
/* Allocate arrays of vertex output values */
for (i = 0; i < 15; i++)
_mesa_vector4f_alloc( &store->attribs[i], 0, size, 32 );
 
/* Make the color0[] and color1[] arrays point into the attribs[] arrays */
init_color_array( &store->color0[0], &store->attribs[VERT_RESULT_COL0] );
init_color_array( &store->color0[1], &store->attribs[VERT_RESULT_COL1] );
init_color_array( &store->color1[0], &store->attribs[VERT_RESULT_BFC0] );
init_color_array( &store->color1[1], &store->attribs[VERT_RESULT_BFC1] );
 
/* a few other misc allocations */
_mesa_vector4f_alloc( &store->ndcCoords, 0, size, 32 );
store->clipmask = (GLubyte *) ALIGN_MALLOC(sizeof(GLubyte)*size, 32 );
 
/* Now validate the stage derived data...
*/
stage->run = run_validate_program;
return stage->run( ctx, stage );
}
 
 
 
/**
* Check if vertex program mode is enabled.
* If so, configure the pipeline stage's type, inputs, and outputs.
*/
static void check_vp( GLcontext *ctx, struct gl_pipeline_stage *stage )
{
stage->active = ctx->VertexProgram.Enabled;
 
if (stage->active) {
/* I believe this is right - Keith?
* Set stage->inputs equal to the bitmask of vertex attributes
* which the program needs for inputs.
*/
 
stage->inputs = ctx->VertexProgram.Current->InputsRead;
 
#if 000
if (stage->privatePtr)
stage->run = run_validate_program;
stage->inputs = VERT_BIT_NORMAL|VERT_BIT_MATERIAL;
if (ctx->Light._NeedVertices)
stage->inputs |= VERT_BIT_EYE; /* effectively, even when lighting in obj */
if (ctx->Light.ColorMaterialEnabled)
stage->inputs |= VERT_BIT_COLOR0;
 
stage->outputs = VERT_BIT_COLOR0;
if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)
stage->outputs |= VERT_BIT_COLOR1;
#endif
}
}
 
 
/**
* Destructor for this pipeline stage.
*/
static void dtr( struct gl_pipeline_stage *stage )
{
struct vp_stage_data *store = VP_STAGE_DATA(stage);
 
if (store) {
GLuint i;
 
/* free the vertex program result arrays */
for (i = 0; i < 15; i++)
_mesa_vector4f_free( &store->attribs[i] );
 
/* free misc arrays */
_mesa_vector4f_free( &store->ndcCoords );
ALIGN_FREE( store->clipmask );
 
FREE( store );
stage->privatePtr = 0;
}
}
 
/**
* Public description of this pipeline stage.
*/
const struct gl_pipeline_stage _tnl_vertex_program_stage =
{
"vertex-program",
_NEW_ALL, /*XXX FIX */ /* recheck */
_NEW_ALL, /*XXX FIX */ /* recalc -- modelview dependency
* otherwise not captured by inputs
* (which may be VERT_BIT_POS) */
GL_FALSE, /* active */
/*0*/ VERT_BIT_POS, /* inputs XXX OK? */
VERT_BIT_CLIP | VERT_BIT_COLOR0, /* outputs XXX OK? */
0, /* changed_inputs */
NULL, /* private_data */
dtr, /* destroy */
check_vp, /* check */
run_init_vp /* run -- initially set to ctr */
};
/shark/trunk/ports/mesa/src/tnl/t_vb_normals.c
0,0 → 1,199
/* $Id: t_vb_normals.c,v 1.1 2003-02-28 11:48:07 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 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.
*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
 
#include "glheader.h"
#include "colormac.h"
#include "context.h"
#include "macros.h"
#include "imports.h"
#include "mmath.h"
#include "mtypes.h"
 
#include "math/m_xform.h"
 
#include "t_context.h"
#include "t_pipeline.h"
 
 
 
struct normal_stage_data {
normal_func NormalTransform;
GLvector4f normal;
};
 
#define NORMAL_STAGE_DATA(stage) ((struct normal_stage_data *)stage->privatePtr)
 
 
 
 
static GLboolean run_normal_stage( GLcontext *ctx,
struct gl_pipeline_stage *stage )
{
struct normal_stage_data *store = NORMAL_STAGE_DATA(stage);
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
 
ASSERT(store->NormalTransform);
 
if (stage->changed_inputs) {
/* We can only use the display list's saved normal lengths if we've
* got a transformation matrix with uniform scaling.
*/
const GLfloat *lengths;
if (ctx->ModelviewMatrixStack.Top->flags & MAT_FLAG_GENERAL_SCALE)
lengths = NULL;
else
lengths = VB->NormalLengthPtr;
 
store->NormalTransform( ctx->ModelviewMatrixStack.Top,
ctx->_ModelViewInvScale,
VB->NormalPtr, /* input normals */
lengths,
&store->normal ); /* resulting normals */
}
 
VB->NormalPtr = &store->normal;
VB->NormalLengthPtr = 0; /* no longer valid */
return GL_TRUE;
}
 
 
static GLboolean run_validate_normal_stage( GLcontext *ctx,
struct gl_pipeline_stage *stage )
{
struct normal_stage_data *store = NORMAL_STAGE_DATA(stage);
 
ASSERT(ctx->_NeedNormals);
 
if (ctx->_NeedEyeCoords) {
GLuint transform = NORM_TRANSFORM_NO_ROT;
 
if (ctx->ModelviewMatrixStack.Top->flags & (MAT_FLAG_GENERAL |
MAT_FLAG_ROTATION |
MAT_FLAG_GENERAL_3D |
MAT_FLAG_PERSPECTIVE))
transform = NORM_TRANSFORM;
 
 
if (ctx->Transform.Normalize) {
store->NormalTransform = _mesa_normal_tab[transform | NORM_NORMALIZE];
}
else if (ctx->Transform.RescaleNormals &&
ctx->_ModelViewInvScale != 1.0) {
store->NormalTransform = _mesa_normal_tab[transform | NORM_RESCALE];
}
else {
store->NormalTransform = _mesa_normal_tab[transform];
}
}
else {
if (ctx->Transform.Normalize) {
store->NormalTransform = _mesa_normal_tab[NORM_NORMALIZE];
}
else if (!ctx->Transform.RescaleNormals &&
ctx->_ModelViewInvScale != 1.0) {
store->NormalTransform = _mesa_normal_tab[NORM_RESCALE];
}
else {
store->NormalTransform = 0;
}
}
 
if (store->NormalTransform) {
stage->run = run_normal_stage;
return stage->run( ctx, stage );
} else {
stage->active = GL_FALSE; /* !!! */
return GL_TRUE;
}
}
 
 
static void check_normal_transform( GLcontext *ctx,
struct gl_pipeline_stage *stage )
{
stage->active = ctx->_NeedNormals && !ctx->VertexProgram.Enabled;
/* Don't clobber the initialize function:
*/
if (stage->privatePtr)
stage->run = run_validate_normal_stage;
}
 
 
static GLboolean alloc_normal_data( GLcontext *ctx,
struct gl_pipeline_stage *stage )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct normal_stage_data *store;
stage->privatePtr = MALLOC(sizeof(*store));
store = NORMAL_STAGE_DATA(stage);
if (!store)
return GL_FALSE;
 
_mesa_vector4f_alloc( &store->normal, 0, tnl->vb.Size, 32 );
 
/* Now run the stage.
*/
stage->run = run_validate_normal_stage;
return stage->run( ctx, stage );
}
 
 
 
static void free_normal_data( struct gl_pipeline_stage *stage )
{
struct normal_stage_data *store = NORMAL_STAGE_DATA(stage);
if (store) {
_mesa_vector4f_free( &store->normal );
FREE( store );
stage->privatePtr = NULL;
}
}
 
#define _TNL_NEW_NORMAL_TRANSFORM (_NEW_MODELVIEW| \
_NEW_TRANSFORM| \
_MESA_NEW_NEED_NORMALS| \
_MESA_NEW_NEED_EYE_COORDS)
 
 
 
const struct gl_pipeline_stage _tnl_normal_transform_stage =
{
"normal transform", /* name */
_TNL_NEW_NORMAL_TRANSFORM, /* re-check */
_TNL_NEW_NORMAL_TRANSFORM, /* re-run */
GL_FALSE, /* active? */
VERT_BIT_NORMAL, /* inputs */
VERT_BIT_NORMAL, /* outputs */
0, /* changed_inputs */
NULL, /* private data */
free_normal_data, /* destructor */
check_normal_transform, /* check */
alloc_normal_data /* run -- initially set to alloc */
};
/shark/trunk/ports/mesa/src/tnl/t_vb_points.c
0,0 → 1,124
/* $Id: t_vb_points.c,v 1.1 2003-02-28 11:48:07 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 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.
*
* Authors:
* Brian Paul
*/
 
#include "mtypes.h"
#include "imports.h"
#include "t_context.h"
#include "t_pipeline.h"
 
 
struct point_stage_data {
GLvector4f PointSize;
};
 
#define POINT_STAGE_DATA(stage) ((struct point_stage_data *)stage->privatePtr)
 
 
/*
* Compute attenuated point sizes
*/
static GLboolean run_point_stage( GLcontext *ctx,
struct gl_pipeline_stage *stage )
{
struct point_stage_data *store = POINT_STAGE_DATA(stage);
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
const GLfloat (*eye)[4] = (const GLfloat (*)[4]) VB->EyePtr->data;
const GLfloat p0 = ctx->Point.Params[0];
const GLfloat p1 = ctx->Point.Params[1];
const GLfloat p2 = ctx->Point.Params[2];
const GLfloat pointSize = ctx->Point._Size;
GLfloat (*size)[4] = store->PointSize.data;
GLuint i;
 
if (stage->changed_inputs) {
/* XXX do threshold and min/max clamping here? */
for (i = 0; i < VB->Count; i++) {
const GLfloat dist = -eye[i][2];
/* GLfloat dist = GL_SQRT(pos[0]*pos[0]+pos[1]*pos[1]+pos[2]*pos[2]);*/
size[i][0] = pointSize / (p0 + dist * (p1 + dist * p2));
}
}
 
VB->PointSizePtr = &store->PointSize;
 
return GL_TRUE;
}
 
 
/* If point size attenuation is on we'll compute the point size for
* each vertex in a special pipeline stage.
*/
static void check_point_size( GLcontext *ctx, struct gl_pipeline_stage *d )
{
d->active = ctx->Point._Attenuated && !ctx->VertexProgram.Enabled;
}
 
static GLboolean alloc_point_data( GLcontext *ctx,
struct gl_pipeline_stage *stage )
{
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
struct point_stage_data *store;
stage->privatePtr = MALLOC(sizeof(*store));
store = POINT_STAGE_DATA(stage);
if (!store)
return GL_FALSE;
 
_mesa_vector4f_alloc( &store->PointSize, 0, VB->Size, 32 );
 
/* Now run the stage.
*/
stage->run = run_point_stage;
return stage->run( ctx, stage );
}
 
 
static void free_point_data( struct gl_pipeline_stage *stage )
{
struct point_stage_data *store = POINT_STAGE_DATA(stage);
if (store) {
_mesa_vector4f_free( &store->PointSize );
FREE( store );
stage->privatePtr = 0;
}
}
 
const struct gl_pipeline_stage _tnl_point_attenuation_stage =
{
"point size attenuation", /* name */
_NEW_POINT, /* build_state_change */
_NEW_POINT, /* run_state_change */
GL_FALSE, /* active */
VERT_BIT_EYE, /* inputs */
VERT_BIT_POINT_SIZE, /* outputs */
0, /* changed_inputs (temporary value) */
NULL, /* stage private data */
free_point_data, /* destructor */
check_point_size, /* check */
alloc_point_data /* run -- initially set to alloc data */
};
/shark/trunk/ports/mesa/src/tnl/t_vb_vertex.c
0,0 → 1,323
/* $Id: t_vb_vertex.c,v 1.1 2003-02-28 11:48:08 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 5.0
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
 
#include "glheader.h"
#include "colormac.h"
#include "context.h"
#include "macros.h"
#include "imports.h"
#include "mmath.h"
#include "mtypes.h"
 
#include "math/m_xform.h"
 
#include "t_context.h"
#include "t_pipeline.h"
 
 
 
struct vertex_stage_data {
GLvector4f eye;
GLvector4f clip;
GLvector4f proj;
GLubyte *clipmask;
GLubyte ormask;
GLubyte andmask;
 
 
/* Need these because it's difficult to replay the sideeffects
* analytically.
*/
GLvector4f *save_eyeptr;
GLvector4f *save_clipptr;
GLvector4f *save_ndcptr;
};
 
#define VERTEX_STAGE_DATA(stage) ((struct vertex_stage_data *)stage->privatePtr)
 
 
 
 
/* This function implements cliptesting for user-defined clip planes.
* The clipping of primitives to these planes is implemented in
* t_render_clip.h.
*/
#define USER_CLIPTEST(NAME, SZ) \
static void NAME( GLcontext *ctx, \
GLvector4f *clip, \
GLubyte *clipmask, \
GLubyte *clipormask, \
GLubyte *clipandmask ) \
{ \
GLuint p; \
\
for (p = 0; p < ctx->Const.MaxClipPlanes; p++) \
if (ctx->Transform.ClipPlanesEnabled & (1 << p)) { \
GLuint nr, i; \
const GLfloat a = ctx->Transform._ClipUserPlane[p][0]; \
const GLfloat b = ctx->Transform._ClipUserPlane[p][1]; \
const GLfloat c = ctx->Transform._ClipUserPlane[p][2]; \
const GLfloat d = ctx->Transform._ClipUserPlane[p][3]; \
GLfloat *coord = (GLfloat *)clip->data; \
GLuint stride = clip->stride; \
GLuint count = clip->count; \
\
for (nr = 0, i = 0 ; i < count ; i++) { \
GLfloat dp = coord[0] * a + coord[1] * b; \
if (SZ > 2) dp += coord[2] * c; \
if (SZ > 3) dp += coord[3] * d; else dp += d; \
\
if (dp < 0) { \
nr++; \
clipmask[i] |= CLIP_USER_BIT; \
} \
\
STRIDE_F(coord, stride); \
} \
\
if (nr > 0) { \
*clipormask |= CLIP_USER_BIT; \
if (nr == count) { \
*clipandmask |= CLIP_USER_BIT; \
return; \
} \
} \
} \
}
 
 
USER_CLIPTEST(userclip2, 2)
USER_CLIPTEST(userclip3, 3)
USER_CLIPTEST(userclip4, 4)
 
static void (*(usercliptab[5]))( GLcontext *,
GLvector4f *, GLubyte *,
GLubyte *, GLubyte * ) =
{
0,
0,
userclip2,
userclip3,
userclip4
};
 
 
 
static GLboolean run_vertex_stage( GLcontext *ctx,
struct gl_pipeline_stage *stage )
{
struct vertex_stage_data *store = (struct vertex_stage_data *)stage->privatePtr;
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
 
ASSERT(!ctx->VertexProgram.Enabled);
 
if (stage->changed_inputs) {
 
if (ctx->_NeedEyeCoords) {
/* Separate modelview transformation:
* Use combined ModelProject to avoid some depth artifacts
*/
if (ctx->ModelviewMatrixStack.Top->type == MATRIX_IDENTITY)
VB->EyePtr = VB->ObjPtr;
else
VB->EyePtr = TransformRaw( &store->eye,
ctx->ModelviewMatrixStack.Top,
VB->ObjPtr);
 
if (ctx->ProjectionMatrixStack.Top->type == MATRIX_IDENTITY)
VB->ClipPtr = VB->EyePtr;
else
VB->ClipPtr = TransformRaw( &store->clip,
&ctx->_ModelProjectMatrix,
VB->ObjPtr );
}
else {
/* Combined modelviewproject transform:
*/
if (ctx->_ModelProjectMatrix.type == MATRIX_IDENTITY)
VB->ClipPtr = VB->ObjPtr;
else
VB->ClipPtr = TransformRaw( &store->clip,
&ctx->_ModelProjectMatrix,
VB->ObjPtr );
}
 
/* Drivers expect this to be clean to element 4...
*/
if (VB->ClipPtr->size < 4) {
if (VB->ClipPtr->flags & VEC_NOT_WRITEABLE) {
ASSERT(VB->ClipPtr == VB->ObjPtr);
VB->import_data( ctx, VERT_BIT_POS, VEC_NOT_WRITEABLE );
VB->ClipPtr = VB->ObjPtr;
}
if (VB->ClipPtr->size == 2)
_mesa_vector4f_clean_elem( VB->ClipPtr, VB->Count, 2 );
_mesa_vector4f_clean_elem( VB->ClipPtr, VB->Count, 3 );
}
 
/* Cliptest and perspective divide. Clip functions must clear
* the clipmask.
*/
store->ormask = 0;
store->andmask = CLIP_ALL_BITS;
 
if (tnl->NeedNdcCoords) {
VB->NdcPtr =
_mesa_clip_tab[VB->ClipPtr->size]( VB->ClipPtr,
&store->proj,
store->clipmask,
&store->ormask,
&store->andmask );
}
else {
VB->NdcPtr = 0;
_mesa_clip_np_tab[VB->ClipPtr->size]( VB->ClipPtr,
0,
store->clipmask,
&store->ormask,
&store->andmask );
}
 
if (store->andmask)
return GL_FALSE;
 
 
/* Test userclip planes. This contributes to VB->ClipMask, so
* is essentially required to be in this stage.
*/
if (ctx->Transform.ClipPlanesEnabled) {
usercliptab[VB->ClipPtr->size]( ctx,
VB->ClipPtr,
store->clipmask,
&store->ormask,
&store->andmask );
 
if (store->andmask)
return GL_FALSE;
}
 
VB->ClipOrMask = store->ormask;
VB->ClipMask = store->clipmask;
 
if (VB->ClipPtr == VB->ObjPtr && (VB->importable_data & VERT_BIT_POS))
VB->importable_data |= VERT_BIT_CLIP;
 
store->save_eyeptr = VB->EyePtr;
store->save_clipptr = VB->ClipPtr;
store->save_ndcptr = VB->NdcPtr;
}
else {
/* Replay the sideeffects.
*/
VB->EyePtr = store->save_eyeptr;
VB->ClipPtr = store->save_clipptr;
VB->NdcPtr = store->save_ndcptr;
VB->ClipMask = store->clipmask;
VB->ClipOrMask = store->ormask;
if (VB->ClipPtr == VB->ObjPtr && (VB->importable_data & VERT_BIT_POS))
VB->importable_data |= VERT_BIT_CLIP;
if (store->andmask)
return GL_FALSE;
}
 
return GL_TRUE;
}
 
 
static void check_vertex( GLcontext *ctx, struct gl_pipeline_stage *stage )
{
stage->active = !ctx->VertexProgram.Enabled;
}
 
static GLboolean init_vertex_stage( GLcontext *ctx,
struct gl_pipeline_stage *stage )
{
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
struct vertex_stage_data *store;
GLuint size = VB->Size;
 
stage->privatePtr = CALLOC(sizeof(*store));
store = VERTEX_STAGE_DATA(stage);
if (!store)
return GL_FALSE;
 
_mesa_vector4f_alloc( &store->eye, 0, size, 32 );
_mesa_vector4f_alloc( &store->clip, 0, size, 32 );
_mesa_vector4f_alloc( &store->proj, 0, size, 32 );
 
store->clipmask = (GLubyte *) ALIGN_MALLOC(sizeof(GLubyte)*size, 32 );
 
if (!store->clipmask ||
!store->eye.data ||
!store->clip.data ||
!store->proj.data)
return GL_FALSE;
 
/* Now run the stage.
*/
stage->run = run_vertex_stage;
return stage->run( ctx, stage );
}
 
static void dtr( struct gl_pipeline_stage *stage )
{
struct vertex_stage_data *store = VERTEX_STAGE_DATA(stage);
 
if (store) {
_mesa_vector4f_free( &store->eye );
_mesa_vector4f_free( &store->clip );
_mesa_vector4f_free( &store->proj );
ALIGN_FREE( store->clipmask );
FREE(store);
stage->privatePtr = NULL;
stage->run = init_vertex_stage;
}
}
 
 
const struct gl_pipeline_stage _tnl_vertex_transform_stage =
{
"modelview/project/cliptest/divide",
_NEW_PROGRAM, /* check_state: only care about vertex prog */
_MESA_NEW_NEED_EYE_COORDS | /* run_state: when to invalidate / re-run */
_NEW_MODELVIEW|
_NEW_PROJECTION|
_NEW_PROGRAM|
_NEW_TRANSFORM,
GL_TRUE, /* active */
VERT_BIT_POS, /* inputs */
VERT_BIT_EYE|VERT_BIT_CLIP, /* outputs */
0, /* changed_inputs */
NULL, /* private data */
dtr, /* destructor */
check_vertex, /* check */
init_vertex_stage /* run -- initially set to init */
};
/shark/trunk/ports/mesa/src/tnl/t_pipeline.c
0,0 → 1,211
/* $Id: t_pipeline.c,v 1.1 2003-02-28 11:48:07 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
#include "glheader.h"
#include "context.h"
#include "imports.h"
#include "mmath.h"
#include "state.h"
#include "mtypes.h"
 
#include "math/m_translate.h"
#include "math/m_xform.h"
 
#include "t_context.h"
#include "t_pipeline.h"
 
 
void _tnl_install_pipeline( GLcontext *ctx,
const struct gl_pipeline_stage **stages )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct gl_pipeline *pipe = &tnl->pipeline;
GLuint i;
 
ASSERT(pipe->nr_stages == 0);
 
pipe->run_state_changes = ~0;
pipe->run_input_changes = ~0;
pipe->build_state_changes = ~0;
pipe->build_state_trigger = 0;
pipe->inputs = 0;
 
/* Create a writeable copy of each stage.
*/
for (i = 0 ; i < MAX_PIPELINE_STAGES && stages[i] ; i++) {
MEMCPY( &pipe->stages[i], stages[i], sizeof( **stages ));
pipe->build_state_trigger |= pipe->stages[i].check_state;
}
 
MEMSET( &pipe->stages[i], 0, sizeof( **stages ));
 
pipe->nr_stages = i;
}
 
void _tnl_destroy_pipeline( GLcontext *ctx )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
GLuint i;
 
for (i = 0 ; i < tnl->pipeline.nr_stages ; i++)
tnl->pipeline.stages[i].destroy( &tnl->pipeline.stages[i] );
 
tnl->pipeline.nr_stages = 0;
}
 
/* TODO: merge validate with run.
*/
void _tnl_validate_pipeline( GLcontext *ctx )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct gl_pipeline *pipe = &tnl->pipeline;
struct gl_pipeline_stage *s = pipe->stages;
GLuint newstate = pipe->build_state_changes;
GLuint generated = 0;
GLuint changed_inputs = 0;
 
pipe->inputs = 0;
pipe->build_state_changes = 0;
 
for ( ; s->check ; s++) {
 
s->changed_inputs |= s->inputs & changed_inputs;
 
if (s->check_state & newstate) {
if (s->active) {
GLuint old_outputs = s->outputs;
s->check(ctx, s);
if (!s->active)
changed_inputs |= old_outputs;
}
else
s->check(ctx, s);
}
 
if (s->active) {
pipe->inputs |= s->inputs & ~generated;
generated |= s->outputs;
}
}
}
 
 
 
void _tnl_run_pipeline( GLcontext *ctx )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
struct gl_pipeline *pipe = &tnl->pipeline;
struct gl_pipeline_stage *s = pipe->stages;
GLuint changed_state = pipe->run_state_changes;
GLuint changed_inputs = pipe->run_input_changes;
GLboolean running = GL_TRUE;
unsigned short __tmp;
 
pipe->run_state_changes = 0;
pipe->run_input_changes = 0;
 
/* Done elsewhere.
*/
ASSERT(pipe->build_state_changes == 0);
 
START_FAST_MATH(__tmp);
 
/* If something changes in the pipeline, tag all subsequent stages
* using this value for recalculation. Inactive stages have their
* state and inputs examined to try to keep cached data alive over
* state-changes.
*/
for ( ; s->run ; s++) {
s->changed_inputs |= s->inputs & changed_inputs;
 
if (s->run_state & changed_state)
s->changed_inputs = s->inputs;
 
if (s->active && running) {
if (s->changed_inputs)
changed_inputs |= s->outputs;
 
running = s->run( ctx, s );
 
s->changed_inputs = 0;
VB->importable_data &= ~s->outputs;
}
}
 
END_FAST_MATH(__tmp);
}
 
 
 
/* The default pipeline. This is useful for software rasterizers, and
* simple hardware rasterizers. For customization, I don't recommend
* tampering with the internals of these stages in the way that
* drivers did in Mesa 3.4. These stages are basically black boxes,
* and should be left intact.
*
* To customize the pipeline, consider:
*
* - removing redundant stages (making sure that the software rasterizer
* can cope with this on fallback paths). An example is fog
* coordinate generation, which is not required in the FX driver.
*
* - replacing general-purpose machine-independent stages with
* general-purpose machine-specific stages. There is no example of
* this to date, though it must be borne in mind that all subsequent
* stages that reference the output of the new stage must cope with
* any machine-specific data introduced. This may not be easy
* unless there are no such stages (ie the new stage is the last in
* the pipe).
*
* - inserting optimized (but specialized) stages ahead of the
* general-purpose fallback implementation. For example, the old
* fastpath mechanism, which only works when the VERT_BIT_ELT input is
* available, can be duplicated by placing the fastpath stage at the
* head of this pipeline. Such specialized stages are currently
* constrained to have no outputs (ie. they must either finish the *
* pipeline by returning GL_FALSE from run(), or do nothing).
*
* Some work can be done to lift some of the restrictions in the final
* case, if it becomes necessary to do so.
*/
const struct gl_pipeline_stage *_tnl_default_pipeline[] = {
&_tnl_vertex_transform_stage,
&_tnl_normal_transform_stage,
&_tnl_lighting_stage,
&_tnl_fog_coordinate_stage,
&_tnl_texgen_stage,
&_tnl_texture_transform_stage,
&_tnl_point_attenuation_stage,
#if FEATURE_NV_vertex_program
&_tnl_vertex_program_stage,
#endif
&_tnl_render_stage,
0
};
/shark/trunk/ports/mesa/src/tnl/t_array_api.c
0,0 → 1,402
/* $Id: t_array_api.c,v 1.1 2003-02-28 11:48:06 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
/**
* \file vpexec.c
* \brief Vertex array API functions (glDrawArrays, etc)
* \author Keith Whitwell
*/
 
#include "glheader.h"
#include "api_validate.h"
#include "context.h"
#include "imports.h"
#include "macros.h"
#include "mmath.h"
#include "mtypes.h"
#include "state.h"
 
#include "array_cache/acache.h"
 
#include "t_array_api.h"
#include "t_array_import.h"
#include "t_imm_api.h"
#include "t_imm_exec.h"
#include "t_context.h"
#include "t_pipeline.h"
 
static void fallback_drawarrays( GLcontext *ctx, GLenum mode, GLint start,
GLsizei count )
{
if (_tnl_hard_begin( ctx, mode )) {
GLint i;
for (i = start; i < count; i++)
glArrayElement( i );
glEnd();
}
}
 
 
static void fallback_drawelements( GLcontext *ctx, GLenum mode, GLsizei count,
const GLuint *indices)
{
if (_tnl_hard_begin(ctx, mode)) {
GLint i;
for (i = 0 ; i < count ; i++)
glArrayElement( indices[i] );
glEnd();
}
}
 
 
static void _tnl_draw_range_elements( GLcontext *ctx, GLenum mode,
GLuint start, GLuint end,
GLsizei count, const GLuint *indices )
 
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
FLUSH_CURRENT( ctx, 0 );
/* _mesa_debug(ctx, "%s\n", __FUNCTION__); */
if (tnl->pipeline.build_state_changes)
_tnl_validate_pipeline( ctx );
 
_tnl_vb_bind_arrays( ctx, start, end );
 
tnl->vb.FirstPrimitive = 0;
tnl->vb.Primitive[0] = mode | PRIM_BEGIN | PRIM_END | PRIM_LAST;
tnl->vb.PrimitiveLength[0] = count;
tnl->vb.Elts = (GLuint *)indices;
 
if (ctx->Array.LockCount)
tnl->Driver.RunPipeline( ctx );
else {
/* Note that arrays may have changed before/after execution.
*/
tnl->pipeline.run_input_changes |= ctx->Array._Enabled;
tnl->Driver.RunPipeline( ctx );
tnl->pipeline.run_input_changes |= ctx->Array._Enabled;
}
}
 
 
 
/**
* Called via the GL API dispatcher.
*/
void
_tnl_DrawArrays(GLenum mode, GLint start, GLsizei count)
{
GET_CURRENT_CONTEXT(ctx);
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
GLuint thresh = (ctx->Driver.NeedFlush & FLUSH_STORED_VERTICES) ? 30 : 10;
if (MESA_VERBOSE & VERBOSE_API)
_mesa_debug(NULL, "_tnl_DrawArrays %d %d\n", start, count);
/* Check arguments, etc.
*/
if (!_mesa_validate_DrawArrays( ctx, mode, start, count ))
return;
 
if (tnl->pipeline.build_state_changes)
_tnl_validate_pipeline( ctx );
 
if (ctx->CompileFlag) {
fallback_drawarrays( ctx, mode, start, start + count );
}
else if (!ctx->Array.LockCount && (GLuint) count < thresh) {
/* Small primitives: attempt to share a vb (at the expense of
* using the immediate interface).
*/
fallback_drawarrays( ctx, mode, start, start + count );
}
else if (ctx->Array.LockCount &&
count < (GLint) ctx->Const.MaxArrayLockSize) {
/* Locked primitives which can fit in a single vertex buffer:
*/
FLUSH_CURRENT( ctx, 0 );
 
if (start < (GLint) ctx->Array.LockFirst)
start = ctx->Array.LockFirst;
if (start + count > (GLint) ctx->Array.LockCount)
count = ctx->Array.LockCount - start;
/* Locked drawarrays. Reuse any previously transformed data.
*/
_tnl_vb_bind_arrays( ctx, ctx->Array.LockFirst, ctx->Array.LockCount );
VB->FirstPrimitive = start;
VB->Primitive[start] = mode | PRIM_BEGIN | PRIM_END | PRIM_LAST;
VB->PrimitiveLength[start] = count;
tnl->Driver.RunPipeline( ctx );
}
else {
int bufsz = 256; /* Use a small buffer for cache goodness */
int j, nr;
int minimum, modulo, skip;
 
/* Large primitives requiring decomposition to multiple vertex
* buffers:
*/
switch (mode) {
case GL_POINTS:
minimum = 0;
modulo = 1;
skip = 0;
case GL_LINES:
minimum = 1;
modulo = 2;
skip = 1;
case GL_LINE_STRIP:
minimum = 1;
modulo = 1;
skip = 0;
break;
case GL_TRIANGLES:
minimum = 2;
modulo = 3;
skip = 2;
break;
case GL_TRIANGLE_STRIP:
minimum = 2;
modulo = 1;
skip = 0;
break;
case GL_QUADS:
minimum = 3;
modulo = 4;
skip = 3;
break;
case GL_QUAD_STRIP:
minimum = 3;
modulo = 2;
skip = 0;
break;
case GL_LINE_LOOP:
case GL_TRIANGLE_FAN:
case GL_POLYGON:
default:
/* Primitives requiring a copied vertex (fan-like primitives)
* must use the slow path if they cannot fit in a single
* vertex buffer.
*/
if (count < (GLint) ctx->Const.MaxArrayLockSize) {
bufsz = ctx->Const.MaxArrayLockSize;
minimum = 0;
modulo = 1;
skip = 0;
}
else {
fallback_drawarrays( ctx, mode, start, start + count );
return;
}
}
 
FLUSH_CURRENT( ctx, 0 );
 
bufsz -= bufsz % modulo;
bufsz -= minimum;
count += start;
 
for (j = start + minimum ; j < count ; j += nr + skip ) {
 
nr = MIN2( bufsz, count - j );
 
_tnl_vb_bind_arrays( ctx, j - minimum, j + nr );
 
VB->FirstPrimitive = 0;
VB->Primitive[0] = mode | PRIM_BEGIN | PRIM_END | PRIM_LAST;
VB->PrimitiveLength[0] = nr + minimum;
tnl->pipeline.run_input_changes |= ctx->Array._Enabled;
tnl->Driver.RunPipeline( ctx );
tnl->pipeline.run_input_changes |= ctx->Array._Enabled;
}
}
}
 
 
/**
* Called via the GL API dispatcher.
*/
void
_tnl_DrawRangeElements(GLenum mode,
GLuint start, GLuint end,
GLsizei count, GLenum type, const GLvoid *indices)
{
GET_CURRENT_CONTEXT(ctx);
GLuint *ui_indices;
 
if (MESA_VERBOSE & VERBOSE_API)
_mesa_debug(NULL, "_tnl_DrawRangeElements %d %d %d\n", start, end, count);
 
/* Check arguments, etc.
*/
if (!_mesa_validate_DrawRangeElements( ctx, mode, start, end, count,
type, indices ))
return;
 
ui_indices = (GLuint *)_ac_import_elements( ctx, GL_UNSIGNED_INT,
count, type, indices );
 
 
if (ctx->CompileFlag) {
/* Can't do anything when compiling:
*/
fallback_drawelements( ctx, mode, count, ui_indices );
}
else if (ctx->Array.LockCount) {
/* Are the arrays already locked? If so we currently have to look
* at the whole locked range.
*/
if (start >= ctx->Array.LockFirst && end <= ctx->Array.LockCount)
_tnl_draw_range_elements( ctx, mode,
ctx->Array.LockFirst,
ctx->Array.LockCount,
count, ui_indices );
else {
/* The spec says referencing elements outside the locked
* range is undefined. I'm going to make it a noop this time
* round, maybe come up with something beter before 3.6.
*
* May be able to get away with just setting LockCount==0,
* though this raises the problems of dependent state. May
* have to call glUnlockArrays() directly?
*
* Or scan the list and replace bad indices?
*/
_mesa_problem( ctx,
"DrawRangeElements references "
"elements outside locked range.");
}
}
else if (end + 1 - start < ctx->Const.MaxArrayLockSize) {
/* The arrays aren't locked but we can still fit them inside a
* single vertexbuffer.
*/
_tnl_draw_range_elements( ctx, mode, start, end + 1, count, ui_indices );
} else {
/* Range is too big to optimize:
*/
fallback_drawelements( ctx, mode, count, ui_indices );
}
}
 
 
 
/**
* Called via the GL API dispatcher.
*/
void
_tnl_DrawElements(GLenum mode, GLsizei count, GLenum type,
const GLvoid *indices)
{
GET_CURRENT_CONTEXT(ctx);
GLuint *ui_indices;
 
if (MESA_VERBOSE & VERBOSE_API)
_mesa_debug(NULL, "_tnl_DrawElements %d\n", count);
 
/* Check arguments, etc.
*/
if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices ))
return;
 
ui_indices = (GLuint *)_ac_import_elements( ctx, GL_UNSIGNED_INT,
count, type, indices );
 
if (ctx->CompileFlag) {
/* Can't do anything when compiling:
*/
fallback_drawelements( ctx, mode, count, ui_indices );
}
else if (ctx->Array.LockCount) {
_tnl_draw_range_elements( ctx, mode,
ctx->Array.LockFirst,
ctx->Array.LockCount,
count, ui_indices );
}
else {
/* Scan the index list and see if we can use the locked path anyway.
*/
GLuint max_elt = 0;
GLint i;
 
for (i = 0 ; i < count ; i++)
if (ui_indices[i] > max_elt)
max_elt = ui_indices[i];
 
if (max_elt < ctx->Const.MaxArrayLockSize && /* can we use it? */
max_elt < (GLuint) count) /* do we want to use it? */
_tnl_draw_range_elements( ctx, mode, 0, max_elt+1, count, ui_indices );
else
fallback_drawelements( ctx, mode, count, ui_indices );
}
}
 
 
/**
* Initialize context's vertex array fields. Called during T 'n L context
* creation.
*/
void _tnl_array_init( GLcontext *ctx )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_arrays *tmp = &tnl->array_inputs;
GLvertexformat *vfmt = &(TNL_CONTEXT(ctx)->vtxfmt);
GLuint i;
 
vfmt->DrawArrays = _tnl_DrawArrays;
vfmt->DrawElements = _tnl_DrawElements;
vfmt->DrawRangeElements = _tnl_DrawRangeElements;
 
/* Setup vector pointers that will be used to bind arrays to VB's.
*/
_mesa_vector4f_init( &tmp->Obj, 0, 0 );
_mesa_vector4f_init( &tmp->Normal, 0, 0 );
_mesa_vector4f_init( &tmp->FogCoord, 0, 0 );
_mesa_vector1ui_init( &tmp->Index, 0, 0 );
_mesa_vector1ub_init( &tmp->EdgeFlag, 0, 0 );
 
for (i = 0; i < ctx->Const.MaxTextureUnits; i++)
_mesa_vector4f_init( &tmp->TexCoord[i], 0, 0);
 
tnl->tmp_primitive = (GLuint *)MALLOC(sizeof(GLuint)*tnl->vb.Size);
tnl->tmp_primitive_length = (GLuint *)MALLOC(sizeof(GLuint)*tnl->vb.Size);
}
 
 
/**
* Destroy the context's vertex array stuff.
* Called during T 'n L context destruction.
*/
void _tnl_array_destroy( GLcontext *ctx )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
if (tnl->tmp_primitive_length) FREE(tnl->tmp_primitive_length);
if (tnl->tmp_primitive) FREE(tnl->tmp_primitive);
}
/shark/trunk/ports/mesa/src/tnl/t_pipeline.h
0,0 → 1,76
/* $Id: t_pipeline.h,v 1.1 2003-02-28 11:48:07 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
 
 
#ifndef _T_PIPELINE_H_
#define _T_PIPELINE_H_
 
#include "mtypes.h"
#include "t_context.h"
 
extern void _tnl_run_pipeline( GLcontext *ctx );
 
extern void _tnl_validate_pipeline( GLcontext *ctx );
 
extern void _tnl_destroy_pipeline( GLcontext *ctx );
 
extern void _tnl_install_pipeline( GLcontext *ctx,
const struct gl_pipeline_stage **stages );
 
 
/* These are implemented in the t_vb_*.c files:
*/
extern const struct gl_pipeline_stage _tnl_vertex_transform_stage;
extern const struct gl_pipeline_stage _tnl_normal_transform_stage;
extern const struct gl_pipeline_stage _tnl_lighting_stage;
extern const struct gl_pipeline_stage _tnl_fog_coordinate_stage;
extern const struct gl_pipeline_stage _tnl_texgen_stage;
extern const struct gl_pipeline_stage _tnl_texture_transform_stage;
extern const struct gl_pipeline_stage _tnl_point_attenuation_stage;
extern const struct gl_pipeline_stage _tnl_vertex_program_stage;
extern const struct gl_pipeline_stage _tnl_render_stage;
 
/* Shorthand to plug in the default pipeline:
*/
extern const struct gl_pipeline_stage *_tnl_default_pipeline[];
 
 
/* Convenience routines provided by t_vb_render.c:
*/
extern render_func _tnl_render_tab_elts[];
extern render_func _tnl_render_tab_verts[];
 
extern void _tnl_RenderClippedPolygon( GLcontext *ctx,
const GLuint *elts, GLuint n );
 
extern void _tnl_RenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj );
 
 
#endif
/shark/trunk/ports/mesa/src/makefile
0,0 → 1,59
# The Frame Buffer Device
 
ifndef BASE
BASE=../../..
endif
 
include $(BASE)/config/config.mk
 
LIBRARY = osmesa
 
# C_OPT += -DUSE_MMX_ASM
# ASM_OPT += -DUSE_MMX_ASM
 
OBJS_PATH = $(BASE)/drivers/mesa/src/
 
OSMESA = accum.o api_arrayelt.o api_eval.o api_loopback.o api_noop.o api_validate.o\
attrib.o blend.o buffers.o clip.o colortab.o context.o convolve.o\
debug.o depth.o dispatch.o dlist.o drawpix.o enable.o enums.o eval.o\
extensions.o feedback.o fog.o get.o glapi.o glthread.o hash.o hint.o\
histogram.o image.o imports.o light.o lines.o matrix.o mmath.o pixel.o\
points.o polygon.o rastpos.o state.o stencil.o texcompress.o texformat.o\
teximage.o texobj.o texstate.o texstore.o texutil.o varray.o vpexec.o\
vpparse.o vpstate.o vtxfmt.o ./osmesa/osmesa.o ./array_cache/ac_context.o\
./array_cache/ac_import.o ./swrast/s_aaline.o ./swrast/s_aatriangle.o\
./swrast/s_accum.o ./swrast/s_alphabuf.o ./swrast/s_alpha.o ./swrast/s_bitmap.o\
./swrast/s_blend.o ./swrast/s_buffers.o ./swrast/s_context.o ./swrast/s_copypix.o\
./swrast/s_depth.o ./swrast/s_drawpix.o ./swrast/s_feedback.o ./swrast/s_fog.o\
./swrast/s_histogram.o ./swrast/s_imaging.o ./swrast/s_lines.o ./swrast/s_logic.o\
./swrast/s_masking.o ./swrast/s_pixeltex.o ./swrast/s_points.o ./swrast/s_readpix.o\
./swrast/s_span.o ./swrast/s_stencil.o ./swrast/s_texstore.o ./swrast/s_texture.o\
./swrast/s_triangle.o ./swrast/s_zoom.o ./swrast_setup/ss_context.o\
./swrast_setup/ss_triangle.o ./swrast_setup/ss_vb.o ./tnl/t_array_api.o\
./tnl/t_array_import.o ./tnl/t_context.o ./tnl/t_eval_api.o ./tnl/t_imm_alloc.o\
./tnl/t_imm_api.o ./tnl/t_imm_debug.o ./tnl/t_imm_dlist.o ./tnl/t_imm_elt.o\
./tnl/t_imm_eval.o ./tnl/t_imm_exec.o ./tnl/t_imm_fixup.o ./tnl/t_pipeline.o\
./tnl/t_vb_fog.o ./tnl/t_vb_light.o\
./tnl/t_vb_normals.o ./tnl/t_vb_points.o ./tnl/t_vb_program.o ./tnl/t_vb_render.o\
./tnl/t_vb_texgen.o ./tnl/t_vb_texmat.o ./tnl/t_vb_vertex.o\
./math/m_debug_clip.o ./math/m_debug_norm.o\
./math/m_debug_xform.o ./math/m_eval.o ./math/m_matrix.o ./math/m_translate.o\
./math/m_vector.o ./math/m_xform.o\
./X86/common_x86_asm.o ./X86/common_x86.o ./X86/gen_matypes.o ./X86/glapi_x86.o\
./X86/mmx_blend.o ./X86/x86.o ./X86/x86_cliptest.o ./X86/x86_xform2.o\
./X86/x86_xform3.o ./X86/x86_xform4.o
OBJS = $(OSMESA)
 
C_OPT += -I../../../drivers/linuxc24/include -I../include -I. -I.. -D__KERNEL__ -D__i368__ \
-ffast-math -fexpensive-optimizations -fstrict-aliasing -fPIC\
-malign-loops=2 -malign-jumps=2 -malign-functions=2 -D_REENTRANT\
-DUSE_X86_ASM -DUSE_MMX_ASM
 
ASM_OPT += -I../../../drivers/linuxc24/include -I../include -I. -I.. -D__KERNEL__ -D__i368__ \
-ffast-math -fexpensive-optimizations -fstrict-aliasing -fPIC -O\
-malign-loops=2 -malign-jumps=2 -malign-functions=2 -D_REENTRANT\
-DUSE_X86_ASM -DUSE_MMX_ASM
 
include $(BASE)/config/lib.mk
 
/shark/trunk/ports/mesa/src/math/mathmod.h
0,0 → 1,32
/* $Id: mathmod.h,v 1.1 2003-02-28 11:48:06 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
#ifndef _MESA_MATH_H_
#define _MESA_MATH_H_
 
extern void _math_init( void );
 
#endif
/shark/trunk/ports/mesa/src/math/m_eval.c
0,0 → 1,462
/* $Id: m_eval.c,v 1.1 2003-02-28 11:48:05 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
 
/*
* eval.c was written by
* Bernd Barsuhn (bdbarsuh@cip.informatik.uni-erlangen.de) and
* Volker Weiss (vrweiss@cip.informatik.uni-erlangen.de).
*
* My original implementation of evaluators was simplistic and didn't
* compute surface normal vectors properly. Bernd and Volker applied
* used more sophisticated methods to get better results.
*
* Thanks guys!
*/
 
 
#include "glheader.h"
#include "config.h"
#include "m_eval.h"
 
static GLfloat inv_tab[MAX_EVAL_ORDER];
 
 
 
/*
* Horner scheme for Bezier curves
*
* Bezier curves can be computed via a Horner scheme.
* Horner is numerically less stable than the de Casteljau
* algorithm, but it is faster. For curves of degree n
* the complexity of Horner is O(n) and de Casteljau is O(n^2).
* Since stability is not important for displaying curve
* points I decided to use the Horner scheme.
*
* A cubic Bezier curve with control points b0, b1, b2, b3 can be
* written as
*
* (([3] [3] ) [3] ) [3]
* c(t) = (([0]*s*b0 + [1]*t*b1)*s + [2]*t^2*b2)*s + [3]*t^2*b3
*
* [n]
* where s=1-t and the binomial coefficients [i]. These can
* be computed iteratively using the identity:
*
* [n] [n ] [n]
* [i] = (n-i+1)/i * [i-1] and [0] = 1
*/
 
 
void
_math_horner_bezier_curve(const GLfloat * cp, GLfloat * out, GLfloat t,
GLuint dim, GLuint order)
{
GLfloat s, powert, bincoeff;
GLuint i, k;
 
if (order >= 2) {
bincoeff = (GLfloat) (order - 1);
s = 1.0F - t;
 
for (k = 0; k < dim; k++)
out[k] = s * cp[k] + bincoeff * t * cp[dim + k];
 
for (i = 2, cp += 2 * dim, powert = t * t; i < order;
i++, powert *= t, cp += dim) {
bincoeff *= (GLfloat) (order - i);
bincoeff *= inv_tab[i];
 
for (k = 0; k < dim; k++)
out[k] = s * out[k] + bincoeff * powert * cp[k];
}
}
else { /* order=1 -> constant curve */
 
for (k = 0; k < dim; k++)
out[k] = cp[k];
}
}
 
/*
* Tensor product Bezier surfaces
*
* Again the Horner scheme is used to compute a point on a
* TP Bezier surface. First a control polygon for a curve
* on the surface in one parameter direction is computed,
* then the point on the curve for the other parameter
* direction is evaluated.
*
* To store the curve control polygon additional storage
* for max(uorder,vorder) points is needed in the
* control net cn.
*/
 
void
_math_horner_bezier_surf(GLfloat * cn, GLfloat * out, GLfloat u, GLfloat v,
GLuint dim, GLuint uorder, GLuint vorder)
{
GLfloat *cp = cn + uorder * vorder * dim;
GLuint i, uinc = vorder * dim;
 
if (vorder > uorder) {
if (uorder >= 2) {
GLfloat s, poweru, bincoeff;
GLuint j, k;
 
/* Compute the control polygon for the surface-curve in u-direction */
for (j = 0; j < vorder; j++) {
GLfloat *ucp = &cn[j * dim];
 
/* Each control point is the point for parameter u on a */
/* curve defined by the control polygons in u-direction */
bincoeff = (GLfloat) (uorder - 1);
s = 1.0F - u;
 
for (k = 0; k < dim; k++)
cp[j * dim + k] = s * ucp[k] + bincoeff * u * ucp[uinc + k];
 
for (i = 2, ucp += 2 * uinc, poweru = u * u; i < uorder;
i++, poweru *= u, ucp += uinc) {
bincoeff *= (GLfloat) (uorder - i);
bincoeff *= inv_tab[i];
 
for (k = 0; k < dim; k++)
cp[j * dim + k] =
s * cp[j * dim + k] + bincoeff * poweru * ucp[k];
}
}
 
/* Evaluate curve point in v */
_math_horner_bezier_curve(cp, out, v, dim, vorder);
}
else /* uorder=1 -> cn defines a curve in v */
_math_horner_bezier_curve(cn, out, v, dim, vorder);
}
else { /* vorder <= uorder */
 
if (vorder > 1) {
GLuint i;
 
/* Compute the control polygon for the surface-curve in u-direction */
for (i = 0; i < uorder; i++, cn += uinc) {
/* For constant i all cn[i][j] (j=0..vorder) are located */
/* on consecutive memory locations, so we can use */
/* horner_bezier_curve to compute the control points */
 
_math_horner_bezier_curve(cn, &cp[i * dim], v, dim, vorder);
}
 
/* Evaluate curve point in u */
_math_horner_bezier_curve(cp, out, u, dim, uorder);
}
else /* vorder=1 -> cn defines a curve in u */
_math_horner_bezier_curve(cn, out, u, dim, uorder);
}
}
 
/*
* The direct de Casteljau algorithm is used when a point on the
* surface and the tangent directions spanning the tangent plane
* should be computed (this is needed to compute normals to the
* surface). In this case the de Casteljau algorithm approach is
* nicer because a point and the partial derivatives can be computed
* at the same time. To get the correct tangent length du and dv
* must be multiplied with the (u2-u1)/uorder-1 and (v2-v1)/vorder-1.
* Since only the directions are needed, this scaling step is omitted.
*
* De Casteljau needs additional storage for uorder*vorder
* values in the control net cn.
*/
 
void
_math_de_casteljau_surf(GLfloat * cn, GLfloat * out, GLfloat * du,
GLfloat * dv, GLfloat u, GLfloat v, GLuint dim,
GLuint uorder, GLuint vorder)
{
GLfloat *dcn = cn + uorder * vorder * dim;
GLfloat us = 1.0F - u, vs = 1.0F - v;
GLuint h, i, j, k;
GLuint minorder = uorder < vorder ? uorder : vorder;
GLuint uinc = vorder * dim;
GLuint dcuinc = vorder;
 
/* Each component is evaluated separately to save buffer space */
/* This does not drasticaly decrease the performance of the */
/* algorithm. If additional storage for (uorder-1)*(vorder-1) */
/* points would be available, the components could be accessed */
/* in the innermost loop which could lead to less cache misses. */
 
#define CN(I,J,K) cn[(I)*uinc+(J)*dim+(K)]
#define DCN(I, J) dcn[(I)*dcuinc+(J)]
if (minorder < 3) {
if (uorder == vorder) {
for (k = 0; k < dim; k++) {
/* Derivative direction in u */
du[k] = vs * (CN(1, 0, k) - CN(0, 0, k)) +
v * (CN(1, 1, k) - CN(0, 1, k));
 
/* Derivative direction in v */
dv[k] = us * (CN(0, 1, k) - CN(0, 0, k)) +
u * (CN(1, 1, k) - CN(1, 0, k));
 
/* bilinear de Casteljau step */
out[k] = us * (vs * CN(0, 0, k) + v * CN(0, 1, k)) +
u * (vs * CN(1, 0, k) + v * CN(1, 1, k));
}
}
else if (minorder == uorder) {
for (k = 0; k < dim; k++) {
/* bilinear de Casteljau step */
DCN(1, 0) = CN(1, 0, k) - CN(0, 0, k);
DCN(0, 0) = us * CN(0, 0, k) + u * CN(1, 0, k);
 
for (j = 0; j < vorder - 1; j++) {
/* for the derivative in u */
DCN(1, j + 1) = CN(1, j + 1, k) - CN(0, j + 1, k);
DCN(1, j) = vs * DCN(1, j) + v * DCN(1, j + 1);
 
/* for the `point' */
DCN(0, j + 1) = us * CN(0, j + 1, k) + u * CN(1, j + 1, k);
DCN(0, j) = vs * DCN(0, j) + v * DCN(0, j + 1);
}
 
/* remaining linear de Casteljau steps until the second last step */
for (h = minorder; h < vorder - 1; h++)
for (j = 0; j < vorder - h; j++) {
/* for the derivative in u */
DCN(1, j) = vs * DCN(1, j) + v * DCN(1, j + 1);
 
/* for the `point' */
DCN(0, j) = vs * DCN(0, j) + v * DCN(0, j + 1);
}
 
/* derivative direction in v */
dv[k] = DCN(0, 1) - DCN(0, 0);
 
/* derivative direction in u */
du[k] = vs * DCN(1, 0) + v * DCN(1, 1);
 
/* last linear de Casteljau step */
out[k] = vs * DCN(0, 0) + v * DCN(0, 1);
}
}
else { /* minorder == vorder */
 
for (k = 0; k < dim; k++) {
/* bilinear de Casteljau step */
DCN(0, 1) = CN(0, 1, k) - CN(0, 0, k);
DCN(0, 0) = vs * CN(0, 0, k) + v * CN(0, 1, k);
for (i = 0; i < uorder - 1; i++) {
/* for the derivative in v */
DCN(i + 1, 1) = CN(i + 1, 1, k) - CN(i + 1, 0, k);
DCN(i, 1) = us * DCN(i, 1) + u * DCN(i + 1, 1);
 
/* for the `point' */
DCN(i + 1, 0) = vs * CN(i + 1, 0, k) + v * CN(i + 1, 1, k);
DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0);
}
 
/* remaining linear de Casteljau steps until the second last step */
for (h = minorder; h < uorder - 1; h++)
for (i = 0; i < uorder - h; i++) {
/* for the derivative in v */
DCN(i, 1) = us * DCN(i, 1) + u * DCN(i + 1, 1);
 
/* for the `point' */
DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0);
}
 
/* derivative direction in u */
du[k] = DCN(1, 0) - DCN(0, 0);
 
/* derivative direction in v */
dv[k] = us * DCN(0, 1) + u * DCN(1, 1);
 
/* last linear de Casteljau step */
out[k] = us * DCN(0, 0) + u * DCN(1, 0);
}
}
}
else if (uorder == vorder) {
for (k = 0; k < dim; k++) {
/* first bilinear de Casteljau step */
for (i = 0; i < uorder - 1; i++) {
DCN(i, 0) = us * CN(i, 0, k) + u * CN(i + 1, 0, k);
for (j = 0; j < vorder - 1; j++) {
DCN(i, j + 1) = us * CN(i, j + 1, k) + u * CN(i + 1, j + 1, k);
DCN(i, j) = vs * DCN(i, j) + v * DCN(i, j + 1);
}
}
 
/* remaining bilinear de Casteljau steps until the second last step */
for (h = 2; h < minorder - 1; h++)
for (i = 0; i < uorder - h; i++) {
DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0);
for (j = 0; j < vorder - h; j++) {
DCN(i, j + 1) = us * DCN(i, j + 1) + u * DCN(i + 1, j + 1);
DCN(i, j) = vs * DCN(i, j) + v * DCN(i, j + 1);
}
}
 
/* derivative direction in u */
du[k] = vs * (DCN(1, 0) - DCN(0, 0)) + v * (DCN(1, 1) - DCN(0, 1));
 
/* derivative direction in v */
dv[k] = us * (DCN(0, 1) - DCN(0, 0)) + u * (DCN(1, 1) - DCN(1, 0));
 
/* last bilinear de Casteljau step */
out[k] = us * (vs * DCN(0, 0) + v * DCN(0, 1)) +
u * (vs * DCN(1, 0) + v * DCN(1, 1));
}
}
else if (minorder == uorder) {
for (k = 0; k < dim; k++) {
/* first bilinear de Casteljau step */
for (i = 0; i < uorder - 1; i++) {
DCN(i, 0) = us * CN(i, 0, k) + u * CN(i + 1, 0, k);
for (j = 0; j < vorder - 1; j++) {
DCN(i, j + 1) = us * CN(i, j + 1, k) + u * CN(i + 1, j + 1, k);
DCN(i, j) = vs * DCN(i, j) + v * DCN(i, j + 1);
}
}
 
/* remaining bilinear de Casteljau steps until the second last step */
for (h = 2; h < minorder - 1; h++)
for (i = 0; i < uorder - h; i++) {
DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0);
for (j = 0; j < vorder - h; j++) {
DCN(i, j + 1) = us * DCN(i, j + 1) + u * DCN(i + 1, j + 1);
DCN(i, j) = vs * DCN(i, j) + v * DCN(i, j + 1);
}
}
 
/* last bilinear de Casteljau step */
DCN(2, 0) = DCN(1, 0) - DCN(0, 0);
DCN(0, 0) = us * DCN(0, 0) + u * DCN(1, 0);
for (j = 0; j < vorder - 1; j++) {
/* for the derivative in u */
DCN(2, j + 1) = DCN(1, j + 1) - DCN(0, j + 1);
DCN(2, j) = vs * DCN(2, j) + v * DCN(2, j + 1);
 
/* for the `point' */
DCN(0, j + 1) = us * DCN(0, j + 1) + u * DCN(1, j + 1);
DCN(0, j) = vs * DCN(0, j) + v * DCN(0, j + 1);
}
 
/* remaining linear de Casteljau steps until the second last step */
for (h = minorder; h < vorder - 1; h++)
for (j = 0; j < vorder - h; j++) {
/* for the derivative in u */
DCN(2, j) = vs * DCN(2, j) + v * DCN(2, j + 1);
 
/* for the `point' */
DCN(0, j) = vs * DCN(0, j) + v * DCN(0, j + 1);
}
 
/* derivative direction in v */
dv[k] = DCN(0, 1) - DCN(0, 0);
 
/* derivative direction in u */
du[k] = vs * DCN(2, 0) + v * DCN(2, 1);
 
/* last linear de Casteljau step */
out[k] = vs * DCN(0, 0) + v * DCN(0, 1);
}
}
else { /* minorder == vorder */
 
for (k = 0; k < dim; k++) {
/* first bilinear de Casteljau step */
for (i = 0; i < uorder - 1; i++) {
DCN(i, 0) = us * CN(i, 0, k) + u * CN(i + 1, 0, k);
for (j = 0; j < vorder - 1; j++) {
DCN(i, j + 1) = us * CN(i, j + 1, k) + u * CN(i + 1, j + 1, k);
DCN(i, j) = vs * DCN(i, j) + v * DCN(i, j + 1);
}
}
 
/* remaining bilinear de Casteljau steps until the second last step */
for (h = 2; h < minorder - 1; h++)
for (i = 0; i < uorder - h; i++) {
DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0);
for (j = 0; j < vorder - h; j++) {
DCN(i, j + 1) = us * DCN(i, j + 1) + u * DCN(i + 1, j + 1);
DCN(i, j) = vs * DCN(i, j) + v * DCN(i, j + 1);
}
}
 
/* last bilinear de Casteljau step */
DCN(0, 2) = DCN(0, 1) - DCN(0, 0);
DCN(0, 0) = vs * DCN(0, 0) + v * DCN(0, 1);
for (i = 0; i < uorder - 1; i++) {
/* for the derivative in v */
DCN(i + 1, 2) = DCN(i + 1, 1) - DCN(i + 1, 0);
DCN(i, 2) = us * DCN(i, 2) + u * DCN(i + 1, 2);
 
/* for the `point' */
DCN(i + 1, 0) = vs * DCN(i + 1, 0) + v * DCN(i + 1, 1);
DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0);
}
 
/* remaining linear de Casteljau steps until the second last step */
for (h = minorder; h < uorder - 1; h++)
for (i = 0; i < uorder - h; i++) {
/* for the derivative in v */
DCN(i, 2) = us * DCN(i, 2) + u * DCN(i + 1, 2);
 
/* for the `point' */
DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0);
}
 
/* derivative direction in u */
du[k] = DCN(1, 0) - DCN(0, 0);
 
/* derivative direction in v */
dv[k] = us * DCN(0, 2) + u * DCN(1, 2);
 
/* last linear de Casteljau step */
out[k] = us * DCN(0, 0) + u * DCN(1, 0);
}
}
#undef DCN
#undef CN
}
 
 
/*
* Do one-time initialization for evaluators.
*/
void
_math_init_eval(void)
{
GLuint i;
 
/* KW: precompute 1/x for useful x.
*/
for (i = 1; i < MAX_EVAL_ORDER; i++)
inv_tab[i] = 1.0F / i;
}
/shark/trunk/ports/mesa/src/math/m_debug_util.h
0,0 → 1,280
/* $Id: m_debug_util.h,v 1.1 2003-02-28 11:48:05 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Gareth Hughes
*/
 
#ifndef __M_DEBUG_UTIL_H__
#define __M_DEBUG_UTIL_H__
 
 
#ifdef DEBUG /* This code only used for debugging */
 
 
/* Comment this out to deactivate the cycle counter.
* NOTE: it works only on CPUs which know the 'rdtsc' command (586 or higher)
* (hope, you don't try to debug Mesa on a 386 ;)
*/
#if defined(__GNUC__) && \
((defined(__i386__) && defined(USE_X86_ASM)) || \
(defined(__sparc__) && defined(USE_SPARC_ASM)))
#define RUN_DEBUG_BENCHMARK
#endif
 
#define TEST_COUNT 128 /* size of the tested vector array */
 
#define REQUIRED_PRECISION 10 /* allow 4 bits to miss */
#define MAX_PRECISION 24 /* max. precision possible */
 
 
#ifdef RUN_DEBUG_BENCHMARK
/* Overhead of profiling counter in cycles. Automatically adjusted to
* your machine at run time - counter initialization should give very
* consistent results.
*/
extern long counter_overhead;
 
/* This is the value of the environment variable MESA_PROFILE, and is
* used to determine if we should benchmark the functions as well as
* verify their correctness.
*/
extern char *mesa_profile;
 
/* Modify the the number of tests if you like.
* We take the minimum of all results, because every error should be
* positive (time used by other processes, task switches etc).
* It is assumed that all calculations are done in the cache.
*/
 
#if defined(__i386__)
 
#if 1 /* PPro, PII, PIII version */
 
/* Profiling on the P6 architecture requires a little more work, due to
* the internal out-of-order execution. We must perform a serializing
* 'cpuid' instruction before and after the 'rdtsc' instructions to make
* sure no other uops are executed when we sample the timestamp counter.
*/
#define INIT_COUNTER() \
do { \
int cycle_i; \
counter_overhead = LONG_MAX; \
for ( cycle_i = 0 ; cycle_i < 8 ; cycle_i++ ) { \
long cycle_tmp1 = 0, cycle_tmp2 = 0; \
__asm__ __volatile__ ( "push %%ebx \n" \
"xor %%eax, %%eax \n" \
"cpuid \n" \
"rdtsc \n" \
"mov %%eax, %0 \n" \
"xor %%eax, %%eax \n" \
"cpuid \n" \
"pop %%ebx \n" \
"push %%ebx \n" \
"xor %%eax, %%eax \n" \
"cpuid \n" \
"rdtsc \n" \
"mov %%eax, %1 \n" \
"xor %%eax, %%eax \n" \
"cpuid \n" \
"pop %%ebx \n" \
: "=m" (cycle_tmp1), "=m" (cycle_tmp2) \
: : "eax", "ecx", "edx" ); \
if ( counter_overhead > (cycle_tmp2 - cycle_tmp1) ) { \
counter_overhead = cycle_tmp2 - cycle_tmp1; \
} \
} \
} while (0)
 
#define BEGIN_RACE(x) \
x = LONG_MAX; \
for ( cycle_i = 0 ; cycle_i < 10 ; cycle_i++ ) { \
long cycle_tmp1 = 0, cycle_tmp2 = 0; \
__asm__ __volatile__ ( "push %%ebx \n" \
"xor %%eax, %%eax \n" \
"cpuid \n" \
"rdtsc \n" \
"mov %%eax, %0 \n" \
"xor %%eax, %%eax \n" \
"cpuid \n" \
"pop %%ebx \n" \
: "=m" (cycle_tmp1) \
: : "eax", "ecx", "edx" );
 
#define END_RACE(x) \
__asm__ __volatile__ ( "push %%ebx \n" \
"xor %%eax, %%eax \n" \
"cpuid \n" \
"rdtsc \n" \
"mov %%eax, %0 \n" \
"xor %%eax, %%eax \n" \
"cpuid \n" \
"pop %%ebx \n" \
: "=m" (cycle_tmp2) \
: : "eax", "ecx", "edx" ); \
if ( x > (cycle_tmp2 - cycle_tmp1) ) { \
x = cycle_tmp2 - cycle_tmp1; \
} \
} \
x -= counter_overhead;
 
#else /* PPlain, PMMX version */
 
/* To ensure accurate results, we stall the pipelines with the
* non-pairable 'cdq' instruction. This ensures all the code being
* profiled is complete when the 'rdtsc' instruction executes.
*/
#define INIT_COUNTER(x) \
do { \
int cycle_i; \
x = LONG_MAX; \
for ( cycle_i = 0 ; cycle_i < 32 ; cycle_i++ ) { \
long cycle_tmp1, cycle_tmp2, dummy; \
__asm__ ( "mov %%eax, %0" : "=a" (cycle_tmp1) ); \
__asm__ ( "mov %%eax, %0" : "=a" (cycle_tmp2) ); \
__asm__ ( "cdq" ); \
__asm__ ( "cdq" ); \
__asm__ ( "rdtsc" : "=a" (cycle_tmp1), "=d" (dummy) ); \
__asm__ ( "cdq" ); \
__asm__ ( "cdq" ); \
__asm__ ( "rdtsc" : "=a" (cycle_tmp2), "=d" (dummy) ); \
if ( x > (cycle_tmp2 - cycle_tmp1) ) \
x = cycle_tmp2 - cycle_tmp1; \
} \
} while (0)
 
#define BEGIN_RACE(x) \
x = LONG_MAX; \
for ( cycle_i = 0 ; cycle_i < 16 ; cycle_i++ ) { \
long cycle_tmp1, cycle_tmp2, dummy; \
__asm__ ( "mov %%eax, %0" : "=a" (cycle_tmp1) ); \
__asm__ ( "mov %%eax, %0" : "=a" (cycle_tmp2) ); \
__asm__ ( "cdq" ); \
__asm__ ( "cdq" ); \
__asm__ ( "rdtsc" : "=a" (cycle_tmp1), "=d" (dummy) );
 
 
#define END_RACE(x) \
__asm__ ( "cdq" ); \
__asm__ ( "cdq" ); \
__asm__ ( "rdtsc" : "=a" (cycle_tmp2), "=d" (dummy) ); \
if ( x > (cycle_tmp2 - cycle_tmp1) ) \
x = cycle_tmp2 - cycle_tmp1; \
} \
x -= counter_overhead;
 
#endif
 
#elif defined(__sparc__)
 
#define INIT_COUNTER() \
do { counter_overhead = 5; } while(0)
 
#define BEGIN_RACE(x) \
x = LONG_MAX; \
for (cycle_i = 0; cycle_i <10; cycle_i++) { \
register long cycle_tmp1 asm("l0"); \
register long cycle_tmp2 asm("l1"); \
/* rd %tick, %l0 */ \
__asm__ __volatile__ (".word 0xa1410000" : "=r" (cycle_tmp1)); /* save timestamp */
 
#define END_RACE(x) \
/* rd %tick, %l1 */ \
__asm__ __volatile__ (".word 0xa3410000" : "=r" (cycle_tmp2)); \
if (x > (cycle_tmp2-cycle_tmp1)) x = cycle_tmp2 - cycle_tmp1; \
} \
x -= counter_overhead;
 
#else
#error Your processor is not supported for RUN_XFORM_BENCHMARK
#endif
 
#else
 
#define BEGIN_RACE(x)
#define END_RACE(x)
 
#endif
 
 
/* =============================================================
* Helper functions
*/
 
static GLfloat rnd( void )
{
GLfloat f = (GLfloat)rand() / (GLfloat)RAND_MAX;
GLfloat gran = (GLfloat)(1 << 13);
 
f = (GLfloat)(GLint)(f * gran) / gran;
 
return f * 2.0 - 1.0;
}
 
static int significand_match( GLfloat a, GLfloat b )
{
GLfloat d = a - b;
int a_ex, b_ex, d_ex;
 
if ( d == 0.0F ) {
return MAX_PRECISION; /* Exact match */
}
 
if ( a == 0.0F || b == 0.0F ) {
/* It would probably be better to check if the
* non-zero number is denormalized and return
* the index of the highest set bit here.
*/
return 0;
}
 
frexp( a, &a_ex );
frexp( b, &b_ex );
frexp( d, &d_ex );
 
if ( a_ex < b_ex ) {
return a_ex - d_ex;
} else {
return b_ex - d_ex;
}
}
 
enum { NIL = 0, ONE = 1, NEG = -1, VAR = 2 };
 
/* Ensure our arrays are correctly aligned.
*/
#if defined(__GNUC__)
# define ALIGN16 __attribute__ ((aligned (16)))
#elif defined(__MSC__)
# define ALIGN16 __declspec(align(16)) /* GH: Does this work? */
#else
# warning "ALIGN16 will not 16-byte align!\n"
# define ALIGN16
#endif
 
 
#endif /* DEBUG */
 
#endif /* __M_DEBUG_UTIL_H__ */
/shark/trunk/ports/mesa/src/math/m_debug.h
0,0 → 1,43
/* $Id: m_debug.h,v 1.1 2003-02-28 11:48:04 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Gareth Hughes
*/
 
#ifndef __M_DEBUG_H__
#define __M_DEBUG_H__
 
extern void _math_test_all_transform_functions( char *description );
extern void _math_test_all_normal_transform_functions( char *description );
extern void _math_test_all_cliptest_functions( char *description );
 
/* Deprecated?
*/
extern void _math_test_all_vertex_functions( char *description );
 
extern char *mesa_profile;
 
#endif
/shark/trunk/ports/mesa/src/math/m_xform.c
0,0 → 1,222
/* $Id: m_xform.c,v 1.1 2003-02-28 11:48:05 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
 
/*
* Matrix/vertex/vector transformation stuff
*
*
* NOTES:
* 1. 4x4 transformation matrices are stored in memory in column major order.
* 2. Points/vertices are to be thought of as column vectors.
* 3. Transformation of a point p by a matrix M is: p' = M * p
*/
 
#include "glheader.h"
#include "macros.h"
#include "mmath.h"
 
#include "m_eval.h"
#include "m_matrix.h"
#include "m_translate.h"
#include "m_xform.h"
#include "mathmod.h"
 
 
#ifdef DEBUG
#include "m_debug.h"
#endif
 
#ifdef USE_X86_ASM
#include "X86/common_x86_asm.h"
#endif
 
#ifdef USE_SPARC_ASM
#include "SPARC/sparc.h"
#endif
 
clip_func _mesa_clip_tab[5];
clip_func _mesa_clip_np_tab[5];
dotprod_func _mesa_dotprod_tab[5];
vec_copy_func _mesa_copy_tab[0x10];
normal_func _mesa_normal_tab[0xf];
transform_func *_mesa_transform_tab[5];
 
 
/* Raw data format used for:
* - Object-to-eye transform prior to culling, although this too
* could be culled under some circumstances.
* - Eye-to-clip transform (via the function above).
* - Cliptesting
* - And everything else too, if culling happens to be disabled.
*
* GH: It's used for everything now, as clipping/culling is done
* elsewhere (most often by the driver itself).
*/
#define TAG(x) x
#define TAG2(x,y) x##y
#define STRIDE_LOOP for ( i = 0 ; i < count ; i++, STRIDE_F(from, stride) )
#define LOOP for ( i = 0 ; i < n ; i++ )
#define ARGS
#include "m_xform_tmp.h"
#include "m_clip_tmp.h"
#include "m_norm_tmp.h"
#include "m_dotprod_tmp.h"
#include "m_copy_tmp.h"
#undef TAG
#undef TAG2
#undef LOOP
#undef ARGS
 
 
 
 
GLvector4f *_mesa_project_points( GLvector4f *proj_vec,
const GLvector4f *clip_vec )
{
const GLuint stride = clip_vec->stride;
const GLfloat *from = (GLfloat *)clip_vec->start;
const GLuint count = clip_vec->count;
GLfloat (*vProj)[4] = (GLfloat (*)[4])proj_vec->start;
GLuint i;
 
for (i = 0 ; i < count ; i++, STRIDE_F(from, stride))
{
GLfloat oow = 1.0F / from[3];
vProj[i][3] = oow;
vProj[i][0] = from[0] * oow;
vProj[i][1] = from[1] * oow;
vProj[i][2] = from[2] * oow;
}
 
proj_vec->flags |= VEC_SIZE_4;
proj_vec->size = 3;
proj_vec->count = clip_vec->count;
return proj_vec;
}
 
 
 
 
 
 
/*
* Transform a 4-element row vector (1x4 matrix) by a 4x4 matrix. This
* function is used for transforming clipping plane equations and spotlight
* directions.
* Mathematically, u = v * m.
* Input: v - input vector
* m - transformation matrix
* Output: u - transformed vector
*/
void _mesa_transform_vector( GLfloat u[4], const GLfloat v[4], const GLfloat m[16] )
{
GLfloat v0=v[0], v1=v[1], v2=v[2], v3=v[3];
#define M(row,col) m[row + col*4]
u[0] = v0 * M(0,0) + v1 * M(1,0) + v2 * M(2,0) + v3 * M(3,0);
u[1] = v0 * M(0,1) + v1 * M(1,1) + v2 * M(2,1) + v3 * M(3,1);
u[2] = v0 * M(0,2) + v1 * M(1,2) + v2 * M(2,2) + v3 * M(3,2);
u[3] = v0 * M(0,3) + v1 * M(1,3) + v2 * M(2,3) + v3 * M(3,3);
#undef M
}
 
 
/* Useful for one-off point transformations, as in clipping.
* Note that because the matrix isn't analysed we do too many
* multiplies, and that the result is always 4-clean.
*/
void _mesa_transform_point_sz( GLfloat Q[4], const GLfloat M[16],
const GLfloat P[4], GLuint sz )
{
if (Q == P)
return;
 
if (sz == 4)
{
Q[0] = M[0] * P[0] + M[4] * P[1] + M[8] * P[2] + M[12] * P[3];
Q[1] = M[1] * P[0] + M[5] * P[1] + M[9] * P[2] + M[13] * P[3];
Q[2] = M[2] * P[0] + M[6] * P[1] + M[10] * P[2] + M[14] * P[3];
Q[3] = M[3] * P[0] + M[7] * P[1] + M[11] * P[2] + M[15] * P[3];
}
else if (sz == 3)
{
Q[0] = M[0] * P[0] + M[4] * P[1] + M[8] * P[2] + M[12];
Q[1] = M[1] * P[0] + M[5] * P[1] + M[9] * P[2] + M[13];
Q[2] = M[2] * P[0] + M[6] * P[1] + M[10] * P[2] + M[14];
Q[3] = M[3] * P[0] + M[7] * P[1] + M[11] * P[2] + M[15];
}
else if (sz == 2)
{
Q[0] = M[0] * P[0] + M[4] * P[1] + M[12];
Q[1] = M[1] * P[0] + M[5] * P[1] + M[13];
Q[2] = M[2] * P[0] + M[6] * P[1] + M[14];
Q[3] = M[3] * P[0] + M[7] * P[1] + M[15];
}
else if (sz == 1)
{
Q[0] = M[0] * P[0] + M[12];
Q[1] = M[1] * P[0] + M[13];
Q[2] = M[2] * P[0] + M[14];
Q[3] = M[3] * P[0] + M[15];
}
}
 
 
/*
* This is called only once. It initializes several tables with pointers
* to optimized transformation functions. This is where we can test for
* AMD 3Dnow! capability, Intel Katmai, etc. and hook in the right code.
*/
void
_math_init_transformation( void )
{
init_c_transformations();
init_c_norm_transform();
init_c_cliptest();
init_copy0();
init_dotprod();
 
#ifdef DEBUG
_math_test_all_transform_functions( "default" );
_math_test_all_normal_transform_functions( "default" );
_math_test_all_cliptest_functions( "default" );
#endif
 
#ifdef USE_X86_ASM
_mesa_init_all_x86_transform_asm();
#endif
#ifdef USE_SPARC_ASM
_mesa_init_all_sparc_transform_asm();
#endif
}
 
void
_math_init( void )
{
_math_init_transformation();
_math_init_translate();
_math_init_eval();
}
/shark/trunk/ports/mesa/src/math/m_eval.h
0,0 → 1,104
/* $Id: m_eval.h,v 1.1 2003-02-28 11:48:05 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
#ifndef _M_EVAL_H
#define _M_EVAL_H
 
#include "glheader.h"
 
void _math_init_eval( void );
 
 
/*
* Horner scheme for Bezier curves
*
* Bezier curves can be computed via a Horner scheme.
* Horner is numerically less stable than the de Casteljau
* algorithm, but it is faster. For curves of degree n
* the complexity of Horner is O(n) and de Casteljau is O(n^2).
* Since stability is not important for displaying curve
* points I decided to use the Horner scheme.
*
* A cubic Bezier curve with control points b0, b1, b2, b3 can be
* written as
*
* (([3] [3] ) [3] ) [3]
* c(t) = (([0]*s*b0 + [1]*t*b1)*s + [2]*t^2*b2)*s + [3]*t^2*b3
*
* [n]
* where s=1-t and the binomial coefficients [i]. These can
* be computed iteratively using the identity:
*
* [n] [n ] [n]
* [i] = (n-i+1)/i * [i-1] and [0] = 1
*/
 
 
void
_math_horner_bezier_curve(const GLfloat *cp, GLfloat *out, GLfloat t,
GLuint dim, GLuint order);
 
 
/*
* Tensor product Bezier surfaces
*
* Again the Horner scheme is used to compute a point on a
* TP Bezier surface. First a control polygon for a curve
* on the surface in one parameter direction is computed,
* then the point on the curve for the other parameter
* direction is evaluated.
*
* To store the curve control polygon additional storage
* for max(uorder,vorder) points is needed in the
* control net cn.
*/
 
void
_math_horner_bezier_surf(GLfloat *cn, GLfloat *out, GLfloat u, GLfloat v,
GLuint dim, GLuint uorder, GLuint vorder);
 
 
/*
* The direct de Casteljau algorithm is used when a point on the
* surface and the tangent directions spanning the tangent plane
* should be computed (this is needed to compute normals to the
* surface). In this case the de Casteljau algorithm approach is
* nicer because a point and the partial derivatives can be computed
* at the same time. To get the correct tangent length du and dv
* must be multiplied with the (u2-u1)/uorder-1 and (v2-v1)/vorder-1.
* Since only the directions are needed, this scaling step is omitted.
*
* De Casteljau needs additional storage for uorder*vorder
* values in the control net cn.
*/
 
void
_math_de_casteljau_surf(GLfloat *cn, GLfloat *out, GLfloat *du, GLfloat *dv,
GLfloat u, GLfloat v, GLuint dim,
GLuint uorder, GLuint vorder);
 
 
#endif
/shark/trunk/ports/mesa/src/math/m_translate.c
0,0 → 1,662
/* $Id: m_translate.c,v 1.1 2003-02-28 11:48:05 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 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.
*/
 
/*
* New (3.1) transformation code written by Keith Whitwell.
*/
 
 
#include "glheader.h"
#include "mtypes.h" /* GLchan hack */
#include "colormac.h"
#include "mmath.h"
 
#include "m_translate.h"
 
 
 
typedef void (*trans_1f_func)(GLfloat *to,
CONST void *ptr,
GLuint stride,
GLuint start,
GLuint n );
 
typedef void (*trans_1ui_func)(GLuint *to,
CONST void *ptr,
GLuint stride,
GLuint start,
GLuint n );
 
typedef void (*trans_1ub_func)(GLubyte *to,
CONST void *ptr,
GLuint stride,
GLuint start,
GLuint n );
 
typedef void (*trans_4ub_func)(GLubyte (*to)[4],
CONST void *ptr,
GLuint stride,
GLuint start,
GLuint n );
 
typedef void (*trans_4us_func)(GLushort (*to)[4],
CONST void *ptr,
GLuint stride,
GLuint start,
GLuint n );
 
typedef void (*trans_4f_func)(GLfloat (*to)[4],
CONST void *ptr,
GLuint stride,
GLuint start,
GLuint n );
 
typedef void (*trans_3f_func)(GLfloat (*to)[3],
CONST void *ptr,
GLuint stride,
GLuint start,
GLuint n );
 
 
 
 
#define TYPE_IDX(t) ((t) & 0xf)
#define MAX_TYPES TYPE_IDX(GL_DOUBLE)+1 /* 0xa + 1 */
 
 
/* This macro is used on other systems, so undefine it for this module */
 
#undef CHECK
 
static trans_1f_func _math_trans_1f_tab[MAX_TYPES];
static trans_1ui_func _math_trans_1ui_tab[MAX_TYPES];
static trans_1ub_func _math_trans_1ub_tab[MAX_TYPES];
static trans_3f_func _math_trans_3f_tab[MAX_TYPES];
static trans_4ub_func _math_trans_4ub_tab[5][MAX_TYPES];
static trans_4us_func _math_trans_4us_tab[5][MAX_TYPES];
static trans_4f_func _math_trans_4f_tab[5][MAX_TYPES];
 
 
#define PTR_ELT(ptr, elt) (((SRC *)ptr)[elt])
 
 
#define TAB(x) _math_trans##x##_tab
#define ARGS GLuint start, GLuint n
#define SRC_START start
#define DST_START 0
#define STRIDE stride
#define NEXT_F f += stride
#define NEXT_F2
#define CHECK
 
 
 
 
/* GL_BYTE
*/
#define SRC GLbyte
#define SRC_IDX TYPE_IDX(GL_BYTE)
#define TRX_3F(f,n) BYTE_TO_FLOAT( PTR_ELT(f,n) )
#define TRX_4F(f,n) BYTE_TO_FLOAT( PTR_ELT(f,n) )
#define TRX_UB(ub, f,n) ub = BYTE_TO_UBYTE( PTR_ELT(f,n) )
#define TRX_US(ch, f,n) ch = BYTE_TO_USHORT( PTR_ELT(f,n) )
#define TRX_UI(f,n) (PTR_ELT(f,n) < 0 ? 0 : (GLuint) PTR_ELT(f,n))
 
 
#define SZ 4
#define INIT init_trans_4_GLbyte_raw
#define DEST_4F trans_4_GLbyte_4f_raw
#define DEST_4UB trans_4_GLbyte_4ub_raw
#define DEST_4US trans_4_GLbyte_4us_raw
#include "m_trans_tmp.h"
 
#define SZ 3
#define INIT init_trans_3_GLbyte_raw
#define DEST_4F trans_3_GLbyte_4f_raw
#define DEST_4UB trans_3_GLbyte_4ub_raw
#define DEST_4US trans_3_GLbyte_4us_raw
#define DEST_3F trans_3_GLbyte_3f_raw
#include "m_trans_tmp.h"
 
#define SZ 2
#define INIT init_trans_2_GLbyte_raw
#define DEST_4F trans_2_GLbyte_4f_raw
#include "m_trans_tmp.h"
 
#define SZ 1
#define INIT init_trans_1_GLbyte_raw
#define DEST_4F trans_1_GLbyte_4f_raw
#define DEST_1UB trans_1_GLbyte_1ub_raw
#define DEST_1UI trans_1_GLbyte_1ui_raw
#include "m_trans_tmp.h"
 
#undef SRC
#undef TRX_3F
#undef TRX_4F
#undef TRX_UB
#undef TRX_US
#undef TRX_UI
#undef SRC_IDX
 
 
/* GL_UNSIGNED_BYTE
*/
#define SRC GLubyte
#define SRC_IDX TYPE_IDX(GL_UNSIGNED_BYTE)
#define TRX_3F(f,n) UBYTE_TO_FLOAT(PTR_ELT(f,n))
#define TRX_4F(f,n) UBYTE_TO_FLOAT(PTR_ELT(f,n))
#define TRX_UB(ub, f,n) ub = PTR_ELT(f,n)
#define TRX_US(us, f,n) us = UBYTE_TO_USHORT(PTR_ELT(f,n))
#define TRX_UI(f,n) (GLuint)PTR_ELT(f,n)
 
/* 4ub->4ub handled in special case below.
*/
#define SZ 4
#define INIT init_trans_4_GLubyte_raw
#define DEST_4F trans_4_GLubyte_4f_raw
#define DEST_4US trans_4_GLubyte_4us_raw
#include "m_trans_tmp.h"
 
 
#define SZ 3
#define INIT init_trans_3_GLubyte_raw
#define DEST_4UB trans_3_GLubyte_4ub_raw
#define DEST_4US trans_3_GLubyte_4us_raw
#define DEST_3F trans_3_GLubyte_3f_raw
#define DEST_4F trans_3_GLubyte_4f_raw
#include "m_trans_tmp.h"
 
 
#define SZ 1
#define INIT init_trans_1_GLubyte_raw
#define DEST_1UI trans_1_GLubyte_1ui_raw
#define DEST_1UB trans_1_GLubyte_1ub_raw
#include "m_trans_tmp.h"
 
#undef SRC
#undef SRC_IDX
#undef TRX_3F
#undef TRX_4F
#undef TRX_UB
#undef TRX_US
#undef TRX_UI
 
 
/* GL_SHORT
*/
#define SRC GLshort
#define SRC_IDX TYPE_IDX(GL_SHORT)
#define TRX_3F(f,n) SHORT_TO_FLOAT( PTR_ELT(f,n) )
#define TRX_4F(f,n) (GLfloat)( PTR_ELT(f,n) )
#define TRX_UB(ub, f,n) ub = SHORT_TO_UBYTE(PTR_ELT(f,n))
#define TRX_US(us, f,n) us = SHORT_TO_USHORT(PTR_ELT(f,n))
#define TRX_UI(f,n) (PTR_ELT(f,n) < 0 ? 0 : (GLuint) PTR_ELT(f,n))
 
 
#define SZ 4
#define INIT init_trans_4_GLshort_raw
#define DEST_4F trans_4_GLshort_4f_raw
#define DEST_4UB trans_4_GLshort_4ub_raw
#define DEST_4US trans_4_GLshort_4us_raw
#include "m_trans_tmp.h"
 
#define SZ 3
#define INIT init_trans_3_GLshort_raw
#define DEST_4F trans_3_GLshort_4f_raw
#define DEST_4UB trans_3_GLshort_4ub_raw
#define DEST_4US trans_3_GLshort_4us_raw
#define DEST_3F trans_3_GLshort_3f_raw
#include "m_trans_tmp.h"
 
#define SZ 2
#define INIT init_trans_2_GLshort_raw
#define DEST_4F trans_2_GLshort_4f_raw
#include "m_trans_tmp.h"
 
#define SZ 1
#define INIT init_trans_1_GLshort_raw
#define DEST_4F trans_1_GLshort_4f_raw
#define DEST_1UB trans_1_GLshort_1ub_raw
#define DEST_1UI trans_1_GLshort_1ui_raw
#include "m_trans_tmp.h"
 
 
#undef SRC
#undef SRC_IDX
#undef TRX_3F
#undef TRX_4F
#undef TRX_UB
#undef TRX_US
#undef TRX_UI
 
 
/* GL_UNSIGNED_SHORT
*/
#define SRC GLushort
#define SRC_IDX TYPE_IDX(GL_UNSIGNED_SHORT)
#define TRX_3F(f,n) USHORT_TO_FLOAT( PTR_ELT(f,n) )
#define TRX_4F(f,n) (GLfloat)( PTR_ELT(f,n) )
#define TRX_UB(ub,f,n) ub = (GLubyte) (PTR_ELT(f,n) >> 8)
#define TRX_US(us,f,n) us = (GLushort) (PTR_ELT(f,n) >> 8)
#define TRX_UI(f,n) (GLuint) PTR_ELT(f,n)
 
 
#define SZ 4
#define INIT init_trans_4_GLushort_raw
#define DEST_4F trans_4_GLushort_4f_raw
#define DEST_4UB trans_4_GLushort_4ub_raw
#define DEST_4US trans_4_GLushort_4us_raw
#include "m_trans_tmp.h"
 
#define SZ 3
#define INIT init_trans_3_GLushort_raw
#define DEST_4F trans_3_GLushort_4f_raw
#define DEST_4UB trans_3_GLushort_4ub_raw
#define DEST_4US trans_3_GLushort_4us_raw
#define DEST_3F trans_3_GLushort_3f_raw
#include "m_trans_tmp.h"
 
#define SZ 2
#define INIT init_trans_2_GLushort_raw
#define DEST_4F trans_2_GLushort_4f_raw
#include "m_trans_tmp.h"
 
#define SZ 1
#define INIT init_trans_1_GLushort_raw
#define DEST_4F trans_1_GLushort_4f_raw
#define DEST_1UB trans_1_GLushort_1ub_raw
#define DEST_1UI trans_1_GLushort_1ui_raw
#include "m_trans_tmp.h"
 
#undef SRC
#undef SRC_IDX
#undef TRX_3F
#undef TRX_4F
#undef TRX_UB
#undef TRX_US
#undef TRX_UI
 
 
/* GL_INT
*/
#define SRC GLint
#define SRC_IDX TYPE_IDX(GL_INT)
#define TRX_3F(f,n) INT_TO_FLOAT( PTR_ELT(f,n) )
#define TRX_4F(f,n) (GLfloat)( PTR_ELT(f,n) )
#define TRX_UB(ub, f,n) ub = INT_TO_UBYTE(PTR_ELT(f,n))
#define TRX_US(us, f,n) us = INT_TO_USHORT(PTR_ELT(f,n))
#define TRX_UI(f,n) (PTR_ELT(f,n) < 0 ? 0 : (GLuint) PTR_ELT(f,n))
 
 
#define SZ 4
#define INIT init_trans_4_GLint_raw
#define DEST_4F trans_4_GLint_4f_raw
#define DEST_4UB trans_4_GLint_4ub_raw
#define DEST_4US trans_4_GLint_4us_raw
#include "m_trans_tmp.h"
 
#define SZ 3
#define INIT init_trans_3_GLint_raw
#define DEST_4F trans_3_GLint_4f_raw
#define DEST_4UB trans_3_GLint_4ub_raw
#define DEST_4US trans_3_GLint_4us_raw
#define DEST_3F trans_3_GLint_3f_raw
#include "m_trans_tmp.h"
 
#define SZ 2
#define INIT init_trans_2_GLint_raw
#define DEST_4F trans_2_GLint_4f_raw
#include "m_trans_tmp.h"
 
#define SZ 1
#define INIT init_trans_1_GLint_raw
#define DEST_4F trans_1_GLint_4f_raw
#define DEST_1UB trans_1_GLint_1ub_raw
#define DEST_1UI trans_1_GLint_1ui_raw
#include "m_trans_tmp.h"
 
 
#undef SRC
#undef SRC_IDX
#undef TRX_3F
#undef TRX_4F
#undef TRX_UB
#undef TRX_US
#undef TRX_UI
 
 
/* GL_UNSIGNED_INT
*/
#define SRC GLuint
#define SRC_IDX TYPE_IDX(GL_UNSIGNED_INT)
#define TRX_3F(f,n) INT_TO_FLOAT( PTR_ELT(f,n) )
#define TRX_4F(f,n) (GLfloat)( PTR_ELT(f,n) )
#define TRX_UB(ub, f,n) ub = (GLubyte) (PTR_ELT(f,n) >> 24)
#define TRX_US(us, f,n) us = (GLshort) (PTR_ELT(f,n) >> 16)
#define TRX_UI(f,n) PTR_ELT(f,n)
 
 
#define SZ 4
#define INIT init_trans_4_GLuint_raw
#define DEST_4F trans_4_GLuint_4f_raw
#define DEST_4UB trans_4_GLuint_4ub_raw
#define DEST_4US trans_4_GLuint_4us_raw
#include "m_trans_tmp.h"
 
#define SZ 3
#define INIT init_trans_3_GLuint_raw
#define DEST_4F trans_3_GLuint_4f_raw
#define DEST_4UB trans_3_GLuint_4ub_raw
#define DEST_4US trans_3_GLuint_4us_raw
#define DEST_3F trans_3_GLuint_3f_raw
#include "m_trans_tmp.h"
 
#define SZ 2
#define INIT init_trans_2_GLuint_raw
#define DEST_4F trans_2_GLuint_4f_raw
#include "m_trans_tmp.h"
 
#define SZ 1
#define INIT init_trans_1_GLuint_raw
#define DEST_4F trans_1_GLuint_4f_raw
#define DEST_1UB trans_1_GLuint_1ub_raw
#define DEST_1UI trans_1_GLuint_1ui_raw
#include "m_trans_tmp.h"
 
#undef SRC
#undef SRC_IDX
#undef TRX_3F
#undef TRX_4F
#undef TRX_UB
#undef TRX_US
#undef TRX_UI
 
 
/* GL_DOUBLE
*/
#define SRC GLdouble
#define SRC_IDX TYPE_IDX(GL_DOUBLE)
#define TRX_3F(f,n) (GLfloat) PTR_ELT(f,n)
#define TRX_4F(f,n) (GLfloat) PTR_ELT(f,n)
#define TRX_UB(ub,f,n) UNCLAMPED_FLOAT_TO_UBYTE(ub, PTR_ELT(f,n))
#define TRX_US(us,f,n) UNCLAMPED_FLOAT_TO_USHORT(us, PTR_ELT(f,n))
#define TRX_UI(f,n) (GLuint) (GLint) PTR_ELT(f,n)
#define TRX_1F(f,n) (GLfloat) PTR_ELT(f,n)
 
 
#define SZ 4
#define INIT init_trans_4_GLdouble_raw
#define DEST_4F trans_4_GLdouble_4f_raw
#define DEST_4UB trans_4_GLdouble_4ub_raw
#define DEST_4US trans_4_GLdouble_4us_raw
#include "m_trans_tmp.h"
 
#define SZ 3
#define INIT init_trans_3_GLdouble_raw
#define DEST_4F trans_3_GLdouble_4f_raw
#define DEST_4UB trans_3_GLdouble_4ub_raw
#define DEST_4US trans_3_GLdouble_4us_raw
#define DEST_3F trans_3_GLdouble_3f_raw
#include "m_trans_tmp.h"
 
#define SZ 2
#define INIT init_trans_2_GLdouble_raw
#define DEST_4F trans_2_GLdouble_4f_raw
#include "m_trans_tmp.h"
 
#define SZ 1
#define INIT init_trans_1_GLdouble_raw
#define DEST_4F trans_1_GLdouble_4f_raw
#define DEST_1UB trans_1_GLdouble_1ub_raw
#define DEST_1UI trans_1_GLdouble_1ui_raw
#define DEST_1F trans_1_GLdouble_1f_raw
#include "m_trans_tmp.h"
 
#undef SRC
#undef SRC_IDX
 
/* GL_FLOAT
*/
#define SRC GLfloat
#define SRC_IDX TYPE_IDX(GL_FLOAT)
#define SZ 4
#define INIT init_trans_4_GLfloat_raw
#define DEST_4UB trans_4_GLfloat_4ub_raw
#define DEST_4US trans_4_GLfloat_4us_raw
#define DEST_4F trans_4_GLfloat_4f_raw
#include "m_trans_tmp.h"
 
#define SZ 3
#define INIT init_trans_3_GLfloat_raw
#define DEST_4F trans_3_GLfloat_4f_raw
#define DEST_4UB trans_3_GLfloat_4ub_raw
#define DEST_4US trans_3_GLfloat_4us_raw
#define DEST_3F trans_3_GLfloat_3f_raw
#include "m_trans_tmp.h"
 
#define SZ 2
#define INIT init_trans_2_GLfloat_raw
#define DEST_4F trans_2_GLfloat_4f_raw
#include "m_trans_tmp.h"
 
#define SZ 1
#define INIT init_trans_1_GLfloat_raw
#define DEST_4F trans_1_GLfloat_4f_raw
#define DEST_1UB trans_1_GLfloat_1ub_raw
#define DEST_1UI trans_1_GLfloat_1ui_raw
#define DEST_1F trans_1_GLfloat_1f_raw
 
#include "m_trans_tmp.h"
 
#undef SRC
#undef SRC_IDX
#undef TRX_3F
#undef TRX_4F
#undef TRX_UB
#undef TRX_US
#undef TRX_UI
 
 
static void trans_4_GLubyte_4ub_raw(GLubyte (*t)[4],
CONST void *Ptr,
GLuint stride,
ARGS )
{
const GLubyte *f = (GLubyte *) Ptr + SRC_START * stride;
GLuint i;
 
if (((((long) f | (long) stride)) & 3L) == 0L) {
/* Aligned.
*/
for (i = DST_START ; i < n ; i++, f += stride) {
COPY_4UBV( t[i], f );
}
} else {
for (i = DST_START ; i < n ; i++, f += stride) {
t[i][0] = f[0];
t[i][1] = f[1];
t[i][2] = f[2];
t[i][3] = f[3];
}
}
}
 
 
static void init_translate_raw(void)
{
MEMSET( TAB(_1ui), 0, sizeof(TAB(_1ui)) );
MEMSET( TAB(_1ub), 0, sizeof(TAB(_1ub)) );
MEMSET( TAB(_3f), 0, sizeof(TAB(_3f)) );
MEMSET( TAB(_4ub), 0, sizeof(TAB(_4ub)) );
MEMSET( TAB(_4us), 0, sizeof(TAB(_4us)) );
MEMSET( TAB(_4f), 0, sizeof(TAB(_4f)) );
 
init_trans_4_GLbyte_raw();
init_trans_3_GLbyte_raw();
init_trans_2_GLbyte_raw();
init_trans_1_GLbyte_raw();
init_trans_1_GLubyte_raw();
init_trans_3_GLubyte_raw();
init_trans_4_GLubyte_raw();
init_trans_4_GLshort_raw();
init_trans_3_GLshort_raw();
init_trans_2_GLshort_raw();
init_trans_1_GLshort_raw();
init_trans_4_GLushort_raw();
init_trans_3_GLushort_raw();
init_trans_2_GLushort_raw();
init_trans_1_GLushort_raw();
init_trans_4_GLint_raw();
init_trans_3_GLint_raw();
init_trans_2_GLint_raw();
init_trans_1_GLint_raw();
init_trans_4_GLuint_raw();
init_trans_3_GLuint_raw();
init_trans_2_GLuint_raw();
init_trans_1_GLuint_raw();
init_trans_4_GLdouble_raw();
init_trans_3_GLdouble_raw();
init_trans_2_GLdouble_raw();
init_trans_1_GLdouble_raw();
init_trans_4_GLfloat_raw();
init_trans_3_GLfloat_raw();
init_trans_2_GLfloat_raw();
init_trans_1_GLfloat_raw();
 
TAB(_4ub)[4][TYPE_IDX(GL_UNSIGNED_BYTE)] = trans_4_GLubyte_4ub_raw;
}
 
 
#undef TAB
#undef CLASS
#undef ARGS
#undef CHECK
#undef SRC_START
#undef DST_START
#undef NEXT_F
#undef NEXT_F2
 
 
 
 
 
void _math_init_translate( void )
{
init_translate_raw();
}
 
 
 
void _math_trans_1f(GLfloat *to,
CONST void *ptr,
GLuint stride,
GLenum type,
GLuint start,
GLuint n )
{
_math_trans_1f_tab[TYPE_IDX(type)]( to, ptr, stride, start, n );
}
 
void _math_trans_1ui(GLuint *to,
CONST void *ptr,
GLuint stride,
GLenum type,
GLuint start,
GLuint n )
{
_math_trans_1ui_tab[TYPE_IDX(type)]( to, ptr, stride, start, n );
}
 
void _math_trans_1ub(GLubyte *to,
CONST void *ptr,
GLuint stride,
GLenum type,
GLuint start,
GLuint n )
{
_math_trans_1ub_tab[TYPE_IDX(type)]( to, ptr, stride, start, n );
}
 
 
void _math_trans_4ub(GLubyte (*to)[4],
CONST void *ptr,
GLuint stride,
GLenum type,
GLuint size,
GLuint start,
GLuint n )
{
_math_trans_4ub_tab[size][TYPE_IDX(type)]( to, ptr, stride, start, n );
}
 
void _math_trans_4chan( GLchan (*to)[4],
CONST void *ptr,
GLuint stride,
GLenum type,
GLuint size,
GLuint start,
GLuint n )
{
#if CHAN_TYPE == GL_UNSIGNED_BYTE
_math_trans_4ub( to, ptr, stride, type, size, start, n );
#elif CHAN_TYPE == GL_UNSIGNED_SHORT
_math_trans_4us( to, ptr, stride, type, size, start, n );
#elif CHAN_TYPE == GL_FLOAT
_math_trans_4f( to, ptr, stride, type, size, start, n );
#endif
}
 
void _math_trans_4us(GLushort (*to)[4],
CONST void *ptr,
GLuint stride,
GLenum type,
GLuint size,
GLuint start,
GLuint n )
{
_math_trans_4us_tab[size][TYPE_IDX(type)]( to, ptr, stride, start, n );
}
 
void _math_trans_4f(GLfloat (*to)[4],
CONST void *ptr,
GLuint stride,
GLenum type,
GLuint size,
GLuint start,
GLuint n )
{
_math_trans_4f_tab[size][TYPE_IDX(type)]( to, ptr, stride, start, n );
}
 
void _math_trans_3f(GLfloat (*to)[3],
CONST void *ptr,
GLuint stride,
GLenum type,
GLuint start,
GLuint n )
{
_math_trans_3f_tab[TYPE_IDX(type)]( to, ptr, stride, start, n );
}
/shark/trunk/ports/mesa/src/math/m_debug_clip.c
0,0 → 1,367
/* $Id: m_debug_clip.c,v 1.1 2003-02-28 11:48:05 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 5.0
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Gareth Hughes
*/
 
#include "glheader.h"
#include "context.h"
#include "macros.h"
#include "imports.h"
 
#include "m_matrix.h"
#include "m_xform.h"
 
#include "m_debug.h"
#include "m_debug_util.h"
 
#ifdef DEBUG /* This code only used for debugging */
 
static clip_func *clip_tab[2] = {
_mesa_clip_tab,
_mesa_clip_np_tab
};
static char *cnames[2] = {
"_mesa_clip_tab",
"_mesa_clip_np_tab"
};
#ifdef RUN_DEBUG_BENCHMARK
static char *cstrings[2] = {
"clip, perspective divide",
"clip, no divide"
};
#endif
 
 
/* =============================================================
* Reference cliptests
*/
 
static GLvector4f *ref_cliptest_points4( GLvector4f *clip_vec,
GLvector4f *proj_vec,
GLubyte clipMask[],
GLubyte *orMask,
GLubyte *andMask )
{
const GLuint stride = clip_vec->stride;
const GLuint count = clip_vec->count;
const GLfloat *from = (GLfloat *)clip_vec->start;
GLuint c = 0;
GLfloat (*vProj)[4] = (GLfloat (*)[4])proj_vec->start;
GLubyte tmpAndMask = *andMask;
GLubyte tmpOrMask = *orMask;
GLuint i;
for ( i = 0 ; i < count ; i++, STRIDE_F(from, stride) ) {
const GLfloat cx = from[0];
const GLfloat cy = from[1];
const GLfloat cz = from[2];
const GLfloat cw = from[3];
GLubyte mask = 0;
if ( -cx + cw < 0 ) mask |= CLIP_RIGHT_BIT;
if ( cx + cw < 0 ) mask |= CLIP_LEFT_BIT;
if ( -cy + cw < 0 ) mask |= CLIP_TOP_BIT;
if ( cy + cw < 0 ) mask |= CLIP_BOTTOM_BIT;
if ( -cz + cw < 0 ) mask |= CLIP_FAR_BIT;
if ( cz + cw < 0 ) mask |= CLIP_NEAR_BIT;
clipMask[i] = mask;
if ( mask ) {
c++;
tmpAndMask &= mask;
tmpOrMask |= mask;
vProj[i][0] = 0;
vProj[i][1] = 0;
vProj[i][2] = 0;
vProj[i][3] = 1;
} else {
GLfloat oow = 1.0F / cw;
vProj[i][0] = cx * oow;
vProj[i][1] = cy * oow;
vProj[i][2] = cz * oow;
vProj[i][3] = oow;
}
}
 
*orMask = tmpOrMask;
*andMask = (GLubyte) (c < count ? 0 : tmpAndMask);
 
proj_vec->flags |= VEC_SIZE_4;
proj_vec->size = 4;
proj_vec->count = clip_vec->count;
return proj_vec;
}
 
/* Keep these here for now, even though we don't use them...
*/
static GLvector4f *ref_cliptest_points3( GLvector4f *clip_vec,
GLvector4f *proj_vec,
GLubyte clipMask[],
GLubyte *orMask,
GLubyte *andMask )
{
const GLuint stride = clip_vec->stride;
const GLuint count = clip_vec->count;
const GLfloat *from = (GLfloat *)clip_vec->start;
 
GLubyte tmpOrMask = *orMask;
GLubyte tmpAndMask = *andMask;
GLuint i;
for ( i = 0 ; i < count ; i++, STRIDE_F(from, stride) ) {
const GLfloat cx = from[0], cy = from[1], cz = from[2];
GLubyte mask = 0;
if ( cx > 1.0 ) mask |= CLIP_RIGHT_BIT;
else if ( cx < -1.0 ) mask |= CLIP_LEFT_BIT;
if ( cy > 1.0 ) mask |= CLIP_TOP_BIT;
else if ( cy < -1.0 ) mask |= CLIP_BOTTOM_BIT;
if ( cz > 1.0 ) mask |= CLIP_FAR_BIT;
else if ( cz < -1.0 ) mask |= CLIP_NEAR_BIT;
clipMask[i] = mask;
tmpOrMask |= mask;
tmpAndMask &= mask;
}
 
*orMask = tmpOrMask;
*andMask = tmpAndMask;
return clip_vec;
}
 
static GLvector4f * ref_cliptest_points2( GLvector4f *clip_vec,
GLvector4f *proj_vec,
GLubyte clipMask[],
GLubyte *orMask,
GLubyte *andMask )
{
const GLuint stride = clip_vec->stride;
const GLuint count = clip_vec->count;
const GLfloat *from = (GLfloat *)clip_vec->start;
 
GLubyte tmpOrMask = *orMask;
GLubyte tmpAndMask = *andMask;
GLuint i;
for ( i = 0 ; i < count ; i++, STRIDE_F(from, stride) ) {
const GLfloat cx = from[0], cy = from[1];
GLubyte mask = 0;
if ( cx > 1.0 ) mask |= CLIP_RIGHT_BIT;
else if ( cx < -1.0 ) mask |= CLIP_LEFT_BIT;
if ( cy > 1.0 ) mask |= CLIP_TOP_BIT;
else if ( cy < -1.0 ) mask |= CLIP_BOTTOM_BIT;
clipMask[i] = mask;
tmpOrMask |= mask;
tmpAndMask &= mask;
}
 
*orMask = tmpOrMask;
*andMask = tmpAndMask;
return clip_vec;
}
 
static clip_func ref_cliptest[5] = {
0,
0,
ref_cliptest_points2,
ref_cliptest_points3,
ref_cliptest_points4
};
 
 
/* =============================================================
* Cliptest tests
*/
 
static GLfloat s[TEST_COUNT][4] ALIGN16;
static GLfloat d[TEST_COUNT][4] ALIGN16;
static GLfloat r[TEST_COUNT][4] ALIGN16;
 
static int test_cliptest_function( clip_func func, int np,
int psize, long *cycles )
{
GLvector4f source[1], dest[1], ref[1];
GLubyte dm[TEST_COUNT], dco, dca;
GLubyte rm[TEST_COUNT], rco, rca;
int i, j;
#ifdef RUN_DEBUG_BENCHMARK
int cycle_i; /* the counter for the benchmarks we run */
#endif
 
(void) cycles;
 
if ( psize > 4 ) {
_mesa_problem( NULL, "test_cliptest_function called with psize > 4\n" );
return 0;
}
 
for ( i = 0 ; i < TEST_COUNT ; i++) {
ASSIGN_4V( d[i], 0.0, 0.0, 0.0, 1.0 );
ASSIGN_4V( s[i], 0.0, 0.0, 0.0, 1.0 );
for ( j = 0 ; j < psize ; j++ )
s[i][j] = rnd();
}
 
source->data = (GLfloat(*)[4])s;
source->start = (GLfloat *)s;
source->count = TEST_COUNT;
source->stride = sizeof(s[0]);
source->size = 4;
source->flags = 0;
 
dest->data = (GLfloat(*)[4])d;
dest->start = (GLfloat *)d;
dest->count = TEST_COUNT;
dest->stride = sizeof(float[4]);
dest->size = 0;
dest->flags = 0;
 
ref->data = (GLfloat(*)[4])r;
ref->start = (GLfloat *)r;
ref->count = TEST_COUNT;
ref->stride = sizeof(float[4]);
ref->size = 0;
ref->flags = 0;
 
dco = rco = 0;
dca = rca = CLIP_ALL_BITS;
 
ref_cliptest[psize]( source, ref, rm, &rco, &rca );
 
if ( mesa_profile ) {
BEGIN_RACE( *cycles );
func( source, dest, dm, &dco, &dca );
END_RACE( *cycles );
}
else {
func( source, dest, dm, &dco, &dca );
}
 
if ( dco != rco ) {
_mesa_printf(NULL, "\n-----------------------------\n" );
_mesa_printf(NULL, "dco = 0x%02x rco = 0x%02x\n", dco, rco );
return 0;
}
if ( dca != rca ) {
_mesa_printf(NULL, "\n-----------------------------\n" );
_mesa_printf(NULL, "dca = 0x%02x rca = 0x%02x\n", dca, rca );
return 0;
}
for ( i = 0 ; i < TEST_COUNT ; i++ ) {
if ( dm[i] != rm[i] ) {
_mesa_printf(NULL, "\n-----------------------------\n" );
_mesa_printf(NULL, "(i = %i)\n", i );
_mesa_printf(NULL, "dm = 0x%02x rm = 0x%02x\n", dm[i], rm[i] );
return 0;
}
}
 
/* Only verify output on projected points4 case. FIXME: Do we need
* to test other cases?
*/
if ( np || psize < 4 )
return 1;
 
for ( i = 0 ; i < TEST_COUNT ; i++ ) {
for ( j = 0 ; j < 4 ; j++ ) {
if ( significand_match( d[i][j], r[i][j] ) < REQUIRED_PRECISION ) {
_mesa_printf(NULL, "\n-----------------------------\n" );
_mesa_printf(NULL, "(i = %i, j = %i) dm = 0x%02x rm = 0x%02x\n",
i, j, dm[i], rm[i] );
_mesa_printf(NULL, "%f \t %f \t [diff = %e - %i bit missed]\n",
d[i][0], r[i][0], r[i][0]-d[i][0],
MAX_PRECISION - significand_match( d[i][0], r[i][0] ) );
_mesa_printf(NULL, "%f \t %f \t [diff = %e - %i bit missed]\n",
d[i][1], r[i][1], r[i][1]-d[i][1],
MAX_PRECISION - significand_match( d[i][1], r[i][1] ) );
_mesa_printf(NULL, "%f \t %f \t [diff = %e - %i bit missed]\n",
d[i][2], r[i][2], r[i][2]-d[i][2],
MAX_PRECISION - significand_match( d[i][2], r[i][2] ) );
_mesa_printf(NULL, "%f \t %f \t [diff = %e - %i bit missed]\n",
d[i][3], r[i][3], r[i][3]-d[i][3],
MAX_PRECISION - significand_match( d[i][3], r[i][3] ) );
return 0;
}
}
}
 
return 1;
}
 
void _math_test_all_cliptest_functions( char *description )
{
int np, psize;
long benchmark_tab[2][4];
static int first_time = 1;
 
if ( first_time ) {
first_time = 0;
mesa_profile = _mesa_getenv( "MESA_PROFILE" );
}
 
#ifdef RUN_DEBUG_BENCHMARK
if ( mesa_profile ) {
if ( !counter_overhead ) {
INIT_COUNTER();
_mesa_printf(NULL, "counter overhead: %ld cycles\n\n", counter_overhead );
}
_mesa_printf(NULL, "cliptest results after hooking in %s functions:\n", description );
}
#endif
 
#ifdef RUN_DEBUG_BENCHMARK
if ( mesa_profile ) {
_mesa_printf(NULL, "\n\t" );
for ( psize = 2 ; psize <= 4 ; psize++ ) {
_mesa_printf(NULL, " p%d\t", psize );
}
_mesa_printf(NULL, "\n--------------------------------------------------------\n\t" );
}
#endif
 
for ( np = 0 ; np < 2 ; np++ ) {
for ( psize = 2 ; psize <= 4 ; psize++ ) {
clip_func func = clip_tab[np][psize];
long *cycles = &(benchmark_tab[np][psize-1]);
 
if ( test_cliptest_function( func, np, psize, cycles ) == 0 ) {
char buf[100];
_mesa_sprintf(NULL, buf, "%s[%d] failed test (%s)",
cnames[np], psize, description );
_mesa_problem( NULL, buf );
}
#ifdef RUN_DEBUG_BENCHMARK
if ( mesa_profile )
_mesa_printf(NULL, " %li\t", benchmark_tab[np][psize-1] );
#endif
}
#ifdef RUN_DEBUG_BENCHMARK
if ( mesa_profile )
_mesa_printf(NULL, " | [%s]\n\t", cstrings[np] );
#endif
}
#ifdef RUN_DEBUG_BENCHMARK
if ( mesa_profile )
_mesa_printf(NULL, "\n" );
#endif
}
 
 
#endif /* DEBUG */
/shark/trunk/ports/mesa/src/math/m_copy_tmp.h
0,0 → 1,87
/* $Id: m_copy_tmp.h,v 1.1 2003-02-28 11:48:04 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
/*
* New (3.1) transformation code written by Keith Whitwell.
*/
 
 
#define COPY_FUNC( BITS ) \
static void TAG2(copy, BITS)( GLvector4f *to, const GLvector4f *f ) \
{ \
GLfloat (*t)[4] = (GLfloat (*)[4])to->start; \
GLfloat *from = f->start; \
GLuint stride = f->stride; \
GLuint count = f->count; \
GLuint i; \
\
if (BITS) \
STRIDE_LOOP { \
if (BITS&1) t[i][0] = from[0]; \
if (BITS&2) t[i][1] = from[1]; \
if (BITS&4) t[i][2] = from[2]; \
if (BITS&8) t[i][3] = from[3]; \
} \
}
 
/* We got them all here:
*/
COPY_FUNC( 0x0 ) /* noop */
COPY_FUNC( 0x1 )
COPY_FUNC( 0x2 )
COPY_FUNC( 0x3 )
COPY_FUNC( 0x4 )
COPY_FUNC( 0x5 )
COPY_FUNC( 0x6 )
COPY_FUNC( 0x7 )
COPY_FUNC( 0x8 )
COPY_FUNC( 0x9 )
COPY_FUNC( 0xa )
COPY_FUNC( 0xb )
COPY_FUNC( 0xc )
COPY_FUNC( 0xd )
COPY_FUNC( 0xe )
COPY_FUNC( 0xf )
 
static void TAG2(init_copy, 0)( void )
{
_mesa_copy_tab[0x0] = TAG2(copy, 0x0);
_mesa_copy_tab[0x1] = TAG2(copy, 0x1);
_mesa_copy_tab[0x2] = TAG2(copy, 0x2);
_mesa_copy_tab[0x3] = TAG2(copy, 0x3);
_mesa_copy_tab[0x4] = TAG2(copy, 0x4);
_mesa_copy_tab[0x5] = TAG2(copy, 0x5);
_mesa_copy_tab[0x6] = TAG2(copy, 0x6);
_mesa_copy_tab[0x7] = TAG2(copy, 0x7);
_mesa_copy_tab[0x8] = TAG2(copy, 0x8);
_mesa_copy_tab[0x9] = TAG2(copy, 0x9);
_mesa_copy_tab[0xa] = TAG2(copy, 0xa);
_mesa_copy_tab[0xb] = TAG2(copy, 0xb);
_mesa_copy_tab[0xc] = TAG2(copy, 0xc);
_mesa_copy_tab[0xd] = TAG2(copy, 0xd);
_mesa_copy_tab[0xe] = TAG2(copy, 0xe);
_mesa_copy_tab[0xf] = TAG2(copy, 0xf);
}
/shark/trunk/ports/mesa/src/math/m_norm_tmp.h
0,0 → 1,391
/* $Id: m_norm_tmp.h,v 1.1 2003-02-28 11:48:05 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 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.
*/
 
/*
* New (3.1) transformation code written by Keith Whitwell.
*/
 
/* Functions to tranform a vector of normals. This includes applying
* the transformation matrix, rescaling and normalization.
*/
 
/*
* mat - the 4x4 transformation matrix
* scale - uniform scale factor of the transformation matrix (not always used)
* in - the source vector of normals
* lengths - length of each incoming normal (may be NULL) (a display list
* optimization)
* dest - the destination vector of normals
*/
static void _XFORMAPI
TAG(transform_normalize_normals)( const GLmatrix *mat,
GLfloat scale,
const GLvector4f *in,
const GLfloat *lengths,
GLvector4f *dest )
{
GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
const GLfloat *from = in->start;
const GLuint stride = in->stride;
const GLuint count = in->count;
const GLfloat *m = mat->inv;
GLfloat m0 = m[0], m4 = m[4], m8 = m[8];
GLfloat m1 = m[1], m5 = m[5], m9 = m[9];
GLfloat m2 = m[2], m6 = m[6], m10 = m[10];
GLuint i;
 
if (!lengths) {
STRIDE_LOOP {
GLfloat tx, ty, tz;
{
const GLfloat ux = from[0], uy = from[1], uz = from[2];
tx = ux * m0 + uy * m1 + uz * m2;
ty = ux * m4 + uy * m5 + uz * m6;
tz = ux * m8 + uy * m9 + uz * m10;
}
{
GLdouble len = tx*tx + ty*ty + tz*tz;
if (len > 1e-20) {
GLdouble scale = 1.0 / GL_SQRT(len);
out[i][0] = (GLfloat) (tx * scale);
out[i][1] = (GLfloat) (ty * scale);
out[i][2] = (GLfloat) (tz * scale);
}
else {
out[i][0] = out[i][1] = out[i][2] = 0;
}
}
}
}
else {
if (scale != 1.0) {
m0 *= scale, m4 *= scale, m8 *= scale;
m1 *= scale, m5 *= scale, m9 *= scale;
m2 *= scale, m6 *= scale, m10 *= scale;
}
 
STRIDE_LOOP {
GLfloat tx, ty, tz;
{
const GLfloat ux = from[0], uy = from[1], uz = from[2];
tx = ux * m0 + uy * m1 + uz * m2;
ty = ux * m4 + uy * m5 + uz * m6;
tz = ux * m8 + uy * m9 + uz * m10;
}
{
GLfloat len = lengths[i];
out[i][0] = tx * len;
out[i][1] = ty * len;
out[i][2] = tz * len;
}
}
}
dest->count = in->count;
}
 
 
static void _XFORMAPI
TAG(transform_normalize_normals_no_rot)( const GLmatrix *mat,
GLfloat scale,
const GLvector4f *in,
const GLfloat *lengths,
GLvector4f *dest )
{
GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
const GLfloat *from = in->start;
const GLuint stride = in->stride;
const GLuint count = in->count;
const GLfloat *m = mat->inv;
GLfloat m0 = m[0];
GLfloat m5 = m[5];
GLfloat m10 = m[10];
GLuint i;
 
if (!lengths) {
STRIDE_LOOP {
GLfloat tx, ty, tz;
{
const GLfloat ux = from[0], uy = from[1], uz = from[2];
tx = ux * m0 ;
ty = uy * m5 ;
tz = uz * m10;
}
{
GLdouble len = tx*tx + ty*ty + tz*tz;
if (len > 1e-20) {
GLdouble scale = 1.0 / GL_SQRT(len);
out[i][0] = (GLfloat) (tx * scale);
out[i][1] = (GLfloat) (ty * scale);
out[i][2] = (GLfloat) (tz * scale);
}
else {
out[i][0] = out[i][1] = out[i][2] = 0;
}
}
}
}
else {
m0 *= scale;
m5 *= scale;
m10 *= scale;
 
STRIDE_LOOP {
GLfloat tx, ty, tz;
{
const GLfloat ux = from[0], uy = from[1], uz = from[2];
tx = ux * m0 ;
ty = uy * m5 ;
tz = uz * m10;
}
{
GLfloat len = lengths[i];
out[i][0] = tx * len;
out[i][1] = ty * len;
out[i][2] = tz * len;
}
}
}
dest->count = in->count;
}
 
 
static void _XFORMAPI
TAG(transform_rescale_normals_no_rot)( const GLmatrix *mat,
GLfloat scale,
const GLvector4f *in,
const GLfloat *lengths,
GLvector4f *dest )
{
GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
const GLfloat *from = in->start;
const GLuint stride = in->stride;
const GLuint count = in->count;
const GLfloat *m = mat->inv;
const GLfloat m0 = scale*m[0];
const GLfloat m5 = scale*m[5];
const GLfloat m10 = scale*m[10];
GLuint i;
 
(void) lengths;
 
STRIDE_LOOP {
GLfloat ux = from[0], uy = from[1], uz = from[2];
out[i][0] = ux * m0;
out[i][1] = uy * m5;
out[i][2] = uz * m10;
}
dest->count = in->count;
}
 
 
static void _XFORMAPI
TAG(transform_rescale_normals)( const GLmatrix *mat,
GLfloat scale,
const GLvector4f *in,
const GLfloat *lengths,
GLvector4f *dest )
{
GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
const GLfloat *from = in->start;
const GLuint stride = in->stride;
const GLuint count = in->count;
/* Since we are unlikely to have < 3 vertices in the buffer,
* it makes sense to pre-multiply by scale.
*/
const GLfloat *m = mat->inv;
const GLfloat m0 = scale*m[0], m4 = scale*m[4], m8 = scale*m[8];
const GLfloat m1 = scale*m[1], m5 = scale*m[5], m9 = scale*m[9];
const GLfloat m2 = scale*m[2], m6 = scale*m[6], m10 = scale*m[10];
GLuint i;
 
(void) lengths;
 
STRIDE_LOOP {
GLfloat ux = from[0], uy = from[1], uz = from[2];
out[i][0] = ux * m0 + uy * m1 + uz * m2;
out[i][1] = ux * m4 + uy * m5 + uz * m6;
out[i][2] = ux * m8 + uy * m9 + uz * m10;
}
dest->count = in->count;
}
 
 
static void _XFORMAPI
TAG(transform_normals_no_rot)( const GLmatrix *mat,
GLfloat scale,
const GLvector4f *in,
const GLfloat *lengths,
GLvector4f *dest )
{
GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
const GLfloat *from = in->start;
const GLuint stride = in->stride;
const GLuint count = in->count;
const GLfloat *m = mat->inv;
const GLfloat m0 = m[0];
const GLfloat m5 = m[5];
const GLfloat m10 = m[10];
GLuint i;
 
(void) scale;
(void) lengths;
 
STRIDE_LOOP {
GLfloat ux = from[0], uy = from[1], uz = from[2];
out[i][0] = ux * m0;
out[i][1] = uy * m5;
out[i][2] = uz * m10;
}
dest->count = in->count;
}
 
 
static void _XFORMAPI
TAG(transform_normals)( const GLmatrix *mat,
GLfloat scale,
const GLvector4f *in,
const GLfloat *lengths,
GLvector4f *dest )
{
GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
const GLfloat *from = in->start;
const GLuint stride = in->stride;
const GLuint count = in->count;
const GLfloat *m = mat->inv;
const GLfloat m0 = m[0], m4 = m[4], m8 = m[8];
const GLfloat m1 = m[1], m5 = m[5], m9 = m[9];
const GLfloat m2 = m[2], m6 = m[6], m10 = m[10];
GLuint i;
 
(void) scale;
(void) lengths;
 
STRIDE_LOOP {
GLfloat ux = from[0], uy = from[1], uz = from[2];
out[i][0] = ux * m0 + uy * m1 + uz * m2;
out[i][1] = ux * m4 + uy * m5 + uz * m6;
out[i][2] = ux * m8 + uy * m9 + uz * m10;
}
dest->count = in->count;
}
 
 
static void _XFORMAPI
TAG(normalize_normals)( const GLmatrix *mat,
GLfloat scale,
const GLvector4f *in,
const GLfloat *lengths,
GLvector4f *dest )
{
GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
const GLfloat *from = in->start;
const GLuint stride = in->stride;
const GLuint count = in->count;
GLuint i;
 
(void) mat;
(void) scale;
 
if (lengths) {
STRIDE_LOOP {
const GLfloat x = from[0], y = from[1], z = from[2];
GLfloat invlen = lengths[i];
out[i][0] = x * invlen;
out[i][1] = y * invlen;
out[i][2] = z * invlen;
}
}
else {
STRIDE_LOOP {
const GLfloat x = from[0], y = from[1], z = from[2];
GLdouble len = x * x + y * y + z * z;
if (len > 1e-50) {
len = 1.0 / GL_SQRT(len);
out[i][0] = (GLfloat) (x * len);
out[i][1] = (GLfloat) (y * len);
out[i][2] = (GLfloat) (z * len);
}
else {
out[i][0] = x;
out[i][1] = y;
out[i][2] = z;
}
}
}
dest->count = in->count;
}
 
 
static void _XFORMAPI
TAG(rescale_normals)( const GLmatrix *mat,
GLfloat scale,
const GLvector4f *in,
const GLfloat *lengths,
GLvector4f *dest )
{
GLfloat (*out)[4] = (GLfloat (*)[4])dest->start;
const GLfloat *from = in->start;
const GLuint stride = in->stride;
const GLuint count = in->count;
GLuint i;
 
(void) mat;
(void) lengths;
 
STRIDE_LOOP {
SCALE_SCALAR_3V( out[i], scale, from );
}
dest->count = in->count;
}
 
 
static void _XFORMAPI
TAG(init_c_norm_transform)( void )
{
_mesa_normal_tab[NORM_TRANSFORM_NO_ROT] =
TAG(transform_normals_no_rot);
 
_mesa_normal_tab[NORM_TRANSFORM_NO_ROT | NORM_RESCALE] =
TAG(transform_rescale_normals_no_rot);
 
_mesa_normal_tab[NORM_TRANSFORM_NO_ROT | NORM_NORMALIZE] =
TAG(transform_normalize_normals_no_rot);
 
_mesa_normal_tab[NORM_TRANSFORM] =
TAG(transform_normals);
 
_mesa_normal_tab[NORM_TRANSFORM | NORM_RESCALE] =
TAG(transform_rescale_normals);
 
_mesa_normal_tab[NORM_TRANSFORM | NORM_NORMALIZE] =
TAG(transform_normalize_normals);
 
_mesa_normal_tab[NORM_RESCALE] =
TAG(rescale_normals);
 
_mesa_normal_tab[NORM_NORMALIZE] =
TAG(normalize_normals);
}
/shark/trunk/ports/mesa/src/math/m_dotprod_tmp.h
0,0 → 1,103
/* $Id: m_dotprod_tmp.h,v 1.1 2003-02-28 11:48:05 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
/*
* New (3.1) transformation code written by Keith Whitwell.
*/
 
 
/* Note - respects the stride of the output vector.
*/
static void TAG(dotprod_vec2)( GLfloat *out,
GLuint outstride,
const GLvector4f *coord_vec,
const GLfloat plane[4] )
{
GLuint stride = coord_vec->stride;
GLfloat *coord = coord_vec->start;
GLuint count = coord_vec->count;
 
GLuint i;
 
const GLfloat plane0 = plane[0], plane1 = plane[1], plane3 = plane[3];
 
for (i=0;i<count;i++,STRIDE_F(coord,stride),STRIDE_F(out,outstride)) {
*out = (coord[0] * plane0 +
coord[1] * plane1 +
plane3);
}
}
 
static void TAG(dotprod_vec3)( GLfloat *out,
GLuint outstride,
const GLvector4f *coord_vec,
const GLfloat plane[4] )
{
GLuint stride = coord_vec->stride;
GLfloat *coord = coord_vec->start;
GLuint count = coord_vec->count;
 
GLuint i;
 
const GLfloat plane0 = plane[0], plane1 = plane[1], plane2 = plane[2];
const GLfloat plane3 = plane[3];
 
for (i=0;i<count;i++,STRIDE_F(coord,stride),STRIDE_F(out,outstride)) {
*out = (coord[0] * plane0 +
coord[1] * plane1 +
coord[2] * plane2 +
plane3);
}
}
 
static void TAG(dotprod_vec4)( GLfloat *out,
GLuint outstride,
const GLvector4f *coord_vec,
const GLfloat plane[4] )
{
GLuint stride = coord_vec->stride;
GLfloat *coord = coord_vec->start;
GLuint count = coord_vec->count;
GLuint i;
 
const GLfloat plane0 = plane[0], plane1 = plane[1], plane2 = plane[2];
const GLfloat plane3 = plane[3];
 
for (i=0;i<count;i++,STRIDE_F(coord,stride),STRIDE_F(out,outstride)) {
*out = (coord[0] * plane0 +
coord[1] * plane1 +
coord[2] * plane2 +
coord[3] * plane3);
}
}
 
 
static void TAG(init_dotprod)( void )
{
_mesa_dotprod_tab[2] = TAG(dotprod_vec2);
_mesa_dotprod_tab[3] = TAG(dotprod_vec3);
_mesa_dotprod_tab[4] = TAG(dotprod_vec4);
}
/shark/trunk/ports/mesa/src/math/m_xform.h
0,0 → 1,217
/* $Id: m_xform.h,v 1.1 2003-02-28 11:48:05 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
 
 
 
 
#ifndef _M_XFORM_H
#define _M_XFORM_H
 
 
#include "glheader.h"
#include "config.h"
#include "math/m_vector.h"
#include "math/m_matrix.h"
 
#ifdef USE_X86_ASM
#define _XFORMAPI _ASMAPI
#define _XFORMAPIP _ASMAPIP
#else
#define _XFORMAPI
#define _XFORMAPIP *
#endif
 
/*
* Transform a point (column vector) by a matrix: Q = M * P
*/
#define TRANSFORM_POINT( Q, M, P ) \
Q[0] = M[0] * P[0] + M[4] * P[1] + M[8] * P[2] + M[12] * P[3]; \
Q[1] = M[1] * P[0] + M[5] * P[1] + M[9] * P[2] + M[13] * P[3]; \
Q[2] = M[2] * P[0] + M[6] * P[1] + M[10] * P[2] + M[14] * P[3]; \
Q[3] = M[3] * P[0] + M[7] * P[1] + M[11] * P[2] + M[15] * P[3];
 
 
#define TRANSFORM_POINT3( Q, M, P ) \
Q[0] = M[0] * P[0] + M[4] * P[1] + M[8] * P[2] + M[12]; \
Q[1] = M[1] * P[0] + M[5] * P[1] + M[9] * P[2] + M[13]; \
Q[2] = M[2] * P[0] + M[6] * P[1] + M[10] * P[2] + M[14]; \
Q[3] = M[3] * P[0] + M[7] * P[1] + M[11] * P[2] + M[15];
 
 
/*
* Transform a normal (row vector) by a matrix: [NX NY NZ] = N * MAT
*/
#define TRANSFORM_NORMAL( TO, N, MAT ) \
do { \
TO[0] = N[0] * MAT[0] + N[1] * MAT[1] + N[2] * MAT[2]; \
TO[1] = N[0] * MAT[4] + N[1] * MAT[5] + N[2] * MAT[6]; \
TO[2] = N[0] * MAT[8] + N[1] * MAT[9] + N[2] * MAT[10]; \
} while (0)
 
 
extern void _mesa_transform_vector( GLfloat u[4],
CONST GLfloat v[4],
CONST GLfloat m[16] );
 
 
extern void
_math_init_transformation( void );
 
 
/* KW: Clip functions now do projective divide as well. The projected
* coordinates are very useful to us because they let us cull
* backfaces and eliminate vertices from lighting, fogging, etc
* calculations. Despite the fact that this divide could be done one
* day in hardware, we would still have a reason to want to do it here
* as long as those other calculations remain in software.
*
* Clipping is a convenient place to do the divide on x86 as it should be
* possible to overlap with integer outcode calculations.
*
* There are two cases where we wouldn't want to do the divide in cliptest:
* - When we aren't clipping. We still might want to cull backfaces
* so the divide should be done elsewhere. This currently never
* happens.
*
* - When culling isn't likely to help us, such as when the GL culling
* is disabled and we not lighting or are only lighting
* one-sided. In this situation, backface determination provides
* us with no useful information. A tricky case to detect is when
* all input data is already culled, although hopefully the
* application wouldn't turn on culling in such cases.
*
* We supply a buffer to hold the [x/w,y/w,z/w,1/w] values which
* are the result of the projection. This is only used in the
* 4-vector case - in other cases, we just use the clip coordinates
* as the projected coordinates - they are identical.
*
* This is doubly convenient because it means the Win[] array is now
* of the same stride as all the others, so I can now turn map_vertices
* into a straight-forward matrix transformation, with asm acceleration
* automatically available.
*/
 
/* Vertex buffer clipping flags
*/
#define CLIP_RIGHT_SHIFT 0
#define CLIP_LEFT_SHIFT 1
#define CLIP_TOP_SHIFT 2
#define CLIP_BOTTOM_SHIFT 3
#define CLIP_NEAR_SHIFT 4
#define CLIP_FAR_SHIFT 5
 
#define CLIP_RIGHT_BIT 0x01
#define CLIP_LEFT_BIT 0x02
#define CLIP_TOP_BIT 0x04
#define CLIP_BOTTOM_BIT 0x08
#define CLIP_NEAR_BIT 0x10
#define CLIP_FAR_BIT 0x20
#define CLIP_USER_BIT 0x40
#define CLIP_ALL_BITS 0x3f
 
 
typedef GLvector4f * (_XFORMAPIP clip_func)( GLvector4f *vClip,
GLvector4f *vProj,
GLubyte clipMask[],
GLubyte *orMask,
GLubyte *andMask );
 
typedef void (*dotprod_func)( GLfloat *out,
GLuint out_stride,
CONST GLvector4f *coord_vec,
CONST GLfloat plane[4] );
 
typedef void (*vec_copy_func)( GLvector4f *to,
CONST GLvector4f *from );
 
 
 
/*
* Functions for transformation of normals in the VB.
*/
typedef void (_NORMAPIP normal_func)( CONST GLmatrix *mat,
GLfloat scale,
CONST GLvector4f *in,
CONST GLfloat lengths[],
GLvector4f *dest );
 
 
/* Flags for selecting a normal transformation function.
*/
#define NORM_RESCALE 0x1 /* apply the scale factor */
#define NORM_NORMALIZE 0x2 /* normalize */
#define NORM_TRANSFORM 0x4 /* apply the transformation matrix */
#define NORM_TRANSFORM_NO_ROT 0x8 /* apply the transformation matrix */
 
 
 
 
/* KW: New versions of the transform function allow a mask array
* specifying that individual vector transform should be skipped
* when the mask byte is zero. This is always present as a
* parameter, to allow a unified interface.
*/
typedef void (_XFORMAPIP transform_func)( GLvector4f *to_vec,
CONST GLfloat m[16],
CONST GLvector4f *from_vec );
 
 
extern GLvector4f *_mesa_project_points( GLvector4f *to,
CONST GLvector4f *from );
 
extern void _mesa_transform_bounds3( GLubyte *orMask, GLubyte *andMask,
CONST GLfloat m[16],
CONST GLfloat src[][3] );
 
extern void _mesa_transform_bounds2( GLubyte *orMask, GLubyte *andMask,
CONST GLfloat m[16],
CONST GLfloat src[][3] );
 
 
extern dotprod_func _mesa_dotprod_tab[5];
extern vec_copy_func _mesa_copy_tab[0x10];
extern vec_copy_func _mesa_copy_clean_tab[5];
extern clip_func _mesa_clip_tab[5];
extern clip_func _mesa_clip_np_tab[5];
extern normal_func _mesa_normal_tab[0xf];
 
/* Use of 2 layers of linked 1-dimensional arrays to reduce
* cost of lookup.
*/
extern transform_func *_mesa_transform_tab[5];
 
 
extern void _mesa_transform_point_sz( GLfloat Q[4], CONST GLfloat M[16],
CONST GLfloat P[4], GLuint sz );
 
 
#define TransformRaw( to, mat, from ) \
( _mesa_transform_tab[(from)->size][(mat)->type]( to, (mat)->m, from ), \
(to) )
 
 
#endif
/shark/trunk/ports/mesa/src/math/m_debug_xform.c
0,0 → 1,335
/* $Id: m_debug_xform.c,v 1.1 2003-02-28 11:48:05 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
/*
* Updated for P6 architecture by Gareth Hughes.
*/
 
#include "glheader.h"
#include "context.h"
#include "macros.h"
#include "imports.h"
 
#include "m_matrix.h"
#include "m_xform.h"
 
#include "m_debug.h"
#include "m_debug_util.h"
 
#ifdef DEBUG /* This code only used for debugging */
 
 
/* Overhead of profiling counter in cycles. Automatically adjusted to
* your machine at run time - counter initialization should give very
* consistent results.
*/
long counter_overhead = 0;
 
/* This is the value of the environment variable MESA_PROFILE, and is
* used to determine if we should benchmark the functions as well as
* verify their correctness.
*/
char *mesa_profile = NULL;
 
 
static int m_general[16] = {
VAR, VAR, VAR, VAR,
VAR, VAR, VAR, VAR,
VAR, VAR, VAR, VAR,
VAR, VAR, VAR, VAR
};
static int m_identity[16] = {
ONE, NIL, NIL, NIL,
NIL, ONE, NIL, NIL,
NIL, NIL, ONE, NIL,
NIL, NIL, NIL, ONE
};
static int m_2d[16] = {
VAR, VAR, NIL, VAR,
VAR, VAR, NIL, VAR,
NIL, NIL, ONE, NIL,
NIL, NIL, NIL, ONE
};
static int m_2d_no_rot[16] = {
VAR, NIL, NIL, VAR,
NIL, VAR, NIL, VAR,
NIL, NIL, ONE, NIL,
NIL, NIL, NIL, ONE
};
static int m_3d[16] = {
VAR, VAR, VAR, VAR,
VAR, VAR, VAR, VAR,
VAR, VAR, VAR, VAR,
NIL, NIL, NIL, ONE
};
static int m_3d_no_rot[16] = {
VAR, NIL, NIL, VAR,
NIL, VAR, NIL, VAR,
NIL, NIL, VAR, VAR,
NIL, NIL, NIL, ONE
};
static int m_perspective[16] = {
VAR, NIL, VAR, NIL,
NIL, VAR, VAR, NIL,
NIL, NIL, VAR, VAR,
NIL, NIL, NEG, NIL
};
static int *templates[7] = {
m_general,
m_identity,
m_3d_no_rot,
m_perspective,
m_2d,
m_2d_no_rot,
m_3d
};
static int mtypes[7] = {
MATRIX_GENERAL,
MATRIX_IDENTITY,
MATRIX_3D_NO_ROT,
MATRIX_PERSPECTIVE,
MATRIX_2D,
MATRIX_2D_NO_ROT,
MATRIX_3D
};
static char *mstrings[7] = {
"MATRIX_GENERAL",
"MATRIX_IDENTITY",
"MATRIX_3D_NO_ROT",
"MATRIX_PERSPECTIVE",
"MATRIX_2D",
"MATRIX_2D_NO_ROT",
"MATRIX_3D"
};
 
 
/* =============================================================
* Reference transformations
*/
 
static void ref_transform( GLvector4f *dst,
const GLmatrix *mat,
const GLvector4f *src )
{
GLuint i;
GLfloat *s = (GLfloat *)src->start;
GLfloat (*d)[4] = (GLfloat (*)[4])dst->start;
const GLfloat *m = mat->m;
 
for ( i = 0 ; i < src->count ; i++ ) {
TRANSFORM_POINT( d[i], m, s );
s = (GLfloat *)((char *)s + src->stride);
}
}
 
 
/* =============================================================
* Vertex transformation tests
*/
 
static void init_matrix( GLfloat *m )
{
m[0] = 63.0; m[4] = 43.0; m[ 8] = 29.0; m[12] = 43.0;
m[1] = 55.0; m[5] = 17.0; m[ 9] = 31.0; m[13] = 7.0;
m[2] = 44.0; m[6] = 9.0; m[10] = 7.0; m[14] = 3.0;
m[3] = 11.0; m[7] = 23.0; m[11] = 91.0; m[15] = 9.0;
}
 
static GLfloat s[TEST_COUNT][4] ALIGN16;
static GLfloat d[TEST_COUNT][4] ALIGN16;
static GLfloat r[TEST_COUNT][4] ALIGN16;
 
static int test_transform_function( transform_func func, int psize,
int mtype, long *cycles )
{
GLvector4f source[1], dest[1], ref[1];
GLmatrix mat[1];
GLfloat *m;
int i, j;
#ifdef RUN_DEBUG_BENCHMARK
int cycle_i; /* the counter for the benchmarks we run */
#endif
 
(void) cycles;
 
if ( psize > 4 ) {
_mesa_problem( NULL, "test_transform_function called with psize > 4\n" );
return 0;
}
 
mat->m = (GLfloat *) ALIGN_MALLOC( 16 * sizeof(GLfloat), 16 );
mat->type = mtypes[mtype];
 
m = mat->m;
ASSERT( ((GLuint)m & 15) == 0 );
 
init_matrix( m );
 
for ( i = 0 ; i < 4 ; i++ ) {
for ( j = 0 ; j < 4 ; j++ ) {
switch ( templates[mtype][i * 4 + j] ) {
case NIL:
m[j * 4 + i] = 0.0;
break;
case ONE:
m[j * 4 + i] = 1.0;
break;
case NEG:
m[j * 4 + i] = -1.0;
break;
case VAR:
break;
default:
abort();
}
}
}
 
for ( i = 0 ; i < TEST_COUNT ; i++) {
ASSIGN_4V( d[i], 0.0, 0.0, 0.0, 1.0 );
ASSIGN_4V( s[i], 0.0, 0.0, 0.0, 1.0 );
for ( j = 0 ; j < psize ; j++ )
s[i][j] = rnd();
}
 
source->data = (GLfloat(*)[4])s;
source->start = (GLfloat *)s;
source->count = TEST_COUNT;
source->stride = sizeof(s[0]);
source->size = 4;
source->flags = 0;
 
dest->data = (GLfloat(*)[4])d;
dest->start = (GLfloat *)d;
dest->count = TEST_COUNT;
dest->stride = sizeof(float[4]);
dest->size = 0;
dest->flags = 0;
 
ref->data = (GLfloat(*)[4])r;
ref->start = (GLfloat *)r;
ref->count = TEST_COUNT;
ref->stride = sizeof(float[4]);
ref->size = 0;
ref->flags = 0;
 
ref_transform( ref, mat, source );
 
if ( mesa_profile ) {
BEGIN_RACE( *cycles );
func( dest, mat->m, source );
END_RACE( *cycles );
}
else {
func( dest, mat->m, source );
}
 
for ( i = 0 ; i < TEST_COUNT ; i++ ) {
for ( j = 0 ; j < 4 ; j++ ) {
if ( significand_match( d[i][j], r[i][j] ) < REQUIRED_PRECISION ) {
_mesa_printf(NULL, "-----------------------------\n" );
_mesa_printf(NULL, "(i = %i, j = %i)\n", i, j );
_mesa_printf(NULL, "%f \t %f \t [diff = %e - %i bit missed]\n",
d[i][0], r[i][0], r[i][0]-d[i][0],
MAX_PRECISION - significand_match( d[i][0], r[i][0] ) );
_mesa_printf(NULL, "%f \t %f \t [diff = %e - %i bit missed]\n",
d[i][1], r[i][1], r[i][1]-d[i][1],
MAX_PRECISION - significand_match( d[i][1], r[i][1] ) );
_mesa_printf(NULL, "%f \t %f \t [diff = %e - %i bit missed]\n",
d[i][2], r[i][2], r[i][2]-d[i][2],
MAX_PRECISION - significand_match( d[i][2], r[i][2] ) );
_mesa_printf(NULL, "%f \t %f \t [diff = %e - %i bit missed]\n",
d[i][3], r[i][3], r[i][3]-d[i][3],
MAX_PRECISION - significand_match( d[i][3], r[i][3] ) );
return 0;
}
}
}
 
ALIGN_FREE( mat->m );
return 1;
}
 
void _math_test_all_transform_functions( char *description )
{
int psize, mtype;
long benchmark_tab[4][7];
static int first_time = 1;
 
if ( first_time ) {
first_time = 0;
mesa_profile = getenv( "MESA_PROFILE" );
}
 
#ifdef RUN_DEBUG_BENCHMARK
if ( mesa_profile ) {
if ( !counter_overhead ) {
INIT_COUNTER();
_mesa_printf(NULL, "counter overhead: %ld cycles\n\n", counter_overhead );
}
_mesa_printf(NULL, "transform results after hooking in %s functions:\n", description );
}
#endif
 
#ifdef RUN_DEBUG_BENCHMARK
if ( mesa_profile ) {
_mesa_printf(NULL, "\n" );
for ( psize = 1 ; psize <= 4 ; psize++ ) {
_mesa_printf(NULL, " p%d\t", psize );
}
_mesa_printf(NULL, "\n--------------------------------------------------------\n" );
}
#endif
 
for ( mtype = 0 ; mtype < 7 ; mtype++ ) {
for ( psize = 1 ; psize <= 4 ; psize++ ) {
transform_func func = _mesa_transform_tab[psize][mtypes[mtype]];
long *cycles = &(benchmark_tab[psize-1][mtype]);
 
if ( test_transform_function( func, psize, mtype, cycles ) == 0 ) {
char buf[100];
_mesa_sprintf(NULL, buf, "_mesa_transform_tab[0][%d][%s] failed test (%s)",
psize, mstrings[mtype], description );
_mesa_problem( NULL, buf );
}
#ifdef RUN_DEBUG_BENCHMARK
if ( mesa_profile )
_mesa_printf(NULL, " %li\t", benchmark_tab[psize-1][mtype] );
#endif
}
#ifdef RUN_DEBUG_BENCHMARK
if ( mesa_profile )
_mesa_printf(NULL, " | [%s]\n", mstrings[mtype] );
#endif
}
#ifdef RUN_DEBUG_BENCHMARK
if ( mesa_profile )
_mesa_printf(NULL, "\n" );
#endif
}
 
 
#endif /* DEBUG */
/shark/trunk/ports/mesa/src/math/m_vector.c
0,0 → 1,430
/* $Id: m_vector.c,v 1.1 2003-02-28 11:48:05 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
/*
* New (3.1) transformation code written by Keith Whitwell.
*/
 
 
#include "glheader.h"
#include "imports.h"
#include "macros.h"
#include "imports.h"
 
#include "m_vector.h"
 
 
 
/*
* Given a vector [count][4] of floats, set all the [][elt] values
* to 0 (if elt = 0, 1, 2) or 1.0 (if elt = 3).
*/
void _mesa_vector4f_clean_elem( GLvector4f *vec, GLuint count, GLuint elt )
{
static const GLubyte elem_bits[4] = {
VEC_DIRTY_0,
VEC_DIRTY_1,
VEC_DIRTY_2,
VEC_DIRTY_3
};
static const GLfloat clean[4] = { 0, 0, 0, 1 };
const GLfloat v = clean[elt];
GLfloat (*data)[4] = (GLfloat (*)[4])vec->start;
GLuint i;
 
for (i = 0 ; i < count ; i++)
data[i][elt] = v;
 
vec->flags &= ~elem_bits[elt];
}
 
static const GLubyte size_bits[5] = {
0,
VEC_SIZE_1,
VEC_SIZE_2,
VEC_SIZE_3,
VEC_SIZE_4,
};
 
 
 
/*
* Initialize GLvector objects.
* Input: v - the vector object to initialize.
* flags - bitwise-OR of VEC_* flags
* storage - pointer to storage for the vector's data
*/
 
 
void _mesa_vector4f_init( GLvector4f *v, GLuint flags, GLfloat (*storage)[4] )
{
v->stride = 4 * sizeof(GLfloat);
v->size = 2; /* may change: 2-4 for vertices and 1-4 for texcoords */
v->data = storage;
v->start = (GLfloat *) storage;
v->count = 0;
v->flags = size_bits[4] | flags ;
}
 
void _mesa_vector3f_init( GLvector3f *v, GLuint flags, GLfloat (*storage)[3] )
{
v->stride = 3 * sizeof(GLfloat);
v->data = storage;
v->start = (GLfloat *) storage;
v->count = 0;
v->flags = flags ;
}
 
void _mesa_vector1f_init( GLvector1f *v, GLuint flags, GLfloat *storage )
{
v->stride = 1*sizeof(GLfloat);
v->data = storage;
v->start = (GLfloat *)storage;
v->count = 0;
v->flags = flags ;
}
 
void _mesa_vector4ub_init( GLvector4ub *v, GLuint flags, GLubyte (*storage)[4] )
{
v->stride = 4 * sizeof(GLubyte);
v->data = storage;
v->start = (GLubyte *) storage;
v->count = 0;
v->flags = flags ;
}
 
void _mesa_vector4chan_init( GLvector4chan *v, GLuint flags, GLchan (*storage)[4] )
{
v->stride = 4 * sizeof(GLchan);
v->data = storage;
v->start = (GLchan *) storage;
v->count = 0;
v->flags = flags ;
}
 
void _mesa_vector4us_init( GLvector4us *v, GLuint flags, GLushort (*storage)[4] )
{
v->stride = 4 * sizeof(GLushort);
v->data = storage;
v->start = (GLushort *) storage;
v->count = 0;
v->flags = flags ;
}
 
void _mesa_vector1ub_init( GLvector1ub *v, GLuint flags, GLubyte *storage )
{
v->stride = 1 * sizeof(GLubyte);
v->data = storage;
v->start = (GLubyte *) storage;
v->count = 0;
v->flags = flags ;
}
 
void _mesa_vector1ui_init( GLvector1ui *v, GLuint flags, GLuint *storage )
{
v->stride = 1 * sizeof(GLuint);
v->data = storage;
v->start = (GLuint *) storage;
v->count = 0;
v->flags = flags ;
}
 
 
/*
* Initialize GLvector objects and allocate storage.
* Input: v - the vector object
* sz - unused????
* flags - bitwise-OR of VEC_* flags
* count - number of elements to allocate in vector
* alignment - desired memory alignment for the data (in bytes)
*/
 
 
void _mesa_vector4f_alloc( GLvector4f *v, GLuint flags, GLuint count,
GLuint alignment )
{
v->stride = 4 * sizeof(GLfloat);
v->size = 2;
v->storage = ALIGN_MALLOC( count * 4 * sizeof(GLfloat), alignment );
v->start = (GLfloat *) v->storage;
v->data = (GLfloat (*)[4]) v->storage;
v->count = 0;
v->flags = size_bits[4] | flags | VEC_MALLOC ;
}
 
void _mesa_vector3f_alloc( GLvector3f *v, GLuint flags, GLuint count,
GLuint alignment )
{
v->stride = 3 * sizeof(GLfloat);
v->storage = ALIGN_MALLOC( count * 3 * sizeof(GLfloat), alignment );
v->start = (GLfloat *) v->storage;
v->data = (GLfloat (*)[3]) v->storage;
v->count = 0;
v->flags = flags | VEC_MALLOC ;
}
 
void _mesa_vector1f_alloc( GLvector1f *v, GLuint flags, GLuint count,
GLuint alignment )
{
v->stride = sizeof(GLfloat);
v->storage = v->start = (GLfloat *)
ALIGN_MALLOC( count * sizeof(GLfloat), alignment );
v->data = v->start;
v->count = 0;
v->flags = flags | VEC_MALLOC ;
}
 
void _mesa_vector4ub_alloc( GLvector4ub *v, GLuint flags, GLuint count,
GLuint alignment )
{
v->stride = 4 * sizeof(GLubyte);
v->storage = ALIGN_MALLOC( count * 4 * sizeof(GLubyte), alignment );
v->start = (GLubyte *) v->storage;
v->data = (GLubyte (*)[4]) v->storage;
v->count = 0;
v->flags = flags | VEC_MALLOC ;
}
 
void _mesa_vector4chan_alloc( GLvector4chan *v, GLuint flags, GLuint count,
GLuint alignment )
{
v->stride = 4 * sizeof(GLchan);
v->storage = ALIGN_MALLOC( count * 4 * sizeof(GLchan), alignment );
v->start = (GLchan *) v->storage;
v->data = (GLchan (*)[4]) v->storage;
v->count = 0;
v->flags = flags | VEC_MALLOC ;
}
 
void _mesa_vector4us_alloc( GLvector4us *v, GLuint flags, GLuint count,
GLuint alignment )
{
v->stride = 4 * sizeof(GLushort);
v->storage = ALIGN_MALLOC( count * 4 * sizeof(GLushort), alignment );
v->start = (GLushort *) v->storage;
v->data = (GLushort (*)[4]) v->storage;
v->count = 0;
v->flags = flags | VEC_MALLOC ;
}
 
void _mesa_vector1ub_alloc( GLvector1ub *v, GLuint flags, GLuint count,
GLuint alignment )
{
v->stride = 1 * sizeof(GLubyte);
v->storage = ALIGN_MALLOC( count * sizeof(GLubyte), alignment );
v->start = (GLubyte *) v->storage;
v->data = (GLubyte *) v->storage;
v->count = 0;
v->flags = flags | VEC_MALLOC ;
}
 
void _mesa_vector1ui_alloc( GLvector1ui *v, GLuint flags, GLuint count,
GLuint alignment )
{
v->stride = 1 * sizeof(GLuint);
v->storage = ALIGN_MALLOC( count * sizeof(GLuint), alignment );
v->start = (GLuint *) v->storage;
v->data = (GLuint *) v->storage;
v->count = 0;
v->flags = flags | VEC_MALLOC ;
}
 
 
 
/*
* Vector deallocation. Free whatever memory is pointed to by the
* vector's storage field if the VEC_MALLOC flag is set.
* DO NOT free the GLvector object itself, though.
*/
 
 
void _mesa_vector4f_free( GLvector4f *v )
{
if (v->flags & VEC_MALLOC) {
ALIGN_FREE( v->storage );
v->data = NULL;
v->start = NULL;
v->storage = NULL;
v->flags &= ~VEC_MALLOC;
}
}
 
void _mesa_vector3f_free( GLvector3f *v )
{
if (v->flags & VEC_MALLOC) {
ALIGN_FREE( v->storage );
v->data = 0;
v->start = 0;
v->storage = 0;
v->flags &= ~VEC_MALLOC;
}
}
 
void _mesa_vector1f_free( GLvector1f *v )
{
if (v->flags & VEC_MALLOC) {
ALIGN_FREE( v->storage );
v->data = NULL;
v->start = NULL;
v->storage = NULL;
v->flags &= ~VEC_MALLOC;
}
}
 
void _mesa_vector4ub_free( GLvector4ub *v )
{
if (v->flags & VEC_MALLOC) {
ALIGN_FREE( v->storage );
v->data = NULL;
v->start = NULL;
v->storage = NULL;
v->flags &= ~VEC_MALLOC;
}
}
 
void _mesa_vector4chan_free( GLvector4chan *v )
{
if (v->flags & VEC_MALLOC) {
ALIGN_FREE( v->storage );
v->data = NULL;
v->start = NULL;
v->storage = NULL;
v->flags &= ~VEC_MALLOC;
}
}
 
void _mesa_vector4us_free( GLvector4us *v )
{
if (v->flags & VEC_MALLOC) {
ALIGN_FREE( v->storage );
v->data = NULL;
v->start = NULL;
v->storage = NULL;
v->flags &= ~VEC_MALLOC;
}
}
 
void _mesa_vector1ub_free( GLvector1ub *v )
{
if (v->flags & VEC_MALLOC) {
ALIGN_FREE( v->storage );
v->data = NULL;
v->start = NULL;
v->storage = NULL;
v->flags &= ~VEC_MALLOC;
}
}
 
void _mesa_vector1ui_free( GLvector1ui *v )
{
if (v->flags & VEC_MALLOC) {
ALIGN_FREE( v->storage );
v->data = NULL;
v->start = NULL;
v->storage = NULL;
v->flags &= ~VEC_MALLOC;
}
}
 
 
/*
* For debugging
*/
void _mesa_vector4f_print( GLvector4f *v, GLubyte *cullmask, GLboolean culling )
{
GLfloat c[4] = { 0, 0, 0, 1 };
const char *templates[5] = {
"%d:\t0, 0, 0, 1\n",
"%d:\t%f, 0, 0, 1\n",
"%d:\t%f, %f, 0, 1\n",
"%d:\t%f, %f, %f, 1\n",
"%d:\t%f, %f, %f, %f\n"
};
 
const char *t = templates[v->size];
GLfloat *d = (GLfloat *)v->data;
GLuint j, i = 0, count;
 
_mesa_printf(NULL, "data-start\n");
for ( ; d != v->start ; STRIDE_F(d, v->stride), i++)
_mesa_printf(NULL, t, i, d[0], d[1], d[2], d[3]);
 
_mesa_printf(NULL, "start-count(%u)\n", v->count);
count = i + v->count;
 
if (culling) {
for ( ; i < count ; STRIDE_F(d, v->stride), i++)
if (cullmask[i])
_mesa_printf(NULL, t, i, d[0], d[1], d[2], d[3]);
}
else {
for ( ; i < count ; STRIDE_F(d, v->stride), i++)
_mesa_printf(NULL, t, i, d[0], d[1], d[2], d[3]);
}
 
for (j = v->size ; j < 4; j++) {
if ((v->flags & (1<<j)) == 0) {
 
_mesa_printf(NULL, "checking col %u is clean as advertised ", j);
 
for (i = 0, d = (GLfloat *) v->data ;
i < count && d[j] == c[j] ;
i++, STRIDE_F(d, v->stride)) {};
 
if (i == count)
_mesa_printf(NULL, " --> ok\n");
else
_mesa_printf(NULL, " --> Failed at %u ******\n", i);
}
}
}
 
 
/*
* For debugging
*/
void _mesa_vector3f_print( GLvector3f *v, GLubyte *cullmask, GLboolean culling )
{
GLfloat *d = (GLfloat *)v->data;
GLuint i = 0, count;
 
_mesa_printf(NULL, "data-start\n");
for ( ; d != v->start ; STRIDE_F(d,v->stride), i++)
_mesa_printf(NULL, "%u:\t%f, %f, %f\n", i, d[0], d[1], d[2]);
 
_mesa_printf(NULL, "start-count(%u)\n", v->count);
count = i + v->count;
 
if (culling) {
for ( ; i < count ; STRIDE_F(d,v->stride), i++)
if (cullmask[i])
_mesa_printf(NULL, "%u:\t%f, %f, %f\n", i, d[0], d[1], d[2]);
}
else {
for ( ; i < count ; STRIDE_F(d,v->stride), i++)
_mesa_printf(NULL, "%u:\t%f, %f, %f\n", i, d[0], d[1], d[2]);
}
}
/shark/trunk/ports/mesa/src/math/m_translate.h
0,0 → 1,99
/* $Id: m_translate.h,v 1.1 2003-02-28 11:48:05 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
 
#ifndef _M_TRANSLATE_H_
#define _M_TRANSLATE_H_
 
#include "config.h"
#include "mtypes.h" /* hack for GLchan */
 
 
 
extern void _math_trans_1f(GLfloat *to,
CONST void *ptr,
GLuint stride,
GLenum type,
GLuint start,
GLuint n );
 
extern void _math_trans_1ui(GLuint *to,
CONST void *ptr,
GLuint stride,
GLenum type,
GLuint start,
GLuint n );
 
extern void _math_trans_1ub(GLubyte *to,
CONST void *ptr,
GLuint stride,
GLenum type,
GLuint start,
GLuint n );
 
extern void _math_trans_4ub(GLubyte (*to)[4],
CONST void *ptr,
GLuint stride,
GLenum type,
GLuint size,
GLuint start,
GLuint n );
 
extern void _math_trans_4chan( GLchan (*to)[4],
CONST void *ptr,
GLuint stride,
GLenum type,
GLuint size,
GLuint start,
GLuint n );
 
extern void _math_trans_4us(GLushort (*to)[4],
CONST void *ptr,
GLuint stride,
GLenum type,
GLuint size,
GLuint start,
GLuint n );
 
extern void _math_trans_4f(GLfloat (*to)[4],
CONST void *ptr,
GLuint stride,
GLenum type,
GLuint size,
GLuint start,
GLuint n );
 
extern void _math_trans_3f(GLfloat (*to)[3],
CONST void *ptr,
GLuint stride,
GLenum type,
GLuint start,
GLuint n );
 
extern void _math_init_translate( void );
 
 
#endif
/shark/trunk/ports/mesa/src/math/m_matrix.c
0,0 → 1,1181
/* $Id: m_matrix.c,v 1.1 2003-02-28 11:48:05 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 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.
*/
 
 
/*
* Matrix operations
*
* NOTES:
* 1. 4x4 transformation matrices are stored in memory in column major order.
* 2. Points/vertices are to be thought of as column vectors.
* 3. Transformation of a point p by a matrix M is: p' = M * p
*/
 
#include "glheader.h"
#include "imports.h"
#include "macros.h"
#include "imports.h"
#include "mmath.h"
 
#include "m_matrix.h"
 
 
static const char *types[] = {
"MATRIX_GENERAL",
"MATRIX_IDENTITY",
"MATRIX_3D_NO_ROT",
"MATRIX_PERSPECTIVE",
"MATRIX_2D",
"MATRIX_2D_NO_ROT",
"MATRIX_3D"
};
 
 
static GLfloat Identity[16] = {
1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0
};
 
 
 
 
/*
* This matmul was contributed by Thomas Malik
*
* Perform a 4x4 matrix multiplication (product = a x b).
* Input: a, b - matrices to multiply
* Output: product - product of a and b
* WARNING: (product != b) assumed
* NOTE: (product == a) allowed
*
* KW: 4*16 = 64 muls
*/
#define A(row,col) a[(col<<2)+row]
#define B(row,col) b[(col<<2)+row]
#define P(row,col) product[(col<<2)+row]
 
static void matmul4( GLfloat *product, const GLfloat *a, const GLfloat *b )
{
GLint i;
for (i = 0; i < 4; i++) {
const GLfloat ai0=A(i,0), ai1=A(i,1), ai2=A(i,2), ai3=A(i,3);
P(i,0) = ai0 * B(0,0) + ai1 * B(1,0) + ai2 * B(2,0) + ai3 * B(3,0);
P(i,1) = ai0 * B(0,1) + ai1 * B(1,1) + ai2 * B(2,1) + ai3 * B(3,1);
P(i,2) = ai0 * B(0,2) + ai1 * B(1,2) + ai2 * B(2,2) + ai3 * B(3,2);
P(i,3) = ai0 * B(0,3) + ai1 * B(1,3) + ai2 * B(2,3) + ai3 * B(3,3);
}
}
 
 
/* Multiply two matrices known to occupy only the top three rows, such
* as typical model matrices, and ortho matrices.
*/
static void matmul34( GLfloat *product, const GLfloat *a, const GLfloat *b )
{
GLint i;
for (i = 0; i < 3; i++) {
const GLfloat ai0=A(i,0), ai1=A(i,1), ai2=A(i,2), ai3=A(i,3);
P(i,0) = ai0 * B(0,0) + ai1 * B(1,0) + ai2 * B(2,0);
P(i,1) = ai0 * B(0,1) + ai1 * B(1,1) + ai2 * B(2,1);
P(i,2) = ai0 * B(0,2) + ai1 * B(1,2) + ai2 * B(2,2);
P(i,3) = ai0 * B(0,3) + ai1 * B(1,3) + ai2 * B(2,3) + ai3;
}
P(3,0) = 0;
P(3,1) = 0;
P(3,2) = 0;
P(3,3) = 1;
}
 
 
#undef A
#undef B
#undef P
 
 
/*
* Multiply a matrix by an array of floats with known properties.
*/
static void matrix_multf( GLmatrix *mat, const GLfloat *m, GLuint flags )
{
mat->flags |= (flags | MAT_DIRTY_TYPE | MAT_DIRTY_INVERSE);
 
if (TEST_MAT_FLAGS(mat, MAT_FLAGS_3D))
matmul34( mat->m, mat->m, m );
else
matmul4( mat->m, mat->m, m );
}
 
 
static void print_matrix_floats( const GLfloat m[16] )
{
int i;
for (i=0;i<4;i++) {
_mesa_debug(NULL,"\t%f %f %f %f\n", m[i], m[4+i], m[8+i], m[12+i] );
}
}
 
void
_math_matrix_print( const GLmatrix *m )
{
_mesa_debug(NULL, "Matrix type: %s, flags: %x\n", types[m->type], m->flags);
print_matrix_floats(m->m);
_mesa_debug(NULL, "Inverse: \n");
if (m->inv) {
GLfloat prod[16];
print_matrix_floats(m->inv);
matmul4(prod, m->m, m->inv);
_mesa_debug(NULL, "Mat * Inverse:\n");
print_matrix_floats(prod);
}
else {
_mesa_debug(NULL, " - not available\n");
}
}
 
 
 
 
#define SWAP_ROWS(a, b) { GLfloat *_tmp = a; (a)=(b); (b)=_tmp; }
#define MAT(m,r,c) (m)[(c)*4+(r)]
 
/*
* 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_general( GLmatrix *mat )
{
const GLfloat *m = mat->m;
GLfloat *out = mat->inv;
GLfloat wtmp[4][8];
GLfloat m0, m1, m2, m3, s;
GLfloat *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.0F/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.0F/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.0F/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.0F/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 SWAP_ROWS
 
 
/* Adapted from graphics gems II.
*/
static GLboolean invert_matrix_3d_general( GLmatrix *mat )
{
const GLfloat *in = mat->m;
GLfloat *out = mat->inv;
GLfloat pos, neg, t;
GLfloat det;
 
/* Calculate the determinant of upper left 3x3 submatrix and
* determine if the matrix is singular.
*/
pos = neg = 0.0;
t = MAT(in,0,0) * MAT(in,1,1) * MAT(in,2,2);
if (t >= 0.0) pos += t; else neg += t;
 
t = MAT(in,1,0) * MAT(in,2,1) * MAT(in,0,2);
if (t >= 0.0) pos += t; else neg += t;
 
t = MAT(in,2,0) * MAT(in,0,1) * MAT(in,1,2);
if (t >= 0.0) pos += t; else neg += t;
 
t = -MAT(in,2,0) * MAT(in,1,1) * MAT(in,0,2);
if (t >= 0.0) pos += t; else neg += t;
 
t = -MAT(in,1,0) * MAT(in,0,1) * MAT(in,2,2);
if (t >= 0.0) pos += t; else neg += t;
 
t = -MAT(in,0,0) * MAT(in,2,1) * MAT(in,1,2);
if (t >= 0.0) pos += t; else neg += t;
 
det = pos + neg;
 
if (det*det < 1e-25)
return GL_FALSE;
 
det = 1.0F / det;
MAT(out,0,0) = ( (MAT(in,1,1)*MAT(in,2,2) - MAT(in,2,1)*MAT(in,1,2) )*det);
MAT(out,0,1) = (- (MAT(in,0,1)*MAT(in,2,2) - MAT(in,2,1)*MAT(in,0,2) )*det);
MAT(out,0,2) = ( (MAT(in,0,1)*MAT(in,1,2) - MAT(in,1,1)*MAT(in,0,2) )*det);
MAT(out,1,0) = (- (MAT(in,1,0)*MAT(in,2,2) - MAT(in,2,0)*MAT(in,1,2) )*det);
MAT(out,1,1) = ( (MAT(in,0,0)*MAT(in,2,2) - MAT(in,2,0)*MAT(in,0,2) )*det);
MAT(out,1,2) = (- (MAT(in,0,0)*MAT(in,1,2) - MAT(in,1,0)*MAT(in,0,2) )*det);
MAT(out,2,0) = ( (MAT(in,1,0)*MAT(in,2,1) - MAT(in,2,0)*MAT(in,1,1) )*det);
MAT(out,2,1) = (- (MAT(in,0,0)*MAT(in,2,1) - MAT(in,2,0)*MAT(in,0,1) )*det);
MAT(out,2,2) = ( (MAT(in,0,0)*MAT(in,1,1) - MAT(in,1,0)*MAT(in,0,1) )*det);
 
/* Do the translation part */
MAT(out,0,3) = - (MAT(in,0,3) * MAT(out,0,0) +
MAT(in,1,3) * MAT(out,0,1) +
MAT(in,2,3) * MAT(out,0,2) );
MAT(out,1,3) = - (MAT(in,0,3) * MAT(out,1,0) +
MAT(in,1,3) * MAT(out,1,1) +
MAT(in,2,3) * MAT(out,1,2) );
MAT(out,2,3) = - (MAT(in,0,3) * MAT(out,2,0) +
MAT(in,1,3) * MAT(out,2,1) +
MAT(in,2,3) * MAT(out,2,2) );
 
return GL_TRUE;
}
 
 
static GLboolean invert_matrix_3d( GLmatrix *mat )
{
const GLfloat *in = mat->m;
GLfloat *out = mat->inv;
 
if (!TEST_MAT_FLAGS(mat, MAT_FLAGS_ANGLE_PRESERVING)) {
return invert_matrix_3d_general( mat );
}
 
if (mat->flags & MAT_FLAG_UNIFORM_SCALE) {
GLfloat scale = (MAT(in,0,0) * MAT(in,0,0) +
MAT(in,0,1) * MAT(in,0,1) +
MAT(in,0,2) * MAT(in,0,2));
 
if (scale == 0.0)
return GL_FALSE;
 
scale = 1.0F / scale;
 
/* Transpose and scale the 3 by 3 upper-left submatrix. */
MAT(out,0,0) = scale * MAT(in,0,0);
MAT(out,1,0) = scale * MAT(in,0,1);
MAT(out,2,0) = scale * MAT(in,0,2);
MAT(out,0,1) = scale * MAT(in,1,0);
MAT(out,1,1) = scale * MAT(in,1,1);
MAT(out,2,1) = scale * MAT(in,1,2);
MAT(out,0,2) = scale * MAT(in,2,0);
MAT(out,1,2) = scale * MAT(in,2,1);
MAT(out,2,2) = scale * MAT(in,2,2);
}
else if (mat->flags & MAT_FLAG_ROTATION) {
/* Transpose the 3 by 3 upper-left submatrix. */
MAT(out,0,0) = MAT(in,0,0);
MAT(out,1,0) = MAT(in,0,1);
MAT(out,2,0) = MAT(in,0,2);
MAT(out,0,1) = MAT(in,1,0);
MAT(out,1,1) = MAT(in,1,1);
MAT(out,2,1) = MAT(in,1,2);
MAT(out,0,2) = MAT(in,2,0);
MAT(out,1,2) = MAT(in,2,1);
MAT(out,2,2) = MAT(in,2,2);
}
else {
/* pure translation */
MEMCPY( out, Identity, sizeof(Identity) );
MAT(out,0,3) = - MAT(in,0,3);
MAT(out,1,3) = - MAT(in,1,3);
MAT(out,2,3) = - MAT(in,2,3);
return GL_TRUE;
}
 
if (mat->flags & MAT_FLAG_TRANSLATION) {
/* Do the translation part */
MAT(out,0,3) = - (MAT(in,0,3) * MAT(out,0,0) +
MAT(in,1,3) * MAT(out,0,1) +
MAT(in,2,3) * MAT(out,0,2) );
MAT(out,1,3) = - (MAT(in,0,3) * MAT(out,1,0) +
MAT(in,1,3) * MAT(out,1,1) +
MAT(in,2,3) * MAT(out,1,2) );
MAT(out,2,3) = - (MAT(in,0,3) * MAT(out,2,0) +
MAT(in,1,3) * MAT(out,2,1) +
MAT(in,2,3) * MAT(out,2,2) );
}
else {
MAT(out,0,3) = MAT(out,1,3) = MAT(out,2,3) = 0.0;
}
 
return GL_TRUE;
}
 
 
 
static GLboolean invert_matrix_identity( GLmatrix *mat )
{
MEMCPY( mat->inv, Identity, sizeof(Identity) );
return GL_TRUE;
}
 
 
static GLboolean invert_matrix_3d_no_rot( GLmatrix *mat )
{
const GLfloat *in = mat->m;
GLfloat *out = mat->inv;
 
if (MAT(in,0,0) == 0 || MAT(in,1,1) == 0 || MAT(in,2,2) == 0 )
return GL_FALSE;
 
MEMCPY( out, Identity, 16 * sizeof(GLfloat) );
MAT(out,0,0) = 1.0F / MAT(in,0,0);
MAT(out,1,1) = 1.0F / MAT(in,1,1);
MAT(out,2,2) = 1.0F / MAT(in,2,2);
 
if (mat->flags & MAT_FLAG_TRANSLATION) {
MAT(out,0,3) = - (MAT(in,0,3) * MAT(out,0,0));
MAT(out,1,3) = - (MAT(in,1,3) * MAT(out,1,1));
MAT(out,2,3) = - (MAT(in,2,3) * MAT(out,2,2));
}
 
return GL_TRUE;
}
 
 
static GLboolean invert_matrix_2d_no_rot( GLmatrix *mat )
{
const GLfloat *in = mat->m;
GLfloat *out = mat->inv;
 
if (MAT(in,0,0) == 0 || MAT(in,1,1) == 0)
return GL_FALSE;
 
MEMCPY( out, Identity, 16 * sizeof(GLfloat) );
MAT(out,0,0) = 1.0F / MAT(in,0,0);
MAT(out,1,1) = 1.0F / MAT(in,1,1);
 
if (mat->flags & MAT_FLAG_TRANSLATION) {
MAT(out,0,3) = - (MAT(in,0,3) * MAT(out,0,0));
MAT(out,1,3) = - (MAT(in,1,3) * MAT(out,1,1));
}
 
return GL_TRUE;
}
 
 
#if 0
/* broken */
static GLboolean invert_matrix_perspective( GLmatrix *mat )
{
const GLfloat *in = mat->m;
GLfloat *out = mat->inv;
 
if (MAT(in,2,3) == 0)
return GL_FALSE;
 
MEMCPY( out, Identity, 16 * sizeof(GLfloat) );
 
MAT(out,0,0) = 1.0F / MAT(in,0,0);
MAT(out,1,1) = 1.0F / MAT(in,1,1);
 
MAT(out,0,3) = MAT(in,0,2);
MAT(out,1,3) = MAT(in,1,2);
 
MAT(out,2,2) = 0;
MAT(out,2,3) = -1;
 
MAT(out,3,2) = 1.0F / MAT(in,2,3);
MAT(out,3,3) = MAT(in,2,2) * MAT(out,3,2);
 
return GL_TRUE;
}
#endif
 
 
typedef GLboolean (*inv_mat_func)( GLmatrix *mat );
 
 
static inv_mat_func inv_mat_tab[7] = {
invert_matrix_general,
invert_matrix_identity,
invert_matrix_3d_no_rot,
#if 0
/* Don't use this function for now - it fails when the projection matrix
* is premultiplied by a translation (ala Chromium's tilesort SPU).
*/
invert_matrix_perspective,
#else
invert_matrix_general,
#endif
invert_matrix_3d, /* lazy! */
invert_matrix_2d_no_rot,
invert_matrix_3d
};
 
 
static GLboolean matrix_invert( GLmatrix *mat )
{
if (inv_mat_tab[mat->type](mat)) {
mat->flags &= ~MAT_FLAG_SINGULAR;
return GL_TRUE;
} else {
mat->flags |= MAT_FLAG_SINGULAR;
MEMCPY( mat->inv, Identity, sizeof(Identity) );
return GL_FALSE;
}
}
 
 
 
 
 
 
/*
* Generate a 4x4 transformation matrix from glRotate parameters, and
* postmultiply the input matrix by it.
* This function contributed by Erich Boleyn (erich@uruk.org).
* Optimizatios contributed by Rudolf Opalla (rudi@khm.de).
*/
void
_math_matrix_rotate( GLmatrix *mat,
GLfloat angle, GLfloat x, GLfloat y, GLfloat z )
{
GLfloat xx, yy, zz, xy, yz, zx, xs, ys, zs, one_c, s, c;
GLfloat m[16];
GLboolean optimized;
 
s = (GLfloat) sin( angle * DEG2RAD );
c = (GLfloat) cos( angle * DEG2RAD );
 
MEMCPY(m, Identity, sizeof(GLfloat)*16);
optimized = GL_FALSE;
 
#define M(row,col) m[col*4+row]
 
if (x == 0.0F) {
if (y == 0.0F) {
if (z != 0.0F) {
optimized = GL_TRUE;
/* rotate only around z-axis */
M(0,0) = c;
M(1,1) = c;
if (z < 0.0F) {
M(0,1) = s;
M(1,0) = -s;
}
else {
M(0,1) = -s;
M(1,0) = s;
}
}
}
else if (z == 0.0F) {
optimized = GL_TRUE;
/* rotate only around y-axis */
M(0,0) = c;
M(2,2) = c;
if (y < 0.0F) {
M(0,2) = -s;
M(2,0) = s;
}
else {
M(0,2) = s;
M(2,0) = -s;
}
}
}
else if (y == 0.0F) {
if (z == 0.0F) {
optimized = GL_TRUE;
/* rotate only around x-axis */
M(1,1) = c;
M(2,2) = c;
if (y < 0.0F) {
M(1,2) = s;
M(2,1) = -s;
}
else {
M(1,2) = -s;
M(2,1) = s;
}
}
}
 
if (!optimized) {
const GLfloat mag = (GLfloat) GL_SQRT(x * x + y * y + z * z);
 
if (mag <= 1.0e-4) {
/* no rotation, leave mat as-is */
return;
}
 
x /= mag;
y /= mag;
z /= mag;
 
 
/*
* Arbitrary axis rotation matrix.
*
* This is composed of 5 matrices, Rz, Ry, T, Ry', Rz', multiplied
* like so: Rz * Ry * T * Ry' * Rz'. T is the final rotation
* (which is about the X-axis), and the two composite transforms
* Ry' * Rz' and Rz * Ry are (respectively) the rotations necessary
* from the arbitrary axis to the X-axis then back. They are
* all elementary rotations.
*
* Rz' is a rotation about the Z-axis, to bring the axis vector
* into the x-z plane. Then Ry' is applied, rotating about the
* Y-axis to bring the axis vector parallel with the X-axis. The
* rotation about the X-axis is then performed. Ry and Rz are
* simply the respective inverse transforms to bring the arbitrary
* axis back to it's original orientation. The first transforms
* Rz' and Ry' are considered inverses, since the data from the
* arbitrary axis gives you info on how to get to it, not how
* to get away from it, and an inverse must be applied.
*
* The basic calculation used is to recognize that the arbitrary
* axis vector (x, y, z), since it is of unit length, actually
* represents the sines and cosines of the angles to rotate the
* X-axis to the same orientation, with theta being the angle about
* Z and phi the angle about Y (in the order described above)
* as follows:
*
* cos ( theta ) = x / sqrt ( 1 - z^2 )
* sin ( theta ) = y / sqrt ( 1 - z^2 )
*
* cos ( phi ) = sqrt ( 1 - z^2 )
* sin ( phi ) = z
*
* Note that cos ( phi ) can further be inserted to the above
* formulas:
*
* cos ( theta ) = x / cos ( phi )
* sin ( theta ) = y / sin ( phi )
*
* ...etc. Because of those relations and the standard trigonometric
* relations, it is pssible to reduce the transforms down to what
* is used below. It may be that any primary axis chosen will give the
* same results (modulo a sign convention) using thie method.
*
* Particularly nice is to notice that all divisions that might
* have caused trouble when parallel to certain planes or
* axis go away with care paid to reducing the expressions.
* After checking, it does perform correctly under all cases, since
* in all the cases of division where the denominator would have
* been zero, the numerator would have been zero as well, giving
* the expected result.
*/
 
xx = x * x;
yy = y * y;
zz = z * z;
xy = x * y;
yz = y * z;
zx = z * x;
xs = x * s;
ys = y * s;
zs = z * s;
one_c = 1.0F - c;
 
/* We already hold the identity-matrix so we can skip some statements */
M(0,0) = (one_c * xx) + c;
M(0,1) = (one_c * xy) - zs;
M(0,2) = (one_c * zx) + ys;
/* M(0,3) = 0.0F; */
 
M(1,0) = (one_c * xy) + zs;
M(1,1) = (one_c * yy) + c;
M(1,2) = (one_c * yz) - xs;
/* M(1,3) = 0.0F; */
 
M(2,0) = (one_c * zx) - ys;
M(2,1) = (one_c * yz) + xs;
M(2,2) = (one_c * zz) + c;
/* M(2,3) = 0.0F; */
 
/*
M(3,0) = 0.0F;
M(3,1) = 0.0F;
M(3,2) = 0.0F;
M(3,3) = 1.0F;
*/
}
#undef M
 
matrix_multf( mat, m, MAT_FLAG_ROTATION );
}
 
 
 
void
_math_matrix_frustum( GLmatrix *mat,
GLfloat left, GLfloat right,
GLfloat bottom, GLfloat top,
GLfloat nearval, GLfloat farval )
{
GLfloat x, y, a, b, c, d;
GLfloat m[16];
 
x = (2.0F*nearval) / (right-left);
y = (2.0F*nearval) / (top-bottom);
a = (right+left) / (right-left);
b = (top+bottom) / (top-bottom);
c = -(farval+nearval) / ( farval-nearval);
d = -(2.0F*farval*nearval) / (farval-nearval); /* error? */
 
#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
 
matrix_multf( mat, m, MAT_FLAG_PERSPECTIVE );
}
 
void
_math_matrix_ortho( GLmatrix *mat,
GLfloat left, GLfloat right,
GLfloat bottom, GLfloat top,
GLfloat nearval, GLfloat farval )
{
GLfloat x, y, z;
GLfloat tx, ty, tz;
GLfloat m[16];
 
x = 2.0F / (right-left);
y = 2.0F / (top-bottom);
z = -2.0F / (farval-nearval);
tx = -(right+left) / (right-left);
ty = -(top+bottom) / (top-bottom);
tz = -(farval+nearval) / (farval-nearval);
 
#define M(row,col) m[col*4+row]
M(0,0) = x; M(0,1) = 0.0F; M(0,2) = 0.0F; M(0,3) = tx;
M(1,0) = 0.0F; M(1,1) = y; M(1,2) = 0.0F; M(1,3) = ty;
M(2,0) = 0.0F; M(2,1) = 0.0F; M(2,2) = z; M(2,3) = tz;
M(3,0) = 0.0F; M(3,1) = 0.0F; M(3,2) = 0.0F; M(3,3) = 1.0F;
#undef M
 
matrix_multf( mat, m, (MAT_FLAG_GENERAL_SCALE|MAT_FLAG_TRANSLATION));
}
 
 
#define ZERO(x) (1<<x)
#define ONE(x) (1<<(x+16))
 
#define MASK_NO_TRX (ZERO(12) | ZERO(13) | ZERO(14))
#define MASK_NO_2D_SCALE ( ONE(0) | ONE(5))
 
#define MASK_IDENTITY ( ONE(0) | ZERO(4) | ZERO(8) | ZERO(12) |\
ZERO(1) | ONE(5) | ZERO(9) | ZERO(13) |\
ZERO(2) | ZERO(6) | ONE(10) | ZERO(14) |\
ZERO(3) | ZERO(7) | ZERO(11) | ONE(15) )
 
#define MASK_2D_NO_ROT ( ZERO(4) | ZERO(8) | \
ZERO(1) | ZERO(9) | \
ZERO(2) | ZERO(6) | ONE(10) | ZERO(14) |\
ZERO(3) | ZERO(7) | ZERO(11) | ONE(15) )
 
#define MASK_2D ( ZERO(8) | \
ZERO(9) | \
ZERO(2) | ZERO(6) | ONE(10) | ZERO(14) |\
ZERO(3) | ZERO(7) | ZERO(11) | ONE(15) )
 
 
#define MASK_3D_NO_ROT ( ZERO(4) | ZERO(8) | \
ZERO(1) | ZERO(9) | \
ZERO(2) | ZERO(6) | \
ZERO(3) | ZERO(7) | ZERO(11) | ONE(15) )
 
#define MASK_3D ( \
\
\
ZERO(3) | ZERO(7) | ZERO(11) | ONE(15) )
 
 
#define MASK_PERSPECTIVE ( ZERO(4) | ZERO(12) |\
ZERO(1) | ZERO(13) |\
ZERO(2) | ZERO(6) | \
ZERO(3) | ZERO(7) | ZERO(15) )
 
#define SQ(x) ((x)*(x))
 
/* Determine type and flags from scratch. This is expensive enough to
* only want to do it once.
*/
static void analyse_from_scratch( GLmatrix *mat )
{
const GLfloat *m = mat->m;
GLuint mask = 0;
GLuint i;
 
for (i = 0 ; i < 16 ; i++) {
if (m[i] == 0.0) mask |= (1<<i);
}
 
if (m[0] == 1.0F) mask |= (1<<16);
if (m[5] == 1.0F) mask |= (1<<21);
if (m[10] == 1.0F) mask |= (1<<26);
if (m[15] == 1.0F) mask |= (1<<31);
 
mat->flags &= ~MAT_FLAGS_GEOMETRY;
 
/* Check for translation - no-one really cares
*/
if ((mask & MASK_NO_TRX) != MASK_NO_TRX)
mat->flags |= MAT_FLAG_TRANSLATION;
 
/* Do the real work
*/
if (mask == (GLuint) MASK_IDENTITY) {
mat->type = MATRIX_IDENTITY;
}
else if ((mask & MASK_2D_NO_ROT) == (GLuint) MASK_2D_NO_ROT) {
mat->type = MATRIX_2D_NO_ROT;
 
if ((mask & MASK_NO_2D_SCALE) != MASK_NO_2D_SCALE)
mat->flags = MAT_FLAG_GENERAL_SCALE;
}
else if ((mask & MASK_2D) == (GLuint) MASK_2D) {
GLfloat mm = DOT2(m, m);
GLfloat m4m4 = DOT2(m+4,m+4);
GLfloat mm4 = DOT2(m,m+4);
 
mat->type = MATRIX_2D;
 
/* Check for scale */
if (SQ(mm-1) > SQ(1e-6) ||
SQ(m4m4-1) > SQ(1e-6))
mat->flags |= MAT_FLAG_GENERAL_SCALE;
 
/* Check for rotation */
if (SQ(mm4) > SQ(1e-6))
mat->flags |= MAT_FLAG_GENERAL_3D;
else
mat->flags |= MAT_FLAG_ROTATION;
 
}
else if ((mask & MASK_3D_NO_ROT) == (GLuint) MASK_3D_NO_ROT) {
mat->type = MATRIX_3D_NO_ROT;
 
/* Check for scale */
if (SQ(m[0]-m[5]) < SQ(1e-6) &&
SQ(m[0]-m[10]) < SQ(1e-6)) {
if (SQ(m[0]-1.0) > SQ(1e-6)) {
mat->flags |= MAT_FLAG_UNIFORM_SCALE;
}
}
else {
mat->flags |= MAT_FLAG_GENERAL_SCALE;
}
}
else if ((mask & MASK_3D) == (GLuint) MASK_3D) {
GLfloat c1 = DOT3(m,m);
GLfloat c2 = DOT3(m+4,m+4);
GLfloat c3 = DOT3(m+8,m+8);
GLfloat d1 = DOT3(m, m+4);
GLfloat cp[3];
 
mat->type = MATRIX_3D;
 
/* Check for scale */
if (SQ(c1-c2) < SQ(1e-6) && SQ(c1-c3) < SQ(1e-6)) {
if (SQ(c1-1.0) > SQ(1e-6))
mat->flags |= MAT_FLAG_UNIFORM_SCALE;
/* else no scale at all */
}
else {
mat->flags |= MAT_FLAG_GENERAL_SCALE;
}
 
/* Check for rotation */
if (SQ(d1) < SQ(1e-6)) {
CROSS3( cp, m, m+4 );
SUB_3V( cp, cp, (m+8) );
if (LEN_SQUARED_3FV(cp) < SQ(1e-6))
mat->flags |= MAT_FLAG_ROTATION;
else
mat->flags |= MAT_FLAG_GENERAL_3D;
}
else {
mat->flags |= MAT_FLAG_GENERAL_3D; /* shear, etc */
}
}
else if ((mask & MASK_PERSPECTIVE) == MASK_PERSPECTIVE && m[11]==-1.0F) {
mat->type = MATRIX_PERSPECTIVE;
mat->flags |= MAT_FLAG_GENERAL;
}
else {
mat->type = MATRIX_GENERAL;
mat->flags |= MAT_FLAG_GENERAL;
}
}
 
 
/* Analyse a matrix given that its flags are accurate - this is the
* more common operation, hopefully.
*/
static void analyse_from_flags( GLmatrix *mat )
{
const GLfloat *m = mat->m;
 
if (TEST_MAT_FLAGS(mat, 0)) {
mat->type = MATRIX_IDENTITY;
}
else if (TEST_MAT_FLAGS(mat, (MAT_FLAG_TRANSLATION |
MAT_FLAG_UNIFORM_SCALE |
MAT_FLAG_GENERAL_SCALE))) {
if ( m[10]==1.0F && m[14]==0.0F ) {
mat->type = MATRIX_2D_NO_ROT;
}
else {
mat->type = MATRIX_3D_NO_ROT;
}
}
else if (TEST_MAT_FLAGS(mat, MAT_FLAGS_3D)) {
if ( m[ 8]==0.0F
&& m[ 9]==0.0F
&& m[2]==0.0F && m[6]==0.0F && m[10]==1.0F && m[14]==0.0F) {
mat->type = MATRIX_2D;
}
else {
mat->type = MATRIX_3D;
}
}
else if ( m[4]==0.0F && m[12]==0.0F
&& m[1]==0.0F && m[13]==0.0F
&& m[2]==0.0F && m[6]==0.0F
&& m[3]==0.0F && m[7]==0.0F && m[11]==-1.0F && m[15]==0.0F) {
mat->type = MATRIX_PERSPECTIVE;
}
else {
mat->type = MATRIX_GENERAL;
}
}
 
 
void
_math_matrix_analyse( GLmatrix *mat )
{
if (mat->flags & MAT_DIRTY_TYPE) {
if (mat->flags & MAT_DIRTY_FLAGS)
analyse_from_scratch( mat );
else
analyse_from_flags( mat );
}
 
if (mat->inv && (mat->flags & MAT_DIRTY_INVERSE)) {
matrix_invert( mat );
}
 
mat->flags &= ~(MAT_DIRTY_FLAGS|
MAT_DIRTY_TYPE|
MAT_DIRTY_INVERSE);
}
 
 
void
_math_matrix_copy( GLmatrix *to, const GLmatrix *from )
{
MEMCPY( to->m, from->m, sizeof(Identity) );
to->flags = from->flags;
to->type = from->type;
 
if (to->inv != 0) {
if (from->inv == 0) {
matrix_invert( to );
}
else {
MEMCPY(to->inv, from->inv, sizeof(GLfloat)*16);
}
}
}
 
 
void
_math_matrix_scale( GLmatrix *mat, GLfloat x, GLfloat y, GLfloat z )
{
GLfloat *m = mat->m;
m[0] *= x; m[4] *= y; m[8] *= z;
m[1] *= x; m[5] *= y; m[9] *= z;
m[2] *= x; m[6] *= y; m[10] *= z;
m[3] *= x; m[7] *= y; m[11] *= z;
 
if (fabs(x - y) < 1e-8 && fabs(x - z) < 1e-8)
mat->flags |= MAT_FLAG_UNIFORM_SCALE;
else
mat->flags |= MAT_FLAG_GENERAL_SCALE;
 
mat->flags |= (MAT_DIRTY_TYPE |
MAT_DIRTY_INVERSE);
}
 
 
void
_math_matrix_translate( GLmatrix *mat, GLfloat x, GLfloat y, GLfloat z )
{
GLfloat *m = mat->m;
m[12] = m[0] * x + m[4] * y + m[8] * z + m[12];
m[13] = m[1] * x + m[5] * y + m[9] * z + m[13];
m[14] = m[2] * x + m[6] * y + m[10] * z + m[14];
m[15] = m[3] * x + m[7] * y + m[11] * z + m[15];
 
mat->flags |= (MAT_FLAG_TRANSLATION |
MAT_DIRTY_TYPE |
MAT_DIRTY_INVERSE);
}
 
 
void
_math_matrix_loadf( GLmatrix *mat, const GLfloat *m )
{
MEMCPY( mat->m, m, 16*sizeof(GLfloat) );
mat->flags = (MAT_FLAG_GENERAL | MAT_DIRTY);
}
 
void
_math_matrix_ctr( GLmatrix *m )
{
m->m = (GLfloat *) ALIGN_MALLOC( 16 * sizeof(GLfloat), 16 );
if (m->m)
MEMCPY( m->m, Identity, sizeof(Identity) );
m->inv = NULL;
m->type = MATRIX_IDENTITY;
m->flags = 0;
}
 
void
_math_matrix_dtr( GLmatrix *m )
{
if (m->m) {
ALIGN_FREE( m->m );
m->m = NULL;
}
if (m->inv) {
ALIGN_FREE( m->inv );
m->inv = NULL;
}
}
 
 
void
_math_matrix_alloc_inv( GLmatrix *m )
{
if (!m->inv) {
m->inv = (GLfloat *) ALIGN_MALLOC( 16 * sizeof(GLfloat), 16 );
if (m->inv)
MEMCPY( m->inv, Identity, 16 * sizeof(GLfloat) );
}
}
 
 
void
_math_matrix_mul_matrix( GLmatrix *dest, const GLmatrix *a, const GLmatrix *b )
{
dest->flags = (a->flags |
b->flags |
MAT_DIRTY_TYPE |
MAT_DIRTY_INVERSE);
 
if (TEST_MAT_FLAGS(dest, MAT_FLAGS_3D))
matmul34( dest->m, a->m, b->m );
else
matmul4( dest->m, a->m, b->m );
}
 
 
void
_math_matrix_mul_floats( GLmatrix *dest, const GLfloat *m )
{
dest->flags |= (MAT_FLAG_GENERAL |
MAT_DIRTY_TYPE |
MAT_DIRTY_INVERSE);
 
matmul4( dest->m, dest->m, m );
}
 
void
_math_matrix_set_identity( GLmatrix *mat )
{
MEMCPY( mat->m, Identity, 16*sizeof(GLfloat) );
 
if (mat->inv)
MEMCPY( mat->inv, Identity, 16*sizeof(GLfloat) );
 
mat->type = MATRIX_IDENTITY;
mat->flags &= ~(MAT_DIRTY_FLAGS|
MAT_DIRTY_TYPE|
MAT_DIRTY_INVERSE);
}
 
 
 
void
_math_transposef( GLfloat to[16], const GLfloat from[16] )
{
to[0] = from[0];
to[1] = from[4];
to[2] = from[8];
to[3] = from[12];
to[4] = from[1];
to[5] = from[5];
to[6] = from[9];
to[7] = from[13];
to[8] = from[2];
to[9] = from[6];
to[10] = from[10];
to[11] = from[14];
to[12] = from[3];
to[13] = from[7];
to[14] = from[11];
to[15] = from[15];
}
 
 
void
_math_transposed( GLdouble to[16], const GLdouble from[16] )
{
to[0] = from[0];
to[1] = from[4];
to[2] = from[8];
to[3] = from[12];
to[4] = from[1];
to[5] = from[5];
to[6] = from[9];
to[7] = from[13];
to[8] = from[2];
to[9] = from[6];
to[10] = from[10];
to[11] = from[14];
to[12] = from[3];
to[13] = from[7];
to[14] = from[11];
to[15] = from[15];
}
 
void
_math_transposefd( GLfloat to[16], const GLdouble from[16] )
{
to[0] = (GLfloat) from[0];
to[1] = (GLfloat) from[4];
to[2] = (GLfloat) from[8];
to[3] = (GLfloat) from[12];
to[4] = (GLfloat) from[1];
to[5] = (GLfloat) from[5];
to[6] = (GLfloat) from[9];
to[7] = (GLfloat) from[13];
to[8] = (GLfloat) from[2];
to[9] = (GLfloat) from[6];
to[10] = (GLfloat) from[10];
to[11] = (GLfloat) from[14];
to[12] = (GLfloat) from[3];
to[13] = (GLfloat) from[7];
to[14] = (GLfloat) from[11];
to[15] = (GLfloat) from[15];
}
/shark/trunk/ports/mesa/src/math/m_vector.h
0,0 → 1,222
/* $Id: m_vector.h,v 1.1 2003-02-28 11:48:05 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
/*
* New (3.1) transformation code written by Keith Whitwell.
*/
 
 
#ifndef _M_VECTOR_H_
#define _M_VECTOR_H_
 
#include "glheader.h"
#include "mtypes.h" /* hack for GLchan */
 
 
#define VEC_DIRTY_0 0x1
#define VEC_DIRTY_1 0x2
#define VEC_DIRTY_2 0x4
#define VEC_DIRTY_3 0x8
#define VEC_MALLOC 0x10 /* storage field points to self-allocated mem*/
#define VEC_NOT_WRITEABLE 0x40 /* writable elements to hold clipped data */
#define VEC_BAD_STRIDE 0x100 /* matches tnl's prefered stride */
 
 
#define VEC_SIZE_1 VEC_DIRTY_0
#define VEC_SIZE_2 (VEC_DIRTY_0|VEC_DIRTY_1)
#define VEC_SIZE_3 (VEC_DIRTY_0|VEC_DIRTY_1|VEC_DIRTY_2)
#define VEC_SIZE_4 (VEC_DIRTY_0|VEC_DIRTY_1|VEC_DIRTY_2|VEC_DIRTY_3)
 
 
 
/* Wrap all the information about vectors up in a struct. Has
* additional fields compared to the other vectors to help us track of
* different vertex sizes, and whether we need to clean columns out
* because they contain non-(0,0,0,1) values.
*
* The start field is used to reserve data for copied vertices at the
* end of _mesa_transform_vb, and avoids the need for a multiplication in
* the transformation routines.
*/
typedef struct {
GLfloat (*data)[4]; /* may be malloc'd or point to client data */
GLfloat *start; /* points somewhere inside of <data> */
GLuint count; /* size of the vector (in elements) */
GLuint stride; /* stride from one element to the next (in bytes) */
GLuint size; /* 2-4 for vertices and 1-4 for texcoords */
GLuint flags; /* which columns are dirty */
void *storage; /* self-allocated storage */
} GLvector4f;
 
 
extern void _mesa_vector4f_init( GLvector4f *v, GLuint flags,
GLfloat (*storage)[4] );
extern void _mesa_vector4f_alloc( GLvector4f *v, GLuint flags,
GLuint count, GLuint alignment );
extern void _mesa_vector4f_free( GLvector4f *v );
extern void _mesa_vector4f_print( GLvector4f *v, GLubyte *, GLboolean );
extern void _mesa_vector4f_clean_elem( GLvector4f *vec, GLuint nr, GLuint elt );
 
 
/* Could use a single vector type for normals and vertices, but
* this way avoids some casts.
*/
typedef struct {
GLfloat (*data)[3];
GLfloat *start;
GLuint count;
GLuint stride;
GLuint flags;
void *storage;
} GLvector3f;
 
extern void _mesa_vector3f_init( GLvector3f *v, GLuint flags, GLfloat (*)[3] );
extern void _mesa_vector3f_alloc( GLvector3f *v, GLuint flags, GLuint count,
GLuint alignment );
extern void _mesa_vector3f_free( GLvector3f *v );
extern void _mesa_vector3f_print( GLvector3f *v, GLubyte *, GLboolean );
 
 
typedef struct {
GLfloat *data;
GLfloat *start;
GLuint count;
GLuint stride;
GLuint flags;
void *storage;
} GLvector1f;
 
extern void _mesa_vector1f_free( GLvector1f *v );
extern void _mesa_vector1f_init( GLvector1f *v, GLuint flags, GLfloat * );
extern void _mesa_vector1f_alloc( GLvector1f *v, GLuint flags, GLuint count,
GLuint alignment );
 
 
/* For 4ub rgba values.
*/
typedef struct {
GLubyte (*data)[4];
GLubyte *start;
GLuint count;
GLuint stride;
GLuint flags;
void *storage;
} GLvector4ub;
 
extern void _mesa_vector4ub_init( GLvector4ub *v, GLuint flags,
GLubyte (*storage)[4] );
extern void _mesa_vector4ub_alloc( GLvector4ub *v, GLuint flags, GLuint count,
GLuint alignment );
extern void _mesa_vector4ub_free( GLvector4ub * );
 
 
/* For 4 * GLchan values.
*/
typedef struct {
GLchan (*data)[4];
GLchan *start;
GLuint count;
GLuint stride;
GLuint flags;
void *storage;
} GLvector4chan;
 
extern void _mesa_vector4chan_init( GLvector4chan *v, GLuint flags,
GLchan (*storage)[4] );
extern void _mesa_vector4chan_alloc( GLvector4chan *v, GLuint flags, GLuint count,
GLuint alignment );
extern void _mesa_vector4chan_free( GLvector4chan * );
 
 
 
 
/* For 4 * GLushort rgba values.
*/
typedef struct {
GLushort (*data)[4];
GLushort *start;
GLuint count;
GLuint stride;
GLuint flags;
void *storage;
} GLvector4us;
 
extern void _mesa_vector4us_init( GLvector4us *v, GLuint flags,
GLushort (*storage)[4] );
extern void _mesa_vector4us_alloc( GLvector4us *v, GLuint flags, GLuint count,
GLuint alignment );
extern void _mesa_vector4us_free( GLvector4us * );
 
 
 
 
/* For 1ub values, eg edgeflag.
*/
typedef struct {
GLubyte *data;
GLubyte *start;
GLuint count;
GLuint stride;
GLuint flags;
void *storage;
} GLvector1ub;
 
extern void _mesa_vector1ub_init( GLvector1ub *v, GLuint flags, GLubyte *storage);
extern void _mesa_vector1ub_alloc( GLvector1ub *v, GLuint flags, GLuint count,
GLuint alignment );
extern void _mesa_vector1ub_free( GLvector1ub * );
 
 
 
 
/* For, eg Index, Array element.
*/
typedef struct {
GLuint *data;
GLuint *start;
GLuint count;
GLuint stride;
GLuint flags;
void *storage;
} GLvector1ui;
 
extern void _mesa_vector1ui_init( GLvector1ui *v, GLuint flags, GLuint *storage );
extern void _mesa_vector1ui_alloc( GLvector1ui *v, GLuint flags, GLuint count,
GLuint alignment );
extern void _mesa_vector1ui_free( GLvector1ui * );
 
 
 
/*
* Given vector <v>, return a pointer (cast to <type *> to the <i>-th element.
*
* End up doing a lot of slow imuls if not careful.
*/
#define VEC_ELT( v, type, i ) \
( (type *) ( ((GLbyte *) ((v)->data)) + (i) * (v)->stride) )
 
 
#endif
/shark/trunk/ports/mesa/src/math/m_matrix.h
0,0 → 1,176
/* $Id: m_matrix.h,v 1.1 2003-02-28 11:48:05 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
 
#ifndef _M_MATRIX_H
#define _M_MATRIX_H
 
 
 
/* Give symbolic names to some of the entries in the matrix to help
* out with the rework of the viewport_map as a matrix transform.
*/
#define MAT_SX 0
#define MAT_SY 5
#define MAT_SZ 10
#define MAT_TX 12
#define MAT_TY 13
#define MAT_TZ 14
 
/*
* Different kinds of 4x4 transformation matrices:
*/
#define MATRIX_GENERAL 0 /* general 4x4 matrix */
#define MATRIX_IDENTITY 1 /* identity matrix */
#define MATRIX_3D_NO_ROT 2 /* ortho projection and others... */
#define MATRIX_PERSPECTIVE 3 /* perspective projection matrix */
#define MATRIX_2D 4 /* 2-D transformation */
#define MATRIX_2D_NO_ROT 5 /* 2-D scale & translate only */
#define MATRIX_3D 6 /* 3-D transformation */
 
#define MAT_FLAG_IDENTITY 0
#define MAT_FLAG_GENERAL 0x1
#define MAT_FLAG_ROTATION 0x2
#define MAT_FLAG_TRANSLATION 0x4
#define MAT_FLAG_UNIFORM_SCALE 0x8
#define MAT_FLAG_GENERAL_SCALE 0x10
#define MAT_FLAG_GENERAL_3D 0x20
#define MAT_FLAG_PERSPECTIVE 0x40
#define MAT_FLAG_SINGULAR 0x80
#define MAT_DIRTY_TYPE 0x100
#define MAT_DIRTY_FLAGS 0x200
#define MAT_DIRTY_INVERSE 0x400
 
#define MAT_FLAGS_ANGLE_PRESERVING (MAT_FLAG_ROTATION | \
MAT_FLAG_TRANSLATION | \
MAT_FLAG_UNIFORM_SCALE)
 
#define MAT_FLAGS_LENGTH_PRESERVING (MAT_FLAG_ROTATION | \
MAT_FLAG_TRANSLATION)
 
#define MAT_FLAGS_3D (MAT_FLAG_ROTATION | \
MAT_FLAG_TRANSLATION | \
MAT_FLAG_UNIFORM_SCALE | \
MAT_FLAG_GENERAL_SCALE | \
MAT_FLAG_GENERAL_3D)
 
#define MAT_FLAGS_GEOMETRY (MAT_FLAG_GENERAL | \
MAT_FLAG_ROTATION | \
MAT_FLAG_TRANSLATION | \
MAT_FLAG_UNIFORM_SCALE | \
MAT_FLAG_GENERAL_SCALE | \
MAT_FLAG_GENERAL_3D | \
MAT_FLAG_PERSPECTIVE | \
MAT_FLAG_SINGULAR)
 
#define MAT_DIRTY (MAT_DIRTY_TYPE | \
MAT_DIRTY_FLAGS | \
MAT_DIRTY_INVERSE)
 
#define TEST_MAT_FLAGS(mat, a) \
((MAT_FLAGS_GEOMETRY & (~(a)) & ((mat)->flags) ) == 0)
 
 
typedef struct {
GLfloat *m; /* 16-byte aligned */
GLfloat *inv; /* optional, 16-byte aligned */
GLuint flags;
GLuint type; /* one of the MATRIX_* values */
} GLmatrix;
 
 
 
 
extern void
_math_matrix_ctr( GLmatrix *m );
 
extern void
_math_matrix_dtr( GLmatrix *m );
 
extern void
_math_matrix_alloc_inv( GLmatrix *m );
 
extern void
_math_matrix_mul_matrix( GLmatrix *dest, const GLmatrix *a, const GLmatrix *b );
 
extern void
_math_matrix_mul_floats( GLmatrix *dest, const GLfloat *b );
 
extern void
_math_matrix_loadf( GLmatrix *mat, const GLfloat *m );
 
extern void
_math_matrix_translate( GLmatrix *mat, GLfloat x, GLfloat y, GLfloat z );
 
extern void
_math_matrix_rotate( GLmatrix *m, GLfloat angle,
GLfloat x, GLfloat y, GLfloat z );
 
extern void
_math_matrix_scale( GLmatrix *mat, GLfloat x, GLfloat y, GLfloat z );
 
extern void
_math_matrix_ortho( GLmatrix *mat,
GLfloat left, GLfloat right,
GLfloat bottom, GLfloat top,
GLfloat nearval, GLfloat farval );
 
extern void
_math_matrix_frustum( GLmatrix *mat,
GLfloat left, GLfloat right,
GLfloat bottom, GLfloat top,
GLfloat nearval, GLfloat farval );
 
extern void
_math_matrix_set_identity( GLmatrix *dest );
 
extern void
_math_matrix_copy( GLmatrix *to, const GLmatrix *from );
 
extern void
_math_matrix_analyse( GLmatrix *mat );
 
extern void
_math_matrix_print( const GLmatrix *m );
 
 
 
 
/* Related functions that don't actually operate on GLmatrix structs:
*/
extern void
_math_transposef( GLfloat to[16], const GLfloat from[16] );
 
extern void
_math_transposed( GLdouble to[16], const GLdouble from[16] );
 
extern void
_math_transposefd( GLfloat to[16], const GLdouble from[16] );
 
 
 
 
#endif
/shark/trunk/ports/mesa/src/math/m_trans_tmp.h
0,0 → 1,236
/* $Id: m_trans_tmp.h,v 1.1 2003-02-28 11:48:05 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.0.2
*
* Copyright (C) 1999-2002 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.
*/
 
/*
* New (3.1) transformation code written by Keith Whitwell.
*/
 
 
/* KW: This file also included by tnl/trans_elt.c to build code
* specific to the implementation of array-elements in the
* tnl module.
*/
 
 
#ifdef DEST_4F
static void DEST_4F( GLfloat (*t)[4],
CONST void *ptr,
GLuint stride,
ARGS )
{
const GLubyte *f = (GLubyte *) ptr + SRC_START * stride;
const GLubyte *first = f;
GLuint i;
 
(void) first;
(void) start;
for (i = DST_START ; i < n ; i++, NEXT_F) {
CHECK {
NEXT_F2;
if (SZ >= 1) t[i][0] = TRX_4F(f, 0);
if (SZ >= 2) t[i][1] = TRX_4F(f, 1);
if (SZ >= 3) t[i][2] = TRX_4F(f, 2);
if (SZ == 4) t[i][3] = TRX_4F(f, 3); else t[i][3] = 1.0;
}
}
}
#endif
 
 
#ifdef DEST_3F
static void DEST_3F( GLfloat (*t)[3],
CONST void *ptr,
GLuint stride,
ARGS )
{
const GLubyte *f = (GLubyte *) ptr + SRC_START * stride;
const GLubyte *first = f;
GLuint i;
(void) first;
(void) start;
for (i = DST_START ; i < n ; i++, NEXT_F) {
CHECK {
NEXT_F2;
t[i][0] = TRX_3F(f, 0);
t[i][1] = TRX_3F(f, 1);
t[i][2] = TRX_3F(f, 2);
}
}
}
#endif
 
#ifdef DEST_1F
static void DEST_1F( GLfloat *t,
CONST void *ptr,
GLuint stride,
ARGS )
{
const GLubyte *f = (GLubyte *) ptr + SRC_START * stride;
const GLubyte *first = f;
GLuint i;
(void) first;
(void) start;
for (i = DST_START ; i < n ; i++, NEXT_F) {
CHECK {
NEXT_F2;
t[i] = TRX_1F(f, 0);
}
}
}
#endif
 
#ifdef DEST_4UB
static void DEST_4UB( GLubyte (*t)[4],
CONST void *ptr,
GLuint stride,
ARGS )
{
const GLubyte *f = (GLubyte *) ptr + SRC_START * stride;
const GLubyte *first = f;
GLuint i;
(void) start;
(void) first;
for (i = DST_START ; i < n ; i++, NEXT_F) {
CHECK {
NEXT_F2;
if (SZ >= 1) TRX_UB(t[i][0], f, 0);
if (SZ >= 2) TRX_UB(t[i][1], f, 1);
if (SZ >= 3) TRX_UB(t[i][2], f, 2);
if (SZ == 4) TRX_UB(t[i][3], f, 3); else t[i][3] = 255;
}
}
}
#endif
 
 
#ifdef DEST_4US
static void DEST_4US( GLushort (*t)[4],
CONST void *ptr,
GLuint stride,
ARGS )
{
const GLubyte *f = (GLubyte *) ((GLubyte *) ptr + SRC_START * stride);
const GLubyte *first = f;
GLuint i;
(void) start;
(void) first;
for (i = DST_START ; i < n ; i++, NEXT_F) {
CHECK {
NEXT_F2;
if (SZ >= 1) TRX_US(t[i][0], f, 0);
if (SZ >= 2) TRX_US(t[i][1], f, 1);
if (SZ >= 3) TRX_US(t[i][2], f, 2);
if (SZ == 4) TRX_US(t[i][3], f, 3); else t[i][3] = 65535;
}
}
}
#endif
 
 
#ifdef DEST_1UB
static void DEST_1UB( GLubyte *t,
CONST void *ptr,
GLuint stride,
ARGS )
{
const GLubyte *f = (GLubyte *) ptr + SRC_START * stride;
const GLubyte *first = f;
GLuint i;
(void) start;
(void) first;
for (i = DST_START ; i < n ; i++, NEXT_F) {
CHECK {
NEXT_F2;
TRX_UB(t[i], f, 0);
}
}
}
#endif
 
 
#ifdef DEST_1UI
static void DEST_1UI( GLuint *t,
CONST void *ptr,
GLuint stride,
ARGS )
{
const GLubyte *f = (GLubyte *) ptr + SRC_START * stride;
const GLubyte *first = f;
GLuint i;
(void) start;
(void) first;
 
for (i = DST_START ; i < n ; i++, NEXT_F) {
CHECK {
NEXT_F2;
t[i] = TRX_UI(f, 0);
}
}
}
#endif
 
 
static void INIT(void)
{
#ifdef DEST_1UI
ASSERT(SZ == 1);
TAB(_1ui)[SRC_IDX] = DEST_1UI;
#endif
#ifdef DEST_1UB
ASSERT(SZ == 1);
TAB(_1ub)[SRC_IDX] = DEST_1UB;
#endif
#ifdef DEST_1F
ASSERT(SZ == 1);
TAB(_1f)[SRC_IDX] = DEST_1F;
#endif
#ifdef DEST_3F
ASSERT(SZ == 3);
TAB(_3f)[SRC_IDX] = DEST_3F;
#endif
#ifdef DEST_4UB
TAB(_4ub)[SZ][SRC_IDX] = DEST_4UB;
#endif
#ifdef DEST_4US
TAB(_4us)[SZ][SRC_IDX] = DEST_4US;
#endif
#ifdef DEST_4F
TAB(_4f)[SZ][SRC_IDX] = DEST_4F;
#endif
 
}
 
 
#undef INIT
#undef DEST_1UI
#undef DEST_1UB
#undef DEST_4UB
#undef DEST_4US
#undef DEST_3F
#undef DEST_4F
#undef DEST_1F
#undef SZ
#undef TAG
/shark/trunk/ports/mesa/src/math/m_clip_tmp.h
0,0 → 1,229
/* $Id: m_clip_tmp.h,v 1.1 2003-02-28 11:48:04 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.0.3
*
* Copyright (C) 1999-2002 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.
*/
 
/*
* New (3.1) transformation code written by Keith Whitwell.
*/
 
 
/* KW: a clever asm implementation would nestle integer versions
* of the outcode calculation underneath the division. Gcc won't
* do this, strangely enough, so I only do the divide in
* the case where the cliptest passes. This isn't essential,
* and an asm implementation needn't replicate that behaviour.
*/
static GLvector4f * _XFORMAPI TAG(cliptest_points4)( GLvector4f *clip_vec,
GLvector4f *proj_vec,
GLubyte clipMask[],
GLubyte *orMask,
GLubyte *andMask )
{
const GLuint stride = clip_vec->stride;
const GLfloat *from = (GLfloat *)clip_vec->start;
const GLuint count = clip_vec->count;
GLuint c = 0;
GLfloat (*vProj)[4] = (GLfloat (*)[4])proj_vec->start;
GLubyte tmpAndMask = *andMask;
GLubyte tmpOrMask = *orMask;
GLuint i;
STRIDE_LOOP {
const GLfloat cx = from[0];
const GLfloat cy = from[1];
const GLfloat cz = from[2];
const GLfloat cw = from[3];
#if defined(macintosh) || defined(__powerpc__)
/* on powerpc cliptest is 17% faster in this way. */
GLuint mask;
mask = (((cw < cx) << CLIP_RIGHT_SHIFT));
mask |= (((cw < -cx) << CLIP_LEFT_SHIFT));
mask |= (((cw < cy) << CLIP_TOP_SHIFT));
mask |= (((cw < -cy) << CLIP_BOTTOM_SHIFT));
mask |= (((cw < cz) << CLIP_FAR_SHIFT));
mask |= (((cw < -cz) << CLIP_NEAR_SHIFT));
#else /* !defined(macintosh)) */
GLubyte mask = 0;
if (-cx + cw < 0) mask |= CLIP_RIGHT_BIT;
if ( cx + cw < 0) mask |= CLIP_LEFT_BIT;
if (-cy + cw < 0) mask |= CLIP_TOP_BIT;
if ( cy + cw < 0) mask |= CLIP_BOTTOM_BIT;
if (-cz + cw < 0) mask |= CLIP_FAR_BIT;
if ( cz + cw < 0) mask |= CLIP_NEAR_BIT;
#endif /* defined(macintosh) */
 
clipMask[i] = mask;
if (mask) {
c++;
tmpAndMask &= mask;
tmpOrMask |= mask;
vProj[i][0] = 0;
vProj[i][1] = 0;
vProj[i][2] = 0;
vProj[i][3] = 1;
} else {
GLfloat oow = 1.0F / cw;
vProj[i][0] = cx * oow;
vProj[i][1] = cy * oow;
vProj[i][2] = cz * oow;
vProj[i][3] = oow;
}
}
 
*orMask = tmpOrMask;
*andMask = (GLubyte) (c < count ? 0 : tmpAndMask);
 
proj_vec->flags |= VEC_SIZE_4;
proj_vec->size = 4;
proj_vec->count = clip_vec->count;
return proj_vec;
}
 
 
 
static GLvector4f * _XFORMAPI TAG(cliptest_np_points4)( GLvector4f *clip_vec,
GLvector4f *proj_vec,
GLubyte clipMask[],
GLubyte *orMask,
GLubyte *andMask )
{
const GLuint stride = clip_vec->stride;
const GLuint count = clip_vec->count;
const GLfloat *from = (GLfloat *)clip_vec->start;
GLuint c = 0;
GLubyte tmpAndMask = *andMask;
GLubyte tmpOrMask = *orMask;
GLuint i;
STRIDE_LOOP {
const GLfloat cx = from[0];
const GLfloat cy = from[1];
const GLfloat cz = from[2];
const GLfloat cw = from[3];
#if defined(macintosh) || defined(__powerpc__)
/* on powerpc cliptest is 17% faster in this way. */
GLuint mask;
mask = (((cw < cx) << CLIP_RIGHT_SHIFT));
mask |= (((cw < -cx) << CLIP_LEFT_SHIFT));
mask |= (((cw < cy) << CLIP_TOP_SHIFT));
mask |= (((cw < -cy) << CLIP_BOTTOM_SHIFT));
mask |= (((cw < cz) << CLIP_FAR_SHIFT));
mask |= (((cw < -cz) << CLIP_NEAR_SHIFT));
#else /* !defined(macintosh)) */
GLubyte mask = 0;
if (-cx + cw < 0) mask |= CLIP_RIGHT_BIT;
if ( cx + cw < 0) mask |= CLIP_LEFT_BIT;
if (-cy + cw < 0) mask |= CLIP_TOP_BIT;
if ( cy + cw < 0) mask |= CLIP_BOTTOM_BIT;
if (-cz + cw < 0) mask |= CLIP_FAR_BIT;
if ( cz + cw < 0) mask |= CLIP_NEAR_BIT;
#endif /* defined(macintosh) */
 
clipMask[i] = mask;
if (mask) {
c++;
tmpAndMask &= mask;
tmpOrMask |= mask;
}
}
 
*orMask = tmpOrMask;
*andMask = (GLubyte) (c < count ? 0 : tmpAndMask);
return clip_vec;
}
 
 
static GLvector4f * _XFORMAPI TAG(cliptest_points3)( GLvector4f *clip_vec,
GLvector4f *proj_vec,
GLubyte clipMask[],
GLubyte *orMask,
GLubyte *andMask )
{
const GLuint stride = clip_vec->stride;
const GLuint count = clip_vec->count;
const GLfloat *from = (GLfloat *)clip_vec->start;
 
GLubyte tmpOrMask = *orMask;
GLubyte tmpAndMask = *andMask;
GLuint i;
STRIDE_LOOP {
const GLfloat cx = from[0], cy = from[1], cz = from[2];
GLubyte mask = 0;
if (cx > 1.0) mask |= CLIP_RIGHT_BIT;
else if (cx < -1.0) mask |= CLIP_LEFT_BIT;
if (cy > 1.0) mask |= CLIP_TOP_BIT;
else if (cy < -1.0) mask |= CLIP_BOTTOM_BIT;
if (cz > 1.0) mask |= CLIP_FAR_BIT;
else if (cz < -1.0) mask |= CLIP_NEAR_BIT;
clipMask[i] = mask;
tmpOrMask |= mask;
tmpAndMask &= mask;
}
 
*orMask = tmpOrMask;
*andMask = tmpAndMask;
return clip_vec;
}
 
 
static GLvector4f * _XFORMAPI TAG(cliptest_points2)( GLvector4f *clip_vec,
GLvector4f *proj_vec,
GLubyte clipMask[],
GLubyte *orMask,
GLubyte *andMask )
{
const GLuint stride = clip_vec->stride;
const GLuint count = clip_vec->count;
const GLfloat *from = (GLfloat *)clip_vec->start;
 
GLubyte tmpOrMask = *orMask;
GLubyte tmpAndMask = *andMask;
GLuint i;
STRIDE_LOOP {
const GLfloat cx = from[0], cy = from[1];
GLubyte mask = 0;
if (cx > 1.0) mask |= CLIP_RIGHT_BIT;
else if (cx < -1.0) mask |= CLIP_LEFT_BIT;
if (cy > 1.0) mask |= CLIP_TOP_BIT;
else if (cy < -1.0) mask |= CLIP_BOTTOM_BIT;
clipMask[i] = mask;
tmpOrMask |= mask;
tmpAndMask &= mask;
}
 
*orMask = tmpOrMask;
*andMask = tmpAndMask;
return clip_vec;
}
 
 
static void TAG(init_c_cliptest)( void )
{
_mesa_clip_tab[4] = TAG(cliptest_points4);
_mesa_clip_tab[3] = TAG(cliptest_points3);
_mesa_clip_tab[2] = TAG(cliptest_points2);
 
_mesa_clip_np_tab[4] = TAG(cliptest_np_points4);
_mesa_clip_np_tab[3] = TAG(cliptest_points3);
_mesa_clip_np_tab[2] = TAG(cliptest_points2);
}
/shark/trunk/ports/mesa/src/math/m_xform_tmp.h
0,0 → 1,807
/* $Id: m_xform_tmp.h,v 1.1 2003-02-28 11:48:05 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 3.5
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
 
/*
* New (3.1) transformation code written by Keith Whitwell.
*/
 
 
/*----------------------------------------------------------------------
* Begin Keith's new code
*
*----------------------------------------------------------------------
*/
 
/* KW: Fixed stride, now measured in bytes as is the OpenGL array stride.
*/
 
/* KW: These are now parameterized to produce two versions, one
* which transforms all incoming points, and a second which
* takes notice of a cullmask array, and only transforms
* unculled vertices.
*/
 
/* KW: 1-vectors can sneak into the texture pipeline via the array
* interface. These functions are here because I want consistant
* treatment of the vertex sizes and a lazy strategy for
* cleaning unused parts of the vector, and so as not to exclude
* them from the vertex array interface.
*
* Under our current analysis of matrices, there is no way that
* the product of a matrix and a 1-vector can remain a 1-vector,
* with the exception of the identity transform.
*/
 
/* KW: No longer zero-pad outgoing vectors. Now that external
* vectors can get into the pipeline we cannot ever assume
* that there is more to a vector than indicated by its
* size.
*/
 
/* KW: Now uses clipmask and a flag to allow us to skip both/either
* cliped and/or culled vertices.
*/
 
/* GH: Not any more -- it's easier (and faster) to just process the
* entire vector. Clipping and culling are handled further down
* the pipe, most often during or after the conversion to some
* driver-specific vertex format.
*/
 
static void _XFORMAPI
TAG(transform_points1_general)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0], m12 = m[12];
const GLfloat m1 = m[1], m13 = m[13];
const GLfloat m2 = m[2], m14 = m[14];
const GLfloat m3 = m[3], m15 = m[15];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0];
to[i][0] = m0 * ox + m12;
to[i][1] = m1 * ox + m13;
to[i][2] = m2 * ox + m14;
to[i][3] = m3 * ox + m15;
}
to_vec->size = 4;
to_vec->flags |= VEC_SIZE_4;
to_vec->count = from_vec->count;
}
 
static void _XFORMAPI
TAG(transform_points1_identity)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLuint count = from_vec->count;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint i;
if (to_vec == from_vec) return;
STRIDE_LOOP {
to[i][0] = from[0];
}
to_vec->size = 1;
to_vec->flags |= VEC_SIZE_1;
to_vec->count = from_vec->count;
}
 
static void _XFORMAPI
TAG(transform_points1_2d)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0], m1 = m[1];
const GLfloat m12 = m[12], m13 = m[13];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0];
to[i][0] = m0 * ox + m12;
to[i][1] = m1 * ox + m13;
}
to_vec->size = 2;
to_vec->flags |= VEC_SIZE_2;
to_vec->count = from_vec->count;
}
 
static void _XFORMAPI
TAG(transform_points1_2d_no_rot)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0], m12 = m[12], m13 = m[13];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0];
to[i][0] = m0 * ox + m12;
to[i][1] = m13;
}
to_vec->size = 2;
to_vec->flags |= VEC_SIZE_2;
to_vec->count = from_vec->count;
}
 
static void _XFORMAPI
TAG(transform_points1_3d)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0], m1 = m[1], m2 = m[2];
const GLfloat m12 = m[12], m13 = m[13], m14 = m[14];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0];
to[i][0] = m0 * ox + m12;
to[i][1] = m1 * ox + m13;
to[i][2] = m2 * ox + m14;
}
to_vec->size = 3;
to_vec->flags |= VEC_SIZE_3;
to_vec->count = from_vec->count;
}
 
 
static void _XFORMAPI
TAG(transform_points1_3d_no_rot)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0];
const GLfloat m12 = m[12], m13 = m[13], m14 = m[14];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0];
to[i][0] = m0 * ox + m12;
to[i][1] = m13;
to[i][2] = m14;
}
to_vec->size = 3;
to_vec->flags |= VEC_SIZE_3;
to_vec->count = from_vec->count;
}
 
static void _XFORMAPI
TAG(transform_points1_perspective)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0], m14 = m[14];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0];
to[i][0] = m0 * ox ;
to[i][1] = 0 ;
to[i][2] = m14;
to[i][3] = 0;
}
to_vec->size = 4;
to_vec->flags |= VEC_SIZE_4;
to_vec->count = from_vec->count;
}
 
 
 
 
/* 2-vectors, which are a lot more relevant than 1-vectors, are
* present early in the geometry pipeline and throughout the
* texture pipeline.
*/
static void _XFORMAPI
TAG(transform_points2_general)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0], m4 = m[4], m12 = m[12];
const GLfloat m1 = m[1], m5 = m[5], m13 = m[13];
const GLfloat m2 = m[2], m6 = m[6], m14 = m[14];
const GLfloat m3 = m[3], m7 = m[7], m15 = m[15];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0], oy = from[1];
to[i][0] = m0 * ox + m4 * oy + m12;
to[i][1] = m1 * ox + m5 * oy + m13;
to[i][2] = m2 * ox + m6 * oy + m14;
to[i][3] = m3 * ox + m7 * oy + m15;
}
to_vec->size = 4;
to_vec->flags |= VEC_SIZE_4;
to_vec->count = from_vec->count;
}
 
static void _XFORMAPI
TAG(transform_points2_identity)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
GLuint i;
if (to_vec == from_vec) return;
STRIDE_LOOP {
to[i][0] = from[0];
to[i][1] = from[1];
}
to_vec->size = 2;
to_vec->flags |= VEC_SIZE_2;
to_vec->count = from_vec->count;
}
 
static void _XFORMAPI
TAG(transform_points2_2d)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0], m1 = m[1], m4 = m[4], m5 = m[5];
const GLfloat m12 = m[12], m13 = m[13];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0], oy = from[1];
to[i][0] = m0 * ox + m4 * oy + m12;
to[i][1] = m1 * ox + m5 * oy + m13;
}
to_vec->size = 2;
to_vec->flags |= VEC_SIZE_2;
to_vec->count = from_vec->count;
}
 
static void _XFORMAPI
TAG(transform_points2_2d_no_rot)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0], m5 = m[5], m12 = m[12], m13 = m[13];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0], oy = from[1];
to[i][0] = m0 * ox + m12;
to[i][1] = m5 * oy + m13;
}
to_vec->size = 2;
to_vec->flags |= VEC_SIZE_2;
to_vec->count = from_vec->count;
}
 
static void _XFORMAPI
TAG(transform_points2_3d)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0], m1 = m[1], m2 = m[2], m4 = m[4], m5 = m[5];
const GLfloat m6 = m[6], m12 = m[12], m13 = m[13], m14 = m[14];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0], oy = from[1];
to[i][0] = m0 * ox + m4 * oy + m12;
to[i][1] = m1 * ox + m5 * oy + m13;
to[i][2] = m2 * ox + m6 * oy + m14;
}
to_vec->size = 3;
to_vec->flags |= VEC_SIZE_3;
to_vec->count = from_vec->count;
}
 
 
/* I would actually say this was a fairly important function, from
* a texture transformation point of view.
*/
static void _XFORMAPI
TAG(transform_points2_3d_no_rot)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0], m5 = m[5];
const GLfloat m12 = m[12], m13 = m[13], m14 = m[14];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0], oy = from[1];
to[i][0] = m0 * ox + m12;
to[i][1] = m5 * oy + m13;
to[i][2] = m14;
}
if (m14 == 0) {
to_vec->size = 2;
to_vec->flags |= VEC_SIZE_2;
} else {
to_vec->size = 3;
to_vec->flags |= VEC_SIZE_3;
}
to_vec->count = from_vec->count;
}
 
 
static void _XFORMAPI
TAG(transform_points2_perspective)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0], m5 = m[5], m14 = m[14];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0], oy = from[1];
to[i][0] = m0 * ox ;
to[i][1] = m5 * oy ;
to[i][2] = m14;
to[i][3] = 0;
}
to_vec->size = 4;
to_vec->flags |= VEC_SIZE_4;
to_vec->count = from_vec->count;
}
 
 
 
static void _XFORMAPI
TAG(transform_points3_general)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0], m4 = m[4], m8 = m[8], m12 = m[12];
const GLfloat m1 = m[1], m5 = m[5], m9 = m[9], m13 = m[13];
const GLfloat m2 = m[2], m6 = m[6], m10 = m[10], m14 = m[14];
const GLfloat m3 = m[3], m7 = m[7], m11 = m[11], m15 = m[15];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0], oy = from[1], oz = from[2];
to[i][0] = m0 * ox + m4 * oy + m8 * oz + m12;
to[i][1] = m1 * ox + m5 * oy + m9 * oz + m13;
to[i][2] = m2 * ox + m6 * oy + m10 * oz + m14;
to[i][3] = m3 * ox + m7 * oy + m11 * oz + m15;
}
to_vec->size = 4;
to_vec->flags |= VEC_SIZE_4;
to_vec->count = from_vec->count;
}
 
static void _XFORMAPI
TAG(transform_points3_identity)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
GLuint i;
if (to_vec == from_vec) return;
STRIDE_LOOP {
to[i][0] = from[0];
to[i][1] = from[1];
to[i][2] = from[2];
}
to_vec->size = 3;
to_vec->flags |= VEC_SIZE_3;
to_vec->count = from_vec->count;
}
 
static void _XFORMAPI
TAG(transform_points3_2d)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0], m1 = m[1], m4 = m[4], m5 = m[5];
const GLfloat m12 = m[12], m13 = m[13];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0], oy = from[1], oz = from[2];
to[i][0] = m0 * ox + m4 * oy + m12 ;
to[i][1] = m1 * ox + m5 * oy + m13 ;
to[i][2] = + oz ;
}
to_vec->size = 3;
to_vec->flags |= VEC_SIZE_3;
to_vec->count = from_vec->count;
}
 
static void _XFORMAPI
TAG(transform_points3_2d_no_rot)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0], m5 = m[5], m12 = m[12], m13 = m[13];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0], oy = from[1], oz = from[2];
to[i][0] = m0 * ox + m12 ;
to[i][1] = m5 * oy + m13 ;
to[i][2] = + oz ;
}
to_vec->size = 3;
to_vec->flags |= VEC_SIZE_3;
to_vec->count = from_vec->count;
}
 
static void _XFORMAPI
TAG(transform_points3_3d)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0], m1 = m[1], m2 = m[2], m4 = m[4], m5 = m[5];
const GLfloat m6 = m[6], m8 = m[8], m9 = m[9], m10 = m[10];
const GLfloat m12 = m[12], m13 = m[13], m14 = m[14];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0], oy = from[1], oz = from[2];
to[i][0] = m0 * ox + m4 * oy + m8 * oz + m12 ;
to[i][1] = m1 * ox + m5 * oy + m9 * oz + m13 ;
to[i][2] = m2 * ox + m6 * oy + m10 * oz + m14 ;
}
to_vec->size = 3;
to_vec->flags |= VEC_SIZE_3;
to_vec->count = from_vec->count;
}
 
/* previously known as ortho...
*/
static void _XFORMAPI
TAG(transform_points3_3d_no_rot)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0], m5 = m[5];
const GLfloat m10 = m[10], m12 = m[12], m13 = m[13], m14 = m[14];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0], oy = from[1], oz = from[2];
to[i][0] = m0 * ox + m12 ;
to[i][1] = m5 * oy + m13 ;
to[i][2] = m10 * oz + m14 ;
}
to_vec->size = 3;
to_vec->flags |= VEC_SIZE_3;
to_vec->count = from_vec->count;
}
 
static void _XFORMAPI
TAG(transform_points3_perspective)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0], m5 = m[5], m8 = m[8], m9 = m[9];
const GLfloat m10 = m[10], m14 = m[14];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0], oy = from[1], oz = from[2];
to[i][0] = m0 * ox + m8 * oz ;
to[i][1] = m5 * oy + m9 * oz ;
to[i][2] = m10 * oz + m14 ;
to[i][3] = -oz ;
}
to_vec->size = 4;
to_vec->flags |= VEC_SIZE_4;
to_vec->count = from_vec->count;
}
 
 
 
static void _XFORMAPI
TAG(transform_points4_general)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0], m4 = m[4], m8 = m[8], m12 = m[12];
const GLfloat m1 = m[1], m5 = m[5], m9 = m[9], m13 = m[13];
const GLfloat m2 = m[2], m6 = m[6], m10 = m[10], m14 = m[14];
const GLfloat m3 = m[3], m7 = m[7], m11 = m[11], m15 = m[15];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0], oy = from[1], oz = from[2], ow = from[3];
to[i][0] = m0 * ox + m4 * oy + m8 * oz + m12 * ow;
to[i][1] = m1 * ox + m5 * oy + m9 * oz + m13 * ow;
to[i][2] = m2 * ox + m6 * oy + m10 * oz + m14 * ow;
to[i][3] = m3 * ox + m7 * oy + m11 * oz + m15 * ow;
}
to_vec->size = 4;
to_vec->flags |= VEC_SIZE_4;
to_vec->count = from_vec->count;
}
 
static void _XFORMAPI
TAG(transform_points4_identity)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
GLuint i;
if (to_vec == from_vec) return;
STRIDE_LOOP {
to[i][0] = from[0];
to[i][1] = from[1];
to[i][2] = from[2];
to[i][3] = from[3];
}
to_vec->size = 4;
to_vec->flags |= VEC_SIZE_4;
to_vec->count = from_vec->count;
}
 
static void _XFORMAPI
TAG(transform_points4_2d)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0], m1 = m[1], m4 = m[4], m5 = m[5];
const GLfloat m12 = m[12], m13 = m[13];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0], oy = from[1], oz = from[2], ow = from[3];
to[i][0] = m0 * ox + m4 * oy + m12 * ow;
to[i][1] = m1 * ox + m5 * oy + m13 * ow;
to[i][2] = + oz ;
to[i][3] = ow;
}
to_vec->size = 4;
to_vec->flags |= VEC_SIZE_4;
to_vec->count = from_vec->count;
}
 
static void _XFORMAPI
TAG(transform_points4_2d_no_rot)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0], m5 = m[5], m12 = m[12], m13 = m[13];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0], oy = from[1], oz = from[2], ow = from[3];
to[i][0] = m0 * ox + m12 * ow;
to[i][1] = m5 * oy + m13 * ow;
to[i][2] = + oz ;
to[i][3] = ow;
}
to_vec->size = 4;
to_vec->flags |= VEC_SIZE_4;
to_vec->count = from_vec->count;
}
 
static void _XFORMAPI
TAG(transform_points4_3d)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0], m1 = m[1], m2 = m[2], m4 = m[4], m5 = m[5];
const GLfloat m6 = m[6], m8 = m[8], m9 = m[9], m10 = m[10];
const GLfloat m12 = m[12], m13 = m[13], m14 = m[14];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0], oy = from[1], oz = from[2], ow = from[3];
to[i][0] = m0 * ox + m4 * oy + m8 * oz + m12 * ow;
to[i][1] = m1 * ox + m5 * oy + m9 * oz + m13 * ow;
to[i][2] = m2 * ox + m6 * oy + m10 * oz + m14 * ow;
to[i][3] = ow;
}
to_vec->size = 4;
to_vec->flags |= VEC_SIZE_4;
to_vec->count = from_vec->count;
}
 
static void _XFORMAPI
TAG(transform_points4_3d_no_rot)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0], m5 = m[5];
const GLfloat m10 = m[10], m12 = m[12], m13 = m[13], m14 = m[14];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0], oy = from[1], oz = from[2], ow = from[3];
to[i][0] = m0 * ox + m12 * ow;
to[i][1] = m5 * oy + m13 * ow;
to[i][2] = m10 * oz + m14 * ow;
to[i][3] = ow;
}
to_vec->size = 4;
to_vec->flags |= VEC_SIZE_4;
to_vec->count = from_vec->count;
}
 
static void _XFORMAPI
TAG(transform_points4_perspective)( GLvector4f *to_vec,
const GLfloat m[16],
const GLvector4f *from_vec )
{
const GLuint stride = from_vec->stride;
GLfloat *from = from_vec->start;
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start;
GLuint count = from_vec->count;
const GLfloat m0 = m[0], m5 = m[5], m8 = m[8], m9 = m[9];
const GLfloat m10 = m[10], m14 = m[14];
GLuint i;
STRIDE_LOOP {
const GLfloat ox = from[0], oy = from[1], oz = from[2], ow = from[3];
to[i][0] = m0 * ox + m8 * oz ;
to[i][1] = m5 * oy + m9 * oz ;
to[i][2] = m10 * oz + m14 * ow ;
to[i][3] = -oz ;
}
to_vec->size = 4;
to_vec->flags |= VEC_SIZE_4;
to_vec->count = from_vec->count;
}
 
static transform_func _XFORMAPI TAG(transform_tab_1)[7];
static transform_func _XFORMAPI TAG(transform_tab_2)[7];
static transform_func _XFORMAPI TAG(transform_tab_3)[7];
static transform_func _XFORMAPI TAG(transform_tab_4)[7];
 
/* Similar functions could be called several times, with more highly
* optimized routines overwriting the arrays. This only occurs during
* startup.
*/
static void _XFORMAPI TAG(init_c_transformations)( void )
{
#define TAG_TAB _mesa_transform_tab
#define TAG_TAB_1 TAG(transform_tab_1)
#define TAG_TAB_2 TAG(transform_tab_2)
#define TAG_TAB_3 TAG(transform_tab_3)
#define TAG_TAB_4 TAG(transform_tab_4)
 
TAG_TAB[1] = TAG_TAB_1;
TAG_TAB[2] = TAG_TAB_2;
TAG_TAB[3] = TAG_TAB_3;
TAG_TAB[4] = TAG_TAB_4;
 
/* 1-D points (ie texcoords) */
TAG_TAB_1[MATRIX_GENERAL] = TAG(transform_points1_general);
TAG_TAB_1[MATRIX_IDENTITY] = TAG(transform_points1_identity);
TAG_TAB_1[MATRIX_3D_NO_ROT] = TAG(transform_points1_3d_no_rot);
TAG_TAB_1[MATRIX_PERSPECTIVE] = TAG(transform_points1_perspective);
TAG_TAB_1[MATRIX_2D] = TAG(transform_points1_2d);
TAG_TAB_1[MATRIX_2D_NO_ROT] = TAG(transform_points1_2d_no_rot);
TAG_TAB_1[MATRIX_3D] = TAG(transform_points1_3d);
 
/* 2-D points */
TAG_TAB_2[MATRIX_GENERAL] = TAG(transform_points2_general);
TAG_TAB_2[MATRIX_IDENTITY] = TAG(transform_points2_identity);
TAG_TAB_2[MATRIX_3D_NO_ROT] = TAG(transform_points2_3d_no_rot);
TAG_TAB_2[MATRIX_PERSPECTIVE] = TAG(transform_points2_perspective);
TAG_TAB_2[MATRIX_2D] = TAG(transform_points2_2d);
TAG_TAB_2[MATRIX_2D_NO_ROT] = TAG(transform_points2_2d_no_rot);
TAG_TAB_2[MATRIX_3D] = TAG(transform_points2_3d);
 
/* 3-D points */
TAG_TAB_3[MATRIX_GENERAL] = TAG(transform_points3_general);
TAG_TAB_3[MATRIX_IDENTITY] = TAG(transform_points3_identity);
TAG_TAB_3[MATRIX_3D_NO_ROT] = TAG(transform_points3_3d_no_rot);
TAG_TAB_3[MATRIX_PERSPECTIVE] = TAG(transform_points3_perspective);
TAG_TAB_3[MATRIX_2D] = TAG(transform_points3_2d);
TAG_TAB_3[MATRIX_2D_NO_ROT] = TAG(transform_points3_2d_no_rot);
TAG_TAB_3[MATRIX_3D] = TAG(transform_points3_3d);
 
/* 4-D points */
TAG_TAB_4[MATRIX_GENERAL] = TAG(transform_points4_general);
TAG_TAB_4[MATRIX_IDENTITY] = TAG(transform_points4_identity);
TAG_TAB_4[MATRIX_3D_NO_ROT] = TAG(transform_points4_3d_no_rot);
TAG_TAB_4[MATRIX_PERSPECTIVE] = TAG(transform_points4_perspective);
TAG_TAB_4[MATRIX_2D] = TAG(transform_points4_2d);
TAG_TAB_4[MATRIX_2D_NO_ROT] = TAG(transform_points4_2d_no_rot);
TAG_TAB_4[MATRIX_3D] = TAG(transform_points4_3d);
 
#undef TAG_TAB
#undef TAG_TAB_1
#undef TAG_TAB_2
#undef TAG_TAB_3
#undef TAG_TAB_4
}
/shark/trunk/ports/mesa/src/math/m_debug_norm.c
0,0 → 1,381
/* $Id: m_debug_norm.c,v 1.1 2003-02-28 11:48:05 pj Exp $ */
 
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 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.
*
* Authors:
* Gareth Hughes
*/
 
#include "glheader.h"
#include "context.h"
#include "macros.h"
#include "imports.h"
#include "mmath.h"
 
#include "m_matrix.h"
#include "m_xform.h"
 
#include "m_debug.h"
#include "m_debug_util.h"
 
 
#ifdef DEBUG /* This code only used for debugging */
 
 
static int m_norm_identity[16] = {
ONE, NIL, NIL, NIL,
NIL, ONE, NIL, NIL,
NIL, NIL, ONE, NIL,
NIL, NIL, NIL, NIL
};
static int m_norm_general[16] = {
VAR, VAR, VAR, NIL,
VAR, VAR, VAR, NIL,
VAR, VAR, VAR, NIL,
NIL, NIL, NIL, NIL
};
static int m_norm_no_rot[16] = {
VAR, NIL, NIL, NIL,
NIL, VAR, NIL, NIL,
NIL, NIL, VAR, NIL,
NIL, NIL, NIL, NIL
};
static int *norm_templates[8] = {
m_norm_no_rot,
m_norm_no_rot,
m_norm_no_rot,
m_norm_general,
m_norm_general,
m_norm_general,
m_norm_identity,
m_norm_identity
};
static int norm_types[8] = {
NORM_TRANSFORM_NO_ROT,
NORM_TRANSFORM_NO_ROT | NORM_RESCALE,
NORM_TRANSFORM_NO_ROT | NORM_NORMALIZE,
NORM_TRANSFORM,
NORM_TRANSFORM | NORM_RESCALE,
NORM_TRANSFORM | NORM_NORMALIZE,
NORM_RESCALE,
NORM_NORMALIZE
};
static int norm_scale_types[8] = { /* rescale factor */
NIL, /* NIL disables rescaling */
VAR,
NIL,
NIL,
VAR,
NIL,
VAR,
NIL
};
static int norm_normalize_types[8] = { /* normalizing ?? (no = 0) */
0,
0,
1,
0,
0,
1,
0,
1
};
static char *norm_strings[8] = {
"NORM_TRANSFORM_NO_ROT",
"NORM_TRANSFORM_NO_ROT | NORM_RESCALE",
"NORM_TRANSFORM_NO_ROT | NORM_NORMALIZE",
"NORM_TRANSFORM",
"NORM_TRANSFORM | NORM_RESCALE",
"NORM_TRANSFORM | NORM_NORMALIZE",
"NORM_RESCALE",
"NORM_NORMALIZE"
};
 
 
/* =============================================================
* Reference transformations
*/
 
static void ref_norm_transform_rescale( const GLmatrix *mat,
GLfloat scale,
const GLvector4f *in,
const GLfloat *lengths,
GLvector4f *dest )
{
GLuint i;
const GLfloat *s = in->start;
const GLfloat *m = mat->inv;
GLfloat (*out)[4] = (GLfloat (*)[4]) dest->start;
 
(void) lengths;
 
for ( i = 0 ; i < in->count ; i++ ) {
GLfloat t[3];
 
TRANSFORM_NORMAL( t, s, m );
SCALE_SCALAR_3V( out[i], scale, t );
 
s = (GLfloat *)((char *)s + in->stride);
}
}
 
static void ref_norm_transform_normalize( const GLmatrix *mat,
GLfloat scale,
const GLvector4f *in,
const GLfloat *lengths,
GLvector4f *dest )
{
GLuint i;
const GLfloat *s = in->start;
const GLfloat *m = mat->inv;
GLfloat (*out)[4] = (GLfloat (*)[4]) dest->start;
 
for ( i = 0 ; i < in->count ; i++ ) {
GLfloat t[3];
 
TRANSFORM_NORMAL( t, s, m );
 
if ( !lengths ) {
GLfloat len = LEN_SQUARED_3FV( t );
if ( len > 1e-20 ) {
/* Hmmm, don't know how we could test the precalculated
* length case...
*/
scale = 1.0 / sqrt( len );
SCALE_SCALAR_3V( out[i], scale, t );
} else {
out[i][0] = out[i][1] = out[i][2] = 0;
}
} else {
scale = lengths[i];;
SCALE_SCALAR_3V( out[i], scale, t );
}
 
s = (GLfloat *)((char *)s + in->stride);
}
}
 
 
/* =============================================================
* Normal transformation tests
*/
 
static void init_matrix( GLfloat *m )
{
m[0] = 63.0; m[4] = 43.0; m[ 8] = 29.0; m[12] = 43.0;
m[1] = 55.0; m[5] = 17.0; m[ 9] = 31.0; m[13] = 7.0;
m[2] = 44.0; m[6] = 9.0; m[10] = 7.0; m[14] = 3.0;
m[3] = 11.0; m[7] = 23.0; m[11] = 91.0; m[15] = 9.0;
}
 
 
static int test_norm_function( normal_func func, int mtype, long *cycles )
{
GLvector4f source[1], dest[1], dest2[1], ref[1], ref2[1];
GLmatrix mat[1];
GLfloat s[TEST_COUNT][5], d[TEST_COUNT][4], r[TEST_COUNT][4];
GLfloat d2[TEST_COUNT][4], r2[TEST_COUNT][4], length[TEST_COUNT];
GLfloat scale;
GLfloat *m;
int i, j;
#ifdef RUN_DEBUG_BENCHMARK
int cycle_i; /* the counter for the benchmarks we run */
#endif
 
(void) cycles;
 
mat->m = (GLfloat *) ALIGN_MALLOC( 16 * sizeof(GLfloat), 16 );
mat->inv = m = mat->m;
 
init_matrix( m );
 
scale = 1.0F + rnd () * norm_scale_types[mtype];
 
for ( i = 0 ; i < 4 ; i++ ) {
for ( j = 0 ; j < 4 ; j++ ) {
switch ( norm_templates[mtype][i * 4 + j] ) {
case NIL:
m[j * 4 + i] = 0.0;
break;
case ONE:
m[j * 4 + i] = 1.0;
break;
case NEG:
m[j * 4 + i] = -1.0;
break;
case VAR:
break;
default:
abort();
}
}
}
 
for ( i = 0 ; i < TEST_COUNT ; i++ ) {
ASSIGN_3V( d[i], 0.0, 0.0, 0.0 );
ASSIGN_3V( s[i], 0.0, 0.0, 0.0 );
ASSIGN_3V( d2[i], 0.0, 0.0, 0.0 );
for ( j = 0 ; j < 3 ; j++ )
s[i][j] = rnd();
length[i] = 1 / sqrt( LEN_SQUARED_3FV( s[i] ) );
}
 
source->data = (GLfloat(*)[4]) s;
source->start = (GLfloat *) s;
source->count = TEST_COUNT;
source->stride = sizeof(s[0]);
source->flags = 0;
 
dest->data = d;
dest->start = (GLfloat *) d;
dest->count = TEST_COUNT;
dest->stride = sizeof(float[4]);
dest->flags = 0;
 
dest2->data = d2;
dest2->start = (GLfloat *) d2;
dest2->count = TEST_COUNT;
dest2->stride = sizeof(float[4]);
dest2->flags = 0;
 
ref->data = r;
ref->start = (GLfloat *) r;
ref->count = TEST_COUNT;
ref->stride = sizeof(float[4]);
ref->flags = 0;
 
ref2->data = r2;
ref2->start = (GLfloat *) r2;
ref2->count = TEST_COUNT;
ref2->stride = sizeof(float[4]);
ref2->flags = 0;
 
if ( norm_normalize_types[mtype] == 0 ) {
ref_norm_transform_rescale( mat, scale, source, NULL, ref );
} else {
ref_norm_transform_normalize( mat, scale, source, NULL, ref );
ref_norm_transform_normalize( mat, scale, source, length, ref2 );
}
 
if ( mesa_profile ) {
BEGIN_RACE( *cycles );
func( mat, scale, source, NULL, dest );
END_RACE( *cycles );
func( mat, scale, source, length, dest2 );
} else {
func( mat, scale, source, NULL, dest );
func( mat, scale, source, length, dest2 );
}
 
for ( i = 0 ; i < TEST_COUNT ; i++ ) {
for ( j = 0 ; j < 3 ; j++ ) {
if ( significand_match( d[i][j], r[i][j] ) < REQUIRED_PRECISION ) {
_mesa_printf(NULL, "-----------------------------\n" );
_mesa_printf(NULL, "(i = %i, j = %i)\n", i, j );
_mesa_printf(NULL, "%f \t %f \t [ratio = %e - %i bit missed]\n",
d[i][0], r[i][0], r[i][0]/d[i][0],
MAX_PRECISION - significand_match( d[i][0], r[i][0] ) );
_mesa_printf(NULL, "%f \t %f \t [ratio = %e - %i bit missed]\n",
d[i][1], r[i][1], r[i][1]/d[i][1],
MAX_PRECISION - significand_match( d[i][1], r[i][1] ) );
_mesa_printf(NULL, "%f \t %f \t [ratio = %e - %i bit missed]\n",
d[i][2], r[i][2], r[i][2]/d[i][2],
MAX_PRECISION - significand_match( d[i][2], r[i][2] ) );
return 0;
}
 
if ( norm_normalize_types[mtype] != 0 ) {
if ( significand_match( d2[i][j], r2[i][j] ) < REQUIRED_PRECISION ) {
_mesa_printf(NULL, "------------------- precalculated length case ------\n" );
_mesa_printf(NULL, "(i = %i, j = %i)\n", i, j );
_mesa_printf(NULL, "%f \t %f \t [ratio = %e - %i bit missed]\n",
d2[i][0], r2[i][0], r2[i][0]/d2[i][0],
MAX_PRECISION - significand_match( d2[i][0], r2[i][0] ) );
_mesa_printf(NULL, "%f \t %f \t [ratio = %e - %i bit missed]\n",
d2[i][1], r2[i][1], r2[i][1]/d2[i][1],
MAX_PRECISION - significand_match( d2[i][1], r2[i][1] ) );
_mesa_printf(NULL, "%f \t %f \t [ratio = %e - %i bit missed]\n",
d2[i][2], r2[i][2], r2[i][2]/d2[i][2],
MAX_PRECISION - significand_match( d2[i][2], r2[i][2] ) );
return 0;
}
}
}
}
 
ALIGN_FREE( mat->m );
return 1;
}
 
void _math_test_all_normal_transform_functions( char *description )
{
int mtype;
long benchmark_tab[0xf];
static int first_time = 1;
 
if ( first_time ) {
first_time = 0;
mesa_profile = getenv( "MESA_PROFILE" );
}
 
#ifdef RUN_DEBUG_BENCHMARK
if ( mesa_profile ) {
if ( !counter_overhead ) {
INIT_COUNTER();
_mesa_printf(NULL, "counter overhead: %ld cycles\n\n", counter_overhead );
}
_mesa_printf(NULL, "normal transform results after hooking in %s functions:\n",
description );
_mesa_printf(NULL, "\n-------------------------------------------------------\n" );
}
#endif
 
for ( mtype = 0 ; mtype < 8 ; mtype++ ) {
normal_func func = _mesa_normal_tab[norm_types[mtype]];
long *cycles = &benchmark_tab[mtype];
 
if ( test_norm_function( func, mtype, cycles ) == 0 ) {
char buf[100];
_mesa_sprintf(NULL, buf, "_mesa_normal_tab[0][%s] failed test (%s)",
norm_strings[mtype], description );
_mesa_problem( NULL, buf );
}
 
#ifdef RUN_DEBUG_BENCHMARK
if ( mesa_profile ) {
_mesa_printf(NULL, " %li\t", benchmark_tab[mtype] );
_mesa_printf(NULL, " | [%s]\n", norm_strings[mtype] );
}
#endif
}
#ifdef RUN_DEBUG_BENCHMARK
if ( mesa_profile ) {
_mesa_printf(NULL, "\n" );
fflush( stdout );
}
#endif
}
 
 
#endif /* DEBUG */
/shark/trunk/ports/mesa/src-glu/makefile
0,0 → 1,23
# The Frame Buffer Device
 
ifndef BASE
BASE=../../..
endif
 
include $(BASE)/config/config.mk
 
LIBRARY = glu
 
OBJS_PATH = $(BASE)/drivers/mesa/src-glu/
 
GLU = glu.o mipmap.o nurbs.o nurbsutl.o project.o tess.o\
nurbscrv.o nurbssrf.o polytest.o quadric.o tesselat.o
 
OBJS = $(GLU)
 
C_OPT += -I../../../drivers/linuxc24/include -I../include -I. -I.. -D__KERNEL__ -D__i368__ \
-ffast-math -fexpensive-optimizations -fstrict-aliasing \
-malign-loops=2 -malign-jumps=2 -malign-functions=2 -D_REENTRANT -DUSE_MMX_ASM -DUSE_X86_ASM
 
include $(BASE)/config/lib.mk