Some work done to draw program icon dynamically.
This commit is contained in:
+175
-20
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user