#include "glutil.hpp"
#include "sdl_renderer.hpp"
#include "sdl_texture.hpp"
+#include "sdl_surface_data.hpp"
#include "drawing_context.hpp"
#include "drawing_request.hpp"
#include "surface.hpp"
#include "font.hpp"
#include "main.hpp"
#include "gameconfig.hpp"
+#include "log.hpp"
#include "texture.hpp"
#include "texture_manager.hpp"
#include "obstack/obstackpp.hpp"
+namespace
+{
+ SDL_Surface *apply_alpha(SDL_Surface *src, float alpha_factor)
+ {
+ // FIXME: This is really slow
+ assert(src->format->Amask);
+ int alpha = (int) (alpha_factor * 256);
+ SDL_Surface *dst = SDL_CreateRGBSurface(src->flags, src->w, src->h, src->format->BitsPerPixel, src->format->Rmask, src->format->Gmask, src->format->Bmask, src->format->Amask);
+ int bpp = dst->format->BytesPerPixel;
+ if(SDL_MUSTLOCK(src))
+ {
+ SDL_LockSurface(src);
+ }
+ if(SDL_MUSTLOCK(dst))
+ {
+ SDL_LockSurface(dst);
+ }
+ for(int y = 0;y < dst->h;y++) {
+ for(int x = 0;x < dst->w;x++) {
+ Uint8 *srcpixel = (Uint8 *) src->pixels + y * src->pitch + x * bpp;
+ Uint8 *dstpixel = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp;
+ Uint32 mapped = 0;
+ switch(bpp) {
+ case 1:
+ mapped = *srcpixel;
+ break;
+ case 2:
+ mapped = *(Uint16 *)srcpixel;
+ break;
+ case 3:
+#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+ mapped |= srcpixel[0] << 16;
+ mapped |= srcpixel[1] << 8;
+ mapped |= srcpixel[2] << 0;
+#else
+ mapped |= srcpixel[0] << 0;
+ mapped |= srcpixel[1] << 8;
+ mapped |= srcpixel[2] << 16;
+#endif
+ break;
+ case 4:
+ mapped = *(Uint32 *)srcpixel;
+ break;
+ }
+ Uint8 r, g, b, a;
+ SDL_GetRGBA(mapped, src->format, &r, &g, &b, &a);
+ mapped = SDL_MapRGBA(dst->format, r, g, b, (a * alpha) >> 8);
+ switch(bpp) {
+ case 1:
+ *dstpixel = mapped;
+ break;
+ case 2:
+ *(Uint16 *)dstpixel = mapped;
+ break;
+ case 3:
+#if SDL_BYTEORDER == SDL_BIG_ENDIAN
+ dstpixel[0] = (mapped >> 16) & 0xff;
+ dstpixel[1] = (mapped >> 8) & 0xff;
+ dstpixel[2] = (mapped >> 0) & 0xff;
+#else
+ dstpixel[0] = (mapped >> 0) & 0xff;
+ dstpixel[1] = (mapped >> 8) & 0xff;
+ dstpixel[2] = (mapped >> 16) & 0xff;
+#endif
+ break;
+ case 4:
+ *(Uint32 *)dstpixel = mapped;
+ break;
+ }
+ }
+ }
+ if(SDL_MUSTLOCK(dst))
+ {
+ SDL_UnlockSurface(dst);
+ }
+ if(SDL_MUSTLOCK(src))
+ {
+ SDL_UnlockSurface(src);
+ }
+ return dst;
+ }
+}
+
namespace SDL
{
Renderer::Renderer()
{
- int flags = SDL_SWSURFACE;
+ const SDL_VideoInfo *info = SDL_GetVideoInfo();
+ log_info << "Hardware surfaces are " << (info->hw_available ? "" : "not ") << "available." << std::endl;
+ log_info << "Hardware to hardware blits are " << (info->blit_hw ? "" : "not ") << "accelerated." << std::endl;
+ log_info << "Hardware to hardware blits with colorkey are " << (info->blit_hw_CC ? "" : "not ") << "accelerated." << std::endl;
+ log_info << "Hardware to hardware blits with alpha are " << (info->blit_hw_A ? "" : "not ") << "accelerated." << std::endl;
+ log_info << "Software to hardware blits are " << (info->blit_sw ? "" : "not ") << "accelerated." << std::endl;
+ log_info << "Software to hardware blits with colorkey are " << (info->blit_sw_CC ? "" : "not ") << "accelerated." << std::endl;
+ log_info << "Software to hardware blits with alpha are " << (info->blit_sw_A ? "" : "not ") << "accelerated." << std::endl;
+ log_info << "Color fills are " << (info->blit_fill ? "" : "not ") << "accelerated." << std::endl;
+
+ int flags = SDL_SWSURFACE | SDL_ANYFORMAT;
if(config->use_fullscreen)
flags |= SDL_FULLSCREEN;
int width = config->screenwidth;
int height = config->screenheight;
- int bpp = 0;
- screen = SDL_SetVideoMode(width, height, bpp, flags);
+ screen = SDL_SetVideoMode(width, height, 0, flags);
if(screen == 0) {
std::stringstream msg;
msg << "Couldn't set video mode (" << width << "x" << height
- << "-" << bpp << "bpp): " << SDL_GetError();
+ << "): " << SDL_GetError();
throw std::runtime_error(msg.str());
}
+ float xfactor = (float) config->screenwidth / SCREEN_WIDTH;
+ float yfactor = (float) config->screenheight / SCREEN_HEIGHT;
+ if(xfactor < yfactor)
+ {
+ numerator = config->screenwidth;
+ denominator = SCREEN_WIDTH;
+ }
+ else
+ {
+ numerator = config->screenheight;
+ denominator = SCREEN_HEIGHT;
+ }
+
if(texture_manager == 0)
texture_manager = new TextureManager();
}
{
//FIXME: support parameters request.alpha, request.angle, request.blend
const Surface* surface = (const Surface*) request.request_data;
- SDL::Texture *sdltexture = dynamic_cast<Texture *>(surface->get_texture());
+ SDL::Texture *sdltexture = dynamic_cast<SDL::Texture *>(surface->get_texture());
+ SDL::SurfaceData *surface_data = reinterpret_cast<SDL::SurfaceData *>(surface->get_surface_data());
+
DrawingEffect effect = request.drawing_effect;
if (surface->get_flipx()) effect = HORIZONTAL_FLIP;
return;
}
- int ox, oy;
- if (effect == HORIZONTAL_FLIP)
- {
- ox = sdltexture->get_texture_width() - surface->get_x() - surface->get_width();
- }
- else
- {
- ox = surface->get_x();
- }
- if (effect == VERTICAL_FLIP)
- {
- oy = sdltexture->get_texture_height() - surface->get_y() - surface->get_height();
- }
- else
- {
- oy = surface->get_y();
- }
+ SDL_Rect *src_rect = surface_data->get_src_rect(effect);
+ SDL_Rect dst_rect;
+ dst_rect.x = (int) request.pos.x * numerator / denominator;
+ dst_rect.y = (int) request.pos.y * numerator / denominator;
- int numerator, denominator;
- float xfactor = (float) config->screenwidth / SCREEN_WIDTH;
- float yfactor = (float) config->screenheight / SCREEN_HEIGHT;
- if(xfactor < yfactor)
- {
- numerator = config->screenwidth;
- denominator = SCREEN_WIDTH;
- }
- else
+ Uint8 alpha = 0;
+ if(request.alpha != 1.0)
{
- numerator = config->screenheight;
- denominator = SCREEN_HEIGHT;
+ if(!transform->format->Amask)
+ {
+ if(transform->flags & SDL_SRCALPHA)
+ {
+ alpha = transform->format->alpha;
+ }
+ else
+ {
+ alpha = 255;
+ }
+ SDL_SetAlpha(transform, SDL_SRCALPHA, (Uint8) (request.alpha * alpha));
+ }
+ /*else
+ {
+ transform = apply_alpha(transform, request.alpha);
+ }*/
}
- SDL_Rect srcRect;
- srcRect.x = ox * numerator / denominator;
- srcRect.y = oy * numerator / denominator;
- srcRect.w = surface->get_width() * numerator / denominator;
- srcRect.h = surface->get_height() * numerator / denominator;
+ SDL_BlitSurface(transform, src_rect, screen, &dst_rect);
- SDL_Rect dstRect;
- dstRect.x = (int) request.pos.x * numerator / denominator;
- dstRect.y = (int) request.pos.y * numerator / denominator;
-
- SDL_BlitSurface(transform, &srcRect, screen, &dstRect);
+ if(request.alpha != 1.0)
+ {
+ if(!transform->format->Amask)
+ {
+ if(alpha == 255)
+ {
+ SDL_SetAlpha(transform, SDL_RLEACCEL, 0);
+ }
+ else
+ {
+ SDL_SetAlpha(transform, SDL_SRCALPHA | SDL_RLEACCEL, alpha);
+ }
+ }
+ /*else
+ {
+ SDL_FreeSurface(transform);
+ }*/
+ }
}
void
= (SurfacePartRequest*) request.request_data;
const Surface* surface = surfacepartrequest->surface;
- SDL::Texture *sdltexture = dynamic_cast<Texture *>(surface->get_texture());
+ SDL::Texture *sdltexture = dynamic_cast<SDL::Texture *>(surface->get_texture());
+
DrawingEffect effect = request.drawing_effect;
if (surface->get_flipx()) effect = HORIZONTAL_FLIP;
oy = surface->get_y();
}
- int numerator, denominator;
- float xfactor = (float) config->screenwidth / SCREEN_WIDTH;
- float yfactor = (float) config->screenheight / SCREEN_HEIGHT;
- if(xfactor < yfactor)
- {
- numerator = config->screenwidth;
- denominator = SCREEN_WIDTH;
- }
- else
+ SDL_Rect src_rect;
+ src_rect.x = (ox + (int) surfacepartrequest->source.x) * numerator / denominator;
+ src_rect.y = (oy + (int) surfacepartrequest->source.y) * numerator / denominator;
+ src_rect.w = (int) surfacepartrequest->size.x * numerator / denominator;
+ src_rect.h = (int) surfacepartrequest->size.y * numerator / denominator;
+
+ SDL_Rect dst_rect;
+ dst_rect.x = (int) request.pos.x * numerator / denominator;
+ dst_rect.y = (int) request.pos.y * numerator / denominator;
+
+ Uint8 alpha = 0;
+ if(request.alpha != 1.0)
{
- numerator = config->screenheight;
- denominator = SCREEN_HEIGHT;
+ if(!transform->format->Amask)
+ {
+ if(transform->flags & SDL_SRCALPHA)
+ {
+ alpha = transform->format->alpha;
+ }
+ else
+ {
+ alpha = 255;
+ }
+ SDL_SetAlpha(transform, SDL_SRCALPHA, (Uint8) (request.alpha * alpha));
+ }
+ /*else
+ {
+ transform = apply_alpha(transform, request.alpha);
+ }*/
}
- SDL_Rect srcRect;
- srcRect.x = (ox + (int) surfacepartrequest->source.x) * numerator / denominator;
- srcRect.y = (oy + (int) surfacepartrequest->source.y) * numerator / denominator;
- srcRect.w = (int) surfacepartrequest->size.x * numerator / denominator;
- srcRect.h = (int) surfacepartrequest->size.y * numerator / denominator;
-
- SDL_Rect dstRect;
- dstRect.x = (int) request.pos.x * numerator / denominator;
- dstRect.y = (int) request.pos.y * numerator / denominator;
+ SDL_BlitSurface(transform, &src_rect, screen, &dst_rect);
- SDL_BlitSurface(transform, &srcRect, screen, &dstRect);
+ if(request.alpha != 1.0)
+ {
+ if(!transform->format->Amask)
+ {
+ if(alpha == 255)
+ {
+ SDL_SetAlpha(transform, SDL_RLEACCEL, 0);
+ }
+ else
+ {
+ SDL_SetAlpha(transform, SDL_SRCALPHA | SDL_RLEACCEL, alpha);
+ }
+ }
+ /*else
+ {
+ SDL_FreeSurface(transform);
+ }*/
+ }
}
void
SDL_Surface *temp = SDL_CreateRGBSurface(screen->flags, rect.w, rect.h, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask);
SDL_FillRect(temp, 0, color);
- SDL_SetAlpha(temp, SDL_SRCALPHA, a);
+ SDL_SetAlpha(temp, SDL_SRCALPHA | SDL_RLEACCEL, a);
SDL_BlitSurface(temp, 0, screen, &rect);
SDL_FreeSurface(temp);
}
}
void
- Renderer::draw_text(const DrawingRequest& request)
- {
- const TextRequest* textrequest = (TextRequest*) request.request_data;
-
- textrequest->font->draw(this, textrequest->text, request.pos,
- textrequest->alignment, request.drawing_effect, request.alpha);
- }
-
- void
Renderer::draw_filled_rect(const DrawingRequest& request)
{
const FillRectRequest* fillrectrequest
SDL_Surface *temp = SDL_CreateRGBSurface(screen->flags, rect.w, rect.h, screen->format->BitsPerPixel, screen->format->Rmask, screen->format->Gmask, screen->format->Bmask, screen->format->Amask);
SDL_FillRect(temp, 0, color);
- SDL_SetAlpha(temp, SDL_SRCALPHA, a);
+ SDL_SetAlpha(temp, SDL_SRCALPHA | SDL_RLEACCEL, a);
SDL_BlitSurface(temp, 0, screen, &rect);
SDL_FreeSurface(temp);
}
{
// [Christoph] TODO: Yes, this method also takes care of the actual disk I/O. Split it?
- SDL_Surface *shot_surf;
- shot_surf = SDL_GetVideoSurface();
- shot_surf->refcount++;
+ SDL_Surface *screen = SDL_GetVideoSurface();
// save screenshot
static const std::string writeDir = PHYSFS_getWriteDir();
std::string fileName = oss.str();
fullFilename = writeDir + dirSep + fileName;
if (!PHYSFS_exists(fileName.c_str())) {
- SDL_SaveBMP(shot_surf, fullFilename.c_str());
+ SDL_SaveBMP(screen, fullFilename.c_str());
log_debug << "Wrote screenshot to \"" << fullFilename << "\"" << std::endl;
- SDL_FreeSurface(shot_surf);
return;
}
}
log_warning << "Did not save screenshot, because all files up to \"" << fullFilename << "\" already existed" << std::endl;
- SDL_FreeSurface(shot_surf);
}
void