From 7f658e81ab32ea2474e1fce3759b5050a8e79738 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Thu, 4 Jun 2020 23:55:47 +0200 Subject: Fix freeze on target window resize --- src/main.cpp | 205 +++++++++++++++------------------------------------ src/window_texture.c | 120 ++++++++++++++++++++++++++++++ 2 files changed, 180 insertions(+), 145 deletions(-) create mode 100644 src/window_texture.c (limited to 'src') diff --git a/src/main.cpp b/src/main.cpp index 0e281e4..51c087b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -31,6 +31,10 @@ // Modified by: DEC05EBA +extern "C" { +#include "../include/window_texture.h" +} + #include #include #include @@ -42,7 +46,6 @@ #include #include #include -#include #include #include @@ -104,8 +107,6 @@ public: void ProcessVREvent( const vr::VREvent_t & event ); void RenderFrame(); - bool SetupTexturemaps(); - void SetupScene(); void AddCubeToScene( const glm::mat4 &mat, std::vector &vertdata ); void AddCubeVertex( float fl0, float fl1, float fl2, float fl3, float fl4, std::vector &vertdata ); @@ -192,8 +193,6 @@ private: // OpenGL bookkeeping float m_fNearClip; float m_fFarClip; - GLuint m_iTexture; - unsigned int m_uiVertcount; GLuint m_glSceneVertBuffer; @@ -271,9 +270,12 @@ private: // OpenGL bookkeeping private: // X compositor Display *x_display = nullptr; Window src_window_id = None; - Pixmap src_window_pixmap; - GLXFBConfig *configs; - GLXPixmap glxpixmap; + WindowTexture window_texture; + + int window_width; + int window_height; + Uint32 window_resize_time; + bool window_resized; GLint pixmap_texture_width = 0; GLint pixmap_texture_height = 0; @@ -508,18 +510,6 @@ std::string GetTrackedDeviceString( vr::TrackedDeviceIndex_t unDevice, vr::Track return sResult; } -static bool x11_supports_composite_named_window_pixmap(Display *dpy) -{ - int extension_major; - int extension_minor; - if(!XCompositeQueryExtension(dpy, &extension_major, &extension_minor)) - return false; - - int major_version; - int minor_version; - return XCompositeQueryVersion(dpy, &major_version, &minor_version) && (major_version > 0 || minor_version >= 2); -} - //----------------------------------------------------------------------------- // Purpose: @@ -533,14 +523,17 @@ bool CMainApplication::BInit() return false; } - bool has_name_pixmap = x11_supports_composite_named_window_pixmap(x_display); - if(!has_name_pixmap) - { - fprintf(stderr, "Error: XComposite name pixmap is not supported by your X11 server\n"); - return false; - } + XWindowAttributes xwa; + if(!XGetWindowAttributes(x_display, src_window_id, &xwa)) { + fprintf(stderr, "Error: Invalid window id: %lud\n", src_window_id); + return false; + } + window_width = xwa.width; + window_height = xwa.height; + window_resize_time = SDL_GetTicks(); + window_resized = false; - XCompositeRedirectWindow(x_display, src_window_id, CompositeRedirectAutomatic); + XSelectInput(x_display, src_window_id, StructureNotifyMask); if ( SDL_Init( SDL_INIT_VIDEO | SDL_INIT_TIMER ) < 0 ) { @@ -566,8 +559,8 @@ bool CMainApplication::BInit() int nWindowPosY = 100; Uint32 unWindowFlags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN; - SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 4 ); - SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 1 ); + SDL_GL_SetAttribute( SDL_GL_CONTEXT_MAJOR_VERSION, 3 ); + SDL_GL_SetAttribute( SDL_GL_CONTEXT_MINOR_VERSION, 2 ); //SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY ); SDL_GL_SetAttribute( SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE ); @@ -625,7 +618,6 @@ bool CMainApplication::BInit() m_fNearClip = 0.01f; m_fFarClip = 30.0f; - m_iTexture = 0; m_uiVertcount = 0; // m_MillisecondsTimer.start(1, this); @@ -709,8 +701,19 @@ bool CMainApplication::BInitGL() if( !CreateAllShaders() ) return false; - if(!SetupTexturemaps()) + if(window_texture_init(&window_texture, x_display, src_window_id) != 0) return false; + + pixmap_texture_width = 0; + pixmap_texture_height = 0; + glBindTexture(GL_TEXTURE_2D, window_texture_get_opengl_texture_id(&window_texture)); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &pixmap_texture_width); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &pixmap_texture_height); + glBindTexture(GL_TEXTURE_2D, 0); + + glGenVertexArrays( 1, &m_unSceneVAO ); + glGenBuffers( 1, &m_glSceneVertBuffer ); + SetupScene(); SetupCameras(); if(!SetupStereoRenderTargets()) @@ -808,6 +811,8 @@ void CMainApplication::Shutdown() } } + window_texture_deinit(&window_texture); + if( m_pCompanionWindow ) { SDL_DestroyWindow(m_pCompanionWindow); @@ -816,13 +821,8 @@ void CMainApplication::Shutdown() SDL_Quit(); - if (x_display) { - glXReleaseTexImageEXT(x_display, glxpixmap, GLX_FRONT_EXT); - glXDestroyPixmap(x_display, glxpixmap); - XFree(configs); - XFreePixmap(x_display, src_window_pixmap); + if (x_display) XCloseDisplay(x_display); - } } //----------------------------------------------------------------------------- @@ -853,14 +853,29 @@ bool CMainApplication::HandleInput() } } - XEvent x_event; + XEvent xev; -#if 0 - if(XCheckTypedWindowEvent(x_display, src_window_id, damage_event + XDamageNotify, &x_event)) { + if (XCheckTypedWindowEvent(x_display, src_window_id, ConfigureNotify, &xev) && xev.xconfigure.window == src_window_id) { + // Window resize + if(xev.xconfigure.width != window_width || xev.xconfigure.height != window_height) { + window_width = xev.xconfigure.width; + window_height = xev.xconfigure.height; + window_resize_time = SDL_GetTicks(); + window_resized = true; + } } -#endif - + Uint32 time_now = SDL_GetTicks(); + const int window_resize_timeout = 500; /* 0.5 seconds */ + if(window_resized && time_now - window_resize_time >= window_resize_timeout) { + window_resized = false; + window_texture_on_resize(&window_texture); + glBindTexture(GL_TEXTURE_2D, window_texture_get_opengl_texture_id(&window_texture)); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &pixmap_texture_width); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &pixmap_texture_height); + glBindTexture(GL_TEXTURE_2D, 0); + SetupScene(); + } // Process SteamVR events vr::VREvent_t event; @@ -1255,86 +1270,6 @@ bool CMainApplication::CreateAllShaders() } -//----------------------------------------------------------------------------- -// Purpose: -//----------------------------------------------------------------------------- -bool CMainApplication::SetupTexturemaps() -{ - GLfloat fLargest; - - const int pixmap_config[] = { - GLX_BIND_TO_TEXTURE_RGBA_EXT, True, - GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT, - GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT, - //GLX_BIND_TO_MIPMAP_TEXTURE_EXT, True, - GLX_BUFFER_SIZE, 32, - GLX_ALPHA_SIZE, 8, - GLX_DOUBLEBUFFER, False, - GLX_Y_INVERTED_EXT, (int)GLX_DONT_CARE, - None - }; - - const int pixmap_attribs[] = { - GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT, - GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGB_EXT, - //GLX_MIPMAP_TEXTURE_EXT, True, - None, None, None - }; - - int c; - configs = glXChooseFBConfig(x_display, 0, pixmap_config, &c); - if (!configs) - { - printf("Failed too choose fb config\n"); - return false; - } - - src_window_pixmap = XCompositeNameWindowPixmap(x_display, src_window_id); - if (!src_window_pixmap) - { - printf("Failed to get pixmap for window %ld\n", src_window_id); - return false; - } - - glxpixmap = glXCreatePixmap(x_display, *configs, src_window_pixmap, pixmap_attribs); - if (!glxpixmap) - { - printf("Failed to create pixmap\n"); - return false; - } - - - glGenTextures(1, &m_iTexture ); - glBindTexture( GL_TEXTURE_2D, m_iTexture ); - - glEnable(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - glXBindTexImageEXT(x_display, glxpixmap, GLX_FRONT_EXT, NULL); - //glGenerateTextureMipmapEXT(glxpixmap, GL_TEXTURE_2D); - - //glGenerateMipmap(GL_TEXTURE_2D); - - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);//GL_LINEAR_MIPMAP_LINEAR ); - glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - - glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &fLargest); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, fLargest); - - pixmap_texture_width = 0; - pixmap_texture_height = 0; - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &pixmap_texture_width); - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &pixmap_texture_height); - - glBindTexture( GL_TEXTURE_2D, 0 ); - - return ( m_iTexture != 0 ); -} - - //----------------------------------------------------------------------------- // Purpose: create a sea of cubes //----------------------------------------------------------------------------- @@ -1384,10 +1319,7 @@ void CMainApplication::SetupScene() #endif m_uiVertcount = vertdataarray.size()/5; - glGenVertexArrays( 1, &m_unSceneVAO ); glBindVertexArray( m_unSceneVAO ); - - glGenBuffers( 1, &m_glSceneVertBuffer ); glBindBuffer( GL_ARRAY_BUFFER, m_glSceneVertBuffer ); glBufferData( GL_ARRAY_BUFFER, sizeof(float) * vertdataarray.size(), &vertdataarray[0], GL_STATIC_DRAW); @@ -1448,8 +1380,8 @@ void CMainApplication::AddCubeToScene( const glm::mat4 &mat, std::vector double radius_height = 0.5; double radius = 0.5 * width_ratio; - for(long row = 0; row < rows-1; ++row) { - for(long column = 0; column < columns-1; ++column) { + for(long row = 0; row < rows; ++row) { + for(long column = 0; column < columns; ++column) { double offset_angle = 0.0;//angle_x*0.5; double y_sin1 = sin((double)row / (double)rows * 3.14); @@ -1772,24 +1704,7 @@ void CMainApplication::RenderStereoTargets() { glClearColor( 0.0f, 0.0f, 0.0f, 1.0f ); glEnable( GL_MULTISAMPLE ); - //TODO: Fix this -#if 0 - glBindTexture( GL_TEXTURE_2D, m_iTexture ); - - glXBindTexImageEXT(x_display, glxpixmap, GLX_FRONT_EXT, NULL); - //glGenerateTextureMipmapEXT(glxpixmap, GL_TEXTURE_2D); - - glGenerateMipmap(GL_TEXTURE_2D); - - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR ); - GLfloat fLargest; - glGetFloatv( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &fLargest ); - glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, fLargest ); -#endif // Left Eye glBindFramebuffer( GL_FRAMEBUFFER, leftEyeDesc.m_nRenderFramebufferId ); glViewport(0, 0, m_nRenderWidth, m_nRenderHeight ); @@ -1859,7 +1774,7 @@ void CMainApplication::RenderScene( vr::Hmd_Eye nEye ) } glBindVertexArray( m_unSceneVAO ); - glBindTexture( GL_TEXTURE_2D, m_iTexture ); + glBindTexture( GL_TEXTURE_2D, window_texture_get_opengl_texture_id(&window_texture) ); glDrawArrays( GL_TRIANGLES, 0, m_uiVertcount ); glBindVertexArray( 0 ); #if 0 diff --git a/src/window_texture.c b/src/window_texture.c new file mode 100644 index 0000000..d899266 --- /dev/null +++ b/src/window_texture.c @@ -0,0 +1,120 @@ +#include "../include/window_texture.h" +#include + +static int x11_supports_composite_named_window_pixmap(Display *display) { + int extension_major; + int extension_minor; + if(!XCompositeQueryExtension(display, &extension_major, &extension_minor)) + return 0; + + int major_version; + int minor_version; + return XCompositeQueryVersion(display, &major_version, &minor_version) && (major_version > 0 || minor_version >= 2); +} + +int window_texture_init(WindowTexture *window_texture, Display *display, Window window) { + if(!x11_supports_composite_named_window_pixmap(display)) + return 1; + + window_texture->display = display; + window_texture->window = window; + window_texture->pixmap = None; + window_texture->glx_pixmap = None; + window_texture->texture_id = 0; + + XCompositeRedirectWindow(display, window, CompositeRedirectAutomatic); + return window_texture_on_resize(window_texture); +} + +static void window_texture_cleanup(WindowTexture *self) { + if(self->texture_id) { + glDeleteTextures(1, &self->texture_id); + self->texture_id = 0; + } + + if(self->glx_pixmap) { + glXDestroyPixmap(self->display, self->glx_pixmap); + glXReleaseTexImageEXT(self->display, self->glx_pixmap, GLX_FRONT_EXT); + self->glx_pixmap = None; + } + + if(self->pixmap) { + XFreePixmap(self->display, self->pixmap); + self->pixmap = None; + } +} + +void window_texture_deinit(WindowTexture *self) { + window_texture_cleanup(self); +} + +int window_texture_on_resize(WindowTexture *self) { + window_texture_cleanup(self); + + int result = 0; + + const int pixmap_config[] = { + GLX_BIND_TO_TEXTURE_RGBA_EXT, True, + GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT, + GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT, + /*GLX_BIND_TO_MIPMAP_TEXTURE_EXT, True,*/ + GLX_DOUBLEBUFFER, False, + GLX_BUFFER_SIZE, 32, + GLX_ALPHA_SIZE, 8, + None + }; + + const int pixmap_attribs[] = { + GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT, + GLX_TEXTURE_FORMAT_EXT, GLX_TEXTURE_FORMAT_RGB_EXT, + /*GLX_MIPMAP_TEXTURE_EXT, True,*/ + None + }; + + int c; + GLXFBConfig *configs = glXChooseFBConfig(self->display, 0, pixmap_config, &c); + if(!configs) + return 1; + + self->pixmap = XCompositeNameWindowPixmap(self->display, self->window); + if(!self->pixmap) { + result = 2; + goto cleanup; + } + + self->glx_pixmap = glXCreatePixmap(self->display, configs[0], self->pixmap, pixmap_attribs); + if(!self->glx_pixmap) { + result = 3; + goto cleanup; + } + + glGenTextures(1, &self->texture_id); + glBindTexture(GL_TEXTURE_2D, self->texture_id); + if(self->texture_id == 0) { + result = 4; + goto cleanup; + } + + glXBindTexImageEXT(self->display, self->glx_pixmap, GLX_FRONT_EXT, NULL); + /*glGenerateMipmap(GL_TEXTURE_2D)*/ + + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); + glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);//GL_LINEAR_MIPMAP_LINEAR ); + glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + + float fLargest = 0.0f; + glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &fLargest); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, fLargest); + + glBindTexture(GL_TEXTURE_2D, 0); + + cleanup: + XFree(configs); + return result; +} + +GLuint window_texture_get_opengl_texture_id(WindowTexture *self) { + return self->texture_id; +} \ No newline at end of file -- cgit v1.2.3