Browse Source

multiple GL_POINTS can now be rendered together into one fragment span

tags/mesa_4_1
Brian Paul 23 years ago
parent
commit
f782b8189e

+ 2
- 1
src/mesa/main/context.c View File

@@ -1,4 +1,4 @@
/* $Id: context.c,v 1.178 2002/10/02 22:05:56 brianp Exp $ */
/* $Id: context.c,v 1.179 2002/10/04 17:37:45 brianp Exp $ */

/*
* Mesa 3-D graphics library
@@ -1478,6 +1478,7 @@ init_attrib_groups( GLcontext *ctx )
ctx->CatchSignals = GL_TRUE;
ctx->OcclusionResult = GL_FALSE;
ctx->OcclusionResultSaved = GL_FALSE;
ctx->_Facing = 0;

/* For debug/development only */
ctx->NoRaster = ctx->imports.getenv(ctx, "MESA_NO_RASTER") ? GL_TRUE : GL_FALSE;

+ 48
- 15
src/mesa/swrast/s_context.c View File

@@ -1,4 +1,4 @@
/* $Id: s_context.c,v 1.38 2002/09/17 15:46:34 brianp Exp $ */
/* $Id: s_context.c,v 1.39 2002/10/04 17:37:46 brianp Exp $ */

/*
* Mesa 3-D graphics library
@@ -33,11 +33,12 @@
#include "mem.h"

#include "swrast.h"
#include "s_points.h"
#include "s_lines.h"
#include "s_triangle.h"
#include "s_blend.h"
#include "s_context.h"
#include "s_lines.h"
#include "s_points.h"
#include "s_span.h"
#include "s_triangle.h"
#include "s_texture.h"


@@ -513,19 +514,26 @@ _swrast_CreateContext( GLcontext *ctx )
for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++)
swrast->TextureSample[i] = _swrast_validate_texture_sample;

swrast->span_data = MALLOC_STRUCT(span_arrays);
if (!swrast->span_data) {
swrast->SpanArrays = MALLOC_STRUCT(span_arrays);
if (!swrast->SpanArrays) {
FREE(swrast);
return GL_FALSE;
}

/* init point span buffer */
swrast->PointSpan.primitive = GL_POINT;
swrast->PointSpan.start = 0;
swrast->PointSpan.end = 0;
swrast->PointSpan.facing = 0;
swrast->PointSpan.array = swrast->SpanArrays;

assert(ctx->Const.MaxTextureUnits > 0);
assert(ctx->Const.MaxTextureUnits <= MAX_TEXTURE_UNITS);

swrast->TexelBuffer = (GLchan *) MALLOC(ctx->Const.MaxTextureUnits *
MAX_WIDTH * 4 * sizeof(GLchan));
if (!swrast->TexelBuffer) {
FREE(swrast->span_data);
FREE(swrast->SpanArrays);
FREE(swrast);
return GL_FALSE;
}
@@ -544,7 +552,7 @@ _swrast_DestroyContext( GLcontext *ctx )
_mesa_debug(ctx, "_swrast_DestroyContext\n");
}

FREE( swrast->span_data );
FREE( swrast->SpanArrays );
FREE( swrast->TexelBuffer );
FREE( swrast );

@@ -559,6 +567,35 @@ _swrast_GetDeviceDriverReference( GLcontext *ctx )
return &swrast->Driver;
}

void
_swrast_flush( GLcontext *ctx )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
/* flush any pending fragments from rendering points */
if (swrast->PointSpan.end > 0) {
if (ctx->Visual.rgbMode) {
if (ctx->Texture._EnabledUnits)
_mesa_write_texture_span(ctx, &(swrast->PointSpan));
else
_mesa_write_rgba_span(ctx, &(swrast->PointSpan));
}
else {
_mesa_write_index_span(ctx, &(swrast->PointSpan));
}
swrast->PointSpan.end = 0;
}
}

void
_swrast_render_primitive( GLcontext *ctx, GLenum prim )
{
SWcontext *swrast = SWRAST_CONTEXT(ctx);
if (swrast->Primitive == GL_POINTS && prim != GL_POINTS) {
_swrast_flush(ctx);
}
swrast->Primitive = prim;
}


