Branimir Karadžić 9 years ago
parent
commit
a96372cd69
3 changed files with 270 additions and 199 deletions
  1. 245 189
      examples/22-windows/windows.cpp
  2. 7 10
      examples/common/entry/entry_windows.cpp
  3. 18 0
      examples/common/entry/input.h

+ 245 - 189
examples/22-windows/windows.cpp

@@ -8,6 +8,8 @@
 #include <entry/input.h>
 #include <bx/string.h>
 
+#define MAX_WINDOWS 8
+
 struct PosColorVertex
 {
 	float m_x;
@@ -57,253 +59,307 @@ static const uint16_t s_cubeIndices[36] =
 	6, 3, 7,
 };
 
-#define MAX_WINDOWS 8
-entry::WindowState windows[MAX_WINDOWS];
+void cmdCreateWindow(const void* _userData);
+void cmdDestroyWindow(const void* _userData);
 
-void cmdCreateWindow(const void* /*_userData*/)
+class ExampleWindows : public entry::AppI
 {
-	entry::WindowHandle handle = entry::createWindow(rand()%1280, rand()%720, 640, 480);
-	if (entry::isValid(handle) )
+public:
+	void init(int _argc, char** _argv) BX_OVERRIDE
 	{
-		char str[256];
-		bx::snprintf(str, BX_COUNTOF(str), "Window - handle %d", handle.idx);
-		entry::setWindowTitle(handle, str);
-		windows[handle.idx].m_handle = handle;
-	}
-}
+		Args args(_argc, _argv);
 
-void cmdDestroyWindow(const void* /*_userData*/)
-{
-	for (uint32_t ii = 0; ii < MAX_WINDOWS; ++ii)
-	{
-		if (entry::isValid(windows[ii].m_handle) )
-		{
-			entry::destroyWindow(windows[ii].m_handle);
-			windows[ii].m_handle.idx = UINT16_MAX;
-			return;
-		}
-	}
-}
+		m_width  = 1280;
+		m_height = 720;
+		m_debug  = BGFX_DEBUG_TEXT;
+		m_reset  = BGFX_RESET_VSYNC;
 
-static const InputBinding s_bindings[] =
-{
-	{ entry::Key::KeyC, entry::Modifier::None, 1, cmdCreateWindow,  NULL },
-	{ entry::Key::KeyD, entry::Modifier::None, 1, cmdDestroyWindow, NULL },
-	INPUT_BINDING_END
-};
+		bgfx::init(args.m_type, args.m_pciId);
+		bgfx::reset(m_width, m_height, m_reset);
 
-int _main_(int _argc, char** _argv)
-{
-	Args args(_argc, _argv);
+		const bgfx::Caps* caps = bgfx::getCaps();
+		bool swapChainSupported = 0 != (caps->supported & BGFX_CAPS_SWAP_CHAIN);
 
-	uint32_t width = 1280;
-	uint32_t height = 720;
-	uint32_t debug = BGFX_DEBUG_TEXT;
-	uint32_t reset = BGFX_RESET_VSYNC;
+		if (swapChainSupported)
+		{
+			m_bindings = (InputBinding*)BX_ALLOC(entry::getAllocator(), sizeof(InputBinding)*3);
+			m_bindings[0].set(entry::Key::KeyC, entry::Modifier::None, 1, cmdCreateWindow,  this);
+			m_bindings[1].set(entry::Key::KeyD, entry::Modifier::None, 1, cmdDestroyWindow, this);
+			m_bindings[2].end();
 
-	bgfx::init(args.m_type, args.m_pciId);
-	bgfx::reset(width, height, reset);
+			inputAddBindings("22-windows", m_bindings);
+		}
+		else
+		{
+			m_bindings = NULL;
+		}
 
-	const bgfx::Caps* caps = bgfx::getCaps();
-	bool swapChainSupported = 0 != (caps->supported & BGFX_CAPS_SWAP_CHAIN);
+		// Enable m_debug text.
+		bgfx::setDebug(m_debug);
 
-	if (swapChainSupported)
-	{
-		inputAddBindings("22-windows", s_bindings);
-	}
+		// Set view 0 clear state.
+		bgfx::setViewClear(0
+			, BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH
+			, 0x303030ff
+			, 1.0f
+			, 0
+			);
 
-	// Enable debug text.
-	bgfx::setDebug(debug);
+		// Create vertex stream declaration.
+		PosColorVertex::init();
 
-	// Set view 0 clear state.
-	bgfx::setViewClear(0
-		, BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH
-		, 0x303030ff
-		, 1.0f
-		, 0
-		);
+		// Create static vertex buffer.
+		m_vbh = bgfx::createVertexBuffer(
+			  // Static data can be passed with bgfx::makeRef
+			  bgfx::makeRef(s_cubeVertices, sizeof(s_cubeVertices) )
+			, PosColorVertex::ms_decl
+			);
 
-	// Create vertex stream declaration.
-	PosColorVertex::init();
+		// Create static index buffer.
+		m_ibh = bgfx::createIndexBuffer(
+			// Static data can be passed with bgfx::makeRef
+			bgfx::makeRef(s_cubeIndices, sizeof(s_cubeIndices) )
+			);
 
-	// Create static vertex buffer.
-	bgfx::VertexBufferHandle vbh = bgfx::createVertexBuffer(
-		  // Static data can be passed with bgfx::makeRef
-		  bgfx::makeRef(s_cubeVertices, sizeof(s_cubeVertices) )
-		, PosColorVertex::ms_decl
-		);
+		// Create program from shaders.
+		m_program = loadProgram("vs_cubes", "fs_cubes");
 
-	// Create static index buffer.
-	bgfx::IndexBufferHandle ibh = bgfx::createIndexBuffer(
-		// Static data can be passed with bgfx::makeRef
-		bgfx::makeRef(s_cubeIndices, sizeof(s_cubeIndices) )
-		);
+		m_timeOffset = bx::getHPCounter();
 
-	// Create program from shaders.
-	bgfx::ProgramHandle program = loadProgram("vs_cubes", "fs_cubes");
+		memset(m_fbh, 0xff, sizeof(m_fbh) );
+	}
 
