src/gfx.cpp
branchNewGRF_ports
changeset 10274 b3c58f3df92b
parent 10184 fcf5fb2548eb
child 10724 68a692eacf22
equal deleted inserted replaced
10243:e9066a148720 10274:b3c58f3df92b
    15 #include "blitter/factory.hpp"
    15 #include "blitter/factory.hpp"
    16 #include "video/video_driver.hpp"
    16 #include "video/video_driver.hpp"
    17 #include "strings_func.h"
    17 #include "strings_func.h"
    18 #include "core/math_func.hpp"
    18 #include "core/math_func.hpp"
    19 #include "settings_type.h"
    19 #include "settings_type.h"
       
    20 #include "core/alloc_func.hpp"
    20 
    21 
    21 #include "table/palettes.h"
    22 #include "table/palettes.h"
    22 #include "table/sprites.h"
    23 #include "table/sprites.h"
    23 #include "table/control_codes.h"
    24 #include "table/control_codes.h"
    24 
    25 
    62  */
    63  */
    63 static Rect _invalid_rect;
    64 static Rect _invalid_rect;
    64 static const byte *_color_remap_ptr;
    65 static const byte *_color_remap_ptr;
    65 static byte _string_colorremap[3];
    66 static byte _string_colorremap[3];
    66 
    67 
    67 #define DIRTY_BYTES_PER_LINE (MAX_SCREEN_WIDTH / 64)
    68 enum {
    68 static byte _dirty_blocks[DIRTY_BYTES_PER_LINE * MAX_SCREEN_HEIGHT / 8];
    69 	DIRTY_BLOCK_HEIGHT   = 8,
       
    70 	DIRTY_BLOCK_WIDTH    = 64,
       
    71 };
       
    72 static uint _dirty_bytes_per_line = 0;
       
    73 static byte *_dirty_blocks = NULL;
    69 
    74 
    70 void GfxScroll(int left, int top, int width, int height, int xo, int yo)
    75 void GfxScroll(int left, int top, int width, int height, int xo, int yo)
    71 {
    76 {
    72 	Blitter *blitter = BlitterFactoryBase::GetCurrentBlitter();
    77 	Blitter *blitter = BlitterFactoryBase::GetCurrentBlitter();
    73 
    78 
   928 }
   933 }
   929 
   934 
   930 
   935 
   931 void ScreenSizeChanged()
   936 void ScreenSizeChanged()
   932 {
   937 {
       
   938 	_dirty_bytes_per_line = (_screen.width + DIRTY_BLOCK_WIDTH - 1) / DIRTY_BLOCK_WIDTH;
       
   939 	_dirty_blocks = ReallocT<byte>(_dirty_blocks, _dirty_bytes_per_line * ((_screen.height + DIRTY_BLOCK_HEIGHT - 1) / DIRTY_BLOCK_HEIGHT));
       
   940 
   933 	/* check the dirty rect */
   941 	/* check the dirty rect */
   934 	if (_invalid_rect.right >= _screen.width) _invalid_rect.right = _screen.width;
   942 	if (_invalid_rect.right >= _screen.width) _invalid_rect.right = _screen.width;
   935 	if (_invalid_rect.bottom >= _screen.height) _invalid_rect.bottom = _screen.height;
   943 	if (_invalid_rect.bottom >= _screen.height) _invalid_rect.bottom = _screen.height;
   936 
   944 
   937 	/* screen size changed and the old bitmap is invalid now, so we don't want to undraw it */
   945 	/* screen size changed and the old bitmap is invalid now, so we don't want to undraw it */
  1031  * @see SetDirtyBlocks
  1039  * @see SetDirtyBlocks
  1032  */
  1040  */
  1033 void DrawDirtyBlocks()
  1041 void DrawDirtyBlocks()
  1034 {
  1042 {
  1035 	byte *b = _dirty_blocks;
  1043 	byte *b = _dirty_blocks;
  1036 	const int w = Align(_screen.width, 64);
  1044 	const int w = Align(_screen.width,  DIRTY_BLOCK_WIDTH);
  1037 	const int h = Align(_screen.height, 8);
  1045 	const int h = Align(_screen.height, DIRTY_BLOCK_HEIGHT);
  1038 	int x;
  1046 	int x;
  1039 	int y;
  1047 	int y;
  1040 
  1048 
  1041 	if (IsGeneratingWorld() && !IsGeneratingWorldReadyForPaint()) return;
  1049 	if (IsGeneratingWorld() && !IsGeneratingWorldReadyForPaint()) return;
  1042 
  1050 
  1045 		x = 0;
  1053 		x = 0;
  1046 		do {
  1054 		do {
  1047 			if (*b != 0) {
  1055 			if (*b != 0) {
  1048 				int left;
  1056 				int left;
  1049 				int top;
  1057 				int top;
  1050 				int right = x + 64;
  1058 				int right = x + DIRTY_BLOCK_WIDTH;
  1051 				int bottom = y;
  1059 				int bottom = y;
  1052 				byte *p = b;
  1060 				byte *p = b;
  1053 				int h2;
  1061 				int h2;
  1054 
  1062 
  1055 				/* First try coalescing downwards */
  1063 				/* First try coalescing downwards */
  1056 				do {
  1064 				do {
  1057 					*p = 0;
  1065 					*p = 0;
  1058 					p += DIRTY_BYTES_PER_LINE;
  1066 					p += _dirty_bytes_per_line;
  1059 					bottom += 8;
  1067 					bottom += DIRTY_BLOCK_HEIGHT;
  1060 				} while (bottom != h && *p != 0);
  1068 				} while (bottom != h && *p != 0);
  1061 
  1069 
  1062 				/* Try coalescing to the right too. */
  1070 				/* Try coalescing to the right too. */
  1063 				h2 = (bottom - y) >> 3;
  1071 				h2 = (bottom - y) / DIRTY_BLOCK_HEIGHT;
  1064 				assert(h2 > 0);
  1072 				assert(h2 > 0);
  1065 				p = b;
  1073 				p = b;
  1066 
  1074 
  1067 				while (right != w) {
  1075 				while (right != w) {
  1068 					byte *p2 = ++p;
  1076 					byte *p2 = ++p;
  1069 					int h = h2;
  1077 					int h = h2;
  1070 					/* Check if a full line of dirty flags is set. */
  1078 					/* Check if a full line of dirty flags is set. */
  1071 					do {
  1079 					do {
  1072 						if (!*p2) goto no_more_coalesc;
  1080 						if (!*p2) goto no_more_coalesc;
  1073 						p2 += DIRTY_BYTES_PER_LINE;
  1081 						p2 += _dirty_bytes_per_line;
  1074 					} while (--h != 0);
  1082 					} while (--h != 0);
  1075 
  1083 
  1076 					/* Wohoo, can combine it one step to the right!
  1084 					/* Wohoo, can combine it one step to the right!
  1077 					 * Do that, and clear the bits. */
  1085 					 * Do that, and clear the bits. */
  1078 					right += 64;
  1086 					right += DIRTY_BLOCK_WIDTH;
  1079 
  1087 
  1080 					h = h2;
  1088 					h = h2;
  1081 					p2 = p;
  1089 					p2 = p;
  1082 					do {
  1090 					do {
  1083 						*p2 = 0;
  1091 						*p2 = 0;
  1084 						p2 += DIRTY_BYTES_PER_LINE;
  1092 						p2 += _dirty_bytes_per_line;
  1085 					} while (--h != 0);
  1093 					} while (--h != 0);
  1086 				}
  1094 				}
  1087 				no_more_coalesc:
  1095 				no_more_coalesc:
  1088 
  1096 
  1089 				left = x;
  1097 				left = x;
  1097 				if (left < right && top < bottom) {
  1105 				if (left < right && top < bottom) {
  1098 					RedrawScreenRect(left, top, right, bottom);
  1106 					RedrawScreenRect(left, top, right, bottom);
  1099 				}
  1107 				}
  1100 
  1108 
  1101 			}
  1109 			}
  1102 		} while (b++, (x += 64) != w);
  1110 		} while (b++, (x += DIRTY_BLOCK_WIDTH) != w);
  1103 	} while (b += -(w >> 6) + DIRTY_BYTES_PER_LINE, (y += 8) != h);
  1111 	} while (b += -(w / DIRTY_BLOCK_WIDTH) + _dirty_bytes_per_line, (y += DIRTY_BLOCK_HEIGHT) != h);
  1104 
  1112 
  1105 	_invalid_rect.left = w;
  1113 	_invalid_rect.left = w;
  1106 	_invalid_rect.top = h;
  1114 	_invalid_rect.top = h;
  1107 	_invalid_rect.right = 0;
  1115 	_invalid_rect.right = 0;
  1108 	_invalid_rect.bottom = 0;
  1116 	_invalid_rect.bottom = 0;
  1145 	if (left   < _invalid_rect.left  ) _invalid_rect.left   = left;
  1153 	if (left   < _invalid_rect.left  ) _invalid_rect.left   = left;
  1146 	if (top    < _invalid_rect.top   ) _invalid_rect.top    = top;
  1154 	if (top    < _invalid_rect.top   ) _invalid_rect.top    = top;
  1147 	if (right  > _invalid_rect.right ) _invalid_rect.right  = right;
  1155 	if (right  > _invalid_rect.right ) _invalid_rect.right  = right;
  1148 	if (bottom > _invalid_rect.bottom) _invalid_rect.bottom = bottom;
  1156 	if (bottom > _invalid_rect.bottom) _invalid_rect.bottom = bottom;
  1149 
  1157 
  1150 	left >>= 6;
  1158 	left /= DIRTY_BLOCK_WIDTH;
  1151 	top  >>= 3;
  1159 	top  /= DIRTY_BLOCK_HEIGHT;
  1152 
  1160 
  1153 	b = _dirty_blocks + top * DIRTY_BYTES_PER_LINE + left;
  1161 	b = _dirty_blocks + top * _dirty_bytes_per_line + left;
  1154 
  1162 
  1155 	width  = ((right  - 1) >> 6) - left + 1;
  1163 	width  = ((right  - 1) / DIRTY_BLOCK_WIDTH)  - left + 1;
  1156 	height = ((bottom - 1) >> 3) - top  + 1;
  1164 	height = ((bottom - 1) / DIRTY_BLOCK_HEIGHT) - top  + 1;
  1157 
  1165 
  1158 	assert(width > 0 && height > 0);
  1166 	assert(width > 0 && height > 0);
  1159 
  1167 
  1160 	do {
  1168 	do {
  1161 		int i = width;
  1169 		int i = width;
  1162 
  1170 
  1163 		do b[--i] = 0xFF; while (i);
  1171 		do b[--i] = 0xFF; while (i);
  1164 
  1172 
  1165 		b += DIRTY_BYTES_PER_LINE;
  1173 		b += _dirty_bytes_per_line;
  1166 	} while (--height != 0);
  1174 	} while (--height != 0);
  1167 }
  1175 }
  1168 
  1176 
  1169 /*!
  1177 /*!
  1170  * This function mark the whole screen as dirty. This results in repainting
  1178  * This function mark the whole screen as dirty. This results in repainting