#include #include #include #include "Alloc.h" #include "Constants.h" #include "Graphics.h" #include "Maths.h" #include "Screen.h" #include "UtilityClass.h" #include "Vlogging.h" void setRect( SDL_Rect& _r, int x, int y, int w, int h ) { _r.x = x; _r.y = y; _r.w = w; _r.h = h; } static SDL_Surface* RecreateSurfaceWithDimensions( SDL_Surface* surface, const int width, const int height ) { SDL_Surface* retval; SDL_BlendMode blend_mode; if (surface == NULL) { return NULL; } retval = SDL_CreateRGBSurface( surface->flags, width, height, surface->format->BitsPerPixel, surface->format->Rmask, surface->format->Gmask, surface->format->Bmask, surface->format->Amask ); if (retval == NULL) { return NULL; } SDL_GetSurfaceBlendMode(surface, &blend_mode); SDL_SetSurfaceBlendMode(retval, blend_mode); return retval; } SDL_Surface* GetSubSurface( SDL_Surface* metaSurface, int x, int y, int width, int height ) { // Create an SDL_Rect with the area of the _surface SDL_Rect area; area.x = x; area.y = y; area.w = width; area.h = height; //Convert to the correct display format after nabbing the new _surface or we will slow things down. SDL_Surface* preSurface = RecreateSurfaceWithDimensions( metaSurface, width, height ); // Lastly, apply the area from the meta _surface onto the whole of the sub _surface. SDL_BlitSurface(metaSurface, &area, preSurface, 0); // Return the new Bitmap _surface return preSurface; } void DrawPixel(SDL_Surface* surface, const int x, const int y, const SDL_Color color) { const SDL_Point point = {x, y}; const SDL_Rect rect = {0, 0, surface->w, surface->h}; const bool inbounds = SDL_PointInRect(&point, &rect); if (!inbounds) { WHINE_ONCE_ARGS(( "Pixel draw is not inbounds: " "Attempted to draw to %i,%i in %ix%i surface", x, y, surface->w, surface->h )); SDL_assert(0 && "Pixel draw is not inbounds!"); return; } const SDL_PixelFormat* fmt = surface->format; const int bpp = fmt->BytesPerPixel; Uint8* pixel = (Uint8*) surface->pixels + y * surface->pitch + x * bpp; Uint32* pixel32 = (Uint32*) pixel; switch (bpp) { case 1: case 2: SDL_assert(0 && "Colors other than 24- or 32- bit unsupported!"); break; case 3: { const Uint32 single = SDL_MapRGB(fmt, color.r, color.g, color.b); pixel[0] = (single & 0xFF0000) >> 16; pixel[1] = (single & 0x00FF00) >> 8; pixel[2] = (single & 0x0000FF) >> 0; break; } case 4: *pixel32 = SDL_MapRGBA(fmt, color.r, color.g, color.b, color.a); } } SDL_Color ReadPixel(const SDL_Surface* surface, const int x, const int y) { SDL_Color color = {0, 0, 0, 0}; const SDL_Point point = {x, y}; const SDL_Rect rect = {0, 0, surface->w, surface->h}; const bool inbounds = SDL_PointInRect(&point, &rect); if (!inbounds) { WHINE_ONCE_ARGS(( "Pixel read is not inbounds: " "Attempted to read %i,%i in %ix%i surface", x, y, surface->w, surface->h )); SDL_assert(0 && "Pixel read is not inbounds!"); return color; } const SDL_PixelFormat* fmt = surface->format; const int bpp = surface->format->BytesPerPixel; const Uint8* pixel = (Uint8*) surface->pixels + y * surface->pitch + x * bpp; const Uint32* pixel32 = (Uint32*) pixel; switch (bpp) { case 1: case 2: SDL_assert(0 && "Colors other than 24- or 32- bit unsupported!"); break; case 3: { const Uint32 single = (pixel[0] << 16) | (pixel[1] << 8) | (pixel[2] << 0); SDL_GetRGB(single, fmt, &color.r, &color.g, &color.b); color.a = 255; break; } case 4: SDL_GetRGBA(*pixel32, fmt, &color.r, &color.g, &color.b, &color.a); } return color; } static int oldscrollamount = 0; static int scrollamount = 0; static bool isscrolling = 0; void UpdateFilter(void) { if (rand() % 4000 < 8) { isscrolling = true; } oldscrollamount = scrollamount; if(isscrolling == true) { scrollamount += 20; if(scrollamount > 240) { scrollamount = 0; oldscrollamount = 0; isscrolling = false; } } } void ApplyFilter(SDL_Surface** src, SDL_Surface** dest) { if (src == NULL || dest == NULL) { SDL_assert(0 && "NULL src or dest!"); return; } if (*src == NULL) { *src = SDL_CreateRGBSurface(0, SCREEN_WIDTH_PIXELS, SCREEN_HEIGHT_PIXELS, 32, 0, 0, 0, 0); } if (*dest == NULL) { *dest = SDL_CreateRGBSurface(0, SCREEN_WIDTH_PIXELS, SCREEN_HEIGHT_PIXELS, 32, 0, 0, 0, 0); } if (*src == NULL || *dest == NULL) { WHINE_ONCE_ARGS(("Could not create temporary surfaces: %s", SDL_GetError())); return; } const int result = SDL_RenderReadPixels(gameScreen.m_renderer, NULL, 0, (*src)->pixels, (*src)->pitch); if (result != 0) { SDL_FreeSurface(*src); WHINE_ONCE_ARGS(("Could not read pixels from renderer: %s", SDL_GetError())); return; } const int red_offset = rand() % 4; for (int x = 0; x < (*src)->w; x++) { for (int y = 0; y < (*src)->h; y++) { const int sampley = (y + (int) graphics.lerp(oldscrollamount, scrollamount)) % 240; const SDL_Color pixel = ReadPixel(*src, x, sampley); Uint8 green = pixel.g; Uint8 blue = pixel.b; const SDL_Color pixel_offset = ReadPixel(*src, SDL_min(x + red_offset, 319), sampley); Uint8 red = pixel_offset.r; double mult; int tmp; /* needed to avoid char overflow */ if (isscrolling && sampley > 220 && ((rand() % 10) < 4)) { mult = 0.6; } else { mult = 0.2; } tmp = red + fRandom() * mult * 254; red = SDL_min(tmp, 255); tmp = green + fRandom() * mult * 254; green = SDL_min(tmp, 255); tmp = blue + fRandom() * mult * 254; blue = SDL_min(tmp, 255); if (y % 2 == 0) { red = (Uint8) (red / 1.2f); green = (Uint8) (green / 1.2f); blue = (Uint8) (blue / 1.2f); } int distX = (int) ((SDL_abs(160.0f - x) / 160.0f) * 16); int distY = (int) ((SDL_abs(120.0f - y) / 120.0f) * 32); red = SDL_max(red - (distX + distY), 0); green = SDL_max(green - (distX + distY), 0); blue = SDL_max(blue - (distX + distY), 0); const SDL_Color color = {red, green, blue, pixel.a}; DrawPixel(*dest, x, y, color); } } SDL_UpdateTexture(graphics.gameTexture, NULL, (*dest)->pixels, (*dest)->pitch); } bool TakeScreenshot(SDL_Surface** surface) { if (surface == NULL) { SDL_assert(0 && "surface is NULL!"); return false; } int width = 0; int height = 0; int result = graphics.query_texture( graphics.gameTexture, NULL, NULL, &width, &height ); if (result != 0) { return false; } if (*surface == NULL) { *surface = SDL_CreateRGBSurface(0, width, height, 24, 0, 0, 0, 0); if (*surface == NULL) { WHINE_ONCE_ARGS( ("Could not create temporary surface: %s", SDL_GetError()) ); return false; } } if ((*surface)->w != width || (*surface)->h != height) { SDL_assert(0 && "Width and height of surface and texture mismatch!"); return false; } result = graphics.set_render_target(graphics.gameTexture); if (result != 0) { return false; } result = SDL_RenderReadPixels( gameScreen.m_renderer, NULL, SDL_PIXELFORMAT_RGB24, (*surface)->pixels, (*surface)->pitch ); if (result != 0) { WHINE_ONCE_ARGS( ("Could not read pixels from renderer: %s", SDL_GetError()) ); return false; } /* Need to manually vertically reverse pixels in Flip Mode. */ if (graphics.flipmode) { for (int x = 0; x < (*surface)->w; x++) { for (int y = 0; y < (*surface)->h / 2; y++) { const SDL_Color upper = ReadPixel(*surface, x, y); const SDL_Color lower = ReadPixel(*surface, x, (*surface)->h - 1 - y); DrawPixel(*surface, x, y, lower); DrawPixel(*surface, x, (*surface)->h - 1 - y, upper); } } } return true; }