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,6 +29,14 @@ | ||
29 | #include "vl.h" | 29 | #include "vl.h" |
30 | #include "vga_int.h" | 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 | //#define DEBUG_CIRRUS | 40 | //#define DEBUG_CIRRUS |
33 | //#define DEBUG_BITBLT | 41 | //#define DEBUG_BITBLT |
34 | 42 | ||
@@ -103,6 +111,7 @@ | @@ -103,6 +111,7 @@ | ||
103 | #define CIRRUS_BLT_START 0x02 | 111 | #define CIRRUS_BLT_START 0x02 |
104 | #define CIRRUS_BLT_RESET 0x04 | 112 | #define CIRRUS_BLT_RESET 0x04 |
105 | #define CIRRUS_BLT_FIFOUSED 0x10 | 113 | #define CIRRUS_BLT_FIFOUSED 0x10 |
114 | +#define CIRRUS_BLT_AUTOSTART 0x80 | ||
106 | 115 | ||
107 | // control 0x32 | 116 | // control 0x32 |
108 | #define CIRRUS_ROP_0 0x00 | 117 | #define CIRRUS_ROP_0 0x00 |
@@ -122,8 +131,12 @@ | @@ -122,8 +131,12 @@ | ||
122 | #define CIRRUS_ROP_NOTSRC_OR_DST 0xd6 | 131 | #define CIRRUS_ROP_NOTSRC_OR_DST 0xd6 |
123 | #define CIRRUS_ROP_NOTSRC_AND_NOTDST 0xda | 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 | // control 0x33 | 137 | // control 0x33 |
126 | -#define CIRRUS_BLTMODEEXT_SOLIDFILL 0x04 | 138 | +#define CIRRUS_BLTMODEEXT_SOLIDFILL 0x04 |
139 | +#define CIRRUS_BLTMODEEXT_DWORDGRANULARITY 0x01 | ||
127 | 140 | ||
128 | // memory-mapped IO | 141 | // memory-mapped IO |
129 | #define CIRRUS_MMIO_BLTBGCOLOR 0x00 // dword | 142 | #define CIRRUS_MMIO_BLTBGCOLOR 0x00 // dword |
@@ -204,16 +217,19 @@ | @@ -204,16 +217,19 @@ | ||
204 | #define CIRRUS_HOOK_NOT_HANDLED 0 | 217 | #define CIRRUS_HOOK_NOT_HANDLED 0 |
205 | #define CIRRUS_HOOK_HANDLED 1 | 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 | int dstpitch, int srcpitch, | 223 | int dstpitch, int srcpitch, |
209 | int bltwidth, int bltheight); | 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 | typedef struct CirrusVGAState { | 228 | typedef struct CirrusVGAState { |
214 | VGA_STATE_COMMON | 229 | VGA_STATE_COMMON |
215 | 230 | ||
216 | int cirrus_linear_io_addr; | 231 | int cirrus_linear_io_addr; |
232 | + int cirrus_linear_bitblt_io_addr; | ||
217 | int cirrus_mmio_io_addr; | 233 | int cirrus_mmio_io_addr; |
218 | uint32_t cirrus_addr_mask; | 234 | uint32_t cirrus_addr_mask; |
219 | uint8_t cirrus_shadow_gr0; | 235 | uint8_t cirrus_shadow_gr0; |
@@ -223,18 +239,21 @@ typedef struct CirrusVGAState { | @@ -223,18 +239,21 @@ typedef struct CirrusVGAState { | ||
223 | uint32_t cirrus_bank_base[2]; | 239 | uint32_t cirrus_bank_base[2]; |
224 | uint32_t cirrus_bank_limit[2]; | 240 | uint32_t cirrus_bank_limit[2]; |
225 | uint8_t cirrus_hidden_palette[48]; | 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 | int cirrus_blt_pixelwidth; | 244 | int cirrus_blt_pixelwidth; |
229 | int cirrus_blt_width; | 245 | int cirrus_blt_width; |
230 | int cirrus_blt_height; | 246 | int cirrus_blt_height; |
231 | int cirrus_blt_dstpitch; | 247 | int cirrus_blt_dstpitch; |
232 | int cirrus_blt_srcpitch; | 248 | int cirrus_blt_srcpitch; |
249 | + uint32_t cirrus_blt_fgcol; | ||
250 | + uint32_t cirrus_blt_bgcol; | ||
233 | uint32_t cirrus_blt_dstaddr; | 251 | uint32_t cirrus_blt_dstaddr; |
234 | uint32_t cirrus_blt_srcaddr; | 252 | uint32_t cirrus_blt_srcaddr; |
235 | uint8_t cirrus_blt_mode; | 253 | uint8_t cirrus_blt_mode; |
254 | + uint8_t cirrus_blt_modeext; | ||
236 | cirrus_bitblt_rop_t cirrus_rop; | 255 | cirrus_bitblt_rop_t cirrus_rop; |
237 | -#define CIRRUS_BLTBUFSIZE 256 | 256 | +#define CIRRUS_BLTBUFSIZE (2048 * 4) /* one line width */ |
238 | uint8_t cirrus_bltbuf[CIRRUS_BLTBUFSIZE]; | 257 | uint8_t cirrus_bltbuf[CIRRUS_BLTBUFSIZE]; |
239 | uint8_t *cirrus_srcptr; | 258 | uint8_t *cirrus_srcptr; |
240 | uint8_t *cirrus_srcptr_end; | 259 | uint8_t *cirrus_srcptr_end; |
@@ -242,8 +261,12 @@ typedef struct CirrusVGAState { | @@ -242,8 +261,12 @@ typedef struct CirrusVGAState { | ||
242 | uint8_t *cirrus_dstptr; | 261 | uint8_t *cirrus_dstptr; |
243 | uint8_t *cirrus_dstptr_end; | 262 | uint8_t *cirrus_dstptr_end; |
244 | uint32_t cirrus_dstcounter; | 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 | } CirrusVGAState; | 270 | } CirrusVGAState; |
248 | 271 | ||
249 | typedef struct PCICirrusVGAState { | 272 | typedef struct PCICirrusVGAState { |
@@ -251,6 +274,8 @@ typedef struct PCICirrusVGAState { | @@ -251,6 +274,8 @@ typedef struct PCICirrusVGAState { | ||
251 | CirrusVGAState cirrus_vga; | 274 | CirrusVGAState cirrus_vga; |
252 | } PCICirrusVGAState; | 275 | } PCICirrusVGAState; |
253 | 276 | ||
277 | +static uint8_t rop_to_index[256]; | ||
278 | + | ||
254 | /*************************************** | 279 | /*************************************** |
255 | * | 280 | * |
256 | * prototypes. | 281 | * prototypes. |
@@ -266,343 +291,233 @@ static void cirrus_bitblt_reset(CirrusVGAState * s); | @@ -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 | switch (s->cirrus_blt_pixelwidth) { | 503 | switch (s->cirrus_blt_pixelwidth) { |
588 | case 1: | 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 | case 2: | 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 | case 3: | 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 | default: | 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,8 +541,6 @@ static void cirrus_invalidate_region(CirrusVGAState * s, int off_begin, | ||
626 | } | 541 | } |
627 | } | 542 | } |
628 | 543 | ||
629 | - | ||
630 | - | ||
631 | static int cirrus_bitblt_common_patterncopy(CirrusVGAState * s, | 544 | static int cirrus_bitblt_common_patterncopy(CirrusVGAState * s, |
632 | const uint8_t * src) | 545 | const uint8_t * src) |
633 | { | 546 | { |
@@ -639,12 +552,16 @@ static int cirrus_bitblt_common_patterncopy(CirrusVGAState * s, | @@ -639,12 +552,16 @@ static int cirrus_bitblt_common_patterncopy(CirrusVGAState * s, | ||
639 | int patternbytes = s->cirrus_blt_pixelwidth * 8; | 552 | int patternbytes = s->cirrus_blt_pixelwidth * 8; |
640 | 553 | ||
641 | if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) { | 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 | src = work_colorexp; | 560 | src = work_colorexp; |
644 | s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_COLOREXPAND; | 561 | s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_COLOREXPAND; |
645 | } | 562 | } |
646 | if (s->cirrus_blt_mode & ~CIRRUS_BLTMODE_PATTERNCOPY) { | 563 | if (s->cirrus_blt_mode & ~CIRRUS_BLTMODE_PATTERNCOPY) { |
647 | -#ifdef DEBUG_CIRRUS | 564 | +#ifdef DEBUG_BITBLT |
648 | printf("cirrus: blt mode %02x (pattercopy) - unimplemented\n", | 565 | printf("cirrus: blt mode %02x (pattercopy) - unimplemented\n", |
649 | s->cirrus_blt_mode); | 566 | s->cirrus_blt_mode); |
650 | #endif | 567 | #endif |
@@ -657,7 +574,7 @@ static int cirrus_bitblt_common_patterncopy(CirrusVGAState * s, | @@ -657,7 +574,7 @@ static int cirrus_bitblt_common_patterncopy(CirrusVGAState * s, | ||
657 | tileheight = qemu_MIN(8, s->cirrus_blt_height - y); | 574 | tileheight = qemu_MIN(8, s->cirrus_blt_height - y); |
658 | for (x = 0; x < s->cirrus_blt_width; x += patternbytes) { | 575 | for (x = 0; x < s->cirrus_blt_width; x += patternbytes) { |
659 | tilewidth = qemu_MIN(patternbytes, s->cirrus_blt_width - x); | 576 | tilewidth = qemu_MIN(patternbytes, s->cirrus_blt_width - x); |
660 | - (*s->cirrus_rop) (dstc, src, | 577 | + (*s->cirrus_rop) (s, dstc, src, |
661 | s->cirrus_blt_dstpitch, patternbytes, | 578 | s->cirrus_blt_dstpitch, patternbytes, |
662 | tilewidth, tileheight); | 579 | tilewidth, tileheight); |
663 | dstc += patternbytes; | 580 | dstc += patternbytes; |
@@ -672,111 +589,14 @@ static int cirrus_bitblt_common_patterncopy(CirrusVGAState * s, | @@ -672,111 +589,14 @@ static int cirrus_bitblt_common_patterncopy(CirrusVGAState * s, | ||
672 | 589 | ||
673 | /* fill */ | 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 | cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, | 600 | cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, |
781 | s->cirrus_blt_dstpitch, s->cirrus_blt_width, | 601 | s->cirrus_blt_dstpitch, s->cirrus_blt_width, |
782 | s->cirrus_blt_height); | 602 | s->cirrus_blt_height); |
@@ -799,21 +619,7 @@ static int cirrus_bitblt_videotovideo_patterncopy(CirrusVGAState * s) | @@ -799,21 +619,7 @@ static int cirrus_bitblt_videotovideo_patterncopy(CirrusVGAState * s) | ||
799 | 619 | ||
800 | static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s) | 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 | s->vram_ptr + s->cirrus_blt_srcaddr, | 623 | s->vram_ptr + s->cirrus_blt_srcaddr, |
818 | s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch, | 624 | s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch, |
819 | s->cirrus_blt_width, s->cirrus_blt_height); | 625 | s->cirrus_blt_width, s->cirrus_blt_height); |
@@ -829,130 +635,38 @@ static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s) | @@ -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 | static void cirrus_bitblt_cputovideo_next(CirrusVGAState * s) | 638 | static void cirrus_bitblt_cputovideo_next(CirrusVGAState * s) |
940 | { | 639 | { |
941 | int copy_count; | 640 | int copy_count; |
942 | - int avail_count; | ||
943 | - | ||
944 | - s->cirrus_blt_handler(s); | ||
945 | - | 641 | + uint8_t *end_ptr; |
642 | + | ||
946 | if (s->cirrus_srccounter > 0) { | 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,49 +686,44 @@ static void cirrus_bitblt_reset(CirrusVGAState * s) | ||
972 | s->cirrus_dstptr = &s->cirrus_bltbuf[0]; | 686 | s->cirrus_dstptr = &s->cirrus_bltbuf[0]; |
973 | s->cirrus_dstptr_end = &s->cirrus_bltbuf[0]; | 687 | s->cirrus_dstptr_end = &s->cirrus_bltbuf[0]; |
974 | s->cirrus_dstcounter = 0; | 688 | s->cirrus_dstcounter = 0; |
975 | - s->cirrus_blt_handler = NULL; | ||
976 | } | 689 | } |
977 | 690 | ||
978 | static int cirrus_bitblt_cputovideo(CirrusVGAState * s) | 691 | static int cirrus_bitblt_cputovideo(CirrusVGAState * s) |
979 | { | 692 | { |
693 | + int w; | ||
694 | + | ||
980 | s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_MEMSYSSRC; | 695 | s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_MEMSYSSRC; |
981 | s->cirrus_srcptr = &s->cirrus_bltbuf[0]; | 696 | s->cirrus_srcptr = &s->cirrus_bltbuf[0]; |
982 | s->cirrus_srcptr_end = &s->cirrus_bltbuf[0]; | 697 | s->cirrus_srcptr_end = &s->cirrus_bltbuf[0]; |
983 | 698 | ||
984 | if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) { | 699 | if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) { |
985 | if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) { | 700 | if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) { |
986 | - s->cirrus_srccounter = 8; | 701 | + s->cirrus_blt_srcpitch = 8; |
987 | } else { | 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 | } else { | 706 | } else { |
993 | if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) { | 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 | } else { | 713 | } else { |
999 | - s->cirrus_srccounter = | ||
1000 | - s->cirrus_blt_width * s->cirrus_blt_height; | ||
1001 | s->cirrus_blt_srcpitch = s->cirrus_blt_width; | 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 | return 1; | 720 | return 1; |
1012 | } | 721 | } |
1013 | 722 | ||
1014 | static int cirrus_bitblt_videotocpu(CirrusVGAState * s) | 723 | static int cirrus_bitblt_videotocpu(CirrusVGAState * s) |
1015 | { | 724 | { |
1016 | /* XXX */ | 725 | /* XXX */ |
1017 | -#ifdef DEBUG_CIRRUS | 726 | +#ifdef DEBUG_BITBLT |
1018 | printf("cirrus: bitblt (video to cpu) is not implemented yet\n"); | 727 | printf("cirrus: bitblt (video to cpu) is not implemented yet\n"); |
1019 | #endif | 728 | #endif |
1020 | return 0; | 729 | return 0; |
@@ -1029,7 +738,6 @@ static int cirrus_bitblt_videotovideo(CirrusVGAState * s) | @@ -1029,7 +738,6 @@ static int cirrus_bitblt_videotovideo(CirrusVGAState * s) | ||
1029 | } else { | 738 | } else { |
1030 | ret = cirrus_bitblt_videotovideo_copy(s); | 739 | ret = cirrus_bitblt_videotovideo_copy(s); |
1031 | } | 740 | } |
1032 | - | ||
1033 | if (ret) | 741 | if (ret) |
1034 | cirrus_bitblt_reset(s); | 742 | cirrus_bitblt_reset(s); |
1035 | return ret; | 743 | return ret; |
@@ -1039,6 +747,8 @@ static void cirrus_bitblt_start(CirrusVGAState * s) | @@ -1039,6 +747,8 @@ static void cirrus_bitblt_start(CirrusVGAState * s) | ||
1039 | { | 747 | { |
1040 | uint8_t blt_rop; | 748 | uint8_t blt_rop; |
1041 | 749 | ||
750 | + s->gr[0x31] |= CIRRUS_BLT_BUSY; | ||
751 | + | ||
1042 | s->cirrus_blt_width = (s->gr[0x20] | (s->gr[0x21] << 8)) + 1; | 752 | s->cirrus_blt_width = (s->gr[0x20] | (s->gr[0x21] << 8)) + 1; |
1043 | s->cirrus_blt_height = (s->gr[0x22] | (s->gr[0x23] << 8)) + 1; | 753 | s->cirrus_blt_height = (s->gr[0x22] | (s->gr[0x23] << 8)) + 1; |
1044 | s->cirrus_blt_dstpitch = (s->gr[0x24] | (s->gr[0x25] << 8)); | 754 | s->cirrus_blt_dstpitch = (s->gr[0x24] | (s->gr[0x25] << 8)); |
@@ -1048,19 +758,21 @@ static void cirrus_bitblt_start(CirrusVGAState * s) | @@ -1048,19 +758,21 @@ static void cirrus_bitblt_start(CirrusVGAState * s) | ||
1048 | s->cirrus_blt_srcaddr = | 758 | s->cirrus_blt_srcaddr = |
1049 | (s->gr[0x2c] | (s->gr[0x2d] << 8) | (s->gr[0x2e] << 16)); | 759 | (s->gr[0x2c] | (s->gr[0x2d] << 8) | (s->gr[0x2e] << 16)); |
1050 | s->cirrus_blt_mode = s->gr[0x30]; | 760 | s->cirrus_blt_mode = s->gr[0x30]; |
761 | + s->cirrus_blt_modeext = s->gr[0x33]; | ||
1051 | blt_rop = s->gr[0x32]; | 762 | blt_rop = s->gr[0x32]; |
1052 | 763 | ||
1053 | #ifdef DEBUG_BITBLT | 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 | blt_rop, | 766 | blt_rop, |
1056 | s->cirrus_blt_mode, | 767 | s->cirrus_blt_mode, |
1057 | - s->gr[0x33], | 768 | + s->cirrus_blt_modeext, |
1058 | s->cirrus_blt_width, | 769 | s->cirrus_blt_width, |
1059 | s->cirrus_blt_height, | 770 | s->cirrus_blt_height, |
1060 | s->cirrus_blt_dstpitch, | 771 | s->cirrus_blt_dstpitch, |
1061 | s->cirrus_blt_srcpitch, | 772 | s->cirrus_blt_srcpitch, |
1062 | s->cirrus_blt_dstaddr, | 773 | s->cirrus_blt_dstaddr, |
1063 | - s->cirrus_blt_srcaddr); | 774 | + s->cirrus_blt_srcaddr, |
775 | + s->sr[0x2f]); | ||
1064 | #endif | 776 | #endif |
1065 | 777 | ||
1066 | switch (s->cirrus_blt_mode & CIRRUS_BLTMODE_PIXELWIDTHMASK) { | 778 | switch (s->cirrus_blt_mode & CIRRUS_BLTMODE_PIXELWIDTHMASK) { |
@@ -1077,7 +789,7 @@ static void cirrus_bitblt_start(CirrusVGAState * s) | @@ -1077,7 +789,7 @@ static void cirrus_bitblt_start(CirrusVGAState * s) | ||
1077 | s->cirrus_blt_pixelwidth = 4; | 789 | s->cirrus_blt_pixelwidth = 4; |
1078 | break; | 790 | break; |
1079 | default: | 791 | default: |
1080 | -#ifdef DEBUG_CIRRUS | 792 | +#ifdef DEBUG_BITBLT |
1081 | printf("cirrus: bitblt - pixel width is unknown\n"); | 793 | printf("cirrus: bitblt - pixel width is unknown\n"); |
1082 | #endif | 794 | #endif |
1083 | goto bitblt_ignore; | 795 | goto bitblt_ignore; |
@@ -1088,26 +800,41 @@ static void cirrus_bitblt_start(CirrusVGAState * s) | @@ -1088,26 +800,41 @@ static void cirrus_bitblt_start(CirrusVGAState * s) | ||
1088 | cirrus_blt_mode & (CIRRUS_BLTMODE_MEMSYSSRC | | 800 | cirrus_blt_mode & (CIRRUS_BLTMODE_MEMSYSSRC | |
1089 | CIRRUS_BLTMODE_MEMSYSDEST)) | 801 | CIRRUS_BLTMODE_MEMSYSDEST)) |
1090 | == (CIRRUS_BLTMODE_MEMSYSSRC | CIRRUS_BLTMODE_MEMSYSDEST)) { | 802 | == (CIRRUS_BLTMODE_MEMSYSSRC | CIRRUS_BLTMODE_MEMSYSDEST)) { |
1091 | -#ifdef DEBUG_CIRRUS | 803 | +#ifdef DEBUG_BITBLT |
1092 | printf("cirrus: bitblt - memory-to-memory copy is requested\n"); | 804 | printf("cirrus: bitblt - memory-to-memory copy is requested\n"); |
1093 | #endif | 805 | #endif |
1094 | goto bitblt_ignore; | 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 | (s->cirrus_blt_mode & (CIRRUS_BLTMODE_MEMSYSDEST | | 810 | (s->cirrus_blt_mode & (CIRRUS_BLTMODE_MEMSYSDEST | |
1099 | CIRRUS_BLTMODE_TRANSPARENTCOMP | | 811 | CIRRUS_BLTMODE_TRANSPARENTCOMP | |
1100 | CIRRUS_BLTMODE_PATTERNCOPY | | 812 | CIRRUS_BLTMODE_PATTERNCOPY | |
1101 | CIRRUS_BLTMODE_COLOREXPAND)) == | 813 | CIRRUS_BLTMODE_COLOREXPAND)) == |
1102 | (CIRRUS_BLTMODE_PATTERNCOPY | CIRRUS_BLTMODE_COLOREXPAND)) { | 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 | } else { | 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 | } else { | 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 | // setup bitblt engine. | 840 | // setup bitblt engine. |
@@ -1139,7 +866,6 @@ static void cirrus_write_bitblt(CirrusVGAState * s, unsigned reg_value) | @@ -1139,7 +866,6 @@ static void cirrus_write_bitblt(CirrusVGAState * s, unsigned reg_value) | ||
1139 | cirrus_bitblt_reset(s); | 866 | cirrus_bitblt_reset(s); |
1140 | } else if (((old_value & CIRRUS_BLT_START) == 0) && | 867 | } else if (((old_value & CIRRUS_BLT_START) == 0) && |
1141 | ((reg_value & CIRRUS_BLT_START) != 0)) { | 868 | ((reg_value & CIRRUS_BLT_START) != 0)) { |
1142 | - s->gr[0x31] |= CIRRUS_BLT_BUSY; | ||
1143 | cirrus_bitblt_start(s); | 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,6 +1038,7 @@ cirrus_hook_read_sr(CirrusVGAState * s, unsigned reg_index, int *reg_value) | ||
1312 | case 0x91: | 1038 | case 0x91: |
1313 | case 0xb1: | 1039 | case 0xb1: |
1314 | case 0xd1: | 1040 | case 0xd1: |
1041 | + case 0xf1: // Graphics Cursor Y | ||
1315 | *reg_value = s->sr[0x11]; | 1042 | *reg_value = s->sr[0x11]; |
1316 | break; | 1043 | break; |
1317 | case 0x05: // ??? | 1044 | case 0x05: // ??? |
@@ -1324,7 +1051,6 @@ cirrus_hook_read_sr(CirrusVGAState * s, unsigned reg_index, int *reg_value) | @@ -1324,7 +1051,6 @@ cirrus_hook_read_sr(CirrusVGAState * s, unsigned reg_index, int *reg_value) | ||
1324 | case 0x0d: // VCLK 2 | 1051 | case 0x0d: // VCLK 2 |
1325 | case 0x0e: // VCLK 3 | 1052 | case 0x0e: // VCLK 3 |
1326 | case 0x0f: // DRAM Control | 1053 | case 0x0f: // DRAM Control |
1327 | - case 0xf1: // Graphics Cursor Y | ||
1328 | case 0x12: // Graphics Cursor Attribute | 1054 | case 0x12: // Graphics Cursor Attribute |
1329 | case 0x13: // Graphics Cursor Pattern Address | 1055 | case 0x13: // Graphics Cursor Pattern Address |
1330 | case 0x14: // Scratch Register 2 | 1056 | case 0x14: // Scratch Register 2 |
@@ -1382,7 +1108,7 @@ cirrus_hook_write_sr(CirrusVGAState * s, unsigned reg_index, int reg_value) | @@ -1382,7 +1108,7 @@ cirrus_hook_write_sr(CirrusVGAState * s, unsigned reg_index, int reg_value) | ||
1382 | case 0xd0: | 1108 | case 0xd0: |
1383 | case 0xf0: // Graphics Cursor X | 1109 | case 0xf0: // Graphics Cursor X |
1384 | s->sr[0x10] = reg_value; | 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 | break; | 1112 | break; |
1387 | case 0x11: | 1113 | case 0x11: |
1388 | case 0x31: | 1114 | case 0x31: |
@@ -1393,7 +1119,7 @@ cirrus_hook_write_sr(CirrusVGAState * s, unsigned reg_index, int reg_value) | @@ -1393,7 +1119,7 @@ cirrus_hook_write_sr(CirrusVGAState * s, unsigned reg_index, int reg_value) | ||
1393 | case 0xd1: | 1119 | case 0xd1: |
1394 | case 0xf1: // Graphics Cursor Y | 1120 | case 0xf1: // Graphics Cursor Y |
1395 | s->sr[0x11] = reg_value; | 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 | break; | 1123 | break; |
1398 | case 0x07: // Extended Sequencer Mode | 1124 | case 0x07: // Extended Sequencer Mode |
1399 | case 0x08: // EEPROM Control | 1125 | case 0x08: // EEPROM Control |
@@ -1471,13 +1197,9 @@ static int cirrus_hook_read_palette(CirrusVGAState * s, int *reg_value) | @@ -1471,13 +1197,9 @@ static int cirrus_hook_read_palette(CirrusVGAState * s, int *reg_value) | ||
1471 | { | 1197 | { |
1472 | if (!(s->sr[0x12] & CIRRUS_CURSOR_HIDDENPEL)) | 1198 | if (!(s->sr[0x12] & CIRRUS_CURSOR_HIDDENPEL)) |
1473 | return CIRRUS_HOOK_NOT_HANDLED; | 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 | if (++s->dac_sub_index == 3) { | 1203 | if (++s->dac_sub_index == 3) { |
1482 | s->dac_sub_index = 0; | 1204 | s->dac_sub_index = 0; |
1483 | s->dac_read_index++; | 1205 | s->dac_read_index++; |
@@ -1491,11 +1213,9 @@ static int cirrus_hook_write_palette(CirrusVGAState * s, int reg_value) | @@ -1491,11 +1213,9 @@ static int cirrus_hook_write_palette(CirrusVGAState * s, int reg_value) | ||
1491 | return CIRRUS_HOOK_NOT_HANDLED; | 1213 | return CIRRUS_HOOK_NOT_HANDLED; |
1492 | s->dac_cache[s->dac_sub_index] = reg_value; | 1214 | s->dac_cache[s->dac_sub_index] = reg_value; |
1493 | if (++s->dac_sub_index == 3) { | 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 | s->dac_sub_index = 0; | 1219 | s->dac_sub_index = 0; |
1500 | s->dac_write_index++; | 1220 | s->dac_write_index++; |
1501 | } | 1221 | } |
@@ -1545,6 +1265,9 @@ cirrus_hook_read_gr(CirrusVGAState * s, unsigned reg_index, int *reg_value) | @@ -1545,6 +1265,9 @@ cirrus_hook_read_gr(CirrusVGAState * s, unsigned reg_index, int *reg_value) | ||
1545 | static int | 1265 | static int |
1546 | cirrus_hook_write_gr(CirrusVGAState * s, unsigned reg_index, int reg_value) | 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 | switch (reg_index) { | 1271 | switch (reg_index) { |
1549 | case 0x00: // Standard VGA, BGCOLOR 0x000000ff | 1272 | case 0x00: // Standard VGA, BGCOLOR 0x000000ff |
1550 | s->cirrus_shadow_gr0 = reg_value; | 1273 | s->cirrus_shadow_gr0 = reg_value; |
@@ -1583,6 +1306,7 @@ cirrus_hook_write_gr(CirrusVGAState * s, unsigned reg_index, int reg_value) | @@ -1583,6 +1306,7 @@ cirrus_hook_write_gr(CirrusVGAState * s, unsigned reg_index, int reg_value) | ||
1583 | case 0x29: // BLT DEST ADDR 0x00ff00 | 1306 | case 0x29: // BLT DEST ADDR 0x00ff00 |
1584 | case 0x2c: // BLT SRC ADDR 0x0000ff | 1307 | case 0x2c: // BLT SRC ADDR 0x0000ff |
1585 | case 0x2d: // BLT SRC ADDR 0x00ff00 | 1308 | case 0x2d: // BLT SRC ADDR 0x00ff00 |
1309 | + case 0x2f: // BLT WRITEMASK | ||
1586 | case 0x30: // BLT MODE | 1310 | case 0x30: // BLT MODE |
1587 | case 0x32: // RASTER OP | 1311 | case 0x32: // RASTER OP |
1588 | case 0x33: // BLT MODEEXT | 1312 | case 0x33: // BLT MODEEXT |
@@ -1599,6 +1323,12 @@ cirrus_hook_write_gr(CirrusVGAState * s, unsigned reg_index, int reg_value) | @@ -1599,6 +1323,12 @@ cirrus_hook_write_gr(CirrusVGAState * s, unsigned reg_index, int reg_value) | ||
1599 | s->gr[reg_index] = reg_value & 0x1f; | 1323 | s->gr[reg_index] = reg_value & 0x1f; |
1600 | break; | 1324 | break; |
1601 | case 0x2a: // BLT DEST ADDR 0x3f0000 | 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 | case 0x2e: // BLT SRC ADDR 0x3f0000 | 1332 | case 0x2e: // BLT SRC ADDR 0x3f0000 |
1603 | s->gr[reg_index] = reg_value & 0x3f; | 1333 | s->gr[reg_index] = reg_value & 0x3f; |
1604 | break; | 1334 | break; |
@@ -2111,7 +1841,7 @@ static void cirrus_vga_mem_writeb(void *opaque, target_phys_addr_t addr, | @@ -2111,7 +1841,7 @@ static void cirrus_vga_mem_writeb(void *opaque, target_phys_addr_t addr, | ||
2111 | if (s->cirrus_srcptr != s->cirrus_srcptr_end) { | 1841 | if (s->cirrus_srcptr != s->cirrus_srcptr_end) { |
2112 | /* bitblt */ | 1842 | /* bitblt */ |
2113 | *s->cirrus_srcptr++ = (uint8_t) mem_value; | 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 | cirrus_bitblt_cputovideo_next(s); | 1845 | cirrus_bitblt_cputovideo_next(s); |
2116 | } | 1846 | } |
2117 | } else { | 1847 | } else { |
@@ -2196,6 +1926,176 @@ static CPUWriteMemoryFunc *cirrus_vga_mem_write[3] = { | @@ -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 | * LFB memory access | 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,7 +2172,7 @@ static void cirrus_linear_writeb(void *opaque, target_phys_addr_t addr, | ||
2272 | } else if (s->cirrus_srcptr != s->cirrus_srcptr_end) { | 2172 | } else if (s->cirrus_srcptr != s->cirrus_srcptr_end) { |
2273 | /* bitblt */ | 2173 | /* bitblt */ |
2274 | *s->cirrus_srcptr++ = (uint8_t) val; | 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 | cirrus_bitblt_cputovideo_next(s); | 2176 | cirrus_bitblt_cputovideo_next(s); |
2277 | } | 2177 | } |
2278 | } else { | 2178 | } else { |
@@ -2339,6 +2239,107 @@ static CPUWriteMemoryFunc *cirrus_linear_write[3] = { | @@ -2339,6 +2239,107 @@ static CPUWriteMemoryFunc *cirrus_linear_write[3] = { | ||
2339 | cirrus_linear_writel, | 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 | /* I/O ports */ | 2343 | /* I/O ports */ |
2343 | 2344 | ||
2344 | static uint32_t vga_ioport_read(void *opaque, uint32_t addr) | 2345 | static uint32_t vga_ioport_read(void *opaque, uint32_t addr) |
@@ -2691,7 +2692,30 @@ static CPUWriteMemoryFunc *cirrus_mmio_write[3] = { | @@ -2691,7 +2692,30 @@ static CPUWriteMemoryFunc *cirrus_mmio_write[3] = { | ||
2691 | 2692 | ||
2692 | static void cirrus_init_common(CirrusVGAState * s, int device_id) | 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 | register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s); | 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,6 +2749,11 @@ static void cirrus_init_common(CirrusVGAState * s, int device_id) | ||
2725 | s->cirrus_linear_io_addr = | 2749 | s->cirrus_linear_io_addr = |
2726 | cpu_register_io_memory(0, cirrus_linear_read, cirrus_linear_write, | 2750 | cpu_register_io_memory(0, cirrus_linear_read, cirrus_linear_write, |
2727 | s); | 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 | /* I/O handler for memory-mapped I/O */ | 2757 | /* I/O handler for memory-mapped I/O */ |
2729 | s->cirrus_mmio_io_addr = | 2758 | s->cirrus_mmio_io_addr = |
2730 | cpu_register_io_memory(0, cirrus_mmio_read, cirrus_mmio_write, s); | 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,6 +2763,8 @@ static void cirrus_init_common(CirrusVGAState * s, int device_id) | ||
2734 | 2763 | ||
2735 | s->get_bpp = cirrus_get_bpp; | 2764 | s->get_bpp = cirrus_get_bpp; |
2736 | s->get_offsets = cirrus_get_offsets; | 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,8 +2798,11 @@ static void cirrus_pci_lfb_map(PCIDevice *d, int region_num, | ||
2767 | { | 2798 | { |
2768 | CirrusVGAState *s = &((PCICirrusVGAState *)d)->cirrus_vga; | 2799 | CirrusVGAState *s = &((PCICirrusVGAState *)d)->cirrus_vga; |
2769 | 2800 | ||
2801 | + /* XXX: add byte swapping apertures */ | ||
2770 | cpu_register_physical_memory(addr, s->vram_size, | 2802 | cpu_register_physical_memory(addr, s->vram_size, |
2771 | s->cirrus_linear_io_addr); | 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 | static void cirrus_pci_mmio_map(PCIDevice *d, int region_num, | 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,7 +2849,7 @@ void pci_cirrus_vga_init(DisplayState *ds, uint8_t *vga_ram_base, | ||
2815 | /* memory #0 LFB */ | 2849 | /* memory #0 LFB */ |
2816 | /* memory #1 memory-mapped I/O */ | 2850 | /* memory #1 memory-mapped I/O */ |
2817 | /* XXX: s->vram_size must be a power of two */ | 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 | PCI_ADDRESS_SPACE_MEM_PREFETCH, cirrus_pci_lfb_map); | 2853 | PCI_ADDRESS_SPACE_MEM_PREFETCH, cirrus_pci_lfb_map); |
2820 | if (device_id == CIRRUS_ID_CLGD5446) { | 2854 | if (device_id == CIRRUS_ID_CLGD5446) { |
2821 | pci_register_io_region((PCIDevice *)d, 1, CIRRUS_PNPMMIO_SIZE, | 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 |