⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sdl_quartzvideo.m

📁 MPEG-4编解码的实现(包括MPEG4视音频编解码)
💻 M
📖 第 1 页 / 共 3 页
字号:
        goto ERR_NO_CAPTURE;
    }

    
    /* Do the physical switch */
    if ( CGDisplayNoErr != CGDisplaySwitchToMode (display_id, mode) ) {
        SDL_SetError ("Failed switching display resolution");
        goto ERR_NO_SWITCH;
    }

    current->pixels = (Uint32*) CGDisplayBaseAddress (display_id);
    current->pitch  = CGDisplayBytesPerRow (display_id);

    current->flags = 0;
    current->w = width;
    current->h = height;
    current->flags |= SDL_FULLSCREEN;  
    current->flags |= SDL_HWSURFACE;
   
    this->UpdateRects = QZ_DirectUpdate;
    
    /* Setup some mode-dependant info */
    if ( CGSDisplayCanHWFill (display_id) ) {
         this->info.blit_fill = 1;
         this->FillHWRect = QZ_FillHWRect;
    }
        
    if ( CGDisplayCanSetPalette (display_id) )
        current->flags |= SDL_HWPALETTE;
    
    /* Setup OpenGL for a fullscreen context */
    if (flags & SDL_OPENGL) {

        CGLError err;
        CGLContextObj ctx;
        
        if ( ! QZ_SetupOpenGL (this, bpp, flags) ) {
            goto ERR_NO_GL;
        }
       
        ctx = [ gl_context cglContext ];
        err = CGLSetFullScreen (ctx);
        
        if (err) {
            sprintf (QZ_Error, "Error setting OpenGL fullscreen: %s", CGLErrorString(err));
            SDL_SetError (QZ_Error);
            goto ERR_NO_GL;
        }
         
        [ gl_context makeCurrentContext];

        glClear (GL_COLOR_BUFFER_BIT);

        [ gl_context flushBuffer ];
        
        current->flags |= SDL_OPENGL;
    }

    /* If we don't hide menu bar, it will get events and interrupt the program */
    HideMenuBar ();

    /* Fade the display to original gamma */
    if (! gamma_error )
        QZ_FadeGammaIn (this, &gamma_table);
    
    /* Save the flags to ensure correct tear-down */
    mode_flags = current->flags;
    
    return current;

 /* Since the blanking window covers *all* windows (even force quit) correct recovery is crucial */
 ERR_NO_GL:      CGDisplaySwitchToMode (display_id, save_mode);
 ERR_NO_SWITCH:  CGDisplayRelease (display_id);
 ERR_NO_CAPTURE: if (!gamma_error) { QZ_FadeGammaIn (this, &gamma_table); }
 ERR_NO_MATCH:	return NULL;
}

static SDL_Surface* QZ_SetVideoWindowed (_THIS, SDL_Surface *current, int width,
                                           int height, int bpp, Uint32 flags) {    
    unsigned int style;
    NSRect rect;    
    rect = NSMakeRect (0, 0, width, height);

#if 1 // FIXME - the resize button doesn't show?  Also need resize events...
    flags &= ~SDL_RESIZABLE;
#endif
    /* Set the window style based on input flags */
    if ( flags & SDL_NOFRAME ) {
        style = NSBorderlessWindowMask;
    } else {
        style = NSTitledWindowMask;
        style |= (NSMiniaturizableWindowMask | NSClosableWindowMask);
        if ( flags & SDL_RESIZABLE )
            style |= NSResizableWindowMask;
    }

    /* Manually create a window, avoids having a nib file resource */
    qz_window = [ [ SDL_QuartzWindow alloc ] initWithContentRect:rect 
        styleMask:style backing:NSBackingStoreBuffered defer:NO ];
    if (qz_window == nil) {
        SDL_SetError ("Could not create the Cocoa window");
        return NULL;
    }
    
    current->flags = 0;
    current->w = width;
    current->h = height;
    
    [ qz_window setReleasedWhenClosed:YES ];
    QZ_SetCaption(this, this->wm_title, this->wm_icon);
    [ qz_window setAcceptsMouseMovedEvents:YES ];
    [ qz_window setViewsNeedDisplay:NO ];
    [ qz_window center ];
    [ qz_window setDelegate:
        [ [ [ SDL_QuartzWindowDelegate alloc ] init ] autorelease ] ];
    
    /* For OpenGL, we set the content view to a NSOpenGLView */
    if ( flags & SDL_OPENGL ) {
    
        if ( ! QZ_SetupOpenGL (this, bpp, flags) ) {
            return NULL;
        }
        
        [ gl_context setView: [ qz_window contentView ] ];
        [ gl_context makeCurrentContext];
        [ qz_window makeKeyAndOrderFront:nil ];
        current->flags |= SDL_OPENGL;
    }
    /* For 2D, we set the content view to a NSQuickDrawView */
    else {
    
        window_view = [ [ SDL_QuartzWindowView alloc ] init ];
        [ qz_window setContentView:window_view ];
        [ qz_window makeKeyAndOrderFront:nil ];    
        
        LockPortBits ( [ window_view qdPort ] );
        current->pixels = GetPixBaseAddr ( GetPortPixMap ( [ window_view qdPort ] ) );
        current->pitch  = GetPixRowBytes ( GetPortPixMap ( [ window_view qdPort ] ) );
        
        current->flags |= SDL_SWSURFACE;
        current->flags |= SDL_PREALLOC;
        
	if ( flags & SDL_NOFRAME )
        	current->flags |= SDL_NOFRAME;
	if ( flags & SDL_RESIZABLE )
        	current->flags |= SDL_RESIZABLE;

        /* Offset 22 pixels down to fill the full content region */
	if ( ! (current->flags & SDL_NOFRAME) ) {
        	current->pixels += 22 * current->pitch;
	}

        this->UpdateRects = QZ_UpdateRects;
    }
    
    /* Save flags to ensure correct teardown */
    mode_flags = current->flags;
      
    return current;
}

