Moving imgui to the new ImmediateDrawer.
This commit is contained in:
parent
c631b965d7
commit
4c2257a29d
|
@ -28,11 +28,11 @@
|
|||
#include "xenia/base/threading.h"
|
||||
#include "xenia/cpu/frontend/ppc_disasm.h"
|
||||
#include "xenia/cpu/stack_walker.h"
|
||||
#include "xenia/debug/ui/imgui_renderer.h"
|
||||
#include "xenia/gpu/graphics_system.h"
|
||||
#include "xenia/kernel/xmodule.h"
|
||||
#include "xenia/kernel/xthread.h"
|
||||
#include "xenia/ui/gl/gl_context.h"
|
||||
#include "xenia/ui/imgui_drawer.h"
|
||||
|
||||
DEFINE_bool(imgui_debug, false, "Show ImGui debugging tools.");
|
||||
|
||||
|
@ -91,7 +91,7 @@ bool DebugWindow::Initialize() {
|
|||
|
||||
window_->on_closed.AddListener([this](UIEvent* e) {
|
||||
// Kill now while we have a GL context.
|
||||
imgui_renderer_.reset();
|
||||
imgui_drawer_.reset();
|
||||
});
|
||||
loop_->on_quit.AddListener([this](UIEvent* e) { window_.reset(); });
|
||||
|
||||
|
@ -120,8 +120,7 @@ bool DebugWindow::Initialize() {
|
|||
window_->set_context(std::move(context));
|
||||
|
||||
// Setup ImGui.
|
||||
imgui_renderer_ =
|
||||
std::make_unique<ImGuiRenderer>(window_.get(), window_->context());
|
||||
imgui_drawer_ = std::make_unique<xe::ui::ImGuiDrawer>(window_.get());
|
||||
window_->on_key_char.AddListener([](xe::ui::KeyEvent* e) {
|
||||
auto& io = ImGui::GetIO();
|
||||
if (e->key_code() > 0 && e->key_code() < 0x10000) {
|
||||
|
|
|
@ -21,12 +21,16 @@
|
|||
#include "xenia/ui/window.h"
|
||||
#include "xenia/xbox.h"
|
||||
|
||||
namespace xe {
|
||||
namespace ui {
|
||||
class ImGuiDrawer;
|
||||
} // namespace ui
|
||||
} // namespace xe
|
||||
|
||||
namespace xe {
|
||||
namespace debug {
|
||||
namespace ui {
|
||||
|
||||
class ImGuiRenderer;
|
||||
|
||||
class DebugWindow : public DebugListener {
|
||||
public:
|
||||
~DebugWindow();
|
||||
|
@ -91,7 +95,7 @@ class DebugWindow : public DebugListener {
|
|||
Debugger* debugger_ = nullptr;
|
||||
xe::ui::Loop* loop_ = nullptr;
|
||||
std::unique_ptr<xe::ui::Window> window_;
|
||||
std::unique_ptr<ImGuiRenderer> imgui_renderer_;
|
||||
std::unique_ptr<xe::ui::ImGuiDrawer> imgui_drawer_;
|
||||
uint64_t last_draw_tick_count_ = 0;
|
||||
|
||||
uintptr_t capstone_handle_ = 0;
|
||||
|
|
|
@ -1,55 +0,0 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2015 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_DEBUG_UI_IMGUI_RENDERER_H_
|
||||
#define XENIA_DEBUG_UI_IMGUI_RENDERER_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "third_party/imgui/imgui.h"
|
||||
#include "xenia/base/clock.h"
|
||||
#include "xenia/base/logging.h"
|
||||
#include "xenia/base/math.h"
|
||||
#include "xenia/ui/gl/circular_buffer.h"
|
||||
#include "xenia/ui/gl/gl_context.h"
|
||||
#include "xenia/ui/window.h"
|
||||
|
||||
namespace xe {
|
||||
namespace debug {
|
||||
namespace ui {
|
||||
|
||||
class ImGuiRenderer {
|
||||
public:
|
||||
ImGuiRenderer(xe::ui::Window* window, xe::ui::GraphicsContext* context);
|
||||
~ImGuiRenderer();
|
||||
|
||||
private:
|
||||
static ImGuiRenderer* global_renderer_;
|
||||
|
||||
void Initialize();
|
||||
void InitializeShaders();
|
||||
void InitializeFontTextures();
|
||||
void Shutdown();
|
||||
|
||||
void RenderDrawLists(ImDrawData* data);
|
||||
|
||||
xe::ui::Window* window_ = nullptr;
|
||||
xe::ui::GraphicsContext* context_ = nullptr;
|
||||
|
||||
GLuint program_ = 0;
|
||||
GLuint vao_ = 0;
|
||||
xe::ui::gl::CircularBuffer vertex_buffer_;
|
||||
xe::ui::gl::CircularBuffer index_buffer_;
|
||||
};
|
||||
|
||||
} // namespace ui
|
||||
} // namespace debug
|
||||
} // namespace xe
|
||||
|
||||
#endif // XENIA_DEBUG_UI_IMGUI_RENDERER_H_
|
|
@ -11,7 +11,6 @@
|
|||
#include <cstring>
|
||||
|
||||
#include "third_party/imgui/imgui.h"
|
||||
|
||||
#include "xenia/base/clock.h"
|
||||
#include "xenia/base/logging.h"
|
||||
#include "xenia/base/main.h"
|
||||
|
@ -25,6 +24,7 @@
|
|||
#include "xenia/gpu/xenos.h"
|
||||
#include "xenia/profiling.h"
|
||||
#include "xenia/ui/gl/gl_context.h"
|
||||
#include "xenia/ui/imgui_drawer.h"
|
||||
#include "xenia/ui/window.h"
|
||||
|
||||
// HACK: until we have another impl, we just use gl4 directly.
|
||||
|
@ -2182,8 +2182,7 @@ void DrawUI(xe::ui::Window* window, TracePlayer& player, Memory* memory) {
|
|||
DrawPacketDisassemblerUI(window, player, memory);
|
||||
}
|
||||
|
||||
void ImImpl_Setup();
|
||||
void ImImpl_Shutdown();
|
||||
std::unique_ptr<xe::ui::ImGuiDrawer> imgui_drawer_;
|
||||
|
||||
int trace_viewer_main(const std::vector<std::wstring>& args) {
|
||||
// Create the emulator but don't initialize so we can setup the window.
|
||||
|
@ -2202,6 +2201,7 @@ int trace_viewer_main(const std::vector<std::wstring>& args) {
|
|||
window->on_closed.AddListener([&loop](xe::ui::UIEvent* e) {
|
||||
loop->Quit();
|
||||
XELOGI("User-initiated death!");
|
||||
imgui_drawer_.reset();
|
||||
exit(1);
|
||||
});
|
||||
loop->on_quit.AddListener([&window](xe::ui::UIEvent* e) { window.reset(); });
|
||||
|
@ -2236,9 +2236,10 @@ int trace_viewer_main(const std::vector<std::wstring>& args) {
|
|||
window->set_title(std::wstring(L"Xenia GPU Trace Viewer: ") + file_name);
|
||||
|
||||
auto graphics_system = emulator->graphics_system();
|
||||
Profiler::set_window(nullptr);
|
||||
|
||||
TracePlayer player(loop.get(), emulator->graphics_system());
|
||||
imgui_drawer_ = std::make_unique<xe::ui::ImGuiDrawer>(window.get());
|
||||
|
||||
TracePlayer player(loop.get(), graphics_system);
|
||||
if (!player.Open(abs_path)) {
|
||||
XELOGE("Could not load trace file");
|
||||
return 1;
|
||||
|
@ -2290,11 +2291,6 @@ int trace_viewer_main(const std::vector<std::wstring>& args) {
|
|||
});
|
||||
|
||||
window->on_painting.AddListener([&](xe::ui::UIEvent* e) {
|
||||
static bool imgui_setup = false;
|
||||
if (!imgui_setup) {
|
||||
ImImpl_Setup();
|
||||
imgui_setup = true;
|
||||
}
|
||||
auto& io = ImGui::GetIO();
|
||||
auto current_ticks = Clock::QueryHostTickCount();
|
||||
static uint64_t last_ticks = 0;
|
||||
|
@ -2326,7 +2322,7 @@ int trace_viewer_main(const std::vector<std::wstring>& args) {
|
|||
// Wait until we are exited.
|
||||
loop->AwaitQuit();
|
||||
|
||||
ImImpl_Shutdown();
|
||||
imgui_drawer_.reset();
|
||||
|
||||
emulator.reset();
|
||||
window.reset();
|
||||
|
@ -2334,260 +2330,6 @@ int trace_viewer_main(const std::vector<std::wstring>& args) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
// TODO(benvanik): move to another file.
|
||||
|
||||
static int shader_handle, vert_handle, frag_handle;
|
||||
static int texture_location, proj_mtx_location;
|
||||
static int position_location, uv_location, colour_location;
|
||||
static size_t vbo_max_size = 20000;
|
||||
static unsigned int vbo_handle, vao_handle;
|
||||
void ImImpl_RenderDrawLists(ImDrawData* data);
|
||||
void ImImpl_Setup() {
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
|
||||
const GLchar* vertex_shader =
|
||||
"#version 330\n"
|
||||
"uniform mat4 ProjMtx;\n"
|
||||
"in vec2 Position;\n"
|
||||
"in vec2 UV;\n"
|
||||
"in vec4 Color;\n"
|
||||
"out vec2 Frag_UV;\n"
|
||||
"out vec4 Frag_Color;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" Frag_UV = UV;\n"
|
||||
" Frag_Color = Color;\n"
|
||||
" gl_Position = ProjMtx * vec4(Position.xy,0,1);\n"
|
||||
"}\n";
|
||||
|
||||
const GLchar* fragment_shader =
|
||||
"#version 330\n"
|
||||
"uniform sampler2D Texture;\n"
|
||||
"in vec2 Frag_UV;\n"
|
||||
"in vec4 Frag_Color;\n"
|
||||
"out vec4 Out_Color;\n"
|
||||
"void main()\n"
|
||||
"{\n"
|
||||
" Out_Color = Frag_Color * texture( Texture, Frag_UV.st);\n"
|
||||
"}\n";
|
||||
|
||||
shader_handle = glCreateProgram();
|
||||
vert_handle = glCreateShader(GL_VERTEX_SHADER);
|
||||
frag_handle = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
glShaderSource(vert_handle, 1, &vertex_shader, 0);
|
||||
glShaderSource(frag_handle, 1, &fragment_shader, 0);
|
||||
glCompileShader(vert_handle);
|
||||
glCompileShader(frag_handle);
|
||||
glAttachShader(shader_handle, vert_handle);
|
||||
glAttachShader(shader_handle, frag_handle);
|
||||
glLinkProgram(shader_handle);
|
||||
|
||||
texture_location = glGetUniformLocation(shader_handle, "Texture");
|
||||
proj_mtx_location = glGetUniformLocation(shader_handle, "ProjMtx");
|
||||
position_location = glGetAttribLocation(shader_handle, "Position");
|
||||
uv_location = glGetAttribLocation(shader_handle, "UV");
|
||||
colour_location = glGetAttribLocation(shader_handle, "Color");
|
||||
|
||||
glGenBuffers(1, &vbo_handle);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo_handle);
|
||||
glBufferData(GL_ARRAY_BUFFER, vbo_max_size, NULL, GL_DYNAMIC_DRAW);
|
||||
|
||||
glGenVertexArrays(1, &vao_handle);
|
||||
glBindVertexArray(vao_handle);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo_handle);
|
||||
glEnableVertexAttribArray(position_location);
|
||||
glEnableVertexAttribArray(uv_location);
|
||||
glEnableVertexAttribArray(colour_location);
|
||||
|
||||
glVertexAttribPointer(position_location, 2, GL_FLOAT, GL_FALSE,
|
||||
sizeof(ImDrawVert), (GLvoid*)offsetof(ImDrawVert, pos));
|
||||
glVertexAttribPointer(uv_location, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert),
|
||||
(GLvoid*)offsetof(ImDrawVert, uv));
|
||||
glVertexAttribPointer(colour_location, 4, GL_UNSIGNED_BYTE, GL_TRUE,
|
||||
sizeof(ImDrawVert), (GLvoid*)offsetof(ImDrawVert, col));
|
||||
glBindVertexArray(0);
|
||||
glDisableVertexAttribArray(position_location);
|
||||
glDisableVertexAttribArray(uv_location);
|
||||
glDisableVertexAttribArray(colour_location);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
unsigned char* pixels;
|
||||
int width, height;
|
||||
io.Fonts->GetTexDataAsRGBA32(
|
||||
&pixels, &width, &height); // Load as RGBA 32-bits for OpenGL3 demo
|
||||
// because it is more likely to be compatible
|
||||
// with user's existing shader.
|
||||
|
||||
GLuint tex_id;
|
||||
glCreateTextures(GL_TEXTURE_2D, 1, &tex_id);
|
||||
glTextureParameteri(tex_id, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTextureParameteri(tex_id, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glTextureStorage2D(tex_id, 1, GL_RGBA8, width, height);
|
||||
glTextureSubImage2D(tex_id, 0, 0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
pixels);
|
||||
|
||||
// Store our identifier
|
||||
io.Fonts->TexID = (void*)(intptr_t)tex_id;
|
||||
|
||||
io.DeltaTime = 1.0f / 60.0f;
|
||||
io.RenderDrawListsFn = ImImpl_RenderDrawLists;
|
||||
|
||||
auto& style = ImGui::GetStyle();
|
||||
style.WindowRounding = 0;
|
||||
|
||||
style.Colors[ImGuiCol_Text] = ImVec4(0.89f, 0.90f, 0.90f, 1.00f);
|
||||
style.Colors[ImGuiCol_WindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f);
|
||||
style.Colors[ImGuiCol_ChildWindowBg] = ImVec4(0.00f, 0.00f, 0.00f, 0.00f);
|
||||
style.Colors[ImGuiCol_Border] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
|
||||
style.Colors[ImGuiCol_BorderShadow] = ImVec4(0.00f, 0.00f, 0.00f, 0.60f);
|
||||
style.Colors[ImGuiCol_FrameBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.22f);
|
||||
style.Colors[ImGuiCol_TitleBg] = ImVec4(0.00f, 1.00f, 0.00f, 0.78f);
|
||||
style.Colors[ImGuiCol_TitleBgCollapsed] = ImVec4(0.00f, 0.58f, 0.00f, 0.61f);
|
||||
style.Colors[ImGuiCol_ScrollbarBg] = ImVec4(0.00f, 0.40f, 0.11f, 0.59f);
|
||||
style.Colors[ImGuiCol_ScrollbarGrab] = ImVec4(0.00f, 0.68f, 0.00f, 0.68f);
|
||||
style.Colors[ImGuiCol_ScrollbarGrabHovered] =
|
||||
ImVec4(0.00f, 1.00f, 0.15f, 0.62f);
|
||||
style.Colors[ImGuiCol_ScrollbarGrabActive] =
|
||||
ImVec4(0.00f, 0.91f, 0.09f, 0.40f);
|
||||
style.Colors[ImGuiCol_ComboBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.99f);
|
||||
style.Colors[ImGuiCol_CheckMark] = ImVec4(0.74f, 0.90f, 0.72f, 0.50f);
|
||||
style.Colors[ImGuiCol_SliderGrab] = ImVec4(1.00f, 1.00f, 1.00f, 0.30f);
|
||||
style.Colors[ImGuiCol_SliderGrabActive] = ImVec4(0.34f, 0.75f, 0.11f, 1.00f);
|
||||
style.Colors[ImGuiCol_Button] = ImVec4(0.15f, 0.56f, 0.11f, 0.60f);
|
||||
style.Colors[ImGuiCol_ButtonHovered] = ImVec4(0.19f, 0.72f, 0.09f, 1.00f);
|
||||
style.Colors[ImGuiCol_ButtonActive] = ImVec4(0.19f, 0.60f, 0.09f, 1.00f);
|
||||
style.Colors[ImGuiCol_Header] = ImVec4(0.00f, 0.40f, 0.00f, 0.71f);
|
||||
style.Colors[ImGuiCol_HeaderHovered] = ImVec4(0.00f, 0.60f, 0.26f, 0.80f);
|
||||
style.Colors[ImGuiCol_HeaderActive] = ImVec4(0.00f, 0.75f, 0.00f, 0.80f);
|
||||
style.Colors[ImGuiCol_Column] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
|
||||
style.Colors[ImGuiCol_ColumnHovered] = ImVec4(0.36f, 0.89f, 0.38f, 1.00f);
|
||||
style.Colors[ImGuiCol_ColumnActive] = ImVec4(0.13f, 0.50f, 0.11f, 1.00f);
|
||||
style.Colors[ImGuiCol_ResizeGrip] = ImVec4(1.00f, 1.00f, 1.00f, 0.30f);
|
||||
style.Colors[ImGuiCol_ResizeGripHovered] = ImVec4(1.00f, 1.00f, 1.00f, 0.60f);
|
||||
style.Colors[ImGuiCol_ResizeGripActive] = ImVec4(1.00f, 1.00f, 1.00f, 0.90f);
|
||||
style.Colors[ImGuiCol_CloseButton] = ImVec4(0.00f, 0.72f, 0.00f, 0.96f);
|
||||
style.Colors[ImGuiCol_CloseButtonHovered] =
|
||||
ImVec4(0.38f, 1.00f, 0.42f, 0.60f);
|
||||
style.Colors[ImGuiCol_CloseButtonActive] = ImVec4(0.56f, 1.00f, 0.64f, 1.00f);
|
||||
style.Colors[ImGuiCol_PlotLines] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
|
||||
style.Colors[ImGuiCol_PlotLinesHovered] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
|
||||
style.Colors[ImGuiCol_PlotHistogram] = ImVec4(0.90f, 0.70f, 0.00f, 1.00f);
|
||||
style.Colors[ImGuiCol_PlotHistogramHovered] =
|
||||
ImVec4(1.00f, 0.60f, 0.00f, 1.00f);
|
||||
style.Colors[ImGuiCol_TextSelectedBg] = ImVec4(0.00f, 0.00f, 1.00f, 0.35f);
|
||||
style.Colors[ImGuiCol_TooltipBg] = ImVec4(0.05f, 0.05f, 0.10f, 0.90f);
|
||||
|
||||
io.KeyMap[ImGuiKey_Tab] = VK_TAB;
|
||||
io.KeyMap[ImGuiKey_LeftArrow] = VK_LEFT;
|
||||
io.KeyMap[ImGuiKey_RightArrow] = VK_RIGHT;
|
||||
io.KeyMap[ImGuiKey_UpArrow] = VK_UP;
|
||||
io.KeyMap[ImGuiKey_DownArrow] = VK_DOWN;
|
||||
io.KeyMap[ImGuiKey_Home] = VK_HOME;
|
||||
io.KeyMap[ImGuiKey_End] = VK_END;
|
||||
io.KeyMap[ImGuiKey_Delete] = VK_DELETE;
|
||||
io.KeyMap[ImGuiKey_Backspace] = VK_BACK;
|
||||
io.KeyMap[ImGuiKey_Enter] = VK_RETURN;
|
||||
io.KeyMap[ImGuiKey_Escape] = VK_ESCAPE;
|
||||
io.KeyMap[ImGuiKey_A] = 'A';
|
||||
io.KeyMap[ImGuiKey_C] = 'C';
|
||||
io.KeyMap[ImGuiKey_V] = 'V';
|
||||
io.KeyMap[ImGuiKey_X] = 'X';
|
||||
io.KeyMap[ImGuiKey_Y] = 'Y';
|
||||
io.KeyMap[ImGuiKey_Z] = 'Z';
|
||||
}
|
||||
void ImImpl_Shutdown() {
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
if (vao_handle) glDeleteVertexArrays(1, &vao_handle);
|
||||
if (vbo_handle) glDeleteBuffers(1, &vbo_handle);
|
||||
glDetachShader(shader_handle, vert_handle);
|
||||
glDetachShader(shader_handle, frag_handle);
|
||||
glDeleteShader(vert_handle);
|
||||
glDeleteShader(frag_handle);
|
||||
glDeleteProgram(shader_handle);
|
||||
auto tex_id = static_cast<GLuint>(intptr_t(io.Fonts->TexID));
|
||||
glDeleteTextures(1, &tex_id);
|
||||
ImGui::Shutdown();
|
||||
}
|
||||
void ImImpl_RenderDrawLists(ImDrawData* data) {
|
||||
if (data->CmdListsCount == 0) return;
|
||||
|
||||
// Setup render state: alpha-blending enabled, no face culling, no depth
|
||||
// testing, scissor enabled
|
||||
glEnable(GL_BLEND);
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
glDisable(GL_CULL_FACE);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
// Setup orthographic projection matrix
|
||||
const float width = ImGui::GetIO().DisplaySize.x;
|
||||
const float height = ImGui::GetIO().DisplaySize.y;
|
||||
const float ortho_projection[4][4] = {
|
||||
{2.0f / width, 0.0f, 0.0f, 0.0f},
|
||||
{0.0f, 2.0f / -height, 0.0f, 0.0f},
|
||||
{0.0f, 0.0f, -1.0f, 0.0f},
|
||||
{-1.0f, 1.0f, 0.0f, 1.0f},
|
||||
};
|
||||
glProgramUniform1i(shader_handle, texture_location, 0);
|
||||
glProgramUniformMatrix4fv(shader_handle, proj_mtx_location, 1, GL_FALSE,
|
||||
&ortho_projection[0][0]);
|
||||
|
||||
// Grow our buffer according to what we need
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo_handle);
|
||||
size_t neededBufferSize = data->TotalVtxCount * sizeof(ImDrawVert);
|
||||
if (neededBufferSize > vbo_max_size) {
|
||||
vbo_max_size = neededBufferSize + 5000; // Grow buffer
|
||||
glBufferData(GL_ARRAY_BUFFER, vbo_max_size, NULL, GL_STREAM_DRAW);
|
||||
}
|
||||
|
||||
glBindVertexArray(vao_handle);
|
||||
glUseProgram(shader_handle);
|
||||
|
||||
GLuint ib;
|
||||
glGenBuffers(1, &ib);
|
||||
|
||||
ImTextureID prev_texture_id = 0;
|
||||
for (int n = 0; n < data->CmdListsCount; n++) {
|
||||
const ImDrawList* cmd_list = data->CmdLists[n];
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
|
||||
(GLsizeiptr)cmd_list->IdxBuffer.size() * sizeof(ImDrawIdx),
|
||||
(GLvoid*)&cmd_list->IdxBuffer.front(), GL_STREAM_DRAW);
|
||||
// Copy and convert all vertices into a single contiguous buffer
|
||||
unsigned char* buffer_data =
|
||||
(unsigned char*)glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY);
|
||||
memcpy(buffer_data, &cmd_list->VtxBuffer[0],
|
||||
cmd_list->VtxBuffer.size() * sizeof(ImDrawVert));
|
||||
glUnmapBuffer(GL_ARRAY_BUFFER);
|
||||
const ImDrawIdx* idx_buffer_offset = 0;
|
||||
for (auto cmd = cmd_list->CmdBuffer.begin();
|
||||
cmd != cmd_list->CmdBuffer.end(); ++cmd) {
|
||||
if (cmd->TextureId != prev_texture_id) {
|
||||
glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)cmd->TextureId);
|
||||
prev_texture_id = cmd->TextureId;
|
||||
}
|
||||
glScissor((int)cmd->ClipRect.x, (int)(height - cmd->ClipRect.w),
|
||||
(int)(cmd->ClipRect.z - cmd->ClipRect.x),
|
||||
(int)(cmd->ClipRect.w - cmd->ClipRect.y));
|
||||
glDrawElements(GL_TRIANGLES, (GLsizei)cmd->ElemCount, GL_UNSIGNED_SHORT,
|
||||
idx_buffer_offset);
|
||||
idx_buffer_offset += cmd->ElemCount;
|
||||
}
|
||||
}
|
||||
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
glDeleteBuffers(1, &ib);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
// Restore modified state
|
||||
glBindVertexArray(0);
|
||||
glUseProgram(0);
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
} // namespace gpu
|
||||
} // namespace xe
|
||||
|
||||
|
|
|
@ -25,8 +25,8 @@ class GLImmediateTexture : public ImmediateTexture {
|
|||
GLImmediateTexture(uint32_t width, uint32_t height,
|
||||
ImmediateTextureFilter filter, bool repeat)
|
||||
: ImmediateTexture(width, height) {
|
||||
GLuint handle;
|
||||
glCreateTextures(GL_TEXTURE_2D, 1, &handle);
|
||||
GLuint gl_handle;
|
||||
glCreateTextures(GL_TEXTURE_2D, 1, &gl_handle);
|
||||
|
||||
GLenum gl_filter = GL_NEAREST;
|
||||
switch (filter) {
|
||||
|
@ -37,21 +37,22 @@ class GLImmediateTexture : public ImmediateTexture {
|
|||
gl_filter = GL_LINEAR;
|
||||
break;
|
||||
}
|
||||
glTextureParameteri(handle, GL_TEXTURE_MIN_FILTER, gl_filter);
|
||||
glTextureParameteri(handle, GL_TEXTURE_MAG_FILTER, gl_filter);
|
||||
glTextureParameteri(gl_handle, GL_TEXTURE_MIN_FILTER, gl_filter);
|
||||
glTextureParameteri(gl_handle, GL_TEXTURE_MAG_FILTER, gl_filter);
|
||||
|
||||
glTextureParameteri(handle, GL_TEXTURE_WRAP_S,
|
||||
glTextureParameteri(gl_handle, GL_TEXTURE_WRAP_S,
|
||||
repeat ? GL_REPEAT : GL_CLAMP_TO_EDGE);
|
||||
glTextureParameteri(handle, GL_TEXTURE_WRAP_T,
|
||||
glTextureParameteri(gl_handle, GL_TEXTURE_WRAP_T,
|
||||
repeat ? GL_REPEAT : GL_CLAMP_TO_EDGE);
|
||||
|
||||
glTextureStorage2D(handle, 1, GL_RGBA8, width, height);
|
||||
glTextureStorage2D(gl_handle, 1, GL_RGBA8, width, height);
|
||||
|
||||
this->handle = static_cast<uintptr_t>(handle);
|
||||
handle = static_cast<uintptr_t>(gl_handle);
|
||||
}
|
||||
|
||||
~GLImmediateTexture() override {
|
||||
//
|
||||
GLuint gl_handle = static_cast<GLuint>(handle);
|
||||
glDeleteTextures(1, &gl_handle);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -191,6 +192,7 @@ void GLImmediateDrawer::Begin(int render_target_width,
|
|||
// Prepare drawing resources.
|
||||
glUseProgram(program_);
|
||||
glBindVertexArray(vao_);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer_);
|
||||
|
||||
// Setup orthographic projection matrix and viewport.
|
||||
const float ortho_projection[4][4] = {
|
||||
|
@ -203,7 +205,7 @@ void GLImmediateDrawer::Begin(int render_target_width,
|
|||
glViewport(0, 0, render_target_width, render_target_height);
|
||||
}
|
||||
|
||||
void GLImmediateDrawer::Draw(const ImmediateDrawBatch& batch) {
|
||||
void GLImmediateDrawer::BeginDrawBatch(const ImmediateDrawBatch& batch) {
|
||||
glNamedBufferSubData(vertex_buffer_, 0,
|
||||
batch.vertex_count * sizeof(ImmediateVertex),
|
||||
batch.vertices);
|
||||
|
@ -212,22 +214,26 @@ void GLImmediateDrawer::Draw(const ImmediateDrawBatch& batch) {
|
|||
batch.indices);
|
||||
}
|
||||
|
||||
if (batch.scissor) {
|
||||
batch_has_index_buffer_ = !!batch.indices;
|
||||
}
|
||||
|
||||
void GLImmediateDrawer::Draw(const ImmediateDraw& draw) {
|
||||
if (draw.scissor) {
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
glScissor(batch.scissor_rect[0], batch.scissor_rect[1],
|
||||
batch.scissor_rect[2], batch.scissor_rect[3]);
|
||||
glScissor(draw.scissor_rect[0], draw.scissor_rect[1], draw.scissor_rect[2],
|
||||
draw.scissor_rect[3]);
|
||||
} else {
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
}
|
||||
|
||||
if (batch.texture_handle) {
|
||||
glBindTextureUnit(0, static_cast<GLuint>(batch.texture_handle));
|
||||
if (draw.texture_handle) {
|
||||
glBindTextureUnit(0, static_cast<GLuint>(draw.texture_handle));
|
||||
} else {
|
||||
glBindTextureUnit(0, 0);
|
||||
}
|
||||
|
||||
GLenum mode = GL_TRIANGLES;
|
||||
switch (batch.primitive_type) {
|
||||
switch (draw.primitive_type) {
|
||||
case ImmediatePrimitiveType::kLines:
|
||||
mode = GL_LINES;
|
||||
break;
|
||||
|
@ -236,21 +242,25 @@ void GLImmediateDrawer::Draw(const ImmediateDrawBatch& batch) {
|
|||
break;
|
||||
}
|
||||
|
||||
if (batch.indices) {
|
||||
glDrawElements(mode, batch.index_count, GL_UNSIGNED_SHORT, nullptr);
|
||||
if (batch_has_index_buffer_) {
|
||||
glDrawElementsBaseVertex(
|
||||
mode, draw.count, GL_UNSIGNED_SHORT,
|
||||
reinterpret_cast<void*>(draw.index_offset * sizeof(uint16_t)),
|
||||
draw.base_vertex);
|
||||
} else {
|
||||
glDrawArrays(mode, 0, batch.vertex_count);
|
||||
glDrawArrays(mode, draw.base_vertex, draw.count);
|
||||
}
|
||||
|
||||
glFlush();
|
||||
}
|
||||
|
||||
void GLImmediateDrawer::EndDrawBatch() { glFlush(); }
|
||||
|
||||
void GLImmediateDrawer::End() {
|
||||
// Restore modified state.
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
glBindTextureUnit(0, 0);
|
||||
glUseProgram(0);
|
||||
glBindVertexArray(0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
|
||||
if (!was_current_) {
|
||||
graphics_context_->ClearCurrent();
|
||||
|
|
|
@ -32,7 +32,9 @@ class GLImmediateDrawer : public ImmediateDrawer {
|
|||
void UpdateTexture(ImmediateTexture* texture, const uint8_t* data) override;
|
||||
|
||||
void Begin(int render_target_width, int render_target_height) override;
|
||||
void Draw(const ImmediateDrawBatch& batch) override;
|
||||
void BeginDrawBatch(const ImmediateDrawBatch& batch) override;
|
||||
void Draw(const ImmediateDraw& draw) override;
|
||||
void EndDrawBatch() override;
|
||||
void End() override;
|
||||
|
||||
private:
|
||||
|
@ -44,6 +46,7 @@ class GLImmediateDrawer : public ImmediateDrawer {
|
|||
GLuint index_buffer_ = 0;
|
||||
|
||||
bool was_current_ = false;
|
||||
bool batch_has_index_buffer_ = false;
|
||||
};
|
||||
|
||||
} // namespace gl
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,51 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2015 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_UI_IMGUI_DRAWER_H_
|
||||
#define XENIA_UI_IMGUI_DRAWER_H_
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
#include "xenia/ui/immediate_drawer.h"
|
||||
|
||||
struct ImDrawData;
|
||||
|
||||
namespace xe {
|
||||
namespace ui {
|
||||
|
||||
class GraphicsContext;
|
||||
class Window;
|
||||
|
||||
class ImGuiDrawer {
|
||||
public:
|
||||
ImGuiDrawer(Window* window);
|
||||
~ImGuiDrawer();
|
||||
|
||||
protected:
|
||||
void Initialize();
|
||||
void SetupFont();
|
||||
|
||||
void RenderDrawLists(ImDrawData* data);
|
||||
|
||||
static ImGuiDrawer* global_drawer_;
|
||||
|
||||
Window* window_ = nullptr;
|
||||
GraphicsContext* graphics_context_ = nullptr;
|
||||
|
||||
std::vector<ImmediateVertex> vertices_;
|
||||
std::vector<uint16_t> indices_;
|
||||
|
||||
std::unique_ptr<ImmediateTexture> font_texture_;
|
||||
};
|
||||
|
||||
} // namespace ui
|
||||
} // namespace xe
|
||||
|
||||
#endif // XENIA_UI_IMGUI_DRAWER_H_
|
|
@ -47,6 +47,9 @@ enum class ImmediatePrimitiveType {
|
|||
};
|
||||
|
||||
// Simple vertex used by the immediate mode drawer.
|
||||
// To avoid translations, this matches both imgui and elemental-forms vertices:
|
||||
// ImDrawVert
|
||||
// el::graphics::Renderer::Vertex
|
||||
struct ImmediateVertex {
|
||||
float x, y;
|
||||
float u, v;
|
||||
|
@ -55,9 +58,6 @@ struct ImmediateVertex {
|
|||
|
||||
// All parameters required to draw an immediate-mode batch of vertices.
|
||||
struct ImmediateDrawBatch {
|
||||
// Primitive type the vertices/indices represent.
|
||||
ImmediatePrimitiveType primitive_type = ImmediatePrimitiveType::kTriangles;
|
||||
|
||||
// Vertices to draw.
|
||||
const ImmediateVertex* vertices = nullptr;
|
||||
int vertex_count = 0;
|
||||
|
@ -65,6 +65,17 @@ struct ImmediateDrawBatch {
|
|||
// Optional index buffer indices.
|
||||
const uint16_t* indices = nullptr;
|
||||
int index_count = 0;
|
||||
};
|
||||
|
||||
struct ImmediateDraw {
|
||||
// Primitive type the vertices/indices represent.
|
||||
ImmediatePrimitiveType primitive_type = ImmediatePrimitiveType::kTriangles;
|
||||
// Total number of elements to draw.
|
||||
int count = 0;
|
||||
// Starting offset in the index buffer.
|
||||
int index_offset = 0;
|
||||
// Base vertex of elements, if using an index buffer.
|
||||
int base_vertex = 0;
|
||||
|
||||
// Texture used when drawing, or nullptr if color only.
|
||||
// This is most commonly the handle of an ImmediateTexture.
|
||||
|
@ -91,8 +102,12 @@ class ImmediateDrawer {
|
|||
|
||||
// Begins drawing in immediate mode using the given projection matrix.
|
||||
virtual void Begin(int render_target_width, int render_target_height) = 0;
|
||||
// Issues an immediate mode draw batch.
|
||||
virtual void Draw(const ImmediateDrawBatch& batch) = 0;
|
||||
// Starts a draw batch.
|
||||
virtual void BeginDrawBatch(const ImmediateDrawBatch& batch) = 0;
|
||||
// Draws one set of a batch.
|
||||
virtual void Draw(const ImmediateDraw& draw) = 0;
|
||||
// Ends a draw batch.
|
||||
virtual void EndDrawBatch() = 0;
|
||||
// Ends drawing in immediate mode and flushes contents.
|
||||
virtual void End() = 0;
|
||||
|
||||
|
|
|
@ -158,8 +158,8 @@ void MicroprofileDrawer::SetupFont() {
|
|||
}
|
||||
|
||||
// Unpack font bitmap into an RGBA texture.
|
||||
const int UNPACKED_SIZE = kFontTextureWidth * kFontTextureHeight * 4;
|
||||
uint32_t unpacked[UNPACKED_SIZE];
|
||||
const int kUnpackedSize = kFontTextureWidth * kFontTextureHeight * 4;
|
||||
uint32_t unpacked[kUnpackedSize];
|
||||
int idx = 0;
|
||||
int end = kFontTextureWidth * kFontTextureHeight / 8;
|
||||
for (int i = 0; i < end; i++) {
|
||||
|
@ -175,7 +175,7 @@ void MicroprofileDrawer::SetupFont() {
|
|||
false, reinterpret_cast<uint8_t*>(unpacked));
|
||||
}
|
||||
|
||||
MicroprofileDrawer::~MicroprofileDrawer() { font_texture_.reset(); }
|
||||
MicroprofileDrawer::~MicroprofileDrawer() = default;
|
||||
|
||||
void MicroprofileDrawer::Begin() {
|
||||
graphics_context_->immediate_drawer()->Begin(window_->width(),
|
||||
|
@ -202,15 +202,24 @@ ImmediateVertex* MicroprofileDrawer::BeginVertices(
|
|||
void MicroprofileDrawer::EndVertices() {}
|
||||
|
||||
void MicroprofileDrawer::Flush() {
|
||||
auto drawer = graphics_context_->immediate_drawer();
|
||||
if (!vertex_count_) {
|
||||
return;
|
||||
}
|
||||
|
||||
ImmediateDrawBatch batch;
|
||||
batch.primitive_type = current_primitive_type_;
|
||||
batch.vertices = vertices_.data();
|
||||
batch.vertex_count = vertex_count_;
|
||||
batch.texture_handle = font_texture_->handle;
|
||||
graphics_context_->immediate_drawer()->Draw(batch);
|
||||
drawer->BeginDrawBatch(batch);
|
||||
|
||||
ImmediateDraw draw;
|
||||
draw.primitive_type = current_primitive_type_;
|
||||
draw.count = vertex_count_;
|
||||
draw.texture_handle = font_texture_->handle;
|
||||
drawer->Draw(draw);
|
||||
|
||||
drawer->EndDrawBatch();
|
||||
|
||||
vertex_count_ = 0;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue