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
= data
->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("%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
)
208 volatile struct Custom
*custom
= (struct Custom
*)0xdff000;
209 struct GfxBase
*GfxBase
= data
->gfxbase
;
210 ULONG srcoffset
, dstoffset
;
212 WORD srcwidth
, dstwidth
, width
;
217 BOOL reverse
= FALSE
;
218 BOOL intersect
= FALSE
;
220 if (USE_BLITTER
== 0)
223 srcx2
= srcx
+ w
- 1;
224 dstx2
= dstx
+ w
- 1;
226 D(bug("CopyBoxMasked %x %x %dx%d %dx%d %dx%d %d %x\n", srcbm
, dstbm
, srcx
, srcy
, dstx
, dsty
, w
, h
, mode
, maskplane
));
228 if (srcbm
== dstbm
) {
229 intersect
= !(srcx
> dstx2
|| srcx2
< dstx
|| srcy
> dsty
+ h
- 1 || srcy
+ h
- 1 < dsty
);
232 srcoffset
= srcbm
->bytesperrow
* srcy
+ (srcx
/ 16) * 2;
233 dstoffset
= dstbm
->bytesperrow
* dsty
+ (dstx
/ 16) * 2;
234 shift
= (dstx
& 15) - (srcx
& 15);
237 // do we need >16 bit edge mask? (not handled yet)
238 if (dstoffset
< srcoffset
&& shift
< 0) // asc + desc
240 if (dstoffset
> srcoffset
&& shift
> 0) // desc + asc
247 } else if (intersect
&& dstoffset
> srcoffset
) {
251 srcwidth
= srcx2
/ 16 - srcx
/ 16 + 1;
252 dstwidth
= dstx2
/ 16 - dstx
/ 16 + 1;
258 bltshift
= shift
<< 12;
260 if (dstwidth
> srcwidth
) {
269 srcoffset
+= srcbm
->bytesperrow
* (h
- 1) + (width
- 1) * 2;
270 dstoffset
+= dstbm
->bytesperrow
* (h
- 1) + (width
- 1) * 2;
271 maskptr
= (UBYTE
*)maskplane
+ (h
- 1) * (width
- 1) * 2;
273 if (dstwidth
> srcwidth
) {
285 D(bug("shift=%d rev=%d sw=%d dw=%d sbpr=%d %04x %04x\n", shift
, reverse
, srcwidth
, dstwidth
, srcbm
->bytesperrow
, afwm
, alwm
));
290 custom
->bltafwm
= afwm
;
291 custom
->bltalwm
= alwm
;
292 custom
->bltamod
= srcbm
->bytesperrow
- dstwidth
* 2;
293 custom
->bltbmod
= srcbm
->bytesperrow
- width
* 2;
294 custom
->bltcmod
= dstbm
->bytesperrow
- width
* 2;
295 custom
->bltdmod
= dstbm
->bytesperrow
- width
* 2;
296 custom
->bltcon1
= (reverse
? 0x0002 : 0x0000) | bltshift
;
297 bltcon0
= 0x0f00 | 0x00ca | bltshift
;
299 for (i
= 0; i
< dstbm
->depth
; i
++) {
300 UWORD bltcon0b
= bltcon0
;
301 if (dstbm
->planes
[i
] == (UBYTE
*)0x00000000 || dstbm
->planes
[i
] == (UBYTE
*)0xffffffff)
304 if (i
>= srcbm
->depth
|| srcbm
->planes
[i
] == (UBYTE
*)0x00000000) {
306 custom
->bltbdat
= 0x0000;
307 } else if (srcbm
->planes
[i
] == (UBYTE
*)0xffffffff) {
309 custom
->bltbdat
= 0xffff;
311 custom
->bltbpt
= (APTR
)(srcbm
->planes
[i
] + srcoffset
);
313 custom
->bltcon0
= bltcon0b
;
314 custom
->bltapt
= (APTR
)maskptr
;
315 custom
->bltcpt
= (APTR
)(dstbm
->planes
[i
] + dstoffset
);
316 custom
->bltdpt
= (APTR
)(dstbm
->planes
[i
] + dstoffset
);
317 startblitter(data
, width
, h
);
326 static const UBYTE fill_minterm
[] = { 0xca, 0x00, 0x00, 0xca, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x00, 0xca };
328 // copy: /AC + AB = (NABC | NANBC) | (ABNC | ABC) = 0xCA
329 // invert: /AC + A/C = (NABC | NANBC) | (ABNC | ANBNC) = 0x5A
331 // A-DAT = edge masking
332 // B-DAT = pixel value (ones or zeros, not used when invert mode)
336 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
)
338 volatile struct Custom
*custom
= (struct Custom
*)0xdff000;
339 struct GfxBase
*GfxBase
= data
->gfxbase
;
344 if (USE_BLITTER
== 0)
347 D(bug("fillrect(%dx%d,%dx%d,%d,%d)\n", x1
, y1
, x2
, y2
, pixel
, mode
));
348 D(bug("bm = %dx%dx%d bpr=%d\n", bm
->width
, bm
->height
, bm
->depth
, bm
->bytesperrow
));
350 if (fill_minterm
[mode
] == 0)
353 offset
= bm
->bytesperrow
* y1
+ (x1
/ 16) * 2;
354 width
= x2
/ 16 - x1
/ 16 + 1;
355 height
= y2
- y1
+ 1;
360 custom
->bltafwm
= leftmask
[x1
& 15];
361 custom
->bltalwm
= rightmask
[x2
& 15];
362 custom
->bltcmod
= bm
->bytesperrow
- width
* 2;
363 custom
->bltdmod
= bm
->bytesperrow
- width
* 2;
364 custom
->bltcon1
= 0x0000;
365 custom
->bltcon0
= 0x0300 | fill_minterm
[mode
];
366 custom
->bltadat
= 0xffff;
368 if (mode
== vHidd_GC_DrawMode_Clear
)
370 else if (mode
== vHidd_GC_DrawMode_Set
)
373 for (i
= 0; i
< bm
->depth
; i
++) {
374 if (bm
->planes
[i
] != (UBYTE
*)0x00000000 && bm
->planes
[i
] != (UBYTE
*)0xffffffff) {
376 custom
->bltbdat
= (pixel
& 1) ? 0xffff : 0x0000;
377 custom
->bltcpt
= (APTR
)(bm
->planes
[i
] + offset
);
378 custom
->bltdpt
= (APTR
)(bm
->planes
[i
] + offset
);
379 startblitter(data
, width
, height
);
391 struct pHidd_BitMap_PutTemplate
404 // A-DAT = edge masking
409 BOOL
blit_puttemplate(struct amigavideo_staticdata
*data
, struct amigabm_data
*bm
, struct pHidd_BitMap_PutTemplate
*tmpl
)
411 volatile struct Custom
*custom
= (struct Custom
*)0xdff000;
412 struct GfxBase
*GfxBase
= data
->gfxbase
;
413 OOP_Object
*gc
= tmpl
->gc
;
414 HIDDT_Pixel fgpen
= GC_FG(tmpl
->gc
);
415 HIDDT_Pixel bgpen
= GC_BG(tmpl
->gc
);
419 UWORD shifta
, shiftb
;
421 ULONG srcoffset
, dstoffset
;
422 WORD width
, srcwidth
, dstwidth
;
424 WORD height
= tmpl
->height
;
427 WORD dstx2
= tmpl
->x
+ tmpl
->width
- 1;
428 WORD srcx
= tmpl
->srcx
;
429 WORD srcx2
= srcx
+ tmpl
->width
- 1;
431 if (USE_BLITTER
== 0)
434 if (GC_COLEXP(gc
) == vHidd_GC_ColExp_Transparent
)
436 else if (GC_DRMD(gc
) == vHidd_GC_DrawMode_Invert
)
440 if (tmpl
->inverttemplate
)
443 D(bug("puttemplate: %x x=%d y=%d w=%d h=%d type=%d fg=%d bg=%d\n",
444 tmpl
->Template
, tmpl
->x
, tmpl
->y
, tmpl
->width
, tmpl
->height
, type
, fgpen
, bgpen
));
447 dstoffset
= bm
->bytesperrow
* dsty
+ (dstx
/ 16) * 2;
449 srcwidth
= srcx2
/ 16;
450 dstwidth
= dstx2
/ 16 - dstx
/ 16 + 1;
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 BOOL
blit_putpattern(struct amigavideo_staticdata
*csd
, struct amigabm_data
*bm
, struct pHidd_BitMap_PutPattern
*pat
)
576 UBYTE fg
= GC_FG(pat
->gc
);
577 UBYTE bg
= GC_BG(pat
->gc
);
579 /* These are unused for the moment. */
583 if (USE_BLITTER
== 0 || 1)
588 if (pat
->patterndepth
> 1)
591 if (GC_COLEXP(pat
->gc
) == vHidd_GC_ColExp_Transparent
)
593 else if (GC_DRMD(pat
->gc
) == vHidd_GC_DrawMode_Invert
)
597 if (pat
->invertpattern
)