diff --git a/examples/22-windows/windows.cpp b/examples/22-windows/windows.cpp new file mode 100644 index 000000000..d2212c4c6 --- /dev/null +++ b/examples/22-windows/windows.cpp @@ -0,0 +1,295 @@ +/* + * Copyright 2011-2014 Branimir Karadzic. All rights reserved. + * License: http://www.opensource.org/licenses/BSD-2-Clause + */ + +#include "common.h" +#include "bgfx_utils.h" +#include +#include + +struct PosColorVertex +{ + float m_x; + float m_y; + float m_z; + uint32_t m_abgr; + + static void init() + { + ms_decl + .begin() + .add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float) + .add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true) + .end(); + }; + + static bgfx::VertexDecl ms_decl; +}; + +bgfx::VertexDecl PosColorVertex::ms_decl; + +static PosColorVertex s_cubeVertices[8] = +{ + {-1.0f, 1.0f, 1.0f, 0xff000000 }, + { 1.0f, 1.0f, 1.0f, 0xff0000ff }, + {-1.0f, -1.0f, 1.0f, 0xff00ff00 }, + { 1.0f, -1.0f, 1.0f, 0xff00ffff }, + {-1.0f, 1.0f, -1.0f, 0xffff0000 }, + { 1.0f, 1.0f, -1.0f, 0xffff00ff }, + {-1.0f, -1.0f, -1.0f, 0xffffff00 }, + { 1.0f, -1.0f, -1.0f, 0xffffffff }, +}; + +static const uint16_t s_cubeIndices[36] = +{ + 0, 1, 2, // 0 + 1, 3, 2, + 4, 6, 5, // 2 + 5, 6, 7, + 0, 2, 4, // 4 + 4, 2, 6, + 1, 5, 3, // 6 + 5, 7, 3, + 0, 4, 1, // 8 + 4, 5, 1, + 2, 3, 6, // 10 + 6, 3, 7, +}; + +#define MAX_WINDOWS 8 +entry::WindowState windows[MAX_WINDOWS]; + +void cmdCreateWindow(const void* /*_userData*/) +{ + 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); + windows[handle.idx].m_handle = handle; + } +} + +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; + } + } +} + +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 +}; + +int _main_(int /*_argc*/, char** /*_argv*/) +{ + inputAddBindings("22-windows", s_bindings); + + uint32_t width = 1280; + uint32_t height = 720; + uint32_t debug = BGFX_DEBUG_TEXT; + uint32_t reset = BGFX_RESET_VSYNC; + + bgfx::init(); + bgfx::reset(width, height, reset); + + // Enable debug text. + bgfx::setDebug(debug); + + // Set view 0 clear state. + bgfx::setViewClear(0 + , BGFX_CLEAR_COLOR_BIT|BGFX_CLEAR_DEPTH_BIT + , 0x303030ff + , 1.0f + , 0 + ); + + // Create vertex stream declaration. + PosColorVertex::init(); + + // 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 static index buffer. + bgfx::IndexBufferHandle ibh = bgfx::createIndexBuffer( + // Static data can be passed with bgfx::makeRef + bgfx::makeRef(s_cubeIndices, sizeof(s_cubeIndices) ) + ); + + // Create program from shaders. + bgfx::ProgramHandle program = loadProgram("vs_cubes", "fs_cubes"); + + float at[3] = { 0.0f, 0.0f, 0.0f }; + float eye[3] = { 0.0f, 0.0f, -35.0f }; + + int64_t timeOffset = bx::getHPCounter(); + + bgfx::FrameBufferHandle fbh[MAX_WINDOWS]; + memset(fbh, 0xff, sizeof(fbh) ); + + entry::WindowState state; + while (!entry::processWindowEvents(state, debug, reset) ) + { + if (isValid(state.m_handle) ) + { + if (0 == state.m_handle.idx) + { + width = state.m_width; + height = state.m_height; + } + else + { + 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) ) + { + // When window changes size or native window handle changed + // frame buffer must be recreated. + if (bgfx::isValid(fbh[viewId]) ) + { + bgfx::destroyFrameBuffer(fbh[viewId]); + 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) + { + fbh[viewId] = bgfx::createFrameBuffer(win.m_nwh, win.m_width, win.m_height); + } + else + { + win.m_handle.idx = UINT16_MAX; + } + } + } + } + + float view[16]; + float proj[16]; + bx::mtxLookAt(view, eye, at); + bx::mtxProj(proj, 60.0f, float(width)/float(height), 0.1f, 100.0f); + + 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::submit(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, fbh[ii]); + + if (!bgfx::isValid(fbh[ii]) ) + { + // Set view to default viewport. + bgfx::setViewRect(ii, 0, 0, width, height); + bgfx::setViewClear(ii, BGFX_CLEAR_NONE); + } + else + { + bgfx::setViewRect(ii, 0, 0, windows[ii].m_width, windows[ii].m_height); + bgfx::setViewClear(ii + , BGFX_CLEAR_COLOR_BIT|BGFX_CLEAR_DEPTH_BIT + , 0x303030ff + , 1.0f + , 0 + ); + } + } + + 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; + + float time = (float)( (now-timeOffset)/double(bx::getHPFrequency() ) ); + + // 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); + bgfx::dbgTextPrintf(0, 5, 0x2f, "Press 'c' to create or 'd' to destroy window."); + + uint32_t count = 0; + + // 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; + + // Set model matrix for rendering. + bgfx::setTransform(mtx); + + // Set vertex and fragment shaders. + bgfx::setProgram(program); + + // Set vertex and index buffer. + bgfx::setVertexBuffer(vbh); + bgfx::setIndexBuffer(ibh); + + // Set render states. + bgfx::setState(BGFX_STATE_DEFAULT); + + // Submit primitive for rendering to view 0. + bgfx::submit(count%MAX_WINDOWS); + ++count; + } + } + + // 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) + { + if (bgfx::isValid(fbh[ii]) ) + { + bgfx::destroyFrameBuffer(fbh[ii]); + } + } + +// entry::destroyWindow(win.m_handle); + + // Cleanup. + bgfx::destroyIndexBuffer(ibh); + bgfx::destroyVertexBuffer(vbh); + bgfx::destroyProgram(program); + + // Shutdown bgfx. + bgfx::shutdown(); + + return 0; +} diff --git a/examples/common/entry/entry.cpp b/examples/common/entry/entry.cpp index 4235e1596..3162c5e75 100644 --- a/examples/common/entry/entry.cpp +++ b/examples/common/entry/entry.cpp @@ -17,6 +17,7 @@ extern "C" int _main_(int _argc, char** _argv); namespace entry { + const uint16_t WindowHandle::invalidHandle = UINT16_MAX; static uint32_t s_debug = BGFX_DEBUG_NONE; static uint32_t s_reset = BGFX_RESET_NONE; static bool s_exit = false; @@ -254,7 +255,7 @@ namespace entry return ascii; } - bool processEvents(uint32_t& _width, uint32_t& _height, uint32_t& _debug, uint32_t& _reset, MouseState* _mouse, KeyState* _keyboard) + bool processEvents(uint32_t& _width, uint32_t& _height, uint32_t& _debug, uint32_t& _reset, MouseState* _mouse) { s_debug = _debug; s_reset = _reset; @@ -263,12 +264,6 @@ namespace entry bool mouseLock = inputIsMouseLocked(); - if (NULL != _keyboard) - { - _keyboard->m_modifiers = 0; - memset(_keyboard->m_keysDown, 0, sizeof(_keyboard->m_keysDown) ); - } - const Event* ev; do { @@ -319,16 +314,6 @@ namespace entry handle = key->m_handle; inputSetKeyState(key->m_key, key->m_modifiers, key->m_down); - - if (NULL != _keyboard) - { - _keyboard->m_modifiers |= key->m_modifiers; - - if (key->m_down) - { - _keyboard->m_keysDown[key->m_key] = true; - } - } } break; @@ -367,6 +352,143 @@ namespace entry return s_exit; } + WindowState s_window[ENTRY_CONFIG_MAX_WINDOWS]; + + bool processWindowEvents(WindowState& _state, uint32_t& _debug, uint32_t& _reset) + { + s_debug = _debug; + s_reset = _reset; + + WindowHandle handle = { UINT16_MAX }; + + bool mouseLock = inputIsMouseLocked(); + + const Event* ev; + do + { + struct SE + { + SE(WindowHandle _handle) + : m_ev(poll(_handle) ) + { + } + + ~SE() + { + if (NULL != m_ev) + { + release(m_ev); + } + } + + const Event* m_ev; + + } scopeEvent(handle); + ev = scopeEvent.m_ev; + + if (NULL != ev) + { + handle = ev->m_handle; + WindowState& win = s_window[handle.idx]; + + switch (ev->m_type) + { + case Event::Exit: + return true; + + case Event::Mouse: + { + const MouseEvent* mouse = static_cast(ev); + win.m_handle = mouse->m_handle; + + if (mouse->m_move) + { + inputSetMousePos(mouse->m_mx, mouse->m_my, mouse->m_mz); + } + else + { + inputSetMouseButtonState(mouse->m_button, mouse->m_down); + } + + if (!mouseLock) + { + if (mouse->m_move) + { + win.m_mouse.m_mx = mouse->m_mx; + win.m_mouse.m_my = mouse->m_my; + win.m_mouse.m_mz = mouse->m_mz; + } + else + { + win.m_mouse.m_buttons[mouse->m_button] = mouse->m_down; + } + } + } + break; + + case Event::Key: + { + const KeyEvent* key = static_cast(ev); + win.m_handle = key->m_handle; + + inputSetKeyState(key->m_key, key->m_modifiers, key->m_down); + } + break; + + case Event::Size: + { + const SizeEvent* size = static_cast(ev); + win.m_handle = size->m_handle; + win.m_width = size->m_width; + win.m_height = size->m_height; + _reset = win.m_handle.idx == 0 + ? !s_reset + : _reset + ; // force reset + } + break; + + case Event::Window: + { + const WindowEvent* window = static_cast(ev); + win.m_handle = window->m_handle; + win.m_nwh = window->m_nwh; + ev = NULL; + } + break; + + default: + break; + } + } + + inputProcess(); + + } while (NULL != ev); + + if (isValid(handle) ) + { + const WindowState& win = s_window[handle.idx]; + _state = win; + + if (handle.idx == 0) + { + inputSetMouseResolution(win.m_width, win.m_height); + } + } + + if (_reset != s_reset) + { + _reset = s_reset; + bgfx::reset(s_window[0].m_width, s_window[0].m_height, _reset); + inputSetMouseResolution(s_window[0].m_width, s_window[0].m_height); + } + + _debug = s_debug; + + return s_exit; + } + bx::FileReaderI* getFileReader() { return s_fileReader; diff --git a/examples/common/entry/entry.h b/examples/common/entry/entry.h index 5814b3d2f..1e43d6133 100644 --- a/examples/common/entry/entry.h +++ b/examples/common/entry/entry.h @@ -14,9 +14,13 @@ namespace bx { struct FileReaderI; struct FileWriterI; } extern "C" int _main_(int _argc, char** _argv); +#define ENTRY_WINDOW_FLAG_NONE UINT32_C(0x00000000) +#define ENTRY_WINDOW_FLAG_ASPECT_RATIO UINT32_C(0x00000001) + namespace entry { - struct WindowHandle { uint16_t idx; }; + struct WindowHandle { uint16_t idx; static const uint16_t invalidHandle; }; + inline bool isValid(WindowHandle _handle) { return WindowHandle::invalidHandle != _handle.idx; } struct MouseButton { @@ -150,25 +154,37 @@ namespace entry uint8_t m_buttons[entry::MouseButton::Count]; }; - struct KeyState - { - uint8_t m_modifiers; - bool m_keysDown[entry::Key::Count]; - }; - char keyToAscii(entry::Key::Enum _key, bool _shiftModifier); - bool processEvents(uint32_t& _width, uint32_t& _height, uint32_t& _debug, uint32_t& _reset, MouseState* _mouse = NULL, KeyState* _keyboard = NULL); + bool processEvents(uint32_t& _width, uint32_t& _height, uint32_t& _debug, uint32_t& _reset, MouseState* _mouse = NULL); bx::FileReaderI* getFileReader(); bx::FileWriterI* getFileWriter(); - WindowHandle createWindow(uint32_t _width, uint32_t _height, const char* _title); + WindowHandle createWindow(int32_t _x, int32_t _y, uint32_t _width, uint32_t _height, uint32_t _flags = ENTRY_WINDOW_FLAG_NONE, const char* _title = ""); void destroyWindow(WindowHandle _handle); + void setWindowPos(WindowHandle _handle, int32_t _x, int32_t _y); void setWindowSize(WindowHandle _handle, uint32_t _width, uint32_t _height); void setWindowTitle(WindowHandle _handle, const char* _title); void toggleWindowFrame(WindowHandle _handle); void setMouseLock(WindowHandle _handle, bool _lock); + struct WindowState + { + WindowState() + : m_nwh(NULL) + { + m_handle.idx = UINT16_MAX; + } + + WindowHandle m_handle; + uint32_t m_width; + uint32_t m_height; + MouseState m_mouse; + void* m_nwh; + }; + + bool processWindowEvents(WindowState& _state, uint32_t& _debug, uint32_t& _reset); + } // namespace entry #endif // ENTRY_H_HEADER_GUARD diff --git a/examples/common/entry/entry_android.cpp b/examples/common/entry/entry_android.cpp index fa0047676..b1615b647 100644 --- a/examples/common/entry/entry_android.cpp +++ b/examples/common/entry/entry_android.cpp @@ -200,11 +200,33 @@ namespace entry return s_ctx.m_eventQueue.poll(); } + const Event* poll(WindowHandle _handle) + { + return s_ctx.m_eventQueue.poll(_handle); + } + void release(const Event* _event) { s_ctx.m_eventQueue.release(_event); } + WindowHandle createWindow(int32_t _x, int32_t _y, uint32_t _width, uint32_t _height, uint32_t _flags, const char* _title) + { + BX_UNUSED(_x, _y, _width, _height, _flags, _title); + WindowHandle handle = { UINT16_MAX }; + return handle; + } + + void destroyWindow(WindowHandle _handle) + { + BX_UNUSED(_handle); + } + + void setWindowPos(WindowHandle _handle, int32_t _x, int32_t _y) + { + BX_UNUSED(_handle, _x, _y); + } + void setWindowSize(WindowHandle _handle, uint32_t _width, uint32_t _height) { BX_UNUSED(_handle, _width, _height); diff --git a/examples/common/entry/entry_asmjs.cpp b/examples/common/entry/entry_asmjs.cpp index 9099ae334..5df3add0c 100644 --- a/examples/common/entry/entry_asmjs.cpp +++ b/examples/common/entry/entry_asmjs.cpp @@ -16,25 +16,52 @@ namespace entry return NULL; } - void release(const Event* /*_event*/) + const Event* poll(WindowHandle _handle) { + BX_UNUSED(_handle); + return NULL; } - void setWindowSize(uint32_t /*_width*/, uint32_t /*_height*/) + void release(const Event* _event) { + BX_UNUSED(_event); } - void setWindowTitle(const char* _title) + WindowHandle createWindow(int32_t _x, int32_t _y, uint32_t _width, uint32_t _height, uint32_t _flags, const char* _title) { - BX_UNUSED(_title); + BX_UNUSED(_x, _y, _width, _height, _flags, _title); + WindowHandle handle = { UINT16_MAX }; + return handle; } - void toggleWindowFrame() + void destroyWindow(WindowHandle _handle) { + BX_UNUSED(_handle); } - void setMouseLock(bool /*_lock*/) + void setWindowPos(WindowHandle _handle, int32_t _x, int32_t _y) { + BX_UNUSED(_handle, _x, _y); + } + + void setWindowSize(WindowHandle _handle, uint32_t _width, uint32_t _height) + { + BX_UNUSED(_handle, _width, _height); + } + + void setWindowTitle(WindowHandle _handle, const char* _title) + { + BX_UNUSED(_handle, _title); + } + + void toggleWindowFrame(WindowHandle _handle) + { + BX_UNUSED(_handle); + } + + void setMouseLock(WindowHandle _handle, bool _lock) + { + BX_UNUSED(_handle, _lock); } } diff --git a/examples/common/entry/entry_ios.mm b/examples/common/entry/entry_ios.mm index 43c2dcfd8..69fc520f3 100644 --- a/examples/common/entry/entry_ios.mm +++ b/examples/common/entry/entry_ios.mm @@ -78,11 +78,33 @@ namespace entry return s_ctx->m_eventQueue.poll(); } + const Event* poll(WindowHandle _handle) + { + return s_ctx->m_eventQueue.poll(_handle); + } + void release(const Event* _event) { s_ctx->m_eventQueue.release(_event); } + WindowHandle createWindow(int32_t _x, int32_t _y, uint32_t _width, uint32_t _height, uint32_t _flags, const char* _title) + { + BX_UNUSED(_x, _y, _width, _height, _flags, _title); + WindowHandle handle = { UINT16_MAX }; + return handle; + } + + void destroyWindow(WindowHandle _handle) + { + BX_UNUSED(_handle); + } + + void setWindowPos(WindowHandle _handle, int32_t _x, int32_t _y) + { + BX_UNUSED(_handle, _x, _y); + } + void setWindowSize(WindowHandle _handle, uint32_t _width, uint32_t _height) { BX_UNUSED(_handle, _width, _height); diff --git a/examples/common/entry/entry_nacl.cpp b/examples/common/entry/entry_nacl.cpp index ea2d52106..37dadc2e4 100644 --- a/examples/common/entry/entry_nacl.cpp +++ b/examples/common/entry/entry_nacl.cpp @@ -51,11 +51,34 @@ namespace entry return NULL; } + const Event* poll(WindowHandle _handle) + { + BX_UNUSED(_handle); + return NULL; + } + void release(const Event* _event) { BX_UNUSED(_event); } + WindowHandle createWindow(int32_t _x, int32_t _y, uint32_t _width, uint32_t _height, uint32_t _flags, const char* _title) + { + BX_UNUSED(_x, _y, _width, _height, _flags, _title); + WindowHandle handle = { UINT16_MAX }; + return handle; + } + + void destroyWindow(WindowHandle _handle) + { + BX_UNUSED(_handle); + } + + void setWindowPos(WindowHandle _handle, int32_t _x, int32_t _y) + { + BX_UNUSED(_handle, _x, _y); + } + void setWindowSize(WindowHandle _handle, uint32_t _width, uint32_t _height) { BX_UNUSED(_handle, _width, _height); diff --git a/examples/common/entry/entry_osx.mm b/examples/common/entry/entry_osx.mm index 1c375b531..27f61e41e 100644 --- a/examples/common/entry/entry_osx.mm +++ b/examples/common/entry/entry_osx.mm @@ -271,11 +271,33 @@ namespace entry return s_ctx.m_eventQueue.poll(); } + const Event* poll(WindowHandle _handle) + { + return s_ctx.m_eventQueue.poll(_handle); + } + void release(const Event* _event) { s_ctx.m_eventQueue.release(_event); } + WindowHandle createWindow(int32_t _x, int32_t _y, uint32_t _width, uint32_t _height, uint32_t _flags, const char* _title) + { + BX_UNUSED(_x, _y, _width, _height, _flags, _title); + WindowHandle handle = { UINT16_MAX }; + return handle; + } + + void destroyWindow(WindowHandle _handle) + { + BX_UNUSED(_handle); + } + + void setWindowPos(WindowHandle _handle, int32_t _x, int32_t _y) + { + BX_UNUSED(_handle, _x, _y); + } + void setWindowSize(WindowHandle _handle, uint32_t _width, uint32_t _height) { BX_UNUSED(_handle, _width, _height); diff --git a/examples/common/entry/entry_p.h b/examples/common/entry/entry_p.h index 8215b195e..bf67a30db 100644 --- a/examples/common/entry/entry_p.h +++ b/examples/common/entry/entry_p.h @@ -103,6 +103,7 @@ namespace entry }; const Event* poll(); + const Event* poll(WindowHandle _handle); void release(const Event* _event); class EventQueue @@ -167,6 +168,21 @@ namespace entry return m_queue.pop(); } + const Event* poll(WindowHandle _handle) + { + if (isValid(_handle) ) + { + Event* ev = m_queue.peek(); + if (NULL == ev + || ev->m_handle.idx != _handle.idx) + { + return NULL; + } + } + + return poll(); + } + void release(const Event* _event) const { delete _event; diff --git a/examples/common/entry/entry_qnx.cpp b/examples/common/entry/entry_qnx.cpp index 550ece2d1..9fb36e8b7 100644 --- a/examples/common/entry/entry_qnx.cpp +++ b/examples/common/entry/entry_qnx.cpp @@ -16,25 +16,52 @@ namespace entry return NULL; } + const Event* poll(WindowHandle _handle) + { + BX_UNUSED(_handle); + return NULL; + } + void release(const Event* _event) { + BX_UNUSED(_event); } - void setWindowSize(uint32_t _width, uint32_t _height) + WindowHandle createWindow(int32_t _x, int32_t _y, uint32_t _width, uint32_t _height, uint32_t _flags, const char* _title) { + BX_UNUSED(_x, _y, _width, _height, _flags, _title); + WindowHandle handle = { UINT16_MAX }; + return handle; } - void setWindowTitle(const char* _title) + void destroyWindow(WindowHandle _handle) { - BX_UNUSED(_title); + BX_UNUSED(_handle); } - void toggleWindowFrame() + void setWindowPos(WindowHandle _handle, int32_t _x, int32_t _y) { + BX_UNUSED(_handle, _x, _y); } - void setMouseLock(bool _lock) + void setWindowSize(WindowHandle _handle, uint32_t _width, uint32_t _height) { + BX_UNUSED(_handle, _width, _height); + } + + void setWindowTitle(WindowHandle _handle, const char* _title) + { + BX_UNUSED(_handle, _title); + } + + void toggleWindowFrame(WindowHandle _handle) + { + BX_UNUSED(_handle); + } + + void setMouseLock(WindowHandle _handle, bool _lock) + { + BX_UNUSED(_handle, _lock); } } // namespace entry diff --git a/examples/common/entry/entry_sdl.cpp b/examples/common/entry/entry_sdl.cpp index 881d88c35..0fe585481 100644 --- a/examples/common/entry/entry_sdl.cpp +++ b/examples/common/entry/entry_sdl.cpp @@ -335,11 +335,33 @@ namespace entry return s_ctx.m_eventQueue.poll(); } + const Event* poll(WindowHandle _handle) + { + return s_ctx.m_eventQueue.poll(_handle); + } + void release(const Event* _event) { s_ctx.m_eventQueue.release(_event); } + WindowHandle createWindow(int32_t _x, int32_t _y, uint32_t _width, uint32_t _height, uint32_t _flags, const char* _title) + { + BX_UNUSED(_x, _y, _width, _height, _flags, _title); + WindowHandle handle = { UINT16_MAX }; + return handle; + } + + void destroyWindow(WindowHandle _handle) + { + BX_UNUSED(_handle); + } + + void setWindowPos(WindowHandle _handle, int32_t _x, int32_t _y) + { + BX_UNUSED(_handle, _x, _y); + } + void setWindowSize(WindowHandle _handle, uint32_t _width, uint32_t _height) { BX_UNUSED(_handle); diff --git a/examples/common/entry/entry_windows.cpp b/examples/common/entry/entry_windows.cpp index 4a17aecfc..a45f4be05 100644 --- a/examples/common/entry/entry_windows.cpp +++ b/examples/common/entry/entry_windows.cpp @@ -16,10 +16,16 @@ #include -#define WM_USER_CREATE_WINDOW (WM_USER+0) -#define WM_USER_SET_WINDOW_SIZE (WM_USER+1) -#define WM_USER_TOGGLE_WINDOW_FRAME (WM_USER+2) -#define WM_USER_MOUSE_LOCK (WM_USER+3) +enum +{ + WM_USER_WINDOW_CREATE = WM_USER, + WM_USER_WINDOW_DESTROY, + WM_USER_WINDOW_SET_TITLE, + WM_USER_WINDOW_SET_POS, + WM_USER_WINDOW_SET_SIZE, + WM_USER_WINDOW_TOGGLE_FRAME, + WM_USER_WINDOW_MOUSE_LOCK, +}; namespace entry { @@ -67,6 +73,25 @@ namespace entry static int32_t threadFunc(void* _userData); }; + struct Msg + { + Msg() + : m_x(0) + , m_y(0) + , m_width(0) + , m_height(0) + , m_flags(0) + { + } + + int32_t m_x; + int32_t m_y; + uint32_t m_width; + uint32_t m_height; + uint32_t m_flags; + std::string m_title; + }; + struct Context { Context() @@ -185,6 +210,8 @@ namespace entry , 0 ); + m_flags[0] = ENTRY_WINDOW_FLAG_ASPECT_RATIO; + bgfx::winSetHwnd(m_hwnd[0]); adjust(m_hwnd[0], ENTRY_DEFAULT_WIDTH, ENTRY_DEFAULT_HEIGHT, true); @@ -230,18 +257,17 @@ namespace entry { switch (_id) { - case WM_USER_CREATE_WINDOW: + case WM_USER_WINDOW_CREATE: { - uint32_t width = GET_X_LPARAM(_lparam); - uint32_t height = GET_Y_LPARAM(_lparam); + Msg* msg = (Msg*)_lparam; HWND hwnd = CreateWindowA("bgfx" - , "" + , msg->m_title.c_str() , WS_OVERLAPPEDWINDOW|WS_VISIBLE - , 0 - , 0 - , width - , height - , NULL + , msg->m_x + , msg->m_y + , msg->m_width + , msg->m_height + , m_hwnd[0] , NULL , (HINSTANCE)GetModuleHandle(NULL) , 0 @@ -250,10 +276,42 @@ namespace entry m_hwnd[_wparam] = hwnd; WindowHandle handle = { (uint16_t)_wparam }; m_eventQueue.postWindowEvent(handle, hwnd); + m_eventQueue.postSizeEvent(handle, msg->m_width, msg->m_height); + + delete msg; } break; - case WM_USER_SET_WINDOW_SIZE: + case WM_USER_WINDOW_DESTROY: + { + WindowHandle handle = { (uint16_t)_wparam }; + PostMessageA(m_hwnd[_wparam], WM_CLOSE, 0, 0); + m_eventQueue.postWindowEvent(handle); + m_hwnd[_wparam] = 0; + } + break; + + case WM_USER_WINDOW_SET_TITLE: + { + Msg* msg = (Msg*)_lparam; + SetWindowTextA(m_hwnd[_wparam], msg->m_title.c_str() ); + delete msg; + } + break; + + case WM_USER_WINDOW_SET_POS: + { + Msg* msg = (Msg*)_lparam; + SetWindowPos(m_hwnd[_wparam], 0, msg->m_x, msg->m_y, 0, 0 + , SWP_NOACTIVATE + | SWP_NOOWNERZORDER + | SWP_NOSIZE + ); + delete msg; + } + break; + + case WM_USER_WINDOW_SET_SIZE: { uint32_t width = GET_X_LPARAM(_lparam); uint32_t height = GET_Y_LPARAM(_lparam); @@ -261,19 +319,19 @@ namespace entry } break; - case WM_USER_TOGGLE_WINDOW_FRAME: + case WM_USER_WINDOW_TOGGLE_FRAME: { if (m_frame) { - m_oldWidth = m_width; + m_oldWidth = m_width; m_oldHeight = m_height; } adjust(m_hwnd[_wparam], m_oldWidth, m_oldHeight, !m_frame); } break; - case WM_USER_MOUSE_LOCK: - setMouseLock(_hwnd, !!_lparam); + case WM_USER_WINDOW_MOUSE_LOCK: + setMouseLock(m_hwnd[_wparam], !!_lparam); break; case WM_DESTROY: @@ -281,69 +339,82 @@ namespace entry case WM_QUIT: case WM_CLOSE: - m_eventQueue.postWindowEvent(findHandle(_hwnd) ); if (_hwnd == m_hwnd[0]) { m_exit = true; m_eventQueue.postExitEvent(); } + else + { + destroyWindow(findHandle(_hwnd) ); + } break; case WM_SIZING: { - RECT& rect = *(RECT*)_lparam; - uint32_t width = rect.right - rect.left - m_frameWidth; - uint32_t height = rect.bottom - rect.top - m_frameHeight; + WindowHandle handle = findHandle(_hwnd); - // Recalculate size according to aspect ratio - switch (_wparam) + if (isValid(handle) + && ENTRY_WINDOW_FLAG_ASPECT_RATIO & m_flags[handle.idx]) { - case WMSZ_LEFT: - case WMSZ_RIGHT: + RECT& rect = *(RECT*)_lparam; + uint32_t width = rect.right - rect.left - m_frameWidth; + uint32_t height = rect.bottom - rect.top - m_frameHeight; + + // Recalculate size according to aspect ratio + switch (_wparam) { - float aspectRatio = 1.0f/m_aspectRatio; - width = bx::uint32_max(ENTRY_DEFAULT_WIDTH/4, width); - height = uint32_t(float(width)*aspectRatio); - } - break; + case WMSZ_LEFT: + case WMSZ_RIGHT: + { + float aspectRatio = 1.0f/m_aspectRatio; + width = bx::uint32_max(ENTRY_DEFAULT_WIDTH/4, width); + height = uint32_t(float(width)*aspectRatio); + } + break; - default: + default: + { + float aspectRatio = m_aspectRatio; + height = bx::uint32_max(ENTRY_DEFAULT_HEIGHT/4, height); + width = uint32_t(float(height)*aspectRatio); + } + break; + } + + // Recalculate position using different anchor points + switch(_wparam) { - float aspectRatio = m_aspectRatio; - height = bx::uint32_max(ENTRY_DEFAULT_HEIGHT/4, height); - width = uint32_t(float(height)*aspectRatio); + case WMSZ_LEFT: + case WMSZ_TOPLEFT: + case WMSZ_BOTTOMLEFT: + rect.left = rect.right - width - m_frameWidth; + rect.bottom = rect.top + height + m_frameHeight; + break; + + default: + rect.right = rect.left + width + m_frameWidth; + rect.bottom = rect.top + height + m_frameHeight; + break; } - break; + + m_eventQueue.postSizeEvent(findHandle(_hwnd), width, height); } - - // Recalculate position using different anchor points - switch(_wparam) - { - case WMSZ_LEFT: - case WMSZ_TOPLEFT: - case WMSZ_BOTTOMLEFT: - rect.left = rect.right - width - m_frameWidth; - rect.bottom = rect.top + height + m_frameHeight; - break; - - default: - rect.right = rect.left + width + m_frameWidth; - rect.bottom = rect.top + height + m_frameHeight; - break; - } - - m_eventQueue.postSizeEvent(findHandle(_hwnd), m_width, m_height); } return 0; case WM_SIZE: { - uint32_t width = GET_X_LPARAM(_lparam); - uint32_t height = GET_Y_LPARAM(_lparam); + WindowHandle handle = findHandle(_hwnd); + if (isValid(handle) ) + { + uint32_t width = GET_X_LPARAM(_lparam); + uint32_t height = GET_Y_LPARAM(_lparam); - m_width = width; - m_height = height; - m_eventQueue.postSizeEvent(findHandle(_hwnd), m_width, m_height); + m_width = width; + m_height = height; + m_eventQueue.postSizeEvent(handle, m_width, m_height); + } } break; @@ -521,10 +592,10 @@ namespace entry UpdateWindow(_hwnd); if (rect.left == -32000 - || rect.top == -32000) + || rect.top == -32000) { rect.left = 0; - rect.top = 0; + rect.top = 0; } int32_t left = rect.left; @@ -619,6 +690,7 @@ namespace entry bx::HandleAllocT m_windowAlloc; HWND m_hwnd[ENTRY_CONFIG_MAX_WINDOWS]; + uint32_t m_flags[ENTRY_CONFIG_MAX_WINDOWS]; RECT m_rect; DWORD m_style; uint32_t m_width; @@ -652,19 +724,31 @@ namespace entry return s_ctx.m_eventQueue.poll(); } + const Event* poll(WindowHandle _handle) + { + return s_ctx.m_eventQueue.poll(_handle); + } + void release(const Event* _event) { s_ctx.m_eventQueue.release(_event); } - WindowHandle createWindow(uint32_t _width, uint32_t _height, const char* /*_title*/) + WindowHandle createWindow(int32_t _x, int32_t _y, uint32_t _width, uint32_t _height, uint32_t _flags, const char* _title) { bx::LwMutexScope scope(s_ctx.m_lock); WindowHandle handle = { s_ctx.m_windowAlloc.alloc() }; if (UINT16_MAX != handle.idx) { - PostMessage(s_ctx.m_hwnd[0], WM_USER_CREATE_WINDOW, handle.idx, (_height<<16) | (_width&0xffff) ); + Msg* msg = new Msg; + msg->m_x = _x; + msg->m_y = _y; + msg->m_width = _width; + msg->m_height = _height; + msg->m_title = _title; + msg->m_flags = _flags; + PostMessage(s_ctx.m_hwnd[0], WM_USER_WINDOW_CREATE, handle.idx, (LPARAM)msg); } return handle; @@ -672,28 +756,43 @@ namespace entry void destroyWindow(WindowHandle _handle) { - PostMessage(s_ctx.m_hwnd[_handle.idx], WM_CLOSE, _handle.idx, 0); + if (UINT16_MAX != _handle.idx) + { + PostMessage(s_ctx.m_hwnd[0], WM_USER_WINDOW_DESTROY, _handle.idx, 0); + + bx::LwMutexScope scope(s_ctx.m_lock); + s_ctx.m_windowAlloc.free(_handle.idx); + } + } + + void setWindowPos(WindowHandle _handle, int32_t _x, int32_t _y) + { + Msg* msg = new Msg; + msg->m_x = _x; + msg->m_y = _y; + PostMessage(s_ctx.m_hwnd[0], WM_USER_WINDOW_SET_POS, _handle.idx, (LPARAM)msg); } void setWindowSize(WindowHandle _handle, uint32_t _width, uint32_t _height) { - PostMessage(s_ctx.m_hwnd[_handle.idx], WM_USER_SET_WINDOW_SIZE, _handle.idx, (_height<<16) | (_width&0xffff) ); + PostMessage(s_ctx.m_hwnd[0], WM_USER_WINDOW_SET_SIZE, _handle.idx, (_height<<16) | (_width&0xffff) ); } void setWindowTitle(WindowHandle _handle, const char* _title) { - SetWindowTextA(s_ctx.m_hwnd[_handle.idx], _title); -// SetWindowTextA(GetWindow(s_ctx.m_hwnd[_handle.idx], GW_HWNDNEXT), _title); + Msg* msg = new Msg; + msg->m_title = _title; + PostMessage(s_ctx.m_hwnd[0], WM_USER_WINDOW_SET_TITLE, _handle.idx, (LPARAM)msg); } void toggleWindowFrame(WindowHandle _handle) { - PostMessage(s_ctx.m_hwnd[_handle.idx], WM_USER_TOGGLE_WINDOW_FRAME, _handle.idx, 0); + PostMessage(s_ctx.m_hwnd[0], WM_USER_WINDOW_TOGGLE_FRAME, _handle.idx, 0); } void setMouseLock(WindowHandle _handle, bool _lock) { - PostMessage(s_ctx.m_hwnd[_handle.idx], WM_USER_MOUSE_LOCK, _handle.idx, _lock); + PostMessage(s_ctx.m_hwnd[0], WM_USER_WINDOW_MOUSE_LOCK, _handle.idx, _lock); } int32_t MainThreadEntry::threadFunc(void* _userData) diff --git a/examples/common/entry/entry_x11.cpp b/examples/common/entry/entry_x11.cpp index 6895bc25c..3046554e3 100644 --- a/examples/common/entry/entry_x11.cpp +++ b/examples/common/entry/entry_x11.cpp @@ -314,11 +314,33 @@ namespace entry return s_ctx.m_eventQueue.poll(); } + const Event* poll(WindowHandle _handle) + { + return s_ctx.m_eventQueue.poll(_handle); + } + void release(const Event* _event) { s_ctx.m_eventQueue.release(_event); } + WindowHandle createWindow(int32_t _x, int32_t _y, uint32_t _width, uint32_t _height, uint32_t _flags, const char* _title) + { + BX_UNUSED(_x, _y, _width, _height, _flags, _title); + WindowHandle handle = { UINT16_MAX }; + return handle; + } + + void destroyWindow(WindowHandle _handle) + { + BX_UNUSED(_handle); + } + + void setWindowPos(WindowHandle _handle, int32_t _x, int32_t _y) + { + BX_UNUSED(_handle, _x, _y); + } + void setWindowSize(WindowHandle _handle, uint32_t _width, uint32_t _height) { BX_UNUSED(_handle); diff --git a/src/renderer_d3d9.cpp b/src/renderer_d3d9.cpp index 00aa45f05..07c556471 100644 --- a/src/renderer_d3d9.cpp +++ b/src/renderer_d3d9.cpp @@ -2539,10 +2539,16 @@ namespace bgfx void FrameBufferD3D9::create(uint16_t _denseIdx, void* _nwh, uint32_t _width, uint32_t _height, TextureFormat::Enum _depthFormat) { - BX_UNUSED(_width, _height, _depthFormat); + BX_UNUSED(_depthFormat); m_hwnd = (HWND)_nwh; - DX_CHECK(s_renderD3D9->m_device->CreateAdditionalSwapChain(&s_renderD3D9->m_params, &m_swapChain) ); + + D3DPRESENT_PARAMETERS params; + memcpy(¶ms, &s_renderD3D9->m_params, sizeof(D3DPRESENT_PARAMETERS) ); + params.BackBufferWidth = _width; + params.BackBufferHeight = _height; + + DX_CHECK(s_renderD3D9->m_device->CreateAdditionalSwapChain(¶ms, &m_swapChain) ); DX_CHECK(m_swapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &m_color[0]) ); m_colorHandle[0].idx = invalidHandle; m_depthStencil = NULL;