/[pcsx2_0.9.7]/trunk/plugins/zzogl-pg/opengl/GLWinX11.cpp
ViewVC logotype

Contents of /trunk/plugins/zzogl-pg/opengl/GLWinX11.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 280 - (show annotations) (download)
Thu Dec 23 12:02:12 2010 UTC (9 years, 2 months ago) by william
File size: 10567 byte(s)
re-commit (had local access denied errors when committing)
1 /* ZZ Open GL graphics plugin
2 * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com
3 * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
18 */
19
20 #include "Util.h"
21 #include "GLWin.h"
22
23 #ifdef GL_X11_WINDOW
24
25 #include <X11/Xlib.h>
26 #include <stdlib.h>
27
28 bool GLWindow::CreateWindow(void *pDisplay)
29 {
30 // init support of multi thread
31 if (!XInitThreads())
32 ZZLog::Error_Log("Failed to init the xlib concurent threads");
33
34 glDisplay = XOpenDisplay(0);
35 glScreen = DefaultScreen(glDisplay);
36
37 if (pDisplay == NULL)
38 {
39 ZZLog::Error_Log("Failed to create window. Exiting...");
40 return false;
41 }
42
43 *(Display**)pDisplay = glDisplay;
44
45 return true;
46 }
47
48 bool GLWindow::ReleaseContext()
49 {
50 bool status = true;
51 if (!glDisplay) return status;
52
53 // free the context
54 if (context)
55 {
56 if (!glXMakeCurrent(glDisplay, None, NULL)) {
57 ZZLog::Error_Log("Could not release drawing context.");
58 status = false;
59 }
60
61 glXDestroyContext(glDisplay, context);
62 context = NULL;
63 }
64
65 // free the visual
66 if (vi) {
67 XFree(vi);
68 vi = NULL;
69 }
70
71 return status;
72 }
73
74 void GLWindow::CloseWindow()
75 {
76 SaveConfig();
77 if (!glDisplay) return;
78
79 XCloseDisplay(glDisplay);
80 glDisplay = NULL;
81 }
82
83 bool GLWindow::CreateVisual()
84 {
85 // attributes for a single buffered visual in RGBA format with at least
86 // 8 bits per color and a 24 bit depth buffer
87 int attrListSgl[] = {GLX_RGBA, GLX_RED_SIZE, 8,
88 GLX_GREEN_SIZE, 8,
89 GLX_BLUE_SIZE, 8,
90 GLX_DEPTH_SIZE, 24,
91 None
92 };
93
94 // attributes for a double buffered visual in RGBA format with at least
95 // 8 bits per color and a 24 bit depth buffer
96 int attrListDbl[] = { GLX_RGBA, GLX_DOUBLEBUFFER,
97 GLX_RED_SIZE, 8,
98 GLX_GREEN_SIZE, 8,
99 GLX_BLUE_SIZE, 8,
100 GLX_DEPTH_SIZE, 24,
101 None
102 };
103
104 /* get an appropriate visual */
105 vi = glXChooseVisual(glDisplay, glScreen, attrListDbl);
106
107 if (vi == NULL)
108 {
109 vi = glXChooseVisual(glDisplay, glScreen, attrListSgl);
110 doubleBuffered = false;
111 ZZLog::Error_Log("Only Singlebuffered Visual!");
112 }
113 else
114 {
115 doubleBuffered = true;
116 ZZLog::Error_Log("Got Doublebuffered Visual!");
117 }
118
119 if (vi == NULL)
120 {
121 ZZLog::Error_Log("Failed to get buffered Visual!");
122 return false;
123 }
124 return true;
125 }
126
127 void GLWindow::GetWindowSize()
128 {
129 if (!glDisplay or !glWindow) return;
130
131 unsigned int borderDummy;
132 Window winDummy;
133 s32 xDummy;
134 s32 yDummy;
135
136 XLockDisplay(glDisplay);
137 XGetGeometry(glDisplay, glWindow, &winDummy, &xDummy, &yDummy, &width, &height, &borderDummy, &depth);
138 XUnlockDisplay(glDisplay);
139
140 // update the gl buffer size
141 UpdateWindowSize(width, height);
142
143 ZZLog::Dev_Log("Resolution %dx%d. Depth %d bpp. Position (%d,%d)", width, height, depth, conf.x, conf.y);
144 }
145
146 void GLWindow::GetGLXVersion()
147 {
148 int glxMajorVersion, glxMinorVersion;
149
150 glXQueryVersion(glDisplay, &glxMajorVersion, &glxMinorVersion);
151
152 ZZLog::Error_Log("glX-Version %d.%d", glxMajorVersion, glxMinorVersion);
153 }
154
155 void GLWindow::UpdateGrabKey()
156 {
157 // Do not stole the key in debug mode. It is not breakpoint friendly...
158 #ifndef _DEBUG
159 XLockDisplay(glDisplay);
160 if (fullScreen) {
161 XGrabPointer(glDisplay, glWindow, True, ButtonPressMask, GrabModeAsync, GrabModeAsync, glWindow, None, CurrentTime);
162 XGrabKeyboard(glDisplay, glWindow, True, GrabModeAsync, GrabModeAsync, CurrentTime);
163 } else {
164 XUngrabPointer(glDisplay, CurrentTime);
165 XUngrabKeyboard(glDisplay, CurrentTime);
166 }
167 XUnlockDisplay(glDisplay);
168 #endif
169 }
170
171 void GLWindow::Force43Ratio()
172 {
173 // avoid black border in fullscreen
174 if (fullScreen && conf.isWideScreen) {
175 conf.width = width;
176 conf.height = height;
177 }
178
179 if(!fullScreen && !conf.isWideScreen) {
180 // Compute the width based on height
181 s32 new_width = (4*height)/3;
182 // do not bother to resize for 5 pixels. Avoid a loop
183 // due to round value
184 if ( abs(new_width - width) > 5) {
185 width = new_width;
186 conf.width = new_width;
187 // resize the window
188 XLockDisplay(glDisplay);
189 XResizeWindow(glDisplay, glWindow, new_width, height);
190 XSync(glDisplay, False);
191 XUnlockDisplay(glDisplay);
192 }
193 }
194 }
195
196 #define _NET_WM_STATE_REMOVE 0
197 #define _NET_WM_STATE_ADD 1
198 #define _NET_WM_STATE_TOGGLE 2
199
200 void GLWindow::ToggleFullscreen()
201 {
202 if (!glDisplay or !glWindow) return;
203
204 Force43Ratio();
205
206 u32 mask = SubstructureRedirectMask | SubstructureNotifyMask;
207 // Setup a new event structure
208 XClientMessageEvent cme;
209 cme.type = ClientMessage;
210 cme.send_event = True;
211 cme.display = glDisplay;
212 cme.window = glWindow;
213 cme.message_type = XInternAtom(glDisplay, "_NET_WM_STATE", False);
214 cme.format = 32;
215 // Note: can not use _NET_WM_STATE_TOGGLE because the WM can change the fullscreen state
216 // and screw up the fullscreen variable... The test on fulscreen restore a sane configuration
217 cme.data.l[0] = fullScreen ? _NET_WM_STATE_REMOVE : _NET_WM_STATE_ADD;
218 cme.data.l[1] = (u32)XInternAtom(glDisplay, "_NET_WM_STATE_FULLSCREEN", False);
219 cme.data.l[2] = 0;
220 cme.data.l[3] = 0;
221
222 // send the event
223 XLockDisplay(glDisplay);
224 if (!XSendEvent(glDisplay, RootWindow(glDisplay, vi->screen), False, mask, (XEvent*)(&cme)))
225 ZZLog::Error_Log("Failed to send event: toggle fullscreen");
226 else {
227 fullScreen = (!fullScreen);
228 conf.setFullscreen(fullScreen);
229 }
230 XUnlockDisplay(glDisplay);
231
232 // Apply the change
233 XSync(glDisplay, false);
234
235 // Wait a little that the VM does his joes. Actually the best is to check some WM event
236 // but it not sure it will appear so a time out is necessary.
237 usleep(100*1000); // 100 us should be far enough for old computer and unnoticeable for users
238
239 // update info structure
240 GetWindowSize();
241
242 UpdateGrabKey();
243
244 // avoid black border in widescreen fullscreen
245 if (fullScreen && conf.isWideScreen) {
246 conf.width = width;
247 conf.height = height;
248 }
249
250 // Hide the cursor in the right bottom corner
251 if(fullScreen)
252 XWarpPointer(glDisplay, None, glWindow, 0, 0, 0, 0, 2*width, 2*height);
253
254 }
255
256 bool GLWindow::DisplayWindow(int _width, int _height)
257 {
258 backbuffer.w = _width;
259 backbuffer.h = _height;
260
261 if (!CreateVisual()) return false;
262
263 /* create a GLX context */
264 context = glXCreateContext(glDisplay, vi, NULL, GL_TRUE);
265
266 /* create a color map */
267 attr.colormap = XCreateColormap(glDisplay, RootWindow(glDisplay, vi->screen),
268 vi->visual, AllocNone);
269 attr.border_pixel = 0;
270 attr.event_mask = ExposureMask | KeyPressMask | KeyReleaseMask | ButtonPressMask |
271 StructureNotifyMask | SubstructureRedirectMask | SubstructureNotifyMask |
272 EnterWindowMask | LeaveWindowMask | FocusChangeMask ;
273
274 GetGLXVersion();
275
276 // Create a window at the last position/size
277 glWindow = XCreateWindow(glDisplay, RootWindow(glDisplay, vi->screen),
278 conf.x , conf.y , _width, _height, 0, vi->depth, InputOutput, vi->visual,
279 CWBorderPixel | CWColormap | CWEventMask,
280 &attr);
281
282 /* Allow to kill properly the window */
283 Atom wmDelete = XInternAtom(glDisplay, "WM_DELETE_WINDOW", True);
284 XSetWMProtocols(glDisplay, glWindow, &wmDelete, 1);
285
286 // Set icon name
287 XSetIconName(glDisplay, glWindow, "ZZogl-pg");
288
289 // Draw the window
290 XMapRaised(glDisplay, glWindow);
291 XSync(glDisplay, false);
292
293 // connect the glx-context to the window
294 glXMakeCurrent(glDisplay, glWindow, context);
295
296 if (glXIsDirect(glDisplay, context))
297 ZZLog::Error_Log("You have Direct Rendering!");
298 else
299 ZZLog::Error_Log("No Direct Rendering possible!");
300
301 // Always start in window mode
302 fullScreen = 0;
303 GetWindowSize();
304
305 return true;
306 }
307
308 void GLWindow::SwapGLBuffers()
309 {
310 if (glGetError() != GL_NO_ERROR) ZZLog::Debug_Log("glError before swap!");
311 glXSwapBuffers(glDisplay, glWindow);
312 }
313
314 void GLWindow::SetTitle(char *strtitle)
315 {
316 if (!glDisplay or !glWindow) return;
317 if (fullScreen) return;
318
319 XTextProperty prop;
320 memset(&prop, 0, sizeof(prop));
321
322 char* ptitle = strtitle;
323 if (XStringListToTextProperty(&ptitle, 1, &prop)) {
324 XLockDisplay(glDisplay);
325 XSetWMName(glDisplay, glWindow, &prop);
326 XUnlockDisplay(glDisplay);
327 }
328
329 XFree(prop.value);
330 }
331
332 void GLWindow::ResizeCheck()
333 {
334 XEvent event;
335 if (!glDisplay or !glWindow) return;
336
337 XLockDisplay(glDisplay);
338 while (XCheckTypedWindowEvent(glDisplay, glWindow, ConfigureNotify, &event))
339 {
340 if ((event.xconfigure.width != width) || (event.xconfigure.height != height))
341 {
342 width = event.xconfigure.width;
343 height = event.xconfigure.height;
344 Force43Ratio();
345 UpdateWindowSize(width, height);
346 }
347
348 if (!fullScreen) {
349 if ((event.xconfigure.x != conf.x) || (event.xconfigure.y != conf.y))
350 {
351 // Fixme; x&y occassionally gives values near the top left corner rather then the real values,
352 // causing the window to change positions when adjusting ZZOgl's settings.
353 conf.x = event.xconfigure.x;
354 conf.y = event.xconfigure.y;
355 }
356 }
357 }
358 XUnlockDisplay(glDisplay);
359 }
360
361 u32 THR_KeyEvent = 0; // Value for key event processing between threads
362 bool THR_bShift = false;
363
364 void GLWindow::ProcessEvents()
365 {
366 FUNCLOG
367
368 // check resizing
369 ResizeCheck();
370
371 if (THR_KeyEvent) // This value was passed from GSKeyEvents which could be in another thread
372 {
373 int my_KeyEvent = THR_KeyEvent;
374 bool my_bShift = THR_bShift;
375 THR_KeyEvent = 0;
376
377 switch (my_KeyEvent)
378 {
379 case XK_F5:
380 case XK_F6:
381 case XK_F7:
382 case XK_F9:
383 OnFKey(my_KeyEvent - XK_F1 + 1, my_bShift);
384 break;
385 }
386 }
387 }
388
389 #endif

  ViewVC Help
Powered by ViewVC 1.1.22