-	float at[3]  = { 0.0f, 0.0f,   0.0f };
-	float eye[3] = { 0.0f, 0.0f, -35.0f };
+	virtual int shutdown() BX_OVERRIDE
+	{
+		for (uint32_t ii = 0; ii < MAX_WINDOWS; ++ii)
+		{
+			if (bgfx::isValid(m_fbh[ii]) )
+			{
+				bgfx::destroyFrameBuffer(m_fbh[ii]);
+			}
+		}
 
-	int64_t timeOffset = bx::getHPCounter();
+		BX_FREE(entry::getAllocator(), m_bindings);
 
-	bgfx::FrameBufferHandle fbh[MAX_WINDOWS];
-	memset(fbh, 0xff, sizeof(fbh) );
+		// Cleanup.
+		bgfx::destroyIndexBuffer(m_ibh);
+		bgfx::destroyVertexBuffer(m_vbh);
+		bgfx::destroyProgram(m_program);
 
-	entry::WindowState state;
-	while (!entry::processWindowEvents(state, debug, reset) )
+		// Shutdown bgfx.
+		bgfx::shutdown();
+
+		return 0;
+	}
+
+	bool update() BX_OVERRIDE
 	{
-		if (isValid(state.m_handle) )
+		entry::WindowState state;
+		if (!entry::processWindowEvents(state, m_debug, m_reset) )
 		{
-			if (0 == state.m_handle.idx)
-			{
-				width  = state.m_width;
-				height = state.m_height;
-			}
-			else
+			if (isValid(state.m_handle) )
 			{
-				uint8_t viewId = (uint8_t)state.m_handle.idx;
-				entry::WindowState& win = windows[viewId];
-
-				if (win.m_nwh    != state.m_nwh
-				|| (win.m_width  != state.m_width
-				||  win.m_height != state.m_height) )
+				if (0 == state.m_handle.idx)
+				{
+					m_width  = state.m_width;
+					m_height = state.m_height;
+				}
+				else
 				{
-					// When window changes size or native window handle changed
-					// frame buffer must be recreated.
-					if (bgfx::isValid(fbh[viewId]) )
+					uint8_t viewId = (uint8_t)state.m_handle.idx;
+					entry::WindowState& win = m_windows[viewId];
+
+					if (win.m_nwh    != state.m_nwh
+					|| (win.m_width  != state.m_width
+					||  win.m_height != state.m_height) )
 					{
-						bgfx::destroyFrameBuffer(fbh[viewId]);
-						fbh[viewId].idx = bgfx::invalidHandle;
+						// When window changes size or native window handle changed
+						// frame buffer must be recreated.
+						if (bgfx::isValid(m_fbh[viewId]) )
+						{
+							bgfx::destroyFrameBuffer(m_fbh[viewId]);
+							m_fbh[viewId].idx = bgfx::invalidHandle;
+						}
+
+						win.m_nwh    = state.m_nwh;
+						win.m_width  = state.m_width;
+						win.m_height = state.m_height;
+
+						if (NULL != win.m_nwh)
+						{
+							m_fbh[viewId] = bgfx::createFrameBuffer(win.m_nwh, win.m_width, win.m_height);
+						}
+						else
+						{
+							win.m_handle.idx = UINT16_MAX;
+						}
 					}
+				}
+			}
 
-					win.m_nwh    = state.m_nwh;
-					win.m_width  = state.m_width;
-					win.m_height = state.m_height;
+			float at[3]  = { 0.0f, 0.0f,   0.0f };
+			float eye[3] = { 0.0f, 0.0f, -35.0f };
 
-					if (NULL != win.m_nwh)
-					{
-						fbh[viewId] = bgfx::createFrameBuffer(win.m_nwh, win.m_width, win.m_height);
-					}
-					else
-					{
-						win.m_handle.idx = UINT16_MAX;
-					}
+			float view[16];
+			bx::mtxLookAt(view, eye, at);
+
+			float proj[16];
+			bx::mtxProj(proj, 60.0f, float(m_width)/float(m_height), 0.1f, 100.0f);
+
+			bgfx::setViewTransform(0, view, proj);
+			bgfx::setViewRect(0, 0, 0, m_width, m_height);
+			// This dummy draw call is here to make sure that view 0 is cleared
+			// if no other draw calls are submitted to view 0.
+			bgfx::touch(0);
+
+			// Set view and projection matrix for view 0.
+			for (uint32_t ii = 1; ii < MAX_WINDOWS; ++ii)
+			{
+				bgfx::setViewTransform(ii, view, proj);
+				bgfx::setViewFrameBuffer(ii, m_fbh[ii]);
+
+				if (!bgfx::isValid(m_fbh[ii]) )
+				{
+					// Set view to default viewport.
+					bgfx::setViewRect(ii, 0, 0, m_width, m_height);
+					bgfx::setViewClear(ii, BGFX_CLEAR_NONE);
+				}
+				else
+				{
+					bgfx::setViewRect(ii, 0, 0, m_windows[ii].m_width, m_windows[ii].m_height);
+					bgfx::setViewClear(ii
+						, BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH
+						, 0x303030ff
+						, 1.0f
+						, 0
+						);
 				}
 			}
-		}
 
-		float view[16];
-		float proj[16];
-		bx::mtxLookAt(view, eye, at);
-		bx::mtxProj(proj, 60.0f, float(width)/float(height), 0.1f, 100.0f);
+			int64_t now = bx::getHPCounter();
+			static int64_t last = now;
+			const int64_t frameTime = now - last;
+			last = now;
+			const double freq = double(bx::getHPFrequency() );
+			const double toMs = 1000.0/freq;
 
-		bgfx::setViewTransform(0, view, proj);
-		bgfx::setViewRect(0, 0, 0, width, height);
-		// This dummy draw call is here to make sure that view 0 is cleared
-		// if no other draw calls are submitted to view 0.
-		bgfx::touch(0);
+			float time = (float)( (now-m_timeOffset)/double(bx::getHPFrequency() ) );
 
-		// Set view and projection matrix for view 0.
-		for (uint32_t ii = 1; ii < MAX_WINDOWS; ++ii)
-		{
-			bgfx::setViewTransform(ii, view, proj);
-			bgfx::setViewFrameBuffer(ii, fbh[ii]);
+			// Use debug font to print information about this example.
+			bgfx::dbgTextClear();
+			bgfx::dbgTextPrintf(0, 1, 0x4f, "bgfx/examples/22-windows");
+			bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: Rendering into multiple windows.");
+			bgfx::dbgTextPrintf(0, 3, 0x0f, "Frame: % 7.3f[ms]", double(frameTime)*toMs);
 
-			if (!bgfx::isValid(fbh[ii]) )
+			if (NULL != m_bindings)
 			{
-				// Set view to default viewport.
-				bgfx::setViewRect(ii, 0, 0, width, height);
-				bgfx::setViewClear(ii, BGFX_CLEAR_NONE);
+				bgfx::dbgTextPrintf(0, 5, 0x2f, "Press 'c' to create or 'd' to destroy window.");
 			}
 			else
 			{
-				bgfx::setViewRect(ii, 0, 0, windows[ii].m_width, windows[ii].m_height);
-				bgfx::setViewClear(ii
-					, BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH
-					, 0x303030ff
-					, 1.0f
-					, 0
-					);
+				bool blink = uint32_t(time*3.0f)&1;
+				bgfx::dbgTextPrintf(0, 5, blink ? 0x1f : 0x01, " Multiple windows is not supported by `%s` renderer. ", bgfx::getRendererName(bgfx::getCaps()->rendererType) );
 			}
-		}
 
-		int64_t now = bx::getHPCounter();
-		static int64_t last = now;
-		const int64_t frameTime = now - last;
-		last = now;
-		const double freq = double(bx::getHPFrequency() );
-		const double toMs = 1000.0/freq;
+			uint32_t count = 0;
 
-		float time = (float)( (now-timeOffset)/double(bx::getHPFrequency() ) );
+			// Submit 11x11 cubes.
+			for (uint32_t yy = 0; yy < 11; ++yy)
+			{
+				for (uint32_t xx = 0; xx < 11; ++xx)
+				{
+					float mtx[16];
+					bx::mtxRotateXY(mtx, time + xx*0.21f, time + yy*0.37f);
+					mtx[12] = -15.0f + float(xx)*3.0f;
+					mtx[13] = -15.0f + float(yy)*3.0f;
+					mtx[14] = 0.0f;
 
-		// Use debug font to print information about this example.
-		bgfx::dbgTextClear();
-		bgfx::dbgTextPrintf(0, 1, 0x4f, "bgfx/examples/22-windows");
-		bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: Rendering into multiple windows.");
-		bgfx::dbgTextPrintf(0, 3, 0x0f, "Frame: % 7.3f[ms]", double(frameTime)*toMs);
+					// Set model matrix for rendering.
+					bgfx::setTransform(mtx);
 
-		if (swapChainSupported)
-		{
-			bgfx::dbgTextPrintf(0, 5, 0x2f, "Press 'c' to create or 'd' to destroy window.");
-		}
-		else
-		{
-			bool blink = uint32_t(time*3.0f)&1;
-			bgfx::dbgTextPrintf(0, 5, blink ? 0x1f : 0x01, " Multiple windows is not supported by `%s` renderer. ", bgfx::getRendererName(caps->rendererType) );
-		}
+					// Set vertex and index buffer.
+					bgfx::setVertexBuffer(m_vbh);
+					bgfx::setIndexBuffer(m_ibh);
 
-		uint32_t count = 0;
+					// Set render states.
+					bgfx::setState(BGFX_STATE_DEFAULT);
 
-		// Submit 11x11 cubes.
-		for (uint32_t yy = 0; yy < 11; ++yy)
-		{
-			for (uint32_t xx = 0; xx < 11; ++xx)
-			{
-				float mtx[16];
-				bx::mtxRotateXY(mtx, time + xx*0.21f, time + yy*0.37f);
-				mtx[12] = -15.0f + float(xx)*3.0f;
-				mtx[13] = -15.0f + float(yy)*3.0f;
-				mtx[14] = 0.0f;
+					// Submit primitive for rendering.
+					bgfx::submit(count%MAX_WINDOWS, m_program);
+					++count;
+				}
+			}
 
-				// Set model matrix for rendering.
-				bgfx::setTransform(mtx);
+			// Advance to next frame. Rendering thread will be kicked to
+			// process submitted rendering primitives.
+			bgfx::frame();
 
-				// Set vertex and index buffer.
-				bgfx::setVertexBuffer(vbh);
-				bgfx::setIndexBuffer(ibh);
+			return true;
+		}
 
-				// Set render states.
-				bgfx::setState(BGFX_STATE_DEFAULT);
+		return false;
+	}
 
-				// Submit primitive for rendering.
-				bgfx::submit(count%MAX_WINDOWS, program);
-				++count;
-			}
+	void createWindow()
+	{
+		entry::WindowHandle handle = entry::createWindow(rand()%1280, rand()%720, 640, 480);
+		if (entry::isValid(handle) )
+		{
+			char str[256];
+			bx::snprintf(str, BX_COUNTOF(str), "Window - handle %d", handle.idx);
+			entry::setWindowTitle(handle, str);
+			m_windows[handle.idx].m_handle = handle;
 		}
-
-		// Advance to next frame. Rendering thread will be kicked to
-		// process submitted rendering primitives.
-		bgfx::frame();
 	}
 
