2 * Copyright 2007 NVIDIA, Corporation
3 * Copyright 2008 Ben Skeggs
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
24 #include "nv_include.h"
26 #include "nv50_accel.h"
27 #include "nv50_texture.h"
29 struct nv50_exa_state {
33 PictTransformPtr transform;
38 static struct nv50_exa_state exa_state;
40 #define NV50EXA_LOCALS(p) \
41 ScrnInfoPtr pScrn = xf86Screens[(p)->drawable.pScreen->myNum]; \
42 NVPtr pNv = NVPTR(pScrn); \
43 struct nouveau_channel *chan = pNv->chan; (void)chan; \
44 struct nouveau_grobj *eng2d = pNv->Nv2D; (void)eng2d; \
45 struct nouveau_grobj *tesla = pNv->Nv3D; (void)tesla; \
46 struct nv50_exa_state *state = &exa_state; (void)state
48 #define BF(f) (NV50TCL_BLEND_FUNC_SRC_RGB_##f | 0x4000)
50 struct nv50_blend_op {
57 static struct nv50_blend_op
59 /* Clear */ { 0, 0, BF( ZERO), BF( ZERO) },
60 /* Src */ { 0, 0, BF( ONE), BF( ZERO) },
61 /* Dst */ { 0, 0, BF( ZERO), BF( ONE) },
62 /* Over */ { 1, 0, BF( ONE), BF(ONE_MINUS_SRC_ALPHA) },
63 /* OverReverse */ { 0, 1, BF(ONE_MINUS_DST_ALPHA), BF( ONE) },
64 /* In */ { 0, 1, BF( DST_ALPHA), BF( ZERO) },
65 /* InReverse */ { 1, 0, BF( ZERO), BF( SRC_ALPHA) },
66 /* Out */ { 0, 1, BF(ONE_MINUS_DST_ALPHA), BF( ZERO) },
67 /* OutReverse */ { 1, 0, BF( ZERO), BF(ONE_MINUS_SRC_ALPHA) },
68 /* Atop */ { 1, 1, BF( DST_ALPHA), BF(ONE_MINUS_SRC_ALPHA) },
69 /* AtopReverse */ { 1, 1, BF(ONE_MINUS_DST_ALPHA), BF( SRC_ALPHA) },
70 /* Xor */ { 1, 1, BF(ONE_MINUS_DST_ALPHA), BF(ONE_MINUS_SRC_ALPHA) },
71 /* Add */ { 0, 0, BF( ONE), BF( ONE) },
75 NV50EXA2DSurfaceFormat(PixmapPtr ppix, uint32_t *fmt)
79 switch (ppix->drawable.depth) {
80 case 8 : *fmt = NV50_2D_SRC_FORMAT_8BPP; break;
81 case 15: *fmt = NV50_2D_SRC_FORMAT_15BPP; break;
82 case 16: *fmt = NV50_2D_SRC_FORMAT_16BPP; break;
83 case 24: *fmt = NV50_2D_SRC_FORMAT_24BPP; break;
84 case 32: *fmt = NV50_2D_SRC_FORMAT_32BPP; break;
86 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
87 "Unknown surface format for bpp=%d\n",
88 ppix->drawable.depth);
95 static void NV50EXASetClip(PixmapPtr ppix, int x, int y, int w, int h)
99 BEGIN_RING(chan, eng2d, NV50_2D_CLIP_X, 4);
107 NV50EXAAcquireSurface2D(PixmapPtr ppix, int is_src)
109 NV50EXA_LOCALS(ppix);
110 int mthd = is_src ? NV50_2D_SRC_FORMAT : NV50_2D_DST_FORMAT;
111 uint32_t fmt, bo_flags;
113 if (!NV50EXA2DSurfaceFormat(ppix, &fmt))
116 bo_flags = NOUVEAU_BO_VRAM;
117 bo_flags |= is_src ? NOUVEAU_BO_RD : NOUVEAU_BO_WR;
119 if (exaGetPixmapOffset(ppix) < pNv->EXADriverPtr->offScreenBase) {
120 BEGIN_RING(chan, eng2d, mthd, 2);
121 OUT_RING (chan, fmt);
123 BEGIN_RING(chan, eng2d, mthd + 0x14, 1);
124 OUT_RING (chan, (uint32_t)exaGetPixmapPitch(ppix));
126 BEGIN_RING(chan, eng2d, mthd, 5);
127 OUT_RING (chan, fmt);
134 BEGIN_RING(chan, eng2d, mthd + 0x18, 4);
135 OUT_RING (chan, ppix->drawable.width);
136 OUT_RING (chan, ppix->drawable.height);
137 OUT_PIXMAPh(chan, ppix, 0, bo_flags);
138 OUT_PIXMAPl(chan, ppix, 0, bo_flags);
141 NV50EXASetClip(ppix, 0, 0, ppix->drawable.width, ppix->drawable.height);
147 NV50EXASetPattern(PixmapPtr pdpix, int col0, int col1, int pat0, int pat1)
149 NV50EXA_LOCALS(pdpix);
151 BEGIN_RING(chan, eng2d, NV50_2D_PATTERN_COLOR(0), 4);
152 OUT_RING (chan, col0);
153 OUT_RING (chan, col1);
154 OUT_RING (chan, pat0);
155 OUT_RING (chan, pat1);
158 extern const int NVCopyROP[16];
160 NV50EXASetROP(PixmapPtr pdpix, int alu, Pixel planemask)
162 NV50EXA_LOCALS(pdpix);
163 int rop = NVCopyROP[alu];
165 BEGIN_RING(chan, eng2d, NV50_2D_OPERATION, 1);
166 if (alu == GXcopy && planemask == ~0) {
167 OUT_RING (chan, NV50_2D_OPERATION_SRCCOPY);
170 OUT_RING (chan, NV50_2D_OPERATION_SRCCOPY_PREMULT);
173 BEGIN_RING(chan, eng2d, NV50_2D_PATTERN_FORMAT, 2);
174 switch (pdpix->drawable.depth) {
175 case 8: OUT_RING (chan, 3); break;
176 case 15: OUT_RING (chan, 1); break;
177 case 16: OUT_RING (chan, 0); break;
186 /* I observed incorrect rendering and found this in a fifo trace. */
187 /* It fixed the one test-case i had, so i'm happy. */
188 if (pdpix->drawable.depth == 32)
191 /* There are 16 alu's. pNv->currentRop stores: */
192 /* 0-15: planemask == ~0 && bpp != 32 */
193 /* 16-31: planemask == ~0 && bpp == 32 */
194 /* 32-47: planemask != ~0 */
195 if (planemask != ~0) {
196 NV50EXASetPattern(pdpix, 0, planemask, ~0, ~0);
197 rop = (rop & 0xf0) | 0x0a;
199 if (pNv->currentRop != (alu + 32)) {
200 BEGIN_RING(chan, eng2d, NV50_2D_ROP, 1);
201 OUT_RING (chan, rop);
202 pNv->currentRop = alu + 32;
205 /* This makes no sense for planemask != ~0, as that already masks with 0xA. */
206 if (pdpix->drawable.depth == 32)
209 if (pNv->currentRop != alu) {
210 if (pNv->currentRop >= 32)
211 NV50EXASetPattern(pdpix, ~0, ~0, ~0, ~0);
213 BEGIN_RING(chan, eng2d, NV50_2D_ROP, 1);
214 OUT_RING (chan, rop);
215 pNv->currentRop = alu;
221 NV50EXAPrepareSolid(PixmapPtr pdpix, int alu, Pixel planemask, Pixel fg)
223 NV50EXA_LOCALS(pdpix);
226 planemask |= ~0 << pdpix->drawable.bitsPerPixel;
228 if (!NV50EXA2DSurfaceFormat(pdpix, &fmt))
229 NOUVEAU_FALLBACK("rect format\n");
230 if (!NV50EXAAcquireSurface2D(pdpix, 0))
231 NOUVEAU_FALLBACK("dest pixmap\n");
232 NV50EXASetROP(pdpix, alu, planemask);
234 BEGIN_RING(chan, eng2d, 0x580, 3);
236 OUT_RING (chan, fmt);
243 NV50EXASolid(PixmapPtr pdpix, int x1, int y1, int x2, int y2)
245 NV50EXA_LOCALS(pdpix);
247 BEGIN_RING(chan, eng2d, NV50_2D_RECT_X1, 4);
253 if((x2 - x1) * (y2 - y1) >= 512)
258 NV50EXADoneSolid(PixmapPtr pdpix)
263 NV50EXAPrepareCopy(PixmapPtr pspix, PixmapPtr pdpix, int dx, int dy,
264 int alu, Pixel planemask)
266 NV50EXA_LOCALS(pdpix);
268 planemask |= ~0 << pdpix->drawable.bitsPerPixel;
270 if (!NV50EXAAcquireSurface2D(pspix, 1))
271 NOUVEAU_FALLBACK("src pixmap\n");
272 if (!NV50EXAAcquireSurface2D(pdpix, 0))
273 NOUVEAU_FALLBACK("dest pixmap\n");
274 NV50EXASetROP(pdpix, alu, planemask);
280 NV50EXACopy(PixmapPtr pdpix, int srcX , int srcY,
282 int width, int height)
284 NV50EXA_LOCALS(pdpix);
286 BEGIN_RING(chan, eng2d, 0x0110, 1);
288 BEGIN_RING(chan, eng2d, 0x088c, 1);
290 BEGIN_RING(chan, eng2d, NV50_2D_BLIT_DST_X, 12);
291 OUT_RING (chan, dstX);
292 OUT_RING (chan, dstY);
293 OUT_RING (chan, width);
294 OUT_RING (chan, height);
300 OUT_RING (chan, srcX);
302 OUT_RING (chan, srcY);
304 if(width * height >= 512)
309 NV50EXADoneCopy(PixmapPtr pdpix)
314 NV50EXAUploadSIFC(const char *src, int src_pitch,
315 PixmapPtr pdpix, int x, int y, int w, int h, int cpp)
317 NV50EXA_LOCALS(pdpix);
318 int line_dwords = (w * cpp + 3) / 4;
321 if (!NV50EXA2DSurfaceFormat(pdpix, &sifc_fmt))
322 NOUVEAU_FALLBACK("hostdata format\n");
323 if (!NV50EXAAcquireSurface2D(pdpix, 0))
324 NOUVEAU_FALLBACK("dest pixmap\n");
326 /* If the pitch isn't aligned to a dword, then you can get corruption at the end of a line. */
327 NV50EXASetClip(pdpix, x, y, w, h);
329 BEGIN_RING(chan, eng2d, NV50_2D_OPERATION, 1);
330 OUT_RING (chan, NV50_2D_OPERATION_SRCCOPY);
331 BEGIN_RING(chan, eng2d, NV50_2D_SIFC_UNK0800, 2);
333 OUT_RING (chan, sifc_fmt);
334 BEGIN_RING(chan, eng2d, NV50_2D_SIFC_WIDTH, 10);
335 OUT_RING (chan, (line_dwords * 4) / cpp);
347 int count = line_dwords;
351 int size = count > 1792 ? 1792 : count;
353 BEGIN_RING(chan, eng2d,
354 NV50_2D_SIFC_DATA | 0x40000000, size);
355 OUT_RINGp (chan, p, size);
368 NV50EXACheckRenderTarget(PicturePtr ppict)
370 if (ppict->pDrawable->width > 8192 ||
371 ppict->pDrawable->height > 8192)
372 NOUVEAU_FALLBACK("render target dimensions exceeded %dx%d\n",
373 ppict->pDrawable->width,
374 ppict->pDrawable->height);
376 switch (ppict->format) {
383 NOUVEAU_FALLBACK("picture format 0x%08x\n", ppict->format);
390 NV50EXARenderTarget(PixmapPtr ppix, PicturePtr ppict)
392 NV50EXA_LOCALS(ppix);
395 /*XXX: Scanout buffer not tiled, someone needs to figure it out */
396 if (exaGetPixmapOffset(ppix) < pNv->EXADriverPtr->offScreenBase)
397 NOUVEAU_FALLBACK("pixmap is scanout buffer\n");
399 switch (ppict->format) {
400 case PICT_a8r8g8b8: format = NV50TCL_RT_FORMAT_32BPP; break;
401 case PICT_x8r8g8b8: format = NV50TCL_RT_FORMAT_24BPP; break;
402 case PICT_r5g6b5 : format = NV50TCL_RT_FORMAT_16BPP; break;
403 case PICT_a8 : format = NV50TCL_RT_FORMAT_8BPP; break;
405 NOUVEAU_FALLBACK("invalid picture format\n");
408 BEGIN_RING(chan, tesla, NV50TCL_RT_ADDRESS_HIGH(0), 5);
409 OUT_PIXMAPh(chan, ppix, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
410 OUT_PIXMAPl(chan, ppix, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_WR);
411 OUT_RING (chan, format);
413 OUT_RING (chan, 0x00000000);
414 BEGIN_RING(chan, tesla, NV50TCL_RT_HORIZ(0), 2);
415 OUT_RING (chan, ppix->drawable.width);
416 OUT_RING (chan, ppix->drawable.height);
417 BEGIN_RING(chan, tesla, 0x1224, 1);
418 OUT_RING (chan, 0x00000001);
424 NV50EXACheckTexture(PicturePtr ppict)
426 if (ppict->pDrawable->width > 8192 ||
427 ppict->pDrawable->height > 8192)
428 NOUVEAU_FALLBACK("texture dimensions exceeded %dx%d\n",
429 ppict->pDrawable->width,
430 ppict->pDrawable->height);
432 switch (ppict->format) {
441 NOUVEAU_FALLBACK("picture format 0x%08x\n", ppict->format);
444 switch (ppict->filter) {
445 case PictFilterNearest:
446 case PictFilterBilinear:
449 NOUVEAU_FALLBACK("picture filter %d\n", ppict->filter);
456 NV50EXATexture(PixmapPtr ppix, PicturePtr ppict, unsigned unit)
458 NV50EXA_LOCALS(ppix);
460 /*XXX: Scanout buffer not tiled, someone needs to figure it out */
461 if (exaGetPixmapOffset(ppix) < pNv->EXADriverPtr->offScreenBase)
462 NOUVEAU_FALLBACK("pixmap is scanout buffer\n");
464 BEGIN_RING(chan, tesla, NV50TCL_CB_ADDR, 1);
465 OUT_RING (chan, CB_TIC | ((unit * 8) << NV50TCL_CB_ADDR_ID_SHIFT));
466 BEGIN_RING(chan, tesla, NV50TCL_CB_DATA(0) | 0x40000000, 8);
467 switch (ppict->format) {
469 OUT_RING (chan, NV50TIC_0_0_MAPA_C3 | NV50TIC_0_0_TYPEA_UNORM |
470 NV50TIC_0_0_MAPR_C0 | NV50TIC_0_0_TYPER_UNORM |
471 NV50TIC_0_0_MAPG_C1 | NV50TIC_0_0_TYPEB_UNORM |
472 NV50TIC_0_0_MAPB_C2 | NV50TIC_0_0_TYPEG_UNORM |
473 NV50TIC_0_0_FMT_8_8_8_8);
476 OUT_RING (chan, NV50TIC_0_0_MAPA_C3 | NV50TIC_0_0_TYPEA_UNORM |
477 NV50TIC_0_0_MAPR_C2 | NV50TIC_0_0_TYPER_UNORM |
478 NV50TIC_0_0_MAPG_C1 | NV50TIC_0_0_TYPEB_UNORM |
479 NV50TIC_0_0_MAPB_C0 | NV50TIC_0_0_TYPEG_UNORM |
480 NV50TIC_0_0_FMT_8_8_8_8);
483 OUT_RING (chan, NV50TIC_0_0_MAPA_ONE | NV50TIC_0_0_TYPEA_UNORM |
484 NV50TIC_0_0_MAPR_C0 | NV50TIC_0_0_TYPER_UNORM |
485 NV50TIC_0_0_MAPG_C1 | NV50TIC_0_0_TYPEB_UNORM |
486 NV50TIC_0_0_MAPB_C2 | NV50TIC_0_0_TYPEG_UNORM |
487 NV50TIC_0_0_FMT_8_8_8_8);
490 OUT_RING (chan, NV50TIC_0_0_MAPA_ONE | NV50TIC_0_0_TYPEA_UNORM |
491 NV50TIC_0_0_MAPR_C2 | NV50TIC_0_0_TYPER_UNORM |
492 NV50TIC_0_0_MAPG_C1 | NV50TIC_0_0_TYPEB_UNORM |
493 NV50TIC_0_0_MAPB_C0 | NV50TIC_0_0_TYPEG_UNORM |
494 NV50TIC_0_0_FMT_8_8_8_8);
497 OUT_RING (chan, NV50TIC_0_0_MAPA_ONE | NV50TIC_0_0_TYPEA_UNORM |
498 NV50TIC_0_0_MAPR_C0 | NV50TIC_0_0_TYPER_UNORM |
499 NV50TIC_0_0_MAPG_C1 | NV50TIC_0_0_TYPEB_UNORM |
500 NV50TIC_0_0_MAPB_C2 | NV50TIC_0_0_TYPEG_UNORM |
501 NV50TIC_0_0_FMT_5_6_5);
504 OUT_RING (chan, NV50TIC_0_0_MAPA_C0 | NV50TIC_0_0_TYPEA_UNORM |
505 NV50TIC_0_0_MAPR_ZERO | NV50TIC_0_0_TYPER_UNORM |
506 NV50TIC_0_0_MAPG_ZERO | NV50TIC_0_0_TYPEB_UNORM |
507 NV50TIC_0_0_MAPB_ZERO | NV50TIC_0_0_TYPEG_UNORM |
511 NOUVEAU_FALLBACK("invalid picture format, this SHOULD NOT HAPPEN. Expect trouble.\n");
513 OUT_PIXMAPl(chan, ppix, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
514 OUT_RING (chan, 0xd0005000);
515 OUT_RING (chan, 0x00300000);
516 OUT_RING (chan, ppix->drawable.width);
517 OUT_RING (chan, (1 << NV50TIC_0_5_DEPTH_SHIFT) | ppix->drawable.height);
518 OUT_RING (chan, 0x03000000);
519 OUT_PIXMAPh(chan, ppix, 0, NOUVEAU_BO_VRAM | NOUVEAU_BO_RD);
521 BEGIN_RING(chan, tesla, NV50TCL_CB_ADDR, 1);
522 OUT_RING (chan, CB_TSC | ((unit * 8) << NV50TCL_CB_ADDR_ID_SHIFT));
523 BEGIN_RING(chan, tesla, NV50TCL_CB_DATA(0) | 0x40000000, 8);
525 switch (ppict->repeatType) {
527 OUT_RING (chan, NV50TSC_1_0_WRAPS_CLAMP |
528 NV50TSC_1_0_WRAPT_CLAMP |
529 NV50TSC_1_0_WRAPR_CLAMP | 0x00024000);
532 OUT_RING (chan, NV50TSC_1_0_WRAPS_MIRROR_REPEAT |
533 NV50TSC_1_0_WRAPT_MIRROR_REPEAT |
534 NV50TSC_1_0_WRAPR_MIRROR_REPEAT | 0x00024000);
538 OUT_RING (chan, NV50TSC_1_0_WRAPS_REPEAT |
539 NV50TSC_1_0_WRAPT_REPEAT |
540 NV50TSC_1_0_WRAPR_REPEAT | 0x00024000);
544 OUT_RING (chan, NV50TSC_1_0_WRAPS_CLAMP_TO_BORDER |
545 NV50TSC_1_0_WRAPT_CLAMP_TO_BORDER |
546 NV50TSC_1_0_WRAPR_CLAMP_TO_BORDER | 0x00024000);
548 if (ppict->filter == PictFilterBilinear) {
549 OUT_RING (chan, NV50TSC_1_1_MAGF_LINEAR |
550 NV50TSC_1_1_MINF_LINEAR |
551 NV50TSC_1_1_MIPF_NONE);
553 OUT_RING (chan, NV50TSC_1_1_MAGF_NEAREST |
554 NV50TSC_1_1_MINF_NEAREST |
555 NV50TSC_1_1_MIPF_NONE);
557 OUT_RING (chan, 0x00000000);
558 OUT_RING (chan, 0x00000000);
559 OUT_RING (chan, 0x00000000);
560 OUT_RING (chan, 0x00000000);
561 OUT_RING (chan, 0x00000000);
562 OUT_RING (chan, 0x00000000);
564 state->unit[unit].width = ppix->drawable.width;
565 state->unit[unit].height = ppix->drawable.height;
566 state->unit[unit].transform = ppict->transform;
571 NV50EXACheckBlend(int op)
574 NOUVEAU_FALLBACK("unsupported blend op %d\n", op);
579 NV50EXABlend(PixmapPtr ppix, PicturePtr ppict, int op, int component_alpha)
581 NV50EXA_LOCALS(ppix);
582 struct nv50_blend_op *b = &NV50EXABlendOp[op];
583 unsigned sblend = b->src_blend;
584 unsigned dblend = b->dst_blend;
587 if (!PICT_FORMAT_A(ppict->format)) {
588 if (sblend == BF(DST_ALPHA))
591 if (sblend == BF(ONE_MINUS_DST_ALPHA))
594 if (ppict->format == PICT_a8) {
595 if (sblend == BF(DST_ALPHA))
596 sblend = BF(DST_COLOR);
598 if (sblend == BF(ONE_MINUS_DST_ALPHA))
599 sblend = BF(ONE_MINUS_DST_COLOR);
603 if (b->src_alpha && (component_alpha || ppict->format == PICT_a8)) {
604 if (dblend == BF(SRC_ALPHA))
605 dblend = BF(SRC_COLOR);
607 if (dblend == BF(ONE_MINUS_SRC_ALPHA))
608 dblend = BF(ONE_MINUS_SRC_COLOR);
611 if (sblend == BF(ONE) && dblend == BF(ZERO)) {
612 BEGIN_RING(chan, tesla, NV50TCL_BLEND_ENABLE(0), 1);
615 BEGIN_RING(chan, tesla, NV50TCL_BLEND_ENABLE(0), 1);
617 BEGIN_RING(chan, tesla, NV50TCL_BLEND_EQUATION_RGB, 5);
618 OUT_RING (chan, NV50TCL_BLEND_EQUATION_RGB_FUNC_ADD);
619 OUT_RING (chan, sblend);
620 OUT_RING (chan, dblend);
621 OUT_RING (chan, NV50TCL_BLEND_EQUATION_ALPHA_FUNC_ADD);
622 OUT_RING (chan, sblend);
623 BEGIN_RING(chan, tesla, NV50TCL_BLEND_FUNC_DST_ALPHA, 1);
624 OUT_RING (chan, dblend);
629 NV50EXACheckComposite(int op,
630 PicturePtr pspict, PicturePtr pmpict, PicturePtr pdpict)
632 if (!NV50EXACheckBlend(op))
633 NOUVEAU_FALLBACK("blend not supported\n");
635 if (!NV50EXACheckRenderTarget(pdpict))
636 NOUVEAU_FALLBACK("render target invalid\n");
638 if (!NV50EXACheckTexture(pspict))
639 NOUVEAU_FALLBACK("src picture invalid\n");
642 if (pmpict->componentAlpha &&
643 PICT_FORMAT_RGB(pmpict->format) &&
644 NV50EXABlendOp[op].src_alpha &&
645 NV50EXABlendOp[op].src_blend != BF(ZERO))
646 NOUVEAU_FALLBACK("component-alpha not supported\n");
648 if (!NV50EXACheckTexture(pmpict))
649 NOUVEAU_FALLBACK("mask picture invalid\n");
656 NV50EXAPrepareComposite(int op,
657 PicturePtr pspict, PicturePtr pmpict, PicturePtr pdpict,
658 PixmapPtr pspix, PixmapPtr pmpix, PixmapPtr pdpix)
660 NV50EXA_LOCALS(pspix);
662 BEGIN_RING(chan, eng2d, 0x0110, 1);
665 if (!NV50EXARenderTarget(pdpix, pdpict))
666 NOUVEAU_FALLBACK("render target invalid\n");
668 NV50EXABlend(pdpix, pdpict, op, pmpict && pmpict->componentAlpha &&
669 PICT_FORMAT_RGB(pmpict->format));
672 if (!NV50EXATexture(pspix, pspict, 0))
673 NOUVEAU_FALLBACK("src picture invalid\n");
674 if (!NV50EXATexture(pmpix, pmpict, 1))
675 NOUVEAU_FALLBACK("mask picture invalid\n");
676 state->have_mask = TRUE;
678 BEGIN_RING(chan, tesla, NV50TCL_FP_START_ID, 1);
679 if (pdpict->format == PICT_a8) {
680 OUT_RING (chan, PFP_C_A8);
682 if (pmpict->componentAlpha &&
683 PICT_FORMAT_RGB(pmpict->format)) {
684 if (NV50EXABlendOp[op].src_alpha)
685 OUT_RING (chan, PFP_CCASA);
687 OUT_RING (chan, PFP_CCA);
689 OUT_RING (chan, PFP_C);
693 if (!NV50EXATexture(pspix, pspict, 0))
694 NOUVEAU_FALLBACK("src picture invalid\n");
695 state->have_mask = FALSE;
697 BEGIN_RING(chan, tesla, NV50TCL_FP_START_ID, 1);
698 if (pdpict->format == PICT_a8)
699 OUT_RING (chan, PFP_S_A8);
701 OUT_RING (chan, PFP_S);
704 BEGIN_RING(chan, tesla, 0x1334, 1);
707 BEGIN_RING(chan, tesla, 0x1458, 1);
709 BEGIN_RING(chan, tesla, 0x1458, 1);
710 OUT_RING (chan, 0x203);
715 #define xFixedToFloat(v) \
716 ((float)xFixedToInt((v)) + ((float)xFixedFrac(v) / 65536.0))
718 NV50EXATransform(PictTransformPtr t, int x, int y, float sx, float sy,
719 float *x_ret, float *y_ret)
724 v.vector[0] = IntToxFixed(x);
725 v.vector[1] = IntToxFixed(y);
726 v.vector[2] = xFixed1;
727 PictureTransformPoint(t, &v);
728 *x_ret = xFixedToFloat(v.vector[0]) / sx;
729 *y_ret = xFixedToFloat(v.vector[1]) / sy;
731 *x_ret = (float)x / sx;
732 *y_ret = (float)y / sy;
737 NV50EXAComposite(PixmapPtr pdpix, int sx, int sy, int mx, int my,
738 int dx, int dy, int w, int h)
740 NV50EXA_LOCALS(pdpix);
741 float sX0, sX1, sX2, sX3, sY0, sY1, sY2, sY3;
742 unsigned dX0 = dx, dX1 = dx + w, dY0 = dy, dY1 = dy + h;
744 NV50EXATransform(state->unit[0].transform, sx, sy,
745 state->unit[0].width, state->unit[0].height,
747 NV50EXATransform(state->unit[0].transform, sx + w, sy,
748 state->unit[0].width, state->unit[0].height,
750 NV50EXATransform(state->unit[0].transform, sx + w, sy + h,
751 state->unit[0].width, state->unit[0].height,
753 NV50EXATransform(state->unit[0].transform, sx, sy + h,
754 state->unit[0].width, state->unit[0].height,
757 BEGIN_RING(chan, tesla, NV50TCL_VERTEX_BEGIN, 1);
758 OUT_RING (chan, NV50TCL_VERTEX_BEGIN_QUADS);
759 if (state->have_mask) {
760 float mX0, mX1, mX2, mX3, mY0, mY1, mY2, mY3;
762 NV50EXATransform(state->unit[1].transform, mx, my,
763 state->unit[1].width, state->unit[1].height,
765 NV50EXATransform(state->unit[1].transform, mx + w, my,
766 state->unit[1].width, state->unit[1].height,
768 NV50EXATransform(state->unit[1].transform, mx + w, my + h,
769 state->unit[1].width, state->unit[1].height,
771 NV50EXATransform(state->unit[1].transform, mx, my + h,
772 state->unit[1].width, state->unit[1].height,
775 VTX2s(pNv, sX0, sY0, mX0, mY0, dX0, dY0);
776 VTX2s(pNv, sX1, sY1, mX1, mY1, dX1, dY0);
777 VTX2s(pNv, sX2, sY2, mX2, mY2, dX1, dY1);
778 VTX2s(pNv, sX3, sY3, mX3, mY3, dX0, dY1);
780 VTX1s(pNv, sX0, sY0, dX0, dY0);
781 VTX1s(pNv, sX1, sY1, dX1, dY0);
782 VTX1s(pNv, sX2, sY2, dX1, dY1);
783 VTX1s(pNv, sX3, sY3, dX0, dY1);
785 BEGIN_RING(chan, tesla, NV50TCL_VERTEX_END, 1);
790 NV50EXADoneComposite(PixmapPtr pdpix)