1 #include "pipe/p_context.h"
2 #include "pipe/p_format.h"
3 #include "util/u_memory.h"
5 #include "nouveau/nouveau_winsys.h"
6 #include "nouveau/nouveau_util.h"
7 #include "nv04_surface_2d.h"
10 nv04_surface_format(enum pipe_format format
)
13 case PIPE_FORMAT_A8_UNORM
:
14 return NV04_CONTEXT_SURFACES_2D_FORMAT_Y8
;
15 case PIPE_FORMAT_R16_SNORM
:
16 case PIPE_FORMAT_R5G6B5_UNORM
:
17 return NV04_CONTEXT_SURFACES_2D_FORMAT_R5G6B5
;
18 case PIPE_FORMAT_X8R8G8B8_UNORM
:
19 case PIPE_FORMAT_A8R8G8B8_UNORM
:
20 return NV04_CONTEXT_SURFACES_2D_FORMAT_A8R8G8B8
;
21 case PIPE_FORMAT_Z24S8_UNORM
:
22 return NV04_CONTEXT_SURFACES_2D_FORMAT_Y32
;
29 nv04_rect_format(enum pipe_format format
)
32 case PIPE_FORMAT_A8_UNORM
:
33 return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8
;
34 case PIPE_FORMAT_R5G6B5_UNORM
:
35 return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A16R5G6B5
;
36 case PIPE_FORMAT_A8R8G8B8_UNORM
:
37 case PIPE_FORMAT_Z24S8_UNORM
:
38 return NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT_A8R8G8B8
;
45 nv04_scaled_image_format(enum pipe_format format
)
48 case PIPE_FORMAT_A1R5G5B5_UNORM
:
49 return NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A1R5G5B5
;
50 case PIPE_FORMAT_A8R8G8B8_UNORM
:
51 return NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_A8R8G8B8
;
52 case PIPE_FORMAT_X8R8G8B8_UNORM
:
53 return NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_X8R8G8B8
;
54 case PIPE_FORMAT_R5G6B5_UNORM
:
55 case PIPE_FORMAT_R16_SNORM
:
56 return NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_FORMAT_R5G6B5
;
62 static INLINE
unsigned
63 nv04_swizzle_bits(unsigned x
, unsigned y
)
65 unsigned u
= (x
& 0x001) << 0 |
78 unsigned v
= (y
& 0x001) << 1 |
94 nv04_surface_copy_swizzle(struct nv04_surface_2d
*ctx
,
95 struct pipe_surface
*dst
, int dx
, int dy
,
96 struct pipe_surface
*src
, int sx
, int sy
,
99 struct nouveau_channel
*chan
= ctx
->nvws
->channel
;
100 struct nouveau_grobj
*swzsurf
= ctx
->swzsurf
;
101 struct nouveau_grobj
*sifm
= ctx
->sifm
;
102 struct nouveau_bo
*src_bo
= ctx
->nvws
->get_bo(ctx
->buf(src
));
103 struct nouveau_bo
*dst_bo
= ctx
->nvws
->get_bo(ctx
->buf(dst
));
104 const unsigned src_pitch
= ((struct nv04_surface
*)src
)->pitch
;
105 const unsigned max_w
= 1024;
106 const unsigned max_h
= 1024;
107 const unsigned sub_w
= w
> max_w
? max_w
: w
;
108 const unsigned sub_h
= h
> max_h
? max_h
: h
;
113 assert(!(w
& (w
- 1)) && !(h
& (h
- 1)));
114 /* That's the way she likes it */
115 assert(src_pitch
== ((struct nv04_surface
*)dst
)->pitch
);
117 BEGIN_RING(chan
, swzsurf
, NV04_SWIZZLED_SURFACE_DMA_IMAGE
, 1);
118 OUT_RELOCo(chan
, dst_bo
,
119 NOUVEAU_BO_GART
| NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
121 BEGIN_RING(chan
, swzsurf
, NV04_SWIZZLED_SURFACE_FORMAT
, 1);
122 OUT_RING (chan
, nv04_surface_format(dst
->format
) |
123 log2i(w
) << NV04_SWIZZLED_SURFACE_FORMAT_BASE_SIZE_U_SHIFT
|
124 log2i(h
) << NV04_SWIZZLED_SURFACE_FORMAT_BASE_SIZE_V_SHIFT
);
126 BEGIN_RING(chan
, sifm
, NV04_SCALED_IMAGE_FROM_MEMORY_DMA_IMAGE
, 1);
127 OUT_RELOCo(chan
, src_bo
,
128 NOUVEAU_BO_GART
| NOUVEAU_BO_VRAM
| NOUVEAU_BO_RD
);
129 BEGIN_RING(chan
, sifm
, NV04_SCALED_IMAGE_FROM_MEMORY_SURFACE
, 1);
130 OUT_RING (chan
, swzsurf
->handle
);
132 for (cy
= 0; cy
< h
; cy
+= sub_h
) {
133 for (cx
= 0; cx
< w
; cx
+= sub_w
) {
134 BEGIN_RING(chan
, swzsurf
, NV04_SWIZZLED_SURFACE_OFFSET
, 1);
135 OUT_RELOCl(chan
, dst_bo
, dst
->offset
+ nv04_swizzle_bits(cx
, cy
) *
136 dst
->texture
->block
.size
, NOUVEAU_BO_GART
|
137 NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
139 BEGIN_RING(chan
, sifm
, NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION
, 9);
140 OUT_RING (chan
, NV04_SCALED_IMAGE_FROM_MEMORY_COLOR_CONVERSION_TRUNCATE
);
141 OUT_RING (chan
, nv04_scaled_image_format(src
->format
));
142 OUT_RING (chan
, NV04_SCALED_IMAGE_FROM_MEMORY_OPERATION_SRCCOPY
);
144 OUT_RING (chan
, sub_h
<< 16 | sub_w
);
146 OUT_RING (chan
, sub_h
<< 16 | sub_w
);
147 OUT_RING (chan
, 1 << 20);
148 OUT_RING (chan
, 1 << 20);
150 BEGIN_RING(chan
, sifm
, NV04_SCALED_IMAGE_FROM_MEMORY_SIZE
, 4);
151 OUT_RING (chan
, sub_h
<< 16 | sub_w
);
152 OUT_RING (chan
, src_pitch
|
153 NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_ORIGIN_CENTER
|
154 NV04_SCALED_IMAGE_FROM_MEMORY_FORMAT_FILTER_POINT_SAMPLE
);
155 OUT_RELOCl(chan
, src_bo
, src
->offset
+ cy
* src_pitch
+
156 cx
* src
->texture
->block
.size
, NOUVEAU_BO_GART
|
157 NOUVEAU_BO_VRAM
| NOUVEAU_BO_RD
);
166 nv04_surface_copy_m2mf(struct nv04_surface_2d
*ctx
,
167 struct pipe_surface
*dst
, int dx
, int dy
,
168 struct pipe_surface
*src
, int sx
, int sy
, int w
, int h
)
170 struct nouveau_channel
*chan
= ctx
->nvws
->channel
;
171 struct nouveau_grobj
*m2mf
= ctx
->m2mf
;
172 struct nouveau_bo
*src_bo
= ctx
->nvws
->get_bo(ctx
->buf(src
));
173 struct nouveau_bo
*dst_bo
= ctx
->nvws
->get_bo(ctx
->buf(dst
));
174 unsigned src_pitch
= ((struct nv04_surface
*)src
)->pitch
;
175 unsigned dst_pitch
= ((struct nv04_surface
*)dst
)->pitch
;
176 unsigned dst_offset
= dst
->offset
+ dy
* dst_pitch
+
177 dx
* dst
->texture
->block
.size
;
178 unsigned src_offset
= src
->offset
+ sy
* src_pitch
+
179 sx
* src
->texture
->block
.size
;
181 WAIT_RING (chan
, 3 + ((h
/ 2047) + 1) * 9);
182 BEGIN_RING(chan
, m2mf
, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_BUFFER_IN
, 2);
183 OUT_RELOCo(chan
, src_bo
,
184 NOUVEAU_BO_GART
| NOUVEAU_BO_VRAM
| NOUVEAU_BO_RD
);
185 OUT_RELOCo(chan
, dst_bo
,
186 NOUVEAU_BO_GART
| NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
189 int count
= (h
> 2047) ? 2047 : h
;
191 BEGIN_RING(chan
, m2mf
, NV04_MEMORY_TO_MEMORY_FORMAT_OFFSET_IN
, 8);
192 OUT_RELOCl(chan
, src_bo
, src_offset
,
193 NOUVEAU_BO_VRAM
| NOUVEAU_BO_GART
| NOUVEAU_BO_RD
);
194 OUT_RELOCl(chan
, dst_bo
, dst_offset
,
195 NOUVEAU_BO_VRAM
| NOUVEAU_BO_GART
| NOUVEAU_BO_WR
);
196 OUT_RING (chan
, src_pitch
);
197 OUT_RING (chan
, dst_pitch
);
198 OUT_RING (chan
, w
* src
->texture
->block
.size
);
199 OUT_RING (chan
, count
);
200 OUT_RING (chan
, 0x0101);
204 src_offset
+= src_pitch
* count
;
205 dst_offset
+= dst_pitch
* count
;
212 nv04_surface_copy_blit(struct nv04_surface_2d
*ctx
, struct pipe_surface
*dst
,
213 int dx
, int dy
, struct pipe_surface
*src
, int sx
, int sy
,
216 struct nouveau_channel
*chan
= ctx
->nvws
->channel
;
217 struct nouveau_grobj
*surf2d
= ctx
->surf2d
;
218 struct nouveau_grobj
*blit
= ctx
->blit
;
219 struct nouveau_bo
*src_bo
= ctx
->nvws
->get_bo(ctx
->buf(src
));
220 struct nouveau_bo
*dst_bo
= ctx
->nvws
->get_bo(ctx
->buf(dst
));
221 unsigned src_pitch
= ((struct nv04_surface
*)src
)->pitch
;
222 unsigned dst_pitch
= ((struct nv04_surface
*)dst
)->pitch
;
225 format
= nv04_surface_format(dst
->format
);
229 WAIT_RING (chan
, 12);
230 BEGIN_RING(chan
, surf2d
, NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE
, 2);
231 OUT_RELOCo(chan
, src_bo
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_RD
);
232 OUT_RELOCo(chan
, dst_bo
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
233 BEGIN_RING(chan
, surf2d
, NV04_CONTEXT_SURFACES_2D_FORMAT
, 4);
234 OUT_RING (chan
, format
);
235 OUT_RING (chan
, (dst_pitch
<< 16) | src_pitch
);
236 OUT_RELOCl(chan
, src_bo
, src
->offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_RD
);
237 OUT_RELOCl(chan
, dst_bo
, dst
->offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
239 BEGIN_RING(chan
, blit
, 0x0300, 3);
240 OUT_RING (chan
, (sy
<< 16) | sx
);
241 OUT_RING (chan
, (dy
<< 16) | dx
);
242 OUT_RING (chan
, ( h
<< 16) | w
);
248 nv04_surface_copy(struct nv04_surface_2d
*ctx
, struct pipe_surface
*dst
,
249 int dx
, int dy
, struct pipe_surface
*src
, int sx
, int sy
,
252 unsigned src_pitch
= ((struct nv04_surface
*)src
)->pitch
;
253 unsigned dst_pitch
= ((struct nv04_surface
*)dst
)->pitch
;
254 int src_linear
= src
->texture
->tex_usage
& NOUVEAU_TEXTURE_USAGE_LINEAR
;
255 int dst_linear
= dst
->texture
->tex_usage
& NOUVEAU_TEXTURE_USAGE_LINEAR
;
257 assert(src
->format
== dst
->format
);
259 /* Setup transfer to swizzle the texture to vram if needed */
260 if (src_linear
&& !dst_linear
&& w
> 1 && h
> 1) {
261 nv04_surface_copy_swizzle(ctx
, dst
, dx
, dy
, src
, sx
, sy
, w
, h
);
265 /* NV_CONTEXT_SURFACES_2D has buffer alignment restrictions, fallback
266 * to NV_MEMORY_TO_MEMORY_FORMAT in this case.
268 if ((src
->offset
& 63) || (dst
->offset
& 63) ||
269 (src_pitch
& 63) || (dst_pitch
& 63) ||
270 debug_get_bool_option("NOUVEAU_NO_COPYBLIT", FALSE
)) {
271 nv04_surface_copy_m2mf(ctx
, dst
, dx
, dy
, src
, sx
, sy
, w
, h
);
275 nv04_surface_copy_blit(ctx
, dst
, dx
, dy
, src
, sx
, sy
, w
, h
);
279 nv04_surface_fill(struct nv04_surface_2d
*ctx
, struct pipe_surface
*dst
,
280 int dx
, int dy
, int w
, int h
, unsigned value
)
282 struct nouveau_channel
*chan
= ctx
->nvws
->channel
;
283 struct nouveau_grobj
*surf2d
= ctx
->surf2d
;
284 struct nouveau_grobj
*rect
= ctx
->rect
;
285 struct nouveau_bo
*dst_bo
= ctx
->nvws
->get_bo(ctx
->buf(dst
));
286 unsigned dst_pitch
= ((struct nv04_surface
*)dst
)->pitch
;
287 int cs2d_format
, gdirect_format
;
289 cs2d_format
= nv04_surface_format(dst
->format
);
290 assert(cs2d_format
>= 0);
292 gdirect_format
= nv04_rect_format(dst
->format
);
293 assert(gdirect_format
>= 0);
295 WAIT_RING (chan
, 16);
296 BEGIN_RING(chan
, surf2d
, NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE
, 2);
297 OUT_RELOCo(chan
, dst_bo
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
298 OUT_RELOCo(chan
, dst_bo
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
299 BEGIN_RING(chan
, surf2d
, NV04_CONTEXT_SURFACES_2D_FORMAT
, 4);
300 OUT_RING (chan
, cs2d_format
);
301 OUT_RING (chan
, (dst_pitch
<< 16) | dst_pitch
);
302 OUT_RELOCl(chan
, dst_bo
, dst
->offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
303 OUT_RELOCl(chan
, dst_bo
, dst
->offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
305 BEGIN_RING(chan
, rect
, NV04_GDI_RECTANGLE_TEXT_COLOR_FORMAT
, 1);
306 OUT_RING (chan
, gdirect_format
);
307 BEGIN_RING(chan
, rect
, NV04_GDI_RECTANGLE_TEXT_COLOR1_A
, 1);
308 OUT_RING (chan
, value
);
309 BEGIN_RING(chan
, rect
,
310 NV04_GDI_RECTANGLE_TEXT_UNCLIPPED_RECTANGLE_POINT(0), 2);
311 OUT_RING (chan
, (dx
<< 16) | dy
);
312 OUT_RING (chan
, ( w
<< 16) | h
);
316 nv04_surface_2d_takedown(struct nv04_surface_2d
**pctx
)
318 struct nv04_surface_2d
*ctx
;
325 nouveau_notifier_free(&ctx
->ntfy
);
326 nouveau_grobj_free(&ctx
->m2mf
);
327 nouveau_grobj_free(&ctx
->surf2d
);
328 nouveau_grobj_free(&ctx
->swzsurf
);
329 nouveau_grobj_free(&ctx
->rect
);
330 nouveau_grobj_free(&ctx
->blit
);
331 nouveau_grobj_free(&ctx
->sifm
);
336 struct nv04_surface_2d
*
337 nv04_surface_2d_init(struct nouveau_winsys
*nvws
)
339 struct nv04_surface_2d
*ctx
= CALLOC_STRUCT(nv04_surface_2d
);
340 struct nouveau_channel
*chan
= nvws
->channel
;
341 unsigned handle
= 0x88000000, class;
347 ret
= nouveau_notifier_alloc(chan
, handle
++, 1, &ctx
->ntfy
);
349 nv04_surface_2d_takedown(&ctx
);
353 ret
= nouveau_grobj_alloc(chan
, handle
++, 0x0039, &ctx
->m2mf
);
355 nv04_surface_2d_takedown(&ctx
);
359 BEGIN_RING(chan
, ctx
->m2mf
, NV04_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY
, 1);
360 OUT_RING (chan
, ctx
->ntfy
->handle
);
362 if (chan
->device
->chipset
< 0x10)
363 class = NV04_CONTEXT_SURFACES_2D
;
365 class = NV10_CONTEXT_SURFACES_2D
;
367 ret
= nouveau_grobj_alloc(chan
, handle
++, class, &ctx
->surf2d
);
369 nv04_surface_2d_takedown(&ctx
);
373 BEGIN_RING(chan
, ctx
->surf2d
,
374 NV04_CONTEXT_SURFACES_2D_DMA_IMAGE_SOURCE
, 2);
375 OUT_RING (chan
, chan
->vram
->handle
);
376 OUT_RING (chan
, chan
->vram
->handle
);
378 if (chan
->device
->chipset
< 0x10)
379 class = NV04_IMAGE_BLIT
;
381 class = NV12_IMAGE_BLIT
;
383 ret
= nouveau_grobj_alloc(chan
, handle
++, class, &ctx
->blit
);
385 nv04_surface_2d_takedown(&ctx
);
389 BEGIN_RING(chan
, ctx
->blit
, NV04_IMAGE_BLIT_DMA_NOTIFY
, 1);
390 OUT_RING (chan
, ctx
->ntfy
->handle
);
391 BEGIN_RING(chan
, ctx
->blit
, NV04_IMAGE_BLIT_SURFACE
, 1);
392 OUT_RING (chan
, ctx
->surf2d
->handle
);
393 BEGIN_RING(chan
, ctx
->blit
, NV04_IMAGE_BLIT_OPERATION
, 1);
394 OUT_RING (chan
, NV04_IMAGE_BLIT_OPERATION_SRCCOPY
);
396 ret
= nouveau_grobj_alloc(chan
, handle
++, NV04_GDI_RECTANGLE_TEXT
,
399 nv04_surface_2d_takedown(&ctx
);
403 BEGIN_RING(chan
, ctx
->rect
, NV04_GDI_RECTANGLE_TEXT_DMA_NOTIFY
, 1);
404 OUT_RING (chan
, ctx
->ntfy
->handle
);
405 BEGIN_RING(chan
, ctx
->rect
, NV04_GDI_RECTANGLE_TEXT_SURFACE
, 1);
406 OUT_RING (chan
, ctx
->surf2d
->handle
);
407 BEGIN_RING(chan
, ctx
->rect
, NV04_GDI_RECTANGLE_TEXT_OPERATION
, 1);
408 OUT_RING (chan
, NV04_GDI_RECTANGLE_TEXT_OPERATION_SRCCOPY
);
409 BEGIN_RING(chan
, ctx
->rect
,
410 NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT
, 1);
411 OUT_RING (chan
, NV04_GDI_RECTANGLE_TEXT_MONOCHROME_FORMAT_LE
);
413 switch (chan
->device
->chipset
& 0xf0) {
416 class = NV04_SWIZZLED_SURFACE
;
419 class = NV20_SWIZZLED_SURFACE
;
422 class = NV30_SWIZZLED_SURFACE
;
426 class = NV40_SWIZZLED_SURFACE
;
429 /* Famous last words: this really can't happen.. */
434 ret
= nouveau_grobj_alloc(chan
, handle
++, class, &ctx
->swzsurf
);
436 nv04_surface_2d_takedown(&ctx
);
440 switch (chan
->device
->chipset
& 0xf0) {
443 class = NV10_SCALED_IMAGE_FROM_MEMORY
;
446 class = NV30_SCALED_IMAGE_FROM_MEMORY
;
450 class = NV40_SCALED_IMAGE_FROM_MEMORY
;
453 class = NV04_SCALED_IMAGE_FROM_MEMORY
;
457 ret
= nouveau_grobj_alloc(chan
, handle
++, class, &ctx
->sifm
);
459 nv04_surface_2d_takedown(&ctx
);
464 ctx
->copy
= nv04_surface_copy
;
465 ctx
->fill
= nv04_surface_fill
;