Mercurial > sdl-ios-xcode
view src/video/photon/SDL_ph_image.c @ 894:1d1a823904d8
Don't crash if the stretch routines are used on hardware surfaces
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Sun, 16 May 2004 21:08:55 +0000 |
parents | 05c551e5bc64 |
children | 4ab6d1fd028f |
line wrap: on
line source
/* SDL - Simple DirectMedia Layer Copyright (C) 1997-2004 Sam Lantinga This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Sam Lantinga slouken@libsdl.org */ #ifdef SAVE_RCSID static char rcsid = "@(#) $Id$"; #endif #include <stdlib.h> #include <Ph.h> #include <photon/Pg.h> #include "SDL.h" #include "SDL_error.h" #include "SDL_endian.h" #include "SDL_video.h" #include "SDL_pixels_c.h" #include "SDL_ph_image_c.h" #include "SDL_ph_modes_c.h" int ph_SetupImage(_THIS, SDL_Surface *screen) { PgColor_t* palette=NULL; int type=0; int bpp; bpp=screen->format->BitsPerPixel; /* Determine image type */ switch(bpp) { case 8:{ type = Pg_IMAGE_PALETTE_BYTE; } break; case 15:{ type = Pg_IMAGE_DIRECT_555; } break; case 16:{ type = Pg_IMAGE_DIRECT_565; } break; case 24:{ type = Pg_IMAGE_DIRECT_888; } break; case 32:{ type = Pg_IMAGE_DIRECT_8888; } break; default:{ SDL_SetError("ph_SetupImage(): unsupported bpp=%d !\n", bpp); return -1; } break; } /* palette emulation code */ if ((bpp==8) && (desktoppal==SDLPH_PAL_EMULATE)) { /* creating image palette */ palette=malloc(_Pg_MAX_PALETTE*sizeof(PgColor_t)); if (palette==NULL) { SDL_SetError("ph_SetupImage(): can't allocate memory for palette !\n"); return -1; } PgGetPalette(palette); /* using shared memory for speed (set last param to 1) */ if ((SDL_Image = PhCreateImage(NULL, screen->w, screen->h, type, palette, _Pg_MAX_PALETTE, 1)) == NULL) { SDL_SetError("ph_SetupImage(): PhCreateImage() failed for bpp=8 !\n"); free(palette); return -1; } } else { /* using shared memory for speed (set last param to 1) */ if ((SDL_Image = PhCreateImage(NULL, screen->w, screen->h, type, NULL, 0, 1)) == NULL) { SDL_SetError("ph_SetupImage(): PhCreateImage() failed for bpp=%d !\n", bpp); return -1; } } screen->pixels = SDL_Image->image; screen->pitch = SDL_Image->bpl; this->UpdateRects = ph_NormalUpdate; return 0; } int ph_SetupOCImage(_THIS, SDL_Surface *screen) { int type = 0; int bpp; OCImage.flags = screen->flags; bpp=screen->format->BitsPerPixel; /* Determine image type */ switch(bpp) { case 8: { type = Pg_IMAGE_PALETTE_BYTE; } break; case 15:{ type = Pg_IMAGE_DIRECT_555; } break; case 16:{ type = Pg_IMAGE_DIRECT_565; } break; case 24:{ type = Pg_IMAGE_DIRECT_888; } break; case 32:{ type = Pg_IMAGE_DIRECT_8888; } break; default:{ SDL_SetError("ph_SetupOCImage(): unsupported bpp=%d !\n", bpp); return -1; } break; } /* Currently offscreen contexts with the same bit depth as display bpp only can be created */ OCImage.offscreen_context = PdCreateOffscreenContext(0, screen->w, screen->h, Pg_OSC_MEM_PAGE_ALIGN); if (OCImage.offscreen_context == NULL) { SDL_SetError("ph_SetupOCImage(): PdCreateOffscreenContext() function failed !\n"); return -1; } screen->pitch = OCImage.offscreen_context->pitch; OCImage.dc_ptr = (unsigned char *)PdGetOffscreenContextPtr(OCImage.offscreen_context); if (OCImage.dc_ptr == NULL) { SDL_SetError("ph_SetupOCImage(): PdGetOffscreenContextPtr function failed !\n"); PhDCRelease(OCImage.offscreen_context); return -1; } OCImage.FrameData0 = OCImage.dc_ptr; OCImage.CurrentFrameData = OCImage.FrameData0; OCImage.current = 0; PhDCSetCurrent(OCImage.offscreen_context); screen->pixels = OCImage.CurrentFrameData; this->UpdateRects = ph_OCUpdate; return 0; } int ph_SetupFullScreenImage(_THIS, SDL_Surface* screen) { OCImage.flags = screen->flags; /* Begin direct mode */ if (!ph_EnterFullScreen(this, screen)) { return -1; } /* store palette for fullscreen */ if ((screen->format->BitsPerPixel==8) && (desktopbpp!=8)) { PgGetPalette(savedpal); PgGetPalette(syspalph); } OCImage.offscreen_context = PdCreateOffscreenContext(0, 0, 0, Pg_OSC_MAIN_DISPLAY | Pg_OSC_MEM_PAGE_ALIGN | Pg_OSC_CRTC_SAFE); if (OCImage.offscreen_context == NULL) { SDL_SetError("ph_SetupFullScreenImage(): PdCreateOffscreenContext() function failed !\n"); return -1; } if ((screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) { 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"); return -1; } } OCImage.FrameData0 = (unsigned char *)PdGetOffscreenContextPtr(OCImage.offscreen_context); if (OCImage.FrameData0 == NULL) { SDL_SetError("ph_SetupFullScreenImage(): PdGetOffscreenContextPtr() function failed !\n"); ph_DestroyImage(this, screen); return -1; } if ((screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) { OCImage.FrameData1 = (unsigned char *)PdGetOffscreenContextPtr(OCImage.offscreen_backcontext); if (OCImage.FrameData1 == NULL) { SDL_SetError("ph_SetupFullScreenImage(back): PdGetOffscreenContextPtr() function failed !\n"); ph_DestroyImage(this, screen); return -1; } } /* wait for the hardware */ PgFlush(); PgWaitHWIdle(); if ((screen->flags & SDL_DOUBLEBUF) == SDL_DOUBLEBUF) { 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 { 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; } } this->UpdateRects = ph_OCDCUpdate; /* wait for the hardware */ PgFlush(); PgWaitHWIdle(); return 0; } #ifdef HAVE_OPENGL static int ph_SetupOpenGLContext(_THIS, int width, int height, int bpp, Uint32 flags) { PhDim_t dim; uint64_t OGLAttrib[PH_OGL_MAX_ATTRIBS]; int exposepost=0; int OGLargc; dim.w=width; dim.h=height; if ((oglctx!=NULL) && (oglflags==flags) && (oglbpp==bpp)) { PdOpenGLContextResize(oglctx, &dim); PhDCSetCurrent(oglctx); return 0; } else { if (oglctx!=NULL) { PhDCSetCurrent(NULL); PhDCRelease(oglctx); oglctx=NULL; exposepost=1; } } OGLargc=0; if (this->gl_config.depth_size) { OGLAttrib[OGLargc++]=PHOGL_ATTRIB_DEPTH_BITS; OGLAttrib[OGLargc++]=this->gl_config.depth_size; } if (this->gl_config.stencil_size) { OGLAttrib[OGLargc++]=PHOGL_ATTRIB_STENCIL_BITS; OGLAttrib[OGLargc++]=this->gl_config.stencil_size; } OGLAttrib[OGLargc++]=PHOGL_ATTRIB_FORCE_SW; if (flags & SDL_FULLSCREEN) { OGLAttrib[OGLargc++]=PHOGL_ATTRIB_FULLSCREEN; OGLAttrib[OGLargc++]=PHOGL_ATTRIB_DIRECT; OGLAttrib[OGLargc++]=PHOGL_ATTRIB_FULLSCREEN_BEST; OGLAttrib[OGLargc++]=PHOGL_ATTRIB_FULLSCREEN_CENTER; } OGLAttrib[OGLargc++]=PHOGL_ATTRIB_NONE; if (this->gl_config.double_buffer) { oglctx=PdCreateOpenGLContext(2, &dim, 0, OGLAttrib); } else { oglctx=PdCreateOpenGLContext(1, &dim, 0, OGLAttrib); } if (oglctx==NULL) { SDL_SetError("ph_SetupOpenGLContext(): cannot create OpenGL context !\n"); return (-1); } PhDCSetCurrent(oglctx); PtFlush(); oglflags=flags; oglbpp=bpp; if (exposepost!=0) { /* OpenGL context has been recreated, so report about this fact */ SDL_PrivateExpose(); } return 0; } int ph_SetupOpenGLImage(_THIS, SDL_Surface* screen) { this->UpdateRects = ph_OpenGLUpdate; screen->pixels=NULL; screen->pitch=NULL; if (ph_SetupOpenGLContext(this, screen->w, screen->h, screen->format->BitsPerPixel, screen->flags)!=0) { screen->flags &= ~SDL_OPENGL; return -1; } return 0; } #endif /* HAVE_OPENGL */ void ph_DestroyImage(_THIS, SDL_Surface* screen) { #ifdef HAVE_OPENGL if ((screen->flags & SDL_OPENGL)==SDL_OPENGL) { if (oglctx) { PhDCSetCurrent(NULL); PhDCRelease(oglctx); oglctx=NULL; oglflags=0; oglbpp=0; } return; } #endif /* HAVE_OPENGL */ if (currently_fullscreen) { /* if we right now in 8bpp fullscreen we must release palette */ if ((screen->format->BitsPerPixel==8) && (desktopbpp!=8)) { PgSetPalette(syspalph, 0, -1, 0, 0, 0); PgSetPalette(savedpal, 0, 0, _Pg_MAX_PALETTE, Pg_PALSET_GLOBAL | Pg_PALSET_FORCE_EXPOSE, 0); PgFlush(); } ph_LeaveFullScreen(this); } if (OCImage.offscreen_context != NULL) { PhDCRelease(OCImage.offscreen_context); OCImage.offscreen_context = NULL; OCImage.FrameData0 = NULL; } if (OCImage.offscreen_backcontext != NULL) { PhDCRelease(OCImage.offscreen_backcontext); OCImage.offscreen_backcontext = NULL; OCImage.FrameData1 = NULL; } OCImage.CurrentFrameData = NULL; if (SDL_Image) { /* if palette allocated, free it */ if (SDL_Image->palette) { free(SDL_Image->palette); } PgShmemDestroy(SDL_Image->image); free(SDL_Image); } /* Must be zeroed everytime */ SDL_Image = NULL; if (screen) { screen->pixels = NULL; } } 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; } if ((vmode.mode_capabilities1 & PgVM_MODE_CAP1_OFFSCREEN) == PgVM_MODE_CAP1_OFFSCREEN) { /* this is a special test for drivers which tries to lie about offscreen capability */ if (hwcaps.currently_available_video_ram!=0) { this->info.hw_available = 1; } else { this->info.hw_available = 0; } } else { this->info.hw_available = 0; } if ((vmode.mode_capabilities2 & PgVM_MODE_CAP2_RECTANGLE) == PgVM_MODE_CAP2_RECTANGLE) { this->info.blit_fill = 1; } else { this->info.blit_fill = 0; } if ((vmode.mode_capabilities2 & PgVM_MODE_CAP2_BITBLT) == PgVM_MODE_CAP2_BITBLT) { this->info.blit_hw = 1; } else { this->info.blit_hw = 0; } 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) { setupresult=ph_SetupOpenGLImage(this, screen); } else { #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 } #endif /* HAVE_OPENGL */ if (setupresult!=-1) { ph_UpdateHWInfo(this); } return setupresult; } int ph_AllocHWSurface(_THIS, SDL_Surface* surface) { 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; if (this->info.blit_fill!=1) { return -1; } 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(); 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) { 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 ((src->flags & SDL_SRCALPHA) == SDL_SRCALPHA) { ph_SetHWAlpha(this, src, src->format->alpha); PgAlphaOn(); } 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 { 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_SRCALPHA) == SDL_SRCALPHA) { PgAlphaOff(); } 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_SetHWColorKey(_THIS, SDL_Surface *surface, Uint32 key) { if (this->info.blit_hw_CC!=1) { return -1; } 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; } int ph_SetHWAlpha(_THIS, SDL_Surface* surface, Uint8 alpha) { if (this->info.blit_hw_A!=1) { return -1; } PgSetAlphaBlend(NULL, alpha); return 0; } #ifdef HAVE_OPENGL void ph_OpenGLUpdate(_THIS, int numrects, SDL_Rect* rects) { this->GL_SwapBuffers(this); return; } #endif /* HAVE_OPENGL */ void ph_NormalUpdate(_THIS, int numrects, SDL_Rect *rects) { PhPoint_t ph_pos; PhRect_t ph_rect; int i; for (i=0; i<numrects; ++i) { if (rects[i].w==0) /* Clipped? dunno why but this occurs sometime. */ { continue; } if (rects[i].h==0) /* Clipped? dunno why but this occurs sometime. */ { continue; } ph_pos.x = rects[i].x; ph_pos.y = rects[i].y; ph_rect.ul.x = rects[i].x; ph_rect.ul.y = rects[i].y; ph_rect.lr.x = rects[i].x + rects[i].w; ph_rect.lr.y = rects[i].y + rects[i].h; if (PgDrawPhImageRectmx(&ph_pos, SDL_Image, &ph_rect, 0) < 0) { SDL_SetError("ph_NormalUpdate(): PgDrawPhImageRectmx failed!\n"); return; } } if (PgFlush() < 0) { SDL_SetError("ph_NormalUpdate(): PgFlush() function failed!\n"); } } void ph_OCUpdate(_THIS, int numrects, SDL_Rect *rects) { int i; PhPoint_t zero = {0, 0}; PhArea_t src_rect; PhArea_t dest_rect; PgSetTranslation(&zero, 0); PgSetRegion(PtWidgetRid(window)); PgSetClipping(0, NULL); PgFlush(); PgWaitHWIdle(); for (i=0; i<numrects; ++i) { if (rects[i].w == 0) /* Clipped? */ { continue; } if (rects[i].h == 0) /* Clipped? */ { continue; } src_rect.pos.x=rects[i].x; src_rect.pos.y=rects[i].y; dest_rect.pos.x=rects[i].x; dest_rect.pos.y=rects[i].y; src_rect.size.w=rects[i].w; src_rect.size.h=rects[i].h; dest_rect.size.w=rects[i].w; dest_rect.size.h=rects[i].h; PgContextBlitArea(OCImage.offscreen_context, &src_rect, NULL, &dest_rect); } if (PgFlush() < 0) { SDL_SetError("ph_OCUpdate(): PgFlush failed.\n"); } } void ph_OCDCUpdate(_THIS, int numrects, SDL_Rect *rects) { PgWaitHWIdle(); if (PgFlush() < 0) { SDL_SetError("ph_OCDCUpdate(): PgFlush failed.\n"); } }