mirror of
https://github.com/TerryCavanagh/VVVVVV.git
synced 2026-01-30 18:04:09 +03:00
Move from surfaces to the SDL render system
Ever since VVVVVV was initially ported to C++ in 2.0, it has used surfaces from SDL. The downside is, that's all software rendering. This commit moves most things off of surfaces, and all into GPU, by using textures and SDL_Renderer. Pixel-perfect collision has been kept by keeping a copy of sprites as surfaces. There's plans for pixel-perfect collision to use masks instead of reading pixel data directly, but that's out of scope for this commit. - `graphics.reloadresources()` is now called later in `main`, because textures cannot be created without a renderer. - This commit also removes a bunch of surface functions which are no longer needed. - This also recaches target textures in certain places for d3d9. - graphics.images was converted to a fixed-size array. - fillbox and fillboxabs use SDL_RenderDrawRect instead of drawing an outline using four filled rectangles - Update my name in the credits
This commit is contained in:
committed by
Misa Elizabeth Kai
parent
556e3a110a
commit
19b2a317f1
@@ -3,8 +3,12 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "Alloc.h"
|
||||
#include "Constants.h"
|
||||
#include "Graphics.h"
|
||||
#include "Maths.h"
|
||||
#include "Screen.h"
|
||||
#include "UtilityClass.h"
|
||||
#include "Vlogging.h"
|
||||
|
||||
|
||||
|
||||
@@ -52,20 +56,6 @@ static SDL_Surface* RecreateSurfaceWithDimensions(
|
||||
return retval;
|
||||
}
|
||||
|
||||
static SDL_Surface* RecreateSurface(SDL_Surface* surface)
|
||||
{
|
||||
if (surface == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return RecreateSurfaceWithDimensions(
|
||||
surface,
|
||||
surface->w,
|
||||
surface->h
|
||||
);
|
||||
}
|
||||
|
||||
SDL_Surface* GetSubSurface( SDL_Surface* metaSurface, int x, int y, int width, int height )
|
||||
{
|
||||
// Create an SDL_Rect with the area of the _surface
|
||||
@@ -89,7 +79,7 @@ SDL_Surface* GetSubSurface( SDL_Surface* metaSurface, int x, int y, int width, i
|
||||
return preSurface;
|
||||
}
|
||||
|
||||
static void DrawPixel(SDL_Surface* surface, const int x, const int y, const SDL_Color color)
|
||||
void DrawPixel(SDL_Surface* surface, const int x, const int y, const SDL_Color color)
|
||||
{
|
||||
const SDL_PixelFormat* fmt = surface->format;
|
||||
const int bpp = fmt->BytesPerPixel;
|
||||
@@ -130,188 +120,6 @@ SDL_Color ReadPixel(const SDL_Surface* surface, const int x, const int y)
|
||||
return color;
|
||||
}
|
||||
|
||||
SDL_Surface * ScaleSurface( SDL_Surface *_surface, int Width, int Height, SDL_Surface * Dest )
|
||||
{
|
||||
if(!_surface || !Width || !Height)
|
||||
return 0;
|
||||
|
||||
SDL_Surface *_ret;
|
||||
if(Dest == NULL)
|
||||
{
|
||||
_ret = RecreateSurfaceWithDimensions(_surface, Width, Height);
|
||||
if(_ret == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
_ret = Dest;
|
||||
}
|
||||
|
||||
SDL_BlitScaled(_surface, NULL, _ret, NULL);
|
||||
|
||||
return _ret;
|
||||
}
|
||||
|
||||
SDL_Surface * FlipSurfaceVerticle(SDL_Surface* _src)
|
||||
{
|
||||
SDL_Surface * ret = RecreateSurface(_src);
|
||||
if(ret == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for(Sint32 y = 0; y < _src->h; y++)
|
||||
{
|
||||
for(Sint32 x = 0; x < _src->w; x++)
|
||||
{
|
||||
DrawPixel(ret, x ,(_src->h-1) - y ,ReadPixel(_src, x, y));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void BlitSurfaceStandard( SDL_Surface* _src, SDL_Rect* _srcRect, SDL_Surface* _dest, SDL_Rect* _destRect )
|
||||
{
|
||||
SDL_BlitSurface( _src, _srcRect, _dest, _destRect );
|
||||
}
|
||||
|
||||
static void BlitSurfaceTransform(
|
||||
SDL_Surface* src,
|
||||
const SDL_Rect* src_rect,
|
||||
SDL_Surface* dest,
|
||||
SDL_Rect* dest_rect,
|
||||
SDL_Color (*transform)(SDL_Color pixel, SDL_Color color),
|
||||
const SDL_Color color
|
||||
) {
|
||||
if (src == NULL || dest == NULL || transform == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (color.a == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_Rect orig_rect;
|
||||
if (src_rect == NULL)
|
||||
{
|
||||
setRect(orig_rect, 0, 0, src->w, src->h);
|
||||
}
|
||||
else
|
||||
{
|
||||
orig_rect = *src_rect;
|
||||
}
|
||||
int blit_x;
|
||||
int blit_y;
|
||||
if (dest_rect == NULL)
|
||||
{
|
||||
blit_x = 0;
|
||||
blit_y = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
blit_x = dest_rect->x;
|
||||
blit_y = dest_rect->y;
|
||||
}
|
||||
|
||||
/* FIXME: Find a way to do this without allocating... */
|
||||
SDL_Surface* tempsurface = RecreateSurfaceWithDimensions(src, orig_rect.w, orig_rect.h);
|
||||
if (tempsurface == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
SDL_SetSurfaceBlendMode(tempsurface, SDL_BLENDMODE_BLEND);
|
||||
|
||||
for (int x = 0; x < orig_rect.w; x++)
|
||||
{
|
||||
for (int y = 0; y < orig_rect.h; y++)
|
||||
{
|
||||
if (blit_x + x < 0 || blit_y + y < 0 ||
|
||||
blit_x + x >= dest->w || blit_y + y >= dest->h)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const SDL_Color pixel = ReadPixel(src, orig_rect.x + x, orig_rect.y + y);
|
||||
if (pixel.a == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const SDL_Color result = transform(pixel, color);
|
||||
DrawPixel(tempsurface, x, y, result);
|
||||
}
|
||||
}
|
||||
|
||||
SDL_Rect final_rect = {blit_x, blit_y, 0, 0};
|
||||
SDL_BlitSurface(tempsurface, NULL, dest, &final_rect);
|
||||
VVV_freefunc(SDL_FreeSurface, tempsurface);
|
||||
}
|
||||
|
||||
static SDL_Color transform_color(const SDL_Color pixel, const SDL_Color color)
|
||||
{
|
||||
const float div1 = pixel.a / 255.0f;
|
||||
const float div2 = color.a / 255.0f;
|
||||
const Uint8 alpha = (div1 * div2) * 255.0f;
|
||||
const SDL_Color result = {color.r, color.g, color.b, alpha};
|
||||
return result;
|
||||
}
|
||||
|
||||
void BlitSurfaceColoured(
|
||||
SDL_Surface* src,
|
||||
const SDL_Rect* src_rect,
|
||||
SDL_Surface* dest,
|
||||
SDL_Rect* dest_rect,
|
||||
const SDL_Color color
|
||||
) {
|
||||
return BlitSurfaceTransform(
|
||||
src, src_rect, dest, dest_rect, transform_color, color
|
||||
);
|
||||
}
|
||||
|
||||
static SDL_Color transform_tint(const SDL_Color pixel, const SDL_Color color)
|
||||
{
|
||||
double red = pixel.r * 0.299;
|
||||
double green = pixel.g * 0.587;
|
||||
double blue = pixel.b * 0.114;
|
||||
|
||||
const double gray = SDL_floor(red + green + blue + 0.5);
|
||||
|
||||
red = gray * color.r / 255.0;
|
||||
green = gray * color.g / 255.0;
|
||||
blue = gray * color.b / 255.0;
|
||||
|
||||
red = SDL_clamp(red, 0, 255);
|
||||
green = SDL_clamp(green, 0, 255);
|
||||
blue = SDL_clamp(blue, 0, 255);
|
||||
|
||||
const float div1 = pixel.a / 255.0f;
|
||||
const float div2 = color.a / 255.0f;
|
||||
const Uint8 alpha = (div1 * div2) * 255.0f;
|
||||
|
||||
const SDL_Color result = {(Uint8) red, (Uint8) green, (Uint8) blue, alpha};
|
||||
return result;
|
||||
}
|
||||
|
||||
void BlitSurfaceTinted(
|
||||
SDL_Surface* src,
|
||||
const SDL_Rect* src_rect,
|
||||
SDL_Surface* dest,
|
||||
SDL_Rect* dest_rect,
|
||||
const SDL_Color color
|
||||
) {
|
||||
return BlitSurfaceTransform(
|
||||
src, src_rect, dest, dest_rect, transform_tint, color
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
static int oldscrollamount = 0;
|
||||
static int scrollamount = 0;
|
||||
static bool isscrolling = 0;
|
||||
@@ -336,15 +144,40 @@ void UpdateFilter(void)
|
||||
}
|
||||
}
|
||||
|
||||
SDL_Surface* ApplyFilter(SDL_Surface* src)
|
||||
void ApplyFilter(void)
|
||||
{
|
||||
SDL_Surface* ret = RecreateSurface(src);
|
||||
// Copy the screen to a temporary surface
|
||||
SDL_Surface* src = SDL_CreateRGBSurface(0, SCREEN_WIDTH_PIXELS, SCREEN_HEIGHT_PIXELS, 32, 0, 0, 0, 0);
|
||||
if (src == NULL)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
Uint32 rawFormat;
|
||||
|
||||
if (graphics.query_texture(graphics.gameTexture, &rawFormat, NULL, NULL, NULL) != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_PixelFormat* format = SDL_AllocFormat(rawFormat);
|
||||
|
||||
// Have a second surface to do work on
|
||||
SDL_Surface* dest = SDL_CreateRGBSurface(0, SCREEN_WIDTH_PIXELS, SCREEN_HEIGHT_PIXELS, 32, 0, 0, 0, 0);
|
||||
|
||||
const int red_offset = rand() % 4;
|
||||
|
||||
for (int x = 0; x < ret->w; x++)
|
||||
for (int x = 0; x < src->w; x++)
|
||||
{
|
||||
for (int y = 0; y < ret->h; y++)
|
||||
for (int y = 0; y < src->h; y++)
|
||||
{
|
||||
const int sampley = (y + (int) graphics.lerp(oldscrollamount, scrollamount)) % 240;
|
||||
|
||||
@@ -389,137 +222,14 @@ SDL_Surface* ApplyFilter(SDL_Surface* src)
|
||||
blue = SDL_max(blue - (distX + distY), 0);
|
||||
|
||||
const SDL_Color color = {red, green, blue, pixel.a};
|
||||
DrawPixel(ret, x, y, color);
|
||||
DrawPixel(dest, x, y, color);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void FillRect( SDL_Surface* _surface, const int _x, const int _y, const int _w, const int _h, const int r, int g, int b )
|
||||
{
|
||||
SDL_Rect rect = {_x, _y, _w, _h};
|
||||
Uint32 color = SDL_MapRGB(_surface->format, r, g, b);
|
||||
SDL_FillRect(_surface, &rect, color);
|
||||
}
|
||||
|
||||
void FillRect( SDL_Surface* _surface, const int r, int g, int b )
|
||||
{
|
||||
Uint32 color = SDL_MapRGB(_surface->format, r, g, b);
|
||||
SDL_FillRect(_surface, NULL, color);
|
||||
}
|
||||
|
||||
void FillRect( SDL_Surface* _surface, SDL_Rect& _rect, const int r, int g, int b )
|
||||
{
|
||||
Uint32 color = SDL_MapRGB(_surface->format, r, g, b);
|
||||
SDL_FillRect(_surface, &_rect, color);
|
||||
}
|
||||
|
||||
void FillRect(SDL_Surface* surface, const SDL_Rect rect, const SDL_Color color)
|
||||
{
|
||||
const Uint32 mapped = SDL_MapRGBA(surface->format, color.r, color.g, color.b, color.a);
|
||||
SDL_FillRect(surface, &rect, mapped);
|
||||
}
|
||||
|
||||
void FillRect(SDL_Surface* surface, const SDL_Color color)
|
||||
{
|
||||
const Uint32 mapped = SDL_MapRGBA(surface->format, color.r, color.g, color.b, color.a);
|
||||
SDL_FillRect(surface, NULL, mapped);
|
||||
}
|
||||
|
||||
void FillRect(SDL_Surface* surface, const int x, const int y, const int w, const int h, const SDL_Color color)
|
||||
{
|
||||
const SDL_Rect rect = {x, y, w, h};
|
||||
const Uint32 mapped = SDL_MapRGBA(surface->format, color.r, color.g, color.b, color.a);
|
||||
SDL_FillRect(surface, &rect, mapped);
|
||||
}
|
||||
|
||||
void FillRect(SDL_Surface* surface, const int r, const int g, const int b, const int a)
|
||||
{
|
||||
const Uint32 mapped = SDL_MapRGBA(surface->format, r, g, b, a);
|
||||
SDL_FillRect(surface, NULL, mapped);
|
||||
}
|
||||
|
||||
void ClearSurface(SDL_Surface* surface)
|
||||
{
|
||||
SDL_FillRect(surface, NULL, 0x00000000);
|
||||
}
|
||||
|
||||
void ScrollSurface( SDL_Surface* _src, int _pX, int _pY )
|
||||
{
|
||||
SDL_Surface* part1 = NULL;
|
||||
|
||||
SDL_Rect rect1;
|
||||
SDL_Rect rect2;
|
||||
//scrolling up;
|
||||
if(_pY < 0)
|
||||
{
|
||||
setRect(rect2, 0, 0, _src->w, _src->h - _pY);
|
||||
|
||||
part1 = GetSubSurface(_src, rect2.x, rect2.y, rect2.w, rect2.h);
|
||||
|
||||
SDL_Rect destrect1;
|
||||
|
||||
SDL_SetSurfaceBlendMode(part1, SDL_BLENDMODE_NONE);
|
||||
|
||||
setRect(destrect1, 0, _pY, _pX, _src->h);
|
||||
|
||||
SDL_BlitSurface (part1, NULL, _src, &destrect1);
|
||||
}
|
||||
|
||||
else if(_pY > 0)
|
||||
{
|
||||
|
||||
setRect(rect1, 0, 0, _src->w, _src->h - _pY);
|
||||
|
||||
part1 = GetSubSurface(_src, rect1.x, rect1.y, rect1.w, rect1.h);
|
||||
|
||||
SDL_Rect destrect1;
|
||||
|
||||
SDL_SetSurfaceBlendMode(part1, SDL_BLENDMODE_NONE);
|
||||
|
||||
setRect(destrect1, _pX, _pY, _src->w, _src->h - _pY);
|
||||
|
||||
SDL_BlitSurface (part1, NULL, _src, &destrect1);
|
||||
|
||||
}
|
||||
|
||||
//Right
|
||||
else if(_pX <= 0)
|
||||
{
|
||||
setRect(rect2, 0, 0, _src->w - _pX, _src->h );
|
||||
|
||||
part1 = GetSubSurface(_src, rect2.x, rect2.y, rect2.w, rect2.h);
|
||||
|
||||
SDL_Rect destrect1;
|
||||
|
||||
SDL_SetSurfaceBlendMode(part1, SDL_BLENDMODE_NONE);
|
||||
|
||||
setRect(destrect1, _pX, 0, _src->w - _pX, _src->h);
|
||||
|
||||
SDL_BlitSurface (part1, NULL, _src, &destrect1);
|
||||
}
|
||||
|
||||
else if(_pX > 0)
|
||||
{
|
||||
|
||||
setRect(rect1, _pX, 0, _src->w - _pX, _src->h );
|
||||
|
||||
part1 = GetSubSurface(_src, rect1.x, rect1.y, rect1.w, rect1.h);
|
||||
|
||||
SDL_Rect destrect1;
|
||||
|
||||
SDL_SetSurfaceBlendMode(part1, SDL_BLENDMODE_NONE);
|
||||
|
||||
setRect(destrect1, 0, 0, _src->w - _pX, _src->h);
|
||||
|
||||
SDL_BlitSurface (part1, NULL, _src, &destrect1);
|
||||
|
||||
}
|
||||
//Cleanup temp surface
|
||||
if (part1)
|
||||
{
|
||||
VVV_freefunc(SDL_FreeSurface, part1);
|
||||
}
|
||||
|
||||
SDL_FreeFormat(format);
|
||||
|
||||
SDL_UpdateTexture(graphics.gameTexture, NULL, dest->pixels, dest->pitch);
|
||||
|
||||
SDL_FreeSurface(src);
|
||||
SDL_FreeSurface(dest);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user