#include "obstack/obstackpp.hpp"
#define LIGHTMAP_DIV 5
+#ifdef GL_VERSION_ES_CM_1_0
+# define glOrtho glOrthof
+#endif
+
namespace
{
+
inline void intern_draw(float left, float top, float right, float bottom,
float uv_left, float uv_top,
float uv_right, float uv_bottom,
if(effect & VERTICAL_FLIP)
std::swap(uv_top, uv_bottom);
+
+ // unrotated blit
+ glBlendFunc(blend.sfactor, blend.dfactor);
+ glColor4f(color.red, color.green, color.blue, color.alpha * alpha);
- if (angle == 0.0f)
- { // unrotated blit
- glBlendFunc(blend.sfactor, blend.dfactor);
- glColor4f(color.red, color.green, color.blue, color.alpha * alpha);
- glBegin(GL_QUADS);
- glTexCoord2f(uv_left, uv_top);
- glVertex2f(left, top);
-
- glTexCoord2f(uv_right, uv_top);
- glVertex2f(right, top);
-
- glTexCoord2f(uv_right, uv_bottom);
- glVertex2f(right, bottom);
-
- glTexCoord2f(uv_left, uv_bottom);
- glVertex2f(left, bottom);
- glEnd();
- }
- else
- { // rotated blit
- float center_x = (left + right) / 2;
- float center_y = (top + bottom) / 2;
-
- float sa = sinf(angle/180.0f*M_PI);
- float ca = cosf(angle/180.0f*M_PI);
-
- left -= center_x;
- right -= center_x;
-
- top -= center_y;
- bottom -= center_y;
-
- glBlendFunc(blend.sfactor, blend.dfactor);
- glColor4f(color.red, color.green, color.blue, color.alpha * alpha);
- glBegin(GL_QUADS);
- glTexCoord2f(uv_left, uv_top);
- glVertex2f(left*ca - top*sa + center_x,
- left*sa + top*ca + center_y);
-
- glTexCoord2f(uv_right, uv_top);
- glVertex2f(right*ca - top*sa + center_x,
- right*sa + top*ca + center_y);
-
- glTexCoord2f(uv_right, uv_bottom);
- glVertex2f(right*ca - bottom*sa + center_x,
- right*sa + bottom*ca + center_y);
-
- glTexCoord2f(uv_left, uv_bottom);
- glVertex2f(left*ca - bottom*sa + center_x,
- left*sa + bottom*ca + center_y);
- glEnd();
- }
+ if (angle == 0.0f) {
+ float vertices[] = {
+ left, top,
+ right, top,
+ right, bottom,
+ left, bottom,
+ };
+ glVertexPointer(2, GL_FLOAT, 0, vertices);
+
+ float uvs[] = {
+ uv_left, uv_top,
+ uv_right, uv_top,
+ uv_right, uv_bottom,
+ uv_left, uv_bottom,
+ };
+ glTexCoordPointer(2, GL_FLOAT, 0, uvs);
+
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ } else {
+ // rotated blit
+ float center_x = (left + right) / 2;
+ float center_y = (top + bottom) / 2;
+
+ float sa = sinf(angle/180.0f*M_PI);
+ float ca = cosf(angle/180.0f*M_PI);
+
+ left -= center_x;
+ right -= center_x;
+
+ top -= center_y;
+ bottom -= center_y;
+
+ float vertices[] = {
+ left*ca - top*sa + center_x, left*sa + top*ca + center_y,
+ right*ca - top*sa + center_x, right*sa + top*ca + center_y,
+ right*ca - bottom*sa + center_x, right*sa + bottom*ca + center_y,
+ left*ca - bottom*sa + center_x, left*sa + bottom*ca + center_y
+ };
+ glVertexPointer(2, GL_FLOAT, 0, vertices);
+
+ float uvs[] = {
+ uv_left, uv_top,
+ uv_right, uv_top,
+ uv_right, uv_bottom,
+ uv_left, uv_bottom,
+ };
+ glTexCoordPointer(2, GL_FLOAT, 0, uvs);
+
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+ }
// FIXME: find a better way to restore the blend mode
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
+
}
namespace GL {
if(texture_manager != 0)
texture_manager->save_textures();
+#ifdef SDL_GL_SWAP_CONTROL
if(config->try_vsync) {
/* we want vsync for smooth scrolling */
SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, 1);
}
+#endif
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
- // Hu? 16bit rendering?
+ // FIXME: Hu? 16bit rendering?
SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 5);
SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 5);
SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 5);
int flags = SDL_OPENGL;
int width;
int height;
+
if(config->use_fullscreen)
{
flags |= SDL_FULLSCREEN;
}
else
{
- flags |= SDL_RESIZABLE;
+// flags |= SDL_RESIZABLE;
width = config->window_width;
height = config->window_height;
}
- int bpp = 0;
+ int bpp = 0;
SDL_Surface *screen = SDL_SetVideoMode(width, height, bpp, flags);
+
if(screen == 0) {
std::stringstream msg;
msg << "Couldn't set video mode (" << width << "x" << height
glDisable(GL_CULL_FACE);
glEnable(GL_TEXTURE_2D);
glEnable(GL_BLEND);
+ glEnableClientState(GL_VERTEX_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- glViewport(0, 0, screen->w, screen->h);
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
-
- // logical resolution here not real monitor resolution
- glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
-
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- glTranslatef(0, 0, 0);
-
- check_gl_error("Setting up view matrices");
-
-
+ // Init the projection matrix, viewport and stuff
+ apply_config();
+
if(texture_manager == 0)
texture_manager = new TextureManager();
else
uv_bottom,
0.0,
request.alpha,
- Color(1.0, 1.0, 1.0),
+ request.color,
Blend(),
request.drawing_effect);
}
const Color& bottom = gradientrequest->bottom;
glDisable(GL_TEXTURE_2D);
- glBegin(GL_QUADS);
- glColor4f(top.red, top.green, top.blue, top.alpha);
- glVertex2f(0, 0);
- glVertex2f(SCREEN_WIDTH, 0);
- glColor4f(bottom.red, bottom.green, bottom.blue, bottom.alpha);
- glVertex2f(SCREEN_WIDTH, SCREEN_HEIGHT);
- glVertex2f(0, SCREEN_HEIGHT);
- glEnd();
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glEnableClientState(GL_COLOR_ARRAY);
+
+ float vertices[] = {
+ 0, 0,
+ SCREEN_WIDTH, 0,
+ SCREEN_WIDTH, SCREEN_HEIGHT,
+ 0, SCREEN_HEIGHT
+ };
+ glVertexPointer(2, GL_FLOAT, 0, vertices);
+
+ float colors[] = {
+ top.red, top.green, top.blue, top.alpha,
+ top.red, top.green, top.blue, top.alpha,
+ bottom.red, bottom.green, bottom.blue, bottom.alpha,
+ bottom.red, bottom.green, bottom.blue, bottom.alpha,
+ };
+ glColorPointer(4, GL_FLOAT, 0, colors);
+
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+ glDisableClientState(GL_COLOR_ARRAY);
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
glEnable(GL_TEXTURE_2D);
glColor4f(1, 1, 1, 1);
}
const FillRectRequest* fillrectrequest
= (FillRectRequest*) request.request_data;
+ glDisable(GL_TEXTURE_2D);
+ glColor4f(fillrectrequest->color.red, fillrectrequest->color.green,
+ fillrectrequest->color.blue, fillrectrequest->color.alpha);
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+
if (fillrectrequest->radius != 0.0f)
{
// draw round rect
request.pos.x + fillrectrequest->size.x - radius,
request.pos.y + fillrectrequest->size.y - radius);
- glDisable(GL_TEXTURE_2D);
- glColor4f(fillrectrequest->color.red, fillrectrequest->color.green,
- fillrectrequest->color.blue, fillrectrequest->color.alpha);
-
int n = 8;
- glBegin(GL_QUAD_STRIP);
+ int p = 0;
+ float vertices[(n+1) * 4 * 2];
+
for(int i = 0; i <= n; ++i)
{
float x = sinf(i * (M_PI/2) / n) * radius;
float y = cosf(i * (M_PI/2) / n) * radius;
- glVertex2f(irect.get_left() - x, irect.get_top() - y);
- glVertex2f(irect.get_right() + x, irect.get_top() - y);
+ vertices[p++] = irect.get_left() - x;
+ vertices[p++] = irect.get_top() - y;
+
+ vertices[p++] = irect.get_right() + x;
+ vertices[p++] = irect.get_top() - y;
}
+
for(int i = 0; i <= n; ++i)
{
float x = cosf(i * (M_PI/2) / n) * radius;
float y = sinf(i * (M_PI/2) / n) * radius;
- glVertex2f(irect.get_left() - x, irect.get_bottom() + y);
- glVertex2f(irect.get_right() + x, irect.get_bottom() + y);
+ vertices[p++] = irect.get_left() - x;
+ vertices[p++] = irect.get_bottom() + y;
+
+ vertices[p++] = irect.get_right() + x;
+ vertices[p++] = irect.get_bottom() + y;
}
- glEnd();
- glEnable(GL_TEXTURE_2D);
- glColor4f(1, 1, 1, 1);
+
+ glVertexPointer(2, GL_FLOAT, 0, vertices);
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, sizeof(vertices)/sizeof(float)/2);
}
else
{
float w = fillrectrequest->size.x;
float h = fillrectrequest->size.y;
- glDisable(GL_TEXTURE_2D);
- glColor4f(fillrectrequest->color.red, fillrectrequest->color.green,
- fillrectrequest->color.blue, fillrectrequest->color.alpha);
-
- glBegin(GL_QUADS);
- glVertex2f(x, y);
- glVertex2f(x+w, y);
- glVertex2f(x+w, y+h);
- glVertex2f(x, y+h);
- glEnd();
- glEnable(GL_TEXTURE_2D);
- glColor4f(1, 1, 1, 1);
+ float vertices[] = {
+ x, y,
+ x+w, y,
+ x+w, y+h,
+ x, y+h
+ };
+ glVertexPointer(2, GL_FLOAT, 0, vertices);
+
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
}
+
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+ glEnable(GL_TEXTURE_2D);
+ glColor4f(1, 1, 1, 1);
}
void
float w = ellipse->size.x/2.0f;
float h = ellipse->size.y/2.0f;
- glBegin(GL_TRIANGLES);
-
+ static const int slices = 16;
+ static const int points = (slices+1) * 12;
+
+ float vertices[points * 2];
+ int p = 0;
+
// Bottom
- glVertex2f(SCREEN_WIDTH, SCREEN_HEIGHT);
- glVertex2f(0, SCREEN_HEIGHT);
- glVertex2f(x, y+h);
+ vertices[p++] = SCREEN_WIDTH; vertices[p++] = SCREEN_HEIGHT;
+ vertices[p++] = 0; vertices[p++] = SCREEN_HEIGHT;
+ vertices[p++] = x; vertices[p++] = y+h;
// Top
- glVertex2f(SCREEN_WIDTH, 0);
- glVertex2f(0, 0);
- glVertex2f(x, y-h);
+ vertices[p++] = SCREEN_WIDTH; vertices[p++] = 0;
+ vertices[p++] = 0; vertices[p++] = 0;
+ vertices[p++] = x; vertices[p++] = y-h;
// Left
- glVertex2f(SCREEN_WIDTH, 0);
- glVertex2f(SCREEN_WIDTH, SCREEN_HEIGHT);
- glVertex2f(x+w, y);
+ vertices[p++] = SCREEN_WIDTH; vertices[p++] = 0;
+ vertices[p++] = SCREEN_WIDTH; vertices[p++] = SCREEN_HEIGHT;
+ vertices[p++] = x+w; vertices[p++] = y;
// Right
- glVertex2f(0, 0);
- glVertex2f(0, SCREEN_HEIGHT);
- glVertex2f(x-w, y);
+ vertices[p++] = 0; vertices[p++] = 0;
+ vertices[p++] = 0; vertices[p++] = SCREEN_HEIGHT;
+ vertices[p++] = x-w; vertices[p++] = y;
- glEnd();
-
- int slices = 16;
for(int i = 0; i < slices; ++i)
{
float ex1 = sinf(M_PI/2 / slices * i) * w;
float ex2 = sinf(M_PI/2 / slices * (i+1)) * w;
float ey2 = cosf(M_PI/2 / slices * (i+1)) * h;
- glBegin(GL_TRIANGLES);
-
// Bottom/Right
- glVertex2f(SCREEN_WIDTH, SCREEN_HEIGHT);
- glVertex2f(x + ex1, y + ey1);
- glVertex2f(x + ex2, y + ey2);
+ vertices[p++] = SCREEN_WIDTH; vertices[p++] = SCREEN_HEIGHT;
+ vertices[p++] = x + ex1; vertices[p++] = y + ey1;
+ vertices[p++] = x + ex2; vertices[p++] = y + ey2;
// Top/Left
- glVertex2f(0, 0);
- glVertex2f(x - ex1, y - ey1);
- glVertex2f(x - ex2, y - ey2);
+ vertices[p++] = 0; vertices[p++] = 0;
+ vertices[p++] = x - ex1; vertices[p++] = y - ey1;
+ vertices[p++] = x - ex2; vertices[p++] = y - ey2;
// Top/Right
- glVertex2f(SCREEN_WIDTH, 0);
- glVertex2f(x + ex1, y - ey1);
- glVertex2f(x + ex2, y - ey2);
+ vertices[p++] = SCREEN_WIDTH; vertices[p++] = 0;
+ vertices[p++] = x + ex1; vertices[p++] = y - ey1;
+ vertices[p++] = x + ex2; vertices[p++] = y - ey2;
// Bottom/Left
- glVertex2f(0, SCREEN_HEIGHT);
- glVertex2f(x - ex1, y + ey1);
- glVertex2f(x - ex2, y + ey2);
-
- glEnd();
+ vertices[p++] = 0; vertices[p++] = SCREEN_HEIGHT;
+ vertices[p++] = x - ex1; vertices[p++] = y + ey1;
+ vertices[p++] = x - ex2; vertices[p++] = y + ey2;
}
+
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
+ glVertexPointer(2, GL_FLOAT, 0, vertices);
+
+ glDrawArrays(GL_TRIANGLES, 0, points);
+
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+
glEnable(GL_TEXTURE_2D);
glColor4f(1, 1, 1, 1);
}
void
Renderer::resize(int w, int h)
{
- SDL_SetVideoMode(w, h, 0, SDL_OPENGL | SDL_RESIZABLE);
+ // This causes the screen to go black, which is annoying, but seems
+ // unavoidable with SDL at the moment
+ SDL_SetVideoMode(w, h, 0, SDL_OPENGL /*| SDL_RESIZABLE*/);
config->window_width = w;
config->window_height = h;
void
Renderer::apply_config()
{
- std::cout << "Applying Config:"
- << "\n Desktop: " << desktop_width << "x" << desktop_height
- << "\n Window: " << config->window_width << "x" << config->window_height
- << "\n FullRes: " << config->fullscreen_width << "x" << config->fullscreen_height
- << "\n Aspect: " << config->aspect_width << ":" << config->aspect_height
- << "\n Magnif: " << config->magnification
- << std::endl;
+ if (0)
+ {
+ std::cout << "Applying Config:"
+ << "\n Desktop: " << desktop_width << "x" << desktop_height
+ << "\n Window: " << config->window_width << "x" << config->window_height
+ << "\n FullRes: " << config->fullscreen_width << "x" << config->fullscreen_height
+ << "\n Aspect: " << config->aspect_width << ":" << config->aspect_height
+ << "\n Magnif: " << config->magnification
+ << std::endl;
+ }
int w,h;
- float target_aspect = float(config->aspect_width) / float(config->aspect_height);
+ float target_aspect = float(desktop_width) / desktop_height;
+
+ if (config->aspect_width != 0 && config->aspect_height != 0)
+ target_aspect = float(config->aspect_width) / float(config->aspect_height);
+
float desktop_aspect = 4.0f / 3.0f; // random default fallback guess
if (desktop_width != -1 && desktop_height != -1)
desktop_aspect = float(desktop_width) / float(desktop_height);
}
+ // Get the screen width
if (config->use_fullscreen)
{
w = config->fullscreen_width;
if (target_aspect > 1.0f)
{
- SCREEN_WIDTH = w * (target_aspect / desktop_aspect);
- SCREEN_HEIGHT = h;
+ SCREEN_WIDTH = static_cast<int>(w * (target_aspect / desktop_aspect));
+ SCREEN_HEIGHT = static_cast<int>(h);
}
else
{
- SCREEN_WIDTH = w;
- SCREEN_HEIGHT = h * (target_aspect / desktop_aspect);
+ SCREEN_WIDTH = static_cast<int>(w);
+ SCREEN_HEIGHT = static_cast<int>(h * (target_aspect / desktop_aspect));
}
- SCREEN_WIDTH /= config->magnification;
- SCREEN_HEIGHT /= config->magnification;
-
int max_width = 1600; // FIXME: Maybe 1920 is ok too
int max_height = 1200;
- if (0)
+ if (config->magnification == 0.0f) // Magic value that means 'minfill'
{
// This scales SCREEN_WIDTH/SCREEN_HEIGHT so that they never excede
// max_width/max_height
if (SCREEN_WIDTH > max_width || SCREEN_HEIGHT > max_height)
{
- float scale1 = float(max_width)/SCREEN_WIDTH;
- float scale2 = float(max_height)/SCREEN_HEIGHT;
- float scale = scale1 < scale2 ? scale1 : scale2;
- SCREEN_WIDTH *= scale;
- SCREEN_HEIGHT *= scale;
+ float scale1 = float(max_width)/SCREEN_WIDTH;
+ float scale2 = float(max_height)/SCREEN_HEIGHT;
+ float scale = (scale1 < scale2) ? scale1 : scale2;
+ SCREEN_WIDTH = static_cast<int>(SCREEN_WIDTH * scale);
+ SCREEN_HEIGHT = static_cast<int>(SCREEN_HEIGHT * scale);
}
glViewport(0, 0, w, h);
}
else
{
+ SCREEN_WIDTH = static_cast<int>(SCREEN_WIDTH / config->magnification);
+ SCREEN_HEIGHT = static_cast<int>(SCREEN_HEIGHT / config->magnification);
+
// This works by adding black borders around the screen to limit
// SCREEN_WIDTH/SCREEN_HEIGHT to max_width/max_height
int nw = w;
if (SCREEN_WIDTH > max_width)
{
- nw *= float(max_width)/SCREEN_WIDTH;
- SCREEN_WIDTH = max_width;
+ nw = static_cast<int>((float) nw * float(max_width)/SCREEN_WIDTH);
+ SCREEN_WIDTH = static_cast<int>(max_width);
}
if (SCREEN_HEIGHT > max_height)
{
- nh *= float(max_height)/SCREEN_HEIGHT;
- SCREEN_HEIGHT = max_height;
+ nh = static_cast<int>((float) nh * float(max_height)/SCREEN_HEIGHT);
+ SCREEN_HEIGHT = static_cast<int>(max_height);
}
+ // Clear both buffers so that we get a clean black border without junk
glClear(GL_COLOR_BUFFER_BIT);
+ SDL_GL_SwapBuffers();
+ glClear(GL_COLOR_BUFFER_BIT);
+ SDL_GL_SwapBuffers();
+
+ if (0)
+ std::cout << (w-nw)/2 << " "
+ << (h-nh)/2 << " "
+ << nw << "x" << nh << std::endl;
- std::cout << (w-nw)/2 << " "
- << (h-nh)/2 << " "
- << nw << "x" << nh << std::endl;
glViewport(std::max(0, (w-nw)/2),
std::max(0, (h-nh)/2),
std::min(nw, w),
std::min(nh, h));
}
- std::cout << " -> " << SCREEN_WIDTH << "x" << SCREEN_HEIGHT << std::endl;
-
+ if (0)
+ std::cout << " -> " << SCREEN_WIDTH << "x" << SCREEN_HEIGHT << std::endl;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
- glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1.0, 1.0);
+
+ glOrtho(0, SCREEN_WIDTH, SCREEN_HEIGHT, 0, -1, 1);
+
+ glMatrixMode(GL_MODELVIEW);
+ glLoadIdentity();
+ glTranslatef(0, 0, 0);
+ check_gl_error("Setting up view matrices");
}
} // namespace GL