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

📄 sdl_dspvideo.c

📁 MPEG-4编解码的实现(包括MPEG4视音频编解码)
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
    SDL - Simple DirectMedia Layer
    Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002  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
*/

/*
 Written by Darrell Walisser <dwaliss1@purdue.edu>

 Implementation notes ----------------------------------------------------------------------

 A bit on GWorlds in VRAM from technote 1182:

 There are two important things to note about GWorld's allocated in
 VRAM. First, the base address retrieved through GetPixBaseAddr or
 read directly from the PixMap structure can become invalid anytime
 memory is allocated in VRAM. This can occur either by explicit
 allocations, such as calls to NewGWorld, or by implicit ones, such as
 those associated with the internal texture allocation of OpenGL. The
 stored pixel images themselves will still be valid but may have been
 moved in VRAM, thus rendering any stored base addresses invalid.
 You should never store an image's base address for longer than is
 necessary and especially never across calls to NewGWorld or
 texture-creation routines. 

 Secondly, an offscreen pixel image allocated in VRAM can be
 purged at system task time by the display driver. This means any
 time your application yields time such by calling WaitNextEvent or
 SystemTask you can lose your VRAM GWorld contents. While this
 happens infrequently, usually associated with display resolution or
 pixel depth changes you must code for this eventuality. This purge
 can occur whether or not the GWorld is locked or not. A return value
 of false from LockPixels, a NULL return value from GetPixBaseAddr
 or NULL in the baseAddr field of the PixMap mean that the pixel
 image has been purged. To reallocate it you can either call
 UpdateGWorld or Dispose your current GWorld through
 DisposeGWorld and reallocate it via NewGWorld. Either way you must
 then rebuild the pixel image. 

------------------------------------------------------------------------------------

  Currently, I don't account for (1). In my testing, NewGWorld never invalidated
  other existing GWorlds in VRAM. However, I do have protection for (2).
  Namely, I am using GetOSEvent() instead of WaitNextEvent() so that there are no
  context switches (the app hogs the CPU). Eventually a book-keeping system should
  be coded to take care of (1) and (2).
  
------------------------------------------------------------------------------------

  System requirements (* denotes optional):
  
  1. DrawSprocket 1.7.3
  2. *MacOS 9 or later for hardware accelerated blit / fill
  3. *May also require certain graphics hardware for (2). I trust that all Apple OEM
     hardware will work. Third party accelerators may work if they have QuickDraw
     acceleration in the drivers and the drivers have been updated for OS 9. The current
     Voodoo 3 drivers (1.0b12) do not work.
  
  Coding suggestions:
  
  1. Use SDL_UpdateRects !
  
    If no QuickDraw acceleration is present, double-buffered surfaces will use a back buffer
    in System memory. I recommend you use SDL_UpdateRects with double-buffered surfaces
    for best performance on these cards, since the overhead is nearly zero for VRAM back buffer.
    
  2. Load most-resident surfaces first.
  
    If you fill up VRAM or AGP memory, there is no contingency for purging to make room for the next one.
    Therefore, you should load the surfaces you plan to use the most frequently first.
    Sooner or later, I will code LRU replacement to help this.
  
  TODO:
  Some kind of posterized mode for resolutions < 640x480.
  Window support / fullscreen toggle.
  Figure out how much VRAM is available. Put in video->info->video_mem.
  Track VRAM usage.
  
  BUGS:
  I can't create a hardware surface the same size as the screen?! How to fix?
  
  

   COMPILE OPTIONS:
   
   DSP_TRY_CC_AND_AA - Define if you want to try HWA color-key and alpha blitters
                       HW color-key blitting gives substantial improvements,
                       but hw alpha is neck-and-neck with SDL's soft bitter.

   DSP_NO_SYNC_VBL   - Define for HWA double-buffered surfaces: don't sync
                       pseudo-flip to monitor redraw.

   DSP_NO_SYNC_OPENGL - Define for OpenGL surfaces: don't sync buffer swap. Synching buffer
                        swap may result in reduced performance, but can eliminate some
                        tearing artifacts.
   CHANGELOG:
   09/17/00 Lots of little tweaks. Build modelist in reverse order so largest contexts
            list first. Compared various methods with ROM methods and fixed rez switch
            crashing bug in GL Tron. (Woohoo!)
*/