static SDL_Surface* QZ_SetVideoMode (_THIS, SDL_Surface *current, int width, 
				     int height, int bpp, Uint32 flags) {

    if (video_set == SDL_TRUE)
        QZ_UnsetVideoMode (this);
       
    current->flags = 0;
    
    /* Setup full screen video */
    if ( flags & SDL_FULLSCREEN ) {
        current = QZ_SetVideoFullScreen (this, current, width, height, bpp, flags );
        if (current == NULL)
            return NULL;
    }
    /* Setup windowed video */
    else {
        /* Force bpp to the device's bpp */
        bpp = device_bpp;
        current = QZ_SetVideoWindowed (this, current, width, height, bpp, flags);
        if (current == NULL)
            return NULL;
    }
    
    /* Setup the new pixel format */
    {
        int amask = 0, 
            rmask = 0, 
            gmask = 0,
            bmask = 0;
            
        switch (bpp) {
            case 16:   /* (1)-5-5-5 RGB */
                amask = 0; 
                rmask = 0x7C00;
                gmask = 0x03E0;
                bmask = 0x001F;
                break;
            case 24:
                SDL_SetError ("24bpp is not available");
                return NULL;
            case 32:   /* (8)-8-8-8 ARGB */
                amask = 0x00000000;
                rmask = 0x00FF0000;
                gmask = 0x0000FF00;
                bmask = 0x000000FF;
                break;
        }
        
        if ( ! SDL_ReallocFormat (current, bpp,
                                  rmask, gmask, bmask, amask ) ) {
       	   SDL_SetError ("Couldn't reallocate pixel format");
           return NULL;
       	}
    }
    
    /* Signal successful completion (used internally) */
    video_set = SDL_TRUE;
    
    return current;
}

static int QZ_ToggleFullScreen (_THIS, int on) { 
    return -1;
}

static int QZ_SetColors (_THIS, int first_color, int num_colors, 
			 SDL_Color *colors) {

    CGTableCount  index;
    CGDeviceColor color;
    
    for (index = first_color; index < first_color+num_colors; index++) {
    
        /* Clamp colors between 0.0 and 1.0 */
        color.red   = colors->r / 255.0;
        color.blue  = colors->b / 255.0;
        color.green = colors->g / 255.0;
        
        colors++;
        
        CGPaletteSetColorAtIndex (palette, color, index);
    }
     
    if ( CGDisplayNoErr != CGDisplaySetPalette (display_id, palette) )
        return 0;
        
    return 1;
}

static void QZ_DirectUpdate (_THIS, int num_rects, SDL_Rect *rects) {
    #pragma unused(this,num_rects,rects)
}

/** 
 *  The obscured code is based on work by Matt Slot fprefect@ambrosiasw.com,
 *  who supplied sample code for Carbon.
 **/
