2 * Copyright 2008 Ben Skeggs
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
25 #include "pipe/p_defines.h"
27 #include "util/u_inlines.h"
28 #include "util/u_pack_color.h"
29 #include "util/u_format.h"
30 #include "util/u_surface.h"
32 #include "nvc0_context.h"
33 #include "nvc0_resource.h"
35 #include "nv50/nv50_defs.xml.h"
37 #define NVC0_ENG2D_SUPPORTED_FORMATS 0xff9ccfe1cce3ccc9ULL
39 /* return TRUE for formats that can be converted among each other by NVC0_2D */
41 nvc0_2d_format_faithful(enum pipe_format format
)
43 uint8_t id
= nvc0_format_table
[format
].rt
;
45 return (id
>= 0xc0) && (NVC0_ENG2D_SUPPORTED_FORMATS
& (1ULL << (id
- 0xc0)));
49 nvc0_2d_format(enum pipe_format format
)
51 uint8_t id
= nvc0_format_table
[format
].rt
;
53 /* Hardware values for color formats range from 0xc0 to 0xff,
54 * but the 2D engine doesn't support all of them.
56 if (nvc0_2d_format_faithful(format
))
59 switch (util_format_get_blocksize(format
)) {
61 return NV50_SURFACE_FORMAT_R8_UNORM
;
63 return NV50_SURFACE_FORMAT_R16_UNORM
;
65 return NV50_SURFACE_FORMAT_BGRA8_UNORM
;
67 return NV50_SURFACE_FORMAT_RGBA16_UNORM
;
69 return NV50_SURFACE_FORMAT_RGBA32_FLOAT
;
76 nvc0_2d_texture_set(struct nouveau_channel
*chan
, int dst
,
77 struct nv50_miptree
*mt
, unsigned level
, unsigned layer
)
79 struct nouveau_bo
*bo
= mt
->base
.bo
;
80 uint32_t width
, height
, depth
;
82 uint32_t mthd
= dst
? NVC0_2D_DST_FORMAT
: NVC0_2D_SRC_FORMAT
;
83 uint32_t flags
= mt
->base
.domain
| (dst
? NOUVEAU_BO_WR
: NOUVEAU_BO_RD
);
84 uint32_t offset
= mt
->level
[level
].offset
;
86 format
= nvc0_2d_format(mt
->base
.base
.format
);
88 NOUVEAU_ERR("invalid/unsupported surface format: %s\n",
89 util_format_name(mt
->base
.base
.format
));
93 width
= u_minify(mt
->base
.base
.width0
, level
) << mt
->ms_x
;
94 height
= u_minify(mt
->base
.base
.height0
, level
) << mt
->ms_y
;
95 depth
= u_minify(mt
->base
.base
.depth0
, level
);
97 /* layer has to be < depth, and depth > tile depth / 2 */
100 offset
+= mt
->layer_stride
* layer
;
105 offset
+= nvc0_mt_zslice_offset(mt
, level
, layer
);
109 if (!(bo
->tile_flags
& NOUVEAU_BO_TILE_LAYOUT_MASK
)) {
110 BEGIN_RING(chan
, RING_2D_(mthd
), 2);
111 OUT_RING (chan
, format
);
113 BEGIN_RING(chan
, RING_2D_(mthd
+ 0x14), 5);
114 OUT_RING (chan
, mt
->level
[level
].pitch
);
115 OUT_RING (chan
, width
);
116 OUT_RING (chan
, height
);
117 OUT_RELOCh(chan
, bo
, offset
, flags
);
118 OUT_RELOCl(chan
, bo
, offset
, flags
);
120 BEGIN_RING(chan
, RING_2D_(mthd
), 5);
121 OUT_RING (chan
, format
);
123 OUT_RING (chan
, mt
->level
[level
].tile_mode
);
124 OUT_RING (chan
, depth
);
125 OUT_RING (chan
, layer
);
126 BEGIN_RING(chan
, RING_2D_(mthd
+ 0x18), 4);
127 OUT_RING (chan
, width
);
128 OUT_RING (chan
, height
);
129 OUT_RELOCh(chan
, bo
, offset
, flags
);
130 OUT_RELOCl(chan
, bo
, offset
, flags
);
135 BEGIN_RING(chan
, RING_2D_(NVC0_2D_CLIP_X
), 4);
138 OUT_RING (chan
, width
);
139 OUT_RING (chan
, height
);
146 nvc0_2d_texture_do_copy(struct nouveau_channel
*chan
,
147 struct nv50_miptree
*dst
, unsigned dst_level
,
148 unsigned dx
, unsigned dy
, unsigned dz
,
149 struct nv50_miptree
*src
, unsigned src_level
,
150 unsigned sx
, unsigned sy
, unsigned sz
,
151 unsigned w
, unsigned h
)
153 static const uint32_t duvdxy
[5] =
155 0x40000000, 0x80000000, 0x00000001, 0x00000002, 0x00000004
159 uint32_t ctrl
= 0x00;
161 ret
= MARK_RING(chan
, 2 * 16 + 32, 4);
165 ret
= nvc0_2d_texture_set(chan
, 1, dst
, dst_level
, dz
);
169 ret
= nvc0_2d_texture_set(chan
, 0, src
, src_level
, sz
);
173 /* NOTE: 2D engine doesn't work for MS8 */
177 /* 0/1 = CENTER/CORNER, 00/10 = POINT/BILINEAR */
178 BEGIN_RING(chan
, RING_2D(BLIT_CONTROL
), 1);
179 OUT_RING (chan
, ctrl
);
180 BEGIN_RING(chan
, RING_2D(BLIT_DST_X
), 4);
181 OUT_RING (chan
, dx
<< dst
->ms_x
);
182 OUT_RING (chan
, dy
<< dst
->ms_y
);
183 OUT_RING (chan
, w
<< dst
->ms_x
);
184 OUT_RING (chan
, h
<< dst
->ms_y
);
185 BEGIN_RING(chan
, RING_2D(BLIT_DU_DX_FRACT
), 4);
186 OUT_RING (chan
, duvdxy
[2 + ((int)src
->ms_x
- (int)dst
->ms_x
)] & 0xf0000000);
187 OUT_RING (chan
, duvdxy
[2 + ((int)src
->ms_x
- (int)dst
->ms_x
)] & 0x0000000f);
188 OUT_RING (chan
, duvdxy
[2 + ((int)src
->ms_y
- (int)dst
->ms_y
)] & 0xf0000000);
189 OUT_RING (chan
, duvdxy
[2 + ((int)src
->ms_y
- (int)dst
->ms_y
)] & 0x0000000f);
190 BEGIN_RING(chan
, RING_2D(BLIT_SRC_X_FRACT
), 4);
192 OUT_RING (chan
, sx
<< src
->ms_x
);
194 OUT_RING (chan
, sy
<< src
->ms_x
);
200 nvc0_resource_copy_region(struct pipe_context
*pipe
,
201 struct pipe_resource
*dst
, unsigned dst_level
,
202 unsigned dstx
, unsigned dsty
, unsigned dstz
,
203 struct pipe_resource
*src
, unsigned src_level
,
204 const struct pipe_box
*src_box
)
206 struct nvc0_screen
*screen
= nvc0_context(pipe
)->screen
;
209 unsigned dst_layer
= dstz
, src_layer
= src_box
->z
;
211 /* Fallback for buffers. */
212 if (dst
->target
== PIPE_BUFFER
&& src
->target
== PIPE_BUFFER
) {
213 util_resource_copy_region(pipe
, dst
, dst_level
, dstx
, dsty
, dstz
,
214 src
, src_level
, src_box
);
218 assert(src
->nr_samples
== dst
->nr_samples
);
220 m2mf
= (src
->format
== dst
->format
) ||
221 (util_format_get_blocksizebits(src
->format
) ==
222 util_format_get_blocksizebits(dst
->format
));
224 nv04_resource(dst
)->status
|= NOUVEAU_BUFFER_STATUS_GPU_WRITING
;
227 struct nv50_m2mf_rect drect
, srect
;
229 unsigned nx
= util_format_get_nblocksx(src
->format
, src_box
->width
);
230 unsigned ny
= util_format_get_nblocksy(src
->format
, src_box
->height
);
232 nv50_m2mf_rect_setup(&drect
, dst
, dst_level
, dstx
, dsty
, dstz
);
233 nv50_m2mf_rect_setup(&srect
, src
, src_level
,
234 src_box
->x
, src_box
->y
, src_box
->z
);
236 for (i
= 0; i
< src_box
->depth
; ++i
) {
237 nvc0_m2mf_transfer_rect(&screen
->base
.base
, &drect
, &srect
, nx
, ny
);
239 if (nv50_miptree(dst
)->layout_3d
)
242 drect
.base
+= nv50_miptree(dst
)->layer_stride
;
244 if (nv50_miptree(src
)->layout_3d
)
247 srect
.base
+= nv50_miptree(src
)->layer_stride
;
252 assert(nvc0_2d_format_faithful(src
->format
));
253 assert(nvc0_2d_format_faithful(dst
->format
));
255 for (; dst_layer
< dstz
+ src_box
->depth
; ++dst_layer
, ++src_layer
) {
256 ret
= nvc0_2d_texture_do_copy(screen
->base
.channel
,
257 nv50_miptree(dst
), dst_level
,
258 dstx
, dsty
, dst_layer
,
259 nv50_miptree(src
), src_level
,
260 src_box
->x
, src_box
->y
, src_layer
,
261 src_box
->width
, src_box
->height
);
268 nvc0_clear_render_target(struct pipe_context
*pipe
,
269 struct pipe_surface
*dst
,
270 const union pipe_color_union
*color
,
271 unsigned dstx
, unsigned dsty
,
272 unsigned width
, unsigned height
)
274 struct nvc0_context
*nv50
= nvc0_context(pipe
);
275 struct nvc0_screen
*screen
= nv50
->screen
;
276 struct nouveau_channel
*chan
= screen
->base
.channel
;
277 struct nv50_surface
*sf
= nv50_surface(dst
);
278 struct nv04_resource
*res
= nv04_resource(sf
->base
.texture
);
281 BEGIN_RING(chan
, RING_3D(CLEAR_COLOR(0)), 4);
282 OUT_RINGf (chan
, color
->f
[0]);
283 OUT_RINGf (chan
, color
->f
[1]);
284 OUT_RINGf (chan
, color
->f
[2]);
285 OUT_RINGf (chan
, color
->f
[3]);
287 if (MARK_RING(chan
, 18, 2))
290 BEGIN_RING(chan
, RING_3D(SCREEN_SCISSOR_HORIZ
), 2);
291 OUT_RING (chan
, ( width
<< 16) | dstx
);
292 OUT_RING (chan
, (height
<< 16) | dsty
);
294 BEGIN_RING(chan
, RING_3D(RT_CONTROL
), 1);
296 BEGIN_RING(chan
, RING_3D(RT_ADDRESS_HIGH(0)), 9);
297 OUT_RESRCh(chan
, res
, sf
->offset
, NOUVEAU_BO_WR
);
298 OUT_RESRCl(chan
, res
, sf
->offset
, NOUVEAU_BO_WR
);
299 if (likely(nouveau_bo_tile_layout(res
->bo
))) {
300 struct nv50_miptree
*mt
= nv50_miptree(dst
->texture
);
302 OUT_RING(chan
, sf
->width
);
303 OUT_RING(chan
, sf
->height
);
304 OUT_RING(chan
, nvc0_format_table
[dst
->format
].rt
);
305 OUT_RING(chan
, (mt
->layout_3d
<< 16) |
306 mt
->level
[sf
->base
.u
.tex
.level
].tile_mode
);
307 OUT_RING(chan
, dst
->u
.tex
.first_layer
+ sf
->depth
);
308 OUT_RING(chan
, mt
->layer_stride
>> 2);
309 OUT_RING(chan
, dst
->u
.tex
.first_layer
);
311 if (res
->base
.target
== PIPE_BUFFER
) {
312 OUT_RING(chan
, 262144);
315 OUT_RING(chan
, nv50_miptree(&res
->base
)->level
[0].pitch
);
316 OUT_RING(chan
, sf
->height
);
318 OUT_RING(chan
, nvc0_format_table
[sf
->base
.format
].rt
);
319 OUT_RING(chan
, 1 << 12);
324 IMMED_RING(chan
, RING_3D(ZETA_ENABLE
), 0);
326 /* tiled textures don't have to be fenced, they're not mapped directly */
327 nvc0_resource_fence(res
, NOUVEAU_BO_WR
);
330 for (z
= 0; z
< sf
->depth
; ++z
) {
331 BEGIN_RING(chan
, RING_3D(CLEAR_BUFFERS
), 1);
332 OUT_RING (chan
, 0x3c |
333 (z
<< NVC0_3D_CLEAR_BUFFERS_LAYER__SHIFT
));
336 nv50
->dirty
|= NVC0_NEW_FRAMEBUFFER
;
340 nvc0_clear_depth_stencil(struct pipe_context
*pipe
,
341 struct pipe_surface
*dst
,
342 unsigned clear_flags
,
345 unsigned dstx
, unsigned dsty
,
346 unsigned width
, unsigned height
)
348 struct nvc0_context
*nv50
= nvc0_context(pipe
);
349 struct nvc0_screen
*screen
= nv50
->screen
;
350 struct nouveau_channel
*chan
= screen
->base
.channel
;
351 struct nv50_miptree
*mt
= nv50_miptree(dst
->texture
);
352 struct nv50_surface
*sf
= nv50_surface(dst
);
353 struct nouveau_bo
*bo
= mt
->base
.bo
;
355 int unk
= mt
->base
.base
.target
== PIPE_TEXTURE_2D
;
358 if (clear_flags
& PIPE_CLEAR_DEPTH
) {
359 BEGIN_RING(chan
, RING_3D(CLEAR_DEPTH
), 1);
360 OUT_RINGf (chan
, depth
);
361 mode
|= NVC0_3D_CLEAR_BUFFERS_Z
;
364 if (clear_flags
& PIPE_CLEAR_STENCIL
) {
365 BEGIN_RING(chan
, RING_3D(CLEAR_STENCIL
), 1);
366 OUT_RING (chan
, stencil
& 0xff);
367 mode
|= NVC0_3D_CLEAR_BUFFERS_S
;
370 if (MARK_RING(chan
, 20, 2))
373 BEGIN_RING(chan
, RING_3D(SCREEN_SCISSOR_HORIZ
), 2);
374 OUT_RING (chan
, ( width
<< 16) | dstx
);
375 OUT_RING (chan
, (height
<< 16) | dsty
);
377 BEGIN_RING(chan
, RING_3D(ZETA_ADDRESS_HIGH
), 5);
378 OUT_RELOCh(chan
, bo
, sf
->offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
379 OUT_RELOCl(chan
, bo
, sf
->offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
380 OUT_RING (chan
, nvc0_format_table
[dst
->format
].rt
);
381 OUT_RING (chan
, mt
->level
[sf
->base
.u
.tex
.level
].tile_mode
);
382 OUT_RING (chan
, mt
->layer_stride
>> 2);
383 BEGIN_RING(chan
, RING_3D(ZETA_ENABLE
), 1);
385 BEGIN_RING(chan
, RING_3D(ZETA_HORIZ
), 3);
386 OUT_RING (chan
, sf
->width
);
387 OUT_RING (chan
, sf
->height
);
388 OUT_RING (chan
, (unk
<< 16) | (dst
->u
.tex
.first_layer
+ sf
->depth
));
389 BEGIN_RING(chan
, RING_3D(ZETA_BASE_LAYER
), 1);
390 OUT_RING (chan
, dst
->u
.tex
.first_layer
);
392 for (z
= 0; z
< sf
->depth
; ++z
) {
393 BEGIN_RING(chan
, RING_3D(CLEAR_BUFFERS
), 1);
394 OUT_RING (chan
, mode
|
395 (z
<< NVC0_3D_CLEAR_BUFFERS_LAYER__SHIFT
));
398 nv50
->dirty
|= NVC0_NEW_FRAMEBUFFER
;
402 nvc0_clear(struct pipe_context
*pipe
, unsigned buffers
,
403 const union pipe_color_union
*color
,
404 double depth
, unsigned stencil
)
406 struct nvc0_context
*nvc0
= nvc0_context(pipe
);
407 struct nouveau_channel
*chan
= nvc0
->screen
->base
.channel
;
408 struct pipe_framebuffer_state
*fb
= &nvc0
->framebuffer
;
412 /* don't need NEW_BLEND, COLOR_MASK doesn't affect CLEAR_BUFFERS */
413 if (!nvc0_state_validate(nvc0
, NVC0_NEW_FRAMEBUFFER
, 9 + (fb
->nr_cbufs
* 2)))
416 if (buffers
& PIPE_CLEAR_COLOR
&& fb
->nr_cbufs
) {
417 BEGIN_RING(chan
, RING_3D(CLEAR_COLOR(0)), 4);
418 OUT_RINGf (chan
, color
->f
[0]);
419 OUT_RINGf (chan
, color
->f
[1]);
420 OUT_RINGf (chan
, color
->f
[2]);
421 OUT_RINGf (chan
, color
->f
[3]);
423 NVC0_3D_CLEAR_BUFFERS_R
| NVC0_3D_CLEAR_BUFFERS_G
|
424 NVC0_3D_CLEAR_BUFFERS_B
| NVC0_3D_CLEAR_BUFFERS_A
;
427 if (buffers
& PIPE_CLEAR_DEPTH
) {
428 BEGIN_RING(chan
, RING_3D(CLEAR_DEPTH
), 1);
429 OUT_RING (chan
, fui(depth
));
430 mode
|= NVC0_3D_CLEAR_BUFFERS_Z
;
433 if (buffers
& PIPE_CLEAR_STENCIL
) {
434 BEGIN_RING(chan
, RING_3D(CLEAR_STENCIL
), 1);
435 OUT_RING (chan
, stencil
& 0xff);
436 mode
|= NVC0_3D_CLEAR_BUFFERS_S
;
439 BEGIN_RING(chan
, RING_3D(CLEAR_BUFFERS
), 1);
440 OUT_RING (chan
, mode
);
442 for (i
= 1; i
< fb
->nr_cbufs
; i
++) {
443 BEGIN_RING(chan
, RING_3D(CLEAR_BUFFERS
), 1);
444 OUT_RING (chan
, (i
<< 6) | 0x3c);
451 struct nvc0_screen
*screen
;
453 struct pipe_framebuffer_state fb
;
454 struct nvc0_program
*vp
;
455 struct nvc0_program
*tcp
;
456 struct nvc0_program
*tep
;
457 struct nvc0_program
*gp
;
458 struct nvc0_program
*fp
;
459 unsigned num_textures
[5];
460 unsigned num_samplers
[5];
461 struct pipe_sampler_view
*texture
;
462 struct nv50_tsc_entry
*sampler
;
466 struct nvc0_program vp
;
467 struct nvc0_program fp
;
468 struct nv50_tsc_entry sampler
[2]; /* nearest, bilinear */
475 nvc0_blitctx_make_vp(struct nvc0_blitctx
*blit
)
477 static const uint32_t code
[] =
479 0xfff01c66, 0x06000080, /* vfetch b128 { $r0 $r1 $r2 $r3 } a[0x80] */
480 0xfff11c26, 0x06000090, /* vfetch b64 { $r4 $r5 } a[0x90]*/
481 0x03f01c66, 0x0a7e0070, /* export b128 o[0x70] { $r0 $r1 $r2 $r3 } */
482 0x13f01c26, 0x0a7e0080, /* export b64 o[0x80] { $r4 $r5 } */
483 0x00001de7, 0x80000000, /* exit */
486 blit
->vp
.type
= PIPE_SHADER_VERTEX
;
487 blit
->vp
.translated
= TRUE
;
488 blit
->vp
.code
= (uint32_t *)code
; /* no relocations -> no modification */
489 blit
->vp
.code_size
= sizeof(code
);
490 blit
->vp
.max_gpr
= 6;
491 blit
->vp
.vp
.edgeflag
= PIPE_MAX_ATTRIBS
;
493 blit
->vp
.hdr
[0] = 0x00020461; /* vertprog magic */
494 blit
->vp
.hdr
[4] = 0x000ff000; /* no outputs read */
495 blit
->vp
.hdr
[6] = 0x0000003f; /* a[0x80], a[0x90] */
496 blit
->vp
.hdr
[13] = 0x0003f000; /* o[0x70], o[0x80] */
500 nvc0_blitctx_make_fp(struct nvc0_blitctx
*blit
)
502 static const uint32_t code
[] = /* use nvc0dis */
504 /* 2 coords RGBA in, RGBA out, also for Z32_FLOAT(_S8X24_UINT)
506 * NVC0 doesn't like tex 3d on non-3d textures, but there should
507 * only be 2d and 2d-array MS resources anyway.
509 0xfff01c00, 0xc07e0080,
510 0xfff05c00, 0xc07e0084,
511 0x00001c86, 0x8013c000,
512 0x00001de7, 0x80000000,
513 /* size: 0x70 + padding */
516 /* 2 coords ZS in, S encoded in R, Z encoded in GBA (8_UNORM)
517 * Setup float outputs in a way that conversion to UNORM yields the
518 * desired byte value.
520 /* NOTE: need to repeat header */
521 0x00021462, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
522 0x80000000, 0x0000000f, 0x00000000, 0x00000000, 0x00000000,
523 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
524 0x00000000, 0x00000000, 0x00000000, 0x0000000f, 0x00000000,
525 0xfff01c00, 0xc07e0080,
526 0xfff05c00, 0xc07e0084,
527 0x00001c86, 0x8010c000,
528 0xfc009c02, 0x312dffff,
531 0x04001c02, 0x30ee0202,
532 0xfc205c02, 0x38000003,
533 0x0020dc02, 0x3803fc00,
534 0x00209c02, 0x380003fc,
537 0x09209e04, 0x18000000,
538 0x04105c02, 0x30ee0202,
539 0x0430dc02, 0x30ce0202,
540 0x04209c02, 0x30de0202,
541 0x00001de7, 0x80000000,
542 /* size: 0xc8 + padding */
543 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
545 /* 2 coords ZS in, Z encoded in RGB, S encoded in A (U8_UNORM) */
546 0x00021462, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
547 0x80000000, 0x0000000f, 0x00000000, 0x00000000, 0x00000000,
548 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
549 0x00000000, 0x00000000, 0x00000000, 0x0000000f, 0x00000000,
550 0xfff01c00, 0xc07e0080,
551 0xfff05c00, 0xc07e0084,
552 0x00001c86, 0x8010c000,
553 0xfc009c02, 0x312dffff,
556 0x0430dc02, 0x30ee0202,
557 0xfc201c02, 0x38000003,
558 0x00205c02, 0x380003fc,
559 0x00209c02, 0x3803fc00,
562 0x09209e04, 0x18000000,
563 0x04001c02, 0x30ee0202,
564 0x04105c02, 0x30de0202,
565 0x04209c02, 0x30ce0202,
566 0x00001de7, 0x80000000,
569 blit
->fp
.type
= PIPE_SHADER_FRAGMENT
;
570 blit
->fp
.translated
= TRUE
;
571 blit
->fp
.code
= (uint32_t *)code
; /* const_cast */
572 blit
->fp
.code_size
= sizeof(code
);
573 blit
->fp
.max_gpr
= 4;
575 blit
->fp
.hdr
[0] = 0x00021462; /* fragprog magic */
576 blit
->fp
.hdr
[5] = 0x80000000;
577 blit
->fp
.hdr
[6] = 0x0000000f; /* 2 linear */
578 blit
->fp
.hdr
[18] = 0x0000000f; /* 1 colour output */
582 nvc0_blitctx_make_sampler(struct nvc0_blitctx
*blit
)
584 /* clamp to edge, min/max lod = 0, nearest filtering */
586 blit
->sampler
[0].id
= -1;
588 blit
->sampler
[0].tsc
[0] = 0x00000092;
589 blit
->sampler
[0].tsc
[1] = 0x00000051;
591 /* clamp to edge, min/max lod = 0, bilinear filtering */
593 blit
->sampler
[1].id
= -1;
595 blit
->sampler
[1].tsc
[0] = 0x00000092;
596 blit
->sampler
[1].tsc
[1] = 0x00000062;
599 /* Since shaders cannot export stencil, we cannot copy stencil values when
600 * rendering to ZETA, so we attach the ZS surface to a colour render target.
602 static INLINE
enum pipe_format
603 nvc0_blit_zeta_to_colour_format(enum pipe_format format
)
606 case PIPE_FORMAT_Z16_UNORM
: return PIPE_FORMAT_R16_UNORM
;
607 case PIPE_FORMAT_Z24_UNORM_S8_UINT
:
608 case PIPE_FORMAT_S8_UINT_Z24_UNORM
:
609 case PIPE_FORMAT_Z24X8_UNORM
: return PIPE_FORMAT_R8G8B8A8_UNORM
;
610 case PIPE_FORMAT_Z32_FLOAT
: return PIPE_FORMAT_R32_FLOAT
;
611 case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT
: return PIPE_FORMAT_R32G32_FLOAT
;
614 return PIPE_FORMAT_NONE
;
619 nvc0_blitctx_get_color_mask_and_fp(struct nvc0_blitctx
*blit
,
620 enum pipe_format format
, uint8_t mask
)
622 blit
->color_mask
= 0;
625 case PIPE_FORMAT_Z24X8_UNORM
:
626 case PIPE_FORMAT_Z24_UNORM_S8_UINT
:
627 blit
->fp_offset
= 0x180;
628 if (mask
& PIPE_MASK_Z
)
629 blit
->color_mask
|= 0x0111;
630 if (mask
& PIPE_MASK_S
)
631 blit
->color_mask
|= 0x1000;
633 case PIPE_FORMAT_S8_UINT_Z24_UNORM
:
634 blit
->fp_offset
= 0x80;
635 if (mask
& PIPE_MASK_Z
)
636 blit
->color_mask
|= 0x1110;
637 if (mask
& PIPE_MASK_S
)
638 blit
->color_mask
|= 0x0001;
642 if (mask
& (PIPE_MASK_R
| PIPE_MASK_Z
)) blit
->color_mask
|= 0x0001;
643 if (mask
& (PIPE_MASK_G
| PIPE_MASK_S
)) blit
->color_mask
|= 0x0010;
644 if (mask
& PIPE_MASK_B
) blit
->color_mask
|= 0x0100;
645 if (mask
& PIPE_MASK_A
) blit
->color_mask
|= 0x1000;
651 nvc0_blit_set_dst(struct nvc0_context
*nvc0
,
652 struct pipe_resource
*res
, unsigned level
, unsigned layer
)
654 struct pipe_context
*pipe
= &nvc0
->base
.pipe
;
655 struct pipe_surface templ
;
657 if (util_format_is_depth_or_stencil(res
->format
))
658 templ
.format
= nvc0_blit_zeta_to_colour_format(res
->format
);
660 templ
.format
= res
->format
;
662 templ
.usage
= PIPE_USAGE_STREAM
;
663 templ
.u
.tex
.level
= level
;
664 templ
.u
.tex
.first_layer
= templ
.u
.tex
.last_layer
= layer
;
666 nvc0
->framebuffer
.cbufs
[0] = nvc0_miptree_surface_new(pipe
, res
, &templ
);
667 nvc0
->framebuffer
.nr_cbufs
= 1;
668 nvc0
->framebuffer
.zsbuf
= NULL
;
669 nvc0
->framebuffer
.width
= nvc0
->framebuffer
.cbufs
[0]->width
;
670 nvc0
->framebuffer
.height
= nvc0
->framebuffer
.cbufs
[0]->height
;
674 nvc0_blit_fixup_tic_entry(struct pipe_sampler_view
*view
)
676 struct nv50_tic_entry
*ent
= nv50_tic_entry(view
);
678 ent
->tic
[2] &= ~(1 << 31); /* scaled coordinates, ok with 3d textures ? */
682 ent
->tic
[3] = 0x20000000; /* affects quality of near vertical edges in MS8 */
686 nvc0_blit_set_src(struct nvc0_context
*nvc0
,
687 struct pipe_resource
*res
, unsigned level
, unsigned layer
)
689 struct pipe_context
*pipe
= &nvc0
->base
.pipe
;
690 struct pipe_sampler_view templ
;
693 templ
.format
= res
->format
;
694 templ
.u
.tex
.first_layer
= templ
.u
.tex
.last_layer
= layer
;
695 templ
.u
.tex
.first_level
= templ
.u
.tex
.last_level
= level
;
696 templ
.swizzle_r
= PIPE_SWIZZLE_RED
;
697 templ
.swizzle_g
= PIPE_SWIZZLE_GREEN
;
698 templ
.swizzle_b
= PIPE_SWIZZLE_BLUE
;
699 templ
.swizzle_a
= PIPE_SWIZZLE_ALPHA
;
701 nvc0
->textures
[4][0] = nvc0_create_sampler_view(pipe
, res
, &templ
);
703 nvc0_blit_fixup_tic_entry(nvc0
->textures
[4][0]);
705 for (s
= 0; s
<= 3; ++s
)
706 nvc0
->num_textures
[s
] = 0;
707 nvc0
->num_textures
[4] = 1;
711 nvc0_blitctx_prepare_state(struct nvc0_blitctx
*blit
)
713 struct nouveau_channel
*chan
= blit
->screen
->base
.channel
;
715 /* TODO: maybe make this a MACRO (if we need more logic) ? */
718 BEGIN_RING(chan
, RING_3D(COLOR_MASK(0)), 1);
719 OUT_RING (chan
, blit
->color_mask
);
720 BEGIN_RING(chan
, RING_3D(BLEND_ENABLE(0)), 1);
722 IMMED_RING(chan
, RING_3D(LOGIC_OP_ENABLE
), 0);
724 /* rasterizer state */
725 BEGIN_RING(chan
, RING_3D(FRAG_COLOR_CLAMP_EN
), 1);
727 IMMED_RING(chan
, RING_3D(MULTISAMPLE_ENABLE
), 0);
728 BEGIN_RING(chan
, RING_3D(MSAA_MASK(0)), 4);
729 OUT_RING (chan
, 0xffff);
730 OUT_RING (chan
, 0xffff);
731 OUT_RING (chan
, 0xffff);
732 OUT_RING (chan
, 0xffff);
733 BEGIN_RING(chan
, RING_3D(POLYGON_MODE_FRONT
), 1);
734 OUT_RING (chan
, NVC0_3D_POLYGON_MODE_FRONT_FILL
);
735 BEGIN_RING(chan
, RING_3D(POLYGON_MODE_BACK
), 1);
736 OUT_RING (chan
, NVC0_3D_POLYGON_MODE_BACK_FILL
);
737 IMMED_RING(chan
, RING_3D(POLYGON_SMOOTH_ENABLE
), 0);
738 IMMED_RING(chan
, RING_3D(POLYGON_OFFSET_FILL_ENABLE
), 0);
739 IMMED_RING(chan
, RING_3D(POLYGON_STIPPLE_ENABLE
), 0);
740 IMMED_RING(chan
, RING_3D(CULL_FACE_ENABLE
), 0);
743 IMMED_RING(chan
, RING_3D(DEPTH_TEST_ENABLE
), 0);
744 IMMED_RING(chan
, RING_3D(STENCIL_ENABLE
), 0);
745 IMMED_RING(chan
, RING_3D(ALPHA_TEST_ENABLE
), 0);
747 /* disable transform feedback */
748 IMMED_RING(chan
, RING_3D(TFB_ENABLE
), 0);
752 nvc0_blitctx_pre_blit(struct nvc0_blitctx
*blit
, struct nvc0_context
*nvc0
)
756 blit
->saved
.fb
.width
= nvc0
->framebuffer
.width
;
757 blit
->saved
.fb
.height
= nvc0
->framebuffer
.height
;
758 blit
->saved
.fb
.nr_cbufs
= nvc0
->framebuffer
.nr_cbufs
;
759 blit
->saved
.fb
.cbufs
[0] = nvc0
->framebuffer
.cbufs
[0];
760 blit
->saved
.fb
.zsbuf
= nvc0
->framebuffer
.zsbuf
;
762 blit
->saved
.vp
= nvc0
->vertprog
;
763 blit
->saved
.tcp
= nvc0
->tctlprog
;
764 blit
->saved
.tep
= nvc0
->tevlprog
;
765 blit
->saved
.gp
= nvc0
->gmtyprog
;
766 blit
->saved
.fp
= nvc0
->fragprog
;
768 nvc0
->vertprog
= &blit
->vp
;
769 nvc0
->fragprog
= &blit
->fp
;
770 nvc0
->tctlprog
= NULL
;
771 nvc0
->tevlprog
= NULL
;
772 nvc0
->gmtyprog
= NULL
;
774 blit
->saved
.clip_nr
= nvc0
->clip
.nr
;
778 for (s
= 0; s
<= 4; ++s
) {
779 blit
->saved
.num_textures
[s
] = nvc0
->num_textures
[s
];
780 blit
->saved
.num_samplers
[s
] = nvc0
->num_samplers
[s
];
782 blit
->saved
.texture
= nvc0
->textures
[4][0];
783 blit
->saved
.sampler
= nvc0
->samplers
[4][0];
785 nvc0
->samplers
[4][0] = &blit
->sampler
[blit
->filter
];
787 for (s
= 0; s
<= 3; ++s
)
788 nvc0
->num_samplers
[s
] = 0;
789 nvc0
->num_samplers
[4] = 1;
791 blit
->saved
.dirty
= nvc0
->dirty
;
793 nvc0
->dirty
= NVC0_NEW_FRAMEBUFFER
|
794 NVC0_NEW_VERTPROG
| NVC0_NEW_FRAGPROG
|
795 NVC0_NEW_TCTLPROG
| NVC0_NEW_TEVLPROG
| NVC0_NEW_GMTYPROG
|
796 NVC0_NEW_TEXTURES
| NVC0_NEW_SAMPLERS
;
800 nvc0_blitctx_post_blit(struct nvc0_context
*nvc0
, struct nvc0_blitctx
*blit
)
804 pipe_surface_reference(&nvc0
->framebuffer
.cbufs
[0], NULL
);
806 nvc0
->framebuffer
.width
= blit
->saved
.fb
.width
;
807 nvc0
->framebuffer
.height
= blit
->saved
.fb
.height
;
808 nvc0
->framebuffer
.nr_cbufs
= blit
->saved
.fb
.nr_cbufs
;
809 nvc0
->framebuffer
.cbufs
[0] = blit
->saved
.fb
.cbufs
[0];
810 nvc0
->framebuffer
.zsbuf
= blit
->saved
.fb
.zsbuf
;
812 nvc0
->vertprog
= blit
->saved
.vp
;
813 nvc0
->tctlprog
= blit
->saved
.tcp
;
814 nvc0
->tevlprog
= blit
->saved
.tep
;
815 nvc0
->gmtyprog
= blit
->saved
.gp
;
816 nvc0
->fragprog
= blit
->saved
.fp
;
818 nvc0
->clip
.nr
= blit
->saved
.clip_nr
;
820 pipe_sampler_view_reference(&nvc0
->textures
[4][0], NULL
);
822 for (s
= 0; s
<= 4; ++s
) {
823 nvc0
->num_textures
[s
] = blit
->saved
.num_textures
[s
];
824 nvc0
->num_samplers
[s
] = blit
->saved
.num_samplers
[s
];
826 nvc0
->textures
[4][0] = blit
->saved
.texture
;
827 nvc0
->samplers
[4][0] = blit
->saved
.sampler
;
829 nvc0
->dirty
= blit
->saved
.dirty
|
830 (NVC0_NEW_FRAMEBUFFER
| NVC0_NEW_SCISSOR
| NVC0_NEW_SAMPLE_MASK
|
831 NVC0_NEW_RASTERIZER
| NVC0_NEW_ZSA
| NVC0_NEW_BLEND
|
832 NVC0_NEW_TEXTURES
| NVC0_NEW_SAMPLERS
|
833 NVC0_NEW_VERTPROG
| NVC0_NEW_FRAGPROG
|
834 NVC0_NEW_TCTLPROG
| NVC0_NEW_TEVLPROG
| NVC0_NEW_GMTYPROG
|
835 NVC0_NEW_TFB_TARGETS
);
839 nvc0_resource_resolve(struct pipe_context
*pipe
,
840 const struct pipe_resolve_info
*info
)
842 struct nvc0_context
*nvc0
= nvc0_context(pipe
);
843 struct nvc0_screen
*screen
= nvc0
->screen
;
844 struct nvc0_blitctx
*blit
= screen
->blitctx
;
845 struct nouveau_channel
*chan
= screen
->base
.channel
;
846 struct pipe_resource
*src
= info
->src
.res
;
847 struct pipe_resource
*dst
= info
->dst
.res
;
848 float x0
, x1
, y0
, y1
;
849 float x_range
, y_range
;
851 /* Would need more shader variants or, better, just change the TIC target.
852 * But no API creates 3D MS textures ...
854 if (src
->target
== PIPE_TEXTURE_3D
)
857 nvc0_blitctx_get_color_mask_and_fp(blit
, dst
->format
, info
->mask
);
859 blit
->filter
= util_format_is_depth_or_stencil(dst
->format
) ? 0 : 1;
861 nvc0_blitctx_pre_blit(blit
, nvc0
);
863 nvc0_blit_set_dst(nvc0
, dst
, info
->dst
.level
, info
->dst
.layer
);
864 nvc0_blit_set_src(nvc0
, src
, 0, info
->src
.layer
);
866 nvc0_blitctx_prepare_state(blit
);
868 nvc0_state_validate(nvc0
, ~0, 36);
871 (float)(info
->src
.x1
- info
->src
.x0
) /
872 (float)(info
->dst
.x1
- info
->dst
.x0
);
874 (float)(info
->src
.y1
- info
->src
.y0
) /
875 (float)(info
->dst
.y1
- info
->dst
.y0
);
877 x0
= (float)info
->src
.x0
- x_range
* (float)info
->dst
.x0
;
878 y0
= (float)info
->src
.y0
- y_range
* (float)info
->dst
.y0
;
880 x1
= x0
+ 16384.0f
* x_range
;
881 y1
= y0
+ 16384.0f
* y_range
;
883 x0
*= (float)(1 << nv50_miptree(src
)->ms_x
);
884 x1
*= (float)(1 << nv50_miptree(src
)->ms_x
);
885 y0
*= (float)(1 << nv50_miptree(src
)->ms_y
);
886 y1
*= (float)(1 << nv50_miptree(src
)->ms_y
);
888 BEGIN_RING(chan
, RING_3D(SP_START_ID(5)), 1);
890 blit
->fp
.code_base
+ blit
->fp_offset
);
892 IMMED_RING(chan
, RING_3D(VIEWPORT_TRANSFORM_EN
), 0);
894 /* Draw a large triangle in screen coordinates covering the whole
895 * render target, with scissors defining the destination region.
896 * The vertex is supplied with non-normalized texture coordinates
897 * arranged in a way to yield the desired offset and scale.
900 BEGIN_RING(chan
, RING_3D(SCISSOR_HORIZ(0)), 2);
901 OUT_RING (chan
, (info
->dst
.x1
<< 16) | info
->dst
.x0
);
902 OUT_RING (chan
, (info
->dst
.y1
<< 16) | info
->dst
.y0
);
904 IMMED_RING(chan
, RING_3D(VERTEX_BEGIN_GL
),
905 NVC0_3D_VERTEX_BEGIN_GL_PRIMITIVE_TRIANGLES
);
907 BEGIN_RING(chan
, RING_3D(VTX_ATTR_DEFINE
), 3);
908 OUT_RING (chan
, 0x74201);
909 OUT_RINGf (chan
, x0
);
910 OUT_RINGf (chan
, y0
);
911 BEGIN_RING(chan
, RING_3D(VTX_ATTR_DEFINE
), 3);
912 OUT_RING (chan
, 0x74200);
913 OUT_RINGf (chan
, 0.0f
);
914 OUT_RINGf (chan
, 0.0f
);
915 BEGIN_RING(chan
, RING_3D(VTX_ATTR_DEFINE
), 3);
916 OUT_RING (chan
, 0x74201);
917 OUT_RINGf (chan
, x1
);
918 OUT_RINGf (chan
, y0
);
919 BEGIN_RING(chan
, RING_3D(VTX_ATTR_DEFINE
), 3);
920 OUT_RING (chan
, 0x74200);
921 OUT_RINGf (chan
, 16384 << nv50_miptree(dst
)->ms_x
);
922 OUT_RINGf (chan
, 0.0f
);
923 BEGIN_RING(chan
, RING_3D(VTX_ATTR_DEFINE
), 3);
924 OUT_RING (chan
, 0x74201);
925 OUT_RINGf (chan
, x0
);
926 OUT_RINGf (chan
, y1
);
927 BEGIN_RING(chan
, RING_3D(VTX_ATTR_DEFINE
), 3);
928 OUT_RING (chan
, 0x74200);
929 OUT_RINGf (chan
, 0.0f
);
930 OUT_RINGf (chan
, 16384 << nv50_miptree(dst
)->ms_y
);
932 IMMED_RING(chan
, RING_3D(VERTEX_END_GL
), 0);
934 /* re-enable normally constant state */
936 IMMED_RING(chan
, RING_3D(VIEWPORT_TRANSFORM_EN
), 1);
938 nvc0_blitctx_post_blit(nvc0
, blit
);
942 nvc0_blitctx_create(struct nvc0_screen
*screen
)
944 screen
->blitctx
= CALLOC_STRUCT(nvc0_blitctx
);
945 if (!screen
->blitctx
) {
946 NOUVEAU_ERR("failed to allocate blit context\n");
950 screen
->blitctx
->screen
= screen
;
952 nvc0_blitctx_make_vp(screen
->blitctx
);
953 nvc0_blitctx_make_fp(screen
->blitctx
);
955 nvc0_blitctx_make_sampler(screen
->blitctx
);
957 screen
->blitctx
->color_mask
= 0x1111;
964 nvc0_init_surface_functions(struct nvc0_context
*nvc0
)
966 struct pipe_context
*pipe
= &nvc0
->base
.pipe
;
968 pipe
->resource_copy_region
= nvc0_resource_copy_region
;
969 pipe
->resource_resolve
= nvc0_resource_resolve
;
970 pipe
->clear_render_target
= nvc0_clear_render_target
;
971 pipe
->clear_depth_stencil
= nvc0_clear_depth_stencil
;