Mercurial > sdl-ios-xcode
view src/video/cybergfx/SDL_cgxvideo.c @ 202:401f0134f4f9
Fixed crash when using double-buffering with DGA
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sun, 30 Sep 2001 20:19:20 +0000 |
parents | 75a95f82bc1f |
children | e8157fcb3114 |
line wrap: on
line source
/* 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); currently_fullscreen=0; } 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; #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; #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->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 }; #if 0 /* Create auxiliary (toplevel) windows with the current visual */ static void create_aux_windows(_THIS) { XSetWindowAttributes xattr; XWMHints *hints; XTextProperty titleprop, iconprop; int def_vis = (SDL_Visual == DefaultVisual(SDL_Display, SDL_Screen)); /* Don't create any extra windows if we are being managed */ if ( SDL_windowid ) { FSwindow = 0; WMwindow = strtol(SDL_windowid, NULL, 0); return; } if(FSwindow) XDestroyWindow(SDL_Display, FSwindow); xattr.override_redirect = True; xattr.background_pixel = def_vis ? BlackPixel(SDL_Display, SDL_Screen) : 0; xattr.border_pixel = 0; xattr.colormap = SDL_XColorMap; FSwindow = XCreateWindow(SDL_Display, SDL_Root, 0, 0, 32, 32, 0, this->hidden->depth, InputOutput, SDL_Visual, CWOverrideRedirect | CWBackPixel | CWBorderPixel | CWColormap, &xattr); XSelectInput(SDL_Display, FSwindow, StructureNotifyMask); /* Tell KDE to keep the fullscreen window on top */ { XEvent ev; long mask; memset(&ev, 0, sizeof(ev)); ev.xclient.type = ClientMessage; ev.xclient.window = SDL_Root; ev.xclient.message_type = XInternAtom(SDL_Display, "KWM_KEEP_ON_TOP", False); ev.xclient.format = 32; ev.xclient.data.l[0] = FSwindow; ev.xclient.data.l[1] = CurrentTime; mask = SubstructureRedirectMask; XSendEvent(SDL_Display, SDL_Root, False, mask, &ev); } hints = NULL; titleprop.value = iconprop.value = NULL; if(WMwindow) { /* All window attributes must survive the recreation */ hints = XGetWMHints(SDL_Display, WMwindow); XGetWMName(SDL_Display, WMwindow, &titleprop); XGetWMIconName(SDL_Display, WMwindow, &iconprop); XDestroyWindow(SDL_Display, WMwindow); } /* Create the window for windowed management */ /* (reusing the xattr structure above) */ WMwindow = XCreateWindow(SDL_Display, SDL_Root, 0, 0, 32, 32, 0, this->hidden->depth, InputOutput, SDL_Visual, CWBackPixel | CWBorderPixel | CWColormap, &xattr); /* Set the input hints so we get keyboard input */ if(!hints) { hints = XAllocWMHints(); hints->input = True; hints->flags = InputHint; } XSetWMHints(SDL_Display, WMwindow, hints); XFree(hints); if(titleprop.value) { XSetWMName(SDL_Display, WMwindow, &titleprop); XFree(titleprop.value); } if(iconprop.value) { XSetWMIconName(SDL_Display, WMwindow, &iconprop); XFree(iconprop.value); } XSelectInput(SDL_Display, WMwindow, FocusChangeMask | KeyPressMask | KeyReleaseMask | PropertyChangeMask | StructureNotifyMask); /* Set the class hints so we can get an icon (AfterStep) */ { XClassHint *classhints; classhints = XAllocClassHint(); if(classhints != NULL) { classhints->res_name = "SDL_App"; classhints->res_class = "SDL_App"; XSetClassHint(SDL_Display, WMwindow, classhints); XFree(classhints); } } /* Allow the window to be deleted by the window manager */ WM_DELETE_WINDOW = XInternAtom(SDL_Display, "WM_DELETE_WINDOW", False); XSetWMProtocols(SDL_Display, WMwindow, &WM_DELETE_WINDOW, 1); } #endif 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; // SDL_XColorMap = SDL_DisplayColormap; 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); } } /* See if we have been passed a window to use */ /* SDL_windowid = getenv("SDL_WINDOWID"); */ SDL_windowid=NULL; /* 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) { if ( ! SDL_windowid ) { /* Hide the managed window */ int was_fullscreen=0; 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 /* 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("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 ( SDL_XColorMap != SDL_DisplayColormap ) { XFreeColormap(SDL_Display, SDL_XColorMap); } */ 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; /* SDL_XColorMap = XCreateColormap(SDL_Display, SDL_Root, SDL_Visual, AllocAll); */ } else { /* SDL_XColorMap = SDL_DisplayColormap; */ } } else { /* SDL_XColorMap = XCreateColormap(SDL_Display, SDL_Root, SDL_Visual, AllocNone); */ } /* Recreate the auxiliary windows, if needed (required for GL) */ /* if ( vis_change ) create_aux_windows(this); */ /* resize the (possibly new) window manager window */ /* Create (or use) the X11 display window */ if ( !SDL_windowid ) { 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); D(bug("Apro finestra backdrop %ldx%ld su %lx!\n",w,h,SDL_Display)); } else { 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, TAG_DONE); D(bug("Apro finestra %ldx%ld sul wb!\n",w,h)); } } /* Only manage our input if we own the window */ /* XSelectInput(SDL_Display, SDL_Window, ( EnterWindowMask | LeaveWindowMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask | ExposureMask )); */ 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; 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); return(0); } int CGX_ResizeWindow(_THIS, SDL_Surface *screen, int w, int h, Uint32 flags) { 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); /* 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); } } */ 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; /* 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->flags&SDL_FULLSCREEN && !(flags&SDL_FULLSCREEN))) needcreate=1; // Check if we need to close an already existing videomode... if(current->flags&SDL_FULLSCREEN && !(flags&SDL_FULLSCREEN)) { unsigned long i; CGX_DestroyImage(this,current); CGX_DestroyWindow(this,current); DestroyScreen(this); D(bug("Distrutte immagine, finestra e schermo!\n")); 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("Setto la profiondita' dello schermo a: %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->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 && !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("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 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("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); /* if ( SDL_iconcolors ) { unsigned long pixel; int numcolors = ((this->screen->format)->palette)->ncolors; for ( pixel=0; pixel<numcolors; ++pixel ) { while ( SDL_iconcolors[pixel] > 0 ) { XFreeColors(SDL_Display, SDL_DisplayColormap,&pixel,1,0); --SDL_iconcolors[pixel]; } } free(SDL_iconcolors); SDL_iconcolors = NULL; } */ /* 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; } }