-	for (uint32_t ii = 0; ii < MAX_WINDOWS; ++ii)
+	void destroyWindow()
 	{
-		if (bgfx::isValid(fbh[ii]) )
+		for (uint32_t ii = 0; ii < MAX_WINDOWS; ++ii)
 		{
-			bgfx::destroyFrameBuffer(fbh[ii]);
+			if (bgfx::isValid(m_fbh[ii]) )
+			{
+				bgfx::destroyFrameBuffer(m_fbh[ii]);
+				m_fbh[ii].idx = bgfx::invalidHandle;
+
+				// Flush destruction of swap chain before destroying window!
+				bgfx::frame();
+				bgfx::frame();
+			}
+
+			if (entry::isValid(m_windows[ii].m_handle) )
+			{
+				entry::destroyWindow(m_windows[ii].m_handle);
+				m_windows[ii].m_handle.idx = UINT16_MAX;
+				return;
+			}
 		}
 	}
 
-//	entry::destroyWindow(win.m_handle);
+	uint32_t m_width;
+	uint32_t m_height;
+	uint32_t m_debug;
+	uint32_t m_reset;
+
+	bgfx::VertexBufferHandle m_vbh;
+	bgfx::IndexBufferHandle m_ibh;
+	bgfx::ProgramHandle m_program;
+
+	entry::WindowState m_windows[MAX_WINDOWS];
+	bgfx::FrameBufferHandle m_fbh[MAX_WINDOWS];
+
+	InputBinding* m_bindings;
 
