Home | History | Annotate | Download | only in src
      1 
      2 #include <kms++/kms++.h>
      3 #include <kms++util/kms++util.h>
      4 
      5 using namespace std;
      6 
      7 namespace kms
      8 {
      9 void draw_rgb_pixel(IFramebuffer& buf, unsigned x, unsigned y, RGB color)
     10 {
     11 	if (x >= buf.width() || y >= buf.height())
     12 		throw runtime_error("attempt to draw outside the buffer");
     13 
     14 	switch (buf.format()) {
     15 	case PixelFormat::XRGB8888:
     16 	case PixelFormat::ARGB8888:
     17 	{
     18 		uint32_t *p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4);
     19 		*p = color.argb8888();
     20 		break;
     21 	}
     22 	case PixelFormat::XBGR8888:
     23 	case PixelFormat::ABGR8888:
     24 	{
     25 		uint32_t *p = (uint32_t*)(buf.map(0) + buf.stride(0) * y + x * 4);
     26 		*p = color.abgr8888();
     27 		break;
     28 	}
     29 	case PixelFormat::RGB888:
     30 	{
     31 		uint8_t *p = buf.map(0) + buf.stride(0) * y + x * 3;
     32 		p[0] = color.b;
     33 		p[1] = color.g;
     34 		p[2] = color.r;
     35 		break;
     36 	}
     37 	case PixelFormat::BGR888:
     38 	{
     39 		uint8_t *p = buf.map(0) + buf.stride(0) * y + x * 3;
     40 		p[0] = color.r;
     41 		p[1] = color.g;
     42 		p[2] = color.b;
     43 		break;
     44 	}
     45 	case PixelFormat::RGB565:
     46 	{
     47 		uint16_t *p = (uint16_t*)(buf.map(0) + buf.stride(0) * y + x * 2);
     48 		*p = color.rgb565();
     49 		break;
     50 	}
     51 	case PixelFormat::BGR565:
     52 	{
     53 		uint16_t *p = (uint16_t*)(buf.map(0) + buf.stride(0) * y + x * 2);
     54 		*p = color.bgr565();
     55 		break;
     56 	}
     57 	default:
     58 		throw std::invalid_argument("invalid pixelformat");
     59 	}
     60 }
     61 
     62 void draw_yuv422_macropixel(IFramebuffer& buf, unsigned x, unsigned y, YUV yuv1, YUV yuv2)
     63 {
     64 	if ((x + 1) >= buf.width() || y >= buf.height())
     65 		throw runtime_error("attempt to draw outside the buffer");
     66 
     67 	ASSERT((x & 1) == 0);
     68 
     69 	uint8_t *p = (uint8_t*)(buf.map(0) + buf.stride(0) * y + x * 2);
     70 
     71 	uint8_t y0 = yuv1.y;
     72 	uint8_t y1 = yuv2.y;
     73 	uint8_t u = (yuv1.u + yuv2.u) / 2;
     74 	uint8_t v = (yuv1.v + yuv2.v) / 2;
     75 
     76 	switch (buf.format()) {
     77 	case PixelFormat::UYVY:
     78 		p[0] = u;
     79 		p[1] = y0;
     80 		p[2] = v;
     81 		p[3] = y1;
     82 		break;
     83 
     84 	case PixelFormat::YUYV:
     85 		p[0] = y0;
     86 		p[1] = u;
     87 		p[2] = y1;
     88 		p[3] = v;
     89 		break;
     90 
     91 	case PixelFormat::YVYU:
     92 		p[0] = y0;
     93 		p[1] = v;
     94 		p[2] = y1;
     95 		p[3] = u;
     96 		break;
     97 
     98 	case PixelFormat::VYUY:
     99 		p[0] = v;
    100 		p[1] = y0;
    101 		p[2] = u;
    102 		p[3] = y1;
    103 		break;
    104 
    105 	default:
    106 		throw std::invalid_argument("invalid pixelformat");
    107 	}
    108 }
    109 
    110 void draw_yuv420_macropixel(IFramebuffer& buf, unsigned x, unsigned y,
    111 			    YUV yuv1, YUV yuv2, YUV yuv3, YUV yuv4)
    112 {
    113 	if ((x + 1) >= buf.width() || (y + 1) >= buf.height())
    114 		throw runtime_error("attempt to draw outside the buffer");
    115 
    116 	ASSERT((x & 1) == 0);
    117 	ASSERT((y & 1) == 0);
    118 
    119 	uint8_t *py1 = (uint8_t*)(buf.map(0) + buf.stride(0) * (y + 0) + x);
    120 	uint8_t *py2 = (uint8_t*)(buf.map(0) + buf.stride(0) * (y + 1) + x);
    121 
    122 	uint8_t *puv = (uint8_t*)(buf.map(1) + buf.stride(1) * (y / 2) + x);
    123 
    124 	uint8_t y0 = yuv1.y;
    125 	uint8_t y1 = yuv2.y;
    126 	uint8_t y2 = yuv3.y;
    127 	uint8_t y3 = yuv4.y;
    128 	uint8_t u = (yuv1.u + yuv2.u + yuv3.u + yuv4.u) / 4;
    129 	uint8_t v = (yuv1.v + yuv2.v + yuv3.v + yuv4.v) / 4;
    130 
    131 	switch (buf.format()) {
    132 	case PixelFormat::NV12:
    133 		py1[0] = y0;
    134 		py1[1] = y1;
    135 		py2[0] = y2;
    136 		py2[1] = y3;
    137 		puv[0] = u;
    138 		puv[1] = v;
    139 		break;
    140 
    141 	case PixelFormat::NV21:
    142 		py1[0] = y0;
    143 		py1[1] = y1;
    144 		py2[0] = y2;
    145 		py2[1] = y3;
    146 		puv[0] = v;
    147 		puv[1] = u;
    148 		break;
    149 
    150 	default:
    151 		throw std::invalid_argument("invalid pixelformat");
    152 	}
    153 }
    154 
    155 void draw_rect(IFramebuffer &fb, uint32_t x, uint32_t y, uint32_t w, uint32_t h, RGB color)
    156 {
    157 	unsigned i, j;
    158 	YUV yuvcolor = color.yuv();
    159 
    160 	switch (fb.format()) {
    161 	case PixelFormat::XRGB8888:
    162 	case PixelFormat::XBGR8888:
    163 	case PixelFormat::ARGB8888:
    164 	case PixelFormat::ABGR8888:
    165 	case PixelFormat::RGB888:
    166 	case PixelFormat::BGR888:
    167 	case PixelFormat::RGB565:
    168 	case PixelFormat::BGR565:
    169 		for (j = 0; j < h; j++) {
    170 			for (i = 0; i < w; i++) {
    171 				draw_rgb_pixel(fb, x + i, y + j, color);
    172 			}
    173 		}
    174 		break;
    175 
    176 	case PixelFormat::UYVY:
    177 	case PixelFormat::YUYV:
    178 	case PixelFormat::YVYU:
    179 	case PixelFormat::VYUY:
    180 		for (j = 0; j < h; j++) {
    181 			for (i = 0; i < w; i += 2) {
    182 				draw_yuv422_macropixel(fb, x + i, y + j, yuvcolor, yuvcolor);
    183 			}
    184 		}
    185 		break;
    186 
    187 	case PixelFormat::NV12:
    188 	case PixelFormat::NV21:
    189 		for (j = 0; j < h; j += 2) {
    190 			for (i = 0; i < w; i += 2) {
    191 				draw_yuv420_macropixel(fb, x + i, y + j,
    192 						       yuvcolor, yuvcolor, yuvcolor, yuvcolor);
    193 			}
    194 		}
    195 		break;
    196 	default:
    197 		throw std::invalid_argument("unknown pixelformat");
    198 	}
    199 }
    200 
    201 static bool get_char_pixel(char c, uint32_t x, uint32_t y)
    202 {
    203 #include "font_8x8.h"
    204 
    205 	uint8_t bits = fontdata_8x8[8 * c + y];
    206 	bool bit = (bits >> (7 - x)) & 1;
    207 
    208 	return bit;
    209 }
    210 
    211 static void draw_char(IFramebuffer& buf, uint32_t xpos, uint32_t ypos, char c, RGB color)
    212 {
    213 	unsigned x, y;
    214 	YUV yuvcolor = color.yuv();
    215 
    216 	switch (buf.format()) {
    217 	case PixelFormat::XRGB8888:
    218 	case PixelFormat::XBGR8888:
    219 	case PixelFormat::ARGB8888:
    220 	case PixelFormat::ABGR8888:
    221 	case PixelFormat::RGB888:
    222 	case PixelFormat::BGR888:
    223 	case PixelFormat::RGB565:
    224 	case PixelFormat::BGR565:
    225 		for (y = 0; y < 8; y++) {
    226 			for (x = 0; x < 8; x++) {
    227 				bool b = get_char_pixel(c, x, y);
    228 
    229 				draw_rgb_pixel(buf, xpos + x, ypos + y, b ? color : RGB());
    230 			}
    231 		}
    232 		break;
    233 
    234 	case PixelFormat::UYVY:
    235 	case PixelFormat::YUYV:
    236 	case PixelFormat::YVYU:
    237 	case PixelFormat::VYUY:
    238 		for (y = 0; y < 8; y++) {
    239 			for (x = 0; x < 8; x += 2) {
    240 				bool b0 = get_char_pixel(c, x, y);
    241 				bool b1 = get_char_pixel(c, x + 1, y);
    242 
    243 				draw_yuv422_macropixel(buf, xpos + x, ypos + y,
    244 						       b0 ? yuvcolor : YUV(RGB()), b1 ? yuvcolor : YUV(RGB()));
    245 			}
    246 		}
    247 		break;
    248 
    249 	case PixelFormat::NV12:
    250 	case PixelFormat::NV21:
    251 		for (y = 0; y < 8; y += 2) {
    252 			for (x = 0; x < 8; x += 2) {
    253 				bool b00 = get_char_pixel(c, x, y);
    254 				bool b10 = get_char_pixel(c, x + 1, y);
    255 				bool b01 = get_char_pixel(c, x, y + 1);
    256 				bool b11 = get_char_pixel(c, x + 1, y + 1);
    257 
    258 				draw_yuv420_macropixel(buf, xpos + x, ypos + y,
    259 						       b00 ? yuvcolor : YUV(RGB()), b10 ? yuvcolor : YUV(RGB()),
    260 						       b01 ? yuvcolor : YUV(RGB()), b11 ? yuvcolor : YUV(RGB()));
    261 			}
    262 		}
    263 		break;
    264 	default:
    265 		throw std::invalid_argument("unknown pixelformat");
    266 	}
    267 }
    268 
    269 void draw_text(IFramebuffer& buf, uint32_t x, uint32_t y, const string& str, RGB color)
    270 {
    271 	for(unsigned i = 0; i < str.size(); i++)
    272 		draw_char(buf, (x + 8 * i), y, str[i], color);
    273 }
    274 
    275 }
    276