Implementation of main RenderingWindow in the RenderingManager.

This commit is contained in:
brunoherbelin
2020-05-31 23:00:47 +02:00
parent 010337518b
commit 38694a474d
4 changed files with 244 additions and 386 deletions

View File

@@ -168,7 +168,7 @@ void Mixer::update()
// swap front and back sessions // swap front and back sessions
swap(); swap();
// set session filename // set session filename
Rendering::manager().setWindowTitle(session_->filename()); Rendering::manager().mainWindow().setTitle(session_->filename());
Settings::application.recentSessions.push(session_->filename()); Settings::application.recentSessions.push(session_->filename());
} }
} }

View File

@@ -55,19 +55,6 @@ static GstGLDisplay *global_display = NULL;
static std::map<GLFWwindow *, RenderingWindow*> GLFW_window_; static std::map<GLFWwindow *, RenderingWindow*> GLFW_window_;
void updateSettings(int id, GLFWwindow *w)
{
if ( !Settings::application.windows[id].fullscreen) {
int x, y;
glfwGetWindowPos(w, &x, &y);
Settings::application.windows[id].x = x;
Settings::application.windows[id].y = y;
glfwGetWindowSize(w, &x, &y);
Settings::application.windows[id].w = x;
Settings::application.windows[id].h = y;
}
}
static void glfw_error_callback(int error, const char* description) static void glfw_error_callback(int error, const char* description)
{ {
Log::Error("Glfw Error %d: %s", error, description); Log::Error("Glfw Error %d: %s", error, description);
@@ -96,7 +83,7 @@ static void WindowMoveCallback( GLFWwindow *w, int x, int y)
} }
} }
static void WindowKeyCallback( GLFWwindow *w, int key, int scancode, int action, int) static void WindowEscapeFullscreen( GLFWwindow *w, int key, int scancode, int action, int)
{ {
if (action == GLFW_PRESS && key == GLFW_KEY_ESCAPE) if (action == GLFW_PRESS && key == GLFW_KEY_ESCAPE)
{ {
@@ -105,7 +92,7 @@ static void WindowKeyCallback( GLFWwindow *w, int key, int scancode, int action,
} }
} }
static void WindowMouseCallback( GLFWwindow *w, int button, int action, int) static void WindowToggleFullscreen( GLFWwindow *w, int button, int action, int)
{ {
static double seconds = 0.f; static double seconds = 0.f;
@@ -123,9 +110,8 @@ static void WindowMouseCallback( GLFWwindow *w, int button, int action, int)
Rendering::Rendering() Rendering::Rendering()
{ {
main_window_ = nullptr; // main_window_ = nullptr;
request_screenshot_ = false; request_screenshot_ = false;
dpi_scale_ = 1.f;
} }
bool Rendering::init() bool Rendering::init()
@@ -145,149 +131,65 @@ bool Rendering::init()
#if __APPLE__ #if __APPLE__
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // Required on Mac glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); // Required on Mac
#endif #endif
// GL Multisampling #3
//
// OpenGL Multisampling main window
//
glfwWindowHint(GLFW_SAMPLES, Settings::application.multisampling_level); glfwWindowHint(GLFW_SAMPLES, Settings::application.multisampling_level);
main_.init(0);
// set application icon
main_.setIcon("images/vimix_256x256.png");
// additional window callbacks for main window
glfwSetWindowRefreshCallback( main_.window(), WindowRefreshCallback );
glfwSetDropCallback( main_.window(), Rendering::FileDropped);
// Create window with graphics context //
Settings::WindowConfig winset = Settings::application.windows[0]; // Gstreamer setup for OpenGL
//
// do not show at creation
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
glfwWindowHint(GLFW_FOCUSED, GLFW_TRUE);
main_window_ = glfwCreateWindow(winset.w, winset.h, winset.name.c_str(), NULL, NULL);
if (main_window_ == NULL){
Log::Error("Failed to Create GLFW Window.");
return false;
}
// Add application icon
size_t fpsize = 0;
const char *fp = Resource::getData("images/vimix_256x256.png", &fpsize);
if (fp != nullptr) {
GLFWimage icon;
icon.pixels = stbi_load_from_memory( (const stbi_uc*)fp, fpsize, &icon.width, &icon.height, nullptr, 4 );
glfwSetWindowIcon( main_window_, 1, &icon );
free( icon.pixels );
}
// callbacks
glfwSetWindowRefreshCallback( main_window_, WindowRefreshCallback );
// glfwSetFramebufferSizeCallback( main_window_, WindowResizeCallback );
// glfwSetWindowPosCallback( main_window_, WindowMoveCallback );
glfwSetWindowPos(main_window_, winset.x, winset.y);
glfwMakeContextCurrent(main_window_);
glfwSwapInterval(1); // Enable vsync
// Initialize OpenGL loader
bool err = gladLoadGLLoader((GLADloadproc) glfwGetProcAddress) == 0;
if (err) {
Log::Error("Failed to initialize GLAD OpenGL loader.");
return false;
}
// // show window
// glfwShowWindow(main_window_);
// // restore fullscreen
// if (winset.fullscreen)
// toggleFullscreen();
// Rendering area (here same as window)
glfwGetFramebufferSize(main_window_, &(main_window_attributes_.viewport.x), &(main_window_attributes_.viewport.y));
glViewport(0, 0, main_window_attributes_.viewport.x, main_window_attributes_.viewport.y);
main_window_attributes_.clear_color = glm::vec4(COLOR_BGROUND, 1.0);
// DPI scaling (retina)
dpi_scale_ = float(main_window_attributes_.viewport.y) / float(winset.h);
// Gstreamer link to context
g_setenv ("GST_GL_API", "opengl3", FALSE); g_setenv ("GST_GL_API", "opengl3", FALSE);
gst_init (NULL, NULL); gst_init (NULL, NULL);
// Antialiasing
if (Settings::application.multisampling_level > 0) {
glEnable(GL_MULTISAMPLE);
glHint(GL_MULTISAMPLE_FILTER_HINT_NV, GL_NICEST);
}
// This hint can improve the speed of texturing when perspective-correct texture coordinate interpolation isn't needed
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
// This hint can improve the speed of shading when dFdx dFdy aren't needed in GLSL
glHint(GL_FRAGMENT_SHADER_DERIVATIVE_HINT, GL_FASTEST);
#if GST_GL_HAVE_PLATFORM_WGL #if GST_GL_HAVE_PLATFORM_WGL
global_gl_context = gst_gl_context_new_wrapped (display, (guintptr) wglGetCurrentContext (), global_gl_context = gst_gl_context_new_wrapped (display, (guintptr) wglGetCurrentContext (),
GST_GL_PLATFORM_WGL, GST_GL_API_OPENGL); GST_GL_PLATFORM_WGL, GST_GL_API_OPENGL);
#elif GST_GL_HAVE_PLATFORM_CGL #elif GST_GL_HAVE_PLATFORM_CGL
// global_display = GST_GL_DISPLAY ( glfwGetCocoaMonitor(main_.window()) );
// global_display = GST_GL_DISPLAY ( glfwGetCocoaMonitor(main_window_) );
global_display = GST_GL_DISPLAY (gst_gl_display_cocoa_new ()); global_display = GST_GL_DISPLAY (gst_gl_display_cocoa_new ());
global_gl_context = gst_gl_context_new_wrapped (global_display, global_gl_context = gst_gl_context_new_wrapped (global_display,
(guintptr) 0, (guintptr) 0,
GST_GL_PLATFORM_CGL, GST_GL_API_OPENGL); GST_GL_PLATFORM_CGL, GST_GL_API_OPENGL);
#elif GST_GL_HAVE_PLATFORM_GLX #elif GST_GL_HAVE_PLATFORM_GLX
//
global_display = (GstGLDisplay*) gst_gl_display_x11_new_with_display( glfwGetX11Display() ); global_display = (GstGLDisplay*) gst_gl_display_x11_new_with_display( glfwGetX11Display() );
global_gl_context = gst_gl_context_new_wrapped (global_display, global_gl_context = gst_gl_context_new_wrapped (global_display,
(guintptr) glfwGetGLXContext(main_window_), (guintptr) glfwGetGLXContext(main_.window()),
GST_GL_PLATFORM_GLX, GST_GL_API_OPENGL); GST_GL_PLATFORM_GLX, GST_GL_API_OPENGL);
#endif #endif
// TODO : force GPU decoding //
// GstElementFactory *vdpauh264dec = gst_element_factory_find("vdpauh264dec");
// if (vdpauh264dec)
// gst_plugin_feature_set_rank (GST_PLUGIN_FEATURE(vdpauh264dec), GST_RANK_PRIMARY); // or GST_RANK_MARGINAL
// GstElementFactory *vdpaumpeg4dec = gst_element_factory_find("vdpaumpeg4dec");
// if (vdpaumpeg4dec)
// gst_plugin_feature_set_rank (GST_PLUGIN_FEATURE(vdpaumpeg4dec), GST_RANK_PRIMARY);
// GstElementFactory *vdpaumpegdec = gst_element_factory_find("vdpaumpegdec");
// if (vdpaumpegdec)
// gst_plugin_feature_set_rank (GST_PLUGIN_FEATURE(vdpaumpegdec), GST_RANK_PRIMARY);
// file drop callback
glfwSetDropCallback(main_window_, Rendering::FileDropped);
// output window // output window
output.init(1, main_window_); //
output.setIcon("images/vimix_square_256x256.png"); glfwWindowHint(GLFW_SAMPLES, 0); // no need for multisampling in displaying output
output_.init(1, main_.window());
// set special icon
output_.setIcon("images/vimix_square_256x256.png");
// special callbacks for user input in output window
glfwSetKeyCallback( output_.window(), WindowEscapeFullscreen);
glfwSetMouseButtonCallback( output_.window(), WindowToggleFullscreen);
// show window // show output window
glfwShowWindow(main_window_); output_.show();
// restore fullscreen
if (winset.fullscreen) // show main window
toggleFullscreen(); main_.show();
return true; return true;
} }
bool Rendering::isActive() bool Rendering::isActive()
{ {
return !glfwWindowShouldClose(main_window_); return !glfwWindowShouldClose(main_.window());
} }
int Rendering::getWindowId(GLFWwindow *w)
{
if (w == main_window_)
return 0;
else
return 1;
// TODO manage more than one output
}
void Rendering::setWindowTitle(std::string title)
{
std::string window_title = std::string(APP_NAME " -- ") + title;
glfwSetWindowTitle(main_window_, window_title.c_str());
}
void Rendering::pushFrontDrawCallback(RenderingCallback function) void Rendering::pushFrontDrawCallback(RenderingCallback function)
{ {
@@ -308,81 +210,48 @@ void Rendering::draw()
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags. // Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
glfwPollEvents(); glfwPollEvents();
if ( Begin() ) main_.makeCurrent();
UserInterface::manager().NewFrame();
std::list<Rendering::RenderingCallback>::iterator iter;
for (iter=draw_callbacks_.begin(); iter != draw_callbacks_.end(); iter++)
{ {
UserInterface::manager().NewFrame(); (*iter)();
std::list<Rendering::RenderingCallback>::iterator iter;
for (iter=draw_callbacks_.begin(); iter != draw_callbacks_.end(); iter++)
{
(*iter)();
}
UserInterface::manager().Render();
End();
} }
UserInterface::manager().Render();
// perform screenshot if requested
if (request_screenshot_) {
// glfwMakeContextCurrent(main_window_);
screenshot_.CreateFromCaptureGL(0, 0, main_.width(), main_.height());
request_screenshot_ = false;
}
// swap GL buffers
glfwSwapBuffers(main_.window());
// no g_main_loop_run(loop) : update global GMainContext // no g_main_loop_run(loop) : update global GMainContext
g_main_context_iteration(NULL, FALSE); g_main_context_iteration(NULL, FALSE);
// draw output window // draw output window
output.draw( Mixer::manager().session()->frame() ); output_.draw( Mixer::manager().session()->frame() );
}
bool Rendering::Begin()
{
// TODO : optimize if window is minimized? (i.e. render output only)
// if( glfwGetWindowAttrib( main_window_, GLFW_ICONIFIED ) )
// {
// std::this_thread::sleep_for( std::chrono::milliseconds( 50 ) );
// return false;
// }
// handle window resize
glfwGetFramebufferSize(main_window_, &(main_window_attributes_.viewport.x), &(main_window_attributes_.viewport.y));
// ensure main context is current
glfwMakeContextCurrent(main_window_);
// setup and clear
glViewport(0, 0, main_window_attributes_.viewport.x, main_window_attributes_.viewport.y);
glClearColor(main_window_attributes_.clear_color.r, main_window_attributes_.clear_color.g,
main_window_attributes_.clear_color.b, main_window_attributes_.clear_color.a);
glClear(GL_COLOR_BUFFER_BIT);
return true;
}
void Rendering::End()
{
// glfwMakeContextCurrent(main_window_);
// perform screenshot if requested
if (request_screenshot_) {
screenshot_.CreateFromCaptureGL(0, 0, main_window_attributes_.viewport.x, main_window_attributes_.viewport.y);
request_screenshot_ = false;
}
// swap GL buffers
glfwSwapBuffers(main_window_);
} }
void Rendering::terminate() void Rendering::terminate()
{ {
// save pos
updateSettings(0, main_window_);
// close window // close window
glfwDestroyWindow(main_window_); glfwDestroyWindow(output_.window());
glfwDestroyWindow(main_.window());
glfwTerminate(); glfwTerminate();
} }
void Rendering::close() void Rendering::close()
{ {
glfwSetWindowShouldClose(main_window_, true); glfwSetWindowShouldClose(main_.window(), true);
} }
@@ -413,7 +282,8 @@ void Rendering::popAttrib()
RenderingAttrib Rendering::currentAttrib() RenderingAttrib Rendering::currentAttrib()
{ {
// default rendering attrib is the main window's // default rendering attrib is the main window's
RenderingAttrib ra = main_window_attributes_; RenderingAttrib ra = main_.attribs();
// but if there is an element at top, return it // but if there is an element at top, return it
if (draw_attributes_.size() > 0) if (draw_attributes_.size() > 0)
ra = draw_attributes_.front(); ra = draw_attributes_.front();
@@ -423,7 +293,7 @@ RenderingAttrib Rendering::currentAttrib()
glm::mat4 Rendering::Projection() glm::mat4 Rendering::Projection()
{ {
static glm::mat4 projection = glm::ortho(-SCENE_UNIT, SCENE_UNIT, -SCENE_UNIT, SCENE_UNIT, -SCENE_DEPTH, 1.f); static glm::mat4 projection = glm::ortho(-SCENE_UNIT, SCENE_UNIT, -SCENE_UNIT, SCENE_UNIT, -SCENE_DEPTH, 1.f);
glm::mat4 scale = glm::scale(glm::identity<glm::mat4>(), glm::vec3(1.f, aspectRatio(), 1.f)); glm::mat4 scale = glm::scale(glm::identity<glm::mat4>(), glm::vec3(1.f, main_.aspectRatio(), 1.f));
return projection * scale; return projection * scale;
} }
@@ -431,8 +301,8 @@ glm::mat4 Rendering::Projection()
glm::vec3 Rendering::unProject(glm::vec2 screen_coordinate, glm::mat4 modelview) glm::vec3 Rendering::unProject(glm::vec2 screen_coordinate, glm::mat4 modelview)
{ {
glm::vec3 coordinates = glm::vec3( screen_coordinate.x, main_window_attributes_.viewport.y - screen_coordinate.y, 0.f); glm::vec3 coordinates = glm::vec3( screen_coordinate.x, main_.height() - screen_coordinate.y, 0.f);
glm::vec4 viewport = glm::vec4( 0.f, 0.f, main_window_attributes_.viewport.x, main_window_attributes_.viewport.y); glm::vec4 viewport = glm::vec4( 0.f, 0.f, main_.width(), main_.height());
// Log::Info("unproject %d x %d", main_window_attributes_.viewport.x, main_window_attributes_.viewport.y); // Log::Info("unproject %d x %d", main_window_attributes_.viewport.x, main_window_attributes_.viewport.y);
@@ -441,69 +311,6 @@ glm::vec3 Rendering::unProject(glm::vec2 screen_coordinate, glm::mat4 modelview)
return point; return point;
} }
float Rendering::monitorWidth()
{
GLFWmonitor *monitor = glfwGetWindowMonitor (main_window_);
if (!monitor)
monitor = glfwGetPrimaryMonitor ();
int xpos, ypos, width, height;
glfwGetMonitorWorkarea(monitor, &xpos, &ypos, &width, &height);
return width;
}
float Rendering::monitorHeight()
{
GLFWmonitor *monitor = glfwGetWindowMonitor (main_window_);
if (!monitor)
monitor = glfwGetPrimaryMonitor ();
// TODO : detect in which monitor is the main window and return the height for that monitor
int xpos, ypos, width, height;
glfwGetMonitorWorkarea(monitor, &xpos, &ypos, &width, &height);
return height;
}
bool Rendering::isFullscreen ()
{
return (glfwGetWindowMonitor(main_window_) != nullptr);
}
void Rendering::toggleFullscreen()
{
// if in fullscreen mode
if (isFullscreen()) {
// set to window mode
glfwSetWindowMonitor( main_window_, nullptr, Settings::application.windows[0].x,
Settings::application.windows[0].y,
Settings::application.windows[0].w,
Settings::application.windows[0].h, 0 );
Settings::application.windows[0].fullscreen = false;
}
// not in fullscreen mode
else {
// remember window geometry
updateSettings(0, main_window_);
// select monitor
GLFWmonitor* monitor = glfwGetPrimaryMonitor();
const GLFWvidmode * mode = glfwGetVideoMode(monitor);
// set to fullscreen mode
glfwSetWindowMonitor( main_window_, monitor, 0, 0, mode->width, mode->height, mode->refreshRate);
Settings::application.windows[0].fullscreen = true;
}
}
float Rendering::aspectRatio()
{
return static_cast<float>(main_window_attributes_.viewport.x) / static_cast<float>(main_window_attributes_.viewport.y);
}
void Rendering::FileDropped(GLFWwindow *, int path_count, const char* paths[]) void Rendering::FileDropped(GLFWwindow *, int path_count, const char* paths[])
{ {
for (int i = 0; i < path_count; ++i) { for (int i = 0; i < path_count; ++i) {
@@ -527,11 +334,8 @@ void Rendering::requestScreenshot()
request_screenshot_ = true; request_screenshot_ = true;
} }
RenderingWindow::RenderingWindow() : window_(nullptr), master_(nullptr), id_(-1), dpi_scale_(1.f)
RenderingWindow::RenderingWindow() : window_(nullptr), master_(nullptr), frame_buffer_(nullptr), id_(-1)
{ {
} }
RenderingWindow::~RenderingWindow() RenderingWindow::~RenderingWindow()
@@ -539,6 +343,15 @@ RenderingWindow::~RenderingWindow()
} }
void RenderingWindow::setTitle(const std::string &title)
{
std::string fulltitle = Settings::application.windows[id_].name;
if ( !title.empty() )
fulltitle += " -- " + title;
glfwSetWindowTitle(window_, fulltitle.c_str());
}
void RenderingWindow::setIcon(const std::string &resource) void RenderingWindow::setIcon(const std::string &resource)
{ {
size_t fpsize = 0; size_t fpsize = 0;
@@ -619,7 +432,6 @@ GLFWmonitor *RenderingWindow::monitor()
return monitorAt(x, y); return monitorAt(x, y);
} }
void RenderingWindow::setFullscreen(GLFWmonitor *mo) void RenderingWindow::setFullscreen(GLFWmonitor *mo)
{ {
// if in fullscreen mode // if in fullscreen mode
@@ -668,6 +480,14 @@ int RenderingWindow::height()
return window_attributes_.viewport.y; return window_attributes_.viewport.y;
} }
int RenderingWindow::maxHeight()
{
int workarea_x, workarea_y, workarea_width, workarea_height;
glfwGetMonitorWorkarea(monitor(), &workarea_x, &workarea_y, &workarea_width, &workarea_height);
return workarea_height * dpi_scale_;
}
float RenderingWindow::aspectRatio() float RenderingWindow::aspectRatio()
{ {
return static_cast<float>(window_attributes_.viewport.x) / static_cast<float>(window_attributes_.viewport.y); return static_cast<float>(window_attributes_.viewport.x) / static_cast<float>(window_attributes_.viewport.y);
@@ -678,58 +498,90 @@ bool RenderingWindow::init(int id, GLFWwindow *share)
id_ = id; id_ = id;
master_ = share; master_ = share;
// access Settings
Settings::WindowConfig winset = Settings::application.windows[id_]; Settings::WindowConfig winset = Settings::application.windows[id_];
// setup endering area
window_attributes_.viewport.x = winset.w;
window_attributes_.viewport.y = winset.h;
window_attributes_.clear_color = glm::vec4(0.f, 0.f, 0.f, 1.0);
// do not show at creation // do not show at creation
glfwWindowHint(GLFW_FOCUSED, GLFW_FALSE); glfwWindowHint(GLFW_FOCUSED, GLFW_FALSE);
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE); glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
glfwWindowHint(GLFW_AUTO_ICONIFY, GLFW_FALSE); glfwWindowHint(GLFW_AUTO_ICONIFY, GLFW_FALSE);
// no need for multisampling in displaying output
glfwWindowHint(GLFW_SAMPLES, 0);
// create the window normal // create the window normal
window_ = glfwCreateWindow(winset.w, winset.h, winset.name.c_str(), NULL, master_); window_ = glfwCreateWindow(winset.w, winset.h, winset.name.c_str(), NULL, master_);
if (window_ == NULL){ if (window_ == NULL){
Log::Error("Failed to create GLFW Window %d", id_); Log::Error("Failed to create GLFW Window %d", id_);
return false; return false;
} }
// set position
glfwSetWindowPos(window_, winset.x, winset.y);
// store global ref to pointers (used by callbacks) // store global ref to pointers (used by callbacks)
GLFW_window_[window_] = this; GLFW_window_[window_] = this;
// callbacks // set position
glfwSetWindowPos(window_, winset.x, winset.y);
// window position and resize callbacks
glfwSetFramebufferSizeCallback( window_, WindowResizeCallback ); glfwSetFramebufferSizeCallback( window_, WindowResizeCallback );
glfwSetWindowPosCallback( window_, WindowMoveCallback ); glfwSetWindowPosCallback( window_, WindowMoveCallback );
glfwSetKeyCallback( window_, WindowKeyCallback);
glfwSetMouseButtonCallback( window_, WindowMouseCallback);
// take context ownership // take opengl context ownership
glfwMakeContextCurrent(window_); glfwMakeContextCurrent(window_);
// While objects are shared, the global context state is not and will static bool glad_initialized = false;
// need to be set up for each context if ( !glad_initialized ) {
glfwSwapInterval(0); // Disable vsync //
glDisable(GL_MULTISAMPLE); // Initialize OpenGL loader
//
bool err = gladLoadGLLoader((GLADloadproc) glfwGetProcAddress) == 0;
if (err) {
Log::Error("Failed to initialize GLAD OpenGL loader.");
return false;
}
glad_initialized = true;
}
// get rendering area
glfwGetFramebufferSize(window_, &(window_attributes_.viewport.x), &(window_attributes_.viewport.y));
// DPI scaling (retina)
dpi_scale_ = float(window_attributes_.viewport.y) / float(winset.h);
// This hint can improve the speed of texturing when perspective-correct texture coordinate interpolation isn't needed
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
// This hint can improve the speed of shading when dFdx dFdy aren't needed in GLSL
glHint(GL_FRAGMENT_SHADER_DERIVATIVE_HINT, GL_FASTEST);
// if not main window
if ( master_ != NULL ) {
// Disable vsync
glfwSwapInterval(0);
// no need for multisampling
glDisable(GL_MULTISAMPLE);
// clear to black
window_attributes_.clear_color = glm::vec4(0.f, 0.f, 0.f, 1.0);
// give back context ownership
glfwMakeContextCurrent(master_);
}
else {
// Enable vsync on main window
glfwSwapInterval(1);
// enable Antialiasing multisampling
if (Settings::application.multisampling_level > 0) {
glEnable(GL_MULTISAMPLE);
glHint(GL_MULTISAMPLE_FILTER_HINT_NV, GL_NICEST);
}
// clear to grey
window_attributes_.clear_color = glm::vec4(COLOR_BGROUND, 1.0);
}
return true;
}
void RenderingWindow::show()
{
if ( Settings::application.windows[id_].fullscreen ) { if ( Settings::application.windows[id_].fullscreen ) {
GLFWmonitor *mo = monitorNamed(Settings::application.windows[id_].monitor); GLFWmonitor *mo = monitorNamed(Settings::application.windows[id_].monitor);
setFullscreen(mo); setFullscreen(mo);
} }
glfwShowWindow(window_); glfwShowWindow(window_);
// give back context ownership
glfwMakeContextCurrent(master_);
return true;
} }
// custom surface with a new VAO // custom surface with a new VAO
@@ -751,6 +603,22 @@ WindowSurface::WindowSurface(Shader *s) : Primitive(s)
drawMode_ = GL_TRIANGLE_STRIP; drawMode_ = GL_TRIANGLE_STRIP;
} }
void RenderingWindow::makeCurrent()
{
// handle window resize
glfwGetFramebufferSize(window_, &(window_attributes_.viewport.x), &(window_attributes_.viewport.y));
// ensure main context is current
glfwMakeContextCurrent(window_);
// set and clear
glViewport(0, 0, window_attributes_.viewport.x, window_attributes_.viewport.y);
glClearColor(window_attributes_.clear_color.r, window_attributes_.clear_color.g,
window_attributes_.clear_color.b, window_attributes_.clear_color.a);
glClear(GL_COLOR_BUFFER_BIT);
}
void RenderingWindow::draw(FrameBuffer *fb) void RenderingWindow::draw(FrameBuffer *fb)
{ {
if (!window_) if (!window_)

View File

@@ -25,18 +25,29 @@ class RenderingWindow
{ {
GLFWwindow *window_, *master_; GLFWwindow *window_, *master_;
RenderingAttrib window_attributes_; RenderingAttrib window_attributes_;
FrameBuffer *frame_buffer_;
int id_; int id_;
float dpi_scale_;
// get monitor in which the window is
GLFWmonitor *monitor();
public: public:
RenderingWindow(); RenderingWindow();
~RenderingWindow(); ~RenderingWindow();
inline int id() const { return id_; } inline int id() const { return id_; }
inline RenderingAttrib& attribs() { return window_attributes_; }
inline GLFWwindow *window() const { return window_; }
bool init(int id, GLFWwindow *share = nullptr); bool init(int id, GLFWwindow *share = NULL);
void setIcon(const std::string &resource); void setIcon(const std::string &resource);
void setTitle(const std::string &title);
// show window (fullscreen if needed)
void show();
// make context current and set viewport
void makeCurrent();
// draw a framebuffer // draw a framebuffer
void draw(FrameBuffer *fb); void draw(FrameBuffer *fb);
@@ -52,15 +63,12 @@ public:
int height(); int height();
// get aspect ratio of rendering area // get aspect ratio of rendering area
float aspectRatio(); float aspectRatio();
// get total height available in monitor
// get GLFW window int maxHeight();
GLFWwindow *window();
// get monitor in which the window is
GLFWmonitor *monitor();
// get which monitor contains this point // get which monitor contains this point
static GLFWmonitor *monitorAt(int x, int y); static GLFWmonitor *monitorAt(int x, int y);
// get which monitor has this name
static GLFWmonitor *monitorNamed(const std::string &name); static GLFWmonitor *monitorNamed(const std::string &name);
}; };
@@ -103,53 +111,32 @@ public:
void popAttrib(); void popAttrib();
RenderingAttrib currentAttrib(); RenderingAttrib currentAttrib();
// get hold on the main window
inline RenderingWindow& mainWindow() { return main_; }
// request screenshot // request screenshot
void requestScreenshot(); void requestScreenshot();
// get Screenshot // get Screenshot
class Screenshot *currentScreenshot(); class Screenshot *currentScreenshot();
// window management
void setWindowTitle(std::string title);
// request fullscreen
bool isFullscreen ();
void toggleFullscreen ();
// get aspect ratio of rendering area
float aspectRatio();
// monitor management
float monitorWidth();
float monitorHeight();
// get projection matrix (for sharers) => Views // get projection matrix (for sharers) => Views
glm::mat4 Projection(); glm::mat4 Projection();
// unproject from window coordinate // unproject from window coordinate
glm::vec3 unProject(glm::vec2 screen_coordinate, glm::mat4 modelview = glm::mat4(1.f)); glm::vec3 unProject(glm::vec2 screen_coordinate, glm::mat4 modelview = glm::mat4(1.f));
// utility for settings
int getWindowId(GLFWwindow *w);
private: private:
// GLFW integration in OS window management
GLFWwindow *main_window_;
std::string glsl_version; std::string glsl_version;
float dpi_scale_;
// loop update to begin new frame
bool Begin();
// loop update end frame
void End();
// void GrabWindow(int dx, int dy);
// list of rendering attributes // list of rendering attributes
std::list<RenderingAttrib> draw_attributes_; std::list<RenderingAttrib> draw_attributes_;
RenderingAttrib main_window_attributes_;
// list of functions to call at each Draw // list of functions to call at each Draw
std::list<RenderingCallback> draw_callbacks_; std::list<RenderingCallback> draw_callbacks_;
RenderingWindow output; RenderingWindow main_;
RenderingWindow output_;
// file drop callback // file drop callback
static void FileDropped(GLFWwindow* main_window_, int path_count, const char* paths[]); static void FileDropped(GLFWwindow* main_window_, int path_count, const char* paths[]);

View File

@@ -140,7 +140,7 @@ UserInterface::UserInterface()
bool UserInterface::Init() bool UserInterface::Init()
{ {
if (Rendering::manager().main_window_ == nullptr) if (Rendering::manager().mainWindow().window()== nullptr)
return false; return false;
// Setup Dear ImGui context // Setup Dear ImGui context
@@ -152,14 +152,14 @@ bool UserInterface::Init()
io.FontGlobalScale = Settings::application.scale; io.FontGlobalScale = Settings::application.scale;
// Setup Platform/Renderer bindings // Setup Platform/Renderer bindings
ImGui_ImplGlfw_InitForOpenGL(Rendering::manager().main_window_, true); ImGui_ImplGlfw_InitForOpenGL(Rendering::manager().mainWindow().window(), true);
ImGui_ImplOpenGL3_Init(Rendering::manager().glsl_version.c_str()); ImGui_ImplOpenGL3_Init(Rendering::manager().glsl_version.c_str());
// Setup Dear ImGui style // Setup Dear ImGui style
ImGuiToolkit::SetAccentColor(static_cast<ImGuiToolkit::accent_color>(Settings::application.accent_color)); ImGuiToolkit::SetAccentColor(static_cast<ImGuiToolkit::accent_color>(Settings::application.accent_color));
// Estalish the base size from the resolution of the monitor // Estalish the base size from the resolution of the monitor
float base_font_size = (Rendering::manager().monitorHeight() * Rendering::manager().dpi_scale_) / 100.f ; float base_font_size = float(Rendering::manager().mainWindow().maxHeight()) / 100.f ;
// Load Fonts (using resource manager, NB: a temporary copy of the raw data is necessary) // Load Fonts (using resource manager, NB: a temporary copy of the raw data is necessary)
ImGuiToolkit::SetFont(ImGuiToolkit::FONT_DEFAULT, "Roboto-Regular", int(base_font_size) ); ImGuiToolkit::SetFont(ImGuiToolkit::FONT_DEFAULT, "Roboto-Regular", int(base_font_size) );
ImGuiToolkit::SetFont(ImGuiToolkit::FONT_BOLD, "Roboto-Bold", int(base_font_size) ); ImGuiToolkit::SetFont(ImGuiToolkit::FONT_BOLD, "Roboto-Bold", int(base_font_size) );
@@ -169,7 +169,7 @@ bool UserInterface::Init()
ImGuiToolkit::SetFont(ImGuiToolkit::FONT_LARGE, "Hack-Regular", MIN(int(base_font_size * 1.5f), 50), 1 ); ImGuiToolkit::SetFont(ImGuiToolkit::FONT_LARGE, "Hack-Regular", MIN(int(base_font_size * 1.5f), 50), 1 );
// info // info
Log::Info("Monitor (%.1f,%.1f)", Rendering::manager().monitorWidth(), Rendering::manager().monitorHeight()); // Log::Info("Monitor (%.1f,%.1f)", Rendering::manager().monitorWidth(), Rendering::manager().monitorHeight());
Log::Info("Font size %d", int(base_font_size) ); Log::Info("Font size %d", int(base_font_size) );
// Style // Style
@@ -262,7 +262,7 @@ void UserInterface::handleKeyboard()
else if (ImGui::IsKeyPressed( GLFW_KEY_F3 )) else if (ImGui::IsKeyPressed( GLFW_KEY_F3 ))
Mixer::manager().setCurrentView(View::LAYER); Mixer::manager().setCurrentView(View::LAYER);
else if (ImGui::IsKeyPressed( GLFW_KEY_F11 )) else if (ImGui::IsKeyPressed( GLFW_KEY_F11 ))
Rendering::manager().toggleFullscreen(); Rendering::manager().mainWindow().toggleFullscreen();
else if (ImGui::IsKeyPressed( GLFW_KEY_F12 )) else if (ImGui::IsKeyPressed( GLFW_KEY_F12 ))
StartScreenshot(); StartScreenshot();
// normal keys // make sure no entry / window box is active // normal keys // make sure no entry / window box is active
@@ -700,81 +700,84 @@ void UserInterface::RenderMediaPlayer()
ImGui::Text(" %s %d x %d\n Framerate %.2f / %.2f", mp->codec().c_str(), mp->width(), mp->height(), mp->updateFrameRate() , mp->frameRate() ); ImGui::Text(" %s %d x %d\n Framerate %.2f / %.2f", mp->codec().c_str(), mp->width(), mp->height(), mp->updateFrameRate() , mp->frameRate() );
} }
if (ImGui::Button(ICON_FA_FAST_BACKWARD)) if (mp->duration() != GST_CLOCK_TIME_NONE) {
mp->rewind();
ImGui::SameLine(0, spacing);
// remember playing mode of the GUI if (ImGui::Button(ICON_FA_FAST_BACKWARD))
bool media_playing_mode = mp->isPlaying(); mp->rewind();
// display buttons Play/Stop depending on current playing mode
if (media_playing_mode) {
if (ImGui::Button(ICON_FA_STOP " Stop"))
media_playing_mode = false;
ImGui::SameLine(0, spacing); ImGui::SameLine(0, spacing);
ImGui::PushButtonRepeat(true); // remember playing mode of the GUI
if (ImGui::Button(ICON_FA_FORWARD)) bool media_playing_mode = mp->isPlaying();
mp->fastForward ();
ImGui::PopButtonRepeat();
}
else {
if (ImGui::Button(ICON_FA_PLAY " Play")) // display buttons Play/Stop depending on current playing mode
media_playing_mode = true; if (media_playing_mode) {
if (ImGui::Button(ICON_FA_STOP " Stop"))
media_playing_mode = false;
ImGui::SameLine(0, spacing);
ImGui::PushButtonRepeat(true);
if (ImGui::Button(ICON_FA_FORWARD))
mp->fastForward ();
ImGui::PopButtonRepeat();
}
else {
if (ImGui::Button(ICON_FA_PLAY " Play"))
media_playing_mode = true;
ImGui::SameLine(0, spacing);
ImGui::PushButtonRepeat(true);
if (ImGui::Button(ICON_FA_STEP_FORWARD))
mp->seekNextFrame();
ImGui::PopButtonRepeat();
}
ImGui::SameLine(0, spacing * 4.f);
static int current_loop = 0;
static std::vector< std::pair<int, int> > iconsloop = { {0,15}, {1,15}, {19,14} };
current_loop = (int) mp->loop();
if ( ImGuiToolkit::ButtonIconMultistate(iconsloop, &current_loop) )
mp->setLoop( (MediaPlayer::LoopMode) current_loop );
float speed = static_cast<float>(mp->playSpeed());
ImGui::SameLine(0, spacing); ImGui::SameLine(0, spacing);
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x - 40.0);
// ImGui::SetNextItemWidth(width - 90.0);
if (ImGui::DragFloat( "##Speed", &speed, 0.01f, -10.f, 10.f, "Speed x %.1f", 2.f))
mp->setPlaySpeed( static_cast<double>(speed) );
ImGui::SameLine(0, spacing);
if (ImGuiToolkit::ButtonIcon(12, 14)) {
speed = 1.f;
mp->setPlaySpeed( static_cast<double>(speed) );
mp->setLoop( MediaPlayer::LOOP_REWIND );
}
ImGui::PushButtonRepeat(true); guint64 current_t = mp->position();
if (ImGui::Button(ICON_FA_STEP_FORWARD)) guint64 seek_t = current_t;
mp->seekNextFrame();
ImGui::PopButtonRepeat();
}
ImGui::SameLine(0, spacing * 4.f); bool slider_pressed = ImGuiToolkit::TimelineSlider( "simpletimeline", &seek_t,
mp->duration(), mp->frameDuration());
static int current_loop = 0; // if the seek target time is different from the current position time
static std::vector< std::pair<int, int> > iconsloop = { {0,15}, {1,15}, {19,14} }; // (i.e. the difference is less than one frame)
current_loop = (int) mp->loop(); if ( ABS_DIFF (current_t, seek_t) > mp->frameDuration() ) {
if ( ImGuiToolkit::ButtonIconMultistate(iconsloop, &current_loop) )
mp->setLoop( (MediaPlayer::LoopMode) current_loop );
float speed = static_cast<float>(mp->playSpeed()); // request seek (ASYNC)
ImGui::SameLine(0, spacing); mp->seekTo(seek_t);
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x - 40.0); }
// ImGui::SetNextItemWidth(width - 90.0);
if (ImGui::DragFloat( "##Speed", &speed, 0.01f, -10.f, 10.f, "Speed x %.1f", 2.f))
mp->setPlaySpeed( static_cast<double>(speed) );
ImGui::SameLine(0, spacing);
if (ImGuiToolkit::ButtonIcon(12, 14)) {
speed = 1.f;
mp->setPlaySpeed( static_cast<double>(speed) );
mp->setLoop( MediaPlayer::LOOP_REWIND );
}
guint64 current_t = mp->position(); // play/stop command should be following the playing mode (buttons)
guint64 seek_t = current_t; // AND force to stop when the slider is pressed
bool media_play = media_playing_mode & (!slider_pressed);
bool slider_pressed = ImGuiToolkit::TimelineSlider( "simpletimeline", &seek_t, // apply play action to media only if status should change
mp->duration(), mp->frameDuration()); // NB: The seek command performed an ASYNC state change, but
// gst_element_get_state called in isPlaying() will wait for the state change to complete.
// if the seek target time is different from the current position time if ( mp->isPlaying(true) != media_play ) {
// (i.e. the difference is less than one frame) mp->play( media_play );
if ( ABS_DIFF (current_t, seek_t) > mp->frameDuration() ) { }
// request seek (ASYNC)
mp->seekTo(seek_t);
}
// play/stop command should be following the playing mode (buttons)
// AND force to stop when the slider is pressed
bool media_play = media_playing_mode & (!slider_pressed);
// apply play action to media only if status should change
// NB: The seek command performed an ASYNC state change, but
// gst_element_get_state called in isPlaying() will wait for the state change to complete.
if ( mp->isPlaying(true) != media_play ) {
mp->play( media_play );
} }
ImGui::End(); ImGui::End();