SDL_Surface* Blitter::create_surface_from_format(SDL_Surface* surface, int w, int h) { SDL_Surface* new_surface = SDL_CreateRGBSurface(0, w, h, surface->format->BitsPerPixel, surface->format->Rmask, surface->format->Gmask, surface->format->Bmask, surface->format->Amask); Uint8 alpha; if (SDL_GetSurfaceAlphaMod(surface, &alpha) == 0) SDL_SetSurfaceAlphaMod(new_surface, alpha); SDL_BlendMode blend_mode; if (SDL_GetSurfaceBlendMode(surface, &blend_mode) == 0) SDL_SetSurfaceBlendMode(new_surface, blend_mode); Uint8 r, g, b; if (SDL_GetSurfaceColorMod(surface, &r, &g, &b) == 0) SDL_SetSurfaceColorMod(new_surface, r, g, b); if (surface->format->palette) SDL_SetSurfacePalette(new_surface, surface->format->palette); Uint32 colorkey; if (SDL_GetColorKey(surface, &colorkey) == 0) SDL_SetColorKey(new_surface, SDL_TRUE, colorkey); return new_surface; }
/* Create a 32-bit writable surface for blitting tests */ void _surfaceSetUp(void *arg) { int result; SDL_BlendMode blendMode = SDL_BLENDMODE_NONE; SDL_BlendMode currentBlendMode; Uint32 rmask, gmask, bmask, amask; #if SDL_BYTEORDER == SDL_BIG_ENDIAN rmask = 0xff000000; gmask = 0x00ff0000; bmask = 0x0000ff00; amask = 0x000000ff; #else rmask = 0x000000ff; gmask = 0x0000ff00; bmask = 0x00ff0000; amask = 0xff000000; #endif referenceSurface = SDLTest_ImageBlit(); /* For size info */ testSurface = SDL_CreateRGBSurface(SDL_SWSURFACE, referenceSurface->w, referenceSurface->h, 32, rmask, gmask, bmask, amask); SDLTest_AssertCheck(testSurface != NULL, "Check that testSurface is not NULL"); if (testSurface != NULL) { /* Disable blend mode for target surface */ result = SDL_SetSurfaceBlendMode(testSurface, blendMode); SDLTest_AssertCheck(result == 0, "Validate result from SDL_SetSurfaceBlendMode, expected: 0, got: %i", result); result = SDL_GetSurfaceBlendMode(testSurface, ¤tBlendMode); SDLTest_AssertCheck(result == 0, "Validate result from SDL_GetSurfaceBlendMode, expected: 0, got: %i", result); SDLTest_AssertCheck(currentBlendMode == blendMode, "Validate blendMode, expected: %i, got: %i", blendMode, currentBlendMode); } }
static mrb_value mrb_sdl2_video_surface_get_blend_mode(mrb_state *mrb, mrb_value self) { SDL_BlendMode mode; SDL_Surface *s = mrb_sdl2_video_surface_get_ptr(mrb, self); if (0 != SDL_GetSurfaceBlendMode(s, &mode)) { mruby_sdl2_raise_error(mrb); } return mrb_fixnum_value(mode); }
int inline Surface::getBlendMode(State & state, SDL_Surface * surface){ SDL_BlendMode blendMode; if (SDL_GetSurfaceBlendMode(surface, &blendMode) == 0){ state.stack->push<int>((int)blendMode); return 1; } else{ return 0; } }
SDL_BlendMode Surface::getBlendMode(void) { SDL_BlendMode mode; if(SDL_GetSurfaceBlendMode(sdlSurface, &mode) == 0) { Logger::Error(SDL_GetError()); } return mode; }
const SDL_BlendMode Image::blend_mode ( void ) const { SDL_BlendMode blend; if ( SDL_GetSurfaceBlendMode ( this->image(), &blend ) != 0 ) { NOM_LOG_ERR ( NOM, SDL_GetError() ); return blend; } return blend; }
Surface::BlendMode SurfaceSDL::getBlendMode() const { SDL_BlendMode sdl_bm; SDL_GetSurfaceBlendMode(surface_, &sdl_bm); switch(sdl_bm) { case SDL_BLENDMODE_NONE: return BLEND_MODE_NONE; case SDL_BLENDMODE_BLEND: return BLEND_MODE_BLEND; case SDL_BLENDMODE_ADD: return BLEND_MODE_ADD; case SDL_BLENDMODE_MOD: return BLEND_MODE_MODULATE; } ASSERT_LOG(false, "Unrecognised SDL blend mode: " << sdl_bm); return BLEND_MODE_NONE; }
bool GsBitmap::scaleTo(const GsRect<Uint16> &destRes) { SDL_Rect newRect = destRes.SDLRect(); // Need to do that, otherwise it won't work. optimizeSurface(); if(newRect.w == mpBitmapSurface->w && newRect.h == mpBitmapSurface->h) return true; std::shared_ptr<SDL_Surface> newSfc; auto bmpSfc = mpBitmapSurface.get(); auto bmpFormat = bmpSfc->format; newSfc.reset( SDL_CreateRGBSurface(bmpSfc->flags, newRect.w, newRect.h, bmpFormat->BitsPerPixel, bmpFormat->Rmask, bmpFormat->Gmask, bmpFormat->Bmask, bmpFormat->Amask ), &SDL_FreeSurface ); if(!newSfc) return false; #if SDL_VERSION_ATLEAST(2, 0, 0) SDL_BlendMode blendMode; SDL_GetSurfaceBlendMode(bmpSfc, &blendMode); SDL_SetSurfaceBlendMode(newSfc.get(), blendMode); #endif CVidConfig &vidConf = gVideoDriver.getVidConfig(); blitScaled(bmpSfc, bmpSfc->clip_rect, newSfc.get(), newRect, vidConf.m_ScaleXFilter); mpBitmapSurface = newSfc; return true; }
SDL_Surface *image_sdl_trim(SDL_Surface *src, uint32_t left, uint32_t top, uint32_t right, uint32_t bottom) { int ret; SDL_Surface *res; SDL_Rect rect; SDL_BlendMode swap; assert(src); if(left + right >= src->w || top + bottom >= src->h) return NULL; if(left == 0 && top == 0 && right == 0 && bottom == 0) return image_sdl_clone(src); res = image_sdl_create(src->w - left - right, src->h - top - bottom, color_transparent); if(!res){ sg_log_err("Image create failure, %s.", SDL_GetError()); return NULL; } rect.x = -left; rect.y = -top; rect.w = src->w - right; rect.h = src->h - bottom; ret = SDL_GetSurfaceBlendMode(src, &swap); if(ret != 0) { sg_log_err("SDL_GetSurfaceBlendMode failure, %s.", SDL_GetError()); SDL_FreeSurface(res); res = NULL; } SDL_SetSurfaceBlendMode(src, SDL_BLENDMODE_NONE); ret = SDL_BlitSurface(src, NULL, res, &rect); if(ret != 0) { sg_log_err("SDL_BlitSurface failure: %s.", SDL_GetError()); SDL_FreeSurface(res); res = NULL; } SDL_SetSurfaceBlendMode(src, swap); return res; }
bool GsSurface::scaleTo(const GsRect<Uint16> &scaledRect, const filterOptionType filter) { SDL_Rect newRect = scaledRect.SDLRect(); if(newRect.w == mpSurface->w && newRect.h == mpSurface->h) return true; // Need to do that, otherwise it won't work ??? //optimizeSurface(); auto sfcFormat = mpSurface->format; SDL_Surface *newSfc = SDL_CreateRGBSurface(mpSurface->flags, newRect.w, newRect.h, sfcFormat->BitsPerPixel, sfcFormat->Rmask, sfcFormat->Gmask, sfcFormat->Bmask, sfcFormat->Amask ); if(!newSfc) return false; #if SDL_VERSION_ATLEAST(2, 0, 0) SDL_BlendMode blendMode; SDL_GetSurfaceBlendMode(mpSurface, &blendMode); SDL_SetSurfaceBlendMode(newSfc, blendMode); #endif blitScaled(mpSurface, mpSurface->clip_rect, newSfc, newRect, filter); // Tear down old surface! SDL_FreeSurface(mpSurface); // And set the newly created and scaled one mpSurface = newSfc; return true; }
void vsTextureInternal::ProcessSurface( SDL_Surface *source ) { // SDL_Surface *screen = SDL_GetVideoSurface(); SDL_Rect area; //SDL_SetAlpha(source, 0, SDL_ALPHA_OPAQUE); m_width = source->w; m_height = source->h; int w = power_of_two(source->w); int h = power_of_two(source->h); m_glTextureWidth = w; m_glTextureHeight = h; SDL_Surface *image = SDL_CreateRGBSurface( SDL_SWSURFACE, w, h, 32, #if SDL_BYTEORDER == SDL_LIL_ENDIAN /* OpenGL RGBA masks */ 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 #else 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF #endif ); vsAssert(image, "Error??"); SDL_BlendMode bm; SDL_GetSurfaceBlendMode(source, &bm); if ( bm != SDL_BLENDMODE_NONE ) { SDL_SetSurfaceBlendMode(source, SDL_BLENDMODE_NONE); } /* Copy the surface into the GL texture image */ area.x = 0; area.y = 0; area.w = source->w; area.h = source->h; SDL_BlitSurface(source, &area, image, &area); /* Restore the alpha blending attributes */ if ( bm != SDL_BLENDMODE_NONE ) { SDL_SetSurfaceBlendMode(source, bm); } /* Create an OpenGL texture for the image */ GLuint t; glGenTextures(1, &t); m_texture = t; glBindTexture(GL_TEXTURE_2D, m_texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); // glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, image->pixels); glGenerateMipmap(GL_TEXTURE_2D); #if 0 /* if ( 0 ) { int wid = w; int hei = h; int mapMapId = 1; while ( wid > 32 || hei > 32 ) { wid = wid >> 1; hei = hei >> 1; glTexImage2D(GL_TEXTURE_2D, mapMapId++, GL_RGBA, wid, hei, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); } glGenerateMipmapEXT(GL_TEXTURE_2D); }*/ // now lets read it back. #endif // 0 bool doIt = false; if ( doIt ) { unsigned char *imageData = new unsigned char[w*h*4]; glGetTexImage(GL_TEXTURE_2D, 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, imageData); for ( int i = 0; i < w*h; i++ ) { int ri = i*4; int gi = ri+1; int bi = ri+2; int ai = ri+3; unsigned char r = imageData[ri]; unsigned char g = imageData[gi]; unsigned char b = imageData[bi]; unsigned char a = imageData[ai]; unsigned char origr = ((unsigned char*)image->pixels)[ri]; unsigned char og = ((unsigned char*)image->pixels)[gi]; unsigned char ob = ((unsigned char*)image->pixels)[bi]; unsigned char oa = ((unsigned char*)image->pixels)[ai]; if ( r != origr || g != og || b != ob || a != oa ) { vsLog("Pixel %d,%d,%d,%d != %d,%d,%d,%d", r,g,b,a,origr,og,ob,oa); } } delete [] imageData; } //#endif //0 SDL_FreeSurface(image); /* No longer needed */ }
static int SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture, const SDL_Rect * srcrect, const SDL_FRect * dstrect, const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip) { SDL_Surface *surface = SW_ActivateRenderer(renderer); SDL_Surface *src = (SDL_Surface *) texture->driverdata; SDL_Rect final_rect, tmp_rect; SDL_Surface *surface_rotated, *surface_scaled; int retval, dstwidth, dstheight, abscenterx, abscentery; double cangle, sangle, px, py, p1x, p1y, p2x, p2y, p3x, p3y, p4x, p4y; if (!surface) { return -1; } if (renderer->viewport.x || renderer->viewport.y) { final_rect.x = (int)(renderer->viewport.x + dstrect->x); final_rect.y = (int)(renderer->viewport.y + dstrect->y); } else { final_rect.x = (int)dstrect->x; final_rect.y = (int)dstrect->y; } final_rect.w = (int)dstrect->w; final_rect.h = (int)dstrect->h; /* SDLgfx_rotateSurface doesn't accept a source rectangle, so crop and scale if we need to */ tmp_rect = final_rect; tmp_rect.x = 0; tmp_rect.y = 0; if (srcrect->w == final_rect.w && srcrect->h == final_rect.h && srcrect->x == 0 && srcrect->y == 0) { surface_scaled = src; /* but if we don't need to, just use the original */ retval = 0; } else { SDL_Surface *blit_src = src; Uint32 colorkey; SDL_BlendMode blendMode; Uint8 alphaMod, r, g, b; SDL_bool cloneSource = SDL_FALSE; surface_scaled = SDL_CreateRGBSurface(SDL_SWSURFACE, final_rect.w, final_rect.h, src->format->BitsPerPixel, src->format->Rmask, src->format->Gmask, src->format->Bmask, src->format->Amask ); if (!surface_scaled) { return -1; } /* copy the color key, alpha mod, blend mode, and color mod so the scaled surface behaves like the source */ if (SDL_GetColorKey(src, &colorkey) == 0) { SDL_SetColorKey(surface_scaled, SDL_TRUE, colorkey); cloneSource = SDL_TRUE; } SDL_GetSurfaceAlphaMod(src, &alphaMod); /* these will be copied to surface_scaled below if necessary */ SDL_GetSurfaceBlendMode(src, &blendMode); SDL_GetSurfaceColorMod(src, &r, &g, &b); /* now we need to blit the src into surface_scaled. since we want to copy the colors from the source to * surface_scaled rather than blend them, etc. we'll need to disable the blend mode, alpha mod, etc. * but we don't want to modify src (in case it's being used on other threads), so we'll need to clone it * before changing the blend options */ cloneSource |= blendMode != SDL_BLENDMODE_NONE || (alphaMod & r & g & b) != 255; if (cloneSource) { blit_src = SDL_ConvertSurface(src, src->format, src->flags); /* clone src */ if (!blit_src) { SDL_FreeSurface(surface_scaled); return -1; } SDL_SetSurfaceAlphaMod(blit_src, 255); /* disable all blending options in blit_src */ SDL_SetSurfaceBlendMode(blit_src, SDL_BLENDMODE_NONE); SDL_SetColorKey(blit_src, 0, 0); SDL_SetSurfaceColorMod(blit_src, 255, 255, 255); SDL_SetSurfaceRLE(blit_src, 0); /* don't RLE encode a surface we'll only use once */ SDL_SetSurfaceAlphaMod(surface_scaled, alphaMod); /* copy blending options to surface_scaled */ SDL_SetSurfaceBlendMode(surface_scaled, blendMode); SDL_SetSurfaceColorMod(surface_scaled, r, g, b); } retval = SDL_BlitScaled(blit_src, srcrect, surface_scaled, &tmp_rect); if (blit_src != src) { SDL_FreeSurface(blit_src); } } if (!retval) { SDLgfx_rotozoomSurfaceSizeTrig(tmp_rect.w, tmp_rect.h, angle, &dstwidth, &dstheight, &cangle, &sangle); surface_rotated = SDLgfx_rotateSurface(surface_scaled, angle, dstwidth/2, dstheight/2, GetScaleQuality(), flip & SDL_FLIP_HORIZONTAL, flip & SDL_FLIP_VERTICAL, dstwidth, dstheight, cangle, sangle); if(surface_rotated) { /* Find out where the new origin is by rotating the four final_rect points around the center and then taking the extremes */ abscenterx = final_rect.x + (int)center->x; abscentery = final_rect.y + (int)center->y; /* Compensate the angle inversion to match the behaviour of the other backends */ sangle = -sangle; /* Top Left */ px = final_rect.x - abscenterx; py = final_rect.y - abscentery; p1x = px * cangle - py * sangle + abscenterx; p1y = px * sangle + py * cangle + abscentery; /* Top Right */ px = final_rect.x + final_rect.w - abscenterx; py = final_rect.y - abscentery; p2x = px * cangle - py * sangle + abscenterx; p2y = px * sangle + py * cangle + abscentery; /* Bottom Left */ px = final_rect.x - abscenterx; py = final_rect.y + final_rect.h - abscentery; p3x = px * cangle - py * sangle + abscenterx; p3y = px * sangle + py * cangle + abscentery; /* Bottom Right */ px = final_rect.x + final_rect.w - abscenterx; py = final_rect.y + final_rect.h - abscentery; p4x = px * cangle - py * sangle + abscenterx; p4y = px * sangle + py * cangle + abscentery; tmp_rect.x = (int)MIN(MIN(p1x, p2x), MIN(p3x, p4x)); tmp_rect.y = (int)MIN(MIN(p1y, p2y), MIN(p3y, p4y)); tmp_rect.w = dstwidth; tmp_rect.h = dstheight; retval = SDL_BlitSurface(surface_rotated, NULL, surface, &tmp_rect); SDL_FreeSurface(surface_rotated); } } if (surface_scaled != src) { SDL_FreeSurface(surface_scaled); } return retval; }
SDL_Texture * SDL_CreateTextureFromSurface(SDL_Renderer * renderer, SDL_Surface * surface) { const SDL_PixelFormat *fmt; SDL_bool needAlpha; Uint32 i; Uint32 format; SDL_Texture *texture; CHECK_RENDERER_MAGIC(renderer, NULL); if (!surface) { SDL_SetError("SDL_CreateTextureFromSurface() passed NULL surface"); return NULL; } /* See what the best texture format is */ fmt = surface->format; if (fmt->Amask || SDL_GetColorKey(surface, NULL) == 0) { needAlpha = SDL_TRUE; } else { needAlpha = SDL_FALSE; } format = renderer->info.texture_formats[0]; for (i = 0; i < renderer->info.num_texture_formats; ++i) { if (!SDL_ISPIXELFORMAT_FOURCC(renderer->info.texture_formats[i]) && SDL_ISPIXELFORMAT_ALPHA(renderer->info.texture_formats[i]) == needAlpha) { format = renderer->info.texture_formats[i]; break; } } texture = SDL_CreateTexture(renderer, format, SDL_TEXTUREACCESS_STATIC, surface->w, surface->h); if (!texture) { return NULL; } if (format == surface->format->format) { if (SDL_MUSTLOCK(surface)) { SDL_LockSurface(surface); SDL_UpdateTexture(texture, NULL, surface->pixels, surface->pitch); SDL_UnlockSurface(surface); } else { SDL_UpdateTexture(texture, NULL, surface->pixels, surface->pitch); } } else { SDL_PixelFormat *dst_fmt; SDL_Surface *temp = NULL; /* Set up a destination surface for the texture update */ dst_fmt = SDL_AllocFormat(format); temp = SDL_ConvertSurface(surface, dst_fmt, 0); SDL_FreeFormat(dst_fmt); if (temp) { SDL_UpdateTexture(texture, NULL, temp->pixels, temp->pitch); SDL_FreeSurface(temp); } else { SDL_DestroyTexture(texture); return NULL; } } { Uint8 r, g, b, a; SDL_BlendMode blendMode; SDL_GetSurfaceColorMod(surface, &r, &g, &b); SDL_SetTextureColorMod(texture, r, g, b); SDL_GetSurfaceAlphaMod(surface, &a); SDL_SetTextureAlphaMod(texture, a); if (SDL_GetColorKey(surface, NULL) == 0) { /* We converted to a texture with alpha format */ SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND); } else { SDL_GetSurfaceBlendMode(surface, &blendMode); SDL_SetTextureBlendMode(texture, blendMode); } } return texture; }
int IMG_SavePNG_RW(SDL_RWops *src, SDL_Surface *surf,int compression){ png_structp png_ptr; png_infop info_ptr; SDL_PixelFormat *fmt=NULL; SDL_Surface *tempsurf=NULL; int ret,funky_format; unsigned int i; png_colorp palette; Uint8 *palette_alpha=NULL; png_byte **row_pointers=NULL; png_ptr=NULL;info_ptr=NULL;palette=NULL;ret=-1; funky_format=0; SDL_BlendMode temp_blend; if( !src || !surf) { goto savedone; /* Nothing to do. */ } row_pointers=(png_byte **)malloc(surf->h * sizeof(png_byte*)); if (!row_pointers) { SDL_SetError("Couldn't allocate memory for rowpointers"); goto savedone; } png_ptr=png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,NULL,NULL); if (!png_ptr){ SDL_SetError("Couldn't allocate memory for PNG file"); goto savedone; } info_ptr= png_create_info_struct(png_ptr); if (!info_ptr){ SDL_SetError("Couldn't allocate image information for PNG file"); goto savedone; } /* setup custom writer functions */ png_set_write_fn(png_ptr,(png_voidp)src,png_write_data,NULL); if (setjmp(png_jmpbuf(png_ptr))){ SDL_SetError("Unknown error writing PNG"); goto savedone; } if(compression>Z_BEST_COMPRESSION) compression=Z_BEST_COMPRESSION; if(compression == Z_NO_COMPRESSION) // No compression { png_set_filter(png_ptr,0,PNG_FILTER_NONE); png_set_compression_level(png_ptr,Z_NO_COMPRESSION); } else if(compression<0) // Default compression png_set_compression_level(png_ptr,Z_DEFAULT_COMPRESSION); else png_set_compression_level(png_ptr,compression); fmt=surf->format; if(fmt->BitsPerPixel==8){ /* Paletted */ png_set_IHDR(png_ptr,info_ptr, surf->w,surf->h,8,PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); palette=(png_colorp) malloc(fmt->palette->ncolors * sizeof(png_color)); if (!palette) { SDL_SetError("Couldn't create memory for palette"); goto savedone; } for (i=0;i<fmt->palette->ncolors;i++) { palette[i].red=fmt->palette->colors[i].r; palette[i].green=fmt->palette->colors[i].g; palette[i].blue=fmt->palette->colors[i].b; } png_set_PLTE(png_ptr,info_ptr,palette,fmt->palette->ncolors); // if (surf->flags&SDL_SRCCOLORKEY) { // palette_alpha=(Uint8 *)malloc((fmt->colorkey+1)*sizeof(Uint8)); // if (!palette_alpha) { // SDL_SetError("Couldn't create memory for palette transparency"); // goto savedone; // } // /* FIXME: memset? */ // for (i=0;i<(fmt->colorkey+1);i++) { // palette_alpha[i]=255; // } // palette_alpha[fmt->colorkey]=0; // png_set_tRNS(png_ptr,info_ptr,palette_alpha,fmt->colorkey+1,NULL); // } }else{ /* Truecolor */ if (fmt->Amask) { png_set_IHDR(png_ptr,info_ptr, surf->w,surf->h,8,PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); } else { png_set_IHDR(png_ptr,info_ptr, surf->w,surf->h,8,PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); } } png_write_info(png_ptr, info_ptr); if (fmt->BitsPerPixel==8) { /* Paletted */ for(i=0;i<surf->h;i++){ row_pointers[i]= ((png_byte*)surf->pixels) + i*surf->pitch; } if(SDL_MUSTLOCK(surf)){ SDL_LockSurface(surf); } png_write_image(png_ptr, row_pointers); if(SDL_MUSTLOCK(surf)){ SDL_UnlockSurface(surf); } }else{ /* Truecolor */ if(fmt->BytesPerPixel==3){ if(fmt->Amask){ /* check for 24 bit with alpha */ funky_format=1; }else{ /* Check for RGB/BGR/GBR/RBG/etc surfaces.*/ #if SDL_BYTEORDER == SDL_BIG_ENDIAN if(fmt->Rmask!=0xFF0000 || fmt->Gmask!=0x00FF00 || fmt->Bmask!=0x0000FF){ #else if(fmt->Rmask!=0x0000FF || fmt->Gmask!=0x00FF00 || fmt->Bmask!=0xFF0000){ #endif funky_format=1; } } }else if (fmt->BytesPerPixel==4){ if (!fmt->Amask) { /* check for 32bit but no alpha */ funky_format=1; }else{ /* Check for ARGB/ABGR/GBAR/RABG/etc surfaces.*/ #if SDL_BYTEORDER == SDL_BIG_ENDIAN if(fmt->Rmask!=0xFF000000 || fmt->Gmask!=0x00FF0000 || fmt->Bmask!=0x0000FF00 || fmt->Amask!=0x000000FF){ #else if(fmt->Rmask!=0x000000FF || fmt->Gmask!=0x0000FF00 || fmt->Bmask!=0x00FF0000 || fmt->Amask!=0xFF000000){ #endif funky_format=1; } } }else{ /* 555 or 565 16 bit color */ funky_format=1; } if (funky_format) { /* Allocate non-funky format, and copy pixeldata in*/ if(fmt->Amask){ #if SDL_BYTEORDER == SDL_BIG_ENDIAN tempsurf = SDL_CreateRGBSurface(SDL_SWSURFACE, surf->w, surf->h, 24, 0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff); #else tempsurf = SDL_CreateRGBSurface(SDL_SWSURFACE, surf->w, surf->h, 24, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000); #endif }else{ #if SDL_BYTEORDER == SDL_BIG_ENDIAN tempsurf = SDL_CreateRGBSurface(SDL_SWSURFACE, surf->w, surf->h, 24, 0xff0000, 0x00ff00, 0x0000ff, 0x00000000); #else tempsurf = SDL_CreateRGBSurface(SDL_SWSURFACE, surf->w, surf->h, 24, 0x000000ff, 0x0000ff00, 0x00ff0000, 0x00000000); #endif } if(!tempsurf){ SDL_SetError("Couldn't allocate temp surface"); goto savedone; } SDL_GetSurfaceBlendMode(surf, &temp_blend); SDL_SetSurfaceBlendMode(surf, SDL_BLENDMODE_NONE); if(SDL_BlitSurface(surf,NULL,tempsurf,NULL)!=0){ SDL_SetError("Couldn't blit surface to temp surface"); SDL_FreeSurface(tempsurf); goto savedone; } SDL_SetSurfaceBlendMode(surf, temp_blend); for(i=0;i<tempsurf->h;i++){ row_pointers[i]= ((png_byte*)tempsurf->pixels) + i*tempsurf->pitch; } if(SDL_MUSTLOCK(tempsurf)){ SDL_LockSurface(tempsurf); } png_write_image(png_ptr, row_pointers); if(SDL_MUSTLOCK(tempsurf)){ SDL_UnlockSurface(tempsurf); } SDL_FreeSurface(tempsurf); } else { for(i=0;i<surf->h;i++){ row_pointers[i]= ((png_byte*)surf->pixels) + i*surf->pitch; } if(SDL_MUSTLOCK(surf)){ SDL_LockSurface(surf); } png_write_image(png_ptr, row_pointers); if(SDL_MUSTLOCK(surf)){ SDL_UnlockSurface(surf); } } } png_write_end(png_ptr, NULL); ret=0; /* got here, so nothing went wrong. YAY! */ savedone: /* clean up and return */ png_destroy_write_struct(&png_ptr,&info_ptr); if (palette) { free(palette); } if (palette_alpha) { free(palette_alpha); } if (row_pointers) { free(row_pointers); } return ret; }
static int SW_RenderCopyEx(SDL_Renderer * renderer, SDL_Texture * texture, const SDL_Rect * srcrect, const SDL_FRect * dstrect, const double angle, const SDL_FPoint * center, const SDL_RendererFlip flip) { SDL_Surface *surface = SW_ActivateRenderer(renderer); SDL_Surface *src = (SDL_Surface *) texture->driverdata; SDL_Rect final_rect, tmp_rect; SDL_Surface *src_clone, *src_rotated, *src_scaled; SDL_Surface *mask = NULL, *mask_rotated = NULL; int retval = 0, dstwidth, dstheight, abscenterx, abscentery; double cangle, sangle, px, py, p1x, p1y, p2x, p2y, p3x, p3y, p4x, p4y; SDL_BlendMode blendmode; Uint8 alphaMod, rMod, gMod, bMod; int applyModulation = SDL_FALSE; int blitRequired = SDL_FALSE; int isOpaque = SDL_FALSE; if (!surface) { return -1; } if (renderer->viewport.x || renderer->viewport.y) { final_rect.x = (int)(renderer->viewport.x + dstrect->x); final_rect.y = (int)(renderer->viewport.y + dstrect->y); } else { final_rect.x = (int)dstrect->x; final_rect.y = (int)dstrect->y; } final_rect.w = (int)dstrect->w; final_rect.h = (int)dstrect->h; tmp_rect = final_rect; tmp_rect.x = 0; tmp_rect.y = 0; /* It is possible to encounter an RLE encoded surface here and locking it is * necessary because this code is going to access the pixel buffer directly. */ if (SDL_MUSTLOCK(src)) { SDL_LockSurface(src); } /* Clone the source surface but use its pixel buffer directly. * The original source surface must be treated as read-only. */ src_clone = SDL_CreateRGBSurfaceFrom(src->pixels, src->w, src->h, src->format->BitsPerPixel, src->pitch, src->format->Rmask, src->format->Gmask, src->format->Bmask, src->format->Amask); if (src_clone == NULL) { if (SDL_MUSTLOCK(src)) { SDL_UnlockSurface(src); } return -1; } SDL_GetSurfaceBlendMode(src, &blendmode); SDL_GetSurfaceAlphaMod(src, &alphaMod); SDL_GetSurfaceColorMod(src, &rMod, &gMod, &bMod); /* SDLgfx_rotateSurface only accepts 32-bit surfaces with a 8888 layout. Everything else has to be converted. */ if (src->format->BitsPerPixel != 32 || SDL_PIXELLAYOUT(src->format->format) != SDL_PACKEDLAYOUT_8888 || !src->format->Amask) { blitRequired = SDL_TRUE; } /* If scaling and cropping is necessary, it has to be taken care of before the rotation. */ if (!(srcrect->w == final_rect.w && srcrect->h == final_rect.h && srcrect->x == 0 && srcrect->y == 0)) { blitRequired = SDL_TRUE; } /* The color and alpha modulation has to be applied before the rotation when using the NONE and MOD blend modes. */ if ((blendmode == SDL_BLENDMODE_NONE || blendmode == SDL_BLENDMODE_MOD) && (alphaMod & rMod & gMod & bMod) != 255) { applyModulation = SDL_TRUE; SDL_SetSurfaceAlphaMod(src_clone, alphaMod); SDL_SetSurfaceColorMod(src_clone, rMod, gMod, bMod); } /* Opaque surfaces are much easier to handle with the NONE blend mode. */ if (blendmode == SDL_BLENDMODE_NONE && !src->format->Amask && alphaMod == 255) { isOpaque = SDL_TRUE; } /* The NONE blend mode requires a mask for non-opaque surfaces. This mask will be used * to clear the pixels in the destination surface. The other steps are explained below. */ if (blendmode == SDL_BLENDMODE_NONE && !isOpaque) { mask = SDL_CreateRGBSurface(0, final_rect.w, final_rect.h, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000); if (mask == NULL) { retval = -1; } else { SDL_SetSurfaceBlendMode(mask, SDL_BLENDMODE_MOD); } } /* Create a new surface should there be a format mismatch or if scaling, cropping, * or modulation is required. It's possible to use the source surface directly otherwise. */ if (!retval && (blitRequired || applyModulation)) { SDL_Rect scale_rect = tmp_rect; src_scaled = SDL_CreateRGBSurface(0, final_rect.w, final_rect.h, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000); if (src_scaled == NULL) { retval = -1; } else { SDL_SetSurfaceBlendMode(src_clone, SDL_BLENDMODE_NONE); retval = SDL_BlitScaled(src_clone, srcrect, src_scaled, &scale_rect); SDL_FreeSurface(src_clone); src_clone = src_scaled; src_scaled = NULL; } } /* SDLgfx_rotateSurface is going to make decisions depending on the blend mode. */ SDL_SetSurfaceBlendMode(src_clone, blendmode); if (!retval) { SDLgfx_rotozoomSurfaceSizeTrig(tmp_rect.w, tmp_rect.h, angle, &dstwidth, &dstheight, &cangle, &sangle); src_rotated = SDLgfx_rotateSurface(src_clone, angle, dstwidth/2, dstheight/2, GetScaleQuality(), flip & SDL_FLIP_HORIZONTAL, flip & SDL_FLIP_VERTICAL, dstwidth, dstheight, cangle, sangle); if (src_rotated == NULL) { retval = -1; } if (!retval && mask != NULL) { /* The mask needed for the NONE blend mode gets rotated with the same parameters. */ mask_rotated = SDLgfx_rotateSurface(mask, angle, dstwidth/2, dstheight/2, SDL_FALSE, 0, 0, dstwidth, dstheight, cangle, sangle); if (mask_rotated == NULL) { retval = -1; } } if (!retval) { /* Find out where the new origin is by rotating the four final_rect points around the center and then taking the extremes */ abscenterx = final_rect.x + (int)center->x; abscentery = final_rect.y + (int)center->y; /* Compensate the angle inversion to match the behaviour of the other backends */ sangle = -sangle; /* Top Left */ px = final_rect.x - abscenterx; py = final_rect.y - abscentery; p1x = px * cangle - py * sangle + abscenterx; p1y = px * sangle + py * cangle + abscentery; /* Top Right */ px = final_rect.x + final_rect.w - abscenterx; py = final_rect.y - abscentery; p2x = px * cangle - py * sangle + abscenterx; p2y = px * sangle + py * cangle + abscentery; /* Bottom Left */ px = final_rect.x - abscenterx; py = final_rect.y + final_rect.h - abscentery; p3x = px * cangle - py * sangle + abscenterx; p3y = px * sangle + py * cangle + abscentery; /* Bottom Right */ px = final_rect.x + final_rect.w - abscenterx; py = final_rect.y + final_rect.h - abscentery; p4x = px * cangle - py * sangle + abscenterx; p4y = px * sangle + py * cangle + abscentery; tmp_rect.x = (int)MIN(MIN(p1x, p2x), MIN(p3x, p4x)); tmp_rect.y = (int)MIN(MIN(p1y, p2y), MIN(p3y, p4y)); tmp_rect.w = dstwidth; tmp_rect.h = dstheight; /* The NONE blend mode needs some special care with non-opaque surfaces. * Other blend modes or opaque surfaces can be blitted directly. */ if (blendmode != SDL_BLENDMODE_NONE || isOpaque) { if (applyModulation == SDL_FALSE) { /* If the modulation wasn't already applied, make it happen now. */ SDL_SetSurfaceAlphaMod(src_rotated, alphaMod); SDL_SetSurfaceColorMod(src_rotated, rMod, gMod, bMod); } retval = SDL_BlitSurface(src_rotated, NULL, surface, &tmp_rect); } else { /* The NONE blend mode requires three steps to get the pixels onto the destination surface. * First, the area where the rotated pixels will be blitted to get set to zero. * This is accomplished by simply blitting a mask with the NONE blend mode. * The colorkey set by the rotate function will discard the correct pixels. */ SDL_Rect mask_rect = tmp_rect; SDL_SetSurfaceBlendMode(mask_rotated, SDL_BLENDMODE_NONE); retval = SDL_BlitSurface(mask_rotated, NULL, surface, &mask_rect); if (!retval) { /* The next step copies the alpha value. This is done with the BLEND blend mode and * by modulating the source colors with 0. Since the destination is all zeros, this * will effectively set the destination alpha to the source alpha. */ SDL_SetSurfaceColorMod(src_rotated, 0, 0, 0); mask_rect = tmp_rect; retval = SDL_BlitSurface(src_rotated, NULL, surface, &mask_rect); if (!retval) { /* The last step gets the color values in place. The ADD blend mode simply adds them to * the destination (where the color values are all zero). However, because the ADD blend * mode modulates the colors with the alpha channel, a surface without an alpha mask needs * to be created. This makes all source pixels opaque and the colors get copied correctly. */ SDL_Surface *src_rotated_rgb; src_rotated_rgb = SDL_CreateRGBSurfaceFrom(src_rotated->pixels, src_rotated->w, src_rotated->h, src_rotated->format->BitsPerPixel, src_rotated->pitch, src_rotated->format->Rmask, src_rotated->format->Gmask, src_rotated->format->Bmask, 0); if (src_rotated_rgb == NULL) { retval = -1; } else { SDL_SetSurfaceBlendMode(src_rotated_rgb, SDL_BLENDMODE_ADD); retval = SDL_BlitSurface(src_rotated_rgb, NULL, surface, &tmp_rect); SDL_FreeSurface(src_rotated_rgb); } } } SDL_FreeSurface(mask_rotated); } if (src_rotated != NULL) { SDL_FreeSurface(src_rotated); } } } if (SDL_MUSTLOCK(src)) { SDL_UnlockSurface(src); } if (mask != NULL) { SDL_FreeSurface(mask); } if (src_clone != NULL) { SDL_FreeSurface(src_clone); } return retval; }
GLuint SDL_GL_LoadTexture(SDL_Surface *surface, GLfloat *texcoord) { GLuint texture; int w, h; SDL_Surface *image; SDL_Rect area; Uint8 saved_alpha; SDL_BlendMode saved_mode; /* Use the surface width and height expanded to powers of 2 */ w = power_of_two(surface->w); h = power_of_two(surface->h); texcoord[0] = 0.0f; /* Min X */ texcoord[1] = 0.0f; /* Min Y */ texcoord[2] = (GLfloat)surface->w / w; /* Max X */ texcoord[3] = (GLfloat)surface->h / h; /* Max Y */ image = SDL_CreateRGBSurface( SDL_SWSURFACE, w, h, 32, #if SDL_BYTEORDER == SDL_LIL_ENDIAN /* OpenGL RGBA masks */ 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 #else 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF #endif ); if ( image == NULL ) { return 0; } /* Save the alpha blending attributes */ SDL_GetSurfaceAlphaMod(surface, &saved_alpha); SDL_SetSurfaceAlphaMod(surface, 0xFF); SDL_GetSurfaceBlendMode(surface, &saved_mode); SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_NONE); /* Copy the surface into the GL texture image */ area.x = 0; area.y = 0; area.w = surface->w; area.h = surface->h; SDL_BlitSurface(surface, &area, image, &area); /* Restore the alpha blending attributes */ SDL_SetSurfaceAlphaMod(surface, saved_alpha); SDL_SetSurfaceBlendMode(surface, saved_mode); /* Create an OpenGL texture for the image */ glGenTextures(1, &texture); glBindTexture(GL_TEXTURE_2D, texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, image->pixels); SDL_FreeSurface(image); /* No longer needed */ return texture; }