]> git.cworth.org Git - vogl/blob - src/voglcommon/vogl_replay_window.cpp
- Adding "-msaa X" command line option to voglreplay tool. We don't fully support...
[vogl] / src / voglcommon / vogl_replay_window.cpp
1 /**************************************************************************
2  *
3  * Copyright 2013-2014 RAD Game Tools and Valve Software
4  * All Rights Reserved.
5  *
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:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
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
22  * THE SOFTWARE.
23  *
24  **************************************************************************/
25
26 // File: vogl_replay_window.cpp
27 #include "vogl_replay_window.h"
28
29 vogl_replay_window::vogl_replay_window()
30     : m_dpy(NULL),
31       m_win((Window)NULL),
32       m_width(0),
33       m_height(0),
34       m_pFB_configs(NULL),
35       m_num_fb_configs(0)
36 {
37     VOGL_FUNC_TRACER
38 }
39
40 vogl_replay_window::~vogl_replay_window()
41 {
42     VOGL_FUNC_TRACER
43
44     close();
45 }
46
47 bool vogl_replay_window::open(int width, int height, int samples)
48 {
49     VOGL_FUNC_TRACER
50
51     close();
52
53     if (!check_glx_version())
54         return false;
55
56     // TODO: These attribs (especially the sizes) should be passed in by the caller!
57     int fbAttribs[64];
58
59     int *pAttribs = fbAttribs;
60
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;
71
72     if (samples > 1)
73     {
74         *pAttribs++ = GLX_SAMPLE_BUFFERS; *pAttribs++ = 1;
75         *pAttribs++ = GLX_SAMPLES;        *pAttribs++ = samples;
76     }
77
78     *pAttribs++ = 0;
79
80     // Tell X we are going to use the display
81     m_dpy = XOpenDisplay(NULL);
82     if (!m_dpy)
83     {
84         console::error("%s: XOpenDisplay() failed!\n", VOGL_METHOD_NAME);
85         return false;
86     }
87
88     // Get a new fb config that meets our attrib requirements
89
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]);
92
93     // Now create an X window
94     XSetWindowAttributes winAttribs;
95     winAttribs.event_mask = ExposureMask | VisibilityChangeMask |
96                             KeyPressMask | PointerMotionMask |
97                             StructureNotifyMask;
98
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;
105
106     m_win = XCreateWindow(m_dpy, DefaultRootWindow(m_dpy), 20, 20,
107                           width, height, 0,
108                           pVisual_info->depth, InputOutput,
109                           pVisual_info->visual, winmask, &winAttribs);
110
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);
114
115     XSizeHints sh;
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)
118     sh.y = 0;
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);
123
124     XResizeWindow(m_dpy, m_win, width, height);
125
126     XMapWindow(m_dpy, m_win);
127
128     //glXWaitX();
129
130     m_width = width;
131     m_height = height;
132
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);
136
137     return true;
138 }
139
140 void vogl_replay_window::set_title(const char *pTitle)
141 {
142     VOGL_FUNC_TRACER
143
144     if (m_win)
145     {
146         XStoreName(m_dpy, m_win, pTitle);
147     }
148 }
149
150 bool vogl_replay_window::resize(int new_width, int new_height)
151 {
152     VOGL_FUNC_TRACER
153
154     if (!is_opened())
155         return open(new_width, new_height);
156
157     if ((new_width == m_width) && (new_height == m_height))
158         return true;
159
160     XSizeHints sh;
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);
167
168     int status = XResizeWindow(m_dpy, m_win, new_width, new_height);
169     VOGL_ASSERT(status == True);
170     VOGL_NOTE_UNUSED(status);
171
172     m_width = new_width;
173     m_height = new_height;
174
175     //glXWaitX();
176
177     return true;
178 }
179
180 void vogl_replay_window::clear_window()
181 {
182     VOGL_FUNC_TRACER
183
184     if (!m_dpy)
185         return;
186
187     XFillRectangle(m_dpy, m_win, DefaultGC(m_dpy, DefaultScreen(m_dpy)), 0, 0, m_width, m_height);
188 }
189
190 void vogl_replay_window::close()
191 {
192     VOGL_FUNC_TRACER
193
194     if (m_win)
195     {
196         XDestroyWindow(m_dpy, m_win);
197         m_win = (Window)NULL;
198     }
199
200     if (m_dpy)
201     {
202         XCloseDisplay(m_dpy);
203         m_dpy = NULL;
204     }
205
206     m_width = 0;
207     m_height = 0;
208 }
209
210 void vogl_replay_window::update_dimensions()
211 {
212     VOGL_FUNC_TRACER
213
214     //XWindowAttributes winData;
215     //XGetWindowAttributes(m_dpy, m_win, &winData);
216
217     //m_width = winData.width;
218     //m_height = winData.height;
219     uint w, h;
220     get_actual_dimensions(w, h);
221     m_width = w;
222     m_height = h;
223 }
224
225 bool vogl_replay_window::get_actual_dimensions(uint &width, uint &height) const
226 {
227     VOGL_FUNC_TRACER
228
229     Window root;
230     int x, y;
231     unsigned int border_width, depth;
232     return (XGetGeometry(m_dpy, m_win, &root, &x, &y, &width, &height, &border_width, &depth) != False);
233 }
234
235 bool vogl_replay_window::check_glx_version()
236 {
237     VOGL_FUNC_TRACER
238
239     GLint nMajorVer = 0;
240     VOGL_NOTE_UNUSED(nMajorVer);
241     GLint nMinorVer = 0;
242     VOGL_NOTE_UNUSED(nMinorVer);
243
244     if ((!GL_ENTRYPOINT(glXQueryVersion)) || (!GL_ENTRYPOINT(glXChooseFBConfig)) || (!GL_ENTRYPOINT(glXGetVisualFromFBConfig)))
245     {
246         vogl_debug_printf("Failed checking GLX version!\n");
247         return false;
248     }
249
250 #if 0
251         // This always returns 0, don't know why yet.
252         ACTUAL_GL_ENTRYPOINT(glXQueryVersion)(m_dpy, &nMajorVer, &nMinorVer);
253
254         vogl_debug_printf("Supported GLX version - %d.%d\n", nMajorVer, nMinorVer);
255
256         if (nMajorVer == 1 && nMinorVer < 2)
257         {
258                 vogl_error_printf("GLX 1.2 or greater is necessary\n");
259                 XCloseDisplay(m_dpy);
260                 return false;
261         }
262 #endif
263
264     return true;
265 }