src/blitter/32bpp_anim.cpp
changeset 9597 825e5483799b
parent 9550 89a9d945b97d
child 9598 101174f1c2b8
equal deleted inserted replaced
9596:bae8462571bf 9597:825e5483799b
    13 
    13 
    14 #include "../table/sprites.h"
    14 #include "../table/sprites.h"
    15 
    15 
    16 static FBlitter_32bppAnim iFBlitter_32bppAnim;
    16 static FBlitter_32bppAnim iFBlitter_32bppAnim;
    17 
    17 
       
    18 template <BlitterMode mode>
       
    19 inline void Blitter_32bppAnim::Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom)
       
    20 {
       
    21 	const SpriteData *src = (const SpriteData *)bp->sprite;
       
    22 
       
    23 	const Colour *src_px = (const Colour *)(src->data + src->offset[zoom][0]);
       
    24 	const uint8  *src_n  = (const uint8  *)(src->data + src->offset[zoom][1]);
       
    25 
       
    26 	for (uint i = bp->skip_top; i != 0; i--) {
       
    27 		src_px = (const Colour *)((const byte *)src_px + *(const uint32 *)src_px);
       
    28 		src_n += *(const uint32 *)src_n;
       
    29 	}
       
    30 
       
    31 	uint32 *dst = (uint32 *)bp->dst + bp->top * bp->pitch + bp->left;
       
    32 	uint8 *anim = this->anim_buf + ((uint32 *)bp->dst - (uint32 *)_screen.dst_ptr) + bp->top * this->anim_buf_width + bp->left;
       
    33 
       
    34 	const byte *remap = bp->remap; // store so we don't have to access it via bp everytime
       
    35 
       
    36 	for (int y = 0; y < bp->height; y++) {
       
    37 		uint32 *dst_ln = dst + bp->pitch;
       
    38 		uint8 *anim_ln = anim + this->anim_buf_width;
       
    39 
       
    40 		const Colour *src_px_ln = (const Colour *)((const byte *)src_px + *(const uint32 *)src_px);
       
    41 		src_px++;
       
    42 
       
    43 		const uint8 *src_n_ln = src_n + *(uint32 *)src_n;
       
    44 		src_n += 4;
       
    45 
       
    46 		uint32 *dst_end = dst + bp->skip_left;
       
    47 
       
    48 		uint n;
       
    49 
       
    50 		while (dst < dst_end) {
       
    51 			n = *src_n++;
       
    52 
       
    53 			if (src_px->a == 0) {
       
    54 				dst += n;
       
    55 				src_px ++;
       
    56 				src_n++;
       
    57 
       
    58 				if (dst > dst_end) anim += dst - dst_end;
       
    59 			} else {
       
    60 				if (dst + n > dst_end) {
       
    61 					uint d = dst_end - dst;
       
    62 					src_px += d;
       
    63 					src_n += d;
       
    64 
       
    65 					dst = dst_end - bp->skip_left;
       
    66 					dst_end = dst + bp->width;
       
    67 
       
    68 					n = min<uint>(n - d, (uint)bp->width);
       
    69 					goto draw;
       
    70 				}
       
    71 				dst += n;
       
    72 				src_px += n;
       
    73 				src_n += n;
       
    74 			}
       
    75 		}
       
    76 
       
    77 		dst -= bp->skip_left;
       
    78 		dst_end -= bp->skip_left;
       
    79 
       
    80 		dst_end += bp->width;
       
    81 
       
    82 		while (dst < dst_end) {
       
    83 			n = min<uint>(*src_n++, (uint)(dst_end - dst));
       
    84 
       
    85 			if (src_px->a == 0) {
       
    86 				anim += n;
       
    87 				dst += n;
       
    88 				src_px++;
       
    89 				src_n++;
       
    90 				continue;
       
    91 			}
       
    92 
       
    93 			draw:;
       
    94 
       
    95 			switch (mode) {
       
    96 				case BM_COLOUR_REMAP:
       
    97 					if (src_px->a == 255) {
       
    98 						do {
       
    99 							uint m = *src_n;
       
   100 							/* In case the m-channel is zero, do not remap this pixel in any way */
       
   101 							if (m == 0) {
       
   102 								*dst = *src_px;
       
   103 								*anim = 0;
       
   104 							} else {
       
   105 								uint r = remap[m];
       
   106 								*anim = r;
       
   107 								if (r != 0) *dst = this->LookupColourInPalette(r);
       
   108 							}
       
   109 							anim++;
       
   110 							dst++;
       
   111 							src_px++;
       
   112 							src_n++;
       
   113 						} while (--n != 0);
       
   114 					} else {
       
   115 						do {
       
   116 							uint m = *src_n;
       
   117 							if (m == 0) {
       
   118 								*dst = ComposeColourRGBANoCheck(src_px->r, src_px->g, src_px->b, src_px->a, *dst);
       
   119 								*anim = 0;
       
   120 							} else {
       
   121 								uint r = remap[m];
       
   122 								*anim = r;
       
   123 								if (r != 0) *dst = ComposeColourPANoCheck(this->LookupColourInPalette(r), src_px->a, *dst);
       
   124 							}
       
   125 							anim++;
       
   126 							dst++;
       
   127 							src_px++;
       
   128 							src_n++;
       
   129 						} while (--n != 0);
       
   130 					}
       
   131 					break;
       
   132 
       
   133 				case BM_TRANSPARENT:
       
   134 					/* TODO -- We make an assumption here that the remap in fact is transparency, not some color.
       
   135 					 *  This is never a problem with the code we produce, but newgrfs can make it fail... or at least:
       
   136 					 *  we produce a result the newgrf maker didn't expect ;) */
       
   137 
       
   138 					/* Make the current color a bit more black, so it looks like this image is transparent */
       
   139 					src_px += n;
       
   140 					src_n += n;
       
   141 
       
   142 					do {
       
   143 						*dst = MakeTransparent(*dst, 192);
       
   144 						*anim = remap[*anim];
       
   145 						anim++;
       
   146 						dst++;
       
   147 					} while (--n != 0);
       
   148 					break;
       
   149 
       
   150 				default:
       
   151 					if (src_px->a == 255) {
       
   152 						do {
       
   153 							/* Compiler assumes pointer aliasing, can't optimise this on its own */
       
   154 							uint m = *src_n++;
       
   155 							/* Above 217 is palette animation */
       
   156 							*anim++ = m;
       
   157 							*dst++ = (m >= 217) ? this->LookupColourInPalette(m) : *src_px;
       
   158 							src_px++;
       
   159 						} while (--n != 0);
       
   160 					} else {
       
   161 						do {
       
   162 							uint m = *src_n++;
       
   163 							*anim++ = m;
       
   164 							if (m >= 217) {
       
   165 								*dst = ComposeColourPANoCheck(this->LookupColourInPalette(m), src_px->a, *dst);
       
   166 							} else {
       
   167 								*dst = ComposeColourRGBANoCheck(src_px->r, src_px->g, src_px->b, src_px->a, *dst);
       
   168 							}
       
   169 							dst++;
       
   170 							src_px++;
       
   171 						} while (--n != 0);
       
   172 					}
       
   173 					break;
       
   174 			}
       
   175 		}
       
   176 
       
   177 		anim = anim_ln;
       
   178 		dst = dst_ln;
       
   179 		src_px = src_px_ln;
       
   180 		src_n  = src_n_ln;
       
   181 	}
       
   182 }
       
   183 
    18 void Blitter_32bppAnim::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom)
   184 void Blitter_32bppAnim::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom)
    19 {
   185 {
    20 	if (_screen_disable_anim) {
   186 	if (_screen_disable_anim) {
    21 		/* This means our output is not to the screen, so we can't be doing any animation stuff, so use our parent Draw() */
   187 		/* This means our output is not to the screen, so we can't be doing any animation stuff, so use our parent Draw() */
    22 		Blitter_32bppOptimized::Draw(bp, mode, zoom);
   188 		Blitter_32bppOptimized::Draw(bp, mode, zoom);
    23 		return;
   189 		return;
    24 	}
   190 	}
    25 
       
    26 	const SpriteLoader::CommonPixel *src, *src_line;
       
    27 	uint32 *dst, *dst_line;
       
    28 	uint8 *anim, *anim_line;
       
    29 
   191 
    30 	if (_screen.width != this->anim_buf_width || _screen.height != this->anim_buf_height) {
   192 	if (_screen.width != this->anim_buf_width || _screen.height != this->anim_buf_height) {
    31 		/* The size of the screen changed; we can assume we can wipe all data from our buffer */
   193 		/* The size of the screen changed; we can assume we can wipe all data from our buffer */
    32 		free(this->anim_buf);
   194 		free(this->anim_buf);
    33 		this->anim_buf = CallocT<uint8>(_screen.width * _screen.height);
   195 		this->anim_buf = CallocT<uint8>(_screen.width * _screen.height);
    34 		this->anim_buf_width = _screen.width;
   196 		this->anim_buf_width = _screen.width;
    35 		this->anim_buf_height = _screen.height;
   197 		this->anim_buf_height = _screen.height;
    36 	}
   198 	}
    37 
   199 
    38 	/* Find where to start reading in the source sprite */
   200 	switch (mode) {
    39 	src_line = (const SpriteLoader::CommonPixel *)bp->sprite + (bp->skip_top * bp->sprite_width + bp->skip_left) * ScaleByZoom(1, zoom);
   201 		default: NOT_REACHED();
    40 	dst_line = (uint32 *)bp->dst + bp->top * bp->pitch + bp->left;
   202 		case BM_NORMAL:       Draw<BM_NORMAL>      (bp, zoom); return;
    41 	anim_line = this->anim_buf + ((uint32 *)bp->dst - (uint32 *)_screen.dst_ptr) + bp->top * this->anim_buf_width + bp->left;
   203 		case BM_COLOUR_REMAP: Draw<BM_COLOUR_REMAP>(bp, zoom); return;
    42 
   204 		case BM_TRANSPARENT:  Draw<BM_TRANSPARENT> (bp, zoom); return;
    43 	for (int y = 0; y < bp->height; y++) {
       
    44 		dst = dst_line;
       
    45 		dst_line += bp->pitch;
       
    46 
       
    47 		src = src_line;
       
    48 		src_line += bp->sprite_width * ScaleByZoom(1, zoom);
       
    49 
       
    50 		anim = anim_line;
       
    51 		anim_line += this->anim_buf_width;
       
    52 
       
    53 		for (int x = 0; x < bp->width; x++) {
       
    54 			if (src->a == 0) {
       
    55 				/* src->r is 'misused' here to indicate how much more pixels are following with an alpha of 0 */
       
    56 				int skip = UnScaleByZoom(src->r, zoom);
       
    57 
       
    58 				dst  += skip;
       
    59 				anim += skip;
       
    60 				x    += skip - 1;
       
    61 				src  += ScaleByZoom(1, zoom) * skip;
       
    62 				continue;
       
    63 			}
       
    64 
       
    65 			switch (mode) {
       
    66 				case BM_COLOUR_REMAP:
       
    67 					/* In case the m-channel is zero, do not remap this pixel in any way */
       
    68 					if (src->m == 0) {
       
    69 						*dst = ComposeColourRGBA(src->r, src->g, src->b, src->a, *dst);
       
    70 						*anim = 0;
       
    71 					} else {
       
    72 						if (bp->remap[src->m] != 0) {
       
    73 							*dst = ComposeColourPA(this->LookupColourInPalette(bp->remap[src->m]), src->a, *dst);
       
    74 							*anim = bp->remap[src->m];
       
    75 						}
       
    76 					}
       
    77 					break;
       
    78 
       
    79 				case BM_TRANSPARENT:
       
    80 					/* TODO -- We make an assumption here that the remap in fact is transparency, not some color.
       
    81 					 *  This is never a problem with the code we produce, but newgrfs can make it fail... or at least:
       
    82 					 *  we produce a result the newgrf maker didn't expect ;) */
       
    83 
       
    84 					/* Make the current color a bit more black, so it looks like this image is transparent */
       
    85 					*dst = MakeTransparent(*dst, 192);
       
    86 					*anim = bp->remap[*anim];
       
    87 					break;
       
    88 
       
    89 				default:
       
    90 					/* Above 217 is palette animation */
       
    91 					if (src->m >= 217) *dst = ComposeColourPA(this->LookupColourInPalette(src->m), src->a, *dst);
       
    92 					else               *dst = ComposeColourRGBA(src->r, src->g, src->b, src->a, *dst);
       
    93 					*anim = src->m;
       
    94 					break;
       
    95 			}
       
    96 			dst++;
       
    97 			anim++;
       
    98 			src += ScaleByZoom(1, zoom);
       
    99 		}
       
   100 	}
   205 	}
   101 }
   206 }
   102 
   207 
   103 void Blitter_32bppAnim::DrawColorMappingRect(void *dst, int width, int height, int pal)
   208 void Blitter_32bppAnim::DrawColorMappingRect(void *dst, int width, int height, int pal)
   104 {
   209 {