From 465771e2ece1f89cfc644101d3513b7973a5c34b Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Fri, 31 Dec 2021 15:24:49 +1100 Subject: [PATCH] Fix rare crash when generating mipmaps, fixes #923 When generating mipmaps from a 1 wide pixel bitmap (e.g. 1x256 --> 1x128), the bilinear filtering code would accidentally read 1 pixel past the end of the source bitmap when generating the last row. On most devices this happened to just always work by accident, but on one user's device this would sometimes result in a SEGFAULT --- src/_GraphicsBase.h | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/src/_GraphicsBase.h b/src/_GraphicsBase.h index 749d0f141..995c8277a 100644 --- a/src/_GraphicsBase.h +++ b/src/_GraphicsBase.h @@ -275,28 +275,34 @@ static BitmapCol AverageCol(BitmapCol p1, BitmapCol p2) { aSum >> 1); } -/* Generates the next mipmaps level bitmap for the given bitmap. */ -static void GenMipmaps(int width, int height, BitmapCol* lvlScan0, BitmapCol* scan0, int rowWidth) { - BitmapCol* baseSrc = (BitmapCol*)scan0; - BitmapCol* baseDst = (BitmapCol*)lvlScan0; - +/* Generates the next mipmaps level bitmap by downsampling from the given bitmap. */ +static void GenMipmaps(int width, int height, BitmapCol* dst, BitmapCol* src, int srcWidth) { int x, y; + /* Downsampling from a 1 pixel wide bitmap requires simpler filtering */ + if (srcWidth == 1) { + for (y = 0; y < height; y++) { + /* 1x2 bilinear filter */ + dst[0] = AverageCol(*src, *(src + srcWidth)); + + dst += width; + src += (srcWidth << 1); + } + return; + } + for (y = 0; y < height; y++) { - int srcY = (y << 1); - BitmapCol* src0 = baseSrc + srcY * rowWidth; - BitmapCol* src1 = src0 + rowWidth; - BitmapCol* dst = baseDst + y * width; + BitmapCol* src0 = src; + BitmapCol* src1 = src + srcWidth; for (x = 0; x < width; x++) { int srcX = (x << 1); - BitmapCol src00 = src0[srcX], src01 = src0[srcX + 1]; - BitmapCol src10 = src1[srcX], src11 = src1[srcX + 1]; - - /* bilinear filter this mipmap */ - BitmapCol ave0 = AverageCol(src00, src01); - BitmapCol ave1 = AverageCol(src10, src11); + /* 2x2 bilinear filter */ + BitmapCol ave0 = AverageCol(src0[srcX], src0[srcX + 1]); + BitmapCol ave1 = AverageCol(src1[srcX], src1[srcX + 1]); dst[x] = AverageCol(ave0, ave1); } + src += (srcWidth << 1); + dst += width; } }