Add minor debug display

This commit is contained in:
Doyle Thai 2017-05-14 17:49:33 +10:00
parent 872ee9efa4
commit 2bb16ebe68
4 changed files with 228 additions and 18 deletions

View File

@ -28,11 +28,27 @@ typedef struct DRFont
stbtt_packedchar *atlas;
} DRFont;
typedef struct DRBitmap
{
u8 *memory;
DqnV2i dim;
i32 bytesPerPixel;
} DRBitmap;
typedef struct DRState
{
DRFont font;
DRFont font;
DRBitmap bitmap;
} DRState;
typedef struct DRDebug
{
i32 setPixelsPerFrame;
i32 totalSetPixels;
i32 displayYOffset;
} DRDebug;
FILE_SCOPE inline DqnV4 PreMultiplyAlpha(DqnV4 color)
{
DqnV4 result;
@ -45,14 +61,15 @@ FILE_SCOPE inline DqnV4 PreMultiplyAlpha(DqnV4 color)
return result;
}
FILE_SCOPE DRDebug globalDebug;
// IMPORTANT(doyle): Color is expected to be premultiplied already
FILE_SCOPE inline void SetPixel(PlatformRenderBuffer *const renderBuffer,
const i32 x, const i32 y, const DqnV4 color)
{
if (!renderBuffer) return;
if (x < 0 || x > renderBuffer->width - 1) return;
if (y < 0 || y > renderBuffer->height - 1) return;
if (x <= 0 || x > (renderBuffer->width - 1)) return;
if (y <= 0 || y > (renderBuffer->height - 1)) return;
u32 *const bitmapPtr = (u32 *)renderBuffer->memory;
const u32 pitchInU32 = (renderBuffer->width * renderBuffer->bytesPerPixel) / 4;
@ -85,6 +102,8 @@ FILE_SCOPE inline void SetPixel(PlatformRenderBuffer *const renderBuffer,
(u32)(destG) << 8 |
(u32)(destB) << 0);
bitmapPtr[x + (y * pitchInU32)] = pixel;
globalDebug.setPixelsPerFrame++;
}
FILE_SCOPE void DrawLine(PlatformRenderBuffer *const renderBuffer, DqnV2i a,
@ -507,6 +526,165 @@ FILE_SCOPE void BitmapFontCreate(const PlatformAPI api,
DqnMemBuffer_EndTempRegion(transientTempBufferRegion);
}
FILE_SCOPE void DrawBitmap(PlatformRenderBuffer *const renderBuffer,
DRBitmap *const bitmap, i32 x, i32 y)
{
if (!bitmap || !bitmap->memory) return;
const i32 pitch = bitmap->dim.w * bitmap->bytesPerPixel;
for (i32 bitmapY = 0; bitmapY < bitmap->dim.w; bitmapY++)
{
u8 *const srcRow = bitmap->memory + (bitmapY * pitch);
i32 bufferY = y + bitmapY;
for (i32 bitmapX = 0; bitmapX < bitmap->dim.w; bitmapX++)
{
u32 *pixelPtr = (u32 *)srcRow;
u32 pixel = pixelPtr[bitmapX];
i32 bufferX = x + bitmapX;
DqnV4 color = {};
color.a = (f32)(pixel >> 24);
color.b = (f32)((pixel >> 16) & 0xFF);
color.g = (f32)((pixel >> 8) & 0xFF);
color.r = (f32)((pixel >> 0) & 0xFF);
SetPixel(renderBuffer, bufferX, bufferY, color);
}
}
}
FILE_SCOPE bool BitmapLoad(const PlatformAPI api, DRBitmap *bitmap,
const char *const path,
DqnMemBuffer *const transientBuffer)
{
if (!bitmap) return false;
PlatformFile file = {};
if (!api.FileOpen(path, &file, PlatformFilePermissionFlag_Read))
return false;
DqnTempBuffer tempBuffer = DqnMemBuffer_BeginTempRegion(transientBuffer);
{
u8 *const rawData =
(u8 *)DqnMemBuffer_Allocate(transientBuffer, file.size);
size_t bytesRead = api.FileRead(&file, rawData, file.size);
api.FileClose(&file);
if (bytesRead != file.size)
{
DqnMemBuffer_EndTempRegion(tempBuffer);
return false;
}
bitmap->memory =
stbi_load_from_memory(rawData, (i32)file.size, &bitmap->dim.w,
&bitmap->dim.h, &bitmap->bytesPerPixel, 4);
}
DqnMemBuffer_EndTempRegion(tempBuffer);
if (!bitmap->memory) return false;
const i32 pitch = bitmap->dim.w * bitmap->bytesPerPixel;
for (i32 y = 0; y < bitmap->dim.h; y++)
{
u8 *const srcRow = bitmap->memory + (y * pitch);
for (i32 x = 0; x < bitmap->dim.w; x++)
{
u32 *pixelPtr = (u32 *)srcRow;
u32 pixel = pixelPtr[x];
DqnV4 color = {};
color.a = (f32)(pixel >> 24);
color.b = (f32)((pixel >> 16) & 0xFF);
color.g = (f32)((pixel >> 8) & 0xFF);
color.r = (f32)((pixel >> 0) & 0xFF);
color = PreMultiplyAlpha(color);
pixel = (((u32)color.a << 24) |
((u32)color.b << 16) |
((u32)color.g << 8) |
((u32)color.r << 0));
pixelPtr[x] = pixel;
}
}
return true;
}
void DebugDisplayMemBuffer(PlatformRenderBuffer *const renderBuffer,
const char *const name,
const DqnMemBuffer *const buffer,
DqnV2 *const debugP, const DRFont font)
{
if (!name && !buffer && !debugP) return;
size_t totalUsed = 0;
size_t totalSize = 0;
size_t totalWasted = 0;
i32 numBlocks = 0;
DqnMemBufferBlock *blockPtr = buffer->block;
while (blockPtr)
{
totalUsed += blockPtr->used;
totalSize += blockPtr->size;
blockPtr = blockPtr->prevBlock;
numBlocks++;
}
size_t totalUsedKb = totalUsed / 1024;
size_t totalSizeKb = totalSize / 1024;
size_t totalWastedKb = totalWasted / 1024;
char str[128] = {};
Dqn_sprintf(str, "%s: %d block(s): %dkb/%dkb", name, numBlocks,
totalUsedKb, totalSizeKb);
DrawText(renderBuffer, font, *debugP, str);
debugP->y += globalDebug.displayYOffset;
}
void DebugUpdate(PlatformRenderBuffer *const renderBuffer,
PlatformInput *const input, PlatformMemory *const memory,
const DRFont font)
{
DRDebug *const debug = &globalDebug;
globalDebug.displayYOffset = -(i32)(font.sizeInPt + 0.5f);
DQN_ASSERT(globalDebug.displayYOffset < 0);
DqnV2 debugP = DqnV2_2i(0, renderBuffer->height + globalDebug.displayYOffset);
debug->totalSetPixels += debug->setPixelsPerFrame;
debug->totalSetPixels = DQN_MAX(0, debug->totalSetPixels);
debug->setPixelsPerFrame = 0;
// totalSetPixels
{
char str[128] = {};
Dqn_sprintf(str, "%s: %d", "TotalSetPixels", debug->totalSetPixels);
DrawText(renderBuffer, font, debugP, str);
debugP.y += globalDebug.displayYOffset;
}
// setPixelsPerFrame
{
char str[128] = {};
Dqn_sprintf(str, "%s: %d", "SetPixelsPerFrame", debug->setPixelsPerFrame);
DrawText(renderBuffer, font, debugP, str);
debugP.y += globalDebug.displayYOffset;
}
// memory
{
DebugDisplayMemBuffer(renderBuffer, "PermBuffer",
&memory->permanentBuffer, &debugP, font);
DebugDisplayMemBuffer(renderBuffer, "TransBuffer",
&memory->transientBuffer, &debugP, font);
}
}
extern "C" void DR_Update(PlatformRenderBuffer *const renderBuffer,
PlatformInput *const input,
PlatformMemory *const memory)
@ -514,17 +692,20 @@ extern "C" void DR_Update(PlatformRenderBuffer *const renderBuffer,
DRState *state = (DRState *)memory->context;
if (!memory->isInit)
{
stbi_set_flip_vertically_on_load(true);
memory->isInit = true;
memory->context =
DqnMemBuffer_Allocate(&memory->permanentBuffer, sizeof(DRState));
DQN_ASSERT(memory->context);
state = (DRState *)memory->context;
BitmapFontCreate(input->api, memory, &state->font, "Roboto-bold.ttf",
DqnV2i_2i(256, 256), DqnV2i_2i(' ', '~'), 35);
BitmapFontCreate(input->api, memory, &state->font, "consola.ttf",
DqnV2i_2i(256, 256), DqnV2i_2i(' ', '~'), 18);
DQN_ASSERT(BitmapLoad(input->api, &state->bitmap, "lune_logo.png",
&memory->transientBuffer));
}
ClearRenderBuffer(renderBuffer, DqnV3_3f(0, 255, 0));
ClearRenderBuffer(renderBuffer, DqnV3_3f(0, 0, 0));
DqnV4 colorRed = DqnV4_4i(50, 0, 0, 255);
DqnV2i bufferMidP = DqnV2i_2f(renderBuffer->width * 0.5f, renderBuffer->height * 0.5f);
i32 boundsOffset = 50;
@ -555,9 +736,6 @@ extern "C" void DR_Update(PlatformRenderBuffer *const renderBuffer,
}
}
DqnV2 fontP = DqnV2_2i(200, 180);
DrawText(renderBuffer, state->font, fontP, "hello world!");
DrawTriangle(renderBuffer, t0[0], t0[1], t0[2], colorRed);
DrawTriangle(renderBuffer, t1[0], t1[1], t1[2], colorRed);
DrawTriangle(renderBuffer, t2[0], t2[1], t2[2], colorRed);
@ -565,4 +743,10 @@ extern "C" void DR_Update(PlatformRenderBuffer *const renderBuffer,
DqnV4 colorRedHalfA = DqnV4_4i(255, 0, 0, 190);
DrawTriangle(renderBuffer, t3[0], t3[1], t3[2], colorRedHalfA);
DqnV2 fontP = DqnV2_2i(200, 180);
DrawText(renderBuffer, state->font, fontP, "hello world!");
DrawBitmap(renderBuffer, &state->bitmap, 700, 400);
DebugUpdate(renderBuffer, input, memory, state->font);
}

View File

@ -70,8 +70,9 @@ typedef struct KeyState
typedef struct PlatformInput
{
f32 deltaForFrame;
PlatformAPI api;
f64 timeNowInS;
PlatformAPI api;
union {
KeyState key[key_count];
struct

View File

@ -90,6 +90,7 @@ typedef struct Win32RenderBitmap
} Win32RenderBitmap;
FILE_SCOPE Win32RenderBitmap globalRenderBitmap;
FILE_SCOPE PlatformMemory globalPlatformMemory;
FILE_SCOPE bool globalRunning;
typedef struct Win32ExternalCode
@ -103,6 +104,7 @@ typedef struct Win32ExternalCode
enum Win32Menu
{
Win32Menu_FileOpen = 4,
Win32Menu_FileFlushMemory,
Win32Menu_FileExit,
};
@ -175,6 +177,7 @@ FILE_SCOPE void Win32CreateMenu(HWND window)
HMENU menu = CreatePopupMenu();
AppendMenu(menuBar, MF_STRING | MF_POPUP, (UINT_PTR)menu, "File");
AppendMenu(menu, MF_STRING, Win32Menu_FileOpen, "Open");
AppendMenu(menu, MF_STRING, Win32Menu_FileFlushMemory, "Flush Memory");
AppendMenu(menu, MF_STRING, Win32Menu_FileExit, "Exit");
}
SetMenu(window, menuBar);
@ -248,6 +251,26 @@ FILE_SCOPE void Win32HandleMenuMessages(HWND window, MSG msg,
}
break;
case Win32Menu_FileFlushMemory:
{
DqnMemBuffer permBuffer = globalPlatformMemory.permanentBuffer;
DqnMemBuffer transBuffer = globalPlatformMemory.transientBuffer;
while (permBuffer.block->prevBlock)
DqnMemBuffer_FreeLastBlock(&permBuffer);
while (transBuffer.block->prevBlock)
DqnMemBuffer_FreeLastBlock(&transBuffer);
DqnMemBuffer_ClearCurrBlock(&transBuffer, true);
DqnMemBuffer_ClearCurrBlock(&permBuffer, true);
PlatformMemory empty = {};
globalPlatformMemory = empty;
globalPlatformMemory.permanentBuffer = permBuffer;
globalPlatformMemory.transientBuffer = transBuffer;
}
break;
case Win32Menu_FileOpen:
{
#if 0
@ -475,9 +498,8 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
////////////////////////////////////////////////////////////////////////////
// Update Loop
////////////////////////////////////////////////////////////////////////////
PlatformMemory platformMemory = {};
DQN_ASSERT(DqnMemBuffer_Init(&platformMemory.permanentBuffer, DQN_MEGABYTE(1), true, 4) &&
DqnMemBuffer_Init(&platformMemory.transientBuffer, DQN_MEGABYTE(1), true, 4));
DQN_ASSERT(DqnMemBuffer_Init(&globalPlatformMemory.permanentBuffer, DQN_MEGABYTE(1), true, 4) &&
DqnMemBuffer_Init(&globalPlatformMemory.transientBuffer, DQN_MEGABYTE(1), true, 4));
const f32 TARGET_FRAMES_PER_S = 60.0f;
f32 targetSecondsPerFrame = 1 / TARGET_FRAMES_PER_S;
@ -506,6 +528,7 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
{
PlatformInput platformInput = {};
platformInput.timeNowInS = DqnTime_NowInS();
platformInput.deltaForFrame = (f32)frameTimeInS;
platformInput.api = platformAPI;
Win32ProcessMessages(mainWindow, &platformInput);
@ -519,7 +542,7 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
if (dllCode.DR_Update)
{
dllCode.DR_Update(&platformBuffer, &platformInput,
&platformMemory);
&globalPlatformMemory);
}
}

View File

@ -611,11 +611,11 @@ DQN_FILE_SCOPE i32 Dqn_strlen (const char *a);
DQN_FILE_SCOPE i32 Dqn_strlenDelimitWith(const char *a, const char delimiter);
DQN_FILE_SCOPE char *Dqn_strncpy (char *dest, const char *src, i32 numChars);
#define DQN_I32_TO_STR_MAX_BUF_SIZE 11
DQN_FILE_SCOPE bool Dqn_StrReverse (char *buf, const i32 bufSize);
DQN_FILE_SCOPE i32 Dqn_StrFindFirstOccurence(const char *const src, const i32 srcLen, const char *const find, const i32 findLen);
DQN_FILE_SCOPE bool Dqn_StrHasSubstring (const char *const src, const i32 srcLen, const char *const find, const i32 findLen);
#define DQN_I32_TO_STR_MAX_BUF_SIZE 11
DQN_FILE_SCOPE i32 Dqn_StrToI32(const char *const buf, const i32 bufSize);
// Return the len of the derived string
DQN_FILE_SCOPE i32 Dqn_I32ToStr(i32 value, char *buf, i32 bufSize);
@ -3163,12 +3163,14 @@ FILE_SCOPE f64 DqnWin32_QueryPerfCounterTimeInSInternal()
f64 DqnTime_NowInS()
{
f64 result;
#ifdef DQN_WIN32_IMPLEMENTATION
return DqnWin32_QueryPerfCounterTimeInSInternal();
result = DQN_MAX(DqnWin32_QueryPerfCounterTimeInSInternal(), 0);
#else
result = 0;
DQN_ASSERT(DQN_INVALID_CODE_PATH);
return 0;
#endif
return result;
};
f64 DqnTime_NowInMs() { return DqnTime_NowInS() * 1000.0f; }