void
_swrast_render_start( GLcontext *ctx )
@@ -566,6 +603,7 @@ _swrast_render_start( GLcontext *ctx )
SWcontext *swrast = SWRAST_CONTEXT(ctx);
if (swrast->Driver.SpanRenderStart)
swrast->Driver.SpanRenderStart( ctx );
swrast->PointSpan.end = 0;
}
void
@@ -574,6 +612,8 @@ _swrast_render_finish( GLcontext *ctx )
SWcontext *swrast = SWRAST_CONTEXT(ctx);
if (swrast->Driver.SpanRenderFinish)
swrast->Driver.SpanRenderFinish( ctx );

_swrast_flush(ctx);
}


@@ -613,10 +653,3 @@ _swrast_print_vertex( GLcontext *ctx, const SWvertex *v )
_mesa_debug(ctx, "\n");
}
}


void
_swrast_flush( GLcontext *ctx )
{
/* no-op */
}

+ 8
- 2
src/mesa/swrast/s_context.h View File

@@ -1,4 +1,4 @@
/* $Id: s_context.h,v 1.19 2002/08/07 00:45:07 brianp Exp $ */
/* $Id: s_context.h,v 1.20 2002/10/04 17:37:47 brianp Exp $ */

/*
* Mesa 3-D graphics library
@@ -137,6 +137,7 @@ typedef struct
GLuint StippleCounter; /**< Line stipple counter */
GLuint NewState;
GLuint StateChanges;
GLenum Primitive; /* current primitive being drawn (ala glBegin) */

/** Mechanism to allow driver (like X11) to register further
* software rasterization routines.
@@ -176,7 +177,12 @@ typedef struct
* this object is big and causes problems when allocated on the stack
* on some systems.
*/
struct span_arrays *span_data;
struct span_arrays *SpanArrays;

/**
* Used to buffer N GL_POINTS, instead of rendering one by one.
*/
struct sw_span PointSpan;

/** Internal hooks, kept uptodate by the same mechanism as above.
*/

+ 179
- 106
src/mesa/swrast/s_pointtemp.h View File

@@ -1,4 +1,4 @@
/* $Id: s_pointtemp.h,v 1.18 2002/08/07 00:45:07 brianp Exp $ */
/* $Id: s_pointtemp.h,v 1.19 2002/10/04 17:37:47 brianp Exp $ */

/*
* Mesa 3-D graphics library
@@ -61,23 +61,32 @@
static void
NAME ( GLcontext *ctx, const SWvertex *vert )
{
#if FLAGS & TEXTURE
GLuint u;
#endif
#if FLAGS & (ATTENUATE | LARGE | SMOOTH | SPRITE)
GLfloat size;
#endif
#if FLAGS & ATTENUATE
GLfloat alphaAtten;
#endif
#if (FLAGS & RGBA) && (FLAGS & SMOOTH)
#if FLAGS & RGBA
const GLchan red = vert->color[0];
const GLchan green = vert->color[1];
const GLchan blue = vert->color[2];
const GLchan alpha = vert->color[3];
#endif

struct sw_span span;
#if FLAGS & SPECULAR
const GLchan specRed = vert->specular[0];
const GLchan specGreen = vert->specular[1];
const GLchan specBlue = vert->specular[2];
#endif
#if FLAGS & INDEX
const GLuint colorIndex = vert->index;
#endif
#if FLAGS & TEXTURE
GLfloat texcoord[MAX_TEXTURE_UNITS][4];
GLuint u;
#endif
SWcontext *swrast = SWRAST_CONTEXT(ctx);
struct sw_span *span = &(swrast->PointSpan);

/* Cull primitives with malformed coordinates.
*/
@@ -87,59 +96,40 @@ NAME ( GLcontext *ctx, const SWvertex *vert )
return;
}

INIT_SPAN(span, GL_POINT, 0, SPAN_FOG, SPAN_XY | SPAN_Z);
span.fog = vert->fog;
span.fogStep = 0.0;

