src/render/opengles2/SDL_render_gles2.c
changeset 5355 cc2215cda170
parent 5333 5d3a2cd4e8c9
child 5402 5d102cd8aef3
--- a/src/render/opengles2/SDL_render_gles2.c	Sat Feb 19 21:51:03 2011 -0800
+++ b/src/render/opengles2/SDL_render_gles2.c	Sat Feb 19 21:51:21 2011 -0800
@@ -58,6 +58,7 @@
     GLenum pixel_type;
     void *pixel_data;
     size_t pitch;
+    GLenum scaleMode;
 } GLES2_TextureData;
 
 typedef struct GLES2_ShaderCacheEntry
@@ -118,6 +119,12 @@
 typedef struct GLES2_DriverContext
 {
     SDL_GLContext *context;
+    struct {
+        int blendMode;
+        GLenum scaleMode;
+        SDL_bool tex_coords;
+    } current;
+
     int shader_format_count;
     GLenum *shader_formats;
     GLES2_ShaderCache shader_cache;
@@ -259,6 +266,7 @@
     tdata->texture_type = GL_TEXTURE_2D;
     tdata->pixel_format = format;
     tdata->pixel_type = type;
+    tdata->scaleMode = GL_LINEAR;
 
     /* Allocate a blob for image data */
     if (texture->access == SDL_TEXTUREACCESS_STREAMING)
@@ -787,59 +795,83 @@
 }
 
 static void
-GLES2_SetBlendMode(int blendMode)
+GLES2_SetBlendMode(GLES2_DriverContext *rdata, int blendMode)
+{
+    if (blendMode != rdata->current.blendMode) {
+        switch (blendMode) {
+        default:
+        case SDL_BLENDMODE_NONE:
+            glDisable(GL_BLEND);
+            break;
+        case SDL_BLENDMODE_BLEND:
+            glEnable(GL_BLEND);
+            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+            break;
+        case SDL_BLENDMODE_ADD:
+            glEnable(GL_BLEND);
+            glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+            break;
+        case SDL_BLENDMODE_MOD:
+            glEnable(GL_BLEND);
+            glBlendFunc(GL_ZERO, GL_SRC_COLOR);
+            break;
+        }
+        rdata->current.blendMode = blendMode;
+    }
+}
+
+static void
+GLES2_SetTexCoords(GLES2_DriverContext * rdata, SDL_bool enabled)
 {
-    switch (blendMode)
-    {
-    case SDL_BLENDMODE_NONE:
-    default:
-        glDisable(GL_BLEND);
-        break;
-    case SDL_BLENDMODE_BLEND:
-        glEnable(GL_BLEND);
-        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-        break;
-    case SDL_BLENDMODE_ADD:
-        glEnable(GL_BLEND);
-        glBlendFunc(GL_SRC_ALPHA, GL_ONE);
-        break;
-    case SDL_BLENDMODE_MOD:
-        glEnable(GL_BLEND);
-        glBlendFunc(GL_ZERO, GL_SRC_COLOR);
-        break;
+    if (enabled != rdata->current.tex_coords) {
+        if (enabled) {
+            glEnableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD);
+        } else {
+            glDisableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD);
+        }
+        rdata->current.tex_coords = enabled;
     }
 }
 
 static int
