Revision a5082316 hw/cirrus_vga.c
b/hw/cirrus_vga.c | ||
---|---|---|
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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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); |
Also available in: Unified diff