From 0818e1bd6454cfe678298d0312ae30c8c789f59b Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 14 Feb 2004 20:22:21 +0000 Subject: [PATCH] Date: Sat, 14 Feb 2004 14:52:40 +0200 From: "Mike Gorchak" Subject: Batch of the QNX6 fixes for the SDL 1. Updated readme.QNX 2. Fixed crashes during intensive window updating under fast machines (got over 200 rectangles for update). 3. Fixed double-buffered fullscreen modes, now it works as needed. 4. Fixed Photon detection algorithm. 5. Fixed HWSURFACE update function. 6. Added SDL_PHOTON_FULLSCREEN_REFRESH environment variable support for control refresh rates under Photon. 7. Added 640x400 fullscreen mode emulation via 640x480 (if videodriver not supports original 640x400 mode of course) shifted by 40 vertical pixels from begin, to center it. It's needed for some old DOS games which ran in doubled 320x200 mode. 8. Added available video ram amount support. 8. Added hardware surface allocation/deallocation support if current videomode and videodriver supports it. 9. Added hardware filling support. 10. Added hardware blits support (simple and colorkeyed). And I've added to testvidinfo test color-keyed blits benchmark (maybe need to add alpha blits benchmark too ?). Currently Photon not supporting any alpha hardware blittings (all drivers lack of alpha blitting code support, only software alpha blitting exist in photon, which is hundreds times slowest than the SDL's one). So I've not added the alpha support. I suppose new QNX 6.3 will have the hardware alpha support, so when it will be done, I'll add alpha support. --- README.QNX | 25 +- src/video/photon/SDL_ph_events.c | 52 ++- src/video/photon/SDL_ph_events_c.h | 4 +- src/video/photon/SDL_ph_image.c | 546 ++++++++++++++++++++++++++--- src/video/photon/SDL_ph_image_c.h | 34 +- src/video/photon/SDL_ph_modes.c | 67 +++- src/video/photon/SDL_ph_video.c | 68 ++-- src/video/photon/SDL_ph_video.h | 43 +-- test/testvidinfo.c | 56 ++- 9 files changed, 765 insertions(+), 130 deletions(-) diff --git a/README.QNX b/README.QNX index 91a477837..2b4992e8e 100644 --- a/README.QNX +++ b/README.QNX @@ -1,5 +1,5 @@ README by Mike Gorchak , -Last changed at 30 Sep 2003. +Last changed at 14 Feb 2004. ====================================================================== Table of Contents: @@ -13,7 +13,7 @@ Table of Contents: 7. Environment variables. ====================================================================== -OpenGL: +1. OpenGL: OpenGL works well and is stable, but fullscreen mode has not been heavily tested yet. @@ -34,7 +34,7 @@ line in the ph_SetupOpenGLContext() function or change the argument to PHOGL_ATTRIB_FORCE_HW or PHOGL_ATTRIB_FAVOR_HW. ====================================================================== -Wheel and multi-button mouses: +2. Wheel and multi-button mouses: Photon emits keyboard events (key up and down) when the mouse wheel is moved. The key_scan field appears valid, and it contains zero. @@ -54,14 +54,14 @@ I've tested it on: front, but works not with any window, looks like bug-o-feature :). ====================================================================== -CDROM handling issues: +3. CDROM handling issues: Access to CDROM can only be provided with 'root' privileges. I can't do anything about that, /dev/cd0 has brw------- permissions and root:root rights. ====================================================================== -Hardware video overlays: +4. Hardware video overlays: Overlays can flicker during window movement, resizing, etc. It happens because the photon driver updates the real window contents be- @@ -82,20 +82,20 @@ smaller). It's really strange, looks like the overlay doesn't like negative coordinates. ======================================================================= -Shared library building: +5. Shared library building: A shared library can be built, but before running the autogen.sh script you must manually delete the libtool.m4 stuff from the acinclu- de.m4 file (it comes after the ESD detection code up to the end of the -file), because the libtool stuff in the acinclude.m4 file is very old -in SDL distribution before the version 1.2.7 and doesn't know anything +file), because the libtool stuff in the acinclude.m4 file was very old +in SDL distribution before the version 1.2.7 and doesn't knew anything about QNX. SDL 1.2.7 distribution contain the new libtool.m4 script, but anyway it is broken :), Just remove it, then run "libtoolize --force --copy", delete the file aclocal.m4 and after that run the autogen.sh script. ====================================================================== -Some building issues: +6. Some building issues: Feel free to not use the --disable-shared configure option if you' ve read the above comment about 'Shared library building'. Otherwise @@ -123,11 +123,16 @@ x11 support, e.g.: --prefix=/usr --without-x ====================================================================== -Environment variables: +7. Environment variables: Please note that the photon driver is sensible to the following environmental variables: + * SDL_PHOTON_FULLSCREEN_REFRESH - this environment variable controls +the refresh rate in all fullscreen modes. Be carefull !!! Photon drivers +usually do not checking the maximum refresh rate, which video adapter or +monitor supports. + * SDL_VIDEO_WINDOW_POS - can be set in the "X,Y" format. If X and Y coordinates are bigger than the current desktop resolution, then win- dow positioning across virtual consoles is activated. If X and Y are diff --git a/src/video/photon/SDL_ph_events.c b/src/video/photon/SDL_ph_events.c index 6dedbb166..18feb13f7 100644 --- a/src/video/photon/SDL_ph_events.c +++ b/src/video/photon/SDL_ph_events.c @@ -47,17 +47,13 @@ static char rcsid = #include "SDL_ph_events_c.h" #include "SDL_phyuv_c.h" - - /* The translation tables from a photon keysym to a SDL keysym */ static SDLKey ODD_keymap[256]; static SDLKey MISC_keymap[0xFF + 1]; SDL_keysym *ph_TranslateKey(PhKeyEvent_t *key, SDL_keysym *keysym); /* Check to see if this is a repeated key. - (idea shamelessly lifted from GII -- thanks guys! :) - */ - + (idea shamelessly lifted from GII -- thanks guys! :) */ static int ph_WarpedMotion(_THIS, PhEvent_t *winEvent) { PhRect_t *rect = PhGetRects( winEvent ); @@ -117,8 +113,6 @@ static Uint8 ph2sdl_mousebutton(unsigned short button_state) return (mouse_button); } -// void* PtAppCreateContext(); - static int ph_DispatchEvent(_THIS) { int posted; @@ -127,7 +121,7 @@ static int ph_DispatchEvent(_THIS) PhKeyEvent_t* keyEvent; PhWindowEvent_t* winEvent; int i, buttons; - SDL_Rect sdlrects[50]; + SDL_Rect sdlrects[PH_SDL_MAX_RECTS]; posted = 0; @@ -217,12 +211,12 @@ static int ph_DispatchEvent(_THIS) set_motion_sensitivity(this, -1); posted = SDL_PrivateAppActive(1, SDL_APPINPUTFOCUS); } - /* quit request */ + /* request quit */ else if (winEvent->event_f==Ph_WM_CLOSE) { posted = SDL_PrivateQuit(); } - /* hide/unhide request */ + /* request hide/unhide */ else if (winEvent->event_f==Ph_WM_HIDE) { if (currently_hided) @@ -287,9 +281,16 @@ static int ph_DispatchEvent(_THIS) { if (event->num_rects!=0) { + int numrects; + if (SDL_VideoSurface) { rect = PhGetRects(event); + if (event->num_rects>PH_SDL_MAX_RECTS) + { + /* sorry, buffers underrun, we'll update only first PH_SDL_MAX_RECTS rects */ + numrects=PH_SDL_MAX_RECTS; + } for(i=0; inum_rects; i++) { @@ -368,6 +369,32 @@ static int ph_DispatchEvent(_THIS) case Ph_EV_INFO: { + if (event->subtype==Ph_OFFSCREEN_INVALID) + { + unsigned long* EvInfoData; + + EvInfoData=(unsigned long*)PhGetData(event); + + switch (*EvInfoData) + { + case Pg_VIDEO_MODE_SWITCHED: + { + } + break; + case Pg_ENTERED_DIRECT: + { + } + break; + case Pg_EXITED_DIRECT: + { + } + break; + case Pg_DRIVER_STARTED: + { + } + break; + } + } } break; } @@ -387,10 +414,9 @@ int ph_Pending(_THIS) { case Ph_EVENT_MSG: return 1; - break; case -1: - perror("ph_Pending(): PhEventNext failed"); - break; + SDL_SetError("ph_Pending(): PhEventNext failed.\n"); + return 0; default: return 0; } diff --git a/src/video/photon/SDL_ph_events_c.h b/src/video/photon/SDL_ph_events_c.h index 4c048e3e8..de80a7149 100644 --- a/src/video/photon/SDL_ph_events_c.h +++ b/src/video/photon/SDL_ph_events_c.h @@ -30,7 +30,9 @@ static char rcsid = #include "SDL_ph_video.h" -#define EVENT_SIZE sizeof(PhEvent_t) + 1000 +#define PH_SDL_MAX_RECTS 256 +#define PH_EVENT_SAFETY_POOL 512 +#define EVENT_SIZE (sizeof(PhEvent_t) + 1000 + PH_EVENT_SAFETY_POOL) /* Functions to be exported */ extern void ph_InitOSKeymap(_THIS); diff --git a/src/video/photon/SDL_ph_image.c b/src/video/photon/SDL_ph_image.c index d7de71033..ff69a0288 100644 --- a/src/video/photon/SDL_ph_image.c +++ b/src/video/photon/SDL_ph_image.c @@ -164,7 +164,7 @@ int ph_SetupOCImage(_THIS, SDL_Surface *screen) screen->pitch = OCImage.offscreen_context->pitch; - OCImage.dc_ptr = (unsigned char *) PdGetOffscreenContextPtr(OCImage.offscreen_context); + OCImage.dc_ptr = (unsigned char *)PdGetOffscreenContextPtr(OCImage.offscreen_context); if (OCImage.dc_ptr == NULL) { @@ -212,7 +212,7 @@ int ph_SetupFullScreenImage(_THIS, SDL_Surface* screen) if ((screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) { - OCImage.offscreen_backcontext = PdDupOffscreenContext(OCImage.offscreen_context, Pg_OSC_CRTC_SAFE | Pg_OSC_MEM_PAGE_ALIGN); + OCImage.offscreen_backcontext = PdDupOffscreenContext(OCImage.offscreen_context, Pg_OSC_MEM_PAGE_ALIGN | Pg_OSC_CRTC_SAFE); if (OCImage.offscreen_backcontext == NULL) { SDL_SetError("ph_SetupFullScreenImage(): PdCreateOffscreenContext(back) function failed !\n"); @@ -240,15 +240,32 @@ int ph_SetupFullScreenImage(_THIS, SDL_Surface* screen) } /* wait for the hardware */ + PgFlush(); PgWaitHWIdle(); if ((screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) { - OCImage.current = 1; - PhDCSetCurrent(OCImage.offscreen_backcontext); - screen->pitch = OCImage.offscreen_backcontext->pitch; - screen->pixels = OCImage.FrameData1; - PgSwapDisplay(OCImage.offscreen_context, 0); + OCImage.current = 0; + PhDCSetCurrent(OCImage.offscreen_context); + screen->pitch = OCImage.offscreen_context->pitch; + screen->pixels = OCImage.FrameData0; + + /* emulate 640x400 videomode */ + if (videomode_emulatemode==1) + { + int i; + + for (i=0; i<40; i++) + { + memset(screen->pixels+screen->pitch*i, 0x00, screen->pitch); + } + for (i=440; i<480; i++) + { + memset(screen->pixels+screen->pitch*i, 0x00, screen->pitch); + } + screen->pixels+=screen->pitch*40; + } + PgSwapDisplay(OCImage.offscreen_backcontext, 0); } else { @@ -256,11 +273,29 @@ int ph_SetupFullScreenImage(_THIS, SDL_Surface* screen) PhDCSetCurrent(OCImage.offscreen_context); screen->pitch = OCImage.offscreen_context->pitch; screen->pixels = OCImage.FrameData0; + + /* emulate 640x400 videomode */ + if (videomode_emulatemode==1) + { + int i; + + for (i=0; i<40; i++) + { + memset(screen->pixels+screen->pitch*i, 0x00, screen->pitch); + } + for (i=440; i<480; i++) + { + memset(screen->pixels+screen->pitch*i, 0x00, screen->pitch); + } + screen->pixels+=screen->pitch*40; + } } this->UpdateRects = ph_OCDCUpdate; + /* wait for the hardware */ PgFlush(); + PgWaitHWIdle(); return 0; } @@ -427,73 +462,495 @@ void ph_DestroyImage(_THIS, SDL_Surface* screen) } } +int ph_UpdateHWInfo(_THIS) +{ + PgVideoModeInfo_t vmode; + PgHWCaps_t hwcaps; + + /* Update video ram amount */ + if (PgGetGraphicsHWCaps(&hwcaps) < 0) + { + SDL_SetError("ph_UpdateHWInfo(): GetGraphicsHWCaps() function failed !\n"); + return -1; + } + this->info.video_mem=hwcaps.currently_available_video_ram/1024; + + /* obtain current mode capabilities */ + if (PgGetVideoModeInfo(hwcaps.current_video_mode, &vmode) < 0) + { + SDL_SetError("ph_UpdateHWInfo(): GetVideoModeInfo() function failed !\n"); + return -1; + } + + this->info.blit_hw = 1; + + if ((vmode.mode_capabilities2 & PgVM_MODE_CAP2_ALPHA_BLEND) == PgVM_MODE_CAP2_ALPHA_BLEND) + { + this->info.blit_hw_A = 1; + } + else + { + this->info.blit_hw_A = 0; + } + + if ((vmode.mode_capabilities2 & PgVM_MODE_CAP2_CHROMA) == PgVM_MODE_CAP2_CHROMA) + { + this->info.blit_hw_CC = 1; + } + else + { + this->info.blit_hw_CC = 0; + } + + return 0; +} + int ph_SetupUpdateFunction(_THIS, SDL_Surface* screen, Uint32 flags) { + int setupresult=-1; + ph_DestroyImage(this, screen); #ifdef HAVE_OPENGL if ((flags & SDL_OPENGL)==SDL_OPENGL) { - return ph_SetupOpenGLImage(this, screen); + setupresult=ph_SetupOpenGLImage(this, screen); } -#endif /* HAVE_OPENGL */ - if ((flags & SDL_FULLSCREEN)==SDL_FULLSCREEN) + else { - return ph_SetupFullScreenImage(this, screen); +#endif /* HAVE_OPENGL */ + if ((flags & SDL_FULLSCREEN)==SDL_FULLSCREEN) + { + setupresult=ph_SetupFullScreenImage(this, screen); + } + else + { + if ((flags & SDL_HWSURFACE)==SDL_HWSURFACE) + { + setupresult=ph_SetupOCImage(this, screen); + } + else + { + setupresult=ph_SetupImage(this, screen); + } + } +#ifdef HAVE_OPENGL } - if ((flags & SDL_HWSURFACE)==SDL_HWSURFACE) +#endif /* HAVE_OPENGL */ + if (setupresult!=-1) { - return ph_SetupOCImage(this, screen); + ph_UpdateHWInfo(this); } - - return ph_SetupImage(this, screen); + + return setupresult; } int ph_AllocHWSurface(_THIS, SDL_Surface* surface) { - return(-1); + PgHWCaps_t hwcaps; + + if (surface->hwdata!=NULL) + { + SDL_SetError("ph_AllocHWSurface(): hwdata already exists!\n"); + return -1; + } + surface->hwdata=malloc(sizeof(struct private_hwdata)); + memset(surface->hwdata, 0x00, sizeof(struct private_hwdata)); + surface->hwdata->offscreenctx=PdCreateOffscreenContext(0, surface->w, surface->h, Pg_OSC_MEM_PAGE_ALIGN); + if (surface->hwdata->offscreenctx == NULL) + { + SDL_SetError("ph_AllocHWSurface(): PdCreateOffscreenContext() function failed !\n"); + return -1; + } + surface->pixels=PdGetOffscreenContextPtr(surface->hwdata->offscreenctx); + if (surface->pixels==NULL) + { + PhDCRelease(surface->hwdata->offscreenctx); + SDL_SetError("ph_AllocHWSurface(): PdGetOffscreenContextPtr() function failed !\n"); + return -1; + } + surface->pitch=surface->hwdata->offscreenctx->pitch; + surface->flags|=SDL_HWSURFACE; + surface->flags|=SDL_PREALLOC; + +#if 0 /* FIXME */ + /* create simple offscreen lock */ + surface->hwdata->crlockparam.flags=0; + if (PdCreateOffscreenLock(surface->hwdata->offscreenctx, &surface->hwdata->crlockparam)!=EOK) + { + PhDCRelease(surface->hwdata->offscreenctx); + SDL_SetError("ph_AllocHWSurface(): Can't create offscreen lock !\n"); + return -1; + } +#endif /* 0 */ + + /* Update video ram amount */ + if (PgGetGraphicsHWCaps(&hwcaps) < 0) + { + PdDestroyOffscreenLock(surface->hwdata->offscreenctx); + PhDCRelease(surface->hwdata->offscreenctx); + SDL_SetError("ph_AllocHWSurface(): GetGraphicsHWCaps() function failed !\n"); + return -1; + } + this->info.video_mem=hwcaps.currently_available_video_ram/1024; + + return 0; } void ph_FreeHWSurface(_THIS, SDL_Surface* surface) { + PgHWCaps_t hwcaps; + + if (surface->hwdata==NULL) + { + SDL_SetError("ph_FreeHWSurface(): no hwdata!\n"); + return; + } + if (surface->hwdata->offscreenctx == NULL) + { + SDL_SetError("ph_FreeHWSurface(): no offscreen context to delete!\n"); + return; + } + +#if 0 /* FIXME */ + /* unlock the offscreen context if it has been locked before destroy it */ + if (PdIsOffscreenLocked(surface->hwdata->offscreenctx)==Pg_OSC_LOCKED) + { + PdUnlockOffscreen(surface->hwdata->offscreenctx); + } + + PdDestroyOffscreenLock(surface->hwdata->offscreenctx); +#endif /* 0 */ + + PhDCRelease(surface->hwdata->offscreenctx); + + free(surface->hwdata); + surface->hwdata=NULL; + + /* Update video ram amount */ + if (PgGetGraphicsHWCaps(&hwcaps) < 0) + { + SDL_SetError("ph_FreeHWSurface(): GetGraphicsHWCaps() function failed !\n"); + return; + } + this->info.video_mem=hwcaps.currently_available_video_ram/1024; + return; } +int ph_CheckHWBlit(_THIS, SDL_Surface *src, SDL_Surface *dst) +{ + if ((src->hwdata==NULL) && (src != this->screen)) + { + SDL_SetError("ph_CheckHWBlit(): Source surface haven't hardware specific data.\n"); + src->flags&=~SDL_HWACCEL; + return -1; + } + if ((src->flags & SDL_HWSURFACE) != SDL_HWSURFACE) + { + SDL_SetError("ph_CheckHWBlit(): Source surface isn't a hardware surface.\n"); + src->flags&=~SDL_HWACCEL; + return -1; + } + + if ((src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) + { + if (this->info.blit_hw_CC!=1) + { + src->flags&=~SDL_HWACCEL; + src->map->hw_blit=NULL; + return -1; + } + } + + if ((src->flags & SDL_SRCALPHA) == SDL_SRCALPHA) + { + if (this->info.blit_hw_A!=1) + { + src->flags&=~SDL_HWACCEL; + src->map->hw_blit=NULL; + return -1; + } + } + + src->flags|=SDL_HWACCEL; + src->map->hw_blit = ph_HWAccelBlit; + + return 1; +} + +PgColor_t ph_ExpandColor(_THIS, SDL_Surface* surface, Uint32 color) +{ + Uint32 truecolor; + + /* Photon API accepts true colors only during hw filling operations */ + switch(surface->format->BitsPerPixel) + { + case 8: + { + if ((surface->format->palette) && (color<=surface->format->palette->ncolors)) + { + truecolor=PgRGB(surface->format->palette->colors[color].r, + surface->format->palette->colors[color].g, + surface->format->palette->colors[color].b); + } + else + { + SDL_SetError("ph_ExpandColor(): Color out of range for the 8bpp mode !\n"); + return 0xFFFFFFFFUL; + } + } + break; + case 15: + { + truecolor = ((color & 0x00007C00UL) << 9) | /* R */ + ((color & 0x000003E0UL) << 6) | /* G */ + ((color & 0x0000001FUL) << 3) | /* B */ + ((color & 0x00007000UL) << 4) | /* R compensation */ + ((color & 0x00000380UL) << 1) | /* G compensation */ + ((color & 0x0000001CUL) >> 2); /* B compensation */ + } + break; + case 16: + { + truecolor = ((color & 0x0000F800UL) << 8) | /* R */ + ((color & 0x000007E0UL) << 5) | /* G */ + ((color & 0x0000001FUL) << 3) | /* B */ + ((color & 0x0000E000UL) << 3) | /* R compensation */ + ((color & 0x00000600UL) >> 1) | /* G compensation */ + ((color & 0x0000001CUL) >> 2); /* B compensation */ + + } + break; + case 24: + { + truecolor=color & 0x00FFFFFFUL; + } + break; + case 32: + { + truecolor=color; + } + break; + default: + { + SDL_SetError("ph_ExpandColor(): Unsupported depth for the hardware operations !\n"); + return 0xFFFFFFFFUL; + } + } + + return truecolor; +} + +int ph_FillHWRect(_THIS, SDL_Surface* surface, SDL_Rect* rect, Uint32 color) +{ + PgColor_t oldcolor; + Uint32 truecolor; + int ydisp=0; + + truecolor=ph_ExpandColor(this, surface, color); + if (truecolor==0xFFFFFFFFUL) + { + return -1; + } + + oldcolor=PgSetFillColor(truecolor); + + /* 640x400 videomode emulation */ + if (videomode_emulatemode==1) + { + ydisp+=40; + } + + PgDrawIRect(rect->x, rect->y+ydisp, rect->w+rect->x-1, rect->h+rect->y+ydisp-1, Pg_DRAW_FILL); + PgSetFillColor(oldcolor); + PgFlush(); + PgWaitHWIdle(); + + return 0; +} + int ph_FlipHWSurface(_THIS, SDL_Surface* screen) { + PhArea_t farea; + if ((screen->flags & SDL_FULLSCREEN) == SDL_FULLSCREEN) { + /* flush all drawing ops before blitting */ + PgFlush(); PgWaitHWIdle(); - if (OCImage.current==0) + + farea.pos.x=0; + farea.pos.y=0; + farea.size.w=screen->w; + farea.size.h=screen->h; + + /* emulate 640x400 videomode */ + if (videomode_emulatemode==1) { - PgSwapDisplay(OCImage.offscreen_context, 0); - OCImage.current=1; - screen->pitch = OCImage.offscreen_backcontext->pitch; - screen->pixels = OCImage.FrameData1; - PhDCSetCurrent(OCImage.offscreen_backcontext); - PgFlush(); + farea.pos.y+=40; + } + + PgContextBlitArea(OCImage.offscreen_context, &farea, OCImage.offscreen_backcontext, &farea); + + /* flush the blitting */ + PgFlush(); + PgWaitHWIdle(); + } + return 0; +} + +int ph_LockHWSurface(_THIS, SDL_Surface* surface) +{ + +#if 0 /* FIXME */ + int lockresult; + + if (surface->hwdata == NULL) + { + return; + } + + surface->hwdata->lockparam.flags=0; + surface->hwdata->lockparam.time_out=NULL; + lockresult=PdLockOffscreen(surface->hwdata->offscreenctx, &surface->hwdata->lockparam); + + switch (lockresult) + { + case EOK: + break; + case Pg_OSC_LOCK_DEADLOCK: + SDL_SetError("ph_LockHWSurface(): Deadlock detected !\n"); + return -1; + case Pg_OSC_LOCK_INVALID: + SDL_SetError("ph_LockHWSurface(): Lock invalid !\n"); + return -1; + default: + SDL_SetError("ph_LockHWSurface(): Can't lock the surface !\n"); + return -1; + } +#endif /* 0 */ + + return 0; +} + +void ph_UnlockHWSurface(_THIS, SDL_Surface* surface) +{ + +#if 0 /* FIXME */ + int unlockresult; + + if ((surface == NULL) || (surface->hwdata == NULL)) + { + return; + } + + if (PdIsOffscreenLocked(surface->hwdata->offscreenctx)==Pg_OSC_LOCKED) + { + unlockresult=PdUnlockOffscreen(surface->hwdata->offscreenctx); + } +#endif /* 0 */ + + return; +} + +int ph_HWAccelBlit(SDL_Surface* src, SDL_Rect* srcrect, SDL_Surface* dst, SDL_Rect* dstrect) +{ + SDL_VideoDevice* this=current_video; + PhArea_t srcarea; + PhArea_t dstarea; + int ydisp=0; + + /* 640x400 videomode emulation */ + if (videomode_emulatemode==1) + { + ydisp+=40; + } + + srcarea.pos.x=srcrect->x; + srcarea.pos.y=srcrect->y; + srcarea.size.w=srcrect->w; + srcarea.size.h=srcrect->h; + + dstarea.pos.x=dstrect->x; + dstarea.pos.y=dstrect->y; + dstarea.size.w=dstrect->w; + dstarea.size.h=dstrect->h; + + if (((src == this->screen) || (src->hwdata!=NULL)) && ((dst == this->screen) || (dst->hwdata!=NULL))) + { + if ((src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) + { + ph_SetHWColorKey(this, src, src->format->colorkey); + PgChromaOn(); + } + + if (dst == this->screen) + { + if (src == this->screen) + { + /* blitting from main screen to main screen */ + dstarea.pos.y+=ydisp; + srcarea.pos.y+=ydisp; + PgContextBlitArea(OCImage.offscreen_context, &srcarea, OCImage.offscreen_context, &dstarea); + } + else + { + /* blitting from offscreen to main screen */ + dstarea.pos.y+=ydisp; + PgContextBlitArea(src->hwdata->offscreenctx, &srcarea, OCImage.offscreen_context, &dstarea); + } } else { - PgSwapDisplay(OCImage.offscreen_backcontext, 0); - OCImage.current=0; - screen->pitch = OCImage.offscreen_context->pitch; - screen->pixels = OCImage.FrameData0; - PhDCSetCurrent(OCImage.offscreen_context); - PgFlush(); + if (src == this->screen) + { + /* blitting from main screen to offscreen */ + srcarea.pos.y+=ydisp; + PgContextBlitArea(OCImage.offscreen_context, &srcarea, dst->hwdata->offscreenctx, &dstarea); + } + else + { + /* blitting offscreen to offscreen */ + PgContextBlitArea(src->hwdata->offscreenctx, &srcarea, dst->hwdata->offscreenctx, &dstarea); + } + } + + if ((src->flags & SDL_SRCCOLORKEY) == SDL_SRCCOLORKEY) + { + PgChromaOff(); } } + else + { + SDL_SetError("ph_HWAccelBlit(): Source or target surface is not a hardware surface !\n"); + return -1; + } + + PgFlush(); + PgWaitHWIdle(); + return 0; } -int ph_LockHWSurface(_THIS, SDL_Surface *surface) +int ph_SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key) { - return(0); + if (surface->hwdata!=NULL) + { + surface->hwdata->colorkey=ph_ExpandColor(this, surface, key); + if (surface->hwdata->colorkey==0xFFFFFFFFUL) + { + return -1; + } + } + PgSetChroma(surface->hwdata->colorkey, Pg_CHROMA_SRC_MATCH | Pg_CHROMA_NODRAW); + + return 0; } -void ph_UnlockHWSurface(_THIS, SDL_Surface *surface) +int ph_SetHWAlpha(_THIS, SDL_Surface* surface, Uint8 alpha) { - return; + return -1; } #ifdef HAVE_OPENGL @@ -513,12 +970,12 @@ void ph_NormalUpdate(_THIS, int numrects, SDL_Rect *rects) for (i=0; ih) + { + if ((mode_info.height==480) && (screen->h==400)) + { + videomode_emulatemode=1; + } + } + else + { + videomode_emulatemode=0; + } } /* save old video mode caps */ @@ -266,6 +306,15 @@ int ph_EnterFullScreen(_THIS, SDL_Surface* screen) settings.refresh = 0; settings.flags = 0; + refreshrate=getenv("SDL_PHOTON_FULLSCREEN_REFRESH"); + if (refreshrate!=NULL) + { + if (sscanf(refreshrate, "%d", &refreshratenum)==1) + { + settings.refresh = refreshratenum; + } + } + if (PgSetVideoMode(&settings) < 0) { SDL_SetError("ph_EnterFullScreen(): PgSetVideoMode() call failed !\n"); diff --git a/src/video/photon/SDL_ph_video.c b/src/video/photon/SDL_ph_video.c index ee1e0d206..9356ec9c4 100644 --- a/src/video/photon/SDL_ph_video.c +++ b/src/video/photon/SDL_ph_video.c @@ -68,7 +68,7 @@ static int phstatus=-1; static int ph_Available(void) { - if (phstatus==-1) + if (phstatus!=0) { phstatus=PtInit(NULL); if (phstatus==0) @@ -116,10 +116,10 @@ static SDL_VideoDevice *ph_CreateDevice(int devindex) device->UpdateRects = NULL; /* set up in ph_SetupUpdateFunction */ device->VideoQuit = ph_VideoQuit; device->AllocHWSurface = ph_AllocHWSurface; - device->CheckHWBlit = NULL; - device->FillHWRect = NULL; - device->SetHWColorKey = NULL; - device->SetHWAlpha = NULL; + device->CheckHWBlit = ph_CheckHWBlit; + device->FillHWRect = ph_FillHWRect; + device->SetHWColorKey = ph_SetHWColorKey; + device->SetHWAlpha = ph_SetHWAlpha; device->LockHWSurface = ph_LockHWSurface; device->UnlockHWSurface = ph_UnlockHWSurface; device->FlipHWSurface = ph_FlipHWSurface; @@ -254,6 +254,14 @@ static int ph_SetupWindow(_THIS, int w, int h, int flags) } else { + if ((flags & SDL_HWSURFACE) == SDL_HWSURFACE) + { + PtSetArg(&args[nargs++], Pt_ARG_BASIC_FLAGS, Pt_TRUE, Pt_BASIC_PREVENT_FILL); + } + else + { + PtSetArg(&args[nargs++], Pt_ARG_FILL_COLOR, Pg_BLACK, 0); + } if (!currently_maximized) { windowpos = getenv("SDL_VIDEO_WINDOW_POS"); @@ -293,8 +301,6 @@ static int ph_SetupWindow(_THIS, int w, int h, int flags) } } - PtSetArg(&args[nargs++], Pt_ARG_FILL_COLOR, Pg_BLACK, 0); - /* if window is maximized render it as maximized */ if (currently_maximized) { @@ -311,7 +317,7 @@ static int ph_SetupWindow(_THIS, int w, int h, int flags) /* bring the focus to the window */ PtSetArg(&args[nargs++], Pt_ARG_WINDOW_STATE, Pt_TRUE, Ph_WM_STATE_ISFOCUS); - /* allow to catch hide events */ + /* allow to catch hide event */ PtSetArg(&args[nargs++], Pt_ARG_WINDOW_MANAGED_FLAGS, Pt_TRUE, Ph_WM_HIDE); PtSetArg(&args[nargs++], Pt_ARG_WINDOW_NOTIFY_FLAGS, Pt_TRUE, Ph_WM_HIDE); } @@ -320,6 +326,11 @@ static int ph_SetupWindow(_THIS, int w, int h, int flags) PtRealizeWidget(window); PtWindowToFront(window); +#if 0 /* FIXME */ + PtGetResource(window, Pt_ARG_POS, &olddim, 0); + fprintf(stderr, "POSITION: %d, %d\n", olddim->w, olddim->h); +#endif + return 0; } @@ -350,9 +361,9 @@ static const struct ColourMasks* ph_GetColourMasks(int bpp) return NULL; } -static int ph_VideoInit(_THIS, SDL_PixelFormat *vformat) +static int ph_VideoInit(_THIS, SDL_PixelFormat* vformat) { - PgHWCaps_t my_hwcaps; + PgHWCaps_t hwcaps; int i; window=NULL; @@ -391,14 +402,14 @@ static int ph_VideoInit(_THIS, SDL_PixelFormat *vformat) return -1; } - if (PgGetGraphicsHWCaps(&my_hwcaps) < 0) + if (PgGetGraphicsHWCaps(&hwcaps) < 0) { SDL_SetError("ph_VideoInit(): GetGraphicsHWCaps function failed !\n"); this->FreeWMCursor(this, SDL_BlankCursor); return -1; } - if (PgGetVideoModeInfo(my_hwcaps.current_video_mode, &desktop_mode) < 0) + if (PgGetVideoModeInfo(hwcaps.current_video_mode, &desktop_mode) < 0) { SDL_SetError("ph_VideoInit(): PgGetVideoModeInfo function failed !\n"); this->FreeWMCursor(this, SDL_BlankCursor); @@ -437,15 +448,22 @@ static int ph_VideoInit(_THIS, SDL_PixelFormat *vformat) OCImage.CurrentFrameData = NULL; OCImage.FrameData0 = NULL; OCImage.FrameData1 = NULL; + videomode_emulatemode = 0; + this->info.video_mem=hwcaps.currently_available_video_ram/1024; this->info.wm_available = 1; + this->info.hw_available = 1; + this->info.blit_fill = 1; + this->info.blit_hw = 1; + this->info.blit_hw_A = 0; + this->info.blit_hw_CC = 1; return 0; } -static SDL_Surface *ph_SetVideoMode(_THIS, SDL_Surface *current, - int width, int height, int bpp, Uint32 flags) +static SDL_Surface* ph_SetVideoMode(_THIS, SDL_Surface *current, int width, int height, int bpp, Uint32 flags) { + PgHWCaps_t hwcaps; const struct ColourMasks* mask; /* Lock the event thread, in multi-threading environments */ @@ -474,13 +492,13 @@ static SDL_Surface *ph_SetVideoMode(_THIS, SDL_Surface *current, return NULL; } -#ifdef HAVE_OPENGL if ((current->flags & SDL_OPENGL)==SDL_OPENGL) { -#else - if ((current->flags & SDL_OPENGL)==SDL_OPENGL) /* if no built-in OpenGL support */ +#if !defined(HAVE_OPENGL) + if ((current->flags & SDL_OPENGL)==SDL_OPENGL) { - SDL_SetError("ph_SetVideoMode(): no OpenGL support, try to recompile library.\n"); + /* if no built-in OpenGL support */ + SDL_SetError("ph_SetVideoMode(): no OpenGL support, you need to recompile SDL.\n"); current->flags &= ~SDL_OPENGL; return NULL; #endif /* HAVE_OPENGL */ @@ -500,13 +518,12 @@ static SDL_Surface *ph_SetVideoMode(_THIS, SDL_Surface *current, } else { - /* remove this if we'll support non-fullscreen sw/hw+doublebuf */ + /* remove this if we'll have support for the non-fullscreen sw/hw+doublebuf one day */ current->flags &= ~SDL_DOUBLEBUF; /* Use offscreen memory if SDL_HWSURFACE flag is set */ if ((current->flags & SDL_HWSURFACE) == SDL_HWSURFACE) { - if (desktopbpp!=bpp) { current->flags &= ~SDL_HWSURFACE; @@ -556,9 +573,18 @@ static SDL_Surface *ph_SetVideoMode(_THIS, SDL_Surface *current, PgFlush(); } + visualbpp=bpp; + + if (PgGetGraphicsHWCaps(&hwcaps) < 0) + { + SDL_SetError("ph_SetVideoMode(): GetGraphicsHWCaps function failed !\n"); + return NULL; + } + this->info.video_mem=hwcaps.currently_available_video_ram/1024; + SDL_Unlock_EventThread(); - /* We're done! */ + /* We've done! */ return (current); } diff --git a/src/video/photon/SDL_ph_video.h b/src/video/photon/SDL_ph_video.h index eb4e85436..49a526a52 100644 --- a/src/video/photon/SDL_ph_video.h +++ b/src/video/photon/SDL_ph_video.h @@ -96,8 +96,9 @@ struct SDL_PrivateVideoData int mouse_relative; WMcursor* BlankCursor; + uint32_t videomode_emulatemode; - Uint32 depth; /* current visual depth (not bpp) */ + Uint32 visualbpp; /* current visual bpp */ Uint32 desktopbpp; /* bpp of desktop at the moment of start */ Uint32 desktoppal; /* palette mode emulation or system */ @@ -109,25 +110,27 @@ struct SDL_PrivateVideoData SDL_Overlay* overlay; }; -#define mode_settings (this->hidden->mode_settings) -#define window (this->hidden->Window) -#define SDL_Image (this->hidden->image) -#define OCImage (this->hidden->ocimage) -#define old_video_mode (this->hidden->old_video_mode) -#define old_refresh_rate (this->hidden->old_refresh_rate) -#define graphics_card_caps (this->hidden->graphics_card_caps) -#define desktopbpp (this->hidden->desktopbpp) -#define desktoppal (this->hidden->desktoppal) -#define savedpal (this->hidden->savedpal) -#define syspalph (this->hidden->syspalph) -#define currently_fullscreen (this->hidden->currently_fullscreen) -#define currently_hided (this->hidden->currently_hided) -#define currently_maximized (this->hidden->currently_maximized) -#define event (this->hidden->event) -#define current_overlay (this->hidden->overlay) -#define desktop_mode (this->hidden->desktop_mode) -#define mouse_relative (this->hidden->mouse_relative) -#define SDL_BlankCursor (this->hidden->BlankCursor) +#define mode_settings (this->hidden->mode_settings) +#define window (this->hidden->Window) +#define SDL_Image (this->hidden->image) +#define OCImage (this->hidden->ocimage) +#define old_video_mode (this->hidden->old_video_mode) +#define old_refresh_rate (this->hidden->old_refresh_rate) +#define graphics_card_caps (this->hidden->graphics_card_caps) +#define desktopbpp (this->hidden->desktopbpp) +#define visualbpp (this->hidden->visualbpp) +#define desktoppal (this->hidden->desktoppal) +#define savedpal (this->hidden->savedpal) +#define syspalph (this->hidden->syspalph) +#define currently_fullscreen (this->hidden->currently_fullscreen) +#define currently_hided (this->hidden->currently_hided) +#define currently_maximized (this->hidden->currently_maximized) +#define event (this->hidden->event) +#define current_overlay (this->hidden->overlay) +#define desktop_mode (this->hidden->desktop_mode) +#define mouse_relative (this->hidden->mouse_relative) +#define SDL_BlankCursor (this->hidden->BlankCursor) +#define videomode_emulatemode (this->hidden->videomode_emulatemode) #ifdef HAVE_OPENGL #define oglctx (this->hidden->OGLContext) diff --git a/test/testvidinfo.c b/test/testvidinfo.c index 813263ef2..2b4b1d023 100644 --- a/test/testvidinfo.c +++ b/test/testvidinfo.c @@ -27,6 +27,12 @@ void PrintFlags(Uint32 flags) if ( flags & SDL_DOUBLEBUF ) { printf(" | SDL_DOUBLEBUF"); } + if ( flags & SDL_SRCCOLORKEY ) { + printf(" | SDL_SRCCOLORKEY"); + } + if ( flags & SDL_RLEACCEL ) { + printf(" | SDL_RLEACCEL"); + } } int RunBlitTests(SDL_Surface *screen, SDL_Surface *bmp, int blitcount) @@ -67,7 +73,7 @@ int RunModeTests(SDL_Surface *screen) float seconds; int i; Uint8 r, g, b; - SDL_Surface *bmp, *tmp; + SDL_Surface *bmp, *bmpcc, *tmp; SDL_Event event; while ( SDL_PollEvent(&event) ) { @@ -116,6 +122,7 @@ int RunModeTests(SDL_Surface *screen) return 0; } + /* run the generic blit test */ bmp = SDL_LoadBMP("sample.bmp"); if ( ! bmp ) { printf("Couldn't load sample.bmp: %s\n", SDL_GetError()); @@ -135,6 +142,29 @@ int RunModeTests(SDL_Surface *screen) printf("%d blits / %d updates in zero seconds!\n", NUM_BLITS*frames, frames); } + /* run the colorkeyed blit test */ + bmpcc = SDL_LoadBMP("sample.bmp"); + if ( ! bmpcc ) { + printf("Couldn't load sample.bmp: %s\n", SDL_GetError()); + return 0; + } + printf("Running freshly loaded cc blit test: %dx%d at %d bpp, flags: ", + bmpcc->w, bmpcc->h, bmpcc->format->BitsPerPixel); + SDL_SetColorKey(bmpcc, SDL_SRCCOLORKEY | SDL_RLEACCEL, *(Uint8 *)bmpcc->pixels); + + PrintFlags(bmpcc->flags); + printf("\n"); + then = SDL_GetTicks(); + frames = RunBlitTests(screen, bmpcc, NUM_BLITS); + now = SDL_GetTicks(); + seconds = (float)(now - then) / 1000.0f; + if ( seconds > 0.0f ) { + printf("%d cc blits / %d updates in %2.2f seconds, %2.2f FPS\n", NUM_BLITS*frames, frames, seconds, (float)frames / seconds); + } else { + printf("%d cc blits / %d updates in zero seconds!\n", NUM_BLITS*frames, frames); + } + + /* run the generic blit test */ tmp = bmp; bmp = SDL_DisplayFormat(bmp); SDL_FreeSurface(tmp); @@ -155,6 +185,30 @@ int RunModeTests(SDL_Surface *screen) } else { printf("%d blits / %d updates in zero seconds!\n", NUM_BLITS*frames, frames); } + + /* run the colorkeyed blit test */ + tmp = bmpcc; + bmpcc = SDL_DisplayFormat(bmpcc); + SDL_FreeSurface(tmp); + if ( ! bmpcc ) { + printf("Couldn't convert sample.bmp: %s\n", SDL_GetError()); + return 0; + } + printf("Running display format cc blit test: %dx%d at %d bpp, flags: ", + bmpcc->w, bmpcc->h, bmpcc->format->BitsPerPixel); + PrintFlags(bmpcc->flags); + printf("\n"); + then = SDL_GetTicks(); + frames = RunBlitTests(screen, bmpcc, NUM_BLITS); + now = SDL_GetTicks(); + seconds = (float)(now - then) / 1000.0f; + if ( seconds > 0.0f ) { + printf("%d cc blits / %d updates in %2.2f seconds, %2.2f FPS\n", NUM_BLITS*frames, frames, seconds, (float)frames / seconds); + } else { + printf("%d cc blits / %d updates in zero seconds!\n", NUM_BLITS*frames, frames); + } + + SDL_FreeSurface(bmpcc); SDL_FreeSurface(bmp); while ( SDL_PollEvent(&event) ) {