#if (FLAGS & RGBA)
#if (FLAGS & SMOOTH)
/* because we need per-fragment alpha values */
span.arrayMask |= SPAN_RGBA;
#else
/* same RGBA for all fragments */
span.interpMask |= SPAN_RGBA;
span.red = ChanToFixed(vert->color[0]);
span.green = ChanToFixed(vert->color[1]);
span.blue = ChanToFixed(vert->color[2]);
span.alpha = ChanToFixed(vert->color[3]);
span.redStep = span.greenStep = span.blueStep = span.alphaStep = 0;
#endif /*SMOOTH*/
#endif /*RGBA*/
/*
* Span init
*/
span->interpMask = SPAN_FOG;
span->arrayMask = SPAN_XY | SPAN_Z;
span->fog = vert->fog;
span->fogStep = 0.0;
#if FLAGS & RGBA
span->arrayMask |= SPAN_RGBA;
#endif
#if FLAGS & SPECULAR
span.interpMask |= SPAN_SPEC;
span.specRed = ChanToFixed(vert->specular[0]);
span.specGreen = ChanToFixed(vert->specular[1]);
span.specBlue = ChanToFixed(vert->specular[2]);
span.specRedStep = span.specGreenStep = span.specBlueStep = 0;
span->arrayMask |= SPAN_SPEC;
#endif
#if FLAGS & INDEX
span.interpMask |= SPAN_INDEX;
span.index = IntToFixed(vert->index);
span.indexStep = 0;
span->arrayMask |= SPAN_INDEX;
#endif
#if FLAGS & TEXTURE
/* but not used for sprite mode */
span.interpMask |= SPAN_TEXTURE;
span->arrayMask |= SPAN_TEXTURE;
for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
if (ctx->Texture.Unit[u]._ReallyEnabled) {
const GLfloat q = vert->texcoord[u][3];
const GLfloat invQ = (q == 0.0 || q == 1.0) ? 1.0 : (1.0 / q);
span.tex[u][0] = vert->texcoord[u][0] * invQ;
span.tex[u][1] = vert->texcoord[u][1] * invQ;
span.tex[u][2] = vert->texcoord[u][2] * invQ;
span.tex[u][3] = q;
span.texStepX[u][0] = span.texStepY[u][0] = 0.0;
span.texStepX[u][1] = span.texStepY[u][1] = 0.0;
span.texStepX[u][2] = span.texStepY[u][2] = 0.0;
span.texStepX[u][3] = span.texStepY[u][3] = 0.0;
texcoord[u][0] = vert->texcoord[u][0] * invQ;
texcoord[u][1] = vert->texcoord[u][1] * invQ;
texcoord[u][2] = vert->texcoord[u][2] * invQ;
texcoord[u][3] = q;
}
}
#endif
#if FLAGS & SMOOTH
span.arrayMask |= SPAN_COVERAGE;
span->arrayMask |= SPAN_COVERAGE;
#endif
#if FLAGS & SPRITE
span.arrayMask |= SPAN_TEXTURE;
span->arrayMask |= SPAN_TEXTURE;
#endif

#if FLAGS & ATTENUATE
@@ -156,12 +146,15 @@ NAME ( GLcontext *ctx, const SWvertex *vert )
size = ctx->Point._Size;
#endif

