Add rendering to screen using win32 blits
This commit is contained in:
		
							parent
							
								
									076f5977a3
								
							
						
					
					
						commit
						1c4c6d3dca
					
				| @ -83,6 +83,7 @@ | ||||
|     </ClCompile> | ||||
|     <Link> | ||||
|       <SubSystem>Windows</SubSystem> | ||||
|       <AdditionalDependencies>msimg32.lib;%(AdditionalDependencies)</AdditionalDependencies> | ||||
|     </Link> | ||||
|   </ItemDefinitionGroup> | ||||
|   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'"> | ||||
|  | ||||
| @ -41,7 +41,7 @@ REM Include directories | ||||
| set IncludeFlags= | ||||
| 
 | ||||
| REM Link libraries | ||||
| set LinkLibraries=user32.lib gdi32.lib | ||||
| set LinkLibraries=user32.lib gdi32.lib msimg32.lib | ||||
| 
 | ||||
| REM incrmenetal:no, turn incremental builds off | ||||
| REM opt:ref, try to remove functions from libs that are referenced at all | ||||
|  | ||||
							
								
								
									
										123
									
								
								src/dchip-8.cpp
									
									
									
									
									
								
							
							
						
						
									
										123
									
								
								src/dchip-8.cpp
									
									
									
									
									
								
							| @ -9,6 +9,15 @@ | ||||
| 
 | ||||
| #include <Windows.h> | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| 
 | ||||
| FILE_SCOPE HBITMAP bitmap; | ||||
| FILE_SCOPE BITMAPINFO bitmapInfo; | ||||
| 
 | ||||
| const i32 WIDTH               = 64; | ||||
| const i32 HEIGHT              = 32; | ||||
| const i32 RESOLUTION          = WIDTH * HEIGHT; | ||||
| FILE_SCOPE void *bitmapMemory; | ||||
| 
 | ||||
| FILE_SCOPE bool globalRunning = false; | ||||
| 
 | ||||
