| /* |
| SDL - Simple DirectMedia Layer |
| Copyright (C) 1997-2006 Sam Lantinga |
| |
| This library is free software; you can redistribute it and/or |
| modify it under the terms of the GNU Lesser General Public |
| License as published by the Free Software Foundation; either |
| version 2.1 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 |
| Lesser General Public License for more details. |
| |
| You should have received a copy of the GNU Lesser General Public |
| License along with this library; if not, write to the Free Software |
| Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
| |
| Sam Lantinga |
| slouken@libsdl.org |
| */ |
| #include "SDL_config.h" |
| |
| /* |
| * CGX based SDL video driver implementation by Gabriele Greco |
| * gabriele.greco@aruba.it |
| */ |
| |
| #include "SDL_endian.h" |
| #include "SDL_timer.h" |
| #include "SDL_thread.h" |
| #include "SDL_video.h" |
| #include "SDL_mouse.h" |
| #include "../SDL_sysvideo.h" |
| #include "../SDL_pixels_c.h" |
| #include "../../events/SDL_events_c.h" |
| #include "SDL_cgxgl_c.h" |
| #include "SDL_cgxvideo.h" |
| #include "SDL_cgxwm_c.h" |
| #include "SDL_amigamouse_c.h" |
| #include "SDL_amigaevents_c.h" |
| #include "SDL_cgxmodes_c.h" |
| #include "SDL_cgximage_c.h" |
| |
| /* Initialization/Query functions */ |
| static int CGX_VideoInit(_THIS, SDL_PixelFormat *vformat); |
| static SDL_Surface *CGX_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags); |
| static int CGX_ToggleFullScreen(_THIS, int on); |
| static void CGX_UpdateMouse(_THIS); |
| static int CGX_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors); |
| static void CGX_VideoQuit(_THIS); |
| |
| /* CGX driver bootstrap functions */ |
| |
| struct Library *CyberGfxBase=NULL; |
| struct IntuitionBase *IntuitionBase=NULL; |
| struct GfxBase *GfxBase=NULL; |
| |
| int CGX_SetGamma(_THIS, float red, float green, float blue) |
| { |
| SDL_SetError("Gamma correction not supported"); |
| return -1; |
| } |
| |
| int CGX_GetGamma(_THIS, float red, float green, float blue) |
| { |
| SDL_SetError("Gamma correction not supported"); |
| return -1; |
| } |
| |
| int CGX_SetGammaRamp(_THIS, Uint16 *ramp) |
| { |
| #if 0 |
| Int i, ncolors; |
| XColor xcmap[256]; |
| |
| /* See if actually setting the gamma is supported */ |
| if ( SDL_Visual->class != DirectColor ) { |
| SDL_SetError("Gamma correction not supported on this visual"); |
| return(-1); |
| } |
| |
| /* Calculate the appropriate palette for the given gamma ramp */ |
| ncolors = SDL_Visual->map_entries; |
| for ( i=0; i<ncolors; ++i ) { |
| Uint8 c = (256 * i / ncolors); |
| xcmap[i].pixel = SDL_MapRGB(this->screen->format, c, c, c); |
| xcmap[i].red = ramp[0*256+c]; |
| xcmap[i].green = ramp[1*256+c]; |
| xcmap[i].blue = ramp[2*256+c]; |
| xcmap[i].flags = (DoRed|DoGreen|DoBlue); |
| } |
| XStoreColors(GFX_Display, SDL_XColorMap, xcmap, ncolors); |
| XSync(GFX_Display, False); |
| |
| return(0); |
| |
| #else |
| SDL_SetError("Gamma correction not supported on this visual"); |
| return(-1); |
| |
| #endif |
| } |
| |
| static void DestroyScreen(_THIS) |
| { |
| if(currently_fullscreen) |
| { |
| if(this->hidden->dbuffer) |
| { |
| extern struct MsgPort *safeport,*dispport; |
| |
| this->hidden->dbuffer=0; |
| |
| if(safeport) |
| { |
| while(GetMsg(safeport)!=NULL); |
| DeleteMsgPort(safeport); |
| } |
| if(dispport) |
| { |
| while(GetMsg(dispport)!=NULL); |
| DeleteMsgPort(dispport); |
| } |
| |
| this->hidden->SB[0]->sb_DBufInfo->dbi_SafeMessage.mn_ReplyPort=this->hidden->SB[0]->sb_DBufInfo->dbi_DispMessage.mn_ReplyPort=NULL; |
| this->hidden->SB[1]->sb_DBufInfo->dbi_SafeMessage.mn_ReplyPort=this->hidden->SB[1]->sb_DBufInfo->dbi_DispMessage.mn_ReplyPort=NULL; |
| |
| if(this->hidden->SB[1]) |
| FreeScreenBuffer(SDL_Display,this->hidden->SB[1]); |
| if(this->hidden->SB[0]) |
| FreeScreenBuffer(SDL_Display,this->hidden->SB[0]); |
| |
| |
| this->hidden->SB[0]=this->hidden->SB[1]=NULL; |
| |
| if(SDL_RastPort && SDL_RastPort != &SDL_Display->RastPort) |
| SDL_free(SDL_RastPort); |
| |
| SDL_RastPort=NULL; |
| } |
| CloseScreen(GFX_Display); |
| currently_fullscreen=0; |
| } |
| else if(GFX_Display) |
| UnlockPubScreen(NULL,GFX_Display); |
| |
| GFX_Display = NULL; |
| } |
| |
| static int CGX_Available(void) |
| { |
| struct Library *l; |
| |
| l = OpenLibrary("cybergraphics.library",0L); |
| |
| if ( l != NULL ) { |
| D(bug("CGX video device AVAILABLE\n")); |
| CloseLibrary(l); |
| } |
| D(else bug("**CGX video device UNAVAILABLE\n")); |
| |
| return(l != NULL); |
| } |
| |
| static void CGX_DeleteDevice(SDL_VideoDevice *device) |
| { |
| if ( device ) { |
| if ( device->hidden ) { |
| SDL_free(device->hidden); |
| } |
| if ( device->gl_data ) { |
| SDL_free(device->gl_data); |
| } |
| SDL_free(device); |
| } |
| } |
| |
| static SDL_VideoDevice *CGX_CreateDevice(int devindex) |
| { |
| SDL_VideoDevice *device; |
| |
| /* Initialize all variables that we clean on shutdown */ |
| device = (SDL_VideoDevice *)SDL_malloc(sizeof(SDL_VideoDevice)); |
| if ( device ) { |
| SDL_memset(device, 0, (sizeof *device)); |
| device->hidden = (struct SDL_PrivateVideoData *) |
| SDL_malloc((sizeof *device->hidden)); |
| device->gl_data = (struct SDL_PrivateGLData *) |
| SDL_malloc((sizeof *device->gl_data)); |
| } |
| if ( (device == NULL) || (device->hidden == NULL) || |
| (device->gl_data == NULL) ) { |
| D(bug("Unable to create video device!\n")); |
| SDL_OutOfMemory(); |
| CGX_DeleteDevice(device); |
| return(0); |
| } |
| SDL_memset(device->hidden, 0, sizeof(*device->hidden)); |
| SDL_memset(device->gl_data, 0, sizeof(*device->gl_data)); |
| |
| /* Set the driver flags */ |
| device->handles_any_size = 1; |
| |
| /* Set the function pointers */ |
| device->VideoInit = CGX_VideoInit; |
| device->ListModes = CGX_ListModes; |
| device->SetVideoMode = CGX_SetVideoMode; |
| device->ToggleFullScreen = CGX_ToggleFullScreen; |
| device->UpdateMouse = CGX_UpdateMouse; |
| device->SetColors = CGX_SetColors; |
| device->UpdateRects = NULL; |
| device->VideoQuit = CGX_VideoQuit; |
| device->AllocHWSurface = CGX_AllocHWSurface; |
| device->CheckHWBlit = CGX_CheckHWBlit; |
| device->FillHWRect = CGX_FillHWRect; |
| device->SetHWColorKey = CGX_SetHWColorKey; |
| device->SetHWAlpha = NULL; |
| device->LockHWSurface = CGX_LockHWSurface; |
| device->UnlockHWSurface = CGX_UnlockHWSurface; |
| device->FlipHWSurface = CGX_FlipHWSurface; |
| device->FreeHWSurface = CGX_FreeHWSurface; |
| device->SetGamma = CGX_SetGamma; |
| device->GetGamma = CGX_GetGamma; |
| device->SetGammaRamp = CGX_SetGammaRamp; |
| device->GetGammaRamp = NULL; |
| #if SDL_VIDEO_OPENGL |
| device->GL_LoadLibrary = CGX_GL_LoadLibrary; |
| device->GL_GetProcAddress = CGX_GL_GetProcAddress; |
| device->GL_GetAttribute = CGX_GL_GetAttribute; |
| device->GL_MakeCurrent = CGX_GL_MakeCurrent; |
| device->GL_SwapBuffers = CGX_GL_SwapBuffers; |
| #endif |
| device->SetIcon = CGX_SetIcon; |
| device->SetCaption = CGX_SetCaption; |
| device->IconifyWindow = NULL; /* CGX_IconifyWindow; */ |
| device->GrabInput = NULL /* CGX_GrabInput*/; |
| device->GetWMInfo = CGX_GetWMInfo; |
| device->FreeWMCursor = amiga_FreeWMCursor; |
| device->CreateWMCursor = amiga_CreateWMCursor; |
| device->ShowWMCursor = amiga_ShowWMCursor; |
| device->WarpWMCursor = amiga_WarpWMCursor; |
| device->CheckMouseMode = amiga_CheckMouseMode; |
| device->InitOSKeymap = amiga_InitOSKeymap; |
| device->PumpEvents = amiga_PumpEvents; |
| |
| device->free = CGX_DeleteDevice; |
| |
| return device; |
| } |
| |
| VideoBootStrap CGX_bootstrap = { |
| "CGX", "AmigaOS CyberGraphics", CGX_Available, CGX_CreateDevice |
| }; |
| |
| Uint32 MakeBitMask(_THIS,int type,int format,int *bpp) |
| { |
| D(if(type==0)bug("REAL pixel format: ")); |
| |
| if(this->hidden->depth==*bpp) |
| { |
| |
| switch(format) |
| { |
| case PIXFMT_LUT8: |
| D(if(type==0)bug("LUT8\n")); |
| return 0; |
| case PIXFMT_BGR15: |
| case PIXFMT_RGB15PC: |
| switch(type) |
| { |
| case 0: |
| D(bug("RGB15PC/BGR15\n")); |
| return 31; |
| case 1: |
| return 992; |
| case 2: |
| return 31744; |
| } |
| case PIXFMT_RGB15: |
| case PIXFMT_BGR15PC: |
| switch(type) |
| { |
| case 0: |
| D(bug("RGB15/BGR15PC\n")); |
| return 31744; |
| case 1: |
| return 992; |
| case 2: |
| return 31; |
| } |
| case PIXFMT_BGR16PC: |
| case PIXFMT_RGB16: |
| switch(type) |
| { |
| case 0: |
| D(bug("RGB16PC\n")); |
| return 63488; |
| case 1: |
| return 2016; |
| case 2: |
| return 31; |
| } |
| case PIXFMT_BGR16: |
| case PIXFMT_RGB16PC: |
| switch(type) |
| { |
| case 0: |
| D(bug("RGB16PC/BGR16\n")); |
| return 31; |
| case 1: |
| return 2016; |
| case 2: |
| return 63488; |
| } |
| |
| case PIXFMT_RGB24: |
| switch(type) |
| { |
| case 0: |
| D(bug("RGB24/BGR24\n")); |
| return 0xff0000; |
| case 1: |
| return 0xff00; |
| case 2: |
| return 0xff; |
| } |
| case PIXFMT_BGR24: |
| switch(type) |
| { |
| case 0: |
| D(bug("BGR24\n")); |
| return 0xff; |
| case 1: |
| return 0xff00; |
| case 2: |
| return 0xff0000; |
| } |
| case PIXFMT_ARGB32: |
| switch(type) |
| { |
| case 0: |
| D(bug("ARGB32\n")); |
| return 0xff0000; |
| case 1: |
| return 0xff00; |
| case 2: |
| return 0xff; |
| } |
| case PIXFMT_BGRA32: |
| switch(type) |
| { |
| case 0: |
| D(bug("BGRA32\n")); |
| return 0xff00; |
| case 1: |
| return 0xff0000; |
| case 2: |
| return 0xff000000; |
| } |
| case PIXFMT_RGBA32: |
| switch(type) |
| { |
| case 0: |
| D(bug("RGBA32\n")); |
| return 0xff000000; |
| case 1: |
| return 0xff0000; |
| case 2: |
| return 0xff00; |
| } |
| default: |
| D(bug("Unknown pixel format! Default to 24bit\n")); |
| return (Uint32) (255<<(type*8)); |
| } |
| } |
| else |
| { |
| D(if(type==0)bug("DIFFERENT from screen.\nAllocated screen format: ")); |
| |
| switch(*bpp) |
| { |
| case 32: |
| D(if(type==0) bug("RGBA32\n")); |
| switch(type) |
| { |
| case 0: |
| return 0xff000000; |
| case 1: |
| return 0xff0000; |
| case 2: |
| return 0xff00; |
| } |
| break; |
| case 24: |
| use_truecolor: |
| switch(type) |
| { |
| case 0: |
| D(bug("RGB24\n")); |
| return 0xff0000; |
| case 1: |
| return 0xff00; |
| case 2: |
| return 0xff; |
| } |
| case 16: |
| case 15: |
| D(if(type==0) bug("Not supported, switching to 24bit!\n")); |
| *bpp=24; |
| goto use_truecolor; |
| break; |
| default: |
| D(if(type==0)bug("This is a chunky display\n")); |
| // For chunky display mask is always 0; |
| return 0; |
| } |
| } |
| return 0; |
| } |
| |
| static int CGX_VideoInit(_THIS, SDL_PixelFormat *vformat) |
| { |
| int i; |
| struct Library *RTGBase; |
| |
| D(bug("VideoInit... Opening libraries\n")); |
| |
| if(!IntuitionBase) { |
| if( !(IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",39L))) { |
| SDL_SetError("Couldn't open intuition V39+"); |
| return -1; |
| } |
| } |
| |
| if(!GfxBase) { |
| if( !(GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",39L))) { |
| SDL_SetError("Couldn't open graphics V39+"); |
| return -1; |
| } |
| } |
| |
| if(!CyberGfxBase) { |
| if( !(CyberGfxBase=OpenLibrary("cybergraphics.library",40L))) { |
| SDL_SetError("Couldn't open cybergraphics."); |
| return(-1); |
| } |
| } |
| |
| if(RTGBase=OpenLibrary("libs:picasso96/rtg.library",0L)) { |
| extern int use_picasso96; |
| |
| CloseLibrary(RTGBase); |
| use_picasso96=1; |
| } |
| |
| D(bug("Library intialized, locking screen...\n")); |
| |
| SDL_Display = LockPubScreen(NULL); |
| |
| if ( SDL_Display == NULL ) { |
| D(bug("Cannot lock display...\n")); |
| SDL_SetError("Couldn't lock the display"); |
| return(-1); |
| } |
| this->info.current_w = SDL_Display->Width; |
| this->info.current_h = SDL_Display->Height; |
| |
| D(bug("Checking if we are using a CGX native display...\n")); |
| |
| if(!IsCyberModeID(GetVPModeID(&SDL_Display->ViewPort))) |
| { |
| Uint32 okid=BestCModeIDTags(CYBRBIDTG_NominalWidth,SDL_Display->Width, |
| CYBRBIDTG_NominalHeight,SDL_Display->Height, |
| CYBRBIDTG_Depth,8, |
| TAG_DONE); |
| |
| D(bug("Default visual is not CGX native!\n")); |
| |
| UnlockPubScreen(NULL,SDL_Display); |
| |
| GFX_Display=NULL; |
| |
| if(okid!=INVALID_ID) |
| { |
| GFX_Display=OpenScreenTags(NULL, |
| SA_Width,SDL_Display->Width, |
| SA_Height,SDL_Display->Height, |
| SA_Depth,8,SA_Quiet,TRUE, |
| SA_ShowTitle,FALSE, |
| SA_DisplayID,okid, |
| TAG_DONE); |
| } |
| |
| if(!GFX_Display) |
| { |
| SDL_SetError("Unable to open a suited CGX display"); |
| return -1; |
| } |
| else SDL_Display=GFX_Display; |
| |
| } |
| else GFX_Display = SDL_Display; |
| |
| |
| /* See whether or not we need to swap pixels */ |
| |
| swap_pixels = 0; |
| |
| // Non e' detto che sia cosi' pero', alcune schede potrebbero gestire i modi in modo differente |
| |
| if ( SDL_BYTEORDER == SDL_LIL_ENDIAN ) { |
| swap_pixels = 1; |
| } |
| |
| D(bug("Before GetVideoModes....\n")); |
| |
| /* Get the available video modes */ |
| if(CGX_GetVideoModes(this) < 0) |
| return -1; |
| |
| /* Determine the default screen depth: |
| Use the default visual (or at least one with the same depth) */ |
| |
| for(i = 0; i < this->hidden->nvisuals; i++) |
| if(this->hidden->visuals[i].depth == GetCyberMapAttr(SDL_Display->RastPort.BitMap,CYBRMATTR_DEPTH)) |
| break; |
| if(i == this->hidden->nvisuals) { |
| /* default visual was useless, take the deepest one instead */ |
| i = 0; |
| } |
| SDL_Visual = this->hidden->visuals[i].visual; |
| |
| // SDL_XColorMap = SDL_DisplayColormap; |
| |
| this->hidden->depth = this->hidden->visuals[i].depth; |
| D(bug("Init: Setting screen depth to: %ld\n",this->hidden->depth)); |
| vformat->BitsPerPixel = this->hidden->visuals[i].depth; /* this->hidden->visuals[i].bpp; */ |
| |
| { |
| int form; |
| APTR handle; |
| struct DisplayInfo info; |
| |
| if(!(handle=FindDisplayInfo(this->hidden->visuals[i].visual))) |
| { |
| D(bug("Unable to get visual info...\n")); |
| return -1; |
| } |
| |
| if(!GetDisplayInfoData(handle,(char *)&info,sizeof(struct DisplayInfo),DTAG_DISP,NULL)) { |
| D(bug("Unable to get visual info data...\n")); |
| return -1; |
| } |
| |
| form=GetCyberIDAttr(CYBRIDATTR_PIXFMT,SDL_Visual); |
| |
| // In this case I use makebitmask in a way that I'm sure I'll get PIXFMT pixel mask |
| |
| if ( vformat->BitsPerPixel > 8 ) |
| { |
| vformat->Rmask = MakeBitMask(this,0,form,&this->hidden->depth); |
| vformat->Gmask = MakeBitMask(this,1,form,&this->hidden->depth); |
| vformat->Bmask = MakeBitMask(this,2,form,&this->hidden->depth); |
| } |
| } |
| |
| /* See if we have been passed a window to use */ |
| /* SDL_windowid = SDL_getenv("SDL_WINDOWID"); */ |
| SDL_windowid=NULL; |
| |
| /* Create the blank cursor */ |
| SDL_BlankCursor = AllocMem(16,MEMF_CHIP|MEMF_CLEAR); |
| |
| /* Fill in some window manager capabilities */ |
| this->info.wm_available = 1; |
| this->info.blit_hw = 1; |
| this->info.blit_hw_CC = 1; |
| this->info.blit_sw = 1; |
| this->info.blit_fill = 1; |
| this->info.video_mem=2000000; // Not always true but almost any Amiga card has this memory! |
| |
| this->hidden->same_format=0; |
| SDL_RastPort=&SDL_Display->RastPort; |
| /* We're done! */ |
| D(bug("End of CGX_VideoInit\n")); |
| |
| return(0); |
| } |
| |
| void CGX_DestroyWindow(_THIS, SDL_Surface *screen) |
| { |
| D(bug("Destroy Window...\n")); |
| |
| if ( ! SDL_windowid ) { |
| /* Hide the managed window */ |
| int was_fullscreen=0; |
| |
| /* Clean up OpenGL */ |
| if ( screen ) { |
| screen->flags &= ~(SDL_OPENGL|SDL_OPENGLBLIT); |
| } |
| |
| if ( screen && (screen->flags & SDL_FULLSCREEN) ) { |
| was_fullscreen=1; |
| screen->flags &= ~SDL_FULLSCREEN; |
| // CGX_LeaveFullScreen(this); tolto x crash |
| } |
| |
| /* Destroy the output window */ |
| if ( SDL_Window ) { |
| CloseWindow(SDL_Window); |
| SDL_Window=NULL; |
| } |
| |
| /* Free the colormap entries */ |
| if ( SDL_XPixels ) { |
| int numcolors; |
| unsigned long pixel; |
| |
| if(this->screen->format&&this->hidden->depth==8&&!was_fullscreen) |
| { |
| numcolors = 1<<this->screen->format->BitsPerPixel; |
| |
| if(numcolors>256) |
| numcolors=256; |
| |
| if(!was_fullscreen&&this->hidden->depth==8) |
| { |
| for ( pixel=0; pixel<numcolors; pixel++ ) |
| { |
| if(SDL_XPixels[pixel]>=0) |
| ReleasePen(GFX_Display->ViewPort.ColorMap,SDL_XPixels[pixel]); |
| } |
| } |
| } |
| SDL_free(SDL_XPixels); |
| SDL_XPixels = NULL; |
| } |
| } |
| } |
| |
| static void CGX_SetSizeHints(_THIS, int w, int h, Uint32 flags) |
| { |
| if ( flags & SDL_RESIZABLE ) { |
| WindowLimits(SDL_Window, 32, 32,4096,4096); |
| } else { |
| WindowLimits(SDL_Window, w,h,w,h); |
| } |
| if ( flags & SDL_FULLSCREEN ) { |
| flags&=~SDL_RESIZABLE; |
| } else if ( SDL_getenv("SDL_VIDEO_CENTERED") ) { |
| int display_w, display_h; |
| |
| display_w = SDL_Display->Width; |
| display_h = SDL_Display->Height; |
| ChangeWindowBox(SDL_Window,(display_w - w - SDL_Window->BorderLeft-SDL_Window->BorderRight)/2, |
| (display_h - h - SDL_Window->BorderTop-SDL_Window->BorderBottom)/2, |
| w+SDL_Window->BorderLeft+SDL_Window->BorderRight, |
| h+SDL_Window->BorderTop+SDL_Window->BorderBottom); |
| } |
| } |
| |
| int CGX_CreateWindow(_THIS, SDL_Surface *screen, |
| int w, int h, int bpp, Uint32 flags) |
| { |
| #if 0 |
| int i, depth; |
| Uint32 vis; |
| #endif |
| D(bug("CGX_CreateWindow\n")); |
| |
| /* If a window is already present, destroy it and start fresh */ |
| if ( SDL_Window ) { |
| CGX_DestroyWindow(this, screen); |
| } |
| |
| /* See if we have been given a window id */ |
| if ( SDL_windowid ) { |
| SDL_Window = (struct Window *)atol(SDL_windowid); |
| } else { |
| SDL_Window = 0; |
| } |
| |
| /* find out which visual we are going to use */ |
| #if 0 |
| /* questo l'ho spostato nell'apertura dello schermo, in quanto su Amiga le finestre |
| hanno il pixel mode degli schermi. |
| */ |
| /*if ( flags & SDL_OPENGL ) { |
| SDL_SetError("OpenGL not supported by the Amiga SDL!"); |
| return -1; |
| } |
| else {*/ |
| for ( i = 0; i < this->hidden->nvisuals; i++ ) { |
| if ( this->hidden->visuals[i].depth == bpp ) /* era .depth */ |
| break; |
| } |
| if ( i == this->hidden->nvisuals ) { |
| SDL_SetError("No matching visual for requested depth"); |
| return -1; /* should never happen */ |
| } |
| vis = this->hidden->visuals[i].visual; |
| depth = this->hidden->visuals[i].depth; |
| // } |
| SDL_Visual = vis; |
| this->hidden->depth = depth; |
| D(bug("Setting screen depth to: %ld\n",this->hidden->depth)); |
| #endif |
| |
| /* Allocate the new pixel format for this video mode */ |
| { |
| Uint32 form; |
| APTR handle; |
| struct DisplayInfo info; |
| |
| if(!(handle=FindDisplayInfo(SDL_Visual))) |
| return -1; |
| |
| if(!GetDisplayInfoData(handle,(char *)&info,sizeof(struct DisplayInfo),DTAG_DISP,NULL)) |
| return -1; |
| |
| form=GetCyberIDAttr(CYBRIDATTR_PIXFMT,SDL_Visual); |
| |
| if(flags&SDL_HWSURFACE) |
| { |
| if(bpp!=this->hidden->depth) |
| { |
| bpp=this->hidden->depth; |
| D(bug("Accel forces bpp to be equal (%ld)\n",bpp)); |
| } |
| } |
| |
| D(bug("BEFORE screen allocation: bpp:%ld (real:%ld)\n",bpp,this->hidden->depth)); |
| |
| /* With this call if needed I'll revert the wanted bpp to a bpp best suited for the display, actually occurs |
| only with requested format 15/16bit and display format != 15/16bit |
| */ |
| |
| if ( ! SDL_ReallocFormat(screen, bpp, |
| MakeBitMask(this,0,form,&bpp), MakeBitMask(this,1,form,&bpp), MakeBitMask(this,2,form,&bpp), 0) ) |
| return -1; |
| |
| D(bug("AFTER screen allocation: bpp:%ld (real:%ld)\n",bpp,this->hidden->depth)); |
| |
| } |
| |
| /* Create the appropriate colormap */ |
| /* |
| if ( SDL_XColorMap != SDL_DisplayColormap ) { |
| XFreeColormap(SDL_Display, SDL_XColorMap); |
| } |
| */ |
| if ( GetCyberMapAttr(SDL_Display->RastPort.BitMap,CYBRMATTR_PIXFMT)==PIXFMT_LUT8 || bpp==8 ) { |
| int ncolors,i; |
| D(bug("XPixels palette allocation...\n")); |
| |
| /* Allocate the pixel flags */ |
| |
| if(bpp==8) |
| ncolors=256; |
| else |
| ncolors = 1 << screen->format->BitsPerPixel; |
| |
| SDL_XPixels = (Sint32 *)SDL_malloc(ncolors * sizeof(Sint32)); |
| |
| if(SDL_XPixels == NULL) { |
| SDL_OutOfMemory(); |
| return -1; |
| } |
| |
| |
| for(i=0;i<ncolors;i++) |
| SDL_XPixels[i]=-1; |
| |
| /* always allocate a private colormap on non-default visuals */ |
| if(bpp==8) |
| flags |= SDL_HWPALETTE; |
| |
| if ( flags & SDL_HWPALETTE ) |
| screen->flags |= SDL_HWPALETTE; |
| } |
| |
| /* resize the (possibly new) window manager window */ |
| |
| /* Create (or use) the X11 display window */ |
| |
| if ( !SDL_windowid ) { |
| if( flags & SDL_FULLSCREEN ) |
| { |
| SDL_Window = OpenWindowTags(NULL,WA_Width,w,WA_Height,h, |
| WA_Flags,WFLG_ACTIVATE|WFLG_RMBTRAP|WFLG_BORDERLESS|WFLG_BACKDROP|WFLG_REPORTMOUSE, |
| WA_IDCMP,IDCMP_RAWKEY|IDCMP_MOUSEBUTTONS|IDCMP_MOUSEMOVE, |
| WA_CustomScreen,(ULONG)SDL_Display, |
| TAG_DONE); |
| |
| D(bug("Opening backdrop window %ldx%ld on display %lx!\n",w,h,SDL_Display)); |
| } |
| else |
| { |
| /* Create GimmeZeroZero window when OpenGL is used */ |
| unsigned long gzz = FALSE; |
| if( flags & SDL_OPENGL ) { |
| gzz = TRUE; |
| } |
| |
| SDL_Window = OpenWindowTags(NULL,WA_InnerWidth,w,WA_InnerHeight,h, |
| WA_Flags,WFLG_REPORTMOUSE|WFLG_ACTIVATE|WFLG_RMBTRAP | ((flags&SDL_NOFRAME) ? 0 : (WFLG_DEPTHGADGET|WFLG_CLOSEGADGET|WFLG_DRAGBAR | ((flags&SDL_RESIZABLE) ? WFLG_SIZEGADGET|WFLG_SIZEBBOTTOM : 0))), |
| WA_IDCMP,IDCMP_RAWKEY|IDCMP_CLOSEWINDOW|IDCMP_MOUSEBUTTONS|IDCMP_NEWSIZE|IDCMP_MOUSEMOVE, |
| WA_PubScreen,(ULONG)SDL_Display, |
| WA_GimmeZeroZero, gzz, |
| TAG_DONE); |
| D(bug("Opening WB window of size: %ldx%ld!\n",w,h)); |
| } |
| |
| if(!SDL_Window) |
| return -1; |
| } |
| |
| this->hidden->BytesPerPixel=GetCyberMapAttr(SDL_Window->RPort->BitMap,CYBRMATTR_BPPIX); |
| |
| if(screen->flags & SDL_DOUBLEBUF) |
| { |
| if(SDL_RastPort=SDL_malloc(sizeof(struct RastPort))) |
| { |
| InitRastPort(SDL_RastPort); |
| SDL_RastPort->BitMap=this->hidden->SB[1]->sb_BitMap; |
| } |
| else |
| return -1; |
| } |
| else SDL_RastPort=SDL_Window->RPort; |
| |
| if(flags&SDL_HWSURFACE) |
| screen->flags|=SDL_HWSURFACE; |
| |
| if( !SDL_windowid ) { |
| CGX_SetSizeHints(this, w, h, flags); |
| } |
| |
| /* Set our colormaps when not setting a GL mode */ |
| /* |
| if ( ! (flags & SDL_OPENGL) ) { |
| XSetWindowColormap(SDL_Display, SDL_Window, SDL_XColorMap); |
| } |
| */ |
| |
| /* Map them both and go fullscreen, if requested */ |
| if ( ! SDL_windowid ) { |
| if ( flags & SDL_FULLSCREEN ) { |
| screen->flags |= SDL_FULLSCREEN; |
| currently_fullscreen=1; |
| // CGX_EnterFullScreen(this); Ci siamo gia'! |
| } else { |
| screen->flags &= ~SDL_FULLSCREEN; |
| } |
| } |
| screen->w = w; |
| screen->h = h; |
| screen->pitch = SDL_CalculatePitch(screen); |
| CGX_ResizeImage(this, screen, flags); |
| |
| /* Make OpenGL Context if needed*/ |
| if(flags & SDL_OPENGL) { |
| if(this->gl_data->gl_active == 0) { |
| if(CGX_GL_Init(this) < 0) |
| return -1; |
| else |
| screen->flags |= SDL_OPENGL; |
| } |
| else { |
| if(CGX_GL_Update(this) < 0) |
| return -1; |
| else |
| screen->flags |= SDL_OPENGL; |
| } |
| } |
| } |
| |
| int CGX_ResizeWindow(_THIS, |
| SDL_Surface *screen, int w, int h, Uint32 flags) |
| { |
| D(bug("CGX_ResizeWindow\n")); |
| |
| if ( ! SDL_windowid ) { |
| /* Resize the window manager window */ |
| CGX_SetSizeHints(this, w, h, flags); |
| |
| ChangeWindowBox(SDL_Window,SDL_Window->LeftEdge,SDL_Window->TopEdge, w+SDL_Window->BorderLeft+SDL_Window->BorderRight, |
| h+SDL_Window->BorderTop+SDL_Window->BorderBottom); |
| |
| screen->w = w; |
| screen->h = h; |
| screen->pitch = SDL_CalculatePitch(screen); |
| CGX_ResizeImage(this, screen, flags); |
| } |
| return(0); |
| } |
| |
| static SDL_Surface *CGX_SetVideoMode(_THIS, SDL_Surface *current, |
| int width, int height, int bpp, Uint32 flags) |
| { |
| Uint32 saved_flags; |
| int needcreate=0; |
| |
| D(bug("CGX_SetVideoMode current:%lx\n",current)); |
| |
| /* Lock the event thread, in multi-threading environments */ |
| SDL_Lock_EventThread(); |
| |
| // Check if the window needs to be closed or can be resized |
| |
| if( (flags&SDL_FULLSCREEN) || (current && current->flags&SDL_FULLSCREEN && !(flags&SDL_FULLSCREEN))) |
| needcreate=1; |
| |
| // Check if we need to close an already existing videomode... |
| |
| if(current && current->flags&SDL_FULLSCREEN && !(flags&SDL_FULLSCREEN)) { |
| unsigned long i; |
| D(bug("Destroying image, window & screen!\n")); |
| |
| CGX_DestroyImage(this,current); |
| CGX_DestroyWindow(this,current); |
| DestroyScreen(this); |
| GFX_Display=SDL_Display=LockPubScreen(NULL); |
| |
| bpp=this->hidden->depth=GetCyberMapAttr(SDL_Display->RastPort.BitMap,CYBRMATTR_DEPTH); |
| |
| for ( i = 0; i < this->hidden->nvisuals; i++ ) { |
| if ( this->hidden->visuals[i].depth == bpp ) /* era .depth */ |
| break; |
| } |
| if ( i == this->hidden->nvisuals ) { |
| SDL_SetError("No matching visual for requested depth"); |
| return NULL; /* should never happen */ |
| } |
| SDL_Visual = this->hidden->visuals[i].visual; |
| |
| D(bug("Setting screen depth to: %ld\n",this->hidden->depth)); |
| |
| } |
| /* Check the combination of flags we were passed */ |
| if ( flags & SDL_FULLSCREEN ) { |
| int i; |
| |
| /* Clear fullscreen flag if not supported */ |
| if ( SDL_windowid ) { |
| flags &= ~SDL_FULLSCREEN; |
| } |
| else if(current && current->flags&SDL_FULLSCREEN ) { |
| if(current->w!=width || |
| current->h!=height || |
| (this->hidden && this->hidden->depth!=bpp)) |
| { |
| D(bug("Deleting previous window...\n")); |
| CGX_DestroyImage(this,current); |
| CGX_DestroyWindow(this,current); |
| DestroyScreen(this); |
| goto buildnewscreen; |
| } |
| } |
| else |
| buildnewscreen: |
| { |
| Uint32 okid=BestCModeIDTags(CYBRBIDTG_NominalWidth,width, |
| CYBRBIDTG_NominalHeight,height, |
| CYBRBIDTG_Depth,bpp, |
| TAG_DONE); |
| |
| GFX_Display=NULL; |
| |
| D(bug("Opening screen...\n")); |
| |
| if(okid!=INVALID_ID) |
| GFX_Display=OpenScreenTags(NULL, |
| SA_Width,width, |
| SA_Height,height, |
| SA_Quiet,TRUE,SA_ShowTitle,FALSE, |
| SA_Depth,bpp, |
| SA_DisplayID,okid, |
| TAG_DONE); |
| |
| if(!GFX_Display) { |
| GFX_Display=SDL_Display; |
| flags &= ~SDL_FULLSCREEN; |
| flags &= ~SDL_DOUBLEBUF; |
| } |
| else { |
| UnlockPubScreen(NULL,SDL_Display); |
| SDL_Display=GFX_Display; |
| |
| D(bug("Screen opened.\n")); |
| |
| if(flags&SDL_DOUBLEBUF) { |
| int ok=0; |
| D(bug("Start of DBuffering allocations...\n")); |
| |
| if(this->hidden->SB[0]=AllocScreenBuffer(SDL_Display,NULL,SB_SCREEN_BITMAP)) { |
| |
| if(this->hidden->SB[1]=AllocScreenBuffer(SDL_Display,NULL,0L)) { |
| extern struct MsgPort *safeport,*dispport; |
| |
| safeport=CreateMsgPort(); |
| dispport=CreateMsgPort(); |
| |
| if(!safeport || !dispport) { |
| if(safeport) { |
| DeleteMsgPort(safeport); |
| safeport=NULL; |
| } |
| if(dispport) { |
| DeleteMsgPort(dispport); |
| dispport=NULL; |
| } |
| FreeScreenBuffer(SDL_Display,this->hidden->SB[0]); |
| FreeScreenBuffer(SDL_Display,this->hidden->SB[1]); |
| } |
| else { |
| extern ULONG safe_sigbit,disp_sigbit; |
| int i; |
| |
| safe_sigbit=1L<< safeport->mp_SigBit; |
| disp_sigbit=1L<< dispport->mp_SigBit; |
| |
| for(i=0;i<2;i++) { |
| this->hidden->SB[i]->sb_DBufInfo->dbi_SafeMessage.mn_ReplyPort=safeport; |
| this->hidden->SB[i]->sb_DBufInfo->dbi_DispMessage.mn_ReplyPort=dispport; |
| } |
| |
| ok=1; |
| D(bug("Dbuffering enabled!\n")); |
| this->hidden->dbuffer=1; |
| current->flags|=SDL_DOUBLEBUF; |
| } |
| } |
| else { |
| FreeScreenBuffer(SDL_Display,this->hidden->SB[1]); |
| this->hidden->SB[0]=NULL; |
| } |
| } |
| |
| if(!ok) |
| flags&=~SDL_DOUBLEBUF; |
| } |
| } |
| |
| if(GetCyberMapAttr(SDL_Display->RastPort.BitMap,CYBRMATTR_DEPTH)==bpp) |
| this->hidden->same_format=1; |
| } |
| |
| bpp=this->hidden->depth=GetCyberMapAttr(SDL_Display->RastPort.BitMap,CYBRMATTR_DEPTH); |
| D(bug("Setting screen depth to: %ld\n",this->hidden->depth)); |
| |
| for ( i = 0; i < this->hidden->nvisuals; i++ ) |
| if ( this->hidden->visuals[i].depth == bpp ) /* era .depth */ |
| break; |
| |
| if ( i == this->hidden->nvisuals ) { |
| SDL_SetError("No matching visual for requested depth"); |
| return NULL; /* should never happen */ |
| } |
| SDL_Visual = this->hidden->visuals[i].visual; |
| |
| } |
| |
| /* Set up the X11 window */ |
| saved_flags = current->flags; |
| |
| if (SDL_Window && (saved_flags&SDL_OPENGL) == (flags&SDL_OPENGL) |
| && bpp == current->format->BitsPerPixel && !needcreate) { |
| if (CGX_ResizeWindow(this, current, width, height, flags) < 0) { |
| current = NULL; |
| goto done; |
| } |
| } else { |
| if (CGX_CreateWindow(this,current,width,height,bpp,flags) < 0) { |
| current = NULL; |
| goto done; |
| } |
| } |
| |
| #if 0 |
| /* Set up the new mode framebuffer */ |
| if ( ((current->w != width) || (current->h != height)) || |
| ((saved_flags&SDL_OPENGL) != (flags&SDL_OPENGL)) ) { |
| current->w = width; |
| current->h = height; |
| current->pitch = SDL_CalculatePitch(current); |
| CGX_ResizeImage(this, current, flags); |
| } |
| #endif |
| |
| current->flags |= (flags&SDL_RESIZABLE); // Resizable only if the user asked it |
| |
| done: |
| /* Release the event thread */ |
| SDL_Unlock_EventThread(); |
| |
| /* We're done! */ |
| return(current); |
| } |
| |
| static int CGX_ToggleFullScreen(_THIS, int on) |
| { |
| Uint32 event_thread; |
| |
| /* Don't switch if we don't own the window */ |
| if ( SDL_windowid ) { |
| return(0); |
| } |
| |
| /* Don't lock if we are the event thread */ |
| event_thread = SDL_EventThreadID(); |
| if ( event_thread && (SDL_ThreadID() == event_thread) ) { |
| event_thread = 0; |
| } |
| if ( event_thread ) { |
| SDL_Lock_EventThread(); |
| } |
| if ( on ) { |
| this->screen->flags |= SDL_FULLSCREEN; |
| CGX_EnterFullScreen(this); |
| } else { |
| this->screen->flags &= ~SDL_FULLSCREEN; |
| CGX_LeaveFullScreen(this); |
| } |
| |
| CGX_RefreshDisplay(this); |
| if ( event_thread ) { |
| SDL_Unlock_EventThread(); |
| } |
| |
| SDL_ResetKeyboard(); |
| |
| return(1); |
| } |
| |
| static void SetSingleColor(Uint32 fmt, unsigned char r, unsigned char g, unsigned char b, unsigned char *c) |
| { |
| switch(fmt) |
| { |
| case PIXFMT_BGR15: |
| case PIXFMT_RGB15PC: |
| { |
| Uint16 *t=(Uint16 *)c; |
| *t=(r>>3) | ((g>>3)<<5) | ((b>>3)<<10) ; |
| } |
| break; |
| case PIXFMT_RGB15: |
| case PIXFMT_BGR15PC: |
| { |
| Uint16 *t=(Uint16 *)c; |
| *t=(b>>3) | ((g>>3)<<5) | ((r>>3)<<10) ; |
| } |
| break; |
| case PIXFMT_BGR16PC: |
| case PIXFMT_RGB16: |
| { |
| Uint16 *t=(Uint16 *)c; |
| *t=(b>>3) | ((g>>2)<<5) | ((r>>3)<<11) ; |
| } |
| break; |
| case PIXFMT_BGR16: |
| case PIXFMT_RGB16PC: |
| { |
| Uint16 *t=(Uint16 *)c; |
| *t=(r>>3) | ((g>>2)<<5) | ((b>>3)<<11) ; |
| } |
| break; |
| case PIXFMT_RGB24: |
| c[0]=r; |
| c[1]=g; |
| c[2]=b; |
| c[3]=0; |
| break; |
| case PIXFMT_BGR24: |
| c[0]=b; |
| c[1]=g; |
| c[2]=r; |
| c[3]=0; |
| break; |
| case PIXFMT_ARGB32: |
| c[0]=0; |
| c[1]=r; |
| c[2]=g; |
| c[3]=b; |
| break; |
| case PIXFMT_BGRA32: |
| c[0]=b; |
| c[1]=g; |
| c[2]=r; |
| c[3]=0; |
| break; |
| case PIXFMT_RGBA32: |
| c[0]=r; |
| c[1]=g; |
| c[2]=b; |
| c[3]=0; |
| break; |
| |
| default: |
| D(bug("Error, SetSingleColor with PIXFMT %ld!\n",fmt)); |
| } |
| } |
| |
| /* Update the current mouse state and position */ |
| static void CGX_UpdateMouse(_THIS) |
| { |
| /* Lock the event thread, in multi-threading environments */ |
| SDL_Lock_EventThread(); |
| |
| if(currently_fullscreen) |
| { |
| SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS); |
| SDL_PrivateMouseMotion(0, 0, SDL_Display->MouseX, SDL_Display->MouseY); |
| } |
| else |
| { |
| if( SDL_Display->MouseX>=(SDL_Window->LeftEdge+SDL_Window->BorderLeft) && SDL_Display->MouseX<(SDL_Window->LeftEdge+SDL_Window->Width-SDL_Window->BorderRight) && |
| SDL_Display->MouseY>=(SDL_Window->TopEdge+SDL_Window->BorderLeft) && SDL_Display->MouseY<(SDL_Window->TopEdge+SDL_Window->Height-SDL_Window->BorderBottom) |
| ) |
| { |
| SDL_PrivateAppActive(1, SDL_APPMOUSEFOCUS); |
| SDL_PrivateMouseMotion(0, 0, SDL_Display->MouseX-SDL_Window->LeftEdge-SDL_Window->BorderLeft, |
| SDL_Display->MouseY-SDL_Window->TopEdge-SDL_Window->BorderTop); |
| } |
| else |
| { |
| SDL_PrivateAppActive(0, SDL_APPMOUSEFOCUS); |
| } |
| } |
| SDL_Unlock_EventThread(); |
| } |
| |
| static int CGX_SetColors(_THIS, int firstcolor, int ncolors, SDL_Color *colors) |
| { |
| int i; |
| |
| /* Check to make sure we have a colormap allocated */ |
| |
| /* It's easy if we have a hidden colormap */ |
| if ( (this->screen->flags & SDL_HWPALETTE) && currently_fullscreen ) |
| { |
| ULONG xcmap[256*3+2]; |
| |
| xcmap[0]=(ncolors<<16); |
| xcmap[0]+=firstcolor; |
| |
| // D(bug("Setting %ld colors on an HWPALETTE screen\n",ncolors)); |
| |
| for ( i=0; i<ncolors; i++ ) { |
| xcmap[i*3+1] = colors[i+firstcolor].r<<24; |
| xcmap[i*3+2] = colors[i+firstcolor].g<<24; |
| xcmap[i*3+3] = colors[i+firstcolor].b<<24; |
| } |
| xcmap[ncolors*3+1]=0; |
| LoadRGB32(&GFX_Display->ViewPort,xcmap); |
| } else { |
| // XPixels are not needed on 8bit screen with hwpalette |
| unsigned long pixel; |
| |
| if ( SDL_XPixels == NULL ) { |
| D(bug("SetColors without colormap!")); |
| return(0); |
| } |
| |
| if(this->hidden->depth==8) |
| { |
| // In this case I have to unalloc and realloc the full palette |
| D(bug("Obtaining %ld colors on the screen\n",ncolors)); |
| |
| /* Free existing allocated colors */ |
| for ( pixel=0; pixel<this->screen->format->palette->ncolors; ++pixel ) { |
| if(SDL_XPixels[pixel]>=0) |
| ReleasePen(GFX_Display->ViewPort.ColorMap,SDL_XPixels[pixel]); |
| } |
| |
| /* Try to allocate all the colors */ |
| for ( i=0; i<this->screen->format->palette->ncolors; ++i ) { |
| SDL_XPixels[i]=ObtainBestPenA(GFX_Display->ViewPort.ColorMap,colors[i].r<<24,colors[i].g<<24,colors[i].b<<24,NULL); |
| } |
| } |
| else |
| { |
| #ifndef USE_CGX_WRITELUTPIXEL |
| Uint32 fmt; |
| D(bug("Preparing a conversion pixel table...\n")); |
| |
| fmt=GetCyberMapAttr(SDL_Display->RastPort.BitMap,CYBRMATTR_PIXFMT); |
| |
| for(i=0;i<ncolors;i++) |
| { |
| SetSingleColor(fmt,colors[firstcolor+i].r,colors[firstcolor+i].g,colors[firstcolor+i].b,(unsigned char *)&SDL_XPixels[firstcolor+i]); |
| } |
| #else |
| // D(bug("Executing XPixel(%lx) remapping: (from %ld, %ld colors) first: r%ld g%ld b%ld\n",SDL_XPixels,firstcolor,ncolors,colors[firstcolor].r,colors[firstcolor].g,colors[firstcolor].b)); |
| for(i=0;i<ncolors;i++) |
| SDL_XPixels[i+firstcolor]=(colors[firstcolor+i].r<<16)+(colors[firstcolor+i].g<<8)+colors[firstcolor+i].b; |
| #endif |
| } |
| } |
| |
| // Actually it cannot fail! |
| |
| return 1; |
| } |
| |
| /* Note: If we are terminated, this could be called in the middle of |
| another SDL video routine -- notably UpdateRects. |
| */ |
| static void CGX_VideoQuit(_THIS) |
| { |
| /* Shutdown everything that's still up */ |
| /* The event thread should be done, so we can touch SDL_Display */ |
| D(bug("CGX_VideoQuit\n")); |
| |
| if ( SDL_Display != NULL ) { |
| /* Clean up OpenGL */ |
| if(this->gl_data->gl_active == 1) { |
| CGX_GL_Quit(this); |
| } |
| /* Start shutting down the windows */ |
| D(bug("Destroying image...\n")); |
| CGX_DestroyImage(this, this->screen); |
| D(bug("Destroying window...\n")); |
| CGX_DestroyWindow(this, this->screen); |
| // Otherwise SDL_VideoQuit will try to free it! |
| SDL_VideoSurface=NULL; |
| |
| CGX_FreeVideoModes(this); |
| |
| /* Free that blank cursor */ |
| if ( SDL_BlankCursor != NULL ) { |
| FreeMem(SDL_BlankCursor,16); |
| SDL_BlankCursor = NULL; |
| } |
| |
| /* Close the X11 graphics connection */ |
| this->hidden->same_format=0; |
| |
| D(bug("Destroying screen...\n")); |
| |
| if ( GFX_Display != NULL ) |
| DestroyScreen(this); |
| |
| /* Close the X11 display connection */ |
| SDL_Display = NULL; |
| |
| /* Unload GL library after X11 shuts down */ |
| } |
| |
| D(bug("Closing libraries...\n")); |
| |
| if( CyberGfxBase) { |
| CloseLibrary(CyberGfxBase); |
| CyberGfxBase=NULL; |
| } |
| |
| if (IntuitionBase) { |
| CloseLibrary((struct Library *)IntuitionBase); |
| IntuitionBase=NULL; |
| } |
| if (GfxBase) { |
| CloseLibrary((struct Library *)GfxBase); |
| GfxBase=NULL; |
| } |
| |
| if ( this->screen && (this->screen->flags & SDL_HWSURFACE) ) { |
| /* Direct screen access, no memory buffer */ |
| this->screen->pixels = NULL; |
| } |
| D(bug("End of CGX_VideoQuit.\n")); |
| |
| } |
| |