X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=src%2Fvideo%2Fsdl_texture.cpp;h=05bf5a2294afdfd8cdc39f5bb030063e76be6ebc;hb=4f423b9bbb6fa694b8c6bcc338e069aad45db3e3;hp=5b4b61f97c5b3ea15a12b8af56738199926ea3b8;hpb=a62a9e28229f7e1def9a32fe9d88cad4debf55d1;p=supertux.git diff --git a/src/video/sdl_texture.cpp b/src/video/sdl_texture.cpp index 5b4b61f97..05bf5a229 100644 --- a/src/video/sdl_texture.cpp +++ b/src/video/sdl_texture.cpp @@ -44,6 +44,14 @@ namespace { SDL_Surface *dst = SDL_CreateRGBSurface(src->flags, src->w * numerator / denominator, src->h * numerator / denominator, src->format->BitsPerPixel, src->format->Rmask, src->format->Gmask, src->format->Bmask, src->format->Amask); int bpp = dst->format->BytesPerPixel; + if(SDL_MUSTLOCK(src)) + { + SDL_LockSurface(src); + } + if(SDL_MUSTLOCK(dst)) + { + SDL_LockSurface(dst); + } for(int y = 0;y < dst->h;y++) { for(int x = 0;x < dst->w;x++) { Uint8 *srcpixel = (Uint8 *) src->pixels + (y * denominator / numerator) * src->pitch + (x * denominator / numerator) * bpp; @@ -60,6 +68,25 @@ namespace } } } + if(SDL_MUSTLOCK(dst)) + { + SDL_UnlockSurface(dst); + } + if(SDL_MUSTLOCK(src)) + { + SDL_UnlockSurface(src); + } + if(!src->format->Amask) + { + if(src->flags & SDL_SRCALPHA) + { + SDL_SetAlpha(dst, SDL_SRCALPHA | SDL_RLEACCEL, src->format->alpha); + } + if(src->flags & SDL_SRCCOLORKEY) + { + SDL_SetColorKey(dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, src->format->colorkey); + } + } return dst; } } @@ -123,6 +150,14 @@ namespace { SDL_Surface *dst = SDL_CreateRGBSurface(src->flags, src->w * numerator / denominator, src->h * numerator / denominator, src->format->BitsPerPixel, src->format->Rmask, src->format->Gmask, src->format->Bmask, src->format->Amask); int bpp = dst->format->BytesPerPixel; + if(SDL_MUSTLOCK(src)) + { + SDL_LockSurface(src); + } + if(SDL_MUSTLOCK(dst)) + { + SDL_LockSurface(dst); + } for(int y = 0;y < dst->h;y++) { for(int x = 0;x < dst->w;x++) { int srcx = x * denominator / numerator; @@ -164,124 +199,23 @@ namespace } } } - return dst; - } - } -#endif - - // FIXME: Horizontal and vertical line problem -#ifdef BRESENHAM - void accumulate(SDL_Surface *src, int srcx, int srcy, int color[4], int weight) - { - if(srcx < 0 || srcy < 0 || weight == 0) { - return; - } - int bpp = src->format->BytesPerPixel; - Uint8 *srcpixel = (Uint8 *) src->pixels + srcy * src->pitch + srcx * bpp; - Uint32 mapped = 0; - switch(bpp) { - case 1: - mapped = *srcpixel; - break; - case 2: - mapped = *(Uint16 *)srcpixel; - break; - case 3: -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - mapped |= srcpixel[0] << 16; - mapped |= srcpixel[1] << 8; - mapped |= srcpixel[2] << 0; -#else - mapped |= srcpixel[0] << 0; - mapped |= srcpixel[1] << 8; - mapped |= srcpixel[2] << 16; -#endif - break; - case 4: - mapped = *(Uint32 *)srcpixel; - break; - } - Uint8 red, green, blue, alpha; - SDL_GetRGBA(mapped, src->format, &red, &green, &blue, &alpha); - color[0] += red * weight; - color[1] += green * weight; - color[2] += blue * weight; - color[3] += alpha * weight; - } - - void accumulate_line(SDL_Surface *src, int srcy, int line[][4], int linesize, int weight, int numerator, int denominator) - { - int intpart = denominator / numerator; - int fractpart = denominator % numerator; - for(int x = 0, xe = 0, srcx = 0;x < linesize;x++) { - accumulate(src, srcx, srcy, line[x], (numerator - xe) * weight); - srcx++; - for(int i = 0;i < intpart - 1;i++) { - accumulate(src, srcx, srcy, line[x], numerator * weight); - srcx++; - } - xe += fractpart; - if(xe >= numerator) { - xe -= numerator; - srcx++; - } - accumulate(src, srcx, srcy, line[x], xe * weight); - } - } - - SDL_Surface *scale(SDL_Surface *src, int numerator, int denominator) - { - if(numerator == denominator) - { - src->refcount++; - return src; - } - else - { - SDL_Surface *dst = SDL_CreateRGBSurface(src->flags, src->w * numerator / denominator, src->h * numerator / denominator, src->format->BitsPerPixel, src->format->Rmask, src->format->Gmask, src->format->Bmask, src->format->Amask); - int bpp = dst->format->BytesPerPixel; - int intpart = denominator / numerator; - int fractpart = denominator % numerator; - for(int y = 0, ye = 0, srcy = 0;y < dst->h;y++) { - int line[dst->w][4]; - memset(line, 0, sizeof(int) * dst->w * 4); - accumulate_line(src, srcy, line, dst->w, numerator - ye, numerator, denominator); - srcy++; - for(int i = 0;i < intpart - 1;i++) { - accumulate_line(src, srcy, line, dst->w, numerator, numerator, denominator); - srcy++; + if(SDL_MUSTLOCK(dst)) + { + SDL_UnlockSurface(dst); + } + if(SDL_MUSTLOCK(src)) + { + SDL_UnlockSurface(src); + } + if(!src->format->Amask) + { + if(src->flags & SDL_SRCALPHA) + { + SDL_SetAlpha(dst, SDL_SRCALPHA | SDL_RLEACCEL, src->format->alpha); } - ye += fractpart; - if(ye >= numerator) { - ye -= numerator; - srcy++; - } - accumulate_line(src, srcy, line, dst->w, ye, numerator, denominator); - for(int x = 0;x < dst->w;x++) { - Uint8 *dstpixel = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp; - Uint32 mapped = SDL_MapRGBA(dst->format, line[x][0] / (denominator * denominator), line[x][1] / (denominator * denominator), line[x][2] / (denominator * denominator), line[x][3] / (denominator * denominator)); - switch(bpp) { - case 1: - *dstpixel = mapped; - break; - case 2: - *(Uint16 *)dstpixel = mapped; - break; - case 3: -#if SDL_BYTEORDER == SDL_BIG_ENDIAN - dstpixel[0] = (mapped >> 16) & 0xff; - dstpixel[1] = (mapped >> 8) & 0xff; - dstpixel[2] = (mapped >> 0) & 0xff; -#else - dstpixel[0] = (mapped >> 0) & 0xff; - dstpixel[1] = (mapped >> 8) & 0xff; - dstpixel[2] = (mapped >> 16) & 0xff; -#endif - break; - case 4: - *(Uint32 *)dstpixel = mapped; - break; - } + if(src->flags & SDL_SRCCOLORKEY) + { + SDL_SetColorKey(dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, src->format->colorkey); } } return dst; @@ -293,6 +227,14 @@ namespace { SDL_Surface *dst = SDL_CreateRGBSurface(src->flags, src->w, src->h, src->format->BitsPerPixel, src->format->Rmask, src->format->Gmask, src->format->Bmask, src->format->Amask); int bpp = dst->format->BytesPerPixel; + if(SDL_MUSTLOCK(src)) + { + SDL_LockSurface(src); + } + if(SDL_MUSTLOCK(dst)) + { + SDL_LockSurface(dst); + } for(int y = 0;y < dst->h;y++) { for(int x = 0;x < dst->w;x++) { Uint8 *srcpixel = (Uint8 *) src->pixels + y * src->pitch + x * bpp; @@ -309,6 +251,25 @@ namespace } } } + if(SDL_MUSTLOCK(dst)) + { + SDL_UnlockSurface(dst); + } + if(SDL_MUSTLOCK(src)) + { + SDL_UnlockSurface(src); + } + if(!src->format->Amask) + { + if(src->flags & SDL_SRCALPHA) + { + SDL_SetAlpha(dst, SDL_SRCALPHA | SDL_RLEACCEL, src->format->alpha); + } + if(src->flags & SDL_SRCCOLORKEY) + { + SDL_SetColorKey(dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, src->format->colorkey); + } + } return dst; } @@ -316,6 +277,14 @@ namespace { SDL_Surface *dst = SDL_CreateRGBSurface(src->flags, src->w, src->h, src->format->BitsPerPixel, src->format->Rmask, src->format->Gmask, src->format->Bmask, src->format->Amask); int bpp = dst->format->BytesPerPixel; + if(SDL_MUSTLOCK(src)) + { + SDL_LockSurface(src); + } + if(SDL_MUSTLOCK(dst)) + { + SDL_LockSurface(dst); + } for(int y = 0;y < dst->h;y++) { for(int x = 0;x < dst->w;x++) { Uint8 *srcpixel = (Uint8 *) src->pixels + y * src->pitch + x * bpp; @@ -332,6 +301,25 @@ namespace } } } + if(SDL_MUSTLOCK(dst)) + { + SDL_UnlockSurface(dst); + } + if(SDL_MUSTLOCK(src)) + { + SDL_UnlockSurface(src); + } + if(!src->format->Amask) + { + if(src->flags & SDL_SRCALPHA) + { + SDL_SetAlpha(dst, SDL_SRCALPHA | SDL_RLEACCEL, src->format->alpha); + } + if(src->flags & SDL_SRCCOLORKEY) + { + SDL_SetColorKey(dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, src->format->colorkey); + } + } return dst; } @@ -339,8 +327,19 @@ namespace { // FIXME: This is really slow assert(color.red != 1.0 || color.green != 1.0 || color.blue != 1.0); + int red = (int) (color.red * 256); + int green = (int) (color.green * 256); + int blue = (int) (color.blue * 256); SDL_Surface *dst = SDL_CreateRGBSurface(src->flags, src->w, src->h, src->format->BitsPerPixel, src->format->Rmask, src->format->Gmask, src->format->Bmask, src->format->Amask); int bpp = dst->format->BytesPerPixel; + if(SDL_MUSTLOCK(src)) + { + SDL_LockSurface(src); + } + if(SDL_MUSTLOCK(dst)) + { + SDL_LockSurface(dst); + } for(int y = 0;y < dst->h;y++) { for(int x = 0;x < dst->w;x++) { Uint8 *srcpixel = (Uint8 *) src->pixels + y * src->pitch + x * bpp; @@ -368,12 +367,12 @@ namespace mapped = *(Uint32 *)srcpixel; break; } - Uint8 red, green, blue, alpha; - SDL_GetRGBA(mapped, src->format, &red, &green, &blue, &alpha); - red = (Uint8) (red * color.red); - green = (Uint8) (green * color.green); - blue = (Uint8) (blue * color.blue); - mapped = SDL_MapRGBA(dst->format, red, green, blue, alpha); + if(src->format->Amask || !(src->flags & SDL_SRCCOLORKEY) || mapped != src->format->colorkey) + { + Uint8 r, g, b, a; + SDL_GetRGBA(mapped, src->format, &r, &g, &b, &a); + mapped = SDL_MapRGBA(dst->format, (r * red) >> 8, (g * green) >> 8, (b * blue) >> 8, a); + } switch(bpp) { case 1: *dstpixel = mapped; @@ -398,27 +397,225 @@ namespace } } } + if(SDL_MUSTLOCK(dst)) + { + SDL_UnlockSurface(dst); + } + if(SDL_MUSTLOCK(src)) + { + SDL_UnlockSurface(src); + } + if(!src->format->Amask) + { + if(src->flags & SDL_SRCALPHA) + { + SDL_SetAlpha(dst, SDL_SRCALPHA | SDL_RLEACCEL, src->format->alpha); + } + if(src->flags & SDL_SRCCOLORKEY) + { + SDL_SetColorKey(dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, src->format->colorkey); + } + } return dst; } -} -namespace SDL -{ - Texture::Texture(SDL_Surface* image) + SDL_Surface *optimize(SDL_Surface *src) { - if(!(image->flags & SDL_SRCALPHA) || !image->format->Amask) + if(!src->format->Amask) { - texture = SDL_DisplayFormat(image); + return SDL_DisplayFormat(src); } else { - texture = SDL_DisplayFormatAlpha(image); + int transparent = 0; + int opaque = 0; + int semitransparent = 0; + int alphasum = 0; + int squaredalphasum = 0; + bool colors[(1 << 12)]; + memset(colors, 0, (1 << 12) * sizeof(bool)); + + int bpp = src->format->BytesPerPixel; + if(SDL_MUSTLOCK(src)) + { + SDL_LockSurface(src); + } + for(int y = 0;y < src->h;y++) { + for(int x = 0;x < src->w;x++) { + Uint8 *pixel = (Uint8 *) src->pixels + y * src->pitch + x * bpp; + Uint32 mapped = 0; + switch(bpp) { + case 1: + mapped = *pixel; + break; + case 2: + mapped = *(Uint16 *)pixel; + break; + case 3: +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + mapped |= pixel[0] << 16; + mapped |= pixel[1] << 8; + mapped |= pixel[2] << 0; +#else + mapped |= pixel[0] << 0; + mapped |= pixel[1] << 8; + mapped |= pixel[2] << 16; +#endif + break; + case 4: + mapped = *(Uint32 *)pixel; + break; + } + Uint8 red, green, blue, alpha; + SDL_GetRGBA(mapped, src->format, &red, &green, &blue, &alpha); + if(alpha < 16) + { + transparent++; + } + else if (alpha > 240) + { + opaque++; + alphasum += alpha; + squaredalphasum += alpha * alpha; + } + else + { + semitransparent++; + squaredalphasum += alpha * alpha; + } + if(alpha != 0) + { + colors[((red & 0xf0) << 4) | (green & 0xf0) | ((blue & 0xf0) >> 4)] = true; + } + } + } + if(SDL_MUSTLOCK(src)) + { + SDL_UnlockSurface(src); + } + int avgalpha = (opaque + semitransparent) ? alphasum / (opaque + semitransparent) : 0; + int avgsquaredalpha = (opaque + semitransparent) ? squaredalphasum / (opaque + semitransparent) : 0; + int alphavariance = avgsquaredalpha - avgalpha * avgalpha; + if(semitransparent > ((transparent + opaque + semitransparent) / 8) && alphavariance > 16) + { + return SDL_DisplayFormatAlpha(src); + } + int keycolor = -1; + for(int i = 0;i < (1 << 12);i++) + { + if(!colors[i]) + { + keycolor = i; + } + } + if(keycolor == -1) + { + return SDL_DisplayFormatAlpha(src); + } + SDL_Surface *dst = SDL_CreateRGBSurface(src->flags & ~(SDL_SRCALPHA), src->w, src->h, src->format->BitsPerPixel, src->format->Rmask, src->format->Gmask, src->format->Bmask, 0); + bpp = dst->format->BytesPerPixel; + Uint32 key = SDL_MapRGB(dst->format, (((keycolor & 0xf00) >> 4) | 0xf), ((keycolor & 0xf0) | 0xf), (((keycolor & 0xf) << 4) | 0xf)); + if(SDL_MUSTLOCK(src)) + { + SDL_LockSurface(src); + } + if(SDL_MUSTLOCK(dst)) + { + SDL_LockSurface(dst); + } + for(int y = 0;y < dst->h;y++) { + for(int x = 0;x < dst->w;x++) { + Uint8 *srcpixel = (Uint8 *) src->pixels + y * src->pitch + x * bpp; + Uint8 *dstpixel = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp; + Uint32 mapped = 0; + switch(bpp) { + case 1: + mapped = *srcpixel; + break; + case 2: + mapped = *(Uint16 *)srcpixel; + break; + case 3: +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + mapped |= srcpixel[0] << 16; + mapped |= srcpixel[1] << 8; + mapped |= srcpixel[2] << 0; +#else + mapped |= srcpixel[0] << 0; + mapped |= srcpixel[1] << 8; + mapped |= srcpixel[2] << 16; +#endif + break; + case 4: + mapped = *(Uint32 *)srcpixel; + break; + } + Uint8 red, green, blue, alpha; + SDL_GetRGBA(mapped, src->format, &red, &green, &blue, &alpha); + if(alpha < (avgalpha / 4)) + { + mapped = key; + } + else + { + mapped = SDL_MapRGB(dst->format, red, green, blue); + } + switch(bpp) { + case 1: + *dstpixel = mapped; + break; + case 2: + *(Uint16 *)dstpixel = mapped; + break; + case 3: +#if SDL_BYTEORDER == SDL_BIG_ENDIAN + dstpixel[0] = (mapped >> 16) & 0xff; + dstpixel[1] = (mapped >> 8) & 0xff; + dstpixel[2] = (mapped >> 0) & 0xff; +#else + dstpixel[0] = (mapped >> 0) & 0xff; + dstpixel[1] = (mapped >> 8) & 0xff; + dstpixel[2] = (mapped >> 16) & 0xff; +#endif + break; + case 4: + *(Uint32 *)dstpixel = mapped; + break; + } + } + } + if(SDL_MUSTLOCK(dst)) + { + SDL_UnlockSurface(dst); + } + if(SDL_MUSTLOCK(src)) + { + SDL_UnlockSurface(src); + } + if(avgalpha < 240) + { + SDL_SetAlpha(dst, SDL_SRCALPHA | SDL_RLEACCEL, avgalpha); + } + SDL_SetColorKey(dst, SDL_SRCCOLORKEY | SDL_RLEACCEL, key); + SDL_Surface *convert = SDL_DisplayFormat(dst); + SDL_FreeSurface(dst); + return convert; } + } +} + +namespace SDL +{ + Texture::Texture(SDL_Surface* image) + { + texture = optimize(image); //width = texture->w; //height = texture->h; - int numerator, denominator; - float xfactor = (float) config->screenwidth / SCREEN_WIDTH; - float yfactor = (float) config->screenheight / SCREEN_HEIGHT; + int numerator = 1; + int denominator = 1; + //FIXME: float xfactor = (float) config->screenwidth / SCREEN_WIDTH; + //FIXME: float yfactor = (float) config->screenheight / SCREEN_HEIGHT; + /* FIXME: if(xfactor < yfactor) { numerator = config->screenwidth; @@ -429,6 +626,7 @@ namespace SDL numerator = config->screenheight; denominator = SCREEN_HEIGHT; } + */ cache[NO_EFFECT][Color::WHITE] = scale(texture, numerator, denominator); }