Overhauled graphics system
Along with being more accurate to the original, this fixes switching out of fullscreen causing textures to disappear. This was caused by DirectX destroying textures that are marked as render-targets when a device-loss occurs. SDL2 doesn't do anything to recover them, unlike regular textures, so my solution is just to avoid render-target textures entirely. On the upside, this should make drawing text to surfaces much faster, since we're not reading back bitmaps from the GPU.
This commit is contained in:
parent
ba13b8aeea
commit
4f7db164d6
4 changed files with 233 additions and 220 deletions
412
src/Draw.cpp
412
src/Draw.cpp
|
@ -64,101 +64,157 @@ bool Flip_SystemTask()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool StartDirectDraw()
|
||||
static bool IsEnableBitmap(SDL_RWops *fp)
|
||||
{
|
||||
//Create renderer
|
||||
gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_TARGETTEXTURE);
|
||||
return true;
|
||||
}
|
||||
char str[16];
|
||||
const char *extra_text = "(C)Pixel";
|
||||
|
||||
void EndDirectDraw()
|
||||
{
|
||||
//Release all surfaces
|
||||
for (int i = 0; i < SURFACE_ID_MAX; i++)
|
||||
{
|
||||
if (surf[i].texture)
|
||||
{
|
||||
SDL_DestroyTexture(surf[i].texture);
|
||||
surf[i].texture = NULL;
|
||||
}
|
||||
}
|
||||
const size_t len = strlen(extra_text);
|
||||
|
||||
fp->seek(fp, -len, RW_SEEK_END);
|
||||
fp->read(fp, str, 1, len);
|
||||
fp->seek(fp, 0, RW_SEEK_SET);
|
||||
return memcmp(str, extra_text, len) == 0;
|
||||
}
|
||||
|
||||
void ReleaseSurface(int s)
|
||||
{
|
||||
//Release the surface we want to release
|
||||
if (surf[s].texture)
|
||||
if (surf[s].in_use)
|
||||
{
|
||||
SDL_DestroyTexture(surf[s].texture);
|
||||
surf[s].texture = NULL;
|
||||
SDL_FreeSurface(surf[s].surface);
|
||||
surf[s].in_use = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool MakeSurface(SDL_RWops *fp, int surf_no)
|
||||
bool MakeSurface_Generic(int bxsize, int bysize, int surf_no)
|
||||
{
|
||||
//Check if surf_no can be used
|
||||
if (surf_no > SURFACE_ID_MAX)
|
||||
bool success = false;
|
||||
|
||||
#ifdef FIX_BUGS
|
||||
if (surf_no >= SURFACE_ID_MAX)
|
||||
#else
|
||||
if (surf_no > SURFACE_ID_MAX) // OOPS (should be '>=')
|
||||
#endif
|
||||
{
|
||||
printf("Tried to create surface with invalid id %d\n", surf_no);
|
||||
return false;
|
||||
printf("Tried to create drawable surface at invalid slot (%d - maximum is %d)\n", surf_no, SURFACE_ID_MAX);
|
||||
}
|
||||
if (surf[surf_no].texture)
|
||||
else
|
||||
{
|
||||
printf("Tried to create surface at id %d, but there's already a texture there\n", surf_no);
|
||||
return false;
|
||||
if (surf[surf_no].in_use == true)
|
||||
{
|
||||
printf("Tried to create drawable surface at occupied slot (%d)\n", surf_no);
|
||||
}
|
||||
else
|
||||
{
|
||||
//Create surface
|
||||
surf[surf_no].surface = SDL_CreateRGBSurfaceWithFormat(0, bxsize * gWindowScale, bysize * gWindowScale, 0, SDL_PIXELFORMAT_RGBA32);
|
||||
|
||||
if (surf[surf_no].surface == NULL)
|
||||
{
|
||||
printf("Failed to create drawable surface %d (SDL_CreateRGBSurfaceWithFormat)\nSDL Error: %s\n", surf_no, SDL_GetError());
|
||||
}
|
||||
else
|
||||
{
|
||||
surf[surf_no].texture = SDL_CreateTexture(gRenderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_STREAMING, bxsize * gWindowScale, bysize * gWindowScale);
|
||||
|
||||
if (surf[surf_no].texture == NULL)
|
||||
{
|
||||
printf("Failed to create drawable surface %d (SDL_CreateTexture)\nSDL Error: %s\n", surf_no, SDL_GetError());
|
||||
SDL_FreeSurface(surf[surf_no].surface);
|
||||
}
|
||||
else
|
||||
{
|
||||
surf[surf_no].in_use = true;
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Load surface from file
|
||||
SDL_Surface *surface = SDL_LoadBMP_RW(fp, 1);
|
||||
if (!surface)
|
||||
{
|
||||
printf("Couldn't load bitmap for surface id %d\nSDL Error: %s\n", surf_no, SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
//Make sure surface has color key on
|
||||
SDL_SetColorKey(surface, SDL_TRUE, SDL_MapRGB(surface->format, 0, 0, 0));
|
||||
|
||||
//Get texture from surface
|
||||
SDL_Texture *texture = SDL_CreateTextureFromSurface(gRenderer, surface);
|
||||
if (!texture)
|
||||
{
|
||||
printf("Failed to convert SDL_Surface to SDL_Texture for surface id %d\nSDL Error: %s\n", surf_no, SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
//Create real texture, and copy loaded texture here (has texture target access)
|
||||
int w, h;
|
||||
SDL_QueryTexture(texture, NULL, NULL, &w, &h);
|
||||
|
||||
SDL_Texture *textureAccessible = SDL_CreateTexture(gRenderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_TARGET, w * gWindowScale, h * gWindowScale);
|
||||
|
||||
if (!textureAccessible)
|
||||
{
|
||||
printf("Failed to create real texture for surface id %d\nSDL Error: %s\n", surf_no, SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
SDL_SetTextureBlendMode(textureAccessible, SDL_BLENDMODE_BLEND);
|
||||
|
||||
SDL_SetRenderTarget(gRenderer, textureAccessible);
|
||||
SDL_SetRenderDrawColor(gRenderer, 0, 0, 0, 0);
|
||||
SDL_RenderClear(gRenderer);
|
||||
SDL_RenderCopy(gRenderer, texture, NULL, NULL);
|
||||
SDL_SetRenderTarget(gRenderer, NULL);
|
||||
|
||||
//Set surface's metadata
|
||||
surf[surf_no].texture = textureAccessible;
|
||||
|
||||
//Free surface and texture
|
||||
SDL_DestroyTexture(texture);
|
||||
SDL_FreeSurface(surface);
|
||||
|
||||
printf(" ^ Successfully loaded\n");
|
||||
return true;
|
||||
return success;
|
||||
}
|
||||
|
||||
bool MakeSurface_File(const char *name, int surf_no)
|
||||
static void FlushSurface(int surf_no)
|
||||
{
|
||||
unsigned char *raw_pixels;
|
||||
int pitch;
|
||||
SDL_LockTexture(surf[surf_no].texture, NULL, (void**)&raw_pixels, &pitch);
|
||||
|
||||
unsigned char (*src_pixels)[surf[surf_no].surface->pitch / 4][4] = (unsigned char (*)[surf[surf_no].surface->pitch/ 4][4])surf[surf_no].surface->pixels;
|
||||
unsigned char (*dst_pixels)[pitch / 4][4] = (unsigned char (*)[pitch/ 4][4])raw_pixels;
|
||||
|
||||
for (unsigned int h = 0; h < surf[surf_no].surface->h; ++h)
|
||||
{
|
||||
for (unsigned int w = 0; w < surf[surf_no].surface->w; ++w)
|
||||
{
|
||||
dst_pixels[h][w][0] = src_pixels[h][w][0];
|
||||
dst_pixels[h][w][1] = src_pixels[h][w][1];
|
||||
dst_pixels[h][w][2] = src_pixels[h][w][2];
|
||||
|
||||
if (src_pixels[h][w][0] || src_pixels[h][w][1] || src_pixels[h][w][2]) // Colour-key
|
||||
dst_pixels[h][w][3] = 0xFF;
|
||||
else
|
||||
dst_pixels[h][w][3] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_UnlockTexture(surf[surf_no].texture);
|
||||
}
|
||||
|
||||
static bool LoadBitmap(SDL_RWops *fp, int surf_no, bool create_surface)
|
||||
{
|
||||
bool success = false;
|
||||
|
||||
if (surf_no >= SURFACE_ID_MAX)
|
||||
{
|
||||
printf("Tried to load bitmap at invalid slot (%d - maximum is %d\n", surf_no, SURFACE_ID_MAX);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (create_surface && surf[surf_no].in_use)
|
||||
{
|
||||
printf("Tried to create drawable surface at occupied slot (%d)\n", surf_no);
|
||||
}
|
||||
else
|
||||
{
|
||||
SDL_Surface *surface = SDL_LoadBMP_RW(fp, 1);
|
||||
|
||||
if (surface == NULL)
|
||||
{
|
||||
printf("Couldn't load bitmap for surface id %d\nSDL Error: %s\n", surf_no, SDL_GetError());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (create_surface == false || MakeSurface_Generic(surface->w, surface->h, surf_no))
|
||||
{
|
||||
SDL_Surface *converted_surface = SDL_ConvertSurface(surface, surf[surf_no].surface->format, 0);
|
||||
|
||||
if (converted_surface == NULL)
|
||||
{
|
||||
printf("Couldn't convert bitmap to surface format (surface id %d)\nSDL Error: %s\n", surf_no, SDL_GetError());
|
||||
}
|
||||
else
|
||||
{
|
||||
SDL_Rect dst_rect = {0, 0, converted_surface->w * gWindowScale, converted_surface->h * gWindowScale};
|
||||
SDL_BlitScaled(converted_surface, NULL, surf[surf_no].surface, &dst_rect);
|
||||
SDL_FreeSurface(converted_surface);
|
||||
surf[surf_no].needs_updating = true;
|
||||
printf(" ^ Successfully loaded\n");
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_FreeSurface(surface);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
static bool LoadBitmap_File(const char *name, int surf_no, bool create_surface)
|
||||
{
|
||||
char path[PATH_LENGTH];
|
||||
SDL_RWops *fp;
|
||||
|
@ -168,9 +224,16 @@ bool MakeSurface_File(const char *name, int surf_no)
|
|||
fp = SDL_RWFromFile(path, "rb");
|
||||
if (fp)
|
||||
{
|
||||
printf("Loading surface (as .pbm) from %s for surface id %d\n", path, surf_no);
|
||||
if (MakeSurface(fp, surf_no))
|
||||
return true;
|
||||
if (!IsEnableBitmap(fp))
|
||||
{
|
||||
printf("Tried to load bitmap to surface %d, but it's missing the '(C)Pixel' string\n", surf_no);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Loading surface (as .pbm) from %s for surface id %d\n", path, surf_no);
|
||||
if (LoadBitmap(fp, surf_no, create_surface))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//Attempt to load BMP
|
||||
|
@ -178,23 +241,31 @@ bool MakeSurface_File(const char *name, int surf_no)
|
|||
fp = SDL_RWFromFile(path, "rb");
|
||||
if (fp)
|
||||
{
|
||||
printf("Loading surface (as .bmp) from %s for surface id %d\n", path, surf_no);
|
||||
if (MakeSurface(fp, surf_no))
|
||||
return true;
|
||||
if (!IsEnableBitmap(fp))
|
||||
{
|
||||
printf("Tried to load bitmap to surface %d, but it's missing the '(C)Pixel' string\n", surf_no);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
printf("Loading surface (as .bmp) from %s for surface id %d\n", path, surf_no);
|
||||
if (LoadBitmap(fp, surf_no, create_surface))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
printf("Failed to open file %s\n", name);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MakeSurface_Resource(const char *res, int surf_no)
|
||||
static bool LoadBitmap_Resource(const char *res, int surf_no, bool create_surface)
|
||||
{
|
||||
SDL_RWops *fp = FindResource(res);
|
||||
|
||||
if (fp)
|
||||
{
|
||||
printf("Loading surface from resource %s for surface id %d\n", res, surf_no);
|
||||
if (MakeSurface(fp, surf_no))
|
||||
if (LoadBitmap(fp, surf_no, create_surface))
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -202,34 +273,24 @@ bool MakeSurface_Resource(const char *res, int surf_no)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool MakeSurface_File(const char *name, int surf_no)
|
||||
{
|
||||
return LoadBitmap_File(name, surf_no, true);
|
||||
}
|
||||
|
||||
bool MakeSurface_Resource(const char *res, int surf_no)
|
||||
{
|
||||
return LoadBitmap_Resource(res, surf_no, true);
|
||||
}
|
||||
|
||||
bool ReloadBitmap_File(const char *name, int surf_no)
|
||||
{
|
||||
ReleaseSurface(surf_no);
|
||||
return MakeSurface_File(name, surf_no);
|
||||
return LoadBitmap_File(name, surf_no, false);
|
||||
}
|
||||
|
||||
bool ReloadBitmap_Resource(const char *res, int surf_no)
|
||||
{
|
||||
ReleaseSurface(surf_no);
|
||||
return MakeSurface_Resource(res, surf_no);
|
||||
}
|
||||
|
||||
bool MakeSurface_Generic(int bxsize, int bysize, int surf_no)
|
||||
{
|
||||
//Delete old surface
|
||||
ReleaseSurface(surf_no);
|
||||
|
||||
//Create surface
|
||||
surf[surf_no].texture = SDL_CreateTexture(gRenderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_TARGET, bxsize * gWindowScale, bysize * gWindowScale);
|
||||
|
||||
if (!surf[surf_no].texture)
|
||||
{
|
||||
printf("Failed to create drawable surface %d\nSDL Error: %s\n", surf_no, SDL_GetError());
|
||||
return false;
|
||||
}
|
||||
|
||||
SDL_SetTextureBlendMode(surf[surf_no].texture, SDL_BLENDMODE_BLEND);
|
||||
return true;
|
||||
return LoadBitmap_Resource(res, surf_no, false);
|
||||
}
|
||||
|
||||
SDL_Rect RectToSDLRect(RECT *rect)
|
||||
|
@ -246,42 +307,27 @@ void BackupSurface(int surf_no, RECT *rect)
|
|||
|
||||
//Get texture of what's currently rendered on screen
|
||||
SDL_Surface *surface = SDL_CreateRGBSurfaceWithFormat(0, w, h, 0, SDL_PIXELFORMAT_RGBA32);
|
||||
SDL_RenderReadPixels(gRenderer, nullptr, SDL_PIXELFORMAT_RGBA32, surface->pixels, surface->pitch);
|
||||
|
||||
SDL_Texture *screenTexture = SDL_CreateTextureFromSurface(gRenderer, surface);
|
||||
|
||||
//Free surface
|
||||
SDL_FreeSurface(surface);
|
||||
SDL_RenderReadPixels(gRenderer, NULL, SDL_PIXELFORMAT_RGBA32, surface->pixels, surface->pitch);
|
||||
|
||||
//Get rects
|
||||
SDL_Rect frameRect = RectToSDLRect(rect);
|
||||
frameRect = {frameRect.x * gWindowScale, frameRect.y * gWindowScale, frameRect.w * gWindowScale, frameRect.h * gWindowScale};
|
||||
|
||||
SDL_Texture *textureAccessible = SDL_CreateTexture(gRenderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_TARGET, frameRect.w, frameRect.h);
|
||||
SDL_BlitSurface(surface, &frameRect, surf[surf_no].surface, &frameRect);
|
||||
surf[surf_no].needs_updating = true;
|
||||
|
||||
if (!textureAccessible)
|
||||
{
|
||||
printf("Failed to create real texture for surface id %d\nSDL Error: %s\n", surf_no, SDL_GetError());
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_SetTextureBlendMode(textureAccessible, SDL_BLENDMODE_BLEND);
|
||||
|
||||
SDL_SetRenderTarget(gRenderer, textureAccessible);
|
||||
SDL_SetRenderDrawColor(gRenderer, 0, 0, 0, 0);
|
||||
SDL_RenderClear(gRenderer);
|
||||
SDL_RenderCopy(gRenderer, screenTexture, &frameRect, NULL);
|
||||
SDL_SetRenderTarget(gRenderer, NULL);
|
||||
|
||||
//Set surface's metadata
|
||||
surf[surf_no].texture = textureAccessible;
|
||||
|
||||
//Free stuff
|
||||
SDL_DestroyTexture(screenTexture);
|
||||
//Free surface
|
||||
SDL_FreeSurface(surface);
|
||||
}
|
||||
|
||||
void PutBitmap3(RECT *rcView, int x, int y, RECT *rect, int surf_no) //Transparency
|
||||
static void DrawBitmap(RECT *rcView, int x, int y, RECT *rect, int surf_no, bool transparent)
|
||||
{
|
||||
if (surf[surf_no].needs_updating)
|
||||
{
|
||||
FlushSurface(surf_no);
|
||||
surf[surf_no].needs_updating = false;
|
||||
}
|
||||
|
||||
//Get SDL_Rects
|
||||
SDL_Rect clipRect = RectToSDLRect(rcView);
|
||||
|
||||
|
@ -295,6 +341,8 @@ void PutBitmap3(RECT *rcView, int x, int y, RECT *rect, int surf_no) //Transpare
|
|||
clipRect = {clipRect.x * gWindowScale, clipRect.y * gWindowScale, clipRect.w * gWindowScale, clipRect.h * gWindowScale};
|
||||
SDL_RenderSetClipRect(gRenderer, &clipRect);
|
||||
|
||||
SDL_SetTextureBlendMode(surf[surf_no].texture, transparent ? SDL_BLENDMODE_BLEND : SDL_BLENDMODE_NONE);
|
||||
|
||||
//Draw to screen
|
||||
if (SDL_RenderCopy(gRenderer, surf[surf_no].texture, &frameRect, &destRect) < 0)
|
||||
printf("Failed to draw texture %d\nSDL Error: %s\n", surf_no, SDL_GetError());
|
||||
|
@ -303,36 +351,14 @@ void PutBitmap3(RECT *rcView, int x, int y, RECT *rect, int surf_no) //Transpare
|
|||
SDL_RenderSetClipRect(gRenderer, NULL);
|
||||
}
|
||||
|
||||
void PutBitmap3(RECT *rcView, int x, int y, RECT *rect, int surf_no) //Transparency
|
||||
{
|
||||
DrawBitmap(rcView, x, y, rect, surf_no, true);
|
||||
}
|
||||
|
||||
void PutBitmap4(RECT *rcView, int x, int y, RECT *rect, int surf_no) //No Transparency
|
||||
{
|
||||
//Get SDL_Rects
|
||||
SDL_Rect clipRect = RectToSDLRect(rcView);
|
||||
|
||||
SDL_Rect frameRect = RectToSDLRect(rect);
|
||||
frameRect = {frameRect.x * gWindowScale, frameRect.y * gWindowScale, frameRect.w * gWindowScale, frameRect.h * gWindowScale};
|
||||
|
||||
//Get dest rect
|
||||
SDL_Rect destRect = {x * gWindowScale, y * gWindowScale, frameRect.w, frameRect.h};
|
||||
|
||||
//Set cliprect
|
||||
clipRect = {clipRect.x * gWindowScale, clipRect.y * gWindowScale, clipRect.w * gWindowScale, clipRect.h * gWindowScale};
|
||||
SDL_RenderSetClipRect(gRenderer, &clipRect);
|
||||
|
||||
//Get original drawing colour
|
||||
uint8_t origR, origG, origB, origA;
|
||||
SDL_GetRenderDrawColor(gRenderer, &origR, &origG, &origB, &origA);
|
||||
|
||||
//Draw black behind texture
|
||||
SDL_SetRenderDrawColor(gRenderer, 0, 0, 0, 0xFF);
|
||||
SDL_RenderFillRect(gRenderer, &destRect);
|
||||
|
||||
//Draw texture
|
||||
if (SDL_RenderCopy(gRenderer, surf[surf_no].texture, &frameRect, &destRect) < 0)
|
||||
printf("Failed to draw texture %d\nSDL Error: %s\n", surf_no, SDL_GetError());
|
||||
|
||||
//Restore original colour, and undo cliprect
|
||||
SDL_RenderSetClipRect(gRenderer, NULL);
|
||||
SDL_SetRenderDrawColor(gRenderer, origR, origG, origB, origA);
|
||||
DrawBitmap(rcView, x, y, rect, surf_no, false);
|
||||
}
|
||||
|
||||
void Surface2Surface(int x, int y, RECT *rect, int to, int from)
|
||||
|
@ -342,21 +368,8 @@ void Surface2Surface(int x, int y, RECT *rect, int to, int from)
|
|||
SDL_Rect frameRect = RectToSDLRect(rect);
|
||||
frameRect = {frameRect.x * gWindowScale, frameRect.y * gWindowScale, frameRect.w * gWindowScale, frameRect.h * gWindowScale};
|
||||
|
||||
//Target surface
|
||||
if (!surf[to].texture)
|
||||
{
|
||||
printf("Tried to draw to surface %d, which doesn't exist\n", to);
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_SetRenderTarget(gRenderer, surf[to].texture);
|
||||
|
||||
//Draw texture
|
||||
if (SDL_RenderCopy(gRenderer, surf[from].texture, &frameRect, &rcSet) < 0)
|
||||
printf("Failed to draw texture %d to %d\nSDL Error: %s\n", from, to, SDL_GetError());
|
||||
|
||||
//Stop targetting surface
|
||||
SDL_SetRenderTarget(gRenderer, NULL);
|
||||
SDL_BlitSurface(surf[from].surface, &frameRect, surf[to].surface, &rcSet);
|
||||
surf[to].needs_updating = true;
|
||||
}
|
||||
|
||||
void CortBox(RECT *rect, uint32_t col)
|
||||
|
@ -376,26 +389,11 @@ void CortBox2(RECT *rect, uint32_t col, int surf_no)
|
|||
SDL_Rect destRect = RectToSDLRect(rect);
|
||||
destRect = {destRect.x * gWindowScale, destRect.y * gWindowScale, destRect.w * gWindowScale, destRect.h * gWindowScale};
|
||||
|
||||
//Target surface
|
||||
if (!surf[surf_no].texture)
|
||||
{
|
||||
printf("Tried to draw a rectangle to surface %d, which doesn't exist\n", surf_no);
|
||||
return;
|
||||
}
|
||||
|
||||
SDL_SetRenderTarget(gRenderer, surf[surf_no].texture);
|
||||
|
||||
const unsigned char col_red = (col & 0xFF0000) >> 16;
|
||||
const unsigned char col_green = (col & 0x00FF00) >> 8;
|
||||
const unsigned char col_blue = col & 0x0000FF;
|
||||
const unsigned char col_alpha = (col_red || col_green || col_blue) ? 0xFF : 0;
|
||||
|
||||
//Set colour and draw
|
||||
SDL_SetRenderDrawColor(gRenderer, col_red, col_green, col_blue, col_alpha);
|
||||
SDL_RenderFillRect(gRenderer, &destRect);
|
||||
|
||||
//Stop targetting surface
|
||||
SDL_SetRenderTarget(gRenderer, NULL);
|
||||
SDL_FillRect(surf[surf_no].surface, &destRect, SDL_MapRGB(surf[surf_no].surface->format, col_red, col_green, col_blue));
|
||||
surf[surf_no].needs_updating = true;
|
||||
}
|
||||
|
||||
#ifdef WINDOWS
|
||||
|
@ -491,12 +489,24 @@ void InitTextObject(const char *font_name)
|
|||
|
||||
void PutText(int x, int y, const char *text, uint32_t color)
|
||||
{
|
||||
DrawText(gFont, gRenderer, NULL, x * gWindowScale, y * gWindowScale, color, text, strlen(text));
|
||||
int surface_width, surface_height;
|
||||
SDL_GetRendererOutputSize(gRenderer, &surface_width, &surface_height);
|
||||
|
||||
SDL_Surface *surface = SDL_CreateRGBSurfaceWithFormat(0, surface_width, surface_height, 0, SDL_PIXELFORMAT_RGBA32);
|
||||
SDL_RenderReadPixels(gRenderer, NULL, SDL_PIXELFORMAT_RGBA32, surface->pixels, surface->pitch);
|
||||
|
||||
DrawText(gFont, surface, x * gWindowScale, y * gWindowScale, color, text, strlen(text));
|
||||
|
||||
SDL_Texture *screen_texture = SDL_CreateTextureFromSurface(gRenderer, surface);
|
||||
SDL_FreeSurface(surface);
|
||||
SDL_RenderCopy(gRenderer, screen_texture, NULL, NULL);
|
||||
SDL_DestroyTexture(screen_texture);
|
||||
}
|
||||
|
||||
void PutText2(int x, int y, const char *text, uint32_t color, int surf_no)
|
||||
{
|
||||
DrawText(gFont, gRenderer, surf[surf_no].texture, x * gWindowScale, y * gWindowScale, color, text, strlen(text));
|
||||
DrawText(gFont, surf[surf_no].surface, x * gWindowScale, y * gWindowScale, color, text, strlen(text));
|
||||
surf[surf_no].needs_updating = true;
|
||||
}
|
||||
|
||||
void EndTextObject()
|
||||
|
@ -505,3 +515,17 @@ void EndTextObject()
|
|||
UnloadFont(gFont);
|
||||
gFont = nullptr;
|
||||
}
|
||||
|
||||
bool StartDirectDraw()
|
||||
{
|
||||
//Create renderer
|
||||
gRenderer = SDL_CreateRenderer(gWindow, -1, SDL_RENDERER_ACCELERATED);
|
||||
return true;
|
||||
}
|
||||
|
||||
void EndDirectDraw()
|
||||
{
|
||||
//Release all surfaces
|
||||
for (int i = 0; i < SURFACE_ID_MAX; i++)
|
||||
ReleaseSurface(i);
|
||||
}
|
||||
|
|
|
@ -45,6 +45,9 @@ enum Surface_Ids
|
|||
|
||||
struct SURFACE
|
||||
{
|
||||
bool in_use;
|
||||
bool needs_updating;
|
||||
SDL_Surface *surface;
|
||||
SDL_Texture *texture;
|
||||
};
|
||||
|
||||
|
|
24
src/Font.cpp
24
src/Font.cpp
|
@ -175,20 +175,12 @@ FontObject* LoadFont(const char *font_filename, unsigned int cell_width, unsigne
|
|||
return font_object;
|
||||
}
|
||||
|
||||
void DrawText(FontObject *font_object, SDL_Renderer *renderer, SDL_Texture *texture, int x, int y, unsigned long colour, const char *string, size_t string_length)
|
||||
void DrawText(FontObject *font_object, SDL_Surface *surface, int x, int y, unsigned long colour, const char *string, size_t string_length)
|
||||
{
|
||||
if (font_object != NULL)
|
||||
{
|
||||
const unsigned char colours[3] = {(unsigned char)(colour >> 16), (unsigned char)(colour >> 8), (unsigned char)colour};
|
||||
|
||||
SDL_Texture *old_render_target = SDL_GetRenderTarget(renderer);
|
||||
SDL_SetRenderTarget(renderer, texture);
|
||||
|
||||
int surface_width, surface_height;
|
||||
SDL_GetRendererOutputSize(renderer, &surface_width, &surface_height);
|
||||
|
||||
SDL_Surface *surface = SDL_CreateRGBSurfaceWithFormat(0, surface_width, surface_height, 0, SDL_PIXELFORMAT_RGBA32);
|
||||
SDL_RenderReadPixels(renderer, NULL, SDL_PIXELFORMAT_RGBA32, surface->pixels, surface->pitch);
|
||||
unsigned char (*surface_buffer)[surface->pitch / 4][4] = (unsigned char (*)[surface->pitch / 4][4])surface->pixels;
|
||||
|
||||
FT_Face face = font_object->face;
|
||||
|
@ -238,11 +230,11 @@ void DrawText(FontObject *font_object, SDL_Renderer *renderer, SDL_Texture *text
|
|||
const int letter_x = x + pen_x + face->glyph->bitmap_left;
|
||||
const int letter_y = y + ((FT_MulFix(face->ascender, face->size->metrics.y_scale) + (64 - 1)) / 64) - (face->glyph->metrics.horiBearingY / 64);
|
||||
|
||||
for (int iy = MAX(-letter_y, 0); letter_y + iy < MIN(letter_y + converted.rows, surface_height); ++iy)
|
||||
for (int iy = MAX(-letter_y, 0); letter_y + iy < MIN(letter_y + converted.rows, surface->h); ++iy)
|
||||
{
|
||||
if (face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_LCD)
|
||||
{
|
||||
for (int ix = MAX(-letter_x, 0); letter_x + ix < MIN(letter_x + (int)converted.width / 3, surface_width); ++ix)
|
||||
for (int ix = MAX(-letter_x, 0); letter_x + ix < MIN(letter_x + (int)converted.width / 3, surface->w); ++ix)
|
||||
{
|
||||
const unsigned char (*font_buffer)[converted.pitch / 3][3] = (unsigned char (*)[converted.pitch / 3][3])converted.buffer;
|
||||
|
||||
|
@ -263,7 +255,7 @@ void DrawText(FontObject *font_object, SDL_Renderer *renderer, SDL_Texture *text
|
|||
}
|
||||
else if (face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_GRAY)
|
||||
{
|
||||
for (int ix = MAX(-letter_x, 0); letter_x + ix < MIN(letter_x + (int)converted.width, surface_width); ++ix)
|
||||
for (int ix = MAX(-letter_x, 0); letter_x + ix < MIN(letter_x + (int)converted.width, surface->w); ++ix)
|
||||
{
|
||||
unsigned char (*font_buffer)[converted.pitch] = (unsigned char (*)[converted.pitch])converted.buffer;
|
||||
|
||||
|
@ -282,7 +274,7 @@ void DrawText(FontObject *font_object, SDL_Renderer *renderer, SDL_Texture *text
|
|||
}
|
||||
else if (face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO)
|
||||
{
|
||||
for (int ix = MAX(-letter_x, 0); letter_x + ix < MIN(letter_x + (int)converted.width, surface_width); ++ix)
|
||||
for (int ix = MAX(-letter_x, 0); letter_x + ix < MIN(letter_x + (int)converted.width, surface->w); ++ix)
|
||||
{
|
||||
unsigned char (*font_buffer)[converted.pitch] = (unsigned char (*)[converted.pitch])converted.buffer;
|
||||
|
||||
|
@ -303,12 +295,6 @@ void DrawText(FontObject *font_object, SDL_Renderer *renderer, SDL_Texture *text
|
|||
|
||||
pen_x += face->glyph->advance.x / 64;
|
||||
}
|
||||
|
||||
SDL_Texture *screen_texture = SDL_CreateTextureFromSurface(renderer, surface);
|
||||
SDL_FreeSurface(surface);
|
||||
SDL_RenderCopy(renderer, screen_texture, NULL, NULL);
|
||||
SDL_DestroyTexture(screen_texture);
|
||||
SDL_SetRenderTarget(renderer, old_render_target);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,5 +8,5 @@ typedef struct FontObject FontObject;
|
|||
|
||||
FontObject* LoadFontFromData(const unsigned char *data, size_t data_size, unsigned int cell_width, unsigned int cell_height);
|
||||
FontObject* LoadFont(const char *font_filename, unsigned int cell_width, unsigned int cell_height);
|
||||
void DrawText(FontObject *font_object, SDL_Renderer *renderer, SDL_Texture *texture, int x, int y, unsigned long colour, const char *string, size_t string_length);
|
||||
void DrawText(FontObject *font_object, SDL_Surface *surface, int x, int y, unsigned long colour, const char *string, size_t string_length);
|
||||
void UnloadFont(FontObject *font_object);
|
||||
|
|
Loading…
Add table
Reference in a new issue