Mercurial > sdl-ios-xcode
view src/video/cybergfx/SDL_cgxvideo.c @ 711:8db4098e944b
Severe bugfix: format->BitsPerPixel not checked in ListModes function
author | Patrice Mandin <patmandin@gmail.com> |
---|---|
date | Tue, 02 Sep 2003 19:49:50 +0000 |
parents | dcb5e869f8b5 |
children | c9b51268668f |
line wrap: on
line source
/* SDL - Simple DirectMedia Layer Copyright (C) 1997, 1998, 1999, 2000 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 */ #ifdef SAVE_RCSID static char rcsid = "@(#) $Id$"; #endif /* * CGX based SDL video driver implementation by Gabriele Greco * gabriele.greco@aruba.it */ /* #include <stdlib.h> #include <stdio.h> #include <unistd.h> #include <string.h> #include <sys/ioctl.h> #ifdef MTRR_SUPPORT #include <asm/mtrr.h> #include <sys/fcntl.h> #endif */ #include "SDL.h" #include "SDL_error.h" #include "SDL_timer.h" #include "SDL_thread.h" #include "SDL_video.h" #include "SDL_mouse.h" #include "SDL_endian.h" #include "SDL_sysvideo.h" #include "SDL_pixels_c.h" #include "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" #include "SDL_cgxyuv_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) 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 ) { free(device->hidden); } if ( device->gl_data ) { free(device->gl_data); } free(device); } } static SDL_VideoDevice *CGX_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)); device->gl_data = (struct SDL_PrivateGLData *) 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); } memset(device->hidden, 0, sizeof(*device->hidden)); 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; #ifdef XFREE86_XV device->CreateYUVOverlay = X11_CreateYUVOverlay; #endif 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; #ifdef HAVE_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); } 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 = 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]); } } } 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 ( 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 *)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=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); current_w = w; current_h = h; } /* 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); current_w = w; current_h = h; 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")); }