Add minor debug display
This commit is contained in:
		
							parent
							
								
									872ee9efa4
								
							
						
					
					
						commit
						2bb16ebe68
					
				| @ -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); | ||||
| 
 | ||||
| } | ||||
|  | ||||
| @ -70,8 +70,9 @@ typedef struct KeyState | ||||
| typedef struct PlatformInput | ||||
| { | ||||
| 	f32 deltaForFrame; | ||||
| 	PlatformAPI api; | ||||
| 	f64 timeNowInS; | ||||
| 
 | ||||
| 	PlatformAPI api; | ||||
| 	union { | ||||
| 		KeyState key[key_count]; | ||||
| 		struct | ||||
|  | ||||
| @ -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); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
|  | ||||
| @ -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; } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user