| @ -52,13 +61,14 @@ inline FILE_SCOPE LARGE_INTEGER getWallClock() | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
| #define ErrorBox(text, title) MessageBox(nullptr, text, title, MB_OK); | ||||
| int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, | ||||
|                    LPSTR lpCmdLine, int nShowCmd) | ||||
| { | ||||
| 	WNDCLASSEX wc = | ||||
| 	{ | ||||
| 		sizeof(WNDCLASSEX), | ||||
| 		CS_HREDRAW | CS_VREDRAW, | ||||
| 		CS_HREDRAW | CS_VREDRAW | CS_OWNDC, | ||||
| 		mainWindowProcCallback, | ||||
| 		0, // int cbClsExtra
 | ||||
| 		0, // int cbWndExtra
 | ||||
| @ -72,34 +82,34 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, | ||||
| 	}; | ||||
| 
 | ||||
| 	if (!RegisterClassEx(&wc)) { | ||||
| 		// TODO(doyle): Logging, couldn't register class
 | ||||
| 		ASSERT(INVALID_CODE_PATH); | ||||
| 		ErrorBox(L"RegisterClassEx() failed.", nullptr); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| 	globalRunning = true; | ||||
| 
 | ||||
| 	// NOTE: Regarding Window Sizes
 | ||||
| 	// If you specify a window size, e.g. 800x600, Windows regards the 800x600
 | ||||
| 	// region to be inclusive of the toolbars and side borders. So in actuality,
 | ||||
| 	// when you blit to the screen blackness, the area that is being blitted to
 | ||||
| 	// is slightly smaller than 800x600. Windows provides a function to help
 | ||||
| 	// calculate the size you'd need by accounting for the window style.
 | ||||
| 	RECT r   = {}; | ||||
| 	r.right  = 450; | ||||
| 	r.bottom = 200; | ||||
| 	RECT rect   = {}; | ||||
| 	rect.right  = 128; | ||||
| 	rect.bottom = 64; | ||||
| 
 | ||||
| 	DWORD windowStyle = WS_OVERLAPPEDWINDOW | WS_VISIBLE; | ||||
| 	AdjustWindowRect(&r, windowStyle, FALSE); | ||||
| 	DWORD windowStyle = | ||||
| 	    WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; | ||||
| 	AdjustWindowRect(&rect, windowStyle, FALSE); | ||||
| 
 | ||||
| 	globalRunning = true; | ||||
| 	HWND mainWindow = CreateWindowEx( | ||||
| 	    WS_EX_COMPOSITED, wc.lpszClassName, L"dchip-8", windowStyle, | ||||
| 	    CW_USEDEFAULT, CW_USEDEFAULT, r.right - r.left, r.bottom - r.top, | ||||
| 	    nullptr, nullptr, hInstance, nullptr); | ||||
| 	    CW_USEDEFAULT, CW_USEDEFAULT, rect.right - rect.left, | ||||
| 	    rect.bottom - rect.top, nullptr, nullptr, hInstance, nullptr); | ||||
| 
 | ||||
| 	if (!mainWindow) | ||||
| 	{ | ||||
| 		// TODO(doyle): Logging, couldn't create root window
 | ||||
| 		ASSERT(INVALID_CODE_PATH); | ||||
| 		ErrorBox(L"CreateWindowEx() failed.", nullptr); | ||||
| 		return -1; | ||||
| 	} | ||||
| 
 | ||||
| @ -109,6 +119,66 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, | ||||
| 	f32 targetSecondsPerFrame       = 1 / targetFramesPerSecond; | ||||
| 	f32 frameTimeInS                = 0.0f; | ||||
| 
 | ||||
| 	{ | ||||
| 		BITMAPINFOHEADER header = {}; | ||||
| 		header.biSize           = sizeof(BITMAPINFOHEADER); | ||||
| 		header.biWidth          = WIDTH; | ||||
| 		header.biHeight         = HEIGHT; | ||||
| 		header.biPlanes         = 1; | ||||
| 		header.biBitCount       = 32; | ||||
| 		header.biCompression    = BI_RGB; // uncompressed bitmap
 | ||||
| 		header.biSizeImage      = 0; | ||||
| 		header.biXPelsPerMeter  = 0; | ||||
| 		header.biYPelsPerMeter  = 0; | ||||
| 		header.biClrUsed        = 0; | ||||
| 		header.biClrImportant   = 0; | ||||
| 
 | ||||
| 		bitmapInfo.bmiHeader = header; | ||||
| 
 | ||||
| 		const i32 numPixels     = header.biWidth * header.biHeight; | ||||
| 		const i32 bytesPerPixel = header.biBitCount / 8; | ||||
| #if 0 | ||||
| 		bitmapMemory            = calloc(1, numPixels * bytesPerPixel); | ||||
| 
 | ||||
| 		if (!bitmapMemory) | ||||
| 		{ | ||||
| 			ErrorBox(L"malloc() failed.", nullptr); | ||||
| 			return -1; | ||||
| 		} | ||||
| 
 | ||||
| #else | ||||
| 		HDC deviceContext = GetDC(mainWindow); | ||||
| 		bitmap = CreateDIBSection(deviceContext, &bitmapInfo, DIB_RGB_COLORS, | ||||
| 		                          &bitmapMemory, NULL, NULL); | ||||
| 		ReleaseDC(mainWindow, deviceContext); | ||||
| 
 | ||||
| 		if (!bitmapMemory) | ||||
| 		{ | ||||
| 			ErrorBox(L"CreateDIBSection() failed.", nullptr); | ||||
| 			return -1; | ||||
| 		} | ||||
| #endif | ||||
| 
 | ||||
| 		u32 *bitmapBuffer = (u32 *)bitmapMemory; | ||||
| 		for (i32 i = 0; i < numPixels; i++) | ||||
| 		{ | ||||
| 			// NOTE: Win32 AlphaBlend requires the RGB components to be
 | ||||
| 			// premultiplied with alpha.
 | ||||
| 			f32 normA = 1.0f; | ||||
| 			f32 normR = (normA * 0.0f); | ||||
| 			f32 normG = (normA * 0.0f); | ||||
| 			f32 normB = (normA * 1.0f); | ||||
| 
 | ||||
| 			u8 r = (u8)(normR * 255.0f); | ||||
| 			u8 g = (u8)(normG * 255.0f); | ||||
| 			u8 b = (u8)(normB * 255.0f); | ||||
| 			u8 a = (u8)(normA * 255.0f); | ||||
| 
 | ||||
| 			u32 color = (a << 24) | (r << 16) | (g << 8) | (b << 0); | ||||
| 			bitmapBuffer[i] = color; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	MSG msg; | ||||
| 	while (globalRunning) | ||||
| 	{ | ||||
| @ -119,10 +189,35 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, | ||||
| 			DispatchMessage(&msg); | ||||
| 		} | ||||
| 
 | ||||
| 		RECT clientRect = {}; | ||||
| 		GetClientRect(mainWindow, &clientRect); | ||||
| 
 | ||||
| 		LONG clientWidth  = clientRect.right - clientRect.left; | ||||
| 		LONG clientHeight = clientRect.bottom - clientRect.top; | ||||
| 
 | ||||
| 		BLENDFUNCTION blend       = {}; | ||||
| 		blend.BlendOp             = AC_SRC_OVER; | ||||
| 		blend.SourceConstantAlpha = 255; | ||||
| 		blend.AlphaFormat         = AC_SRC_ALPHA; | ||||
| 
 | ||||
| 		HDC deviceContext = GetDC(mainWindow); | ||||
| 		HDC alphaBlendDC  = CreateCompatibleDC(deviceContext); | ||||
| 		SelectObject(alphaBlendDC, bitmap); | ||||
| 
 | ||||
| 		AlphaBlend(deviceContext, 0, 0, WIDTH, HEIGHT, alphaBlendDC, 0, 0, | ||||
| 		           WIDTH, HEIGHT, blend); | ||||
| 		StretchBlt(deviceContext, 0, 0, clientWidth, clientHeight, | ||||
| 		           deviceContext, 0, 0, WIDTH, HEIGHT, SRCCOPY); | ||||
| 
 | ||||
| 		DeleteDC(alphaBlendDC); | ||||
| 		ReleaseDC(mainWindow, deviceContext); | ||||
| 
 | ||||
| 		////////////////////////////////////////////////////////////////////////
 | ||||
| 		// Frame Limiting
 | ||||
| 		////////////////////////////////////////////////////////////////////////
 | ||||
| 		LARGE_INTEGER endWorkTime = getWallClock(); | ||||
| 		f32 workTimeInS = | ||||
| 		    getTimeFromQueryPerfCounter(startFrameTime, endWorkTime); | ||||
| 
 | ||||
| 		if (workTimeInS < targetSecondsPerFrame) | ||||
| 		{ | ||||
| 			DWORD remainingTimeInMs = | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user