blob: 9b32b3788dfaba20c7a49d86d94a680872dd8568 [file] [log] [blame]
From c215ba1d52a3d4ef03af3ab1a5baa1863f812aed Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Andreas=20M=C3=BCller?= <schnitzeltony@gmail.com>
Date: Fri, 24 Aug 2018 23:10:25 +0200
Subject: [PATCH] GLES2: Get sin/cos out of vertex shader
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
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]
Upstream-Status: Accepted [4]
[1] https://github.com/schnitzeltony/sdl2box
[2] https://github.com/schnitzeltony/sdl2rendercopyex
[3] https://github.com/anholt/mesa/issues/110
[4] https://hg.libsdl.org/SDL/rev/e5a666405750
Signed-off-by: Andreas Müller <schnitzeltony@gmail.com>
---
src/render/opengles2/SDL_render_gles2.c | 17 ++++++++++++-----
src/render/opengles2/SDL_shaders_gles2.c | 14 +++++++++-----
2 files changed, 21 insertions(+), 10 deletions(-)
diff --git a/src/render/opengles2/SDL_render_gles2.c b/src/render/opengles2/SDL_render_gles2.c
index 14671f7c8..7c54a7333 100644
--- a/src/render/opengles2/SDL_render_gles2.c
+++ b/src/render/opengles2/SDL_render_gles2.c
@@ -1530,7 +1530,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]);
@@ -1545,7 +1545,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;
@@ -1853,6 +1853,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)
@@ -1861,8 +1863,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);
@@ -1872,7 +1875,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);
@@ -1901,7 +1908,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 b0bcdff25..f428a4945 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; \
--
2.14.4