+GLES2_SetDrawingState(SDL_Renderer * renderer)
+{
+    GLES2_DriverContext *rdata = (GLES2_DriverContext *)renderer->driverdata;
+    int blendMode = renderer->blendMode;
+    GLuint locColor;
+
+    glGetError();
+
+    GLES2_ActivateRenderer(renderer);
+
+    GLES2_SetBlendMode(rdata, blendMode);
+
+    GLES2_SetTexCoords(rdata, SDL_FALSE);
+
+    /* Activate an appropriate shader and set the projection matrix */
+    if (GLES2_SelectProgram(renderer, GLES2_IMAGESOURCE_SOLID, blendMode) < 0)
+        return -1;
+
+    /* Select the color to draw with */
+    locColor = rdata->current_program->uniform_locations[GLES2_UNIFORM_COLOR];
+    glUniform4f(locColor,
+                renderer->r * inv255f,
+                renderer->g * inv255f,
+                renderer->b * inv255f,
+                renderer->a * inv255f);
+    return 0;
+}
+
+static int
 GLES2_RenderDrawPoints(SDL_Renderer *renderer, const SDL_Point *points, int count)
 {
     GLES2_DriverContext *rdata = (GLES2_DriverContext *)renderer->driverdata;
     GLfloat *vertices;
-    SDL_BlendMode blendMode;
-    int alpha;
-    GLuint locColor;
     int idx;
 
-    GLES2_ActivateRenderer(renderer);
-
-    blendMode = renderer->blendMode;
-    alpha = renderer->a;
-
-    /* Activate an appropriate shader and set the projection matrix */
-    if (GLES2_SelectProgram(renderer, GLES2_IMAGESOURCE_SOLID, blendMode) < 0)
+    if (GLES2_SetDrawingState(renderer) < 0) {
         return -1;
-
-    /* Select the color to draw with */
-    locColor = rdata->current_program->uniform_locations[GLES2_UNIFORM_COLOR];
-    glGetError();
-    glUniform4f(locColor,
-                renderer->r * inv255f,
-                renderer->g * inv255f,
-                renderer->b * inv255f,
-                alpha * inv255f);
-
-    /* Configure the correct blend mode */
-    GLES2_SetBlendMode(blendMode);
+    }
 
     /* Emit the specified vertices as points */
     vertices = SDL_stack_alloc(GLfloat, count * 2);
@@ -851,10 +883,9 @@
         vertices[idx * 2] = x;
         vertices[(idx * 2) + 1] = y;
     }
-    glEnableVertexAttribArray(GLES2_ATTRIBUTE_POSITION);
+    glGetError();
     glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
     glDrawArrays(GL_POINTS, 0, count);