#if FLAGS & (LARGE | ATTENUATE | SMOOTH | SPRITE)
{
#if FLAGS & (ATTENUATE | LARGE | SMOOTH | SPRITE)
/*
* Multi-pixel points
*/
{{
GLint x, y;
const GLfloat radius = 0.5F * size;
const GLint z = (GLint) (vert->win[2]);
GLuint count = 0;
GLuint count;
#if FLAGS & SMOOTH
const GLfloat rmin = radius - 0.7071F; /* 0.7071 = sqrt(2)/2 */
const GLfloat rmax = radius + 0.7071F;
@@ -195,104 +188,184 @@ NAME ( GLcontext *ctx, const SWvertex *vert )
}
#endif /*SMOOTH*/

/* check if we need to flush */
if (span->end + (xmax-xmin+1) * (ymax-ymin+1) >= MAX_WIDTH ||
(swrast->_RasterMask & (BLEND_BIT | LOGIC_OP_BIT | MASKING_BIT))) {
#if FLAGS & (TEXTURE | SPRITE)
if (ctx->Texture._EnabledUnits)
_mesa_write_texture_span(ctx, span);
else
_mesa_write_rgba_span(ctx, span);
#elif FLAGS & RGBA
_mesa_write_rgba_span(ctx, span);
#else
_mesa_write_index_span(ctx, span);
#endif
span->end = 0;
}

/*
* OK, generate fragments
*/
count = span->end;
(void) radius;
for (y = ymin; y <= ymax; y++) {
for (x = xmin; x <= xmax; x++) {
#if FLAGS & SPRITE
#if FLAGS & (SPRITE | TEXTURE)
GLuint u;
#endif

#if FLAGS & RGBA
span->array->rgba[count][RCOMP] = red;
span->array->rgba[count][GCOMP] = green;
span->array->rgba[count][BCOMP] = blue;
span->array->rgba[count][ACOMP] = alpha;
#endif
#if FLAGS & SPECULAR
span->array->spec[count][RCOMP] = specRed;
span->array->spec[count][GCOMP] = specGreen;
span->array->spec[count][BCOMP] = specBlue;
#endif
#if FLAGS & INDEX
span->array->index[count] = colorIndex;
#endif
#if FLAGS & TEXTURE
for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
if (ctx->Texture.Unit[u]._ReallyEnabled) {
COPY_4V(span->array->texcoords[u][count], texcoord[u]);
}
}
#endif

#if FLAGS & SMOOTH
/* compute coverage */
const GLfloat dx = x - vert->win[0] + 0.5F;
const GLfloat dy = y - vert->win[1] + 0.5F;
const GLfloat dist2 = dx * dx + dy * dy;
if (dist2 < rmax2) {
if (dist2 >= rmin2) {
/* compute partial coverage */
span.array->coverage[count] = 1.0F - (dist2 - rmin2) * cscale;
{
const GLfloat dx = x - vert->win[0] + 0.5F;
const GLfloat dy = y - vert->win[1] + 0.5F;
const GLfloat dist2 = dx * dx + dy * dy;
if (dist2 < rmax2) {
if (dist2 >= rmin2) {
/* compute partial coverage */
span->array->coverage[count] = 1.0F - (dist2 - rmin2) * cscale;
#if FLAGS & INDEX
span.array->coverage[count] *= 15.0; /* coverage in [0,15] */
/* coverage in [0,15] */
span->array->coverage[count] *= 15.0;
#endif
}
else {
/* full coverage */
span.array->coverage[count] = 1.0F;
}
}
else {
/* full coverage */
span->array->coverage[count] = 1.0F;
}

span.array->x[count] = x;
span.array->y[count] = y;
span.array->z[count] = z;
span->array->x[count] = x;
span->array->y[count] = y;
span->array->z[count] = z;

#if FLAGS & RGBA
span.array->rgba[count][RCOMP] = red;
span.array->rgba[count][GCOMP] = green;
span.array->rgba[count][BCOMP] = blue;
#if FLAGS & ATTENUATE
span.array->rgba[count][ACOMP] = (GLchan) (alpha * alphaAtten);
#else
span.array->rgba[count][ACOMP] = alpha;
#if (FLAGS & ATTENUATE) && (FLAGS & RGBA)
span->array->rgba[count][ACOMP] = (GLchan) (alpha * alphaAtten);
#elif FLAGS & RGBA
span->array->rgba[count][ACOMP] = alpha;
#endif /*ATTENUATE*/
#endif /*RGBA*/
count++;
} /*if*/
count++;
} /*if*/
}

#else /*SMOOTH*/

/* not smooth (square points) */
span.array->x[count] = x;
span.array->y[count] = y;
span.array->z[count] = z;
span->array->x[count] = x;
span->array->y[count] = y;
span->array->z[count] = z;

#if FLAGS & SPRITE
for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
if (ctx->Texture.Unit[u]._ReallyEnabled) {
if (ctx->Point.CoordReplace[u]) {
GLfloat s = 0.5F + (x + 0.5F - vert->win[0]) / size;
GLfloat t = 0.5F - (y + 0.5F - vert->win[1]) / size;
span.array->texcoords[u][count][0] = s;
span.array->texcoords[u][count][1] = t;
span.array->texcoords[u][count][3] = 1.0F;
span->array->texcoords[u][count][0] = s;
span->array->texcoords[u][count][1] = t;
span->array->texcoords[u][count][3] = 1.0F;
if (ctx->Point.SpriteRMode == GL_ZERO)
span.array->texcoords[u][count][2] = 0.0F;
span->array->texcoords[u][count][2] = 0.0F;
else if (ctx->Point.SpriteRMode == GL_S)
span.array->texcoords[u][count][2] = vert->texcoord[u][0];
span->array->texcoords[u][count][2] = vert->texcoord[u][0];
else /* GL_R */
span.array->texcoords[u][count][2] = vert->texcoord[u][2];
span->array->texcoords[u][count][2] = vert->texcoord[u][2];
}
else {
COPY_4V(span.array->texcoords[u][count], vert->texcoord[u]);
COPY_4V(span->array->texcoords[u][count], vert->texcoord[u]);
}
}
}
#endif /*SPRITE*/
count++;

count++; /* square point */

#endif /*SMOOTH*/

} /*for x*/
} /*for y*/
span.end = count;
}
span->end = count;
}}

