add idnestcnt and tdnestcnt overrides. use atomic operations when appropriate
[AROS.git] / workbench / hidds / nouveau / nouveau_accel.c
blob74cd97be9786ad1867a8b1181bd844124be17820
1 /*
2 * Copyright 2009 Nouveau Project
3 * Copyright (C) 2010-2013, The AROS Development Team. All rights reserved.
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice shall be included in
13 * all copies or substantial portions of the Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
19 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
20 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
24 #include "nouveau_intern.h"
25 #include "nouveau_class.h"
26 #include <proto/oop.h>
28 #undef HiddBitMapAttrBase
29 #define HiddBitMapAttrBase (SD(cl)->bitMapAttrBase)
31 static inline int do_alpha(int a, int v)
33 int tmp = a*v;
34 return ((tmp << 8) + tmp + 32768) >> 16;
37 /* NOTE: Assumes lock on bitmap is already made */
38 /* NOTE: Assumes buffer is mapped */
39 VOID HIDDNouveauBitMapPutAlphaImage32(struct HIDDNouveauBitMapData * bmdata,
40 APTR srcbuff, ULONG srcpitch, LONG destX, LONG destY, LONG width, LONG height)
42 LONG x,y;
44 for(y = 0; y < height; y++)
46 /* Calculate line start addresses */
47 IPTR srcaddr = (srcpitch * y) + (IPTR)srcbuff;
48 IPTR destaddr = (destX * 4) + (bmdata->pitch * (destY + y)) + (IPTR)bmdata->bo->map;
50 for (x = 0; x < width; x++)
52 ULONG destpix;
53 ULONG srcpix;
54 LONG src_red, src_green, src_blue, src_alpha;
55 LONG dst_red, dst_green, dst_blue;
57 /* Read RGBA pixel from input array */
58 srcpix = *(ULONG *)srcaddr;
59 #if AROS_BIG_ENDIAN
60 src_red = (srcpix & 0x00FF0000) >> 16;
61 src_green = (srcpix & 0x0000FF00) >> 8;
62 src_blue = (srcpix & 0x000000FF);
63 src_alpha = (srcpix & 0xFF000000) >> 24;
64 #else
65 src_red = (srcpix & 0x0000FF00) >> 8;
66 src_green = (srcpix & 0x00FF0000) >> 16;
67 src_blue = (srcpix & 0xFF000000) >> 24;
68 src_alpha = (srcpix & 0x000000FF);
69 #endif
72 * If alpha=0, do not change the destination pixel at all.
73 * This saves us unnecessary reads and writes to VRAM.
75 if (src_alpha != 0)
78 * Full opacity. Do not read the destination pixel, as
79 * it's value does not matter anyway.
81 if (src_alpha == 0xff)
83 dst_red = src_red;
84 dst_green = src_green;
85 dst_blue = src_blue;
87 else
90 * Alpha blending with source and destination pixels.
91 * Get destination.
93 destpix = readl(destaddr);
95 dst_red = (destpix & 0x00FF0000) >> 16;
96 dst_green = (destpix & 0x0000FF00) >> 8;
97 dst_blue = (destpix & 0x000000FF);
99 dst_red += do_alpha(src_alpha, src_red - dst_red);
100 dst_green += do_alpha(src_alpha, src_green - dst_green);
101 dst_blue += do_alpha(src_alpha, src_blue - dst_blue);
104 destpix = (dst_red << 16) + (dst_green << 8) + (dst_blue);
106 /* Store the new pixel */
107 writel(destpix, destaddr);
110 /* Advance pointers */
111 srcaddr += 4;
112 destaddr += 4;
117 /* NOTE: Assumes lock on bitmap is already made */
118 /* NOTE: Assumes buffer is mapped */
119 VOID HIDDNouveauBitMapPutAlphaImage16(struct HIDDNouveauBitMapData * bmdata,
120 APTR srcbuff, ULONG srcpitch, LONG destX, LONG destY, LONG width, LONG height)
122 LONG x,y;
124 for(y = 0; y < height; y++)
126 /* Calculate line start addresses */
127 IPTR srcaddr = (srcpitch * y) + (IPTR)srcbuff;
128 IPTR destaddr = (destX * 2) + (bmdata->pitch * (destY + y)) + (IPTR)bmdata->bo->map;
130 for (x = 0; x < width; x++)
132 UWORD destpix;
133 ULONG srcpix;
134 LONG src_red, src_green, src_blue, src_alpha;
135 LONG dst_red, dst_green, dst_blue;
137 /* Read RGBA pixel from input array */
138 srcpix = *(ULONG *)srcaddr;
139 #if AROS_BIG_ENDIAN
140 src_red = (srcpix & 0x00FF0000) >> 16;
141 src_green = (srcpix & 0x0000FF00) >> 8;
142 src_blue = (srcpix & 0x000000FF);
143 src_alpha = (srcpix & 0xFF000000) >> 24;
144 #else
145 src_red = (srcpix & 0x0000FF00) >> 8;
146 src_green = (srcpix & 0x00FF0000) >> 16;
147 src_blue = (srcpix & 0xFF000000) >> 24;
148 src_alpha = (srcpix & 0x000000FF);
149 #endif
152 * If alpha=0, do not change the destination pixel at all.
153 * This saves us unnecessary reads and writes to VRAM.
155 if (src_alpha != 0)
158 * Full opacity. Do not read the destination pixel, as
159 * it's value does not matter anyway.
161 if (src_alpha == 0xff)
163 dst_red = src_red;
164 dst_green = src_green;
165 dst_blue = src_blue;
167 else
170 * Alpha blending with source and destination pixels.
171 * Get destination.
174 destpix = readw(destaddr);
176 dst_red = (destpix & 0x0000F800) >> 8;
177 dst_green = (destpix & 0x000007e0) >> 3;
178 dst_blue = (destpix & 0x0000001f) << 3;
180 dst_red += do_alpha(src_alpha, src_red - dst_red);
181 dst_green += do_alpha(src_alpha, src_green - dst_green);
182 dst_blue += do_alpha(src_alpha, src_blue - dst_blue);
185 destpix = (((dst_red << 8) & 0xf800) | ((dst_green << 3) & 0x07e0) | ((dst_blue >> 3) & 0x001f));
187 writew(destpix, destaddr);
190 /* Advance pointers */
191 srcaddr += 4;
192 destaddr += 2;
197 /* NOTE: Assumes lock on bitmap is already made */
198 /* NOTE: Assumes buffer is mapped */
199 VOID HIDDNouveauBitMapPutAlphaTemplate32(struct HIDDNouveauBitMapData * bmdata,
200 OOP_Object * gc, OOP_Object * bm, BOOL invertalpha,
201 UBYTE * srcalpha, ULONG srcpitch, LONG destX, LONG destY, LONG width, LONG height)
203 WORD x, y;
204 UBYTE *pixarray = srcalpha;
205 HIDDT_Color color;
206 LONG fg_red, fg_green, fg_blue;
207 LONG bg_red = 0, bg_green = 0, bg_blue = 0;
208 WORD type = 0;
210 if (width <= 0 || height <= 0)
211 return;
213 HIDD_BM_UnmapPixel(bm, GC_FG(gc), &color);
215 fg_red = color.red >> 8;
216 fg_green = color.green >> 8;
217 fg_blue = color.blue >> 8;
219 if (GC_COLEXP(gc) == vHidd_GC_ColExp_Transparent)
221 type = 0;
223 else if (GC_DRMD(gc) == vHidd_GC_DrawMode_Invert)
225 type = 2;
227 else
229 type = 4;
231 HIDD_BM_UnmapPixel(bm, GC_BG(gc), &color);
232 bg_red = color.red >> 8;
233 bg_green = color.green >> 8;
234 bg_blue = color.blue >> 8;
237 if (invertalpha) type++;
240 for(y = 0; y < height; y++)
242 IPTR destaddr = (destX * 4) + ((destY + y) * bmdata->pitch) + (IPTR)bmdata->bo->map;
244 switch(type)
246 case 0: /* JAM1 */
247 for(x = 0; x < width; x++)
249 ULONG destpix;
250 LONG dst_red, dst_green, dst_blue, alpha;
252 alpha = *pixarray++;
255 if (alpha != 0) /* If alpha=0, do not change the destination pixel at all. */
257 if (alpha == 0xff) /* Full opacity. Do not read the destination pixel. */
259 dst_red = fg_red;
260 dst_green = fg_green;
261 dst_blue = fg_blue;
263 else
265 destpix = readl(destaddr);
267 dst_red = (destpix & 0x00FF0000) >> 16;
268 dst_green = (destpix & 0x0000FF00) >> 8;
269 dst_blue = (destpix & 0x000000FF);
271 dst_red += do_alpha(alpha, fg_red - dst_red);
272 dst_green += do_alpha(alpha, fg_green - dst_green);
273 dst_blue += do_alpha(alpha, fg_blue - dst_blue);
276 destpix = (dst_red << 16) + (dst_green << 8) + (dst_blue);
277 writel(destpix, destaddr);
280 destaddr += 4;
282 } /* for(x = 0; x < msg->width; x++) */
283 break;
285 case 1: /* JAM1 | INVERSVID */
286 for(x = 0; x < width; x++)
288 ULONG destpix;
289 LONG dst_red, dst_green, dst_blue, alpha;
291 alpha = (*pixarray++) ^ 255;
294 if (alpha != 0) /* If alpha=0, do not change the destination pixel at all. */
296 if (alpha == 0xff) /* Full opacity. Do not read the destination pixel. */
298 dst_red = fg_red;
299 dst_green = fg_green;
300 dst_blue = fg_blue;
302 else
304 destpix = readl(destaddr);
306 dst_red = (destpix & 0x00FF0000) >> 16;
307 dst_green = (destpix & 0x0000FF00) >> 8;
308 dst_blue = (destpix & 0x000000FF);
310 dst_red += do_alpha(alpha, fg_red - dst_red);
311 dst_green += do_alpha(alpha, fg_green - dst_green);
312 dst_blue += do_alpha(alpha, fg_blue - dst_blue);
315 destpix = (dst_red << 16) + (dst_green << 8) + (dst_blue);
316 writel(destpix, destaddr);
319 destaddr += 4;
321 } /* for(x = 0; x < width; x++) */
322 break;
324 case 2: /* COMPLEMENT */
325 for(x = 0; x < width; x++)
327 ULONG destpix;
328 UBYTE alpha;
330 alpha = *pixarray++;
333 if (alpha >= 0x80)
335 destpix = readl(destaddr);
336 destpix = ~destpix;
337 writel(destpix, destaddr);
340 destaddr += 4;
342 } /* for(x = 0; x < width; x++) */
343 break;
345 case 3: /* COMPLEMENT | INVERSVID*/
346 for(x = 0; x < width; x++)
348 ULONG destpix;
349 UBYTE alpha;
351 alpha = *pixarray++;
354 if (alpha < 0x80)
356 destpix = readl(destaddr);
357 destpix = ~destpix;
358 writel(destpix, destaddr);
361 destaddr += 4;
363 } /* for(x = 0; x < width; x++) */
364 break;
366 case 4: /* JAM2 */
367 for(x = 0; x < width; x++)
369 ULONG destpix;
370 LONG dst_red, dst_green, dst_blue, alpha;
372 alpha = *pixarray++;
375 dst_red = bg_red + ((fg_red - bg_red) * alpha) / 256;
376 dst_green = bg_green + ((fg_green - bg_green) * alpha) / 256;
377 dst_blue = bg_blue + ((fg_blue - bg_blue) * alpha) / 256;
379 destpix = (dst_red << 16) + (dst_green << 8) + (dst_blue);
381 writel(destpix, destaddr);
382 destaddr += 4;
384 } /* for(x = 0; x < width; x++) */
385 break;
387 case 5: /* JAM2 | INVERSVID */
388 for(x = 0; x < width; x++)
390 ULONG destpix;
391 LONG dst_red, dst_green, dst_blue, alpha;
393 alpha = (*pixarray++) ^ 255;
396 dst_red = bg_red + ((fg_red - bg_red) * alpha) / 256;
397 dst_green = bg_green + ((fg_green - bg_green) * alpha) / 256;
398 dst_blue = bg_blue + ((fg_blue - bg_blue) * alpha) / 256;
400 destpix = (dst_red << 16) + (dst_green << 8) + (dst_blue);
401 writel(destpix, destaddr);
403 destaddr += 4;
405 } /* for(x = 0; x < width; x++) */
406 break;
408 } /* switch(type) */
410 pixarray += srcpitch - width;
412 } /* for(y = 0; y < height; y++) */
415 /* NOTE: Assumes lock on bitmap is already made */
416 /* NOTE: Assumes buffer is mapped */
417 VOID HIDDNouveauBitMapPutAlphaTemplate16(struct HIDDNouveauBitMapData * bmdata,
418 OOP_Object * gc, OOP_Object * bm, BOOL invertalpha,
419 UBYTE * srcalpha, ULONG srcpitch, LONG destX, LONG destY, LONG width, LONG height)
421 WORD x, y;
422 UBYTE *pixarray = srcalpha;
423 HIDDT_Color color;
424 LONG fg_red, fg_green, fg_blue;
425 LONG bg_red = 0, bg_green = 0, bg_blue = 0;
426 WORD type = 0;
428 if (width <= 0 || height <= 0)
429 return;
431 HIDD_BM_UnmapPixel(bm, GC_FG(gc), &color);
433 fg_red = color.red >> 8;
434 fg_green = color.green >> 8;
435 fg_blue = color.blue >> 8;
437 if (GC_COLEXP(gc) == vHidd_GC_ColExp_Transparent)
439 type = 0;
441 else if (GC_DRMD(gc) == vHidd_GC_DrawMode_Invert)
443 type = 2;
445 else
447 type = 4;
449 HIDD_BM_UnmapPixel(bm, GC_BG(gc), &color);
450 bg_red = color.red >> 8;
451 bg_green = color.green >> 8;
452 bg_blue = color.blue >> 8;
455 if (invertalpha) type++;
458 for(y = 0; y < height; y++)
460 IPTR destaddr = (destX * 2) + ((destY + y) * bmdata->pitch) + (IPTR)bmdata->bo->map;
462 switch(type)
464 case 0: /* JAM1 */
465 for(x = 0; x < width; x++)
467 UWORD destpix;
468 LONG dst_red, dst_green, dst_blue, alpha;
470 alpha = *pixarray++;
473 if (alpha != 0) /* If alpha=0, do not change the destination pixel at all. */
475 if (alpha == 0xff) /* Full opacity. Do not read the destination pixel. */
477 dst_red = fg_red;
478 dst_green = fg_green;
479 dst_blue = fg_blue;
481 else
483 destpix = readw(destaddr);
485 dst_red = (destpix & 0x0000F800) >> 8;
486 dst_green = (destpix & 0x000007e0) >> 3;
487 dst_blue = (destpix & 0x0000001f) << 3;
489 dst_red += do_alpha(alpha, fg_red - dst_red);
490 dst_green += do_alpha(alpha, fg_green - dst_green);
491 dst_blue += do_alpha(alpha, fg_blue - dst_blue);
494 destpix = (((dst_red << 8) & 0xf800) | ((dst_green << 3) & 0x07e0) | ((dst_blue >> 3) & 0x001f));
495 writew(destpix, destaddr);
498 destaddr += 2;
500 } /* for(x = 0; x < msg->width; x++) */
501 break;
503 case 1: /* JAM1 | INVERSVID */
504 for(x = 0; x < width; x++)
506 UWORD destpix;
507 LONG dst_red, dst_green, dst_blue, alpha;
509 alpha = (*pixarray++) ^ 255;
512 if (alpha != 0) /* If alpha=0, do not change the destination pixel at all. */
514 if (alpha == 0xff) /* Full opacity. Do not read the destination pixel. */
516 dst_red = fg_red;
517 dst_green = fg_green;
518 dst_blue = fg_blue;
520 else
522 destpix = readw(destaddr);
524 dst_red = (destpix & 0x0000F800) >> 8;
525 dst_green = (destpix & 0x000007e0) >> 3;
526 dst_blue = (destpix & 0x0000001f) << 3;
528 dst_red += do_alpha(alpha, fg_red - dst_red);
529 dst_green += do_alpha(alpha, fg_green - dst_green);
530 dst_blue += do_alpha(alpha, fg_blue - dst_blue);
533 destpix = (((dst_red << 8) & 0xf800) | ((dst_green << 3) & 0x07e0) | ((dst_blue >> 3) & 0x001f));
534 writew(destpix, destaddr);
537 destaddr += 2;
539 } /* for(x = 0; x < width; x++) */
540 break;
542 case 2: /* COMPLEMENT */
543 for(x = 0; x < width; x++)
545 UWORD destpix;
546 UBYTE alpha;
548 alpha = *pixarray++;
551 if (alpha >= 0x80)
553 destpix = readw(destaddr);
554 destpix = ~destpix;
555 writew(destpix, destaddr);
558 destaddr += 2;
560 } /* for(x = 0; x < width; x++) */
561 break;
563 case 3: /* COMPLEMENT | INVERSVID*/
564 for(x = 0; x < width; x++)
566 UWORD destpix;
567 UBYTE alpha;
569 alpha = *pixarray++;
572 if (alpha < 0x80)
574 destpix = readw(destaddr);
575 destpix = ~destpix;
576 writew(destpix, destaddr);
579 destaddr += 2;
581 } /* for(x = 0; x < width; x++) */
582 break;
584 case 4: /* JAM2 */
585 for(x = 0; x < width; x++)
587 UWORD destpix;
588 LONG dst_red, dst_green, dst_blue, alpha;
590 alpha = *pixarray++;
593 dst_red = bg_red + ((fg_red - bg_red) * alpha) / 256;
594 dst_green = bg_green + ((fg_green - bg_green) * alpha) / 256;
595 dst_blue = bg_blue + ((fg_blue - bg_blue) * alpha) / 256;
597 destpix = (((dst_red << 8) & 0xf800) | ((dst_green << 3) & 0x07e0) | ((dst_blue >> 3) & 0x001f));
598 writew(destpix, destaddr);
600 destaddr += 2;
602 } /* for(x = 0; x < width; x++) */
603 break;
605 case 5: /* JAM2 | INVERSVID */
606 for(x = 0; x < width; x++)
608 UWORD destpix;
609 LONG dst_red, dst_green, dst_blue, alpha;
611 alpha = (*pixarray++) ^ 255;
614 dst_red = bg_red + ((fg_red - bg_red) * alpha) / 256;
615 dst_green = bg_green + ((fg_green - bg_green) * alpha) / 256;
616 dst_blue = bg_blue + ((fg_blue - bg_blue) * alpha) / 256;
618 destpix = (((dst_red << 8) & 0xf800) | ((dst_green << 3) & 0x07e0) | ((dst_blue >> 3) & 0x001f));
619 writew(destpix, destaddr);
621 destaddr += 2;
623 } /* for(x = 0; x < width; x++) */
624 break;
626 } /* switch(type) */
628 pixarray += srcpitch - width;
630 } /* for(y = 0; y < height; y++) */
633 /* Assumes input and output buffers are lock-protected */
634 /* Takes pixels from RAM buffer, converts them and puts them into destination
635 buffer. The destination buffer can be in VRAM or GART or RAM */
636 BOOL HiddNouveauWriteFromRAM(
637 APTR src, ULONG srcPitch, HIDDT_StdPixFmt srcPixFmt,
638 APTR dst, ULONG dstPitch,
639 ULONG width, ULONG height,
640 OOP_Class *cl, OOP_Object *o)
642 struct HIDDNouveauBitMapData * bmdata = OOP_INST_DATA(cl, o);
643 UBYTE dstBpp = bmdata->bytesperpixel;
645 switch(srcPixFmt)
647 case vHidd_StdPixFmt_Native:
648 switch(dstBpp)
650 case 1:
651 /* Not supported */
652 break;
654 case 2:
656 struct pHidd_BitMap_CopyMemBox16 __m =
658 SD(cl)->mid_CopyMemBox16, src, 0, 0, dst,
659 0, 0, width, height, srcPitch, dstPitch
660 }, *m = &__m;
661 OOP_DoMethod(o, (OOP_Msg)m);
663 break;
665 case 4:
667 struct pHidd_BitMap_CopyMemBox32 __m =
669 SD(cl)->mid_CopyMemBox32, src, 0, 0, dst,
670 0, 0, width, height, srcPitch, dstPitch
671 }, *m = &__m;
672 OOP_DoMethod(o, (OOP_Msg)m);
674 break;
676 } /* switch(data->bytesperpixel) */
677 break;
679 case vHidd_StdPixFmt_Native32:
680 switch(dstBpp)
682 case 1:
683 /* Not supported */
684 break;
686 case 2:
688 struct pHidd_BitMap_PutMem32Image16 __m =
690 SD(cl)->mid_PutMem32Image16, src, dst,
691 0, 0, width, height, srcPitch, dstPitch
692 }, *m = &__m;
693 OOP_DoMethod(o, (OOP_Msg)m);
695 break;
697 case 4:
699 struct pHidd_BitMap_CopyMemBox32 __m =
701 SD(cl)->mid_CopyMemBox32, src, 0, 0, dst,
702 0, 0, width, height, srcPitch, dstPitch
703 }, *m = &__m;
704 OOP_DoMethod(o, (OOP_Msg)m);
706 break;
708 } /* switch(data->bytesperpixel) */
709 break;
710 default:
712 /* Use ConvertPixels to convert that data to destination format */
713 APTR csrc = src;
714 APTR * psrc = &csrc;
715 APTR cdst = dst;
716 APTR * pdst = &cdst;
717 OOP_Object * dstPF = NULL;
718 OOP_Object * srcPF = NULL;
719 OOP_Object * gfxHidd = NULL;
720 struct pHidd_Gfx_GetPixFmt __gpf =
722 SD(cl)->mid_GetPixFmt, srcPixFmt
723 }, *gpf = &__gpf;
725 OOP_GetAttr(o, aHidd_BitMap_PixFmt, (APTR)&dstPF);
726 OOP_GetAttr(o, aHidd_BitMap_GfxHidd, (APTR)&gfxHidd);
727 srcPF = (OOP_Object *)OOP_DoMethod(gfxHidd, (OOP_Msg)gpf);
730 struct pHidd_BitMap_ConvertPixels __m =
732 SD(cl)->mid_ConvertPixels,
733 psrc, (HIDDT_PixelFormat *)srcPF, srcPitch,
734 pdst, (HIDDT_PixelFormat *)dstPF, dstPitch,
735 width, height, NULL
736 }, *m = &__m;
737 OOP_DoMethod(o, (OOP_Msg)m);
741 break;
744 return TRUE;
747 /* Assumes input and output buffers are lock-protected */
748 /* Takes pixels from source buffer, converts them and puts them into RAM
749 buffer. The source buffer can be in VRAM or GART or RAM */
750 BOOL HiddNouveauReadIntoRAM(
751 APTR src, ULONG srcPitch,
752 APTR dst, ULONG dstPitch, HIDDT_StdPixFmt dstPixFmt,
753 ULONG width, ULONG height,
754 OOP_Class *cl, OOP_Object *o)
756 struct HIDDNouveauBitMapData * bmdata = OOP_INST_DATA(cl, o);
757 UBYTE srcBpp = bmdata->bytesperpixel;
759 switch(dstPixFmt)
761 case vHidd_StdPixFmt_Native:
762 switch(srcBpp)
764 case 1:
765 /* Not supported */
766 break;
768 case 2:
770 struct pHidd_BitMap_CopyMemBox16 __m =
772 SD(cl)->mid_CopyMemBox16, src, 0, 0, dst,
773 0, 0, width, height, srcPitch, dstPitch
774 }, *m = &__m;
775 OOP_DoMethod(o, (OOP_Msg)m);
777 break;
779 case 4:
781 struct pHidd_BitMap_CopyMemBox32 __m =
783 SD(cl)->mid_CopyMemBox32, src, 0, 0, dst,
784 0, 0, width, height, srcPitch, dstPitch
785 }, *m = &__m;
786 OOP_DoMethod(o, (OOP_Msg)m);
788 break;
790 } /* switch(data->bytesperpixel) */
791 break;
793 case vHidd_StdPixFmt_Native32:
794 switch(srcBpp)
796 case 1:
797 /* Not supported */
798 break;
800 case 2:
802 struct pHidd_BitMap_GetMem32Image16 __m =
804 SD(cl)->mid_GetMem32Image16, src, 0, 0, dst,
805 width, height, srcPitch, dstPitch
806 }, *m = &__m;
807 OOP_DoMethod(o, (OOP_Msg)m);
809 break;
811 case 4:
813 struct pHidd_BitMap_CopyMemBox32 __m =
815 SD(cl)->mid_CopyMemBox32, src, 0, 0, dst,
816 0, 0, width, height, srcPitch, dstPitch
817 }, *m = &__m;
818 OOP_DoMethod(o, (OOP_Msg)m);
820 break;
822 } /* switch(data->bytesperpixel) */
823 break;
824 default:
826 /* Use ConvertPixels to convert that data to destination format */
827 APTR csrc = src;
828 APTR * psrc = &csrc;
829 APTR cdst = dst;
830 APTR * pdst = &cdst;
831 OOP_Object * dstPF = NULL;
832 OOP_Object * srcPF = NULL;
833 OOP_Object * gfxHidd = NULL;
834 struct pHidd_Gfx_GetPixFmt __gpf =
836 SD(cl)->mid_GetPixFmt, dstPixFmt
837 }, *gpf = &__gpf;
839 OOP_GetAttr(o, aHidd_BitMap_PixFmt, (APTR)&srcPF);
840 OOP_GetAttr(o, aHidd_BitMap_GfxHidd, (APTR)&gfxHidd);
841 dstPF = (OOP_Object *)OOP_DoMethod(gfxHidd, (OOP_Msg)gpf);
844 struct pHidd_BitMap_ConvertPixels __m =
846 SD(cl)->mid_ConvertPixels,
847 psrc, (HIDDT_PixelFormat *)srcPF, srcPitch,
848 pdst, (HIDDT_PixelFormat *)dstPF, dstPitch,
849 width, height, NULL
850 }, *m = &__m;
851 OOP_DoMethod(o, (OOP_Msg)m);
855 break;
858 return TRUE;
861 static inline VOID HiddNouveau3DCopyBoxFromGART(struct CardData * carddata,
862 struct HIDDNouveauBitMapData * dstdata, ULONG gartpitch,
863 LONG x, LONG y, LONG width, LONG height)
865 struct HIDDNouveauBitMapData srcdata;
867 /* Wrap GART */
868 srcdata.bo = carddata->GART;
869 srcdata.width = width;
870 srcdata.height = height;
871 srcdata.depth = 32;
872 srcdata.bytesperpixel = 4;
873 srcdata.pitch = gartpitch;
875 /* Render using 3D engine */
876 switch(carddata->architecture)
878 case(NV_ARCH_40):
879 HIDDNouveauNV403DCopyBox(carddata,
880 &srcdata, dstdata,
881 0, 0, x, y, width, height, BLENDOP_ALPHA);
882 break;
883 case(NV_ARCH_30):
884 HIDDNouveauNV303DCopyBox(carddata,
885 &srcdata, dstdata,
886 0, 0, x, y, width, height, BLENDOP_ALPHA);
887 break;
888 case(NV_ARCH_20):
889 case(NV_ARCH_10):
890 HIDDNouveauNV103DCopyBox(carddata,
891 &srcdata, dstdata,
892 0, 0, x, y, width, height, BLENDOP_ALPHA);
893 break;
897 /* NOTE: Assumes lock on bitmap is already made */
898 /* NOTE: Assumes lock on GART object is already made */
899 /* NOTE: Assumes buffer is not mapped */
900 BOOL HiddNouveauAccelARGBUpload3D(
901 UBYTE * srcpixels, ULONG srcpitch,
902 LONG x, LONG y, LONG width, LONG height,
903 OOP_Class *cl, OOP_Object *o)
905 struct HIDDNouveauBitMapData * dstdata = OOP_INST_DATA(cl, o);
906 struct CardData * carddata = &(SD(cl)->carddata);
907 unsigned cpp = 4; /* We are always getting ARGB buffer */
908 unsigned line_len = width * cpp;
909 /* Maximum DMA transfer */
910 unsigned line_count = carddata->GART->size / line_len;
911 char *src = (char *)srcpixels;
913 /* HW limitations */
914 if (line_count > 2047)
915 line_count = 2047;
917 while (height) {
918 char *dst;
920 if (line_count > height)
921 line_count = height;
923 /* Upload to GART */
924 if (nouveau_bo_map(carddata->GART, NOUVEAU_BO_WR))
925 return FALSE;
926 dst = carddata->GART->map;
928 #if AROS_BIG_ENDIAN
930 /* Just use copy. Memory formats match */
931 struct pHidd_BitMap_CopyMemBox32 __m =
933 SD(cl)->mid_CopyMemBox32, src, 0, 0, dst,
934 0, 0, width, height, srcpitch, line_len
935 }, *m = &__m;
936 OOP_DoMethod(o, (OOP_Msg)m);
938 #else
940 /* Use ConvertPixels to convert that data to destination format */
941 APTR csrc = src;
942 APTR * psrc = &csrc;
943 APTR cdst = dst;
944 APTR * pdst = &cdst;
945 OOP_Object * dstPF = NULL;
946 OOP_Object * srcPF = NULL;
947 OOP_Object * gfxHidd = NULL;
948 struct pHidd_Gfx_GetPixFmt __gpfsrc =
950 SD(cl)->mid_GetPixFmt, vHidd_StdPixFmt_BGRA32
951 }, *gpfsrc = &__gpfsrc;
952 struct pHidd_Gfx_GetPixFmt __gpfdst =
954 SD(cl)->mid_GetPixFmt, vHidd_StdPixFmt_ARGB32
955 }, *gpfdst = &__gpfdst;
957 OOP_GetAttr(o, aHidd_BitMap_GfxHidd, (APTR)&gfxHidd);
958 srcPF = (OOP_Object *)OOP_DoMethod(gfxHidd, (OOP_Msg)gpfsrc);
959 dstPF = (OOP_Object *)OOP_DoMethod(gfxHidd, (OOP_Msg)gpfdst);
962 struct pHidd_BitMap_ConvertPixels __m =
964 SD(cl)->mid_ConvertPixels,
965 psrc, (HIDDT_PixelFormat *)srcPF, srcpitch,
966 pdst, (HIDDT_PixelFormat *)dstPF, line_len,
967 width, height, NULL
968 }, *m = &__m;
969 OOP_DoMethod(o, (OOP_Msg)m);
972 #endif
974 src += srcpitch * line_count;
975 nouveau_bo_unmap(carddata->GART);
977 HiddNouveau3DCopyBoxFromGART(carddata, dstdata, line_len, x, y, width, line_count);
979 height -= line_count;
980 y += line_count;
983 return TRUE;
986 /* NOTE: Assumes lock on bitmap is already made */
987 /* NOTE: Assumes lock on GART object is already made */
988 /* NOTE: Assumes buffer is not mapped */
989 BOOL HiddNouveauAccelAPENUpload3D(
990 UBYTE * srcalpha, BOOL srcinvertalpha, ULONG srcpitch, ULONG srcpenrgb,
991 LONG x, LONG y, LONG width, LONG height,
992 OOP_Class *cl, OOP_Object *o)
994 struct HIDDNouveauBitMapData * dstdata = OOP_INST_DATA(cl, o);
995 struct CardData * carddata = &(SD(cl)->carddata);
996 unsigned cpp = 4; /* We are always getting ARGB buffer */
997 unsigned line_len = width * cpp;
998 /* Maximum DMA transfer */
999 unsigned line_count = carddata->GART->size / line_len;
1000 char *src = (char *)srcalpha;
1002 /* HW limitations */
1003 if (line_count > 2047)
1004 line_count = 2047;
1006 while (height) {
1007 char *dst;
1008 ULONG srcy, srcx;
1010 if (line_count > height)
1011 line_count = height;
1013 /* Upload to GART */
1014 if (nouveau_bo_map(carddata->GART, NOUVEAU_BO_WR))
1015 return FALSE;
1016 dst = carddata->GART->map;
1018 /* Draw data into GART */
1019 if (srcinvertalpha) /* Keep condition outside loop to improve performance */
1021 for (srcy = 0; srcy < line_count; srcy++)
1023 for (srcx = 0; srcx < width; srcx++)
1025 ULONG * pos = (ULONG *)(dst + (srcx * cpp));
1026 *pos = srcpenrgb | ((src[srcx] << 24) ^ 255);
1028 src += srcpitch;
1029 dst += line_len;
1032 else
1034 for (srcy = 0; srcy < line_count; srcy++)
1036 for (srcx = 0; srcx < width; srcx++)
1038 ULONG * pos = (ULONG *)(dst + (srcx * cpp));
1039 *pos = srcpenrgb | (src[srcx] << 24);
1041 src += srcpitch;
1042 dst += line_len;
1046 nouveau_bo_unmap(carddata->GART);
1048 HiddNouveau3DCopyBoxFromGART(carddata, dstdata, line_len, x, y, width, line_count);
1050 height -= line_count;
1051 y += line_count;
1054 return TRUE;
1057 #define POINT_OUTSIDE_CLIP(gc, x, y) \
1058 ( (x) < GC_CLIPX1(gc) \
1059 || (x) > GC_CLIPX2(gc) \
1060 || (y) < GC_CLIPY1(gc) \
1061 || (y) > GC_CLIPY2(gc) )
1063 /* NOTE: Assumes lock on bitmap is already made */
1064 /* NOTE: Assumes buffer is mapped */
1065 VOID HIDDNouveauBitMapDrawSolidLine(struct HIDDNouveauBitMapData * bmdata,
1066 OOP_Object * gc, LONG destX1, LONG destY1, LONG destX2, LONG destY2)
1068 WORD i;
1069 LONG x1, y1, x2, y2;
1070 ULONG fg; /* foreground pen */
1071 APTR doclip;
1073 IPTR map = (IPTR)bmdata->bo->map;
1075 doclip = GC_DOCLIP(gc);
1076 fg = GC_FG(gc);
1078 /* Normalize coords */
1079 if (destX1 > destX2)
1081 x1 = destX2; x2 = destX1;
1083 else
1085 x1 = destX1; x2 = destX2;
1088 if (destY1 > destY2)
1090 y1 = destY2; y2 = destY1;
1092 else
1094 y1 = destY1; y2 = destY2;
1097 if (doclip)
1099 /* If line is not inside cliprect, then just return */
1100 if ( x1 > GC_CLIPX2(gc)
1101 || x2 < GC_CLIPX1(gc)
1102 || y1 > GC_CLIPY2(gc)
1103 || y2 < GC_CLIPY1(gc) )
1106 /* Line is not inside cliprect, so just return */
1107 return;
1111 if (y1 == y2)
1114 Horizontal line drawing code.
1116 IPTR addr = map + (bmdata->pitch * y1) + (x1 * bmdata->bytesperpixel);
1118 for(i = x1; i != x2; i++)
1120 /* Pixel inside ? */
1121 if ((!doclip) || (!POINT_OUTSIDE_CLIP(gc, i, y1)))
1123 if (bmdata->bytesperpixel == 2)
1124 writew(fg, (APTR)addr);
1125 else
1126 writel(fg, (APTR)addr);
1128 addr += bmdata->bytesperpixel;
1131 else if (x1 == x2)
1134 Vertical line drawing code.
1136 IPTR addr = map + (bmdata->pitch * y1) + (x1 * bmdata->bytesperpixel);
1138 for(i = y1; i != y2; i++)
1140 /* Pixel inside ? */
1141 if (!doclip || !POINT_OUTSIDE_CLIP(gc, x1, i ))
1143 if (bmdata->bytesperpixel == 2)
1144 writew(fg, (APTR)addr);
1145 else
1146 writel(fg, (APTR)addr);
1148 addr += bmdata->pitch;
1151 else
1154 Generic line drawing code.
1156 WORD dx, dy, x, y, incrE, incrNE, d, s1, s2, t;
1157 IPTR addr;
1159 /* Restore original coordinates - important for non-straight lines as
1160 normalization might have switched them */
1161 x1 = destX1;
1162 y1 = destY1;
1163 x2 = destX2;
1164 y2 = destY2;
1166 /* Calculate slope */
1167 dx = abs(x2 - x1);
1168 dy = abs(y2 - y1);
1170 /* which direction? */
1171 if((x2 - x1) > 0) s1 = 1; else s1 = - 1;
1172 if((y2 - y1) > 0) s2 = 1; else s2 = - 1;
1174 /* change axes if dx < dy */
1175 if(dx < dy)
1177 d = dx;
1178 dx = dy;
1179 dy = d;
1180 t = 0;
1182 else
1184 t = 1;
1187 d = 2 * dy - dx; /* initial value of d */
1189 incrE = 2 * dy; /* Increment use for move to E */
1190 incrNE = 2 * (dy - dx); /* Increment use for move to NE */
1192 x = x1; y = y1;
1194 for(i = 0; i <= dx; i++)
1196 /* Pixel inside ? */
1197 if (!doclip || !POINT_OUTSIDE_CLIP(gc, x, y ))
1199 addr = map + (x * bmdata->bytesperpixel) + (bmdata->pitch * y);
1200 if (bmdata->bytesperpixel == 2)
1201 writew(fg, (APTR)addr);
1202 else
1203 writel(fg, (APTR)addr);
1206 if(d <= 0)
1208 if(t == 1)
1210 x = x + s1;
1212 else
1214 y = y + s2;
1217 d = d + incrE;
1219 else
1221 x = x + s1;
1222 y = y + s2;
1223 d = d + incrNE;