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