#else /* LARGE | ATTENUATE | SMOOTH | SPRITE */

{
/* size == 1 */
span.array->x[0] = (GLint) vert->win[0];
span.array->y[0] = (GLint) vert->win[1];
span.array->z[0] = (GLint) vert->win[2];
span.end = 1;
}

#endif /* LARGE || ATTENUATE || SMOOTH */

ASSERT(span.end > 0);
/*
* Single-pixel points
*/
{{
GLuint count;

/* check if we need to flush */
if (span->end >= MAX_WIDTH ||
(swrast->_RasterMask & (BLEND_BIT | LOGIC_OP_BIT | MASKING_BIT))) {
#if FLAGS & (TEXTURE | SPRITE)
if (ctx->Texture._EnabledUnits)
_mesa_write_texture_span(ctx, &span);
else
_mesa_write_rgba_span(ctx, &span);
if (ctx->Texture._EnabledUnits)
_mesa_write_texture_span(ctx, span);
else
_mesa_write_rgba_span(ctx, span);
#elif FLAGS & RGBA
_mesa_write_rgba_span(ctx, &span);
_mesa_write_rgba_span(ctx, span);
#else
_mesa_write_index_span(ctx, &span);
_mesa_write_index_span(ctx, span);
#endif
span->end = 0;
}

count = span->end;

#if FLAGS & RGBA
span->array->rgba[count][RCOMP] = red;
span->array->rgba[count][GCOMP] = green;
span->array->rgba[count][BCOMP] = blue;
span->array->rgba[count][ACOMP] = alpha;
#endif
#if FLAGS & SPECULAR
span->array->spec[count][RCOMP] = specRed;
span->array->spec[count][GCOMP] = specGreen;
span->array->spec[count][BCOMP] = specBlue;
#endif
#if FLAGS & INDEX
span->array->index[count] = colorIndex;
#endif
#if FLAGS & TEXTURE
for (u = 0; u < ctx->Const.MaxTextureUnits; u++) {
if (ctx->Texture.Unit[u]._ReallyEnabled) {
COPY_4V(span->array->texcoords[u][count], texcoord[u]);
}
}
#endif

span->array->x[count] = (GLint) vert->win[0];
span->array->y[count] = (GLint) vert->win[1];
span->array->z[count] = (GLint) vert->win[2];
span->end = count + 1;
}}

#endif /* LARGE || ATTENUATE || SMOOTH */

ASSERT(span->end <= MAX_WIDTH);
}



+ 5
- 2
src/mesa/swrast/swrast.h View File

@@ -1,4 +1,4 @@
/* $Id: swrast.h,v 1.28 2002/10/02 23:24:04 brianp Exp $ */
/* $Id: swrast.h,v 1.29 2002/10/04 17:37:47 brianp Exp $ */