#define DSP_TRY_CC_AND_AA

/* #define DSP_NO_SYNC_VBL */

#define DSP_NO_SYNC_OPENGL


#ifdef SAVE_RCSID
static char rcsid =
 "@(#) $Id: SDL_dspvideo.c,v 1.4 2002/04/22 21:38:05 wmay Exp $";
#endif

#include <stdio.h>
#include <stdlib.h>

#if TARGET_API_MAC_CARBON
#include <Carbon.h>
#else
#include <LowMem.h>
#include <Gestalt.h>
#include <Devices.h>
#include <DiskInit.h>
#include <QDOffscreen.h>
#endif

#include "SDL_video.h"
#include "SDL_blit.h"
#include "SDL_error.h"
#include "SDL_syswm.h"
#include "SDL_sysvideo.h"
#include "SDL_dspvideo.h"
#include "SDL_macgl_c.h"
#include "SDL_macwm_c.h"
#include "SDL_macmouse_c.h"
#include "SDL_macevents_c.h"

/* Initialization/Query functions */
static int DSp_VideoInit(_THIS, SDL_PixelFormat *vformat);
static SDL_Rect **DSp_ListModes(_THIS, SDL_PixelFormat *format, Uint32 flags);
static SDL_Surface *DSp_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags);
static int DSp_SetColors(_THIS, int firstcolor, int ncolors,
			 SDL_Color *colors);
static int DSp_CreatePalette(_THIS);
static int DSp_DestroyPalette(_THIS);
static void DSp_VideoQuit(_THIS);

static int DSp_GetMainDevice (_THIS, GDHandle *device);
static void DSp_IsHWAvailable (_THIS, SDL_PixelFormat *vformat);
static void DSp_DSpUpdate(_THIS, int numrects, SDL_Rect *sdl_rects);
static void DSp_DirectUpdate(_THIS, int numrects, SDL_Rect *sdl_rects);

/* Hardware surface functions */
static int DSp_SetHWAlpha(_THIS, SDL_Surface *surface, UInt8 alpha);
static int DSp_SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key);
static int DSp_NewHWSurface(_THIS, CGrafPtr *port, int depth, int width, int height);
static int DSp_AllocHWSurface(_THIS, SDL_Surface *surface);
static int DSp_LockHWSurface(_THIS, SDL_Surface *surface);
static void DSp_UnlockHWSurface(_THIS, SDL_Surface *surface);
static void DSp_FreeHWSurface(_THIS, SDL_Surface *surface);
static int DSp_FlipHWSurface(_THIS, SDL_Surface *surface);
static int DSp_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dest);
static int DSp_HWAccelBlit(SDL_Surface *src, SDL_Rect *srcrect,
                           SDL_Surface *dst, SDL_Rect *dstrect);
static int DSp_FillHWRect(_THIS, SDL_Surface *dst, SDL_Rect *rect, Uint32 color);

#ifdef HAVE_OPENGL
   static void DSp_GL_SwapBuffers (_THIS);
#endif

#if ! TARGET_API_MAC_CARBON

    #define GetPortPixRowBytes(x)  ( (*(x->portPixMap))->rowBytes )
   #define GetGDevPixMap(x) ((**(x)).gdPMap)   
   #define GetPortPixMap(x) ((*(x)).portPixMap)
   
   #define GetPixDepth(y)    ((**(y)).pixelSize)
   //#define GetPixRowBytes(y) ((**(y)).rowBytes)
   //#define GetPixBaseAddr(y) ((**(y)).baseAddr)
   #define GetPixCTab(y)     ((**(y)).pmTable)
    #define GetPortBitMapForCopyBits(x) (&(((GrafPtr)(x))->portBits))
   
#else
    #define GetPortPixRowBytes(x) (GetPixRowBytes(GetPortPixMap(x)) )
    #define GetGDevPixMap(x) ((**(x)).gdPMap)

#endif

typedef struct private_hwdata {

  GWorldPtr offscreen;    // offscreen gworld in VRAM or AGP
  
  #ifdef DSP_TRY_CC_AND_AA
    GWorldPtr mask;         // transparent mask
    RGBColor  alpha;        // alpha color
    RGBColor  trans;        // transparent color
  #endif
  
} private_hwdata;

