Commit a5082316e97abb65d3e10085c50b6497473a9265
1 parent
20ba3ae1
hardware cursor support - fill with rop support - color expand and color expand …
…with transparent support - various optimisations git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@902 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
873 additions
and
621 deletions
hw/cirrus_vga.c
... | ... | @@ -29,6 +29,14 @@ |
29 | 29 | #include "vl.h" |
30 | 30 | #include "vga_int.h" |
31 | 31 | |
32 | +/* | |
33 | + * TODO: | |
34 | + * - add support for WRITEMASK (GR2F) | |
35 | + * - add support for scanline modulo in pattern fill | |
36 | + * - optimize linear mappings | |
37 | + * - optimize bitblt functions | |
38 | + */ | |
39 | + | |
32 | 40 | //#define DEBUG_CIRRUS |
33 | 41 | //#define DEBUG_BITBLT |
34 | 42 | |
... | ... | @@ -103,6 +111,7 @@ |
103 | 111 | #define CIRRUS_BLT_START 0x02 |
104 | 112 | #define CIRRUS_BLT_RESET 0x04 |
105 | 113 | #define CIRRUS_BLT_FIFOUSED 0x10 |
114 | +#define CIRRUS_BLT_AUTOSTART 0x80 | |
106 | 115 | |
107 | 116 | // control 0x32 |
108 | 117 | #define CIRRUS_ROP_0 0x00 |
... | ... | @@ -122,8 +131,12 @@ |
122 | 131 | #define CIRRUS_ROP_NOTSRC_OR_DST 0xd6 |
123 | 132 | #define CIRRUS_ROP_NOTSRC_AND_NOTDST 0xda |
124 | 133 | |
134 | +#define CIRRUS_ROP_NOP_INDEX 2 | |
135 | +#define CIRRUS_ROP_SRC_INDEX 5 | |
136 | + | |
125 | 137 | // control 0x33 |
126 | -#define CIRRUS_BLTMODEEXT_SOLIDFILL 0x04 | |
138 | +#define CIRRUS_BLTMODEEXT_SOLIDFILL 0x04 | |
139 | +#define CIRRUS_BLTMODEEXT_DWORDGRANULARITY 0x01 | |
127 | 140 | |
128 | 141 | // memory-mapped IO |
129 | 142 | #define CIRRUS_MMIO_BLTBGCOLOR 0x00 // dword |
... | ... | @@ -204,16 +217,19 @@ |
204 | 217 | #define CIRRUS_HOOK_NOT_HANDLED 0 |
205 | 218 | #define CIRRUS_HOOK_HANDLED 1 |
206 | 219 | |
207 | -typedef void (*cirrus_bitblt_rop_t) (uint8_t * dst, const uint8_t * src, | |
220 | +struct CirrusVGAState; | |
221 | +typedef void (*cirrus_bitblt_rop_t) (struct CirrusVGAState *s, | |
222 | + uint8_t * dst, const uint8_t * src, | |
208 | 223 | int dstpitch, int srcpitch, |
209 | 224 | int bltwidth, int bltheight); |
210 | - | |
211 | -typedef void (*cirrus_bitblt_handler_t) (void *opaque); | |
225 | +typedef void (*cirrus_fill_t)(struct CirrusVGAState *s, | |
226 | + uint8_t *dst, int dst_pitch, int width, int height); | |
212 | 227 | |
213 | 228 | typedef struct CirrusVGAState { |
214 | 229 | VGA_STATE_COMMON |
215 | 230 | |
216 | 231 | int cirrus_linear_io_addr; |
232 | + int cirrus_linear_bitblt_io_addr; | |
217 | 233 | int cirrus_mmio_io_addr; |
218 | 234 | uint32_t cirrus_addr_mask; |
219 | 235 | uint8_t cirrus_shadow_gr0; |
... | ... | @@ -223,18 +239,21 @@ typedef struct CirrusVGAState { |
223 | 239 | uint32_t cirrus_bank_base[2]; |
224 | 240 | uint32_t cirrus_bank_limit[2]; |
225 | 241 | uint8_t cirrus_hidden_palette[48]; |
226 | - uint32_t cirrus_hw_cursor_x; | |
227 | - uint32_t cirrus_hw_cursor_y; | |
242 | + uint32_t hw_cursor_x; | |
243 | + uint32_t hw_cursor_y; | |
228 | 244 | int cirrus_blt_pixelwidth; |
229 | 245 | int cirrus_blt_width; |
230 | 246 | int cirrus_blt_height; |
231 | 247 | int cirrus_blt_dstpitch; |
232 | 248 | int cirrus_blt_srcpitch; |
249 | + uint32_t cirrus_blt_fgcol; | |
250 | + uint32_t cirrus_blt_bgcol; | |
233 | 251 | uint32_t cirrus_blt_dstaddr; |
234 | 252 | uint32_t cirrus_blt_srcaddr; |
235 | 253 | uint8_t cirrus_blt_mode; |
254 | + uint8_t cirrus_blt_modeext; | |
236 | 255 | cirrus_bitblt_rop_t cirrus_rop; |
237 | -#define CIRRUS_BLTBUFSIZE 256 | |
256 | +#define CIRRUS_BLTBUFSIZE (2048 * 4) /* one line width */ | |
238 | 257 | uint8_t cirrus_bltbuf[CIRRUS_BLTBUFSIZE]; |
239 | 258 | uint8_t *cirrus_srcptr; |
240 | 259 | uint8_t *cirrus_srcptr_end; |
... | ... | @@ -242,8 +261,12 @@ typedef struct CirrusVGAState { |
242 | 261 | uint8_t *cirrus_dstptr; |
243 | 262 | uint8_t *cirrus_dstptr_end; |
244 | 263 | uint32_t cirrus_dstcounter; |
245 | - cirrus_bitblt_handler_t cirrus_blt_handler; | |
246 | - int cirrus_blt_horz_counter; | |
264 | + /* hwcursor display state */ | |
265 | + int last_hw_cursor_size; | |
266 | + int last_hw_cursor_x; | |
267 | + int last_hw_cursor_y; | |
268 | + int last_hw_cursor_y_start; | |
269 | + int last_hw_cursor_y_end; | |
247 | 270 | } CirrusVGAState; |
248 | 271 | |
249 | 272 | typedef struct PCICirrusVGAState { |
... | ... | @@ -251,6 +274,8 @@ typedef struct PCICirrusVGAState { |
251 | 274 | CirrusVGAState cirrus_vga; |
252 | 275 | } PCICirrusVGAState; |
253 | 276 | |
277 | +static uint8_t rop_to_index[256]; | |
278 | + | |
254 | 279 | /*************************************** |
255 | 280 | * |
256 | 281 | * prototypes. |
... | ... | @@ -266,343 +291,233 @@ static void cirrus_bitblt_reset(CirrusVGAState * s); |
266 | 291 | * |
267 | 292 | ***************************************/ |
268 | 293 | |
269 | -#define IMPLEMENT_BITBLT(name,opline) \ | |
270 | - static void \ | |
271 | - cirrus_bitblt_rop_fwd_##name( \ | |
272 | - uint8_t *dst,const uint8_t *src, \ | |
273 | - int dstpitch,int srcpitch, \ | |
274 | - int bltwidth,int bltheight) \ | |
275 | - { \ | |
276 | - int x,y; \ | |
277 | - dstpitch -= bltwidth; \ | |
278 | - srcpitch -= bltwidth; \ | |
279 | - for (y = 0; y < bltheight; y++) { \ | |
280 | - for (x = 0; x < bltwidth; x++) { \ | |
281 | - opline; \ | |
282 | - dst++; \ | |
283 | - src++; \ | |
284 | - } \ | |
285 | - dst += dstpitch; \ | |
286 | - src += srcpitch; \ | |
287 | - } \ | |
288 | - } \ | |
289 | - \ | |
290 | - static void \ | |
291 | - cirrus_bitblt_rop_bkwd_##name( \ | |
292 | - uint8_t *dst,const uint8_t *src, \ | |
293 | - int dstpitch,int srcpitch, \ | |
294 | - int bltwidth,int bltheight) \ | |
295 | - { \ | |
296 | - int x,y; \ | |
297 | - dstpitch += bltwidth; \ | |
298 | - srcpitch += bltwidth; \ | |
299 | - for (y = 0; y < bltheight; y++) { \ | |
300 | - for (x = 0; x < bltwidth; x++) { \ | |
301 | - opline; \ | |
302 | - dst--; \ | |
303 | - src--; \ | |
304 | - } \ | |
305 | - dst += dstpitch; \ | |
306 | - src += srcpitch; \ | |
307 | - } \ | |
308 | - } | |
309 | - | |
310 | -IMPLEMENT_BITBLT(0, *dst = 0) | |
311 | -IMPLEMENT_BITBLT(src_and_dst, *dst = (*src) & (*dst)) | |
312 | -IMPLEMENT_BITBLT(nop, (void) 0) | |
313 | -IMPLEMENT_BITBLT(src_and_notdst, *dst = (*src) & (~(*dst))) | |
314 | -IMPLEMENT_BITBLT(notdst, *dst = ~(*dst)) | |
315 | -IMPLEMENT_BITBLT(src, *dst = *src) | |
316 | -IMPLEMENT_BITBLT(1, *dst = 0xff) | |
317 | -IMPLEMENT_BITBLT(notsrc_and_dst, *dst = (~(*src)) & (*dst)) | |
318 | -IMPLEMENT_BITBLT(src_xor_dst, *dst = (*src) ^ (*dst)) | |
319 | -IMPLEMENT_BITBLT(src_or_dst, *dst = (*src) | (*dst)) | |
320 | -IMPLEMENT_BITBLT(notsrc_or_notdst, *dst = (~(*src)) | (~(*dst))) | |
321 | -IMPLEMENT_BITBLT(src_notxor_dst, *dst = ~((*src) ^ (*dst))) | |
322 | -IMPLEMENT_BITBLT(src_or_notdst, *dst = (*src) | (~(*dst))) | |
323 | -IMPLEMENT_BITBLT(notsrc, *dst = (~(*src))) | |
324 | -IMPLEMENT_BITBLT(notsrc_or_dst, *dst = (~(*src)) | (*dst)) | |
325 | -IMPLEMENT_BITBLT(notsrc_and_notdst, *dst = (~(*src)) & (~(*dst))) | |
326 | - | |
327 | -static cirrus_bitblt_rop_t cirrus_get_fwd_rop_handler(uint8_t rop) | |
328 | -{ | |
329 | - cirrus_bitblt_rop_t rop_handler = cirrus_bitblt_rop_fwd_nop; | |
330 | - | |
331 | - switch (rop) { | |
332 | - case CIRRUS_ROP_0: | |
333 | - rop_handler = cirrus_bitblt_rop_fwd_0; | |
334 | - break; | |
335 | - case CIRRUS_ROP_SRC_AND_DST: | |
336 | - rop_handler = cirrus_bitblt_rop_fwd_src_and_dst; | |
337 | - break; | |
338 | - case CIRRUS_ROP_NOP: | |
339 | - rop_handler = cirrus_bitblt_rop_fwd_nop; | |
340 | - break; | |
341 | - case CIRRUS_ROP_SRC_AND_NOTDST: | |
342 | - rop_handler = cirrus_bitblt_rop_fwd_src_and_notdst; | |
343 | - break; | |
344 | - case CIRRUS_ROP_NOTDST: | |
345 | - rop_handler = cirrus_bitblt_rop_fwd_notdst; | |
346 | - break; | |
347 | - case CIRRUS_ROP_SRC: | |
348 | - rop_handler = cirrus_bitblt_rop_fwd_src; | |
349 | - break; | |
350 | - case CIRRUS_ROP_1: | |
351 | - rop_handler = cirrus_bitblt_rop_fwd_1; | |
352 | - break; | |
353 | - case CIRRUS_ROP_NOTSRC_AND_DST: | |
354 | - rop_handler = cirrus_bitblt_rop_fwd_notsrc_and_dst; | |
355 | - break; | |
356 | - case CIRRUS_ROP_SRC_XOR_DST: | |
357 | - rop_handler = cirrus_bitblt_rop_fwd_src_xor_dst; | |
358 | - break; | |
359 | - case CIRRUS_ROP_SRC_OR_DST: | |
360 | - rop_handler = cirrus_bitblt_rop_fwd_src_or_dst; | |
361 | - break; | |
362 | - case CIRRUS_ROP_NOTSRC_OR_NOTDST: | |
363 | - rop_handler = cirrus_bitblt_rop_fwd_notsrc_or_notdst; | |
364 | - break; | |
365 | - case CIRRUS_ROP_SRC_NOTXOR_DST: | |
366 | - rop_handler = cirrus_bitblt_rop_fwd_src_notxor_dst; | |
367 | - break; | |
368 | - case CIRRUS_ROP_SRC_OR_NOTDST: | |
369 | - rop_handler = cirrus_bitblt_rop_fwd_src_or_notdst; | |
370 | - break; | |
371 | - case CIRRUS_ROP_NOTSRC: | |
372 | - rop_handler = cirrus_bitblt_rop_fwd_notsrc; | |
373 | - break; | |
374 | - case CIRRUS_ROP_NOTSRC_OR_DST: | |
375 | - rop_handler = cirrus_bitblt_rop_fwd_notsrc_or_dst; | |
376 | - break; | |
377 | - case CIRRUS_ROP_NOTSRC_AND_NOTDST: | |
378 | - rop_handler = cirrus_bitblt_rop_fwd_notsrc_and_notdst; | |
379 | - break; | |
380 | - default: | |
381 | -#ifdef DEBUG_CIRRUS | |
382 | - printf("unknown ROP %02x\n", rop); | |
383 | -#endif | |
384 | - break; | |
385 | - } | |
386 | - | |
387 | - return rop_handler; | |
294 | +static void cirrus_bitblt_rop_nop(CirrusVGAState *s, | |
295 | + uint8_t *dst,const uint8_t *src, | |
296 | + int dstpitch,int srcpitch, | |
297 | + int bltwidth,int bltheight) | |
298 | +{ | |
388 | 299 | } |
389 | 300 | |
390 | -static cirrus_bitblt_rop_t cirrus_get_bkwd_rop_handler(uint8_t rop) | |
301 | +static void cirrus_bitblt_fill_nop(CirrusVGAState *s, | |
302 | + uint8_t *dst, | |
303 | + int dstpitch, int bltwidth,int bltheight) | |
391 | 304 | { |
392 | - cirrus_bitblt_rop_t rop_handler = cirrus_bitblt_rop_bkwd_nop; | |
305 | +} | |
393 | 306 | |
394 | - switch (rop) { | |
395 | - case CIRRUS_ROP_0: | |
396 | - rop_handler = cirrus_bitblt_rop_bkwd_0; | |
397 | - break; | |
398 | - case CIRRUS_ROP_SRC_AND_DST: | |
399 | - rop_handler = cirrus_bitblt_rop_bkwd_src_and_dst; | |
400 | - break; | |
401 | - case CIRRUS_ROP_NOP: | |
402 | - rop_handler = cirrus_bitblt_rop_bkwd_nop; | |
403 | - break; | |
404 | - case CIRRUS_ROP_SRC_AND_NOTDST: | |
405 | - rop_handler = cirrus_bitblt_rop_bkwd_src_and_notdst; | |
406 | - break; | |
407 | - case CIRRUS_ROP_NOTDST: | |
408 | - rop_handler = cirrus_bitblt_rop_bkwd_notdst; | |
409 | - break; | |
410 | - case CIRRUS_ROP_SRC: | |
411 | - rop_handler = cirrus_bitblt_rop_bkwd_src; | |
412 | - break; | |
413 | - case CIRRUS_ROP_1: | |
414 | - rop_handler = cirrus_bitblt_rop_bkwd_1; | |
415 | - break; | |
416 | - case CIRRUS_ROP_NOTSRC_AND_DST: | |
417 | - rop_handler = cirrus_bitblt_rop_bkwd_notsrc_and_dst; | |
418 | - break; | |
419 | - case CIRRUS_ROP_SRC_XOR_DST: | |
420 | - rop_handler = cirrus_bitblt_rop_bkwd_src_xor_dst; | |
421 | - break; | |
422 | - case CIRRUS_ROP_SRC_OR_DST: | |
423 | - rop_handler = cirrus_bitblt_rop_bkwd_src_or_dst; | |
424 | - break; | |
425 | - case CIRRUS_ROP_NOTSRC_OR_NOTDST: | |
426 | - rop_handler = cirrus_bitblt_rop_bkwd_notsrc_or_notdst; | |
427 | - break; | |
428 | - case CIRRUS_ROP_SRC_NOTXOR_DST: | |
429 | - rop_handler = cirrus_bitblt_rop_bkwd_src_notxor_dst; | |
430 | - break; | |
431 | - case CIRRUS_ROP_SRC_OR_NOTDST: | |
432 | - rop_handler = cirrus_bitblt_rop_bkwd_src_or_notdst; | |
433 | - break; | |
434 | - case CIRRUS_ROP_NOTSRC: | |
435 | - rop_handler = cirrus_bitblt_rop_bkwd_notsrc; | |
436 | - break; | |
437 | - case CIRRUS_ROP_NOTSRC_OR_DST: | |
438 | - rop_handler = cirrus_bitblt_rop_bkwd_notsrc_or_dst; | |
439 | - break; | |
440 | - case CIRRUS_ROP_NOTSRC_AND_NOTDST: | |
441 | - rop_handler = cirrus_bitblt_rop_bkwd_notsrc_and_notdst; | |
442 | - break; | |
443 | - default: | |
444 | -#ifdef DEBUG_CIRRUS | |
445 | - printf("unknown ROP %02x\n", rop); | |
446 | -#endif | |
447 | - break; | |
448 | - } | |
307 | +#define ROP_NAME 0 | |
308 | +#define ROP_OP(d, s) d = 0 | |
309 | +#include "cirrus_vga_rop.h" | |
449 | 310 | |
450 | - return rop_handler; | |
451 | -} | |
311 | +#define ROP_NAME src_and_dst | |
312 | +#define ROP_OP(d, s) d = (s) & (d) | |
313 | +#include "cirrus_vga_rop.h" | |
452 | 314 | |
453 | -/*************************************** | |
454 | - * | |
455 | - * color expansion | |
456 | - * | |
457 | - ***************************************/ | |
315 | +#define ROP_NAME src_and_notdst | |
316 | +#define ROP_OP(d, s) d = (s) & (~(d)) | |
317 | +#include "cirrus_vga_rop.h" | |
458 | 318 | |
459 | -static void | |
460 | -cirrus_colorexpand_8(CirrusVGAState * s, uint8_t * dst, | |
461 | - const uint8_t * src, int count) | |
462 | -{ | |
463 | - int x; | |
464 | - uint8_t colors[2]; | |
465 | - unsigned bits; | |
466 | - unsigned bitmask; | |
467 | - int srcskipleft = 0; | |
468 | - | |
469 | - colors[0] = s->cirrus_shadow_gr0; | |
470 | - colors[1] = s->cirrus_shadow_gr1; | |
471 | - | |
472 | - bitmask = 0x80 >> srcskipleft; | |
473 | - bits = *src++; | |
474 | - for (x = 0; x < count; x++) { | |
475 | - if ((bitmask & 0xff) == 0) { | |
476 | - bitmask = 0x80; | |
477 | - bits = *src++; | |
478 | - } | |
479 | - *dst++ = colors[!!(bits & bitmask)]; | |
480 | - bitmask >>= 1; | |
481 | - } | |
482 | -} | |
319 | +#define ROP_NAME notdst | |
320 | +#define ROP_OP(d, s) d = ~(d) | |
321 | +#include "cirrus_vga_rop.h" | |
483 | 322 | |
484 | -static void | |
485 | -cirrus_colorexpand_16(CirrusVGAState * s, uint8_t * dst, | |
486 | - const uint8_t * src, int count) | |
487 | -{ | |
488 | - int x; | |
489 | - uint8_t colors[2][2]; | |
490 | - unsigned bits; | |
491 | - unsigned bitmask; | |
492 | - unsigned index; | |
493 | - int srcskipleft = 0; | |
494 | - | |
495 | - colors[0][0] = s->cirrus_shadow_gr0; | |
496 | - colors[0][1] = s->gr[0x10]; | |
497 | - colors[1][0] = s->cirrus_shadow_gr1; | |
498 | - colors[1][1] = s->gr[0x11]; | |
499 | - | |
500 | - bitmask = 0x80 >> srcskipleft; | |
501 | - bits = *src++; | |
502 | - for (x = 0; x < count; x++) { | |
503 | - if ((bitmask & 0xff) == 0) { | |
504 | - bitmask = 0x80; | |
505 | - bits = *src++; | |
506 | - } | |
507 | - index = !!(bits & bitmask); | |
508 | - *dst++ = colors[index][0]; | |
509 | - *dst++ = colors[index][1]; | |
510 | - bitmask >>= 1; | |
511 | - } | |
512 | -} | |
323 | +#define ROP_NAME src | |
324 | +#define ROP_OP(d, s) d = s | |
325 | +#include "cirrus_vga_rop.h" | |
513 | 326 | |
514 | -static void | |
515 | -cirrus_colorexpand_24(CirrusVGAState * s, uint8_t * dst, | |
516 | - const uint8_t * src, int count) | |
517 | -{ | |
518 | - int x; | |
519 | - uint8_t colors[2][3]; | |
520 | - unsigned bits; | |
521 | - unsigned bitmask; | |
522 | - unsigned index; | |
523 | - int srcskipleft = 0; | |
524 | - | |
525 | - colors[0][0] = s->cirrus_shadow_gr0; | |
526 | - colors[0][1] = s->gr[0x10]; | |
527 | - colors[0][2] = s->gr[0x12]; | |
528 | - colors[1][0] = s->cirrus_shadow_gr1; | |
529 | - colors[1][1] = s->gr[0x11]; | |
530 | - colors[1][2] = s->gr[0x13]; | |
531 | - | |
532 | - bitmask = 0x80 << srcskipleft; | |
533 | - bits = *src++; | |
534 | - for (x = 0; x < count; x++) { | |
535 | - if ((bitmask & 0xff) == 0) { | |
536 | - bitmask = 0x80; | |
537 | - bits = *src++; | |
538 | - } | |
539 | - index = !!(bits & bitmask); | |
540 | - *dst++ = colors[index][0]; | |
541 | - *dst++ = colors[index][1]; | |
542 | - *dst++ = colors[index][2]; | |
543 | - bitmask >>= 1; | |
544 | - } | |
545 | -} | |
327 | +#define ROP_NAME 1 | |
328 | +#define ROP_OP(d, s) d = 0xff | |
329 | +#include "cirrus_vga_rop.h" | |
330 | + | |
331 | +#define ROP_NAME notsrc_and_dst | |
332 | +#define ROP_OP(d, s) d = (~(s)) & (d) | |
333 | +#include "cirrus_vga_rop.h" | |
334 | + | |
335 | +#define ROP_NAME src_xor_dst | |
336 | +#define ROP_OP(d, s) d = (s) ^ (d) | |
337 | +#include "cirrus_vga_rop.h" | |
338 | + | |
339 | +#define ROP_NAME src_or_dst | |
340 | +#define ROP_OP(d, s) d = (s) | (d) | |
341 | +#include "cirrus_vga_rop.h" | |
342 | + | |
343 | +#define ROP_NAME notsrc_or_notdst | |
344 | +#define ROP_OP(d, s) d = (~(s)) | (~(d)) | |
345 | +#include "cirrus_vga_rop.h" | |
346 | + | |
347 | +#define ROP_NAME src_notxor_dst | |
348 | +#define ROP_OP(d, s) d = ~((s) ^ (d)) | |
349 | +#include "cirrus_vga_rop.h" | |
546 | 350 | |
547 | -static void | |
548 | -cirrus_colorexpand_32(CirrusVGAState * s, uint8_t * dst, | |
549 | - const uint8_t * src, int count) | |
351 | +#define ROP_NAME src_or_notdst | |
352 | +#define ROP_OP(d, s) d = (s) | (~(d)) | |
353 | +#include "cirrus_vga_rop.h" | |
354 | + | |
355 | +#define ROP_NAME notsrc | |
356 | +#define ROP_OP(d, s) d = (~(s)) | |
357 | +#include "cirrus_vga_rop.h" | |
358 | + | |
359 | +#define ROP_NAME notsrc_or_dst | |
360 | +#define ROP_OP(d, s) d = (~(s)) | (d) | |
361 | +#include "cirrus_vga_rop.h" | |
362 | + | |
363 | +#define ROP_NAME notsrc_and_notdst | |
364 | +#define ROP_OP(d, s) d = (~(s)) & (~(d)) | |
365 | +#include "cirrus_vga_rop.h" | |
366 | + | |
367 | +static const cirrus_bitblt_rop_t cirrus_fwd_rop[16] = { | |
368 | + cirrus_bitblt_rop_fwd_0, | |
369 | + cirrus_bitblt_rop_fwd_src_and_dst, | |
370 | + cirrus_bitblt_rop_nop, | |
371 | + cirrus_bitblt_rop_fwd_src_and_notdst, | |
372 | + cirrus_bitblt_rop_fwd_notdst, | |
373 | + cirrus_bitblt_rop_fwd_src, | |
374 | + cirrus_bitblt_rop_fwd_1, | |
375 | + cirrus_bitblt_rop_fwd_notsrc_and_dst, | |
376 | + cirrus_bitblt_rop_fwd_src_xor_dst, | |
377 | + cirrus_bitblt_rop_fwd_src_or_dst, | |
378 | + cirrus_bitblt_rop_fwd_notsrc_or_notdst, | |
379 | + cirrus_bitblt_rop_fwd_src_notxor_dst, | |
380 | + cirrus_bitblt_rop_fwd_src_or_notdst, | |
381 | + cirrus_bitblt_rop_fwd_notsrc, | |
382 | + cirrus_bitblt_rop_fwd_notsrc_or_dst, | |
383 | + cirrus_bitblt_rop_fwd_notsrc_and_notdst, | |
384 | +}; | |
385 | + | |
386 | +static const cirrus_bitblt_rop_t cirrus_bkwd_rop[16] = { | |
387 | + cirrus_bitblt_rop_bkwd_0, | |
388 | + cirrus_bitblt_rop_bkwd_src_and_dst, | |
389 | + cirrus_bitblt_rop_nop, | |
390 | + cirrus_bitblt_rop_bkwd_src_and_notdst, | |
391 | + cirrus_bitblt_rop_bkwd_notdst, | |
392 | + cirrus_bitblt_rop_bkwd_src, | |
393 | + cirrus_bitblt_rop_bkwd_1, | |
394 | + cirrus_bitblt_rop_bkwd_notsrc_and_dst, | |
395 | + cirrus_bitblt_rop_bkwd_src_xor_dst, | |
396 | + cirrus_bitblt_rop_bkwd_src_or_dst, | |
397 | + cirrus_bitblt_rop_bkwd_notsrc_or_notdst, | |
398 | + cirrus_bitblt_rop_bkwd_src_notxor_dst, | |
399 | + cirrus_bitblt_rop_bkwd_src_or_notdst, | |
400 | + cirrus_bitblt_rop_bkwd_notsrc, | |
401 | + cirrus_bitblt_rop_bkwd_notsrc_or_dst, | |
402 | + cirrus_bitblt_rop_bkwd_notsrc_and_notdst, | |
403 | +}; | |
404 | + | |
405 | +#define ROP2(name) {\ | |
406 | + name ## _8,\ | |
407 | + name ## _16,\ | |
408 | + name ## _24,\ | |
409 | + name ## _32,\ | |
410 | + } | |
411 | + | |
412 | +#define ROP_NOP2(func) {\ | |
413 | + func,\ | |
414 | + func,\ | |
415 | + func,\ | |
416 | + func,\ | |
417 | + } | |
418 | + | |
419 | +static const cirrus_bitblt_rop_t cirrus_colorexpand_transp[16][4] = { | |
420 | + ROP2(cirrus_colorexpand_transp_0), | |
421 | + ROP2(cirrus_colorexpand_transp_src_and_dst), | |
422 | + ROP_NOP2(cirrus_bitblt_rop_nop), | |
423 | + ROP2(cirrus_colorexpand_transp_src_and_notdst), | |
424 | + ROP2(cirrus_colorexpand_transp_notdst), | |
425 | + ROP2(cirrus_colorexpand_transp_src), | |
426 | + ROP2(cirrus_colorexpand_transp_1), | |
427 | + ROP2(cirrus_colorexpand_transp_notsrc_and_dst), | |
428 | + ROP2(cirrus_colorexpand_transp_src_xor_dst), | |
429 | + ROP2(cirrus_colorexpand_transp_src_or_dst), | |
430 | + ROP2(cirrus_colorexpand_transp_notsrc_or_notdst), | |
431 | + ROP2(cirrus_colorexpand_transp_src_notxor_dst), | |
432 | + ROP2(cirrus_colorexpand_transp_src_or_notdst), | |
433 | + ROP2(cirrus_colorexpand_transp_notsrc), | |
434 | + ROP2(cirrus_colorexpand_transp_notsrc_or_dst), | |
435 | + ROP2(cirrus_colorexpand_transp_notsrc_and_notdst), | |
436 | +}; | |
437 | + | |
438 | +static const cirrus_bitblt_rop_t cirrus_colorexpand[16][4] = { | |
439 | + ROP2(cirrus_colorexpand_0), | |
440 | + ROP2(cirrus_colorexpand_src_and_dst), | |
441 | + ROP_NOP2(cirrus_bitblt_rop_nop), | |
442 | + ROP2(cirrus_colorexpand_src_and_notdst), | |
443 | + ROP2(cirrus_colorexpand_notdst), | |
444 | + ROP2(cirrus_colorexpand_src), | |
445 | + ROP2(cirrus_colorexpand_1), | |
446 | + ROP2(cirrus_colorexpand_notsrc_and_dst), | |
447 | + ROP2(cirrus_colorexpand_src_xor_dst), | |
448 | + ROP2(cirrus_colorexpand_src_or_dst), | |
449 | + ROP2(cirrus_colorexpand_notsrc_or_notdst), | |
450 | + ROP2(cirrus_colorexpand_src_notxor_dst), | |
451 | + ROP2(cirrus_colorexpand_src_or_notdst), | |
452 | + ROP2(cirrus_colorexpand_notsrc), | |
453 | + ROP2(cirrus_colorexpand_notsrc_or_dst), | |
454 | + ROP2(cirrus_colorexpand_notsrc_and_notdst), | |
455 | +}; | |
456 | + | |
457 | +static const cirrus_fill_t cirrus_fill[16][4] = { | |
458 | + ROP2(cirrus_fill_0), | |
459 | + ROP2(cirrus_fill_src_and_dst), | |
460 | + ROP_NOP2(cirrus_bitblt_fill_nop), | |
461 | + ROP2(cirrus_fill_src_and_notdst), | |
462 | + ROP2(cirrus_fill_notdst), | |
463 | + ROP2(cirrus_fill_src), | |
464 | + ROP2(cirrus_fill_1), | |
465 | + ROP2(cirrus_fill_notsrc_and_dst), | |
466 | + ROP2(cirrus_fill_src_xor_dst), | |
467 | + ROP2(cirrus_fill_src_or_dst), | |
468 | + ROP2(cirrus_fill_notsrc_or_notdst), | |
469 | + ROP2(cirrus_fill_src_notxor_dst), | |
470 | + ROP2(cirrus_fill_src_or_notdst), | |
471 | + ROP2(cirrus_fill_notsrc), | |
472 | + ROP2(cirrus_fill_notsrc_or_dst), | |
473 | + ROP2(cirrus_fill_notsrc_and_notdst), | |
474 | +}; | |
475 | + | |
476 | +static inline void cirrus_bitblt_fgcol(CirrusVGAState *s) | |
550 | 477 | { |
551 | - int x; | |
552 | - uint8_t colors[2][4]; | |
553 | - unsigned bits; | |
554 | - unsigned bitmask; | |
555 | - unsigned index; | |
556 | - int srcskipleft = 0; | |
557 | - | |
558 | - colors[0][0] = s->cirrus_shadow_gr0; | |
559 | - colors[0][1] = s->gr[0x10]; | |
560 | - colors[0][2] = s->gr[0x12]; | |
561 | - colors[0][3] = s->gr[0x14]; | |
562 | - colors[1][0] = s->cirrus_shadow_gr1; | |
563 | - colors[1][1] = s->gr[0x11]; | |
564 | - colors[1][2] = s->gr[0x13]; | |
565 | - colors[1][3] = s->gr[0x15]; | |
566 | - | |
567 | - bitmask = 0x80 << srcskipleft; | |
568 | - bits = *src++; | |
569 | - for (x = 0; x < count; x++) { | |
570 | - if ((bitmask & 0xff) == 0) { | |
571 | - bitmask = 0x80; | |
572 | - bits = *src++; | |
573 | - } | |
574 | - index = !!(bits & bitmask); | |
575 | - *dst++ = colors[index][0]; | |
576 | - *dst++ = colors[index][1]; | |
577 | - *dst++ = colors[index][2]; | |
578 | - *dst++ = colors[index][3]; | |
579 | - bitmask >>= 1; | |
478 | + unsigned int color; | |
479 | + switch (s->cirrus_blt_pixelwidth) { | |
480 | + case 1: | |
481 | + s->cirrus_blt_fgcol = s->cirrus_shadow_gr1; | |
482 | + break; | |
483 | + case 2: | |
484 | + color = s->cirrus_shadow_gr1 | (s->gr[0x11] << 8); | |
485 | + s->cirrus_blt_fgcol = le16_to_cpu(color); | |
486 | + break; | |
487 | + case 3: | |
488 | + s->cirrus_blt_fgcol = s->cirrus_shadow_gr1 | | |
489 | + (s->gr[0x11] << 8) | (s->gr[0x13] << 16); | |
490 | + break; | |
491 | + default: | |
492 | + case 4: | |
493 | + color = s->cirrus_shadow_gr1 | (s->gr[0x11] << 8) | | |
494 | + (s->gr[0x13] << 16) | (s->gr[0x15] << 24); | |
495 | + s->cirrus_blt_fgcol = le32_to_cpu(color); | |
496 | + break; | |
580 | 497 | } |
581 | 498 | } |
582 | 499 | |
583 | -static void | |
584 | -cirrus_colorexpand(CirrusVGAState * s, uint8_t * dst, const uint8_t * src, | |
585 | - int count) | |
500 | +static inline void cirrus_bitblt_bgcol(CirrusVGAState *s) | |
586 | 501 | { |
502 | + unsigned int color; | |
587 | 503 | switch (s->cirrus_blt_pixelwidth) { |
588 | 504 | case 1: |
589 | - cirrus_colorexpand_8(s, dst, src, count); | |
590 | - break; | |
505 | + s->cirrus_blt_bgcol = s->cirrus_shadow_gr0; | |
506 | + break; | |
591 | 507 | case 2: |
592 | - cirrus_colorexpand_16(s, dst, src, count); | |
593 | - break; | |
508 | + color = s->cirrus_shadow_gr0 | (s->gr[0x10] << 8); | |
509 | + s->cirrus_blt_bgcol = le16_to_cpu(color); | |
510 | + break; | |
594 | 511 | case 3: |
595 | - cirrus_colorexpand_24(s, dst, src, count); | |
596 | - break; | |
597 | - case 4: | |
598 | - cirrus_colorexpand_32(s, dst, src, count); | |
599 | - break; | |
512 | + s->cirrus_blt_bgcol = s->cirrus_shadow_gr0 | | |
513 | + (s->gr[0x10] << 8) | (s->gr[0x12] << 16); | |
514 | + break; | |
600 | 515 | default: |
601 | -#ifdef DEBUG_CIRRUS | |
602 | - printf("cirrus: COLOREXPAND pixelwidth %d - unimplemented\n", | |
603 | - s->cirrus_blt_pixelwidth); | |
604 | -#endif | |
605 | - break; | |
516 | + case 4: | |
517 | + color = s->cirrus_shadow_gr0 | (s->gr[0x10] << 8) | | |
518 | + (s->gr[0x12] << 16) | (s->gr[0x14] << 24); | |
519 | + s->cirrus_blt_bgcol = le32_to_cpu(color); | |
520 | + break; | |
606 | 521 | } |
607 | 522 | } |
608 | 523 | |
... | ... | @@ -626,8 +541,6 @@ static void cirrus_invalidate_region(CirrusVGAState * s, int off_begin, |
626 | 541 | } |
627 | 542 | } |
628 | 543 | |
629 | - | |
630 | - | |
631 | 544 | static int cirrus_bitblt_common_patterncopy(CirrusVGAState * s, |
632 | 545 | const uint8_t * src) |
633 | 546 | { |
... | ... | @@ -639,12 +552,16 @@ static int cirrus_bitblt_common_patterncopy(CirrusVGAState * s, |
639 | 552 | int patternbytes = s->cirrus_blt_pixelwidth * 8; |
640 | 553 | |
641 | 554 | if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) { |
642 | - cirrus_colorexpand(s, work_colorexp, src, 8 * 8); | |
555 | + cirrus_bitblt_rop_t rop_func; | |
556 | + cirrus_bitblt_fgcol(s); | |
557 | + cirrus_bitblt_bgcol(s); | |
558 | + rop_func = cirrus_colorexpand[CIRRUS_ROP_SRC_INDEX][s->cirrus_blt_pixelwidth - 1]; | |
559 | + rop_func(s, work_colorexp, src, patternbytes, 1, patternbytes, 8); | |
643 | 560 | src = work_colorexp; |
644 | 561 | s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_COLOREXPAND; |
645 | 562 | } |
646 | 563 | if (s->cirrus_blt_mode & ~CIRRUS_BLTMODE_PATTERNCOPY) { |
647 | -#ifdef DEBUG_CIRRUS | |
564 | +#ifdef DEBUG_BITBLT | |
648 | 565 | printf("cirrus: blt mode %02x (pattercopy) - unimplemented\n", |
649 | 566 | s->cirrus_blt_mode); |
650 | 567 | #endif |
... | ... | @@ -657,7 +574,7 @@ static int cirrus_bitblt_common_patterncopy(CirrusVGAState * s, |
657 | 574 | tileheight = qemu_MIN(8, s->cirrus_blt_height - y); |
658 | 575 | for (x = 0; x < s->cirrus_blt_width; x += patternbytes) { |
659 | 576 | tilewidth = qemu_MIN(patternbytes, s->cirrus_blt_width - x); |
660 | - (*s->cirrus_rop) (dstc, src, | |
577 | + (*s->cirrus_rop) (s, dstc, src, | |
661 | 578 | s->cirrus_blt_dstpitch, patternbytes, |
662 | 579 | tilewidth, tileheight); |
663 | 580 | dstc += patternbytes; |
... | ... | @@ -672,111 +589,14 @@ static int cirrus_bitblt_common_patterncopy(CirrusVGAState * s, |
672 | 589 | |
673 | 590 | /* fill */ |
674 | 591 | |
675 | -static void cirrus_fill_8(CirrusVGAState *s, | |
676 | - uint8_t *dst, int dst_pitch, int width, int height) | |
592 | +static int cirrus_bitblt_solidfill(CirrusVGAState *s, int blt_rop) | |
677 | 593 | { |
678 | - uint8_t *d, *d1; | |
679 | - uint32_t val; | |
680 | - int x, y; | |
594 | + cirrus_fill_t rop_func; | |
681 | 595 | |
682 | - val = s->cirrus_shadow_gr1; | |
683 | - | |
684 | - d1 = dst; | |
685 | - for(y = 0; y < height; y++) { | |
686 | - d = d1; | |
687 | - for(x = 0; x < width; x++) { | |
688 | - *d++ = val; | |
689 | - } | |
690 | - d1 += dst_pitch; | |
691 | - } | |
692 | -} | |
693 | - | |
694 | -static void cirrus_fill_16(CirrusVGAState *s, | |
695 | - uint8_t *dst, int dst_pitch, int width, int height) | |
696 | -{ | |
697 | - uint8_t *d, *d1; | |
698 | - uint32_t val; | |
699 | - int x, y; | |
700 | - | |
701 | - val = s->cirrus_shadow_gr1 | (s->gr[0x11] << 8); | |
702 | - val = le16_to_cpu(val); | |
703 | - width >>= 1; | |
704 | - | |
705 | - d1 = dst; | |
706 | - for(y = 0; y < height; y++) { | |
707 | - d = d1; | |
708 | - for(x = 0; x < width; x++) { | |
709 | - ((uint16_t *)d)[0] = val; | |
710 | - d += 2; | |
711 | - } | |
712 | - d1 += dst_pitch; | |
713 | - } | |
714 | -} | |
715 | - | |
716 | -static void cirrus_fill_24(CirrusVGAState *s, | |
717 | - uint8_t *dst, int dst_pitch, int width, int height) | |
718 | -{ | |
719 | - uint8_t *d, *d1; | |
720 | - int x, y; | |
721 | - | |
722 | - d1 = dst; | |
723 | - for(y = 0; y < height; y++) { | |
724 | - d = d1; | |
725 | - for(x = 0; x < width; x += 3) { | |
726 | - *d++ = s->cirrus_shadow_gr1; | |
727 | - *d++ = s->gr[0x11]; | |
728 | - *d++ = s->gr[0x13]; | |
729 | - } | |
730 | - d1 += dst_pitch; | |
731 | - } | |
732 | -} | |
733 | - | |
734 | -static void cirrus_fill_32(CirrusVGAState *s, | |
735 | - uint8_t *dst, int dst_pitch, int width, int height) | |
736 | -{ | |
737 | - uint8_t *d, *d1; | |
738 | - uint32_t val; | |
739 | - int x, y; | |
740 | - | |
741 | - val = s->cirrus_shadow_gr1 | (s->gr[0x11] << 8) | | |
742 | - (s->gr[0x13] << 8) | (s->gr[0x15] << 8); | |
743 | - val = le32_to_cpu(val); | |
744 | - width >>= 2; | |
745 | - | |
746 | - d1 = dst; | |
747 | - for(y = 0; y < height; y++) { | |
748 | - d = d1; | |
749 | - for(x = 0; x < width; x++) { | |
750 | - ((uint32_t *)d)[0] = val; | |
751 | - d += 4; | |
752 | - } | |
753 | - d1 += dst_pitch; | |
754 | - } | |
755 | -} | |
756 | - | |
757 | -static int cirrus_bitblt_solidfill(CirrusVGAState *s) | |
758 | -{ | |
759 | - uint8_t *dst; | |
760 | - dst = s->vram_ptr + s->cirrus_blt_dstaddr; | |
761 | - switch (s->cirrus_blt_pixelwidth) { | |
762 | - case 1: | |
763 | - cirrus_fill_8(s, dst, s->cirrus_blt_dstpitch, | |
764 | - s->cirrus_blt_width, s->cirrus_blt_height); | |
765 | - break; | |
766 | - case 2: | |
767 | - cirrus_fill_16(s, dst, s->cirrus_blt_dstpitch, | |
768 | - s->cirrus_blt_width, s->cirrus_blt_height); | |
769 | - break; | |
770 | - case 3: | |
771 | - cirrus_fill_24(s, dst, s->cirrus_blt_dstpitch, | |
772 | - s->cirrus_blt_width, s->cirrus_blt_height); | |
773 | - break; | |
774 | - default: | |
775 | - case 4: | |
776 | - cirrus_fill_32(s, dst, s->cirrus_blt_dstpitch, | |
777 | - s->cirrus_blt_width, s->cirrus_blt_height); | |
778 | - break; | |
779 | - } | |
596 | + rop_func = cirrus_fill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1]; | |
597 | + rop_func(s, s->vram_ptr + s->cirrus_blt_dstaddr, | |
598 | + s->cirrus_blt_dstpitch, | |
599 | + s->cirrus_blt_width, s->cirrus_blt_height); | |
780 | 600 | cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, |
781 | 601 | s->cirrus_blt_dstpitch, s->cirrus_blt_width, |
782 | 602 | s->cirrus_blt_height); |
... | ... | @@ -799,21 +619,7 @@ static int cirrus_bitblt_videotovideo_patterncopy(CirrusVGAState * s) |
799 | 619 | |
800 | 620 | static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s) |
801 | 621 | { |
802 | - if ((s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) != 0) { | |
803 | -#ifdef DEBUG_CIRRUS | |
804 | - printf("cirrus: CIRRUS_BLTMODE_COLOREXPAND - unimplemented\n"); | |
805 | -#endif | |
806 | - return 0; | |
807 | - } | |
808 | - if ((s->cirrus_blt_mode & (~CIRRUS_BLTMODE_BACKWARDS)) != 0) { | |
809 | -#ifdef DEBUG_CIRRUS | |
810 | - printf("cirrus: blt mode %02x - unimplemented\n", | |
811 | - s->cirrus_blt_mode); | |
812 | -#endif | |
813 | - return 0; | |
814 | - } | |
815 | - | |
816 | - (*s->cirrus_rop) (s->vram_ptr + s->cirrus_blt_dstaddr, | |
622 | + (*s->cirrus_rop) (s, s->vram_ptr + s->cirrus_blt_dstaddr, | |
817 | 623 | s->vram_ptr + s->cirrus_blt_srcaddr, |
818 | 624 | s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch, |
819 | 625 | s->cirrus_blt_width, s->cirrus_blt_height); |
... | ... | @@ -829,130 +635,38 @@ static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s) |
829 | 635 | * |
830 | 636 | ***************************************/ |
831 | 637 | |
832 | -static void cirrus_bitblt_cputovideo_patterncopy(void *opaque) | |
833 | -{ | |
834 | - CirrusVGAState *s = (CirrusVGAState *) opaque; | |
835 | - int data_count; | |
836 | - | |
837 | - data_count = s->cirrus_srcptr - &s->cirrus_bltbuf[0]; | |
838 | - | |
839 | - if (data_count > 0) { | |
840 | - if (data_count != s->cirrus_srccounter) { | |
841 | -#ifdef DEBUG_CIRRUS | |
842 | - printf("cirrus: internal error\n"); | |
843 | -#endif | |
844 | - } else { | |
845 | - cirrus_bitblt_common_patterncopy(s, &s->cirrus_bltbuf[0]); | |
846 | - } | |
847 | - cirrus_bitblt_reset(s); | |
848 | - } | |
849 | -} | |
850 | - | |
851 | -static void cirrus_bitblt_cputovideo_copy(void *opaque) | |
852 | -{ | |
853 | - CirrusVGAState *s = (CirrusVGAState *) opaque; | |
854 | - int data_count; | |
855 | - int data_avail; | |
856 | - uint8_t work_colorexp[256]; | |
857 | - uint8_t *src_ptr = NULL; | |
858 | - int src_avail = 0; | |
859 | - int src_processing; | |
860 | - int src_linepad = 0; | |
861 | - | |
862 | - if (s->cirrus_blt_height <= 0) { | |
863 | - s->cirrus_srcptr = s->cirrus_srcptr_end; | |
864 | - return; | |
865 | - } | |
866 | - | |
867 | - s->cirrus_srcptr = &s->cirrus_bltbuf[0]; | |
868 | - while (1) { | |
869 | - /* get BLT source. */ | |
870 | - if (src_avail <= 0) { | |
871 | - data_count = s->cirrus_srcptr_end - s->cirrus_srcptr; | |
872 | - if (data_count <= 0) | |
873 | - break; | |
874 | - | |
875 | - if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) { | |
876 | - if (s->cirrus_blt_mode & ~CIRRUS_BLTMODE_COLOREXPAND) { | |
877 | -#ifdef DEBUG_CIRRUS | |
878 | - printf("cirrus: unsupported\n"); | |
879 | -#endif | |
880 | - cirrus_bitblt_reset(s); | |
881 | - return; | |
882 | - } | |
883 | - data_avail = qemu_MIN(data_count, 256 / 32); | |
884 | - cirrus_colorexpand(s, work_colorexp, s->cirrus_srcptr, | |
885 | - data_avail * 8); | |
886 | - src_ptr = &work_colorexp[0]; | |
887 | - src_avail = data_avail * 8 * s->cirrus_blt_pixelwidth; | |
888 | - s->cirrus_srcptr += data_avail; | |
889 | - src_linepad = | |
890 | - ((s->cirrus_blt_width + 7) / 8) * 8 - | |
891 | - s->cirrus_blt_width; | |
892 | - src_linepad *= s->cirrus_blt_pixelwidth; | |
893 | - } else { | |
894 | - if (s->cirrus_blt_mode != 0) { | |
895 | -#ifdef DEBUG_CIRRUS | |
896 | - printf("cirrus: unsupported\n"); | |
897 | -#endif | |
898 | - cirrus_bitblt_reset(s); | |
899 | - return; | |
900 | - } | |
901 | - src_ptr = s->cirrus_srcptr; | |
902 | - src_avail = | |
903 | - data_count / s->cirrus_blt_pixelwidth * | |
904 | - s->cirrus_blt_pixelwidth; | |
905 | - s->cirrus_srcptr += src_avail; | |
906 | - } | |
907 | - if (src_avail <= 0) | |
908 | - break; | |
909 | - } | |
910 | - | |
911 | - /* 1-line BLT */ | |
912 | - src_processing = | |
913 | - s->cirrus_blt_srcpitch - s->cirrus_blt_horz_counter; | |
914 | - src_processing = qemu_MIN(src_avail, src_processing); | |
915 | - (*s->cirrus_rop) (s->vram_ptr + s->cirrus_blt_dstaddr, | |
916 | - src_ptr, 0, 0, src_processing, 1); | |
917 | - cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, 0, | |
918 | - src_processing, 1); | |
919 | - | |
920 | - s->cirrus_blt_dstaddr += src_processing; | |
921 | - src_ptr += src_processing; | |
922 | - src_avail -= src_processing; | |
923 | - s->cirrus_blt_horz_counter += src_processing; | |
924 | - if (s->cirrus_blt_horz_counter >= s->cirrus_blt_srcpitch) { | |
925 | - src_ptr += src_linepad; | |
926 | - src_avail -= src_linepad; | |
927 | - s->cirrus_blt_dstaddr += | |
928 | - s->cirrus_blt_dstpitch - s->cirrus_blt_srcpitch; | |
929 | - s->cirrus_blt_horz_counter = 0; | |
930 | - s->cirrus_blt_height--; | |
931 | - if (s->cirrus_blt_height <= 0) { | |
932 | - s->cirrus_srcptr = s->cirrus_srcptr_end; | |
933 | - return; | |
934 | - } | |
935 | - } | |
936 | - } | |
937 | -} | |
938 | - | |
939 | 638 | static void cirrus_bitblt_cputovideo_next(CirrusVGAState * s) |
940 | 639 | { |
941 | 640 | int copy_count; |
942 | - int avail_count; | |
943 | - | |
944 | - s->cirrus_blt_handler(s); | |
945 | - | |
641 | + uint8_t *end_ptr; | |
642 | + | |
946 | 643 | if (s->cirrus_srccounter > 0) { |
947 | - s->cirrus_srccounter -= s->cirrus_srcptr - &s->cirrus_bltbuf[0]; | |
948 | - copy_count = s->cirrus_srcptr_end - s->cirrus_srcptr; | |
949 | - memmove(&s->cirrus_bltbuf[0], s->cirrus_srcptr, copy_count); | |
950 | - avail_count = qemu_MIN(CIRRUS_BLTBUFSIZE, s->cirrus_srccounter); | |
951 | - s->cirrus_srcptr = &s->cirrus_bltbuf[0]; | |
952 | - s->cirrus_srcptr_end = s->cirrus_srcptr + avail_count; | |
953 | - if (s->cirrus_srccounter <= 0) { | |
954 | - cirrus_bitblt_reset(s); | |
955 | - } | |
644 | + if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) { | |
645 | + cirrus_bitblt_common_patterncopy(s, s->cirrus_bltbuf); | |
646 | + the_end: | |
647 | + s->cirrus_srccounter = 0; | |
648 | + cirrus_bitblt_reset(s); | |
649 | + } else { | |
650 | + /* at least one scan line */ | |
651 | + do { | |
652 | + (*s->cirrus_rop)(s, s->vram_ptr + s->cirrus_blt_dstaddr, | |
653 | + s->cirrus_bltbuf, 0, 0, s->cirrus_blt_width, 1); | |
654 | + cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, 0, | |
655 | + s->cirrus_blt_width, 1); | |
656 | + s->cirrus_blt_dstaddr += s->cirrus_blt_dstpitch; | |
657 | + s->cirrus_srccounter -= s->cirrus_blt_srcpitch; | |
658 | + if (s->cirrus_srccounter <= 0) | |
659 | + goto the_end; | |
660 | + /* more bytes than needed can be transfered because of | |
661 | + word alignment, so we keep them for the next line */ | |
662 | + /* XXX: keep alignment to speed up transfer */ | |
663 | + end_ptr = s->cirrus_bltbuf + s->cirrus_blt_srcpitch; | |
664 | + copy_count = s->cirrus_srcptr_end - end_ptr; | |
665 | + memmove(s->cirrus_bltbuf, end_ptr, copy_count); | |
666 | + s->cirrus_srcptr = s->cirrus_bltbuf + copy_count; | |
667 | + s->cirrus_srcptr_end = s->cirrus_bltbuf + s->cirrus_blt_srcpitch; | |
668 | + } while (s->cirrus_srcptr >= s->cirrus_srcptr_end); | |
669 | + } | |
956 | 670 | } |
957 | 671 | } |
958 | 672 | |
... | ... | @@ -972,49 +686,44 @@ static void cirrus_bitblt_reset(CirrusVGAState * s) |
972 | 686 | s->cirrus_dstptr = &s->cirrus_bltbuf[0]; |
973 | 687 | s->cirrus_dstptr_end = &s->cirrus_bltbuf[0]; |
974 | 688 | s->cirrus_dstcounter = 0; |
975 | - s->cirrus_blt_handler = NULL; | |
976 | 689 | } |
977 | 690 | |
978 | 691 | static int cirrus_bitblt_cputovideo(CirrusVGAState * s) |
979 | 692 | { |
693 | + int w; | |
694 | + | |
980 | 695 | s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_MEMSYSSRC; |
981 | 696 | s->cirrus_srcptr = &s->cirrus_bltbuf[0]; |
982 | 697 | s->cirrus_srcptr_end = &s->cirrus_bltbuf[0]; |
983 | 698 | |
984 | 699 | if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) { |
985 | 700 | if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) { |
986 | - s->cirrus_srccounter = 8; | |
701 | + s->cirrus_blt_srcpitch = 8; | |
987 | 702 | } else { |
988 | - s->cirrus_srccounter = 8 * 8 * s->cirrus_blt_pixelwidth; | |
703 | + s->cirrus_blt_srcpitch = 8 * 8 * s->cirrus_blt_pixelwidth; | |
989 | 704 | } |
990 | - s->cirrus_blt_srcpitch = 0; | |
991 | - s->cirrus_blt_handler = cirrus_bitblt_cputovideo_patterncopy; | |
705 | + s->cirrus_srccounter = s->cirrus_blt_srcpitch; | |
992 | 706 | } else { |
993 | 707 | if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) { |
994 | - s->cirrus_srccounter = | |
995 | - ((s->cirrus_blt_width + 7) / 8) * s->cirrus_blt_height; | |
996 | - s->cirrus_blt_srcpitch = | |
997 | - s->cirrus_blt_width * s->cirrus_blt_pixelwidth; | |
708 | + w = s->cirrus_blt_width / s->cirrus_blt_pixelwidth; | |
709 | + if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_DWORDGRANULARITY) | |
710 | + s->cirrus_blt_srcpitch = ((w + 31) >> 5); | |
711 | + else | |
712 | + s->cirrus_blt_srcpitch = ((w + 7) >> 3); | |
998 | 713 | } else { |
999 | - s->cirrus_srccounter = | |
1000 | - s->cirrus_blt_width * s->cirrus_blt_height; | |
1001 | 714 | s->cirrus_blt_srcpitch = s->cirrus_blt_width; |
1002 | 715 | } |
1003 | - /* 4-byte alignment */ | |
1004 | - s->cirrus_srccounter = (s->cirrus_srccounter + 3) & (~3); | |
1005 | - | |
1006 | - s->cirrus_blt_handler = cirrus_bitblt_cputovideo_copy; | |
1007 | - s->cirrus_blt_horz_counter = 0; | |
716 | + s->cirrus_srccounter = s->cirrus_blt_srcpitch * s->cirrus_blt_height; | |
1008 | 717 | } |
1009 | - | |
1010 | - cirrus_bitblt_cputovideo_next(s); | |
718 | + s->cirrus_srcptr = s->cirrus_bltbuf; | |
719 | + s->cirrus_srcptr_end = s->cirrus_bltbuf + s->cirrus_blt_srcpitch; | |
1011 | 720 | return 1; |
1012 | 721 | } |
1013 | 722 | |
1014 | 723 | static int cirrus_bitblt_videotocpu(CirrusVGAState * s) |
1015 | 724 | { |
1016 | 725 | /* XXX */ |
1017 | -#ifdef DEBUG_CIRRUS | |
726 | +#ifdef DEBUG_BITBLT | |
1018 | 727 | printf("cirrus: bitblt (video to cpu) is not implemented yet\n"); |
1019 | 728 | #endif |
1020 | 729 | return 0; |
... | ... | @@ -1029,7 +738,6 @@ static int cirrus_bitblt_videotovideo(CirrusVGAState * s) |
1029 | 738 | } else { |
1030 | 739 | ret = cirrus_bitblt_videotovideo_copy(s); |
1031 | 740 | } |
1032 | - | |
1033 | 741 | if (ret) |
1034 | 742 | cirrus_bitblt_reset(s); |
1035 | 743 | return ret; |
... | ... | @@ -1039,6 +747,8 @@ static void cirrus_bitblt_start(CirrusVGAState * s) |
1039 | 747 | { |
1040 | 748 | uint8_t blt_rop; |
1041 | 749 | |
750 | + s->gr[0x31] |= CIRRUS_BLT_BUSY; | |
751 | + | |
1042 | 752 | s->cirrus_blt_width = (s->gr[0x20] | (s->gr[0x21] << 8)) + 1; |
1043 | 753 | s->cirrus_blt_height = (s->gr[0x22] | (s->gr[0x23] << 8)) + 1; |
1044 | 754 | s->cirrus_blt_dstpitch = (s->gr[0x24] | (s->gr[0x25] << 8)); |
... | ... | @@ -1048,19 +758,21 @@ static void cirrus_bitblt_start(CirrusVGAState * s) |
1048 | 758 | s->cirrus_blt_srcaddr = |
1049 | 759 | (s->gr[0x2c] | (s->gr[0x2d] << 8) | (s->gr[0x2e] << 16)); |
1050 | 760 | s->cirrus_blt_mode = s->gr[0x30]; |
761 | + s->cirrus_blt_modeext = s->gr[0x33]; | |
1051 | 762 | blt_rop = s->gr[0x32]; |
1052 | 763 | |
1053 | 764 | #ifdef DEBUG_BITBLT |
1054 | - printf("rop=%02x mode=%02x modeext=%02x w=%d h=%d dpitch=%d spicth=%d daddr=%08x saddr=%08x\n", | |
765 | + printf("rop=0x%02x mode=0x%02x modeext=0x%02x w=%d h=%d dpitch=%d spicth=%d daddr=0x%08x saddr=0x%08x writemask=0x%02x\n", | |
1055 | 766 | blt_rop, |
1056 | 767 | s->cirrus_blt_mode, |
1057 | - s->gr[0x33], | |
768 | + s->cirrus_blt_modeext, | |
1058 | 769 | s->cirrus_blt_width, |
1059 | 770 | s->cirrus_blt_height, |
1060 | 771 | s->cirrus_blt_dstpitch, |
1061 | 772 | s->cirrus_blt_srcpitch, |
1062 | 773 | s->cirrus_blt_dstaddr, |
1063 | - s->cirrus_blt_srcaddr); | |
774 | + s->cirrus_blt_srcaddr, | |
775 | + s->sr[0x2f]); | |
1064 | 776 | #endif |
1065 | 777 | |
1066 | 778 | switch (s->cirrus_blt_mode & CIRRUS_BLTMODE_PIXELWIDTHMASK) { |
... | ... | @@ -1077,7 +789,7 @@ static void cirrus_bitblt_start(CirrusVGAState * s) |
1077 | 789 | s->cirrus_blt_pixelwidth = 4; |
1078 | 790 | break; |
1079 | 791 | default: |
1080 | -#ifdef DEBUG_CIRRUS | |
792 | +#ifdef DEBUG_BITBLT | |
1081 | 793 | printf("cirrus: bitblt - pixel width is unknown\n"); |
1082 | 794 | #endif |
1083 | 795 | goto bitblt_ignore; |
... | ... | @@ -1088,26 +800,41 @@ static void cirrus_bitblt_start(CirrusVGAState * s) |
1088 | 800 | cirrus_blt_mode & (CIRRUS_BLTMODE_MEMSYSSRC | |
1089 | 801 | CIRRUS_BLTMODE_MEMSYSDEST)) |
1090 | 802 | == (CIRRUS_BLTMODE_MEMSYSSRC | CIRRUS_BLTMODE_MEMSYSDEST)) { |
1091 | -#ifdef DEBUG_CIRRUS | |
803 | +#ifdef DEBUG_BITBLT | |
1092 | 804 | printf("cirrus: bitblt - memory-to-memory copy is requested\n"); |
1093 | 805 | #endif |
1094 | 806 | goto bitblt_ignore; |
1095 | 807 | } |
1096 | 808 | |
1097 | - if ((s->gr[0x33] & CIRRUS_BLTMODEEXT_SOLIDFILL) && | |
809 | + if ((s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_SOLIDFILL) && | |
1098 | 810 | (s->cirrus_blt_mode & (CIRRUS_BLTMODE_MEMSYSDEST | |
1099 | 811 | CIRRUS_BLTMODE_TRANSPARENTCOMP | |
1100 | 812 | CIRRUS_BLTMODE_PATTERNCOPY | |
1101 | 813 | CIRRUS_BLTMODE_COLOREXPAND)) == |
1102 | 814 | (CIRRUS_BLTMODE_PATTERNCOPY | CIRRUS_BLTMODE_COLOREXPAND)) { |
1103 | - cirrus_bitblt_solidfill(s); | |
815 | + cirrus_bitblt_fgcol(s); | |
816 | + cirrus_bitblt_solidfill(s, blt_rop); | |
1104 | 817 | } else { |
1105 | - if (s->cirrus_blt_mode & CIRRUS_BLTMODE_BACKWARDS) { | |
1106 | - s->cirrus_blt_dstpitch = -s->cirrus_blt_dstpitch; | |
1107 | - s->cirrus_blt_srcpitch = -s->cirrus_blt_srcpitch; | |
1108 | - s->cirrus_rop = cirrus_get_bkwd_rop_handler(blt_rop); | |
818 | + if ((s->cirrus_blt_mode & (CIRRUS_BLTMODE_COLOREXPAND | | |
819 | + CIRRUS_BLTMODE_PATTERNCOPY)) == | |
820 | + CIRRUS_BLTMODE_COLOREXPAND) { | |
821 | + | |
822 | + if (s->cirrus_blt_mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) { | |
823 | + cirrus_bitblt_fgcol(s); | |
824 | + s->cirrus_rop = cirrus_colorexpand_transp[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1]; | |
825 | + } else { | |
826 | + cirrus_bitblt_fgcol(s); | |
827 | + cirrus_bitblt_bgcol(s); | |
828 | + s->cirrus_rop = cirrus_colorexpand[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1]; | |
829 | + } | |
1109 | 830 | } else { |
1110 | - s->cirrus_rop = cirrus_get_fwd_rop_handler(blt_rop); | |
831 | + if (s->cirrus_blt_mode & CIRRUS_BLTMODE_BACKWARDS) { | |
832 | + s->cirrus_blt_dstpitch = -s->cirrus_blt_dstpitch; | |
833 | + s->cirrus_blt_srcpitch = -s->cirrus_blt_srcpitch; | |
834 | + s->cirrus_rop = cirrus_bkwd_rop[rop_to_index[blt_rop]]; | |
835 | + } else { | |
836 | + s->cirrus_rop = cirrus_fwd_rop[rop_to_index[blt_rop]]; | |
837 | + } | |
1111 | 838 | } |
1112 | 839 | |
1113 | 840 | // setup bitblt engine. |
... | ... | @@ -1139,7 +866,6 @@ static void cirrus_write_bitblt(CirrusVGAState * s, unsigned reg_value) |
1139 | 866 | cirrus_bitblt_reset(s); |
1140 | 867 | } else if (((old_value & CIRRUS_BLT_START) == 0) && |
1141 | 868 | ((reg_value & CIRRUS_BLT_START) != 0)) { |
1142 | - s->gr[0x31] |= CIRRUS_BLT_BUSY; | |
1143 | 869 | cirrus_bitblt_start(s); |
1144 | 870 | } |
1145 | 871 | } |
... | ... | @@ -1312,6 +1038,7 @@ cirrus_hook_read_sr(CirrusVGAState * s, unsigned reg_index, int *reg_value) |
1312 | 1038 | case 0x91: |
1313 | 1039 | case 0xb1: |
1314 | 1040 | case 0xd1: |
1041 | + case 0xf1: // Graphics Cursor Y | |
1315 | 1042 | *reg_value = s->sr[0x11]; |
1316 | 1043 | break; |
1317 | 1044 | case 0x05: // ??? |
... | ... | @@ -1324,7 +1051,6 @@ cirrus_hook_read_sr(CirrusVGAState * s, unsigned reg_index, int *reg_value) |
1324 | 1051 | case 0x0d: // VCLK 2 |
1325 | 1052 | case 0x0e: // VCLK 3 |
1326 | 1053 | case 0x0f: // DRAM Control |
1327 | - case 0xf1: // Graphics Cursor Y | |
1328 | 1054 | case 0x12: // Graphics Cursor Attribute |
1329 | 1055 | case 0x13: // Graphics Cursor Pattern Address |
1330 | 1056 | case 0x14: // Scratch Register 2 |
... | ... | @@ -1382,7 +1108,7 @@ cirrus_hook_write_sr(CirrusVGAState * s, unsigned reg_index, int reg_value) |
1382 | 1108 | case 0xd0: |
1383 | 1109 | case 0xf0: // Graphics Cursor X |
1384 | 1110 | s->sr[0x10] = reg_value; |
1385 | - s->cirrus_hw_cursor_x = ((reg_index << 3) & 0x700) | reg_value; | |
1111 | + s->hw_cursor_x = (reg_value << 3) | (reg_index >> 5); | |
1386 | 1112 | break; |
1387 | 1113 | case 0x11: |
1388 | 1114 | case 0x31: |
... | ... | @@ -1393,7 +1119,7 @@ cirrus_hook_write_sr(CirrusVGAState * s, unsigned reg_index, int reg_value) |
1393 | 1119 | case 0xd1: |
1394 | 1120 | case 0xf1: // Graphics Cursor Y |
1395 | 1121 | s->sr[0x11] = reg_value; |
1396 | - s->cirrus_hw_cursor_y = ((reg_index << 3) & 0x700) | reg_value; | |
1122 | + s->hw_cursor_y = (reg_value << 3) | (reg_index >> 5); | |
1397 | 1123 | break; |
1398 | 1124 | case 0x07: // Extended Sequencer Mode |
1399 | 1125 | case 0x08: // EEPROM Control |
... | ... | @@ -1471,13 +1197,9 @@ static int cirrus_hook_read_palette(CirrusVGAState * s, int *reg_value) |
1471 | 1197 | { |
1472 | 1198 | if (!(s->sr[0x12] & CIRRUS_CURSOR_HIDDENPEL)) |
1473 | 1199 | return CIRRUS_HOOK_NOT_HANDLED; |
1474 | - if (s->dac_read_index < 0x10) { | |
1475 | - *reg_value = | |
1476 | - s->cirrus_hidden_palette[s->dac_read_index * 3 + | |
1477 | - s->dac_sub_index]; | |
1478 | - } else { | |
1479 | - *reg_value = 0xff; /* XXX */ | |
1480 | - } | |
1200 | + *reg_value = | |
1201 | + s->cirrus_hidden_palette[(s->dac_read_index & 0x0f) * 3 + | |
1202 | + s->dac_sub_index]; | |
1481 | 1203 | if (++s->dac_sub_index == 3) { |
1482 | 1204 | s->dac_sub_index = 0; |
1483 | 1205 | s->dac_read_index++; |
... | ... | @@ -1491,11 +1213,9 @@ static int cirrus_hook_write_palette(CirrusVGAState * s, int reg_value) |
1491 | 1213 | return CIRRUS_HOOK_NOT_HANDLED; |
1492 | 1214 | s->dac_cache[s->dac_sub_index] = reg_value; |
1493 | 1215 | if (++s->dac_sub_index == 3) { |
1494 | - if (s->dac_read_index < 0x10) { | |
1495 | - memcpy(&s->cirrus_hidden_palette[s->dac_write_index * 3], | |
1496 | - s->dac_cache, 3); | |
1497 | - /* XXX update cursor */ | |
1498 | - } | |
1216 | + memcpy(&s->cirrus_hidden_palette[(s->dac_write_index & 0x0f) * 3], | |
1217 | + s->dac_cache, 3); | |
1218 | + /* XXX update cursor */ | |
1499 | 1219 | s->dac_sub_index = 0; |
1500 | 1220 | s->dac_write_index++; |
1501 | 1221 | } |
... | ... | @@ -1545,6 +1265,9 @@ cirrus_hook_read_gr(CirrusVGAState * s, unsigned reg_index, int *reg_value) |
1545 | 1265 | static int |
1546 | 1266 | cirrus_hook_write_gr(CirrusVGAState * s, unsigned reg_index, int reg_value) |
1547 | 1267 | { |
1268 | +#if defined(DEBUG_BITBLT) && 0 | |
1269 | + printf("gr%02x: %02x\n", reg_index, reg_value); | |
1270 | +#endif | |
1548 | 1271 | switch (reg_index) { |
1549 | 1272 | case 0x00: // Standard VGA, BGCOLOR 0x000000ff |
1550 | 1273 | s->cirrus_shadow_gr0 = reg_value; |
... | ... | @@ -1583,6 +1306,7 @@ cirrus_hook_write_gr(CirrusVGAState * s, unsigned reg_index, int reg_value) |
1583 | 1306 | case 0x29: // BLT DEST ADDR 0x00ff00 |
1584 | 1307 | case 0x2c: // BLT SRC ADDR 0x0000ff |
1585 | 1308 | case 0x2d: // BLT SRC ADDR 0x00ff00 |
1309 | + case 0x2f: // BLT WRITEMASK | |
1586 | 1310 | case 0x30: // BLT MODE |
1587 | 1311 | case 0x32: // RASTER OP |
1588 | 1312 | case 0x33: // BLT MODEEXT |
... | ... | @@ -1599,6 +1323,12 @@ cirrus_hook_write_gr(CirrusVGAState * s, unsigned reg_index, int reg_value) |
1599 | 1323 | s->gr[reg_index] = reg_value & 0x1f; |
1600 | 1324 | break; |
1601 | 1325 | case 0x2a: // BLT DEST ADDR 0x3f0000 |
1326 | + s->gr[reg_index] = reg_value & 0x3f; | |
1327 | + /* if auto start mode, starts bit blt now */ | |
1328 | + if (s->gr[0x31] & CIRRUS_BLT_AUTOSTART) { | |
1329 | + cirrus_bitblt_start(s); | |
1330 | + } | |
1331 | + break; | |
1602 | 1332 | case 0x2e: // BLT SRC ADDR 0x3f0000 |
1603 | 1333 | s->gr[reg_index] = reg_value & 0x3f; |
1604 | 1334 | break; |
... | ... | @@ -2111,7 +1841,7 @@ static void cirrus_vga_mem_writeb(void *opaque, target_phys_addr_t addr, |
2111 | 1841 | if (s->cirrus_srcptr != s->cirrus_srcptr_end) { |
2112 | 1842 | /* bitblt */ |
2113 | 1843 | *s->cirrus_srcptr++ = (uint8_t) mem_value; |
2114 | - if (s->cirrus_srcptr == s->cirrus_srcptr_end) { | |
1844 | + if (s->cirrus_srcptr >= s->cirrus_srcptr_end) { | |
2115 | 1845 | cirrus_bitblt_cputovideo_next(s); |
2116 | 1846 | } |
2117 | 1847 | } else { |
... | ... | @@ -2196,6 +1926,176 @@ static CPUWriteMemoryFunc *cirrus_vga_mem_write[3] = { |
2196 | 1926 | |
2197 | 1927 | /*************************************** |
2198 | 1928 | * |
1929 | + * hardware cursor | |
1930 | + * | |
1931 | + ***************************************/ | |
1932 | + | |
1933 | +static inline void invalidate_cursor1(CirrusVGAState *s) | |
1934 | +{ | |
1935 | + if (s->last_hw_cursor_size) { | |
1936 | + vga_invalidate_scanlines((VGAState *)s, | |
1937 | + s->last_hw_cursor_y + s->last_hw_cursor_y_start, | |
1938 | + s->last_hw_cursor_y + s->last_hw_cursor_y_end); | |
1939 | + } | |
1940 | +} | |
1941 | + | |
1942 | +static inline void cirrus_cursor_compute_yrange(CirrusVGAState *s) | |
1943 | +{ | |
1944 | + const uint8_t *src; | |
1945 | + uint32_t content; | |
1946 | + int y, y_min, y_max; | |
1947 | + | |
1948 | + src = s->vram_ptr + 0x200000 - 16 * 1024; | |
1949 | + if (s->sr[0x12] & CIRRUS_CURSOR_LARGE) { | |
1950 | + src += (s->sr[0x13] & 0x3c) * 256; | |
1951 | + y_min = 64; | |
1952 | + y_max = -1; | |
1953 | + for(y = 0; y < 64; y++) { | |
1954 | + content = ((uint32_t *)src)[0] | | |
1955 | + ((uint32_t *)src)[1] | | |
1956 | + ((uint32_t *)src)[2] | | |
1957 | + ((uint32_t *)src)[3]; | |
1958 | + if (content) { | |
1959 | + if (y < y_min) | |
1960 | + y_min = y; | |
1961 | + if (y > y_max) | |
1962 | + y_max = y; | |
1963 | + } | |
1964 | + src += 16; | |
1965 | + } | |
1966 | + } else { | |
1967 | + src += (s->sr[0x13] & 0x3f) * 256; | |
1968 | + y_min = 32; | |
1969 | + y_max = -1; | |
1970 | + for(y = 0; y < 32; y++) { | |
1971 | + content = ((uint32_t *)src)[0] | | |
1972 | + ((uint32_t *)(src + 128))[0]; | |
1973 | + if (content) { | |
1974 | + if (y < y_min) | |
1975 | + y_min = y; | |
1976 | + if (y > y_max) | |
1977 | + y_max = y; | |
1978 | + } | |
1979 | + src += 4; | |
1980 | + } | |
1981 | + } | |
1982 | + if (y_min > y_max) { | |
1983 | + s->last_hw_cursor_y_start = 0; | |
1984 | + s->last_hw_cursor_y_end = 0; | |
1985 | + } else { | |
1986 | + s->last_hw_cursor_y_start = y_min; | |
1987 | + s->last_hw_cursor_y_end = y_max + 1; | |
1988 | + } | |
1989 | +} | |
1990 | + | |
1991 | +/* NOTE: we do not currently handle the cursor bitmap change, so we | |
1992 | + update the cursor only if it moves. */ | |
1993 | +static void cirrus_cursor_invalidate(VGAState *s1) | |
1994 | +{ | |
1995 | + CirrusVGAState *s = (CirrusVGAState *)s1; | |
1996 | + int size; | |
1997 | + | |
1998 | + if (!s->sr[0x12] & CIRRUS_CURSOR_SHOW) { | |
1999 | + size = 0; | |
2000 | + } else { | |
2001 | + if (s->sr[0x12] & CIRRUS_CURSOR_LARGE) | |
2002 | + size = 64; | |
2003 | + else | |
2004 | + size = 32; | |
2005 | + } | |
2006 | + /* invalidate last cursor and new cursor if any change */ | |
2007 | + if (s->last_hw_cursor_size != size || | |
2008 | + s->last_hw_cursor_x != s->hw_cursor_x || | |
2009 | + s->last_hw_cursor_y != s->hw_cursor_y) { | |
2010 | + | |
2011 | + invalidate_cursor1(s); | |
2012 | + | |
2013 | + s->last_hw_cursor_size = size; | |
2014 | + s->last_hw_cursor_x = s->hw_cursor_x; | |
2015 | + s->last_hw_cursor_y = s->hw_cursor_y; | |
2016 | + /* compute the real cursor min and max y */ | |
2017 | + cirrus_cursor_compute_yrange(s); | |
2018 | + invalidate_cursor1(s); | |
2019 | + } | |
2020 | +} | |
2021 | + | |
2022 | +static void cirrus_cursor_draw_line(VGAState *s1, uint8_t *d1, int scr_y) | |
2023 | +{ | |
2024 | + CirrusVGAState *s = (CirrusVGAState *)s1; | |
2025 | + int w, h, bpp, x1, x2, poffset; | |
2026 | + unsigned int color0, color1; | |
2027 | + const uint8_t *palette, *src; | |
2028 | + uint32_t content; | |
2029 | + | |
2030 | + if (!(s->sr[0x12] & CIRRUS_CURSOR_SHOW)) | |
2031 | + return; | |
2032 | + /* fast test to see if the cursor intersects with the scan line */ | |
2033 | + if (s->sr[0x12] & CIRRUS_CURSOR_LARGE) { | |
2034 | + h = 64; | |
2035 | + } else { | |
2036 | + h = 32; | |
2037 | + } | |
2038 | + if (scr_y < s->hw_cursor_y || | |
2039 | + scr_y >= (s->hw_cursor_y + h)) | |
2040 | + return; | |
2041 | + | |
2042 | + src = s->vram_ptr + 0x200000 - 16 * 1024; | |
2043 | + if (s->sr[0x12] & CIRRUS_CURSOR_LARGE) { | |
2044 | + src += (s->sr[0x13] & 0x3c) * 256; | |
2045 | + src += (scr_y - s->hw_cursor_y) * 16; | |
2046 | + poffset = 8; | |
2047 | + content = ((uint32_t *)src)[0] | | |
2048 | + ((uint32_t *)src)[1] | | |
2049 | + ((uint32_t *)src)[2] | | |
2050 | + ((uint32_t *)src)[3]; | |
2051 | + } else { | |
2052 | + src += (s->sr[0x13] & 0x3f) * 256; | |
2053 | + src += (scr_y - s->hw_cursor_y) * 4; | |
2054 | + poffset = 128; | |
2055 | + content = ((uint32_t *)src)[0] | | |
2056 | + ((uint32_t *)(src + 128))[0]; | |
2057 | + } | |
2058 | + /* if nothing to draw, no need to continue */ | |
2059 | + if (!content) | |
2060 | + return; | |
2061 | + w = h; | |
2062 | + | |
2063 | + x1 = s->hw_cursor_x; | |
2064 | + if (x1 >= s->last_scr_width) | |
2065 | + return; | |
2066 | + x2 = s->hw_cursor_x + w; | |
2067 | + if (x2 > s->last_scr_width) | |
2068 | + x2 = s->last_scr_width; | |
2069 | + w = x2 - x1; | |
2070 | + palette = s->cirrus_hidden_palette; | |
2071 | + color0 = s->rgb_to_pixel(c6_to_8(palette[0x0 * 3]), | |
2072 | + c6_to_8(palette[0x0 * 3 + 1]), | |
2073 | + c6_to_8(palette[0x0 * 3 + 2])); | |
2074 | + color1 = s->rgb_to_pixel(c6_to_8(palette[0xf * 3]), | |
2075 | + c6_to_8(palette[0xf * 3 + 1]), | |
2076 | + c6_to_8(palette[0xf * 3 + 2])); | |
2077 | + bpp = ((s->ds->depth + 7) >> 3); | |
2078 | + d1 += x1 * bpp; | |
2079 | + switch(s->ds->depth) { | |
2080 | + default: | |
2081 | + break; | |
2082 | + case 8: | |
2083 | + vga_draw_cursor_line_8(d1, src, poffset, w, color0, color1, 0xff); | |
2084 | + break; | |
2085 | + case 15: | |
2086 | + vga_draw_cursor_line_16(d1, src, poffset, w, color0, color1, 0x7fff); | |
2087 | + break; | |
2088 | + case 16: | |
2089 | + vga_draw_cursor_line_16(d1, src, poffset, w, color0, color1, 0xffff); | |
2090 | + break; | |
2091 | + case 32: | |
2092 | + vga_draw_cursor_line_32(d1, src, poffset, w, color0, color1, 0xffffff); | |
2093 | + break; | |
2094 | + } | |
2095 | +} | |
2096 | + | |
2097 | +/*************************************** | |
2098 | + * | |
2199 | 2099 | * LFB memory access |
2200 | 2100 | * |
2201 | 2101 | ***************************************/ |
... | ... | @@ -2272,7 +2172,7 @@ static void cirrus_linear_writeb(void *opaque, target_phys_addr_t addr, |
2272 | 2172 | } else if (s->cirrus_srcptr != s->cirrus_srcptr_end) { |
2273 | 2173 | /* bitblt */ |
2274 | 2174 | *s->cirrus_srcptr++ = (uint8_t) val; |
2275 | - if (s->cirrus_srcptr == s->cirrus_srcptr_end) { | |
2175 | + if (s->cirrus_srcptr >= s->cirrus_srcptr_end) { | |
2276 | 2176 | cirrus_bitblt_cputovideo_next(s); |
2277 | 2177 | } |
2278 | 2178 | } else { |
... | ... | @@ -2339,6 +2239,107 @@ static CPUWriteMemoryFunc *cirrus_linear_write[3] = { |
2339 | 2239 | cirrus_linear_writel, |
2340 | 2240 | }; |
2341 | 2241 | |
2242 | +/*************************************** | |
2243 | + * | |
2244 | + * system to screen memory access | |
2245 | + * | |
2246 | + ***************************************/ | |
2247 | + | |
2248 | + | |
2249 | +static uint32_t cirrus_linear_bitblt_readb(void *opaque, target_phys_addr_t addr) | |
2250 | +{ | |
2251 | + uint32_t ret; | |
2252 | + | |
2253 | + /* XXX handle bitblt */ | |
2254 | + ret = 0xff; | |
2255 | + return ret; | |
2256 | +} | |
2257 | + | |
2258 | +static uint32_t cirrus_linear_bitblt_readw(void *opaque, target_phys_addr_t addr) | |
2259 | +{ | |
2260 | + uint32_t v; | |
2261 | +#ifdef TARGET_WORDS_BIGENDIAN | |
2262 | + v = cirrus_linear_bitblt_readb(opaque, addr) << 8; | |
2263 | + v |= cirrus_linear_bitblt_readb(opaque, addr + 1); | |
2264 | +#else | |
2265 | + v = cirrus_linear_bitblt_readb(opaque, addr); | |
2266 | + v |= cirrus_linear_bitblt_readb(opaque, addr + 1) << 8; | |
2267 | +#endif | |
2268 | + return v; | |
2269 | +} | |
2270 | + | |
2271 | +static uint32_t cirrus_linear_bitblt_readl(void *opaque, target_phys_addr_t addr) | |
2272 | +{ | |
2273 | + uint32_t v; | |
2274 | +#ifdef TARGET_WORDS_BIGENDIAN | |
2275 | + v = cirrus_linear_bitblt_readb(opaque, addr) << 24; | |
2276 | + v |= cirrus_linear_bitblt_readb(opaque, addr + 1) << 16; | |
2277 | + v |= cirrus_linear_bitblt_readb(opaque, addr + 2) << 8; | |
2278 | + v |= cirrus_linear_bitblt_readb(opaque, addr + 3); | |
2279 | +#else | |
2280 | + v = cirrus_linear_bitblt_readb(opaque, addr); | |
2281 | + v |= cirrus_linear_bitblt_readb(opaque, addr + 1) << 8; | |
2282 | + v |= cirrus_linear_bitblt_readb(opaque, addr + 2) << 16; | |
2283 | + v |= cirrus_linear_bitblt_readb(opaque, addr + 3) << 24; | |
2284 | +#endif | |
2285 | + return v; | |
2286 | +} | |
2287 | + | |
2288 | +static void cirrus_linear_bitblt_writeb(void *opaque, target_phys_addr_t addr, | |
2289 | + uint32_t val) | |
2290 | +{ | |
2291 | + CirrusVGAState *s = (CirrusVGAState *) opaque; | |
2292 | + | |
2293 | + if (s->cirrus_srcptr != s->cirrus_srcptr_end) { | |
2294 | + /* bitblt */ | |
2295 | + *s->cirrus_srcptr++ = (uint8_t) val; | |
2296 | + if (s->cirrus_srcptr >= s->cirrus_srcptr_end) { | |
2297 | + cirrus_bitblt_cputovideo_next(s); | |
2298 | + } | |
2299 | + } | |
2300 | +} | |
2301 | + | |
2302 | +static void cirrus_linear_bitblt_writew(void *opaque, target_phys_addr_t addr, | |
2303 | + uint32_t val) | |
2304 | +{ | |
2305 | +#ifdef TARGET_WORDS_BIGENDIAN | |
2306 | + cirrus_linear_bitblt_writeb(opaque, addr, (val >> 8) & 0xff); | |
2307 | + cirrus_linear_bitblt_writeb(opaque, addr + 1, val & 0xff); | |
2308 | +#else | |
2309 | + cirrus_linear_bitblt_writeb(opaque, addr, val & 0xff); | |
2310 | + cirrus_linear_bitblt_writeb(opaque, addr + 1, (val >> 8) & 0xff); | |
2311 | +#endif | |
2312 | +} | |
2313 | + | |
2314 | +static void cirrus_linear_bitblt_writel(void *opaque, target_phys_addr_t addr, | |
2315 | + uint32_t val) | |
2316 | +{ | |
2317 | +#ifdef TARGET_WORDS_BIGENDIAN | |
2318 | + cirrus_linear_bitblt_writeb(opaque, addr, (val >> 24) & 0xff); | |
2319 | + cirrus_linear_bitblt_writeb(opaque, addr + 1, (val >> 16) & 0xff); | |
2320 | + cirrus_linear_bitblt_writeb(opaque, addr + 2, (val >> 8) & 0xff); | |
2321 | + cirrus_linear_bitblt_writeb(opaque, addr + 3, val & 0xff); | |
2322 | +#else | |
2323 | + cirrus_linear_bitblt_writeb(opaque, addr, val & 0xff); | |
2324 | + cirrus_linear_bitblt_writeb(opaque, addr + 1, (val >> 8) & 0xff); | |
2325 | + cirrus_linear_bitblt_writeb(opaque, addr + 2, (val >> 16) & 0xff); | |
2326 | + cirrus_linear_bitblt_writeb(opaque, addr + 3, (val >> 24) & 0xff); | |
2327 | +#endif | |
2328 | +} | |
2329 | + | |
2330 | + | |
2331 | +static CPUReadMemoryFunc *cirrus_linear_bitblt_read[3] = { | |
2332 | + cirrus_linear_bitblt_readb, | |
2333 | + cirrus_linear_bitblt_readw, | |
2334 | + cirrus_linear_bitblt_readl, | |
2335 | +}; | |
2336 | + | |
2337 | +static CPUWriteMemoryFunc *cirrus_linear_bitblt_write[3] = { | |
2338 | + cirrus_linear_bitblt_writeb, | |
2339 | + cirrus_linear_bitblt_writew, | |
2340 | + cirrus_linear_bitblt_writel, | |
2341 | +}; | |
2342 | + | |
2342 | 2343 | /* I/O ports */ |
2343 | 2344 | |
2344 | 2345 | static uint32_t vga_ioport_read(void *opaque, uint32_t addr) |
... | ... | @@ -2691,7 +2692,30 @@ static CPUWriteMemoryFunc *cirrus_mmio_write[3] = { |
2691 | 2692 | |
2692 | 2693 | static void cirrus_init_common(CirrusVGAState * s, int device_id) |
2693 | 2694 | { |
2694 | - int vga_io_memory; | |
2695 | + int vga_io_memory, i; | |
2696 | + static int inited; | |
2697 | + | |
2698 | + if (!inited) { | |
2699 | + inited = 1; | |
2700 | + for(i = 0;i < 256; i++) | |
2701 | + rop_to_index[i] = CIRRUS_ROP_NOP_INDEX; /* nop rop */ | |
2702 | + rop_to_index[CIRRUS_ROP_0] = 0; | |
2703 | + rop_to_index[CIRRUS_ROP_SRC_AND_DST] = 1; | |
2704 | + rop_to_index[CIRRUS_ROP_NOP] = 2; | |
2705 | + rop_to_index[CIRRUS_ROP_SRC_AND_NOTDST] = 3; | |
2706 | + rop_to_index[CIRRUS_ROP_NOTDST] = 4; | |
2707 | + rop_to_index[CIRRUS_ROP_SRC] = 5; | |
2708 | + rop_to_index[CIRRUS_ROP_1] = 6; | |
2709 | + rop_to_index[CIRRUS_ROP_NOTSRC_AND_DST] = 7; | |
2710 | + rop_to_index[CIRRUS_ROP_SRC_XOR_DST] = 8; | |
2711 | + rop_to_index[CIRRUS_ROP_SRC_OR_DST] = 9; | |
2712 | + rop_to_index[CIRRUS_ROP_NOTSRC_OR_NOTDST] = 10; | |
2713 | + rop_to_index[CIRRUS_ROP_SRC_NOTXOR_DST] = 11; | |
2714 | + rop_to_index[CIRRUS_ROP_SRC_OR_NOTDST] = 12; | |
2715 | + rop_to_index[CIRRUS_ROP_NOTSRC] = 13; | |
2716 | + rop_to_index[CIRRUS_ROP_NOTSRC_OR_DST] = 14; | |
2717 | + rop_to_index[CIRRUS_ROP_NOTSRC_AND_NOTDST] = 15; | |
2718 | + } | |
2695 | 2719 | |
2696 | 2720 | register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s); |
2697 | 2721 | |
... | ... | @@ -2725,6 +2749,11 @@ static void cirrus_init_common(CirrusVGAState * s, int device_id) |
2725 | 2749 | s->cirrus_linear_io_addr = |
2726 | 2750 | cpu_register_io_memory(0, cirrus_linear_read, cirrus_linear_write, |
2727 | 2751 | s); |
2752 | + /* I/O handler for LFB */ | |
2753 | + s->cirrus_linear_bitblt_io_addr = | |
2754 | + cpu_register_io_memory(0, cirrus_linear_bitblt_read, cirrus_linear_bitblt_write, | |
2755 | + s); | |
2756 | + | |
2728 | 2757 | /* I/O handler for memory-mapped I/O */ |
2729 | 2758 | s->cirrus_mmio_io_addr = |
2730 | 2759 | cpu_register_io_memory(0, cirrus_mmio_read, cirrus_mmio_write, s); |
... | ... | @@ -2734,6 +2763,8 @@ static void cirrus_init_common(CirrusVGAState * s, int device_id) |
2734 | 2763 | |
2735 | 2764 | s->get_bpp = cirrus_get_bpp; |
2736 | 2765 | s->get_offsets = cirrus_get_offsets; |
2766 | + s->cursor_invalidate = cirrus_cursor_invalidate; | |
2767 | + s->cursor_draw_line = cirrus_cursor_draw_line; | |
2737 | 2768 | } |
2738 | 2769 | |
2739 | 2770 | /*************************************** |
... | ... | @@ -2767,8 +2798,11 @@ static void cirrus_pci_lfb_map(PCIDevice *d, int region_num, |
2767 | 2798 | { |
2768 | 2799 | CirrusVGAState *s = &((PCICirrusVGAState *)d)->cirrus_vga; |
2769 | 2800 | |
2801 | + /* XXX: add byte swapping apertures */ | |
2770 | 2802 | cpu_register_physical_memory(addr, s->vram_size, |
2771 | 2803 | s->cirrus_linear_io_addr); |
2804 | + cpu_register_physical_memory(addr + 0x1000000, 0x400000, | |
2805 | + s->cirrus_linear_bitblt_io_addr); | |
2772 | 2806 | } |
2773 | 2807 | |
2774 | 2808 | static void cirrus_pci_mmio_map(PCIDevice *d, int region_num, |
... | ... | @@ -2815,7 +2849,7 @@ void pci_cirrus_vga_init(DisplayState *ds, uint8_t *vga_ram_base, |
2815 | 2849 | /* memory #0 LFB */ |
2816 | 2850 | /* memory #1 memory-mapped I/O */ |
2817 | 2851 | /* XXX: s->vram_size must be a power of two */ |
2818 | - pci_register_io_region((PCIDevice *)d, 0, s->vram_size, | |
2852 | + pci_register_io_region((PCIDevice *)d, 0, 0x2000000, | |
2819 | 2853 | PCI_ADDRESS_SPACE_MEM_PREFETCH, cirrus_pci_lfb_map); |
2820 | 2854 | if (device_id == CIRRUS_ID_CLGD5446) { |
2821 | 2855 | pci_register_io_region((PCIDevice *)d, 1, CIRRUS_PNPMMIO_SIZE, | ... | ... |
hw/cirrus_vga_rop.h
0 → 100644
1 | +/* | |
2 | + * QEMU Cirrus CLGD 54xx VGA Emulator. | |
3 | + * | |
4 | + * Copyright (c) 2004 Fabrice Bellard | |
5 | + * | |
6 | + * Permission is hereby granted, free of charge, to any person obtaining a copy | |
7 | + * of this software and associated documentation files (the "Software"), to deal | |
8 | + * in the Software without restriction, including without limitation the rights | |
9 | + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
10 | + * copies of the Software, and to permit persons to whom the Software is | |
11 | + * furnished to do so, subject to the following conditions: | |
12 | + * | |
13 | + * The above copyright notice and this permission notice shall be included in | |
14 | + * all copies or substantial portions of the Software. | |
15 | + * | |
16 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
17 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
18 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
19 | + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
20 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
21 | + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
22 | + * THE SOFTWARE. | |
23 | + */ | |
24 | + | |
25 | +static void | |
26 | +glue(cirrus_bitblt_rop_fwd_, ROP_NAME)(CirrusVGAState *s, | |
27 | + uint8_t *dst,const uint8_t *src, | |
28 | + int dstpitch,int srcpitch, | |
29 | + int bltwidth,int bltheight) | |
30 | +{ | |
31 | + int x,y; | |
32 | + dstpitch -= bltwidth; | |
33 | + srcpitch -= bltwidth; | |
34 | + for (y = 0; y < bltheight; y++) { | |
35 | + for (x = 0; x < bltwidth; x++) { | |
36 | + ROP_OP(*dst, *src); | |
37 | + dst++; | |
38 | + src++; | |
39 | + } | |
40 | + dst += dstpitch; | |
41 | + src += srcpitch; | |
42 | + } | |
43 | +} | |
44 | + | |
45 | +static void | |
46 | +glue(cirrus_bitblt_rop_bkwd_, ROP_NAME)(CirrusVGAState *s, | |
47 | + uint8_t *dst,const uint8_t *src, | |
48 | + int dstpitch,int srcpitch, | |
49 | + int bltwidth,int bltheight) | |
50 | +{ | |
51 | + int x,y; | |
52 | + dstpitch += bltwidth; | |
53 | + srcpitch += bltwidth; | |
54 | + for (y = 0; y < bltheight; y++) { | |
55 | + for (x = 0; x < bltwidth; x++) { | |
56 | + ROP_OP(*dst, *src); | |
57 | + dst--; | |
58 | + src--; | |
59 | + } | |
60 | + dst += dstpitch; | |
61 | + src += srcpitch; | |
62 | + } | |
63 | +} | |
64 | + | |
65 | +#define DEPTH 8 | |
66 | +#include "cirrus_vga_rop2.h" | |
67 | + | |
68 | +#define DEPTH 16 | |
69 | +#include "cirrus_vga_rop2.h" | |
70 | + | |
71 | +#define DEPTH 24 | |
72 | +#include "cirrus_vga_rop2.h" | |
73 | + | |
74 | +#define DEPTH 32 | |
75 | +#include "cirrus_vga_rop2.h" | |
76 | + | |
77 | +#undef ROP_NAME | |
78 | +#undef ROP_OP | ... | ... |
hw/cirrus_vga_rop2.h
0 → 100644
1 | +/* | |
2 | + * QEMU Cirrus CLGD 54xx VGA Emulator. | |
3 | + * | |
4 | + * Copyright (c) 2004 Fabrice Bellard | |
5 | + * | |
6 | + * Permission is hereby granted, free of charge, to any person obtaining a copy | |
7 | + * of this software and associated documentation files (the "Software"), to deal | |
8 | + * in the Software without restriction, including without limitation the rights | |
9 | + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
10 | + * copies of the Software, and to permit persons to whom the Software is | |
11 | + * furnished to do so, subject to the following conditions: | |
12 | + * | |
13 | + * The above copyright notice and this permission notice shall be included in | |
14 | + * all copies or substantial portions of the Software. | |
15 | + * | |
16 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
17 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
18 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
19 | + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
20 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
21 | + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
22 | + * THE SOFTWARE. | |
23 | + */ | |
24 | + | |
25 | +#if DEPTH == 8 | |
26 | +#define PUTPIXEL() ROP_OP(d[0], col) | |
27 | +#elif DEPTH == 16 | |
28 | +#define PUTPIXEL() ROP_OP(((uint16_t *)d)[0], col); | |
29 | +#elif DEPTH == 24 | |
30 | +#define PUTPIXEL() ROP_OP(d[0], col); \ | |
31 | + ROP_OP(d[1], (col >> 8)); \ | |
32 | + ROP_OP(d[2], (col >> 16)) | |
33 | +#elif DEPTH == 32 | |
34 | +#define PUTPIXEL() ROP_OP(((uint32_t *)d)[0], col) | |
35 | +#else | |
36 | +#error unsupported DEPTH | |
37 | +#endif | |
38 | + | |
39 | +static void | |
40 | +glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH) | |
41 | + (CirrusVGAState * s, uint8_t * dst, | |
42 | + const uint8_t * src1, | |
43 | + int dstpitch, int srcpitch, | |
44 | + int bltwidth, int bltheight) | |
45 | +{ | |
46 | + const uint8_t *src; | |
47 | + uint8_t *d; | |
48 | + int x, y; | |
49 | + unsigned bits; | |
50 | + unsigned int col; | |
51 | + unsigned bitmask; | |
52 | + unsigned index; | |
53 | + int srcskipleft = 0; | |
54 | + | |
55 | + col = s->cirrus_blt_fgcol; | |
56 | + for(y = 0; y < bltheight; y++) { | |
57 | + src = src1; | |
58 | + bitmask = 0x80 >> srcskipleft; | |
59 | + bits = *src++; | |
60 | + d = dst; | |
61 | + for (x = 0; x < bltwidth; x += (DEPTH / 8)) { | |
62 | + if ((bitmask & 0xff) == 0) { | |
63 | + bitmask = 0x80; | |
64 | + bits = *src++; | |
65 | + } | |
66 | + index = (bits & bitmask); | |
67 | + if (index) { | |
68 | + PUTPIXEL(); | |
69 | + } | |
70 | + d += (DEPTH / 8); | |
71 | + bitmask >>= 1; | |
72 | + } | |
73 | + src1 += srcpitch; | |
74 | + dst += dstpitch; | |
75 | + } | |
76 | +} | |
77 | + | |
78 | +static void | |
79 | +glue(glue(glue(cirrus_colorexpand_, ROP_NAME), _),DEPTH) | |
80 | + (CirrusVGAState * s, uint8_t * dst, | |
81 | + const uint8_t * src1, | |
82 | + int dstpitch, int srcpitch, | |
83 | + int bltwidth, int bltheight) | |
84 | +{ | |
85 | + const uint8_t *src; | |
86 | + uint32_t colors[2]; | |
87 | + uint8_t *d; | |
88 | + int x, y; | |
89 | + unsigned bits; | |
90 | + unsigned int col; | |
91 | + unsigned bitmask; | |
92 | + int srcskipleft = 0; | |
93 | + | |
94 | + colors[0] = s->cirrus_blt_bgcol; | |
95 | + colors[1] = s->cirrus_blt_fgcol; | |
96 | + for(y = 0; y < bltheight; y++) { | |
97 | + src = src1; | |
98 | + bitmask = 0x80 >> srcskipleft; | |
99 | + bits = *src++; | |
100 | + d = dst; | |
101 | + for (x = 0; x < bltwidth; x += (DEPTH / 8)) { | |
102 | + if ((bitmask & 0xff) == 0) { | |
103 | + bitmask = 0x80; | |
104 | + bits = *src++; | |
105 | + } | |
106 | + col = colors[!!(bits & bitmask)]; | |
107 | + PUTPIXEL(); | |
108 | + d += (DEPTH / 8); | |
109 | + bitmask >>= 1; | |
110 | + } | |
111 | + src1 += srcpitch; | |
112 | + dst += dstpitch; | |
113 | + } | |
114 | +} | |
115 | + | |
116 | +static void | |
117 | +glue(glue(glue(cirrus_fill_, ROP_NAME), _),DEPTH) | |
118 | + (CirrusVGAState *s, | |
119 | + uint8_t *dst, int dst_pitch, | |
120 | + int width, int height) | |
121 | +{ | |
122 | + uint8_t *d, *d1; | |
123 | + uint32_t col; | |
124 | + int x, y; | |
125 | + | |
126 | + col = s->cirrus_blt_fgcol; | |
127 | + | |
128 | + d1 = dst; | |
129 | + for(y = 0; y < height; y++) { | |
130 | + d = d1; | |
131 | + for(x = 0; x < width; x += (DEPTH / 8)) { | |
132 | + PUTPIXEL(); | |
133 | + d += (DEPTH / 8); | |
134 | + } | |
135 | + d1 += dst_pitch; | |
136 | + } | |
137 | +} | |
138 | + | |
139 | +#undef DEPTH | |
140 | +#undef PUTPIXEL | ... | ... |