浏览代码

[rlsw] Completeness of `glDraw` functions (#5304)

* adding `glDrawElements`

* tweaks

* fix `glDrawArrays` and `glDrawElements` behavior
Le Juez Victor 1 月之前
父节点
当前提交
a818508158
共有 1 个文件被更改,包括 229 次插入74 次删除
  1. 229 74
      src/external/rlsw.h

+ 229 - 74
src/external/rlsw.h

@@ -376,6 +376,7 @@ typedef double              GLclampd;
 #define glTexCoordPointer(sz, t, s, p)              swBindArray(SW_TEXTURE_COORD_ARRAY, (p))
 #define glColorPointer(sz, t, s, p)                 swBindArray(SW_COLOR_ARRAY, (p))
 #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 glDeleteTextures(c, v)                      swDeleteTextures((c), (v))
 #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 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 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 glNormal3fv(X)                          ((void)(X))
 #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 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 swDeleteTextures(int count, uint32_t *textures);
@@ -674,6 +675,7 @@ SWAPI void swBindTexture(uint32_t id);
 // Defines and Macros
 //----------------------------------------------------------------------------------
 #define SW_PI       3.14159265358979323846f
+#define SW_INV_255  0.00392156862745098f
 #define SW_DEG2RAD  (SW_PI/180.0f)
 #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));
 
     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);
 #elif defined(SW_HAS_SSE41)
     __m128i bytes = _mm_cvtsi32_si128(*(const uint32_t*)src);
     __m128i ints = _mm_cvtepu8_epi32(bytes);
     __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);
 #elif defined(SW_HAS_SSE2)
     __m128i bytes = _mm_cvtsi32_si128(*(const uint32_t*)src);
     bytes = _mm_unpacklo_epi8(bytes, _mm_setzero_si128());
     __m128i ints = _mm_unpacklo_epi16(bytes, _mm_setzero_si128());
     __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);
 #else
-    dst[0] = (float)src[0]/255.0f;
-    dst[1] = (float)src[1]/255.0f;
-    dst[2] = (float)src[2]/255.0f;
-    dst[3] = (float)src[3]/255.0f;
+    dst[0] = (float)src[0]*SW_INV_255;
+    dst[1] = (float)src[1]*SW_INV_255;
+    dst[2] = (float)src[2]*SW_INV_255;
+    dst[3] = (float)src[3]*SW_INV_255;
 #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:
         {
             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[1] = 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:
         {
             const uint16_t *src = &((const uint16_t*)pixels)[offset*3];
-            color[0] = sw_half_to_float(src[0])/255.0f;
-            color[1] = sw_half_to_float(src[1])/255.0f;
-            color[2] = sw_half_to_float(src[2])/255.0f;
+            color[0] = sw_half_to_float(src[0])*SW_INV_255;
+            color[1] = sw_half_to_float(src[1])*SW_INV_255;
+            color[2] = sw_half_to_float(src[2])*SW_INV_255;
             color[3] = 255;
             break;
         }
         case SW_PIXELFORMAT_UNCOMPRESSED_R16G16B16A16:
         {
             const uint16_t *src = &((const uint16_t*)pixels)[offset*4];
-            color[0] = sw_half_to_float(src[0])/255.0f;
-            color[1] = sw_half_to_float(src[1])/255.0f;
-            color[2] = sw_half_to_float(src[2])/255.0f;
-            color[3] = sw_half_to_float(src[3])/255.0f;
+            color[0] = sw_half_to_float(src[0])*SW_INV_255;
+            color[1] = sw_half_to_float(src[1])*SW_INV_255;
+            color[2] = sw_half_to_float(src[2])*SW_INV_255;
+            color[3] = sw_half_to_float(src[3])*SW_INV_255;
             break;
         }
         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)
 {
@@ -3436,9 +3438,47 @@ static inline void sw_poly_fill_render(void)
         case SW_QUADS: sw_quad_render(); break;
     }
 }
+//-------------------------------------------------------------------------------------------
 
-// Validity check helper functions
+// 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
+//-------------------------------------------------------------------------------------------
 static inline bool sw_is_texture_valid(uint32_t id)
 {
     bool valid = true;
@@ -4301,89 +4341,62 @@ void swEnd(void)
 void swVertex2i(int x, int y)
 {
     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)
 {
     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)
 {
     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)
 {
     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)
 {
     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)
 {
     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)
 {
     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)
 {
     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)
 {
-    // Copy the position in the current vertex
-    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;
-    }
+    sw_immediate_push_vertex(v, RLSW.current.color, RLSW.current.texcoord);
 }
 
 void swColor3ub(uint8_t r, uint8_t g, uint8_t b)
 {
     float cv[4];
-    cv[0] = (float)r/255;
-    cv[1] = (float)g/255;
-    cv[2] = (float)b/255;
+    cv[0] = (float)r*SW_INV_255;
+    cv[1] = (float)g*SW_INV_255;
+    cv[2] = (float)b*SW_INV_255;
     cv[3] = 1.0f;
 
     swColor4fv(cv);
@@ -4392,9 +4405,9 @@ void swColor3ub(uint8_t r, uint8_t g, uint8_t b)
 void swColor3ubv(const uint8_t *v)
 {
     float cv[4];
-    cv[0] = (float)v[0]/255;
-    cv[1] = (float)v[1]/255;
-    cv[2] = (float)v[2]/255;
+    cv[0] = (float)v[0]*SW_INV_255;
+    cv[1] = (float)v[1]*SW_INV_255;
+    cv[2] = (float)v[2]*SW_INV_255;
     cv[3] = 1.0f;
 
     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)
 {
     float cv[4];
-    cv[0] = (float)r/255;
-    cv[1] = (float)g/255;
-    cv[2] = (float)b/255;
-    cv[3] = (float)a/255;
+    cv[0] = (float)r*SW_INV_255;
+    cv[1] = (float)g*SW_INV_255;
+    cv[2] = (float)b*SW_INV_255;
+    cv[3] = (float)a*SW_INV_255;
 
     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)
 {
     float cv[4];
-    cv[0] = (float)v[0]/255;
-    cv[1] = (float)v[1]/255;
-    cv[2] = (float)v[2]/255;
-    cv[3] = (float)v[3]/255;
+    cv[0] = (float)v[0]*SW_INV_255;
+    cv[1] = (float)v[1]*SW_INV_255;
+    cv[2] = (float)v[2]*SW_INV_255;
+    cv[3] = (float)v[3]*SW_INV_255;
 
     swColor4fv(cv);
 }
@@ -4497,14 +4510,156 @@ void swDrawArrays(SWdraw mode, int offset, int count)
 
     swBegin(mode);
     {
-        swTexCoord2f(0.0f, 0.0f);
-        swColor4f(1.0f, 1.0f, 1.0f, 1.0f);
+        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;
+
+        int end = offset + count;
+        
+        for (int i = offset; i < end; i++)
+        {
+            float u, v;
+            if (texcoords)
+            {
+                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;
+    }
 
-        for (int i = offset; i < count; i++)
+    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++)
         {
-            if (RLSW.array.texcoords) swTexCoord2fv(RLSW.array.texcoords + 2*i);
-            if (RLSW.array.colors) swColor4ubv(RLSW.array.colors + 4*i);
-            swVertex3fv(RLSW.array.positions + 3*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();