2 * Copyright 2003 NVIDIA, Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
18 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
19 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 #include "nv_include.h"
26 #include "nv04_pushbuf.h"
29 NV04EXASetPattern(ScrnInfoPtr pScrn
, CARD32 clr0
, CARD32 clr1
,
30 CARD32 pat0
, CARD32 pat1
)
32 NVPtr pNv
= NVPTR(pScrn
);
33 struct nouveau_channel
*chan
= pNv
->chan
;
34 struct nouveau_grobj
*patt
= pNv
->NvImagePattern
;
36 BEGIN_RING(chan
, patt
, NV04_IMAGE_PATTERN_MONOCHROME_COLOR0
, 4);
37 OUT_RING (chan
, clr0
);
38 OUT_RING (chan
, clr1
);
39 OUT_RING (chan
, pat0
);
40 OUT_RING (chan
, pat1
);
43 #if !defined(__AROS__)
45 NV04EXASetROP(ScrnInfoPtr pScrn
, CARD32 alu
, CARD32 planemask
)
47 NVPtr pNv
= NVPTR(pScrn
);
48 struct nouveau_channel
*chan
= pNv
->chan
;
49 struct nouveau_grobj
*rop
= pNv
->NvRop
;
51 if (planemask
!= ~0) {
52 NV04EXASetPattern(pScrn
, 0, planemask
, ~0, ~0);
53 if (pNv
->currentRop
!= (alu
+ 32)) {
54 BEGIN_RING(chan
, rop
, NV03_CONTEXT_ROP_ROP
, 1);
55 OUT_RING (chan
, NVROP
[alu
].copy_planemask
);
56 pNv
->currentRop
= alu
+ 32;
59 if (pNv
->currentRop
!= alu
) {
60 if(pNv
->currentRop
>= 16)
61 NV04EXASetPattern(pScrn
, ~0, ~0, ~0, ~0);
62 BEGIN_RING(chan
, rop
, NV03_CONTEXT_ROP_ROP
, 1);
63 OUT_RING (chan
, NVROP
[alu
].copy
);
64 pNv
->currentRop
= alu
;
69 NV04EXASetROP(ScrnInfoPtr pScrn
, CARD32 alu
, CARD32 planemask
)
71 NVPtr pNv
= NVPTR(pScrn
);
72 struct nouveau_channel
*chan
= pNv
->chan
;
73 struct nouveau_grobj
*rop
= pNv
->NvRop
;
75 BEGIN_RING(chan
, rop
, NV03_CONTEXT_ROP_ROP
, 1);
76 OUT_RING (chan
, NVROP
[alu
].copy
);
80 #if !defined(__AROS__)
82 NV04EXAStateSolidResubmit(struct nouveau_channel
*chan
)
84 ScrnInfoPtr pScrn
= chan
->user_private
;
85 NVPtr pNv
= NVPTR(pScrn
);
87 NV04EXAPrepareSolid(pNv
->pdpix
, pNv
->alu
, pNv
->planemask
, pNv
->fg_colour
);
92 NV04EXAPrepareSolid(PixmapPtr pPixmap
, int alu
, Pixel planemask
, Pixel fg
)
94 #if !defined(__AROS__)
95 ScrnInfoPtr pScrn
= xf86Screens
[pPixmap
->drawable
.pScreen
->myNum
];
97 ScrnInfoPtr pScrn
= globalcarddataptr
;
99 NVPtr pNv
= NVPTR(pScrn
);
100 struct nouveau_channel
*chan
= pNv
->chan
;
101 struct nouveau_grobj
*surf2d
= pNv
->NvContextSurfaces
;
102 struct nouveau_grobj
*rect
= pNv
->NvRectangle
;
103 struct nouveau_bo
*bo
= nouveau_pixmap_bo(pPixmap
);
104 unsigned int fmt
, pitch
, fmt2
= NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8
;
106 if (MARK_RING(chan
, 64, 2))
109 #if !defined(__AROS__)
110 planemask
|= ~0 << pPixmap
->drawable
.bitsPerPixel
;
111 if (planemask
!= ~0 || alu
!= GXcopy
) {
112 if (pPixmap
->drawable
.bitsPerPixel
== 32)
115 if (alu
!= 0x03 /* DrawMode_Copy */) {
117 BEGIN_RING(chan
, rect
, NV04_GDI_RECTANGLE_TEXT_OPERATION
, 1);
118 OUT_RING (chan
, 1); /* ROP_AND */
119 NV04EXASetROP(pScrn
, alu
, planemask
);
121 BEGIN_RING(chan
, rect
, NV04_GDI_RECTANGLE_TEXT_OPERATION
, 1);
122 OUT_RING (chan
, 3); /* SRCCOPY */
125 if (!NVAccelGetCtxSurf2DFormatFromPixmap(pPixmap
, (int*)&fmt
))
127 pitch
= exaGetPixmapPitch(pPixmap
);
129 #if !defined(__AROS__)
130 if (pPixmap
->drawable
.bitsPerPixel
== 16) {
131 if (pPixmap
->drawable
.depth
== 16) {
132 fmt2
= NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A16R5G6B5
;
133 } else if (pPixmap
->drawable
.depth
== 15) {
134 fmt2
= NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_X16A1R5G5B5
;
138 if (pPixmap
->depth
== 16)
139 fmt2
= NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A16R5G6B5
;
142 /* When SURFACE_FORMAT_A8R8G8B8 is used with GDI_RECTANGLE_TEXT, the
143 * alpha channel gets forced to 0xFF for some reason. We're using
144 * SURFACE_FORMAT_Y32 as a workaround
146 if (fmt
== NV04_CONTEXT_SURFACES_2D_FORMAT_A8R8G8B8
)
147 fmt
= NV04_CONTEXT_SURFACES_2D_FORMAT_Y32
;
149 BEGIN_RING(chan
, surf2d
, NV04_CONTEXT_SURFACES_2D_FORMAT
, 4);
150 OUT_RING (chan
, fmt
);
151 OUT_RING (chan
, (pitch
<< 16) | pitch
);
152 if (OUT_RELOCl(chan
, bo
, 0, NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
) ||
153 OUT_RELOCl(chan
, bo
, 0, NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
)) {
158 BEGIN_RING(chan
, rect
, NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT
, 1);
159 OUT_RING (chan
, fmt2
);
160 BEGIN_RING(chan
, rect
, NV04_GDI_RECTANGLE_TEXT_COLOR1_A
, 1);
163 #if !defined(__AROS__)
164 pNv
->pdpix
= pPixmap
;
166 pNv
->planemask
= planemask
;
168 chan
->flush_notify
= NV04EXAStateSolidResubmit
;
170 chan
->flush_notify
= NULL
;
176 NV04EXASolid (PixmapPtr pPixmap
, int x1
, int y1
, int x2
, int y2
)
178 #if !defined(__AROS__)
179 ScrnInfoPtr pScrn
= xf86Screens
[pPixmap
->drawable
.pScreen
->myNum
];
181 ScrnInfoPtr pScrn
= globalcarddataptr
;
183 NVPtr pNv
= NVPTR(pScrn
);
184 struct nouveau_channel
*chan
= pNv
->chan
;
185 struct nouveau_grobj
*rect
= pNv
->NvRectangle
;
189 BEGIN_RING(chan
, rect
,
190 NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT(0), 2);
191 OUT_RING (chan
, (x1
<< 16) | y1
);
192 OUT_RING (chan
, (width
<< 16) | height
);
194 #if !defined(__AROS__)
195 if((width
* height
) >= 512)
200 #if !defined(__AROS__)
202 NV04EXADoneSolid (PixmapPtr pPixmap
)
204 ScrnInfoPtr pScrn
= xf86Screens
[pPixmap
->drawable
.pScreen
->myNum
];
205 NVPtr pNv
= NVPTR(pScrn
);
207 pNv
->chan
->flush_notify
= NULL
;
211 NV04EXAStateCopyResubmit(struct nouveau_channel
*chan
)
213 ScrnInfoPtr pScrn
= chan
->user_private
;
214 NVPtr pNv
= NVPTR(pScrn
);
216 NV04EXAPrepareCopy(pNv
->pspix
, pNv
->pdpix
, 0, 0, pNv
->alu
,
222 NV04EXAPrepareCopy(PixmapPtr pSrcPixmap
, PixmapPtr pDstPixmap
, int dx
, int dy
,
223 int alu
, Pixel planemask
)
225 #if !defined(__AROS__)
226 ScrnInfoPtr pScrn
= xf86Screens
[pSrcPixmap
->drawable
.pScreen
->myNum
];
228 ScrnInfoPtr pScrn
= globalcarddataptr
;
230 NVPtr pNv
= NVPTR(pScrn
);
231 struct nouveau_channel
*chan
= pNv
->chan
;
232 struct nouveau_grobj
*surf2d
= pNv
->NvContextSurfaces
;
233 struct nouveau_grobj
*blit
= pNv
->NvImageBlit
;
234 struct nouveau_bo
*src_bo
= nouveau_pixmap_bo(pSrcPixmap
);
235 struct nouveau_bo
*dst_bo
= nouveau_pixmap_bo(pDstPixmap
);
238 #if !defined(__AROS__)
239 if (pSrcPixmap
->drawable
.bitsPerPixel
!=
240 pDstPixmap
->drawable
.bitsPerPixel
)
242 if (pSrcPixmap
->depth
!= pDstPixmap
->depth
)
246 if (!NVAccelGetCtxSurf2DFormatFromPixmap(pDstPixmap
, &fmt
))
249 if (MARK_RING(chan
, 64, 2))
252 #if !defined(__AROS__)
253 planemask
|= ~0 << pDstPixmap
->drawable
.bitsPerPixel
;
254 if (planemask
!= ~0 || alu
!= GXcopy
) {
255 if (pDstPixmap
->drawable
.bitsPerPixel
== 32) {
260 if (alu
!= 0x03 /* DrawMode_Copy */) {
263 BEGIN_RING(chan
, blit
, NV01_IMAGE_BLIT_OPERATION
, 1);
264 OUT_RING (chan
, 1); /* ROP_AND */
266 NV04EXASetROP(pScrn
, alu
, planemask
);
268 BEGIN_RING(chan
, blit
, NV01_IMAGE_BLIT_OPERATION
, 1);
269 OUT_RING (chan
, 3); /* SRCCOPY */
272 BEGIN_RING(chan
, surf2d
, NV04_CONTEXT_SURFACES_2D_FORMAT
, 4);
273 OUT_RING (chan
, fmt
);
274 OUT_RING (chan
, (exaGetPixmapPitch(pDstPixmap
) << 16) |
275 (exaGetPixmapPitch(pSrcPixmap
)));
276 if (OUT_RELOCl(chan
, src_bo
, 0, NOUVEAU_BO_VRAM
| NOUVEAU_BO_RD
) ||
277 OUT_RELOCl(chan
, dst_bo
, 0, NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
)) {
282 #if !defined(__AROS__)
283 pNv
->pspix
= pSrcPixmap
;
284 pNv
->pdpix
= pDstPixmap
;
286 pNv
->planemask
= planemask
;
287 chan
->flush_notify
= NV04EXAStateCopyResubmit
;
289 chan
->flush_notify
= NULL
;
295 NV04EXACopy(PixmapPtr pDstPixmap
, int srcX
, int srcY
, int dstX
, int dstY
,
296 int width
, int height
)
298 #if !defined(__AROS__)
299 ScrnInfoPtr pScrn
= xf86Screens
[pDstPixmap
->drawable
.pScreen
->myNum
];
301 ScrnInfoPtr pScrn
= globalcarddataptr
;
303 NVPtr pNv
= NVPTR(pScrn
);
304 struct nouveau_channel
*chan
= pNv
->chan
;
305 struct nouveau_grobj
*blit
= pNv
->NvImageBlit
;
306 #if !defined(__AROS__)
307 int split_dstY
= NOUVEAU_ALIGN(dstY
+ 1, 64);
308 int split_height
= split_dstY
- dstY
;
310 if ((width
* height
) >= 200000 && pNv
->pspix
!= pNv
->pdpix
&&
311 (dstY
> srcY
|| dstX
> srcX
) && split_height
< height
) {
313 * KLUDGE - Split the destination rectangle in an
314 * upper misaligned half and a lower tile-aligned
315 * half, then get IMAGE_BLIT to blit the lower piece
316 * downwards (required for sync-to-vblank if the area
317 * to be blitted is large enough). The blob does a
318 * different (not nicer) trick to achieve the same
321 struct nouveau_grobj
*surf2d
= pNv
->NvContextSurfaces
;
322 struct nouveau_bo
*dst_bo
= nouveau_pixmap_bo(pNv
->pdpix
);
323 unsigned dst_pitch
= exaGetPixmapPitch(pNv
->pdpix
);
325 if (MARK_RING(chan
, 10, 1))
328 BEGIN_RING(chan
, blit
, NV01_IMAGE_BLIT_POINT_IN
, 3);
329 OUT_RING (chan
, (srcY
<< 16) | srcX
);
330 OUT_RING (chan
, (dstY
<< 16) | dstX
);
331 OUT_RING (chan
, (split_height
<< 16) | width
);
333 BEGIN_RING(chan
, surf2d
,
334 NV04_CONTEXT_SURFACES_2D_OFFSET_DESTIN
, 1);
335 OUT_RELOCl(chan
, dst_bo
, split_dstY
* dst_pitch
,
336 NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
338 srcY
+= split_height
;
339 height
-= split_height
;
344 BEGIN_RING(chan
, blit
, NV01_IMAGE_BLIT_POINT_IN
, 3);
345 OUT_RING (chan
, (srcY
<< 16) | srcX
);
346 OUT_RING (chan
, (dstY
<< 16) | dstX
);
347 OUT_RING (chan
, (height
<< 16) | width
);
349 #if !defined(__AROS__)
350 if((width
* height
) >= 512)
355 #if !defined(__AROS__)
357 NV04EXADoneCopy(PixmapPtr pDstPixmap
)
359 ScrnInfoPtr pScrn
= xf86Screens
[pDstPixmap
->drawable
.pScreen
->myNum
];
360 NVPtr pNv
= NVPTR(pScrn
);
362 pNv
->chan
->flush_notify
= NULL
;
366 NV04EXAStateIFCSubmit(struct nouveau_channel
*chan
)
368 ScrnInfoPtr pScrn
= chan
->user_private
;
369 NVPtr pNv
= NVPTR(pScrn
);
370 struct nouveau_grobj
*surf2d
= pNv
->NvContextSurfaces
;
371 struct nouveau_grobj
*ifc
= pNv
->NvImageFromCpu
;
372 struct nouveau_bo
*bo
= nouveau_pixmap_bo(pNv
->pdpix
);
375 NVAccelGetCtxSurf2DFormatFromPixmap(pNv
->pdpix
, &surf_fmt
);
377 if (MARK_RING(chan
, 64, 2))
380 BEGIN_RING(chan
, surf2d
, NV04_CONTEXT_SURFACES_2D_FORMAT
, 4);
381 OUT_RING (chan
, surf_fmt
);
382 OUT_RING (chan
, (exaGetPixmapPitch(pNv
->pdpix
) << 16) |
383 exaGetPixmapPitch(pNv
->pdpix
));
384 if (OUT_RELOCl(chan
, bo
, 0, NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
) ||
385 OUT_RELOCl(chan
, bo
, 0, NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
)) {
389 BEGIN_RING(chan
, ifc
, NV01_IMAGE_FROM_CPU_POINT
, 3);
390 OUT_RING (chan
, (pNv
->point_y
<< 16) | pNv
->point_x
);
391 OUT_RING (chan
, (pNv
->height_out
<< 16) | pNv
->width_out
);
392 OUT_RING (chan
, (pNv
->height_in
<< 16) | pNv
->width_in
);
398 NV04EXAStateIFCResubmit(struct nouveau_channel
*chan
)
400 NV04EXAStateIFCSubmit(chan
);
404 NV04EXAUploadIFC(ScrnInfoPtr pScrn
, const char *src
, int src_pitch
,
405 PixmapPtr pDst
, int x
, int y
, int w
, int h
, int cpp
)
407 NVPtr pNv
= NVPTR(pScrn
);
408 ScreenPtr pScreen
= pDst
->drawable
.pScreen
;
409 struct nouveau_channel
*chan
= pNv
->chan
;
410 struct nouveau_grobj
*clip
= pNv
->NvClipRectangle
;
411 struct nouveau_grobj
*ifc
= pNv
->NvImageFromCpu
;
412 int line_len
= w
* cpp
;
413 int iw
, id
, surf_fmt
, ifc_fmt
;
416 if (pNv
->Architecture
>= NV_ARCH_50
)
426 case 2: ifc_fmt
= 1; break;
427 case 4: ifc_fmt
= 4; break;
432 if (!NVAccelGetCtxSurf2DFormatFromPixmap(pDst
, &surf_fmt
))
435 /* Pad out input width to cover both COLORA() and COLORB() */
436 iw
= (line_len
+ 7) & ~7;
437 padbytes
= iw
- line_len
;
438 id
= iw
/ 4; /* line push size */
441 /* Don't support lines longer than max push size yet.. */
445 BEGIN_RING(chan
, clip
, NV01_CONTEXT_CLIP_RECTANGLE_POINT
, 2);
446 OUT_RING (chan
, (y
<< 16) | x
);
447 OUT_RING (chan
, (h
<< 16) | w
);
448 BEGIN_RING(chan
, ifc
, NV01_IMAGE_FROM_CPU_OPERATION
, 2);
449 OUT_RING (chan
, NV01_IMAGE_FROM_CPU_OPERATION_SRCCOPY
);
450 OUT_RING (chan
, ifc_fmt
);
454 pNv
->height_in
= pNv
->height_out
= h
;
458 chan
->flush_notify
= NV04EXAStateIFCResubmit
;
459 if (!NV04EXAStateIFCSubmit(chan
))
466 BEGIN_RING(chan
, ifc
, NV01_IMAGE_FROM_CPU_COLOR(0), id
);
467 OUT_RINGp (chan
, src
, id
);
474 int aux
= (padbytes
+ 7) >> 2;
475 BEGIN_RING(chan
, ifc
, NV01_IMAGE_FROM_CPU_COLOR(0), id
);
476 OUT_RINGp (chan
, src
, id
- aux
);
477 memcpy(padding
, src
+ (id
- aux
) * 4, padbytes
);
478 OUT_RINGp (chan
, padding
, aux
);
481 chan
->flush_notify
= NULL
;
483 if (pDst
== pScreen
->GetScreenPixmap(pScreen
))
491 VOID
HIDDNouveauNV04SetPattern(struct CardData
* carddata
, LONG clr0
, LONG clr1
,
492 LONG pat0
, LONG pat1
)
494 NV04EXASetPattern(carddata
, clr0
, clr1
, pat0
, pat1
);
497 /* NOTE: Assumes lock on bitmap is already made */
498 /* NOTE: Assumes buffer is not mapped */
499 BOOL
HIDDNouveauNV04FillSolidRect(struct CardData
* carddata
,
500 struct HIDDNouveauBitMapData
* bmdata
, LONG minX
, LONG minY
, LONG maxX
,
501 LONG maxY
, ULONG drawmode
, ULONG color
)
503 if (NV04EXAPrepareSolid(bmdata
, drawmode
, ~0, color
))
505 NV04EXASolid(bmdata
, minX
, minY
, maxX
+ 1, maxY
+ 1);
512 /* NOTE: Assumes lock on bitmap is already made */
513 /* NOTE: Assumes buffer is not mapped */
514 BOOL
HIDDNouveauNV04CopySameFormat(struct CardData
* carddata
,
515 struct HIDDNouveauBitMapData
* srcdata
, struct HIDDNouveauBitMapData
* destdata
,
516 LONG srcX
, LONG srcY
, LONG destX
, LONG destY
, LONG width
, LONG height
,
519 if (NV04EXAPrepareCopy(srcdata
, destdata
, 0, 0, drawmode
, ~0))
521 NV04EXACopy(destdata
, srcX
, srcY
, destX
, destY
, width
, height
);