Skip to content

Commit 10a889c

Browse files
authored
[rlsw] Replace SW_TEXTURE_REPEAT_POT_FAST with SW_SUPPORT_NPOT_TEXTURE (#5901)
* replace `SW_TEXTURE_REPEAT_POT_FAST` by `SW_SUPPORT_NPOT_TEXTURE` * tweak `SW_SUPPORT_NPOT_TEXTURE` comment * remove extra comment
1 parent b7f50b2 commit 10a889c

1 file changed

Lines changed: 54 additions & 58 deletions

File tree

src/external/rlsw.h

Lines changed: 54 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -164,17 +164,10 @@
164164
#endif
165165
#endif
166166

167-
// Fast power-of-two texture wrap (SW_REPEAT mode only)
168-
// When defined, textures whose width/height are powers of two use a bitmask
169-
// wrap (`x & (size-1)`) instead of `floorf`-based fractional wrap or the signed `%` chain in the linear sampler
170-
// Saves a software divide on Xtensa and a few instructions everywhere
171-
// NPOT textures keep using the original path via a runtime `(size & (size-1)) == 0` check,
172-
// so SW_REPEAT remains correct for them
173-
// The only observable behavior change is for POT textures sampled with negative UV coordinates:
174-
// bitmask wrap (two's complement) can differ from `sw_fract` by one texel
175-
// Off by default to keep bit-for-bit behavior; opt in if you control your asset UVs
176-
//
177-
//#define SW_TEXTURE_REPEAT_POT_FAST
167+
// Full NPOT texture support (enabled by default)
168+
// When disabled, SW_REPEAT requires POT on its axis (fast bitmask wrap)
169+
// SW_CLAMP remains supported for any dimension, per-axis
170+
#define SW_SUPPORT_NPOT_TEXTURE true
178171

179172
//----------------------------------------------------------------------------------
180173
// OpenGL Compatibility Types
@@ -2406,6 +2399,14 @@ static inline bool sw_texture_alloc(sw_texture_t *texture, const void *data, int
24062399
int bpp = SW_PIXELFORMAT_SIZE[format];
24072400
int newSize = w*h*bpp;
24082401

2402+
if (texture->pixels == NULL)
2403+
{
2404+
texture->minFilter = SW_NEAREST;
2405+
texture->magFilter = SW_NEAREST;
2406+
texture->sWrap = SW_CLAMP;
2407+
texture->tWrap = SW_CLAMP;
2408+
}
2409+
24092410
if (newSize > texture->allocSz)
24102411
{
24112412
void *ptr = SW_REALLOC(texture->pixels, newSize);
@@ -2470,38 +2471,25 @@ static inline void sw_texture_sample_nearest(float *SW_RESTRICT color, const sw_
24702471
{
24712472
int x, y;
24722473

2473-
#ifdef SW_TEXTURE_REPEAT_POT_FAST
2474-
if ((tex->sWrap == SW_REPEAT) && ((tex->width & tex->wMinus1) == 0))
2475-
{
2476-
x = (int)(u*tex->width) & tex->wMinus1;
2477-
}
2478-
else
2479-
#endif
2480-
{
2481-
u = (tex->sWrap == SW_REPEAT)? sw_fract(u) : sw_saturate(u);
2482-
x = (int)(u*tex->width);
2483-
}
2474+
#if SW_SUPPORT_NPOT_TEXTURE
2475+
if (tex->sWrap == SW_REPEAT) x = (int)(sw_fract(u)*tex->width);
2476+
else x = (int)(sw_saturate(u)*tex->width);
24842477

2485-
#ifdef SW_TEXTURE_REPEAT_POT_FAST
2486-
if ((tex->tWrap == SW_REPEAT) && ((tex->height & tex->hMinus1) == 0))
2487-
{
2488-
y = (int)(v*tex->height) & tex->hMinus1;
2489-
}
2490-
else
2478+
if (tex->tWrap == SW_REPEAT) y = (int)(sw_fract(v)*tex->height);
2479+
else y = (int)(sw_saturate(v)*tex->height);
2480+
#else
2481+
if (tex->sWrap == SW_REPEAT) x = (int)(u*tex->width) & tex->wMinus1;
2482+
else x = (int)(sw_saturate(u)*tex->width);
2483+
2484+
if (tex->tWrap == SW_REPEAT) y = (int)(v*tex->height) & tex->hMinus1;
2485+
else y = (int)(sw_saturate(v)*tex->height);
24912486
#endif
2492-
{
2493-
v = (tex->tWrap == SW_REPEAT)? sw_fract(v) : sw_saturate(v);
2494-
y = (int)(v*tex->height);
2495-
}
24962487

24972488
tex->readColor(color, tex->pixels, y*tex->width + x);
24982489
}
24992490

25002491
static inline void sw_texture_sample_linear(float *SW_RESTRICT color, const sw_texture_t *SW_RESTRICT tex, float u, float v)
25012492
{
2502-
// TODO: With a bit more cleverness the number of operations can
2503-
// be clearly reduced, but for now it works fine
2504-
25052493
float xf = (u*tex->width) - 0.5f;
25062494
float yf = (v*tex->height) - 0.5f;
25072495

@@ -2514,41 +2502,36 @@ static inline void sw_texture_sample_linear(float *SW_RESTRICT color, const sw_t
25142502
int x1 = x0 + 1;
25152503
int y1 = y0 + 1;
25162504

2517-
if (tex->sWrap == SW_CLAMP)
2505+
if (tex->sWrap == SW_REPEAT)
25182506
{
2519-
x0 = (x0 > tex->wMinus1)? tex->wMinus1 : x0;
2520-
x1 = (x1 > tex->wMinus1)? tex->wMinus1 : x1;
2521-
}
2522-
#ifdef SW_TEXTURE_REPEAT_POT_FAST
2523-
else if ((tex->width & tex->wMinus1) == 0)
2524-
{
2525-
// POT fast path: bitmask wrap covers negative ints via two's complement
2507+
#if SW_SUPPORT_NPOT_TEXTURE
2508+
x0 = (x0%tex->width + tex->width)%tex->width;
2509+
x1 = (x1%tex->width + tex->width)%tex->width;
2510+
#else
25262511
x0 = x0 & tex->wMinus1;
25272512
x1 = x1 & tex->wMinus1;
2513+
#endif
25282514
}
2529-
#endif
25302515
else
25312516
{
2532-
x0 = (x0%tex->width + tex->width)%tex->width;
2533-
x1 = (x1%tex->width + tex->width)%tex->width;
2517+
x0 = sw_clamp_int(x0, 0, tex->wMinus1);
2518+
x1 = sw_clamp_int(x1, 0, tex->wMinus1);
25342519
}
25352520

2536-
if (tex->tWrap == SW_CLAMP)
2537-
{
2538-
y0 = (y0 > tex->hMinus1)? tex->hMinus1 : y0;
2539-
y1 = (y1 > tex->hMinus1)? tex->hMinus1 : y1;
2540-
}
2541-
#ifdef SW_TEXTURE_REPEAT_POT_FAST
2542-
else if ((tex->height & tex->hMinus1) == 0)
2521+
if (tex->tWrap == SW_REPEAT)
25432522
{
2523+
#if SW_SUPPORT_NPOT_TEXTURE
2524+
y0 = (y0%tex->height + tex->height)%tex->height;
2525+
y1 = (y1%tex->height + tex->height)%tex->height;
2526+
#else
25442527
y0 = y0 & tex->hMinus1;
25452528
y1 = y1 & tex->hMinus1;
2529+
#endif
25462530
}
2547-
#endif
25482531
else
25492532
{
2550-
y0 = (y0%tex->height + tex->height)%tex->height;
2551-
y1 = (y1%tex->height + tex->height)%tex->height;
2533+
y0 = sw_clamp_int(y0, 0, tex->hMinus1);
2534+
y1 = sw_clamp_int(y1, 0, tex->hMinus1);
25522535
}
25532536

25542537
float c00[4], c10[4], c01[4], c11[4];
@@ -5187,11 +5170,25 @@ void swTexParameteri(int param, int value)
51875170
case SW_TEXTURE_WRAP_S:
51885171
{
51895172
if (!sw_is_texture_wrap_valid(value)) { RLSW.errCode = SW_INVALID_ENUM; return; }
5173+
#if !SW_SUPPORT_NPOT_TEXTURE
5174+
if (value == SW_REPEAT && (RLSW.boundTexture->width & RLSW.boundTexture->wMinus1) != 0)
5175+
{
5176+
RLSW.errCode = SW_INVALID_OPERATION;
5177+
return;
5178+
}
5179+
#endif
51905180
RLSW.boundTexture->sWrap = (SWwrap)value;
51915181
} break;
51925182
case SW_TEXTURE_WRAP_T:
51935183
{
51945184
if (!sw_is_texture_wrap_valid(value)) { RLSW.errCode = SW_INVALID_ENUM; return; }
5185+
#if !SW_SUPPORT_NPOT_TEXTURE
5186+
if (value == SW_REPEAT && (RLSW.boundTexture->height & RLSW.boundTexture->hMinus1) != 0)
5187+
{
5188+
RLSW.errCode = SW_INVALID_OPERATION;
5189+
return;
5190+
}
5191+
#endif
51955192
RLSW.boundTexture->tWrap = (SWwrap)value;
51965193
} break;
51975194
default: RLSW.errCode = SW_INVALID_ENUM; break;
@@ -5574,8 +5571,7 @@ static void SW_RASTER_TRIANGLE(const sw_vertex_t *v0, const sw_vertex_t *v1, con
55745571
if (v1->position[1] > v2->position[1]) { const sw_vertex_t *tmp = v1; v1 = v2; v2 = tmp; }
55755572
if (v0->position[1] > v1->position[1]) { const sw_vertex_t *tmp = v0; v0 = v1; v1 = tmp; }
55765573

5577-
// Extracting coordinates from the sorted vertices
5578-
// Put x away for safe keeping; only y is used right now; silences warnings
5574+
// Extracting Y coordinates from the sorted vertices
55795575
float y0 = v0->position[1];
55805576
float y1 = v1->position[1];
55815577
float y2 = v2->position[1];

0 commit comments

Comments
 (0)