Mercurial > sdl-ios-xcode
view src/video/cybergfx/SDL_cgxvideo.c @ 3844:332a59e39ce1 SDL-ryan-multiple-audio-device
I really don't want to update these last two audio backends...I added an
error that says if no one complains, the backends will be removed eventually.
So if anyone ever wants them and they care enough to speak up, we'll know to
do something about it. If no one does, that's less code to maintain. :)
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Tue, 17 Oct 2006 06:45:17 +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: */