2 * Copyright (C) 2007-2010 The Nouveau Project.
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial
15 * portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 #include "nouveau_driver.h"
28 #include "nouveau_class.h"
29 #include "nouveau_context.h"
30 #include "nouveau_util.h"
31 #include "nv04_driver.h"
34 swzsurf_format(gl_format format
)
40 case MESA_FORMAT_RGB332
:
42 return NV04_SWIZZLED_SURFACE_FORMAT_COLOR_Y8
;
44 case MESA_FORMAT_RGB565
:
45 case MESA_FORMAT_RGB565_REV
:
46 case MESA_FORMAT_ARGB4444
:
47 case MESA_FORMAT_ARGB4444_REV
:
48 case MESA_FORMAT_ARGB1555
:
49 case MESA_FORMAT_RGBA5551
:
50 case MESA_FORMAT_ARGB1555_REV
:
51 case MESA_FORMAT_AL88
:
52 case MESA_FORMAT_AL88_REV
:
53 case MESA_FORMAT_YCBCR
:
54 case MESA_FORMAT_YCBCR_REV
:
56 return NV04_SWIZZLED_SURFACE_FORMAT_COLOR_R5G6B5
;
58 case MESA_FORMAT_RGBA8888
:
59 case MESA_FORMAT_RGBA8888_REV
:
60 case MESA_FORMAT_XRGB8888
:
61 case MESA_FORMAT_ARGB8888
:
62 case MESA_FORMAT_ARGB8888_REV
:
63 case MESA_FORMAT_S8_Z24
:
64 case MESA_FORMAT_Z24_S8
:
66 return NV04_SWIZZLED_SURFACE_FORMAT_COLOR_A8R8G8B8
;
74 surf2d_format(gl_format format
)
80 case MESA_FORMAT_RGB332
:
82 return NV04_CONTEXT_SURFACES_2D_FORMAT_Y8
;
84 case MESA_FORMAT_RGB565
:
85 case MESA_FORMAT_RGB565_REV
:
86 case MESA_FORMAT_ARGB4444
:
87 case MESA_FORMAT_ARGB4444_REV
:
88 case MESA_FORMAT_ARGB1555
:
89 case MESA_FORMAT_RGBA5551
:
90 case MESA_FORMAT_ARGB1555_REV
:
91 case MESA_FORMAT_AL88
:
92 case MESA_FORMAT_AL88_REV
:
93 case MESA_FORMAT_YCBCR
:
94 case MESA_FORMAT_YCBCR_REV
:
96 return NV04_CONTEXT_SURFACES_2D_FORMAT_R5G6B5
;
98 case MESA_FORMAT_RGBA8888
:
99 case MESA_FORMAT_RGBA8888_REV
:
100 case MESA_FORMAT_XRGB8888
:
101 case MESA_FORMAT_ARGB8888
:
102 case MESA_FORMAT_ARGB8888_REV
:
103 case MESA_FORMAT_S8_Z24
:
104 case MESA_FORMAT_Z24_S8
:
105 case MESA_FORMAT_Z32
:
106 return NV04_CONTEXT_SURFACES_2D_FORMAT_Y32
;
114 rect_format(gl_format format
)
120 case MESA_FORMAT_RGB332
:
121 case MESA_FORMAT_CI8
:
122 return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8
;
124 case MESA_FORMAT_RGB565
:
125 case MESA_FORMAT_RGB565_REV
:
126 case MESA_FORMAT_ARGB4444
:
127 case MESA_FORMAT_ARGB4444_REV
:
128 case MESA_FORMAT_ARGB1555
:
129 case MESA_FORMAT_RGBA5551
:
130 case MESA_FORMAT_ARGB1555_REV
:
131 case MESA_FORMAT_AL88
:
132 case MESA_FORMAT_AL88_REV
:
133 case MESA_FORMAT_YCBCR
:
134 case MESA_FORMAT_YCBCR_REV
:
135 case MESA_FORMAT_Z16
:
136 return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A16R5G6B5
;
138 case MESA_FORMAT_RGBA8888
:
139 case MESA_FORMAT_RGBA8888_REV
:
140 case MESA_FORMAT_XRGB8888
:
141 case MESA_FORMAT_ARGB8888
:
142 case MESA_FORMAT_ARGB8888_REV
:
143 case MESA_FORMAT_S8_Z24
:
144 case MESA_FORMAT_Z24_S8
:
145 case MESA_FORMAT_Z32
:
146 return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8
;
154 sifm_format(gl_format format
)
160 case MESA_FORMAT_RGB332
:
161 case MESA_FORMAT_CI8
:
162 return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_AY8
;
164 case MESA_FORMAT_RGB565
:
165 case MESA_FORMAT_RGB565_REV
:
166 case MESA_FORMAT_ARGB4444
:
167 case MESA_FORMAT_ARGB4444_REV
:
168 case MESA_FORMAT_ARGB1555
:
169 case MESA_FORMAT_RGBA5551
:
170 case MESA_FORMAT_ARGB1555_REV
:
171 case MESA_FORMAT_AL88
:
172 case MESA_FORMAT_AL88_REV
:
173 case MESA_FORMAT_YCBCR
:
174 case MESA_FORMAT_YCBCR_REV
:
175 case MESA_FORMAT_Z16
:
176 return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_R5G6B5
;
178 case MESA_FORMAT_RGBA8888
:
179 case MESA_FORMAT_RGBA8888_REV
:
180 case MESA_FORMAT_XRGB8888
:
181 case MESA_FORMAT_ARGB8888
:
182 case MESA_FORMAT_ARGB8888_REV
:
183 case MESA_FORMAT_S8_Z24
:
184 case MESA_FORMAT_Z24_S8
:
185 case MESA_FORMAT_Z32
:
186 return NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A8R8G8B8
;
194 nv04_surface_copy_swizzle(GLcontext
*ctx
,
195 struct nouveau_surface
*dst
,
196 struct nouveau_surface
*src
,
197 int dx
, int dy
, int sx
, int sy
,
200 struct nouveau_channel
*chan
= context_chan(ctx
);
201 struct nouveau_screen
*screen
= to_nouveau_context(ctx
)->screen
;
202 struct nouveau_grobj
*swzsurf
= screen
->swzsurf
;
203 struct nouveau_grobj
*sifm
= screen
->sifm
;
204 struct nouveau_bo_context
*bctx
= context_bctx(ctx
, SURFACE
);
205 const unsigned bo_flags
= NOUVEAU_BO_VRAM
| NOUVEAU_BO_GART
;
206 /* Max width & height may not be the same on all HW, but must be POT */
207 const unsigned max_w
= 1024;
208 const unsigned max_h
= 1024;
209 unsigned sub_w
= w
> max_w
? max_w
: w
;
210 unsigned sub_h
= h
> max_h
? max_h
: h
;
213 /* Swizzled surfaces must be POT */
214 assert(_mesa_is_pow_two(dst
->width
) &&
215 _mesa_is_pow_two(dst
->height
));
217 /* If area is too large to copy in one shot we must copy it in
218 * POT chunks to meet alignment requirements */
219 assert(sub_w
== w
|| _mesa_is_pow_two(sub_w
));
220 assert(sub_h
== h
|| _mesa_is_pow_two(sub_h
));
222 nouveau_bo_marko(bctx
, sifm
, NV03_SCALED_IMAGE_FROM_MEMORY_DMA_IMAGE
,
223 src
->bo
, bo_flags
| NOUVEAU_BO_RD
);
224 nouveau_bo_marko(bctx
, swzsurf
, NV04_SWIZZLED_SURFACE_DMA_IMAGE
,
225 dst
->bo
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
226 nouveau_bo_markl(bctx
, swzsurf
, NV04_SWIZZLED_SURFACE_OFFSET
,
227 dst
->bo
, dst
->offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
229 BEGIN_RING(chan
, swzsurf
, NV04_SWIZZLED_SURFACE_FORMAT
, 1);
230 OUT_RING (chan
, swzsurf_format(dst
->format
) |
231 log2i(dst
->width
) << 16 |
232 log2i(dst
->height
) << 24);
234 BEGIN_RING(chan
, sifm
, NV04_SCALED_IMAGE_FROM_MEMORY_SURFACE
, 1);
235 OUT_RING (chan
, swzsurf
->handle
);
237 for (y
= 0; y
< h
; y
+= sub_h
) {
238 sub_h
= MIN2(sub_h
, h
- y
);
240 for (x
= 0; x
< w
; x
+= sub_w
) {
241 sub_w
= MIN2(sub_w
, w
- x
);
242 /* Must be 64-byte aligned */
243 assert(!(dst
->offset
& 63));
245 MARK_RING(chan
, 15, 1);
247 BEGIN_RING(chan
, sifm
,
248 NV03_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT
, 8);
249 OUT_RING(chan
, sifm_format(src
->format
));
250 OUT_RING(chan
, NV03_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY
);
251 OUT_RING(chan
, (y
+ dy
) << 16 | (x
+ dx
));
252 OUT_RING(chan
, sub_h
<< 16 | sub_w
);
253 OUT_RING(chan
, (y
+ dy
) << 16 | (x
+ dx
));
254 OUT_RING(chan
, sub_h
<< 16 | sub_w
);
255 OUT_RING(chan
, 1 << 20);
256 OUT_RING(chan
, 1 << 20);
258 BEGIN_RING(chan
, sifm
,
259 NV03_SCALED_IMAGE_FROM_MEMORY_SIZE
, 4);
260 OUT_RING(chan
, sub_h
<< 16 | sub_w
);
261 OUT_RING(chan
, src
->pitch
|
262 NV03_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_CENTER
|
263 NV03_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_POINT_SAMPLE
);
264 OUT_RELOCl(chan
, src
->bo
, src
->offset
+
265 (y
+ sy
) * src
->pitch
+
267 bo_flags
| NOUVEAU_BO_RD
);
272 nouveau_bo_context_reset(bctx
);
274 if (context_chipset(ctx
) < 0x10)
279 nv04_surface_copy_m2mf(GLcontext
*ctx
,
280 struct nouveau_surface
*dst
,
281 struct nouveau_surface
*src
,
282 int dx
, int dy
, int sx
, int sy
,
285 struct nouveau_channel
*chan
= context_chan(ctx
);
286 struct nouveau_screen
*screen
= to_nouveau_context(ctx
)->screen
;
287 struct nouveau_grobj
*m2mf
= screen
->m2mf
;
288 struct nouveau_bo_context
*bctx
= context_bctx(ctx
, SURFACE
);
289 const unsigned bo_flags
= NOUVEAU_BO_VRAM
| NOUVEAU_BO_GART
;
290 unsigned dst_offset
= dst
->offset
+ dy
* dst
->pitch
+ dx
* dst
->cpp
;
291 unsigned src_offset
= src
->offset
+ sy
* src
->pitch
+ sx
* src
->cpp
;
293 nouveau_bo_marko(bctx
, m2mf
, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN
,
294 src
->bo
, bo_flags
| NOUVEAU_BO_RD
);
295 nouveau_bo_marko(bctx
, m2mf
, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_OUT
,
296 dst
->bo
, bo_flags
| NOUVEAU_BO_WR
);
299 int count
= (h
> 2047) ? 2047 : h
;
301 MARK_RING(chan
, 9, 2);
303 BEGIN_RING(chan
, m2mf
, NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN
, 8);
304 OUT_RELOCl(chan
, src
->bo
, src_offset
,
305 bo_flags
| NOUVEAU_BO_RD
);
306 OUT_RELOCl(chan
, dst
->bo
, dst_offset
,
307 bo_flags
| NOUVEAU_BO_WR
);
308 OUT_RING (chan
, src
->pitch
);
309 OUT_RING (chan
, dst
->pitch
);
310 OUT_RING (chan
, w
* src
->cpp
);
311 OUT_RING (chan
, count
);
312 OUT_RING (chan
, 0x0101);
316 src_offset
+= src
->pitch
* count
;
317 dst_offset
+= dst
->pitch
* count
;
320 nouveau_bo_context_reset(bctx
);
322 if (context_chipset(ctx
) < 0x10)
327 nv04_surface_copy(GLcontext
*ctx
,
328 struct nouveau_surface
*dst
,
329 struct nouveau_surface
*src
,
330 int dx
, int dy
, int sx
, int sy
,
333 /* Setup transfer to swizzle the texture to vram if needed */
334 if (src
->layout
!= SWIZZLED
&&
335 dst
->layout
== SWIZZLED
&&
336 dst
->width
> 2 && dst
->height
> 1) {
337 nv04_surface_copy_swizzle(ctx
, dst
, src
,
338 dx
, dy
, sx
, sy
, w
, h
);
342 nv04_surface_copy_m2mf(ctx
, dst
, src
, dx
, dy
, sx
, sy
, w
, h
);
346 nv04_surface_fill(GLcontext
*ctx
,
347 struct nouveau_surface
*dst
,
348 unsigned mask
, unsigned value
,
349 int dx
, int dy
, int w
, int h
)
351 struct nouveau_channel
*chan
= context_chan(ctx
);
352 struct nouveau_screen
*screen
= to_nouveau_context(ctx
)->screen
;
353 struct nouveau_grobj
*surf2d
= screen
->surf2d
;
354 struct nouveau_grobj
*patt
= screen
->patt
;
355 struct nouveau_grobj
*rect
= screen
->rect
;
356 unsigned bo_flags
= NOUVEAU_BO_VRAM
| NOUVEAU_BO_GART
;
358 MARK_RING (chan
, 19, 4);
360 BEGIN_RING(chan
, surf2d
, NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE
, 2);
361 OUT_RELOCo(chan
, dst
->bo
, bo_flags
| NOUVEAU_BO_WR
);
362 OUT_RELOCo(chan
, dst
->bo
, bo_flags
| NOUVEAU_BO_WR
);
363 BEGIN_RING(chan
, surf2d
, NV04_CONTEXT_SURFACES_2D_FORMAT
, 4);
364 OUT_RING (chan
, surf2d_format(dst
->format
));
365 OUT_RING (chan
, (dst
->pitch
<< 16) | dst
->pitch
);
366 OUT_RELOCl(chan
, dst
->bo
, dst
->offset
, bo_flags
| NOUVEAU_BO_WR
);
367 OUT_RELOCl(chan
, dst
->bo
, dst
->offset
, bo_flags
| NOUVEAU_BO_WR
);
369 BEGIN_RING(chan
, patt
, NV04_IMAGE_PATTERN_COLOR_FORMAT
, 1);
370 OUT_RING (chan
, rect_format(dst
->format
));
371 BEGIN_RING(chan
, patt
, NV04_IMAGE_PATTERN_MONOCHROME_COLOR1
, 1);
372 OUT_RING (chan
, mask
| ~0 << (8 * dst
->cpp
));
374 BEGIN_RING(chan
, rect
, NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT
, 1);
375 OUT_RING (chan
, rect_format(dst
->format
));
376 BEGIN_RING(chan
, rect
, NV04_GDI_RECTANGLE_TEXT_COLOR1_A
, 1);
377 OUT_RING (chan
, value
);
378 BEGIN_RING(chan
, rect
,
379 NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT(0), 2);
380 OUT_RING (chan
, (dx
<< 16) | dy
);
381 OUT_RING (chan
, ( w
<< 16) | h
);
383 if (context_chipset(ctx
) < 0x10)
388 nv04_surface_takedown(struct nouveau_screen
*screen
)
390 nouveau_grobj_free(&screen
->swzsurf
);
391 nouveau_grobj_free(&screen
->sifm
);
392 nouveau_grobj_free(&screen
->rect
);
393 nouveau_grobj_free(&screen
->rop
);
394 nouveau_grobj_free(&screen
->patt
);
395 nouveau_grobj_free(&screen
->surf2d
);
396 nouveau_grobj_free(&screen
->m2mf
);
397 nouveau_notifier_free(&screen
->ntfy
);
401 nv04_surface_init(struct nouveau_screen
*screen
)
403 struct nouveau_channel
*chan
= screen
->chan
;
404 const unsigned chipset
= screen
->device
->chipset
;
405 unsigned handle
= 0x88000000, class;
408 /* Notifier object. */
409 ret
= nouveau_notifier_alloc(chan
, handle
++, 1, &screen
->ntfy
);
413 /* Memory to memory format. */
414 ret
= nouveau_grobj_alloc(chan
, handle
++, NV04_MEMORY_TO_MEMORY_FORMAT
,
419 BEGIN_RING(chan
, screen
->m2mf
, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY
, 1);
420 OUT_RING (chan
, screen
->ntfy
->handle
);
422 /* Context surfaces 2D. */
423 if (chan
->device
->chipset
< 0x10)
424 class = NV04_CONTEXT_SURFACES_2D
;
426 class = NV10_CONTEXT_SURFACES_2D
;
428 ret
= nouveau_grobj_alloc(chan
, handle
++, class, &screen
->surf2d
);
433 ret
= nouveau_grobj_alloc(chan
, handle
++, NV03_CONTEXT_ROP
,
438 BEGIN_RING(chan
, screen
->rop
, NV03_CONTEXT_ROP_DMA_NOTIFY
, 1);
439 OUT_RING (chan
, screen
->ntfy
->handle
);
441 BEGIN_RING(chan
, screen
->rop
, NV03_CONTEXT_ROP_ROP
, 1);
442 OUT_RING (chan
, 0xca); /* DPSDxax in the GDI speech. */
445 ret
= nouveau_grobj_alloc(chan
, handle
++, NV04_IMAGE_PATTERN
,
450 BEGIN_RING(chan
, screen
->patt
,
451 NV04_IMAGE_PATTERN_DMA_NOTIFY
, 1);
452 OUT_RING (chan
, screen
->ntfy
->handle
);
454 BEGIN_RING(chan
, screen
->patt
,
455 NV04_IMAGE_PATTERN_MONOCHROME_FORMAT
, 3);
456 OUT_RING (chan
, NV04_IMAGE_PATTERN_MONOCHROME_FORMAT_LE
);
457 OUT_RING (chan
, NV04_IMAGE_PATTERN_MONOCHROME_SHAPE_8X8
);
458 OUT_RING (chan
, NV04_IMAGE_PATTERN_PATTERN_SELECT_MONO
);
460 BEGIN_RING(chan
, screen
->patt
,
461 NV04_IMAGE_PATTERN_MONOCHROME_COLOR0
, 4);
467 /* GDI rectangle text. */
468 ret
= nouveau_grobj_alloc(chan
, handle
++, NV04_GDI_RECTANGLE_TEXT
,
473 BEGIN_RING(chan
, screen
->rect
, NV04_GDI_RECTANGLE_TEXT_DMA_NOTIFY
, 1);
474 OUT_RING (chan
, screen
->ntfy
->handle
);
475 BEGIN_RING(chan
, screen
->rect
, NV04_GDI_RECTANGLE_TEXT_SURFACE
, 1);
476 OUT_RING (chan
, screen
->surf2d
->handle
);
477 BEGIN_RING(chan
, screen
->rect
, NV04_GDI_RECTANGLE_TEXT_ROP
, 1);
478 OUT_RING (chan
, screen
->rop
->handle
);
479 BEGIN_RING(chan
, screen
->rect
, NV04_GDI_RECTANGLE_TEXT_PATTERN
, 1);
480 OUT_RING (chan
, screen
->patt
->handle
);
482 BEGIN_RING(chan
, screen
->rect
, NV04_GDI_RECTANGLE_TEXT_OPERATION
, 1);
483 OUT_RING (chan
, NV04_GDI_RECTANGLE_TEXT_OPERATION_ROP_AND
);
484 BEGIN_RING(chan
, screen
->rect
,
485 NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT
, 1);
486 OUT_RING (chan
, NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT_LE
);
488 /* Swizzled surface. */
489 switch (chan
->device
->chipset
& 0xf0) {
492 class = NV04_SWIZZLED_SURFACE
;
495 class = NV20_SWIZZLED_SURFACE
;
498 class = NV30_SWIZZLED_SURFACE
;
502 class = NV40_SWIZZLED_SURFACE
;
505 /* Famous last words: this really can't happen.. */
510 ret
= nouveau_grobj_alloc(chan
, handle
++, class, &screen
->swzsurf
);
514 /* Scaled image from memory. */
515 switch (chan
->device
->chipset
& 0xf0) {
518 class = NV10_SCALED_IMAGE_FROM_MEMORY
;
521 class = NV30_SCALED_IMAGE_FROM_MEMORY
;
525 class = NV40_SCALED_IMAGE_FROM_MEMORY
;
528 class = NV04_SCALED_IMAGE_FROM_MEMORY
;
532 ret
= nouveau_grobj_alloc(chan
, handle
++, class, &screen
->sifm
);
536 if (chipset
>= 0x10) {
537 BEGIN_RING(chan
, screen
->sifm
,
538 NV05_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION
, 1);
539 OUT_RING(chan
, NV05_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_TRUNCATE
);
545 nv04_surface_takedown(screen
);