-	// Cleanup.
-	bgfx::destroyIndexBuffer(ibh);
-	bgfx::destroyVertexBuffer(vbh);
-	bgfx::destroyProgram(program);
+	int64_t m_timeOffset;
+};
 
-	// Shutdown bgfx.
-	bgfx::shutdown();
+ENTRY_IMPLEMENT_MAIN(ExampleWindows);
 
-	return 0;
+void cmdCreateWindow(const void* _userData)
+{
+	( (ExampleWindows*)_userData)->createWindow();
+}
+
+void cmdDestroyWindow(const void* _userData)
+{
+	( (ExampleWindows*)_userData)->destroyWindow();
 }

+ 7 - 10
examples/common/entry/entry_windows.cpp

@@ -560,10 +560,15 @@ namespace entry
 				case WM_USER_WINDOW_DESTROY:
 					{
 						WindowHandle handle = { (uint16_t)_wparam };
-						PostMessageA(m_hwnd[_wparam], WM_CLOSE, 0, 0);
 						m_eventQueue.postWindowEvent(handle);
 						DestroyWindow(m_hwnd[_wparam]);
 						m_hwnd[_wparam] = 0;
+
+						if (0 == handle.idx)
+						{
+							m_exit = true;
+							m_eventQueue.postExitEvent();
+						}
 					}
 					break;
 
