1 /**************************************************************************
3 * Copyright 2013-2014 RAD Game Tools and Valve Software
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 **************************************************************************/
26 // File: vogl_replay_window.cpp
27 #include "vogl_replay_window.h"
29 vogl_replay_window::vogl_replay_window()
40 vogl_replay_window::~vogl_replay_window()
47 bool vogl_replay_window::open(int width, int height, int samples)
53 if (!check_glx_version())
56 // TODO: These attribs (especially the sizes) should be passed in by the caller!
59 int *pAttribs = fbAttribs;
61 *pAttribs++ = GLX_RENDER_TYPE; *pAttribs++ = GLX_RGBA_BIT;
62 *pAttribs++ = GLX_X_RENDERABLE; *pAttribs++ = True;
63 *pAttribs++ = GLX_DRAWABLE_TYPE; *pAttribs++ = GLX_WINDOW_BIT;
64 *pAttribs++ = GLX_DOUBLEBUFFER; *pAttribs++ = True;
65 *pAttribs++ = GLX_RED_SIZE; *pAttribs++ = 8;
66 *pAttribs++ = GLX_BLUE_SIZE; *pAttribs++ = 8;
67 *pAttribs++ = GLX_GREEN_SIZE; *pAttribs++ = 8;
68 *pAttribs++ = GLX_ALPHA_SIZE; *pAttribs++ = 8;
69 *pAttribs++ = GLX_DEPTH_SIZE; *pAttribs++ = 24;
70 *pAttribs++ = GLX_STENCIL_SIZE; *pAttribs++ = 8;
74 *pAttribs++ = GLX_SAMPLE_BUFFERS; *pAttribs++ = 1;
75 *pAttribs++ = GLX_SAMPLES; *pAttribs++ = samples;
80 // Tell X we are going to use the display
81 m_dpy = XOpenDisplay(NULL);
84 console::error("%s: XOpenDisplay() failed!\n", VOGL_METHOD_NAME);
88 // Get a new fb config that meets our attrib requirements
90 m_pFB_configs = GL_ENTRYPOINT(glXChooseFBConfig)(m_dpy, DefaultScreen(m_dpy), fbAttribs, &m_num_fb_configs);
91 XVisualInfo *pVisual_info = GL_ENTRYPOINT(glXGetVisualFromFBConfig)(m_dpy, m_pFB_configs[0]);
93 // Now create an X window
94 XSetWindowAttributes winAttribs;
95 winAttribs.event_mask = ExposureMask | VisibilityChangeMask |
96 KeyPressMask | PointerMotionMask |
99 winAttribs.border_pixel = 0;
100 winAttribs.bit_gravity = StaticGravity;
101 winAttribs.colormap = XCreateColormap(m_dpy,
102 RootWindow(m_dpy, pVisual_info->screen),
103 pVisual_info->visual, AllocNone);
104 GLint winmask = CWBorderPixel | CWBitGravity | CWEventMask | CWColormap;
106 m_win = XCreateWindow(m_dpy, DefaultRootWindow(m_dpy), 20, 20,
108 pVisual_info->depth, InputOutput,
109 pVisual_info->visual, winmask, &winAttribs);
111 const char *pWindow_name = (sizeof(void *) == sizeof(uint32)) ? "voglreplay 32-bit" : "voglreplay 64-bit";
112 XStoreName(m_dpy, m_win, pWindow_name);
113 XSetIconName(m_dpy, m_win, pWindow_name);
116 utils::zero_object(sh);
117 sh.x = 0; // slam position up so when/if we resize the window glReadPixels still works as expected (this may be a bug in the NV driver, I dunno yet)
119 sh.width = sh.min_width = sh.max_width = sh.base_width = width;
120 sh.height = sh.min_height = sh.max_height = sh.base_height = height;
121 sh.flags = PSize | PMinSize | PMaxSize | PBaseSize | PPosition;
122 XSetWMNormalHints(m_dpy, m_win, &sh);
124 XResizeWindow(m_dpy, m_win, width, height);
126 XMapWindow(m_dpy, m_win);
133 uint actual_width = 0, actual_height = 0;
134 vogl_replay_window::get_actual_dimensions(actual_width, actual_height);
135 vogl_debug_printf("%s: Created window, requested dimensions %ux%u, actual dimensions %ux%u\n", VOGL_METHOD_NAME, m_width, m_height, actual_width, actual_height);
140 void vogl_replay_window::set_title(const char *pTitle)
146 XStoreName(m_dpy, m_win, pTitle);
150 bool vogl_replay_window::resize(int new_width, int new_height)
155 return open(new_width, new_height);
157 if ((new_width == m_width) && (new_height == m_height))
161 utils::zero_object(sh);
162 sh.width = sh.min_width = sh.max_width = sh.base_width = new_width;
163 sh.height = sh.min_height = sh.max_height = sh.base_height = new_height;
164 sh.flags = PSize | PMinSize | PMaxSize | PBaseSize;
165 XSetWMNormalHints(m_dpy, m_win, &sh);
166 //XMapWindow(dpy, win);
168 int status = XResizeWindow(m_dpy, m_win, new_width, new_height);
169 VOGL_ASSERT(status == True);
170 VOGL_NOTE_UNUSED(status);
173 m_height = new_height;
180 void vogl_replay_window::clear_window()
187 XFillRectangle(m_dpy, m_win, DefaultGC(m_dpy, DefaultScreen(m_dpy)), 0, 0, m_width, m_height);
190 void vogl_replay_window::close()
196 XDestroyWindow(m_dpy, m_win);
197 m_win = (Window)NULL;
202 XCloseDisplay(m_dpy);
210 void vogl_replay_window::update_dimensions()
214 //XWindowAttributes winData;
215 //XGetWindowAttributes(m_dpy, m_win, &winData);
217 //m_width = winData.width;
218 //m_height = winData.height;
220 get_actual_dimensions(w, h);
225 bool vogl_replay_window::get_actual_dimensions(uint &width, uint &height) const
231 unsigned int border_width, depth;
232 return (XGetGeometry(m_dpy, m_win, &root, &x, &y, &width, &height, &border_width, &depth) != False);
235 bool vogl_replay_window::check_glx_version()
240 VOGL_NOTE_UNUSED(nMajorVer);
242 VOGL_NOTE_UNUSED(nMinorVer);
244 if ((!GL_ENTRYPOINT(glXQueryVersion)) || (!GL_ENTRYPOINT(glXChooseFBConfig)) || (!GL_ENTRYPOINT(glXGetVisualFromFBConfig)))
246 vogl_debug_printf("Failed checking GLX version!\n");
251 // This always returns 0, don't know why yet.
252 ACTUAL_GL_ENTRYPOINT(glXQueryVersion)(m_dpy, &nMajorVer, &nMinorVer);
254 vogl_debug_printf("Supported GLX version - %d.%d\n", nMajorVer, nMinorVer);
256 if (nMajorVer == 1 && nMinorVer < 2)
258 vogl_error_printf("GLX 1.2 or greater is necessary\n");
259 XCloseDisplay(m_dpy);