static int QZ_IsWindowObscured (NSWindow *window) {

//#define TEST_OBSCURED 1

#if TEST_OBSCURED
    
    /*  In order to determine if a direct copy to the screen is possible,
       we must figure out if there are any windows covering ours (including shadows).
       This can be done by querying the window server about the on screen            
       windows for their screen rectangle and window level.                          
       The procedure used below is puts accuracy before speed; however, it aims to call 
       the window server the fewest number of times possible to keep things reasonable.
       In my testing on a 300mhz G3, this routine typically takes < 2 ms. -DW
    
        Notes:
            -Calls into the Window Server involve IPC which is slow.
            -Getting a rectangle seems slower than getting the window level
            -The window list we get back is in sorted order, top to bottom
            -On average, I suspect, most windows above ours are dock icon windows (hence optimization)
            -Some windows above ours are always there, and cannot move or obscure us (menu bar)
            
        Bugs:
            -no way (yet) to deactivate direct drawing when a window is dragged, 
               or suddenly obscured, so drawing continues and can produce garbage
               We need some kind of locking mechanism on window movement to prevent this
               
            -deactivated normal windows use activated normal 
               window shadows (slight inaccuraccy)
    */
    
    /* Cache the connection to the window server */
    static CGSConnectionID	cgsConnection = (CGSConnectionID) -1;
    
    /* Cache the dock icon windows */
    static CGSWindowID          dockIcons[kMaxWindows];
    static int                  numCachedDockIcons = 0;
    
    CGSWindowID		        windows[kMaxWindows];
    CGSWindowCount	        i, count;
    CGSWindowLevel	        winLevel;
    CGSRect			winRect;

    CGSRect contentRect;
    int     windowNumber;
    //int     isMainWindow;
    int     firstDockIcon;    
    int     dockIconCacheMiss;
    int     windowContentOffset;
    
    int     obscured = SDL_TRUE;
        
    if ( [ window isVisible ] ) {
        
        /*  walk the window list looking for windows over top of 
                (or casting a shadow on) ours */
       
        /* Get a connection to the window server */
        /* Should probably be moved out into SetVideoMode() or InitVideo() */
        if (cgsConnection == (CGSConnectionID) -1) {
            cgsConnection = (CGSConnectionID) 0;
            cgsConnection = _CGSDefaultConnection ();
        }
        
        if (cgsConnection) { 
        
            if ( ! [ window styleMask ] & NSBorderlessWindowMask )
                windowContentOffset = 22;
            else
                windowContentOffset = 0;
                
            windowNumber = [ window windowNumber ];
            //isMainWindow = [ window isMainWindow ];
            
            /* The window list is sorted according to order on the screen */
            count = 0;
            CGSGetOnScreenWindowList (cgsConnection, 0, kMaxWindows, windows, &count);
            CGSGetScreenRectForWindow (cgsConnection, windowNumber, &contentRect);
    
            /* adjust rect for window title bar (if present) */
            contentRect.origin.y    += windowContentOffset;
            contentRect.size.height -= windowContentOffset;
            
            firstDockIcon = -1;
            dockIconCacheMiss = SDL_FALSE;
            
            /* The first window is always an empty window with level kCGSWindowLevelTop 
               so start at index 1 */
            for (i = 1; i < count; i++) {
                
                /* If we reach our window in the list, it cannot be obscured */
                if (windows[i] == windowNumber) {
                    
                    obscured = SDL_FALSE;
                    break;
                }
                else {
                    
                    float shadowSide;
                    float shadowTop;
                    float shadowBottom;

                    CGSGetWindowLevel (cgsConnection, windows[i], &winLevel);
                    
                    if (winLevel == kCGSWindowLevelDockIcon) {
                    
                        int j;
                        
                        if (firstDockIcon < 0) {
                            
                            firstDockIcon = i;
                        
                            if (numCachedDockIcons > 0) {
                            
                                for (j = 0; j < numCachedDockIcons; j++) {
                            
                                    if (windows[i] == dockIcons[j])
                                        i++;
                                    else
                                        break;
                                }
                            
                                if (j != 0) {
                                 
                                    i--;
                                                                    
                                    if (j < numCachedDockIcons) {
                                        
                                        dockIconCacheMiss = SDL_TRUE;
                                    }
                                }

                            }
                        }
                                               
                        continue;
                    }
                    else if (winLevel == kCGSWindowLevelMenuIgnore
                             /* winLevel == kCGSWindowLevelTop */) {
                     
                        continue; /* cannot obscure window */
                    }
                    else if (winLevel == kCGSWindowLevelDockMenu ||
                             winLevel == kCGSWindowLevelMenu) {
                     
                        shadowSide = 18;
                        shadowTop = 4;
                        shadowBottom = 22;   
                    }
                    else if (winLevel == kCGSWindowLevelUtility) {
                    
                        shadowSide = 8;
                        shadowTop = 4;
                        shadowBottom = 12;
                    }
                    else if (winLevel == kCGSWindowLevelNormal) {
                    
                        /* These numbers are for foreground windows,
                           they are too big (but will work) for background windows */
                        shadowSide = 20;
                        shadowTop = 10;
                        shadowBottom = 24;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -