X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;ds=sidebyside;f=src%2Fvideo%2Fgl_renderer.cpp;h=e182988d15c5e1f23b3c7f87e362c431dd9d8ff7;hb=69fcf99ff4db01d788a7fa17906d260ebaf67b49;hp=764f061c4d8ac642db1a2b2fc3c042cc15cc917a;hpb=07ed4c2b80f0bff52fe86cd62acf718b12455962;p=supertux.git diff --git a/src/video/gl_renderer.cpp b/src/video/gl_renderer.cpp index 764f061c4..e182988d1 100644 --- a/src/video/gl_renderer.cpp +++ b/src/video/gl_renderer.cpp @@ -45,8 +45,13 @@ #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, @@ -60,64 +65,67 @@ inline void intern_draw(float left, float top, float right, float bottom, if(effect & VERTICAL_FLIP) std::swap(uv_top, uv_bottom); - - 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(); - } + // unrotated blit + glBlendFunc(blend.sfactor, blend.dfactor); + glColor4f(color.red, color.green, color.blue, color.alpha * alpha); + + 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 { @@ -150,7 +158,7 @@ Renderer::Renderer() 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); @@ -158,6 +166,7 @@ Renderer::Renderer() int flags = SDL_OPENGL; int width; int height; + if(config->use_fullscreen) { flags |= SDL_FULLSCREEN; @@ -170,9 +179,10 @@ Renderer::Renderer() 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 @@ -185,22 +195,13 @@ Renderer::Renderer() glDisable(GL_CULL_FACE); glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); + glEnable(GL_VERTEX_ARRAY); + glEnable(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 @@ -274,14 +275,30 @@ Renderer::draw_gradient(const DrawingRequest& request) 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(); + glDisable(GL_TEXTURE_COORD_ARRAY); + glEnable(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); + + glDisable(GL_COLOR_ARRAY); + glEnable(GL_TEXTURE_COORD_ARRAY); + glEnable(GL_TEXTURE_2D); glColor4f(1, 1, 1, 1); } @@ -344,13 +361,19 @@ Renderer::draw_filled_rect(const DrawingRequest& request) glDisable(GL_TEXTURE_2D); glColor4f(fillrectrequest->color.red, fillrectrequest->color.green, fillrectrequest->color.blue, fillrectrequest->color.alpha); + glDisable(GL_TEXTURE_COORD_ARRAY); - glBegin(GL_QUADS); - glVertex2f(x, y); - glVertex2f(x+w, y); - glVertex2f(x+w, y+h); - glVertex2f(x, y+h); - glEnd(); + 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); + + glEnable(GL_TEXTURE_COORD_ARRAY); glEnable(GL_TEXTURE_2D); glColor4f(1, 1, 1, 1); } @@ -370,31 +393,32 @@ Renderer::draw_inverse_ellipse(const DrawingRequest& request) 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; @@ -403,30 +427,34 @@ Renderer::draw_inverse_ellipse(const DrawingRequest& request) 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; } + + glDisable(GL_TEXTURE_COORD_ARRAY); + glVertexPointer(2, GL_FLOAT, 0, vertices); + + glDrawArrays(GL_TRIANGLES, 0, points); + + glEnable(GL_TEXTURE_COORD_ARRAY); + glEnable(GL_TEXTURE_2D); glColor4f(1, 1, 1, 1); } @@ -522,13 +550,16 @@ Renderer::resize(int w, int 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); @@ -539,6 +570,7 @@ Renderer::apply_config() desktop_aspect = float(desktop_width) / float(desktop_height); } + // Get the screen width if (config->use_fullscreen) { w = config->fullscreen_width; @@ -553,32 +585,32 @@ Renderer::apply_config() if (target_aspect > 1.0f) { - SCREEN_WIDTH = w * (target_aspect / desktop_aspect); - SCREEN_HEIGHT = h; + SCREEN_WIDTH = static_cast(w * (target_aspect / desktop_aspect)); + SCREEN_HEIGHT = static_cast(h); } else { - SCREEN_WIDTH = w; - SCREEN_HEIGHT = h * (target_aspect / desktop_aspect); + SCREEN_WIDTH = static_cast(w); + SCREEN_HEIGHT = static_cast(h * (target_aspect / desktop_aspect)); } - SCREEN_WIDTH /= config->magnification; - SCREEN_HEIGHT /= config->magnification; + SCREEN_WIDTH = static_cast(SCREEN_WIDTH / config->magnification); + SCREEN_HEIGHT = static_cast(SCREEN_HEIGHT / config->magnification); int max_width = 1600; // FIXME: Maybe 1920 is ok too int max_height = 1200; - if (0) + if (config->fill_screen) { // 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(SCREEN_WIDTH * scale); + SCREEN_HEIGHT = static_cast(SCREEN_HEIGHT * scale); } glViewport(0, 0, w, h); @@ -592,33 +624,42 @@ Renderer::apply_config() if (SCREEN_WIDTH > max_width) { - nw *= float(max_width)/SCREEN_WIDTH; - SCREEN_WIDTH = max_width; + nw = static_cast((float) nw * float(max_width)/SCREEN_WIDTH); + SCREEN_WIDTH = static_cast(max_width); } if (SCREEN_HEIGHT > max_height) { - nh *= float(max_height)/SCREEN_HEIGHT; - SCREEN_HEIGHT = max_height; + nh = static_cast((float) nh * float(max_height)/SCREEN_HEIGHT); + SCREEN_HEIGHT = static_cast(max_height); } + // Clear so that we get a clean black border without junk glClear(GL_COLOR_BUFFER_BIT); - std::cout << (w-nw)/2 << " " - << (h-nh)/2 << " " - << nw << "x" << nh << std::endl; + if (0) + 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