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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
|
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
#include "private.h"
GLboolean STATE_DIRTY = GL_TRUE;
GLboolean DEPTH_TEST_ENABLED = GL_FALSE;
GLboolean DEPTH_MASK_ENABLED = GL_FALSE;
GLboolean CULLING_ENABLED = GL_FALSE;
GLboolean FOG_ENABLED = GL_FALSE;
GLboolean ALPHA_TEST_ENABLED = GL_FALSE;
GLboolean SCISSOR_TEST_ENABLED = GL_FALSE;
GLenum SHADE_MODEL = PVR_SHADE_GOURAUD;
GLboolean BLEND_ENABLED = GL_FALSE;
GLboolean TEXTURES_ENABLED = GL_FALSE;
GLboolean AUTOSORT_ENABLED = GL_FALSE;
static struct {
int x;
int y;
int width;
int height;
GLboolean applied;
} scissor_rect = {0, 0, 640, 480, false};
void _glInitContext() {
scissor_rect.x = 0;
scissor_rect.y = 0;
scissor_rect.width = vid_mode->width;
scissor_rect.height = vid_mode->height;
}
/* Depth Testing */
void glClearDepth(float depth) {
/* We reverse because using invW means that farther Z == lower number */
pvr_set_zclip(MIN(1.0f - depth, PVR_MIN_Z));
}
void glScissor(int x, int y, int width, int height) {
if(scissor_rect.x == x &&
scissor_rect.y == y &&
scissor_rect.width == width &&
scissor_rect.height == height) {
return;
}
scissor_rect.x = x;
scissor_rect.y = y;
scissor_rect.width = width;
scissor_rect.height = height;
scissor_rect.applied = false;
STATE_DIRTY = GL_TRUE; // FIXME: do we need this?
_glApplyScissor(false);
}
/* Setup the hardware user clip rectangle.
The minimum clip rectangle is a 32x32 area which is dependent on the tile
size use by the tile accelerator. The PVR swithes off rendering to tiles
outside or inside the defined rectangle dependant upon the 'clipmode'
bits in the polygon header.
Clip rectangles therefore must have a size that is some multiple of 32.
glScissor(0, 0, 32, 32) allows only the 'tile' in the lower left
hand corner of the screen to be modified and glScissor(0, 0, 0, 0)
disallows modification to all 'tiles' on the screen.
We call this in the following situations:
- glEnable(GL_SCISSOR_TEST) is called
- glScissor() is called
- After glKosSwapBuffers()
This ensures that a clip command is added to every vertex list
at the right place, either when enabling the scissor test, or
when the scissor test changes.
*/
void _glApplyScissor(int force) {
/* Don't do anyting if clipping is disabled */
if(!SCISSOR_TEST_ENABLED) {
return;
}
/* Don't apply if we already applied - nothing changed */
if(scissor_rect.applied && !force) {
return;
}
PVRTileClipCommand c;
int miny, maxx, maxy;
int scissor_width = MAX(MIN(scissor_rect.width, vid_mode->width), 0);
int scissor_height = MAX(MIN(scissor_rect.height, vid_mode->height), 0);
/* force the origin to the lower left-hand corner of the screen */
miny = (vid_mode->height - scissor_height) - scissor_rect.y;
maxx = (scissor_width + scissor_rect.x);
maxy = (scissor_height + miny);
/* load command structure while mapping screen coords to TA tiles */
c.flags = PVR_CMD_USERCLIP;
c.d1 = c.d2 = c.d3 = 0;
uint16_t vw = vid_mode->width >> 5;
uint16_t vh = vid_mode->height >> 5;
c.sx = CLAMP(scissor_rect.x >> 5, 0, vw);
c.sy = CLAMP(miny >> 5, 0, vh);
c.ex = CLAMP((maxx >> 5) - 1, 0, vw);
c.ey = CLAMP((maxy >> 5) - 1, 0, vh);
aligned_vector_push_back(&OP_LIST.vector, &c, 1);
aligned_vector_push_back(&PT_LIST.vector, &c, 1);
aligned_vector_push_back(&TR_LIST.vector, &c, 1);
scissor_rect.applied = true;
}
Viewport VIEWPORT;
/* Set the GL viewport */
void glViewport(int x, int y, int width, int height) {
VIEWPORT.hwidth = width * 0.5f;
VIEWPORT.hheight = height * -0.5f;
VIEWPORT.x_plus_hwidth = x + width * 0.5f;
VIEWPORT.y_plus_hheight = y + height * 0.5f;
}
void apply_poly_header(PolyHeader* dst, PolyList* activePolyList) {
const TextureObject *tx1 = TEXTURE_ACTIVE;
uint32_t txr_base;
TRACE();
int list_type = activePolyList->list_type;
int gen_color_clamp = PVR_CLRCLAMP_DISABLE;
int gen_culling = CULLING_ENABLED ? PVR_CULLING_CW : PVR_CULLING_SMALL;
int depth_comp = DEPTH_TEST_ENABLED ? PVR_DEPTHCMP_GEQUAL : PVR_DEPTHCMP_ALWAYS;
int depth_write = DEPTH_MASK_ENABLED ? PVR_DEPTHWRITE_ENABLE : PVR_DEPTHWRITE_DISABLE;
int gen_shading = SHADE_MODEL;
int gen_clip_mode = SCISSOR_TEST_ENABLED ? PVR_USERCLIP_INSIDE : PVR_USERCLIP_DISABLE;
int gen_fog_type = FOG_ENABLED ? PVR_FOG_TABLE : PVR_FOG_DISABLE;
int gen_alpha = (BLEND_ENABLED || ALPHA_TEST_ENABLED) ? PVR_ALPHA_ENABLE : PVR_ALPHA_DISABLE;
int blend_src = PVR_BLEND_SRCALPHA;
int blend_dst = PVR_BLEND_INVSRCALPHA;
if (list_type == PVR_LIST_OP_POLY) {
/* Opaque polys are always one/zero */
blend_src = PVR_BLEND_ONE;
blend_dst = PVR_BLEND_ZERO;
} else if (list_type == PVR_LIST_PT_POLY) {
/* Punch-through polys require fixed blending and depth modes */
blend_src = PVR_BLEND_SRCALPHA;
blend_dst = PVR_BLEND_INVSRCALPHA;
depth_comp = PVR_DEPTHCMP_LEQUAL;
} else if (list_type == PVR_LIST_TR_POLY && AUTOSORT_ENABLED) {
/* Autosort mode requires this mode for transparent polys */
depth_comp = PVR_DEPTHCMP_GEQUAL;
}
int txr_enable, txr_alpha;
if (!TEXTURES_ENABLED || !tx1 || !tx1->data) {
/* Disable all texturing to start with */
txr_enable = PVR_TEXTURE_DISABLE;
} else {
txr_alpha = (BLEND_ENABLED || ALPHA_TEST_ENABLED) ? PVR_TXRALPHA_ENABLE : PVR_TXRALPHA_DISABLE;
txr_enable = PVR_TEXTURE_ENABLE;
}
/* The base values for CMD */
dst->cmd = PVR_CMD_POLYHDR;
dst->cmd |= txr_enable << 3;
/* Force bits 18 and 19 on to switch to 6 triangle strips */
dst->cmd |= 0xC0000;
/* Or in the list type, shading type, color and UV formats */
dst->cmd |= (list_type << PVR_TA_CMD_TYPE_SHIFT) & PVR_TA_CMD_TYPE_MASK;
dst->cmd |= (PVR_CLRFMT_ARGBPACKED << PVR_TA_CMD_CLRFMT_SHIFT) & PVR_TA_CMD_CLRFMT_MASK;
dst->cmd |= (gen_shading << PVR_TA_CMD_SHADE_SHIFT) & PVR_TA_CMD_SHADE_MASK;
dst->cmd |= (PVR_UVFMT_32BIT << PVR_TA_CMD_UVFMT_SHIFT) & PVR_TA_CMD_UVFMT_MASK;
dst->cmd |= (gen_clip_mode << PVR_TA_CMD_USERCLIP_SHIFT) & PVR_TA_CMD_USERCLIP_MASK;
/* Polygon mode 1 */
dst->mode1 = (depth_comp << PVR_TA_PM1_DEPTHCMP_SHIFT) & PVR_TA_PM1_DEPTHCMP_MASK;
dst->mode1 |= (gen_culling << PVR_TA_PM1_CULLING_SHIFT) & PVR_TA_PM1_CULLING_MASK;
dst->mode1 |= (depth_write << PVR_TA_PM1_DEPTHWRITE_SHIFT) & PVR_TA_PM1_DEPTHWRITE_MASK;
dst->mode1 |= (txr_enable << PVR_TA_PM1_TXRENABLE_SHIFT) & PVR_TA_PM1_TXRENABLE_MASK;
/* Polygon mode 2 */
dst->mode2 = (blend_src << PVR_TA_PM2_SRCBLEND_SHIFT) & PVR_TA_PM2_SRCBLEND_MASK;
dst->mode2 |= (blend_dst << PVR_TA_PM2_DSTBLEND_SHIFT) & PVR_TA_PM2_DSTBLEND_MASK;
dst->mode2 |= (gen_fog_type << PVR_TA_PM2_FOG_SHIFT) & PVR_TA_PM2_FOG_MASK;
dst->mode2 |= (gen_color_clamp << PVR_TA_PM2_CLAMP_SHIFT) & PVR_TA_PM2_CLAMP_MASK;
dst->mode2 |= (gen_alpha << PVR_TA_PM2_ALPHA_SHIFT) & PVR_TA_PM2_ALPHA_MASK;
if (txr_enable == PVR_TEXTURE_DISABLE) {
dst->mode3 = 0;
} else {
GLuint filter = PVR_FILTER_NEAREST;
if (tx1->minFilter == GL_LINEAR && tx1->magFilter == GL_LINEAR) filter = PVR_FILTER_BILINEAR;
dst->mode2 |= (txr_alpha << PVR_TA_PM2_TXRALPHA_SHIFT) & PVR_TA_PM2_TXRALPHA_MASK;
dst->mode2 |= (filter << PVR_TA_PM2_FILTER_SHIFT) & PVR_TA_PM2_FILTER_MASK;
dst->mode2 |= (tx1->mipmap_bias << PVR_TA_PM2_MIPBIAS_SHIFT) & PVR_TA_PM2_MIPBIAS_MASK;
dst->mode2 |= (PVR_TXRENV_MODULATEALPHA << PVR_TA_PM2_TXRENV_SHIFT) & PVR_TA_PM2_TXRENV_MASK;
dst->mode2 |= (DimensionFlag(tx1->width) << PVR_TA_PM2_USIZE_SHIFT) & PVR_TA_PM2_USIZE_MASK;
dst->mode2 |= (DimensionFlag(tx1->height) << PVR_TA_PM2_VSIZE_SHIFT) & PVR_TA_PM2_VSIZE_MASK;
/* Polygon mode 3 */
dst->mode3 = (GL_FALSE << PVR_TA_PM3_MIPMAP_SHIFT) & PVR_TA_PM3_MIPMAP_MASK;
dst->mode3 |= (tx1->color << PVR_TA_PM3_TXRFMT_SHIFT) & PVR_TA_PM3_TXRFMT_MASK;
/* Convert the texture address */
txr_base = (uint32_t)tx1->data;
txr_base = (txr_base & 0x00fffff8) >> 3;
dst->mode3 |= txr_base;
}
dst->d1 = dst->d2 = 0xffffffff;
dst->d3 = dst->d4 = 0xffffffff;
}
|