/*
* Mesa 3-D graphics library
@@ -205,7 +205,7 @@ do { \
(S).start = 0; \
(S).end = (END); \
(S).facing = 0; \
(S).array = SWRAST_CONTEXT(ctx)->span_data; \
(S).array = SWRAST_CONTEXT(ctx)->SpanArrays; \
} while (0)


@@ -306,6 +306,9 @@ _swrast_Quad( GLcontext *ctx,
extern void
_swrast_flush( GLcontext *ctx );

extern void
_swrast_render_primitive( GLcontext *ctx, GLenum mode );

extern void
_swrast_render_start( GLcontext *ctx );


+ 12
- 2
src/mesa/swrast_setup/ss_context.c View File

@@ -1,9 +1,10 @@
/* $Id: ss_context.c,v 1.18 2002/10/04 17:37:47 brianp Exp $ */

/*
* Mesa 3-D graphics library
* Version: 3.5
* Version: 4.1
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
* 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"),
@@ -97,8 +98,13 @@ static void
_swsetup_RenderPrimitive( GLcontext *ctx, GLenum mode )
{
SWSETUP_CONTEXT(ctx)->render_prim = mode;
_swrast_render_primitive( ctx, mode );
}

/*
* We patch this function into tnl->Driver.Render.Start.
* It's called when we start rendering a vertex buffer.
*/
static void
_swsetup_RenderStart( GLcontext *ctx )
{
@@ -118,6 +124,10 @@ _swsetup_RenderStart( GLcontext *ctx )
_swrast_render_start( ctx );
}

/*
* We patch this function into tnl->Driver.Render.Finish.
* It's called when we finish rendering a vertex buffer.
*/
static void
_swsetup_RenderFinish( GLcontext *ctx )
{

+ 3
- 2
src/mesa/swrast_setup/ss_context.h View File

@@ -1,9 +1,10 @@
/* $Id: ss_context.h,v 1.11 2002/10/04 17:37:47 brianp Exp $ */

/*
* Mesa 3-D graphics library
* Version: 3.5
* Version: 4.1
*
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
* 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"),

+ 4
- 3
src/mesa/swrast_setup/ss_triangle.c View File

@@ -1,4 +1,4 @@
/* $Id: ss_triangle.c,v 1.17 2002/10/02 23:24:04 brianp Exp $ */
/* $Id: ss_triangle.c,v 1.18 2002/10/04 17:37:47 brianp Exp $ */

/*
* Mesa 3-D graphics library
@@ -139,6 +139,7 @@ static void _swsetup_render_point_tri( GLcontext *ctx,
v0->index = i[0];
v1->index = i[1];
}
_swrast_flush(ctx);
}

#define SS_COLOR(a,b) COPY_CHAN4(a,b)
@@ -280,8 +281,6 @@ void _swsetup_choose_trifuncs( GLcontext *ctx )
(ctx->Stencil.Enabled && ctx->Stencil.TestTwoSide))
ind |= SS_UNFILLED_BIT;

ctx->_Facing = 0;

if (ctx->Visual.rgbMode)
ind |= SS_RGBA_BIT;

@@ -289,4 +288,6 @@ void _swsetup_choose_trifuncs( GLcontext *ctx )
tnl->Driver.Render.Quad = quad_tab[ind];
tnl->Driver.Render.Line = swsetup_line;
tnl->Driver.Render.Points = swsetup_points;

ctx->_Facing = 0;
}

+ 3
- 2
src/mesa/swrast_setup/ss_tritmp.h View File

@@ -1,4 +1,4 @@
/* $Id: ss_tritmp.h,v 1.16 2002/10/02 23:24:04 brianp Exp $ */
/* $Id: ss_tritmp.h,v 1.17 2002/10/04 17:37:47 brianp Exp $ */

/*
* Mesa 3-D graphics library
@@ -54,7 +54,8 @@ static void TAG(triangle)(GLcontext *ctx, GLuint e0, GLuint e1, GLuint e2 )
if (IND & (SS_TWOSIDE_BIT | SS_UNFILLED_BIT))
{
facing = (cc < 0.0) ^ ctx->Polygon._FrontBit;
ctx->_Facing = facing; /* for 2-sided stencil test */
if (ctx->Stencil.TestTwoSide)
ctx->_Facing = facing; /* for 2-sided stencil test */

if (IND & SS_UNFILLED_BIT)
mode = facing ? ctx->Polygon.BackMode : ctx->Polygon.FrontMode;

Loading…
Cancel
Save