Added OpenGL state caching for decent speed improvement.
authorSam Lantinga <slouken@libsdl.org>
Sat, 19 Feb 2011 21:51:21 -0800
changeset 5355cc2215cda170
parent 5354 a606515be168
child 5356 dc48dd5129a5
Added OpenGL state caching for decent speed improvement.
src/render/opengl/SDL_render_gl.c
src/render/opengl/SDL_shaders_gl.c
src/render/opengles/SDL_render_gles.c
src/render/opengles2/SDL_render_gles2.c
     1.1 --- a/src/render/opengl/SDL_render_gl.c	Sat Feb 19 21:51:03 2011 -0800
     1.2 +++ b/src/render/opengl/SDL_render_gl.c	Sat Feb 19 21:51:21 2011 -0800
     1.3 @@ -87,7 +87,12 @@
     1.4  {
     1.5      SDL_GLContext context;
     1.6      SDL_bool GL_ARB_texture_rectangle_supported;
     1.7 -    int blendMode;
     1.8 +    struct {
     1.9 +        GL_Shader shader;
    1.10 +        Uint32 color;
    1.11 +        int blendMode;
    1.12 +        GLenum scaleMode;
    1.13 +    } current;
    1.14  
    1.15      /* OpenGL functions */
    1.16  #define SDL_PROC(ret,func,params) ret (APIENTRY *func) params;
    1.17 @@ -117,6 +122,7 @@
    1.18      GLenum formattype;
    1.19      void *pixels;
    1.20      int pitch;
    1.21 +    int scaleMode;
    1.22      SDL_Rect locked_rect;
    1.23  
    1.24      /* YV12 texture support */
    1.25 @@ -202,6 +208,32 @@
    1.26      return 0;
    1.27  }
    1.28  
    1.29 +/* This is called if we need to invalidate all of the SDL OpenGL state */
    1.30 +static void
    1.31 +GL_ResetState(SDL_Renderer *renderer)
    1.32 +{
    1.33 +    GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
    1.34 +
    1.35 +    if (SDL_CurrentContext == data->context) {
    1.36 +        GL_UpdateViewport(renderer);
    1.37 +    } else {
    1.38 +        GL_ActivateRenderer(renderer);
    1.39 +    }
    1.40 +
    1.41 +    data->current.shader = SHADER_NONE;
    1.42 +    data->current.color = 0;
    1.43 +    data->current.blendMode = -1;
    1.44 +    data->current.scaleMode = 0;
    1.45 +
    1.46 +    data->glDisable(GL_DEPTH_TEST);
    1.47 +    data->glDisable(GL_CULL_FACE);
    1.48 +    /* This ended up causing video discrepancies between OpenGL and Direct3D */
    1.49 +    /*data->glEnable(GL_LINE_SMOOTH);*/
    1.50 +
    1.51 +    data->glMatrixMode(GL_MODELVIEW);
    1.52 +    data->glLoadIdentity();
    1.53 +}
    1.54 +
    1.55  SDL_Renderer *
    1.56  GL_CreateRenderer(SDL_Window * window, Uint32 flags)
    1.57  {
    1.58 @@ -320,13 +352,7 @@
    1.59      }
    1.60  
    1.61      /* Set up parameters for rendering */
    1.62 -    data->blendMode = -1;
    1.63 -    data->glDisable(GL_DEPTH_TEST);
    1.64 -    data->glDisable(GL_CULL_FACE);
    1.65 -    /* This ended up causing video discrepancies between OpenGL and Direct3D */
    1.66 -    /*data->glEnable(GL_LINE_SMOOTH);*/
    1.67 -    data->glMatrixMode(GL_MODELVIEW);
    1.68 -    data->glLoadIdentity();
    1.69 +    GL_ResetState(renderer);
    1.70  
    1.71      return renderer;
    1.72  }
    1.73 @@ -437,12 +463,9 @@
    1.74  
    1.75      data->format = format;
    1.76      data->formattype = type;
    1.77 +    data->scaleMode = GL_LINEAR;
    1.78      renderdata->glEnable(data->type);
    1.79      renderdata->glBindTexture(data->type, data->texture);
    1.80 -    renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER,
    1.81 -                                GL_LINEAR);
    1.82 -    renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER,
    1.83 -                                GL_LINEAR);
    1.84      renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S,
    1.85                                  GL_CLAMP_TO_EDGE);
    1.86      renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T,
    1.87 @@ -492,10 +515,6 @@
    1.88          renderdata->glEnable(data->type);
    1.89  
    1.90          renderdata->glBindTexture(data->type, data->utexture);
    1.91 -        renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER,
    1.92 -                                    GL_LINEAR);
    1.93 -        renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER,
    1.94 -                                    GL_LINEAR);
    1.95          renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S,
    1.96                                      GL_CLAMP_TO_EDGE);
    1.97          renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T,
    1.98 @@ -504,10 +523,6 @@
    1.99                                   texture_h/2, 0, format, type, NULL);
   1.100  
   1.101          renderdata->glBindTexture(data->type, data->vtexture);
   1.102 -        renderdata->glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER,
   1.103 -                                    GL_LINEAR);
   1.104 -        renderdata->glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER,
   1.105 -                                    GL_LINEAR);
   1.106          renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_S,
   1.107                                      GL_CLAMP_TO_EDGE);
   1.108          renderdata->glTexParameteri(data->type, GL_TEXTURE_WRAP_T,
   1.109 @@ -632,9 +647,32 @@
   1.110  }
   1.111  
   1.112  static void
   1.113 +GL_SetShader(GL_RenderData * data, GL_Shader shader)
   1.114 +{
   1.115 +    if (data->shaders && shader != data->current.shader) {
   1.116 +        GL_SelectShader(data->shaders, shader);
   1.117 +        data->current.shader = shader;
   1.118 +    }
   1.119 +}
   1.120 +
   1.121 +static void
   1.122 +GL_SetColor(GL_RenderData * data, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
   1.123 +{
   1.124 +    Uint32 color = ((a << 24) | (r << 16) | (g << 8) | b);
   1.125 +
   1.126 +    if (color != data->current.color) {
   1.127 +        data->glColor4f((GLfloat) r * inv255f,
   1.128 +                        (GLfloat) g * inv255f,
   1.129 +                        (GLfloat) b * inv255f,
   1.130 +                        (GLfloat) a * inv255f);
   1.131 +        data->current.color = color;
   1.132 +    }
   1.133 +}
   1.134 +
   1.135 +static void
   1.136  GL_SetBlendMode(GL_RenderData * data, int blendMode)
   1.137  {
   1.138 -    if (blendMode != data->blendMode) {
   1.139 +    if (blendMode != data->current.blendMode) {
   1.140          switch (blendMode) {
   1.141          case SDL_BLENDMODE_NONE:
   1.142              data->glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
   1.143 @@ -656,10 +694,27 @@
   1.144              data->glBlendFunc(GL_ZERO, GL_SRC_COLOR);
   1.145              break;
   1.146          }
   1.147 -        data->blendMode = blendMode;
   1.148 +        data->current.blendMode = blendMode;
   1.149      }
   1.150  }
   1.151  
   1.152 +static void
   1.153 +GL_SetDrawingState(SDL_Renderer * renderer)
   1.154 +{
   1.155 +    GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
   1.156 +
   1.157 +    GL_ActivateRenderer(renderer);
   1.158 +
   1.159 +    GL_SetColor(data, (GLfloat) renderer->r,
   1.160 +                      (GLfloat) renderer->g,
   1.161 +                      (GLfloat) renderer->b,
   1.162 +                      (GLfloat) renderer->a);
   1.163 +
   1.164 +    GL_SetBlendMode(data, renderer->blendMode);
   1.165 +
   1.166 +    GL_SetShader(data, SHADER_SOLID);
   1.167 +}
   1.168 +
   1.169  static int
   1.170  GL_RenderClear(SDL_Renderer * renderer)
   1.171  {
   1.172 @@ -684,15 +739,7 @@
   1.173      GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
   1.174      int i;
   1.175  
   1.176 -    GL_ActivateRenderer(renderer);
   1.177 -
   1.178 -    GL_SetBlendMode(data, renderer->blendMode);
   1.179 -    GL_SelectShader(data->shaders, SHADER_SOLID);
   1.180 -
   1.181 -    data->glColor4f((GLfloat) renderer->r * inv255f,
   1.182 -                    (GLfloat) renderer->g * inv255f,
   1.183 -                    (GLfloat) renderer->b * inv255f,
   1.184 -                    (GLfloat) renderer->a * inv255f);
   1.185 +    GL_SetDrawingState(renderer);
   1.186  
   1.187      data->glBegin(GL_POINTS);
   1.188      for (i = 0; i < count; ++i) {
   1.189 @@ -710,15 +757,7 @@
   1.190      GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
   1.191      int i;
   1.192  
   1.193 -    GL_ActivateRenderer(renderer);
   1.194 -
   1.195 -    GL_SetBlendMode(data, renderer->blendMode);
   1.196 -    GL_SelectShader(data->shaders, SHADER_SOLID);
   1.197 -
   1.198 -    data->glColor4f((GLfloat) renderer->r * inv255f,
   1.199 -                    (GLfloat) renderer->g * inv255f,
   1.200 -                    (GLfloat) renderer->b * inv255f,
   1.201 -                    (GLfloat) renderer->a * inv255f);
   1.202 +    GL_SetDrawingState(renderer);
   1.203  
   1.204      if (count > 2 && 
   1.205          points[0].x == points[count-1].x && points[0].y == points[count-1].y) {
   1.206 @@ -781,15 +820,7 @@
   1.207      GL_RenderData *data = (GL_RenderData *) renderer->driverdata;
   1.208      int i;
   1.209  
   1.210 -    GL_ActivateRenderer(renderer);
   1.211 -
   1.212 -    GL_SetBlendMode(data, renderer->blendMode);
   1.213 -    GL_SelectShader(data->shaders, SHADER_SOLID);
   1.214 -
   1.215 -    data->glColor4f((GLfloat) renderer->r * inv255f,
   1.216 -                    (GLfloat) renderer->g * inv255f,
   1.217 -                    (GLfloat) renderer->b * inv255f,
   1.218 -                    (GLfloat) renderer->a * inv255f);
   1.219 +    GL_SetDrawingState(renderer);
   1.220  
   1.221      for (i = 0; i < count; ++i) {
   1.222          const SDL_Rect *rect = &rects[i];
   1.223 @@ -811,6 +842,52 @@
   1.224  
   1.225      GL_ActivateRenderer(renderer);
   1.226  
   1.227 +    data->glEnable(texturedata->type);
   1.228 +    if (texturedata->yuv) {
   1.229 +        data->glActiveTextureARB(GL_TEXTURE2_ARB);
   1.230 +        data->glBindTexture(texturedata->type, texturedata->vtexture);
   1.231 +        if (texturedata->scaleMode != data->current.scaleMode) {
   1.232 +            data->glTexParameteri(texturedata->type, GL_TEXTURE_MIN_FILTER,
   1.233 +                                  texturedata->scaleMode);
   1.234 +            data->glTexParameteri(texturedata->type, GL_TEXTURE_MAG_FILTER,
   1.235 +                                  texturedata->scaleMode);
   1.236 +        }
   1.237 +
   1.238 +        data->glActiveTextureARB(GL_TEXTURE1_ARB);
   1.239 +        data->glBindTexture(texturedata->type, texturedata->utexture);
   1.240 +        if (texturedata->scaleMode != data->current.scaleMode) {
   1.241 +            data->glTexParameteri(texturedata->type, GL_TEXTURE_MIN_FILTER,
   1.242 +                                  texturedata->scaleMode);
   1.243 +            data->glTexParameteri(texturedata->type, GL_TEXTURE_MAG_FILTER,
   1.244 +                                  texturedata->scaleMode);
   1.245 +        }
   1.246 +
   1.247 +        data->glActiveTextureARB(GL_TEXTURE0_ARB);
   1.248 +    }
   1.249 +    data->glBindTexture(texturedata->type, texturedata->texture);
   1.250 +
   1.251 +    if (texturedata->scaleMode != data->current.scaleMode) {
   1.252 +        data->glTexParameteri(texturedata->type, GL_TEXTURE_MIN_FILTER,
   1.253 +                              texturedata->scaleMode);
   1.254 +        data->glTexParameteri(texturedata->type, GL_TEXTURE_MAG_FILTER,
   1.255 +                              texturedata->scaleMode);
   1.256 +        data->current.scaleMode = texturedata->scaleMode;
   1.257 +    }
   1.258 +
   1.259 +    if (texture->modMode) {
   1.260 +        GL_SetColor(data, texture->r, texture->g, texture->b, texture->a);
   1.261 +    } else {
   1.262 +        GL_SetColor(data, 255, 255, 255, 255);
   1.263 +    }
   1.264 +
   1.265 +    GL_SetBlendMode(data, texture->blendMode);
   1.266 +
   1.267 +    if (texturedata->yuv) {
   1.268 +        GL_SetShader(data, SHADER_YV12);
   1.269 +    } else {
   1.270 +        GL_SetShader(data, SHADER_RGB);
   1.271 +    }
   1.272 +
   1.273      minx = dstrect->x;
   1.274      miny = dstrect->y;
   1.275      maxx = dstrect->x + dstrect->w;
   1.276 @@ -825,32 +902,6 @@
   1.277      maxv = (GLfloat) (srcrect->y + srcrect->h) / texture->h;
   1.278      maxv *= texturedata->texh;
   1.279  
   1.280 -    data->glEnable(texturedata->type);
   1.281 -    if (texturedata->yuv) {
   1.282 -        data->glActiveTextureARB(GL_TEXTURE2_ARB);
   1.283 -        data->glBindTexture(texturedata->type, texturedata->vtexture);
   1.284 -        data->glActiveTextureARB(GL_TEXTURE1_ARB);
   1.285 -        data->glBindTexture(texturedata->type, texturedata->utexture);
   1.286 -        data->glActiveTextureARB(GL_TEXTURE0_ARB);
   1.287 -    }
   1.288 -    data->glBindTexture(texturedata->type, texturedata->texture);
   1.289 -
   1.290 -    if (texture->modMode) {
   1.291 -        data->glColor4f((GLfloat) texture->r * inv255f,
   1.292 -                        (GLfloat) texture->g * inv255f,
   1.293 -                        (GLfloat) texture->b * inv255f,
   1.294 -                        (GLfloat) texture->a * inv255f);
   1.295 -    } else {
   1.296 -        data->glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
   1.297 -    }
   1.298 -
   1.299 -    GL_SetBlendMode(data, texture->blendMode);
   1.300 -    if (texturedata->yuv) {
   1.301 -        GL_SelectShader(data->shaders, SHADER_YV12);
   1.302 -    } else {
   1.303 -        GL_SelectShader(data->shaders, SHADER_RGB);
   1.304 -    }
   1.305 -
   1.306      data->glBegin(GL_TRIANGLE_STRIP);
   1.307      data->glTexCoord2f(minu, minv);
   1.308      data->glVertex2f((GLfloat) minx, (GLfloat) miny);
     2.1 --- a/src/render/opengl/SDL_shaders_gl.c	Sat Feb 19 21:51:03 2011 -0800
     2.2 +++ b/src/render/opengl/SDL_shaders_gl.c	Sat Feb 19 21:51:21 2011 -0800
     2.3 @@ -60,7 +60,6 @@
     2.4  
     2.5      SDL_bool GL_ARB_texture_rectangle_supported;
     2.6  
     2.7 -    GL_Shader current_shader;
     2.8      GL_ShaderData shaders[NUM_SHADERS];
     2.9  };
    2.10  
    2.11 @@ -341,18 +340,7 @@
    2.12  void
    2.13  GL_SelectShader(GL_ShaderContext *ctx, GL_Shader shader)
    2.14  {
    2.15 -    /* Nothing to do if there's no shader support */
    2.16 -    if (!ctx) {
    2.17 -        return;
    2.18 -    }
    2.19 -
    2.20 -    /* Nothing to do if there's no shader change */
    2.21 -    if (shader == ctx->current_shader) {
    2.22 -        return;
    2.23 -    }
    2.24 -
    2.25      ctx->glUseProgramObjectARB(ctx->shaders[shader].program);
    2.26 -    ctx->current_shader = shader;
    2.27  }
    2.28  
    2.29  void
     3.1 --- a/src/render/opengles/SDL_render_gles.c	Sat Feb 19 21:51:03 2011 -0800
     3.2 +++ b/src/render/opengles/SDL_render_gles.c	Sat Feb 19 21:51:21 2011 -0800
     3.3 @@ -84,7 +84,12 @@
     3.4  typedef struct
     3.5  {
     3.6      SDL_GLContext context;
     3.7 -    int blendMode;
     3.8 +    struct {
     3.9 +        Uint32 color;
    3.10 +        int blendMode;
    3.11 +        GLenum scaleMode;
    3.12 +        SDL_bool tex_coords;
    3.13 +    } current;
    3.14  
    3.15      SDL_bool useDrawTexture;
    3.16      SDL_bool GL_OES_draw_texture_supported;
    3.17 @@ -100,6 +105,7 @@
    3.18      GLenum formattype;
    3.19      void *pixels;
    3.20      int pitch;
    3.21 +    GLenum scaleMode;
    3.22  } GLES_TextureData;
    3.23  
    3.24  static void
    3.25 @@ -154,6 +160,33 @@
    3.26      return 0;
    3.27  }
    3.28  
    3.29 +/* This is called if we need to invalidate all of the SDL OpenGL state */
    3.30 +static void
    3.31 +GLES_ResetState(SDL_Renderer *renderer)
    3.32 +{
    3.33 +    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
    3.34 +
    3.35 +    if (SDL_CurrentContext == data->context) {
    3.36 +        GLES_UpdateViewport(renderer);
    3.37 +    } else {
    3.38 +        GLES_ActivateRenderer(renderer);
    3.39 +    }
    3.40 +
    3.41 +    data->current.color = 0;
    3.42 +    data->current.blendMode = -1;
    3.43 +    data->current.scaleMode = 0;
    3.44 +    data->current.tex_coords = SDL_FALSE;
    3.45 +
    3.46 +    glDisable(GL_DEPTH_TEST);
    3.47 +    glDisable(GL_CULL_FACE);
    3.48 +
    3.49 +    glMatrixMode(GL_MODELVIEW);
    3.50 +    glLoadIdentity();
    3.51 +
    3.52 +    glEnableClientState(GL_VERTEX_ARRAY);
    3.53 +    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
    3.54 +}
    3.55 +
    3.56  SDL_Renderer *
    3.57  GLES_CreateRenderer(SDL_Window * window, Uint32 flags)
    3.58  {
    3.59 @@ -234,15 +267,8 @@
    3.60      renderer->info.max_texture_height = value;
    3.61  
    3.62      /* Set up parameters for rendering */
    3.63 -    data->blendMode = -1;
    3.64 -    glDisable(GL_DEPTH_TEST);
    3.65 -    glDisable(GL_CULL_FACE);
    3.66 -    glMatrixMode(GL_MODELVIEW);
    3.67 -    glLoadIdentity();
    3.68 +    GLES_ResetState(renderer);
    3.69  
    3.70 -    glEnableClientState(GL_VERTEX_ARRAY);
    3.71 -    //glEnableClientState(GL_TEXTURE_COORD_ARRAY);
    3.72 -    
    3.73      return renderer;
    3.74  }
    3.75  
    3.76 @@ -319,15 +345,10 @@
    3.77  
    3.78      data->format = format;
    3.79      data->formattype = type;
    3.80 +    data->scaleMode = GL_LINEAR;
    3.81      glBindTexture(data->type, data->texture);
    3.82 -    glTexParameteri(data->type, GL_TEXTURE_MIN_FILTER,
    3.83 -                                GL_LINEAR);
    3.84 -    glTexParameteri(data->type, GL_TEXTURE_MAG_FILTER,
    3.85 -                                GL_LINEAR);
    3.86 -    glTexParameteri(data->type, GL_TEXTURE_WRAP_S,
    3.87 -                                GL_CLAMP_TO_EDGE);
    3.88 -    glTexParameteri(data->type, GL_TEXTURE_WRAP_T,
    3.89 -                                GL_CLAMP_TO_EDGE);
    3.90 +    glTexParameteri(data->type, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    3.91 +    glTexParameteri(data->type, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    3.92  
    3.93      glTexImage2D(data->type, 0, internalFormat, texture_w,
    3.94                               texture_h, 0, format, type, NULL);
    3.95 @@ -453,25 +474,24 @@
    3.96      return 0;
    3.97  }
    3.98  
    3.99 -static int
   3.100 -GLES_RenderClear(SDL_Renderer * renderer)
   3.101 +static void
   3.102 +GLES_SetColor(GLES_RenderData * data, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
   3.103  {
   3.104 -    GLES_ActivateRenderer(renderer);
   3.105 +    Uint32 color = ((a << 24) | (r << 16) | (g << 8) | b);
   3.106  
   3.107 -    glClearColor((GLfloat) renderer->r * inv255f,
   3.108 -                 (GLfloat) renderer->g * inv255f,
   3.109 -                 (GLfloat) renderer->b * inv255f,
   3.110 -                 (GLfloat) renderer->a * inv255f);
   3.111 -
   3.112 -    glClear(GL_COLOR_BUFFER_BIT);
   3.113 -
   3.114 -    return 0;
   3.115 +    if (color != data->current.color) {
   3.116 +        glColor4f((GLfloat) r * inv255f,
   3.117 +                        (GLfloat) g * inv255f,
   3.118 +                        (GLfloat) b * inv255f,
   3.119 +                        (GLfloat) a * inv255f);
   3.120 +        data->current.color = color;
   3.121 +    }
   3.122  }
   3.123  
   3.124  static void
   3.125  GLES_SetBlendMode(GLES_RenderData * data, int blendMode)
   3.126  {
   3.127 -    if (blendMode != data->blendMode) {
   3.128 +    if (blendMode != data->current.blendMode) {
   3.129          switch (blendMode) {
   3.130          case SDL_BLENDMODE_NONE:
   3.131              glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
   3.132 @@ -493,10 +513,55 @@
   3.133              glBlendFunc(GL_ZERO, GL_SRC_COLOR);
   3.134              break;
   3.135          }
   3.136 -        data->blendMode = blendMode;
   3.137 +        data->current.blendMode = blendMode;
   3.138 +    }
   3.139 +}
   3.140 +
   3.141 +static void
   3.142 +GLES_SetTexCoords(GLES_RenderData * data, SDL_bool enabled)
   3.143 +{
   3.144 +    if (enabled != data->current.tex_coords) {
   3.145 +        if (enabled) {
   3.146 +            glEnableClientState(GL_TEXTURE_COORD_ARRAY);
   3.147 +        } else {
   3.148 +            glDisableClientState(GL_TEXTURE_COORD_ARRAY);
   3.149 +        }
   3.150 +        data->current.tex_coords = enabled;
   3.151      }
   3.152  }
   3.153  
   3.154 +static void
   3.155 +GLES_SetDrawingState(SDL_Renderer * renderer)
   3.156 +{
   3.157 +    GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
   3.158 +
   3.159 +    GLES_ActivateRenderer(renderer);
   3.160 +
   3.161 +    GLES_SetColor(data, (GLfloat) renderer->r,
   3.162 +                        (GLfloat) renderer->g,
   3.163 +                        (GLfloat) renderer->b,
   3.164 +                        (GLfloat) renderer->a);
   3.165 +
   3.166 +    GLES_SetBlendMode(data, renderer->blendMode);
   3.167 +
   3.168 +    GLES_SetTexCoords(data, SDL_FALSE);
   3.169 +}
   3.170 +
   3.171 +static int
   3.172 +GLES_RenderClear(SDL_Renderer * renderer)
   3.173 +{
   3.174 +    GLES_ActivateRenderer(renderer);
   3.175 +
   3.176 +    glClearColor((GLfloat) renderer->r * inv255f,
   3.177 +                 (GLfloat) renderer->g * inv255f,
   3.178 +                 (GLfloat) renderer->b * inv255f,
   3.179 +                 (GLfloat) renderer->a * inv255f);
   3.180 +
   3.181 +    glClear(GL_COLOR_BUFFER_BIT);
   3.182 +
   3.183 +    return 0;
   3.184 +}
   3.185 +
   3.186  static int
   3.187  GLES_RenderDrawPoints(SDL_Renderer * renderer, const SDL_Point * points,
   3.188                        int count)
   3.189 @@ -505,14 +570,7 @@
   3.190      int i;
   3.191      GLshort *vertices;
   3.192  
   3.193 -    GLES_ActivateRenderer(renderer);
   3.194 -
   3.195 -    GLES_SetBlendMode(data, renderer->blendMode);
   3.196 -
   3.197 -    glColor4f((GLfloat) renderer->r * inv255f,
   3.198 -                    (GLfloat) renderer->g * inv255f,
   3.199 -                    (GLfloat) renderer->b * inv255f,
   3.200 -                    (GLfloat) renderer->a * inv255f);
   3.201 +    GLES_SetDrawingState(renderer);
   3.202  
   3.203      vertices = SDL_stack_alloc(GLshort, count*2);
   3.204      for (i = 0; i < count; ++i) {
   3.205 @@ -534,14 +592,7 @@
   3.206      int i;
   3.207      GLshort *vertices;
   3.208  
   3.209 -    GLES_ActivateRenderer(renderer);
   3.210 -
   3.211 -    GLES_SetBlendMode(data, renderer->blendMode);
   3.212 -
   3.213 -    glColor4f((GLfloat) renderer->r * inv255f,
   3.214 -                    (GLfloat) renderer->g * inv255f,
   3.215 -                    (GLfloat) renderer->b * inv255f,
   3.216 -                    (GLfloat) renderer->a * inv255f);
   3.217 +    GLES_SetDrawingState(renderer);
   3.218  
   3.219      vertices = SDL_stack_alloc(GLshort, count*2);
   3.220      for (i = 0; i < count; ++i) {
   3.221 @@ -569,14 +620,7 @@
   3.222      GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata;
   3.223      int i;
   3.224  
   3.225 -    GLES_ActivateRenderer(renderer);
   3.226 -
   3.227 -    GLES_SetBlendMode(data, renderer->blendMode);
   3.228 -
   3.229 -    glColor4f((GLfloat) renderer->r * inv255f,
   3.230 -                    (GLfloat) renderer->g * inv255f,
   3.231 -                    (GLfloat) renderer->b * inv255f,
   3.232 -                    (GLfloat) renderer->a * inv255f);
   3.233 +    GLES_SetDrawingState(renderer);
   3.234  
   3.235      for (i = 0; i < count; ++i) {
   3.236          const SDL_Rect *rect = &rects[i];
   3.237 @@ -614,21 +658,27 @@
   3.238      GLES_ActivateRenderer(renderer);
   3.239  
   3.240      glEnable(GL_TEXTURE_2D);
   3.241 -    glEnableClientState(GL_TEXTURE_COORD_ARRAY);
   3.242  
   3.243      glBindTexture(texturedata->type, texturedata->texture);
   3.244  
   3.245 +    if (texturedata->scaleMode != data->current.scaleMode) {
   3.246 +        glTexParameteri(texturedata->type, GL_TEXTURE_MIN_FILTER,
   3.247 +                        texturedata->scaleMode);
   3.248 +        glTexParameteri(texturedata->type, GL_TEXTURE_MAG_FILTER,
   3.249 +                        texturedata->scaleMode);
   3.250 +        data->current.scaleMode = texturedata->scaleMode;
   3.251 +    }
   3.252 +
   3.253      if (texture->modMode) {
   3.254 -        glColor4f((GLfloat) texture->r * inv255f,
   3.255 -                        (GLfloat) texture->g * inv255f,
   3.256 -                        (GLfloat) texture->b * inv255f,
   3.257 -                        (GLfloat) texture->a * inv255f);
   3.258 +        GLES_SetColor(data, texture->r, texture->g, texture->b, texture->a);
   3.259      } else {
   3.260 -        glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
   3.261 +        GLES_SetColor(data, 255, 255, 255, 255);
   3.262      }
   3.263  
   3.264      GLES_SetBlendMode(data, texture->blendMode);
   3.265  
   3.266 +    GLES_SetTexCoords(data, SDL_TRUE);
   3.267 +
   3.268      if (data->GL_OES_draw_texture_supported && data->useDrawTexture) {
   3.269          /* this code is a little funny because the viewport is upside down vs SDL's coordinate system */
   3.270          GLint cropRect[4];
   3.271 @@ -685,8 +735,6 @@
   3.272          glTexCoordPointer(2, GL_FLOAT, 0, texCoords);
   3.273          glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
   3.274      }
   3.275 -	
   3.276 -    glDisableClientState(GL_TEXTURE_COORD_ARRAY);
   3.277      glDisable(GL_TEXTURE_2D);
   3.278  
   3.279      return 0;
     4.1 --- a/src/render/opengles2/SDL_render_gles2.c	Sat Feb 19 21:51:03 2011 -0800
     4.2 +++ b/src/render/opengles2/SDL_render_gles2.c	Sat Feb 19 21:51:21 2011 -0800
     4.3 @@ -58,6 +58,7 @@
     4.4      GLenum pixel_type;
     4.5      void *pixel_data;
     4.6      size_t pitch;
     4.7 +    GLenum scaleMode;
     4.8  } GLES2_TextureData;
     4.9  
    4.10  typedef struct GLES2_ShaderCacheEntry
    4.11 @@ -118,6 +119,12 @@
    4.12  typedef struct GLES2_DriverContext
    4.13  {
    4.14      SDL_GLContext *context;
    4.15 +    struct {
    4.16 +        int blendMode;
    4.17 +        GLenum scaleMode;
    4.18 +        SDL_bool tex_coords;
    4.19 +    } current;
    4.20 +
    4.21      int shader_format_count;
    4.22      GLenum *shader_formats;
    4.23      GLES2_ShaderCache shader_cache;
    4.24 @@ -259,6 +266,7 @@
    4.25      tdata->texture_type = GL_TEXTURE_2D;
    4.26      tdata->pixel_format = format;
    4.27      tdata->pixel_type = type;
    4.28 +    tdata->scaleMode = GL_LINEAR;
    4.29  
    4.30      /* Allocate a blob for image data */
    4.31      if (texture->access == SDL_TEXTUREACCESS_STREAMING)
    4.32 @@ -787,59 +795,83 @@
    4.33  }
    4.34  
    4.35  static void
    4.36 -GLES2_SetBlendMode(int blendMode)
    4.37 +GLES2_SetBlendMode(GLES2_DriverContext *rdata, int blendMode)
    4.38 +{
    4.39 +    if (blendMode != rdata->current.blendMode) {
    4.40 +        switch (blendMode) {
    4.41 +        default:
    4.42 +        case SDL_BLENDMODE_NONE:
    4.43 +            glDisable(GL_BLEND);
    4.44 +            break;
    4.45 +        case SDL_BLENDMODE_BLEND:
    4.46 +            glEnable(GL_BLEND);
    4.47 +            glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    4.48 +            break;
    4.49 +        case SDL_BLENDMODE_ADD:
    4.50 +            glEnable(GL_BLEND);
    4.51 +            glBlendFunc(GL_SRC_ALPHA, GL_ONE);
    4.52 +            break;
    4.53 +        case SDL_BLENDMODE_MOD:
    4.54 +            glEnable(GL_BLEND);
    4.55 +            glBlendFunc(GL_ZERO, GL_SRC_COLOR);
    4.56 +            break;
    4.57 +        }
    4.58 +        rdata->current.blendMode = blendMode;
    4.59 +    }
    4.60 +}
    4.61 +
    4.62 +static void
    4.63 +GLES2_SetTexCoords(GLES2_DriverContext * rdata, SDL_bool enabled)
    4.64  {
    4.65 -    switch (blendMode)
    4.66 -    {
    4.67 -    case SDL_BLENDMODE_NONE:
    4.68 -    default:
    4.69 -        glDisable(GL_BLEND);
    4.70 -        break;
    4.71 -    case SDL_BLENDMODE_BLEND:
    4.72 -        glEnable(GL_BLEND);
    4.73 -        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    4.74 -        break;
    4.75 -    case SDL_BLENDMODE_ADD:
    4.76 -        glEnable(GL_BLEND);
    4.77 -        glBlendFunc(GL_SRC_ALPHA, GL_ONE);
    4.78 -        break;
    4.79 -    case SDL_BLENDMODE_MOD:
    4.80 -        glEnable(GL_BLEND);
    4.81 -        glBlendFunc(GL_ZERO, GL_SRC_COLOR);
    4.82 -        break;
    4.83 +    if (enabled != rdata->current.tex_coords) {
    4.84 +        if (enabled) {
    4.85 +            glEnableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD);
    4.86 +        } else {
    4.87 +            glDisableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD);
    4.88 +        }
    4.89 +        rdata->current.tex_coords = enabled;
    4.90      }
    4.91  }
    4.92  
    4.93  static int
    4.94 +GLES2_SetDrawingState(SDL_Renderer * renderer)
    4.95 +{
    4.96 +    GLES2_DriverContext *rdata = (GLES2_DriverContext *)renderer->driverdata;
    4.97 +    int blendMode = renderer->blendMode;
    4.98 +    GLuint locColor;
    4.99 +
   4.100 +    glGetError();
   4.101 +
   4.102 +    GLES2_ActivateRenderer(renderer);
   4.103 +
   4.104 +    GLES2_SetBlendMode(rdata, blendMode);
   4.105 +
   4.106 +    GLES2_SetTexCoords(rdata, SDL_FALSE);
   4.107 +
   4.108 +    /* Activate an appropriate shader and set the projection matrix */
   4.109 +    if (GLES2_SelectProgram(renderer, GLES2_IMAGESOURCE_SOLID, blendMode) < 0)
   4.110 +        return -1;
   4.111 +
   4.112 +    /* Select the color to draw with */
   4.113 +    locColor = rdata->current_program->uniform_locations[GLES2_UNIFORM_COLOR];
   4.114 +    glUniform4f(locColor,
   4.115 +                renderer->r * inv255f,
   4.116 +                renderer->g * inv255f,
   4.117 +                renderer->b * inv255f,
   4.118 +                renderer->a * inv255f);
   4.119 +    return 0;
   4.120 +}
   4.121 +
   4.122 +static int
   4.123  GLES2_RenderDrawPoints(SDL_Renderer *renderer, const SDL_Point *points, int count)
   4.124  {
   4.125      GLES2_DriverContext *rdata = (GLES2_DriverContext *)renderer->driverdata;
   4.126      GLfloat *vertices;
   4.127 -    SDL_BlendMode blendMode;
   4.128 -    int alpha;
   4.129 -    GLuint locColor;
   4.130      int idx;
   4.131  
   4.132 -    GLES2_ActivateRenderer(renderer);
   4.133 -
   4.134 -    blendMode = renderer->blendMode;
   4.135 -    alpha = renderer->a;
   4.136 -
   4.137 -    /* Activate an appropriate shader and set the projection matrix */
   4.138 -    if (GLES2_SelectProgram(renderer, GLES2_IMAGESOURCE_SOLID, blendMode) < 0)
   4.139 +    if (GLES2_SetDrawingState(renderer) < 0) {
   4.140          return -1;
   4.141 -
   4.142 -    /* Select the color to draw with */
   4.143 -    locColor = rdata->current_program->uniform_locations[GLES2_UNIFORM_COLOR];
   4.144 -    glGetError();
   4.145 -    glUniform4f(locColor,
   4.146 -                renderer->r * inv255f,
   4.147 -                renderer->g * inv255f,
   4.148 -                renderer->b * inv255f,
   4.149 -                alpha * inv255f);
   4.150 -
   4.151 -    /* Configure the correct blend mode */
   4.152 -    GLES2_SetBlendMode(blendMode);
   4.153 +    }
   4.154  
   4.155      /* Emit the specified vertices as points */
   4.156      vertices = SDL_stack_alloc(GLfloat, count * 2);
   4.157 @@ -851,10 +883,9 @@
   4.158          vertices[idx * 2] = x;
   4.159          vertices[(idx * 2) + 1] = y;
   4.160      }
   4.161 -    glEnableVertexAttribArray(GLES2_ATTRIBUTE_POSITION);
   4.162 +    glGetError();
   4.163      glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
   4.164      glDrawArrays(GL_POINTS, 0, count);
   4.165 -    glDisableVertexAttribArray(GLES2_ATTRIBUTE_POSITION);
   4.166      SDL_stack_free(vertices);
   4.167      if (glGetError() != GL_NO_ERROR)
   4.168      {
   4.169 @@ -869,31 +900,11 @@
   4.170  {
   4.171      GLES2_DriverContext *rdata = (GLES2_DriverContext *)renderer->driverdata;
   4.172      GLfloat *vertices;
   4.173 -    SDL_BlendMode blendMode;
   4.174 -    int alpha;
   4.175 -    GLuint locColor;
   4.176      int idx;
   4.177  
   4.178 -    GLES2_ActivateRenderer(renderer);
   4.179 -
   4.180 -    blendMode = renderer->blendMode;
   4.181 -    alpha = renderer->a;
   4.182 -
   4.183 -    /* Activate an appropriate shader and set the projection matrix */
   4.184 -    if (GLES2_SelectProgram(renderer, GLES2_IMAGESOURCE_SOLID, blendMode) < 0)
   4.185 +    if (GLES2_SetDrawingState(renderer) < 0) {
   4.186          return -1;
   4.187 -
   4.188 -    /* Select the color to draw with */
   4.189 -    locColor = rdata->current_program->uniform_locations[GLES2_UNIFORM_COLOR];
   4.190 -    glGetError();
   4.191 -    glUniform4f(locColor,
   4.192 -                renderer->r * inv255f,
   4.193 -                renderer->g * inv255f,
   4.194 -                renderer->b * inv255f,
   4.195 -                alpha * inv255f);
   4.196 -
   4.197 -    /* Configure the correct blend mode */
   4.198 -    GLES2_SetBlendMode(blendMode);
   4.199 +    }
   4.200  
   4.201      /* Emit a line strip including the specified vertices */
   4.202      vertices = SDL_stack_alloc(GLfloat, count * 2);
   4.203 @@ -905,10 +916,9 @@
   4.204          vertices[idx * 2] = x;
   4.205          vertices[(idx * 2) + 1] = y;
   4.206      }
   4.207 -    glEnableVertexAttribArray(GLES2_ATTRIBUTE_POSITION);
   4.208 +    glGetError();
   4.209      glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
   4.210      glDrawArrays(GL_LINE_STRIP, 0, count);
   4.211 -    glDisableVertexAttribArray(GLES2_ATTRIBUTE_POSITION);
   4.212      SDL_stack_free(vertices);
   4.213      if (glGetError() != GL_NO_ERROR)
   4.214      {
   4.215 @@ -923,34 +933,14 @@
   4.216  {
   4.217      GLES2_DriverContext *rdata = (GLES2_DriverContext *)renderer->driverdata;
   4.218      GLfloat vertices[8];
   4.219 -    SDL_BlendMode blendMode;
   4.220 -    int alpha;
   4.221 -    GLuint locColor;
   4.222      int idx;
   4.223  
   4.224 -    GLES2_ActivateRenderer(renderer);
   4.225 -
   4.226 -    blendMode = renderer->blendMode;
   4.227 -    alpha = renderer->a;
   4.228 -
   4.229 -    /* Activate an appropriate shader and set the projection matrix */
   4.230 -    if (GLES2_SelectProgram(renderer, GLES2_IMAGESOURCE_SOLID, blendMode) < 0)
   4.231 +    if (GLES2_SetDrawingState(renderer) < 0) {
   4.232          return -1;
   4.233 -
   4.234 -    /* Select the color to draw with */
   4.235 -    locColor = rdata->current_program->uniform_locations[GLES2_UNIFORM_COLOR];
   4.236 -    glGetError();
   4.237 -    glUniform4f(locColor,
   4.238 -                renderer->r * inv255f,
   4.239 -                renderer->g * inv255f,
   4.240 -                renderer->b * inv255f,
   4.241 -                alpha * inv255f);
   4.242 -
   4.243 -    /* Configure the correct blend mode */
   4.244 -    GLES2_SetBlendMode(blendMode);
   4.245 +    }
   4.246  
   4.247      /* Emit a line loop for each rectangle */
   4.248 -    glEnableVertexAttribArray(GLES2_ATTRIBUTE_POSITION);
   4.249 +    glGetError();
   4.250      for (idx = 0; idx < count; ++idx) {
   4.251          const SDL_Rect *rect = &rects[idx];
   4.252  
   4.253 @@ -970,7 +960,6 @@
   4.254          glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, 0, vertices);
   4.255          glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
   4.256      }
   4.257 -    glDisableVertexAttribArray(GLES2_ATTRIBUTE_POSITION);
   4.258      if (glGetError() != GL_NO_ERROR)
   4.259      {
   4.260          SDL_SetError("Failed to render lines");
   4.261 @@ -987,7 +976,6 @@
   4.262      GLES2_TextureData *tdata = (GLES2_TextureData *)texture->driverdata;
   4.263      GLES2_ImageSource sourceType;
   4.264      SDL_BlendMode blendMode;
   4.265 -    int alpha;
   4.266      GLfloat vertices[8];
   4.267      GLfloat texCoords[8];
   4.268      GLuint locTexture;
   4.269 @@ -997,7 +985,6 @@
   4.270  
   4.271      /* Activate an appropriate shader and set the projection matrix */
   4.272      blendMode = texture->blendMode;
   4.273 -    alpha = texture->a;
   4.274      sourceType = GLES2_IMAGESOURCE_TEXTURE;
   4.275      if (GLES2_SelectProgram(renderer, sourceType, blendMode) < 0)
   4.276          return -1;
   4.277 @@ -1009,8 +996,13 @@
   4.278      glBindTexture(tdata->texture_type, tdata->texture);
   4.279      glUniform1i(locTexture, 0);
   4.280  
   4.281 -    /* Configure texture blending */
   4.282 -    GLES2_SetBlendMode(blendMode);
   4.283 +    if (tdata->scaleMode != rdata->current.scaleMode) {
   4.284 +        glTexParameteri(tdata->texture_type, GL_TEXTURE_MIN_FILTER,
   4.285 +                        tdata->scaleMode);
   4.286 +        glTexParameteri(tdata->texture_type, GL_TEXTURE_MAG_FILTER,
   4.287 +                        tdata->scaleMode);
   4.288 +        rdata->current.scaleMode = tdata->scaleMode;
   4.289 +    }
   4.290  
   4.291      /* Configure color modulation */
   4.292      locModulation = rdata->current_program->uniform_locations[GLES2_UNIFORM_MODULATION];
   4.293 @@ -1018,11 +1010,14 @@
   4.294                  texture->r * inv255f,
   4.295                  texture->g * inv255f,
   4.296                  texture->b * inv255f,
   4.297 -                alpha * inv255f);
   4.298 +                texture->a * inv255f);
   4.299 +
   4.300 +    /* Configure texture blending */
   4.301 +    GLES2_SetBlendMode(rdata, blendMode);
   4.302 +
   4.303 +    GLES2_SetTexCoords(rdata, SDL_TRUE);
   4.304  
   4.305      /* Emit the textured quad */
   4.306 -    glEnableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD);
   4.307 -    glEnableVertexAttribArray(GLES2_ATTRIBUTE_POSITION);
   4.308      vertices[0] = (GLfloat)dstrect->x;
   4.309      vertices[1] = (GLfloat)dstrect->y;
   4.310      vertices[2] = (GLfloat)(dstrect->x + dstrect->w);
   4.311 @@ -1042,8 +1037,6 @@
   4.312      texCoords[7] = (srcrect->y + srcrect->h) / (GLfloat)texture->h;
   4.313      glVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, 0, texCoords);
   4.314      glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
   4.315 -    glDisableVertexAttribArray(GLES2_ATTRIBUTE_POSITION);
   4.316 -    glDisableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD);
   4.317      if (glGetError() != GL_NO_ERROR)
   4.318      {
   4.319          SDL_SetError("Failed to render texture");
   4.320 @@ -1067,6 +1060,25 @@
   4.321  
   4.322  #define GL_NVIDIA_PLATFORM_BINARY_NV 0x890B
   4.323  
   4.324 +static void
   4.325 +GLES2_ResetState(SDL_Renderer *renderer)
   4.326 +{
   4.327 +    GLES2_DriverContext *rdata = (GLES2_DriverContext *) renderer->driverdata;
   4.328 +
   4.329 +    if (SDL_CurrentContext == rdata->context) {
   4.330 +        GLES2_UpdateViewport(renderer);
   4.331 +    } else {
   4.332 +        GLES2_ActivateRenderer(renderer);
   4.333 +    }
   4.334 +
   4.335 +    rdata->current.blendMode = -1;
   4.336 +    rdata->current.scaleMode = 0;
   4.337 +    rdata->current.tex_coords = SDL_FALSE;
   4.338 +
   4.339 +    glEnableVertexAttribArray(GLES2_ATTRIBUTE_POSITION);
   4.340 +    glDisableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD);
   4.341 +}
   4.342 +
   4.343  static SDL_Renderer *
   4.344  GLES2_CreateRenderer(SDL_Window *window, Uint32 flags)
   4.345  {
   4.346 @@ -1166,6 +1178,9 @@
   4.347      renderer->RenderPresent       = &GLES2_RenderPresent;
   4.348      renderer->DestroyTexture      = &GLES2_DestroyTexture;
   4.349      renderer->DestroyRenderer     = &GLES2_DestroyRenderer;
   4.350 +
   4.351 +    GLES2_ResetState(renderer);
   4.352 +
   4.353      return renderer;
   4.354  }
   4.355