-    glDisableVertexAttribArray(GLES2_ATTRIBUTE_POSITION);
     SDL_stack_free(vertices);
     if (glGetError() != GL_NO_ERROR)
     {
@@ -869,31 +900,11 @@
 {
     GLES2_DriverContext *rdata = (GLES2_DriverContext *)renderer->driverdata;
     GLfloat *vertices;
-    SDL_BlendMode blendMode;
-    int alpha;
-    GLuint locColor;
     int idx;
 
-    GLES2_ActivateRenderer(renderer);
-
-    blendMode = renderer->blendMode;
-    alpha = renderer->a;
-
-    /* Activate an appropriate shader and set the projection matrix */
-    if (GLES2_SelectProgram(renderer, GLES2_IMAGESOURCE_SOLID, blendMode) < 0)
+    if (GLES2_SetDrawingState(renderer) < 0) {
         return -1;
-
-    /* Select the color to draw with */
-    locColor = rdata->current_program->uniform_locations[GLES2_UNIFORM_COLOR];
-    glGetError();
-    glUniform4f(locColor,
-                renderer->r * inv255f,
-                renderer->g * inv255f,
-                renderer->b * inv255f,
-                alpha * inv255f);
-
-    /* Configure the correct blend mode */
-    GLES2_SetBlendMode(blendMode);
+    }
 
     /* Emit a line strip including the specified vertices */
     vertices = SDL_stack_alloc(GLfloat, count * 2);
@@ -905,10 +916,9 @@
         vertices[idx * 2] = x;
         vertices[(idx * 2) + 1] = y;
     }
-    glEnableVertexAttribArray(GLES2_ATTRIBUTE_POSITION);
+    glGetError();
     glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
     glDrawArrays(GL_LINE_STRIP, 0, count);
-    glDisableVertexAttribArray(GLES2_ATTRIBUTE_POSITION);
     SDL_stack_free(vertices);
     if (glGetError() != GL_NO_ERROR)
     {
@@ -923,34 +933,14 @@
 {
     GLES2_DriverContext *rdata = (GLES2_DriverContext *)renderer->driverdata;
     GLfloat vertices[8];
-    SDL_BlendMode blendMode;
-    int alpha;
-    GLuint locColor;
     int idx;
 
-    GLES2_ActivateRenderer(renderer);
-
-    blendMode = renderer->blendMode;
-    alpha = renderer->a;
-
-    /* Activate an appropriate shader and set the projection matrix */
-    if (GLES2_SelectProgram(renderer, GLES2_IMAGESOURCE_SOLID, blendMode) < 0)
+    if (GLES2_SetDrawingState(renderer) < 0) {
         return -1;
-
-    /* Select the color to draw with */
-    locColor = rdata->current_program->uniform_locations[GLES2_UNIFORM_COLOR];
-    glGetError();
-    glUniform4f(locColor,
-                renderer->r * inv255f,
-                renderer->g * inv255f,
-                renderer->b * inv255f,
-                alpha * inv255f);
-
-    /* Configure the correct blend mode */
-    GLES2_SetBlendMode(blendMode);
+    }
 
     /* Emit a line loop for each rectangle */
-    glEnableVertexAttribArray(GLES2_ATTRIBUTE_POSITION);
+    glGetError();
     for (idx = 0; idx < count; ++idx) {
         const SDL_Rect *rect = &rects[idx];
 
@@ -970,7 +960,6 @@
         glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
         glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
     }
-    glDisableVertexAttribArray(GLES2_ATTRIBUTE_POSITION);
     if (glGetError() != GL_NO_ERROR)
     {
         SDL_SetError("Failed to render lines");
@@ -987,7 +976,6 @@
     GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
     GLES2_ImageSource sourceType;
     SDL_BlendMode blendMode;
-    int alpha;
     GLfloat vertices[8];
     GLfloat texCoords[8];
     GLuint locTexture;
@@ -997,7 +985,6 @@
 
     /* Activate an appropriate shader and set the projection matrix */
     blendMode = texture->blendMode;
-    alpha = texture->a;
     sourceType = GLES2_IMAGESOURCE_TEXTURE;
     if (GLES2_SelectProgram(renderer, sourceType, blendMode) < 0)
         return -1;
@@ -1009,8 +996,13 @@
     glBindTexture(tdata->texture_type, tdata->texture);
     glUniform1i(locTexture, 0);
 
-    /* Configure texture blending */
-    GLES2_SetBlendMode(blendMode);
+    if (tdata->scaleMode != rdata->current.scaleMode) {
+        glTexParameteri(tdata->texture_type, GL_TEXTURE_MIN_FILTER,
+                        tdata->scaleMode);
+        glTexParameteri(tdata->texture_type, GL_TEXTURE_MAG_FILTER,
+                        tdata->scaleMode);
+        rdata->current.scaleMode = tdata->scaleMode;
+    }
 
     /* Configure color modulation */
     locModulation = rdata->current_program->uniform_locations[GLES2_UNIFORM_MODULATION];
@@ -1018,11 +1010,14 @@
                 texture->r * inv255f,
                 texture->g * inv255f,
                 texture->b * inv255f,
-                alpha * inv255f);
+                texture->a * inv255f);
+
+    /* Configure texture blending */
+    GLES2_SetBlendMode(rdata, blendMode);
+
+    GLES2_SetTexCoords(rdata, SDL_TRUE);
 
     /* Emit the textured quad */
-    glEnableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD);
-    glEnableVertexAttribArray(GLES2_ATTRIBUTE_POSITION);
     vertices[0] = (GLfloat)dstrect->x;
     vertices[1] = (GLfloat)dstrect->y;
     vertices[2] = (GLfloat)(dstrect->x + dstrect->w);
@@ -1042,8 +1037,6 @@
     texCoords[7] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
     glVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, texCoords);
     glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
-    glDisableVertexAttribArray(GLES2_ATTRIBUTE_POSITION);
-    glDisableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD);
     if (glGetError() != GL_NO_ERROR)
     {
         SDL_SetError("Failed to render texture");
@@ -1067,6 +1060,25 @@
 
 #define GL_NVIDIA_PLATFORM_BINARY_NV 0x890B
 
+static void
+GLES2_ResetState(SDL_Renderer *renderer)
+{
+    GLES2_DriverContext *rdata = (GLES2_DriverContext *) renderer->driverdata;
+
+    if (SDL_CurrentContext == rdata->context) {
+        GLES2_UpdateViewport(renderer);
+    } else {
+        GLES2_ActivateRenderer(renderer);
+    }
+
+    rdata->current.blendMode = -1;
+    rdata->current.scaleMode = 0;
+    rdata->current.tex_coords = SDL_FALSE;
+
+    glEnableVertexAttribArray(GLES2_ATTRIBUTE_POSITION);
+    glDisableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD);
+}
+
 static SDL_Renderer *
 GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
 {
@@ -1166,6 +1178,9 @@
     renderer->RenderPresent       = &GLES2_RenderPresent;
     renderer->DestroyTexture      = &GLES2_DestroyTexture;
     renderer->DestroyRenderer     = &GLES2_DestroyRenderer;
+
+    GLES2_ResetState(renderer);
+
     return renderer;
 }