Copyright clean-up (part 1):
[AROS.git] / arch / m68k-amiga / hidd / gfx / blitter.c
blob8c4dce9c83c80e02513ce02b3d66c70eba2f61f1
1 /*
2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <proto/exec.h>
7 #include <proto/graphics.h>
9 #include <exec/libraries.h>
10 #include <hardware/custom.h>
11 #include <hardware/intbits.h>
12 #include <hidd/graphics.h>
14 #include "amigavideogfx.h"
15 #include "amigavideobitmap.h"
16 #include "blitter.h"
18 #define DEBUG 0
19 #include <aros/debug.h>
21 #define ABC 0x80
22 #define ABNC 0x40
23 #define ANBC 0x20
24 #define ANBNC 0x10
25 #define NABC 0x08
26 #define NABNC 0x04
27 #define NANBC 0x02
28 #define NANBNC 0x01
30 // Safety check for fast ram bitmaps
31 static BOOL canblit(struct BitMap *bm)
33 WORD i;
34 for (i = 0; i < bm->Depth; i++) {
35 UBYTE *p = bm->Planes[i];
36 if (p == (UBYTE*)0x00000000 || p == (UBYTE*)0xffffffff)
37 continue;
38 // Lower 2M is guaranteed to be Chip RAM
39 if (p < (UBYTE)0x00200000)
40 break;
41 // Re-implementations and UAE may have more Chip RAM.
42 if (TypeOfMem(p) & MEMF_CHIP)
43 break;
44 return FALSE;
46 return USE_BLITTER != 0;
49 static void startblitter(struct amigavideo_staticdata *data, UWORD w, UWORD h)
51 volatile struct Custom *custom = (struct Custom*)0xdff000;
53 if (data->ecs_agnus) {
54 custom->bltsizv = h;
55 custom->bltsizh = w;
56 } else {
57 if (h > 1024 || w > 64)
58 return;
59 custom->bltsize = (h << 6) | (w & 63);
62 static const UWORD leftmask[] = {
63 0xffff, 0x7fff, 0x3fff, 0x1fff,
64 0x0fff, 0x07ff, 0x03ff, 0x01ff,
65 0x00ff, 0x007f, 0x003f, 0x001f,
66 0x000f, 0x0007, 0x0003, 0x0001
68 static const UWORD rightmask[] = {
69 0x8000, 0xc000, 0xe000, 0xf000,
70 0xf800, 0xfc00, 0xfe00, 0xff00,
71 0xff80, 0xffc0, 0xffe0, 0xfff0,
72 0xfff8, 0xfffc, 0xfffe, 0xffff
75 static const UBYTE copy_minterm[] = { 0xff, 0x00, 0x00, 0xca, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff };
76 // A-DAT = edge masking
77 // B = source
78 // C = destination
79 // D = destination
80 // 0: zero (->fillrect)
81 // 1: src AND dst /AC + ABC
82 // 2: src AND NOT dst /AC + AB/C
83 // 3: src /AC + AB
84 // 4: NOT src AND dst /AC + A/B/C
85 // 5: dst (nop)
86 // 6: src XOR dst /AC + A
87 // 7: copy source and blit thru mask
88 // 8:
89 // 9:
90 // 10: NOT dst (->fillrect)
91 // 11:
92 // 12:
93 // 13:
94 // 14:
95 // 15: one (->fillrect)
97 BOOL blit_copybox(struct amigavideo_staticdata *data, struct BitMap *srcbm, struct BitMap *dstbm,
98 WORD srcx, WORD srcy, WORD w, WORD h, WORD dstx, WORD dsty, HIDDT_DrawMode mode)
100 volatile struct Custom *custom = (struct Custom*)0xdff000;
101 struct GfxBase *GfxBase = (APTR)data->cs_GfxBase;
102 ULONG srcoffset, dstoffset;
103 BYTE shift, i;
104 WORD srcwidth, dstwidth, width;
105 WORD srcx2, dstx2;
106 UWORD shifta, shiftb;
107 UWORD afwm, alwm;
108 UWORD bltcon0;
109 BOOL reverse = FALSE;
110 BOOL intersect = FALSE;
112 if (!canblit(srcbm) || !canblit(dstbm))
113 return FALSE;
115 srcx2 = srcx + w - 1;
116 dstx2 = dstx + w - 1;
117 if (copy_minterm[mode] == 0xff)
118 return blit_fillrect(data, dstbm, dstx, dsty, dstx2, dsty + h - 1, 0, mode);
120 if (copy_minterm[mode] == 0)
121 return FALSE;
123 D(bug("copybox(%x %x %dx%d %dx%d %dx%d %d)\n", srcbm, dstbm, srcx, srcy, dstx, dsty, w, h, mode));
125 if (srcbm == dstbm) {
126 intersect = !(srcx > dstx2 || srcx2 < dstx || srcy > dsty + h - 1 || srcy + h - 1 < dsty);
129 srcoffset = srcbm->BytesPerRow * srcy + (srcx / 16) * 2;
130 dstoffset = dstbm->BytesPerRow * dsty + (dstx / 16) * 2;
131 shift = (dstx & 15) - (srcx & 15);
133 if (intersect) {
134 // do we need >16 bit edge mask? (not handled yet)
135 if (dstoffset < srcoffset && shift < 0) // asc + desc
136 return FALSE;
137 if (dstoffset > srcoffset && shift > 0) // desc + asc
138 return FALSE;
141 if (shift < 0) {
142 reverse = TRUE;
143 shift = -shift;
144 } else if (intersect && dstoffset > srcoffset) {
145 reverse = TRUE;
148 srcwidth = srcx2 / 16 - srcx / 16 + 1;
149 dstwidth = dstx2 / 16 - dstx / 16 + 1;
151 srcx &= 15;
152 dstx &= 15;
153 dstx2 &= 15;
154 srcx2 &= 15;
156 if (reverse) {
157 if (dstwidth >= srcwidth) {
158 width = dstwidth;
159 shifta = 0;
160 shiftb = shift << 12;
161 alwm = leftmask[dstx];
162 afwm = rightmask[dstx2];
163 } else {
164 width = srcwidth;
165 shifta = shift << 12;
166 shiftb = shift << 12;
167 alwm = leftmask[srcx];
168 afwm = rightmask[srcx2];
170 srcoffset += srcbm->BytesPerRow * (h - 1) + (width - 1) * 2;
171 dstoffset += dstbm->BytesPerRow * (h - 1) + (width - 1) * 2;
172 } else {
173 if (dstwidth >= srcwidth) {
174 width = dstwidth;
175 shifta = 0;
176 shiftb = shift << 12;
177 afwm = leftmask[dstx];
178 alwm = rightmask[dstx2];
179 } else {
180 width = srcwidth;
181 shifta = shift << 12;
182 shiftb = shift << 12;
183 afwm = leftmask[srcx];
184 alwm = rightmask[srcx2];
188 D(bug("shift=%d rev=%d sw=%d dw=%d %04x %04x\n", shift, reverse, srcwidth, dstwidth, afwm, alwm));
190 OwnBlitter();
191 WaitBlit();
193 custom->bltafwm = afwm;
194 custom->bltalwm = alwm;
195 custom->bltbmod = srcbm->BytesPerRow - width * 2;
196 custom->bltcmod = dstbm->BytesPerRow - width * 2;
197 custom->bltdmod = dstbm->BytesPerRow - width * 2;
198 custom->bltcon1 = (reverse ? 0x0002 : 0x0000) | shiftb;
199 bltcon0 = 0x0700 | copy_minterm[mode] | shifta;
200 custom->bltadat = 0xffff;
202 for (i = 0; i < dstbm->Depth; i++) {
203 UWORD bltcon0b = bltcon0;
204 if (dstbm->Planes[i] == (UBYTE*)0x00000000 || dstbm->Planes[i] == (UBYTE*)0xffffffff)
205 continue;
206 WaitBlit();
207 if (i >= srcbm->Depth || srcbm->Planes[i] == (UBYTE*)0x00000000) {
208 bltcon0b &= ~0x0400;
209 custom->bltbdat = 0x0000;
210 } else if (srcbm->Planes[i] == (UBYTE*)0xffffffff) {
211 bltcon0b &= ~0x0400;
212 custom->bltbdat = 0xffff;
213 } else {
214 custom->bltbpt = (APTR)(srcbm->Planes[i] + srcoffset);
216 custom->bltcon0 = bltcon0b;
217 custom->bltcpt = (APTR)(dstbm->Planes[i] + dstoffset);
218 custom->bltdpt = (APTR)(dstbm->Planes[i] + dstoffset);
219 startblitter(data, width, h);
222 WaitBlit();
223 DisownBlitter();
225 return TRUE;
228 BOOL blit_copybox_mask(struct amigavideo_staticdata *data, struct BitMap *srcbm, struct BitMap *dstbm,
229 WORD srcx, WORD srcy, WORD w, WORD h, WORD dstx, WORD dsty, HIDDT_DrawMode mode, APTR maskplane)
231 volatile struct Custom *custom = (struct Custom*)0xdff000;
232 struct GfxBase *GfxBase = (APTR)data->cs_GfxBase;
233 ULONG srcoffset, dstoffset;
234 BYTE shift, i;
235 WORD srcwidth, dstwidth, width;
236 WORD srcx2, dstx2;
237 UWORD bltshift;
238 UWORD afwm, alwm;
239 UWORD bltcon0, maskmod;
240 BOOL reverse = FALSE;
241 BOOL intersect = FALSE;
242 UWORD *tempmask = NULL;
243 BOOL needtempmask = FALSE;
245 if (!canblit(srcbm) || !canblit(dstbm))
246 return FALSE;
248 srcx2 = srcx + w - 1;
249 dstx2 = dstx + w - 1;
251 D(bug("CopyBoxMasked(%x %x %dx%d %dx%d %dx%d %d %x)\n", srcbm, dstbm, srcx, srcy, dstx, dsty, w, h, mode, maskplane));
253 if (srcbm == dstbm) {
254 intersect = !(srcx > dstx2 || srcx2 < dstx || srcy > dsty + h - 1 || srcy + h - 1 < dsty);
257 srcoffset = srcbm->BytesPerRow * srcy + (srcx / 16) * 2;
258 dstoffset = dstbm->BytesPerRow * dsty + (dstx / 16) * 2;
259 shift = (dstx & 15) - (srcx & 15);
261 if (intersect) {
262 // do we need >16 bit edge mask? (not handled yet)
263 if (dstoffset < srcoffset && shift < 0) // asc + desc
264 return FALSE;
265 if (dstoffset > srcoffset && shift > 0) // desc + asc
266 return FALSE;
269 if (shift < 0) {
270 reverse = TRUE;
271 shift = -shift;
272 } else if (intersect && dstoffset > srcoffset) {
273 reverse = TRUE;
276 srcwidth = srcx2 / 16 - srcx / 16 + 1;
277 dstwidth = dstx2 / 16 - dstx / 16 + 1;
279 srcx &= 15;
280 dstx &= 15;
281 dstx2 &= 15;
282 srcx2 &= 15;
284 if (dstwidth > srcwidth && ((srcx + w - 1) & ~15) != ((dstx + w - 1) & ~15)) {
285 // >16 bit edge mask needed?
286 D(bug("unsupported %d,%d %d,%d %d %d,%d\n", srcwidth, dstwidth, srcx, dstx, w, srcx + w, dstx + w));
287 needtempmask = TRUE;
290 bltshift = shift << 12;
291 if (reverse) {
292 if (dstwidth > srcwidth) {
293 width = dstwidth;
294 alwm = leftmask[srcx];
295 if (srcwidth == 1 && srcx2 > srcx) {
296 // source is single word
297 alwm &= rightmask[srcx2];
298 afwm = 0xffff;
299 } else {
300 afwm = rightmask[srcx2];
302 } else {
303 width = srcwidth;
304 alwm = leftmask[srcx];
305 afwm = rightmask[srcx2];
307 srcoffset += srcbm->BytesPerRow * (h - 1) + (width - 1) * 2;
308 dstoffset += dstbm->BytesPerRow * (h - 1) + (width - 1) * 2;
309 } else {
310 if (dstwidth > srcwidth) {
311 width = dstwidth;
312 afwm = leftmask[srcx];
313 if (srcwidth == 1 && srcx2 > srcx) {
314 // source is single word
315 afwm &= rightmask[srcx2];
316 alwm = 0xffff;
317 } else {
318 alwm = rightmask[srcx2];
320 } else {
321 width = srcwidth;
322 afwm = leftmask[srcx];
323 alwm = rightmask[srcx2];
327 if (needtempmask) {
328 UWORD *oldmask = maskplane + srcoffset, *newmask, *mask2;
329 WORD ww;
330 tempmask = AllocVec((srcwidth + 1) * 2 * (h + 1), MEMF_CHIP);
331 if (!tempmask)
332 return FALSE;
333 mask2 = tempmask;
334 newmask = tempmask + (srcwidth + 1);
336 // create temp mask generation mask
337 for (ww = 0; ww < srcwidth - 1; ww++)
338 mask2[ww] = 0xffff;
339 // we need to mask out part of second to last word which
340 // is not directly supported by the blitter.
341 mask2[srcwidth - 1] = reverse ? afwm : alwm;
342 mask2[srcwidth] = 0x0000;
344 // create temp mask
345 OwnBlitter();
346 WaitBlit();
347 custom->bltapt = mask2;
348 custom->bltbdat = 0x0000;
349 custom->bltcpt = oldmask;
350 custom->bltdpt = newmask;
351 custom->bltamod = -(srcwidth + 1) * 2;
352 custom->bltcmod = srcbm->BytesPerRow - (srcwidth + 1) * 2;
353 custom->bltdmod = 0;
354 custom->bltafwm = 0xffff;
355 custom->bltalwm = 0xffff;
356 // AC+/AB
357 custom->bltcon0 = 0x0bac;
358 custom->bltcon1 = 0x0000;
359 startblitter(data, srcwidth + 1, h);
360 DisownBlitter();
362 maskplane = newmask;
363 maskmod = 0;
364 } else {
365 maskplane += srcoffset;
366 maskmod = srcbm->BytesPerRow - width * 2;
369 D(bug("shift=%d rev=%d sw=%d dw=%d sbpr=%d srcx=%d/%d %04x %04x %p\n", shift, reverse, srcwidth, dstwidth, srcbm->BytesPerRow, srcx, srcx2, afwm, alwm, maskplane));
371 OwnBlitter();
372 WaitBlit();
374 custom->bltafwm = afwm;
375 custom->bltalwm = alwm;
376 custom->bltamod = maskmod;
377 custom->bltbmod = srcbm->BytesPerRow - width * 2;
378 custom->bltcmod = dstbm->BytesPerRow - width * 2;
379 custom->bltdmod = dstbm->BytesPerRow - width * 2;
380 custom->bltcon1 = (reverse ? 0x0002 : 0x0000) | bltshift;
381 bltcon0 = 0x0f00 | 0x00ca | bltshift;
383 for (i = 0; i < dstbm->Depth; i++) {
384 UWORD bltcon0b = bltcon0;
385 if (dstbm->Planes[i] == (UBYTE*)0x00000000 || dstbm->Planes[i] == (UBYTE*)0xffffffff)
386 continue;
387 WaitBlit();
388 if (i >= srcbm->Depth || srcbm->Planes[i] == (UBYTE*)0x00000000) {
389 bltcon0b &= ~0x0400;
390 custom->bltbdat = 0x0000;
391 } else if (srcbm->Planes[i] == (UBYTE*)0xffffffff) {
392 bltcon0b &= ~0x0400;
393 custom->bltbdat = 0xffff;
394 } else {
395 custom->bltbpt = (APTR)(srcbm->Planes[i] + srcoffset);
397 custom->bltcon0 = bltcon0b;
398 custom->bltapt = (APTR)maskplane;
399 custom->bltcpt = (APTR)(dstbm->Planes[i] + dstoffset);
400 custom->bltdpt = (APTR)(dstbm->Planes[i] + dstoffset);
401 startblitter(data, width, h);
404 WaitBlit();
405 DisownBlitter();
407 if (tempmask)
408 FreeVec(tempmask);
410 return TRUE;
413 static const UBYTE fill_minterm[] = { 0xca, 0x00, 0x00, 0xca, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x5a, 0x00, 0x00, 0x00, 0x00, 0xca };
415 // copy: /AC + AB = (NABC | NANBC) | (ABNC | ABC) = 0xCA
416 // invert: /AC + A/C = (NABC | NANBC) | (ABNC | ANBNC) = 0x5A
418 // A-DAT = edge masking
419 // B-DAT = pixel value (ones or zeros, not used when invert mode)
420 // C = source
421 // D = destination
423 BOOL blit_fillrect(struct amigavideo_staticdata *data, struct BitMap *bm, WORD x1,WORD y1,WORD x2,WORD y2, HIDDT_Pixel pixel, HIDDT_DrawMode mode)
425 volatile struct Custom *custom = (struct Custom*)0xdff000;
426 struct GfxBase *GfxBase = (APTR)data->cs_GfxBase;
427 ULONG offset;
428 WORD width, height;
429 UBYTE i;
431 if (!canblit(bm))
432 return FALSE;
434 D(bug("fillrect(%dx%d,%dx%d,%d,%d)\n", x1, y1, x2, y2, pixel, mode));
435 D(bug("bm = %dx%dx%d bpr=%d\n", bm->BytesPerRow * 8, bm->Rows, bm->Depth, bm->BytesPerRow));
437 if (fill_minterm[mode] == 0)
438 return FALSE;
440 offset = bm->BytesPerRow * y1 + (x1 / 16) * 2;
441 width = x2 / 16 - x1 / 16 + 1;
442 height = y2 - y1 + 1;
444 OwnBlitter();
445 WaitBlit();
447 custom->bltafwm = leftmask[x1 & 15];
448 custom->bltalwm = rightmask[x2 & 15];
449 custom->bltcmod = bm->BytesPerRow - width * 2;
450 custom->bltdmod = bm->BytesPerRow - width * 2;
451 custom->bltcon1 = 0x0000;
452 custom->bltcon0 = 0x0300 | fill_minterm[mode];
453 custom->bltadat = 0xffff;
455 if (mode == vHidd_GC_DrawMode_Clear)
456 pixel = 0x00;
457 else if (mode == vHidd_GC_DrawMode_Set || mode == vHidd_GC_DrawMode_Invert)
458 pixel = 0xff;
460 for (i = 0; i < bm->Depth; i++) {
461 if (bm->Planes[i] != (UBYTE*)0x00000000 && bm->Planes[i] != (UBYTE*)0xffffffff) {
462 WaitBlit();
463 custom->bltbdat = (pixel & 1) ? 0xffff : 0x0000;
464 custom->bltcpt = (APTR)(bm->Planes[i] + offset);
465 custom->bltdpt = (APTR)(bm->Planes[i] + offset);
466 startblitter(data, width, height);
468 pixel >>= 1;
471 WaitBlit();
472 DisownBlitter();
474 return TRUE;
477 #if 0
478 struct pHidd_BitMap_PutTemplate
480 OOP_MethodID mID;
481 OOP_Object *gc;
482 UBYTE *Template;
483 ULONG modulo;
484 WORD srcx;
485 WORD x, y;
486 WORD width, height;
487 BOOL inverttemplate;
489 #endif
491 // A-DAT = edge masking
492 // B = template
493 // C = destination
494 // D = destination
496 BOOL blit_puttemplate(struct amigavideo_staticdata *data, struct BitMap *bm, struct pHidd_BitMap_PutTemplate *tmpl)
498 volatile struct Custom *custom = (struct Custom*)0xdff000;
499 struct GfxBase *GfxBase = (APTR)data->cs_GfxBase;
500 OOP_Object *gc = tmpl->gc;
501 HIDDT_Pixel fgpen = GC_FG(tmpl->gc);
502 HIDDT_Pixel bgpen = GC_BG(tmpl->gc);
504 UBYTE type, i;
505 BYTE shift;
506 UWORD shifta, shiftb;
507 UWORD afwm, alwm;
508 ULONG srcoffset, dstoffset;
509 WORD width, srcwidth, dstwidth;
510 BOOL reverse;
511 WORD height = tmpl->height;
512 WORD dstx = tmpl->x;
513 WORD dsty = tmpl->y;
514 WORD dstx2 = tmpl->x + tmpl->width - 1;
515 WORD srcx = tmpl->srcx;
516 WORD srcx2 = srcx + tmpl->width - 1;
518 if (!canblit(bm))
519 return FALSE;
521 if (GC_COLEXP(gc) == vHidd_GC_ColExp_Transparent)
522 type = 0;
523 else if (GC_DRMD(gc) == vHidd_GC_DrawMode_Invert)
524 type = 2;
525 else
526 type = 4;
527 if (tmpl->inverttemplate)
528 type++;
530 D(bug("puttemplate: %x srcx=%d x=%d y=%d w=%d h=%d type=%d fg=%d bg=%d\n",
531 tmpl->masktemplate, tmpl->srcx, tmpl->x, tmpl->y, tmpl->width, tmpl->height, type, fgpen, bgpen));
533 srcoffset = (srcx / 16) * 2;
534 dstoffset = bm->BytesPerRow * dsty + (dstx / 16) * 2;
536 srcwidth = srcx2 / 16 - srcx / 16 + 1;
537 dstwidth = dstx2 / 16 - dstx / 16 + 1;
539 dstx &= 15;
540 dstx2 &= 15;
541 srcx &= 15;
542 srcx2 &= 15;
544 shift = dstx - srcx;
546 D(bug("shift=%d srcwidth=%d dstwidth=%d\n", shift, srcwidth, dstwidth));
548 if (shift < 0) {
549 reverse = TRUE;
550 shift = -shift;
551 if (dstwidth >= srcwidth) {
552 width = dstwidth;
553 shifta = 0;
554 shiftb = shift << 12;
555 alwm = leftmask[dstx];
556 afwm = rightmask[dstx2];
557 } else {
558 width = srcwidth;
559 shifta = shift << 12;
560 shiftb = shift << 12;
561 alwm = leftmask[srcx];
562 afwm = rightmask[srcx2];
564 srcoffset += tmpl->modulo * (height - 1) + (width - 1) * 2;
565 dstoffset += bm->BytesPerRow * (height - 1) + (width - 1) * 2;
566 } else {
567 reverse = FALSE;
568 if (dstwidth >= srcwidth) {
569 width = dstwidth;
570 shifta = 0;
571 shiftb = shift << 12;
572 afwm = leftmask[dstx];
573 alwm = rightmask[dstx2];
574 } else {
575 width = srcwidth;
576 shifta = shift << 12;
577 shiftb = shift << 12;
578 afwm = leftmask[srcx];
579 alwm = rightmask[srcx2];
583 OwnBlitter();
584 WaitBlit();
586 custom->bltafwm = afwm;
587 custom->bltalwm = alwm;
588 custom->bltbmod = tmpl->modulo - width * 2;
589 custom->bltcmod = bm->BytesPerRow - width * 2;
590 custom->bltdmod = bm->BytesPerRow - width * 2;
591 custom->bltadat = 0xffff;
593 for (i = 0; i < bm->Depth; i++) {
594 UBYTE minterm;
595 UWORD chmask, shiftbv;
596 UBYTE fg, bg, tg;
598 fg = fgpen & 1;
599 bg = bgpen & 1;
600 fgpen >>= 1;
601 bgpen >>= 1;
603 if (bm->Planes[i] == (UBYTE*)0x00000000 || bm->Planes[i] == (UBYTE*)0xffffffff)
604 continue;
606 chmask = 0x0700;
607 shiftbv = shiftb;
609 /* not guaranteed to be correct, last time I played with minterms
610 * was something like 20 years ago..
612 switch (type)
614 case 0: // JAM1:
615 minterm = (NABC | NANBC) | (fg ? ABC | ABNC | ANBC : ANBC);
616 break;
617 case 1: // JAM1 | INVERSVID
618 minterm = (NABC | NANBC) | (fg ? ANBC | ANBNC | ABC : ABC);
619 break;
620 case 2: // COMPLEMENT:
621 minterm = (NABC | NANBC) | (ANBC | ABNC);
622 break;
623 case 3: // COMPLEMENT | INVERSVID:
624 minterm = (NABC | NANBC) | (ABC | ANBNC);
625 break;
626 case 5: // JAM2 | INVERSVID
627 tg = fg;
628 fg = bg;
629 bg = tg;
630 case 4: // JAM2
631 if (fg && bg) {
632 minterm = (NABC | NANBC) | (ABC | ABNC);
633 chmask = 0x0300;
634 shiftbv = 0;
635 } else if (!fg && !bg) {
636 minterm = (NABC | NANBC);
637 chmask = 0x0300;
638 shiftbv = 0;
639 } else if (fg) {
640 minterm = (NABC | NANBC) | (ABC | ABNC);
641 } else {
642 minterm = (NABC | NANBC) | (ANBC | ANBNC);
644 break;
647 WaitBlit();
648 custom->bltcon0 = shifta | chmask | minterm;
649 custom->bltcon1 = (reverse ? 0x0002 : 0x0000) | shiftbv;
650 custom->bltbdat = 0xffff;
651 custom->bltbpt = (APTR)(tmpl->masktemplate + srcoffset);
652 custom->bltcpt = (APTR)(bm->Planes[i] + dstoffset);
653 custom->bltdpt = (APTR)(bm->Planes[i] + dstoffset);
654 startblitter(data, width, height);
657 WaitBlit();
658 DisownBlitter();
660 return TRUE;
663 static UBYTE getminterm(UBYTE type, UBYTE fg, UBYTE bg)
665 UBYTE minterm = 0, tg;
666 switch (type)
668 case 0: // JAM1:
669 minterm = (NABC | NANBC) | (fg ? ABC | ABNC | ANBC : ANBC);
670 break;
671 case 1: // JAM1 | INVERSVID
672 minterm = (NABC | NANBC) | (fg ? ANBC | ANBNC | ABC : ABC);
673 break;
674 case 2: // COMPLEMENT:
675 minterm = (NABC | NANBC) | (ANBC | ABNC);
676 break;
677 case 3: // COMPLEMENT | INVERSVID:
678 minterm = (NABC | NANBC) | (ABC | ANBNC);
679 break;
680 case 5: // JAM2 | INVERSVID
681 tg = fg;
682 fg = bg;
683 bg = tg;
684 case 4: // JAM2
685 if (fg && bg) {
686 minterm = (NABC | NANBC) | (ABC | ABNC);
687 } else if (!fg && !bg) {
688 minterm = (NABC | NANBC);
689 } else if (fg) {
690 minterm = (NABC | NANBC) | (ABC | ABNC);
691 } else {
692 minterm = (NABC | NANBC) | (ANBC | ANBNC);
694 break;
696 return minterm;
699 BOOL blit_putpattern(struct amigavideo_staticdata *csd, struct BitMap *bm, struct pHidd_BitMap_PutPattern *pat)
701 volatile struct Custom *custom = (struct Custom*)0xdff000;
702 struct GfxBase *GfxBase = (APTR)csd->cs_GfxBase;
704 UBYTE type;
705 UBYTE fgpen = GC_FG(pat->gc);
706 UBYTE bgpen = GC_BG(pat->gc);
708 UBYTE i;
709 UWORD shifta, shiftb;
710 UWORD afwm, alwm;
711 ULONG dstoffset;
712 WORD dstwidth;
713 WORD patcnt;
715 WORD height = pat->height;
716 WORD dstx = pat->x;
717 WORD dsty = pat->y;
718 WORD dstx2 = pat->x + pat->width - 1;
720 WORD patternymask = pat->patternheight - 1;
722 if (!canblit(bm))
723 return FALSE;
725 if (pat->mask)
726 return FALSE;
727 if (pat->patterndepth != 1)
728 return FALSE;
730 if (GC_COLEXP(pat->gc) == vHidd_GC_ColExp_Transparent)
731 type = 0;
732 else if (GC_DRMD(pat->gc) == vHidd_GC_DrawMode_Invert)
733 type = 2;
734 else
735 type = 4;
736 if (pat->invertpattern)
737 type++;
739 D(bug("PutPattern(%dx%d,%dx%d,mask=%x,mod=%d,masksrcx=%d,P=%x,%dx%d,h=%d,T=%d)\n",
740 pat->x, pat->y, pat->width, pat->height,
741 pat->mask, pat->maskmodulo, pat->masksrcx,
742 pat->pattern, pat->patternsrcx, pat->patternsrcy, pat->patternheight, type));
744 dstoffset = bm->BytesPerRow * dsty + (dstx / 16) * 2;
745 dstwidth = dstx2 / 16 - dstx / 16 + 1;
747 dstx &= 15;
748 dstx2 &= 15;
750 shifta = 0;
751 shiftb = 0;
752 afwm = leftmask[dstx];
753 alwm = rightmask[dstx2];
755 OwnBlitter();
756 WaitBlit();
758 custom->bltafwm = afwm;
759 custom->bltalwm = alwm;
760 custom->bltcmod = (bm->BytesPerRow - dstwidth * 2) + bm->BytesPerRow * (pat->patternheight - 1);
761 custom->bltdmod = (bm->BytesPerRow - dstwidth * 2) + bm->BytesPerRow * (pat->patternheight - 1);
762 custom->bltadat = 0xffff;
764 for (i = 0; i < bm->Depth; i++, fgpen >>= 1, bgpen >>= 1) {
765 ULONG dstoffset2;
766 UBYTE minterm;
767 UWORD chmask;
768 UBYTE fg, bg;
770 if (bm->Planes[i] == (UBYTE*)0x00000000 || bm->Planes[i] == (UBYTE*)0xffffffff)
771 continue;
773 fg = fgpen & 1;
774 bg = bgpen & 1;
776 chmask = 0x0300;
778 minterm = getminterm(type, fg, bg);
780 WaitBlit();
781 custom->bltcon0 = shifta | chmask | minterm;
782 custom->bltcon1 = shiftb;
784 for(patcnt = 0, dstoffset2 = 0; patcnt < pat->patternheight; patcnt++, dstoffset2 += bm->BytesPerRow) {
785 UWORD blitheight = (height - patcnt + 1) / pat->patternheight;
786 UWORD pattern = ((UWORD*)pat->pattern)[(pat->patternsrcy + patcnt) & patternymask];
787 if (blitheight && pattern) {
788 WaitBlit();
789 custom->bltbdat = pattern;
790 custom->bltcpt = (APTR)(bm->Planes[i] + dstoffset + dstoffset2);
791 custom->bltdpt = (APTR)(bm->Planes[i] + dstoffset + dstoffset2);
792 startblitter(csd, dstwidth, blitheight);
797 WaitBlit();
798 DisownBlitter();
800 return TRUE;