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