Update BGFX to latest (nw)

This commit is contained in:
Branimir Karadžić 2016-04-04 13:52:25 +02:00 committed by Miodrag Milanovic
parent 9496a5b24d
commit e63f379a0e
42 changed files with 1773 additions and 1382 deletions

View File

@ -152,6 +152,8 @@
Here is a change-log of API breaking changes, if you are using one of the functions listed, expect to have to fix some code.
Also read releases logs https://github.com/ocornut/imgui/releases for more details.
- 2016/04/03 (1.48) - removed style.WindowFillAlphaDefault setting which was redundant. Bake default BG alpha inside style.Colors[ImGuiCol_WindowBg] and all other Bg color values. (ref github issue #337).
- 2016/04/03 (1.48) - renamed ImGuiCol_TooltipBg to ImGuiCol_PopupBg, used by popups/menus and tooltips. popups/menus were previously using ImGuiCol_WindowBg. (ref github issue #337)
- 2016/03/21 (1.48) - renamed GetWindowFont() to GetFont(), GetWindowFontSize() to GetFontSize(). Kept inline redirection function (will obsolete).
- 2016/03/02 (1.48) - InputText() completion/history/always callbacks: if you modify the text buffer manually (without using DeleteChars()/InsertChars() helper) you need to maintain the BufTextLen field. added an assert.
- 2016/01/23 (1.48) - fixed not honoring exact width passed to PushItemWidth(), previously it would add extra FramePadding.x*2 over that width. if you had manual pixel-perfect alignment in place it might affect you.
@ -439,6 +441,7 @@
!- window: begin with *p_opened == false should return false.
- window: get size/pos helpers given names (see discussion in #249)
- window: a collapsed window can be stuck behind the main menu bar?
- window: when window is small, prioritize resize button over close button.
- window: detect extra End() call that pop the "Debug" window out and assert at call site instead of later.
- window/tooltip: allow to set the width of a tooltip to allow TextWrapped() etc. while keeping the height automatic.
- window: increase minimum size of a window with menus or fix the menu rendering so that it doesn't look odd.
@ -448,15 +451,19 @@
- widgets: display mode: widget-label, label-widget (aligned on column or using fixed size), label-newline-tab-widget etc.
- widgets: clean up widgets internal toward exposing everything.
- widgets: add disabled and read-only modes (#211)
- main: considering adding EndFrame()/Init(). some constructs are awkward in the implementation because of the lack of them.
- main: make it so that a frame with no window registered won't refocus every window on subsequent frames (~bump LastFrameActive of all windows).
- main: considering adding an Init() function? some constructs are awkward in the implementation because of the lack of them.
!- main: make it so that a frame with no window registered won't refocus every window on subsequent frames (~bump LastFrameActive of all windows).
- main: IsItemHovered() make it more consistent for various type of widgets, widgets with multiple components, etc. also effectively IsHovered() region sometimes differs from hot region, e.g tree nodes
- main: IsItemHovered() info stored in a stack? so that 'if TreeNode() { Text; TreePop; } if IsHovered' return the hover state of the TreeNode?
- input text: add ImGuiInputTextFlags_EnterToApply? (off #218)
- input text: clean up the mess caused by converting UTF-8 <> wchar. the code is rather inefficient right now.
- input text: reorganize event handling, allow CharFilter to modify buffers, allow multiple events? (#541)
- input text: flag to disable live update of the user buffer (also applies to float/int text input)
- input text: resize behavior - field could stretch when being edited? hover tooltip shows more text?
- input text: add ImGuiInputTextFlags_EnterToApply? (off #218)
- input text multi-line: don't directly call AddText() which does an unnecessary vertex reserve for character count prior to clipping. and/or more line-based clipping to AddText(). and/or reorganize TextUnformatted/RenderText for more efficiency for large text (e.g TextUnformatted could clip and log separately, etc).
- input text multi-line: way to dynamically grow the buffer without forcing the user to initially allocate for worse case (follow up on #200)
- input text multi-line: line numbers? status bar? (follow up on #200)
- input text: allow centering/positioning text so that ctrl+clicking Drag or Slider keeps the textual value at the same pixel position.
- input number: optional range min/max for Input*() functions
- input number: holding [-]/[+] buttons could increase the step speed non-linearly (or user-controlled)
- input number: use mouse wheel to step up/down
@ -495,10 +502,11 @@
- statusbar: add a per-window status bar helper similar to what menubar does.
- tabs (#261, #351)
- separator: separator on the initial position of a window is not visible (cursorpos.y <= clippos.y)
- color: the color helpers/typing is a mess and needs sorting out.
!- color: the color helpers/typing is a mess and needs sorting out.
- color: add a better color picker (#346)
- node/graph editor (#306)
- pie menus patterns (#434)
- drag'n drop, dragging helpers (carry dragging info, visualize drag source before clicking, drop target, etc.) (#143, #479)
- plot: PlotLines() should use the polygon-stroke facilities (currently issues with averaging normals)
- plot: make it easier for user to draw extra stuff into the graph (e.g: draw basis, highlight certain points, 2d plots, multiple plots)
- plot: "smooth" automatic scale over time, user give an input 0.0(full user scale) 1.0(full derived from value)
@ -510,14 +518,11 @@
- slider & drag: int data passing through a float
- drag float: up/down axis
- drag float: added leeway on edge (e.g. a few invisible steps past the clamp limits)
- text edit: clean up the mess caused by converting UTF-8 <> wchar. the code is rather inefficient right now.
- text edit: centered text for slider as input text so it matches typical positioning.
- text edit: flag to disable live update of the user buffer.
- text edit: field resize behavior - field could stretch when being edited? hover tooltip shows more text?
- tree node / optimization: avoid formatting when clipped.
- tree node: clarify spacing, perhaps provide API to query exact spacing. provide API to draw the primitive. same with Bullet().
- tree node: tree-node/header right-most side doesn't take account of horizontal scrolling.
- tree node: add treenode/treepush int variants? because (void*) cast from int warns on some platforms/settings
- tree node: try to apply scrolling at time of TreePop() if node was just opened and end of node is past scrolling limits?
- tree node / selectable render mismatch which is visible if you use them both next to each other (e.g. cf. property viewer)
- textwrapped: figure out better way to use TextWrapped() in an always auto-resize context (tooltip, etc.) (git issue #249)
- settings: write more decent code to allow saving/loading new fields
@ -527,6 +532,7 @@
- style: color-box not always square?
- style: a concept of "compact style" that the end-user can easily rely on (e.g. PushStyleCompact()?) that maps to other settings? avoid implementing duplicate helpers such as SmallCheckbox(), etc.
- style: try to make PushStyleVar() more robust to incorrect parameters (to be more friendly to edit & continues situation).
- style/opt: PopStyleVar could be optimized by having GetStyleVar returns the type, using a table mapping stylevar enum to data type.
- style: global scale setting.
- text: simple markup language for color change?
- font: dynamic font atlas to avoid baking huge ranges into bitmap and make scaling easier.
@ -550,7 +556,8 @@
- style editor: have a more global HSV setter (e.g. alter hue on all elements). consider replacing active/hovered by offset in HSV space? (#438)
- style editor: color child window height expressed in multiple of line height.
- remote: make a system like RemoteImGui first-class citizen/project (#75)
- drawlist: user probably can't call Clear() because we expect a texture to be pushed in the stack.
!- demo: custom render demo pushes a clipping rectangle past parent window bounds. expose ImGui::PushClipRect() from imgui_internal.h?
- drawlist: end-user probably can't call Clear() directly because we expect a texture to be pushed in the stack.
- examples: directx9/directx11: save/restore device state more thoroughly.
- optimization: use another hash function than crc32, e.g. FNV1a
- optimization/render: merge command-lists with same clip-rect into one even if they aren't sequential? (as long as in-between clip rectangle don't overlap)?
@ -689,13 +696,12 @@ ImGuiStyle::ImGuiStyle()
WindowMinSize = ImVec2(32,32); // Minimum window size
WindowRounding = 9.0f; // Radius of window corners rounding. Set to 0.0f to have rectangular windows
WindowTitleAlign = ImGuiAlign_Left; // Alignment for title bar text
ChildWindowRounding = 0.0f; // Radius of child window corners rounding. Set to 0.0f to have rectangular windows
ChildWindowRounding = 0.0f; // Radius of child window corners rounding. Set to 0.0f to have rectangular child windows
FramePadding = ImVec2(4,3); // Padding within a framed rectangle (used by most widgets)
FrameRounding = 0.0f; // Radius of frame corners rounding. Set to 0.0f to have rectangular frames (used by most widgets).
ItemSpacing = ImVec2(8,4); // Horizontal and vertical spacing between widgets/lines
ItemInnerSpacing = ImVec2(4,4); // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label)
TouchExtraPadding = ImVec2(0,0); // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much!
WindowFillAlphaDefault = 0.70f; // Default alpha of window background, if not specified in ImGui::Begin()
IndentSpacing = 22.0f; // Horizontal spacing when e.g. entering a tree node
ColumnsMinSpacing = 6.0f; // Minimum horizontal spacing between two columns
ScrollbarSize = 16.0f; // Width of the vertical scrollbar, Height of the horizontal scrollbar
@ -710,8 +716,9 @@ ImGuiStyle::ImGuiStyle()
Colors[ImGuiCol_Text] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f);
Colors[ImGuiCol_TextDisabled] = ImVec4(0.60f, 0.60f, 0.60f, 1.00f);
Colors[ImGuiCol_WindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f);
Colors[ImGuiCol_WindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.70f);
Colors[ImGuiCol_ChildWindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
Colors[ImGuiCol_PopupBg] = ImVec4(0.05f, 0.05f, 0.10f, 0.90f);
Colors[ImGuiCol_Border] = ImVec4(0.70f, 0.70f, 0.70f, 0.65f);
Colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
Colors[ImGuiCol_FrameBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.30f); // Background of checkbox, radio button, plot, slider, text input
@ -749,7 +756,6 @@ ImGuiStyle::ImGuiStyle()
Colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
Colors[ImGuiCol_PlotHistogramHovered] = ImVec4(1.00f, 0.60f, 0.00f, 1.00f);
Colors[ImGuiCol_TextSelectedBg] = ImVec4(0.00f, 0.00f, 1.00f, 0.35f);
Colors[ImGuiCol_TooltipBg] = ImVec4(0.05f, 0.05f, 0.10f, 0.90f);
Colors[ImGuiCol_ModalWindowDarkening] = ImVec4(0.20f, 0.20f, 0.20f, 0.35f);
}
@ -788,6 +794,14 @@ ImGuiIO::ImGuiIO()
GetClipboardTextFn = GetClipboardTextFn_DefaultImpl; // Platform dependent default implementations
SetClipboardTextFn = SetClipboardTextFn_DefaultImpl;
ImeSetInputScreenPosFn = ImeSetInputScreenPosFn_DefaultImpl;
// Set OS X style defaults based on __APPLE__ compile time flag
#ifdef __APPLE__
WordMovementUsesAltKey = true; // OS X style: Text editing cursor movement using Alt instead of Ctrl
ShortcutsUseSuperKey = true; // OS X style: Shortcuts using Cmd/Super instead of Ctrl
DoubleClickSelectsWord = true; // OS X style: Double click selects by word instead of selecting whole text
MultiSelectUsesSuperKey = true; // OS X style: Multi-selection in lists uses Cmd/Super instead of Ctrl
#endif
}
// Pass in translated ASCII characters for text input.
@ -3126,9 +3140,8 @@ static ImRect GetVisibleRect()
void ImGui::BeginTooltip()
{
ImGuiState& g = *GImGui;
ImGuiWindowFlags flags = ImGuiWindowFlags_Tooltip|ImGuiWindowFlags_NoTitleBar|ImGuiWindowFlags_NoMove|ImGuiWindowFlags_NoResize|ImGuiWindowFlags_NoSavedSettings|ImGuiWindowFlags_AlwaysAutoResize;
ImGui::Begin("##Tooltip", NULL, ImVec2(0,0), g.Style.Colors[ImGuiCol_TooltipBg].w, flags);
ImGui::Begin("##Tooltip", NULL, flags);
}
void ImGui::EndTooltip()
@ -3266,9 +3279,8 @@ static bool BeginPopupEx(const char* str_id, ImGuiWindowFlags extra_flags)
ImFormatString(name, 20, "##menu_%d", g.CurrentPopupStack.Size); // Recycle windows based on depth
else
ImFormatString(name, 20, "##popup_%08x", id); // Not recycling, so we can close/open during the same frame
float alpha = 1.0f;
bool opened = ImGui::Begin(name, NULL, ImVec2(0.0f, 0.0f), alpha, flags);
bool opened = ImGui::Begin(name, NULL, flags);
if (!(window->Flags & ImGuiWindowFlags_ShowBorders))
g.CurrentWindow->Flags &= ~ImGuiWindowFlags_ShowBorders;
if (!opened) // opened can be 'false' when the popup is completely clipped (e.g. zero size display)
@ -3299,7 +3311,7 @@ bool ImGui::BeginPopupModal(const char* name, bool* p_opened, ImGuiWindowFlags e
}
ImGuiWindowFlags flags = extra_flags|ImGuiWindowFlags_Popup|ImGuiWindowFlags_Modal|ImGuiWindowFlags_NoCollapse|ImGuiWindowFlags_NoSavedSettings;
bool opened = ImGui::Begin(name, p_opened, ImVec2(0.0f, 0.0f), -1.0f, flags);
bool opened = ImGui::Begin(name, p_opened, flags);
if (!opened || (p_opened && !*p_opened)) // Opened can be 'false' when the popup is completely clipped (e.g. zero size display)
{
ImGui::EndPopup();
@ -3379,8 +3391,7 @@ bool ImGui::BeginChild(const char* str_id, const ImVec2& size_arg, bool border,
char title[256];
ImFormatString(title, IM_ARRAYSIZE(title), "%s.%s", window->Name, str_id);
const float alpha = 1.0f;
bool ret = ImGui::Begin(title, NULL, size, alpha, flags);
bool ret = ImGui::Begin(title, NULL, size, -1.0f, flags);
if (!(window->Flags & ImGuiWindowFlags_ShowBorders))
GetCurrentWindow()->Flags &= ~ImGuiWindowFlags_ShowBorders;
@ -3430,13 +3441,14 @@ bool ImGui::BeginChildFrame(ImGuiID id, const ImVec2& size, ImGuiWindowFlags ext
const ImGuiStyle& style = g.Style;
ImGui::PushStyleColor(ImGuiCol_ChildWindowBg, style.Colors[ImGuiCol_FrameBg]);
ImGui::PushStyleVar(ImGuiStyleVar_ChildWindowRounding, style.FrameRounding);
return ImGui::BeginChild(id, size, false, ImGuiWindowFlags_NoMove | extra_flags);
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, style.FramePadding);
return ImGui::BeginChild(id, size, (g.CurrentWindow->Flags & ImGuiWindowFlags_ShowBorders) ? true : false, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysUseWindowPadding | extra_flags);
}
void ImGui::EndChildFrame()
{
ImGui::EndChild();
ImGui::PopStyleVar();
ImGui::PopStyleVar(2);
ImGui::PopStyleColor();
}
@ -3679,10 +3691,6 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_
window->RootWindow = g.CurrentWindowStack[root_idx];
window->RootNonPopupWindow = g.CurrentWindowStack[root_non_popup_idx]; // This is merely for displaying the TitleBgActive color.
// Default alpha
if (bg_alpha < 0.0f)
bg_alpha = style.WindowFillAlphaDefault;
// When reusing window again multiple times a frame, just append content (don't need to setup again)
if (first_begin_of_the_frame)
{
@ -3754,7 +3762,7 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_
}
// Lock window padding so that altering the ShowBorders flag for children doesn't have side-effects.
window->WindowPadding = ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_ShowBorders | ImGuiWindowFlags_ComboBox | ImGuiWindowFlags_Popup))) ? ImVec2(0,0) : style.WindowPadding;
window->WindowPadding = ((flags & ImGuiWindowFlags_ChildWindow) && !(flags & (ImGuiWindowFlags_AlwaysUseWindowPadding | ImGuiWindowFlags_ShowBorders | ImGuiWindowFlags_ComboBox | ImGuiWindowFlags_Popup))) ? ImVec2(0,0) : style.WindowPadding;
// Calculate auto-fit size
ImVec2 size_auto_fit;
@ -3968,27 +3976,26 @@ bool ImGui::Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_
}
// Scrollbars
window->ScrollbarY = (flags & ImGuiWindowFlags_ForceVerticalScrollbar) || ((window->SizeContents.y > window->Size.y + style.ItemSpacing.y) && !(flags & ImGuiWindowFlags_NoScrollbar));
window->ScrollbarX = (flags & ImGuiWindowFlags_ForceHorizontalScrollbar) || ((window->SizeContents.x > window->Size.x - (window->ScrollbarY ? style.ScrollbarSize : 0.0f) - window->WindowPadding.x) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar));
window->ScrollbarY = (flags & ImGuiWindowFlags_AlwaysVerticalScrollbar) || ((window->SizeContents.y > window->Size.y + style.ItemSpacing.y) && !(flags & ImGuiWindowFlags_NoScrollbar));
window->ScrollbarX = (flags & ImGuiWindowFlags_AlwaysHorizontalScrollbar) || ((window->SizeContents.x > window->Size.x - (window->ScrollbarY ? style.ScrollbarSize : 0.0f) - window->WindowPadding.x) && !(flags & ImGuiWindowFlags_NoScrollbar) && (flags & ImGuiWindowFlags_HorizontalScrollbar));
window->ScrollbarSizes = ImVec2(window->ScrollbarY ? style.ScrollbarSize : 0.0f, window->ScrollbarX ? style.ScrollbarSize : 0.0f);
window->BorderSize = (flags & ImGuiWindowFlags_ShowBorders) ? 1.0f : 0.0f;
// Window background
if (bg_alpha > 0.0f)
{
ImGuiCol col_idx;
if ((flags & ImGuiWindowFlags_ComboBox) != 0)
col_idx = ImGuiCol_ComboBg;
else if ((flags & ImGuiWindowFlags_Tooltip) != 0)
col_idx = ImGuiCol_TooltipBg;
else if ((flags & ImGuiWindowFlags_Popup) != 0)
col_idx = ImGuiCol_WindowBg;
else if ((flags & ImGuiWindowFlags_ChildWindow) != 0)
col_idx = ImGuiCol_ChildWindowBg;
else
col_idx = ImGuiCol_WindowBg;
window->DrawList->AddRectFilled(window->Pos, window->Pos+window->Size, GetColorU32(col_idx, bg_alpha), window_rounding);
}
// Default alpha
ImGuiCol bg_color_idx = ImGuiCol_WindowBg;
if ((flags & ImGuiWindowFlags_ComboBox) != 0)
bg_color_idx = ImGuiCol_ComboBg;
else if ((flags & ImGuiWindowFlags_Tooltip) != 0 || (flags & ImGuiWindowFlags_Popup) != 0)
bg_color_idx = ImGuiCol_PopupBg;
else if ((flags & ImGuiWindowFlags_ChildWindow) != 0)
bg_color_idx = ImGuiCol_ChildWindowBg;
ImVec4 bg_color = style.Colors[bg_color_idx];
if (bg_alpha >= 0.0f)
bg_color.w = bg_alpha;
bg_color.w *= style.Alpha;
if (bg_color.w > 0.0f)
window->DrawList->AddRectFilled(window->Pos, window->Pos+window->Size, ColorConvertFloat4ToU32(bg_color), window_rounding);
// Title bar
if (!(flags & ImGuiWindowFlags_NoTitleBar))
@ -4510,6 +4517,7 @@ const char* ImGui::GetStyleColName(ImGuiCol idx)
case ImGuiCol_TextDisabled: return "TextDisabled";
case ImGuiCol_WindowBg: return "WindowBg";
case ImGuiCol_ChildWindowBg: return "ChildWindowBg";
case ImGuiCol_PopupBg: return "PopupBg";
case ImGuiCol_Border: return "Border";
case ImGuiCol_BorderShadow: return "BorderShadow";
case ImGuiCol_FrameBg: return "FrameBg";
@ -4547,7 +4555,6 @@ const char* ImGui::GetStyleColName(ImGuiCol idx)
case ImGuiCol_PlotHistogram: return "PlotHistogram";
case ImGuiCol_PlotHistogramHovered: return "PlotHistogramHovered";
case ImGuiCol_TextSelectedBg: return "TextSelectedBg";
case ImGuiCol_TooltipBg: return "TooltipBg";
case ImGuiCol_ModalWindowDarkening: return "ModalWindowDarkening";
}
IM_ASSERT(0);
@ -7091,8 +7098,18 @@ static void STB_TEXTEDIT_LAYOUTROW(StbTexteditRow* r, STB_TEXTEDIT_STRING* ob
r->num_chars = (int)(text_remaining - (text + line_start_idx));
}
static bool is_separator(unsigned int c) { return c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || c=='|'; }
#define STB_TEXTEDIT_IS_SPACE(CH) ( ImCharIsSpace((unsigned int)CH) || is_separator((unsigned int)CH) )
static bool is_separator(unsigned int c) { return ImCharIsSpace(c) || c==',' || c==';' || c=='(' || c==')' || c=='{' || c=='}' || c=='[' || c==']' || c=='|'; }
static int is_word_boundary_from_right(STB_TEXTEDIT_STRING* obj, int idx) { return idx > 0 ? (is_separator( obj->Text[idx-1] ) && !is_separator( obj->Text[idx] ) ) : 1; }
static int is_word_boundary_from_left(STB_TEXTEDIT_STRING* obj, int idx) { return idx > 0 ? (!is_separator( obj->Text[idx-1] ) && is_separator( obj->Text[idx] ) ) : 1; }
static int STB_TEXTEDIT_MOVEWORDLEFT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { while (idx >= 0 && !is_word_boundary_from_right(obj, idx)) idx--; return idx < 0 ? 0 : idx; }
#ifdef __APPLE__ // FIXME: Move setting to IO structure
static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_left(obj, idx)) idx++; return idx > len ? len : idx; }
#else
static int STB_TEXTEDIT_MOVEWORDRIGHT_IMPL(STB_TEXTEDIT_STRING* obj, int idx) { int len = obj->CurLenW; while (idx < len && !is_word_boundary_from_right(obj, idx)) idx++; return idx > len ? len : idx; }
#endif
#define STB_TEXTEDIT_MOVEWORDLEFT STB_TEXTEDIT_MOVEWORDLEFT_IMPL // They need to be #define for stb_textedit.h
#define STB_TEXTEDIT_MOVEWORDRIGHT STB_TEXTEDIT_MOVEWORDRIGHT_IMPL
static void STB_TEXTEDIT_DELETECHARS(STB_TEXTEDIT_STRING* obj, int pos, int n)
{
ImWchar* dst = obj->Text.Data + pos;
@ -7289,7 +7306,6 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
return false;
}
draw_window = GetCurrentWindow();
draw_window->DC.CursorPos += style.FramePadding;
size.x -= draw_window->ScrollbarSizes.x;
}
else
@ -7322,6 +7338,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
const bool is_ctrl_down = io.KeyCtrl;
const bool is_shift_down = io.KeyShift;
const bool is_alt_down = io.KeyAlt;
const bool is_super_down = io.KeySuper;
const bool focus_requested = FocusableItemRegister(window, g.ActiveId == id, (flags & (ImGuiInputTextFlags_CallbackCompletion|ImGuiInputTextFlags_AllowTabInput)) == 0); // Using completion callback disable keyboard tabbing
const bool focus_requested_by_code = focus_requested && (window->FocusIdxAllCounter == window->FocusIdxAllRequestCurrent);
const bool focus_requested_by_tab = focus_requested && !focus_requested_by_code;
@ -7409,11 +7426,17 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
const float mouse_x = (g.IO.MousePos.x - frame_bb.Min.x - style.FramePadding.x) + edit_state.ScrollX;
const float mouse_y = (is_multiline ? (g.IO.MousePos.y - draw_window->DC.CursorPos.y - style.FramePadding.y) : (g.FontSize*0.5f));
if (select_all || (hovered && io.MouseDoubleClicked[0]))
if (select_all || (hovered && !io.DoubleClickSelectsWord && io.MouseDoubleClicked[0]))
{
edit_state.SelectAll();
edit_state.SelectedAllMouseLock = true;
}
else if (hovered && io.DoubleClickSelectsWord && io.MouseDoubleClicked[0])
{
// Select a word only, OS X style (by simulating keystrokes)
edit_state.OnKeyPressed(STB_TEXTEDIT_K_WORDLEFT);
edit_state.OnKeyPressed(STB_TEXTEDIT_K_WORDRIGHT | STB_TEXTEDIT_K_SHIFT);
}
else if (io.MouseClicked[0] && !edit_state.SelectedAllMouseLock)
{
stb_textedit_click(&edit_state, &edit_state.StbState, mouse_x, mouse_y);
@ -7451,9 +7474,11 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
// Handle various key-presses
bool cancel_edit = false;
const int k_mask = (is_shift_down ? STB_TEXTEDIT_K_SHIFT : 0);
const bool is_ctrl_only = is_ctrl_down && !is_alt_down && !is_shift_down;
if (IsKeyPressedMap(ImGuiKey_LeftArrow)) { edit_state.OnKeyPressed(is_ctrl_down ? STB_TEXTEDIT_K_WORDLEFT | k_mask : STB_TEXTEDIT_K_LEFT | k_mask); }
else if (IsKeyPressedMap(ImGuiKey_RightArrow)) { edit_state.OnKeyPressed(is_ctrl_down ? STB_TEXTEDIT_K_WORDRIGHT | k_mask : STB_TEXTEDIT_K_RIGHT | k_mask); }
const bool is_shortcutkey_only = (io.ShortcutsUseSuperKey ? (is_super_down && !is_alt_down && !is_shift_down && !is_ctrl_down) : (is_ctrl_down && !is_alt_down && !is_shift_down && !is_super_down));
const bool is_wordmove_key_down = (io.WordMovementUsesAltKey ? io.KeyAlt : io.KeyCtrl);
if (IsKeyPressedMap(ImGuiKey_LeftArrow)) { edit_state.OnKeyPressed(is_wordmove_key_down ? STB_TEXTEDIT_K_WORDLEFT | k_mask : STB_TEXTEDIT_K_LEFT | k_mask); }
else if (IsKeyPressedMap(ImGuiKey_RightArrow)) { edit_state.OnKeyPressed(is_wordmove_key_down ? STB_TEXTEDIT_K_WORDRIGHT | k_mask : STB_TEXTEDIT_K_RIGHT | k_mask); }
else if (is_multiline && IsKeyPressedMap(ImGuiKey_UpArrow)) { if (is_ctrl_down) SetWindowScrollY(draw_window, draw_window->Scroll.y - g.FontSize); else edit_state.OnKeyPressed(STB_TEXTEDIT_K_UP | k_mask); }
else if (is_multiline && IsKeyPressedMap(ImGuiKey_DownArrow)) { if (is_ctrl_down) SetWindowScrollY(draw_window, draw_window->Scroll.y + g.FontSize); else edit_state.OnKeyPressed(STB_TEXTEDIT_K_DOWN| k_mask); }
else if (IsKeyPressedMap(ImGuiKey_Home)) { edit_state.OnKeyPressed(is_ctrl_down ? STB_TEXTEDIT_K_TEXTSTART | k_mask : STB_TEXTEDIT_K_LINESTART | k_mask); }
@ -7481,11 +7506,11 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
if (InputTextFilterCharacter(&c, flags, callback, user_data))
edit_state.OnKeyPressed((int)c);
}
else if (IsKeyPressedMap(ImGuiKey_Escape)) { SetActiveID(0); cancel_edit = true; }
else if (is_ctrl_only && IsKeyPressedMap(ImGuiKey_Z) && is_editable) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_UNDO); edit_state.ClearSelection(); }
else if (is_ctrl_only && IsKeyPressedMap(ImGuiKey_Y) && is_editable) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_REDO); edit_state.ClearSelection(); }
else if (is_ctrl_only && IsKeyPressedMap(ImGuiKey_A)) { edit_state.SelectAll(); edit_state.CursorFollow = true; }
else if (is_ctrl_only && !is_password && ((IsKeyPressedMap(ImGuiKey_X) && is_editable) || IsKeyPressedMap(ImGuiKey_C)) && (!is_multiline || edit_state.HasSelection()))
else if (IsKeyPressedMap(ImGuiKey_Escape)) { SetActiveID(0); cancel_edit = true; }
else if (is_shortcutkey_only && IsKeyPressedMap(ImGuiKey_Z) && is_editable) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_UNDO); edit_state.ClearSelection(); }
else if (is_shortcutkey_only && IsKeyPressedMap(ImGuiKey_Y) && is_editable) { edit_state.OnKeyPressed(STB_TEXTEDIT_K_REDO); edit_state.ClearSelection(); }
else if (is_shortcutkey_only && IsKeyPressedMap(ImGuiKey_A)) { edit_state.SelectAll(); edit_state.CursorFollow = true; }
else if (is_shortcutkey_only && !is_password && ((IsKeyPressedMap(ImGuiKey_X) && is_editable) || IsKeyPressedMap(ImGuiKey_C)) && (!is_multiline || edit_state.HasSelection()))
{
// Cut, Copy
const bool cut = IsKeyPressedMap(ImGuiKey_X);
@ -7507,7 +7532,7 @@ bool ImGui::InputTextEx(const char* label, char* buf, int buf_size, const ImVec2
stb_textedit_cut(&edit_state, &edit_state.StbState);
}
}
else if (is_ctrl_only && IsKeyPressedMap(ImGuiKey_V) && is_editable)
else if (is_shortcutkey_only && IsKeyPressedMap(ImGuiKey_V) && is_editable)
{
// Paste
if (g.IO.GetClipboardTextFn)
@ -8471,7 +8496,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled)
bool want_open = false, want_close = false;
if (window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu))
{
// Implement http://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown to avoid using timers so menus feel more reactive.
// Implement http://bjk5.com/post/44698559168/breaking-down-amazons-mega-dropdown to avoid using timers, so menus feels more reactive.
bool moving_within_opened_triangle = false;
if (g.HoveredWindow == window && g.OpenedPopupStack.Size > g.CurrentPopupStack.Size && g.OpenedPopupStack[g.CurrentPopupStack.Size].ParentWindow == window)
{

View File

@ -105,7 +105,6 @@ namespace ImGui
IMGUI_API ImGuiStyle& GetStyle();
IMGUI_API ImDrawData* GetDrawData(); // same value as passed to your io.RenderDrawListsFn() function. valid after Render() and until the next call to NewFrame()
IMGUI_API void NewFrame(); // start a new ImGui frame, you can submit any command from this point until NewFrame()/Render().
IMGUI_API void EndFrame(); // ends the ImGui frame. automatically called by Render()!
IMGUI_API void Render(); // ends the ImGui frame, finalize rendering data, then call your io.RenderDrawListsFn() function if set.
IMGUI_API void Shutdown();
IMGUI_API void ShowUserGuide(); // help block
@ -114,11 +113,11 @@ namespace ImGui
IMGUI_API void ShowMetricsWindow(bool* opened = NULL); // metrics window for debugging ImGui
// Window
IMGUI_API bool Begin(const char* name, bool* p_opened = NULL, ImGuiWindowFlags flags = 0); // see .cpp for details. return false when window is collapsed, so you can early out in your code. 'bool* p_opened' creates a widget on the upper-right to close the window (which sets your bool to false).
IMGUI_API bool Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_use, float bg_alpha = -1.0f, ImGuiWindowFlags flags = 0); // this is the older/longer API. the extra parameters aren't very relevant. call SetNextWindowSize() instead if you want to set a window size. For regular windows, 'size_on_first_use' only applies to the first time EVER the window is created and probably not what you want! maybe obsolete this API eventually.
IMGUI_API void End();
IMGUI_API bool BeginChild(const char* str_id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags extra_flags = 0); // begin a scrolling region. size==0.0f: use remaining window size, size<0.0f: use remaining window size minus abs(size). size>0.0f: fixed size. each axis can use a different mode, e.g. ImVec2(0,400).
IMGUI_API bool BeginChild(ImGuiID id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags extra_flags = 0); // "
IMGUI_API bool Begin(const char* name, bool* p_opened = NULL, ImGuiWindowFlags flags = 0); // push window to the stack and start appending to it. see .cpp for details. return false when window is collapsed, so you can early out in your code. 'bool* p_opened' creates a widget on the upper-right to close the window (which sets your bool to false).
IMGUI_API bool Begin(const char* name, bool* p_opened, const ImVec2& size_on_first_use, float bg_alpha = -1.0f, ImGuiWindowFlags flags = 0); // OBSOLETE. this is the older/longer API. the extra parameters aren't very relevant. call SetNextWindowSize() instead if you want to set a window size. For regular windows, 'size_on_first_use' only applies to the first time EVER the window is created and probably not what you want! might obsolete this API eventually.
IMGUI_API void End(); // finish appending to current window, pop it off the window stack.
IMGUI_API bool BeginChild(const char* str_id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags extra_flags = 0); // begin a scrolling region. size==0.0f: use remaining window size, size<0.0f: use remaining window size minus abs(size). size>0.0f: fixed size. each axis can use a different mode, e.g. ImVec2(0,400).
IMGUI_API bool BeginChild(ImGuiID id, const ImVec2& size = ImVec2(0,0), bool border = false, ImGuiWindowFlags extra_flags = 0); // "
IMGUI_API void EndChild();
IMGUI_API ImVec2 GetContentRegionMax(); // current content boundaries (typically window boundaries including scrolling, or current column boundaries), in windows coordinates
IMGUI_API ImVec2 GetContentRegionAvail(); // == GetContentRegionMax() - GetCursorPos()
@ -467,11 +466,12 @@ enum ImGuiWindowFlags_
ImGuiWindowFlags_NoSavedSettings = 1 << 8, // Never load/save settings in .ini file
ImGuiWindowFlags_NoInputs = 1 << 9, // Disable catching mouse or keyboard inputs
ImGuiWindowFlags_MenuBar = 1 << 10, // Has a menu-bar
ImGuiWindowFlags_HorizontalScrollbar = 1 << 11, // Allow horizontal scrollbar to appear (off by default). You need to use SetNextWindowContentSize(ImVec2(width,0.0f)); prior to calling Begin() to specify width. Read code in imgui_demo in the "Horizontal Scrolling" section.
ImGuiWindowFlags_HorizontalScrollbar = 1 << 11, // Allow horizontal scrollbar to appear (off by default). You may use SetNextWindowContentSize(ImVec2(width,0.0f)); prior to calling Begin() to specify width. Read code in imgui_demo in the "Horizontal Scrolling" section.
ImGuiWindowFlags_NoFocusOnAppearing = 1 << 12, // Disable taking focus when transitioning from hidden to visible state
ImGuiWindowFlags_NoBringToFrontOnFocus = 1 << 13, // Disable bringing window to front when taking focus (e.g. clicking on it or programatically giving it focus)
ImGuiWindowFlags_ForceVerticalScrollbar = 1 << 14, // Always show vertical scrollbar (even if ContentSize.y < Size.y)
ImGuiWindowFlags_ForceHorizontalScrollbar=1 << 15, // Always show horizontal scrollbar (even if ContentSize.x < Size.x)
ImGuiWindowFlags_AlwaysVerticalScrollbar= 1 << 14, // Always show vertical scrollbar (even if ContentSize.y < Size.y)
ImGuiWindowFlags_AlwaysHorizontalScrollbar=1<< 15, // Always show horizontal scrollbar (even if ContentSize.x < Size.x)
ImGuiWindowFlags_AlwaysUseWindowPadding = 1 << 16, // Ensure child windows without border uses style.WindowPadding (ignored by default for non-bordered child windows, because more convenient)
// [Internal]
ImGuiWindowFlags_ChildWindow = 1 << 20, // Don't use! For internal use by BeginChild()
ImGuiWindowFlags_ChildWindowAutoFitX = 1 << 21, // Don't use! For internal use by BeginChild()
@ -546,8 +546,9 @@ enum ImGuiCol_
{
ImGuiCol_Text,
ImGuiCol_TextDisabled,
ImGuiCol_WindowBg,
ImGuiCol_ChildWindowBg,
ImGuiCol_WindowBg, // Background of normal windows
ImGuiCol_ChildWindowBg, // Background of child windows
ImGuiCol_PopupBg, // Background of popups, menus, tooltips windows
ImGuiCol_Border,
ImGuiCol_BorderShadow,
ImGuiCol_FrameBg, // Background of checkbox, radio button, plot, slider, text input
@ -585,7 +586,6 @@ enum ImGuiCol_
ImGuiCol_PlotHistogram,
ImGuiCol_PlotHistogramHovered,
ImGuiCol_TextSelectedBg,
ImGuiCol_TooltipBg,
ImGuiCol_ModalWindowDarkening, // darken entire screen when a modal window is active
ImGuiCol_COUNT
};
@ -664,7 +664,6 @@ struct ImGuiStyle
ImVec2 ItemSpacing; // Horizontal and vertical spacing between widgets/lines
ImVec2 ItemInnerSpacing; // Horizontal and vertical spacing between within elements of a composed widget (e.g. a slider and its label)
ImVec2 TouchExtraPadding; // Expand reactive bounding box for touch-based system where touch position is not accurate enough. Unfortunately we don't sort widgets so priority on overlap will always be given to the first widget. So don't grow this too much!
float WindowFillAlphaDefault; // Default alpha of window background, if not specified in ImGui::Begin()
float IndentSpacing; // Horizontal indentation when e.g. entering a tree node
float ColumnsMinSpacing; // Minimum horizontal spacing between two columns
float ScrollbarSize; // Width of the vertical scrollbar, Height of the horizontal scrollbar
@ -710,6 +709,12 @@ struct ImGuiIO
ImVec2 DisplayVisibleMin; // <unset> (0.0f,0.0f) // If you use DisplaySize as a virtual space larger than your screen, set DisplayVisibleMin/Max to the visible area.
ImVec2 DisplayVisibleMax; // <unset> (0.0f,0.0f) // If the values are the same, we defaults to Min=(0.0f) and Max=DisplaySize
// Advanced/subtle behaviors
bool WordMovementUsesAltKey; // = defined(__APPLE__) // OS X style: Text editing cursor movement using Alt instead of Ctrl
bool ShortcutsUseSuperKey; // = defined(__APPLE__) // OS X style: Shortcuts using Cmd/Super instead of Ctrl
bool DoubleClickSelectsWord; // = defined(__APPLE__) // OS X style: Double click selects by word instead of selecting whole text
bool MultiSelectUsesSuperKey; // = defined(__APPLE__) // OS X style: Multi-selection in lists uses Cmd/Super instead of Ctrl [unused yet]
//------------------------------------------------------------------
// User Functions
//------------------------------------------------------------------
@ -745,6 +750,7 @@ struct ImGuiIO
bool KeyCtrl; // Keyboard modifier pressed: Control
bool KeyShift; // Keyboard modifier pressed: Shift
bool KeyAlt; // Keyboard modifier pressed: Alt
bool KeySuper; // Keyboard modifier pressed: Cmd/Super/Windows
bool KeysDown[512]; // Keyboard keys that are pressed (in whatever storage order you naturally have access to keyboard data)
ImWchar InputCharacters[16+1]; // List of characters input (translated by user from keypress+keyboard state). Fill using AddInputCharacter() helper.
@ -982,7 +988,8 @@ struct ImGuiTextEditCallbackData
bool HasSelection() const { return SelectionStart != SelectionEnd; }
};
// ImColor() is just a helper that implicity converts to either ImU32 (packed 4x1 byte) or ImVec4 (4x1 float)
// ImColor() helper to implicity converts colors to either ImU32 (packed 4x1 byte) or ImVec4 (4x1 float)
// Avoid storing ImColor! Store either u32 of ImVec4. This is not a full-featured color class.
// None of the ImGui API are using ImColor directly but you can use it as a convenience to pass colors in either ImU32 or ImVec4 formats.
struct ImColor
{

View File

@ -139,7 +139,6 @@ void ImGui::ShowTestWindow(bool* p_opened)
static bool no_scrollbar = false;
static bool no_collapse = false;
static bool no_menu = false;
static float bg_alpha = -0.01f; // <0: default
// Demonstrate the various window flags. Typically you would just use the default.
ImGuiWindowFlags window_flags = 0;
@ -150,7 +149,8 @@ void ImGui::ShowTestWindow(bool* p_opened)
if (no_scrollbar) window_flags |= ImGuiWindowFlags_NoScrollbar;
if (no_collapse) window_flags |= ImGuiWindowFlags_NoCollapse;
if (!no_menu) window_flags |= ImGuiWindowFlags_MenuBar;
if (!ImGui::Begin("ImGui Demo", p_opened, ImVec2(550,680), bg_alpha, window_flags))
ImGui::SetNextWindowSize(ImVec2(550,680), ImGuiSetCond_FirstUseEver);
if (!ImGui::Begin("ImGui Demo", p_opened, window_flags))
{
// Early out if the window is collapsed, as an optimization.
ImGui::End();
@ -211,10 +211,6 @@ void ImGui::ShowTestWindow(bool* p_opened)
ImGui::Checkbox("No collapse", &no_collapse);
ImGui::Checkbox("No menu", &no_menu);
ImGui::PushItemWidth(100);
ImGui::DragFloat("Window Fill Alpha", &bg_alpha, 0.005f, -0.01f, 1.0f, bg_alpha < 0.0f ? "(default)" : "%.3f"); // Not exposing zero here so user doesn't "lose" the UI (zero alpha clips all widgets). But application code could have a toggle to switch between zero and non-zero.
ImGui::PopItemWidth();
if (ImGui::TreeNode("Style"))
{
ImGui::ShowStyleEditor();
@ -1500,7 +1496,7 @@ void ImGui::ShowTestWindow(bool* p_opened)
ImGui::Text("Keys down:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (io.KeysDownDuration[i] >= 0.0f) { ImGui::SameLine(); ImGui::Text("%d (%.02f secs)", i, io.KeysDownDuration[i]); }
ImGui::Text("Keys pressed:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyPressed(i)) { ImGui::SameLine(); ImGui::Text("%d", i); }
ImGui::Text("Keys release:"); for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); i++) if (ImGui::IsKeyReleased(i)) { ImGui::SameLine(); ImGui::Text("%d", i); }
ImGui::Text("KeyMods: %s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "");
ImGui::Text("KeyMods: %s%s%s%s", io.KeyCtrl ? "CTRL " : "", io.KeyShift ? "SHIFT " : "", io.KeyAlt ? "ALT " : "", io.KeySuper ? "SUPER " : "");
ImGui::Text("WantCaptureMouse: %s", io.WantCaptureMouse ? "true" : "false");
ImGui::Text("WantCaptureKeyboard: %s", io.WantCaptureKeyboard ? "true" : "false");
@ -1561,7 +1557,6 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
ImGui::DragFloat("Curve Tessellation Tolerance", &style.CurveTessellationTol, 0.02f, 0.10f, FLT_MAX, NULL, 2.0f);
if (style.CurveTessellationTol < 0.0f) style.CurveTessellationTol = 0.10f;
ImGui::DragFloat("Global Alpha", &style.Alpha, 0.005f, 0.20f, 1.0f, "%.2f"); // Not exposing zero here so user doesn't "lose" the UI (zero alpha clips all widgets). But application code could have a toggle to switch between zero and non-zero.
ImGui::DragFloat("Window Fill Alpha Default", &style.WindowFillAlphaDefault, 0.005f, 0.0f, 1.0f, "%.2f");
ImGui::PopItemWidth();
ImGui::TreePop();
}
@ -1618,7 +1613,7 @@ void ImGui::ShowStyleEditor(ImGuiStyle* ref)
static ImGuiTextFilter filter;
filter.Draw("Filter colors", 200);
ImGui::BeginChild("#colors", ImVec2(0, 300), true);
ImGui::BeginChild("#colors", ImVec2(0, 300), true, ImGuiWindowFlags_AlwaysVerticalScrollbar);
ImGui::PushItemWidth(-160);
ImGui::ColorEditMode(edit_mode);
for (int i = 0; i < ImGuiCol_COUNT; i++)

View File

@ -679,6 +679,8 @@ namespace ImGui
IMGUI_API ImGuiWindow* FindWindowByName(const char* name);
IMGUI_API void FocusWindow(ImGuiWindow* window);
IMGUI_API void EndFrame(); // Ends the ImGui frame. Automatically called by Render()! you most likely don't need to ever call that yourself directly. If you don't need to render you can call EndFrame() but you'll have wasted CPU already. If you don't need to render, don't create any windows instead!
IMGUI_API void SetActiveID(ImGuiID id, ImGuiWindow* window);
IMGUI_API void SetHoveredID(ImGuiID id);
IMGUI_API void KeepAliveID(ImGuiID id);

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,12 @@
// stb_rect_pack.h - v0.05 - public domain - rectangle packing
#if defined(__GNUC__) || defined(__clang__)
# pragma GCC diagnostic ignored "-Wtype-limits"
# pragma GCC diagnostic ignored "-Wunused-function"
# pragma GCC diagnostic ignored "-Wunused-parameter"
#else
# pragma warning(disable:4100) // C4100: 'c': unreferenced formal parameter
#endif
// stb_rect_pack.h - v0.08 - public domain - rectangle packing
// Sean Barrett 2014
//
// Useful for e.g. packing rectangular textures into an atlas.
@ -13,6 +21,7 @@
// More docs to come.
//
// No memory allocations; uses qsort() and assert() from stdlib.
// Can override those by defining STBRP_SORT and STBRP_ASSERT.
//
// This library currently uses the Skyline Bottom-Left algorithm.
//
@ -20,11 +29,29 @@
// implement them to the same API, but with a different init
// function.
//
// Credits
//
// Library
// Sean Barrett
// Minor features
// Martins Mozeiko
// Bugfixes / warning fixes
// Jeremy Jaussaud
//
// Version history:
//
// 0.08 (2015-09-13) really fix bug with empty rects (w=0 or h=0)
// 0.07 (2015-09-13) fix bug with empty rects (w=0 or h=0)
// 0.06 (2015-04-15) added STBRP_SORT to allow replacing qsort
// 0.05: added STBRP_ASSERT to allow replacing assert
// 0.04: fixed minor bug in STBRP_LARGE_RECTS support
// 0.01: initial release
//
// LICENSE
//
// This software is dual-licensed to the public domain and under the following
// license: you are granted a perpetual, irrevocable license to copy, modify,
// publish, and distribute this file as you see fit.
//////////////////////////////////////////////////////////////////////////////
//
@ -129,7 +156,7 @@ enum
{
STBRP_HEURISTIC_Skyline_default=0,
STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default,
STBRP_HEURISTIC_Skyline_BF_sortHeight
STBRP_HEURISTIC_Skyline_BF_sortHeight,
};
@ -169,7 +196,10 @@ struct stbrp_context
//
#ifdef STB_RECT_PACK_IMPLEMENTATION
#ifndef STBRP_SORT
#include <stdlib.h>
#define STBRP_SORT qsort
#endif
#ifndef STBRP_ASSERT
#include <assert.h>
@ -178,7 +208,7 @@ struct stbrp_context
enum
{
STBRP__INIT_skyline = 1
STBRP__INIT_skyline = 1,
};
STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic)
@ -248,7 +278,6 @@ STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height,
// find minimum y position if it starts at x1
static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0, int width, int *pwaste)
{
(void)c;
stbrp_node *node = first;
int x1 = x0 + width;
int min_y, visited_width, waste_area;
@ -525,20 +554,24 @@ STBRP_DEF void stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int n
}
// sort according to heuristic
qsort(rects, num_rects, sizeof(rects[0]), rect_height_compare);
STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare);
for (i=0; i < num_rects; ++i) {
stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h);
if (fr.prev_link) {
rects[i].x = (stbrp_coord) fr.x;
rects[i].y = (stbrp_coord) fr.y;
if (rects[i].w == 0 || rects[i].h == 0) {
rects[i].x = rects[i].y = 0; // empty rect needs no space
} else {
rects[i].x = rects[i].y = STBRP__MAXVAL;
stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h);
if (fr.prev_link) {
rects[i].x = (stbrp_coord) fr.x;
rects[i].y = (stbrp_coord) fr.y;
} else {
rects[i].x = rects[i].y = STBRP__MAXVAL;
}
}
}
// unsort
qsort(rects, num_rects, sizeof(rects[0]), rect_original_order);
STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order);
// set was_packed flags
for (i=0; i < num_rects; ++i)

