comparison src/video/quartz/SDL_QuartzYUV.m @ 761:c5b2b6d2d1fe

Date: Wed, 31 Dec 2003 21:55:30 +0100 From: Max Horn Subject: SDL: video/quartz cleanup while doing some experimental changes in the quartz code, I was annoyed by having to recompile that one big .o file over and over again. So I decided to finally realize one TODO: properly splitting the code over multiple files :-). With two exceptions, I didn't make code changes, only rearranged files and added new headers. Since there are several new files, making a patch didn't work out so well, so I decided to just send you all the new & modified files. The one source change I made is related to showing/hiding the mouse. I renamed cursor_visible to cursor_should_be_visible and cursor_hidden to cursor_visible; I think that makes reading the code easier. Then I added two new functions: QZ_ShowMouse and QZ_HideMouse. They help manage cursor_visible (the former 'cursor_hidden'). Finally I replaced the Carbon ShowCursor/HiderCuror calls by [NSCursor hide] and [NSCursor unhide]. The API docs are not conclusive, but it might be that with those the "cursor_visible" (former 'cursor_hidden') hack may not be necessary anymore; however so far I didn't test this hypothesis, so I left that in. The other change was to remove in_foreground and use [NSApp isActive] instead: Manually keeping track of whether we are in the foreground is error prone. This should work better in some corner cases.
author Sam Lantinga <slouken@libsdl.org>
date Sun, 04 Jan 2004 14:55:35 +0000
parents
children 19418e4422cb
comparison
equal deleted inserted replaced
760:cf9dd3aa6756 761:c5b2b6d2d1fe
1 /*
2 SDL - Simple DirectMedia Layer
3 Copyright (C) 1997-2003 Sam Lantinga
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
20 slouken@libsdl.org
21 */
22
23 #include "SDL_QuartzVideo.h"
24 #include "SDL_QuartzWindow.h"
25 #include "SDL_yuvfuncs.h"
26
27
28 #define yuv_idh (this->hidden->yuv_idh)
29 #define yuv_matrix (this->hidden->yuv_matrix)
30 #define yuv_codec (this->hidden->yuv_codec)
31 #define yuv_seq (this->hidden->yuv_seq)
32 #define yuv_pixmap (this->hidden->yuv_pixmap)
33 #define yuv_data (this->hidden->yuv_data)
34 #define yuv_width (this->hidden->yuv_width)
35 #define yuv_height (this->hidden->yuv_height)
36 #define yuv_port (this->hidden->yuv_port)
37
38
39 static int QZ_LockYUV (_THIS, SDL_Overlay *overlay) {
40
41 return 0;
42 }
43
44 static void QZ_UnlockYUV (_THIS, SDL_Overlay *overlay) {
45
46 ;
47 }
48
49 static int QZ_DisplayYUV (_THIS, SDL_Overlay *overlay, SDL_Rect *dstrect) {
50
51 OSErr err;
52 CodecFlags flags;
53
54 if (dstrect->x != 0 || dstrect->y != 0) {
55
56 SDL_SetError ("Need a dstrect at (0,0)");
57 return -1;
58 }
59
60 if (dstrect->w != yuv_width || dstrect->h != yuv_height) {
61
62 Fixed scale_x, scale_y;
63
64 scale_x = FixDiv ( Long2Fix (dstrect->w), Long2Fix (overlay->w) );
65 scale_y = FixDiv ( Long2Fix (dstrect->h), Long2Fix (overlay->h) );
66
67 SetIdentityMatrix (yuv_matrix);
68 ScaleMatrix (yuv_matrix, scale_x, scale_y, Long2Fix (0), Long2Fix (0));
69
70 SetDSequenceMatrix (yuv_seq, yuv_matrix);
71
72 yuv_width = dstrect->w;
73 yuv_height = dstrect->h;
74 }
75
76 if( ( err = DecompressSequenceFrameS(
77 yuv_seq,
78 (void*)yuv_pixmap,
79 sizeof (PlanarPixmapInfoYUV420),
80 codecFlagUseImageBuffer, &flags, nil ) != noErr ) )
81 {
82 SDL_SetError ("DecompressSequenceFrameS failed");
83 }
84
85 return err == noErr;
86 }
87
88 static void QZ_FreeHWYUV (_THIS, SDL_Overlay *overlay) {
89
90 CDSequenceEnd (yuv_seq);
91 ExitMovies();
92
93 free (overlay->hwfuncs);
94 free (overlay->pitches);
95 free (overlay->pixels);
96
97 if (SDL_VideoSurface->flags & SDL_FULLSCREEN) {
98 [ qz_window close ];
99 qz_window = nil;
100 }
101
102 free (yuv_matrix);
103 DisposeHandle ((Handle)yuv_idh);
104 }
105
106 /* check for 16 byte alignment, bail otherwise */
107 #define CHECK_ALIGN(x) do { if ((Uint32)x & 15) { SDL_SetError("Alignment error"); return NULL; } } while(0)
108
109 /* align a byte offset, return how much to add to make it a multiple of 16 */
110 #define ALIGN(x) ((16 - (x & 15)) & 15)
111
112 SDL_Overlay* QZ_CreateYUVOverlay (_THIS, int width, int height,
113 Uint32 format, SDL_Surface *display) {
114
115 Uint32 codec;
116 OSStatus err;
117 CGrafPtr port;
118 SDL_Overlay *overlay;
119
120 if (format == SDL_YV12_OVERLAY ||
121 format == SDL_IYUV_OVERLAY) {
122
123 codec = kYUV420CodecType;
124 }
125 else {
126 SDL_SetError ("Hardware: unsupported video format");
127 return NULL;
128 }
129
130 yuv_idh = (ImageDescriptionHandle) NewHandleClear (sizeof(ImageDescription));
131 if (yuv_idh == NULL) {
132 SDL_OutOfMemory();
133 return NULL;
134 }
135
136 yuv_matrix = (MatrixRecordPtr) malloc (sizeof(MatrixRecord));
137 if (yuv_matrix == NULL) {
138 SDL_OutOfMemory();
139 return NULL;
140 }
141
142 if ( EnterMovies() != noErr ) {
143 SDL_SetError ("Could not init QuickTime for YUV playback");
144 return NULL;
145 }
146
147 err = FindCodec (codec, bestSpeedCodec, nil, &yuv_codec);
148 if (err != noErr) {
149 SDL_SetError ("Could not find QuickTime codec for format");
150 return NULL;
151 }
152
153 if (SDL_VideoSurface->flags & SDL_FULLSCREEN) {
154
155 /*
156 Acceleration requires a window to be present.
157 A CGrafPtr that points to the screen isn't good enough
158 */
159 NSRect content = NSMakeRect (0, 0, SDL_VideoSurface->w, SDL_VideoSurface->h);
160
161 qz_window = [ [ SDL_QuartzWindow alloc ]
162 initWithContentRect:content
163 styleMask:NSBorderlessWindowMask
164 backing:NSBackingStoreBuffered defer:NO ];
165
166 if (qz_window == nil) {
167 SDL_SetError ("Could not create the Cocoa window");
168 return NULL;
169 }
170
171 [ qz_window setContentView:[ [ NSQuickDrawView alloc ] init ] ];
172 [ qz_window setReleasedWhenClosed:YES ];
173 [ qz_window center ];
174 [ qz_window setAcceptsMouseMovedEvents:YES ];
175 [ qz_window setLevel:CGShieldingWindowLevel() ];
176 [ qz_window makeKeyAndOrderFront:nil ];
177
178 port = [ [ qz_window contentView ] qdPort ];
179 SetPort (port);
180
181 /*
182 BUG: would like to remove white flash when window kicks in
183 {
184 Rect r;
185 SetRect (&r, 0, 0, SDL_VideoSurface->w, SDL_VideoSurface->h);
186 PaintRect (&r);
187 QDFlushPortBuffer (port, nil);
188 }
189 */
190 }
191 else {
192 port = [ window_view qdPort ];
193 SetPort (port);
194 }
195
196 SetIdentityMatrix (yuv_matrix);
197
198 HLock ((Handle)yuv_idh);
199
200 (**yuv_idh).idSize = sizeof(ImageDescription);
201 (**yuv_idh).cType = codec;
202 (**yuv_idh).version = 1;
203 (**yuv_idh).revisionLevel = 0;
204 (**yuv_idh).width = width;
205 (**yuv_idh).height = height;
206 (**yuv_idh).hRes = Long2Fix(72);
207 (**yuv_idh).vRes = Long2Fix(72);
208 (**yuv_idh).spatialQuality = codecLosslessQuality;
209 (**yuv_idh).frameCount = 1;
210 (**yuv_idh).clutID = -1;
211 (**yuv_idh).dataSize = 0;
212 (**yuv_idh).depth = 24;
213
214 HUnlock ((Handle)yuv_idh);
215
216 err = DecompressSequenceBeginS (
217 &yuv_seq,
218 yuv_idh,
219 NULL,
220 0,
221 port,
222 NULL,
223 NULL,
224 yuv_matrix,
225 0,
226 NULL,
227 codecFlagUseImageBuffer,
228 codecLosslessQuality,
229 yuv_codec);
230
231 if (err != noErr) {
232 SDL_SetError ("Error trying to start YUV codec.");
233 return NULL;
234 }
235
236 overlay = (SDL_Overlay*) malloc (sizeof(*overlay));
237 if (overlay == NULL) {
238 SDL_OutOfMemory();
239 return NULL;
240 }
241
242 overlay->format = format;
243 overlay->w = width;
244 overlay->h = height;
245 overlay->planes = 3;
246 overlay->hw_overlay = 1;
247 {
248 int offset;
249 Uint8 **pixels;
250 Uint16 *pitches;
251 int plane2, plane3;
252
253 if (format == SDL_IYUV_OVERLAY) {
254
255 plane2 = 1; /* Native codec format */
256 plane3 = 2;
257 }
258 else if (format == SDL_YV12_OVERLAY) {
259
260 /* switch the U and V planes */
261 plane2 = 2; /* U plane maps to plane 3 */
262 plane3 = 1; /* V plane maps to plane 2 */
263 }
264 else {
265 SDL_SetError("Unsupported YUV format");
266 return NULL;
267 }
268
269 pixels = (Uint8**) malloc (sizeof(*pixels) * 3);
270 pitches = (Uint16*) malloc (sizeof(*pitches) * 3);
271 if (pixels == NULL || pitches == NULL) {
272 SDL_OutOfMemory();
273 return NULL;
274 }
275
276 yuv_pixmap = (PlanarPixmapInfoYUV420*)
277 malloc (sizeof(PlanarPixmapInfoYUV420) +
278 (width * height * 2));
279 if (yuv_pixmap == NULL) {
280 SDL_OutOfMemory ();
281 return NULL;
282 }
283
284 /* CHECK_ALIGN(yuv_pixmap); */
285 offset = sizeof(PlanarPixmapInfoYUV420);
286 /* offset += ALIGN(offset); */
287 /* CHECK_ALIGN(offset); */
288
289 pixels[0] = (Uint8*)yuv_pixmap + offset;
290 /* CHECK_ALIGN(pixels[0]); */
291
292 pitches[0] = width;
293 yuv_pixmap->componentInfoY.offset = offset;
294 yuv_pixmap->componentInfoY.rowBytes = width;
295
296 offset += width * height;
297 pixels[plane2] = (Uint8*)yuv_pixmap + offset;
298 pitches[plane2] = width / 2;
299 yuv_pixmap->componentInfoCb.offset = offset;
300 yuv_pixmap->componentInfoCb.rowBytes = width / 2;
301
302 offset += (width * height / 4);
303 pixels[plane3] = (Uint8*)yuv_pixmap + offset;
304 pitches[plane3] = width / 2;
305 yuv_pixmap->componentInfoCr.offset = offset;
306 yuv_pixmap->componentInfoCr.rowBytes = width / 2;
307
308 overlay->pixels = pixels;
309 overlay->pitches = pitches;
310 }
311
312 overlay->hwfuncs = malloc (sizeof(*overlay->hwfuncs));
313 if (overlay->hwfuncs == NULL) {
314 SDL_OutOfMemory();
315 return NULL;
316 }
317
318 overlay->hwfuncs->Lock = QZ_LockYUV;
319 overlay->hwfuncs->Unlock = QZ_UnlockYUV;
320 overlay->hwfuncs->Display = QZ_DisplayYUV;
321 overlay->hwfuncs->FreeHW = QZ_FreeHWYUV;
322
323 yuv_width = overlay->w;
324 yuv_height = overlay->h;
325
326 return overlay;
327 }