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.