View File

@ -1,4 +1,4 @@
// stb_textedit.h - v1.4 - public domain - Sean Barrett
// stb_textedit.h - v1.8 - public domain - Sean Barrett
// Development of this library was sponsored by RAD Game Tools
//
// This C header file implements the guts of a multi-line text-editing
@ -17,19 +17,24 @@
//
// LICENSE
//
// This software has been placed in the public domain by its author.
// Where that dedication is not recognized, you are granted a perpetual,
// irrevocable license to copy and modify this file as you see fit.
// This software is dual-licensed to the public domain and under the following
// license: you are granted a perpetual, irrevocable license to copy, modify,
// publish, and distribute this file as you see fit.
//
//
// DEPENDENCIES
//
// Uses the C runtime function 'memmove'. Uses no other functions.
// Performs no runtime allocations.
// Uses the C runtime function 'memmove', which you can override
// by defining STB_TEXTEDIT_memmove before the implementation.
// Uses no other functions. Performs no runtime allocations.
//
//
// VERSION HISTORY
//
// 1.8 (2016-04-02) better keyboard handling when mouse button is down
// 1.7 (2015-09-13) change y range handling in case baseline is non-0
// 1.6 (2015-04-15) allow STB_TEXTEDIT_memmove
// 1.5 (2014-09-10) add support for secondary keys for OS X
// 1.4 (2014-08-17) fix signed/unsigned warnings
// 1.3 (2014-06-19) fix mouse clicking to round to nearest char boundary
// 1.2 (2014-05-27) fix some RAD types that had crept into the new code
@ -42,7 +47,13 @@
// ADDITIONAL CONTRIBUTORS
//
// Ulf Winklemann: move-by-word in 1.1
// Scott Graham: mouse selection bugfix in 1.3
// Fabian Giesen: secondary key inputs in 1.5
// Martins Mozeiko: STB_TEXTEDIT_memmove
//
// Bugfixes:
// Scott Graham
// Daniel Keller
// Omar Cornut
//
// USAGE
//
@ -142,6 +153,10 @@
// required for WORDLEFT/WORDRIGHT
// STB_TEXTEDIT_K_WORDLEFT keyboard input to move cursor left one word // e.g. ctrl-LEFT
// STB_TEXTEDIT_K_WORDRIGHT keyboard input to move cursor right one word // e.g. ctrl-RIGHT
// STB_TEXTEDIT_K_LINESTART2 secondary keyboard input to move cursor to start of line
// STB_TEXTEDIT_K_LINEEND2 secondary keyboard input to move cursor to end of line
// STB_TEXTEDIT_K_TEXTSTART2 secondary keyboard input to move cursor to start of text
// STB_TEXTEDIT_K_TEXTEND2 secondary keyboard input to move cursor to end of text
//
// Todo:
// STB_TEXTEDIT_K_PGUP keyboard input to move cursor up a page
@ -352,7 +367,10 @@ typedef struct
// included just the "header" portion
#ifdef STB_TEXTEDIT_IMPLEMENTATION
#include <string.h> // memmove
#ifndef STB_TEXTEDIT_memmove
#include <string.h>
#define STB_TEXTEDIT_memmove memmove
#endif
/////////////////////////////////////////////////////////////////////////////
@ -368,9 +386,6 @@ static int stb_text_locate_coord(STB_TEXTEDIT_STRING *str, float x, float y)
float base_y = 0, prev_x;
int i=0, k;
if (y < 0)
return 0;
r.x0 = r.x1 = 0;
r.ymin = r.ymax = 0;
r.num_chars = 0;
@ -381,6 +396,9 @@ static int stb_text_locate_coord(STB_TEXTEDIT_STRING *str, float x, float y)
if (r.num_chars <= 0)
return n;
if (i==0 && y < base_y + r.ymin)
return 0;
if (y < base_y + r.ymax)
break;
@ -434,6 +452,8 @@ static void stb_textedit_click(STB_TEXTEDIT_STRING *str, STB_TexteditState *stat
static void stb_textedit_drag(STB_TEXTEDIT_STRING *str, STB_TexteditState *state, float x, float y)
{
int p = stb_text_locate_coord(str, x, y);
if (state->select_start == state->select_end)
state->select_start = state->cursor;
state->cursor = state->select_end = p;
}
@ -917,23 +937,35 @@ retry:
state->has_preferred_x = 0;
break;
#ifdef STB_TEXTEDIT_K_TEXTSTART2
case STB_TEXTEDIT_K_TEXTSTART2:
#endif
case STB_TEXTEDIT_K_TEXTSTART:
state->cursor = state->select_start = state->select_end = 0;
state->has_preferred_x = 0;
break;
#ifdef STB_TEXTEDIT_K_TEXTEND2
case STB_TEXTEDIT_K_TEXTEND2:
#endif
case STB_TEXTEDIT_K_TEXTEND:
state->cursor = STB_TEXTEDIT_STRINGLEN(str);
state->select_start = state->select_end = 0;
state->has_preferred_x = 0;
break;
#ifdef STB_TEXTEDIT_K_TEXTSTART2
case STB_TEXTEDIT_K_TEXTSTART2 | STB_TEXTEDIT_K_SHIFT:
#endif
case STB_TEXTEDIT_K_TEXTSTART | STB_TEXTEDIT_K_SHIFT:
stb_textedit_prep_selection_at_cursor(state);
state->cursor = state->select_end = 0;
state->has_preferred_x = 0;
break;
#ifdef STB_TEXTEDIT_K_TEXTEND2
case STB_TEXTEDIT_K_TEXTEND2 | STB_TEXTEDIT_K_SHIFT:
#endif
case STB_TEXTEDIT_K_TEXTEND | STB_TEXTEDIT_K_SHIFT:
stb_textedit_prep_selection_at_cursor(state);
state->cursor = state->select_end = STB_TEXTEDIT_STRINGLEN(str);
@ -941,6 +973,9 @@ retry:
break;
#ifdef STB_TEXTEDIT_K_LINESTART2
case STB_TEXTEDIT_K_LINESTART2:
#endif
case STB_TEXTEDIT_K_LINESTART: {
StbFindState find;
stb_textedit_clamp(str, state);
@ -951,16 +986,25 @@ retry:
break;
}
#ifdef STB_TEXTEDIT_K_LINEEND2
case STB_TEXTEDIT_K_LINEEND2:
#endif
case STB_TEXTEDIT_K_LINEEND: {
StbFindState find;
stb_textedit_clamp(str, state);
stb_textedit_move_to_first(state);
stb_textedit_find_charpos(&find, str, state->cursor, state->single_line);
state->cursor = find.first_char + find.length;
state->has_preferred_x = 0;
state->cursor = find.first_char + find.length;
if (find.length > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) == STB_TEXTEDIT_NEWLINE)
--state->cursor;
break;
}
#ifdef STB_TEXTEDIT_K_LINESTART2
case STB_TEXTEDIT_K_LINESTART2 | STB_TEXTEDIT_K_SHIFT:
#endif
case STB_TEXTEDIT_K_LINESTART | STB_TEXTEDIT_K_SHIFT: {
StbFindState find;
stb_textedit_clamp(str, state);
@ -971,13 +1015,19 @@ retry:
break;
}
#ifdef STB_TEXTEDIT_K_LINEEND2
case STB_TEXTEDIT_K_LINEEND2 | STB_TEXTEDIT_K_SHIFT:
#endif
case STB_TEXTEDIT_K_LINEEND | STB_TEXTEDIT_K_SHIFT: {
StbFindState find;
stb_textedit_clamp(str, state);
stb_textedit_prep_selection_at_cursor(state);
stb_textedit_find_charpos(&find, str, state->cursor, state->single_line);
state->cursor = state->select_end = find.first_char + find.length;
state->has_preferred_x = 0;
state->cursor = find.first_char + find.length;
if (find.length > 0 && STB_TEXTEDIT_GETCHAR(str, state->cursor-1) == STB_TEXTEDIT_NEWLINE)
--state->cursor;
state->select_end = state->cursor;
break;
}
@ -1008,13 +1058,13 @@ static void stb_textedit_discard_undo(StbUndoState *state)
int n = state->undo_rec[0].insert_length, i;
// delete n characters from all other records
state->undo_char_point = state->undo_char_point - (short) n; // vsnet05
memmove(state->undo_char, state->undo_char + n, (size_t) ((size_t)state->undo_char_point*sizeof(STB_TEXTEDIT_CHARTYPE)));
STB_TEXTEDIT_memmove(state->undo_char, state->undo_char + n, (size_t) (state->undo_char_point*sizeof(STB_TEXTEDIT_CHARTYPE)));
for (i=0; i < state->undo_point; ++i)
if (state->undo_rec[i].char_storage >= 0)
state->undo_rec[i].char_storage = state->undo_rec[i].char_storage - (short) n; // vsnet05 // @OPTIMIZE: get rid of char_storage and infer it
}
--state->undo_point;
memmove(state->undo_rec, state->undo_rec+1, (size_t) ((size_t)state->undo_point*sizeof(state->undo_rec[0])));
STB_TEXTEDIT_memmove(state->undo_rec, state->undo_rec+1, (size_t) (state->undo_point*sizeof(state->undo_rec[0])));
}
}
@ -1032,13 +1082,13 @@ static void stb_textedit_discard_redo(StbUndoState *state)
int n = state->undo_rec[k].insert_length, i;
// delete n characters from all other records
state->redo_char_point = state->redo_char_point + (short) n; // vsnet05
memmove(state->undo_char + state->redo_char_point, state->undo_char + state->redo_char_point-n, (size_t) ((size_t)(STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_char_point)*sizeof(STB_TEXTEDIT_CHARTYPE)));
STB_TEXTEDIT_memmove(state->undo_char + state->redo_char_point, state->undo_char + state->redo_char_point-n, (size_t) ((STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_char_point)*sizeof(STB_TEXTEDIT_CHARTYPE)));
for (i=state->redo_point; i < k; ++i)
if (state->undo_rec[i].char_storage >= 0)
state->undo_rec[i].char_storage = state->undo_rec[i].char_storage + (short) n; // vsnet05
}
++state->redo_point;
memmove(state->undo_rec + state->redo_point-1, state->undo_rec + state->redo_point, (size_t) ((size_t)(STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point)*sizeof(state->undo_rec[0])));
STB_TEXTEDIT_memmove(state->undo_rec + state->redo_point-1, state->undo_rec + state->redo_point, (size_t) ((STB_TEXTEDIT_UNDOSTATECOUNT - state->redo_point)*sizeof(state->undo_rec[0])));
}
}