typedef private_hwdata private_swdata ; /* have same fields */

/* Macintosh toolbox driver bootstrap functions */

static int DSp_Available(void)
{
	/* Check for DrawSprocket */
	/* This check is only meaningful if you weak-link DrawSprocketLib */  
	return ((Ptr)DSpStartup != (Ptr)kUnresolvedCFragSymbolAddress);
}

static void DSp_DeleteDevice(SDL_VideoDevice *device)
{
	/* -dw- taking no chances with null pointers */
	if (device) {
		
   	if (device->hidden) {
   	   
   	   if (device->hidden->dspinfo)
	         free(device->hidden->dspinfo);
   	   
   	   free(device->hidden);
   	}
	   free(device);	
	}
}

static SDL_VideoDevice *DSp_CreateDevice(int devindex)
{
	SDL_VideoDevice *device;

	/* Initialize all variables that we clean on shutdown */
	device = (SDL_VideoDevice *)malloc(sizeof(SDL_VideoDevice));
	if ( device ) {
		memset(device, 0, sizeof (*device));
		device->hidden = (struct SDL_PrivateVideoData *)
				malloc((sizeof *device->hidden));
	    if (device->hidden)
	        memset(device->hidden, 0, sizeof ( *(device->hidden) ) );
	}
	if ( (device == NULL) || (device->hidden == NULL) ) {
		SDL_OutOfMemory();
			
		if ( device ) {
			
			if (device->hidden)
		        free (device->hidden);			
			
			free(device);
		}
		
		return(NULL);
	}
	
	/* Allocate DrawSprocket information */
	device->hidden->dspinfo = (struct DSpInfo *)malloc(
					(sizeof *device->hidden->dspinfo));
	if ( device->hidden->dspinfo == NULL ) {
		SDL_OutOfMemory();
		free(device->hidden);
		free(device);
		return(0);
	}
	memset(device->hidden->dspinfo, 0, (sizeof *device->hidden->dspinfo));

	/* Set the function pointers */
	device->VideoInit       = DSp_VideoInit;
	device->ListModes       = DSp_ListModes;
	device->SetVideoMode    = DSp_SetVideoMode;
	device->SetColors       = DSp_SetColors;
	device->UpdateRects     = NULL;
	device->VideoQuit       = DSp_VideoQuit;
	device->AllocHWSurface  = DSp_AllocHWSurface;
	device->CheckHWBlit     = NULL;
	device->FillHWRect      = NULL;
	device->SetHWColorKey   = NULL;
	device->SetHWAlpha      = NULL;
	device->LockHWSurface   = DSp_LockHWSurface;
	device->UnlockHWSurface = DSp_UnlockHWSurface;
	device->FlipHWSurface   = DSp_FlipHWSurface;
	device->FreeHWSurface   = DSp_FreeHWSurface;
#ifdef HAVE_OPENGL
	device->GL_MakeCurrent  = Mac_GL_MakeCurrent;
	device->GL_SwapBuffers  = DSp_GL_SwapBuffers;
#endif
	device->SetCaption = NULL;
	device->SetIcon = NULL;
	device->IconifyWindow = NULL;
	device->GrabInput = NULL;
	device->GetWMInfo = NULL;
	device->FreeWMCursor    = Mac_FreeWMCursor;
	device->CreateWMCursor  = Mac_CreateWMCursor;
	device->ShowWMCursor    = Mac_ShowWMCursor;
	device->WarpWMCursor    = Mac_WarpWMCursor;
	device->InitOSKeymap    = Mac_InitOSKeymap;
	device->PumpEvents      = Mac_PumpEvents;
	
	device->GrabInput      = NULL;
	device->CheckMouseMode = NULL;
	
	device->free = DSp_DeleteDevice;

	return device;
}

VideoBootStrap DSp_bootstrap = {
	"DSp", "MacOS DrawSprocket",
	DSp_Available, DSp_CreateDevice
};

