balrog | a171fe3 | 2007-04-30 01:48:07 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Intel XScale PXA255/270 LCDC emulation. |
| 3 | * |
| 4 | * Copyright (c) 2006 Openedhand Ltd. |
| 5 | * Written by Andrzej Zaborowski <balrog@zabor.org> |
| 6 | * |
| 7 | * This code is licensed under the GPLv2. |
| 8 | * |
| 9 | * Framebuffer format conversion routines. |
| 10 | */ |
| 11 | |
| 12 | # define SKIP_PIXEL(to) to += deststep |
| 13 | #if BITS == 8 |
| 14 | # define COPY_PIXEL(to, from) *to = from; SKIP_PIXEL(to) |
| 15 | #elif BITS == 15 || BITS == 16 |
| 16 | # define COPY_PIXEL(to, from) *(uint16_t *) to = from; SKIP_PIXEL(to) |
ths | 5fafdf2 | 2007-09-16 21:08:06 +0000 | [diff] [blame] | 17 | #elif BITS == 24 |
balrog | a171fe3 | 2007-04-30 01:48:07 +0000 | [diff] [blame] | 18 | # define COPY_PIXEL(to, from) \ |
| 19 | *(uint16_t *) to = from; *(to + 2) = (from) >> 16; SKIP_PIXEL(to) |
| 20 | #elif BITS == 32 |
| 21 | # define COPY_PIXEL(to, from) *(uint32_t *) to = from; SKIP_PIXEL(to) |
| 22 | #else |
| 23 | # error unknown bit depth |
| 24 | #endif |
| 25 | |
Juan Quintela | e2542fe | 2009-07-27 16:13:06 +0200 | [diff] [blame] | 26 | #ifdef HOST_WORDS_BIGENDIAN |
balrog | a171fe3 | 2007-04-30 01:48:07 +0000 | [diff] [blame] | 27 | # define SWAP_WORDS 1 |
| 28 | #endif |
| 29 | |
| 30 | #define FN_2(x) FN(x + 1) FN(x) |
| 31 | #define FN_4(x) FN_2(x + 2) FN_2(x) |
| 32 | |
pbrook | 714fa30 | 2009-04-01 12:27:59 +0000 | [diff] [blame] | 33 | static void glue(pxa2xx_draw_line2_, BITS)(void *opaque, |
balrog | a171fe3 | 2007-04-30 01:48:07 +0000 | [diff] [blame] | 34 | uint8_t *dest, const uint8_t *src, int width, int deststep) |
| 35 | { |
pbrook | 714fa30 | 2009-04-01 12:27:59 +0000 | [diff] [blame] | 36 | uint32_t *palette = opaque; |
balrog | a171fe3 | 2007-04-30 01:48:07 +0000 | [diff] [blame] | 37 | uint32_t data; |
| 38 | while (width > 0) { |
| 39 | data = *(uint32_t *) src; |
| 40 | #define FN(x) COPY_PIXEL(dest, palette[(data >> ((x) * 2)) & 3]); |
| 41 | #ifdef SWAP_WORDS |
| 42 | FN_4(12) |
| 43 | FN_4(8) |
| 44 | FN_4(4) |
| 45 | FN_4(0) |
| 46 | #else |
| 47 | FN_4(0) |
| 48 | FN_4(4) |
| 49 | FN_4(8) |
| 50 | FN_4(12) |
| 51 | #endif |
| 52 | #undef FN |
| 53 | width -= 16; |
| 54 | src += 4; |
| 55 | } |
| 56 | } |
| 57 | |
pbrook | 714fa30 | 2009-04-01 12:27:59 +0000 | [diff] [blame] | 58 | static void glue(pxa2xx_draw_line4_, BITS)(void *opaque, |
balrog | a171fe3 | 2007-04-30 01:48:07 +0000 | [diff] [blame] | 59 | uint8_t *dest, const uint8_t *src, int width, int deststep) |
| 60 | { |
pbrook | 714fa30 | 2009-04-01 12:27:59 +0000 | [diff] [blame] | 61 | uint32_t *palette = opaque; |
balrog | a171fe3 | 2007-04-30 01:48:07 +0000 | [diff] [blame] | 62 | uint32_t data; |
| 63 | while (width > 0) { |
| 64 | data = *(uint32_t *) src; |
| 65 | #define FN(x) COPY_PIXEL(dest, palette[(data >> ((x) * 4)) & 0xf]); |
| 66 | #ifdef SWAP_WORDS |
| 67 | FN_2(6) |
| 68 | FN_2(4) |
| 69 | FN_2(2) |
| 70 | FN_2(0) |
| 71 | #else |
| 72 | FN_2(0) |
| 73 | FN_2(2) |
| 74 | FN_2(4) |
| 75 | FN_2(6) |
| 76 | #endif |
| 77 | #undef FN |
| 78 | width -= 8; |
| 79 | src += 4; |
| 80 | } |
| 81 | } |
| 82 | |
pbrook | 714fa30 | 2009-04-01 12:27:59 +0000 | [diff] [blame] | 83 | static void glue(pxa2xx_draw_line8_, BITS)(void *opaque, |
balrog | a171fe3 | 2007-04-30 01:48:07 +0000 | [diff] [blame] | 84 | uint8_t *dest, const uint8_t *src, int width, int deststep) |
| 85 | { |
pbrook | 714fa30 | 2009-04-01 12:27:59 +0000 | [diff] [blame] | 86 | uint32_t *palette = opaque; |
balrog | a171fe3 | 2007-04-30 01:48:07 +0000 | [diff] [blame] | 87 | uint32_t data; |
| 88 | while (width > 0) { |
| 89 | data = *(uint32_t *) src; |
| 90 | #define FN(x) COPY_PIXEL(dest, palette[(data >> (x)) & 0xff]); |
| 91 | #ifdef SWAP_WORDS |
| 92 | FN(24) |
| 93 | FN(16) |
| 94 | FN(8) |
| 95 | FN(0) |
| 96 | #else |
| 97 | FN(0) |
| 98 | FN(8) |
| 99 | FN(16) |
| 100 | FN(24) |
| 101 | #endif |
| 102 | #undef FN |
| 103 | width -= 4; |
| 104 | src += 4; |
| 105 | } |
| 106 | } |
| 107 | |
pbrook | 714fa30 | 2009-04-01 12:27:59 +0000 | [diff] [blame] | 108 | static void glue(pxa2xx_draw_line16_, BITS)(void *opaque, |
balrog | a171fe3 | 2007-04-30 01:48:07 +0000 | [diff] [blame] | 109 | uint8_t *dest, const uint8_t *src, int width, int deststep) |
| 110 | { |
| 111 | uint32_t data; |
| 112 | unsigned int r, g, b; |
| 113 | while (width > 0) { |
| 114 | data = *(uint32_t *) src; |
| 115 | #ifdef SWAP_WORDS |
| 116 | data = bswap32(data); |
| 117 | #endif |
| 118 | b = (data & 0x1f) << 3; |
| 119 | data >>= 5; |
| 120 | g = (data & 0x3f) << 2; |
| 121 | data >>= 6; |
| 122 | r = (data & 0x1f) << 3; |
| 123 | data >>= 5; |
| 124 | COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); |
| 125 | b = (data & 0x1f) << 3; |
| 126 | data >>= 5; |
| 127 | g = (data & 0x3f) << 2; |
| 128 | data >>= 6; |
| 129 | r = (data & 0x1f) << 3; |
| 130 | COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); |
| 131 | width -= 2; |
| 132 | src += 4; |
| 133 | } |
| 134 | } |
| 135 | |
pbrook | 714fa30 | 2009-04-01 12:27:59 +0000 | [diff] [blame] | 136 | static void glue(pxa2xx_draw_line16t_, BITS)(void *opaque, |
balrog | a171fe3 | 2007-04-30 01:48:07 +0000 | [diff] [blame] | 137 | uint8_t *dest, const uint8_t *src, int width, int deststep) |
| 138 | { |
| 139 | uint32_t data; |
| 140 | unsigned int r, g, b; |
| 141 | while (width > 0) { |
| 142 | data = *(uint32_t *) src; |
| 143 | #ifdef SWAP_WORDS |
| 144 | data = bswap32(data); |
| 145 | #endif |
| 146 | b = (data & 0x1f) << 3; |
| 147 | data >>= 5; |
| 148 | g = (data & 0x1f) << 3; |
| 149 | data >>= 5; |
| 150 | r = (data & 0x1f) << 3; |
| 151 | data >>= 5; |
| 152 | if (data & 1) |
| 153 | SKIP_PIXEL(dest); |
| 154 | else |
| 155 | COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); |
| 156 | data >>= 1; |
| 157 | b = (data & 0x1f) << 3; |
| 158 | data >>= 5; |
| 159 | g = (data & 0x1f) << 3; |
| 160 | data >>= 5; |
| 161 | r = (data & 0x1f) << 3; |
balrog | abbaab5 | 2008-11-03 01:08:14 +0000 | [diff] [blame] | 162 | data >>= 5; |
balrog | a171fe3 | 2007-04-30 01:48:07 +0000 | [diff] [blame] | 163 | if (data & 1) |
| 164 | SKIP_PIXEL(dest); |
| 165 | else |
| 166 | COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); |
| 167 | width -= 2; |
| 168 | src += 4; |
| 169 | } |
| 170 | } |
| 171 | |
pbrook | 714fa30 | 2009-04-01 12:27:59 +0000 | [diff] [blame] | 172 | static void glue(pxa2xx_draw_line18_, BITS)(void *opaque, |
balrog | a171fe3 | 2007-04-30 01:48:07 +0000 | [diff] [blame] | 173 | uint8_t *dest, const uint8_t *src, int width, int deststep) |
| 174 | { |
| 175 | uint32_t data; |
| 176 | unsigned int r, g, b; |
| 177 | while (width > 0) { |
| 178 | data = *(uint32_t *) src; |
| 179 | #ifdef SWAP_WORDS |
| 180 | data = bswap32(data); |
| 181 | #endif |
| 182 | b = (data & 0x3f) << 2; |
| 183 | data >>= 6; |
| 184 | g = (data & 0x3f) << 2; |
| 185 | data >>= 6; |
| 186 | r = (data & 0x3f) << 2; |
| 187 | COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); |
| 188 | width -= 1; |
| 189 | src += 4; |
| 190 | } |
| 191 | } |
| 192 | |
| 193 | /* The wicked packed format */ |
pbrook | 714fa30 | 2009-04-01 12:27:59 +0000 | [diff] [blame] | 194 | static void glue(pxa2xx_draw_line18p_, BITS)(void *opaque, |
balrog | a171fe3 | 2007-04-30 01:48:07 +0000 | [diff] [blame] | 195 | uint8_t *dest, const uint8_t *src, int width, int deststep) |
| 196 | { |
| 197 | uint32_t data[3]; |
| 198 | unsigned int r, g, b; |
| 199 | while (width > 0) { |
| 200 | data[0] = *(uint32_t *) src; |
| 201 | src += 4; |
| 202 | data[1] = *(uint32_t *) src; |
| 203 | src += 4; |
| 204 | data[2] = *(uint32_t *) src; |
| 205 | src += 4; |
| 206 | #ifdef SWAP_WORDS |
| 207 | data[0] = bswap32(data[0]); |
| 208 | data[1] = bswap32(data[1]); |
| 209 | data[2] = bswap32(data[2]); |
| 210 | #endif |
| 211 | b = (data[0] & 0x3f) << 2; |
| 212 | data[0] >>= 6; |
| 213 | g = (data[0] & 0x3f) << 2; |
| 214 | data[0] >>= 6; |
| 215 | r = (data[0] & 0x3f) << 2; |
| 216 | data[0] >>= 12; |
| 217 | COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); |
| 218 | b = (data[0] & 0x3f) << 2; |
| 219 | data[0] >>= 6; |
| 220 | g = ((data[1] & 0xf) << 4) | (data[0] << 2); |
| 221 | data[1] >>= 4; |
| 222 | r = (data[1] & 0x3f) << 2; |
| 223 | data[1] >>= 12; |
| 224 | COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); |
| 225 | b = (data[1] & 0x3f) << 2; |
| 226 | data[1] >>= 6; |
| 227 | g = (data[1] & 0x3f) << 2; |
| 228 | data[1] >>= 6; |
| 229 | r = ((data[2] & 0x3) << 6) | (data[1] << 2); |
| 230 | data[2] >>= 8; |
| 231 | COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); |
| 232 | b = (data[2] & 0x3f) << 2; |
| 233 | data[2] >>= 6; |
| 234 | g = (data[2] & 0x3f) << 2; |
| 235 | data[2] >>= 6; |
| 236 | r = data[2] << 2; |
| 237 | COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); |
| 238 | width -= 4; |
| 239 | } |
| 240 | } |
| 241 | |
pbrook | 714fa30 | 2009-04-01 12:27:59 +0000 | [diff] [blame] | 242 | static void glue(pxa2xx_draw_line19_, BITS)(void *opaque, |
balrog | a171fe3 | 2007-04-30 01:48:07 +0000 | [diff] [blame] | 243 | uint8_t *dest, const uint8_t *src, int width, int deststep) |
| 244 | { |
| 245 | uint32_t data; |
| 246 | unsigned int r, g, b; |
| 247 | while (width > 0) { |
| 248 | data = *(uint32_t *) src; |
| 249 | #ifdef SWAP_WORDS |
| 250 | data = bswap32(data); |
| 251 | #endif |
| 252 | b = (data & 0x3f) << 2; |
| 253 | data >>= 6; |
| 254 | g = (data & 0x3f) << 2; |
| 255 | data >>= 6; |
| 256 | r = (data & 0x3f) << 2; |
| 257 | data >>= 6; |
| 258 | if (data & 1) |
| 259 | SKIP_PIXEL(dest); |
| 260 | else |
| 261 | COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); |
| 262 | width -= 1; |
| 263 | src += 4; |
| 264 | } |
| 265 | } |
| 266 | |
| 267 | /* The wicked packed format */ |
pbrook | 714fa30 | 2009-04-01 12:27:59 +0000 | [diff] [blame] | 268 | static void glue(pxa2xx_draw_line19p_, BITS)(void *opaque, |
balrog | a171fe3 | 2007-04-30 01:48:07 +0000 | [diff] [blame] | 269 | uint8_t *dest, const uint8_t *src, int width, int deststep) |
| 270 | { |
| 271 | uint32_t data[3]; |
| 272 | unsigned int r, g, b; |
| 273 | while (width > 0) { |
| 274 | data[0] = *(uint32_t *) src; |
| 275 | src += 4; |
| 276 | data[1] = *(uint32_t *) src; |
| 277 | src += 4; |
| 278 | data[2] = *(uint32_t *) src; |
| 279 | src += 4; |
| 280 | # ifdef SWAP_WORDS |
| 281 | data[0] = bswap32(data[0]); |
| 282 | data[1] = bswap32(data[1]); |
| 283 | data[2] = bswap32(data[2]); |
| 284 | # endif |
| 285 | b = (data[0] & 0x3f) << 2; |
| 286 | data[0] >>= 6; |
| 287 | g = (data[0] & 0x3f) << 2; |
| 288 | data[0] >>= 6; |
| 289 | r = (data[0] & 0x3f) << 2; |
| 290 | data[0] >>= 6; |
| 291 | if (data[0] & 1) |
| 292 | SKIP_PIXEL(dest); |
| 293 | else |
| 294 | COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); |
| 295 | data[0] >>= 6; |
| 296 | b = (data[0] & 0x3f) << 2; |
| 297 | data[0] >>= 6; |
| 298 | g = ((data[1] & 0xf) << 4) | (data[0] << 2); |
| 299 | data[1] >>= 4; |
| 300 | r = (data[1] & 0x3f) << 2; |
| 301 | data[1] >>= 6; |
| 302 | if (data[1] & 1) |
| 303 | SKIP_PIXEL(dest); |
| 304 | else |
| 305 | COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); |
| 306 | data[1] >>= 6; |
| 307 | b = (data[1] & 0x3f) << 2; |
| 308 | data[1] >>= 6; |
| 309 | g = (data[1] & 0x3f) << 2; |
| 310 | data[1] >>= 6; |
| 311 | r = ((data[2] & 0x3) << 6) | (data[1] << 2); |
| 312 | data[2] >>= 2; |
| 313 | if (data[2] & 1) |
| 314 | SKIP_PIXEL(dest); |
| 315 | else |
| 316 | COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); |
| 317 | data[2] >>= 6; |
| 318 | b = (data[2] & 0x3f) << 2; |
| 319 | data[2] >>= 6; |
| 320 | g = (data[2] & 0x3f) << 2; |
| 321 | data[2] >>= 6; |
| 322 | r = data[2] << 2; |
| 323 | data[2] >>= 6; |
| 324 | if (data[2] & 1) |
| 325 | SKIP_PIXEL(dest); |
| 326 | else |
| 327 | COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); |
| 328 | width -= 4; |
| 329 | } |
| 330 | } |
| 331 | |
pbrook | 714fa30 | 2009-04-01 12:27:59 +0000 | [diff] [blame] | 332 | static void glue(pxa2xx_draw_line24_, BITS)(void *opaque, |
balrog | a171fe3 | 2007-04-30 01:48:07 +0000 | [diff] [blame] | 333 | uint8_t *dest, const uint8_t *src, int width, int deststep) |
| 334 | { |
| 335 | uint32_t data; |
| 336 | unsigned int r, g, b; |
| 337 | while (width > 0) { |
| 338 | data = *(uint32_t *) src; |
| 339 | #ifdef SWAP_WORDS |
| 340 | data = bswap32(data); |
| 341 | #endif |
| 342 | b = data & 0xff; |
| 343 | data >>= 8; |
| 344 | g = data & 0xff; |
| 345 | data >>= 8; |
| 346 | r = data & 0xff; |
| 347 | COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); |
| 348 | width -= 1; |
| 349 | src += 4; |
| 350 | } |
| 351 | } |
| 352 | |
pbrook | 714fa30 | 2009-04-01 12:27:59 +0000 | [diff] [blame] | 353 | static void glue(pxa2xx_draw_line24t_, BITS)(void *opaque, |
balrog | a171fe3 | 2007-04-30 01:48:07 +0000 | [diff] [blame] | 354 | uint8_t *dest, const uint8_t *src, int width, int deststep) |
| 355 | { |
| 356 | uint32_t data; |
| 357 | unsigned int r, g, b; |
| 358 | while (width > 0) { |
| 359 | data = *(uint32_t *) src; |
| 360 | #ifdef SWAP_WORDS |
| 361 | data = bswap32(data); |
| 362 | #endif |
| 363 | b = (data & 0x7f) << 1; |
| 364 | data >>= 7; |
| 365 | g = data & 0xff; |
| 366 | data >>= 8; |
| 367 | r = data & 0xff; |
| 368 | data >>= 8; |
| 369 | if (data & 1) |
| 370 | SKIP_PIXEL(dest); |
| 371 | else |
| 372 | COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); |
| 373 | width -= 1; |
| 374 | src += 4; |
| 375 | } |
| 376 | } |
| 377 | |
pbrook | 714fa30 | 2009-04-01 12:27:59 +0000 | [diff] [blame] | 378 | static void glue(pxa2xx_draw_line25_, BITS)(void *opaque, |
balrog | a171fe3 | 2007-04-30 01:48:07 +0000 | [diff] [blame] | 379 | uint8_t *dest, const uint8_t *src, int width, int deststep) |
| 380 | { |
| 381 | uint32_t data; |
| 382 | unsigned int r, g, b; |
| 383 | while (width > 0) { |
| 384 | data = *(uint32_t *) src; |
| 385 | #ifdef SWAP_WORDS |
| 386 | data = bswap32(data); |
| 387 | #endif |
| 388 | b = data & 0xff; |
| 389 | data >>= 8; |
| 390 | g = data & 0xff; |
| 391 | data >>= 8; |
| 392 | r = data & 0xff; |
| 393 | data >>= 8; |
| 394 | if (data & 1) |
| 395 | SKIP_PIXEL(dest); |
| 396 | else |
| 397 | COPY_PIXEL(dest, glue(rgb_to_pixel, BITS)(r, g, b)); |
| 398 | width -= 1; |
| 399 | src += 4; |
| 400 | } |
| 401 | } |
| 402 | |
| 403 | /* Overlay planes disabled, no transparency */ |
| 404 | static drawfn glue(pxa2xx_draw_fn_, BITS)[16] = |
| 405 | { |
Blue Swirl | b9d38e9 | 2009-09-21 18:11:34 +0000 | [diff] [blame] | 406 | [0 ... 0xf] = NULL, |
balrog | a171fe3 | 2007-04-30 01:48:07 +0000 | [diff] [blame] | 407 | [pxa_lcdc_2bpp] = glue(pxa2xx_draw_line2_, BITS), |
| 408 | [pxa_lcdc_4bpp] = glue(pxa2xx_draw_line4_, BITS), |
| 409 | [pxa_lcdc_8bpp] = glue(pxa2xx_draw_line8_, BITS), |
| 410 | [pxa_lcdc_16bpp] = glue(pxa2xx_draw_line16_, BITS), |
| 411 | [pxa_lcdc_18bpp] = glue(pxa2xx_draw_line18_, BITS), |
| 412 | [pxa_lcdc_18pbpp] = glue(pxa2xx_draw_line18p_, BITS), |
| 413 | [pxa_lcdc_24bpp] = glue(pxa2xx_draw_line24_, BITS), |
| 414 | }; |
| 415 | |
| 416 | /* Overlay planes enabled, transparency used */ |
| 417 | static drawfn glue(glue(pxa2xx_draw_fn_, BITS), t)[16] = |
| 418 | { |
Blue Swirl | b9d38e9 | 2009-09-21 18:11:34 +0000 | [diff] [blame] | 419 | [0 ... 0xf] = NULL, |
balrog | a171fe3 | 2007-04-30 01:48:07 +0000 | [diff] [blame] | 420 | [pxa_lcdc_4bpp] = glue(pxa2xx_draw_line4_, BITS), |
| 421 | [pxa_lcdc_8bpp] = glue(pxa2xx_draw_line8_, BITS), |
| 422 | [pxa_lcdc_16bpp] = glue(pxa2xx_draw_line16t_, BITS), |
| 423 | [pxa_lcdc_19bpp] = glue(pxa2xx_draw_line19_, BITS), |
| 424 | [pxa_lcdc_19pbpp] = glue(pxa2xx_draw_line19p_, BITS), |
| 425 | [pxa_lcdc_24bpp] = glue(pxa2xx_draw_line24t_, BITS), |
| 426 | [pxa_lcdc_25bpp] = glue(pxa2xx_draw_line25_, BITS), |
| 427 | }; |
| 428 | |
| 429 | #undef BITS |
| 430 | #undef COPY_PIXEL |
| 431 | #undef SKIP_PIXEL |
| 432 | |
| 433 | #ifdef SWAP_WORDS |
| 434 | # undef SWAP_WORDS |
| 435 | #endif |