diff options
author | Andrei Karas <akaras@inbox.ru> | 2013-11-03 22:40:36 +0300 |
---|---|---|
committer | Andrei Karas <akaras@inbox.ru> | 2013-11-03 23:52:58 +0300 |
commit | 1485b138c5b906546381f1ae4a91553a3c2fc6c4 (patch) | |
tree | 3148467fc2d6146f57fae7b014b7c3dd1e5b07af | |
parent | 36574fe72662e807ec679e6f54a32685ee23ee57 (diff) | |
download | manaplus-1485b138c5b906546381f1ae4a91553a3c2fc6c4.tar.gz manaplus-1485b138c5b906546381f1ae4a91553a3c2fc6c4.tar.bz2 manaplus-1485b138c5b906546381f1ae4a91553a3c2fc6c4.tar.xz manaplus-1485b138c5b906546381f1ae4a91553a3c2fc6c4.zip |
improve alpha change speed in software mode
aslo fix random wrong textures alpha in software mode.
-rw-r--r-- | src/resources/image.cpp | 73 |
1 files changed, 53 insertions, 20 deletions
diff --git a/src/resources/image.cpp b/src/resources/image.cpp index b217db683..4229cb8af 100644 --- a/src/resources/image.cpp +++ b/src/resources/image.cpp @@ -320,30 +320,63 @@ void Image::setAlpha(const float alpha) if (SDL_MUSTLOCK(mSDLSurface)) SDL_LockSurface(mSDLSurface); - // Precompute as much as possible - const int maxHeight = std::min((mBounds.y + mBounds.h), - mSDLSurface->h); - const int maxWidth = std::min((mBounds.x + mBounds.w), - mSDLSurface->w); - const int i1 = mBounds.y * mSDLSurface->w + mBounds.x; - const int i2 = (maxHeight - 1) * mSDLSurface->w + maxWidth - 1; - + const int bx = mBounds.x; + const int by = mBounds.y; + const int bw = mBounds.w; + const int bh = mBounds.h; + const int bxw = bx + bw; + const int sw = mSDLSurface->w; + const int maxHeight = std::min(by + bh, mSDLSurface->h); + const int maxWidth = std::min(bxw, sw); + const int i1 = by * sw + bx; const SDL_PixelFormat * const fmt = mSDLSurface->format; + const uint32_t amask = fmt->Amask; + const uint32_t invMask = ~fmt->Amask; + const uint8_t aloss = fmt->Aloss; + const uint8_t ashift = fmt->Ashift; - for (int i = i1; i <= i2; i++) + if (!bx && bxw == sw) + { + const int i2 = (maxHeight - 1) * sw + maxWidth - 1; + for (int i = i1; i <= i2; i++) + { + const uint8_t sourceAlpha = mAlphaChannel[i]; + if (sourceAlpha > 0) + { + const uint8_t a = static_cast<uint8_t>( + static_cast<float>(sourceAlpha) * mAlpha); + + uint32_t c = (static_cast<uint32_t*>( + mSDLSurface->pixels))[i]; + c &= invMask; + c |= ((a >> aloss) << ashift & amask); + (static_cast<uint32_t*>(mSDLSurface->pixels))[i] = c; + } + } + } + else { - // Only change the pixel if it was visible at load time... - const uint8_t sourceAlpha = mAlphaChannel[i]; - if (sourceAlpha > 0) + for (int y = by; y < maxHeight; y ++) { - const uint8_t a = static_cast<uint8_t>( - static_cast<float>(sourceAlpha) * mAlpha); - - uint32_t c = (static_cast<uint32_t*>( - mSDLSurface->pixels))[i]; - c &= ~fmt->Amask; - c |= ((a >> fmt->Aloss) << fmt->Ashift & fmt->Amask); - (static_cast<uint32_t*>(mSDLSurface->pixels))[i] = c; + const int i1 = y * sw; + const int x1 = i1 + bx; + const int x2 = i1 + maxWidth; + for (int i = x1; i < x2; i ++) + { + const uint8_t sourceAlpha = mAlphaChannel[i]; + if (sourceAlpha > 0) + { + const uint8_t a = static_cast<uint8_t>( + static_cast<float>(sourceAlpha) * mAlpha); + + uint32_t c = (static_cast<uint32_t*>( + mSDLSurface->pixels))[i]; + c &= invMask; + c |= ((a >> aloss) << ashift & amask); + (static_cast<uint32_t*>( + mSDLSurface->pixels))[i] = c; + } + } } } |