View File

@ -27,6 +27,10 @@
// Mikko Mononen: compound shape support, more cmap formats
// Tor Andersson: kerning, subpixel rendering
//
// Misc other:
// Ryan Gordon
// Simon Glass
//
// Bug/warning reports/fixes:
// "Zer" on mollyrocket (with fix)
// Cass Everitt
@ -45,13 +49,18 @@
// Omar Cornut
// github:aloucks
// Peter LaValle
// Sergey Popov
// Giumo X. Clanjor
//
// Misc other:
// Ryan Gordon
// Higor Euripedes
// Thomas Fields
// Derek Vinyard
//
// VERSION HISTORY
//
// 1.11 (2016-04-02) fix unused-variable warning
// 1.10 (2016-04-02) user-defined fabs(); rare memory leak; remove duplicate typedef
// 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use allocation userdata properly
// 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges
// 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints;
// variant PackFontRanges to pack and render in separate phases;
// fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?);
@ -68,9 +77,9 @@
//
// LICENSE
//
// This software is in the public domain. Where that dedication is not
// recognized, you are granted a perpetual, irrevocable license to copy,
// distribute, and modify this file as you see fit.
// This software is dual-licensed to the public domain and under the following
// license: you are granted a perpetual, irrevocable license to copy, modify,
// publish, and distribute this file as you see fit.
//
// USAGE
//
@ -406,6 +415,11 @@ int main(int arg, char **argv)
#define STBTT_sqrt(x) sqrt(x)
#endif
#ifndef STBTT_fabs
#include <math.h>
#define STBTT_fabs(x) fabs(x)
#endif
// #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h
#ifndef STBTT_malloc
#include <stdlib.h>
@ -629,7 +643,7 @@ STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index);
// The following structure is defined publically so you can declare one on
// the stack or as a global or etc, but you should treat it as opaque.
typedef struct stbtt_fontinfo
struct stbtt_fontinfo
{
void * userdata;
unsigned char * data; // pointer to .ttf file
@ -640,7 +654,7 @@ typedef struct stbtt_fontinfo
int loca,head,glyf,hhea,hmtx,kern; // table locations as offset from start of .ttf
int index_map; // a cmap mapping for our chosen character encoding
int indexToLocFormat; // format needed to map from glyph index to glyph
} stbtt_fontinfo;
};
STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset);
// Given an offset into the file that defines a font, this function builds
@ -808,7 +822,16 @@ typedef struct
unsigned char *pixels;
} stbtt__bitmap;
STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata);
// rasterize a shape with quadratic beziers into a bitmap
STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, // 1-channel bitmap to draw into
float flatness_in_pixels, // allowable error of curve in pixels
stbtt_vertex *vertices, // array of vertices defining shape
int num_verts, // number of vertices in above array
float scale_x, float scale_y, // scale applied to input vertices
float shift_x, float shift_y, // translation applied to input vertices
int x_off, int y_off, // another translation applied to input
int invert, // if non-zero, vertically flip shape
void *userdata); // context for to STBTT_MALLOC
//////////////////////////////////////////////////////////////////////////////
//
@ -933,6 +956,12 @@ typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERS
#define STBTT_RASTERIZER_VERSION 2
#endif
#ifdef _MSC_VER
#define STBTT__NOTUSED(v) (void)(v)
#else
#define STBTT__NOTUSED(v) (void)sizeof(v)
#endif
//////////////////////////////////////////////////////////////////////////
//
// accessors to parse data from file
@ -1550,7 +1579,7 @@ STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v)
STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1)
{
int x0,y0,x1,y1;
int x0=0,y0=0,x1,y1; // =0 suppresses compiler warning
if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) {
// e.g. space character
if (ix0) *ix0 = 0;
@ -1666,6 +1695,7 @@ static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, i
{
stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata);
float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
STBTT_assert(z != NULL);
if (!z) return z;
// round dx down to avoid overshooting
@ -1687,10 +1717,11 @@ static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, i
{
stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata);
float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
STBTT_assert(z != NULL);
//STBTT_assert(e->y0 <= start_point);
if (!z) return z;
z->fdx = dxdy;
z->fdy = (1/dxdy);
z->fdy = dxdy != 0.0f ? (1.0f/dxdy) : 0.0f;
z->fx = e->x0 + dxdy * (start_point - e->y0);
z->fx -= off_x;
z->direction = e->invert ? 1.0f : -1.0f;
@ -1751,7 +1782,7 @@ static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__ac
static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata)
{
stbtt__hheap hh = { 0 };
stbtt__hheap hh = { 0, 0, 0 };
stbtt__active_edge *active = NULL;
int y,j=0;
int max_weight = (255 / vsubsample); // weight per vertical scanline
@ -1811,21 +1842,23 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e,
while (e->y0 <= scan_y) {
if (e->y1 > scan_y) {
stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y, userdata);
// find insertion point
if (active == NULL)
active = z;
else if (z->x < active->x) {
// insert at front
z->next = active;
active = z;
} else {
// find thing to insert AFTER
stbtt__active_edge *p = active;
while (p->next && p->next->x < z->x)
p = p->next;
// at this point, p->next->x is NOT < z->x
z->next = p->next;
p->next = z;
if (z != NULL) {
// find insertion point
if (active == NULL)
active = z;
else if (z->x < active->x) {
// insert at front
z->next = active;
active = z;
} else {
// find thing to insert AFTER
stbtt__active_edge *p = active;
while (p->next && p->next->x < z->x)
p = p->next;
// at this point, p->next->x is NOT < z->x
z->next = p->next;
p->next = z;
}
}
}
++e;
@ -1913,7 +1946,7 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill,
float dx = e->fdx;
float xb = x0 + dx;
float x_top, x_bottom;
float y0,y1;
float sy0,sy1;
float dy = e->fdy;
STBTT_assert(e->sy <= y_bottom && e->ey >= y_top);
@ -1922,17 +1955,17 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill,
// line with y_top, but that may be off the line segment.
if (e->sy > y_top) {
x_top = x0 + dx * (e->sy - y_top);
y0 = e->sy;
sy0 = e->sy;
} else {
x_top = x0;
y0 = y_top;
sy0 = y_top;
}
if (e->ey < y_bottom) {
x_bottom = x0 + dx * (e->ey - y_top);
y1 = e->ey;
sy1 = e->ey;
} else {
x_bottom = xb;
y1 = y_bottom;
sy1 = y_bottom;
}
if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len) {
@ -1942,7 +1975,7 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill,
float height;
// simple case, only spans one pixel
int x = (int) x_top;
height = y1 - y0;
height = sy1 - sy0;
STBTT_assert(x >= 0 && x < len);
scanline[x] += e->direction * (1-((x_top - x) + (x_bottom-x))/2) * height;
scanline_fill[x] += e->direction * height; // everything right of this pixel is filled
@ -1953,9 +1986,9 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill,
if (x_top > x_bottom) {
// flip scanline vertically; signed area is the same
float t;
y0 = y_bottom - (y0 - y_top);
y1 = y_bottom - (y1 - y_top);
t = y0, y0 = y1, y1 = t;
sy0 = y_bottom - (sy0 - y_top);
sy1 = y_bottom - (sy1 - y_top);
t = sy0, sy0 = sy1, sy1 = t;
t = x_bottom, x_bottom = x_top, x_top = t;
dx = -dx;
dy = -dy;
@ -1969,7 +2002,7 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill,
sign = e->direction;
// area of the rectangle covered from y0..y_crossing
area = sign * (y_crossing-y0);
area = sign * (y_crossing-sy0);
// area of the triangle (x_top,y0), (x+1,y0), (x+1,y_crossing)
scanline[x1] += area * (1-((x_top - x1)+(x1+1-x1))/2);
@ -1980,11 +2013,11 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill,
}
y_crossing += dy * (x2 - (x1+1));
STBTT_assert(fabs(area) <= 1.01f);
STBTT_assert(STBTT_fabs(area) <= 1.01f);
scanline[x2] += area + sign * (1-((x2-x2)+(x_bottom-x2))/2) * (y1-y_crossing);
scanline[x2] += area + sign * (1-((x2-x2)+(x_bottom-x2))/2) * (sy1-y_crossing);
scanline_fill[x2] += sign * (y1-y0);
scanline_fill[x2] += sign * (sy1-sy0);
}
} else {
// if edge goes outside of box we're drawing, we require
@ -2053,13 +2086,13 @@ static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill,
// directly AA rasterize edges w/o supersampling
static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata)
{
(void)vsubsample;
stbtt__hheap hh;
memset(&hh, 0, sizeof(hh));
stbtt__hheap hh = { 0, 0, 0 };
stbtt__active_edge *active = NULL;
int y,j=0, i;
float scanline_data[129], *scanline, *scanline2;
STBTT__NOTUSED(vsubsample);
if (result->w > 64)
scanline = (float *) STBTT_malloc((result->w*2+1) * sizeof(float), userdata);
else
@ -2095,11 +2128,15 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e,
// insert all edges that start before the bottom of this scanline
while (e->y0 <= scan_y_bottom) {
stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata);
STBTT_assert(z->ey >= scan_y_top);
// insert at front
z->next = active;
active = z;
if (e->y0 != e->y1) {
stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata);
if (z != NULL) {
STBTT_assert(z->ey >= scan_y_top);
// insert at front
z->next = active;
active = z;
}
}
++e;
}
@ -2114,7 +2151,7 @@ static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e,
int m;
sum += scanline2[i];
k = scanline[i] + sum;
k = (float) fabs(k)*255 + 0.5f;
k = (float) STBTT_fabs(k)*255 + 0.5f;
m = (int) k;
if (m > 255) m = 255;
result->pixels[j*result->stride + i] = (unsigned char) m;
@ -2415,7 +2452,10 @@ STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info
if (scale_x == 0) scale_x = scale_y;
if (scale_y == 0) {
if (scale_x == 0) return NULL;
if (scale_x == 0) {
STBTT_free(vertices, info->userdata);
return NULL;
}
scale_y = scale_x;
}
@ -2507,6 +2547,7 @@ STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, // fo
float scale;
int x,y,bottom_y, i;
stbtt_fontinfo f;
f.userdata = NULL;
if (!stbtt_InitFont(&f, data, offset))
return -1;
STBTT_memset(pixels, 0, pw*ph); // background of 0 around pixels
@ -2570,11 +2611,6 @@ STBTT_DEF void stbtt_GetBakedQuad(stbtt_bakedchar *chardata, int pw, int ph, int
//
#ifndef STB_RECT_PACK_VERSION
#ifdef _MSC_VER
#define STBTT__NOTUSED(v) (void)(v)
#else
#define STBTT__NOTUSED(v) (void)sizeof(v)
#endif
typedef int stbrp_coord;
@ -2700,6 +2736,7 @@ static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_i
unsigned char buffer[STBTT_MAX_OVERSAMPLE];
int safe_w = w - kernel_width;
int j;
STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze
for (j=0; j < h; ++j) {
int i;
unsigned int total;
@ -2761,6 +2798,7 @@ static void stbtt__v_prefilter(unsigned char *pixels, int w, int h, int stride_i
unsigned char buffer[STBTT_MAX_OVERSAMPLE];
int safe_h = h - kernel_width;
int j;
STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); // suppress bogus warning from VS2013 -analyze
for (j=0; j < w; ++j) {
int i;
unsigned int total;
@ -2842,7 +2880,7 @@ STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, stbtt_fon
ranges[i].v_oversample = (unsigned char) spc->v_oversample;
for (j=0; j < ranges[i].num_chars; ++j) {
int x0,y0,x1,y1;
int codepoint = ranges[i].first_unicode_codepoint_in_range ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];
int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];
int glyph = stbtt_FindGlyphIndex(info, codepoint);
stbtt_GetGlyphBitmapBoxSubpixel(info,glyph,
scale * spc->h_oversample,
@ -2883,7 +2921,7 @@ STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, stbtt
if (r->was_packed) {
stbtt_packedchar *bc = &ranges[i].chardata_for_range[j];
int advance, lsb, x0,y0,x1,y1;
int codepoint = ranges[i].first_unicode_codepoint_in_range ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];
int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j];
int glyph = stbtt_FindGlyphIndex(info, codepoint);
stbrp_coord pad = (stbrp_coord) spc->padding;
@ -2969,6 +3007,7 @@ STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, unsigned char *fontd
if (rects == NULL)
return 0;
info.userdata = spc->user_allocator_context;
stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata,font_index));
n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects);
@ -3186,6 +3225,12 @@ STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *font_collection, const
// FULL VERSION HISTORY
//
// 1.11 (2016-04-02) fix unused-variable warning
// 1.10 (2016-04-02) allow user-defined fabs() replacement
// fix memory leak if fontsize=0.0
// fix warning from duplicate typedef
// 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use alloc userdata for PackFontRanges
// 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges
// 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints;
// allow PackFontRanges to pack and render in separate phases;
// fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?);

