Browse files

GLVideoDriver: GLSLProgram class to manage programs, Shader class rem…

…oved, changes in shaders, DrawEllipse
  • Loading branch information...
1 parent f07c489 commit feb31b23d0f7f494e0143a3792097d343ec9f2f3 @BehoIder BehoIder committed with lynxlynxlynx Jan 18, 2014
View
2 gemrb/plugins/SDLVideo/GLPaletteManager.cpp
@@ -49,7 +49,9 @@ GLuint GLPaletteManager::CreatePaletteTexture(Palette* palette, unsigned int col
if(i == colorKey) colors[i].a = 0;
}
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+#ifdef USE_GL
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+#endif
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 256, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*) colors);
delete[] colors;
palette->acquire();
View
243 gemrb/plugins/SDLVideo/GLSLProgram.cpp
@@ -0,0 +1,243 @@
+#include <cstdio>
+#include <cstring>
+
+#include "GLSLProgram.h"
+
+using namespace GemRB;
+
+char GLSLProgram::errMessage[512];
+
+GLSLProgram* GLSLProgram::Create(const char* vertexSource, const char* fragmentSource)
+{
+ GLSLProgram* program = new GLSLProgram();
+ if (!program->buildProgram(vertexSource, fragmentSource))
+ {
+ delete program;
+ return NULL;
+ }
+ return program;
+}
+
+
+GLuint GLSLProgram::buildShader(GLenum type, const char* source)
+{
+ GLuint id = glCreateShader(type);
+ glShaderSource(id, 1, &source, 0);
+ glCompileShader(id);
+ GLint result = GL_FALSE;
+ glGetShaderiv(id, GL_COMPILE_STATUS, &result);
+ if (result != GL_TRUE)
+ {
+ glGetShaderInfoLog(id, sizeof(GLSLProgram::errMessage), 0, GLSLProgram::errMessage);
+ GLSLProgram::errMessage[strlen(GLSLProgram::errMessage)]='\0';
+ }
+ return id;
+}
+
+bool GLSLProgram::buildProgram(const char* vertexSource, const char* fragmentSource)
+{
+ program = 0;
+ program = glCreateProgram();
+ if (program == 0)
+ {
+ strcpy(GLSLProgram::errMessage, "GLSLProgram error: glCreateProgram failed\0");
+ return false;
+ }
+
+ GLuint vertexId = buildShader(GL_VERTEX_SHADER, vertexSource);
+ if (vertexId == 0) return false;
+ GLuint fragmentId = buildShader(GL_FRAGMENT_SHADER, fragmentSource);
+ if (fragmentId == 0) return false;
+
+ glAttachShader(program, vertexId);
+ glAttachShader(program, fragmentId);
+
+ glLinkProgram(program);
+ GLint result = GL_FALSE;
+ glGetProgramiv(program, GL_LINK_STATUS, &result);
+ if (result != GL_TRUE)
+ {
+ glGetProgramInfoLog(program, sizeof(GLSLProgram::errMessage), 0, GLSLProgram::errMessage);
+ GLSLProgram::errMessage[strlen(GLSLProgram::errMessage)]='\0';
+ glDeleteProgram(program);
+ program = 0;
+ }
+ glDeleteShader(vertexId);
+ glDeleteShader(fragmentId);
+
+ return program != 0;
+}
+
+GLint GLSLProgram::getUniformLocation(const char* uniformName)
+{
+ if (uniforms.find(uniformName) == uniforms.end())
+ {
+ strcpy(GLSLProgram::errMessage, "GLSLProgram error: invalid uniform location\0");
+ return -1;
+ }
+ return uniforms.at(uniformName);
+}
+
+void GLSLProgram::Release()
+{
+ if (program != 0) glDeleteProgram(program);
+ delete this;
+}
+
+void GLSLProgram::GetLastError(char* msg , unsigned int msgSize)
+{
+ strncpy(msg, GLSLProgram::errMessage, msgSize);
+}
+
+bool GLSLProgram::StoreUniformLocation(const char* uniformName)
+{
+ if (uniforms.find(uniformName) == uniforms.end())
+ {
+ GLint location = glGetUniformLocation(program, uniformName);
+ if (location == -1)
+ {
+ strcpy(GLSLProgram::errMessage, "GLSLProgram error: invalid uniform location\0");
+ return false;
+ }
+ uniforms[uniformName] = location;
+ return true;
+ }
+ else
+ {
+ strcpy(GLSLProgram::errMessage, "GLSLProgram error: uniform already stored\0");
+ return false;
+ }
+}
+
+bool GLSLProgram::SetUniformValue(const char* uniformName, const unsigned char size, GLsizei count, const GLfloat* value)
+{
+ GLint location = getUniformLocation(uniformName);
+ if (location == -1) return false;
+ switch(size)
+ {
+ case 1:
+ glUniform1fv(location, count, value);
+ return true;
+ case 2:
+ glUniform2fv(location, count, value);
+ return true;
+ case 3:
+ glUniform3fv(location, count, value);
+ return true;
+ case 4:
+ glUniform4fv(location, count, value);
+ return true;
+ default:
+ strcpy(GLSLProgram::errMessage, "GLSLProgram error: invalid uniform size\0");
+ return false;
+ }
+}
+
+bool GLSLProgram::SetUniformValue(const char* uniformName, const unsigned char size, GLsizei count, const GLint* value)
+{
+ GLint location = getUniformLocation(uniformName);
+ if (location == -1) return false;
+ switch(size)
+ {
+ case 1:
+ glUniform1iv(location, count, value);
+ return true;
+ case 2:
+ glUniform2iv(location, count, value);
+ return true;
+ case 3:
+ glUniform3iv(location, count, value);
+ return true;
+ case 4:
+ glUniform4iv(location, count, value);
+ return true;
+ default:
+ strcpy(GLSLProgram::errMessage, "GLSLProgram error: invalid uniform size\0");
+ return false;
+ }
+}
+
+bool GLSLProgram::SetUniformMatrixValue(const char* uniformName, const unsigned char size, GLsizei count, GLboolean transpose, const GLfloat* value)
+{
+ GLint location = getUniformLocation(uniformName);
+ if (location == -1) return false;
+ switch(size)
+ {
+ case 2:
+ glUniformMatrix2fv(location, count, transpose, value);
+ return true;
+ case 3:
+ glUniformMatrix3fv(location, count, transpose, value);
+ return true;
+ case 4:
+ glUniformMatrix4fv(location, count, transpose, value);
+ return true;
+ default:
+ strcpy(GLSLProgram::errMessage, "GLSLProgram error: invalid uniform size\0");
+ return false;
+ }
+}
+
+bool GLSLProgram::SetUniformValue(const char* uniformName, const unsigned char size, GLfloat value1, GLfloat value2, GLfloat value3, GLfloat value4)
+{
+ GLint location = getUniformLocation(uniformName);
+ if (location == -1) return false;
+ GLint loc;
+ switch(size)
+ {
+ case 1:
+ glUniform1f(location, value1);
+ return true;
+ case 2:
+ glUniform2f(location, value1, value2);
+ return true;
+ case 3:
+ glUniform3f(location, value1, value2, value3);
+ return true;
+ case 4:
+ glUniform4f(location, value1, value2, value3, value4);
+ return true;
+ default:
+ strcpy(GLSLProgram::errMessage, "GLSLProgram error: invalid uniform size\0");
+ return false;
+ }
+}
+
+bool GLSLProgram::SetUniformValue(const char* uniformName, const unsigned char size, GLint value1, GLint value2, GLint value3, GLint value4)
+{
+ GLint location = getUniformLocation(uniformName);
+ if (location == -1) return false;
+ switch(size)
+ {
+ case 1:
+ glUniform1i(location, value1);
+ return true;
+ case 2:
+ glUniform2i(location, value1, value2);
+ return true;
+ case 3:
+ glUniform3i(location, value1, value2, value3);
+ return true;
+ case 4:
+ glUniform4i(location, value1, value2, value3, value4);
+ return true;
+ default:
+ strcpy(GLSLProgram::errMessage, "GLSLProgram error: invalid uniform size\0");
+ return false;
+ }
+}
+
+void GLSLProgram::Use()
+{
+ glUseProgram(program);
+}
+
+void GLSLProgram::UnUse()
+{
+ glUseProgram(0);
+}
+
+GLint GLSLProgram::GetAttribLocation(const char* attribName)
+{
+ return glGetAttribLocation(program, attribName);
+}
View
43 gemrb/plugins/SDLVideo/GLSLProgram.h
@@ -0,0 +1,43 @@
+#ifndef GLSLPROGRAM_H
+#define GLSLPROGRAM_H
+
+#ifdef USE_GL
+#include <GL/glew.h>
+#else
+#include <GLES2/GL2.h>
+#include <GLES2/GL2ext.h>
+#endif
+#include <map>
+
+namespace GemRB
+{
+ class GLSLProgram
+ {
+ public:
+ static GLSLProgram* Create(const char* vertexSource, const char* fragmentSource);
+ static void GetLastError(char* msg , unsigned int msgSize);
+
+ void Release();
+ void Use();
+ void UnUse();
+ bool StoreUniformLocation(const char* uniformName);
+ bool SetUniformValue(const char* uniformName, const unsigned char size, GLfloat value1, GLfloat value2 = 0.0f, GLfloat value3 = 0.0f, GLfloat value4 = 0.0f);
+ bool SetUniformValue(const char* uniformName, const unsigned char size, GLint value1, GLint value2 = 0, GLint value3 = 0, GLint value4 = 0);
+ bool SetUniformValue(const char* uniformName, const unsigned char size, GLsizei count, const GLfloat* value);
+ bool SetUniformValue(const char* uniformName, const unsigned char size, GLsizei count, const GLint* value);
+ bool SetUniformMatrixValue(const char* uniformName, const unsigned char size, GLsizei count, GLboolean transpose, const GLfloat* value);
+ GLint GetAttribLocation(const char* attribName);
+ private:
+ static char errMessage[512];
+
+ GLuint program;
+ std::map<const char*, GLint> uniforms;
+ bool buildProgram(const char* vertexSource, const char* fragmentSource);
+ GLuint buildShader(GLenum type, const char* source);
+ GLint getUniformLocation(const char* uniformName);
+ GLSLProgram(){}
+ ~GLSLProgram(){}
+ };
+};
+
+#endif
View
6 gemrb/plugins/SDLVideo/GLTextureSprite2D.cpp
@@ -148,14 +148,18 @@ void GLTextureSprite2D::createGlTexture()
buffer[i] = r | (g << 8) | (b << 16) | (a << 24);
}
glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
+#ifdef USE_GL
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+#endif
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, Width, Height, 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*) buffer);
delete[] buffer;
}
else if(Bpp == 8) // indexed
{
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+#ifdef USE_GL
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+#endif
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, Width, Height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, (GLvoid*) pixels);
}
}
@@ -181,7 +185,9 @@ void GLTextureSprite2D::createGLMaskTexture()
else mask[i] = 0x00;
}
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+#ifdef USE_GL
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+#endif
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, Width, Height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, (GLvoid*) mask);
delete[] mask;
}
View
356 gemrb/plugins/SDLVideo/SDL20GLVideo.cpp
@@ -17,35 +17,32 @@
#include "Game.h" // for GetGlobalTint
#include "GLTextureSprite2D.h"
#include "GLPaletteManager.h"
-#include "Shader.h"
+#include "GLSLProgram.h"
#include "Matrix.h"
using namespace GemRB;
const char* vertexRect=
-"uniform mat4 u_matrix;\n"
"attribute vec2 a_position;\n"
-"attribute vec4 a_color;\n"
-"varying vec4 v_color;\n"
+"uniform mat4 u_matrix;\n"
"void main()\n"
"{\n"
" gl_Position = u_matrix * vec4(a_position, 0.0, 1.0);\n"
-" v_color = a_color;\n"
"}\n";
const char* fragmentRect =
-"varying vec4 v_color; \n"
+"uniform vec4 u_color; \n"
"void main() \n"
"{\n"
-" gl_FragColor = v_color;\n"
+" gl_FragColor = u_color;\n"
"}\n";
const char* vertex =
-"uniform mat4 u_matrix;\n"
"attribute vec2 a_position;\n"
"attribute vec2 a_texCoord;\n"
"attribute float a_alphaModifier;\n"
"attribute vec4 a_tint;\n"
+"uniform mat4 u_matrix;\n"
"varying vec2 v_texCoord;\n"
"varying float v_alphaModifier;\n"
"varying vec4 v_tint;\n"
@@ -131,13 +128,56 @@ const char* fragmentPalSepia =
" gl_FragColor = vec4(sepia, color.a * alphaModifier);\n"
"}\n";
+
+const char* vertexEllipse=
+"attribute vec2 a_position;\n"
+"uniform mat4 u_matrix;\n"
+"attribute vec2 a_texCoord;\n"
+"varying vec2 v_texCoord;\n"
+"void main()\n"
+"{\n"
+" gl_Position = u_matrix * vec4(a_position, 0.0, 1.0);\n"
+" v_texCoord = a_texCoord;\n"
+"}\n";
+
+const char* fragmentEllipse =
+#ifndef USE_GL
+"precision highp float; \n"
+#endif
+"uniform float u_radiusX;\n"
+"uniform float u_radiusY;\n"
+"uniform float u_thickness;\n"
+"uniform float u_support;\n"
+"uniform vec4 u_color;\n"
+"varying vec2 v_texCoord;\n"
+"void main()\n"
+"{\n"
+" float x = v_texCoord.x;\n"
+" float y = v_texCoord.y;\n"
+
+" float x_mid = u_radiusX + u_thickness/2.0;\n"
+" float y_mid = u_radiusY + u_thickness/2.0;\n"
+" float distance1 = sqrt(x*x/(x_mid*x_mid) + y*y/(y_mid*y_mid));\n"
+" float width1 = fwidth(distance1) * u_support/1.25;\n"
+" float alpha1 = smoothstep(1.0 - width1, 1.0 + width1, distance1);\n"
+
+" x_mid = u_radiusX - u_thickness/2.0;\n"
+" y_mid = u_radiusY - u_thickness/2.0;\n"
+" float distance2 = sqrt(x*x/(x_mid*x_mid) + y*y/(y_mid*y_mid));\n"
+" float width2 = fwidth(distance2) * u_support/1.25;\n"
+" float alpha2 = smoothstep(1.0 + width2, 1.0 - width2, distance2);\n"
+
+" gl_FragColor = vec4(u_color.rgb, (1.0 - max(alpha1, alpha2))*u_color.a);\n"
+"}\n";
+
GLVideoDriver::~GLVideoDriver()
{
- glDeleteProgram(program32);
- glDeleteProgram(programPal);
- glDeleteProgram(programPalGrayed);
- glDeleteProgram(programPalSepia);
- glDeleteProgram(programRect);
+ program32->Release();
+ programPal->Release();
+ programPalGrayed->Release();
+ programPalSepia->Release();
+ programRect->Release();
+ programEllipse->Release();
delete paletteManager;
SDL_GL_DeleteContext(context);
}
@@ -242,93 +282,111 @@ int GLVideoDriver::CreateDisplay(int w, int h, int bpp, bool fs, const char* tit
return GEM_OK;
}
-void GLVideoDriver::useProgram(GLuint program)
+void GLVideoDriver::useProgram(GLSLProgram* program)
{
- if(lastUsedProgram == program) return;
- glUseProgram(program);
+ if (lastUsedProgram == program) return;
+ program->Use();
lastUsedProgram = program;
}
bool GLVideoDriver::createPrograms()
{
- ShaderOperationResult* result = Shader::BuildProgram(vertex, fragment);
- if(result->Id == 0)
- {
- Log(ERROR, "SDL 2 GL Driver", "can't build shader program:%s", result->Message);
- delete result;
- return false;
- }
- program32 = result->Id;
- delete result;
- glUseProgram(program32);
- glUniform1i(glGetUniformLocation(program32, "s_texture"), 0);
+ char msg[512];
float matrix[16];
Matrix::SetIdentityM(matrix);
- glUniformMatrix4fv(glGetUniformLocation(program32, "u_matrix"), 1, GL_FALSE, matrix);
- glUseProgram(0);
- result = Shader::BuildProgram(vertex, fragmentPal);
- if(result->Id == 0)
+ program32 = GLSLProgram::Create(vertex, fragment);
+ if (!program32)
+ {
+ GLSLProgram::GetLastError(msg, sizeof(msg));
+ Log(ERROR, "SDL 2 GL Driver", "can't build shader program:%s", msg);
+ return false;
+ }
+ program32->Use();
+ program32->StoreUniformLocation("s_texture");
+ program32->SetUniformValue("s_texture", 1, 0);
+ program32->StoreUniformLocation("u_matrix");
+ program32->SetUniformMatrixValue("u_matrix", 4, 1, GL_FALSE, matrix);
+
+ programPal = GLSLProgram::Create(vertex, fragmentPal);
+ if (!programPal)
{
- Log(ERROR, "SDL 2 GL Driver", "can't build shader program:%s", result->Message);
- delete result;
+ GLSLProgram::GetLastError(msg, sizeof(msg));
+ Log(ERROR, "SDL 2 GL Driver", "can't build shader program:%s", msg);
return false;
}
- programPal = result->Id;
- delete result;
- glUseProgram(programPal);
- glUniform1i(glGetUniformLocation(programPal, "s_texture"), 0);
- glUniform1i(glGetUniformLocation(programPal, "s_palette"), 1);
- glUniform1i(glGetUniformLocation(programPal, "s_mask"), 2);
- glUniformMatrix4fv(glGetUniformLocation(programPal, "u_matrix"), 1, GL_FALSE, matrix);
- glUseProgram(0);
-
- result = Shader::BuildProgram(vertex, fragmentPalGrayed);
- if(result->Id == 0)
+ programPal->Use();
+ programPal->StoreUniformLocation("s_texture");
+ programPal->StoreUniformLocation("s_palette");
+ programPal->StoreUniformLocation("s_mask");
+ programPal->SetUniformValue("s_texture", 1, 0);
+ programPal->SetUniformValue("s_palette", 1, 1);
+ programPal->SetUniformValue("s_mask", 1, 2);
+ programPal->StoreUniformLocation("u_matrix");
+ programPal->SetUniformMatrixValue("u_matrix", 4, 1, GL_FALSE, matrix);
+
+ programPalGrayed = GLSLProgram::Create(vertex, fragmentPalGrayed);
+ if (!programPalGrayed)
{
- Log(ERROR, "SDL 2 GL Driver", "can't build shader program:%s", result->Message);
- delete result;
+ GLSLProgram::GetLastError(msg, sizeof(msg));
+ Log(ERROR, "SDL 2 GL Driver", "can't build shader program:%s", msg);
return false;
}
- programPalGrayed = result->Id;
- delete result;
- glUseProgram(programPalGrayed);
- glUniform1i(glGetUniformLocation(programPalGrayed, "s_texture"), 0);
- glUniform1i(glGetUniformLocation(programPalGrayed, "s_palette"), 1);
- glUniform1i(glGetUniformLocation(programPalGrayed, "s_mask"), 2);
- glUniformMatrix4fv(glGetUniformLocation(programPalGrayed, "u_matrix"), 1, GL_FALSE, matrix);
- glUseProgram(0);
-
- result = Shader::BuildProgram(vertex, fragmentPalSepia);
- if(result->Id == 0)
+ programPalGrayed->Use();
+ programPalGrayed->StoreUniformLocation("s_texture");
+ programPalGrayed->StoreUniformLocation("s_palette");
+ programPalGrayed->StoreUniformLocation("s_mask");
+ programPal->SetUniformValue("s_texture", 1, 0);
+ programPal->SetUniformValue("s_palette", 1, 1);
+ programPal->SetUniformValue("s_mask", 1, 2);
+ programPalGrayed->StoreUniformLocation("u_matrix");
+ programPalGrayed->SetUniformMatrixValue("u_matrix", 4, 1, GL_FALSE, matrix);
+
+ programPalSepia = GLSLProgram::Create(vertex, fragmentPalSepia);
+ if (!programPalSepia)
{
- Log(ERROR, "SDL 2 GL Driver", "can't build shader program:%s", result->Message);
- delete result;
+ GLSLProgram::GetLastError(msg, sizeof(msg));
+ Log(ERROR, "SDL 2 GL Driver", "can't build shader program:%s", msg);
return false;
}
- programPalSepia = result->Id;
- delete result;
- glUseProgram(programPalSepia);
- glUniform1i(glGetUniformLocation(programPalSepia, "s_texture"), 0);
- glUniform1i(glGetUniformLocation(programPalSepia, "s_palette"), 1);
- glUniform1i(glGetUniformLocation(programPalSepia, "s_mask"), 2);
- glUniformMatrix4fv(glGetUniformLocation(programPalSepia, "u_matrix"), 1, GL_FALSE, matrix);
- glUseProgram(0);
+ programPalSepia->Use();
+ programPalSepia->StoreUniformLocation("s_texture");
+ programPalSepia->StoreUniformLocation("s_palette");
+ programPalSepia->StoreUniformLocation("s_mask");
+ programPal->SetUniformValue("s_texture", 1, 0);
+ programPal->SetUniformValue("s_palette", 1, 1);
+ programPal->SetUniformValue("s_mask", 1, 2);;
+ programPalSepia->StoreUniformLocation("u_matrix");
+ programPalSepia->SetUniformMatrixValue("u_matrix", 4, 1, GL_FALSE, matrix);
- result = Shader::BuildProgram(vertexRect, fragmentRect);
- if(result->Id == 0)
+ programEllipse = GLSLProgram::Create(vertexEllipse, fragmentEllipse);
+ if (!programEllipse)
{
- Log(ERROR, "SDL 2 GL Driver", "can't build shader program:%s", result->Message);
- delete result;
+ GLSLProgram::GetLastError(msg, sizeof(msg));
+ Log(ERROR, "SDL 2 GL Driver", "can't build shader program:%s", msg);
return false;
}
- programRect = result->Id;
- delete result;
- glUseProgram(programRect);
- glUniformMatrix4fv(glGetUniformLocation(programRect, "u_matrix"), 1, GL_FALSE, matrix);
- glUseProgram(0);
+ programEllipse->Use();
+ programEllipse->StoreUniformLocation("u_matrix");
+ programEllipse->SetUniformMatrixValue("u_matrix", 4, 1, GL_FALSE, matrix);
+ programEllipse->StoreUniformLocation("u_radiusX");
+ programEllipse->StoreUniformLocation("u_radiusY");
+ programEllipse->StoreUniformLocation("u_thickness");
+ programEllipse->StoreUniformLocation("u_support");
+ programEllipse->StoreUniformLocation("u_color");
+
+ programRect = GLSLProgram::Create(vertexRect, fragmentRect);
+ if (!programRect)
+ {
+ GLSLProgram::GetLastError(msg, sizeof(msg));
+ Log(ERROR, "SDL 2 GL Driver", "can't build shader program:%s", msg);
+ return false;
+ }
+ programRect->Use();
+ programRect->StoreUniformLocation("u_matrix");
+ programRect->SetUniformMatrixValue("u_matrix", 4, 1, GL_FALSE, matrix);
- lastUsedProgram = 0;
+ lastUsedProgram = NULL;
return true;
}
@@ -424,7 +482,7 @@ void GLVideoDriver::blitSprite(GLTextureSprite2D* spr, int x, int y, const Regio
};
// shader program selection
- GLuint program;
+ GLSLProgram* program;
GLuint palTexture;
if(spr->IsPaletted())
{
@@ -467,10 +525,10 @@ void GLVideoDriver::blitSprite(GLTextureSprite2D* spr, int x, int y, const Regio
glBindTexture(GL_TEXTURE_2D, 0);
}
- GLint a_position = glGetAttribLocation(program, "a_position");
- GLint a_texCoord = glGetAttribLocation(program, "a_texCoord");
- GLint a_alphaModifier = glGetAttribLocation(program, "a_alphaModifier");
- GLint a_tint = glGetAttribLocation(program, "a_tint");
+ GLint a_position = program->GetAttribLocation("a_position");
+ GLint a_texCoord = program->GetAttribLocation("a_texCoord");
+ GLint a_alphaModifier = program->GetAttribLocation("a_alphaModifier");
+ GLint a_tint = program->GetAttribLocation("a_tint");
GLuint buffer;
glGenBuffers(1, &buffer);
@@ -501,6 +559,86 @@ void GLVideoDriver::blitSprite(GLTextureSprite2D* spr, int x, int y, const Regio
spritesPerFrame++;
}
+void GLVideoDriver::drawColoredRect(const Region& rgn, const Color& color)
+{
+ if (SDL_ALPHA_TRANSPARENT == color.a) return;
+
+ glScissor(rgn.x, height - rgn.y - rgn.h, rgn.w, rgn.h);
+ if (SDL_ALPHA_OPAQUE == color.a) // possible to work faster than shader but a lot... may be disable in future
+ {
+ glClearColor(color.r/255, color.g/255, color.b/255, color.a/255);
+ glClear(GL_COLOR_BUFFER_BIT);
+ }
+ else
+ {
+ useProgram(programRect);
+ glViewport(rgn.x, height - rgn.y - rgn.h, rgn.w, rgn.h);
+ GLfloat data[] =
+ {
+ -1.0f, 1.0f,
+ 1.0f, 1.0f,
+ -1.0f, -1.0f,
+ 1.0f, -1.0f
+ };
+ GLuint buffer;
+ glGenBuffers(1, &buffer);
+ glBindBuffer(GL_ARRAY_BUFFER, buffer);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
+
+ GLint a_position = programRect->GetAttribLocation("a_position");
+ glVertexAttribPointer(a_position, VERTEX_SIZE, GL_FLOAT, GL_FALSE, 0, 0);
+ programRect->SetUniformValue("u_color", 4, (GLfloat)color.r/255, (GLfloat)color.g/255, (GLfloat)color.b/255, (GLfloat)color.a/255);
+
+ glEnableVertexAttribArray(a_position);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ glDisableVertexAttribArray(a_position);
+
+ glDeleteBuffers(1, &buffer);
+ }
+}
+
+void GLVideoDriver::drawEllipse(int cx /*center*/, int cy /*center*/, unsigned short xr, unsigned short yr, float thickness, const Color& color)
+{
+ const float support = 0.75;
+ useProgram(programEllipse);
+ float alpha = min(thickness, 1.0);
+ thickness = max(thickness, 1.0);
+ float dx = (int)ceilf(xr + thickness/2.0 + 2.5*support);
+ float dy = (int)ceilf(yr + thickness/2.0 + 2.5*support);
+ glViewport(cx - dx, height - cy - dy, dx*2, dy*2);
+ GLfloat data[] =
+ {
+ -1.0f, 1.0f, -1.0f, 1.0f,
+ 1.0f, 1.0f, 1.0f, 1.0f,
+ -1.0f,-1.0f, -1.0f,-1.0f,
+ 1.0f,-1.0f, 1.0f,-1.0f
+ };
+ GLuint buffer;
+ glGenBuffers(1, &buffer);
+ glBindBuffer(GL_ARRAY_BUFFER, buffer);
+ glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
+
+ GLint a_position = programEllipse->GetAttribLocation("a_position");
+ GLint a_texCoord = programEllipse->GetAttribLocation("a_texCoord");
+
+ programEllipse->SetUniformValue("u_radiusX", 1, (GLfloat)xr/dx);
+ programEllipse->SetUniformValue("u_radiusY", 1, (GLfloat)yr/dy);
+ programEllipse->SetUniformValue("u_thickness", 1, (GLfloat)thickness/(dx + dy));
+ programEllipse->SetUniformValue("u_support", 1, (GLfloat)support);
+ programEllipse->SetUniformValue("u_color", 4, (GLfloat)color.r/255, (GLfloat)color.g/255, (GLfloat)color.b/255, (GLfloat)color.a/255);
+
+ glVertexAttribPointer(a_position, VERTEX_SIZE, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*(VERTEX_SIZE + TEX_SIZE), 0);
+ glVertexAttribPointer(a_texCoord, TEX_SIZE, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*(VERTEX_SIZE + TEX_SIZE), BUFFER_OFFSET(sizeof(GLfloat)*VERTEX_SIZE));
+
+ glEnableVertexAttribArray(a_position);
+ glEnableVertexAttribArray(a_texCoord);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
+ glDisableVertexAttribArray(a_texCoord);
+ glDisableVertexAttribArray(a_position);
+
+ glDeleteBuffers(1, &buffer);
+}
+
void GLVideoDriver::BlitTile(const Sprite2D* spr, const Sprite2D* mask, int x, int y, const Region* clip, unsigned int flags)
{
int tx = x - spr->XPos;
@@ -572,7 +710,9 @@ void GLVideoDriver::BlitGameSprite(const Sprite2D* spr, int x, int y, unsigned i
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+#ifdef USE_GL
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+#endif
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, glSprite->Width, glSprite->Height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, (GLvoid*) data);
delete[] data;
flags |= BLIT_EXTERNAL_MASK;
@@ -639,50 +779,24 @@ void GLVideoDriver::DrawVLine(short x, short y1, short y2, const Color& color, b
return drawColoredRect(rgn, color);
}
-void GLVideoDriver::drawColoredRect(const Region& rgn, const Color& color)
+void GLVideoDriver::DrawEllipse(short cx, short cy, unsigned short xr, unsigned short yr, const Color& color, bool clipped)
{
- if (SDL_ALPHA_TRANSPARENT == color.a) return;
-
- glScissor(rgn.x, height - rgn.y - rgn.h, rgn.w, rgn.h);
- if (SDL_ALPHA_OPAQUE == color.a) // possible to work faster than shader but a lot... may be disable in future
+ if (clipped)
{
- glClearColor(color.r/255, color.g/255, color.b/255, color.a/255);
- glClear(GL_COLOR_BUFFER_BIT);
- }
- else
+ cx += xCorr;
+ cy += yCorr;
+ if ((cx >= xCorr + Viewport.w || cy >= yCorr + Viewport.h) || (cx < xCorr || cy < yCorr))
+ return;
+ }
+ else
{
- useProgram(programRect);
- glViewport(rgn.x, height - rgn.y - rgn.h, rgn.w, rgn.h);
- GLfloat data[] =
- {
- -1.0f, 1.0f, (GLfloat)color.r/255, (GLfloat)color.g/255, (GLfloat)color.b/255, (GLfloat)color.a/255,
- 1.0f, 1.0f, (GLfloat)color.r/255, (GLfloat)color.g/255, (GLfloat)color.b/255, (GLfloat)color.a/255,
- -1.0f, -1.0f, (GLfloat)color.r/255, (GLfloat)color.g/255, (GLfloat)color.b/255, (GLfloat)color.a/255,
- 1.0f, -1.0f, (GLfloat)color.r/255, (GLfloat)color.g/255, (GLfloat)color.b/255, (GLfloat)color.a/255
- };
- GLuint buffer;
- glGenBuffers(1, &buffer);
- glBindBuffer(GL_ARRAY_BUFFER, buffer);
- glBufferData(GL_ARRAY_BUFFER, sizeof(data), data, GL_STATIC_DRAW);
-
- GLint a_position = glGetAttribLocation(programRect, "a_position");
- GLint a_color = glGetAttribLocation(programRect, "a_color");
-
- glVertexAttribPointer(a_position, VERTEX_SIZE, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*6, 0);
- glVertexAttribPointer(a_color, COLOR_SIZE, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*6, BUFFER_OFFSET(sizeof(GLfloat)*VERTEX_SIZE));
-
- glEnableVertexAttribArray(a_position);
- glEnableVertexAttribArray(a_color);
-
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
-
- glDisableVertexAttribArray(a_color);
- glDisableVertexAttribArray(a_position);
-
- glDeleteBuffers(1, &buffer);
+ if ((cx >= disp->w || cy >= disp->h) || (cx < 0 || cy < 0))
+ return;
}
+ return drawEllipse(cx, cy, xr, yr, 3, color);
}
+
int GLVideoDriver::SwapBuffers()
{
int val = SDLVideoDriver::SwapBuffers();
@@ -708,7 +822,9 @@ Sprite2D* GLVideoDriver::GetScreenshot(Region r)
Uint32* glPixels = (Uint32*)malloc( w * h * 4 );
Uint32* pixels = (Uint32*)malloc( w * h * 4 );
+#ifdef USE_GL
glReadBuffer(GL_BACK);
+#endif
glReadPixels(r.x, r.y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, glPixels);
// flip pixels vertical
Uint32* pixelDstPointer = pixels;
View
18 gemrb/plugins/SDLVideo/SDL20GLVideo.h
@@ -15,27 +15,30 @@ namespace GemRB
{
class GLTextureSprite2D;
class GLPaletteManager;
+ class GLSLProgram;
class GLVideoDriver : public SDL20VideoDriver
{
private:
SDL_GLContext context; // opengl context
// Shader programs
- GLuint program32; // shader program for 32bpp sprites
- GLuint programPal; // shader program for paletted sprites
- GLuint programPalGrayed; // shader program for paletted sprites with grayscale effect
- GLuint programPalSepia; // shader program for paletted sprites with sepia effect
- GLuint programRect; // shader program for drawing rects and lines
+ GLSLProgram* program32; // shader program for 32bpp sprites
+ GLSLProgram* programPal; // shader program for paletted sprites
+ GLSLProgram* programPalGrayed; // shader program for paletted sprites with grayscale effect
+ GLSLProgram* programPalSepia; // shader program for paletted sprites with sepia effect
+ GLSLProgram* programRect; // shader program for drawing rects and lines
+ GLSLProgram* programEllipse; // shader program for drawing ellipses and circles
Uint32 spritesPerFrame; // sprites counter
- GLuint lastUsedProgram; // stores last used program to prevent switching if possible (switching may cause performance lack)
+ GLSLProgram* lastUsedProgram; // stores last used program to prevent switching if possible (switching may cause performance lack)
GLPaletteManager* paletteManager; // palette manager instance
- void useProgram(GLuint program); // use this instead glUseProgram
+ void useProgram(GLSLProgram* program); // use this instead glUseProgram
bool createPrograms();
void blitSprite(GLTextureSprite2D* spr, int x, int y, const Region* clip, Palette* attachedPal = NULL, unsigned int flags = 0, const Color* tint = NULL, GLTextureSprite2D* mask = NULL);
void drawColoredRect(const Region& rgn, const Color& color);
+ void drawEllipse(int cx, int cy, unsigned short xr, unsigned short yr, float thickness, const Color& color);
public:
~GLVideoDriver();
@@ -51,6 +54,7 @@ namespace GemRB
void DrawRect(const Region& rgn, const Color& color, bool fill = true, bool clipped = false);
void DrawHLine(short x1, short y, short x2, const Color& color, bool clipped = false);
void DrawVLine(short x, short y1, short y2, const Color& color, bool clipped = false);
+ void DrawEllipse(short cx, short cy, unsigned short xr, unsigned short yr, const Color& color, bool clipped = true);
void DestroyMovieScreen();
Sprite2D* GetScreenshot(Region r);
};
View
2 gemrb/plugins/SDLVideo/SDLVideo.h
@@ -111,7 +111,7 @@ class SDLVideoDriver : public Video {
void DrawEllipseSegment(short cx, short cy, unsigned short xr, unsigned short yr, const Color& color,
double anglefrom, double angleto, bool drawlines = true, bool clipped = true);
/** This functions Draws an Ellipse */
- void DrawEllipse(short cx, short cy, unsigned short xr, unsigned short yr,
+ virtual void DrawEllipse(short cx, short cy, unsigned short xr, unsigned short yr,
const Color& color, bool clipped = true);
/** This function Draws a Polygon on the Screen */
void DrawPolyline(Gem_Polygon* poly, const Color& color, bool fill = false);
View
64 gemrb/plugins/SDLVideo/Shader.cpp
@@ -1,64 +0,0 @@
-#ifdef USE_GL
-#include <GL/glew.h>
-#else
-#include <GLES2/GL2.h>
-#include <GLES2/GL2ext.h>
-#endif
-#include <cstdio>
-#include <cstring>
-
-#include "Shader.h"
-
-
-ShaderOperationResult* Shader::BuildShader(GLenum type, const char* source)
-{
- ShaderOperationResult* opResult = new ShaderOperationResult();
- GLuint id = glCreateShader(type);
- glShaderSource(id, 1, &source, 0);
- glCompileShader(id);
- opResult->Id = id;
- GLint result = GL_FALSE;
- glGetShaderiv(id, GL_COMPILE_STATUS, &result);
- if (result != GL_TRUE)
- {
- char tmp[2048];
- glGetShaderInfoLog(id, sizeof(tmp), 0, tmp);
- opResult->Id = 0;
- tmp[strlen(tmp)]='\0';
- opResult->Message = strdup(tmp);
- }
- return opResult;
-}
-
-ShaderOperationResult* Shader::BuildProgram(const char* vertexSource, const char* fragmentSource)
-{
- GLuint id = glCreateProgram();
-
- ShaderOperationResult* vertexShader = BuildShader(GL_VERTEX_SHADER, vertexSource);
- if (vertexShader->Id == 0) return vertexShader;
- ShaderOperationResult* fragmentShader = BuildShader(GL_FRAGMENT_SHADER, fragmentSource);
- if (fragmentShader->Id == 0) return fragmentShader;
-
- glAttachShader(id, vertexShader->Id);
- glAttachShader(id, fragmentShader->Id);
-
- ShaderOperationResult* opResult = new ShaderOperationResult();
- opResult->Id = id;
-
- glLinkProgram(id);
- GLint result = GL_FALSE;
- glGetProgramiv(id, GL_LINK_STATUS, &result);
- if (result != GL_TRUE)
- {
- char tmp[2048];
- opResult->Id = 0;
- glGetProgramInfoLog(id, sizeof(tmp), 0, tmp);
- tmp[strlen(tmp)]='\0';
- opResult->Message = strdup(tmp);
- }
-
- glDeleteShader(vertexShader->Id);
- glDeleteShader(fragmentShader->Id);
-
- return opResult;
-}
View
14 gemrb/plugins/SDLVideo/Shader.h
@@ -1,14 +0,0 @@
-
-class ShaderOperationResult
-{
-public:
- GLuint Id;
- char* Message;
-};
-
-class Shader
-{
-public:
- static ShaderOperationResult* BuildShader(GLenum type, const char* source);
- static ShaderOperationResult* BuildProgram(const char* vertexSource, const char* fragmentSource);
-};

0 comments on commit feb31b2

Please sign in to comment.