Dreamcast: Tidy up code a bit more

This commit is contained in:
UnknownShadow200 2024-10-15 21:00:15 +11:00
parent 5687f8070c
commit a9868556a3
5 changed files with 150 additions and 235 deletions

View File

@ -23,6 +23,7 @@ jobs:
run: |
wget https://cdn.classicube.net/client/latest/ClassiCube.64.exe -O cc-w64.exe
wget https://cdn.classicube.net/client/latest/ClassiCube.exe -O cc-w32.exe
wget https://cdn.classicube.net/client/latest/cc-w9x.exe -O cc-w9x.exe
# Download Linux artifacts
- name: Retrieve Linux binaries
@ -162,6 +163,12 @@ jobs:
SOURCE_FILE: 'cc-win64.zip'
DEST_NAME: 'cc-win64.zip'
- uses: ./.github/actions/upload_build
if: ${{ always() && steps.compile.outcome == 'success' }}
with:
SOURCE_FILE: 'cc-w9x.exe'
DEST_NAME: 'cc-win9x.exe'
# Generate RPI release files
- uses: ./.github/actions/upload_build

View File

@ -5,6 +5,7 @@
#include "Logger.h"
#include "Window.h"
#include <malloc.h>
#include <string.h>
#include <kos.h>
#include <dc/matrix.h>
#include <dc/pvr.h>
@ -12,22 +13,60 @@
static cc_bool renderingDisabled;
static cc_bool stateDirty;
#define VERTEX_BUFFER_SIZE 32 * 40000
#define PT_ALPHA_REF 0x011c
#define MAX_TEXTURE_COUNT 768
/*########################################################################################################################*
*-------------------------------------------------------Vertex list-------------------------------------------------------*
*------------------------------------------------------Commands list------------------------------------------------------*
*#########################################################################################################################*/
static void VertexList_Append(AlignedVector* list, const void* cmd) {
void* dst = aligned_vector_reserve(list, list->size + 1);
assert(dst);
#define VERTEX_SIZE 32
memcpy(dst, cmd, VERTEX_SIZE);
list->size++;
struct CommandsList {
uint32_t length;
uint32_t capacity;
uint32_t list_type;
uint8_t* data;
} __attribute__((aligned(32)));
// e.g. 1 -> 256, 50 -> 256, 256 -> 256
#define ROUND_UP_256(v) (((v) + 0xFFu) & ~0xFFu)
static CC_INLINE void* CommandsList_Reserve(struct CommandsList* list, cc_uint32 count) {
cc_uint32 cur_size = list->length * VERTEX_SIZE;
if (count < list->capacity) {
return list->data + cur_size;
}
/* We overallocate so that we don't make small allocations during push backs */
count = ROUND_UP_256(count);
cc_uint32 new_size = count * VERTEX_SIZE;
cc_uint8* cur_data = list->data;
cc_uint8* data = (cc_uint8*)memalign(0x20, new_size);
if (!data) return NULL;
memcpy(data, cur_data, cur_size);
free(cur_data);
list->data = data;
list->capacity = count;
return data + cur_size;
}
static void CommandsList_Append(struct CommandsList* list, const void* cmd) {
void* dst = CommandsList_Reserve(list, list->length + 1);
if (!dst) Logger_Abort("Out of memory");
memcpy(dst, cmd, VERTEX_SIZE);
list->length++;
}
/*########################################################################################################################*
*-----------------------------------------------------Texture memory------------------------------------------------------*
*#########################################################################################################################*/
@ -163,16 +202,16 @@ static cc_uint32 texmem_total_used(void) {
/*########################################################################################################################*
*---------------------------------------------------------General---------------------------------------------------------*
*#########################################################################################################################*/
static AlignedVector listOP;
static AlignedVector listPT;
static AlignedVector listTR;
static struct CommandsList listOP;
static struct CommandsList listPT;
static struct CommandsList listTR;
// For faster performance, instead of having all 3 lists buffer everything first
// and then have all the buffered data submitted to the TA (i.e. drawn) at the end of the frame,
// instead have the most common list have data directly submitted to the TA throughout the frame
static AlignedVector* direct = &listPT;
static struct CommandsList* direct = &listPT;
static cc_bool exceeded_vram;
static CC_INLINE AlignedVector* ActivePolyList(void) {
static CC_INLINE struct CommandsList* ActivePolyList(void) {
if (gfx_alphaBlend) return &listTR;
if (gfx_alphaTest) return &listPT;
@ -215,13 +254,13 @@ static void InitGLState(void) {
FOG_ENABLED = false;
stateDirty = true;
listOP.list_type = PVR_LIST_OP_POLY;
listPT.list_type = PVR_LIST_PT_POLY;
listTR.list_type = PVR_LIST_TR_POLY;
listOP.list_type = PVR_LIST_OP_POLY;
listPT.list_type = PVR_LIST_PT_POLY;
listTR.list_type = PVR_LIST_TR_POLY;
aligned_vector_reserve(&listOP, 1024 * 3);
aligned_vector_reserve(&listPT, 512 * 3);
aligned_vector_reserve(&listTR, 1024 * 3);
CommandsList_Reserve(&listOP, 1024 * 3);
CommandsList_Reserve(&listPT, 512 * 3);
CommandsList_Reserve(&listTR, 1024 * 3);
}
void Gfx_Create(void) {
@ -708,11 +747,11 @@ static cc_bool loggedNoVRAM;
extern Vertex* DrawColouredQuads(const void* src, Vertex* dst, int numQuads);
extern Vertex* DrawTexturedQuads(const void* src, Vertex* dst, int numQuads);
static Vertex* ReserveOutput(AlignedVector* vec, cc_uint32 elems) {
static Vertex* ReserveOutput(struct CommandsList* list, cc_uint32 elems) {
Vertex* beg;
for (;;)
{
if ((beg = aligned_vector_reserve(vec, elems))) return beg;
if ((beg = CommandsList_Reserve(list, elems))) return beg;
// Try to reduce view distance to save on RAM
if (Game_ReduceVRAM()) continue;
@ -726,18 +765,18 @@ static Vertex* ReserveOutput(AlignedVector* vec, cc_uint32 elems) {
void DrawQuads(int count, void* src) {
if (!count) return;
AlignedVector* vec = ActivePolyList();
struct CommandsList* list = ActivePolyList();
cc_uint32 header_required = (vec->size == 0) || stateDirty;
cc_uint32 header_required = (list->length == 0) || stateDirty;
// Reserve room for the vertices and header
Vertex* beg = ReserveOutput(vec, vec->size + (header_required) + count);
Vertex* beg = ReserveOutput(list, list->length + (header_required) + count);
if (!beg) return;
if (header_required) {
apply_poly_header((pvr_poly_hdr_t*)beg, vec->list_type);
apply_poly_header((pvr_poly_hdr_t*)beg, list->list_type);
stateDirty = false;
beg++;
vec->size += 1;
list->length++;
beg++;
}
Vertex* end;
@ -746,11 +785,11 @@ void DrawQuads(int count, void* src) {
} else {
end = DrawColouredQuads(src, beg, count >> 2);
}
vec->size += (end - beg);
list->length += (end - beg);
if (vec != direct) return;
SceneListSubmit((Vertex*)vec->data, vec->size);
vec->size = 0;
if (list != direct) return;
SceneListSubmit((Vertex*)list->data, list->length);
list->length = 0;
}
void Gfx_SetVertexFormat(VertexFormat fmt) {
@ -834,7 +873,7 @@ static void FinishList(void) {
}
void Gfx_BeginFrame(void) {
pvr_scene_begin();
pvr_scene_begin();
// Directly render PT list, buffer other lists first
BeginList(PVR_LIST_PT_POLY);
if (!exceeded_vram) return;
@ -843,13 +882,13 @@ void Gfx_BeginFrame(void) {
Game_ReduceVRAM();
}
static void SubmitList(AlignedVector* cmds) {
if (!cmds->size || cmds == direct) return;
static void SubmitList(struct CommandsList* list) {
if (!list->length || list == direct) return;
BeginList(cmds->list_type);
SceneListSubmit((Vertex*)cmds->data, cmds->size);
BeginList(list->list_type);
SceneListSubmit((Vertex*)list->data, list->length);
FinishList();
cmds->size = 0;
list->length = 0;
}
void Gfx_EndFrame(void) {
@ -859,7 +898,7 @@ void Gfx_EndFrame(void) {
SubmitList(&listOP);
SubmitList(&listPT);
SubmitList(&listTR);
pvr_scene_finish();
pvr_scene_finish();
}
void Gfx_OnWindowResize(void) {
@ -886,8 +925,8 @@ void Gfx_SetScissor(int x, int y, int w, int h) {
c.d3 = ((x + w) >> 5) - 1;
c.d4 = ((y + h) >> 5) - 1;
VertexList_Append(&listOP, &c);
VertexList_Append(&listPT, &c);
VertexList_Append(&listTR, &c);
CommandsList_Append(&listOP, &c);
CommandsList_Append(&listPT, &c);
CommandsList_Append(&listTR, &c);
}
#endif

View File

@ -1,50 +1,6 @@
#ifndef PRIVATE_H
#define PRIVATE_H
#include <stdint.h>
#include <assert.h>
#include <string.h>
#include <stdint.h>
#include <malloc.h>
#define AV_FORCE_INLINE static __attribute__((always_inline)) inline
#define VERTEX_SIZE 32
typedef struct {
uint32_t size;
uint32_t capacity;
uint32_t list_type;
uint8_t* data;
} __attribute__((aligned(32))) AlignedVector;
#define ALIGNED_VECTOR_CHUNK_SIZE 256u
#define ROUND_TO_CHUNK_SIZE(v) \
((((v) + ALIGNED_VECTOR_CHUNK_SIZE - 1) / ALIGNED_VECTOR_CHUNK_SIZE) * ALIGNED_VECTOR_CHUNK_SIZE)
AV_FORCE_INLINE void* aligned_vector_reserve(AlignedVector* vector, uint32_t element_count) {
uint32_t original_byte_size = (vector->size * VERTEX_SIZE);
if(element_count < vector->capacity) {
return vector->data + original_byte_size;
}
/* We overallocate so that we don't make small allocations during push backs */
element_count = ROUND_TO_CHUNK_SIZE(element_count);
uint32_t new_byte_size = (element_count * VERTEX_SIZE);
uint8_t* original_data = vector->data;
uint8_t* data = (uint8_t*) memalign(0x20, new_byte_size);
if (!data) return NULL;
memcpy(data, original_data, original_byte_size);
free(original_data);
vector->data = data;
vector->capacity = element_count;
return data + original_byte_size;
}
#define GLenum unsigned int
#define GLboolean unsigned char
@ -54,7 +10,7 @@ typedef struct {
uint32_t flags;
float x, y, z;
float u, v;
uint8_t bgra[4];
uint32_t bgra;
/* In the pvr_vertex_t structure, this next 4 bytes is oargb
* but we're not using that for now, so having W here makes the code

View File

@ -21,6 +21,10 @@ static GL_FORCE_INLINE float _glFastInvert(float x) {
return sh4_fsrra(x * x);
}
#define PushVertex(v) \
_glPerspectiveDivideVertex(v); \
_glPushHeaderOrVertex(v);
static GL_FORCE_INLINE void _glPerspectiveDivideVertex(Vertex* vertex) {
const float f = _glFastInvert(vertex->w);
@ -72,14 +76,9 @@ static void SubmitClipped(Vertex* v0, Vertex* v1, Vertex* v2, Vertex* v3, uint8_
ClipEdge(v0, v1, b);
b->flags = PVR_CMD_VERTEX;
_glPerspectiveDivideVertex(v0);
_glPushHeaderOrVertex(v0);
_glPerspectiveDivideVertex(b);
_glPushHeaderOrVertex(b);
_glPerspectiveDivideVertex(a);
_glPushHeaderOrVertex(a);
PushVertex(v0);
PushVertex(b);
PushVertex(a);
}
break;
case V1_VIS:
@ -95,14 +94,9 @@ static void SubmitClipped(Vertex* v0, Vertex* v1, Vertex* v2, Vertex* v3, uint8_
ClipEdge(v1, v2, b);
b->flags = PVR_CMD_VERTEX_EOL;
_glPerspectiveDivideVertex(a);
_glPushHeaderOrVertex(a);
_glPerspectiveDivideVertex(v1);
_glPushHeaderOrVertex(v1);
_glPerspectiveDivideVertex(b);
_glPushHeaderOrVertex(b);
PushVertex(a);
PushVertex(v1);
PushVertex(b);
} break;
case V2_VIS:
{
@ -118,14 +112,9 @@ static void SubmitClipped(Vertex* v0, Vertex* v1, Vertex* v2, Vertex* v3, uint8_
ClipEdge(v2, v3, b);
b->flags = PVR_CMD_VERTEX_EOL;
_glPerspectiveDivideVertex(a);
_glPushHeaderOrVertex(a);
_glPerspectiveDivideVertex(v2);
_glPushHeaderOrVertex(v2);
_glPerspectiveDivideVertex(b);
_glPushHeaderOrVertex(b);
PushVertex(a);
PushVertex(v2);
PushVertex(b);
} break;
case V3_VIS:
{
@ -140,14 +129,9 @@ static void SubmitClipped(Vertex* v0, Vertex* v1, Vertex* v2, Vertex* v3, uint8_
ClipEdge(v3, v0, b);
b->flags = PVR_CMD_VERTEX;
_glPerspectiveDivideVertex(b);
_glPushHeaderOrVertex(b);
_glPerspectiveDivideVertex(a);
_glPushHeaderOrVertex(a);
_glPerspectiveDivideVertex(v3);
_glPushHeaderOrVertex(v3);
PushVertex(b);
PushVertex(a);
PushVertex(v3);
}
break;
case V0_VIS | V1_VIS:
@ -162,17 +146,10 @@ static void SubmitClipped(Vertex* v0, Vertex* v1, Vertex* v2, Vertex* v3, uint8_
ClipEdge(v3, v0, b);
b->flags = PVR_CMD_VERTEX_EOL;
_glPerspectiveDivideVertex(v1);
_glPushHeaderOrVertex(v1);
_glPerspectiveDivideVertex(a);
_glPushHeaderOrVertex(a);
_glPerspectiveDivideVertex(v0);
_glPushHeaderOrVertex(v0);
_glPerspectiveDivideVertex(b);
_glPushHeaderOrVertex(b);
PushVertex(v1);
PushVertex(a);
PushVertex(v0);
PushVertex(b);
} break;
// case V0_VIS | V2_VIS: degenerate case that should never happen
case V0_VIS | V3_VIS:
@ -187,17 +164,10 @@ static void SubmitClipped(Vertex* v0, Vertex* v1, Vertex* v2, Vertex* v3, uint8_
ClipEdge(v2, v3, b);
b->flags = PVR_CMD_VERTEX;
_glPerspectiveDivideVertex(a);
_glPushHeaderOrVertex(a);
_glPerspectiveDivideVertex(b);
_glPushHeaderOrVertex(b);
_glPerspectiveDivideVertex(v0);
_glPushHeaderOrVertex(v0);
_glPerspectiveDivideVertex(v3);
_glPushHeaderOrVertex(v3);
PushVertex(a);
PushVertex(b);
PushVertex(v0);
PushVertex(v3);
} break;
case V1_VIS | V2_VIS:
{
@ -211,17 +181,10 @@ static void SubmitClipped(Vertex* v0, Vertex* v1, Vertex* v2, Vertex* v3, uint8_
ClipEdge(v0, v1, b);
b->flags = PVR_CMD_VERTEX;
_glPerspectiveDivideVertex(v1);
_glPushHeaderOrVertex(v1);
_glPerspectiveDivideVertex(v2);
_glPushHeaderOrVertex(v2);
_glPerspectiveDivideVertex(b);
_glPushHeaderOrVertex(b);
_glPerspectiveDivideVertex(a);
_glPushHeaderOrVertex(a);
PushVertex(v1);
PushVertex(v2);
PushVertex(b);
PushVertex(a);
} break;
// case V1_VIS | V3_VIS: degenerate case that should never happen
case V2_VIS | V3_VIS:
@ -236,17 +199,10 @@ static void SubmitClipped(Vertex* v0, Vertex* v1, Vertex* v2, Vertex* v3, uint8_
ClipEdge(v1, v2, b);
b->flags = PVR_CMD_VERTEX;
_glPerspectiveDivideVertex(b);
_glPushHeaderOrVertex(b);
_glPerspectiveDivideVertex(v2);
_glPushHeaderOrVertex(v2);
_glPerspectiveDivideVertex(a);
_glPushHeaderOrVertex(a);
_glPerspectiveDivideVertex(v3);
_glPushHeaderOrVertex(v3);
PushVertex(b);
PushVertex(v2);
PushVertex(a);
PushVertex(v3);
} break;
case V0_VIS | V1_VIS | V2_VIS:
{
@ -262,20 +218,11 @@ static void SubmitClipped(Vertex* v0, Vertex* v1, Vertex* v2, Vertex* v3, uint8_
ClipEdge(v3, v0, b);
b->flags = PVR_CMD_VERTEX_EOL;
_glPerspectiveDivideVertex(v1);
_glPushHeaderOrVertex(v1);
_glPerspectiveDivideVertex(v2);
_glPushHeaderOrVertex(v2);
_glPerspectiveDivideVertex(v0);
_glPushHeaderOrVertex(v0);
_glPerspectiveDivideVertex(a);
_glPushHeaderOrVertex(a);
_glPerspectiveDivideVertex(b);
_glPushHeaderOrVertex(b);
PushVertex(v1);
PushVertex(v2);
PushVertex(v0);
PushVertex(a);
PushVertex(b);
} break;
case V0_VIS | V1_VIS | V3_VIS:
{
@ -292,20 +239,11 @@ static void SubmitClipped(Vertex* v0, Vertex* v1, Vertex* v2, Vertex* v3, uint8_
b->flags = PVR_CMD_VERTEX_EOL;
v3->flags = PVR_CMD_VERTEX;
_glPerspectiveDivideVertex(v0);
_glPushHeaderOrVertex(v0);
_glPerspectiveDivideVertex(v1);
_glPushHeaderOrVertex(v1);
_glPerspectiveDivideVertex(v3);
_glPushHeaderOrVertex(v3);
_glPerspectiveDivideVertex(a);
_glPushHeaderOrVertex(a);
_glPerspectiveDivideVertex(b);
_glPushHeaderOrVertex(b);
PushVertex(v0);
PushVertex(v1);
PushVertex(v3);
PushVertex(a);
PushVertex(b);
} break;
case V0_VIS | V2_VIS | V3_VIS:
{
@ -322,20 +260,11 @@ static void SubmitClipped(Vertex* v0, Vertex* v1, Vertex* v2, Vertex* v3, uint8_
b->flags = PVR_CMD_VERTEX_EOL;
v3->flags = PVR_CMD_VERTEX;
_glPerspectiveDivideVertex(v3);
_glPushHeaderOrVertex(v3);
_glPerspectiveDivideVertex(v0);
_glPushHeaderOrVertex(v0);
_glPerspectiveDivideVertex(v2);
_glPushHeaderOrVertex(v2);
_glPerspectiveDivideVertex(a);
_glPushHeaderOrVertex(a);
_glPerspectiveDivideVertex(b);
_glPushHeaderOrVertex(b);
PushVertex(v3);
PushVertex(v0);
PushVertex(v2);
PushVertex(a);
PushVertex(b);
} break;
case V1_VIS | V2_VIS | V3_VIS:
{
@ -352,20 +281,12 @@ static void SubmitClipped(Vertex* v0, Vertex* v1, Vertex* v2, Vertex* v3, uint8_
b->flags = PVR_CMD_VERTEX_EOL;
v3->flags = PVR_CMD_VERTEX;
_glPerspectiveDivideVertex(v2);
_glPushHeaderOrVertex(v2);
_glPerspectiveDivideVertex(v3);
_glPushHeaderOrVertex(v3);
_glPerspectiveDivideVertex(v1);
_glPushHeaderOrVertex(v1);
_glPerspectiveDivideVertex(a);
_glPushHeaderOrVertex(a);
_glPerspectiveDivideVertex(b);
_glPushHeaderOrVertex(b);
PushVertex(v2);
PushVertex(v3);
PushVertex(v3);
PushVertex(v1);
PushVertex(a);
PushVertex(b);
} break;
}
}
@ -408,17 +329,10 @@ void SceneListSubmit(Vertex* v3, int n) {
case V0_VIS | V1_VIS | V2_VIS | V3_VIS: // All vertices visible
{
// Triangle strip: {1,2,0} {2,0,3}
_glPerspectiveDivideVertex(v1);
_glPushHeaderOrVertex(v1);
_glPerspectiveDivideVertex(v2);
_glPushHeaderOrVertex(v2);
_glPerspectiveDivideVertex(v0);
_glPushHeaderOrVertex(v0);
_glPerspectiveDivideVertex(v3);
_glPushHeaderOrVertex(v3);
PushVertex(v1);
PushVertex(v2);
PushVertex(v0);
PushVertex(v3);
}
break;

View File

@ -34,7 +34,6 @@ static inline int DimensionFlag(int w) {
}
}
#define DEFAULT_MIPMAP_BIAS 4
void apply_poly_header(pvr_poly_hdr_t* dst, int list_type) {
TextureObject* tx1 = TEXTURE_ACTIVE;
@ -42,8 +41,8 @@ void apply_poly_header(pvr_poly_hdr_t* dst, int list_type) {
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_clip_mode = SCISSOR_TEST_ENABLED ? PVR_USERCLIP_INSIDE : PVR_USERCLIP_DISABLE;
int gen_fog_type = FOG_ENABLED ? PVR_FOG_TABLE : PVR_FOG_DISABLE;
int clip_mode = SCISSOR_TEST_ENABLED ? PVR_USERCLIP_INSIDE : PVR_USERCLIP_DISABLE;
int 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;
@ -81,17 +80,17 @@ void apply_poly_header(pvr_poly_hdr_t* dst, int list_type) {
dst->cmd |= (PVR_CLRFMT_ARGBPACKED << PVR_TA_CMD_CLRFMT_SHIFT) & PVR_TA_CMD_CLRFMT_MASK;
dst->cmd |= (SHADE_MODEL << 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;
dst->cmd |= (clip_mode << PVR_TA_CMD_USERCLIP_SHIFT) & PVR_TA_CMD_USERCLIP_MASK;
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;
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_alpha << PVR_TA_PM2_ALPHA_SHIFT) & PVR_TA_PM2_ALPHA_MASK;
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 |= (fog_type << PVR_TA_PM2_FOG_SHIFT) & PVR_TA_PM2_FOG_MASK;
dst->mode2 |= (gen_alpha << PVR_TA_PM2_ALPHA_SHIFT) & PVR_TA_PM2_ALPHA_MASK;
if (txr_enable == PVR_TEXTURE_DISABLE) {
dst->mode3 = 0;