[rlsw] Completeness of glDraw functions (#5304)

* adding `glDrawElements`

* tweaks

* fix `glDrawArrays` and `glDrawElements` behavior
This commit is contained in:
Le Juez Victor 2025-10-26 00:58:56 +02:00 committed by GitHub
parent 1c20b5588d
commit a818508158
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

303
src/external/rlsw.h vendored
View File

@ -376,6 +376,7 @@ typedef double GLclampd;
#define glTexCoordPointer(sz, t, s, p) swBindArray(SW_TEXTURE_COORD_ARRAY, (p)) #define glTexCoordPointer(sz, t, s, p) swBindArray(SW_TEXTURE_COORD_ARRAY, (p))
#define glColorPointer(sz, t, s, p) swBindArray(SW_COLOR_ARRAY, (p)) #define glColorPointer(sz, t, s, p) swBindArray(SW_COLOR_ARRAY, (p))
#define glDrawArrays(m, o, c) swDrawArrays((m), (o), (c)) #define glDrawArrays(m, o, c) swDrawArrays((m), (o), (c))
#define glDrawElements(m,c,t,i) swDrawElements((m),(c),(t),(i))
#define glGenTextures(c, v) swGenTextures((c), (v)) #define glGenTextures(c, v) swGenTextures((c), (v))
#define glDeleteTextures(c, v) swDeleteTextures((c), (v)) #define glDeleteTextures(c, v) swDeleteTextures((c), (v))
#define glTexImage2D(tr, l, if, w, h, b, f, t, p) swTexImage2D((w), (h), (f), (t), (p)) #define glTexImage2D(tr, l, if, w, h, b, f, t, p) swTexImage2D((w), (h), (f), (t), (p))
@ -393,7 +394,6 @@ typedef double GLclampd;
#define glDepthFunc(X) ((void)(X)) #define glDepthFunc(X) ((void)(X))
#define glTexSubImage2D(X,Y,Z,W,A,B,C,D,E) ((void)(X),(void)(Y),(void)(Z),(void)(W),(void)(A),(void)(B),(void)(C),(void)(D),(void)(E)) #define glTexSubImage2D(X,Y,Z,W,A,B,C,D,E) ((void)(X),(void)(Y),(void)(Z),(void)(W),(void)(A),(void)(B),(void)(C),(void)(D),(void)(E))
#define glGetTexImage(X,Y,Z,W,A) ((void)(X),(void)(Y),(void)(Z),(void)(W),(void)(A)) #define glGetTexImage(X,Y,Z,W,A) ((void)(X),(void)(Y),(void)(Z),(void)(W),(void)(A))
#define glDrawElements(X,Y,Z,W) ((void)(X),(void)(Y),(void)(Z),(void)(W))
#define glNormal3f(X,Y,Z) ((void)(X),(void)(Y),(void)(Z)) #define glNormal3f(X,Y,Z) ((void)(X),(void)(Y),(void)(Z))
#define glNormal3fv(X) ((void)(X)) #define glNormal3fv(X) ((void)(X))
#define glNormalPointer(X,Y,Z) ((void)(X),(void)(Y),(void)(Z)) #define glNormalPointer(X,Y,Z) ((void)(X),(void)(Y),(void)(Z))
@ -589,6 +589,7 @@ SWAPI void swTexCoord2fv(const float *v);
SWAPI void swBindArray(SWarray type, void *buffer); SWAPI void swBindArray(SWarray type, void *buffer);
SWAPI void swDrawArrays(SWdraw mode, int offset, int count); SWAPI void swDrawArrays(SWdraw mode, int offset, int count);
SWAPI void swDrawElements(SWdraw mode, int count, int type, const void *indices);
SWAPI void swGenTextures(int count, uint32_t *textures); SWAPI void swGenTextures(int count, uint32_t *textures);
SWAPI void swDeleteTextures(int count, uint32_t *textures); SWAPI void swDeleteTextures(int count, uint32_t *textures);
@ -674,6 +675,7 @@ SWAPI void swBindTexture(uint32_t id);
// Defines and Macros // Defines and Macros
//---------------------------------------------------------------------------------- //----------------------------------------------------------------------------------
#define SW_PI 3.14159265358979323846f #define SW_PI 3.14159265358979323846f
#define SW_INV_255 0.00392156862745098f
#define SW_DEG2RAD (SW_PI/180.0f) #define SW_DEG2RAD (SW_PI/180.0f)
#define SW_RAD2DEG (180.0f/SW_PI) #define SW_RAD2DEG (180.0f/SW_PI)
@ -1120,26 +1122,26 @@ static inline void sw_float_from_unorm8_simd(float dst[4], const uint8_t src[4])
uint32x4_t ints = vmovl_u16(vget_low_u16(bytes16)); uint32x4_t ints = vmovl_u16(vget_low_u16(bytes16));
float32x4_t floats = vcvtq_f32_u32(ints); float32x4_t floats = vcvtq_f32_u32(ints);
floats = vmulq_n_f32(floats, 1.0f/255.0f); floats = vmulq_n_f32(floats, SW_INV_255);
vst1q_f32(dst, floats); vst1q_f32(dst, floats);
#elif defined(SW_HAS_SSE41) #elif defined(SW_HAS_SSE41)
__m128i bytes = _mm_cvtsi32_si128(*(const uint32_t*)src); __m128i bytes = _mm_cvtsi32_si128(*(const uint32_t*)src);
__m128i ints = _mm_cvtepu8_epi32(bytes); __m128i ints = _mm_cvtepu8_epi32(bytes);
__m128 floats = _mm_cvtepi32_ps(ints); __m128 floats = _mm_cvtepi32_ps(ints);
floats = _mm_mul_ps(floats, _mm_set1_ps(1.0f/255.0f)); floats = _mm_mul_ps(floats, _mm_set1_ps(SW_INV_255));
_mm_storeu_ps(dst, floats); _mm_storeu_ps(dst, floats);
#elif defined(SW_HAS_SSE2) #elif defined(SW_HAS_SSE2)
__m128i bytes = _mm_cvtsi32_si128(*(const uint32_t*)src); __m128i bytes = _mm_cvtsi32_si128(*(const uint32_t*)src);
bytes = _mm_unpacklo_epi8(bytes, _mm_setzero_si128()); bytes = _mm_unpacklo_epi8(bytes, _mm_setzero_si128());
__m128i ints = _mm_unpacklo_epi16(bytes, _mm_setzero_si128()); __m128i ints = _mm_unpacklo_epi16(bytes, _mm_setzero_si128());
__m128 floats = _mm_cvtepi32_ps(ints); __m128 floats = _mm_cvtepi32_ps(ints);
floats = _mm_mul_ps(floats, _mm_set1_ps(1.0f/255.0f)); floats = _mm_mul_ps(floats, _mm_set1_ps(SW_INV_255));
_mm_storeu_ps(dst, floats); _mm_storeu_ps(dst, floats);
#else #else
dst[0] = (float)src[0]/255.0f; dst[0] = (float)src[0]*SW_INV_255;
dst[1] = (float)src[1]/255.0f; dst[1] = (float)src[1]*SW_INV_255;
dst[2] = (float)src[2]/255.0f; dst[2] = (float)src[2]*SW_INV_255;
dst[3] = (float)src[3]/255.0f; dst[3] = (float)src[3]*SW_INV_255;
#endif #endif
} }
@ -1894,7 +1896,7 @@ static inline void sw_get_pixel(uint8_t *color, const void *pixels, uint32_t off
case SW_PIXELFORMAT_UNCOMPRESSED_R16: case SW_PIXELFORMAT_UNCOMPRESSED_R16:
{ {
uint16_t val = ((const uint16_t*)pixels)[offset]; uint16_t val = ((const uint16_t*)pixels)[offset];
uint8_t gray = sw_half_to_float(val)/255.0f; uint8_t gray = sw_half_to_float(val)*SW_INV_255;
color[0] = gray; color[0] = gray;
color[1] = gray; color[1] = gray;
color[2] = gray; color[2] = gray;
@ -1904,19 +1906,19 @@ static inline void sw_get_pixel(uint8_t *color, const void *pixels, uint32_t off
case SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16: case SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16:
{ {
const uint16_t *src = &((const uint16_t*)pixels)[offset*3]; const uint16_t *src = &((const uint16_t*)pixels)[offset*3];
color[0] = sw_half_to_float(src[0])/255.0f; color[0] = sw_half_to_float(src[0])*SW_INV_255;
color[1] = sw_half_to_float(src[1])/255.0f; color[1] = sw_half_to_float(src[1])*SW_INV_255;
color[2] = sw_half_to_float(src[2])/255.0f; color[2] = sw_half_to_float(src[2])*SW_INV_255;
color[3] = 255; color[3] = 255;
break; break;
} }
case SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16: case SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16:
{ {
const uint16_t *src = &((const uint16_t*)pixels)[offset*4]; const uint16_t *src = &((const uint16_t*)pixels)[offset*4];
color[0] = sw_half_to_float(src[0])/255.0f; color[0] = sw_half_to_float(src[0])*SW_INV_255;
color[1] = sw_half_to_float(src[1])/255.0f; color[1] = sw_half_to_float(src[1])*SW_INV_255;
color[2] = sw_half_to_float(src[2])/255.0f; color[2] = sw_half_to_float(src[2])*SW_INV_255;
color[3] = sw_half_to_float(src[3])/255.0f; color[3] = sw_half_to_float(src[3])*SW_INV_255;
break; break;
} }
case SW_PIXELFORMAT_UNKNOWN: case SW_PIXELFORMAT_UNKNOWN:
@ -3404,7 +3406,7 @@ static inline void sw_point_render(sw_vertex_t *v)
} }
//------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------
// Polygon modes mendering logic // Polygon modes rendering logic
//------------------------------------------------------------------------------------------- //-------------------------------------------------------------------------------------------
static inline void sw_poly_point_render(void) static inline void sw_poly_point_render(void)
{ {
@ -3436,9 +3438,47 @@ static inline void sw_poly_fill_render(void)
case SW_QUADS: sw_quad_render(); break; case SW_QUADS: sw_quad_render(); break;
} }
} }
//-------------------------------------------------------------------------------------------
// Immediate rendering logic
//-------------------------------------------------------------------------------------------
void sw_immediate_push_vertex(const float position[4], const float color[4], const float texcoord[2])
{
// Copy the attributes in the current vertex
sw_vertex_t *vertex = &RLSW.vertexBuffer[RLSW.vertexCounter++];
for (int i = 0; i < 4; i++)
{
vertex->position[i] = position[i];
if (i < 2) vertex->texcoord[i] = texcoord[i];
vertex->color[i] = color[i];
}
// Calculate homogeneous coordinates
const float *m = RLSW.matMVP, *v = vertex->position;
vertex->homogeneous[0] = m[0]*v[0] + m[4]*v[1] + m[8]*v[2] + m[12]*v[3];
vertex->homogeneous[1] = m[1]*v[0] + m[5]*v[1] + m[9]*v[2] + m[13]*v[3];
vertex->homogeneous[2] = m[2]*v[0] + m[6]*v[1] + m[10]*v[2] + m[14]*v[3];
vertex->homogeneous[3] = m[3]*v[0] + m[7]*v[1] + m[11]*v[2] + m[15]*v[3];
// Immediate rendering of the primitive if the required number is reached
if (RLSW.vertexCounter == RLSW.reqVertices)
{
switch (RLSW.polyMode)
{
case SW_FILL: sw_poly_fill_render(); break;
case SW_LINE: sw_poly_line_render(); break;
case SW_POINT: sw_poly_point_render(); break;
default: break;
}
RLSW.vertexCounter = 0;
}
}
//-------------------------------------------------------------------------------------------
// Validity check helper functions // Validity check helper functions
//-------------------------------------------------------------------------------------------
static inline bool sw_is_texture_valid(uint32_t id) static inline bool sw_is_texture_valid(uint32_t id)
{ {
bool valid = true; bool valid = true;
@ -4301,89 +4341,62 @@ void swEnd(void)
void swVertex2i(int x, int y) void swVertex2i(int x, int y)
{ {
const float v[4] = { (float)x, (float)y, 0.0f, 1.0f }; const float v[4] = { (float)x, (float)y, 0.0f, 1.0f };
swVertex4fv(v); sw_immediate_push_vertex(v, RLSW.current.color, RLSW.current.texcoord);
} }
void swVertex2f(float x, float y) void swVertex2f(float x, float y)
{ {
const float v[4] = { x, y, 0.0f, 1.0f }; const float v[4] = { x, y, 0.0f, 1.0f };
swVertex4fv(v); sw_immediate_push_vertex(v, RLSW.current.color, RLSW.current.texcoord);
} }
void swVertex2fv(const float *v) void swVertex2fv(const float *v)
{ {
const float v4[4] = { v[0], v[1], 0.0f, 1.0f }; const float v4[4] = { v[0], v[1], 0.0f, 1.0f };
swVertex4fv(v4); sw_immediate_push_vertex(v, RLSW.current.color, RLSW.current.texcoord);
} }
void swVertex3i(int x, int y, int z) void swVertex3i(int x, int y, int z)
{ {
const float v[4] = { (float)x, (float)y, (float)z, 1.0f }; const float v[4] = { (float)x, (float)y, (float)z, 1.0f };
swVertex4fv(v); sw_immediate_push_vertex(v, RLSW.current.color, RLSW.current.texcoord);
} }
void swVertex3f(float x, float y, float z) void swVertex3f(float x, float y, float z)
{ {
const float v[4] = { x, y, z, 1.0f }; const float v[4] = { x, y, z, 1.0f };
swVertex4fv(v); sw_immediate_push_vertex(v, RLSW.current.color, RLSW.current.texcoord);
} }
void swVertex3fv(const float *v) void swVertex3fv(const float *v)
{ {
const float v4[4] = { v[0], v[1], v[2], 1.0f }; const float v4[4] = { v[0], v[1], v[2], 1.0f };
swVertex4fv(v4); sw_immediate_push_vertex(v, RLSW.current.color, RLSW.current.texcoord);
} }
void swVertex4i(int x, int y, int z, int w) void swVertex4i(int x, int y, int z, int w)
{ {
const float v[4] = { (float)x, (float)y, (float)z, (float)w }; const float v[4] = { (float)x, (float)y, (float)z, (float)w };
swVertex4fv(v); sw_immediate_push_vertex(v, RLSW.current.color, RLSW.current.texcoord);
} }
void swVertex4f(float x, float y, float z, float w) void swVertex4f(float x, float y, float z, float w)
{ {
const float v[4] = { x, y, z, w }; const float v[4] = { x, y, z, w };
swVertex4fv(v); sw_immediate_push_vertex(v, RLSW.current.color, RLSW.current.texcoord);
} }
void swVertex4fv(const float *v) void swVertex4fv(const float *v)
{ {
// Copy the position in the current vertex sw_immediate_push_vertex(v, RLSW.current.color, RLSW.current.texcoord);
sw_vertex_t *vertex = &RLSW.vertexBuffer[RLSW.vertexCounter++];
for (int i = 0; i < 4; i++) vertex->position[i] = v[i];
// Copy additonal vertex data
for (int i = 0; i < 2; i++) vertex->texcoord[i] = RLSW.current.texcoord[i];
for (int i = 0; i < 4; i++) vertex->color[i] = RLSW.current.color[i];
// Calculation of homogeneous coordinates
const float *m = RLSW.matMVP;
vertex->homogeneous[0] = m[0]*v[0] + m[4]*v[1] + m[8]*v[2] + m[12]*v[3];
vertex->homogeneous[1] = m[1]*v[0] + m[5]*v[1] + m[9]*v[2] + m[13]*v[3];
vertex->homogeneous[2] = m[2]*v[0] + m[6]*v[1] + m[10]*v[2] + m[14]*v[3];
vertex->homogeneous[3] = m[3]*v[0] + m[7]*v[1] + m[11]*v[2] + m[15]*v[3];
// Immediate rendering of the primitive if the required number is reached
if (RLSW.vertexCounter == RLSW.reqVertices)
{
switch (RLSW.polyMode)
{
case SW_FILL: sw_poly_fill_render(); break;
case SW_LINE: sw_poly_line_render(); break;
case SW_POINT: sw_poly_point_render(); break;
default: break;
}
RLSW.vertexCounter = 0;
}
} }
void swColor3ub(uint8_t r, uint8_t g, uint8_t b) void swColor3ub(uint8_t r, uint8_t g, uint8_t b)
{ {
float cv[4]; float cv[4];
cv[0] = (float)r/255; cv[0] = (float)r*SW_INV_255;
cv[1] = (float)g/255; cv[1] = (float)g*SW_INV_255;
cv[2] = (float)b/255; cv[2] = (float)b*SW_INV_255;
cv[3] = 1.0f; cv[3] = 1.0f;
swColor4fv(cv); swColor4fv(cv);
@ -4392,9 +4405,9 @@ void swColor3ub(uint8_t r, uint8_t g, uint8_t b)
void swColor3ubv(const uint8_t *v) void swColor3ubv(const uint8_t *v)
{ {
float cv[4]; float cv[4];
cv[0] = (float)v[0]/255; cv[0] = (float)v[0]*SW_INV_255;
cv[1] = (float)v[1]/255; cv[1] = (float)v[1]*SW_INV_255;
cv[2] = (float)v[2]/255; cv[2] = (float)v[2]*SW_INV_255;
cv[3] = 1.0f; cv[3] = 1.0f;
swColor4fv(cv); swColor4fv(cv);
@ -4425,10 +4438,10 @@ void swColor3fv(const float *v)
void swColor4ub(uint8_t r, uint8_t g, uint8_t b, uint8_t a) void swColor4ub(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
{ {
float cv[4]; float cv[4];
cv[0] = (float)r/255; cv[0] = (float)r*SW_INV_255;
cv[1] = (float)g/255; cv[1] = (float)g*SW_INV_255;
cv[2] = (float)b/255; cv[2] = (float)b*SW_INV_255;
cv[3] = (float)a/255; cv[3] = (float)a*SW_INV_255;
swColor4fv(cv); swColor4fv(cv);
} }
@ -4436,10 +4449,10 @@ void swColor4ub(uint8_t r, uint8_t g, uint8_t b, uint8_t a)
void swColor4ubv(const uint8_t *v) void swColor4ubv(const uint8_t *v)
{ {
float cv[4]; float cv[4];
cv[0] = (float)v[0]/255; cv[0] = (float)v[0]*SW_INV_255;
cv[1] = (float)v[1]/255; cv[1] = (float)v[1]*SW_INV_255;
cv[2] = (float)v[2]/255; cv[2] = (float)v[2]*SW_INV_255;
cv[3] = (float)v[3]/255; cv[3] = (float)v[3]*SW_INV_255;
swColor4fv(cv); swColor4fv(cv);
} }
@ -4497,14 +4510,156 @@ void swDrawArrays(SWdraw mode, int offset, int count)
swBegin(mode); swBegin(mode);
{ {
swTexCoord2f(0.0f, 0.0f); const float *texMatrix = RLSW.stackTexture[RLSW.stackTextureCounter - 1];
swColor4f(1.0f, 1.0f, 1.0f, 1.0f); const float *defaultTexcoord = RLSW.current.texcoord;
const float *defaultColor = RLSW.current.color;
for (int i = offset; i < count; i++) const float *positions = RLSW.array.positions;
const float *texcoords = RLSW.array.texcoords;
const uint8_t *colors = RLSW.array.colors;
int end = offset + count;
for (int i = offset; i < end; i++)
{ {
if (RLSW.array.texcoords) swTexCoord2fv(RLSW.array.texcoords + 2*i); float u, v;
if (RLSW.array.colors) swColor4ubv(RLSW.array.colors + 4*i); if (texcoords)
swVertex3fv(RLSW.array.positions + 3*i); {
int idx = 2 * i;
u = texcoords[idx];
v = texcoords[idx + 1];
}
else
{
u = defaultTexcoord[0];
v = defaultTexcoord[1];
}
float texcoord[2];
texcoord[0] = texMatrix[0] * u + texMatrix[4] * v + texMatrix[12];
texcoord[1] = texMatrix[1] * u + texMatrix[5] * v + texMatrix[13];
float color[4] = {
defaultColor[0],
defaultColor[1],
defaultColor[2],
defaultColor[3]
};
if (colors)
{
int idx = 4 * i;
color[0] *= (float)colors[idx]*SW_INV_255;
color[1] *= (float)colors[idx + 1]*SW_INV_255;
color[2] *= (float)colors[idx + 2]*SW_INV_255;
color[3] *= (float)colors[idx + 3]*SW_INV_255;
}
int idx = 3 * i;
float position[4] = {
positions[idx],
positions[idx + 1],
positions[idx + 2],
1.0f
};
sw_immediate_push_vertex(position, color, texcoord);
}
}
swEnd();
}
void swDrawElements(SWdraw mode, int count, int type, const void *indices)
{
if (RLSW.array.positions == 0)
{
RLSW.errCode = SW_INVALID_OPERATION;
return;
}
if (count < 0)
{
RLSW.errCode = SW_INVALID_VALUE;
return;
}
const uint8_t *indicesUb = NULL;
const uint16_t *indicesUs = NULL;
const uint32_t *indicesUi = NULL;
switch (type)
{
case SW_UNSIGNED_BYTE:
indicesUb = (const uint8_t *)indices;
break;
case SW_UNSIGNED_SHORT:
indicesUs = (const uint16_t *)indices;
break;
case SW_UNSIGNED_INT:
indicesUi = (const uint32_t *)indices;
break;
default:
RLSW.errCode = SW_INVALID_ENUM;
return;
}
swBegin(mode);
{
const float *texMatrix = RLSW.stackTexture[RLSW.stackTextureCounter - 1];
const float *defaultTexcoord = RLSW.current.texcoord;
const float *defaultColor = RLSW.current.color;
const float *positions = RLSW.array.positions;
const float *texcoords = RLSW.array.texcoords;
const uint8_t *colors = RLSW.array.colors;
for (int i = 0; i < count; i++)
{
int index = indicesUb ? indicesUb[i] :
(indicesUs ? indicesUs[i] : indicesUi[i]);
float u, v;
if (texcoords)
{
int idx = 2 * index;
u = texcoords[idx];
v = texcoords[idx + 1];
}
else
{
u = defaultTexcoord[0];
v = defaultTexcoord[1];
}
float texcoord[2];
texcoord[0] = texMatrix[0] * u + texMatrix[4] * v + texMatrix[12];
texcoord[1] = texMatrix[1] * u + texMatrix[5] * v + texMatrix[13];
float color[4] = {
defaultColor[0],
defaultColor[1],
defaultColor[2],
defaultColor[3]
};
if (colors)
{
int idx = 4 * index;
color[0] *= (float)colors[idx]*SW_INV_255;
color[1] *= (float)colors[idx + 1]*SW_INV_255;
color[2] *= (float)colors[idx + 2]*SW_INV_255;
color[3] *= (float)colors[idx + 3]*SW_INV_255;
}
int idx = 3 * index;
float position[4] = {
positions[idx],
positions[idx + 1],
positions[idx + 2],
1.0f
};
sw_immediate_push_vertex(position, color, texcoord);
} }
} }
swEnd(); swEnd();