/* Use DSp/Display Manager to build mode list for given screen */
static SDL_Rect**  DSp_BuildModeList (const GDHandle gDevice)
{
	DSpContextAttributes  attributes;
	DSpContextReference   context;
	DisplayIDType         displayID;
	SDL_Rect temp_list [16];
	SDL_Rect **mode_list;
	int width, height, i, j;
        
        #if TARGET_API_MAC_OSX		
	
        displayID = 0;
        
        #else
        /* Ask Display Manager for integer id of screen device */
	if ( DMGetDisplayIDByGDevice (gDevice, &displayID, SDL_TRUE) != noErr ) {
		return NULL;
	}
	#endif
	/* Get the first possible DSp context on this device */
	if ( DSpGetFirstContext (displayID, &context) != noErr ) {
		return NULL;
	}
	
	if ( DSpContext_GetAttributes (context, &attributes) != noErr )
		return NULL;
			
	for ( i = 0; i < SDL_TABLESIZE(temp_list); i++ ) {
		width  = attributes.displayWidth;
		height = attributes.displayHeight;
		
		temp_list [i].x = 0 | attributes.displayBestDepth;
		temp_list [i].y = 0;
		temp_list [i].w = width;
		temp_list [i].h = height;
	
		/* DSp will report many different contexts with the same width and height. */
		/* They will differ in bit depth and refresh rate. */
		/* We will ignore them until we reach one with a different width/height */
		/* When there are no more contexts to look at, we will quit building the list*/
		while ( width == attributes.displayWidth && height == attributes.displayHeight ) {
		
			OSStatus err = DSpGetNextContext (context, &context);
			if (err != noErr)
				if (err == kDSpContextNotFoundErr)
					goto done;
				else
					return NULL;		
			
			if ( DSpContext_GetAttributes (context, &attributes) != noErr )
				return NULL;
				
			temp_list [i].x |= attributes.displayBestDepth;
		}
	}
done:
	i++;          /* i was not incremented before kicking out of the loop */
	
	mode_list = (SDL_Rect**) malloc (sizeof (SDL_Rect*) * (i+1));
	if (mode_list) {
	
	   /* -dw- new stuff: build in reverse order so largest sizes list first */
		for (j = i-1; j >= 0; j--) {
			mode_list [j] = (SDL_Rect*) malloc (sizeof (SDL_Rect));	
			if (mode_list [j])
				memcpy (mode_list [j], &(temp_list [j]), sizeof (SDL_Rect));
			else {
				SDL_OutOfMemory ();
				return NULL;
			}
		}
		mode_list [i] = NULL;		/* append null to the end */
	}
	else {
		SDL_OutOfMemory ();
		return NULL;
	}
		
	return mode_list;
}

static void DSp_IsHWAvailable (_THIS, SDL_PixelFormat *vformat)
{
  /* 
     VRAM GWorlds are only available on OS 9 or later.
     Even with OS 9, some display drivers won't support it, 
     so we create a test GWorld and check for errors. 
  */

  long versionSystem;

  dsp_vram_available = SDL_FALSE;
  dsp_agp_available  = SDL_FALSE;
  
  Gestalt ('sysv', &versionSystem);
  if (0x00000860 < (versionSystem & 0x0000FFFF)) {
    
    GWorldPtr offscreen;
    OSStatus  err;
    Rect      bounds;
    
    SetRect (&bounds, 0, 0, 320, 240);
    
    err = NewGWorld (&offscreen, vformat->BitsPerPixel, &bounds, NULL, SDL_Display, useDistantHdwrMem | noNewDevice);
    if (err == noErr) {
      dsp_vram_available = SDL_TRUE;
      DisposeGWorld (offscreen);
    }
	
    err = NewGWorld (&offscreen, vformat->BitsPerPixel, &bounds, NULL, SDL_Display, useLocalHdwrMem | noNewDevice);
    if (err == noErr) {
      DisposeGWorld (offscreen);
      dsp_agp_available = SDL_TRUE;
    }
  }
}

static int DSp_GetMainDevice (_THIS, GDHandle *device)
{
    
#if TARGET_API_MAC_OSX
        /* DSpUserSelectContext not available on OS X */
        *device = GetMainDevice();
        return 0;
#else
        
	DSpContextAttributes attrib;
	DSpContextReference  context;
	DisplayIDType        display_id;
	GDHandle             main_device;
	GDHandle             device_list;
	
	device_list = GetDeviceList ();
	main_device = GetMainDevice ();
	
	/* Quick check to avoid slower method when only one display exists */

⌨️ 快捷键说明

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