Hint added.
[AROS.git] / workbench / hidds / nouveau / xf86-video-nouveau / nv10_exa.c
blob8441528d62c31d487665f506372703bf6060e9f1
1 /*
2 * Copyright 2007 Stephane Marchesin
3 * Copyright 2007 Arthur Huillet
4 * Copyright 2007 Peter Winters
5 * Copyright 2009 Francisco Jerez
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
22 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
26 #ifdef HAVE_CONFIG_H
27 #include "config.h"
28 #endif
30 #include "nv_include.h"
31 #include "nv04_pushbuf.h"
33 /* Texture/Render target formats. */
34 static struct pict_format {
35 int exa;
36 int hw;
37 } nv10_tex_format_pot[] = {
38 { PICT_a8, 0x80 },
39 { PICT_r5g6b5, 0x280 },
40 { PICT_x8r8g8b8, 0x300 },
41 { PICT_a8r8g8b8, 0x300 },
42 {},
44 }, nv10_tex_format_rect[] = {
45 { PICT_a8, 0x980 },
46 { PICT_r5g6b5, 0x880 },
47 { PICT_x8r8g8b8, 0x900 },
48 { PICT_a8r8g8b8, 0x900 },
49 {},
51 }, nv20_tex_format_rect[] = {
52 { PICT_a8, 0xd80 },
53 { PICT_r5g6b5, 0x880 },
54 { PICT_x8r8g8b8, 0x900 },
55 { PICT_a8r8g8b8, 0x900 },
56 {},
58 }, nv10_rt_format[] = {
59 { PICT_r5g6b5, 0x103 },
60 { PICT_x8r8g8b8, 0x108 },
61 { PICT_a8r8g8b8, 0x108 },
62 {},
65 static int
66 get_tex_format(PicturePtr pict)
68 #if !defined(__AROS__)
69 ScrnInfoPtr pScrn = xf86Screens[pict->pDrawable->pScreen->myNum];
70 #else
71 ScrnInfoPtr pScrn = globalcarddataptr;
72 #endif
73 NVPtr pNv = NVPTR(pScrn);
75 /* If repeat is set we're always handling a 1x1 texture with
76 * ARGB/XRGB destination, in that case we change the format to
77 * use the POT (swizzled) matching format.
79 struct pict_format *format =
80 pict->repeat != RepeatNone ? nv10_tex_format_pot :
81 pNv->Architecture == NV_ARCH_20 ? nv20_tex_format_rect :
82 nv10_tex_format_rect;
84 for (; format->hw; format++) {
85 if (format->exa == pict->format)
86 return format->hw;
89 return 0;
92 static int
93 get_rt_format(PicturePtr pict)
95 struct pict_format *format = nv10_rt_format;
97 for (; format->hw; format++) {
98 if (format->exa == pict->format)
99 return format->hw;
102 return 0;
105 /* Blending functions. */
106 #define SF(x) NV10TCL_BLEND_FUNC_SRC_##x
107 #define DF(x) NV10TCL_BLEND_FUNC_DST_##x
109 static struct pict_op {
110 int src;
111 int dst;
113 } nv10_pict_op[] = {
114 { SF(ZERO), DF(ZERO) }, /* Clear */
115 { SF(ONE), DF(ZERO) }, /* Src */
116 { SF(ZERO), DF(ONE) }, /* Dst */
117 { SF(ONE), DF(ONE_MINUS_SRC_ALPHA) }, /* Over */
118 { SF(ONE_MINUS_DST_ALPHA), DF(ONE) }, /* OverReverse */
119 { SF(DST_ALPHA), DF(ZERO) }, /* In */
120 { SF(ZERO), DF(SRC_ALPHA) }, /* InReverse */
121 { SF(ONE_MINUS_DST_ALPHA), DF(ZERO) }, /* Out */
122 { SF(ZERO), DF(ONE_MINUS_SRC_ALPHA) }, /* OutReverse */
123 { SF(DST_ALPHA), DF(ONE_MINUS_SRC_ALPHA) }, /* Atop */
124 { SF(ONE_MINUS_DST_ALPHA), DF(SRC_ALPHA) }, /* AtopReverse */
125 { SF(ONE_MINUS_DST_ALPHA), DF(ONE_MINUS_SRC_ALPHA) }, /* Xor */
126 { SF(ONE), DF(ONE) }, /* Add */
127 { SF(SRC_ALPHA), DF(ONE_MINUS_SRC_ALPHA) }, /* OverAlpha */
130 static inline Bool
131 needs_src_alpha(int op)
133 return nv10_pict_op[op].dst == DF(ONE_MINUS_SRC_ALPHA)
134 || nv10_pict_op[op].dst == DF(SRC_ALPHA);
137 static inline Bool
138 needs_src(int op)
140 return nv10_pict_op[op].src != DF(ZERO);
143 static inline Bool
144 effective_component_alpha(PicturePtr mask)
146 return mask && mask->componentAlpha && PICT_FORMAT_RGB(mask->format);
149 #if !defined(__AROS__)
150 static Bool
151 check_texture(PicturePtr pict)
153 int w, h;
155 if (!pict->pDrawable)
156 NOUVEAU_FALLBACK("Solid and gradient pictures unsupported\n");
158 w = pict->pDrawable->width;
159 h = pict->pDrawable->height;
161 if (w > 2046 || h > 2046)
162 NOUVEAU_FALLBACK("picture too large, %dx%d\n", w, h);
164 if (!get_tex_format(pict))
165 return FALSE;
167 if (pict->filter != PictFilterNearest &&
168 pict->filter != PictFilterBilinear)
169 return FALSE;
171 /* We cannot repeat on NV10 because NPOT textures do not
172 * support this. unfortunately. */
173 if (pict->repeat != RepeatNone)
174 /* we can repeat 1x1 textures */
175 if (!(w == 1 && h == 1))
176 return FALSE;
178 return TRUE;
181 static Bool
182 check_render_target(PicturePtr pict)
184 int w = pict->pDrawable->width;
185 int h = pict->pDrawable->height;
187 if (w > 4096 || h > 4096)
188 return FALSE;
190 if (!get_rt_format(pict))
191 return FALSE;
193 return TRUE;
196 static Bool
197 check_pict_op(int op)
199 /* We do no saturate, disjoint, conjoint, though we
200 * could do e.g. DisjointClear which really is
201 * Clear. */
202 return op < PictOpSaturate;
205 #if 0
206 static void
207 print_fallback_info(char *reason, int op, PicturePtr src, PicturePtr mask,
208 PicturePtr dst)
210 char out2[4096];
211 char *out = out2;
213 sprintf(out, "%s ", reason);
214 out += strlen(out);
216 switch (op) {
217 case PictOpClear:
218 sprintf(out, "PictOpClear ");
219 break;
220 case PictOpSrc:
221 sprintf(out, "PictOpSrc ");
222 break;
223 case PictOpDst:
224 sprintf(out, "PictOpDst ");
225 break;
226 case PictOpOver:
227 sprintf(out, "PictOpOver ");
228 break;
229 case PictOpOutReverse:
230 sprintf(out, "PictOpOutReverse ");
231 break;
232 case PictOpAdd:
233 sprintf(out, "PictOpAdd ");
234 break;
235 default:
236 sprintf(out, "PictOp%d ", op);
238 out += strlen(out);
240 switch (src->format) {
241 case PICT_a8r8g8b8:
242 sprintf(out, "A8R8G8B8 ");
243 break;
244 case PICT_x8r8g8b8:
245 sprintf(out, "X8R8G8B8 ");
246 break;
247 case PICT_x8b8g8r8:
248 sprintf(out, "X8B8G8R8 ");
249 break;
250 case PICT_r5g6b5:
251 sprintf(out, "R5G6B5 ");
252 break;
253 case PICT_a8:
254 sprintf(out, "A8 ");
255 break;
256 case PICT_a1:
257 sprintf(out, "A1 ");
258 break;
259 default:
260 sprintf(out, "%x ", src->format);
262 out += strlen(out);
264 sprintf(out, "(%dx%d) ", src->pDrawable->width,
265 src->pDrawable->height);
266 if (src->repeat != RepeatNone)
267 strcat(out, "R ");
268 strcat(out, "-> ");
269 out += strlen(out);
271 switch (dst->format) {
272 case PICT_a8r8g8b8:
273 sprintf(out, "A8R8G8B8 ");
274 break;
275 case PICT_x8r8g8b8:
276 sprintf(out, "X8R8G8B8 ");
277 break;
278 case PICT_x8b8g8r8:
279 sprintf(out, "X8B8G8R8 ");
280 break;
281 case PICT_r5g6b5:
282 sprintf(out, "R5G6B5 ");
283 break;
284 case PICT_a8:
285 sprintf(out, "A8 ");
286 break;
287 case PICT_a1:
288 sprintf(out, "A1 ");
289 break;
290 default:
291 sprintf(out, "%x ", dst->format);
293 out += strlen(out);
295 sprintf(out, "(%dx%d) ", dst->pDrawable->width,
296 dst->pDrawable->height);
297 if (dst->repeat != RepeatNone)
298 strcat(out, "R ");
299 out += strlen(out);
301 if (!mask)
302 sprintf(out, "& NONE");
303 else {
304 switch (mask->format) {
305 case PICT_a8r8g8b8:
306 sprintf(out, "& A8R8G8B8 ");
307 break;
308 case PICT_x8r8g8b8:
309 sprintf(out, "& X8R8G8B8 ");
310 break;
311 case PICT_x8b8g8r8:
312 sprintf(out, "& X8B8G8R8 ");
313 break;
314 case PICT_a8:
315 sprintf(out, "& A8 ");
316 break;
317 case PICT_a1:
318 sprintf(out, "& A1 ");
319 break;
320 default:
321 sprintf(out, "& %x ", mask->format);
323 out += strlen(out);
325 sprintf(out, "(%dx%d) ", mask->pDrawable->width,
326 mask->pDrawable->height);
327 if (mask->repeat != RepeatNone)
328 strcat(out, "R ");
329 if (mask->componentAlpha)
330 strcat(out, "C ");
331 out += strlen(out);
333 strcat(out, "\n");
335 xf86DrvMsg(0, X_INFO, "%s", out2);
337 #else
338 #define print_fallback_info(...)
339 #endif
341 Bool
342 NV10EXACheckComposite(int op, PicturePtr src, PicturePtr mask, PicturePtr dst)
344 if (!check_pict_op(op)) {
345 print_fallback_info("pictop", op, src, mask, dst);
346 return FALSE;
349 if (!check_render_target(dst)) {
350 print_fallback_info("dst", op, src, mask, dst);
351 return FALSE;
354 if (!check_texture(src)) {
355 print_fallback_info("src", op, src, mask, dst);
356 return FALSE;
359 if (mask) {
360 if (!check_texture(mask)) {
361 print_fallback_info("mask", op, src,
362 mask, dst);
363 return FALSE;
366 if (effective_component_alpha(mask) &&
367 needs_src(op) && needs_src_alpha(op)) {
368 print_fallback_info("ca-mask", op, src,
369 mask, dst);
370 return FALSE;
374 print_fallback_info("Accelerating", op, src, mask, dst);
375 return TRUE;
377 #endif
379 static Bool
380 setup_texture(NVPtr pNv, int unit, PicturePtr pict, PixmapPtr pixmap)
382 struct nouveau_channel *chan = pNv->chan;
383 struct nouveau_grobj *celsius = pNv->Nv3D;
384 struct nouveau_bo *bo = nouveau_pixmap_bo(pixmap);
385 unsigned tex_reloc = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
386 #if !defined(__AROS__)
387 long w = pict->pDrawable->width,
388 h = pict->pDrawable->height;
389 #else
390 long w = pixmap->width,
391 h = pixmap->height;
392 #endif
393 unsigned int txfmt =
394 NV10TCL_TX_FORMAT_WRAP_T_CLAMP_TO_EDGE |
395 NV10TCL_TX_FORMAT_WRAP_S_CLAMP_TO_EDGE |
396 log2i(w) << 20 | log2i(h) << 16 |
397 1 << 12 | /* lod == 1 */
398 get_tex_format(pict) |
399 0x50 /* UNK */;
401 BEGIN_RING(chan, celsius, NV10TCL_TX_OFFSET(unit), 1);
402 if (OUT_RELOCl(chan, bo, 0, tex_reloc))
403 return FALSE;
405 if (pict->repeat == RepeatNone) {
406 /* NPOT_SIZE expects an even number for width, we can
407 * round up uneven numbers here because EXA always
408 * gives 64 byte aligned pixmaps and for all formats
409 * we support 64 bytes represents an even number of
410 * pixels
412 w = (w + 1) &~ 1;
414 BEGIN_RING(chan, celsius, NV10TCL_TX_NPOT_PITCH(unit), 1);
415 OUT_RING (chan, exaGetPixmapPitch(pixmap) << 16);
417 BEGIN_RING(chan, celsius, NV10TCL_TX_NPOT_SIZE(unit), 1);
418 OUT_RING (chan, w << 16 | h);
421 BEGIN_RING(chan, celsius, NV10TCL_TX_FORMAT(unit), 1 );
422 if (OUT_RELOCd(chan, bo, txfmt, tex_reloc | NOUVEAU_BO_OR,
423 NV10TCL_TX_FORMAT_DMA0, NV10TCL_TX_FORMAT_DMA1))
424 return FALSE;
426 BEGIN_RING(chan, celsius, NV10TCL_TX_ENABLE(unit), 1 );
427 OUT_RING (chan, NV10TCL_TX_ENABLE_ENABLE);
429 BEGIN_RING(chan, celsius, NV10TCL_TX_FILTER(unit), 1);
430 if (pict->filter == PictFilterNearest)
431 OUT_RING(chan, (NV10TCL_TX_FILTER_MAGNIFY_NEAREST |
432 NV10TCL_TX_FILTER_MINIFY_NEAREST));
433 else
434 OUT_RING(chan, (NV10TCL_TX_FILTER_MAGNIFY_LINEAR |
435 NV10TCL_TX_FILTER_MINIFY_LINEAR));
437 return TRUE;
440 static Bool
441 setup_render_target(NVPtr pNv, PicturePtr pict, PixmapPtr pixmap)
443 struct nouveau_channel *chan = pNv->chan;
444 struct nouveau_grobj *celsius = pNv->Nv3D;
445 struct nouveau_bo *bo = nouveau_pixmap_bo(pixmap);
447 BEGIN_RING(chan, celsius, NV10TCL_RT_FORMAT, 2);
448 OUT_RING (chan, get_rt_format(pict));
449 OUT_RING (chan, (exaGetPixmapPitch(pixmap) << 16 |
450 exaGetPixmapPitch(pixmap)));
452 BEGIN_RING(chan, celsius, NV10TCL_COLOR_OFFSET, 1);
453 if (OUT_RELOCl(chan, bo, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR))
454 return FALSE;
456 return TRUE;
460 * This can be a bit difficult to understand at first glance. Reg
461 * combiners are described here:
462 * http://icps.u-strasbg.fr/~marchesin/perso/extensions/NV/register_combiners.html
464 * Single texturing setup, without honoring vertex colors (non default
465 * setup) is: Alpha RC 0 : a_0 * 1 + 0 * 0 RGB RC 0 : rgb_0 * 1 + 0 *
466 * 0 RC 1s are unused Final combiner uses default setup
468 * Default setup uses vertex rgb/alpha in place of 1s above, but we
469 * don't need that in 2D.
471 * Multi texturing setup, where we do TEX0 in TEX1 (masking) is:
472 * Alpha RC 0 : a_0 * a_1 + 0 * 0
473 * RGB RC0 : rgb_0 * a_1 + 0 * 0
474 * RC 1s are unused
475 * Final combiner uses default setup
478 /* Bind the combiner variable <input> to a constant 1. */
479 #define RC_IN_ONE(input) \
480 (NV10TCL_RC_IN_RGB_##input##_INPUT_ZERO | \
481 NV10TCL_RC_IN_RGB_##input##_COMPONENT_USAGE_ALPHA | \
482 NV10TCL_RC_IN_RGB_##input##_MAPPING_UNSIGNED_INVERT)
484 /* Bind the combiner variable <input> to the specified channel from
485 * the texture unit <unit>. */
486 #define RC_IN_TEX(input, chan, unit) \
487 (NV10TCL_RC_IN_RGB_##input##_INPUT_TEXTURE##unit | \
488 NV10TCL_RC_IN_RGB_##input##_COMPONENT_USAGE_##chan)
490 /* Bind the combiner variable <input> to the specified channel from
491 * the constant color <unit>. */
492 #define RC_IN_COLOR(input, chan, unit) \
493 (NV10TCL_RC_IN_RGB_##input##_INPUT_CONSTANT_COLOR##unit | \
494 NV10TCL_RC_IN_RGB_##input##_COMPONENT_USAGE_##chan)
496 #if !defined(__AROS__)
497 static void
498 setup_combiners(NVPtr pNv, PicturePtr src, PicturePtr mask)
499 #else
500 static void
501 setup_combiners(NVPtr pNv, PicturePtr src, PicturePtr mask, int op)
502 #endif
504 struct nouveau_channel *chan = pNv->chan;
505 struct nouveau_grobj *celsius = pNv->Nv3D;
506 uint32_t rc_in_alpha = 0, rc_in_rgb = 0;
508 if (PICT_FORMAT_A(src->format))
509 rc_in_alpha |= RC_IN_TEX(A, ALPHA, 0);
510 else
511 rc_in_alpha |= RC_IN_ONE(A);
513 if (mask && PICT_FORMAT_A(mask->format))
514 rc_in_alpha |= RC_IN_TEX(B, ALPHA, 1);
515 else
516 rc_in_alpha |= RC_IN_ONE(B);
518 if (effective_component_alpha(mask)) {
519 #if !defined(__AROS__)
520 if (!needs_src_alpha(pNv->alu)) {
521 #else
522 if (!needs_src_alpha(op)) {
523 #endif
524 /* The alpha channels won't be used for blending. Drop
525 * them, as our pixels only have 4 components...
526 * output_i = src_i * mask_i
528 if (PICT_FORMAT_RGB(src->format))
529 rc_in_rgb |= RC_IN_TEX(A, RGB, 0);
530 } else {
531 /* The RGB channels won't be used for blending. Drop
532 * them.
533 * output_i = src_alpha * mask_i
535 if (PICT_FORMAT_A(src->format))
536 rc_in_rgb |= RC_IN_TEX(A, ALPHA, 0);
537 else
538 rc_in_rgb |= RC_IN_ONE(A);
541 rc_in_rgb |= RC_IN_TEX(B, RGB, 1);
543 } else {
544 if (PICT_FORMAT_RGB(src->format))
545 rc_in_rgb |= RC_IN_TEX(A, RGB, 0);
547 if (mask && PICT_FORMAT_A(mask->format))
548 rc_in_rgb |= RC_IN_TEX(B, ALPHA, 1);
549 else
550 rc_in_rgb |= RC_IN_ONE(B);
553 BEGIN_RING(chan, celsius, NV10TCL_RC_IN_ALPHA(0), 1);
554 OUT_RING (chan, rc_in_alpha);
555 BEGIN_RING(chan, celsius, NV10TCL_RC_IN_RGB(0), 1);
556 OUT_RING (chan, rc_in_rgb);
559 #if !defined(__AROS__)
560 static void
561 setup_blend_function(NVPtr pNv)
562 #else
563 static void
564 setup_blend_function(NVPtr pNv, PicturePtr dst, PicturePtr mask, int blendop)
565 #endif
567 struct nouveau_channel *chan = pNv->chan;
568 struct nouveau_grobj *celsius = pNv->Nv3D;
569 #if !defined(__AROS__)
570 struct pict_op *op = &nv10_pict_op[pNv->alu];
571 #else
572 struct pict_op *op = &nv10_pict_op[blendop];
573 #endif
574 int src_factor = op->src;
575 int dst_factor = op->dst;
577 if (src_factor == SF(ONE_MINUS_DST_ALPHA) &&
578 #if !defined(__AROS__)
579 !PICT_FORMAT_A(pNv->pdpict->format))
580 #else
581 !PICT_FORMAT_A(dst->format))
582 #endif
583 /* ONE_MINUS_DST_ALPHA doesn't always do the right thing for
584 * framebuffers without alpha channel. But it's the same as
585 * ZERO in that case.
587 src_factor = SF(ZERO);
589 #if !defined(__AROS__)
590 if (effective_component_alpha(pNv->pmpict)) {
591 #else
592 if (effective_component_alpha(mask)) {
593 #endif
594 if (dst_factor == DF(SRC_ALPHA))
595 dst_factor = DF(SRC_COLOR);
596 else if (dst_factor == DF(ONE_MINUS_SRC_ALPHA))
597 dst_factor = DF(ONE_MINUS_SRC_COLOR);
600 BEGIN_RING(chan, celsius, NV10TCL_BLEND_FUNC_SRC, 2);
601 OUT_RING (chan, src_factor);
602 OUT_RING (chan, dst_factor);
603 BEGIN_RING(chan, celsius, NV10TCL_BLEND_FUNC_ENABLE, 1);
604 OUT_RING (chan, 1);
607 #if !defined(__AROS__)
608 static void
609 NV10StateCompositeReemit(struct nouveau_channel *chan)
611 ScrnInfoPtr pScrn = chan->user_private;
612 NVPtr pNv = NVPTR(pScrn);
614 NV10EXAPrepareComposite(pNv->alu, pNv->pspict, pNv->pmpict, pNv->pdpict,
615 pNv->pspix, pNv->pmpix, pNv->pdpix);
617 #endif
619 Bool
620 NV10EXAPrepareComposite(int op,
621 PicturePtr pict_src,
622 PicturePtr pict_mask,
623 PicturePtr pict_dst,
624 PixmapPtr src,
625 PixmapPtr mask,
626 PixmapPtr dst)
628 #if !defined(__AROS__)
629 ScrnInfoPtr pScrn = xf86Screens[dst->drawable.pScreen->myNum];
630 #else
631 ScrnInfoPtr pScrn = globalcarddataptr;
632 #endif
633 NVPtr pNv = NVPTR(pScrn);
634 struct nouveau_channel *chan = pNv->chan;
636 if (MARK_RING(chan, 128, 5))
637 return FALSE;
639 #if !defined(__AROS__)
640 pNv->alu = op;
641 pNv->pspict = pict_src;
642 pNv->pmpict = pict_mask;
643 pNv->pdpict = pict_dst;
644 pNv->pspix = src;
645 pNv->pmpix = mask;
646 pNv->pdpix = dst;
647 #endif
649 /* Set dst format */
650 if (!setup_render_target(pNv, pict_dst, dst))
651 goto fail;
653 /* Set src format */
654 if (!setup_texture(pNv, 0, pict_src, src))
655 goto fail;
657 /* Set mask format */
658 if (mask &&
659 !setup_texture(pNv, 1, pict_mask, mask))
660 goto fail;
662 #if !defined(__AROS__)
663 /* Set the register combiners up. */
664 setup_combiners(pNv, pict_src, pict_mask);
666 /* Set PictOp */
667 setup_blend_function(pNv);
669 chan->flush_notify = NV10StateCompositeReemit;
670 #else
671 /* Set the register combiners up. */
672 setup_combiners(pNv, pict_src, pict_mask, op);
674 /* Set PictOp */
675 setup_blend_function(pNv, pict_dst, pict_mask, op);
677 chan->flush_notify = NULL;
678 #endif
680 return TRUE;
682 fail:
683 MARK_UNDO(chan);
685 return FALSE;
688 #if defined(__AROS__)
689 /* WARNING: These defines are only used to hack QUAD/MAP/OUT_RINGi defines
690 in this use case. They WILL NOT work in generic case. DO NOT reuse them. */
691 struct _PictVector
693 float vector[3];
695 typedef struct _PictVector PictVector;
696 #define xFixed1 0.0f
697 #define xFixedFrac(x) 0
698 #define xFixedToInt(x) (x)
699 #define IntToxFixed(x) (float)(x)
700 #endif
702 #define QUAD(x, y, w, h) \
703 {{{ IntToxFixed(x), IntToxFixed(y), xFixed1 }}, \
704 {{ IntToxFixed(x + w), IntToxFixed(y), xFixed1 }}, \
705 {{ IntToxFixed(x + w), IntToxFixed(y + h), xFixed1 }}, \
706 {{ IntToxFixed(x), IntToxFixed(y + h), xFixed1 }}}
708 #define MAP(f, p, v, ...) do { \
709 int __i; \
710 for (__i = 0; __i < sizeof(v)/sizeof((v)[0]); __i++) \
711 f(p, __i, v, ## __VA_ARGS__); \
712 } while (0);
714 #define xFixedToFloat(v) \
715 ((float)xFixedToInt((v)) + ((float)xFixedFrac(v) / 65536.0))
717 #define OUT_RINGi(chan, v, i) \
718 OUT_RINGf(chan, xFixedToFloat((v).vector[i]))
720 static inline void
721 emit_vertex(NVPtr pNv, int i, PictVector pos[],
722 PictVector tex0[], PictVector tex1[])
724 struct nouveau_channel *chan = pNv->chan;
725 struct nouveau_grobj *celsius = pNv->Nv3D;
727 BEGIN_RING(chan, celsius, NV10TCL_VERTEX_TX0_2F_S, 2);
728 OUT_RINGi (chan, tex0[i], 0);
729 OUT_RINGi (chan, tex0[i], 1);
731 if (tex1) {
732 BEGIN_RING(chan, celsius, NV10TCL_VERTEX_TX1_2F_S, 2);
733 OUT_RINGi (chan, tex1[i], 0);
734 OUT_RINGi (chan, tex1[i], 1);
737 BEGIN_RING(chan, celsius, NV10TCL_VERTEX_POS_3F_X, 3);
738 OUT_RINGi (chan, pos[i], 0);
739 OUT_RINGi (chan, pos[i], 1);
740 OUT_RINGf (chan, 0);
743 #if !defined(__AROS__)
744 static inline void
745 transform_vertex(PictTransformPtr t, int i, PictVector vs[])
747 if (t)
748 PictureTransformPoint(t, &vs[i]);
751 void
752 NV10EXAComposite(PixmapPtr pix_dst,
753 int srcX, int srcY,
754 int maskX, int maskY,
755 int dstX, int dstY,
756 int width, int height)
758 ScrnInfoPtr pScrn = xf86Screens[pix_dst->drawable.pScreen->myNum];
759 #else
760 static void
761 NV10EXAComposite(PixmapPtr pix_dst,
762 int srcX, int srcY,
763 int maskX, int maskY,
764 int dstX, int dstY,
765 int width, int height,
766 PicturePtr src, PicturePtr mask)
768 ScrnInfoPtr pScrn = globalcarddataptr;
769 #endif
770 NVPtr pNv = NVPTR(pScrn);
771 struct nouveau_channel *chan = pNv->chan;
772 struct nouveau_grobj *celsius = pNv->Nv3D;
773 #if !defined(__AROS__)
774 PicturePtr mask = pNv->pmpict,
775 src = pNv->pspict;
776 #endif
777 PictVector dstq[4] = QUAD(dstX, dstY, width, height),
778 maskq[4] = QUAD(maskX, maskY, width, height),
779 srcq[4] = QUAD(srcX, srcY, width, height);
781 #if !defined(__AROS__)
782 /* We are not doing any transformations */
783 MAP(transform_vertex, src->transform, srcq);
784 if (mask)
785 MAP(transform_vertex, mask->transform, maskq);
786 #endif
788 WAIT_RING (chan, 64);
789 BEGIN_RING(chan, celsius, NV10TCL_VERTEX_BEGIN_END, 1);
790 OUT_RING (chan, NV10TCL_VERTEX_BEGIN_END_QUADS);
792 MAP(emit_vertex, pNv, dstq, srcq, mask ? maskq : NULL);
794 BEGIN_RING(chan, celsius, NV10TCL_VERTEX_BEGIN_END, 1);
795 OUT_RING (chan, NV10TCL_VERTEX_BEGIN_END_STOP);
798 #if !defined(__AROS__)
799 void
800 NV10EXADoneComposite(PixmapPtr dst)
802 ScrnInfoPtr pScrn = xf86Screens[dst->drawable.pScreen->myNum];
803 NVPtr pNv = NVPTR(pScrn);
804 struct nouveau_channel *chan = pNv->chan;
806 chan->flush_notify = NULL;
808 #endif
810 Bool
811 NVAccelInitNV10TCL(ScrnInfoPtr pScrn)
813 NVPtr pNv = NVPTR(pScrn);
814 struct nouveau_channel *chan = pNv->chan;
815 struct nouveau_grobj *celsius;
816 uint32_t class = 0;
817 int i;
819 if (((pNv->dev->chipset & 0xf0) != NV_ARCH_10) &&
820 ((pNv->dev->chipset & 0xf0) != NV_ARCH_20))
821 return FALSE;
823 if (pNv->dev->chipset >= 0x20 || pNv->dev->chipset == 0x1a)
824 class = NV11TCL;
825 else if (pNv->dev->chipset >= 0x17)
826 class = NV17TCL;
827 else if (pNv->dev->chipset >= 0x11)
828 class = NV11TCL;
829 else
830 class = NV10TCL;
832 if (!pNv->Nv3D) {
833 if (nouveau_grobj_alloc(pNv->chan, Nv3D, class, &pNv->Nv3D))
834 return FALSE;
836 celsius = pNv->Nv3D;
838 BEGIN_RING(chan, celsius, NV10TCL_DMA_NOTIFY, 1);
839 OUT_RING (chan, chan->nullobj->handle);
841 BEGIN_RING(chan, celsius, NV10TCL_DMA_IN_MEMORY0, 2);
842 OUT_RING (chan, pNv->chan->vram->handle);
843 OUT_RING (chan, pNv->chan->gart->handle);
845 BEGIN_RING(chan, celsius, NV10TCL_DMA_IN_MEMORY2, 2);
846 OUT_RING (chan, pNv->chan->vram->handle);
847 OUT_RING (chan, pNv->chan->vram->handle);
849 BEGIN_RING(chan, celsius, NV10TCL_NOP, 1);
850 OUT_RING (chan, 0);
852 BEGIN_RING(chan, celsius, NV10TCL_RT_HORIZ, 2);
853 OUT_RING (chan, 2048 << 16 | 0);
854 OUT_RING (chan, 2048 << 16 | 0);
856 BEGIN_RING(chan, celsius, NV10TCL_ZETA_OFFSET, 1);
857 OUT_RING (chan, 0);
859 BEGIN_RING(chan, celsius, NV10TCL_VIEWPORT_CLIP_MODE, 1);
860 OUT_RING (chan, 0);
862 BEGIN_RING(chan, celsius, NV10TCL_VIEWPORT_CLIP_HORIZ(0), 1);
863 OUT_RING (chan, 0x7ff << 16 | 0x800800);
864 BEGIN_RING(chan, celsius, NV10TCL_VIEWPORT_CLIP_VERT(0), 1);
865 OUT_RING (chan, 0x7ff << 16 | 0x800800);
867 for (i = 1; i < 8; i++) {
868 BEGIN_RING(chan, celsius, NV10TCL_VIEWPORT_CLIP_HORIZ(i), 1);
869 OUT_RING (chan, 0);
870 BEGIN_RING(chan, celsius, NV10TCL_VIEWPORT_CLIP_VERT(i), 1);
871 OUT_RING (chan, 0);
874 BEGIN_RING(chan, celsius, 0x290, 1);
875 OUT_RING (chan, (0x10<<16)|1);
876 BEGIN_RING(chan, celsius, 0x3f4, 1);
877 OUT_RING (chan, 0);
879 BEGIN_RING(chan, celsius, NV10TCL_NOP, 1);
880 OUT_RING (chan, 0);
882 if (class != NV10TCL) {
883 /* For nv11, nv17 */
884 BEGIN_RING(chan, celsius, 0x120, 3);
885 OUT_RING (chan, 0);
886 OUT_RING (chan, 1);
887 OUT_RING (chan, 2);
889 BEGIN_RING(chan, pNv->NvImageBlit, 0x120, 3);
890 OUT_RING (chan, 0);
891 OUT_RING (chan, 1);
892 OUT_RING (chan, 2);
894 BEGIN_RING(chan, celsius, NV10TCL_NOP, 1);
895 OUT_RING (chan, 0);
898 BEGIN_RING(chan, celsius, NV10TCL_NOP, 1);
899 OUT_RING (chan, 0);
901 /* Set state */
902 BEGIN_RING(chan, celsius, NV10TCL_FOG_ENABLE, 1);
903 OUT_RING (chan, 0);
904 BEGIN_RING(chan, celsius, NV10TCL_ALPHA_FUNC_ENABLE, 1);
905 OUT_RING (chan, 0);
906 BEGIN_RING(chan, celsius, NV10TCL_ALPHA_FUNC_FUNC, 2);
907 OUT_RING (chan, 0x207);
908 OUT_RING (chan, 0);
909 BEGIN_RING(chan, celsius, NV10TCL_TX_ENABLE(0), 2);
910 OUT_RING (chan, 0);
911 OUT_RING (chan, 0);
912 BEGIN_RING(chan, celsius, NV10TCL_RC_IN_ALPHA(0), 6);
913 OUT_RING (chan, 0);
914 OUT_RING (chan, 0);
915 OUT_RING (chan, 0);
916 OUT_RING (chan, 0);
917 OUT_RING (chan, 0);
918 OUT_RING (chan, 0);
919 BEGIN_RING(chan, celsius, NV10TCL_RC_OUT_ALPHA(0), 6);
920 OUT_RING (chan, 0x00000c00);
921 OUT_RING (chan, 0);
922 OUT_RING (chan, 0x00000c00);
923 OUT_RING (chan, 0x18000000);
924 OUT_RING (chan, 0x300c0000);
925 OUT_RING (chan, 0x00001c80);
926 BEGIN_RING(chan, celsius, NV10TCL_BLEND_FUNC_ENABLE, 1);
927 OUT_RING (chan, 0);
928 BEGIN_RING(chan, celsius, NV10TCL_DITHER_ENABLE, 2);
929 OUT_RING (chan, 1);
930 OUT_RING (chan, 0);
931 BEGIN_RING(chan, celsius, NV10TCL_LINE_SMOOTH_ENABLE, 1);
932 OUT_RING (chan, 0);
933 BEGIN_RING(chan, celsius, NV10TCL_VERTEX_WEIGHT_ENABLE, 2);
934 OUT_RING (chan, 0);
935 OUT_RING (chan, 0);
936 BEGIN_RING(chan, celsius, NV10TCL_BLEND_FUNC_SRC, 4);
937 OUT_RING (chan, 1);
938 OUT_RING (chan, 0);
939 OUT_RING (chan, 0);
940 OUT_RING (chan, 0x8006);
941 BEGIN_RING(chan, celsius, NV10TCL_STENCIL_MASK, 8);
942 OUT_RING (chan, 0xff);
943 OUT_RING (chan, 0x207);
944 OUT_RING (chan, 0);
945 OUT_RING (chan, 0xff);
946 OUT_RING (chan, 0x1e00);
947 OUT_RING (chan, 0x1e00);
948 OUT_RING (chan, 0x1e00);
949 OUT_RING (chan, 0x1d01);
950 BEGIN_RING(chan, celsius, NV10TCL_NORMALIZE_ENABLE, 1);
951 OUT_RING (chan, 0);
952 BEGIN_RING(chan, celsius, NV10TCL_FOG_ENABLE, 2);
953 OUT_RING (chan, 0);
954 OUT_RING (chan, 0);
955 BEGIN_RING(chan, celsius, NV10TCL_LIGHT_MODEL, 1);
956 OUT_RING (chan, 0);
957 BEGIN_RING(chan, celsius, NV10TCL_SEPARATE_SPECULAR_ENABLE, 1);
958 OUT_RING (chan, 0);
959 BEGIN_RING(chan, celsius, NV10TCL_ENABLED_LIGHTS, 1);
960 OUT_RING (chan, 0);
961 BEGIN_RING(chan, celsius, NV10TCL_POLYGON_OFFSET_POINT_ENABLE, 3);
962 OUT_RING (chan, 0);
963 OUT_RING (chan, 0);
964 OUT_RING (chan, 0);
965 BEGIN_RING(chan, celsius, NV10TCL_DEPTH_FUNC, 1);
966 OUT_RING (chan, 0x201);
967 BEGIN_RING(chan, celsius, NV10TCL_DEPTH_WRITE_ENABLE, 1);
968 OUT_RING (chan, 0);
969 BEGIN_RING(chan, celsius, NV10TCL_DEPTH_TEST_ENABLE, 1);
970 OUT_RING (chan, 0);
971 BEGIN_RING(chan, celsius, NV10TCL_POLYGON_OFFSET_FACTOR, 2);
972 OUT_RING (chan, 0);
973 OUT_RING (chan, 0);
974 BEGIN_RING(chan, celsius, NV10TCL_POINT_SIZE, 1);
975 OUT_RING (chan, 8);
976 BEGIN_RING(chan, celsius, NV10TCL_POINT_PARAMETERS_ENABLE, 2);
977 OUT_RING (chan, 0);
978 OUT_RING (chan, 0);
979 BEGIN_RING(chan, celsius, NV10TCL_LINE_WIDTH, 1);
980 OUT_RING (chan, 8);
981 BEGIN_RING(chan, celsius, NV10TCL_LINE_SMOOTH_ENABLE, 1);
982 OUT_RING (chan, 0);
983 BEGIN_RING(chan, celsius, NV10TCL_POLYGON_MODE_FRONT, 2);
984 OUT_RING (chan, 0x1b02);
985 OUT_RING (chan, 0x1b02);
986 BEGIN_RING(chan, celsius, NV10TCL_CULL_FACE, 2);
987 OUT_RING (chan, 0x405);
988 OUT_RING (chan, 0x901);
989 BEGIN_RING(chan, celsius, NV10TCL_POLYGON_SMOOTH_ENABLE, 1);
990 OUT_RING (chan, 0);
991 BEGIN_RING(chan, celsius, NV10TCL_CULL_FACE_ENABLE, 1);
992 OUT_RING (chan, 0);
993 BEGIN_RING(chan, celsius, NV10TCL_TX_GEN_MODE_S(0), 8);
994 for (i = 0; i < 8; i++)
995 OUT_RING (chan, 0);
997 BEGIN_RING(chan, celsius, NV10TCL_FOG_EQUATION_CONSTANT, 3);
998 OUT_RING (chan, 0x3fc00000); /* -1.50 */
999 OUT_RING (chan, 0xbdb8aa0a); /* -0.09 */
1000 OUT_RING (chan, 0); /* 0.00 */
1002 BEGIN_RING(chan, celsius, NV10TCL_NOP, 1);
1003 OUT_RING (chan, 0);
1005 BEGIN_RING(chan, celsius, NV10TCL_FOG_MODE, 2);
1006 OUT_RING (chan, 0x802);
1007 OUT_RING (chan, 2);
1008 /* for some reason VIEW_MATRIX_ENABLE need to be 6 instead of 4 when
1009 * using texturing, except when using the texture matrix
1011 BEGIN_RING(chan, celsius, NV10TCL_VIEW_MATRIX_ENABLE, 1);
1012 OUT_RING (chan, 6);
1013 BEGIN_RING(chan, celsius, NV10TCL_COLOR_MASK, 1);
1014 OUT_RING (chan, 0x01010101);
1016 BEGIN_RING(chan, celsius, NV10TCL_PROJECTION_MATRIX(0), 16);
1017 for(i = 0; i < 16; i++)
1018 OUT_RINGf(chan, i/4 == i%4 ? 1.0 : 0.0);
1020 BEGIN_RING(chan, celsius, NV10TCL_DEPTH_RANGE_NEAR, 2);
1021 OUT_RING (chan, 0);
1022 OUT_RINGf (chan, 65536.0);
1024 BEGIN_RING(chan, celsius, NV10TCL_VIEWPORT_TRANSLATE_X, 4);
1025 OUT_RINGf (chan, -2048.0);
1026 OUT_RINGf (chan, -2048.0);
1027 OUT_RINGf (chan, 0);
1028 OUT_RING (chan, 0);
1030 /* Set vertex component */
1031 BEGIN_RING(chan, celsius, NV10TCL_VERTEX_COL_4F_R, 4);
1032 OUT_RINGf (chan, 1.0);
1033 OUT_RINGf (chan, 1.0);
1034 OUT_RINGf (chan, 1.0);
1035 OUT_RINGf (chan, 1.0);
1036 BEGIN_RING(chan, celsius, NV10TCL_VERTEX_COL2_3F_R, 3);
1037 OUT_RING (chan, 0);
1038 OUT_RING (chan, 0);
1039 OUT_RING (chan, 0);
1040 BEGIN_RING(chan, celsius, NV10TCL_VERTEX_NOR_3F_X, 3);
1041 OUT_RING (chan, 0);
1042 OUT_RING (chan, 0);
1043 OUT_RINGf (chan, 1.0);
1044 BEGIN_RING(chan, celsius, NV10TCL_VERTEX_TX0_4F_S, 4);
1045 OUT_RINGf (chan, 0.0);
1046 OUT_RINGf (chan, 0.0);
1047 OUT_RINGf (chan, 0.0);
1048 OUT_RINGf (chan, 1.0);
1049 BEGIN_RING(chan, celsius, NV10TCL_VERTEX_TX1_4F_S, 4);
1050 OUT_RINGf (chan, 0.0);
1051 OUT_RINGf (chan, 0.0);
1052 OUT_RINGf (chan, 0.0);
1053 OUT_RINGf (chan, 1.0);
1054 BEGIN_RING(chan, celsius, NV10TCL_VERTEX_FOG_1F, 1);
1055 OUT_RINGf (chan, 0.0);
1056 BEGIN_RING(chan, celsius, NV10TCL_EDGEFLAG_ENABLE, 1);
1057 OUT_RING (chan, 1);
1059 return TRUE;
1062 /* AROS CODE */
1064 /* NOTE: Assumes lock on bitmap is already made */
1065 /* NOTE: Assumes buffer is not mapped */
1066 /* NOTE: Allows different formats of source and destination */
1067 BOOL HIDDNouveauNV103DCopyBox(struct CardData * carddata,
1068 struct HIDDNouveauBitMapData * srcdata, struct HIDDNouveauBitMapData * destdata,
1069 LONG srcX, LONG srcY, LONG destX, LONG destY, LONG width, LONG height,
1070 ULONG blendop)
1072 struct Picture sPict, dPict;
1073 LONG maskX = 0; LONG maskY = 0;
1075 HIDDNouveauFillPictureFromBitMapData(&sPict, srcdata);
1076 HIDDNouveauFillPictureFromBitMapData(&dPict, destdata);
1078 if (NV10EXAPrepareComposite(blendop,
1079 &sPict, NULL, &dPict, srcdata, NULL, destdata))
1081 NV10EXAComposite(destdata, srcX, srcY,
1082 maskX, maskY,
1083 destX , destY,
1084 width, height, &sPict, NULL);
1085 return TRUE;
1088 return FALSE;