openblt

a hobby OS from the late 90s
git clone http://frotz.net/git/openblt.git
Log | Files | Refs | LICENSE

Renderer_vga.cpp (6886B)


      1 #include "Renderer_vga.h"
      2 #include "assert.h"
      3 
      4 #define MIN(a, b) ((a) < (b) ? (a) : (b))
      5 
      6 const unsigned char kCursorBits [] = {
      7 	0x3f,0x3f,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
      8 	0x3f,0x3f,0x3f,0x3f,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
      9 	0xff,0x3f,0x3f,0x3f,0x3f,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
     10 	0xff,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
     11 	0xff,0xff,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x00,0xff,0xff,0xff,0xff,0xff,0xff,
     12 	0xff,0xff,0xff,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0x00,0xff,0xff,0xff,0xff,0xff,
     13 	0xff,0xff,0xff,0x3f,0x3f,0x3f,0x3f,0x3f,0x3f,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
     14 	0xff,0xff,0xff,0xff,0x3f,0x3f,0x3f,0x3f,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
     15 	0xff,0xff,0xff,0xff,0x3f,0x3f,0x3f,0xff,0x3f,0x00,0xff,0xff,0xff,0xff,0xff,0xff,
     16 	0xff,0xff,0xff,0xff,0xff,0x3f,0xff,0xff,0xff,0x3f,0x00,0xff,0xff,0xff,0xff,0xff,
     17 	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0xff,0xff,0xff,0xff,
     18 	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0xff,0xff,0xff,
     19 	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0xff,0xff,
     20 	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0x00,0xff,
     21 	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,0xff,
     22 	0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff
     23 };
     24 
     25 Renderer_vga::Renderer_vga(char *baseAddress, int width, int height, int bytesPerRow)
     26 	:	Renderer_8bpp(baseAddress, width, height, bytesPerRow)
     27 {
     28 	fCursorX = width / 2;
     29 	fCursorY = height / 2;
     30 	DrawCursor();
     31 }
     32 
     33 const unsigned kBottom = 1;
     34 const unsigned kTop = 2;
     35 const unsigned kLeft = 4;
     36 const unsigned kRight = 8;
     37 
     38 #define clipmask(x, y, rect) 		\
     39 	({	unsigned mask = 0;								\
     40 		if (x < rect.left) mask |= kLeft;			\
     41 		else if (x > rect.right) mask |= kRight;	\
     42 		if (y < rect.top) mask |= kTop;			\
     43 		else if (y > rect.bottom) mask |= kBottom;	\
     44 		mask;})											
     45 
     46 inline int vert_intersection(int x1, int y1, int x2, int y2, int x)
     47 {
     48 	return y1 + (y2 - y1) * (x - x1) / (x2 - x1);
     49 }
     50 
     51 inline int horz_intersection(int x1, int y1, int x2, int y2, int y)
     52 {
     53 	return x1 + (x2 - x1) * (y - y1) / (y2 - y1);
     54 }
     55 
     56 void Renderer_vga::DrawLine(int x1, int y1, int x2, int y2, char color)
     57 {
     58 	Rect cursorRect(fCursorX, fCursorY, fCursorX + 16, fCursorY + 16);
     59 	bool invalidateCursor = true;
     60 
     61 	int clippedX1 = x1;
     62 	int clippedY1 = y1;
     63 	int clippedX2 = x2;
     64 	int clippedY2 = y2;
     65 	unsigned point1mask = clipmask(clippedX1, clippedY1, cursorRect);
     66 	unsigned point2mask = clipmask(clippedX2, clippedY2, cursorRect);
     67 	while (point1mask != 0 || point2mask != 0) {
     68 		if ((point1mask & point2mask) != 0) {
     69 			invalidateCursor = false;
     70 			break;
     71 		}
     72 
     73 		unsigned  mask = point1mask ? point1mask : point2mask;
     74 		int x = 0;
     75 		int y = 0;
     76 		if (mask & kBottom) {
     77 			y = cursorRect.bottom;
     78 			x = horz_intersection(clippedX1, clippedY1, clippedX2, clippedY2, y);
     79 		} else if (mask & kTop) {
     80 			y = cursorRect.top;
     81 			x = horz_intersection(clippedX1, clippedY1, clippedX2, clippedY2, y);
     82 		} else if (mask & kRight) {
     83 			x = cursorRect.right;
     84 			y = vert_intersection(clippedX1, clippedY1, clippedX2, clippedY2, x);
     85 		} else if (mask & kLeft) {
     86 			x = cursorRect.left;
     87 			y = vert_intersection(clippedX1, clippedY1, clippedX2, clippedY2, x);
     88 		}
     89 		
     90 		if (point1mask) {
     91 			// Clip point 1
     92 			point1mask = clipmask(x, y, cursorRect);
     93 			clippedX1 = x;
     94 			clippedY1 = y;
     95 		} else {
     96 			// Clip point 2
     97 			point2mask = clipmask(x, y, cursorRect);
     98 			clippedX2 = x;
     99 			clippedY2 = y;
    100 		}
    101 	}
    102 
    103 	if (invalidateCursor)
    104 		EraseCursor();
    105 	
    106 	Renderer_8bpp::DrawLine(x1, y1, x2, y2, color);
    107 	
    108 	if (invalidateCursor)
    109 		DrawCursor();
    110 }
    111 
    112 void Renderer_vga::FillRect(int x1, int y1, int x2, int y2, char color)
    113 {
    114 
    115 	bool invalidateCursor = false;
    116 	if (Rect(x1, y1, x2, y2).Intersects(Rect(fCursorX, fCursorY, fCursorX + 16,
    117 		fCursorY + 16))) {
    118 		invalidateCursor = true;
    119 		EraseCursor();
    120 	}
    121 
    122 	Renderer_8bpp::FillRect(x1, y1, x2, y2, color);
    123 	if (invalidateCursor)
    124 		DrawCursor();
    125 }
    126 
    127 void Renderer_vga::Blit(int x, int y, char image[], int imageWidth,
    128     int imageHeight, int imageBytesPerRow)
    129 {
    130 
    131 	bool invalidateCursor = false;
    132 	if (Rect(x, y, x + imageWidth, y + imageHeight).Intersects(Rect(fCursorX,
    133 		fCursorY, fCursorX + 16, fCursorY + 16))) {
    134 		invalidateCursor = true;
    135 		EraseCursor();
    136 	}
    137 
    138 	Renderer_8bpp::Blit(x, y, image, imageWidth, imageHeight, imageBytesPerRow);
    139 	if (invalidateCursor)
    140 		DrawCursor();
    141 }
    142 
    143 void Renderer_vga::StretchBlit(const Rect &imageRect, const Rect &displayRect, char image[],
    144 	int imageBytesPerRow)
    145 {
    146 
    147 	bool invalidateCursor = false;
    148 	if (displayRect.Intersects(Rect(fCursorX, fCursorY, fCursorX + 16,
    149 		fCursorY + 16))) {
    150 		invalidateCursor = true;
    151 		EraseCursor();
    152 	}
    153 
    154 	Renderer_8bpp::StretchBlit(imageRect, displayRect, image, imageBytesPerRow);
    155 
    156 	if (invalidateCursor)
    157 		DrawCursor();
    158 }
    159 
    160 void Renderer_vga::CopyRect(const Rect &source, const Rect &dest)
    161 {
    162 	bool invalidateCursor = false;
    163 	Rect cursorRect(fCursorX, fCursorY, fCursorX + 16, fCursorY + 16);
    164 	if (cursorRect.Intersects(source) || cursorRect.Intersects(dest)) {
    165 		invalidateCursor = true;
    166 		EraseCursor();
    167 	}
    168 
    169 	Renderer_8bpp::CopyRect(source, dest);
    170 	if (invalidateCursor)
    171 		DrawCursor(); 
    172 }
    173 
    174 void Renderer_vga::SetCursorPosition(int x, int  y)
    175 {
    176 	EraseCursor();
    177 	fCursorX = x;
    178 	fCursorY = y;
    179 	DrawCursor();
    180 }
    181 
    182 void Renderer_vga::EraseCursor()
    183 {
    184 	char *screen_ptr = BufferBaseAddress() + fCursorX + fCursorY * BufferBytesPerRow();
    185 	char *saveBackground = fSavedBackground;
    186 	int cursorDisplayWidth = MIN(16, BufferBytesPerRow() - fCursorX);
    187 	int cursorDisplayHeight = MIN(16, BufferHeight() - fCursorY);
    188 	int stride = BufferBytesPerRow() - cursorDisplayWidth;
    189 
    190 	for (int y = 0; y < cursorDisplayHeight; y++) {
    191 		for (int x = 0; x < cursorDisplayWidth; x++) {
    192 			if ((unsigned char) *saveBackground != 0xff)
    193 				*screen_ptr = *saveBackground;
    194 
    195 			screen_ptr++;
    196 			saveBackground++;
    197 		}
    198 
    199 		screen_ptr += stride;
    200 		saveBackground += 16 - cursorDisplayWidth;
    201 	}
    202 }
    203 
    204 void Renderer_vga::DrawCursor()
    205 {
    206 	char *screen_ptr = BufferBaseAddress() + fCursorX + fCursorY * BufferBytesPerRow();
    207 	char *cursorImage = (char *) kCursorBits;
    208 	char *saveBackground = fSavedBackground;
    209 	int cursorDisplayWidth = MIN(16, BufferBytesPerRow() - fCursorX);
    210 	int cursorDisplayHeight = MIN(16, BufferHeight() - fCursorY);
    211 	int stride = BufferBytesPerRow() - cursorDisplayWidth;
    212 
    213 	for (int y = 0; y < cursorDisplayHeight; y++) {
    214 		for (int x = 0; x < cursorDisplayWidth; x++) {
    215 			if ((unsigned char) *cursorImage != 0xff) {
    216 				*saveBackground = *screen_ptr;
    217 				*screen_ptr = *cursorImage;
    218 			} else
    219 				*saveBackground = 0xff;
    220 
    221 			screen_ptr++;
    222 			cursorImage++;
    223 			saveBackground++;
    224 		}
    225 
    226 		screen_ptr += stride;
    227 		cursorImage += 16 - cursorDisplayWidth;
    228 		saveBackground += 16 - cursorDisplayWidth;
    229 	}
    230 }