Mercurial > sdl-ios-xcode
diff src/video/cybergfx/SDL_cgxvideo.c @ 0:74212992fb08
Initial revision
author | Sam Lantinga <slouken@lokigames.com> |
---|---|
date | Thu, 26 Apr 2001 16:45:43 +0000 |
parents | |
children | 75a95f82bc1f |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/video/cybergfx/SDL_cgxvideo.c Thu Apr 26 16:45:43 2001 +0000 @@ -0,0 +1,1221 @@ +/* + SDL - Simple DirectMedia Layer + Copyright (C) 1997, 1998, 1999, 2000, 2001 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@devolution.com +*/ + +#ifdef SAVE_RCSID +static char rcsid = + "@(#) $Id$"; +#endif + +/* CGX based SDL video driver implementation. +*/ + +/* +#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_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" +#include "SDL_cgxgl_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; + +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[0]); + if(this->hidden->SB[0]) + FreeScreenBuffer(SDL_Display,this->hidden->SB[1]); + + + this->hidden->SB[0]=this->hidden->SB[1]=NULL; + free(SDL_RastPort); + SDL_RastPort=NULL; + this->hidden->dbuffer=0; + } + CloseScreen(GFX_Display); + } + else + UnlockPubScreen(NULL,GFX_Display); + + GFX_Display = NULL; +} + +static int CGX_Available(void) +{ + struct Library *l; + + l = OpenLibrary("cybergraphics.library",NULL); + + if ( l != NULL ) { + CloseLibrary(l); + } + 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) ) { + 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; + 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; +#ifdef HAVE_OPENGL + device->GL_LoadLibrary = X11_GL_LoadLibrary; + device->GL_GetProcAddress = X11_GL_GetProcAddress; + device->GL_GetAttribute = X11_GL_GetAttribute; + device->GL_MakeCurrent = X11_GL_MakeCurrent; + device->GL_SwapBuffers = X11_GL_SwapBuffers; +#endif + device->SetCaption = CGX_SetCaption; + device->SetIcon = CGX_SetIcon; + 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", "Amiga CyberGFX video", + 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; + + if(!(IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",39L))) + { + SDL_SetError("Couldn't open intuition V39+"); + return -1; + } + if(!(GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",39L))) + { + SDL_SetError("Couldn't open graphics V39+"); + return -1; + } + if(!(CyberGfxBase=OpenLibrary("cybergraphics.library",40L))) + { + SDL_SetError("Couldn't open cybergraphics."); + return(-1); + } + + SDL_Display = LockPubScreen(NULL); + + if ( SDL_Display == NULL ) { + SDL_SetError("Couldn't lock the display"); + return(-1); + } + + if(!IsCyberModeID(GetVPModeID(&SDL_Display->ViewPort))) + { + Uint32 okid=BestCModeIDTags(CYBRBIDTG_NominalWidth,SDL_Display->Width, + CYBRBIDTG_NominalHeight,SDL_Display->Height, + CYBRBIDTG_Depth,8, + TAG_DONE); + + 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; + } + + /* 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; + + this->hidden->depth = this->hidden->visuals[i].depth; + D(bug("Setto la profiondita' dello schermo a: %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))) + return -1; + + if(!GetDisplayInfoData(handle,(char *)&info,sizeof(struct DisplayInfo),DTAG_DISP,NULL)) + 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); + } + } + + /* Create the fullscreen and managed windows */ +// create_aux_windows(this); + + /* 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! */ + return(0); +} + +void CGX_DestroyWindow(_THIS, SDL_Surface *screen) +{ + /* Hide the managed window */ + int was_fullscreen=0; + + if ( screen && (screen->flags & SDL_FULLSCREEN) ) { + was_fullscreen=1; + screen->flags &= ~SDL_FULLSCREEN; + CGX_LeaveFullScreen(this); + } + + /* 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 + /* If a window is already present, destroy it and start fresh */ + if ( SDL_Window ) { + CGX_DestroyWindow(this, screen); + } + 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("Setto la profiondita' dello schermo a: %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 ( GetCyberMapAttr(SDL_Display->RastPort.BitMap,CYBRMATTR_PIXFMT)==PIXFMT_LUT8 || bpp==8 ) { + int ncolors; + D(bug("Alloco XPixels x la palette...\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; + } + + memset(SDL_XPixels, -1, ncolors * sizeof(Sint32)); + + /* 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 ( flags & SDL_OPENGL ) { + return(-1); + } else { + 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); + else + SDL_Window = OpenWindowTags(NULL,WA_InnerWidth,w,WA_InnerHeight,h, + WA_Flags,WFLG_REPORTMOUSE|WFLG_ACTIVATE|WFLG_RMBTRAP|WFLG_DEPTHGADGET|WFLG_CLOSEGADGET|WFLG_DRAGBAR| ((screen->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, + TAG_DONE); + } + /* Only manage our input if we own the window */ + 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 0 + + if(screen->flags & SDL_HWPALETTE) { + /* Since the full-screen window might have got a nonzero background + colour (0 is white on some displays), we should reset the + background to 0 here since that is what the user expects + with a private colormap */ + SetAPen(SDL_Window->RPort,0); + RectFill(SDL_Window->RPort,SDL_Window->BorderLeft,SDL_Window->BorderTop,w+SDL_Window->BorderLeft,h+SDL_Window->BorderTop); + } +#endif + + if(flags&SDL_HWSURFACE) + screen->flags|=SDL_HWSURFACE; + + CGX_SetSizeHints(this, w, h, flags); + current_w = w; + current_h = h; + + /* Map them both and go fullscreen, if requested */ + if ( flags & SDL_FULLSCREEN ) { + screen->flags |= SDL_FULLSCREEN; + currently_fullscreen=1; +// CGX_EnterFullScreen(this); Ci siamo gia'! + } else { + screen->flags &= ~SDL_FULLSCREEN; + } + return(0); +} + +int CGX_ResizeWindow(_THIS, + SDL_Surface *screen, int w, int h, Uint32 flags) +{ + /* 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); + + /* Resize the fullscreen and display windows */ + if ( flags & SDL_FULLSCREEN ) { + if ( screen->flags & SDL_FULLSCREEN ) { + CGX_ResizeFullScreen(this); + } else { + screen->flags |= SDL_FULLSCREEN; + CGX_EnterFullScreen(this); + } + } else { + if ( screen->flags & SDL_FULLSCREEN ) { + screen->flags &= ~SDL_FULLSCREEN; + CGX_LeaveFullScreen(this); + } + } + return(0); +} + +static SDL_Surface *CGX_SetVideoMode(_THIS, SDL_Surface *current, + int width, int height, int bpp, Uint32 flags) +{ + Uint32 saved_flags; + + /* Lock the event thread, in multi-threading environments */ + SDL_Lock_EventThread(); + +// Check if we need to close an already existing videomode... + + if(current->flags&SDL_FULLSCREEN && !(flags&SDL_FULLSCREEN)) + { + CGX_DestroyImage(this,current); + CGX_DestroyWindow(this,current); + DestroyScreen(this); + } + /* Check the combination of flags we were passed */ + if ( flags & SDL_FULLSCREEN ) { + int i; + + /* Clear fullscreen flag if not supported */ + if(current->flags&SDL_FULLSCREEN ) + { + if(current->w!=width || + current->h!=height || + this->hidden->depth!=bpp) + { + 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; + + 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; + + if(flags&SDL_DOUBLEBUF) + { + int ok=0; + + 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("Setto la profiondita' dello schermo a: %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) { + 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; + } + } + + /* 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); + } + 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 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("Errore, SetSingleColor con 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 not needed to reload the whole palette each time on Amiga! +// ncolors = this->screen->format->palette->ncolors; + + /* 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].r<<24; + xcmap[i*3+2] = colors[i].g<<24; + xcmap[i*3+3] = colors[i].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); + } + + colors = this->screen->format->palette->colors; + 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("Eseguo remap degli XPixel(%lx): (da %ld, %ld colori) primo: 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 */ + if ( SDL_Display != NULL ) { + /* Clean up OpenGL */ + + /* Start shutting down the windows */ + CGX_DestroyImage(this, this->screen); + 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; + + if ( GFX_Display != NULL ) + DestroyScreen(this); + + /* Close the X11 display connection */ + SDL_Display = NULL; + + /* Unload GL library after X11 shuts down */ + } + + 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; + } +} +