View File

@ -4,6 +4,9 @@ Everyone is welcome to contribute to bgfx by submitting bug reports, testing on
different platforms, writing examples, improving documentation, profiling and
optimizing, helping newcomers, telling others about bgfx, etc.
If you have just quick oneliner question it's prefereable to ask it at chat
https://gitter.im/bkaradzic/bgfx instead opening new issue.
## Submitting bugs
Unless bug is trivial, and easy to explain and understand, the fastest way to

View File

@ -1,6 +1,8 @@
[bgfx](https://github.com/bkaradzic/bgfx) - Cross-platform rendering library
============================================================================
[![Join the chat at https://gitter.im/bkaradzic/bgfx](https://badges.gitter.im/bkaradzic/bgfx.svg)](https://gitter.im/bkaradzic/bgfx)
[![Build Status](https://travis-ci.org/bkaradzic/bgfx.svg?branch=master)](https://travis-ci.org/bkaradzic/bgfx)
[![Build status](https://ci.appveyor.com/api/projects/status/ipa3ojgeaet1oko5?svg=true)](https://ci.appveyor.com/project/bkaradzic/bgfx)
@ -25,7 +27,7 @@ Supported rendering backends:
Supported HMD:
* OculusVR (0.4.2+)
* OculusVR (1.3.0)
Supported platforms:

View File

@ -7,7 +7,6 @@
#include "common.h"
#include "bgfx_utils.h"
#include "logo.h"
#include "imgui/imgui.h"
class ExampleHelloWorld : public entry::AppI
{
@ -29,111 +28,23 @@ class ExampleHelloWorld : public entry::AppI
// Set view 0 clear state.
bgfx::setViewClear(0
, BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH
, 0x000000ff
, 0x303030ff
, 1.0f
, 0
);
imguiCreate();
ImGui::GetIO().FontGlobalScale = 1.5;
}
virtual int shutdown() BX_OVERRIDE
{
// Cleanup.
imguiDestroy();
// Shutdown bgfx.
bgfx::shutdown();
return 0;
}
void displayMainMenu()
{
if (ImGui::BeginMainMenuBar())
{
if (ImGui::BeginMenu("Left"))
{
if (ImGui::MenuItem("Brief", "CTRL+1")) {}
if (ImGui::MenuItem("Medium", "CTRL+2")) {}
if (ImGui::MenuItem("Two columns", "CTRL+3")) {}
if (ImGui::MenuItem("Full (name)", "CTRL+4")) {}
if (ImGui::MenuItem("Full (size, time)", "CTRL+5")) {}
if (ImGui::MenuItem("Full (access)", "CTRL+6")) {}
ImGui::Separator();
if (ImGui::BeginMenu("Sort mode"))
{
ImGui::MenuItem("Name");
ImGui::MenuItem("Extension");
ImGui::MenuItem("Modif. Time");
ImGui::MenuItem("Size");
ImGui::MenuItem("Unsorted");
ImGui::EndMenu();
}
if (ImGui::MenuItem("Change source")) {}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Files"))
{
if (ImGui::MenuItem("User menu", "F2")) {}
if (ImGui::MenuItem("View", "F3")) {}
if (ImGui::MenuItem("Edit", "F4")) {}
if (ImGui::MenuItem("Copy", "F5")) {}
if (ImGui::MenuItem("Rename or move", "F6")) {}
if (ImGui::MenuItem("Make directory", "F7")) {}
if (ImGui::MenuItem("Delete", "F8")) {}
ImGui::Separator();
if (ImGui::MenuItem("File attributes", "CTRL+A")) {}
if (ImGui::MenuItem("Apply command", "CTRL+G")) {}
ImGui::Separator();
if (ImGui::MenuItem("Select group")) {}
if (ImGui::MenuItem("Unselect group")) {}
if (ImGui::MenuItem("Invert selection")) {}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Commands"))
{
if (ImGui::MenuItem("Find file", "ALT+F7")) {}
if (ImGui::MenuItem("History", "ALT+F8")) {}
if (ImGui::MenuItem("Maximize window", "ALT+F9")) {}
ImGui::Separator();
if (ImGui::MenuItem("Panel on/off", "CTRL+O")) {}
if (ImGui::MenuItem("Equal panels", "CTRL+=")) {}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Options"))
{
if (ImGui::MenuItem("Settings")) {}
ImGui::EndMenu();
}
if (ImGui::BeginMenu("Right"))
{
if (ImGui::MenuItem("Brief", "CTRL+1")) {}
if (ImGui::MenuItem("Medium", "CTRL+2")) {}
if (ImGui::MenuItem("Two columns", "CTRL+3")) {}
if (ImGui::MenuItem("Full (name)", "CTRL+4")) {}
if (ImGui::MenuItem("Full (size, time)", "CTRL+5")) {}
if (ImGui::MenuItem("Full (access)", "CTRL+6")) {}
ImGui::Separator();
if (ImGui::BeginMenu("Sort mode"))
{
ImGui::MenuItem("Name");
ImGui::MenuItem("Extension");
ImGui::MenuItem("Modif. Time");
ImGui::MenuItem("Size");
ImGui::MenuItem("Unsorted");
ImGui::EndMenu();
}
if (ImGui::MenuItem("Change source")) {}
ImGui::EndMenu();
}
ImGui::EndMainMenuBar();
}
}
bool update() BX_OVERRIDE
{
if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
if (!entry::processEvents(m_width, m_height, m_debug, m_reset) )
{
// Set view 0 default viewport.
bgfx::setViewRect(0, 0, 0, m_width, m_height);
@ -142,91 +53,18 @@ class ExampleHelloWorld : public entry::AppI
// if no other draw calls are submitted to view 0.
bgfx::touch(0);
imguiBeginFrame(m_mouseState.m_mx
, m_mouseState.m_my
, (m_mouseState.m_buttons[entry::MouseButton::Left] ? IMGUI_MBUT_LEFT : 0)
| (m_mouseState.m_buttons[entry::MouseButton::Right] ? IMGUI_MBUT_RIGHT : 0)
, m_mouseState.m_mz
, m_width
, m_height
);
displayMainMenu();
ImGui::SetNextWindowPos(ImVec2(0, 32));
ImGui::SetNextWindowSize(ImVec2(m_width/2, m_height - 32));
if (ImGui::Begin("Window1", nullptr, ImVec2(m_width/2, m_height-32), 1.0f, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoScrollbar))
{
ImGui::PushStyleVar(ImGuiStyleVar_ChildWindowRounding, 5.0f);
ImGui::BeginChild("Sub1", ImVec2(0, m_height - 48), true);
// Use debug font to print information about this example.
bgfx::dbgTextClear();
bgfx::dbgTextImage(bx::uint16_max(m_width /2/8, 20)-20
, bx::uint16_max(m_height/2/16, 6)-6
, 40
, 12
, s_logo
, 160
);
bgfx::dbgTextPrintf(0, 1, 0x4f, "bgfx/examples/00-helloworld");
bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: Initialization and debug text.");
ImGui::Columns(4, "mycolumns");
ImGui::Separator();
ImGui::Text("ID"); ImGui::NextColumn();
ImGui::Text("Name"); ImGui::NextColumn();
ImGui::Text("Path"); ImGui::NextColumn();
ImGui::Text("Flags"); ImGui::NextColumn();
ImGui::Separator();
const char* names[3] = { "One", "Two", "Three" };
const char* paths[3] = { "/path/one", "/path/two", "/path/three" };
static int selected = -1;
for (int i = 0; i < 50; i++)
{
char label[32];
sprintf(label, "%04d", i);
if (ImGui::Selectable(label, selected == i, ImGuiSelectableFlags_SpanAllColumns))
selected = i;
ImGui::NextColumn();
ImGui::Text(names[i%3]); ImGui::NextColumn();
ImGui::Text(paths[i % 3]); ImGui::NextColumn();
ImGui::Text("...."); ImGui::NextColumn();
}
ImGui::Columns(1);
ImGui::Separator();
ImGui::EndChild();
ImGui::PopStyleVar();
}
ImGui::End();
ImGui::SameLine();
ImGui::SetNextWindowPos(ImVec2(m_width / 2, 32));
ImGui::SetNextWindowSize(ImVec2(m_width / 2, m_height - 32));
if (ImGui::Begin("Window2", nullptr, ImVec2(m_width/2, m_height - 32), 1.0f, ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoScrollbar))
{
ImGui::PushStyleVar(ImGuiStyleVar_ChildWindowRounding, 5.0f);
ImGui::BeginChild("Sub2", ImVec2(0, m_height - 48), true);
ImGui::Columns(4, "mycolumns");
ImGui::Separator();
ImGui::Text("ID"); ImGui::NextColumn();
ImGui::Text("Name"); ImGui::NextColumn();
ImGui::Text("Path"); ImGui::NextColumn();
ImGui::Text("Flags"); ImGui::NextColumn();
ImGui::Separator();
const char* names[3] = { "One", "Two", "Three" };
const char* paths[3] = { "/path/one", "/path/two", "/path/three" };
static int selected = -1;
for (int i = 0; i < 3; i++)
{
char label[32];
sprintf(label, "%04d", i);
if (ImGui::Selectable(label, selected == i, ImGuiSelectableFlags_SpanAllColumns))
selected = i;
ImGui::NextColumn();
ImGui::Text(names[i]); ImGui::NextColumn();
ImGui::Text(paths[i]); ImGui::NextColumn();
ImGui::Text("...."); ImGui::NextColumn();
}
ImGui::Columns(1);
ImGui::Separator();
ImGui::EndChild();
ImGui::PopStyleVar();
}
ImGui::End();
imguiEndFrame();
// Advance to next frame. Rendering thread will be kicked to
// process submitted rendering primitives.
bgfx::frame();
@ -241,7 +79,6 @@ class ExampleHelloWorld : public entry::AppI
uint32_t m_height;
uint32_t m_debug;
uint32_t m_reset;
entry::MouseState m_mouseState;
};
ENTRY_IMPLEMENT_MAIN(ExampleHelloWorld);

View File

@ -143,11 +143,7 @@ class ExampleCubes : public entry::AppI
{
float view[16];
bx::mtxQuatTranslationHMD(view, hmd->eye[0].rotation, eye);
float proj[16];
bx::mtxProj(proj, hmd->eye[0].fov, 0.1f, 100.0f);
bgfx::setViewTransform(0, view, proj);
bgfx::setViewTransform(0, view, hmd->eye[0].projection);
// Set view 0 default viewport.
//

View File

@ -577,11 +577,7 @@ class ExampleMetaballs : public entry::AppI
{
float view[16];
bx::mtxQuatTranslationHMD(view, hmd->eye[0].rotation, eye);
float proj[16];
bx::mtxProj(proj, hmd->eye[0].fov, 0.1f, 100.0f);
bgfx::setViewTransform(0, view, proj);
bgfx::setViewTransform(0, view, hmd->eye[0].projection);
// Set view 0 default viewport.
//

View File

@ -107,7 +107,7 @@ class ExampleRaymarch : public entry::AppI
void init(int _argc, char** _argv) BX_OVERRIDE
{
Args args(_argc, _argv);
m_width = 1280;
m_height = 720;
m_debug = BGFX_DEBUG_TEXT;
@ -127,18 +127,8 @@ class ExampleRaymarch : public entry::AppI
, 0
);
// Setup root path for binary shaders. Shader binaries are different
// for each renderer.
switch (bgfx::getRendererType() )
{
default:
break;
case bgfx::RendererType::OpenGL:
case bgfx::RendererType::OpenGLES:
s_oglNdc = true;
break;
}
const bgfx::Caps* caps = bgfx::getCaps();
s_oglNdc = caps->homogeneousDepth;
// Create vertex stream declaration.
PosColorTexCoord0Vertex::init();

View File

@ -91,11 +91,7 @@ class ExampleMesh : public entry::AppI
{
float view[16];
bx::mtxQuatTranslationHMD(view, hmd->eye[0].rotation, eye);
float proj[16];
bx::mtxProj(proj, hmd->eye[0].fov, 0.1f, 100.0f);
bgfx::setViewTransform(0, view, proj);
bgfx::setViewTransform(0, view, hmd->eye[0].projection);
// Set view 0 default viewport.
//

View File

@ -160,11 +160,7 @@ class ExampleInstancing : public entry::AppI
{
float view[16];
bx::mtxQuatTranslationHMD(view, hmd->eye[0].rotation, eye);
float proj[16];
bx::mtxProj(proj, hmd->eye[0].fov, 0.1f, 100.0f);
bgfx::setViewTransform(0, view, proj);
bgfx::setViewTransform(0, view, hmd->eye[0].projection);
// Set view 0 default viewport.
//

View File

@ -225,11 +225,7 @@ class ExampleBump : public entry::AppI
{
float view[16];
bx::mtxQuatTranslationHMD(view, hmd->eye[0].rotation, eye);
float proj[16];
bx::mtxProj(proj, hmd->eye[0].fov, 0.1f, 100.0f);
bgfx::setViewTransform(0, view, proj);
bgfx::setViewTransform(0, view, hmd->eye[0].projection);
// Set view 0 default viewport.
//

View File

@ -8,7 +8,6 @@
#include "imgui/imgui.h"
static float s_texelHalf = 0.0f;
static bool s_originBottomLeft = false;
struct PosColorTexCoord0Vertex
{
@ -230,9 +229,8 @@ class ExampleHDR : public entry::AppI
// Imgui.
imguiCreate();
const bgfx::RendererType::Enum renderer = bgfx::getRendererType();
s_texelHalf = bgfx::RendererType::Direct3D9 == renderer ? 0.5f : 0.0f;
s_originBottomLeft = bgfx::RendererType::OpenGL == renderer || bgfx::RendererType::OpenGLES == renderer;
m_caps = bgfx::getCaps();
s_texelHalf = bgfx::RendererType::Direct3D9 == m_caps->rendererType ? 0.5f : 0.0f;
m_oldWidth = 0;
m_oldHeight = 0;
@ -441,35 +439,35 @@ class ExampleHDR : public entry::AppI
setOffsets2x2Lum(u_offset, 128, 128);
bgfx::setTexture(0, s_texColor, m_fbtextures[0]);
bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE);
screenSpaceQuad(128.0f, 128.0f, s_originBottomLeft);
screenSpaceQuad(128.0f, 128.0f, m_caps->originBottomLeft);
bgfx::submit(2, m_lumProgram);
// Downscale luminance 0.
setOffsets4x4Lum(u_offset, 128, 128);
bgfx::setTexture(0, s_texColor, m_lum[0]);
bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE);
screenSpaceQuad(64.0f, 64.0f, s_originBottomLeft);
screenSpaceQuad(64.0f, 64.0f, m_caps->originBottomLeft);
bgfx::submit(3, m_lumAvgProgram);
// Downscale luminance 1.
setOffsets4x4Lum(u_offset, 64, 64);
bgfx::setTexture(0, s_texColor, m_lum[1]);
bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE);
screenSpaceQuad(16.0f, 16.0f, s_originBottomLeft);
screenSpaceQuad(16.0f, 16.0f, m_caps->originBottomLeft);
bgfx::submit(4, m_lumAvgProgram);
// Downscale luminance 2.
setOffsets4x4Lum(u_offset, 16, 16);
bgfx::setTexture(0, s_texColor, m_lum[2]);
bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE);
screenSpaceQuad(4.0f, 4.0f, s_originBottomLeft);
screenSpaceQuad(4.0f, 4.0f, m_caps->originBottomLeft);
bgfx::submit(5, m_lumAvgProgram);
// Downscale luminance 3.
setOffsets4x4Lum(u_offset, 4, 4);
bgfx::setTexture(0, s_texColor, m_lum[3]);
bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE);
screenSpaceQuad(1.0f, 1.0f, s_originBottomLeft);
screenSpaceQuad(1.0f, 1.0f, m_caps->originBottomLeft);
bgfx::submit(6, m_lumAvgProgram);
float tonemap[4] = { m_middleGray, square(m_white), m_threshold, m_time };
@ -480,13 +478,13 @@ class ExampleHDR : public entry::AppI
bgfx::setTexture(0, s_texColor, m_fbtextures[0]);
bgfx::setTexture(1, s_texLum, m_lum[4]);
bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE);
screenSpaceQuad( (float)m_width/2.0f, (float)m_height/2.0f, s_originBottomLeft);
screenSpaceQuad( (float)m_width/2.0f, (float)m_height/2.0f, m_caps->originBottomLeft);
bgfx::submit(7, m_brightProgram);
// m_blur m_bright pass vertically.
bgfx::setTexture(0, s_texColor, m_bright);
bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE);
screenSpaceQuad( (float)m_width/8.0f, (float)m_height/8.0f, s_originBottomLeft);
screenSpaceQuad( (float)m_width/8.0f, (float)m_height/8.0f, m_caps->originBottomLeft);
bgfx::submit(8, m_blurProgram);
// m_blur m_bright pass horizontally, do tonemaping and combine.
@ -494,7 +492,7 @@ class ExampleHDR : public entry::AppI
bgfx::setTexture(1, s_texLum, m_lum[4]);
bgfx::setTexture(2, s_texBlur, m_blur);
bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE);
screenSpaceQuad( (float)m_width, (float)m_height, s_originBottomLeft);
screenSpaceQuad( (float)m_width, (float)m_height, m_caps->originBottomLeft);
bgfx::submit(9, m_tonemapProgram);
if (bgfx::isValid(m_rb) )
@ -558,6 +556,7 @@ class ExampleHDR : public entry::AppI
int32_t m_scrollArea;
const bgfx::Caps* m_caps;
float m_time;
};

View File

@ -174,11 +174,7 @@ class ExampleLod : public entry::AppI
{
float view[16];
bx::mtxQuatTranslationHMD(view, hmd->eye[0].rotation, eye);
float proj[16];
bx::mtxProj(proj, hmd->eye[0].fov, 0.1f, 100.0f);
bgfx::setViewTransform(0, view, proj);
bgfx::setViewTransform(0, view, hmd->eye[0].projection);
// Set view 0 default viewport.
//

View File

@ -1866,22 +1866,9 @@ int _main_(int _argc, char** _argv)
// Enable debug text.
bgfx::setDebug(debug);
// Setup root path for binary shaders. Shader binaries are different
// for each renderer.
switch (bgfx::getRendererType() )
{
case bgfx::RendererType::Direct3D9:
s_texelHalf = 0.5f;
break;
case bgfx::RendererType::OpenGL:
case bgfx::RendererType::OpenGLES:
s_oglNdc = true;
break;
default:
break;
}
const bgfx::Caps* caps = bgfx::getCaps();
s_oglNdc = caps->homogeneousDepth;
s_texelHalf = bgfx::RendererType::Direct3D9 == caps->rendererType ? 0.5f : 0.0f;
// Imgui
imguiCreate();

View File

@ -16,7 +16,6 @@
#define RENDER_PASS_DEBUG_GBUFFER_ID 4
static float s_texelHalf = 0.0f;
static bool s_originBottomLeft = false;
struct PosNormalTangentTexcoordVertex
{
@ -218,7 +217,7 @@ class ExampleDeferred : public entry::AppI
void init(int _argc, char** _argv) BX_OVERRIDE
{
Args args(_argc, _argv);
m_width = 1280;
m_height = 720;
m_debug = BGFX_DEBUG_TEXT;
@ -311,7 +310,6 @@ class ExampleDeferred : public entry::AppI
m_timeOffset = bx::getHPCounter();
const bgfx::RendererType::Enum renderer = bgfx::getRendererType();
s_texelHalf = bgfx::RendererType::Direct3D9 == renderer ? 0.5f : 0.0f;
s_originBottomLeft = bgfx::RendererType::OpenGL == renderer || bgfx::RendererType::OpenGLES == renderer;
// Get renderer capabilities info.
m_caps = bgfx::getCaps();
@ -501,7 +499,7 @@ class ExampleDeferred : public entry::AppI
bgfx::setViewFrameBuffer(RENDER_PASS_LIGHT_ID, m_lightBuffer);
float proj[16];
bx::mtxProj(proj, 60.0f, float(m_width)/float(m_height), 0.1f, 100.0f, s_originBottomLeft);
bx::mtxProj(proj, 60.0f, float(m_width)/float(m_height), 0.1f, 100.0f, m_caps->homogeneousDepth);
bgfx::setViewFrameBuffer(RENDER_PASS_GEOMETRY_ID, m_gbuffer);
bgfx::setViewTransform(RENDER_PASS_GEOMETRY_ID, view, proj);
@ -695,7 +693,7 @@ class ExampleDeferred : public entry::AppI
| BGFX_STATE_ALPHA_WRITE
| BGFX_STATE_BLEND_ADD
);
screenSpaceQuad( (float)m_width, (float)m_height, s_texelHalf, s_originBottomLeft);
screenSpaceQuad( (float)m_width, (float)m_height, s_texelHalf, m_caps->originBottomLeft);
bgfx::submit(RENDER_PASS_LIGHT_ID, m_lightProgram);
}
}
@ -707,7 +705,7 @@ class ExampleDeferred : public entry::AppI
| BGFX_STATE_RGB_WRITE
| BGFX_STATE_ALPHA_WRITE
);
screenSpaceQuad( (float)m_width, (float)m_height, s_texelHalf, s_originBottomLeft);
screenSpaceQuad( (float)m_width, (float)m_height, s_texelHalf, m_caps->originBottomLeft);
bgfx::submit(RENDER_PASS_COMBINE_ID, m_combineProgram);
if (m_showGBuffer)

View File

@ -72,7 +72,7 @@ vec3 clipToWorld(mat4 _invViewProj, vec3 _clipPos)
void main()
{
vec3 normal = decodeNormalUint(texture2D(s_normal, v_texcoord0).xyz);
float deviceDepth = texture2D(s_depth, v_texcoord0).x;
float deviceDepth = texture2D(s_depth, v_texcoord0).x;
float depth = toClipSpaceDepth(deviceDepth);
vec3 clip = vec3(v_texcoord0 * 2.0 - 1.0, depth);

View File

@ -305,11 +305,7 @@ int _main_(int _argc, char** _argv)
float tmp[16];
bx::mtxMul(tmp, view, viewHead);
float proj[16];
bx::mtxProj(proj, hmd->eye[0].fov, 0.1f, 10000.0f);
bgfx::setViewTransform(0, tmp, proj);
bgfx::setViewTransform(0, tmp, hmd->eye[0].projection);
// Set view 0 default viewport.
//

View File

@ -181,13 +181,10 @@ class ExampleOcclusion : public entry::AppI
float tmp[16];
bx::mtxMul(tmp, view, viewHead);
float proj[16];
bx::mtxProj(proj, hmd->eye[0].fov, 0.1f, 10000.0f);
bgfx::setViewTransform(0, tmp, proj);
bgfx::setViewTransform(0, tmp, hmd->eye[0].projection);
bgfx::setViewRect(0, 0, 0, hmd->width, hmd->height);
bgfx::setViewTransform(1, tmp, proj);
bgfx::setViewTransform(1, tmp, hmd->eye[1].projection);
bgfx::setViewRect(1, 0, 0, hmd->width, hmd->height);
}
else

View File

@ -12,8 +12,6 @@
#include <bx/debug.h>
#include <bx/fpumath.h>
static float s_texelHalf = 0.0f;
static bool s_originBottomLeft = false;
static uint32_t s_terrainSize = 256;
struct PosTexCoord0Vertex
@ -94,9 +92,6 @@ class ExampleTerrain : public entry::AppI
imguiCreate();
m_timeOffset = bx::getHPCounter();
const bgfx::RendererType::Enum renderer = bgfx::getRendererType();
s_texelHalf = bgfx::RendererType::Direct3D9 == renderer ? 0.5f : 0.0f;
s_originBottomLeft = bgfx::RendererType::OpenGL == renderer || bgfx::RendererType::OpenGLES == renderer;
m_vbh.idx = bgfx::invalidHandle;
m_ibh.idx = bgfx::invalidHandle;
@ -463,7 +458,7 @@ class ExampleTerrain : public entry::AppI
bgfx::setViewRect(0, 0, 0, m_width, m_height);
cameraGetViewMtx(m_viewMtx);
bx::mtxProj(m_projMtx, 60.0f, float(m_width) / float(m_height), 0.1f, 2000.0f, s_originBottomLeft);
bx::mtxProj(m_projMtx, 60.0f, float(m_width) / float(m_height), 0.1f, 2000.0f);
bgfx::setViewTransform(0, m_viewMtx, m_projMtx);
bgfx::setTransform(m_terrain.m_transform);

View File

@ -499,6 +499,8 @@ namespace bgfx
uint8_t numGPUs; //!< Number of enumerated GPUs.
uint16_t vendorId; //!< Selected GPU vendor id.
uint16_t deviceId; //!< Selected GPU device id.
bool homogeneousDepth; //!< True when NDC depth is in [-1, 1] range.
bool originBottomLeft; //!< True when NDC origin is at bottom left.
/// GPU info.
///
@ -613,6 +615,7 @@ namespace bgfx
float translation[3]; //!< Eye translation.
float fov[4]; //!< Field of view (up, down, left, right).
float viewOffset[3]; //!< Eye view matrix translation adjustment.
float projection[16]; //!< Eye projection matrix
float pixelsPerTanAngle[2]; //!<
};
@ -1912,7 +1915,7 @@ namespace bgfx
///
void setViewRect(uint8_t _id, uint16_t _x, uint16_t _y, uint16_t _width, uint16_t _height);
/// @attention C99 equivalent is `bgfx_set_view_rect_auto`.
/// @attention C99 equivalent is `bgfx_set_view_rect_auto`.
///
void setViewRect(uint8_t _id, uint16_t _x, uint16_t _y, BackbufferRatio::Enum _ratio);

View File

@ -393,6 +393,8 @@ typedef struct bgfx_caps
uint16_t maxViews;
uint8_t maxFBAttachments;
uint8_t numGPUs;
bool homogeneousDepth;
bool originBottomLeft;
uint16_t vendorId;
uint16_t deviceId;

View File

@ -173,47 +173,14 @@ function exampleProject(_name)
end
if _OPTIONS["with-ovr"] then
links {
"winmm",
"ws2_32",
}
configuration { "x32" }
libdirs { path.join("$(OVR_DIR)/LibOVR/Lib/Windows/Win32/Release", _ACTION) }
-- Check for LibOVR 5.0+
if os.isdir(path.join(os.getenv("OVR_DIR"), "LibOVR/Lib/Windows/Win32/Debug/VS2012")) then
configuration { "x64" }
libdirs { path.join("$(OVR_DIR)/LibOVR/Lib/Windows/x64/Release", _ACTION) }
configuration { "x32", "Debug" }
libdirs { path.join("$(OVR_DIR)/LibOVR/Lib/Windows/Win32/Debug", _ACTION) }
configuration { "x32", "Release" }
libdirs { path.join("$(OVR_DIR)/LibOVR/Lib/Windows/Win32/Release", _ACTION) }
configuration { "x64", "Debug" }
libdirs { path.join("$(OVR_DIR)/LibOVR/Lib/Windows/x64/Debug", _ACTION) }
configuration { "x64", "Release" }
libdirs { path.join("$(OVR_DIR)/LibOVR/Lib/Windows/x64/Release", _ACTION) }
configuration { "x32 or x64" }
links { "libovr" }
else
configuration { "x32" }
libdirs { path.join("$(OVR_DIR)/LibOVR/Lib/Win32", _ACTION) }
configuration { "x64" }
libdirs { path.join("$(OVR_DIR)/LibOVR/Lib/x64", _ACTION) }
configuration { "x32", "Debug" }
links { "libovrd" }
configuration { "x32", "Release" }
links { "libovr" }
configuration { "x64", "Debug" }
links { "libovr64d" }
configuration { "x64", "Release" }
links { "libovr64" }
end
configuration { "x32 or x64" }
links { "libovr" }
configuration {}
end

View File

@ -9,8 +9,8 @@
#include "glcontext_ppapi.cpp"
#include "glcontext_wgl.cpp"
#include "image.cpp"
#include "ovr.cpp"
#include "renderdoc.cpp"
#include "hmd_ovr.cpp"
#include "debug_renderdoc.cpp"
#include "renderer_d3d9.cpp"
#include "renderer_d3d11.cpp"
#include "renderer_d3d12.cpp"

View File

@ -1151,6 +1151,10 @@ namespace bgfx
}
BX_TRACE("Max FB attachments: %d", g_caps.maxFBAttachments);
BX_TRACE("NDC depth [%d, 1], origin %s left."
, g_caps.homogeneousDepth ? -1 : 0
, g_caps.originBottomLeft ? "bottom" : "top"
);
}
TextureFormat::Enum getViableTextureFormat(const ImageContainer& _imageContainer)

View File

@ -88,6 +88,50 @@ struct BgfxSampler2D
Texture2D m_texture;
};
struct BgfxISampler2D
{
Texture2D<ivec4> m_texture;
};
struct BgfxUSampler2D
{
Texture2D<uvec4> m_texture;
};
struct BgfxSampler2DShadow
{
SamplerComparisonState m_sampler;
Texture2D m_texture;
};
struct BgfxSampler3D
{
SamplerState m_sampler;
Texture3D m_texture;
};
struct BgfxISampler3D
{
Texture3D<ivec4> m_texture;
};
struct BgfxUSampler3D
{
Texture3D<uvec4> m_texture;
};
struct BgfxSamplerCube
{
SamplerState m_sampler;
TextureCube m_texture;
};
struct BgfxSampler2DMS
{
SamplerState m_sampler;
Texture2DMS<vec4> m_texture;
};
vec4 bgfxTexture2D(BgfxSampler2D _sampler, vec2 _coord)
{
return _sampler.m_texture.Sample(_sampler.m_sampler, _coord);
@ -110,18 +154,6 @@ vec4 bgfxTexture2DProj(BgfxSampler2D _sampler, vec4 _coord)
return _sampler.m_texture.Sample(_sampler.m_sampler, coord);
}
struct BgfxSampler2DMS
{
SamplerState m_sampler;
Texture2DMS m_texture;
};
struct BgfxSampler2DShadow
{
SamplerComparisonState m_sampler;
Texture2D m_texture;
};
float bgfxShadow2D(BgfxSampler2DShadow _sampler, vec3 _coord)
{
return _sampler.m_texture.SampleCmpLevelZero(_sampler.m_sampler, _coord.xy, _coord.z);
@ -133,22 +165,6 @@ float bgfxShadow2DProj(BgfxSampler2DShadow _sampler, vec4 _coord)
return _sampler.m_texture.SampleCmpLevelZero(_sampler.m_sampler, coord.xy, coord.z);
}
struct BgfxSampler3D
{
SamplerState m_sampler;
Texture3D m_texture;
};
struct BgfxISampler3D
{
Texture3D<ivec4> m_texture;
};
struct BgfxUSampler3D
{
Texture3D<uvec4> m_texture;
};
vec4 bgfxTexture3D(BgfxSampler3D _sampler, vec3 _coord)
{
return _sampler.m_texture.Sample(_sampler.m_sampler, _coord);
@ -173,12 +189,6 @@ uvec4 bgfxTexture3D(BgfxUSampler3D _sampler, vec3 _coord)
return _sampler.m_texture.Load(uvec4(_coord * size, 0) );
}
struct BgfxSamplerCube
{
SamplerState m_sampler;
TextureCube m_texture;
};
vec4 bgfxTextureCube(BgfxSamplerCube _sampler, vec3 _coord)
{
return _sampler.m_texture.Sample(_sampler.m_sampler, _coord);
@ -194,6 +204,16 @@ vec4 bgfxTexelFetch(BgfxSampler2D _sampler, ivec2 _coord, int _lod)
return _sampler.m_texture.Load(ivec3(_coord, _lod) );
}
ivec4 bgfxTexelFetch(BgfxISampler2D _sampler, ivec2 _coord, int _lod)
{
return _sampler.m_texture.Load(ivec3(_coord, _lod) );
}
uvec4 bgfxTexelFetch(BgfxUSampler2D _sampler, ivec2 _coord, int _lod)
{
return _sampler.m_texture.Load(ivec3(_coord, _lod) );
}
vec4 bgfxTexelFetch(BgfxSampler2DMS _sampler, ivec2 _coord, int _sampleIdx)
{
return _sampler.m_texture.Load(_coord, _sampleIdx);
@ -208,6 +228,12 @@ vec4 bgfxTexelFetch(BgfxSampler3D _sampler, ivec3 _coord, int _lod)
uniform SamplerState _name ## Sampler : register(s[_reg]); \
uniform Texture2D _name ## Texture : register(t[_reg]); \
static BgfxSampler2D _name = { _name ## Sampler, _name ## Texture }
# define ISAMPLER2D(_name, _reg) \
uniform Texture2D<ivec4> _name ## Texture : register(t[_reg]); \
static BgfxISampler2D _name = { _name ## Texture }
# define USAMPLER2D(_name, _reg) \
uniform Texture2D<uvec4> _name ## Texture : register(t[_reg]); \
static BgfxUSampler2D _name = { _name ## Texture }
# define sampler2D BgfxSampler2D
# define texture2D(_sampler, _coord) bgfxTexture2D(_sampler, _coord)
# define texture2DLod(_sampler, _coord, _level) bgfxTexture2DLod(_sampler, _coord, _level)
@ -364,8 +390,12 @@ vec4 mod(vec4 _a, vec4 _b) { return _a - _b * floor(_a / _b); }
# define SAMPLER2DSHADOW(_name, _reg) uniform sampler2DShadow _name
# if BGFX_SHADER_LANGUAGE_GLSL >= 130
# define ISAMPLER2D(_name, _reg) uniform isampler2D _name
# define USAMPLER2D(_name, _reg) uniform usampler2D _name
# define ISAMPLER3D(_name, _reg) uniform isampler3D _name
# define USAMPLER3D(_name, _reg) uniform usampler3D _name
ivec4 texture2D(isampler2D _sampler, vec2 _coord) { return texture(_sampler, _coord); }
uvec4 texture2D(usampler2D _sampler, vec2 _coord) { return texture(_sampler, _coord); }
ivec4 texture3D(isampler3D _sampler, vec3 _coord) { return texture(_sampler, _coord); }
uvec4 texture3D(usampler3D _sampler, vec3 _coord) { return texture(_sampler, _coord); }
# endif // BGFX_SHADER_LANGUAGE_GLSL >= 130

View File

@ -515,6 +515,7 @@ GL_IMPORT_OES__(true, PFNGLBINDVERTEXARRAYPROC, glBindVertexA
GL_IMPORT_OES__(true, PFNGLDELETEVERTEXARRAYSPROC, glDeleteVertexArrays);
GL_IMPORT_OES__(true, PFNGLGENVERTEXARRAYSPROC, glGenVertexArrays);
GL_IMPORT_____x(true, PFNGLCLIPCONTROLPROC, glClipControl);
GL_IMPORT_____x(true, PFNGLENABLEIPROC, glEnablei);
GL_IMPORT_____x(true, PFNGLDISABLEIPROC, glDisablei);
GL_IMPORT_____x(true, PFNGLBLENDEQUATIONIPROC, glBlendEquationi);
@ -556,6 +557,7 @@ GL_IMPORT_NV___(true, PFNGLQUERYCOUNTERPROC, glQueryCounte
GL_IMPORT (true, PFNGLINVALIDATEFRAMEBUFFERPROC, glInvalidateFramebuffer, glDiscardFramebufferEXT);
# elif !BGFX_USE_GL_DYNAMIC_LIB
GL_IMPORT______(true, PFNGLCLIPCONTROLPROC, glClipControl);
GL_IMPORT______(true, PFNGLGETSTRINGIPROC, glGetStringi);
GL_IMPORT______(true, PFNGLTEXIMAGE3DPROC, glTexImage3D);

249
3rdparty/bgfx/src/hmd_ovr.cpp vendored Normal file
View File

@ -0,0 +1,249 @@
/*
* Copyright 2011-2016 Branimir Karadzic. All rights reserved.
* License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
*/
#include "hmd_ovr.h"
#if BGFX_CONFIG_USE_OVR
namespace bgfx
{
OVR::OVR()
: m_hmd(NULL)
, m_isenabled(false)
, m_mirror(NULL)
, m_hmdFrameReady(-1)
, m_frameIndex(0)
, m_sensorSampleTime(0)
{
memset(m_eyeBuffers, 0, sizeof(m_eyeBuffers));
}
OVR::~OVR()
{
BX_CHECK(NULL == m_hmd, "OVR not shutdown properly.");
}
void OVR::init()
{
ovrResult initialized = ovr_Initialize(NULL);
ovrGraphicsLuid luid;
BX_WARN(initialized == ovrSuccess, "Unable to create OVR device.");
if (initialized != ovrSuccess)
{
return;
}
initialized = ovr_Create(&m_hmd, &luid);
if (initialized != ovrSuccess)
{
BX_WARN(initialized == ovrSuccess, "Unable to create OVR device.");
return;
}
m_hmdDesc = ovr_GetHmdDesc(m_hmd);
BX_TRACE("HMD: %s, %s, firmware: %d.%d"
, m_hmdDesc.ProductName
, m_hmdDesc.Manufacturer
, m_hmdDesc.FirmwareMajor
, m_hmdDesc.FirmwareMinor
);
ovrSizei sizeL = ovr_GetFovTextureSize(m_hmd, ovrEye_Left, m_hmdDesc.DefaultEyeFov[0], 1.0f);
ovrSizei sizeR = ovr_GetFovTextureSize(m_hmd, ovrEye_Right, m_hmdDesc.DefaultEyeFov[1], 1.0f);
m_hmdSize.w = sizeL.w + sizeR.w;
m_hmdSize.h = bx::uint32_max(sizeL.h, sizeR.h);
}
void OVR::shutdown()
{
BX_CHECK(!m_isenabled, "HMD not disabled.");
for (int i = 0; i < 2; i++)
{
if (m_eyeBuffers[i])
{
m_eyeBuffers[i]->destroy(m_hmd);
BX_DELETE(g_allocator, m_eyeBuffers[i]);
}
}
if (m_mirror)
{
m_mirror->destroy(m_hmd);
BX_DELETE(g_allocator, m_mirror);
}
ovr_Destroy(m_hmd);
m_hmd = NULL;
ovr_Shutdown();
}
void OVR::getViewport(uint8_t _eye, Rect* _viewport)
{
_viewport->m_x = 0;
_viewport->m_y = 0;
_viewport->m_width = m_eyeBuffers[_eye]->m_eyeTextureSize.w;
_viewport->m_height = m_eyeBuffers[_eye]->m_eyeTextureSize.h;
}
void OVR::renderEyeStart(uint8_t _eye)
{
m_eyeBuffers[_eye]->onRender(m_hmd);
}
bool OVR::postReset()
{
if (NULL == m_hmd)
{
return false;
}
for (int eyeIdx = 0; eyeIdx < ovrEye_Count; eyeIdx++)
{
m_erd[eyeIdx] = ovr_GetRenderDesc(m_hmd, (ovrEyeType)eyeIdx, m_hmdDesc.DefaultEyeFov[eyeIdx]);
}
m_isenabled = true;
return true;
}
void OVR::preReset()
{
if (m_isenabled)
{
// on window resize this will recreate the mirror texture in ovrPostReset
m_mirror->destroy(m_hmd);
BX_DELETE(g_allocator, m_mirror);
m_mirror = NULL;
m_isenabled = false;
}
}
void OVR::commitEye(uint8_t _eye)
{
if (m_isenabled)
{
m_hmdFrameReady = ovr_CommitTextureSwapChain(m_hmd, m_eyeBuffers[_eye]->m_swapTextureChain);
}
}
bool OVR::swap(HMD& _hmd, bool originBottomLeft)
{
_hmd.flags = BGFX_HMD_NONE;
if (NULL != m_hmd)
{
_hmd.flags |= BGFX_HMD_DEVICE_RESOLUTION;
_hmd.deviceWidth = m_hmdDesc.Resolution.w;
_hmd.deviceHeight = m_hmdDesc.Resolution.h;
}
if (!m_isenabled || !OVR_SUCCESS(m_hmdFrameReady))
{
return false;
}
_hmd.flags |= BGFX_HMD_RENDERING;
// finish frame for current eye
ovrViewScaleDesc viewScaleDesc;
viewScaleDesc.HmdSpaceToWorldScaleInMeters = 1.0f;
viewScaleDesc.HmdToEyeOffset[0] = m_hmdToEyeOffset[0];
viewScaleDesc.HmdToEyeOffset[1] = m_hmdToEyeOffset[1];
// create the main eye layer
ovrLayerEyeFov eyeLayer;
eyeLayer.Header.Type = ovrLayerType_EyeFov;
eyeLayer.Header.Flags = originBottomLeft ? ovrLayerFlag_TextureOriginAtBottomLeft : 0;
for (int eye = 0; eye < ovrEye_Count; eye++)
{
eyeLayer.ColorTexture[eye] = m_eyeBuffers[eye]->m_swapTextureChain;
eyeLayer.Viewport[eye].Pos.x = 0;
eyeLayer.Viewport[eye].Pos.y = 0;
eyeLayer.Viewport[eye].Size.w = m_eyeBuffers[eye]->m_eyeTextureSize.w;
eyeLayer.Viewport[eye].Size.h = m_eyeBuffers[eye]->m_eyeTextureSize.h;
eyeLayer.Fov[eye] = m_hmdDesc.DefaultEyeFov[eye];
eyeLayer.RenderPose[eye] = m_pose[eye];
eyeLayer.SensorSampleTime = m_sensorSampleTime;
}
// append all the layers to global list
ovrLayerHeader* layerList = &eyeLayer.Header;
ovr_SubmitFrame(m_hmd, m_frameIndex, NULL, &layerList, 1);
// perform mirror texture blit right after the entire frame is submitted to HMD
m_mirror->blit(m_hmd);
m_hmdToEyeOffset[0] = m_erd[0].HmdToEyeOffset;
m_hmdToEyeOffset[1] = m_erd[1].HmdToEyeOffset;
ovr_GetEyePoses(m_hmd, m_frameIndex, ovrTrue, m_hmdToEyeOffset, m_pose, &m_sensorSampleTime);
getEyePose(_hmd);
return true;
}
void OVR::recenter()
{
if (NULL != m_hmd)
{
ovr_RecenterTrackingOrigin(m_hmd);
}
}
void OVR::getEyePose(HMD& _hmd)
{
if (NULL != m_hmd)
{
for (int ii = 0; ii < 2; ++ii)
{
const ovrPosef& pose = m_pose[ii];
HMD::Eye& eye = _hmd.eye[ii];
eye.rotation[0] = pose.Orientation.x;
eye.rotation[1] = pose.Orientation.y;
eye.rotation[2] = pose.Orientation.z;
eye.rotation[3] = pose.Orientation.w;
eye.translation[0] = pose.Position.x;
eye.translation[1] = pose.Position.y;
eye.translation[2] = pose.Position.z;
const ovrEyeRenderDesc& erd = m_erd[ii];
eye.fov[0] = erd.Fov.UpTan;
eye.fov[1] = erd.Fov.DownTan;
eye.fov[2] = erd.Fov.LeftTan;
eye.fov[3] = erd.Fov.RightTan;
ovrMatrix4f eyeProj = ovrMatrix4f_Projection(m_erd[ii].Fov, 0.01f, 1000.0f, ovrProjection_LeftHanded);
for (int jj = 0; jj < 4; ++jj)
{
for (int kk = 0; kk < 4; ++kk)
{
eye.projection[4 * jj + kk] = eyeProj.M[kk][jj];
}
}
eye.viewOffset[0] = erd.HmdToEyeOffset.x;
eye.viewOffset[1] = erd.HmdToEyeOffset.y;
eye.viewOffset[2] = erd.HmdToEyeOffset.z;
eye.pixelsPerTanAngle[0] = erd.PixelsPerTanAngleAtCenter.x;
eye.pixelsPerTanAngle[1] = erd.PixelsPerTanAngleAtCenter.y;
}
}
_hmd.width = uint16_t(m_hmdSize.w);
_hmd.height = uint16_t(m_hmdSize.h);
}
} // namespace bgfx
#endif // BGFX_CONFIG_USE_OVR

View File

@ -14,36 +14,42 @@
# define OVR_VERSION_(_a, _b, _c) (_a * 10000 + _b * 100 + _c)
# define OVR_VERSION OVR_VERSION_(OVR_PRODUCT_VERSION, OVR_MAJOR_VERSION, OVR_MINOR_VERSION)
# define OVR_VERSION_042 OVR_VERSION_(0, 4, 2)
# define OVR_VERSION_043 OVR_VERSION_(0, 4, 3)
# define OVR_VERSION_044 OVR_VERSION_(0, 4, 4)
# define OVR_VERSION_050 OVR_VERSION_(0, 5, 0)
# if OVR_VERSION < OVR_VERSION_050
# include <OVR.h>
# else
# include <OVR_CAPI.h>
# endif // OVR_VERSION < OVR_VERSION_050
# include <OVR_CAPI.h>
# if BGFX_CONFIG_RENDERER_DIRECT3D11
# if OVR_VERSION < OVR_VERSION_050
# define OVR_D3D_VERSION 11
# include <OVR_D3D.h>
# else
# include <OVR_CAPI_D3D.h>
# endif
# include <OVR_CAPI_D3D.h>
# endif // BGFX_CONFIG_RENDERER_DIRECT3D11
# if BGFX_CONFIG_RENDERER_OPENGL
# if OVR_VERSION < OVR_VERSION_050
# include <OVR_GL.h>
# else
# include <OVR_CAPI_GL.h>
# endif
# include <OVR_CAPI_GL.h>
# endif // BGFX_CONFIG_RENDERER_OPENGL
namespace bgfx
{
// single eye buffer
struct OVRBufferI
{
virtual ~OVRBufferI() {};
virtual void onRender(const ovrSession &session) = 0;
virtual void destroy(const ovrSession &session) = 0;
ovrSizei m_eyeTextureSize;
ovrTextureSwapChain m_swapTextureChain;
};
// mirrored window output
struct OVRMirrorI
{
virtual ~OVRMirrorI() {};
virtual void init(const ovrSession &session, int windowWidth, int windowHeight) = 0;
virtual void destroy(const ovrSession &session) = 0;
virtual void blit(const ovrSession &session) = 0;
ovrMirrorTexture m_mirrorTexture;
ovrMirrorTextureDesc m_mirrorDesc;
};
struct OVR
{
OVR();
@ -59,37 +65,31 @@ namespace bgfx
return m_isenabled;
}
bool isDebug() const
{
return m_debug;
}
void init();
void shutdown();
void getViewport(uint8_t _eye, Rect* _viewport);
bool postReset(void* _nwh, ovrRenderAPIConfig* _config, bool _debug = false);
void postReset(const ovrTexture& _texture);
void renderEyeStart(uint8_t _eye);
bool postReset();
void preReset();
bool swap(HMD& _hmd);
void commitEye(uint8_t _eye);
bool swap(HMD& _hmd, bool originBottomLeft);
void recenter();
void getEyePose(HMD& _hmd);
void getSize(uint32_t& _width, uint32_t& _height) const
{
_width = m_rtSize.w;
_height = m_rtSize.h;
}
ovrHmd m_hmd;
ovrFrameTiming m_timing;
ovrSession m_hmd;
ovrHmdDesc m_hmdDesc;
ovrEyeRenderDesc m_erd[2];
ovrRecti m_rect[2];
ovrPosef m_pose[2];
ovrTexture m_texture[2];
ovrSizei m_rtSize;
bool m_warning;
ovrRecti m_rect[2];
ovrPosef m_pose[2];
ovrVector3f m_hmdToEyeOffset[2];
ovrSizei m_hmdSize;
ovrResult m_hmdFrameReady;
OVRBufferI *m_eyeBuffers[2];
OVRMirrorI *m_mirror;
long long m_frameIndex;
double m_sensorSampleTime;
bool m_isenabled;
bool m_debug;
};
} // namespace bgfx
@ -139,7 +139,15 @@ namespace bgfx
_viewport->m_height = 0;
}
bool swap(HMD& _hmd)
void commitEye(uint8_t /*_eye*/)
{
}
void renderEyeStart(uint8_t /*_eye*/)
{
}
bool swap(HMD& _hmd, bool /*originBottomLeft*/)
{
_hmd.flags = BGFX_HMD_NONE;
getEyePose(_hmd);
@ -155,12 +163,6 @@ namespace bgfx
_hmd.width = 0;
_hmd.height = 0;
}
void getSize(uint32_t& _width, uint32_t& _height) const
{
_width = 0;
_height = 0;
}
};
} // namespace bgfx

View File

@ -1,328 +0,0 @@
/*
* Copyright 2011-2016 Branimir Karadzic. All rights reserved.
* License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
*/
#include "ovr.h"
#if BGFX_CONFIG_USE_OVR
namespace bgfx
{
#if OVR_VERSION <= OVR_VERSION_050
# define OVR_EYE_BUFFER 100
#else
# define OVR_EYE_BUFFER 8
#endif // OVR_VERSION...
OVR::OVR()
: m_hmd(NULL)
, m_isenabled(false)
, m_debug(false)
{
}
OVR::~OVR()
{
BX_CHECK(NULL == m_hmd, "OVR not shutdown properly.");
}
void OVR::init()
{
bool initialized = !!ovr_Initialize();
BX_WARN(initialized, "Unable to create OVR device.");
if (!initialized)
{
return;
}
m_hmd = ovrHmd_Create(0);
if (NULL == m_hmd)
{
m_hmd = ovrHmd_CreateDebug(ovrHmd_DK2);
BX_WARN(NULL != m_hmd, "Unable to create OVR device.");
if (NULL == m_hmd)
{
return;
}
}
BX_TRACE("HMD: %s, %s, firmware: %d.%d"
, m_hmd->ProductName
, m_hmd->Manufacturer
, m_hmd->FirmwareMajor
, m_hmd->FirmwareMinor
);
ovrSizei sizeL = ovrHmd_GetFovTextureSize(m_hmd, ovrEye_Left, m_hmd->DefaultEyeFov[0], 1.0f);
ovrSizei sizeR = ovrHmd_GetFovTextureSize(m_hmd, ovrEye_Right, m_hmd->DefaultEyeFov[1], 1.0f);
m_rtSize.w = sizeL.w + sizeR.w + OVR_EYE_BUFFER;
m_rtSize.h = bx::uint32_max(sizeL.h, sizeR.h);
m_warning = true;
}
void OVR::shutdown()
{
BX_CHECK(!m_isenabled, "HMD not disabled.");
ovrHmd_Destroy(m_hmd);
m_hmd = NULL;
ovr_Shutdown();
}
void OVR::getViewport(uint8_t _eye, Rect* _viewport)
{
_viewport->m_x = _eye * (m_rtSize.w + OVR_EYE_BUFFER + 1)/2;
_viewport->m_y = 0;
_viewport->m_width = (m_rtSize.w - OVR_EYE_BUFFER)/2;
_viewport->m_height = m_rtSize.h;
}
bool OVR::postReset(void* _nwh, ovrRenderAPIConfig* _config, bool _debug)
{
if (_debug)
{
switch (_config->Header.API)
{
#if BGFX_CONFIG_RENDERER_DIRECT3D11
case ovrRenderAPI_D3D11:
{
ovrD3D11ConfigData* data = (ovrD3D11ConfigData*)_config;
# if OVR_VERSION > OVR_VERSION_043
m_rtSize = data->Header.BackBufferSize;
# else
m_rtSize = data->Header.RTSize;
# endif // OVR_VERSION > OVR_VERSION_043
}
break;
#endif // BGFX_CONFIG_RENDERER_DIRECT3D11
#if BGFX_CONFIG_RENDERER_OPENGL
case ovrRenderAPI_OpenGL:
{
ovrGLConfigData* data = (ovrGLConfigData*)_config;
# if OVR_VERSION > OVR_VERSION_043
m_rtSize = data->Header.BackBufferSize;
# else
m_rtSize = data->Header.RTSize;
# endif // OVR_VERSION > OVR_VERSION_043
}
break;
#endif // BGFX_CONFIG_RENDERER_OPENGL
case ovrRenderAPI_None:
default:
BX_CHECK(false, "You should not be here!");
break;
}
m_debug = true;
return false;
}
if (NULL == m_hmd)
{
return false;
}
m_isenabled = true;
ovrBool result;
result = ovrHmd_AttachToWindow(m_hmd, _nwh, NULL, NULL);
if (!result) { goto ovrError; }
ovrFovPort eyeFov[2] = { m_hmd->DefaultEyeFov[0], m_hmd->DefaultEyeFov[1] };
result = ovrHmd_ConfigureRendering(m_hmd
, _config
, 0
#if OVR_VERSION < OVR_VERSION_050
| ovrDistortionCap_Chromatic // permanently enabled >= v5.0
#endif
| ovrDistortionCap_Vignette
| ovrDistortionCap_TimeWarp
| ovrDistortionCap_Overdrive
| ovrDistortionCap_NoRestore
| ovrDistortionCap_HqDistortion
, eyeFov
, m_erd
);
if (!result) { goto ovrError; }
ovrHmd_SetEnabledCaps(m_hmd
, 0
| ovrHmdCap_LowPersistence
| ovrHmdCap_DynamicPrediction
);
result = ovrHmd_ConfigureTracking(m_hmd
, 0
| ovrTrackingCap_Orientation
| ovrTrackingCap_MagYawCorrection
| ovrTrackingCap_Position
, 0
);
if (!result)
{
ovrError:
BX_TRACE("Failed to initialize OVR.");
m_isenabled = false;
return false;
}
m_warning = true;
return true;
}
void OVR::postReset(const ovrTexture& _texture)
{
if (NULL != m_hmd)
{
m_texture[0] = _texture;
m_texture[1] = _texture;
ovrRecti rect;
rect.Pos.x = 0;
rect.Pos.y = 0;
rect.Size.w = (m_rtSize.w - OVR_EYE_BUFFER)/2;
rect.Size.h = m_rtSize.h;
m_texture[0].Header.RenderViewport = rect;
rect.Pos.x += rect.Size.w + OVR_EYE_BUFFER;
m_texture[1].Header.RenderViewport = rect;
m_timing = ovrHmd_BeginFrame(m_hmd, 0);
#if OVR_VERSION > OVR_VERSION_042
m_pose[0] = ovrHmd_GetHmdPosePerEye(m_hmd, ovrEye_Left);
m_pose[1] = ovrHmd_GetHmdPosePerEye(m_hmd, ovrEye_Right);
#else
m_pose[0] = ovrHmd_GetEyePose(m_hmd, ovrEye_Left);
m_pose[1] = ovrHmd_GetEyePose(m_hmd, ovrEye_Right);
#endif // OVR_VERSION > OVR_VERSION_042
}
}
void OVR::preReset()
{
if (m_isenabled)
{
ovrHmd_EndFrame(m_hmd, m_pose, m_texture);
ovrHmd_AttachToWindow(m_hmd, NULL, NULL, NULL);
ovrHmd_ConfigureRendering(m_hmd, NULL, 0, NULL, NULL);
m_isenabled = false;
}
m_debug = false;
}
bool OVR::swap(HMD& _hmd)
{
_hmd.flags = BGFX_HMD_NONE;
if (NULL != m_hmd)
{
_hmd.flags |= BGFX_HMD_DEVICE_RESOLUTION;
_hmd.deviceWidth = m_hmd->Resolution.w;
_hmd.deviceHeight = m_hmd->Resolution.h;
}
if (!m_isenabled)
{
return false;
}
_hmd.flags |= BGFX_HMD_RENDERING;
ovrHmd_EndFrame(m_hmd, m_pose, m_texture);
if (m_warning)
{
m_warning = !ovrHmd_DismissHSWDisplay(m_hmd);
}
m_timing = ovrHmd_BeginFrame(m_hmd, 0);
#if OVR_VERSION > OVR_VERSION_042
m_pose[0] = ovrHmd_GetHmdPosePerEye(m_hmd, ovrEye_Left);
m_pose[1] = ovrHmd_GetHmdPosePerEye(m_hmd, ovrEye_Right);
#else
m_pose[0] = ovrHmd_GetEyePose(m_hmd, ovrEye_Left);
m_pose[1] = ovrHmd_GetEyePose(m_hmd, ovrEye_Right);
#endif // OVR_VERSION > OVR_VERSION_042
getEyePose(_hmd);
return true;
}
void OVR::recenter()
{
if (NULL != m_hmd)
{
ovrHmd_RecenterPose(m_hmd);
}
}
void OVR::getEyePose(HMD& _hmd)
{
if (NULL != m_hmd)
{
for (int ii = 0; ii < 2; ++ii)
{
const ovrPosef& pose = m_pose[ii];
HMD::Eye& eye = _hmd.eye[ii];
eye.rotation[0] = pose.Orientation.x;
eye.rotation[1] = pose.Orientation.y;
eye.rotation[2] = pose.Orientation.z;
eye.rotation[3] = pose.Orientation.w;
eye.translation[0] = pose.Position.x;
eye.translation[1] = pose.Position.y;
eye.translation[2] = pose.Position.z;
const ovrEyeRenderDesc& erd = m_erd[ii];
eye.fov[0] = erd.Fov.UpTan;
eye.fov[1] = erd.Fov.DownTan;
eye.fov[2] = erd.Fov.LeftTan;
eye.fov[3] = erd.Fov.RightTan;
#if OVR_VERSION > OVR_VERSION_042
eye.viewOffset[0] = erd.HmdToEyeViewOffset.x;
eye.viewOffset[1] = erd.HmdToEyeViewOffset.y;
eye.viewOffset[2] = erd.HmdToEyeViewOffset.z;
#else
eye.viewOffset[0] = erd.ViewAdjust.x;
eye.viewOffset[1] = erd.ViewAdjust.y;
eye.viewOffset[2] = erd.ViewAdjust.z;
#endif // OVR_VERSION > OVR_VERSION_042
eye.pixelsPerTanAngle[0] = erd.PixelsPerTanAngleAtCenter.x;
eye.pixelsPerTanAngle[1] = erd.PixelsPerTanAngleAtCenter.y;
}
}
else
{
for (int ii = 0; ii < 2; ++ii)
{
_hmd.eye[ii].rotation[0] = 0.0f;
_hmd.eye[ii].rotation[1] = 0.0f;
_hmd.eye[ii].rotation[2] = 0.0f;
_hmd.eye[ii].rotation[3] = 1.0f;
_hmd.eye[ii].translation[0] = 0.0f;
_hmd.eye[ii].translation[1] = 0.0f;
_hmd.eye[ii].translation[2] = 0.0f;
_hmd.eye[ii].fov[0] = 1.32928634f;
_hmd.eye[ii].fov[1] = 1.32928634f;
_hmd.eye[ii].fov[2] = 0 == ii ? 1.05865765f : 1.09236801f;
_hmd.eye[ii].fov[3] = 0 == ii ? 1.09236801f : 1.05865765f;
_hmd.eye[ii].viewOffset[0] = 0 == ii ? 0.0355070010f : -0.0375000015f;
_hmd.eye[ii].viewOffset[1] = 0.0f;
_hmd.eye[ii].viewOffset[2] = 0 == ii ? 0.00150949787f : -0.00150949787f;
_hmd.eye[ii].pixelsPerTanAngle[0] = 1;
_hmd.eye[ii].pixelsPerTanAngle[1] = 1;
}
}
_hmd.width = uint16_t(m_rtSize.w);
_hmd.height = uint16_t(m_rtSize.h);
}
} // namespace bgfx
#endif // BGFX_CONFIG_USE_OVR

View File

@ -601,6 +601,170 @@ namespace bgfx { namespace d3d11
static PFN_GET_DEBUG_INTERFACE1 DXGIGetDebugInterface1;
#endif // USE_D3D11_DYNAMIC_LIB
#if BGFX_CONFIG_USE_OVR
#include <tinystl/vector.h>
// Oculus Rift eye buffer
struct OVRBufferDX11 : public OVRBufferI
{
OVRBufferDX11(const ovrSession& session, int eyeIdx, ID3D11Device* d3dDevice, ID3D11DeviceContext* d3dCtx)
{
m_d3dDevice = d3dDevice;
m_d3dContext = d3dCtx;
ovrHmdDesc hmdDesc = ovr_GetHmdDesc(session);
m_eyeTextureSize = ovr_GetFovTextureSize(session, (ovrEyeType)eyeIdx, hmdDesc.DefaultEyeFov[eyeIdx], 1.0f);
ovrTextureSwapChainDesc desc = {};
desc.Type = ovrTexture_2D;
desc.ArraySize = 1;
desc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;
desc.Width = m_eyeTextureSize.w;
desc.Height = m_eyeTextureSize.h;
desc.MipLevels = 1;
desc.SampleCount = 1;
desc.MiscFlags = ovrTextureMisc_DX_Typeless;
desc.BindFlags = ovrTextureBind_DX_RenderTarget;
desc.StaticImage = ovrFalse;
ovrResult result = ovr_CreateTextureSwapChainDX(session, d3dDevice, &desc, &m_swapTextureChain);
if (!OVR_SUCCESS(result))
{
BX_CHECK(false, "Could not create D3D11 OVR swap texture");
}
int textureCount = 0;
ovr_GetTextureSwapChainLength(session, m_swapTextureChain, &textureCount);
for (int i = 0; i < textureCount; ++i)
{
ID3D11Texture2D* tex = NULL;
ovr_GetTextureSwapChainBufferDX(session, m_swapTextureChain, i, IID_PPV_ARGS(&tex));
D3D11_RENDER_TARGET_VIEW_DESC rtvd = {};
rtvd.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
rtvd.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
ID3D11RenderTargetView* rtv;
DX_CHECK(d3dDevice->CreateRenderTargetView(tex, &rtvd, &rtv));
m_eyeRtv.push_back(rtv);
tex->Release();
}
// setup depth buffer
D3D11_TEXTURE2D_DESC dbDesc;
dbDesc.Width = m_eyeTextureSize.w;
dbDesc.Height = m_eyeTextureSize.h;
dbDesc.MipLevels = 1;
dbDesc.ArraySize = 1;
dbDesc.Format = DXGI_FORMAT_D32_FLOAT;
dbDesc.SampleDesc.Count = 1;
dbDesc.SampleDesc.Quality = 0;
dbDesc.Usage = D3D11_USAGE_DEFAULT;
dbDesc.CPUAccessFlags = 0;
dbDesc.MiscFlags = 0;
dbDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
ID3D11Texture2D* tex;
DX_CHECK(d3dDevice->CreateTexture2D(&dbDesc, NULL, &tex));
DX_CHECK(d3dDevice->CreateDepthStencilView(tex, NULL, &m_depthBuffer));
tex->Release();
}
void onRender(const ovrSession& session)
{
// Clear and set up rendertarget
int texIndex = 0;
ovr_GetTextureSwapChainCurrentIndex(session, m_swapTextureChain, &texIndex);
float black[] = { 0.f, 0.f, 0.f, 0.f }; // Important that alpha=0, if want pixels to be transparent, for manual layers
m_d3dContext->OMSetRenderTargets(1, &m_eyeRtv[texIndex], m_depthBuffer);
m_d3dContext->ClearRenderTargetView(m_eyeRtv[texIndex], black);
m_d3dContext->ClearDepthStencilView(m_depthBuffer, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1, 0);
D3D11_VIEWPORT D3Dvp;
D3Dvp.TopLeftX = 0;
D3Dvp.TopLeftY = 0;
D3Dvp.Width = (FLOAT)m_eyeTextureSize.w;
D3Dvp.Height = (FLOAT)m_eyeTextureSize.h;
D3Dvp.MinDepth = 0;
D3Dvp.MaxDepth = 1;
m_d3dContext->RSSetViewports(1, &D3Dvp);
}
void destroy(const ovrSession& session)
{
for (size_t i = 0; i < m_eyeRtv.size(); ++i)
{
m_eyeRtv[i]->Release();
}
ovr_DestroyTextureSwapChain(session, m_swapTextureChain);
m_depthBuffer->Release();
}
ID3D11Device* m_d3dDevice;
ID3D11DeviceContext* m_d3dContext;
stl::vector<ID3D11RenderTargetView *> m_eyeRtv;
ID3D11DepthStencilView* m_depthBuffer;
};
// Oculus Rift mirror
struct OVRMirrorDX11 : public OVRMirrorI
{
OVRMirrorDX11(ID3D11Device* d3dDevice,
ID3D11DeviceContext* d3dCtx,
IDXGISwapChain* d3dSc) : m_d3dDevice(d3dDevice)
, m_d3dContext(d3dCtx)
, m_d3dSwapChain(d3dSc)
{
}
void init(const ovrSession& session, int windowWidth, int windowHeight)
{
m_mirrorDesc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;
m_mirrorDesc.Width = windowWidth;
m_mirrorDesc.Height = windowHeight;
ovrResult result = ovr_CreateMirrorTextureDX(session, m_d3dDevice, &m_mirrorDesc, &m_mirrorTexture);
if (!OVR_SUCCESS(result))
{
BX_CHECK(false, "Could not create D3D11 OVR mirror texture");
}
}
void destroy(const ovrSession& session)
{
if (!m_mirrorTexture)
return;
ovr_DestroyMirrorTexture(session, m_mirrorTexture);
m_mirrorTexture = NULL;
}
void blit(const ovrSession& session)
{
if (!m_mirrorTexture)
return;
ID3D11Texture2D* tex = NULL;
ovr_GetMirrorTextureBufferDX(session, m_mirrorTexture, IID_PPV_ARGS(&tex));
ID3D11Texture2D* backBuffer;
DX_CHECK(m_d3dSwapChain->GetBuffer(0, IID_ID3D11Texture2D, (void**)&backBuffer));
m_d3dContext->CopyResource(backBuffer, tex);
DX_CHECK(m_d3dSwapChain->Present(0, 0));
tex->Release();
backBuffer->Release();
}
ID3D11Device* m_d3dDevice;
ID3D11DeviceContext* m_d3dContext;
IDXGISwapChain* m_d3dSwapChain;
};
#endif // BGFX_CONFIG_USE_OVR
struct RendererContextD3D11 : public RendererContextI
{
RendererContextD3D11()
@ -635,8 +799,6 @@ namespace bgfx { namespace d3d11
, m_fsChanges(0)
, m_rtMsaa(false)
, m_timerQuerySupport(false)
, m_ovrRtv(NULL)
, m_ovrDsv(NULL)
{
m_fbh.idx = invalidHandle;
memset(&m_adapterDesc, 0, sizeof(m_adapterDesc) );
@ -2001,10 +2163,6 @@ BX_PRAGMA_DIAGNOSTIC_POP();
uint32_t width = getBufferWidth();
uint32_t height = getBufferHeight();
if (m_ovr.isEnabled() )
{
m_ovr.getSize(width, height);
}
FrameBufferHandle fbh = BGFX_INVALID_HANDLE;
setFrameBuffer(fbh, false);
@ -2192,7 +2350,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
if (SUCCEEDED(hr) )
{
if (!m_ovr.swap(_hmd) )
if (!m_ovr.swap(_hmd, false) )
{
hr = m_swapChain->Present(syncInterval, 0);
}
@ -3083,77 +3241,22 @@ BX_PRAGMA_DIAGNOSTIC_POP();
void ovrPostReset()
{
#if BGFX_CONFIG_USE_OVR
if (m_flags & (BGFX_RESET_HMD|BGFX_RESET_HMD_DEBUG) )
if (m_resolution.m_flags & (BGFX_RESET_HMD|BGFX_RESET_HMD_DEBUG) )
{
ovrD3D11Config config;
config.D3D11.Header.API = ovrRenderAPI_D3D11;
# if OVR_VERSION > OVR_VERSION_043
config.D3D11.Header.BackBufferSize.w = m_scd.BufferDesc.Width;
config.D3D11.Header.BackBufferSize.h = m_scd.BufferDesc.Height;
config.D3D11.pBackBufferUAV = NULL;
# else
config.D3D11.Header.RTSize.w = m_scd.BufferDesc.Width;
config.D3D11.Header.RTSize.h = m_scd.BufferDesc.Height;
# endif // OVR_VERSION > OVR_VERSION_042
config.D3D11.Header.Multisample = 0;
config.D3D11.pDevice = m_device;
config.D3D11.pDeviceContext = m_deviceCtx;
config.D3D11.pBackBufferRT = m_backBufferColor;
config.D3D11.pSwapChain = m_swapChain;
if (m_ovr.postReset(g_platformData.nwh, &config.Config, !!(m_flags & BGFX_RESET_HMD_DEBUG) ) )
if (m_ovr.postReset())
{
uint32_t size = sizeof(uint32_t) + sizeof(TextureCreate);
const Memory* mem = alloc(size);
for (int eyeIdx = 0; eyeIdx < ovrEye_Count; eyeIdx++)
{
// eye buffers need to be initialized only once during application lifetime
if (!m_ovr.m_eyeBuffers[eyeIdx])
{
m_ovr.m_eyeBuffers[eyeIdx] = BX_NEW(g_allocator, OVRBufferDX11(m_ovr.m_hmd, eyeIdx, m_device, m_deviceCtx));
}
}
bx::StaticMemoryBlockWriter writer(mem->data, mem->size);
uint32_t magic = BGFX_CHUNK_MAGIC_TEX;
bx::write(&writer, magic);
TextureCreate tc;
tc.m_flags = BGFX_TEXTURE_RT|( ((m_flags & BGFX_RESET_MSAA_MASK) >> BGFX_RESET_MSAA_SHIFT) << BGFX_TEXTURE_RT_MSAA_SHIFT);
tc.m_width = m_ovr.m_rtSize.w;
tc.m_height = m_ovr.m_rtSize.h;
tc.m_sides = 0;
tc.m_depth = 0;
tc.m_numMips = 1;
tc.m_format = uint8_t(bgfx::TextureFormat::BGRA8);
tc.m_cubeMap = false;
tc.m_mem = NULL;
bx::write(&writer, tc);
m_ovrRT.create(mem, tc.m_flags, 0);
release(mem);
DX_CHECK(m_device->CreateRenderTargetView(m_ovrRT.m_ptr, NULL, &m_ovrRtv) );
D3D11_TEXTURE2D_DESC dsd;
dsd.Width = m_ovr.m_rtSize.w;
dsd.Height = m_ovr.m_rtSize.h;
dsd.MipLevels = 1;
dsd.ArraySize = 1;
dsd.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
dsd.SampleDesc = m_scd.SampleDesc;
dsd.Usage = D3D11_USAGE_DEFAULT;
dsd.BindFlags = D3D11_BIND_DEPTH_STENCIL;
dsd.CPUAccessFlags = 0;
dsd.MiscFlags = 0;
ID3D11Texture2D* depthStencil;
DX_CHECK(m_device->CreateTexture2D(&dsd, NULL, &depthStencil) );
DX_CHECK(m_device->CreateDepthStencilView(depthStencil, NULL, &m_ovrDsv) );
DX_RELEASE(depthStencil, 0);
ovrD3D11Texture texture;
texture.D3D11.Header.API = ovrRenderAPI_D3D11;
texture.D3D11.Header.TextureSize = m_ovr.m_rtSize;
texture.D3D11.pTexture = m_ovrRT.m_texture2d;
texture.D3D11.pSRView = m_ovrRT.m_srv;
m_ovr.postReset(texture.Texture);
bx::xchg(m_ovrRtv, m_backBufferColor);
BX_CHECK(NULL == m_backBufferDepthStencil, "");
bx::xchg(m_ovrDsv, m_backBufferDepthStencil);
// recreate mirror texture
m_ovr.m_mirror = BX_NEW(g_allocator, OVRMirrorDX11(m_device, m_deviceCtx, m_swapChain));
m_ovr.m_mirror->init(m_ovr.m_hmd, m_resolution.m_width, m_resolution.m_height);
}
}
#endif // BGFX_CONFIG_USE_OVR
@ -3163,16 +3266,6 @@ BX_PRAGMA_DIAGNOSTIC_POP();
{
#if BGFX_CONFIG_USE_OVR
m_ovr.preReset();
if (NULL != m_ovrRtv)
{
bx::xchg(m_ovrRtv, m_backBufferColor);
bx::xchg(m_ovrDsv, m_backBufferDepthStencil);
BX_CHECK(NULL == m_backBufferDepthStencil, "");
DX_RELEASE(m_ovrRtv, 0);
DX_RELEASE(m_ovrDsv, 0);
m_ovrRT.destroy();
}
#endif // BGFX_CONFIG_USE_OVR
}
@ -3564,9 +3657,6 @@ BX_PRAGMA_DIAGNOSTIC_POP();
bool m_timerQuerySupport;
OVR m_ovr;
TextureD3D11 m_ovrRT;
ID3D11RenderTargetView* m_ovrRtv;
ID3D11DepthStencilView* m_ovrDsv;
};
static RendererContextD3D11* s_renderD3D11;
@ -4864,7 +4954,7 @@ BX_PRAGMA_DIAGNOSTIC_POP();
_render->m_hmdInitialized = m_ovr.isInitialized();
const bool hmdEnabled = m_ovr.isEnabled() || m_ovr.isDebug();
const bool hmdEnabled = m_ovr.isEnabled();
ViewState viewState(_render, hmdEnabled);
bool wireframe = !!(_render->m_debug&BGFX_DEBUG_WIREFRAME);
@ -4987,6 +5077,9 @@ BX_PRAGMA_DIAGNOSTIC_POP();
if (m_ovr.isEnabled() )
{
m_ovr.getViewport(eye, &viewState.m_rect);
// commit previous eye to HMD and start rendering new frame
m_ovr.commitEye(eye);
m_ovr.renderEyeStart(eye);
}
else
{

View File

@ -32,8 +32,8 @@ BX_PRAGMA_DIAGNOSTIC_POP()
#include "renderer.h"
#include "renderer_d3d.h"
#include "shader_dxbc.h"
#include "ovr.h"
#include "renderdoc.h"
#include "hmd_ovr.h"
#include "debug_renderdoc.h"
#ifndef D3DCOLOR_ARGB
# define D3DCOLOR_ARGB(_a, _r, _g, _b) ( (DWORD)( ( ( (_a)&0xff)<<24)|( ( (_r)&0xff)<<16)|( ( (_g)&0xff)<<8)|( (_b)&0xff) ) )

View File

@ -1274,6 +1274,144 @@ namespace bgfx { namespace gl
BX_UNUSED(supported);
}
#if BGFX_CONFIG_USE_OVR
// Oculus Rift eye buffer
struct OVRBufferGL : public OVRBufferI
{
OVRBufferGL(const ovrSession& session, int eyeIdx)
{
ovrHmdDesc hmdDesc = ovr_GetHmdDesc(session);
m_eyeTextureSize = ovr_GetFovTextureSize(session, (ovrEyeType)eyeIdx, hmdDesc.DefaultEyeFov[eyeIdx], 1.0f);
ovrTextureSwapChainDesc desc = {};
desc.Type = ovrTexture_2D;
desc.ArraySize = 1;
desc.Width = m_eyeTextureSize.w;
desc.Height = m_eyeTextureSize.h;
desc.MipLevels = 1;
desc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;
desc.SampleCount = 1;
desc.StaticImage = ovrFalse;
ovr_CreateTextureSwapChainGL(session, &desc, &m_swapTextureChain);
int textureCount = 0;
ovr_GetTextureSwapChainLength(session, m_swapTextureChain, &textureCount);
for (int j = 0; j < textureCount; ++j)
{
GLuint chainTexId;
ovr_GetTextureSwapChainBufferGL(session, m_swapTextureChain, j, &chainTexId);
GL_CHECK(glBindTexture(GL_TEXTURE_2D, chainTexId));
GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
}
GL_CHECK(glGenFramebuffers(1, &m_eyeFbo));
// create depth buffer
GL_CHECK(glGenTextures(1, &m_depthBuffer));
GL_CHECK(glBindTexture(GL_TEXTURE_2D, m_depthBuffer));
GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
GL_CHECK(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
GL_CHECK(glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT24, m_eyeTextureSize.w, m_eyeTextureSize.h, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL));
}
void onRender(const ovrSession& session)
{
// set the current eye texture in swap chain
int curIndex;
ovr_GetTextureSwapChainCurrentIndex(session, m_swapTextureChain, &curIndex);
ovr_GetTextureSwapChainBufferGL(session, m_swapTextureChain, curIndex, &m_eyeTexId);
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_eyeFbo));
GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_eyeTexId, 0));
GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, m_depthBuffer, 0));
GL_CHECK(glViewport(0, 0, m_eyeTextureSize.w, m_eyeTextureSize.h));
GL_CHECK(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT));
}
void destroy(const ovrSession& session)
{
GL_CHECK(glDeleteFramebuffers(1, &m_eyeFbo));
GL_CHECK(glDeleteTextures(1, &m_depthBuffer));
ovr_DestroyTextureSwapChain(session, m_swapTextureChain);
}
GLuint m_eyeFbo;
GLuint m_eyeTexId;
GLuint m_depthBuffer;
};
// Oculus Rift mirror
struct OVRMirrorGL : public OVRMirrorI
{
void init(const ovrSession& session, int windowWidth, int windowHeight)
{
memset(&m_mirrorDesc, 0, sizeof(m_mirrorDesc));
m_mirrorDesc.Width = windowWidth;
m_mirrorDesc.Height = windowHeight;
m_mirrorDesc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;
ovr_CreateMirrorTextureGL(session, &m_mirrorDesc, &m_mirrorTexture);
// Fallback to doing nothing if mirror was not created. This is to prevent errors with fast window resizes
if (!m_mirrorTexture)
return;
// Configure the mirror read buffer
GLuint texId;
ovr_GetMirrorTextureBufferGL(session, m_mirrorTexture, &texId);
GL_CHECK(glGenFramebuffers(1, &m_mirrorFBO));
GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, m_mirrorFBO));
GL_CHECK(glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texId, 0));
GL_CHECK(glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0));
GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, 0));
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
{
GL_CHECK(glDeleteFramebuffers(1, &m_mirrorFBO));
BX_CHECK(false, "Could not initialize VR buffers!");
}
}
void destroy(const ovrSession& session)
{
if (!m_mirrorTexture)
return;
GL_CHECK(glDeleteFramebuffers(1, &m_mirrorFBO));
ovr_DestroyMirrorTexture(session, m_mirrorTexture);
m_mirrorTexture = NULL;
}
void blit(const ovrSession& /*session*/)
{
if (!m_mirrorTexture)
return;
// Blit mirror texture to back buffer
GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, m_mirrorFBO));
GL_CHECK(glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0));
GLint w = m_mirrorDesc.Width;
GLint h = m_mirrorDesc.Height;
GL_CHECK(glBlitFramebuffer(0, h, w, 0, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_NEAREST));
GL_CHECK(glBindFramebuffer(GL_READ_FRAMEBUFFER, 0));
}
GLuint m_mirrorFBO;
};
#endif // BGFX_CONFIG_USE_OVR
struct RendererContextGL : public RendererContextI
{
RendererContextGL()
@ -1304,7 +1442,6 @@ namespace bgfx { namespace gl
, m_hash( (BX_PLATFORM_WINDOWS<<1) | BX_ARCH_64BIT)
, m_backBufferFbo(0)
, m_msaaBackBufferFbo(0)
, m_ovrFbo(0)
{
memset(m_msaaBackBufferRbos, 0, sizeof(m_msaaBackBufferRbos) );
}
@ -1818,6 +1955,17 @@ namespace bgfx { namespace gl
);
}
// if (s_extension[Extension::ARB_clip_control].m_supported)
// {
// GL_CHECK(glClipControl(GL_LOWER_LEFT, GL_ZERO_TO_ONE) );
// g_caps.originBottomLeft = true;
// }
// else
{
g_caps.homogeneousDepth = true;
g_caps.originBottomLeft = true;
}
m_vaoSupport = !!(BGFX_CONFIG_RENDERER_OPENGLES >= 30)
|| s_extension[Extension::ARB_vertex_array_object].m_supported
|| s_extension[Extension::OES_vertex_array_object].m_supported
@ -2096,10 +2244,9 @@ namespace bgfx { namespace gl
m_glctx.swap(m_frameBuffers[m_windows[ii].idx].m_swapChain);
}
if (!m_ovr.swap(_hmd) )
{
m_glctx.swap();
}
m_ovr.swap(_hmd, true);
// need to swap GL render context even if OVR is enabled to get the mirror texture in the output
m_glctx.swap();
}
}
@ -2386,10 +2533,6 @@ namespace bgfx { namespace gl
uint32_t width = m_resolution.m_width;
uint32_t height = m_resolution.m_height;
if (m_ovr.isEnabled() )
{
m_ovr.getSize(width, height);
}
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_backBufferFbo) );
GL_CHECK(glViewport(0, 0, width, height) );
@ -2846,63 +2989,22 @@ namespace bgfx { namespace gl
void ovrPostReset()
{
#if BGFX_CONFIG_USE_OVR
if (m_resolution.m_flags & (BGFX_RESET_HMD|BGFX_RESET_HMD_DEBUG) )
if (m_resolution.m_flags & (BGFX_RESET_HMD | BGFX_RESET_HMD_DEBUG))
{
ovrGLConfig config;
config.OGL.Header.API = ovrRenderAPI_OpenGL;
# if OVR_VERSION > OVR_VERSION_043
config.OGL.Header.BackBufferSize.w = m_resolution.m_width;
config.OGL.Header.BackBufferSize.h = m_resolution.m_height;
# else
config.OGL.Header.RTSize.w = m_resolution.m_width;
config.OGL.Header.RTSize.h = m_resolution.m_height;
# endif // OVR_VERSION > OVR_VERSION_043
config.OGL.Header.Multisample = 0;
config.OGL.Window = (HWND)g_platformData.nwh;
config.OGL.DC = GetDC(config.OGL.Window);
if (m_ovr.postReset(g_platformData.nwh, &config.Config, !!(m_resolution.m_flags & BGFX_RESET_HMD_DEBUG) ) )
if (m_ovr.postReset())
{
uint32_t size = sizeof(uint32_t) + sizeof(TextureCreate);
const Memory* mem = alloc(size);
for (int eyeIdx = 0; eyeIdx < ovrEye_Count; eyeIdx++)
{
// eye buffers need to be initialized only once during application lifetime
if (!m_ovr.m_eyeBuffers[eyeIdx])
{
m_ovr.m_eyeBuffers[eyeIdx] = BX_NEW(g_allocator, OVRBufferGL(m_ovr.m_hmd, eyeIdx));
}
}
bx::StaticMemoryBlockWriter writer(mem->data, mem->size);
uint32_t magic = BGFX_CHUNK_MAGIC_TEX;
bx::write(&writer, magic);
TextureCreate tc;
tc.m_flags = BGFX_TEXTURE_RT|( ((m_resolution.m_flags & BGFX_RESET_MSAA_MASK) >> BGFX_RESET_MSAA_SHIFT) << BGFX_TEXTURE_RT_MSAA_SHIFT);;
tc.m_width = m_ovr.m_rtSize.w;
tc.m_height = m_ovr.m_rtSize.h;
tc.m_sides = 0;
tc.m_depth = 0;
tc.m_numMips = 1;
tc.m_format = uint8_t(bgfx::TextureFormat::BGRA8);
tc.m_cubeMap = false;
tc.m_mem = NULL;
bx::write(&writer, tc);
m_ovrRT.create(mem, tc.m_flags, 0);
release(mem);
m_ovrFbo = m_msaaBackBufferFbo;
GL_CHECK(glGenFramebuffers(1, &m_msaaBackBufferFbo) );
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_msaaBackBufferFbo) );
GL_CHECK(glFramebufferTexture2D(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
, GL_TEXTURE_2D
, m_ovrRT.m_id
, 0
) );
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_ovrFbo) );
ovrGLTexture texture;
texture.OGL.Header.API = ovrRenderAPI_OpenGL;
texture.OGL.Header.TextureSize = m_ovr.m_rtSize;
texture.OGL.TexId = m_ovrRT.m_id;
m_ovr.postReset(texture.Texture);
// recreate mirror texture
m_ovr.m_mirror = BX_NEW(g_allocator, OVRMirrorGL);
m_ovr.m_mirror->init(m_ovr.m_hmd, m_resolution.m_width, m_resolution.m_height);
}
}
#endif // BGFX_CONFIG_USE_OVR
@ -2912,14 +3014,6 @@ namespace bgfx { namespace gl
{
#if BGFX_CONFIG_USE_OVR
m_ovr.preReset();
if (m_ovr.isEnabled() )
{
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0) );
GL_CHECK(glDeleteFramebuffers(1, &m_msaaBackBufferFbo) );
m_msaaBackBufferFbo = m_ovrFbo;
m_ovrFbo = 0;
m_ovrRT.destroy();
}
#endif // BGFX_CONFIG_USE_OVR
}
@ -3343,8 +3437,6 @@ namespace bgfx { namespace gl
const char* m_glslVersion;
OVR m_ovr;
TextureGL m_ovrRT;
GLint m_ovrFbo;
};
RendererContextGL* s_renderGL;
@ -3636,7 +3728,7 @@ namespace bgfx { namespace gl
}
m_numPredefined = 0;
m_numSamplers = 0;
m_numSamplers = 0;
BX_TRACE("Uniforms (%d):", activeUniforms);
for (int32_t ii = 0; ii < activeUniforms; ++ii)
@ -5428,7 +5520,7 @@ namespace bgfx { namespace gl
_render->m_hmdInitialized = m_ovr.isInitialized();
const bool hmdEnabled = m_ovr.isEnabled() || m_ovr.isDebug();
const bool hmdEnabled = m_ovr.isEnabled();
ViewState viewState(_render, hmdEnabled);
uint16_t programIdx = invalidHandle;
@ -5478,12 +5570,13 @@ namespace bgfx { namespace gl
m_occlusionQuery.resolve(_render);
}
uint8_t eye = 0;
if (0 == (_render->m_debug&BGFX_DEBUG_IFH) )
{
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, m_msaaBackBufferFbo) );
bool viewRestart = false;
uint8_t eye = 0;
uint8_t restartState = 0;
viewState.m_rect = _render->m_rect[0];
@ -5565,6 +5658,9 @@ namespace bgfx { namespace gl
if (m_ovr.isEnabled() )
{
m_ovr.getViewport(eye, &viewState.m_rect);
// commit previous eye to HMD and start rendering new frame
m_ovr.commitEye(eye);
m_ovr.renderEyeStart(eye);
}
else
{
@ -5584,7 +5680,7 @@ namespace bgfx { namespace gl
}
const Rect& scissorRect = _render->m_scissor[view];
viewHasScissor = !scissorRect.isZero();
viewHasScissor = !scissorRect.isZero();
viewScissorRect = viewHasScissor ? scissorRect : viewState.m_rect;
GL_CHECK(glViewport(viewState.m_rect.m_x
@ -5666,7 +5762,7 @@ namespace bgfx { namespace gl
const RenderCompute& compute = renderItem.compute;
ProgramGL& program = m_program[key.m_program];
GL_CHECK(glUseProgram(program.m_id) );
GL_CHECK(glUseProgram(program.m_id) );
GLbitfield barrier = 0;
for (uint32_t ii = 0; ii < BGFX_MAX_COMPUTE_BINDINGS; ++ii)

View File

@ -107,8 +107,8 @@ typedef uint64_t GLuint64;
#endif // BGFX_CONFIG_RENDERER_OPENGL
#include "renderer.h"
#include "ovr.h"
#include "renderdoc.h"
#include "hmd_ovr.h"
#include "debug_renderdoc.h"
#ifndef GL_LUMINANCE
# define GL_LUMINANCE 0x1909
@ -791,6 +791,22 @@ typedef uint64_t GLuint64;
# define GL_CONSERVATIVE_RASTERIZATION_NV 0x9346
#endif // GL_CONSERVATIVE_RASTERIZATION_NV
#ifndef GL_NEGATIVE_ONE_TO_ONE
# define GL_NEGATIVE_ONE_TO_ONE 0x935E
#endif // GL_NEGATIVE_ONE_TO_ONE
#ifndef GL_ZERO_TO_ONE
# define GL_ZERO_TO_ONE 0x935F
#endif // GL_ZERO_TO_ONE
#ifndef GL_LOWER_LEFT
# define GL_LOWER_LEFT 0x8CA1
#endif // GL_LOWER_LEFT
#ifndef GL_UPPER_LEFT
# define GL_UPPER_LEFT 0x8CA2
#endif // GL_UPPER_LEFT
// _KHR or _ARB...
#define GL_DEBUG_OUTPUT_SYNCHRONOUS 0x8242
#define GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH 0x8243

View File

@ -765,14 +765,14 @@ end
MAME_DIR .. "3rdparty/bgfx/src/glcontext_ppapi.cpp",
MAME_DIR .. "3rdparty/bgfx/src/glcontext_wgl.cpp",
MAME_DIR .. "3rdparty/bgfx/src/image.cpp",
MAME_DIR .. "3rdparty/bgfx/src/ovr.cpp",
MAME_DIR .. "3rdparty/bgfx/src/hmd_ovr.cpp",
MAME_DIR .. "3rdparty/bgfx/src/renderer_d3d12.cpp",
MAME_DIR .. "3rdparty/bgfx/src/renderer_d3d11.cpp",
MAME_DIR .. "3rdparty/bgfx/src/renderer_d3d9.cpp",
MAME_DIR .. "3rdparty/bgfx/src/renderer_gl.cpp",
MAME_DIR .. "3rdparty/bgfx/src/renderer_null.cpp",
MAME_DIR .. "3rdparty/bgfx/src/renderer_vk.cpp",
MAME_DIR .. "3rdparty/bgfx/src/renderdoc.cpp",
MAME_DIR .. "3rdparty/bgfx/src/debug_renderdoc.cpp",
MAME_DIR .. "3rdparty/bgfx/src/shader.cpp",
MAME_DIR .. "3rdparty/bgfx/src/shader_dxbc.cpp",
MAME_DIR .. "3rdparty/bgfx/src/shader_dx9bc.cpp",