Some work done to draw program icon dynamically.

This commit is contained in:
2026-05-27 18:19:20 -07:00
parent e72db80fb4
commit cbc0a07a1c
2 changed files with 175 additions and 20 deletions
Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

+175 -20
View File
@@ -595,32 +595,175 @@ U64 __rdtsc()
* path. This is to be determined. One cool feature this might
* support is displaying certain information in the program icon by
* drawing into a bitmap. */
void SDLSetProgramIcon(SDL_Window *Window)
{
#if 0
U32 Rmask, Gmask, Bmask, Amask;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
S32 shift_by = (program_icon.bytes_per_pixel == 3) ? 8 : 0;
Rmask = 0xff000000 >> shift_by;
Gmask = 0x00ff0000 >> shift_by;
Bmask = 0x0000ff00 >> shift_by;
Amask = 0x000000ff >> shift_by;
#else
Rmask = 0x000000ff;
Gmask = 0x0000ff00;
Bmask = 0x00ff0000;
Amask = (program_icon.bytes_per_pixel == 3) ? 0 : 0xff000000;
#endif
SDL_Surface * icon = SDL_CreateRGBSurfaceFrom((void *)program_icon.pixel_data, program_icon.width, program_icon.height,
program_icon.bytes_per_pixel * 8, program_icon.bytes_per_pixel * program_icon.width, Rmask, Gmask, Bmask, Amask);
#include "handmade_intrinsics.h"
static void DrawBitmap(game_offscreen_buffer *Buffer, loaded_bitmap *Bitmap, F32 RelX, F32 RelY, S32 AlignX, S32 AlignY)
{
RelX -= (F32)AlignX;
RelY -= (F32)AlignY;
S32 MinX = RoundF32toS32(RelX);
S32 MinY = RoundF32toS32(RelY);
S32 MaxX = RoundF32toS32(RelX + (F32)Bitmap->Width);
S32 MaxY = RoundF32toS32(RelY + (F32)Bitmap->Height);
S32 Width = Buffer->Width;
S32 Height = Buffer->Height;
S32 SourceOffsetX = 0;
if(MinX < 0) {
SourceOffsetX = -MinX;
MinX = 0;
}
S32 SourceOffsetY = 0;
if(MinY < 0) {
SourceOffsetY = -MinY;
MinY = 0;
}
if(MaxX > Width)
MaxX = Width;
if(MaxY > Height)
MaxY = Height;
U32 *SourceRow = Bitmap->Pixels + Bitmap->Width*(Bitmap->Height - 1);
SourceRow += -Bitmap->Width*SourceOffsetY + SourceOffsetX;
U8 *DestRow = ((U8 *)Buffer->Memory + MinX*Buffer->BytesPerPixel + MinY*Buffer->Pitch);
for(S32 Y = MinY; Y < MaxY; Y++) {
U32 *Dest = (U32 *)DestRow;
U32 *Source = SourceRow;
for(S32 X = MinX; X < MaxX; X++) {
F32 A = (F32)((*Source >> 24) & 0xFF) / 255.0f;
F32 SR = (F32)((*Source >> 16) & 0xFF);
F32 SG = (F32)((*Source >> 8) & 0xFF);
F32 SB = (F32)((*Source >> 0) & 0xFF);
F32 DR = (F32)((*Dest >> 16) & 0xFF);
F32 DG = (F32)((*Dest >> 8) & 0xFF);
F32 DB = (F32)((*Dest >> 0) & 0xFF);
// TODO: This should be replaced by premultiplied alpha.
F32 R = (1.0f-A)*DR + A*SR;
F32 G = (1.0f-A)*DG + A*SG;
F32 B = (1.0f-A)*DB + A*SB;
*Dest = (((U32)RoundF32toS32(R) << 16) | ((U32)RoundF32toS32(G) << 8) | ((U32)RoundF32toS32(B) << 0));
Dest++;
Source++;
}
DestRow += Buffer->Pitch;
SourceRow -= Bitmap->Width;
}
}
#pragma pack(push, 1)
typedef struct bitmap_header {
U16 FileType;
U32 FileSize;
U16 Reserved1;
U16 Reserved2;
U32 BitmapOffset;
U32 Size;
S32 Width;
S32 Height;
U16 Planes;
U16 BitsPerPixel;
U32 Compression;
U32 SizeOfBitmap;
S32 HorzResolution;
S32 VertResolution;
U32 ColorsUsed;
U32 ColorsImportant;
U32 RedMask;
U32 GreenMask;
U32 BlueMask;
} bitmap_header;
#pragma pack(pop)
static loaded_bitmap DEBUGLoadBMPP(thread_context *Thread, debug_read_file_result (*DEBUGPlatformReadEntireFile)(thread_context *Thread, const char *), char *FileName)
{
loaded_bitmap Result;
memset(&Result, 0, sizeof(Result));
debug_read_file_result ReadResult = DEBUGPlatformReadEntireFile(Thread, FileName);
if(ReadResult.ContentsSize > 0) {
bitmap_header *Header = (bitmap_header *)ReadResult.Contents;
U32 *Pixels = (U32 *)((U8 *)ReadResult.Contents + Header->BitmapOffset);
Result.Pixels = Pixels;
Result.Width = Header->Width;
Result.Height = Header->Height;
ASSERT(Header->Compression == 3);
// NOTE: The byte order in memory is determined by the Header.
U32 RedMask = Header->RedMask;
U32 GreenMask = Header->GreenMask;
U32 BlueMask = Header->BlueMask;
U32 AlphaMask = ~(RedMask | GreenMask | BlueMask);
bit_scan_result RedShift = FindLeastSignificantSetBit(RedMask);
bit_scan_result GreenShift = FindLeastSignificantSetBit(GreenMask);
bit_scan_result BlueShift = FindLeastSignificantSetBit(BlueMask);
bit_scan_result AlphaShift = FindLeastSignificantSetBit(AlphaMask);
ASSERT(RedShift.Found);
ASSERT(GreenShift.Found);
ASSERT(BlueShift.Found);
ASSERT(AlphaShift.Found);
U32 *SourceDest = Pixels;
for(S32 Y = 0; Y < Header->Height; Y++) {
for(S32 X = 0; X < Header->Width; X++) {
U32 C = *SourceDest;
*SourceDest = ((((C >> AlphaShift.Index) & 0xFF) << 24) |
(((C >> RedShift.Index ) & 0xFF) << 16) |
(((C >> GreenShift.Index) & 0xFF) << 8) |
(((C >> BlueShift.Index ) & 0xFF) << 0));
SourceDest++;
}
}
#if 0
U32 *Beginning = Pixels;
U32 *Ending = Pixels + (Header->Width * Header->Height);
for(S32 Y = 0; Y < Header->Height; Y++) {
for(S32 X = 0; X < Header->Width; X++) {
U32 Temp = *Beginning;
*Beginning = *Ending;
*Ending = Temp;
Beginning++;
Ending--;
}
}
#endif
}
return Result;
}
void SDLSetProgramIcon(SDL_Window *Window, game_offscreen_buffer *ProgramIcon)
{
U32 Rmask, Gmask, Bmask, Amask;
Rmask = 0x00ff0000;
Gmask = 0x0000ff00;
Bmask = 0x000000ff;
Amask = 0xff000000;
SDL_Surface *icon = SDL_CreateRGBSurfaceFrom((void *)ProgramIcon->Memory, ProgramIcon->Width, ProgramIcon->Height, ProgramIcon->BytesPerPixel * 8, ProgramIcon->BytesPerPixel * ProgramIcon->Width, Rmask, Gmask, Bmask, Amask);
if(icon) {
SDL_SetWindowIcon(Window, icon);
SDL_FreeSurface(icon);
} else {
/* TODO: This didn't work . . . SDL_GetError() */
}
#endif
}
#include "handmade_intrinsics.h"
@@ -662,7 +805,19 @@ S32 main(S32 argc, char *argv[])
* its actual size. */
/* SDL_RenderPresent(Renderer) is enough to display the window. */
if(Renderer) {
SDLSetProgramIcon(Window);
thread_context TempContext; // TODO:
memset(&TempContext, 0, sizeof(TempContext));
loaded_bitmap ProgramIcon = DEBUGLoadBMPP(&TempContext, DEBUGPlatformReadEntireFile, "data/program_icon.bmp");
game_offscreen_buffer ProgramIconBuffer;
ProgramIconBuffer.Memory = malloc((ProgramIcon.Width * ProgramIcon.Height) * 4);
ProgramIconBuffer.Width = ProgramIcon.Width;
ProgramIconBuffer.Height = ProgramIcon.Height;
ProgramIconBuffer.BytesPerPixel = 4;
ProgramIconBuffer.Pitch = 4 * ProgramIcon.Width;
DrawBitmap(&ProgramIconBuffer, &ProgramIcon, 0, 0, 0, 0);
SDLSetProgramIcon(Window, &ProgramIconBuffer);
// TODO: Make it a global.
SDL_Cursor *PointerCursor = SDL_CreateSystemCursor(SDL_SYSTEM_CURSOR_ARROW);