If you're drawing full-screen, the hardware will clip everything to the screen coordinates. It's a side-effect of the tile-based rendering approach the PVR uses - for each tile (32x32 pixel block) on-screen, it finds all the polygons that intersect the tile, clips them to the tile, and then renders them.BB Hood wrote:How can the PVR handle clipping in hardware if I don't tell it where to clip? My drawing block function will only draw the whole tile.
If you're not drawing full-screen, you can set the clipping region. However, since the clipping is based on tiles, you can only clip to tile boundaries. You send a PVR_CMD_USERCLIP primitive to the PVR to set the clipping region. Then, for polygons you want to be affected by clipping, you need to set gen.clip_mode in the polygon context to PVR_USERCLIP_INSIDE. You could also use PVR_USERCLIP_OUTSIDE to exclude polygons from that area.
At least, that's the theory - I've never been able to get it to work - it works on half the screen only, with a flickery mess at the borders. In theory, this should set the clipping region:
Code: Select all
#define CLAMP( X, MIN, MAX ) ( (X)<(MIN) ? (MIN) : ((X)>(MAX) ? (MAX) : (X)) )
void set_clip(int x, int y, int width, int height)
{
int min_x, min_y, max_x, max_y;
int screen_width, screen_height;
// Empty userclip polygon header
// KOS has no code to support this - we have to build the header ourselves
pvr_poly_hdr_t user_clip = {
PVR_CMD_USERCLIP, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000
};
// Get the screen size (in tiles)
screen_width = vid_mode->width / 32;
screen_height = vid_mode->height / 32;
// Calculate the minimum and maximum tile to render
min_x = x / 32;
min_y = y / 32;
max_x = ((x + width) - 1) / 32;
max_y = ((y + height) - 1) / 32;
// Copy into the header, clamping to the acceptable range as we go
user_clip.d1 = CLAMP(min_x, 0, screen_width);
user_clip.d2 = CLAMP(min_y, 0, screen_height);
user_clip.d3 = CLAMP(max_x, 0, screen_width);
user_clip.d4 = CLAMP(max_y, 0, screen_height);
// Send the clipping rectangle command
pvr_prim(&user_clip, sizeof(user_clip));
}
If you need finer clipping than that, there's no hardware mechanism to help you. You'll have to clip the tiles manually against the viewing area.