From 39b21a2b4a45fe80b4e08e59cdc61556f9da8b20 Mon Sep 17 00:00:00 2001 From: Ingo Ruhnke Date: Sat, 16 Aug 2014 22:43:40 +0200 Subject: [PATCH] Moved all duplicated drawing code from GLLightmap and GLRenderer into new GLPainter class --- src/video/gl/gl_lightmap.cpp | 113 ++----------- src/video/gl/gl_lightmap.hpp | 1 + src/video/gl/gl_painter.cpp | 374 +++++++++++++++++++++++++++++++++++++++++++ src/video/gl/gl_painter.hpp | 46 ++++++ src/video/gl/gl_renderer.cpp | 305 ++++------------------------------- src/video/gl/gl_renderer.hpp | 82 ---------- 6 files changed, 464 insertions(+), 457 deletions(-) create mode 100644 src/video/gl/gl_painter.cpp create mode 100644 src/video/gl/gl_painter.hpp diff --git a/src/video/gl/gl_lightmap.cpp b/src/video/gl/gl_lightmap.cpp index 41041817f..a0ce5e4b4 100644 --- a/src/video/gl/gl_lightmap.cpp +++ b/src/video/gl/gl_lightmap.cpp @@ -32,8 +32,9 @@ #include "video/drawing_context.hpp" #include "video/drawing_request.hpp" #include "video/font.hpp" -#include "video/gl/gl_surface_data.hpp" +#include "video/gl/gl_painter.hpp" #include "video/gl/gl_renderer.hpp" +#include "video/gl/gl_surface_data.hpp" #include "video/gl/gl_texture.hpp" #include "video/glutil.hpp" #include "video/lightmap.hpp" @@ -148,123 +149,31 @@ GLLightmap::do_draw() void GLLightmap::draw_surface(const DrawingRequest& request) { - const Surface* surface = static_cast(request.request_data)->surface; - boost::shared_ptr gltexture = boost::dynamic_pointer_cast(surface->get_texture()); - GLSurfaceData *surface_data = reinterpret_cast(surface->get_surface_data()); - - glBindTexture(GL_TEXTURE_2D, gltexture->get_handle()); - intern_draw(request.pos.x, request.pos.y, - request.pos.x + surface->get_width(), - request.pos.y + surface->get_height(), - surface_data->get_uv_left(), - surface_data->get_uv_top(), - surface_data->get_uv_right(), - surface_data->get_uv_bottom(), - request.angle, - request.alpha, - request.color, - request.blend, - request.drawing_effect); + GLPainter::draw_surface(request); } void GLLightmap::draw_surface_part(const DrawingRequest& request) { - const SurfacePartRequest* surfacepartrequest - = (SurfacePartRequest*) request.request_data; - const Surface* surface = surfacepartrequest->surface; - boost::shared_ptr gltexture = boost::dynamic_pointer_cast(surface->get_texture()); - GLSurfaceData *surface_data = reinterpret_cast(surface->get_surface_data()); - - float uv_width = surface_data->get_uv_right() - surface_data->get_uv_left(); - float uv_height = surface_data->get_uv_bottom() - surface_data->get_uv_top(); - - float uv_left = surface_data->get_uv_left() + (uv_width * surfacepartrequest->srcrect.p1.x) / surface->get_width(); - float uv_top = surface_data->get_uv_top() + (uv_height * surfacepartrequest->srcrect.p1.y) / surface->get_height(); - float uv_right = surface_data->get_uv_left() + (uv_width * surfacepartrequest->srcrect.p2.x) / surface->get_width(); - float uv_bottom = surface_data->get_uv_top() + (uv_height * surfacepartrequest->srcrect.p2.y) / surface->get_height(); - - glBindTexture(GL_TEXTURE_2D, gltexture->get_handle()); - intern_draw(request.pos.x, request.pos.y, - request.pos.x + surfacepartrequest->dstsize.width, - request.pos.y + surfacepartrequest->dstsize.height, - uv_left, - uv_top, - uv_right, - uv_bottom, - 0.0, - request.alpha, - Color(1.0, 1.0, 1.0), - Blend(), - request.drawing_effect); + GLPainter::draw_surface_part(request); } void GLLightmap::draw_gradient(const DrawingRequest& request) { - const GradientRequest* gradientrequest - = (GradientRequest*) request.request_data; - const Color& top = gradientrequest->top; - const Color& bottom = gradientrequest->bottom; - - glDisable(GL_TEXTURE_2D); - glDisable(GL_TEXTURE_COORD_ARRAY); - glEnable(GL_COLOR_ARRAY); - - float vertices[] = { - 0, 0, - float(SCREEN_WIDTH), 0, - float(SCREEN_WIDTH), float(SCREEN_HEIGHT), - 0, float(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); + GLPainter::draw_gradient(request); } void GLLightmap::draw_filled_rect(const DrawingRequest& request) { - const FillRectRequest* fillrectrequest - = (FillRectRequest*) request.request_data; - - float x = request.pos.x; - float y = request.pos.y; - 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); - glDisable(GL_TEXTURE_COORD_ARRAY); - - 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); + GLPainter::draw_filled_rect(request); +} - glEnable(GL_TEXTURE_COORD_ARRAY); - glEnable(GL_TEXTURE_2D); - glColor4f(1, 1, 1, 1); +void +GLLightmap::draw_inverse_ellipse(const DrawingRequest& request) +{ + GLPainter::draw_inverse_ellipse(request); } void diff --git a/src/video/gl/gl_lightmap.hpp b/src/video/gl/gl_lightmap.hpp index b44063908..0cd473c2f 100644 --- a/src/video/gl/gl_lightmap.hpp +++ b/src/video/gl/gl_lightmap.hpp @@ -36,6 +36,7 @@ public: void draw_surface_part(const DrawingRequest& request); void draw_gradient(const DrawingRequest& request); void draw_filled_rect(const DrawingRequest& request); + void draw_inverse_ellipse(const DrawingRequest& request); void get_light(const DrawingRequest& request) const; private: diff --git a/src/video/gl/gl_painter.cpp b/src/video/gl/gl_painter.cpp new file mode 100644 index 000000000..3617dde2f --- /dev/null +++ b/src/video/gl/gl_painter.cpp @@ -0,0 +1,374 @@ +// SuperTux +// Copyright (C) 2014 Ingo Ruhnke +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#include "video/gl/gl_painter.hpp" + +#include "video/drawing_request.hpp" +#include "video/gl/gl_surface_data.hpp" +#include "video/gl/gl_texture.hpp" + +GLuint GLPainter::last_texture = static_cast(-1); + +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, + float angle, float alpha, + const Color& color, + const Blend& blend, + DrawingEffect effect) +{ + if(effect & HORIZONTAL_FLIP) + std::swap(uv_left, uv_right); + + if(effect & VERTICAL_FLIP) + std::swap(uv_top, uv_bottom); + + glBlendFunc(blend.sfactor, blend.dfactor); + glColor4f(color.red, color.green, color.blue, color.alpha * alpha); + + // unrotated blit + 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 + +void +GLPainter::draw_surface(const DrawingRequest& request) +{ + const Surface* surface = static_cast(request.request_data)->surface; + if(surface == NULL) + { + return; + } + GLTexture* gltexture = static_cast(surface->get_texture().get()); + if(gltexture == NULL) + { + return; + } + GLSurfaceData *surface_data = static_cast(surface->get_surface_data()); + if(surface_data == NULL) + { + return; + } + + GLuint th = gltexture->get_handle(); + if (th != last_texture) { + last_texture = th; + glBindTexture(GL_TEXTURE_2D, th); + } + intern_draw(request.pos.x, request.pos.y, + request.pos.x + surface->get_width(), + request.pos.y + surface->get_height(), + surface_data->get_uv_left(), + surface_data->get_uv_top(), + surface_data->get_uv_right(), + surface_data->get_uv_bottom(), + request.angle, + request.alpha, + request.color, + request.blend, + request.drawing_effect); +} + +void +GLPainter::draw_surface_part(const DrawingRequest& request) +{ + const SurfacePartRequest* surfacepartrequest + = (SurfacePartRequest*) request.request_data; + const Surface* surface = surfacepartrequest->surface; + boost::shared_ptr gltexture = boost::dynamic_pointer_cast(surface->get_texture()); + GLSurfaceData *surface_data = reinterpret_cast(surface->get_surface_data()); + + float uv_width = surface_data->get_uv_right() - surface_data->get_uv_left(); + float uv_height = surface_data->get_uv_bottom() - surface_data->get_uv_top(); + + float uv_left = surface_data->get_uv_left() + (uv_width * surfacepartrequest->srcrect.p1.x) / surface->get_width(); + float uv_top = surface_data->get_uv_top() + (uv_height * surfacepartrequest->srcrect.p1.y) / surface->get_height(); + float uv_right = surface_data->get_uv_left() + (uv_width * surfacepartrequest->srcrect.p2.x) / surface->get_width(); + float uv_bottom = surface_data->get_uv_top() + (uv_height * surfacepartrequest->srcrect.p2.y) / surface->get_height(); + + GLuint th = gltexture->get_handle(); + if (th != last_texture) { + last_texture = th; + glBindTexture(GL_TEXTURE_2D, th); + } + intern_draw(request.pos.x, request.pos.y, + request.pos.x + surfacepartrequest->dstsize.width, + request.pos.y + surfacepartrequest->dstsize.height, + uv_left, + uv_top, + uv_right, + uv_bottom, + 0.0, + request.alpha, + request.color, + Blend(), + request.drawing_effect); +} + +void +GLPainter::draw_gradient(const DrawingRequest& request) +{ + const GradientRequest* gradientrequest + = (GradientRequest*) request.request_data; + const Color& top = gradientrequest->top; + const Color& bottom = gradientrequest->bottom; + + glDisable(GL_TEXTURE_2D); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glEnableClientState(GL_COLOR_ARRAY); + + float vertices[] = { + 0, 0, + float(SCREEN_WIDTH), 0, + float(SCREEN_WIDTH), float(SCREEN_HEIGHT), + 0, float(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); +} + +void +GLPainter::draw_filled_rect(const DrawingRequest& request) +{ + 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 + // Keep radius in the limits, so that we get a circle instead of + // just graphic junk + float radius = std::min(fillrectrequest->radius, + std::min(fillrectrequest->size.x/2, + fillrectrequest->size.y/2)); + + // inner rectangle + Rectf irect(request.pos.x + radius, + request.pos.y + radius, + request.pos.x + fillrectrequest->size.x - radius, + request.pos.y + fillrectrequest->size.y - radius); + + int n = 8; + int p = 0; + std::vector 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; + + 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; + + vertices[p++] = irect.get_left() - x; + vertices[p++] = irect.get_bottom() + y; + + vertices[p++] = irect.get_right() + x; + vertices[p++] = irect.get_bottom() + y; + } + + glVertexPointer(2, GL_FLOAT, 0, &*vertices.begin()); + glDrawArrays(GL_TRIANGLE_STRIP, 0, vertices.size()/2); + } + else + { + float x = request.pos.x; + float y = request.pos.y; + float w = fillrectrequest->size.x; + float h = fillrectrequest->size.y; + + 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 +GLPainter::draw_inverse_ellipse(const DrawingRequest& request) +{ + const InverseEllipseRequest* ellipse = (InverseEllipseRequest*)request.request_data; + + glDisable(GL_TEXTURE_2D); + glColor4f(ellipse->color.red, ellipse->color.green, + ellipse->color.blue, ellipse->color.alpha); + + float x = request.pos.x; + float y = request.pos.y; + float w = ellipse->size.x/2.0f; + float h = ellipse->size.y/2.0f; + + static const int slices = 16; + static const int points = (slices+1) * 12; + + float vertices[points * 2]; + int p = 0; + + // Bottom + vertices[p++] = SCREEN_WIDTH; vertices[p++] = SCREEN_HEIGHT; + vertices[p++] = 0; vertices[p++] = SCREEN_HEIGHT; + vertices[p++] = x; vertices[p++] = y+h; + + // Top + vertices[p++] = SCREEN_WIDTH; vertices[p++] = 0; + vertices[p++] = 0; vertices[p++] = 0; + vertices[p++] = x; vertices[p++] = y-h; + + // Left + vertices[p++] = SCREEN_WIDTH; vertices[p++] = 0; + vertices[p++] = SCREEN_WIDTH; vertices[p++] = SCREEN_HEIGHT; + vertices[p++] = x+w; vertices[p++] = y; + + // Right + vertices[p++] = 0; vertices[p++] = 0; + vertices[p++] = 0; vertices[p++] = SCREEN_HEIGHT; + vertices[p++] = x-w; vertices[p++] = y; + + for(int i = 0; i < slices; ++i) + { + float ex1 = sinf(M_PI/2 / slices * i) * w; + float ey1 = cosf(M_PI/2 / slices * i) * h; + + float ex2 = sinf(M_PI/2 / slices * (i+1)) * w; + float ey2 = cosf(M_PI/2 / slices * (i+1)) * h; + + // Bottom/Right + 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 + vertices[p++] = 0; vertices[p++] = 0; + vertices[p++] = x - ex1; vertices[p++] = y - ey1; + vertices[p++] = x - ex2; vertices[p++] = y - ey2; + + // Top/Right + 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 + 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); +} + +/* EOF */ diff --git a/src/video/gl/gl_painter.hpp b/src/video/gl/gl_painter.hpp new file mode 100644 index 000000000..3b006afbf --- /dev/null +++ b/src/video/gl/gl_painter.hpp @@ -0,0 +1,46 @@ +// SuperTux +// Copyright (C) 2014 Ingo Ruhnke +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +#ifndef HEADER_SUPERTUX_VIDEO_GL_GL_PAINTER_HPP +#define HEADER_SUPERTUX_VIDEO_GL_GL_PAINTER_HPP + +#include +#include "SDL_opengl.h" + +class DrawingRequest; + +class GLPainter +{ +private: + static GLuint last_texture; + +public: + GLPainter(); + + static void draw_surface(const DrawingRequest& request); + static void draw_surface_part(const DrawingRequest& request); + static void draw_gradient(const DrawingRequest& request); + static void draw_filled_rect(const DrawingRequest& request); + static void draw_inverse_ellipse(const DrawingRequest& request); + +private: + GLPainter(const GLPainter&) = delete; + GLPainter& operator=(const GLPainter&) = delete; +}; + +#endif + +/* EOF */ diff --git a/src/video/gl/gl_renderer.cpp b/src/video/gl/gl_renderer.cpp index 15fcafe58..03dadfffc 100644 --- a/src/video/gl/gl_renderer.cpp +++ b/src/video/gl/gl_renderer.cpp @@ -25,6 +25,7 @@ #include "supertux/gameconfig.hpp" #include "supertux/globals.hpp" #include "video/drawing_request.hpp" +#include "video/gl/gl_painter.hpp" #include "video/gl/gl_surface_data.hpp" #include "video/gl/gl_texture.hpp" #include "video/util.hpp" @@ -40,8 +41,7 @@ GLRenderer::GLRenderer() : glcontext(), viewport(), desktop_size(0, 0), - fullscreen_active(false), - last_texture(static_cast (-1)) + fullscreen_active(false) { Renderer::instance_ = this; @@ -109,277 +109,6 @@ GLRenderer::~GLRenderer() } void -GLRenderer::draw_surface(const DrawingRequest& request) -{ - const Surface* surface = static_cast(request.request_data)->surface; - if(surface == NULL) - { - return; - } - GLTexture* gltexture = static_cast(surface->get_texture().get()); - if(gltexture == NULL) - { - return; - } - GLSurfaceData *surface_data = static_cast(surface->get_surface_data()); - if(surface_data == NULL) - { - return; - } - - GLuint th = gltexture->get_handle(); - if (th != last_texture) { - last_texture = th; - glBindTexture(GL_TEXTURE_2D, th); - } - intern_draw(request.pos.x, request.pos.y, - request.pos.x + surface->get_width(), - request.pos.y + surface->get_height(), - surface_data->get_uv_left(), - surface_data->get_uv_top(), - surface_data->get_uv_right(), - surface_data->get_uv_bottom(), - request.angle, - request.alpha, - request.color, - request.blend, - request.drawing_effect); -} - -void -GLRenderer::draw_surface_part(const DrawingRequest& request) -{ - const SurfacePartRequest* surfacepartrequest - = (SurfacePartRequest*) request.request_data; - const Surface* surface = surfacepartrequest->surface; - boost::shared_ptr gltexture = boost::dynamic_pointer_cast(surface->get_texture()); - GLSurfaceData *surface_data = reinterpret_cast(surface->get_surface_data()); - - float uv_width = surface_data->get_uv_right() - surface_data->get_uv_left(); - float uv_height = surface_data->get_uv_bottom() - surface_data->get_uv_top(); - - float uv_left = surface_data->get_uv_left() + (uv_width * surfacepartrequest->srcrect.p1.x) / surface->get_width(); - float uv_top = surface_data->get_uv_top() + (uv_height * surfacepartrequest->srcrect.p1.y) / surface->get_height(); - float uv_right = surface_data->get_uv_left() + (uv_width * surfacepartrequest->srcrect.p2.x) / surface->get_width(); - float uv_bottom = surface_data->get_uv_top() + (uv_height * surfacepartrequest->srcrect.p2.y) / surface->get_height(); - - GLuint th = gltexture->get_handle(); - if (th != last_texture) { - last_texture = th; - glBindTexture(GL_TEXTURE_2D, th); - } - intern_draw(request.pos.x, request.pos.y, - request.pos.x + surfacepartrequest->dstsize.width, - request.pos.y + surfacepartrequest->dstsize.height, - uv_left, - uv_top, - uv_right, - uv_bottom, - 0.0, - request.alpha, - request.color, - Blend(), - request.drawing_effect); -} - -void -GLRenderer::draw_gradient(const DrawingRequest& request) -{ - const GradientRequest* gradientrequest - = (GradientRequest*) request.request_data; - const Color& top = gradientrequest->top; - const Color& bottom = gradientrequest->bottom; - - glDisable(GL_TEXTURE_2D); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glEnableClientState(GL_COLOR_ARRAY); - - float vertices[] = { - 0, 0, - float(SCREEN_WIDTH), 0, - float(SCREEN_WIDTH), float(SCREEN_HEIGHT), - 0, float(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); -} - -void -GLRenderer::draw_filled_rect(const DrawingRequest& request) -{ - 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 - // Keep radius in the limits, so that we get a circle instead of - // just graphic junk - float radius = std::min(fillrectrequest->radius, - std::min(fillrectrequest->size.x/2, - fillrectrequest->size.y/2)); - - // inner rectangle - Rectf irect(request.pos.x + radius, - request.pos.y + radius, - request.pos.x + fillrectrequest->size.x - radius, - request.pos.y + fillrectrequest->size.y - radius); - - int n = 8; - int p = 0; - std::vector 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; - - 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; - - vertices[p++] = irect.get_left() - x; - vertices[p++] = irect.get_bottom() + y; - - vertices[p++] = irect.get_right() + x; - vertices[p++] = irect.get_bottom() + y; - } - - glVertexPointer(2, GL_FLOAT, 0, &*vertices.begin()); - glDrawArrays(GL_TRIANGLE_STRIP, 0, vertices.size()/2); - } - else - { - float x = request.pos.x; - float y = request.pos.y; - float w = fillrectrequest->size.x; - float h = fillrectrequest->size.y; - - 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 -GLRenderer::draw_inverse_ellipse(const DrawingRequest& request) -{ - const InverseEllipseRequest* ellipse = (InverseEllipseRequest*)request.request_data; - - glDisable(GL_TEXTURE_2D); - glColor4f(ellipse->color.red, ellipse->color.green, - ellipse->color.blue, ellipse->color.alpha); - - float x = request.pos.x; - float y = request.pos.y; - float w = ellipse->size.x/2.0f; - float h = ellipse->size.y/2.0f; - - static const int slices = 16; - static const int points = (slices+1) * 12; - - float vertices[points * 2]; - int p = 0; - - // Bottom - vertices[p++] = SCREEN_WIDTH; vertices[p++] = SCREEN_HEIGHT; - vertices[p++] = 0; vertices[p++] = SCREEN_HEIGHT; - vertices[p++] = x; vertices[p++] = y+h; - - // Top - vertices[p++] = SCREEN_WIDTH; vertices[p++] = 0; - vertices[p++] = 0; vertices[p++] = 0; - vertices[p++] = x; vertices[p++] = y-h; - - // Left - vertices[p++] = SCREEN_WIDTH; vertices[p++] = 0; - vertices[p++] = SCREEN_WIDTH; vertices[p++] = SCREEN_HEIGHT; - vertices[p++] = x+w; vertices[p++] = y; - - // Right - vertices[p++] = 0; vertices[p++] = 0; - vertices[p++] = 0; vertices[p++] = SCREEN_HEIGHT; - vertices[p++] = x-w; vertices[p++] = y; - - for(int i = 0; i < slices; ++i) - { - float ex1 = sinf(M_PI/2 / slices * i) * w; - float ey1 = cosf(M_PI/2 / slices * i) * h; - - float ex2 = sinf(M_PI/2 / slices * (i+1)) * w; - float ey2 = cosf(M_PI/2 / slices * (i+1)) * h; - - // Bottom/Right - 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 - vertices[p++] = 0; vertices[p++] = 0; - vertices[p++] = x - ex1; vertices[p++] = y - ey1; - vertices[p++] = x - ex2; vertices[p++] = y - ey2; - - // Top/Right - 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 - 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 GLRenderer::do_take_screenshot() { // [Christoph] TODO: Yes, this method also takes care of the actual disk I/O. Split it? @@ -622,6 +351,36 @@ GLRenderer::apply_video_mode() } } +void +GLRenderer::draw_surface(const DrawingRequest& request) +{ + GLPainter::draw_surface(request); +} + +void +GLRenderer::draw_surface_part(const DrawingRequest& request) +{ + GLPainter::draw_surface_part(request); +} + +void +GLRenderer::draw_gradient(const DrawingRequest& request) +{ + GLPainter::draw_gradient(request); +} + +void +GLRenderer::draw_filled_rect(const DrawingRequest& request) +{ + GLPainter::draw_filled_rect(request); +} + +void +GLRenderer::draw_inverse_ellipse(const DrawingRequest& request) +{ + GLPainter::draw_inverse_ellipse(request); +} + Vector GLRenderer::to_logical(int physical_x, int physical_y) { diff --git a/src/video/gl/gl_renderer.hpp b/src/video/gl/gl_renderer.hpp index 13bc6f995..afb7542d1 100644 --- a/src/video/gl/gl_renderer.hpp +++ b/src/video/gl/gl_renderer.hpp @@ -24,86 +24,6 @@ #include "SDL.h" #include -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, - float angle, float alpha, - const Color& color, - const Blend& blend, - DrawingEffect effect) -{ - if(effect & HORIZONTAL_FLIP) - std::swap(uv_left, uv_right); - - if(effect & VERTICAL_FLIP) - std::swap(uv_top, uv_bottom); - - glBlendFunc(blend.sfactor, blend.dfactor); - glColor4f(color.red, color.green, color.blue, color.alpha * alpha); - - // unrotated blit - 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 - - - class GLRenderer : public Renderer { private: @@ -113,8 +33,6 @@ private: Size desktop_size; bool fullscreen_active; - GLuint last_texture; - public: GLRenderer(); ~GLRenderer(); -- 2.11.0