Added multiple windows example.

This commit is contained in:
Branimir Karadžić 2014-09-22 19:34:10 -07:00
parent 892262f419
commit de3d152b9c
14 changed files with 849 additions and 108 deletions

View file

@ -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 <entry/input.h>
#include <bx/string.h>
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;
}

View file

@ -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<const MouseEvent*>(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<const KeyEvent*>(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<const SizeEvent*>(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<const WindowEvent*>(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;

View file

@ -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

View file

@ -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);

View file

@ -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);
}
}

View file

@ -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);

View file

@ -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);

View file

@ -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);

View file

@ -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;

View file

@ -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

View file

@ -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);

View file

@ -16,10 +16,16 @@
#include <windowsx.h>
#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<ENTRY_CONFIG_MAX_WINDOWS> 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)

View file

@ -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);

View file

@ -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(&params, &s_renderD3D9->m_params, sizeof(D3DPRESENT_PARAMETERS) );
params.BackBufferWidth = _width;
params.BackBufferHeight = _height;
DX_CHECK(s_renderD3D9->m_device->CreateAdditionalSwapChain(&params, &m_swapChain) );
DX_CHECK(m_swapChain->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &m_color[0]) );
m_colorHandle[0].idx = invalidHandle;
m_depthStencil = NULL;