# HG changeset patch # User Gabriel Jacobo # Date 1361891292 10800 # Branch RenderGeometry # Node ID b73a4afb8b7116baa4886d9d87d9218b5a4eddad # Parent c550cccb91fc554d30b7c8ecc4524fa530bcd9d9 Adds SDL_RenderGeometry,SDL_EnableScissor,SDL_DisableScissor,SDL_ScissorRegion extern DECLSPEC int SDL_RenderGeometry(SDL_Renderer * renderer, SDL_Texture *texture, SDL_Vertex *vertices, int num_vertices, int* indices, int num_indices, const SDL_Vector2f *translation); extern DECLSPEC int SDL_EnableScissor(SDL_Renderer * renderer); extern DECLSPEC int SDL_DisableScissor(SDL_Renderer * renderer); extern DECLSPEC int SDL_ScissorRegion(SDL_Renderer * renderer, const SDL_Rect *region); diff -r c550cccb91fc -r b73a4afb8b71 Makefile.in --- a/Makefile.in lun feb 25 16:22:34 2013 -0300 +++ b/Makefile.in mar feb 26 12:08:12 2013 -0300 @@ -89,6 +89,7 @@ SDL_touch.h \ SDL_types.h \ SDL_version.h \ + SDL_vertex.h \ SDL_video.h \ begin_code.h \ close_code.h diff -r c550cccb91fc -r b73a4afb8b71 include/SDL_render.h --- a/include/SDL_render.h lun feb 25 16:22:34 2013 -0300 +++ b/include/SDL_render.h mar feb 26 12:08:12 2013 -0300 @@ -48,6 +48,7 @@ #include "SDL_stdinc.h" #include "SDL_rect.h" #include "SDL_video.h" +#include "SDL_vertex.h" #include "begin_code.h" /* Set up for C function definitions, even when using C++ */ @@ -775,6 +776,42 @@ extern DECLSPEC int SDLCALL SDL_GL_UnbindTexture(SDL_Texture *texture); +/** + * \brief Render a set of vertex, optionally using a texture and indices into the vertex array + * + * \param texture (optional) The SDL texture to unbind + * \param vertices An array of SDL_Vertex elements to be rendered + * \param num_vertices Number of elements in the vertices array + * \param indices (optional) An array of integers indices into the vertices array, if NULL all vertices will be rendered in sequential order + * \param num_indices Number of elements in the indices array (ignored if indices is NULL) + * \param translation (optional) A translation vector that will be applied to the vertices prior to rendering + * + * \return 0 on success, or -1 if the operation is not supported + */ +extern DECLSPEC int SDL_RenderGeometry(SDL_Renderer * renderer, SDL_Texture *texture, SDL_Vertex *vertices, int num_vertices, int* indices, int num_indices, const SDL_Vector2f *translation); + +/** + * \brief Enable the Scissor Region + * + * \return 0 on success, or -1 if the operation is not supported + */ +extern DECLSPEC int SDL_EnableScissor(SDL_Renderer * renderer); + +/** + * \brief Disable the Scissor Region + * + * \return 0 on success, or -1 if the operation is not supported + */ +extern DECLSPEC int SDL_DisableScissor(SDL_Renderer * renderer); + +/** + * \brief Set the scissor region + * + * \return 0 on success, or -1 if the operation is not supported or region is NULL + */ +extern DECLSPEC int SDL_ScissorRegion(SDL_Renderer * renderer, const SDL_Rect *region); + + /* Ends C function definitions when using C++ */ #ifdef __cplusplus /* *INDENT-OFF* */ diff -r c550cccb91fc -r b73a4afb8b71 include/SDL_vertex.h --- /dev/null jue ene 01 00:00:00 1970 +0000 +++ b/include/SDL_vertex.h mar feb 26 12:08:12 2013 -0300 @@ -0,0 +1,71 @@ +/* + Simple DirectMedia Layer + Copyright (C) 1997-2013 Sam Lantinga + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. +*/ + +/** + * \file SDL_vertex.h + * + * Header file for SDL_vertex definition and management functions. + */ + +#ifndef _SDL_vertex_h +#define _SDL_vertex_h + +#include "SDL_pixels.h" + +#include "begin_code.h" +/* Set up for C function definitions, even when using C++ */ +#ifdef __cplusplus +/* *INDENT-OFF* */ +extern "C" { +/* *INDENT-ON* */ +#endif + +typedef struct +{ + float x; + float y; +} SDL_Vector2f; + +/** + * \brief The structure that defines a vertex + * + */ +typedef struct +{ + SDL_Vector2f position; + union { + SDL_Color color; + SDL_Color colour; + }; + SDL_Vector2f tex_coord; +} SDL_Vertex; + +/* Ends C function definitions when using C++ */ +#ifdef __cplusplus +/* *INDENT-OFF* */ +} +/* *INDENT-ON* */ +#endif +#include "close_code.h" + +#endif /* _SDL_vertex_h */ + +/* vi: set ts=4 sw=4 expandtab: */ diff -r c550cccb91fc -r b73a4afb8b71 src/render/SDL_render.c --- a/src/render/SDL_render.c lun feb 25 16:22:34 2013 -0300 +++ b/src/render/SDL_render.c mar feb 26 12:08:12 2013 -0300 @@ -1747,4 +1747,64 @@ return -1; } + +int SDL_RenderGeometry(SDL_Renderer * renderer, SDL_Texture *texture, SDL_Vertex *vertices, int num_vertices, int* indices, int num_indices, const SDL_Vector2f *translation) +{ + CHECK_RENDERER_MAGIC(renderer, -1); + + if (texture) { + CHECK_TEXTURE_MAGIC(texture, -1); + + if (renderer != texture->renderer) { + SDL_SetError("Texture was not created with this renderer"); + return -1; + } + } + + if (!renderer->RenderGeometry) { + SDL_SetError("Renderer does not support RenderGeometry"); + return -1; + } + + if(!vertices) { + SDL_SetError("Vertices parameter can not be null"); + return -1; + } + + return renderer->RenderGeometry(renderer, texture, vertices, num_vertices, indices, num_indices, translation); +} + +int SDL_EnableScissor (SDL_Renderer * renderer) +{ + if(renderer && renderer->EnableScissor) { + renderer->EnableScissor(renderer); + } + + SDL_Unsupported(); + return -1; +} + +int SDL_DisableScissor (SDL_Renderer * renderer) +{ + if(renderer && renderer->DisableScissor) { + renderer->DisableScissor(renderer); + } + + SDL_Unsupported(); + return -1; +} + +int SDL_ScissorRegion(SDL_Renderer * renderer, const SDL_Rect *region) +{ + if(renderer && renderer->ScissorRegion) { + if (region) { + return renderer->ScissorRegion(renderer, region); + } + return -1; + } + + SDL_Unsupported(); + return -1; +} + /* vi: set ts=4 sw=4 expandtab: */ diff -r c550cccb91fc -r b73a4afb8b71 src/render/SDL_sysrender.h --- a/src/render/SDL_sysrender.h lun feb 25 16:22:34 2013 -0300 +++ b/src/render/SDL_sysrender.h mar feb 26 12:08:12 2013 -0300 @@ -26,6 +26,7 @@ #include "SDL_render.h" #include "SDL_events.h" #include "SDL_yuv_sw_c.h" +#include "SDL_vertex.h" /* The SDL 2D rendering system */ @@ -115,6 +116,11 @@ int (*GL_BindTexture) (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh); int (*GL_UnbindTexture) (SDL_Renderer * renderer, SDL_Texture *texture); + int (*RenderGeometry) (SDL_Renderer * renderer, SDL_Texture *texture, SDL_Vertex *vertices, int num_vertices, int* indices, int num_indices, const SDL_Vector2f *translation); + int (*EnableScissor) (SDL_Renderer * renderer); + int (*DisableScissor) (SDL_Renderer * renderer); + int (*ScissorRegion) (SDL_Renderer * renderer, const SDL_Rect *region); + /* The current renderer info */ SDL_RendererInfo info; diff -r c550cccb91fc -r b73a4afb8b71 src/render/opengl/SDL_glfuncs.h --- a/src/render/opengl/SDL_glfuncs.h lun feb 25 16:22:34 2013 -0300 +++ b/src/render/opengl/SDL_glfuncs.h mar feb 26 12:08:12 2013 -0300 @@ -63,7 +63,7 @@ (GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)) SDL_PROC_UNUSED(void, glColorMaterial, (GLenum face, GLenum mode)) -SDL_PROC_UNUSED(void, glColorPointer, +SDL_PROC(void, glColorPointer, (GLint size, GLenum type, GLsizei stride, const GLvoid * pointer)) SDL_PROC_UNUSED(void, glCopyPixels, @@ -88,10 +88,10 @@ SDL_PROC_UNUSED(void, glDepthMask, (GLboolean flag)) SDL_PROC_UNUSED(void, glDepthRange, (GLclampd zNear, GLclampd zFar)) SDL_PROC(void, glDisable, (GLenum cap)) -SDL_PROC_UNUSED(void, glDisableClientState, (GLenum array)) -SDL_PROC_UNUSED(void, glDrawArrays, (GLenum mode, GLint first, GLsizei count)) +SDL_PROC(void, glDisableClientState, (GLenum array)) +SDL_PROC(void, glDrawArrays, (GLenum mode, GLint first, GLsizei count)) SDL_PROC_UNUSED(void, glDrawBuffer, (GLenum mode)) -SDL_PROC_UNUSED(void, glDrawElements, +SDL_PROC(void, glDrawElements, (GLenum mode, GLsizei count, GLenum type, const GLvoid * indices)) SDL_PROC(void, glDrawPixels, @@ -102,7 +102,7 @@ (GLsizei stride, const GLvoid * pointer)) SDL_PROC_UNUSED(void, glEdgeFlagv, (const GLboolean * flag)) SDL_PROC(void, glEnable, (GLenum cap)) -SDL_PROC_UNUSED(void, glEnableClientState, (GLenum array)) +SDL_PROC(void, glEnableClientState, (GLenum array)) SDL_PROC(void, glEnd, (void)) SDL_PROC_UNUSED(void, glEndList, (void)) SDL_PROC_UNUSED(void, glEvalCoord1d, (GLdouble u)) @@ -378,7 +378,7 @@ SDL_PROC_UNUSED(void, glTexCoord4s, (GLshort s, GLshort t, GLshort r, GLshort q)) SDL_PROC_UNUSED(void, glTexCoord4sv, (const GLshort * v)) -SDL_PROC_UNUSED(void, glTexCoordPointer, +SDL_PROC(void, glTexCoordPointer, (GLint size, GLenum type, GLsizei stride, const GLvoid * pointer)) SDL_PROC(void, glTexEnvf, (GLenum target, GLenum pname, GLfloat param)) @@ -447,9 +447,10 @@ SDL_PROC_UNUSED(void, glVertex4s, (GLshort x, GLshort y, GLshort z, GLshort w)) SDL_PROC_UNUSED(void, glVertex4sv, (const GLshort * v)) -SDL_PROC_UNUSED(void, glVertexPointer, +SDL_PROC(void, glVertexPointer, (GLint size, GLenum type, GLsizei stride, const GLvoid * pointer)) SDL_PROC(void, glViewport, (GLint x, GLint y, GLsizei width, GLsizei height)) +SDL_PROC(void, glUseProgramObjectARB, (GLhandleARB programObj)) /* vi: set ts=4 sw=4 expandtab: */ diff -r c550cccb91fc -r b73a4afb8b71 src/render/opengl/SDL_render_gl.c --- a/src/render/opengl/SDL_render_gl.c lun feb 25 16:22:34 2013 -0300 +++ b/src/render/opengl/SDL_render_gl.c mar feb 26 12:08:12 2013 -0300 @@ -75,6 +75,10 @@ static void GL_DestroyRenderer(SDL_Renderer * renderer); static int GL_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh); static int GL_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture); +static int GL_RenderGeometry (SDL_Renderer * renderer, SDL_Texture *texture, SDL_Vertex *vertices, int num_vertices, int* indices, int num_indices, const SDL_Vector2f *translation); +static int GL_EnableScissor(SDL_Renderer * renderer); +static int GL_DisableScissor(SDL_Renderer * renderer); +static int GL_ScissorRegion(SDL_Renderer * renderer, const SDL_Rect *region); SDL_RenderDriver GL_RenderDriver = { GL_CreateRenderer, @@ -127,6 +131,7 @@ /* Shader support */ GL_ShaderContext *shaders; + SDL_bool GL_shaders_textureSize_supported; } GL_RenderData; @@ -295,6 +300,7 @@ const char *hint; GLint value; Uint32 window_flags; + const char *shading_language_version; window_flags = SDL_GetWindowFlags(window); if (!(window_flags & SDL_WINDOW_OPENGL)) { @@ -337,6 +343,10 @@ renderer->DestroyRenderer = GL_DestroyRenderer; renderer->GL_BindTexture = GL_BindTexture; renderer->GL_UnbindTexture = GL_UnbindTexture; + renderer->RenderGeometry = GL_RenderGeometry; + renderer->EnableScissor = GL_EnableScissor; + renderer->DisableScissor = GL_DisableScissor; + renderer->ScissorRegion = GL_ScissorRegion; renderer->info = GL_RenderDriver.info; renderer->info.flags = SDL_RENDERER_ACCELERATED; renderer->driverdata = data; @@ -385,6 +395,21 @@ renderer->info.max_texture_height = value; } + data->GL_shaders_textureSize_supported = SDL_FALSE; + if (SDL_GL_ExtensionSupported("GL_ARB_shading_language_100")) { + shading_language_version = data->glGetString(GL_SHADING_LANGUAGE_VERSION); + if (data->glGetError() == GL_NO_ERROR) { + /* If there's an error it means shading language v1.00 aka v1.051 */ + /* We are looking for v1.30 or higher */ + if (! (shading_language_version[0] == '1' && shading_language_version[1] == '.' && ( + shading_language_version[2]=='0' || shading_language_version[2]=='1' || shading_language_version[2]=='2' + ))) { + data->GL_shaders_textureSize_supported = SDL_TRUE; + } + + } + } + /* Check for multitexture support */ if (SDL_GL_ExtensionSupported("GL_ARB_multitexture")) { data->glActiveTextureARB = (PFNGLACTIVETEXTUREARBPROC) SDL_GL_GetProcAddress("glActiveTextureARB"); @@ -1299,6 +1324,123 @@ return 0; } +static int GL_RenderGeometry (SDL_Renderer * renderer, SDL_Texture *texture, SDL_Vertex *vertices, int num_vertices, int* indices, int num_indices, const SDL_Vector2f *translation) { + int i; + GL_RenderData *data = (GL_RenderData *) renderer->driverdata; + GL_TextureData *texturedata = NULL; + + if (texture) { + texturedata = (GL_TextureData *) texture->driverdata; + } + + GL_ActivateRenderer(renderer); + + data->glPushMatrix(); + if(translation) { + data->glTranslatef(translation->x, translation->y, 0); + } + + if (texture) { + data->glEnableClientState(GL_TEXTURE_COORD_ARRAY); + data->glEnable(texturedata->type); + if (texturedata->yuv) { + data->glActiveTextureARB(GL_TEXTURE2_ARB); + data->glBindTexture(texturedata->type, texturedata->vtexture); + + data->glActiveTextureARB(GL_TEXTURE1_ARB); + data->glBindTexture(texturedata->type, texturedata->utexture); + + data->glActiveTextureARB(GL_TEXTURE0_ARB); + if (texturedata->type == GL_TEXTURE_RECTANGLE_ARB && data->GL_shaders_textureSize_supported) { + GL_SetShader(data, SHADER_YV12_AUTOSCALE); + } + else { + GL_SetShader(data, SHADER_YV12); + } + } + else { + if (texturedata->type == GL_TEXTURE_RECTANGLE_ARB && data->GL_shaders_textureSize_supported) { + GL_SetShader(data, SHADER_RGB_AUTOSCALE); + } + else { + GL_SetShader(data, SHADER_RGB); + } + } + + data->glBindTexture(texturedata->type, texturedata->texture); + + if (texturedata->type == GL_TEXTURE_RECTANGLE_ARB && !data->GL_shaders_textureSize_supported ) { + for(i = 0; i < num_vertices; i++) + { + /* GL_TEXTURE_RECTANGLE_ARB texture coordinates go from 0 to texture width/height */ + vertices[i].tex_coord.x *= texturedata->texw; + vertices[i].tex_coord.y *= texturedata->texh; + }; + } + GL_SetBlendMode(data, texture->blendMode); + } + else { + GL_SetShader(data, SHADER_SOLID); + GL_SetBlendMode(data, SDL_BLENDMODE_BLEND); + } + + data->glEnableClientState(GL_VERTEX_ARRAY); + data->glEnableClientState(GL_COLOR_ARRAY); + data->glVertexPointer(2, GL_FLOAT, sizeof(SDL_Vertex), &vertices[0].position); + data->glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(SDL_Vertex), &vertices[0].color); + data->glTexCoordPointer(2, GL_FLOAT, sizeof(SDL_Vertex), &vertices[0].tex_coord); + + if (indices) { + data->glDrawElements(GL_TRIANGLES, num_indices, GL_UNSIGNED_INT, indices); + } + else { + data->glDrawArrays(GL_TRIANGLES, 0, num_vertices); + } + data->glDisableClientState(GL_VERTEX_ARRAY); + data->glDisableClientState(GL_COLOR_ARRAY); + + if(texture) { + if (texturedata->type == GL_TEXTURE_RECTANGLE_ARB && !data->GL_shaders_textureSize_supported ) { + /* Unscale values in case the user wants to re submit them + TODO: As this is not an exact procedure, evaluate the merits of allocating extra memory and copying values + instead, trying to avoid excessive fragmentation. + */ + for(i = 0; i < num_vertices; i++) + { + /* GL_TEXTURE_RECTANGLE_ARB texture coordinates go from 0 to texture width/height */ + vertices[i].tex_coord.x /= texturedata->texw; + vertices[i].tex_coord.y /= texturedata->texh; + }; + } + } + + data->glPopMatrix(); + + return 0; +} + + +static int GL_EnableScissor(SDL_Renderer * renderer) { + GL_RenderData *data = (GL_RenderData *) renderer->driverdata; + data->glEnable(GL_SCISSOR_TEST); + return 0; +} + +static int GL_DisableScissor(SDL_Renderer * renderer) { + GL_RenderData *data = (GL_RenderData *) renderer->driverdata; + data->glDisable(GL_SCISSOR_TEST); + return 0; +} + +static int GL_ScissorRegion(SDL_Renderer * renderer, const SDL_Rect *region) +{ + GL_RenderData *data = (GL_RenderData *) renderer->driverdata; + int w_width, w_height; + SDL_GetWindowSize(renderer->window, &w_width, &w_height); + data->glScissor(region->x, w_height - (region->y + region->h), region->w, region->h); + return 0; +} + #endif /* SDL_VIDEO_RENDER_OGL && !SDL_RENDER_DISABLED */ /* vi: set ts=4 sw=4 expandtab: */ diff -r c550cccb91fc -r b73a4afb8b71 src/render/opengl/SDL_shaders_gl.c --- a/src/render/opengl/SDL_shaders_gl.c lun feb 25 16:22:34 2013 -0300 +++ b/src/render/opengl/SDL_shaders_gl.c mar feb 26 12:08:12 2013 -0300 @@ -164,6 +164,80 @@ " gl_FragColor = vec4(rgb, 1.0) * v_color;\n" "}" }, + /* SHADER_RGB_AUTOSCALE */ + { + /* vertex shader */ +"varying vec4 v_color;\n" +"varying vec2 v_texCoord;\n" +"\n" +"void main()\n" +"{\n" +" gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n" +" v_color = gl_Color;\n" +" v_texCoord = vec2(gl_MultiTexCoord0);\n" +"}", + /* fragment shader */ +"varying vec4 v_color;\n" +"varying vec2 v_texCoord;\n" +"uniform sampler2D tex0;\n" +"\n" +"void main()\n" +"{\n" +" gl_FragColor = texture2D(tex0, v_texCoord*textureSize(tex0, 0)) * v_color;\n" +"}" + }, + + /* SHADER_YV12_AUTOSCALE */ + { + /* vertex shader */ +"varying vec4 v_color;\n" +"varying vec2 v_texCoord;\n" +"\n" +"void main()\n" +"{\n" +" gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;\n" +" v_color = gl_Color;\n" +" v_texCoord = vec2(gl_MultiTexCoord0);\n" +"}", + /* fragment shader */ +"varying vec4 v_color;\n" +"varying vec2 v_texCoord;\n" +"uniform sampler2D tex0; // Y \n" +"uniform sampler2D tex1; // U \n" +"uniform sampler2D tex2; // V \n" +"\n" +"// YUV offset \n" +"const vec3 offset = vec3(-0.0625, -0.5, -0.5);\n" +"\n" +"// RGB coefficients \n" +"const vec3 Rcoeff = vec3(1.164, 0.000, 1.596);\n" +"const vec3 Gcoeff = vec3(1.164, -0.391, -0.813);\n" +"const vec3 Bcoeff = vec3(1.164, 2.018, 0.000);\n" +"\n" +"void main()\n" +"{\n" +" vec2 tcoord;\n" +" vec3 yuv, rgb;\n" +"\n" +" // Get the Y value \n" +" tcoord = v_texCoord;\n" +" yuv.x = texture2D(tex0, tcoord*textureSize(tex0, 0)).r;\n" +"\n" +" // Get the U and V values \n" +" tcoord *= 0.5;\n" +" yuv.y = texture2D(tex1, tcoord*textureSize(tex1, 0)).r;\n" +" yuv.z = texture2D(tex2, tcoord*textureSize(tex2, 0)).r;\n" +"\n" +" // Do the color transform \n" +" yuv += offset;\n" +" rgb.r = dot(yuv, Rcoeff);\n" +" rgb.g = dot(yuv, Gcoeff);\n" +" rgb.b = dot(yuv, Bcoeff);\n" +"\n" +" // That was easy. :) \n" +" gl_FragColor = vec4(rgb, 1.0) * v_color;\n" +"}" + }, }; static SDL_bool diff -r c550cccb91fc -r b73a4afb8b71 src/render/opengl/SDL_shaders_gl.h --- a/src/render/opengl/SDL_shaders_gl.h lun feb 25 16:22:34 2013 -0300 +++ b/src/render/opengl/SDL_shaders_gl.h mar feb 26 12:08:12 2013 -0300 @@ -27,6 +27,8 @@ SHADER_SOLID, SHADER_RGB, SHADER_YV12, + SHADER_RGB_AUTOSCALE, + SHADER_YV12_AUTOSCALE, NUM_SHADERS } GL_Shader; diff -r c550cccb91fc -r b73a4afb8b71 src/render/opengles/SDL_glesfuncs.h --- a/src/render/opengles/SDL_glesfuncs.h lun feb 25 16:22:34 2013 -0300 +++ b/src/render/opengles/SDL_glesfuncs.h mar feb 26 12:08:12 2013 -0300 @@ -36,5 +36,12 @@ SDL_PROC(void, glRotatef, (GLfloat, GLfloat, GLfloat, GLfloat)) SDL_PROC(void, glPopMatrix, (void)) SDL_PROC(void, glDeleteFramebuffersOES, (GLsizei, const GLuint*)) +SDL_PROC(void, glColorPointer, + (GLint size, GLenum type, GLsizei stride, + const GLvoid * pointer)) +SDL_PROC(void, glDrawElements, + (GLenum mode, GLsizei count, GLenum type, + const GLvoid * indices)) +SDL_PROC(void, glScissor, (GLint x, GLint y, GLsizei width, GLsizei height)) /* vi: set ts=4 sw=4 expandtab: */ diff -r c550cccb91fc -r b73a4afb8b71 src/render/opengles/SDL_render_gles.c --- a/src/render/opengles/SDL_render_gles.c lun feb 25 16:22:34 2013 -0300 +++ b/src/render/opengles/SDL_render_gles.c mar feb 26 12:08:12 2013 -0300 @@ -80,6 +80,11 @@ static void GLES_DestroyRenderer(SDL_Renderer * renderer); static int GLES_BindTexture (SDL_Renderer * renderer, SDL_Texture *texture, float *texw, float *texh); static int GLES_UnbindTexture (SDL_Renderer * renderer, SDL_Texture *texture); +static int GLES_RenderGeometry (SDL_Renderer * renderer, SDL_Texture *texture, SDL_Vertex *vertices, int num_vertices, int* indices, int num_indices, const SDL_Vector2f *translation); +static int GLES_EnableScissor(SDL_Renderer * renderer); +static int GLES_DisableScissor(SDL_Renderer * renderer); +static int GLES_ScissorRegion(SDL_Renderer * renderer, const SDL_Rect *region); + typedef struct GLES_FBOList GLES_FBOList; @@ -316,6 +321,10 @@ renderer->DestroyRenderer = GLES_DestroyRenderer; renderer->GL_BindTexture = GLES_BindTexture; renderer->GL_UnbindTexture = GLES_UnbindTexture; + renderer->RenderGeometry = GLES_RenderGeometry; + renderer->EnableScissor = GLES_EnableScissor; + renderer->DisableScissor = GLES_DisableScissor; + renderer->ScissorRegion = GLES_ScissorRegion; renderer->info = GLES_RenderDriver.info; renderer->info.flags = SDL_RENDERER_ACCELERATED; renderer->driverdata = data; @@ -1114,6 +1123,93 @@ return 0; } +#define MAX_SHORT_INDICES 1024 + +static int GLES_RenderGeometry (SDL_Renderer * renderer, SDL_Texture *texture, SDL_Vertex *vertices, int num_vertices, int* indices, int num_indices, const SDL_Vector2f *translation) +{ + int i, base; + GLES_RenderData *data = (GLES_RenderData *)renderer->driverdata; + GLES_TextureData *texturedata = NULL; + static unsigned short indices_[MAX_SHORT_INDICES]; + + GLES_ActivateRenderer(renderer); + data->glPushMatrix(); + + if (texture) { + texturedata = (GLES_TextureData *) texture->driverdata; + GLES_SetTexCoords(data, SDL_TRUE); + data->glEnable(texturedata->type); + data->glBindTexture(texturedata->type, texturedata->texture); + GLES_SetBlendMode(data, texture->blendMode); + } + else { + GLES_SetTexCoords(data, SDL_FALSE); + GLES_SetBlendMode(data, SDL_BLENDMODE_BLEND); + } + + if (translation) { + data->glTranslatef(translation->x, translation->y, 0); + } + + data->glEnableClientState(GL_COLOR_ARRAY); + data->glVertexPointer(2, GL_FLOAT, sizeof(SDL_Vertex), &vertices[0].position); + data->glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(SDL_Vertex), &vertices[0].color); + data->glTexCoordPointer(2, GL_FLOAT, sizeof(SDL_Vertex), &vertices[0].tex_coord); + + if (indices) { + /* int indices need to be converted to short */ + base = 0; + for ( i = 0; base + i < num_indices; i++) + { + if (i == MAX_SHORT_INDICES) { + base += MAX_SHORT_INDICES; + i = 0; + data->glDrawElements(GL_TRIANGLES, MAX_SHORT_INDICES, GL_UNSIGNED_SHORT, indices_); + } + indices_[i] = (unsigned short) indices[i+base]; + } + if (i) { + data->glDrawElements(GL_TRIANGLES, i, GL_UNSIGNED_SHORT, indices_); + } + } + else { + data->glDrawArrays(GL_TRIANGLES, 0, num_vertices); + } + + data->glDisableClientState(GL_COLOR_ARRAY); + + if (texture) { + data->glDisable(texturedata->type); + } + + data->glPopMatrix(); + + return 0; +} + + +static int GLES_EnableScissor(SDL_Renderer * renderer) +{ + GLES_RenderData *data = (GLES_RenderData *) renderer->driverdata; + data->glEnable(GL_SCISSOR_TEST); + return 0; +} + +static int GLES_DisableScissor(SDL_Renderer * renderer) +{ + GLES_RenderData *data = (GLES_RenderData *)renderer->driverdata; + data->glDisable(GL_SCISSOR_TEST); + return 0; +} + +static int GLES_ScissorRegion(SDL_Renderer * renderer, const SDL_Rect *region) +{ + GLES_RenderData *data = (GLES_RenderData *)renderer->driverdata; + int w_width, w_height; + SDL_GetWindowSize(renderer->window, &w_width, &w_height); + data->glScissor(region->x, w_height - (region->y + region->h), region->w, region->h); + return 0; +} #endif /* SDL_VIDEO_RENDER_OGL_ES && !SDL_RENDER_DISABLED */ diff -r c550cccb91fc -r b73a4afb8b71 src/render/opengles2/SDL_gles2funcs.h --- a/src/render/opengles2/SDL_gles2funcs.h lun feb 25 16:22:34 2013 -0300 +++ b/src/render/opengles2/SDL_gles2funcs.h mar feb 26 12:08:12 2013 -0300 @@ -45,3 +45,7 @@ SDL_PROC(void, glFramebufferTexture2D, (GLenum, GLenum, GLenum, GLuint, GLint)) SDL_PROC(GLenum, glCheckFramebufferStatus, (GLenum)) SDL_PROC(void, glDeleteFramebuffers, (GLsizei, const GLuint *)) +SDL_PROC(void, glDrawElements, (GLenum, GLsizei, GLenum, const GLvoid *)) +SDL_PROC(void, glScissor, (GLint, GLint, GLsizei, GLsizei)) +SDL_PROC(void, glUniform2f, (GLint, GLfloat, GLfloat)) + diff -r c550cccb91fc -r b73a4afb8b71 src/render/opengles2/SDL_render_gles2.c --- a/src/render/opengles2/SDL_render_gles2.c lun feb 25 16:22:34 2013 -0300 +++ b/src/render/opengles2/SDL_render_gles2.c mar feb 26 12:08:12 2013 -0300 @@ -115,6 +115,7 @@ GLES2_ATTRIBUTE_TEXCOORD = 1, GLES2_ATTRIBUTE_ANGLE = 2, GLES2_ATTRIBUTE_CENTER = 3, + GLES2_ATTRIBUTE_COLOR = 4, } GLES2_Attribute; typedef enum @@ -123,7 +124,8 @@ GLES2_UNIFORM_TEXTURE, GLES2_UNIFORM_MODULATION, GLES2_UNIFORM_COLOR, - GLES2_UNIFORM_COLORTABLE + GLES2_UNIFORM_COLORTABLE, + GLES2_UNIFORM_TRANSLATION } GLES2_Uniform; typedef enum @@ -577,7 +579,7 @@ GLES2_ShaderCacheEntry *fragment, SDL_BlendMode blendMode); static int GLES2_SelectProgram(SDL_Renderer *renderer, GLES2_ImageSource source, - SDL_BlendMode blendMode); + SDL_BlendMode blendMode, GLES2_ShaderType vtype); static GLES2_ProgramCacheEntry * GLES2_CacheProgram(SDL_Renderer *renderer, GLES2_ShaderCacheEntry *vertex, @@ -632,6 +634,7 @@ rdata->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_TEXCOORD, "a_texCoord"); rdata->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_ANGLE, "a_angle"); rdata->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_CENTER, "a_center"); + rdata->glBindAttribLocation(entry->id, GLES2_ATTRIBUTE_COLOR, "a_color"); rdata->glLinkProgram(entry->id); rdata->glGetProgramiv(entry->id, GL_LINK_STATUS, &linkSuccessful); if (rdata->glGetError() != GL_NO_ERROR || !linkSuccessful) @@ -653,6 +656,10 @@ rdata->glGetUniformLocation(entry->id, "u_color"); entry->uniform_locations[GLES2_UNIFORM_COLORTABLE] = rdata->glGetUniformLocation(entry->id, "u_colorTable"); + entry->uniform_locations[GLES2_UNIFORM_TRANSLATION] = + rdata->glGetUniformLocation(entry->id, "u_translation"); + + /* Cache the linked program */ if (rdata->program_cache.head) @@ -816,16 +823,15 @@ } static int -GLES2_SelectProgram(SDL_Renderer *renderer, GLES2_ImageSource source, SDL_BlendMode blendMode) +GLES2_SelectProgram(SDL_Renderer *renderer, GLES2_ImageSource source, SDL_BlendMode blendMode, GLES2_ShaderType vtype) { GLES2_DriverContext *rdata = (GLES2_DriverContext *)renderer->driverdata; GLES2_ShaderCacheEntry *vertex = NULL; GLES2_ShaderCacheEntry *fragment = NULL; - GLES2_ShaderType vtype, ftype; + GLES2_ShaderType ftype; GLES2_ProgramCacheEntry *program; /* Select an appropriate shader pair for the specified modes */ - vtype = GLES2_SHADER_VERTEX_DEFAULT; switch (source) { case GLES2_IMAGESOURCE_SOLID: @@ -1030,7 +1036,7 @@ GLES2_SetTexCoords(rdata, SDL_FALSE); /* Activate an appropriate shader and set the projection matrix */ - if (GLES2_SelectProgram(renderer, GLES2_IMAGESOURCE_SOLID, blendMode) < 0) + if (GLES2_SelectProgram(renderer, GLES2_IMAGESOURCE_SOLID, blendMode, GLES2_SHADER_VERTEX_DEFAULT) < 0 ) return -1; /* Select the color to draw with */ @@ -1260,7 +1266,7 @@ break; } } - if (GLES2_SelectProgram(renderer, sourceType, blendMode) < 0) + if (GLES2_SelectProgram(renderer, sourceType, blendMode, GLES2_SHADER_VERTEX_DEFAULT) < 0 ) return -1; /* Select the target texture */ @@ -1426,7 +1432,7 @@ break; } } - if (GLES2_SelectProgram(renderer, sourceType, blendMode) < 0) + if (GLES2_SelectProgram(renderer, sourceType, blendMode, GLES2_SHADER_VERTEX_DEFAULT) < 0 ) return -1; /* Select the target texture */ @@ -1598,6 +1604,202 @@ /************************************************************************************************* + * Geometry rendering + *************************************************************************************************/ +static void GLES2_ResetState(SDL_Renderer *renderer); +static int GLES2_RenderGeometry (SDL_Renderer * renderer, SDL_Texture *texture, SDL_Vertex *vertices, int num_vertices, int* indices, int num_indices, const SDL_Vector2f *translation); +static int GLES2_EnableScissor(SDL_Renderer * renderer); +static int GLES2_DisableScissor(SDL_Renderer * renderer); +static int GLES2_ScissorRegion(SDL_Renderer * renderer, const SDL_Rect *region); + +#define MAX_SHORT_INDICES 1024 + +static int GLES2_RenderGeometry (SDL_Renderer * renderer, SDL_Texture *texture, SDL_Vertex *vertices, int num_vertices, int* indices, int num_indices, const SDL_Vector2f *translation) +{ + int i, base; + GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata; + GLES2_TextureData *texturedata = NULL; + GLES2_ImageSource sourceType; + static unsigned short indices_[MAX_SHORT_INDICES]; + + if (texture) { + texturedata = (GLES2_TextureData *) texture->driverdata; + } + + GLES2_ActivateRenderer(renderer); + + if(texture) { + if (renderer->target) { + /* Check if we need to do color mapping between the source and render target textures */ + if (renderer->target->format != texture->format) { + switch (texture->format) + { + case SDL_PIXELFORMAT_ABGR8888: + switch (renderer->target->format) + { + case SDL_PIXELFORMAT_ARGB8888: + case SDL_PIXELFORMAT_RGB888: + sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB; + break; + case SDL_PIXELFORMAT_BGR888: + sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR; + break; + } + break; + case SDL_PIXELFORMAT_ARGB8888: + switch (renderer->target->format) + { + case SDL_PIXELFORMAT_ABGR8888: + case SDL_PIXELFORMAT_BGR888: + sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB; + break; + case SDL_PIXELFORMAT_RGB888: + sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR; + break; + } + break; + case SDL_PIXELFORMAT_BGR888: + switch (renderer->target->format) + { + case SDL_PIXELFORMAT_ABGR8888: + sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR; + break; + case SDL_PIXELFORMAT_ARGB8888: + sourceType = GLES2_IMAGESOURCE_TEXTURE_RGB; + break; + case SDL_PIXELFORMAT_RGB888: + sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB; + break; + } + break; + case SDL_PIXELFORMAT_RGB888: + switch (renderer->target->format) + { + case SDL_PIXELFORMAT_ABGR8888: + sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB; + break; + case SDL_PIXELFORMAT_ARGB8888: + sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR; + break; + case SDL_PIXELFORMAT_BGR888: + sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB; + break; + } + break; + } + } + else sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR; // Texture formats match, use the non color mapping shader (even if the formats are not ABGR) + } + else { + switch (texture->format) + { + case SDL_PIXELFORMAT_ABGR8888: + sourceType = GLES2_IMAGESOURCE_TEXTURE_ABGR; + break; + case SDL_PIXELFORMAT_ARGB8888: + sourceType = GLES2_IMAGESOURCE_TEXTURE_ARGB; + break; + case SDL_PIXELFORMAT_BGR888: + sourceType = GLES2_IMAGESOURCE_TEXTURE_BGR; + break; + case SDL_PIXELFORMAT_RGB888: + sourceType = GLES2_IMAGESOURCE_TEXTURE_RGB; + break; + } + } + if (GLES2_SelectProgram(renderer, sourceType, texture->blendMode, GLES2_SHADER_VERTEX_GEOMETRY) < 0 ) + return -1; + } + else { + GLES2_SelectProgram(renderer, GLES2_IMAGESOURCE_SOLID, SDL_BLENDMODE_BLEND, GLES2_SHADER_VERTEX_GEOMETRY); + } + + + if (texture) { + GLES2_SetBlendMode(data, texture->blendMode); + } + else { + GLES2_SetBlendMode(data, SDL_BLENDMODE_BLEND); + } + + data->glVertexAttribPointer(GLES2_ATTRIBUTE_POSITION, 2, GL_FLOAT, GL_FALSE, sizeof(SDL_Vertex), &vertices[0].position); + data->glVertexAttribPointer(GLES2_ATTRIBUTE_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(SDL_Vertex), &vertices[0].colour); + data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_POSITION); + data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD); + data->glEnableVertexAttribArray(GLES2_ATTRIBUTE_COLOR); + + if(texture) { + data->glActiveTexture(GL_TEXTURE0); + data->glBindTexture(texturedata->texture_type, texturedata->texture); + data->glUniform1i(data->current_program->uniform_locations[GLES2_UNIFORM_TEXTURE], 0); + glVertexAttribPointer(GLES2_ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, GL_FALSE, sizeof(SDL_Vertex), &vertices[0].tex_coord); + } + else { + data->glActiveTexture(GL_TEXTURE0); + data->glDisable(GL_TEXTURE_2D); + data->glDisableVertexAttribArray(GLES2_ATTRIBUTE_TEXCOORD); + } + + if (translation) { + data->glUniform2f(data->current_program->uniform_locations[GLES2_UNIFORM_TRANSLATION], translation->x, translation->y); + } + + data->glUniform4f(data->current_program->uniform_locations[GLES2_UNIFORM_COLOR], 1.0, 1.0, 1.0, 1.0); + data->glUniform4f(data->current_program->uniform_locations[GLES2_UNIFORM_MODULATION], 1.0, 1.0, 1.0, 1.0); + + if (indices) { + /* int indices need to be converted to short */ + base = 0; + for ( i = 0; base + i < num_indices; i++) + { + if (i == MAX_SHORT_INDICES) { + base += MAX_SHORT_INDICES; + i = 0; + data->glDrawElements(GL_TRIANGLES, MAX_SHORT_INDICES, GL_UNSIGNED_SHORT, indices_); + } + indices_[i] = (unsigned short) indices[i+base]; + } + + if (i) { + data->glDrawElements(GL_TRIANGLES, i, GL_UNSIGNED_SHORT, indices_); + } + } + else { + data->glDrawArrays(GL_TRIANGLES, 0, num_vertices); + } + + data->glDisableVertexAttribArray(GLES2_ATTRIBUTE_COLOR); + + return 0; +} + + +static int GLES2_EnableScissor(SDL_Renderer * renderer) +{ + GLES2_DriverContext *data = (GLES2_DriverContext *) renderer->driverdata; + data->glEnable(GL_SCISSOR_TEST); + return 0; +} + +static int GLES2_DisableScissor(SDL_Renderer * renderer) +{ + GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata; + data->glDisable(GL_SCISSOR_TEST); + return 0; +} + +static int GLES2_ScissorRegion(SDL_Renderer * renderer, const SDL_Rect *region) +{ + GLES2_DriverContext *data = (GLES2_DriverContext *)renderer->driverdata; + int w_width, w_height; + SDL_GetWindowSize(renderer->window, &w_width, &w_height); + data->glScissor(region->x, w_height - (region->y + region->h), region->w, region->h); + return 0; +} + + + +/************************************************************************************************* * Renderer instantiation * *************************************************************************************************/ @@ -1747,6 +1949,10 @@ renderer->DestroyRenderer = &GLES2_DestroyRenderer; renderer->GL_BindTexture = &GLES2_BindTexture; renderer->GL_UnbindTexture = &GLES2_UnbindTexture; + renderer->RenderGeometry = &GLES2_RenderGeometry; + renderer->EnableScissor = &GLES2_EnableScissor; + renderer->DisableScissor = &GLES2_DisableScissor; + renderer->ScissorRegion = &GLES2_ScissorRegion; GLES2_ResetState(renderer); diff -r c550cccb91fc -r b73a4afb8b71 src/render/opengles2/SDL_shaders_gles2.c --- a/src/render/opengles2/SDL_shaders_gles2.c lun feb 25 16:22:34 2013 -0300 +++ b/src/render/opengles2/SDL_shaders_gles2.c mar feb 26 12:08:12 2013 -0300 @@ -38,6 +38,7 @@ attribute float a_angle; \ attribute vec2 a_center; \ varying vec2 v_texCoord; \ + varying vec4 v_color; \ \ void main() \ { \ @@ -47,18 +48,40 @@ mat2 rotationMatrix = mat2(c, -s, s, c); \ vec2 position = rotationMatrix * (a_position - a_center) + a_center; \ v_texCoord = a_texCoord; \ + v_color = vec4(1.0, 1.0, 1.0, 1.0);\ gl_Position = u_projection * vec4(position, 0.0, 1.0);\ gl_PointSize = 1.0; \ } \ "; +static const Uint8 GLES2_VertexSrc_Geometry_[] = " \ + attribute vec2 a_position; \ + attribute vec2 a_texCoord; \ + attribute vec4 a_color; \ + varying vec2 v_texCoord; \ + varying vec4 v_color; \ + varying vec2 v_position; \ + uniform mat4 u_projection; \ + uniform vec2 u_translation; \ +\ + void main() \ + { \ + v_position = a_position + u_translation; \ + gl_Position = u_projection * vec4(v_position, 0.0, 1.0); \ + v_texCoord = a_texCoord; \ + v_color = a_color; \ + }\ +"; + + static const Uint8 GLES2_FragmentSrc_SolidSrc_[] = " \ precision mediump float; \ uniform vec4 u_color; \ + varying vec4 v_color; \ \ void main() \ { \ - gl_FragColor = u_color; \ + gl_FragColor = u_color * v_color; \ } \ "; @@ -67,10 +90,11 @@ uniform sampler2D u_texture; \ uniform vec4 u_modulation; \ varying vec2 v_texCoord; \ + varying vec4 v_color; \ \ void main() \ { \ - gl_FragColor = texture2D(u_texture, v_texCoord); \ + gl_FragColor = texture2D(u_texture, v_texCoord) * v_color; \ gl_FragColor *= u_modulation; \ } \ "; @@ -81,10 +105,11 @@ uniform sampler2D u_texture; \ uniform vec4 u_modulation; \ varying vec2 v_texCoord; \ + varying vec4 v_color; \ \ void main() \ { \ - vec4 abgr = texture2D(u_texture, v_texCoord); \ + vec4 abgr = texture2D(u_texture, v_texCoord) * v_color; \ gl_FragColor = abgr; \ gl_FragColor.r = abgr.b; \ gl_FragColor.b = abgr.r; \ @@ -98,10 +123,11 @@ uniform sampler2D u_texture; \ uniform vec4 u_modulation; \ varying vec2 v_texCoord; \ + varying vec4 v_color; \ \ void main() \ { \ - vec4 abgr = texture2D(u_texture, v_texCoord); \ + vec4 abgr = texture2D(u_texture, v_texCoord) * v_color; \ gl_FragColor = abgr; \ gl_FragColor.r = abgr.b; \ gl_FragColor.b = abgr.r; \ @@ -116,10 +142,11 @@ uniform sampler2D u_texture; \ uniform vec4 u_modulation; \ varying vec2 v_texCoord; \ + varying vec4 v_color; \ \ void main() \ { \ - vec4 abgr = texture2D(u_texture, v_texCoord); \ + vec4 abgr = texture2D(u_texture, v_texCoord) * v_color; \ gl_FragColor = abgr; \ gl_FragColor.a = 1.0; \ gl_FragColor *= u_modulation; \ @@ -133,6 +160,13 @@ GLES2_VertexSrc_Default_ }; +static const GLES2_ShaderInstance GLES2_VertexSrc_Geometry = { + GL_VERTEX_SHADER, + GLES2_SOURCE_SHADER, + sizeof(GLES2_VertexSrc_Geometry_), + GLES2_VertexSrc_Geometry_ +}; + static const GLES2_ShaderInstance GLES2_FragmentSrc_SolidSrc = { GL_FRAGMENT_SHADER, GLES2_SOURCE_SHADER, @@ -168,6 +202,7 @@ GLES2_FragmentSrc_TextureBGRSrc_ }; + /************************************************************************************************* * Vertex/fragment shader binaries (NVIDIA Tegra 1/2) * *************************************************************************************************/ @@ -496,6 +531,13 @@ } }; +static GLES2_Shader GLES2_VertexShader_Geometry = { + 1, + { + &GLES2_VertexSrc_Geometry + } +}; + static GLES2_Shader GLES2_FragmentShader_None_SolidSrc = { #if GLES2_INCLUDE_NVIDIA_SHADERS 2, @@ -702,6 +744,8 @@ { case GLES2_SHADER_VERTEX_DEFAULT: return &GLES2_VertexShader_Default; + case GLES2_SHADER_VERTEX_GEOMETRY: + return &GLES2_VertexShader_Geometry; case GLES2_SHADER_FRAGMENT_SOLID_SRC: switch (blendMode) { diff -r c550cccb91fc -r b73a4afb8b71 src/render/opengles2/SDL_shaders_gles2.h --- a/src/render/opengles2/SDL_shaders_gles2.h lun feb 25 16:22:34 2013 -0300 +++ b/src/render/opengles2/SDL_shaders_gles2.h mar feb 26 12:08:12 2013 -0300 @@ -42,6 +42,7 @@ typedef enum { GLES2_SHADER_VERTEX_DEFAULT, + GLES2_SHADER_VERTEX_GEOMETRY, GLES2_SHADER_FRAGMENT_SOLID_SRC, GLES2_SHADER_FRAGMENT_TEXTURE_ABGR_SRC, GLES2_SHADER_FRAGMENT_TEXTURE_ARGB_SRC,