X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=src%2Fvideo%2Fsdl_renderer.cpp;h=56cb6b89918092f339e276ab674cdbfcf1838c88;hb=d427db3e7c37d524e540511dd8cfce6e985bf32b;hp=f4bae637723fc6e025e80560b79b3206eaaf8c91;hpb=20efd7620620892d92b1c7df124c3a0c8df22a82;p=supertux.git diff --git a/src/video/sdl_renderer.cpp b/src/video/sdl_renderer.cpp index f4bae6377..56cb6b899 100644 --- a/src/video/sdl_renderer.cpp +++ b/src/video/sdl_renderer.cpp @@ -31,35 +31,148 @@ #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; + ::Renderer::instance_ = this; + + 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; + + int width = 800; //FIXME: config->screenwidth; + int height = 600; //FIXME: config->screenheight; - 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()); } + numerator = 1; + denominator = 1; + /* FIXME: + 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(); } @@ -73,7 +186,9 @@ namespace SDL { //FIXME: support parameters request.alpha, request.angle, request.blend const Surface* surface = (const Surface*) request.request_data; - SDL::Texture *sdltexture = dynamic_cast(surface->get_texture()); + SDL::Texture *sdltexture = dynamic_cast(surface->get_texture()); + SDL::SurfaceData *surface_data = reinterpret_cast(surface->get_surface_data()); + DrawingEffect effect = request.drawing_effect; if (surface->get_flipx()) effect = HORIZONTAL_FLIP; @@ -85,49 +200,52 @@ namespace SDL 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 @@ -137,7 +255,8 @@ namespace SDL = (SurfacePartRequest*) request.request_data; const Surface* surface = surfacepartrequest->surface; - SDL::Texture *sdltexture = dynamic_cast(surface->get_texture()); + SDL::Texture *sdltexture = dynamic_cast(surface->get_texture()); + DrawingEffect effect = request.drawing_effect; if (surface->get_flipx()) effect = HORIZONTAL_FLIP; @@ -167,31 +286,57 @@ namespace SDL 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 @@ -222,7 +367,7 @@ namespace SDL 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); } @@ -230,15 +375,6 @@ namespace SDL } 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 @@ -260,20 +396,23 @@ namespace SDL 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_inverse_ellipse(const DrawingRequest&) + { + } + void Renderer::do_take_screenshot() { // [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(); @@ -289,14 +428,12 @@ namespace SDL 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 @@ -304,4 +441,10 @@ namespace SDL { SDL_Flip(screen); } + + void + Renderer::resize(int, int) + { + + } }