2 #include <proto/exec.h>
3 #include <proto/graphics.h>
5 #include <exec/libraries.h>
6 #include <hardware/custom.h>
7 #include <hardware/intbits.h>
8 #include <hidd/graphics.h>
10 #include "amigavideogfx.h"
11 #include "amigavideobitmap.h"
15 #include <aros/debug.h>
26 static void startblitter(struct amigavideo_staticdata
*data
, UWORD w
, UWORD h
)
28 volatile struct Custom
*custom
= (struct Custom
*)0xdff000;
30 if (data
->ecs_agnus
) {
34 if (h
> 1024 || w
> 64)
36 custom
->bltsize
= (h
<< 6) | (w
& 63);
39 static const UWORD leftmask
[] = {
40 0xffff, 0x7fff, 0x3fff, 0x1fff,
41 0x0fff, 0x07ff, 0x03ff, 0x01ff,
42 0x00ff, 0x007f, 0x003f, 0x001f,
43 0x000f, 0x0007, 0x0003, 0x0001
45 static const UWORD rightmask
[] = {
46 0x8000, 0xc000, 0xe000, 0xf000,
47 0xf800, 0xfc00, 0xfe00, 0xff00,
48 0xff80, 0xffc0, 0xffe0, 0xfff0,
49 0xfff8, 0xfffc, 0xfffe, 0xffff
52 static const UBYTE copy_minterm
[] = { 0xff, 0x00, 0x00, 0xca, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff };
53 // A-DAT = edge masking
57 // 0: zero (->fillrect)
58 // 1: src AND dst /AC + ABC
59 // 2: src AND NOT dst /AC + AB/C
61 // 4: NOT src AND dst /AC + A/B/C
63 // 6: src XOR dst /AC + A
64 // 7: copy source and blit thru mask
67 // 10: NOT dst (->fillrect)
72 // 15: one (->fillrect)
74 BOOL
blit_copybox(struct amigavideo_staticdata
*data
, struct amigabm_data
*srcbm
, struct amigabm_data
*dstbm
,
75 WORD srcx
, WORD srcy
, WORD w
, WORD h
, WORD dstx
, WORD dsty
, HIDDT_DrawMode mode
)
77 volatile struct Custom
*custom
= (struct Custom
*)0xdff000;
78 struct GfxBase
*GfxBase
= (APTR
)data
->cs_GfxBase
;
79 ULONG srcoffset
, dstoffset
;
81 WORD srcwidth
, dstwidth
, width
;
87 BOOL intersect
= FALSE
;
94 if (copy_minterm
[mode
] == 0xff)
95 return blit_fillrect(data
, dstbm
, dstx
, dsty
, dstx2
, dsty
+ h
- 1, 0, mode
);
97 if (copy_minterm
[mode
] == 0)
100 D(bug("copybox(%x %x %dx%d %dx%d %dx%d %d)\n", srcbm
, dstbm
, srcx
, srcy
, dstx
, dsty
, w
, h
, mode
));
102 if (srcbm
== dstbm
) {
103 intersect
= !(srcx
> dstx2
|| srcx2
< dstx
|| srcy
> dsty
+ h
- 1 || srcy
+ h
- 1 < dsty
);
106 srcoffset
= srcbm
->bytesperrow
* srcy
+ (srcx
/ 16) * 2;
107 dstoffset
= dstbm
->bytesperrow
* dsty
+ (dstx
/ 16) * 2;
108 shift
= (dstx
& 15) - (srcx
& 15);
111 // do we need >16 bit edge mask? (not handled yet)
112 if (dstoffset
< srcoffset
&& shift
< 0) // asc + desc
114 if (dstoffset
> srcoffset
&& shift
> 0) // desc + asc
121 } else if (intersect
&& dstoffset
> srcoffset
) {
125 srcwidth
= srcx2
/ 16 - srcx
/ 16 + 1;
126 dstwidth
= dstx2
/ 16 - dstx
/ 16 + 1;
133 if (dstwidth
>= srcwidth
) {
136 shiftb
= shift
<< 12;
137 alwm
= leftmask
[dstx
];
138 afwm
= rightmask
[dstx2
];
141 shifta
= shift
<< 12;
142 shiftb
= shift
<< 12;
143 alwm
= leftmask
[srcx
];
144 afwm
= rightmask
[srcx2
];
146 srcoffset
+= srcbm
->bytesperrow
* (h
- 1) + (width
- 1) * 2;
147 dstoffset
+= dstbm
->bytesperrow
* (h
- 1) + (width
- 1) * 2;
149 if (dstwidth
>= srcwidth
) {
152 shiftb
= shift
<< 12;
153 afwm
= leftmask
[dstx
];
154 alwm
= rightmask
[dstx2
];
157 shifta
= shift
<< 12;
158 shiftb
= shift
<< 12;
159 afwm
= leftmask
[srcx
];
160 alwm
= rightmask
[srcx2
];
164 //D(bug("shift=%d rev=%d sw=%d dw=%d %04x %04x\n", shift, reverse, srcwidth, dstwidth, afwm, alwm));
169 custom
->bltafwm
= afwm
;
170 custom
->bltalwm
= alwm
;
171 custom
->bltbmod
= srcbm
->bytesperrow
- width
* 2;
172 custom
->bltcmod
= dstbm
->bytesperrow
- width
* 2;
173 custom
->bltdmod
= dstbm
->bytesperrow
- width
* 2;
174 custom
->bltcon1
= (reverse
? 0x0002 : 0x0000) | shiftb
;
175 bltcon0
= 0x0700 | copy_minterm
[mode
] | shifta
;
176 custom
->bltadat
= 0xffff;
178 for (i
= 0; i
< dstbm
->depth
; i
++) {
179 UWORD bltcon0b
= bltcon0
;
180 if (dstbm
->planes
[i
] == (UBYTE
*)0x00000000 || dstbm
->planes
[i
] == (UBYTE
*)0xffffffff)
183 if (i
>= srcbm
->depth
|| srcbm
->planes
[i
] == (UBYTE
*)0x00000000) {
185 custom
->bltbdat
= 0x0000;
186 } else if (srcbm
->planes
[i
] == (UBYTE
*)0xffffffff) {
188 custom
->bltbdat
= 0xffff;
190 custom
->bltbpt
= (APTR
)(srcbm
->planes
[i
] + srcoffset
);
192 custom
->bltcon0
= bltcon0b
;
193 custom
->bltcpt
= (APTR
)(dstbm
->planes
[i
] + dstoffset
);
194 custom
->bltdpt
= (APTR
)(dstbm
->planes
[i
] + dstoffset
);
195 startblitter(data
, width
, h
);
204 BOOL
blit_copybox_mask(struct amigavideo_staticdata
*data
, struct amigabm_data
*srcbm
, struct amigabm_data
*dstbm
,
205 WORD srcx
, WORD srcy
, WORD w
, WORD h
, WORD dstx
, WORD dsty
, HIDDT_DrawMode mode
, APTR maskplane
)
207 volatile struct Custom
*custom
= (struct Custom
*)0xdff000;
208 struct GfxBase
*GfxBase
= (APTR
)data
->cs_GfxBase
;
209 ULONG srcoffset
, dstoffset
;
211 WORD srcwidth
, dstwidth
, width
;
216 BOOL reverse
= FALSE
;
217 BOOL intersect
= FALSE
;
219 if (USE_BLITTER
== 0)
222 srcx2
= srcx
+ w
- 1;
223 dstx2
= dstx
+ w
- 1;
225 D(bug("CopyBoxMasked(%x %x %dx%d %dx%d %dx%d %d %x)\n", srcbm
, dstbm
, srcx
, srcy
, dstx
, dsty
, w
, h
, mode
, maskplane
));
227 if (srcbm
== dstbm
) {
228 intersect
= !(srcx
> dstx2
|| srcx2
< dstx
|| srcy
> dsty
+ h
- 1 || srcy
+ h
- 1 < dsty
);
231 srcoffset
= srcbm
->bytesperrow
* srcy
+ (srcx
/ 16) * 2;
232 dstoffset
= dstbm
->bytesperrow
* dsty
+ (dstx
/ 16) * 2;
233 shift
= (dstx
& 15) - (srcx
& 15);
236 // do we need >16 bit edge mask? (not handled yet)
237 if (dstoffset
< srcoffset
&& shift
< 0) // asc + desc
239 if (dstoffset
> srcoffset
&& shift
> 0) // desc + asc
246 } else if (intersect
&& dstoffset
> srcoffset
) {
250 srcwidth
= srcx2
/ 16 - srcx
/ 16 + 1;
251 dstwidth
= dstx2
/ 16 - dstx
/ 16 + 1;
257 bltshift
= shift
<< 12;
259 if (dstwidth
> srcwidth
) {
268 srcoffset
+= srcbm
->bytesperrow
* (h
- 1) + (width
- 1) * 2;
269 dstoffset
+= dstbm
->bytesperrow
* (h
- 1) + (width
- 1) * 2;
271 if (dstwidth
> srcwidth
) {
282 D(bug("shift=%d rev=%d sw=%d dw=%d sbpr=%d %04x %04x\n", shift
, reverse
, srcwidth
, dstwidth
, srcbm
->bytesperrow
, afwm
, alwm
));
287 custom
->bltafwm
= afwm
;
288 custom
->bltalwm
= alwm
;
289 custom
->bltamod
= srcbm
->bytesperrow
- width
* 2;
290 custom
->bltbmod
= srcbm
->bytesperrow
- width
* 2;
291 custom
->bltcmod
= dstbm
->bytesperrow
- width
* 2;
292 custom
->bltdmod
= dstbm
->bytesperrow
- width
* 2;
293 custom
->bltcon1
= (reverse
? 0x0002 : 0x0000) | bltshift
;
294 bltcon0
= 0x0f00 | 0x00ca | bltshift
;
296 for (i
= 0; i
< dstbm
->depth
; i
++) {
297 UWORD bltcon0b
= bltcon0
;
298 if (dstbm
->planes
[i
] == (UBYTE
*)0x00000000 || dstbm
->planes
[i
] == (UBYTE
*)0xffffffff)
301 if (i
>= srcbm
->depth
|| srcbm
->planes
[i
] == (UBYTE
*)0x00000000) {
303 custom
->bltbdat
= 0x0000;
304 } else if (srcbm
->planes
[i
] == (UBYTE
*)0xffffffff) {
306 custom
->bltbdat
= 0xffff;
308 custom
->bltbpt
= (APTR
)(srcbm
->planes
[i
] + srcoffset
);
310 custom
->bltcon0
= bltcon0b
;
311 custom
->bltapt
= (APTR
)(maskplane
+ srcoffset
);
312 custom
->bltcpt
= (APTR
)(dstbm
->planes
[i
] + dstoffset
);
313 custom
->bltdpt
= (APTR
)(dstbm
->planes
[i
] + dstoffset
);
314 startblitter(data
, width
, h
);
323 static const UBYTE fill_minterm
[] = { 0xca, 0x00, 0x00, 0xca, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x00, 0xca };
325 // copy: /AC + AB = (NABC | NANBC) | (ABNC | ABC) = 0xCA
326 // invert: /AC + A/C = (NABC | NANBC) | (ABNC | ANBNC) = 0x5A
328 // A-DAT = edge masking
329 // B-DAT = pixel value (ones or zeros, not used when invert mode)
333 BOOL
blit_fillrect(struct amigavideo_staticdata
*data
, struct amigabm_data
*bm
, WORD x1
,WORD y1
,WORD x2
,WORD y2
, HIDDT_Pixel pixel
, HIDDT_DrawMode mode
)
335 volatile struct Custom
*custom
= (struct Custom
*)0xdff000;
336 struct GfxBase
*GfxBase
= (APTR
)data
->cs_GfxBase
;
341 if (USE_BLITTER
== 0)
344 D(bug("fillrect(%dx%d,%dx%d,%d,%d)\n", x1
, y1
, x2
, y2
, pixel
, mode
));
345 D(bug("bm = %dx%dx%d bpr=%d\n", bm
->width
, bm
->height
, bm
->depth
, bm
->bytesperrow
));
347 if (fill_minterm
[mode
] == 0)
350 offset
= bm
->bytesperrow
* y1
+ (x1
/ 16) * 2;
351 width
= x2
/ 16 - x1
/ 16 + 1;
352 height
= y2
- y1
+ 1;
357 custom
->bltafwm
= leftmask
[x1
& 15];
358 custom
->bltalwm
= rightmask
[x2
& 15];
359 custom
->bltcmod
= bm
->bytesperrow
- width
* 2;
360 custom
->bltdmod
= bm
->bytesperrow
- width
* 2;
361 custom
->bltcon1
= 0x0000;
362 custom
->bltcon0
= 0x0300 | fill_minterm
[mode
];
363 custom
->bltadat
= 0xffff;
365 if (mode
== vHidd_GC_DrawMode_Clear
)
367 else if (mode
== vHidd_GC_DrawMode_Set
)
370 for (i
= 0; i
< bm
->depth
; i
++) {
371 if (bm
->planes
[i
] != (UBYTE
*)0x00000000 && bm
->planes
[i
] != (UBYTE
*)0xffffffff) {
373 custom
->bltbdat
= (pixel
& 1) ? 0xffff : 0x0000;
374 custom
->bltcpt
= (APTR
)(bm
->planes
[i
] + offset
);
375 custom
->bltdpt
= (APTR
)(bm
->planes
[i
] + offset
);
376 startblitter(data
, width
, height
);
388 struct pHidd_BitMap_PutTemplate
401 // A-DAT = edge masking
406 BOOL
blit_puttemplate(struct amigavideo_staticdata
*data
, struct amigabm_data
*bm
, struct pHidd_BitMap_PutTemplate
*tmpl
)
408 volatile struct Custom
*custom
= (struct Custom
*)0xdff000;
409 struct GfxBase
*GfxBase
= (APTR
)data
->cs_GfxBase
;
410 OOP_Object
*gc
= tmpl
->gc
;
411 HIDDT_Pixel fgpen
= GC_FG(tmpl
->gc
);
412 HIDDT_Pixel bgpen
= GC_BG(tmpl
->gc
);
416 UWORD shifta
, shiftb
;
418 ULONG srcoffset
, dstoffset
;
419 WORD width
, srcwidth
, dstwidth
;
421 WORD height
= tmpl
->height
;
424 WORD dstx2
= tmpl
->x
+ tmpl
->width
- 1;
425 WORD srcx
= tmpl
->srcx
;
426 WORD srcx2
= srcx
+ tmpl
->width
- 1;
428 if (USE_BLITTER
== 0)
431 if (GC_COLEXP(gc
) == vHidd_GC_ColExp_Transparent
)
433 else if (GC_DRMD(gc
) == vHidd_GC_DrawMode_Invert
)
437 if (tmpl
->inverttemplate
)
440 D(bug("puttemplate: %x srcx=%d x=%d y=%d w=%d h=%d type=%d fg=%d bg=%d\n",
441 tmpl
->Template
, tmpl
->srcx
, tmpl
->x
, tmpl
->y
, tmpl
->width
, tmpl
->height
, type
, fgpen
, bgpen
));
443 srcoffset
= (srcx
/ 16) * 2;
444 dstoffset
= bm
->bytesperrow
* dsty
+ (dstx
/ 16) * 2;
446 srcwidth
= srcx2
/ 16 - srcx
/ 16 + 1;
447 dstwidth
= dstx2
/ 16 - dstx
/ 16 + 1;
456 D(bug("shift=%d srcwidth=%d dstwidth=%d\n", shift
, srcwidth
, dstwidth
));
461 if (dstwidth
>= srcwidth
) {
464 shiftb
= shift
<< 12;
465 alwm
= leftmask
[dstx
];
466 afwm
= rightmask
[dstx2
];
469 shifta
= shift
<< 12;
470 shiftb
= shift
<< 12;
471 alwm
= leftmask
[srcx
];
472 afwm
= rightmask
[srcx2
];
474 srcoffset
+= tmpl
->modulo
* (height
- 1) + (width
- 1) * 2;
475 dstoffset
+= bm
->bytesperrow
* (height
- 1) + (width
- 1) * 2;
478 if (dstwidth
>= srcwidth
) {
481 shiftb
= shift
<< 12;
482 afwm
= leftmask
[dstx
];
483 alwm
= rightmask
[dstx2
];
486 shifta
= shift
<< 12;
487 shiftb
= shift
<< 12;
488 afwm
= leftmask
[srcx
];
489 alwm
= rightmask
[srcx2
];
496 custom
->bltafwm
= afwm
;
497 custom
->bltalwm
= alwm
;
498 custom
->bltbmod
= tmpl
->modulo
- width
* 2;
499 custom
->bltcmod
= bm
->bytesperrow
- width
* 2;
500 custom
->bltdmod
= bm
->bytesperrow
- width
* 2;
501 custom
->bltadat
= 0xffff;
503 for (i
= 0; i
< bm
->depth
; i
++) {
505 UWORD chmask
, shiftbv
;
513 if (bm
->planes
[i
] == (UBYTE
*)0x00000000 || bm
->planes
[i
] == (UBYTE
*)0xffffffff)
519 /* not guaranteed to be correct, last time I played with minterms
520 * was something like 20 years ago..
525 minterm
= (NABC
| NANBC
) | (fg
? ABC
| ABNC
| ANBC
: ANBC
);
527 case 1: // JAM1 | INVERSVID
528 minterm
= (NABC
| NANBC
) | (fg
? ANBC
| ANBNC
| ABC
: ABC
);
530 case 2: // COMPLEMENT:
531 minterm
= (NABC
| NANBC
) | (ANBC
| ABNC
);
533 case 3: // COMPLEMENT | INVERSVID:
534 minterm
= (NABC
| NANBC
) | (ABC
| ANBNC
);
536 case 5: // JAM2 | INVERSVID
542 minterm
= (NABC
| NANBC
) | (ABC
| ABNC
);
545 } else if (!fg
&& !bg
) {
546 minterm
= (NABC
| NANBC
);
550 minterm
= (NABC
| NANBC
) | (ABC
| ABNC
);
552 minterm
= (NABC
| NANBC
) | (ANBC
| ANBNC
);
558 custom
->bltcon0
= shifta
| chmask
| minterm
;
559 custom
->bltcon1
= (reverse
? 0x0002 : 0x0000) | shiftbv
;
560 custom
->bltbdat
= 0xffff;
561 custom
->bltbpt
= (APTR
)(tmpl
->Template
+ srcoffset
);
562 custom
->bltcpt
= (APTR
)(bm
->planes
[i
] + dstoffset
);
563 custom
->bltdpt
= (APTR
)(bm
->planes
[i
] + dstoffset
);
564 startblitter(data
, width
, height
);
573 static UBYTE
getminterm(UBYTE type
, UBYTE fg
, UBYTE bg
)
575 UBYTE minterm
= 0, tg
;
579 minterm
= (NABC
| NANBC
) | (fg
? ABC
| ABNC
| ANBC
: ANBC
);
581 case 1: // JAM1 | INVERSVID
582 minterm
= (NABC
| NANBC
) | (fg
? ANBC
| ANBNC
| ABC
: ABC
);
584 case 2: // COMPLEMENT:
585 minterm
= (NABC
| NANBC
) | (ANBC
| ABNC
);
587 case 3: // COMPLEMENT | INVERSVID:
588 minterm
= (NABC
| NANBC
) | (ABC
| ANBNC
);
590 case 5: // JAM2 | INVERSVID
596 minterm
= (NABC
| NANBC
) | (ABC
| ABNC
);
597 } else if (!fg
&& !bg
) {
598 minterm
= (NABC
| NANBC
);
600 minterm
= (NABC
| NANBC
) | (ABC
| ABNC
);
602 minterm
= (NABC
| NANBC
) | (ANBC
| ANBNC
);
609 BOOL
blit_putpattern(struct amigavideo_staticdata
*csd
, struct amigabm_data
*bm
, struct pHidd_BitMap_PutPattern
*pat
)
611 volatile struct Custom
*custom
= (struct Custom
*)0xdff000;
612 struct GfxBase
*GfxBase
= (APTR
)csd
->cs_GfxBase
;
615 UBYTE fgpen
= GC_FG(pat
->gc
);
616 UBYTE bgpen
= GC_BG(pat
->gc
);
619 UWORD shifta
, shiftb
;
625 WORD height
= pat
->height
;
628 WORD dstx2
= pat
->x
+ pat
->width
- 1;
630 WORD patternymask
= pat
->patternheight
- 1;
632 if (USE_BLITTER
== 0)
637 if (pat
->patterndepth
!= 1)
640 if (GC_COLEXP(pat
->gc
) == vHidd_GC_ColExp_Transparent
)
642 else if (GC_DRMD(pat
->gc
) == vHidd_GC_DrawMode_Invert
)
646 if (pat
->invertpattern
)
649 D(bug("PutPattern(%dx%d,%dx%d,mask=%x,mod=%d,masksrcx=%d,P=%x,%dx%d,h=%d,T=%d)\n",
650 pat
->x
, pat
->y
, pat
->width
, pat
->height
,
651 pat
->mask
, pat
->maskmodulo
, pat
->masksrcx
,
652 pat
->pattern
, pat
->patternsrcx
, pat
->patternsrcy
, pat
->patternheight
, type
));
654 dstoffset
= bm
->bytesperrow
* dsty
+ (dstx
/ 16) * 2;
655 dstwidth
= dstx2
/ 16 - dstx
/ 16 + 1;
662 afwm
= leftmask
[dstx
];
663 alwm
= rightmask
[dstx2
];
668 custom
->bltafwm
= afwm
;
669 custom
->bltalwm
= alwm
;
670 custom
->bltcmod
= (bm
->bytesperrow
- dstwidth
* 2) + bm
->bytesperrow
* (pat
->patternheight
- 1);
671 custom
->bltdmod
= (bm
->bytesperrow
- dstwidth
* 2) + bm
->bytesperrow
* (pat
->patternheight
- 1);
672 custom
->bltadat
= 0xffff;
674 for (i
= 0; i
< bm
->depth
; i
++, fgpen
>>= 1, bgpen
>>= 1) {
680 if (bm
->planes
[i
] == (UBYTE
*)0x00000000 || bm
->planes
[i
] == (UBYTE
*)0xffffffff)
688 minterm
= getminterm(type
, fg
, bg
);
691 custom
->bltcon0
= shifta
| chmask
| minterm
;
692 custom
->bltcon1
= shiftb
;
694 for(patcnt
= 0, dstoffset2
= 0; patcnt
< pat
->patternheight
; patcnt
++, dstoffset2
+= bm
->bytesperrow
) {
695 UWORD blitheight
= (height
- patcnt
+ 1) / pat
->patternheight
;
696 UWORD pattern
= ((UWORD
*)pat
->pattern
)[(pat
->patternsrcy
+ patcnt
) & patternymask
];
697 if (blitheight
&& pattern
) {
699 custom
->bltbdat
= pattern
;
700 custom
->bltcpt
= (APTR
)(bm
->planes
[i
] + dstoffset
+ dstoffset2
);
701 custom
->bltdpt
= (APTR
)(bm
->planes
[i
] + dstoffset
+ dstoffset2
);
702 startblitter(csd
, dstwidth
, blitheight
);