mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-26 06:10:56 +00:00
[sw] Take advantage of the ECS for edge rendering
This fixes the segfault due to the world entity not actually existing, without adding a world entity. It takes advantage of the ECS in that the edge renderer needs only the world matrix, brush model pointer, and the animation frame number (which is just 0/1 for brush models), thus the inherent SOA of ECS helps out, though benchmarking is needed to see if it made any real difference. With this, all 4 renderers are working again.
This commit is contained in:
parent
2a9fcf4f5f
commit
20c861027e
18 changed files with 168 additions and 82 deletions
|
@ -166,6 +166,7 @@ typedef struct {
|
||||||
int ambientlight;
|
int ambientlight;
|
||||||
int drawflat;
|
int drawflat;
|
||||||
|
|
||||||
|
struct ecs_registry_s *registry;
|
||||||
struct model_s *worldmodel;
|
struct model_s *worldmodel;
|
||||||
} refdef_t;
|
} refdef_t;
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,13 @@ enum scene_components {
|
||||||
scene_active,
|
scene_active,
|
||||||
scene_old_origin, //XXX FIXME XXX should not be here
|
scene_old_origin, //XXX FIXME XXX should not be here
|
||||||
|
|
||||||
|
//FIXME these should probably be private to the sw renderer (and in a
|
||||||
|
//group, which needs to be implemented), but need to sort out a good
|
||||||
|
//scheme for semi-dynamic components
|
||||||
|
scene_sw_matrix, // world transform matrix
|
||||||
|
scene_sw_frame, // animation frame
|
||||||
|
scene_sw_brush, // brush model data pointer
|
||||||
|
|
||||||
scene_num_components
|
scene_num_components
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -201,7 +201,7 @@ typedef struct
|
||||||
|
|
||||||
extern drawsurf_t r_drawsurf;
|
extern drawsurf_t r_drawsurf;
|
||||||
struct transform_s;
|
struct transform_s;
|
||||||
void R_DrawSurface (struct transform_s transform);
|
void R_DrawSurface (uint32_t render_id);
|
||||||
void R_GenTile (msurface_t *psurf, void *pdest);
|
void R_GenTile (msurface_t *psurf, void *pdest);
|
||||||
|
|
||||||
// !!! if this is changed, it must be changed in d_iface.h too !!!
|
// !!! if this is changed, it must be changed in d_iface.h too !!!
|
||||||
|
|
|
@ -92,7 +92,7 @@ void D_DrawSkyScans (struct espan_s *pspan);
|
||||||
void R_ShowSubDiv (void);
|
void R_ShowSubDiv (void);
|
||||||
extern void (*prealspandrawer)(void);
|
extern void (*prealspandrawer)(void);
|
||||||
struct entity_s;
|
struct entity_s;
|
||||||
surfcache_t *D_CacheSurface (struct entity_s ent,
|
surfcache_t *D_CacheSurface (uint32_t render_id,
|
||||||
msurface_t *surface, int miplevel);
|
msurface_t *surface, int miplevel);
|
||||||
|
|
||||||
int D_MipLevelForScale (float scale) __attribute__((pure));
|
int D_MipLevelForScale (float scale) __attribute__((pure));
|
||||||
|
|
|
@ -21,6 +21,7 @@ extern vid_render_funcs_t *vid_render_funcs;
|
||||||
#define vr_funcs vid_render_funcs
|
#define vr_funcs vid_render_funcs
|
||||||
|
|
||||||
extern refdef_t r_refdef;
|
extern refdef_t r_refdef;
|
||||||
|
#define SW_COMP(comp, id) ((void *)((byte *)r_refdef.registry->comp_pools[comp].data + (id) * r_refdef.registry->components[comp].size))
|
||||||
extern int r_viewsize;
|
extern int r_viewsize;
|
||||||
|
|
||||||
void R_LineGraph (int x, int y, int *h_vals, int count, int height);
|
void R_LineGraph (int x, int y, int *h_vals, int count, int height);
|
||||||
|
|
|
@ -150,18 +150,18 @@ struct animation_s;
|
||||||
void R_SpriteBegin (void);
|
void R_SpriteBegin (void);
|
||||||
void R_SpriteEnd (void);
|
void R_SpriteEnd (void);
|
||||||
void R_DrawSprite (struct entity_s ent);
|
void R_DrawSprite (struct entity_s ent);
|
||||||
void R_RenderFace (struct entity_s ent, msurface_t *fa, int clipflags);
|
void R_RenderFace (uint32_t render_id, msurface_t *fa, int clipflags);
|
||||||
void R_RenderPoly (struct entity_s ent, msurface_t *fa, int clipflags);
|
void R_RenderPoly (uint32_t render_id, msurface_t *fa, int clipflags);
|
||||||
void R_RenderBmodelFace (struct entity_s ent, bedge_t *pedges, msurface_t *psurf);
|
void R_RenderBmodelFace (uint32_t render_id, bedge_t *pedges, msurface_t *psurf);
|
||||||
void R_TransformFrustum (void);
|
void R_TransformFrustum (void);
|
||||||
void R_SetSkyFrame (void);
|
void R_SetSkyFrame (void);
|
||||||
void R_DrawSurfaceBlock (void);
|
void R_DrawSurfaceBlock (void);
|
||||||
struct texture_s *R_TextureAnimation (const struct animation_s *animation, msurface_t *surf) __attribute__((pure));
|
struct texture_s *R_TextureAnimation (int frame, msurface_t *surf) __attribute__((pure));
|
||||||
|
|
||||||
void R_GenSkyTile (void *pdest);
|
void R_GenSkyTile (void *pdest);
|
||||||
void R_SurfPatch (void);
|
void R_SurfPatch (void);
|
||||||
void R_DrawSubmodelPolygons (struct entity_s ent, model_t *pmodel, int clipflags, struct mleaf_s *topleaf);
|
void R_DrawSubmodelPolygons (uint32_t render_id, mod_brush_t *brush, int clipflags, struct mleaf_s *topleaf);
|
||||||
void R_DrawSolidClippedSubmodelPolygons (struct entity_s ent, model_t *pmodel, struct mnode_s *topnode);
|
void R_DrawSolidClippedSubmodelPolygons (uint32_t render_id, mod_brush_t *brush, struct mnode_s *topnode);
|
||||||
|
|
||||||
void R_AddPolygonEdges (emitpoint_t *pverts, int numverts, int miplevel);
|
void R_AddPolygonEdges (emitpoint_t *pverts, int numverts, int miplevel);
|
||||||
surf_t *R_GetSurf (void);
|
surf_t *R_GetSurf (void);
|
||||||
|
@ -198,7 +198,7 @@ extern void R_EdgeCodeStart (void);
|
||||||
extern void R_EdgeCodeEnd (void);
|
extern void R_EdgeCodeEnd (void);
|
||||||
|
|
||||||
struct transform_s;
|
struct transform_s;
|
||||||
extern void R_RotateBmodel (struct transform_s transform);
|
extern void R_RotateBmodel (vec4f_t *mat);
|
||||||
|
|
||||||
extern int c_faceclip;
|
extern int c_faceclip;
|
||||||
extern int r_polycount;
|
extern int r_polycount;
|
||||||
|
@ -230,7 +230,7 @@ typedef struct btofpoly_s {
|
||||||
extern int numbtofpolys;
|
extern int numbtofpolys;
|
||||||
|
|
||||||
void R_InitTurb (void);
|
void R_InitTurb (void);
|
||||||
void R_ZDrawSubmodelPolys (struct entity_s ent, model_t *clmodel);
|
void R_ZDrawSubmodelPolys (uint32_t render_id, mod_brush_t *brush);
|
||||||
|
|
||||||
// Alias models ===========================================
|
// Alias models ===========================================
|
||||||
|
|
||||||
|
|
|
@ -99,7 +99,7 @@ typedef struct surf_s {
|
||||||
// start)
|
// start)
|
||||||
int flags; // currentface flags
|
int flags; // currentface flags
|
||||||
void *data; // associated data like msurface_t
|
void *data; // associated data like msurface_t
|
||||||
entity_t entity;
|
uint32_t render_id;
|
||||||
float nearzi; // nearest 1/z on surface, for mipmapping
|
float nearzi; // nearest 1/z on surface, for mipmapping
|
||||||
qboolean insubmodel;
|
qboolean insubmodel;
|
||||||
float d_ziorigin, d_zistepu, d_zistepv;
|
float d_ziorigin, d_zistepu, d_zistepv;
|
||||||
|
@ -163,4 +163,6 @@ typedef struct edge_s
|
||||||
extern float r_avertexnormals[NUMVERTEXNORMALS][3];
|
extern float r_avertexnormals[NUMVERTEXNORMALS][3];
|
||||||
extern vec3_t ambientcolor;
|
extern vec3_t ambientcolor;
|
||||||
|
|
||||||
|
uint32_t SW_AddEntity (entity_t ent);
|
||||||
|
|
||||||
#endif // _R_SHARED_H
|
#endif // _R_SHARED_H
|
||||||
|
|
|
@ -60,6 +60,27 @@ create_old_origin (void *_old_origin)
|
||||||
*old_origin = (vec4f_t) {0, 0, 0, 1};
|
*old_origin = (vec4f_t) {0, 0, 0, 1};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sw_identity_matrix (void *_mat)
|
||||||
|
{
|
||||||
|
mat4f_t *mat = _mat;
|
||||||
|
mat4fidentity (*mat);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sw_frame_0 (void *_frame)
|
||||||
|
{
|
||||||
|
byte *frame = _frame;
|
||||||
|
*frame = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
sw_null_brush (void *_brush)
|
||||||
|
{
|
||||||
|
struct mod_brush_s **brush = _brush;
|
||||||
|
*brush = 0;
|
||||||
|
}
|
||||||
|
|
||||||
static const component_t scene_components[] = {
|
static const component_t scene_components[] = {
|
||||||
[scene_href] = {
|
[scene_href] = {
|
||||||
.size = sizeof (hierref_t),
|
.size = sizeof (hierref_t),
|
||||||
|
@ -91,6 +112,22 @@ static const component_t scene_components[] = {
|
||||||
.create = create_old_origin,
|
.create = create_old_origin,
|
||||||
.name = "old_origin",
|
.name = "old_origin",
|
||||||
},
|
},
|
||||||
|
|
||||||
|
[scene_sw_matrix] = {
|
||||||
|
.size = sizeof (mat4f_t),
|
||||||
|
.create = sw_identity_matrix,
|
||||||
|
.name = "sw world transform",
|
||||||
|
},
|
||||||
|
[scene_sw_frame] = {
|
||||||
|
.size = sizeof (byte),
|
||||||
|
.create = sw_frame_0,
|
||||||
|
.name = "sw brush model animation frame",
|
||||||
|
},
|
||||||
|
[scene_sw_brush] = {
|
||||||
|
.size = sizeof (struct mod_brush_s *),
|
||||||
|
.create = sw_null_brush,
|
||||||
|
.name = "sw brush model data pointer",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static byte empty_visdata[] = { 0x01 };
|
static byte empty_visdata[] = { 0x01 };
|
||||||
|
|
|
@ -486,7 +486,7 @@ chain_surface (glbspctx_t *bctx, msurface_t *surf)
|
||||||
if (!surf->texinfo->texture->anim_total)
|
if (!surf->texinfo->texture->anim_total)
|
||||||
tx = surf->texinfo->texture;
|
tx = surf->texinfo->texture;
|
||||||
else
|
else
|
||||||
tx = R_TextureAnimation (bctx->animation, surf);
|
tx = R_TextureAnimation (bctx->animation->frame, surf);
|
||||||
tex = tx->render;
|
tex = tx->render;
|
||||||
sc = CHAIN_SURF_F2B (surf, tex->tex_chain);
|
sc = CHAIN_SURF_F2B (surf, tex->tex_chain);
|
||||||
|
|
||||||
|
|
|
@ -399,7 +399,7 @@ chain_surface (glslbspctx_t *bctx, msurface_t *surf)
|
||||||
if (!surf->texinfo->texture->anim_total)
|
if (!surf->texinfo->texture->anim_total)
|
||||||
tx = surf->texinfo->texture;
|
tx = surf->texinfo->texture;
|
||||||
else
|
else
|
||||||
tx = R_TextureAnimation (bctx->animation, surf);
|
tx = R_TextureAnimation (bctx->animation->frame, surf);
|
||||||
tex = tx->render;
|
tex = tx->render;
|
||||||
is = CHAIN_SURF_F2B (surf, tex->tex_chain);
|
is = CHAIN_SURF_F2B (surf, tex->tex_chain);
|
||||||
|
|
||||||
|
|
|
@ -103,12 +103,12 @@ R_MarkLeaves (mleaf_t *viewleaf, int *node_visframes, int *leaf_visframes,
|
||||||
Returns the proper texture for a given time and base texture
|
Returns the proper texture for a given time and base texture
|
||||||
*/
|
*/
|
||||||
texture_t *
|
texture_t *
|
||||||
R_TextureAnimation (const animation_t *animation, msurface_t *surf)
|
R_TextureAnimation (int frame, msurface_t *surf)
|
||||||
{
|
{
|
||||||
texture_t *base = surf->texinfo->texture;
|
texture_t *base = surf->texinfo->texture;
|
||||||
int count, relative;
|
int count, relative;
|
||||||
|
|
||||||
if (animation->frame) {
|
if (frame) {
|
||||||
if (base->alternate_anims)
|
if (base->alternate_anims)
|
||||||
base = base->alternate_anims;
|
base = base->alternate_anims;
|
||||||
}
|
}
|
||||||
|
|
|
@ -150,12 +150,11 @@ transform_submodel_poly (surf_t *s)
|
||||||
{
|
{
|
||||||
// FIXME: we don't want to do all this for every polygon!
|
// FIXME: we don't want to do all this for every polygon!
|
||||||
// TODO: store once at start of frame
|
// TODO: store once at start of frame
|
||||||
transform_t transform = Entity_Transform (s->entity);
|
vec4f_t *transform = SW_COMP(scene_sw_matrix, s->render_id);
|
||||||
vec4f_t local_modelorg = r_refdef.frame.position -
|
vec4f_t local_modelorg = r_refdef.frame.position - transform[3];
|
||||||
Transform_GetWorldPosition (transform);
|
|
||||||
TransformVector ((vec_t*)&local_modelorg, transformed_modelorg);//FIXME
|
TransformVector ((vec_t*)&local_modelorg, transformed_modelorg);//FIXME
|
||||||
|
|
||||||
R_RotateBmodel (transform); // FIXME: don't mess with the
|
R_RotateBmodel (transform); // FIXME: don't mess with the
|
||||||
// frustum, make entity passed in
|
// frustum, make entity passed in
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -249,7 +248,7 @@ D_DrawSurfaces (void)
|
||||||
* pface->texinfo->mipadjust);
|
* pface->texinfo->mipadjust);
|
||||||
|
|
||||||
// FIXME: make this passed in to D_CacheSurface
|
// FIXME: make this passed in to D_CacheSurface
|
||||||
pcurrentcache = D_CacheSurface (s->entity, pface, miplevel);
|
pcurrentcache = D_CacheSurface (s->render_id, pface, miplevel);
|
||||||
|
|
||||||
cacheblock = (byte *) pcurrentcache->data;
|
cacheblock = (byte *) pcurrentcache->data;
|
||||||
cachewidth = pcurrentcache->width;
|
cachewidth = pcurrentcache->width;
|
||||||
|
|
|
@ -227,14 +227,13 @@ D_SCDump (void)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
surfcache_t *
|
surfcache_t *
|
||||||
D_CacheSurface (entity_t ent, msurface_t *surface, int miplevel)
|
D_CacheSurface (uint32_t render_id, msurface_t *surface, int miplevel)
|
||||||
{
|
{
|
||||||
surfcache_t *cache;
|
surfcache_t *cache;
|
||||||
animation_t *animation = Ent_GetComponent (ent.id, scene_animation,
|
byte frame = *(byte *) SW_COMP (scene_sw_frame, render_id);
|
||||||
ent.reg);
|
|
||||||
|
|
||||||
// if the surface is animating or flashing, flush the cache
|
// if the surface is animating or flashing, flush the cache
|
||||||
r_drawsurf.texture = R_TextureAnimation (animation, surface);
|
r_drawsurf.texture = R_TextureAnimation (frame, surface);
|
||||||
r_drawsurf.lightadj[0] = d_lightstylevalue[surface->styles[0]];
|
r_drawsurf.lightadj[0] = d_lightstylevalue[surface->styles[0]];
|
||||||
r_drawsurf.lightadj[1] = d_lightstylevalue[surface->styles[1]];
|
r_drawsurf.lightadj[1] = d_lightstylevalue[surface->styles[1]];
|
||||||
r_drawsurf.lightadj[2] = d_lightstylevalue[surface->styles[2]];
|
r_drawsurf.lightadj[2] = d_lightstylevalue[surface->styles[2]];
|
||||||
|
@ -285,8 +284,7 @@ D_CacheSurface (entity_t ent, msurface_t *surface, int miplevel)
|
||||||
r_drawsurf.surf = surface;
|
r_drawsurf.surf = surface;
|
||||||
|
|
||||||
c_surf++;
|
c_surf++;
|
||||||
transform_t transform = Entity_Transform (ent);
|
R_DrawSurface (render_id);
|
||||||
R_DrawSurface (transform);
|
|
||||||
|
|
||||||
return surface->cachespots[miplevel];
|
return surface->cachespots[miplevel];
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@
|
||||||
|
|
||||||
typedef struct glbspctx_s {
|
typedef struct glbspctx_s {
|
||||||
mod_brush_t *brush;
|
mod_brush_t *brush;
|
||||||
entity_t entity;
|
uint32_t render_id;
|
||||||
} swbspctx_t;
|
} swbspctx_t;
|
||||||
|
|
||||||
// current entity info
|
// current entity info
|
||||||
|
@ -85,10 +85,8 @@ R_EntityRotate (vec3_t vec)
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
R_RotateBmodel (transform_t transform)
|
R_RotateBmodel (vec4f_t *mat)
|
||||||
{
|
{
|
||||||
mat4f_t mat;
|
|
||||||
Transform_GetWorldMatrix (transform, mat);
|
|
||||||
VectorCopy (mat[0], entity_rotation[0]);
|
VectorCopy (mat[0], entity_rotation[0]);
|
||||||
VectorCopy (mat[1], entity_rotation[1]);
|
VectorCopy (mat[1], entity_rotation[1]);
|
||||||
VectorCopy (mat[2], entity_rotation[2]);
|
VectorCopy (mat[2], entity_rotation[2]);
|
||||||
|
@ -104,7 +102,7 @@ R_RotateBmodel (transform_t transform)
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
R_RecursiveClipBPoly (entity_t ent, bedge_t *pedges, mnode_t *pnode,
|
R_RecursiveClipBPoly (uint32_t render_id, bedge_t *pedges, mnode_t *pnode,
|
||||||
msurface_t *psurf)
|
msurface_t *psurf)
|
||||||
{
|
{
|
||||||
bedge_t *psideedges[2], *pnextedge, *ptedge;
|
bedge_t *psideedges[2], *pnextedge, *ptedge;
|
||||||
|
@ -239,11 +237,11 @@ R_RecursiveClipBPoly (entity_t ent, bedge_t *pedges, mnode_t *pnode,
|
||||||
if (r_leaf_visframes[~child_id] == r_visframecount
|
if (r_leaf_visframes[~child_id] == r_visframecount
|
||||||
&& leaf->contents != CONTENTS_SOLID) {
|
&& leaf->contents != CONTENTS_SOLID) {
|
||||||
r_currentbkey = leaf->key;
|
r_currentbkey = leaf->key;
|
||||||
R_RenderBmodelFace (ent, psideedges[i], psurf);
|
R_RenderBmodelFace (render_id, psideedges[i], psurf);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (r_node_visframes[child_id] == r_visframecount) {
|
if (r_node_visframes[child_id] == r_visframecount) {
|
||||||
R_RecursiveClipBPoly (ent, psideedges[i], pn, psurf);
|
R_RecursiveClipBPoly (render_id, psideedges[i], pn, psurf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -252,7 +250,7 @@ R_RecursiveClipBPoly (entity_t ent, bedge_t *pedges, mnode_t *pnode,
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
R_DrawSolidClippedSubmodelPolygons (entity_t ent, model_t *model,
|
R_DrawSolidClippedSubmodelPolygons (uint32_t render_id, mod_brush_t *brush,
|
||||||
mnode_t *topnode)
|
mnode_t *topnode)
|
||||||
{
|
{
|
||||||
int i, j, lindex;
|
int i, j, lindex;
|
||||||
|
@ -263,7 +261,6 @@ R_DrawSolidClippedSubmodelPolygons (entity_t ent, model_t *model,
|
||||||
mvertex_t bverts[MAX_BMODEL_VERTS];
|
mvertex_t bverts[MAX_BMODEL_VERTS];
|
||||||
bedge_t bedges[MAX_BMODEL_EDGES], *pbedge;
|
bedge_t bedges[MAX_BMODEL_EDGES], *pbedge;
|
||||||
medge_t *pedge, *pedges;
|
medge_t *pedge, *pedges;
|
||||||
mod_brush_t *brush = &model->brush;
|
|
||||||
|
|
||||||
// FIXME: use bounding-box-based frustum clipping info?
|
// FIXME: use bounding-box-based frustum clipping info?
|
||||||
|
|
||||||
|
@ -313,7 +310,7 @@ R_DrawSolidClippedSubmodelPolygons (entity_t ent, model_t *model,
|
||||||
|
|
||||||
pbedge[j - 1].pnext = NULL; // mark end of edges
|
pbedge[j - 1].pnext = NULL; // mark end of edges
|
||||||
|
|
||||||
R_RecursiveClipBPoly (ent, pbedge, topnode, psurf);
|
R_RecursiveClipBPoly (render_id, pbedge, topnode, psurf);
|
||||||
} else {
|
} else {
|
||||||
Sys_Error ("no edges in bmodel");
|
Sys_Error ("no edges in bmodel");
|
||||||
}
|
}
|
||||||
|
@ -323,7 +320,7 @@ R_DrawSolidClippedSubmodelPolygons (entity_t ent, model_t *model,
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
R_DrawSubmodelPolygons (entity_t ent, model_t *model, int clipflags,
|
R_DrawSubmodelPolygons (uint32_t render_id, mod_brush_t *brush, int clipflags,
|
||||||
mleaf_t *topleaf)
|
mleaf_t *topleaf)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -331,7 +328,6 @@ R_DrawSubmodelPolygons (entity_t ent, model_t *model, int clipflags,
|
||||||
msurface_t *psurf;
|
msurface_t *psurf;
|
||||||
int numsurfaces;
|
int numsurfaces;
|
||||||
plane_t *pplane;
|
plane_t *pplane;
|
||||||
mod_brush_t *brush = &model->brush;
|
|
||||||
|
|
||||||
// FIXME: use bounding-box-based frustum clipping info?
|
// FIXME: use bounding-box-based frustum clipping info?
|
||||||
|
|
||||||
|
@ -350,7 +346,7 @@ R_DrawSubmodelPolygons (entity_t ent, model_t *model, int clipflags,
|
||||||
r_currentkey = topleaf->key;
|
r_currentkey = topleaf->key;
|
||||||
|
|
||||||
// FIXME: use bounding-box-based frustum clipping info?
|
// FIXME: use bounding-box-based frustum clipping info?
|
||||||
R_RenderFace (ent, psurf, clipflags);
|
R_RenderFace (render_id, psurf, clipflags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -379,7 +375,7 @@ visit_node (swbspctx_t *bctx, mnode_t *node, int side, int clipflags)
|
||||||
{
|
{
|
||||||
int c;
|
int c;
|
||||||
msurface_t *surf;
|
msurface_t *surf;
|
||||||
entity_t ent = bctx->entity;
|
uint32_t render_id = bctx->render_id;
|
||||||
mod_brush_t *brush = bctx->brush;
|
mod_brush_t *brush = bctx->brush;
|
||||||
|
|
||||||
// sneaky hack for side = side ? SURF_PLANEBACK : 0;
|
// sneaky hack for side = side ? SURF_PLANEBACK : 0;
|
||||||
|
@ -404,10 +400,10 @@ visit_node (swbspctx_t *bctx, mnode_t *node, int side, int clipflags)
|
||||||
numbtofpolys++;
|
numbtofpolys++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
R_RenderPoly (ent, surf, clipflags);
|
R_RenderPoly (render_id, surf, clipflags);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
R_RenderFace (ent, surf, clipflags);
|
R_RenderFace (render_id, surf, clipflags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// all surfaces on the same node share the same sequence number
|
// all surfaces on the same node share the same sequence number
|
||||||
|
@ -533,11 +529,10 @@ R_RenderWorld (void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
btofpoly_t btofpolys[MAX_BTOFPOLYS];
|
btofpoly_t btofpolys[MAX_BTOFPOLYS];
|
||||||
entity_t ent = nullentity;
|
|
||||||
mod_brush_t *brush = &r_refdef.worldmodel->brush;
|
mod_brush_t *brush = &r_refdef.worldmodel->brush;
|
||||||
swbspctx_t bspctx = {
|
swbspctx_t bspctx = {
|
||||||
brush,
|
brush,
|
||||||
ent,
|
0,
|
||||||
};
|
};
|
||||||
|
|
||||||
pbtofpolys = btofpolys;
|
pbtofpolys = btofpolys;
|
||||||
|
@ -551,7 +546,7 @@ R_RenderWorld (void)
|
||||||
// back in that order
|
// back in that order
|
||||||
if (r_worldpolysbacktofront) {
|
if (r_worldpolysbacktofront) {
|
||||||
for (i = numbtofpolys - 1; i >= 0; i--) {
|
for (i = numbtofpolys - 1; i >= 0; i--) {
|
||||||
R_RenderPoly (ent, btofpolys[i].psurf, btofpolys[i].clipflags);
|
R_RenderPoly (0, btofpolys[i].psurf, btofpolys[i].clipflags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -347,7 +347,7 @@ R_EmitCachedEdge (void)
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
R_RenderFace (entity_t ent, msurface_t *fa, int clipflags)
|
R_RenderFace (uint32_t render_id, msurface_t *fa, int clipflags)
|
||||||
{
|
{
|
||||||
int i, lindex;
|
int i, lindex;
|
||||||
unsigned int mask;
|
unsigned int mask;
|
||||||
|
@ -356,8 +356,7 @@ R_RenderFace (entity_t ent, msurface_t *fa, int clipflags)
|
||||||
vec3_t p_normal;
|
vec3_t p_normal;
|
||||||
medge_t *pedges, tedge;
|
medge_t *pedges, tedge;
|
||||||
clipplane_t *pclip;
|
clipplane_t *pclip;
|
||||||
renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg);
|
mod_brush_t *brush = *(mod_brush_t **) SW_COMP (scene_sw_brush, render_id);
|
||||||
mod_brush_t *brush = &renderer->model->brush;
|
|
||||||
|
|
||||||
// skip out if no more surfs
|
// skip out if no more surfs
|
||||||
if ((surface_p) >= surf_max) {
|
if ((surface_p) >= surf_max) {
|
||||||
|
@ -494,7 +493,7 @@ R_RenderFace (entity_t ent, msurface_t *fa, int clipflags)
|
||||||
surface_p->flags = fa->flags;
|
surface_p->flags = fa->flags;
|
||||||
surface_p->insubmodel = insubmodel;
|
surface_p->insubmodel = insubmodel;
|
||||||
surface_p->spanstate = 0;
|
surface_p->spanstate = 0;
|
||||||
surface_p->entity = ent;
|
surface_p->render_id = render_id;
|
||||||
surface_p->key = r_currentkey++;
|
surface_p->key = r_currentkey++;
|
||||||
surface_p->spans = NULL;
|
surface_p->spans = NULL;
|
||||||
|
|
||||||
|
@ -514,7 +513,7 @@ R_RenderFace (entity_t ent, msurface_t *fa, int clipflags)
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
R_RenderBmodelFace (entity_t ent, bedge_t *pedges, msurface_t *psurf)
|
R_RenderBmodelFace (uint32_t render_id, bedge_t *pedges, msurface_t *psurf)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
unsigned int mask;
|
unsigned int mask;
|
||||||
|
@ -593,7 +592,7 @@ R_RenderBmodelFace (entity_t ent, bedge_t *pedges, msurface_t *psurf)
|
||||||
surface_p->flags = psurf->flags;
|
surface_p->flags = psurf->flags;
|
||||||
surface_p->insubmodel = true;
|
surface_p->insubmodel = true;
|
||||||
surface_p->spanstate = 0;
|
surface_p->spanstate = 0;
|
||||||
surface_p->entity = ent;
|
surface_p->render_id = render_id;
|
||||||
surface_p->key = r_currentbkey;
|
surface_p->key = r_currentbkey;
|
||||||
surface_p->spans = NULL;
|
surface_p->spans = NULL;
|
||||||
|
|
||||||
|
@ -613,7 +612,7 @@ R_RenderBmodelFace (entity_t ent, bedge_t *pedges, msurface_t *psurf)
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
R_RenderPoly (entity_t ent, msurface_t *fa, int clipflags)
|
R_RenderPoly (uint32_t render_id, msurface_t *fa, int clipflags)
|
||||||
{
|
{
|
||||||
int i, lindex, lnumverts, s_axis, t_axis;
|
int i, lindex, lnumverts, s_axis, t_axis;
|
||||||
float dist, lastdist, lzi, scale, u, v, frac;
|
float dist, lastdist, lzi, scale, u, v, frac;
|
||||||
|
@ -626,8 +625,7 @@ R_RenderPoly (entity_t ent, msurface_t *fa, int clipflags)
|
||||||
polyvert_t pverts[100]; // FIXME: do real number, safely
|
polyvert_t pverts[100]; // FIXME: do real number, safely
|
||||||
int vertpage, newverts, newpage, lastvert;
|
int vertpage, newverts, newpage, lastvert;
|
||||||
qboolean visible;
|
qboolean visible;
|
||||||
renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, ent.reg);
|
mod_brush_t *brush = *(mod_brush_t **) SW_COMP (scene_sw_brush, render_id);
|
||||||
mod_brush_t *brush = &renderer->model->brush;
|
|
||||||
|
|
||||||
// FIXME: clean this up and make it faster
|
// FIXME: clean this up and make it faster
|
||||||
// FIXME: guard against running out of vertices
|
// FIXME: guard against running out of vertices
|
||||||
|
@ -782,13 +780,12 @@ R_RenderPoly (entity_t ent, msurface_t *fa, int clipflags)
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
R_ZDrawSubmodelPolys (entity_t ent, model_t *model)
|
R_ZDrawSubmodelPolys (uint32_t render_id, mod_brush_t *brush)
|
||||||
{
|
{
|
||||||
int i, numsurfaces;
|
int i, numsurfaces;
|
||||||
msurface_t *psurf;
|
msurface_t *psurf;
|
||||||
float dot;
|
float dot;
|
||||||
plane_t *pplane;
|
plane_t *pplane;
|
||||||
mod_brush_t *brush = &model->brush;
|
|
||||||
|
|
||||||
psurf = &brush->surfaces[brush->firstmodelsurface];
|
psurf = &brush->surfaces[brush->firstmodelsurface];
|
||||||
numsurfaces = brush->nummodelsurfaces;
|
numsurfaces = brush->nummodelsurfaces;
|
||||||
|
@ -803,7 +800,7 @@ R_ZDrawSubmodelPolys (entity_t ent, model_t *model)
|
||||||
if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) ||
|
if (((psurf->flags & SURF_PLANEBACK) && (dot < -BACKFACE_EPSILON)) ||
|
||||||
(!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) {
|
(!(psurf->flags & SURF_PLANEBACK) && (dot > BACKFACE_EPSILON))) {
|
||||||
// FIXME: use bounding-box-based frustum clipping info?
|
// FIXME: use bounding-box-based frustum clipping info?
|
||||||
R_RenderPoly (ent, psurf, 15);
|
R_RenderPoly (render_id, psurf, 15);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,7 +89,7 @@ R_DrawCulledPolys (void)
|
||||||
|
|
||||||
if (!(s->flags & SURF_DRAWBACKGROUND)) {
|
if (!(s->flags & SURF_DRAWBACKGROUND)) {
|
||||||
pface = (msurface_t *) s->data;
|
pface = (msurface_t *) s->data;
|
||||||
R_RenderPoly (s->entity, pface, 15);
|
R_RenderPoly (s->render_id, pface, 15);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -99,7 +99,7 @@ R_DrawCulledPolys (void)
|
||||||
|
|
||||||
if (!(s->flags & SURF_DRAWBACKGROUND)) {
|
if (!(s->flags & SURF_DRAWBACKGROUND)) {
|
||||||
pface = (msurface_t *) s->data;
|
pface = (msurface_t *) s->data;
|
||||||
R_RenderPoly (s->entity, pface, 15);
|
R_RenderPoly (s->render_id, pface, 15);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -146,12 +146,58 @@ sw_R_Init (void)
|
||||||
Skin_Init ();
|
Skin_Init ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t
|
||||||
|
SW_AddEntity (entity_t ent)
|
||||||
|
{
|
||||||
|
// This takes advantage of the implicit (FIXME, make explicit) grouping of
|
||||||
|
// the sw components: as all entities that get added here will always have
|
||||||
|
// all three components, the three component pools are always in sync, thus
|
||||||
|
// the pool count can be used as a render id which can in turn be used to
|
||||||
|
// index the components within the pools.
|
||||||
|
ecs_registry_t *reg = ent.reg;
|
||||||
|
ecs_pool_t *pool = ®->comp_pools[scene_sw_matrix];
|
||||||
|
uint32_t render_id = pool->count;
|
||||||
|
|
||||||
|
transform_t transform = Entity_Transform (ent);
|
||||||
|
Ent_SetComponent (ent.id, scene_sw_matrix, reg,
|
||||||
|
Transform_GetWorldMatrixPtr (transform));
|
||||||
|
animation_t *animation = Ent_GetComponent (ent.id, scene_animation, reg);
|
||||||
|
Ent_SetComponent (ent.id, scene_sw_frame, reg, &animation->frame);
|
||||||
|
renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer, reg);
|
||||||
|
mod_brush_t *brush = &renderer->model->brush;
|
||||||
|
Ent_SetComponent (ent.id, scene_sw_brush, reg, &brush);
|
||||||
|
|
||||||
|
return render_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
reset_sw_components (ecs_registry_t *reg)
|
||||||
|
{
|
||||||
|
static uint32_t sw_comps[] = {
|
||||||
|
scene_sw_matrix,
|
||||||
|
scene_sw_frame,
|
||||||
|
scene_sw_brush,
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++) {
|
||||||
|
ecs_pool_t *pool = ®->comp_pools[sw_comps[i]];
|
||||||
|
pool->count = 0; // remove component from every entity
|
||||||
|
// reserve first component object (render id 0) for the world
|
||||||
|
// pseudo-entity.
|
||||||
|
Ent_SetComponent (0, sw_comps[i], reg, 0);
|
||||||
|
// make sure entity 0 gets allocated a new component object as the
|
||||||
|
// world pseudo-entity currently has no actual entity (FIXME)
|
||||||
|
pool->dense[0] = nullent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
R_NewScene (scene_t *scene)
|
R_NewScene (scene_t *scene)
|
||||||
{
|
{
|
||||||
model_t *worldmodel = scene->worldmodel;
|
model_t *worldmodel = scene->worldmodel;
|
||||||
mod_brush_t *brush = &worldmodel->brush;
|
mod_brush_t *brush = &worldmodel->brush;
|
||||||
|
|
||||||
|
r_refdef.registry = scene->reg;
|
||||||
r_refdef.worldmodel = worldmodel;
|
r_refdef.worldmodel = worldmodel;
|
||||||
|
|
||||||
// clear out efrags in case the level hasn't been reloaded
|
// clear out efrags in case the level hasn't been reloaded
|
||||||
|
@ -380,25 +426,23 @@ R_DrawViewModel (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
R_BmodelCheckBBox (transform_t transform, model_t *clmodel, float *minmaxs)
|
R_BmodelCheckBBox (const vec4f_t *transform, float radius, float *minmaxs)
|
||||||
{
|
{
|
||||||
int i, *pindex, clipflags;
|
int i, *pindex, clipflags;
|
||||||
vec3_t acceptpt, rejectpt;
|
vec3_t acceptpt, rejectpt;
|
||||||
double d;
|
double d;
|
||||||
mat4f_t mat;
|
|
||||||
|
|
||||||
clipflags = 0;
|
clipflags = 0;
|
||||||
|
|
||||||
Transform_GetWorldMatrix (transform, mat);
|
if (transform[0][0] != 1 || transform[1][1] != 1 || transform[2][2] != 1) {
|
||||||
if (mat[0][0] != 1 || mat[1][1] != 1 || mat[2][2] != 1) {
|
|
||||||
for (i = 0; i < 4; i++) {
|
for (i = 0; i < 4; i++) {
|
||||||
d = DotProduct (mat[3], view_clipplanes[i].normal);
|
d = DotProduct (transform[3], view_clipplanes[i].normal);
|
||||||
d -= view_clipplanes[i].dist;
|
d -= view_clipplanes[i].dist;
|
||||||
|
|
||||||
if (d <= -clmodel->radius)
|
if (d <= -radius)
|
||||||
return BMODEL_FULLY_CLIPPED;
|
return BMODEL_FULLY_CLIPPED;
|
||||||
|
|
||||||
if (d <= clmodel->radius)
|
if (d <= radius)
|
||||||
clipflags |= (1 << i);
|
clipflags |= (1 << i);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -449,9 +493,11 @@ R_DrawBrushEntitiesOnList (entqueue_t *queue)
|
||||||
|
|
||||||
for (size_t i = 0; i < queue->ent_queues[mod_brush].size; i++) {
|
for (size_t i = 0; i < queue->ent_queues[mod_brush].size; i++) {
|
||||||
entity_t ent = queue->ent_queues[mod_brush].a[i];
|
entity_t ent = queue->ent_queues[mod_brush].a[i];
|
||||||
|
uint32_t render_id = SW_AddEntity (ent);
|
||||||
|
|
||||||
transform_t transform = Entity_Transform (ent);
|
vec4f_t *transform = Ent_GetComponent (ent.id, scene_sw_matrix,
|
||||||
VectorCopy (Transform_GetWorldPosition (transform), origin);
|
ent.reg);
|
||||||
|
VectorCopy (transform[3], origin);
|
||||||
renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer,
|
renderer_t *renderer = Ent_GetComponent (ent.id, scene_renderer,
|
||||||
ent.reg);
|
ent.reg);
|
||||||
model_t *model = renderer->model;
|
model_t *model = renderer->model;
|
||||||
|
@ -463,7 +509,7 @@ R_DrawBrushEntitiesOnList (entqueue_t *queue)
|
||||||
minmaxs[3 + j] = origin[j] + model->maxs[j];
|
minmaxs[3 + j] = origin[j] + model->maxs[j];
|
||||||
}
|
}
|
||||||
|
|
||||||
clipflags = R_BmodelCheckBBox (transform, model, minmaxs);
|
clipflags = R_BmodelCheckBBox (transform, model->radius, minmaxs);
|
||||||
|
|
||||||
if (clipflags != BMODEL_FULLY_CLIPPED) {
|
if (clipflags != BMODEL_FULLY_CLIPPED) {
|
||||||
mod_brush_t *brush = &model->brush;
|
mod_brush_t *brush = &model->brush;
|
||||||
|
@ -496,26 +542,26 @@ R_DrawBrushEntitiesOnList (entqueue_t *queue)
|
||||||
// Z-buffering is on at this point, so no clipping to the
|
// Z-buffering is on at this point, so no clipping to the
|
||||||
// world tree is needed, just frustum clipping
|
// world tree is needed, just frustum clipping
|
||||||
if (r_drawpolys | r_drawculledpolys) {
|
if (r_drawpolys | r_drawculledpolys) {
|
||||||
R_ZDrawSubmodelPolys (ent, model);
|
R_ZDrawSubmodelPolys (render_id, brush);
|
||||||
} else {
|
} else {
|
||||||
visibility_t *visibility = Ent_GetComponent (ent.id,
|
visibility_t *visibility = Ent_GetComponent (ent.id,
|
||||||
scene_visibility,
|
scene_visibility,
|
||||||
ent.reg);
|
ent.reg);
|
||||||
int topnode_id = visibility->topnode_id;
|
int topnode_id = visibility->topnode_id;
|
||||||
mod_brush_t *brush = &r_refdef.worldmodel->brush;
|
mod_brush_t *world_brush = &r_refdef.worldmodel->brush;
|
||||||
|
|
||||||
if (topnode_id >= 0) {
|
if (topnode_id >= 0) {
|
||||||
// not a leaf; has to be clipped to the world
|
// not a leaf; has to be clipped to the world
|
||||||
// BSP
|
// BSP
|
||||||
mnode_t *node = brush->nodes + topnode_id;
|
mnode_t *node = world_brush->nodes + topnode_id;
|
||||||
r_clipflags = clipflags;
|
r_clipflags = clipflags;
|
||||||
R_DrawSolidClippedSubmodelPolygons (ent, model, node);
|
R_DrawSolidClippedSubmodelPolygons (render_id, brush, node);
|
||||||
} else {
|
} else {
|
||||||
// falls entirely in one leaf, so we just put
|
// falls entirely in one leaf, so we just put
|
||||||
// all the edges in the edge list and let 1/z
|
// all the edges in the edge list and let 1/z
|
||||||
// sorting handle drawing order
|
// sorting handle drawing order
|
||||||
mleaf_t *leaf = brush->leafs + ~topnode_id;
|
mleaf_t *leaf = world_brush->leafs + ~topnode_id;
|
||||||
R_DrawSubmodelPolygons (ent, model, clipflags, leaf);
|
R_DrawSubmodelPolygons (render_id, brush, clipflags, leaf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -588,6 +634,8 @@ R_RenderView_ (void)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reset_sw_components (r_refdef.registry);
|
||||||
|
*(mod_brush_t **) SW_COMP (scene_sw_brush, 0) = &r_refdef.worldmodel->brush;
|
||||||
R_SetupFrame ();
|
R_SetupFrame ();
|
||||||
|
|
||||||
// make FDIV fast. This reduces timing precision after we've been running for a
|
// make FDIV fast. This reduces timing precision after we've been running for a
|
||||||
|
|
|
@ -73,7 +73,7 @@ static unsigned int blocklights[34 * 34]; //FIXME make dynamic
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
R_AddDynamicLights (transform_t transform)
|
R_AddDynamicLights (uint32_t render_id)
|
||||||
{
|
{
|
||||||
msurface_t *surf;
|
msurface_t *surf;
|
||||||
unsigned int lnum;
|
unsigned int lnum;
|
||||||
|
@ -91,9 +91,10 @@ R_AddDynamicLights (transform_t transform)
|
||||||
tmax = (surf->extents[1] >> 4) + 1;
|
tmax = (surf->extents[1] >> 4) + 1;
|
||||||
tex = surf->texinfo;
|
tex = surf->texinfo;
|
||||||
|
|
||||||
if (Transform_Valid (transform)) {
|
if (render_id) {
|
||||||
//FIXME give world entity a transform
|
//FIXME give world entity a transform
|
||||||
entorigin = Transform_GetWorldPosition (transform);
|
vec4f_t *transform = SW_COMP (scene_sw_matrix, render_id);
|
||||||
|
entorigin = transform[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
for (lnum = 0; lnum < r_maxdlights; lnum++) {
|
for (lnum = 0; lnum < r_maxdlights; lnum++) {
|
||||||
|
@ -144,7 +145,7 @@ R_AddDynamicLights (transform_t transform)
|
||||||
Combine and scale multiple lightmaps into the 8.8 format in blocklights
|
Combine and scale multiple lightmaps into the 8.8 format in blocklights
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
R_BuildLightMap (transform_t transform)
|
R_BuildLightMap (uint32_t render_id)
|
||||||
{
|
{
|
||||||
int smax, tmax;
|
int smax, tmax;
|
||||||
int t;
|
int t;
|
||||||
|
@ -180,7 +181,7 @@ R_BuildLightMap (transform_t transform)
|
||||||
}
|
}
|
||||||
// add all the dynamic lights
|
// add all the dynamic lights
|
||||||
if (surf->dlightframe == r_framecount)
|
if (surf->dlightframe == r_framecount)
|
||||||
R_AddDynamicLights (transform);
|
R_AddDynamicLights (render_id);
|
||||||
|
|
||||||
// bound, invert, and shift
|
// bound, invert, and shift
|
||||||
for (i = 0; i < size; i++) {
|
for (i = 0; i < size; i++) {
|
||||||
|
@ -194,7 +195,7 @@ R_BuildLightMap (transform_t transform)
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
R_DrawSurface (transform_t transform)
|
R_DrawSurface (uint32_t render_id)
|
||||||
{
|
{
|
||||||
byte *basetptr;
|
byte *basetptr;
|
||||||
int smax, tmax, twidth;
|
int smax, tmax, twidth;
|
||||||
|
@ -206,7 +207,7 @@ R_DrawSurface (transform_t transform)
|
||||||
texture_t *mt;
|
texture_t *mt;
|
||||||
|
|
||||||
// calculate the lightings
|
// calculate the lightings
|
||||||
R_BuildLightMap (transform);
|
R_BuildLightMap (render_id);
|
||||||
|
|
||||||
surfrowbytes = r_drawsurf.rowbytes;
|
surfrowbytes = r_drawsurf.rowbytes;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue