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"
27 #include "nv04_pushbuf.h"
28 #include "nv50_accel.h"
29 #include "nv50_texture.h"
31 struct nv50_exa_state
{
35 PictTransformPtr transform
;
40 #if !defined(__AROS__)
41 static struct nv50_exa_state exa_state
;
43 #define NV50EXA_LOCALS(p) \
44 ScrnInfoPtr pScrn = xf86Screens[(p)->drawable.pScreen->myNum]; \
45 NVPtr pNv = NVPTR(pScrn); \
46 struct nouveau_channel *chan = pNv->chan; (void)chan; \
47 struct nouveau_grobj *eng2d = pNv->Nv2D; (void)eng2d; \
48 struct nouveau_grobj *tesla = pNv->Nv3D; (void)tesla; \
49 struct nv50_exa_state *state = &exa_state; (void)state
51 #define NV50EXA_LOCALS(p) \
52 ScrnInfoPtr pScrn = globalcarddataptr; \
53 NVPtr pNv = NVPTR(pScrn); \
54 struct nouveau_channel *chan = pNv->chan; (void)chan; \
55 struct nouveau_grobj *eng2d = pNv->Nv2D; (void)eng2d; \
56 struct nouveau_grobj *tesla = pNv->Nv3D; (void)tesla;
60 #define BF(f) NV50TCL_BLEND_FUNC_SRC_RGB_##f
62 struct nv50_blend_op
{
69 static struct nv50_blend_op
71 /* Clear */ { 0, 0, BF( ZERO
), BF( ZERO
) },
72 /* Src */ { 0, 0, BF( ONE
), BF( ZERO
) },
73 /* Dst */ { 0, 0, BF( ZERO
), BF( ONE
) },
74 /* Over */ { 1, 0, BF( ONE
), BF(ONE_MINUS_SRC_ALPHA
) },
75 /* OverReverse */ { 0, 1, BF(ONE_MINUS_DST_ALPHA
), BF( ONE
) },
76 /* In */ { 0, 1, BF( DST_ALPHA
), BF( ZERO
) },
77 /* InReverse */ { 1, 0, BF( ZERO
), BF( SRC_ALPHA
) },
78 /* Out */ { 0, 1, BF(ONE_MINUS_DST_ALPHA
), BF( ZERO
) },
79 /* OutReverse */ { 1, 0, BF( ZERO
), BF(ONE_MINUS_SRC_ALPHA
) },
80 /* Atop */ { 1, 1, BF( DST_ALPHA
), BF(ONE_MINUS_SRC_ALPHA
) },
81 /* AtopReverse */ { 1, 1, BF(ONE_MINUS_DST_ALPHA
), BF( SRC_ALPHA
) },
82 /* Xor */ { 1, 1, BF(ONE_MINUS_DST_ALPHA
), BF(ONE_MINUS_SRC_ALPHA
) },
83 /* Add */ { 0, 0, BF( ONE
), BF( ONE
) },
84 /* OverAlpha */ { 1, 0, BF( SRC_ALPHA
), BF(ONE_MINUS_SRC_ALPHA
) },
88 NV50EXA2DSurfaceFormat(PixmapPtr ppix
, uint32_t *fmt
)
92 #if !defined(__AROS__)
93 switch (ppix
->drawable
.bitsPerPixel
) {
95 switch (ppix
->depth
) {
97 case 8 : *fmt
= NV50_2D_SRC_FORMAT_R8_UNORM
; break;
98 case 15: *fmt
= NV50_2D_SRC_FORMAT_X1R5G5B5_UNORM
; break;
99 case 16: *fmt
= NV50_2D_SRC_FORMAT_R5G6B5_UNORM
; break;
100 case 24: *fmt
= NV50_2D_SRC_FORMAT_X8R8G8B8_UNORM
; break;
101 case 30: *fmt
= NV50_2D_SRC_FORMAT_A2B10G10R10_UNORM
; break;
102 case 32: *fmt
= NV50_2D_SRC_FORMAT_A8R8G8B8_UNORM
; break;
104 NOUVEAU_FALLBACK("Unknown surface format for bpp=%d\n",
105 ppix
->drawable
.bitsPerPixel
);
112 static void NV50EXASetClip(PixmapPtr ppix
, int x
, int y
, int w
, int h
)
114 NV50EXA_LOCALS(ppix
);
116 BEGIN_RING(chan
, eng2d
, NV50_2D_CLIP_X
, 4);
124 NV50EXAAcquireSurface2D(PixmapPtr ppix
, int is_src
)
126 NV50EXA_LOCALS(ppix
);
127 struct nouveau_bo
*bo
= nouveau_pixmap_bo(ppix
);
128 int mthd
= is_src
? NV50_2D_SRC_FORMAT
: NV50_2D_DST_FORMAT
;
129 uint32_t fmt
, bo_flags
;
131 if (!NV50EXA2DSurfaceFormat(ppix
, &fmt
))
134 bo_flags
= NOUVEAU_BO_VRAM
;
135 bo_flags
|= is_src
? NOUVEAU_BO_RD
: NOUVEAU_BO_WR
;
137 if (!nv50_style_tiled_pixmap(ppix
)) {
138 BEGIN_RING(chan
, eng2d
, mthd
, 2);
139 OUT_RING (chan
, fmt
);
141 BEGIN_RING(chan
, eng2d
, mthd
+ 0x14, 1);
142 OUT_RING (chan
, (uint32_t)exaGetPixmapPitch(ppix
));
144 BEGIN_RING(chan
, eng2d
, mthd
, 5);
145 OUT_RING (chan
, fmt
);
147 OUT_RING (chan
, bo
->tile_mode
<< 4);
152 BEGIN_RING(chan
, eng2d
, mthd
+ 0x18, 4);
153 #if !defined(__AROS__)
154 OUT_RING (chan
, ppix
->drawable
.width
);
155 OUT_RING (chan
, ppix
->drawable
.height
);
157 OUT_RING (chan
, ppix
->width
);
158 OUT_RING (chan
, ppix
->height
);
160 if (OUT_RELOCh(chan
, bo
, 0, bo_flags
) ||
161 OUT_RELOCl(chan
, bo
, 0, bo_flags
))
165 #if !defined(__AROS__)
166 NV50EXASetClip(ppix
, 0, 0, ppix
->drawable
.width
, ppix
->drawable
.height
);
168 NV50EXASetClip(ppix
, 0, 0, ppix
->width
, ppix
->height
);
175 NV50EXASetPattern(PixmapPtr pdpix
, int col0
, int col1
, int pat0
, int pat1
)
177 NV50EXA_LOCALS(pdpix
);
179 BEGIN_RING(chan
, eng2d
, NV50_2D_PATTERN_COLOR(0), 4);
180 OUT_RING (chan
, col0
);
181 OUT_RING (chan
, col1
);
182 OUT_RING (chan
, pat0
);
183 OUT_RING (chan
, pat1
);
186 #if !defined(__AROS__)
188 NV50EXASetROP(PixmapPtr pdpix
, int alu
, Pixel planemask
)
190 NV50EXA_LOCALS(pdpix
);
194 rop
= NVROP
[alu
].copy_planemask
;
196 rop
= NVROP
[alu
].copy
;
198 BEGIN_RING(chan
, eng2d
, NV50_2D_OPERATION
, 1);
199 if (alu
== GXcopy
&& EXA_PM_IS_SOLID(&pdpix
->drawable
, planemask
)) {
200 OUT_RING (chan
, NV50_2D_OPERATION_SRCCOPY
);
203 OUT_RING (chan
, NV50_2D_OPERATION_SRCCOPY_PREMULT
);
206 BEGIN_RING(chan
, eng2d
, NV50_2D_PATTERN_FORMAT
, 2);
207 switch (pdpix
->drawable
.bitsPerPixel
) {
208 case 8: OUT_RING (chan
, 3); break;
209 case 15: OUT_RING (chan
, 1); break;
210 case 16: OUT_RING (chan
, 0); break;
219 /* There are 16 alu's.
221 * 16-31: copy_planemask
224 if (!EXA_PM_IS_SOLID(&pdpix
->drawable
, planemask
)) {
226 NV50EXASetPattern(pdpix
, 0, planemask
, ~0, ~0);
228 if (pNv
->currentRop
> 15)
229 NV50EXASetPattern(pdpix
, ~0, ~0, ~0, ~0);
232 if (pNv
->currentRop
!= alu
) {
233 BEGIN_RING(chan
, eng2d
, NV50_2D_ROP
, 1);
234 OUT_RING (chan
, rop
);
235 pNv
->currentRop
= alu
;
240 NV50EXASetROP(PixmapPtr pdpix
, int alu
, Pixel planemask
)
242 NV50EXA_LOCALS(pdpix
);
245 rop
= NVROP
[alu
].copy
;
247 BEGIN_RING(chan
, eng2d
, NV50_2D_OPERATION
, 1);
248 if (alu
== 0x03 /* DrawMode_Copy */) {
249 OUT_RING (chan
, NV50_2D_OPERATION_SRCCOPY
);
252 OUT_RING (chan
, NV50_2D_OPERATION_SRCCOPY_PREMULT
);
255 BEGIN_RING(chan
, eng2d
, NV50_2D_PATTERN_FORMAT
, 2);
256 switch (pdpix
->depth
) {
257 case 8: OUT_RING (chan
, 3); break;
258 case 15: OUT_RING (chan
, 1); break;
259 case 16: OUT_RING (chan
, 0); break;
269 BEGIN_RING(chan
, eng2d
, NV50_2D_ROP
, 1);
270 OUT_RING (chan
, rop
);
274 #if !defined(__AROS__)
276 NV50EXAStateSolidResubmit(struct nouveau_channel
*chan
)
278 ScrnInfoPtr pScrn
= chan
->user_private
;
279 NVPtr pNv
= NVPTR(pScrn
);
281 NV50EXAPrepareSolid(pNv
->pdpix
, pNv
->alu
, pNv
->planemask
,
287 NV50EXAPrepareSolid(PixmapPtr pdpix
, int alu
, Pixel planemask
, Pixel fg
)
289 NV50EXA_LOCALS(pdpix
);
292 if (!NV50EXA2DSurfaceFormat(pdpix
, &fmt
))
293 NOUVEAU_FALLBACK("rect format\n");
295 if (MARK_RING(chan
, 64, 4))
296 NOUVEAU_FALLBACK("ring space\n");
298 if (!NV50EXAAcquireSurface2D(pdpix
, 0)) {
300 NOUVEAU_FALLBACK("dest pixmap\n");
303 NV50EXASetROP(pdpix
, alu
, planemask
);
305 BEGIN_RING(chan
, eng2d
, NV50_2D_DRAW_SHAPE
, 3);
306 OUT_RING (chan
, NV50_2D_DRAW_SHAPE_RECTANGLES
);
307 OUT_RING (chan
, fmt
);
310 #if !defined(__AROS__)
313 pNv
->planemask
= planemask
;
315 chan
->flush_notify
= NV50EXAStateSolidResubmit
;
317 chan
->flush_notify
= NULL
;
323 NV50EXASolid(PixmapPtr pdpix
, int x1
, int y1
, int x2
, int y2
)
325 NV50EXA_LOCALS(pdpix
);
328 BEGIN_RING(chan
, eng2d
, NV50_2D_DRAW_POINT32_X(0), 4);
334 #if !defined(__AROS__)
335 if((x2
- x1
) * (y2
- y1
) >= 512)
340 #if !defined(__AROS__)
342 NV50EXADoneSolid(PixmapPtr pdpix
)
344 NV50EXA_LOCALS(pdpix
);
346 chan
->flush_notify
= NULL
;
350 NV50EXAStateCopyResubmit(struct nouveau_channel
*chan
)
352 ScrnInfoPtr pScrn
= chan
->user_private
;
353 NVPtr pNv
= NVPTR(pScrn
);
355 NV50EXAPrepareCopy(pNv
->pspix
, pNv
->pdpix
, 0, 0, pNv
->alu
,
361 NV50EXAPrepareCopy(PixmapPtr pspix
, PixmapPtr pdpix
, int dx
, int dy
,
362 int alu
, Pixel planemask
)
364 NV50EXA_LOCALS(pdpix
);
366 if (MARK_RING(chan
, 64, 4))
367 NOUVEAU_FALLBACK("ring space\n");
369 if (!NV50EXAAcquireSurface2D(pspix
, 1)) {
371 NOUVEAU_FALLBACK("src pixmap\n");
374 if (!NV50EXAAcquireSurface2D(pdpix
, 0)) {
376 NOUVEAU_FALLBACK("dest pixmap\n");
379 NV50EXASetROP(pdpix
, alu
, planemask
);
381 #if !defined(__AROS__)
385 pNv
->planemask
= planemask
;
386 chan
->flush_notify
= NV50EXAStateCopyResubmit
;
388 chan
->flush_notify
= NULL
;
394 NV50EXACopy(PixmapPtr pdpix
, int srcX
, int srcY
,
396 int width
, int height
)
398 NV50EXA_LOCALS(pdpix
);
400 WAIT_RING (chan
, 17);
401 BEGIN_RING(chan
, eng2d
, 0x0110, 1);
403 BEGIN_RING(chan
, eng2d
, 0x088c, 1);
405 BEGIN_RING(chan
, eng2d
, NV50_2D_BLIT_DST_X
, 12);
406 OUT_RING (chan
, dstX
);
407 OUT_RING (chan
, dstY
);
408 OUT_RING (chan
, width
);
409 OUT_RING (chan
, height
);
415 OUT_RING (chan
, srcX
);
417 OUT_RING (chan
, srcY
);
419 #if !defined(__AROS__)
420 if(width
* height
>= 512)
425 #if !defined(__AROS__)
427 NV50EXADoneCopy(PixmapPtr pdpix
)
429 NV50EXA_LOCALS(pdpix
);
431 chan
->flush_notify
= NULL
;
435 NV50EXAStateSIFCResubmit(struct nouveau_channel
*chan
)
437 ScrnInfoPtr pScrn
= chan
->user_private
;
438 NVPtr pNv
= NVPTR(pScrn
);
440 if (MARK_RING(pNv
->chan
, 32, 2))
443 if (!NV50EXAAcquireSurface2D(pNv
->pdpix
, 0))
444 MARK_UNDO(pNv
->chan
);
448 NV50EXAUploadSIFC(const char *src
, int src_pitch
,
449 PixmapPtr pdpix
, int x
, int y
, int w
, int h
, int cpp
)
451 NV50EXA_LOCALS(pdpix
);
452 ScreenPtr pScreen
= pdpix
->drawable
.pScreen
;
453 int line_dwords
= (w
* cpp
+ 3) / 4;
456 if (!NV50EXA2DSurfaceFormat(pdpix
, &sifc_fmt
))
457 NOUVEAU_FALLBACK("hostdata format\n");
459 if (MARK_RING(chan
, 64, 2))
462 if (!NV50EXAAcquireSurface2D(pdpix
, 0)) {
464 NOUVEAU_FALLBACK("dest pixmap\n");
467 /* If the pitch isn't aligned to a dword, then you can get corruption at the end of a line. */
468 NV50EXASetClip(pdpix
, x
, y
, w
, h
);
470 BEGIN_RING(chan
, eng2d
, NV50_2D_OPERATION
, 1);
471 OUT_RING (chan
, NV50_2D_OPERATION_SRCCOPY
);
472 BEGIN_RING(chan
, eng2d
, NV50_2D_SIFC_BITMAP_ENABLE
, 2);
474 OUT_RING (chan
, sifc_fmt
);
475 BEGIN_RING(chan
, eng2d
, NV50_2D_SIFC_WIDTH
, 10);
476 OUT_RING (chan
, (line_dwords
* 4) / cpp
);
488 chan
->flush_notify
= NV50EXAStateSIFCResubmit
;
491 int count
= line_dwords
;
495 int size
= count
> 1792 ? 1792 : count
;
497 WAIT_RING (chan
, size
+ 1);
498 BEGIN_RING_NI(chan
, eng2d
, NV50_2D_SIFC_DATA
, size
);
499 OUT_RINGp (chan
, p
, size
);
508 chan
->flush_notify
= NULL
;
510 if (pdpix
== pScreen
->GetScreenPixmap(pScreen
))
516 NV50EXACheckRenderTarget(PicturePtr ppict
)
518 if (ppict
->pDrawable
->width
> 8192 ||
519 ppict
->pDrawable
->height
> 8192)
520 NOUVEAU_FALLBACK("render target dimensions exceeded %dx%d\n",
521 ppict
->pDrawable
->width
,
522 ppict
->pDrawable
->height
);
524 switch (ppict
->format
) {
532 case PICT_a2b10g10r10
:
533 case PICT_x2b10g10r10
:
534 case PICT_a2r10g10b10
:
535 case PICT_x2r10g10b10
:
538 NOUVEAU_FALLBACK("picture format 0x%08x\n", ppict
->format
);
546 NV50EXARenderTarget(PixmapPtr ppix
, PicturePtr ppict
)
548 NV50EXA_LOCALS(ppix
);
549 struct nouveau_bo
*bo
= nouveau_pixmap_bo(ppix
);
552 /*XXX: Scanout buffer not tiled, someone needs to figure it out */
553 if (!nv50_style_tiled_pixmap(ppix
))
554 NOUVEAU_FALLBACK("pixmap is scanout buffer\n");
556 switch (ppict
->format
) {
557 case PICT_a8r8g8b8
: format
= NV50TCL_RT_FORMAT_A8R8G8B8_UNORM
; break;
558 case PICT_x8r8g8b8
: format
= NV50TCL_RT_FORMAT_X8R8G8B8_UNORM
; break;
559 case PICT_r5g6b5
: format
= NV50TCL_RT_FORMAT_R5G6B5_UNORM
; break;
560 case PICT_a8
: format
= NV50TCL_RT_FORMAT_A8_UNORM
; break;
563 format
= NV50TCL_RT_FORMAT_A1R5G5B5_UNORM
;
565 case PICT_x8b8g8r8
: format
= NV50TCL_RT_FORMAT_X8B8G8R8_UNORM
; break;
566 case PICT_a2b10g10r10
:
567 case PICT_x2b10g10r10
:
568 format
= NV50TCL_RT_FORMAT_A2B10G10R10_UNORM
;
570 case PICT_a2r10g10b10
:
571 case PICT_x2r10g10b10
:
572 format
= NV50TCL_RT_FORMAT_A2R10G10B10_UNORM
;
575 NOUVEAU_FALLBACK("invalid picture format\n");
578 BEGIN_RING(chan
, tesla
, NV50TCL_RT_ADDRESS_HIGH(0), 5);
579 if (OUT_RELOCh(chan
, bo
, 0, NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
) ||
580 OUT_RELOCl(chan
, bo
, 0, NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
))
582 OUT_RING (chan
, format
);
583 OUT_RING (chan
, bo
->tile_mode
<< 4);
584 OUT_RING (chan
, 0x00000000);
585 BEGIN_RING(chan
, tesla
, NV50TCL_RT_HORIZ(0), 2);
586 #if !defined(__AROS__)
587 OUT_RING (chan
, ppix
->drawable
.width
);
588 OUT_RING (chan
, ppix
->drawable
.height
);
590 OUT_RING (chan
, ppix
->width
);
591 OUT_RING (chan
, ppix
->height
);
593 BEGIN_RING(chan
, tesla
, NV50TCL_RT_ARRAY_MODE
, 1);
594 OUT_RING (chan
, 0x00000001);
599 #if !defined(__AROS__)
601 NV50EXACheckTexture(PicturePtr ppict
, PicturePtr pdpict
, int op
)
603 if (!ppict
->pDrawable
)
604 NOUVEAU_FALLBACK("Solid and gradient pictures unsupported\n");
606 if (ppict
->pDrawable
->width
> 8192 ||
607 ppict
->pDrawable
->height
> 8192)
608 NOUVEAU_FALLBACK("texture dimensions exceeded %dx%d\n",
609 ppict
->pDrawable
->width
,
610 ppict
->pDrawable
->height
);
612 switch (ppict
->format
) {
626 case PICT_a2b10g10r10
:
627 case PICT_x2b10g10r10
:
628 case PICT_x2r10g10b10
:
629 case PICT_a2r10g10b10
:
636 NOUVEAU_FALLBACK("picture format 0x%08x\n", ppict
->format
);
639 switch (ppict
->filter
) {
640 case PictFilterNearest
:
641 case PictFilterBilinear
:
644 NOUVEAU_FALLBACK("picture filter %d\n", ppict
->filter
);
647 /* Opengl and Render disagree on what should be sampled outside an XRGB
648 * texture (with no repeating). Opengl has a hardcoded alpha value of
649 * 1.0, while render expects 0.0. We assume that clipping is done for
650 * untranformed sources.
652 if (NV50EXABlendOp
[op
].src_alpha
&& !ppict
->repeat
&&
653 ppict
->transform
&& (PICT_FORMAT_A(ppict
->format
) == 0)
654 && (PICT_FORMAT_A(pdpict
->format
) != 0))
655 NOUVEAU_FALLBACK("REPEAT_NONE unsupported for XRGB source\n");
661 #define _(X1,X2,X3,X4,FMT) (NV50TIC_0_0_TYPER_UNORM | NV50TIC_0_0_TYPEG_UNORM | NV50TIC_0_0_TYPEB_UNORM | NV50TIC_0_0_TYPEA_UNORM | \
662 NV50TIC_0_0_MAP##X1 | NV50TIC_0_0_MAP##X2 | NV50TIC_0_0_MAP##X3 | NV50TIC_0_0_MAP##X4 | \
663 NV50TIC_0_0_FMT_##FMT)
665 #if !defined(__AROS__)
667 NV50EXATexture(PixmapPtr ppix
, PicturePtr ppict
, unsigned unit
)
670 NV50EXATexture(PixmapPtr ppix
, PicturePtr ppict
, unsigned unit
, struct nv50_exa_state
* state
)
673 NV50EXA_LOCALS(ppix
);
674 struct nouveau_bo
*bo
= nouveau_pixmap_bo(ppix
);
675 const unsigned tcb_flags
= NOUVEAU_BO_RDWR
| NOUVEAU_BO_VRAM
;
678 /*XXX: Scanout buffer not tiled, someone needs to figure it out */
679 if (!nv50_style_tiled_pixmap(ppix
))
680 NOUVEAU_FALLBACK("pixmap is scanout buffer\n");
682 BEGIN_RING(chan
, tesla
, NV50TCL_TIC_ADDRESS_HIGH
, 3);
683 if (OUT_RELOCh(chan
, pNv
->tesla_scratch
, TIC_OFFSET
, tcb_flags
) ||
684 OUT_RELOCl(chan
, pNv
->tesla_scratch
, TIC_OFFSET
, tcb_flags
))
686 OUT_RING (chan
, 0x00000800);
687 BEGIN_RING(chan
, tesla
, NV50TCL_CB_DEF_ADDRESS_HIGH
, 3);
688 if (OUT_RELOCh(chan
, pNv
->tesla_scratch
, TIC_OFFSET
, tcb_flags
) ||
689 OUT_RELOCl(chan
, pNv
->tesla_scratch
, TIC_OFFSET
, tcb_flags
))
691 OUT_RING (chan
, (CB_TIC
<< NV50TCL_CB_DEF_SET_BUFFER_SHIFT
) | 0x4000);
692 BEGIN_RING(chan
, tesla
, NV50TCL_CB_ADDR
, 1);
693 OUT_RING (chan
, CB_TIC
| ((unit
* 8) << NV50TCL_CB_ADDR_ID_SHIFT
));
694 BEGIN_RING_NI(chan
, tesla
, NV50TCL_CB_DATA(0), 8);
696 switch (ppict
->format
) {
698 OUT_RING(chan
, _(B_C0
, G_C1
, R_C2
, A_C3
, 8_8_8_8
));
701 OUT_RING(chan
, _(R_C0
, G_C1
, B_C2
, A_C3
, 8_8_8_8
));
704 OUT_RING(chan
, _(B_C0
, G_C1
, R_C2
, A_ONE
, 8_8_8_8
));
707 OUT_RING(chan
, _(R_C0
, G_C1
, B_C2
, A_ONE
, 8_8_8_8
));
710 OUT_RING(chan
, _(B_C0
, G_C1
, R_C2
, A_ONE
, 5_6_5
));
713 OUT_RING(chan
, _(A_C0
, B_ZERO
, G_ZERO
, R_ZERO
, 8));
716 OUT_RING(chan
, _(B_C0
, G_C1
, R_C2
, A_ONE
, 1_5_5_5
));
719 OUT_RING(chan
, _(R_C0
, G_C1
, B_C2
, A_ONE
, 1_5_5_5
));
722 OUT_RING(chan
, _(B_C0
, G_C1
, R_C2
, A_C3
, 1_5_5_5
));
725 OUT_RING(chan
, _(R_C0
, G_C1
, B_C2
, A_C3
, 1_5_5_5
));
728 OUT_RING(chan
, _(R_C0
, G_C1
, B_C2
, A_ONE
, 5_6_5
));
731 OUT_RING(chan
, _(A_ONE
, R_C1
, G_C2
, B_C3
, 8_8_8_8
));
734 OUT_RING(chan
, _(A_C0
, R_C1
, G_C2
, B_C3
, 8_8_8_8
));
736 case PICT_a2b10g10r10
:
737 OUT_RING(chan
, _(R_C0
, G_C1
, B_C2
, A_C3
, 2_10_10_10
));
739 case PICT_x2b10g10r10
:
740 OUT_RING(chan
, _(R_C0
, G_C1
, B_C2
, A_ONE
, 2_10_10_10
));
742 case PICT_x2r10g10b10
:
743 OUT_RING(chan
, _(B_C0
, G_C1
, R_C2
, A_ONE
, 2_10_10_10
));
745 case PICT_a2r10g10b10
:
746 OUT_RING(chan
, _(B_C0
, G_C1
, R_C2
, A_C3
, 2_10_10_10
));
749 OUT_RING(chan
, _(B_C0
, G_C1
, R_C2
, A_ONE
, 4_4_4_4
));
752 OUT_RING(chan
, _(R_C0
, G_C1
, B_C2
, A_ONE
, 4_4_4_4
));
755 OUT_RING(chan
, _(B_C0
, G_C1
, R_C2
, A_C3
, 4_4_4_4
));
758 OUT_RING(chan
, _(R_C0
, G_C1
, B_C2
, A_C3
, 4_4_4_4
));
761 NOUVEAU_FALLBACK("invalid picture format, this SHOULD NOT HAPPEN. Expect trouble.\n");
765 mode
= 0xd0005000 | (bo
->tile_mode
<< 22);
766 if (OUT_RELOCl(chan
, bo
, 0, NOUVEAU_BO_VRAM
| NOUVEAU_BO_RD
) ||
767 OUT_RELOCd(chan
, bo
, 0, NOUVEAU_BO_VRAM
| NOUVEAU_BO_RD
|
768 NOUVEAU_BO_HIGH
| NOUVEAU_BO_OR
, mode
, mode
))
770 OUT_RING (chan
, 0x00300000);
771 #if !defined(__AROS__)
772 OUT_RING (chan
, ppix
->drawable
.width
);
773 OUT_RING (chan
, (1 << NV50TIC_0_5_DEPTH_SHIFT
) | ppix
->drawable
.height
);
775 OUT_RING (chan
, ppix
->width
);
776 OUT_RING (chan
, (1 << NV50TIC_0_5_DEPTH_SHIFT
) | ppix
->height
);
778 OUT_RING (chan
, 0x03000000);
779 OUT_RING (chan
, 0x00000000);
781 BEGIN_RING(chan
, tesla
, NV50TCL_TSC_ADDRESS_HIGH
, 3);
782 if (OUT_RELOCh(chan
, pNv
->tesla_scratch
, TSC_OFFSET
, tcb_flags
) ||
783 OUT_RELOCl(chan
, pNv
->tesla_scratch
, TSC_OFFSET
, tcb_flags
))
785 OUT_RING (chan
, 0x00000000);
786 BEGIN_RING(chan
, tesla
, NV50TCL_CB_DEF_ADDRESS_HIGH
, 3);
787 if (OUT_RELOCh(chan
, pNv
->tesla_scratch
, TSC_OFFSET
, tcb_flags
) ||
788 OUT_RELOCl(chan
, pNv
->tesla_scratch
, TSC_OFFSET
, tcb_flags
))
790 OUT_RING (chan
, (CB_TSC
<< NV50TCL_CB_DEF_SET_BUFFER_SHIFT
) | 0x4000);
791 BEGIN_RING(chan
, tesla
, NV50TCL_CB_ADDR
, 1);
792 OUT_RING (chan
, CB_TSC
| ((unit
* 8) << NV50TCL_CB_ADDR_ID_SHIFT
));
793 BEGIN_RING_NI(chan
, tesla
, NV50TCL_CB_DATA(0), 8);
795 switch (ppict
->repeatType
) {
797 OUT_RING (chan
, NV50TSC_1_0_WRAPS_CLAMP
|
798 NV50TSC_1_0_WRAPT_CLAMP
|
799 NV50TSC_1_0_WRAPR_CLAMP
| 0x00024000);
802 OUT_RING (chan
, NV50TSC_1_0_WRAPS_MIRROR_REPEAT
|
803 NV50TSC_1_0_WRAPT_MIRROR_REPEAT
|
804 NV50TSC_1_0_WRAPR_MIRROR_REPEAT
| 0x00024000);
808 OUT_RING (chan
, NV50TSC_1_0_WRAPS_REPEAT
|
809 NV50TSC_1_0_WRAPT_REPEAT
|
810 NV50TSC_1_0_WRAPR_REPEAT
| 0x00024000);
814 OUT_RING (chan
, NV50TSC_1_0_WRAPS_CLAMP_TO_BORDER
|
815 NV50TSC_1_0_WRAPT_CLAMP_TO_BORDER
|
816 NV50TSC_1_0_WRAPR_CLAMP_TO_BORDER
| 0x00024000);
818 if (ppict
->filter
== PictFilterBilinear
) {
819 OUT_RING (chan
, NV50TSC_1_1_MAGF_LINEAR
|
820 NV50TSC_1_1_MINF_LINEAR
|
821 NV50TSC_1_1_MIPF_NONE
);
823 OUT_RING (chan
, NV50TSC_1_1_MAGF_NEAREST
|
824 NV50TSC_1_1_MINF_NEAREST
|
825 NV50TSC_1_1_MIPF_NONE
);
827 OUT_RING (chan
, 0x00000000);
828 OUT_RING (chan
, 0x00000000);
829 OUT_RING (chan
, 0x00000000);
830 OUT_RING (chan
, 0x00000000);
831 OUT_RING (chan
, 0x00000000);
832 OUT_RING (chan
, 0x00000000);
834 #if !defined(__AROS__)
835 state
->unit
[unit
].width
= ppix
->drawable
.width
;
836 state
->unit
[unit
].height
= ppix
->drawable
.height
;
837 state
->unit
[unit
].transform
= ppict
->transform
;
839 state
->unit
[unit
].width
= ppix
->width
;
840 state
->unit
[unit
].height
= ppix
->height
;
841 state
->unit
[unit
].transform
= NULL
; /* Keep this NULL, we are doing simple blits */
846 #if !defined(__AROS__)
848 NV50EXACheckBlend(int op
)
851 NOUVEAU_FALLBACK("unsupported blend op %d\n", op
);
857 NV50EXABlend(PixmapPtr ppix
, PicturePtr ppict
, int op
, int component_alpha
)
859 NV50EXA_LOCALS(ppix
);
860 struct nv50_blend_op
*b
= &NV50EXABlendOp
[op
];
861 unsigned sblend
= b
->src_blend
;
862 unsigned dblend
= b
->dst_blend
;
865 if (!PICT_FORMAT_A(ppict
->format
)) {
866 if (sblend
== BF(DST_ALPHA
))
869 if (sblend
== BF(ONE_MINUS_DST_ALPHA
))
874 if (b
->src_alpha
&& component_alpha
) {
875 if (dblend
== BF(SRC_ALPHA
))
876 dblend
= BF(SRC_COLOR
);
878 if (dblend
== BF(ONE_MINUS_SRC_ALPHA
))
879 dblend
= BF(ONE_MINUS_SRC_COLOR
);
882 if (sblend
== BF(ONE
) && dblend
== BF(ZERO
)) {
883 BEGIN_RING(chan
, tesla
, NV50TCL_BLEND_ENABLE(0), 1);
886 BEGIN_RING(chan
, tesla
, NV50TCL_BLEND_ENABLE(0), 1);
888 BEGIN_RING(chan
, tesla
, NV50TCL_BLEND_EQUATION_RGB
, 5);
889 OUT_RING (chan
, NV50TCL_BLEND_EQUATION_RGB_FUNC_ADD
);
890 OUT_RING (chan
, sblend
);
891 OUT_RING (chan
, dblend
);
892 OUT_RING (chan
, NV50TCL_BLEND_EQUATION_ALPHA_FUNC_ADD
);
893 OUT_RING (chan
, sblend
);
894 BEGIN_RING(chan
, tesla
, NV50TCL_BLEND_FUNC_DST_ALPHA
, 1);
895 OUT_RING (chan
, dblend
);
899 #if !defined(__AROS__)
901 NV50EXACheckComposite(int op
,
902 PicturePtr pspict
, PicturePtr pmpict
, PicturePtr pdpict
)
904 if (!NV50EXACheckBlend(op
))
905 NOUVEAU_FALLBACK("blend not supported\n");
907 if (!NV50EXACheckRenderTarget(pdpict
))
908 NOUVEAU_FALLBACK("render target invalid\n");
910 if (!NV50EXACheckTexture(pspict
, pdpict
, op
))
911 NOUVEAU_FALLBACK("src picture invalid\n");
914 if (pmpict
->componentAlpha
&&
915 PICT_FORMAT_RGB(pmpict
->format
) &&
916 NV50EXABlendOp
[op
].src_alpha
&&
917 NV50EXABlendOp
[op
].src_blend
!= BF(ZERO
))
918 NOUVEAU_FALLBACK("component-alpha not supported\n");
920 if (!NV50EXACheckTexture(pmpict
, pdpict
, op
))
921 NOUVEAU_FALLBACK("mask picture invalid\n");
928 NV50EXAStateCompositeResubmit(struct nouveau_channel
*chan
)
930 ScrnInfoPtr pScrn
= chan
->user_private
;
931 NVPtr pNv
= NVPTR(pScrn
);
933 NV50EXAPrepareComposite(pNv
->alu
, pNv
->pspict
, pNv
->pmpict
, pNv
->pdpict
,
934 pNv
->pspix
, pNv
->pmpix
, pNv
->pdpix
);
938 #if !defined(__AROS__)
940 NV50EXAPrepareComposite(int op
,
941 PicturePtr pspict
, PicturePtr pmpict
, PicturePtr pdpict
,
942 PixmapPtr pspix
, PixmapPtr pmpix
, PixmapPtr pdpix
)
945 NV50EXAPrepareComposite(int op
,
946 PicturePtr pspict
, PicturePtr pmpict
, PicturePtr pdpict
,
947 PixmapPtr pspix
, PixmapPtr pmpix
, PixmapPtr pdpix
,
948 struct nv50_exa_state
* state
)
951 NV50EXA_LOCALS(pspix
);
952 const unsigned shd_flags
= NOUVEAU_BO_VRAM
| NOUVEAU_BO_RD
;
954 if (MARK_RING (chan
, 128, 4 + 2 + 2 * 10))
955 NOUVEAU_FALLBACK("ring space\n");
957 BEGIN_RING(chan
, eng2d
, 0x0110, 1);
960 if (!NV50EXARenderTarget(pdpix
, pdpict
)) {
962 NOUVEAU_FALLBACK("render target invalid\n");
965 NV50EXABlend(pdpix
, pdpict
, op
, pmpict
&& pmpict
->componentAlpha
&&
966 PICT_FORMAT_RGB(pmpict
->format
));
968 BEGIN_RING(chan
, tesla
, NV50TCL_VP_ADDRESS_HIGH
, 2);
969 if (OUT_RELOCh(chan
, pNv
->tesla_scratch
, PVP_OFFSET
, shd_flags
) ||
970 OUT_RELOCl(chan
, pNv
->tesla_scratch
, PVP_OFFSET
, shd_flags
)) {
975 BEGIN_RING(chan
, tesla
, NV50TCL_FP_ADDRESS_HIGH
, 2);
976 if (OUT_RELOCh(chan
, pNv
->tesla_scratch
, PFP_OFFSET
, shd_flags
) ||
977 OUT_RELOCl(chan
, pNv
->tesla_scratch
, PFP_OFFSET
, shd_flags
)) {
982 #if !defined(__AROS__)
983 if (!NV50EXATexture(pspix
, pspict
, 0)) {
985 if (!NV50EXATexture(pspix
, pspict
, 0, state
)) {
988 NOUVEAU_FALLBACK("src picture invalid\n");
992 #if !defined(__AROS__)
993 if (!NV50EXATexture(pmpix
, pmpict
, 1)) {
995 if (!NV50EXATexture(pmpix
, pmpict
, 1, state
)) {
998 NOUVEAU_FALLBACK("mask picture invalid\n");
1000 state
->have_mask
= TRUE
;
1002 BEGIN_RING(chan
, tesla
, NV50TCL_FP_START_ID
, 1);
1003 if (pdpict
->format
== PICT_a8
) {
1004 OUT_RING (chan
, PFP_C_A8
);
1006 if (pmpict
->componentAlpha
&&
1007 PICT_FORMAT_RGB(pmpict
->format
)) {
1008 if (NV50EXABlendOp
[op
].src_alpha
)
1009 OUT_RING (chan
, PFP_CCASA
);
1011 OUT_RING (chan
, PFP_CCA
);
1013 OUT_RING (chan
, PFP_C
);
1017 state
->have_mask
= FALSE
;
1019 BEGIN_RING(chan
, tesla
, NV50TCL_FP_START_ID
, 1);
1020 if (pdpict
->format
== PICT_a8
)
1021 OUT_RING (chan
, PFP_S_A8
);
1023 OUT_RING (chan
, PFP_S
);
1026 BEGIN_RING(chan
, tesla
, 0x1334, 1);
1029 BEGIN_RING(chan
, tesla
, NV50TCL_BIND_TIC(2), 1);
1031 BEGIN_RING(chan
, tesla
, NV50TCL_BIND_TIC(2), 1);
1032 OUT_RING (chan
, 0x203);
1034 #if !defined(__AROS__)
1036 pNv
->pspict
= pspict
;
1037 pNv
->pmpict
= pmpict
;
1038 pNv
->pdpict
= pdpict
;
1042 chan
->flush_notify
= NV50EXAStateCompositeResubmit
;
1044 chan
->flush_notify
= NULL
;
1049 #define xFixedToFloat(v) \
1050 ((float)xFixedToInt((v)) + ((float)xFixedFrac(v) / 65536.0))
1052 NV50EXATransform(PictTransformPtr t
, int x
, int y
, float sx
, float sy
,
1053 float *x_ret
, float *y_ret
)
1056 /* Note: current t is always NULL in AROS. That is good enough for
1057 operations being done (simple blits with alpha) */
1058 #if !defined(__AROS__)
1061 v
.vector
[0] = IntToxFixed(x
);
1062 v
.vector
[1] = IntToxFixed(y
);
1063 v
.vector
[2] = xFixed1
;
1064 PictureTransformPoint(t
, &v
);
1065 *x_ret
= xFixedToFloat(v
.vector
[0]) / sx
;
1066 *y_ret
= xFixedToFloat(v
.vector
[1]) / sy
;
1069 *x_ret
= (float)x
/ sx
;
1070 *y_ret
= (float)y
/ sy
;
1074 #if !defined(__AROS__)
1076 NV50EXAComposite(PixmapPtr pdpix
, int sx
, int sy
, int mx
, int my
,
1077 int dx
, int dy
, int w
, int h
)
1080 NV50EXAComposite(PixmapPtr pdpix
, int sx
, int sy
, int mx
, int my
,
1081 int dx
, int dy
, int w
, int h
, struct nv50_exa_state
* state
)
1084 NV50EXA_LOCALS(pdpix
);
1085 float sX0
=0.0f
, sX1
=0.0f
, sX2
=0.0f
, sY0
=0.0f
, sY1
=0.0f
, sY2
=0.0f
;
1087 WAIT_RING (chan
, 64);
1088 BEGIN_RING(chan
, tesla
, NV50TCL_SCISSOR_HORIZ(0), 2);
1089 OUT_RING (chan
, (dx
+ w
) << 16 | dx
);
1090 OUT_RING (chan
, (dy
+ h
) << 16 | dy
);
1091 BEGIN_RING(chan
, tesla
, NV50TCL_VERTEX_BEGIN
, 1);
1092 OUT_RING (chan
, NV50TCL_VERTEX_BEGIN_TRIANGLES
);
1094 NV50EXATransform(state
->unit
[0].transform
, sx
, sy
+ (h
* 2),
1095 state
->unit
[0].width
, state
->unit
[0].height
,
1097 NV50EXATransform(state
->unit
[0].transform
, sx
, sy
,
1098 state
->unit
[0].width
, state
->unit
[0].height
,
1100 NV50EXATransform(state
->unit
[0].transform
, sx
+ (w
* 2), sy
,
1101 state
->unit
[0].width
, state
->unit
[0].height
,
1104 if (state
->have_mask
) {
1105 float mX0
=0.0f
, mX1
=0.0f
, mX2
=0.0f
, mY0
=0.0f
, mY1
=0.0f
, mY2
=0.0f
;
1107 NV50EXATransform(state
->unit
[1].transform
, mx
, my
+ (h
* 2),
1108 state
->unit
[1].width
, state
->unit
[1].height
,
1110 NV50EXATransform(state
->unit
[1].transform
, mx
, my
,
1111 state
->unit
[1].width
, state
->unit
[1].height
,
1113 NV50EXATransform(state
->unit
[1].transform
, mx
+ (w
* 2), my
,
1114 state
->unit
[1].width
, state
->unit
[1].height
,
1117 VTX2s(pNv
, sX0
, sY0
, mX0
, mY0
, dx
, dy
+ (h
* 2));
1118 VTX2s(pNv
, sX1
, sY1
, mX1
, mY1
, dx
, dy
);
1119 VTX2s(pNv
, sX2
, sY2
, mX2
, mY2
, dx
+ (w
* 2), dy
);
1121 VTX1s(pNv
, sX0
, sY0
, dx
, dy
+ (h
* 2));
1122 VTX1s(pNv
, sX1
, sY1
, dx
, dy
);
1123 VTX1s(pNv
, sX2
, sY2
, dx
+ (w
* 2), dy
);
1126 BEGIN_RING(chan
, tesla
, NV50TCL_VERTEX_END
, 1);
1130 #if !defined(__AROS__)
1132 NV50EXADoneComposite(PixmapPtr pdpix
)
1134 NV50EXA_LOCALS(pdpix
);
1136 chan
->flush_notify
= NULL
;
1142 VOID
HIDDNouveauNV50SetPattern(struct CardData
* carddata
, LONG col0
,
1143 LONG col1
, LONG pat0
, LONG pat1
)
1145 NV50EXASetPattern(NULL
, col0
, col1
, pat0
, pat1
);
1148 /* NOTE: Assumes lock on bitmap is already made */
1149 /* NOTE: Assumes buffer is not mapped */
1150 BOOL
HIDDNouveauNV50FillSolidRect(struct CardData
* carddata
,
1151 struct HIDDNouveauBitMapData
* bmdata
, LONG minX
, LONG minY
, LONG maxX
,
1152 LONG maxY
, ULONG drawmode
, ULONG color
)
1154 if (NV50EXAPrepareSolid(bmdata
, drawmode
, ~0, color
))
1156 NV50EXASolid(bmdata
, minX
, minY
, maxX
+ 1, maxY
+ 1);
1163 /* NOTE: Assumes lock on bitmap is already made */
1164 /* NOTE: Assumes buffer is not mapped */
1165 BOOL
HIDDNouveauNV50CopySameFormat(struct CardData
* carddata
,
1166 struct HIDDNouveauBitMapData
* srcdata
, struct HIDDNouveauBitMapData
* destdata
,
1167 LONG srcX
, LONG srcY
, LONG destX
, LONG destY
, LONG width
, LONG height
,
1170 if (NV50EXAPrepareCopy(srcdata
, destdata
, 0, 0, drawmode
, ~0))
1172 NV50EXACopy(destdata
, srcX
, srcY
, destX
, destY
, width
, height
);
1179 /* NOTE: Assumes lock on bitmap is already made */
1180 /* NOTE: Assumes buffer is not mapped */
1181 /* NOTE: Allows different formats of source and destination */
1182 BOOL
HIDDNouveauNV503DCopyBox(struct CardData
* carddata
,
1183 struct HIDDNouveauBitMapData
* srcdata
, struct HIDDNouveauBitMapData
* destdata
,
1184 LONG srcX
, LONG srcY
, LONG destX
, LONG destY
, LONG width
, LONG height
,
1187 struct Picture sPict
, dPict
;
1188 struct nv50_exa_state state
;
1189 ULONG maskX
= 0; ULONG maskY
= 0;
1191 HIDDNouveauFillPictureFromBitMapData(&sPict
, srcdata
);
1192 HIDDNouveauFillPictureFromBitMapData(&dPict
, destdata
);
1194 if (NV50EXAPrepareComposite(blendop
,
1195 &sPict
, NULL
, &dPict
, srcdata
, NULL
, destdata
, &state
))
1197 NV50EXAComposite(destdata
, srcX
, srcY
,
1200 width
, height
, &state
);