@@ -615,15 +620,7 @@ namespace entry
 
 				case WM_QUIT:
 				case WM_CLOSE:
-					if (_hwnd == m_hwnd[0])
-					{
-						m_exit = true;
-						m_eventQueue.postExitEvent();
-					}
-					else
-					{
-						destroyWindow(findHandle(_hwnd) );
-					}
+					destroyWindow(findHandle(_hwnd) );
 					// Don't process message. Window will be destroyed later.
 					return 0;
 

+ 18 - 0
examples/common/entry/input.h

@@ -12,6 +12,24 @@ typedef void (*InputBindingFn)(const void* _userData);
 
 struct InputBinding
 {
+	void set(entry::Key::Enum _key, uint8_t _modifiers, uint8_t _flags, InputBindingFn _fn, const void* _userData = NULL)
+	{
+		m_key = _key;
+		m_modifiers = _modifiers;
+		m_flags     = _flags;
+		m_fn        = _fn;
+		m_userData  = _userData;
+	}
+
+	void end()
+	{
+		m_key = entry::Key::None;
+		m_modifiers = entry::Modifier::None;
+		m_flags     = 0;
+		m_fn        = NULL;
+		m_userData  = NULL;
+	}
+
 	entry::Key::Enum m_key;
 	uint8_t m_modifiers;
 	uint8_t m_flags;