Mercurial > sdl-ios-xcode
annotate src/video/x11/SDL_x11yuv.c @ 563:04dcaf3da918
Massive Quartz input enhancements from Darrell Walisser. His email:
Enclosed is a patch that addresses the following:
--Various minor cleanups.
Removed dead/obsolete code, made some style cleanups
--Mouse Events
Now keep track of what button(s) were pressed so we know when to send
the mouse up event. This fixes the case where the mouse is dragged
outside of the game window and released (in which case we want to send
the mouse up event even though the mouse is outside the game window).
--Input Grabbing
Here is my take on the grabbing situation, which is the basis for the
new implementation.
There are 3 grab states, ungrabbed (UG), visible (VG), and invisible
(IG). Both VG and IG keep the mouse constrained to the window and
produce relative motion events. In VG the cursor is visible (duh), in
IG it is not. In VG, absolute motion events also work.
There are 6 actions that can affect grabbing:
1. Set Fullscreen/Window (F/W). In fullscreen, a visible grab should do
nothing. However, a fullscreen visible grab can be treated just like a
windowed visible grab, which is what I have done to help simplify
things.
2. Cursor hide/show (H/S). If the cursor is hidden when grabbing, the
grab is an invisible grab. If the cursor is visible, the grab should
just constrain the mouse to the window.
3. Input grab/ungrab(G/U). If grabbed, the cursor should be confined to
the window as should the keyboard input. On Mac OS X, the keyboard
input is implicitly grabbed by confining the cursor, except for
command-tab which can switch away from the application. Should the
window come to the foreground if the application is deactivated and
grab input is called? This isn't necessary in this implementation
because the grab state will be asserted upon activation.
Using my notation, these are all the cases that need to be handled
(state + action = new state).
UG+U = UG
UG+G = VG or IG, if cursor is visible or not
UG+H = UG
UG+S = UG
VG+U = UG
VG+G = VG
VG+H = IG
VG+S = VG
IG+U = UG
IG+G = IG
IG+H = IG
IG+S = VG
The cases that result in the same state can be ignored in the code,
which cuts it down to just 5 cases.
Another issue is what happens when the app loses/gains input focus from
deactivate/activate or iconify/deiconify. I think that if input focus
is ever lost (outside of SDL's control), the grab state should be
suspended and the cursor should become visible and active again. When
regained, the cursor should reappear in its original location and/or
grab state. This way, when reactivating the cursor is still in the same
position as before so apps shouldn't get confused when the next motion
event comes in. This is what I've done in this patch.
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Fri, 27 Dec 2002 20:52:41 +0000 |
parents | 95aa4041e7f9 |
children | e3d0517bf67e |
rev | line source |
---|---|
0 | 1 /* |
2 SDL - Simple DirectMedia Layer | |
297
f6ffac90895c
Updated copyright information for 2002
Sam Lantinga <slouken@libsdl.org>
parents:
292
diff
changeset
|
3 Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga |
0 | 4 |
5 This library is free software; you can redistribute it and/or | |
6 modify it under the terms of the GNU Library General Public | |
7 License as published by the Free Software Foundation; either | |
8 version 2 of the License, or (at your option) any later version. | |
9 | |
10 This library 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 GNU | |
13 Library General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU Library General Public | |
16 License along with this library; if not, write to the Free | |
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 | |
19 Sam Lantinga | |
252
e8157fcb3114
Updated the source with the correct e-mail address
Sam Lantinga <slouken@libsdl.org>
parents:
182
diff
changeset
|
20 slouken@libsdl.org |
0 | 21 */ |
22 | |
23 #ifdef SAVE_RCSID | |
24 static char rcsid = | |
25 "@(#) $Id$"; | |
26 #endif | |
27 | |
28 /* This is the XFree86 Xv extension implementation of YUV video overlays */ | |
29 | |
30 #ifdef XFREE86_XV | |
31 | |
32 #include <stdlib.h> | |
33 #include <string.h> | |
34 #include <X11/Xlib.h> | |
35 #include <sys/ipc.h> | |
36 #include <sys/shm.h> | |
37 #include <X11/extensions/XShm.h> | |
292
eadc0746dfaf
Added SDL_LockRect() and SDL_UnlockRect()
Sam Lantinga <slouken@libsdl.org>
parents:
252
diff
changeset
|
38 #include <XFree86/extensions/Xvlib.h> |
0 | 39 |
40 #include "SDL_error.h" | |
41 #include "SDL_video.h" | |
42 #include "SDL_x11yuv_c.h" | |
43 #include "SDL_yuvfuncs.h" | |
44 | |
45 #define XFREE86_REFRESH_HACK | |
46 #ifdef XFREE86_REFRESH_HACK | |
47 #include "SDL_x11image_c.h" | |
48 #endif | |
49 | |
50 /* Workaround when pitch != width */ | |
51 #define PITCH_WORKAROUND | |
52 | |
182
d4ebd1bbea9a
Fix XVideo on GeForce by using last available adaptor
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
53 /* Fix for the NVidia GeForce 2 - use the last available adaptor */ |
341
6ca967a46bf1
*** empty log message ***
Sam Lantinga <slouken@libsdl.org>
parents:
297
diff
changeset
|
54 /*#define USE_LAST_ADAPTOR*/ /* Apparently the NVidia drivers are fixed */ |
182
d4ebd1bbea9a
Fix XVideo on GeForce by using last available adaptor
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
55 |
0 | 56 /* The functions used to manipulate software video overlays */ |
57 static struct private_yuvhwfuncs x11_yuvfuncs = { | |
58 X11_LockYUVOverlay, | |
59 X11_UnlockYUVOverlay, | |
60 X11_DisplayYUVOverlay, | |
61 X11_FreeYUVOverlay | |
62 }; | |
63 | |
64 struct private_yuvhwdata { | |
65 int port; | |
66 XShmSegmentInfo yuvshm; | |
292
eadc0746dfaf
Added SDL_LockRect() and SDL_UnlockRect()
Sam Lantinga <slouken@libsdl.org>
parents:
252
diff
changeset
|
67 SDL_NAME(XvImage) *image; |
0 | 68 }; |
69 | |
70 | |
71 SDL_Overlay *X11_CreateYUVOverlay(_THIS, int width, int height, Uint32 format, SDL_Surface *display) | |
72 { | |
73 SDL_Overlay *overlay; | |
74 struct private_yuvhwdata *hwdata; | |
75 int xv_port; | |
76 int i, j, k; | |
77 int adaptors; | |
292
eadc0746dfaf
Added SDL_LockRect() and SDL_UnlockRect()
Sam Lantinga <slouken@libsdl.org>
parents:
252
diff
changeset
|
78 SDL_NAME(XvAdaptorInfo) *ainfo; |
0 | 79 XShmSegmentInfo *yuvshm; |
80 | |
81 /* Look for the XVideo extension with a valid port for this format */ | |
82 xv_port = -1; | |
292
eadc0746dfaf
Added SDL_LockRect() and SDL_UnlockRect()
Sam Lantinga <slouken@libsdl.org>
parents:
252
diff
changeset
|
83 if ( (Success == SDL_NAME(XvQueryExtension)(GFX_Display, &j, &j, &j, &j, &j)) && |
eadc0746dfaf
Added SDL_LockRect() and SDL_UnlockRect()
Sam Lantinga <slouken@libsdl.org>
parents:
252
diff
changeset
|
84 (Success == SDL_NAME(XvQueryAdaptors)(GFX_Display, |
0 | 85 RootWindow(GFX_Display, SDL_Screen), |
86 &adaptors, &ainfo)) ) { | |
182
d4ebd1bbea9a
Fix XVideo on GeForce by using last available adaptor
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
87 #ifdef USE_LAST_ADAPTOR |
d4ebd1bbea9a
Fix XVideo on GeForce by using last available adaptor
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
88 for ( i=0; i < adaptors; ++i ) { |
d4ebd1bbea9a
Fix XVideo on GeForce by using last available adaptor
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
89 #else |
0 | 90 for ( i=0; (i < adaptors) && (xv_port == -1); ++i ) { |
182
d4ebd1bbea9a
Fix XVideo on GeForce by using last available adaptor
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
91 #endif /* USE_LAST_ADAPTOR */ |
0 | 92 /* Check to see if the visual can be used */ |
93 if ( BUGGY_XFREE86(<=, 4001) ) { | |
94 int visual_ok = 0; | |
95 for ( j=0; j<ainfo[i].num_formats; ++j ) { | |
96 if ( ainfo[i].formats[j].visual_id == | |
97 SDL_Visual->visualid ) { | |
98 visual_ok = 1; | |
99 break; | |
100 } | |
101 } | |
102 if ( ! visual_ok ) { | |
103 continue; | |
104 } | |
105 } | |
106 if ( (ainfo[i].type & XvInputMask) && | |
107 (ainfo[i].type & XvImageMask) ) { | |
108 int num_formats; | |
292
eadc0746dfaf
Added SDL_LockRect() and SDL_UnlockRect()
Sam Lantinga <slouken@libsdl.org>
parents:
252
diff
changeset
|
109 SDL_NAME(XvImageFormatValues) *formats; |
eadc0746dfaf
Added SDL_LockRect() and SDL_UnlockRect()
Sam Lantinga <slouken@libsdl.org>
parents:
252
diff
changeset
|
110 formats = SDL_NAME(XvListImageFormats)(GFX_Display, |
0 | 111 ainfo[i].base_id, &num_formats); |
182
d4ebd1bbea9a
Fix XVideo on GeForce by using last available adaptor
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
112 #ifdef USE_LAST_ADAPTOR |
d4ebd1bbea9a
Fix XVideo on GeForce by using last available adaptor
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
113 for ( j=0; j < num_formats; ++j ) { |
d4ebd1bbea9a
Fix XVideo on GeForce by using last available adaptor
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
114 #else |
0 | 115 for ( j=0; (j < num_formats) && (xv_port == -1); ++j ) { |
182
d4ebd1bbea9a
Fix XVideo on GeForce by using last available adaptor
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
116 #endif /* USE_LAST_ADAPTOR */ |
0 | 117 if ( (Uint32)formats[j].id == format ) { |
118 for ( k=0; k < ainfo[i].num_ports; ++k ) { | |
292
eadc0746dfaf
Added SDL_LockRect() and SDL_UnlockRect()
Sam Lantinga <slouken@libsdl.org>
parents:
252
diff
changeset
|
119 if ( Success == SDL_NAME(XvGrabPort)(GFX_Display, ainfo[i].base_id+k, CurrentTime) ) { |
0 | 120 xv_port = ainfo[i].base_id+k; |
121 break; | |
122 } | |
123 } | |
124 } | |
125 } | |
410
365f57b7c4ac
*** empty log message ***
Sam Lantinga <slouken@libsdl.org>
parents:
409
diff
changeset
|
126 if ( formats ) { |
365f57b7c4ac
*** empty log message ***
Sam Lantinga <slouken@libsdl.org>
parents:
409
diff
changeset
|
127 XFree(formats); |
365f57b7c4ac
*** empty log message ***
Sam Lantinga <slouken@libsdl.org>
parents:
409
diff
changeset
|
128 } |
0 | 129 } |
130 } | |
409
1c3cf7231cd4
Fixed memory leaks in YUV code
Sam Lantinga <slouken@libsdl.org>
parents:
341
diff
changeset
|
131 SDL_NAME(XvFreeAdaptorInfo)(ainfo); |
0 | 132 } |
429
c1666427297c
Memory leak fixes by Bill May.
Ryan C. Gordon <icculus@icculus.org>
parents:
410
diff
changeset
|
133 |
434
ed58b98c0d9d
Commented double-free buggy code. Will examine more closely later.
Ryan C. Gordon <icculus@icculus.org>
parents:
429
diff
changeset
|
134 #if 0 |
429
c1666427297c
Memory leak fixes by Bill May.
Ryan C. Gordon <icculus@icculus.org>
parents:
410
diff
changeset
|
135 /* |
c1666427297c
Memory leak fixes by Bill May.
Ryan C. Gordon <icculus@icculus.org>
parents:
410
diff
changeset
|
136 * !!! FIXME: |
c1666427297c
Memory leak fixes by Bill May.
Ryan C. Gordon <icculus@icculus.org>
parents:
410
diff
changeset
|
137 * "Here are some diffs for X11 and yuv. Note that the last part 2nd |
c1666427297c
Memory leak fixes by Bill May.
Ryan C. Gordon <icculus@icculus.org>
parents:
410
diff
changeset
|
138 * diff should probably be a new call to XvQueryAdaptorFree with ainfo |
c1666427297c
Memory leak fixes by Bill May.
Ryan C. Gordon <icculus@icculus.org>
parents:
410
diff
changeset
|
139 * and the number of adaptors, instead of the loop through like I did." |
434
ed58b98c0d9d
Commented double-free buggy code. Will examine more closely later.
Ryan C. Gordon <icculus@icculus.org>
parents:
429
diff
changeset
|
140 * |
ed58b98c0d9d
Commented double-free buggy code. Will examine more closely later.
Ryan C. Gordon <icculus@icculus.org>
parents:
429
diff
changeset
|
141 * ACHTUNG: This is broken! It looks like XvFreeAdaptorInfo does this |
ed58b98c0d9d
Commented double-free buggy code. Will examine more closely later.
Ryan C. Gordon <icculus@icculus.org>
parents:
429
diff
changeset
|
142 * for you, so we end up with a double-free. I need to look at this |
ed58b98c0d9d
Commented double-free buggy code. Will examine more closely later.
Ryan C. Gordon <icculus@icculus.org>
parents:
429
diff
changeset
|
143 * more closely... --ryan. |
429
c1666427297c
Memory leak fixes by Bill May.
Ryan C. Gordon <icculus@icculus.org>
parents:
410
diff
changeset
|
144 */ |
c1666427297c
Memory leak fixes by Bill May.
Ryan C. Gordon <icculus@icculus.org>
parents:
410
diff
changeset
|
145 for ( i=0; i < adaptors; ++i ) { |
c1666427297c
Memory leak fixes by Bill May.
Ryan C. Gordon <icculus@icculus.org>
parents:
410
diff
changeset
|
146 if (ainfo[i].name != NULL) Xfree(ainfo[i].name); |
c1666427297c
Memory leak fixes by Bill May.
Ryan C. Gordon <icculus@icculus.org>
parents:
410
diff
changeset
|
147 if (ainfo[i].formats != NULL) Xfree(ainfo[i].formats); |
c1666427297c
Memory leak fixes by Bill May.
Ryan C. Gordon <icculus@icculus.org>
parents:
410
diff
changeset
|
148 } |
c1666427297c
Memory leak fixes by Bill May.
Ryan C. Gordon <icculus@icculus.org>
parents:
410
diff
changeset
|
149 Xfree(ainfo); |
434
ed58b98c0d9d
Commented double-free buggy code. Will examine more closely later.
Ryan C. Gordon <icculus@icculus.org>
parents:
429
diff
changeset
|
150 #endif |
429
c1666427297c
Memory leak fixes by Bill May.
Ryan C. Gordon <icculus@icculus.org>
parents:
410
diff
changeset
|
151 |
0 | 152 if ( xv_port == -1 ) { |
153 SDL_SetError("No available video ports for requested format"); | |
154 return(NULL); | |
155 } | |
156 | |
157 /* Create the overlay structure */ | |
158 overlay = (SDL_Overlay *)malloc(sizeof *overlay); | |
159 if ( overlay == NULL ) { | |
292
eadc0746dfaf
Added SDL_LockRect() and SDL_UnlockRect()
Sam Lantinga <slouken@libsdl.org>
parents:
252
diff
changeset
|
160 SDL_NAME(XvUngrabPort)(GFX_Display, xv_port, CurrentTime); |
0 | 161 SDL_OutOfMemory(); |
162 return(NULL); | |
163 } | |
164 memset(overlay, 0, (sizeof *overlay)); | |
165 | |
166 /* Fill in the basic members */ | |
167 overlay->format = format; | |
168 overlay->w = width; | |
169 overlay->h = height; | |
170 | |
171 /* Set up the YUV surface function structure */ | |
172 overlay->hwfuncs = &x11_yuvfuncs; | |
173 overlay->hw_overlay = 1; | |
174 | |
175 /* Create the pixel data and lookup tables */ | |
176 hwdata = (struct private_yuvhwdata *)malloc(sizeof *hwdata); | |
177 overlay->hwdata = hwdata; | |
178 if ( hwdata == NULL ) { | |
292
eadc0746dfaf
Added SDL_LockRect() and SDL_UnlockRect()
Sam Lantinga <slouken@libsdl.org>
parents:
252
diff
changeset
|
179 SDL_NAME(XvUngrabPort)(GFX_Display, xv_port, CurrentTime); |
0 | 180 SDL_OutOfMemory(); |
181 SDL_FreeYUVOverlay(overlay); | |
182 return(NULL); | |
183 } | |
184 yuvshm = &hwdata->yuvshm; | |
185 memset(yuvshm, 0, sizeof(*yuvshm)); | |
186 hwdata->port = xv_port; | |
292
eadc0746dfaf
Added SDL_LockRect() and SDL_UnlockRect()
Sam Lantinga <slouken@libsdl.org>
parents:
252
diff
changeset
|
187 hwdata->image = SDL_NAME(XvShmCreateImage)(GFX_Display, xv_port, format, |
0 | 188 0, width, height, yuvshm); |
189 | |
190 #ifdef PITCH_WORKAROUND | |
191 if ( hwdata->image != NULL && hwdata->image->pitches[0] != width ) | |
192 { | |
193 /* Ajust overlay width according to pitch */ | |
194 switch (format) { | |
195 case SDL_YV12_OVERLAY: | |
196 case SDL_IYUV_OVERLAY: | |
197 width = hwdata->image->pitches[0]; | |
198 break; | |
199 case SDL_YUY2_OVERLAY: | |
200 case SDL_UYVY_OVERLAY: | |
201 case SDL_YVYU_OVERLAY: | |
202 width = hwdata->image->pitches[0] / 2; | |
203 break; | |
204 default: | |
205 /* We should never get here (caught above) */ | |
206 return(NULL); | |
207 } | |
208 | |
209 XFree(hwdata->image); | |
292
eadc0746dfaf
Added SDL_LockRect() and SDL_UnlockRect()
Sam Lantinga <slouken@libsdl.org>
parents:
252
diff
changeset
|
210 hwdata->image = SDL_NAME(XvShmCreateImage)(GFX_Display, xv_port, format, |
0 | 211 0, width, height, yuvshm); |
212 } | |
213 #endif | |
214 | |
215 if ( hwdata->image == NULL ) { | |
216 SDL_OutOfMemory(); | |
217 SDL_FreeYUVOverlay(overlay); | |
218 return(NULL); | |
219 } | |
220 yuvshm->shmid = shmget(IPC_PRIVATE, hwdata->image->data_size, | |
221 IPC_CREAT | 0777); | |
222 if ( yuvshm->shmid < 0 ) { | |
223 SDL_SetError("Unable to get %d bytes shared memory", | |
224 hwdata->image->data_size); | |
225 SDL_FreeYUVOverlay(overlay); | |
226 return(NULL); | |
227 } | |
228 yuvshm->shmaddr = (char *) shmat(yuvshm->shmid, 0, 0); | |
229 yuvshm->readOnly = False; | |
230 hwdata->image->data = yuvshm->shmaddr; | |
231 | |
232 XShmAttach(GFX_Display, yuvshm); | |
233 XSync(GFX_Display, False); | |
234 shmctl(yuvshm->shmid, IPC_RMID, 0); | |
235 | |
236 /* Find the pitch and offset values for the overlay */ | |
237 overlay->planes = hwdata->image->num_planes; | |
238 overlay->pitches = (Uint16 *)malloc(overlay->planes * sizeof(Uint16)); | |
239 overlay->pixels = (Uint8 **)malloc(overlay->planes * sizeof(Uint8 *)); | |
240 if ( !overlay->pitches || !overlay->pixels ) { | |
241 SDL_OutOfMemory(); | |
242 SDL_FreeYUVOverlay(overlay); | |
243 return(NULL); | |
244 } | |
245 for ( i=0; i<overlay->planes; ++i ) { | |
246 overlay->pitches[i] = hwdata->image->pitches[i]; | |
247 overlay->pixels[i] = (Uint8 *)hwdata->image->data + | |
248 hwdata->image->offsets[i]; | |
249 } | |
250 | |
251 #ifdef XFREE86_REFRESH_HACK | |
252 /* Work around an XFree86 X server bug (?) | |
253 We can't perform normal updates in windows that have video | |
254 being output to them. See SDL_x11image.c for more details. | |
255 */ | |
256 X11_DisableAutoRefresh(this); | |
257 #endif | |
258 | |
259 /* We're all done.. */ | |
260 return(overlay); | |
261 } | |
262 | |
263 int X11_LockYUVOverlay(_THIS, SDL_Overlay *overlay) | |
264 { | |
265 return(0); | |
266 } | |
267 | |
268 void X11_UnlockYUVOverlay(_THIS, SDL_Overlay *overlay) | |
269 { | |
270 return; | |
271 } | |
272 | |
273 int X11_DisplayYUVOverlay(_THIS, SDL_Overlay *overlay, SDL_Rect *dstrect) | |
274 { | |
275 struct private_yuvhwdata *hwdata; | |
276 | |
277 hwdata = overlay->hwdata; | |
292
eadc0746dfaf
Added SDL_LockRect() and SDL_UnlockRect()
Sam Lantinga <slouken@libsdl.org>
parents:
252
diff
changeset
|
278 SDL_NAME(XvShmPutImage)(GFX_Display, hwdata->port, SDL_Window, SDL_GC, |
0 | 279 hwdata->image, 0, 0, overlay->w, overlay->h, |
280 dstrect->x, dstrect->y, dstrect->w, dstrect->h, False); | |
281 XSync(GFX_Display, False); | |
282 return(0); | |
283 } | |
284 | |
285 void X11_FreeYUVOverlay(_THIS, SDL_Overlay *overlay) | |
286 { | |
287 struct private_yuvhwdata *hwdata; | |
288 | |
289 hwdata = overlay->hwdata; | |
290 if ( hwdata ) { | |
292
eadc0746dfaf
Added SDL_LockRect() and SDL_UnlockRect()
Sam Lantinga <slouken@libsdl.org>
parents:
252
diff
changeset
|
291 SDL_NAME(XvUngrabPort)(GFX_Display, hwdata->port, CurrentTime); |
0 | 292 if ( hwdata->yuvshm.shmaddr ) { |
293 XShmDetach(GFX_Display, &hwdata->yuvshm); | |
294 shmdt(hwdata->yuvshm.shmaddr); | |
295 } | |
296 if ( hwdata->image ) { | |
297 XFree(hwdata->image); | |
298 } | |
299 free(hwdata); | |
300 } | |
301 if ( overlay->pitches ) { | |
302 free(overlay->pitches); | |
303 overlay->pitches = NULL; | |
304 } | |
305 if ( overlay->pixels ) { | |
306 free(overlay->pixels); | |
307 overlay->pixels = NULL; | |
308 } | |
309 #ifdef XFREE86_REFRESH_HACK | |
310 X11_EnableAutoRefresh(this); | |
311 #endif | |
312 } | |
313 | |
314 #endif /* XFREE86_XV */ |