Mercurial > sdl-ios-xcode
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/video/quartz/SDL_QuartzYUV.m Sun Jan 04 14:55:35 2004 +0000 @@ -0,0 +1,327 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997-2003 Sam Lantinga + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public + License along with this library; if not, write to the Free + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + Sam Lantinga + slouken@libsdl.org +*/ + +#include "SDL_QuartzVideo.h" +#include "SDL_QuartzWindow.h" +#include "SDL_yuvfuncs.h" + + +#define yuv_idh (this->hidden->yuv_idh) +#define yuv_matrix (this->hidden->yuv_matrix) +#define yuv_codec (this->hidden->yuv_codec) +#define yuv_seq (this->hidden->yuv_seq) +#define yuv_pixmap (this->hidden->yuv_pixmap) +#define yuv_data (this->hidden->yuv_data) +#define yuv_width (this->hidden->yuv_width) +#define yuv_height (this->hidden->yuv_height) +#define yuv_port (this->hidden->yuv_port) + + +static int QZ_LockYUV (_THIS, SDL_Overlay *overlay) { + + return 0; +} + +static void QZ_UnlockYUV (_THIS, SDL_Overlay *overlay) { + + ; +} + +static int QZ_DisplayYUV (_THIS, SDL_Overlay *overlay, SDL_Rect *dstrect) { + + OSErr err; + CodecFlags flags; + + if (dstrect->x != 0 || dstrect->y != 0) { + + SDL_SetError ("Need a dstrect at (0,0)"); + return -1; + } + + if (dstrect->w != yuv_width || dstrect->h != yuv_height) { + + Fixed scale_x, scale_y; + + scale_x = FixDiv ( Long2Fix (dstrect->w), Long2Fix (overlay->w) ); + scale_y = FixDiv ( Long2Fix (dstrect->h), Long2Fix (overlay->h) ); + + SetIdentityMatrix (yuv_matrix); + ScaleMatrix (yuv_matrix, scale_x, scale_y, Long2Fix (0), Long2Fix (0)); + + SetDSequenceMatrix (yuv_seq, yuv_matrix); + + yuv_width = dstrect->w; + yuv_height = dstrect->h; + } + + if( ( err = DecompressSequenceFrameS( + yuv_seq, + (void*)yuv_pixmap, + sizeof (PlanarPixmapInfoYUV420), + codecFlagUseImageBuffer, &flags, nil ) != noErr ) ) + { + SDL_SetError ("DecompressSequenceFrameS failed"); + } + + return err == noErr; +} + +static void QZ_FreeHWYUV (_THIS, SDL_Overlay *overlay) { + + CDSequenceEnd (yuv_seq); + ExitMovies(); + + free (overlay->hwfuncs); + free (overlay->pitches); + free (overlay->pixels); + + if (SDL_VideoSurface->flags & SDL_FULLSCREEN) { + [ qz_window close ]; + qz_window = nil; + } + + free (yuv_matrix); + DisposeHandle ((Handle)yuv_idh); +} + +/* check for 16 byte alignment, bail otherwise */ +#define CHECK_ALIGN(x) do { if ((Uint32)x & 15) { SDL_SetError("Alignment error"); return NULL; } } while(0) + +/* align a byte offset, return how much to add to make it a multiple of 16 */ +#define ALIGN(x) ((16 - (x & 15)) & 15) + +SDL_Overlay* QZ_CreateYUVOverlay (_THIS, int width, int height, + Uint32 format, SDL_Surface *display) { + + Uint32 codec; + OSStatus err; + CGrafPtr port; + SDL_Overlay *overlay; + + if (format == SDL_YV12_OVERLAY || + format == SDL_IYUV_OVERLAY) { + + codec = kYUV420CodecType; + } + else { + SDL_SetError ("Hardware: unsupported video format"); + return NULL; + } + + yuv_idh = (ImageDescriptionHandle) NewHandleClear (sizeof(ImageDescription)); + if (yuv_idh == NULL) { + SDL_OutOfMemory(); + return NULL; + } + + yuv_matrix = (MatrixRecordPtr) malloc (sizeof(MatrixRecord)); + if (yuv_matrix == NULL) { + SDL_OutOfMemory(); + return NULL; + } + + if ( EnterMovies() != noErr ) { + SDL_SetError ("Could not init QuickTime for YUV playback"); + return NULL; + } + + err = FindCodec (codec, bestSpeedCodec, nil, &yuv_codec); + if (err != noErr) { + SDL_SetError ("Could not find QuickTime codec for format"); + return NULL; + } + + if (SDL_VideoSurface->flags & SDL_FULLSCREEN) { + + /* + Acceleration requires a window to be present. + A CGrafPtr that points to the screen isn't good enough + */ + NSRect content = NSMakeRect (0, 0, SDL_VideoSurface->w, SDL_VideoSurface->h); + + qz_window = [ [ SDL_QuartzWindow alloc ] + initWithContentRect:content + styleMask:NSBorderlessWindowMask + backing:NSBackingStoreBuffered defer:NO ]; + + if (qz_window == nil) { + SDL_SetError ("Could not create the Cocoa window"); + return NULL; + } + + [ qz_window setContentView:[ [ NSQuickDrawView alloc ] init ] ]; + [ qz_window setReleasedWhenClosed:YES ]; + [ qz_window center ]; + [ qz_window setAcceptsMouseMovedEvents:YES ]; + [ qz_window setLevel:CGShieldingWindowLevel() ]; + [ qz_window makeKeyAndOrderFront:nil ]; + + port = [ [ qz_window contentView ] qdPort ]; + SetPort (port); + + /* + BUG: would like to remove white flash when window kicks in + { + Rect r; + SetRect (&r, 0, 0, SDL_VideoSurface->w, SDL_VideoSurface->h); + PaintRect (&r); + QDFlushPortBuffer (port, nil); + } + */ + } + else { + port = [ window_view qdPort ]; + SetPort (port); + } + + SetIdentityMatrix (yuv_matrix); + + HLock ((Handle)yuv_idh); + + (**yuv_idh).idSize = sizeof(ImageDescription); + (**yuv_idh).cType = codec; + (**yuv_idh).version = 1; + (**yuv_idh).revisionLevel = 0; + (**yuv_idh).width = width; + (**yuv_idh).height = height; + (**yuv_idh).hRes = Long2Fix(72); + (**yuv_idh).vRes = Long2Fix(72); + (**yuv_idh).spatialQuality = codecLosslessQuality; + (**yuv_idh).frameCount = 1; + (**yuv_idh).clutID = -1; + (**yuv_idh).dataSize = 0; + (**yuv_idh).depth = 24; + + HUnlock ((Handle)yuv_idh); + + err = DecompressSequenceBeginS ( + &yuv_seq, + yuv_idh, + NULL, + 0, + port, + NULL, + NULL, + yuv_matrix, + 0, + NULL, + codecFlagUseImageBuffer, + codecLosslessQuality, + yuv_codec); + + if (err != noErr) { + SDL_SetError ("Error trying to start YUV codec."); + return NULL; + } + + overlay = (SDL_Overlay*) malloc (sizeof(*overlay)); + if (overlay == NULL) { + SDL_OutOfMemory(); + return NULL; + } + + overlay->format = format; + overlay->w = width; + overlay->h = height; + overlay->planes = 3; + overlay->hw_overlay = 1; + { + int offset; + Uint8 **pixels; + Uint16 *pitches; + int plane2, plane3; + + if (format == SDL_IYUV_OVERLAY) { + + plane2 = 1; /* Native codec format */ + plane3 = 2; + } + else if (format == SDL_YV12_OVERLAY) { + + /* switch the U and V planes */ + plane2 = 2; /* U plane maps to plane 3 */ + plane3 = 1; /* V plane maps to plane 2 */ + } + else { + SDL_SetError("Unsupported YUV format"); + return NULL; + } + + pixels = (Uint8**) malloc (sizeof(*pixels) * 3); + pitches = (Uint16*) malloc (sizeof(*pitches) * 3); + if (pixels == NULL || pitches == NULL) { + SDL_OutOfMemory(); + return NULL; + } + + yuv_pixmap = (PlanarPixmapInfoYUV420*) + malloc (sizeof(PlanarPixmapInfoYUV420) + + (width * height * 2)); + if (yuv_pixmap == NULL) { + SDL_OutOfMemory (); + return NULL; + } + + /* CHECK_ALIGN(yuv_pixmap); */ + offset = sizeof(PlanarPixmapInfoYUV420); + /* offset += ALIGN(offset); */ + /* CHECK_ALIGN(offset); */ + + pixels[0] = (Uint8*)yuv_pixmap + offset; + /* CHECK_ALIGN(pixels[0]); */ + + pitches[0] = width; + yuv_pixmap->componentInfoY.offset = offset; + yuv_pixmap->componentInfoY.rowBytes = width; + + offset += width * height; + pixels[plane2] = (Uint8*)yuv_pixmap + offset; + pitches[plane2] = width / 2; + yuv_pixmap->componentInfoCb.offset = offset; + yuv_pixmap->componentInfoCb.rowBytes = width / 2; + + offset += (width * height / 4); + pixels[plane3] = (Uint8*)yuv_pixmap + offset; + pitches[plane3] = width / 2; + yuv_pixmap->componentInfoCr.offset = offset; + yuv_pixmap->componentInfoCr.rowBytes = width / 2; + + overlay->pixels = pixels; + overlay->pitches = pitches; + } + + overlay->hwfuncs = malloc (sizeof(*overlay->hwfuncs)); + if (overlay->hwfuncs == NULL) { + SDL_OutOfMemory(); + return NULL; + } + + overlay->hwfuncs->Lock = QZ_LockYUV; + overlay->hwfuncs->Unlock = QZ_UnlockYUV; + overlay->hwfuncs->Display = QZ_DisplayYUV; + overlay->hwfuncs->FreeHW = QZ_FreeHWYUV; + + yuv_width = overlay->w; + yuv_height = overlay->h; + + return overlay; +}