From: Ricardo Cruz Date: Thu, 10 Jun 2004 14:09:49 +0000 (+0000) Subject: This is an implementation that creates a gradient Surface, in order to speed up the... X-Git-Url: https://git.verplant.org/?a=commitdiff_plain;h=66ab8f75a39aa01b16dd752f35a7cf778a17e841;p=supertux.git This is an implementation that creates a gradient Surface, in order to speed up the gradient drawing. But it is working even slower in SDL, and doesn't work at all in OpenGL. Just committed, in the hope that someone finds the problem. SVN-Revision: 1462 --- diff --git a/src/background.cpp b/src/background.cpp index ed51950f3..65d7be70a 100644 --- a/src/background.cpp +++ b/src/background.cpp @@ -95,13 +95,17 @@ Background::set_gradient(Color top, Color bottom) type = GRADIENT; gradient_top = top; gradient_bottom = bottom; + + delete image; + image = new Surface(top, bottom, screen->w, screen->h); } void Background::draw(DrawingContext& context) { if(type == GRADIENT) { - context.draw_gradient(gradient_top, gradient_bottom, LAYER_BACKGROUND0); + context.draw_surface(image, Vector(0, 0), LAYER_BACKGROUND0); +// context.draw_gradient(gradient_top, gradient_bottom, LAYER_BACKGROUND0); } else if(type == IMAGE) { int sx = int(-context.get_translation().x * speed) % image->w - image->w; diff --git a/src/screen/drawing_context.h b/src/screen/drawing_context.h index 0051301b8..d171c4413 100644 --- a/src/screen/drawing_context.h +++ b/src/screen/drawing_context.h @@ -43,24 +43,6 @@ enum { LAYER_GUI = 500 }; -class Color -{ -public: - Color() - : red(0), green(0), blue(0), alpha(0) - {} - - Color(Uint8 red_, Uint8 green_, Uint8 blue_, Uint8 alpha_ = 0) - : red(red_), green(green_), blue(blue_), alpha(alpha_) - {} - - Color(const Color& o) - : red(o.red), green(o.green), blue(o.blue), alpha(o.alpha) - { } - - Uint8 red, green, blue, alpha; -}; - /** * This class provides functions for drawing things on screen. It also * maintains a stack of transforms that are applied to graphics. diff --git a/src/screen/screen.h b/src/screen/screen.h index 4c7f3df77..85744e833 100644 --- a/src/screen/screen.h +++ b/src/screen/screen.h @@ -24,6 +24,25 @@ #ifndef NOOPENGL #include #endif + +class Color +{ +public: + Color() + : red(0), green(0), blue(0), alpha(0) + {} + + Color(Uint8 red_, Uint8 green_, Uint8 blue_, Uint8 alpha_ = 0) + : red(red_), green(green_), blue(blue_), alpha(alpha_) + {} + + Color(const Color& o) + : red(o.red), green(o.green), blue(o.blue), alpha(o.alpha) + { } + + Uint8 red, green, blue, alpha; +}; + #include "texture.h" class Vector; diff --git a/src/screen/texture.cpp b/src/screen/texture.cpp index fbb9a101b..d84175419 100644 --- a/src/screen/texture.cpp +++ b/src/screen/texture.cpp @@ -58,6 +58,14 @@ SurfaceData::SurfaceData(const std::string& file_, int x_, int y_, int w_, int h x(x_), y(y_), w(w_), h(h_) {} +SurfaceData::SurfaceData(Color top_gradient_, Color bottom_gradient_, int w_, int h_) + : type(GRADIENT), surface(0), use_alpha(false), w(w_), h(h_) +{ +top_gradient = top_gradient_; +bottom_gradient = bottom_gradient_; +} + + SurfaceData::~SurfaceData() { SDL_FreeSurface(surface); @@ -87,6 +95,8 @@ SurfaceData::create_SurfaceSDL() return new SurfaceSDL(file, x, y, w, h, use_alpha); case SURFACE: return new SurfaceSDL(surface, use_alpha); + case GRADIENT: + return new SurfaceSDL(top_gradient, bottom_gradient, w, h); } assert(0); } @@ -103,6 +113,8 @@ SurfaceData::create_SurfaceOpenGL() return new SurfaceOpenGL(file, x, y, w, h, use_alpha); case SURFACE: return new SurfaceOpenGL(surface, use_alpha); + case GRADIENT: + return new SurfaceOpenGL(top_gradient, bottom_gradient, w, h); } #endif assert(0); @@ -158,6 +170,18 @@ Surface::Surface(const std::string& file, int x, int y, int w, int h, int use_al surfaces.push_back(this); } +Surface::Surface(Color top_background, Color bottom_background, int w, int h) + : data(top_background, bottom_background, w, h), w(0), h(0) +{ + impl = data.create(); + if (impl) + { + w = impl->w; + h = impl->h; + } + surfaces.push_back(this); +} + void Surface::reload() { @@ -337,6 +361,53 @@ sdl_surface_from_sdl_surface(SDL_Surface* sdl_surf, int use_alpha) return sdl_surface; } +SDL_Surface* +sdl_surface_from_gradient(Color top, Color bottom, int w, int h) +{ + SDL_Surface* sdl_surface; + + Uint32 rmask, gmask, bmask, amask; + + /* SDL interprets each pixel as a 32-bit number, so our masks must depend + on the endianness (byte order) of the machine */ +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + rmask = 0xff000000; + gmask = 0x00ff0000; + bmask = 0x0000ff00; + amask = 0x000000ff; +#else + rmask = 0x000000ff; + gmask = 0x0000ff00; + bmask = 0x00ff0000; + amask = 0xff000000; +#endif + + sdl_surface = SDL_CreateRGBSurface(screen->flags, w, h, + screen->format->BitsPerPixel, rmask, gmask, bmask, amask); + + if(sdl_surface == NULL) + st_abort("Cannot create surface for the gradient", "SURFACE"); + + float redstep = (float(bottom.red)-float(top.red)) / float(h); + float greenstep = (float(bottom.green)-float(top.green)) / float(h); + float bluestep = (float(bottom.blue) - float(top.blue)) / float(h); + + SDL_Rect rect; + rect.x = 0; + rect.w = w; + rect.h = 1; + for(float y = 0; y < h; y++) + { + rect.y = (int)y; + SDL_FillRect(sdl_surface, &rect, SDL_MapRGB(sdl_surface->format, + int(float(top.red) + redstep * y), + int(float(top.green) + greenstep * y), + int(float(top.blue) + bluestep * y))); + } + + return sdl_surface; +} + //--------------------------------------------------------------------------- SurfaceImpl::SurfaceImpl() @@ -394,6 +465,15 @@ SurfaceOpenGL::SurfaceOpenGL(const std::string& file, int x, int y, int w, int h h = sdl_surface->h; } +SurfaceOpenGL::SurfaceOpenGL(Color top_gradient, Color bottom_gradient, int w, int h) +{ + sdl_surface = sdl_surface_from_gradient(top_gradient, bottom_gradient, w, h); + create_gl(sdl_surface, &gl_texture); + + w = sdl_surface->w; + h = sdl_surface->h; +} + SurfaceOpenGL::~SurfaceOpenGL() { glDeleteTextures(1, &gl_texture); @@ -620,6 +700,13 @@ SurfaceSDL::SurfaceSDL(const std::string& file, int x, int y, int w, int h, int h = sdl_surface->h; } +SurfaceSDL::SurfaceSDL(Color top_gradient, Color bottom_gradient, int w, int h) +{ + sdl_surface = sdl_surface_from_gradient(top_gradient, bottom_gradient, w, h); + w = sdl_surface->w; + h = sdl_surface->h; +} + int SurfaceSDL::draw(float x, float y, Uint8 alpha, Uint32 effect) { diff --git a/src/screen/texture.h b/src/screen/texture.h index 469b30912..6fe26e332 100644 --- a/src/screen/texture.h +++ b/src/screen/texture.h @@ -34,6 +34,7 @@ #include "vector.h" SDL_Surface* sdl_surface_from_sdl_surface(SDL_Surface* sdl_surf, int use_alpha); +SDL_Surface* sdl_surface_from_nothing(); class SurfaceImpl; class SurfaceSDL; @@ -42,7 +43,7 @@ class DrawingContext; /// bitset for drawing effects enum { - /** Draw the Surface upside down */ + /** Don't apply anything */ NONE_EFFECT = 0x0000, /** Draw the Surface upside down */ VERTICAL_FLIP = 0x0001, @@ -54,7 +55,7 @@ enum { class SurfaceData { public: - enum ConstructorType { LOAD, LOAD_PART, SURFACE }; + enum ConstructorType { LOAD, LOAD_PART, SURFACE, GRADIENT }; ConstructorType type; SDL_Surface* surface; std::string file; @@ -63,10 +64,13 @@ public: int y; int w; int h; + Color top_gradient; + Color bottom_gradient; SurfaceData(SDL_Surface* surf, int use_alpha_); SurfaceData(const std::string& file_, int use_alpha_); SurfaceData(const std::string& file_, int x_, int y_, int w_, int h_, int use_alpha_); + SurfaceData(Color top_gradient_, Color bottom_gradient_, int w_, int h_); ~SurfaceData(); SurfaceSDL* create_SurfaceSDL(); @@ -93,6 +97,7 @@ public: Surface(SDL_Surface* surf, int use_alpha); Surface(const std::string& file, int use_alpha); Surface(const std::string& file, int x, int y, int w, int h, int use_alpha); + Surface(Color top_gradient, Color bottom_gradient, int w, int h); ~Surface(); /** Reload the surface, which is necesarry in case of a mode swich */ @@ -133,6 +138,7 @@ public: SurfaceSDL(SDL_Surface* surf, int use_alpha); SurfaceSDL(const std::string& file, int use_alpha); SurfaceSDL(const std::string& file, int x, int y, int w, int h, int use_alpha); + SurfaceSDL(Color top_gradient, Color bottom_gradient, int w, int h); virtual ~SurfaceSDL(); int draw(float x, float y, Uint8 alpha, Uint32 effect = NONE_EFFECT); @@ -152,6 +158,8 @@ public: SurfaceOpenGL(SDL_Surface* surf, int use_alpha); SurfaceOpenGL(const std::string& file, int use_alpha); SurfaceOpenGL(const std::string& file, int x, int y, int w, int h, int use_alpha); + SurfaceOpenGL(Color top_gradient, Color bottom_gradient, int w, int h); + virtual ~SurfaceOpenGL(); int draw(float x, float y, Uint8 alpha, Uint32 effect = NONE_EFFECT);