Commit 87bc1fb55240839f00e4346e56576ea9f7a20d67

Andreas M?ller 2018-08-28T12:57:51

GLES2: Get sin/cos out of vertex shader The only place angle is activated and causes effect is RenderCopyEx. All other methods which use vertex shader, leave angle disabled and cause useless sin/cos calculation in shader. To get around shader's interface is changed to a vector that contains results of sin and cos. To behave properly when disabled, cos value is set with offset -1.0 making 0.0 default when deactivated. As nice side effect it simplifies GLES2_UpdateVertexBuffer: All attributes are vectors now. Additional background: * On RaspberryPi it gives a performace win for operations. Tested with [1] numbers go down for 5-10% (not easy to estimate due to huge variation). * SDL_RenderCopyEx was tested with [2] * It works around left rotated display caused by low accuracy sin implemetation in RaspberryPi/VC4 [3] [1] https://github.com/schnitzeltony/sdl2box [2] https://github.com/schnitzeltony/sdl2rendercopyex [3] https://github.com/anholt/mesa/issues/110 Signed-off-by: Andreas M?ller <schnitzeltony@gmail.com>

diff --git a/src/render/opengles2/SDL_render_gles2.c b/src/render/opengles2/SDL_render_gles2.c
index a2399a7..af83740 100644
--- a/src/render/opengles2/SDL_render_gles2.c
+++ b/src/render/opengles2/SDL_render_gles2.c
@@ -1534,7 +1534,7 @@ GLES2_UpdateVertexBuffer(SDL_Renderer *renderer, GLES2_Attribute attr,
     GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata;
 
 #if !SDL_GLES2_USE_VBOS
-    data->glVertexAttribPointer(attr, attr == GLES2_ATTRIBUTE_ANGLE ? 1 : 2, GL_FLOAT, GL_FALSE, 0, vertexData);
+    data->glVertexAttribPointer(attr, 2, GL_FLOAT, GL_FALSE, 0, vertexData);
 #else
     if (!data->vertex_buffers[attr]) {
         data->glGenBuffers(1, &data->vertex_buffers[attr]);
@@ -1549,7 +1549,7 @@ GLES2_UpdateVertexBuffer(SDL_Renderer *renderer, GLES2_Attribute attr,
         data->glBufferSubData(GL_ARRAY_BUFFER, 0, dataSizeInBytes, vertexData);
     }
 
-    data->glVertexAttribPointer(attr, attr == GLES2_ATTRIBUTE_ANGLE ? 1 : 2, GL_FLOAT, GL_FALSE, 0, 0);
+    data->glVertexAttribPointer(attr, 2, GL_FLOAT, GL_FALSE, 0, 0);
 #endif
 
     return 0;
@@ -1857,6 +1857,8 @@ GLES2_RenderCopy(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *s
     return GL_CheckError("", renderer);
 }
 
+#define PI 3.14159265f
+
 static int
 GLES2_RenderCopyEx(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect *srcrect,
                  const SDL_FRect *dstrect, const double angle, const SDL_FPoint *center, const SDL_RendererFlip flip)
@@ -1865,8 +1867,9 @@ GLES2_RenderCopyEx(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect 
     GLfloat vertices[8];
     GLfloat texCoords[8];
     GLfloat translate[8];
-    GLfloat fAngle[4];
+    GLfloat fAngle[8];
     GLfloat tmp;
+    float radian_angle;
 
     GLES2_ActivateRenderer(renderer);
 
@@ -1876,7 +1879,11 @@ GLES2_RenderCopyEx(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect 
 
     data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_CENTER);
     data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_ANGLE);
-    fAngle[0] = fAngle[1] = fAngle[2] = fAngle[3] = (GLfloat)(360.0f - angle);
+
+    radian_angle = PI * (360.0f - angle) / 180.f;
+    fAngle[0] = fAngle[2] = fAngle[4] = fAngle[6] = (GLfloat)sin(radian_angle);
+    /* render expects cos value - 1 (see GLES2_VertexSrc_Default_) */
+    fAngle[1] = fAngle[3] = fAngle[5] = fAngle[7] = (GLfloat)cos(radian_angle) - 1.0f;
     /* Calculate the center of rotation */
     translate[0] = translate[2] = translate[4] = translate[6] = (center->x + dstrect->x);
     translate[1] = translate[3] = translate[5] = translate[7] = (center->y + dstrect->y);
@@ -1905,7 +1912,7 @@ GLES2_RenderCopyEx(SDL_Renderer *renderer, SDL_Texture *texture, const SDL_Rect 
     data->glVertexAttribPointer(GLES2_ATTRIBUTE_CENTER, 2, GL_FLOAT, GL_FALSE, 0, translate);
     data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);*/
 
-    GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_ANGLE, fAngle, 4 * sizeof(GLfloat));
+    GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_ANGLE, fAngle, 8 * sizeof(GLfloat));
     GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_CENTER, translate, 8 * sizeof(GLfloat));
     GLES2_UpdateVertexBuffer(renderer, GLES2_ATTRIBUTE_POSITION, vertices, 8 * sizeof(GLfloat));
 
diff --git a/src/render/opengles2/SDL_shaders_gles2.c b/src/render/opengles2/SDL_shaders_gles2.c
index b0bcdff..f428a49 100644
--- a/src/render/opengles2/SDL_shaders_gles2.c
+++ b/src/render/opengles2/SDL_shaders_gles2.c
@@ -30,20 +30,24 @@
 /*************************************************************************************************
  * Vertex/fragment shader source                                                                 *
  *************************************************************************************************/
-
+/* Notes on a_angle:
+   * It is a vector containing sin and cos for rotation matrix
+   * To get correct rotation for most cases when a_angle is disabled cos
+     value is decremented by 1.0 to get proper output with 0.0 which is
+     default value
+*/
 static const Uint8 GLES2_VertexSrc_Default_[] = " \
     uniform mat4 u_projection; \
     attribute vec2 a_position; \
     attribute vec2 a_texCoord; \
-    attribute float a_angle; \
+    attribute vec2 a_angle; \
     attribute vec2 a_center; \
     varying vec2 v_texCoord; \
     \
     void main() \
     { \
-        float angle = radians(a_angle); \
-        float c = cos(angle); \
-        float s = sin(angle); \
+        float s = a_angle[0]; \
+        float c = a_angle[1] + 1.0; \
         mat2 rotationMatrix = mat2(c, -s, s, c); \
         vec2 position = rotationMatrix * (a_position - a_center) + a_center; \
         v_texCoord = a_texCoord; \