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 "nv50_context.h"
33 #include "nv50_resource.h"
35 #include "nv50_defs.xml.h"
37 #define NV50_ENG2D_SUPPORTED_FORMATS 0xff0843e080608409ULL
39 /* return TRUE for formats that can be converted among each other by NV50_2D */
41 nv50_2d_format_faithful(enum pipe_format format
)
43 uint8_t id
= nv50_format_table
[format
].rt
;
45 return (id
>= 0xc0) &&
46 (NV50_ENG2D_SUPPORTED_FORMATS
& (1ULL << (id
- 0xc0)));
50 nv50_2d_format(enum pipe_format format
)
52 uint8_t id
= nv50_format_table
[format
].rt
;
54 /* Hardware values for color formats range from 0xc0 to 0xff,
55 * but the 2D engine doesn't support all of them.
57 if ((id
>= 0xc0) && (NV50_ENG2D_SUPPORTED_FORMATS
& (1ULL << (id
- 0xc0))))
60 switch (util_format_get_blocksize(format
)) {
62 return NV50_SURFACE_FORMAT_R8_UNORM
;
64 return NV50_SURFACE_FORMAT_R16_UNORM
;
66 return NV50_SURFACE_FORMAT_BGRA8_UNORM
;
73 nv50_2d_texture_set(struct nouveau_channel
*chan
, int dst
,
74 struct nv50_miptree
*mt
, unsigned level
, unsigned layer
)
76 struct nouveau_bo
*bo
= mt
->base
.bo
;
77 uint32_t width
, height
, depth
;
79 uint32_t mthd
= dst
? NV50_2D_DST_FORMAT
: NV50_2D_SRC_FORMAT
;
80 uint32_t flags
= mt
->base
.domain
| (dst
? NOUVEAU_BO_WR
: NOUVEAU_BO_RD
);
81 uint32_t offset
= mt
->level
[level
].offset
;
83 format
= nv50_2d_format(mt
->base
.base
.format
);
85 NOUVEAU_ERR("invalid/unsupported surface format: %s\n",
86 util_format_name(mt
->base
.base
.format
));
90 width
= u_minify(mt
->base
.base
.width0
, level
) << mt
->ms_x
;
91 height
= u_minify(mt
->base
.base
.height0
, level
) << mt
->ms_y
;
93 offset
= mt
->level
[level
].offset
;
95 offset
+= mt
->layer_stride
* layer
;
99 depth
= u_minify(mt
->base
.base
.depth0
, level
);
102 if (!(bo
->tile_flags
& NOUVEAU_BO_TILE_LAYOUT_MASK
)) {
103 BEGIN_RING(chan
, RING_2D_(mthd
), 2);
104 OUT_RING (chan
, format
);
106 BEGIN_RING(chan
, RING_2D_(mthd
+ 0x14), 5);
107 OUT_RING (chan
, mt
->level
[level
].pitch
);
108 OUT_RING (chan
, width
);
109 OUT_RING (chan
, height
);
110 OUT_RELOCh(chan
, bo
, offset
, flags
);
111 OUT_RELOCl(chan
, bo
, offset
, flags
);
113 BEGIN_RING(chan
, RING_2D_(mthd
), 5);
114 OUT_RING (chan
, format
);
116 OUT_RING (chan
, mt
->level
[level
].tile_mode
<< 4);
117 OUT_RING (chan
, depth
);
118 OUT_RING (chan
, layer
);
119 BEGIN_RING(chan
, RING_2D_(mthd
+ 0x18), 4);
120 OUT_RING (chan
, width
);
121 OUT_RING (chan
, height
);
122 OUT_RELOCh(chan
, bo
, offset
, flags
);
123 OUT_RELOCl(chan
, bo
, offset
, flags
);
128 BEGIN_RING(chan
, RING_2D_(NV50_2D_CLIP_X
), 4);
131 OUT_RING (chan
, width
);
132 OUT_RING (chan
, height
);
139 nv50_2d_texture_do_copy(struct nouveau_channel
*chan
,
140 struct nv50_miptree
*dst
, unsigned dst_level
,
141 unsigned dx
, unsigned dy
, unsigned dz
,
142 struct nv50_miptree
*src
, unsigned src_level
,
143 unsigned sx
, unsigned sy
, unsigned sz
,
144 unsigned w
, unsigned h
)
146 static const uint32_t duvdxy
[5] =
148 0x40000000, 0x80000000, 0x00000001, 0x00000002, 0x00000004
154 ret
= MARK_RING(chan
, 2 * 16 + 32, 4);
158 ret
= nv50_2d_texture_set(chan
, 1, dst
, dst_level
, dz
);
162 ret
= nv50_2d_texture_set(chan
, 0, src
, src_level
, sz
);
166 /* NOTE: 2D engine doesn't work for MS8 */
170 /* 0/1 = CENTER/CORNER, 00/10 = POINT/BILINEAR */
171 BEGIN_RING(chan
, RING_2D(BLIT_CONTROL
), 1);
172 OUT_RING (chan
, ctrl
);
173 BEGIN_RING(chan
, RING_2D(BLIT_DST_X
), 4);
174 OUT_RING (chan
, dx
<< dst
->ms_x
);
175 OUT_RING (chan
, dy
<< dst
->ms_y
);
176 OUT_RING (chan
, w
<< dst
->ms_x
);
177 OUT_RING (chan
, h
<< dst
->ms_y
);
178 BEGIN_RING(chan
, RING_2D(BLIT_DU_DX_FRACT
), 4);
179 OUT_RING (chan
, duvdxy
[2 + ((int)src
->ms_x
- (int)dst
->ms_x
)] & 0xf0000000);
180 OUT_RING (chan
, duvdxy
[2 + ((int)src
->ms_x
- (int)dst
->ms_x
)] & 0x0000000f);
181 OUT_RING (chan
, duvdxy
[2 + ((int)src
->ms_y
- (int)dst
->ms_y
)] & 0xf0000000);
182 OUT_RING (chan
, duvdxy
[2 + ((int)src
->ms_y
- (int)dst
->ms_y
)] & 0x0000000f);
183 BEGIN_RING(chan
, RING_2D(BLIT_SRC_X_FRACT
), 4);
185 OUT_RING (chan
, sx
<< src
->ms_x
);
187 OUT_RING (chan
, sy
<< src
->ms_y
);
193 nv50_resource_copy_region(struct pipe_context
*pipe
,
194 struct pipe_resource
*dst
, unsigned dst_level
,
195 unsigned dstx
, unsigned dsty
, unsigned dstz
,
196 struct pipe_resource
*src
, unsigned src_level
,
197 const struct pipe_box
*src_box
)
199 struct nv50_screen
*screen
= nv50_context(pipe
)->screen
;
202 unsigned dst_layer
= dstz
, src_layer
= src_box
->z
;
204 /* Fallback for buffers. */
205 if (dst
->target
== PIPE_BUFFER
&& src
->target
== PIPE_BUFFER
) {
206 util_resource_copy_region(pipe
, dst
, dst_level
, dstx
, dsty
, dstz
,
207 src
, src_level
, src_box
);
211 assert(src
->nr_samples
== dst
->nr_samples
);
213 m2mf
= (src
->format
== dst
->format
) ||
214 (util_format_get_blocksizebits(src
->format
) ==
215 util_format_get_blocksizebits(dst
->format
));
217 nv04_resource(dst
)->status
|= NOUVEAU_BUFFER_STATUS_GPU_WRITING
;
220 struct nv50_m2mf_rect drect
, srect
;
222 unsigned nx
= util_format_get_nblocksx(src
->format
, src_box
->width
);
223 unsigned ny
= util_format_get_nblocksy(src
->format
, src_box
->height
);
225 nv50_m2mf_rect_setup(&drect
, dst
, dst_level
, dstx
, dsty
, dstz
);
226 nv50_m2mf_rect_setup(&srect
, src
, src_level
,
227 src_box
->x
, src_box
->y
, src_box
->z
);
229 for (i
= 0; i
< src_box
->depth
; ++i
) {
230 nv50_m2mf_transfer_rect(&screen
->base
.base
, &drect
, &srect
, nx
, ny
);
232 if (nv50_miptree(dst
)->layout_3d
)
235 drect
.base
+= nv50_miptree(dst
)->layer_stride
;
237 if (nv50_miptree(src
)->layout_3d
)
240 srect
.base
+= nv50_miptree(src
)->layer_stride
;
245 assert((src
->format
== dst
->format
) ||
246 (nv50_2d_format_faithful(src
->format
) &&
247 nv50_2d_format_faithful(dst
->format
)));
249 for (; dst_layer
< dstz
+ src_box
->depth
; ++dst_layer
, ++src_layer
) {
250 ret
= nv50_2d_texture_do_copy(screen
->base
.channel
,
251 nv50_miptree(dst
), dst_level
,
252 dstx
, dsty
, dst_layer
,
253 nv50_miptree(src
), src_level
,
254 src_box
->x
, src_box
->y
, src_layer
,
255 src_box
->width
, src_box
->height
);
262 nv50_clear_render_target(struct pipe_context
*pipe
,
263 struct pipe_surface
*dst
,
264 const union pipe_color_union
*color
,
265 unsigned dstx
, unsigned dsty
,
266 unsigned width
, unsigned height
)
268 struct nv50_context
*nv50
= nv50_context(pipe
);
269 struct nv50_screen
*screen
= nv50
->screen
;
270 struct nouveau_channel
*chan
= screen
->base
.channel
;
271 struct nv50_miptree
*mt
= nv50_miptree(dst
->texture
);
272 struct nv50_surface
*sf
= nv50_surface(dst
);
273 struct nouveau_bo
*bo
= mt
->base
.bo
;
275 BEGIN_RING(chan
, RING_3D(CLEAR_COLOR(0)), 4);
276 OUT_RINGf (chan
, color
->f
[0]);
277 OUT_RINGf (chan
, color
->f
[1]);
278 OUT_RINGf (chan
, color
->f
[2]);
279 OUT_RINGf (chan
, color
->f
[3]);
281 if (MARK_RING(chan
, 18, 2))
284 BEGIN_RING(chan
, RING_3D(RT_CONTROL
), 1);
286 BEGIN_RING(chan
, RING_3D(RT_ADDRESS_HIGH(0)), 5);
287 OUT_RELOCh(chan
, bo
, sf
->offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
288 OUT_RELOCl(chan
, bo
, sf
->offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
289 OUT_RING (chan
, nv50_format_table
[dst
->format
].rt
);
290 OUT_RING (chan
, mt
->level
[sf
->base
.u
.tex
.level
].tile_mode
<< 4);
292 BEGIN_RING(chan
, RING_3D(RT_HORIZ(0)), 2);
293 if (nouveau_bo_tile_layout(bo
))
294 OUT_RING(chan
, sf
->width
);
296 OUT_RING(chan
, NV50_3D_RT_HORIZ_LINEAR
| mt
->level
[0].pitch
);
297 OUT_RING (chan
, sf
->height
);
298 BEGIN_RING(chan
, RING_3D(RT_ARRAY_MODE
), 1);
301 if (!nouveau_bo_tile_layout(bo
)) {
302 BEGIN_RING(chan
, RING_3D(ZETA_ENABLE
), 1);
306 /* NOTE: only works with D3D clear flag (5097/0x143c bit 4) */
308 BEGIN_RING(chan
, RING_3D(VIEWPORT_HORIZ(0)), 2);
309 OUT_RING (chan
, (width
<< 16) | dstx
);
310 OUT_RING (chan
, (height
<< 16) | dsty
);
312 BEGIN_RING(chan
, RING_3D(CLEAR_BUFFERS
), 1);
313 OUT_RING (chan
, 0x3c);
315 nv50
->dirty
|= NV50_NEW_FRAMEBUFFER
;
319 nv50_clear_depth_stencil(struct pipe_context
*pipe
,
320 struct pipe_surface
*dst
,
321 unsigned clear_flags
,
324 unsigned dstx
, unsigned dsty
,
325 unsigned width
, unsigned height
)
327 struct nv50_context
*nv50
= nv50_context(pipe
);
328 struct nv50_screen
*screen
= nv50
->screen
;
329 struct nouveau_channel
*chan
= screen
->base
.channel
;
330 struct nv50_miptree
*mt
= nv50_miptree(dst
->texture
);
331 struct nv50_surface
*sf
= nv50_surface(dst
);
332 struct nouveau_bo
*bo
= mt
->base
.bo
;
335 assert(nouveau_bo_tile_layout(bo
)); /* ZETA cannot be linear */
337 if (clear_flags
& PIPE_CLEAR_DEPTH
) {
338 BEGIN_RING(chan
, RING_3D(CLEAR_DEPTH
), 1);
339 OUT_RINGf (chan
, depth
);
340 mode
|= NV50_3D_CLEAR_BUFFERS_Z
;
343 if (clear_flags
& PIPE_CLEAR_STENCIL
) {
344 BEGIN_RING(chan
, RING_3D(CLEAR_STENCIL
), 1);
345 OUT_RING (chan
, stencil
& 0xff);
346 mode
|= NV50_3D_CLEAR_BUFFERS_S
;
349 if (MARK_RING(chan
, 17, 2))
352 BEGIN_RING(chan
, RING_3D(ZETA_ADDRESS_HIGH
), 5);
353 OUT_RELOCh(chan
, bo
, sf
->offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
354 OUT_RELOCl(chan
, bo
, sf
->offset
, NOUVEAU_BO_VRAM
| NOUVEAU_BO_WR
);
355 OUT_RING (chan
, nv50_format_table
[dst
->format
].rt
);
356 OUT_RING (chan
, mt
->level
[sf
->base
.u
.tex
.level
].tile_mode
<< 4);
358 BEGIN_RING(chan
, RING_3D(ZETA_ENABLE
), 1);
360 BEGIN_RING(chan
, RING_3D(ZETA_HORIZ
), 3);
361 OUT_RING (chan
, sf
->width
);
362 OUT_RING (chan
, sf
->height
);
363 OUT_RING (chan
, (1 << 16) | 1);
365 BEGIN_RING(chan
, RING_3D(VIEWPORT_HORIZ(0)), 2);
366 OUT_RING (chan
, (width
<< 16) | dstx
);
367 OUT_RING (chan
, (height
<< 16) | dsty
);
369 BEGIN_RING(chan
, RING_3D(CLEAR_BUFFERS
), 1);
370 OUT_RING (chan
, mode
);
372 nv50
->dirty
|= NV50_NEW_FRAMEBUFFER
;
376 nv50_clear(struct pipe_context
*pipe
, unsigned buffers
,
377 const union pipe_color_union
*color
,
378 double depth
, unsigned stencil
)
380 struct nv50_context
*nv50
= nv50_context(pipe
);
381 struct nouveau_channel
*chan
= nv50
->screen
->base
.channel
;
382 struct pipe_framebuffer_state
*fb
= &nv50
->framebuffer
;
386 /* don't need NEW_BLEND, COLOR_MASK doesn't affect CLEAR_BUFFERS */
387 if (!nv50_state_validate(nv50
, NV50_NEW_FRAMEBUFFER
, 9 + (fb
->nr_cbufs
* 2)))
390 if (buffers
& PIPE_CLEAR_COLOR
&& fb
->nr_cbufs
) {
391 BEGIN_RING(chan
, RING_3D(CLEAR_COLOR(0)), 4);
392 OUT_RINGf (chan
, color
->f
[0]);
393 OUT_RINGf (chan
, color
->f
[1]);
394 OUT_RINGf (chan
, color
->f
[2]);
395 OUT_RINGf (chan
, color
->f
[3]);
397 NV50_3D_CLEAR_BUFFERS_R
| NV50_3D_CLEAR_BUFFERS_G
|
398 NV50_3D_CLEAR_BUFFERS_B
| NV50_3D_CLEAR_BUFFERS_A
;
401 if (buffers
& PIPE_CLEAR_DEPTH
) {
402 BEGIN_RING(chan
, RING_3D(CLEAR_DEPTH
), 1);
403 OUT_RING (chan
, fui(depth
));
404 mode
|= NV50_3D_CLEAR_BUFFERS_Z
;
407 if (buffers
& PIPE_CLEAR_STENCIL
) {
408 BEGIN_RING(chan
, RING_3D(CLEAR_STENCIL
), 1);
409 OUT_RING (chan
, stencil
& 0xff);
410 mode
|= NV50_3D_CLEAR_BUFFERS_S
;
413 BEGIN_RING(chan
, RING_3D(CLEAR_BUFFERS
), 1);
414 OUT_RING (chan
, mode
);
416 for (i
= 1; i
< fb
->nr_cbufs
; i
++) {
417 BEGIN_RING(chan
, RING_3D(CLEAR_BUFFERS
), 1);
418 OUT_RING (chan
, (i
<< 6) | 0x3c);
425 struct nv50_screen
*screen
;
427 struct pipe_framebuffer_state fb
;
428 struct nv50_program
*vp
;
429 struct nv50_program
*gp
;
430 struct nv50_program
*fp
;
431 unsigned num_textures
[3];
432 unsigned num_samplers
[3];
433 struct pipe_sampler_view
*texture
;
434 struct nv50_tsc_entry
*sampler
;
438 struct nv50_program vp
;
439 struct nv50_program fp
;
440 struct nv50_tsc_entry sampler
[2]; /* nearest, bilinear */
447 nv50_blitctx_make_vp(struct nv50_blitctx
*blit
)
449 static const uint32_t code
[] =
451 0x10000001, /* mov b32 o[0x00] s[0x00] */ /* HPOS.x */
453 0x10000205, /* mov b32 o[0x04] s[0x04] */ /* HPOS.y */
455 0x10000409, /* mov b32 o[0x08] s[0x08] */ /* TEXC.x */
457 0x1000060d, /* mov b32 o[0x0c] s[0x0c] */ /* TEXC.y */
459 0x10000811, /* exit mov b32 o[0x10] s[0x10] */ /* TEXC.z */
463 blit
->vp
.type
= PIPE_SHADER_VERTEX
;
464 blit
->vp
.translated
= TRUE
;
465 blit
->vp
.code
= (uint32_t *)code
; /* const_cast */
466 blit
->vp
.code_size
= sizeof(code
);
467 blit
->vp
.max_gpr
= 4;
468 blit
->vp
.max_out
= 5;
470 blit
->vp
.out
[0].mask
= 0x3;
471 blit
->vp
.out
[0].sn
= TGSI_SEMANTIC_POSITION
;
472 blit
->vp
.out
[1].hw
= 2;
473 blit
->vp
.out
[1].mask
= 0x7;
474 blit
->vp
.out
[1].sn
= TGSI_SEMANTIC_GENERIC
;
475 blit
->vp
.vp
.attrs
[0] = 0x73;
476 blit
->vp
.vp
.psiz
= 0x40;
477 blit
->vp
.vp
.edgeflag
= 0x40;
481 nv50_blitctx_make_fp(struct nv50_blitctx
*blit
)
483 static const uint32_t code
[] =
485 /* 3 coords RGBA in, RGBA out, also for Z32_FLOAT(_S8X24_UINT) */
486 0x80000000, /* interp $r0 v[0x0] */
487 0x80010004, /* interp $r1 v[0x4] */
488 0x80020009, /* interp $r2 flat v[0x8] */
490 0xf6800001, /* texauto live { $r0,1,2,3 } $t0 $s0 { $r0,1,2 } */
491 0x0000c785, /* exit */
493 /* 3 coords ZS in, S encoded in R, Z encoded in GBA (8_UNORM) */
494 0x80000000, /* interp $r0 v[0x00] */
495 0x80010004, /* interp $r1 v[0x04] */
496 0x80020009, /* interp $r2 flat v[0x8] */
498 0xf6800001, /* texauto live { $r0,1,#,# } $t0 $s0 { $r0,1,2 } */
500 0xc03f0009, /* mul f32 $r2 $r0 (2^24 - 1) */
502 0xa0000201, /* cvt f32 $r0 s32 $r1 */
504 0xa0000409, /* cvt rni s32 $r2 f32 $r2 */
506 0xc0010001, /* mul f32 $r0 $r0 1/0xff */
508 0xd03f0405, /* and b32 $r1 $r2 0x0000ff */
510 0xd000040d, /* and b32 $r3 $r2 0xff0000 */
512 0xd0000409, /* and b32 $r2 $r2 0x00ff00 */
514 0xa0000205, /* cvt f32 $r1 s32 $r1 */
516 0xa000060d, /* cvt f32 $r3 s32 $r3 */
518 0xa0000409, /* cvt f32 $r2 s32 $r2 */
520 0xc0010205, /* mul f32 $r1 $r1 1/0x0000ff */
522 0xc001060d, /* mul f32 $r3 $r3 1/0x00ff00 */
524 0xc0010409, /* mul f32 $r2 $r2 1/0xff0000 */
526 0xf0000001, /* exit never nop */
529 /* 3 coords ZS in, Z encoded in RGB, S encoded in A (U8_UNORM) */
530 0x80000000, /* interp $r0 v[0x00] */
531 0x80010004, /* interp $r1 v[0x04] */
532 0x80020009, /* interp $r2 flat v[0x8] */
534 0xf6800001, /* texauto live { $r0,1,#,# } $t0 $s0 { $r0,1,2 } */
536 0xc03f0009, /* mul f32 $r2 $r0 (2^24 - 1) */
538 0xa0000281, /* cvt f32 $r3 s32 $r1 */
540 0xa0000409, /* cvt rni s32 $r2 f32 $r2 */
542 0xc001060d, /* mul f32 $r3 $r3 1/0xff */
544 0xd03f0401, /* and b32 $r0 $r2 0x0000ff */
546 0xd0000405, /* and b32 $r1 $r2 0x00ff00 */
548 0xd0000409, /* and b32 $r2 $r2 0xff0000 */
550 0xa0000001, /* cvt f32 $r0 s32 $r0 */
552 0xa0000205, /* cvt f32 $r1 s32 $r1 */
554 0xa0000409, /* cvt f32 $r2 s32 $r2 */
556 0xc0010001, /* mul f32 $r0 $r0 1/0x0000ff */
558 0xc0010205, /* mul f32 $r1 $r1 1/0x00ff00 */
560 0xc0010409, /* mul f32 $r2 $r2 1/0xff0000 */
562 0xf0000001, /* exit never nop */
566 blit
->fp
.type
= PIPE_SHADER_FRAGMENT
;
567 blit
->fp
.translated
= TRUE
;
568 blit
->fp
.code
= (uint32_t *)code
; /* const_cast */
569 blit
->fp
.code_size
= sizeof(code
);
570 blit
->fp
.max_gpr
= 4;
571 blit
->fp
.max_out
= 4;
573 blit
->fp
.in
[0].mask
= 0x7; /* last component flat */
574 blit
->fp
.in
[0].linear
= 1;
575 blit
->fp
.in
[0].sn
= TGSI_SEMANTIC_GENERIC
;
577 blit
->fp
.out
[0].mask
= 0xf;
578 blit
->fp
.out
[0].sn
= TGSI_SEMANTIC_COLOR
;
579 blit
->fp
.fp
.interp
= 0x00020403;
580 blit
->fp
.gp
.primid
= 0x80;
584 nv50_blitctx_make_sampler(struct nv50_blitctx
*blit
)
586 /* clamp to edge, min/max lod = 0, nearest filtering */
588 blit
->sampler
[0].id
= -1;
590 blit
->sampler
[0].tsc
[0] = 0x00000092;
591 blit
->sampler
[0].tsc
[1] = 0x00000051;
593 /* clamp to edge, min/max lod = 0, bilinear filtering */
595 blit
->sampler
[1].id
= -1;
597 blit
->sampler
[1].tsc
[0] = 0x00000092;
598 blit
->sampler
[1].tsc
[1] = 0x00000062;
601 /* Since shaders cannot export stencil, we cannot copy stencil values when
602 * rendering to ZETA, so we attach the ZS surface to a colour render target.
604 static INLINE
enum pipe_format
605 nv50_blit_zeta_to_colour_format(enum pipe_format format
)
608 case PIPE_FORMAT_Z16_UNORM
: return PIPE_FORMAT_R16_UNORM
;
609 case PIPE_FORMAT_Z24_UNORM_S8_UINT
:
610 case PIPE_FORMAT_S8_UINT_Z24_UNORM
:
611 case PIPE_FORMAT_Z24X8_UNORM
: return PIPE_FORMAT_R8G8B8A8_UNORM
;
612 case PIPE_FORMAT_Z32_FLOAT
: return PIPE_FORMAT_R32_FLOAT
;
613 case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT
: return PIPE_FORMAT_R32G32_FLOAT
;
616 return PIPE_FORMAT_NONE
;
621 nv50_blitctx_get_color_mask_and_fp(struct nv50_blitctx
*blit
,
622 enum pipe_format format
, uint8_t mask
)
624 blit
->color_mask
= 0;
627 case PIPE_FORMAT_Z24X8_UNORM
:
628 case PIPE_FORMAT_Z24_UNORM_S8_UINT
:
629 blit
->fp_offset
= 160;
630 if (mask
& PIPE_MASK_Z
)
631 blit
->color_mask
|= 0x0111;
632 if (mask
& PIPE_MASK_S
)
633 blit
->color_mask
|= 0x1000;
635 case PIPE_FORMAT_S8_UINT_Z24_UNORM
:
636 blit
->fp_offset
= 24;
637 if (mask
& PIPE_MASK_Z
)
638 blit
->color_mask
|= 0x1110;
639 if (mask
& PIPE_MASK_S
)
640 blit
->color_mask
|= 0x0001;
644 if (mask
& (PIPE_MASK_R
| PIPE_MASK_Z
)) blit
->color_mask
|= 0x0001;
645 if (mask
& (PIPE_MASK_G
| PIPE_MASK_S
)) blit
->color_mask
|= 0x0010;
646 if (mask
& PIPE_MASK_B
) blit
->color_mask
|= 0x0100;
647 if (mask
& PIPE_MASK_A
) blit
->color_mask
|= 0x1000;
653 nv50_blit_set_dst(struct nv50_context
*nv50
,
654 struct pipe_resource
*res
, unsigned level
, unsigned layer
)
656 struct pipe_context
*pipe
= &nv50
->base
.pipe
;
657 struct pipe_surface templ
;
659 if (util_format_is_depth_or_stencil(res
->format
))
660 templ
.format
= nv50_blit_zeta_to_colour_format(res
->format
);
662 templ
.format
= res
->format
;
664 templ
.usage
= PIPE_USAGE_STREAM
;
665 templ
.u
.tex
.level
= level
;
666 templ
.u
.tex
.first_layer
= templ
.u
.tex
.last_layer
= layer
;
668 nv50
->framebuffer
.cbufs
[0] = nv50_miptree_surface_new(pipe
, res
, &templ
);
669 nv50
->framebuffer
.nr_cbufs
= 1;
670 nv50
->framebuffer
.zsbuf
= NULL
;
671 nv50
->framebuffer
.width
= nv50
->framebuffer
.cbufs
[0]->width
;
672 nv50
->framebuffer
.height
= nv50
->framebuffer
.cbufs
[0]->height
;
676 nv50_blit_fixup_tic_entry(struct pipe_sampler_view
*view
)
678 struct nv50_tic_entry
*ent
= nv50_tic_entry(view
);
680 ent
->tic
[2] &= ~(1 << 31); /* scaled coordinates, ok with 3d textures ? */
684 ent
->tic
[3] = 0x20000000; /* affects quality of near vertical edges in MS8 */
688 nv50_blit_set_src(struct nv50_context
*nv50
,
689 struct pipe_resource
*res
, unsigned level
, unsigned layer
)
691 struct pipe_context
*pipe
= &nv50
->base
.pipe
;
692 struct pipe_sampler_view templ
;
694 templ
.format
= res
->format
;
695 templ
.u
.tex
.first_layer
= templ
.u
.tex
.last_layer
= layer
;
696 templ
.u
.tex
.first_level
= templ
.u
.tex
.last_level
= level
;
697 templ
.swizzle_r
= PIPE_SWIZZLE_RED
;
698 templ
.swizzle_g
= PIPE_SWIZZLE_GREEN
;
699 templ
.swizzle_b
= PIPE_SWIZZLE_BLUE
;
700 templ
.swizzle_a
= PIPE_SWIZZLE_ALPHA
;
702 nv50
->textures
[2][0] = nv50_create_sampler_view(pipe
, res
, &templ
);
704 nv50_blit_fixup_tic_entry(nv50
->textures
[2][0]);
706 nv50
->num_textures
[0] = nv50
->num_textures
[1] = 0;
707 nv50
->num_textures
[2] = 1;
711 nv50_blitctx_prepare_state(struct nv50_blitctx
*blit
)
713 struct nouveau_channel
*chan
= blit
->screen
->base
.channel
;
716 BEGIN_RING(chan
, RING_3D(COLOR_MASK(0)), 1);
717 OUT_RING (chan
, blit
->color_mask
);
718 BEGIN_RING(chan
, RING_3D(BLEND_ENABLE(0)), 1);
720 BEGIN_RING(chan
, RING_3D(LOGIC_OP_ENABLE
), 1);
723 /* rasterizer state */
724 #ifndef NV50_SCISSORS_CLIPPING
725 BEGIN_RING(chan
, RING_3D(SCISSOR_ENABLE(0)), 1);
728 BEGIN_RING(chan
, RING_3D(VERTEX_TWO_SIDE_ENABLE
), 1);
730 BEGIN_RING(chan
, RING_3D(FRAG_COLOR_CLAMP_EN
), 1);
732 BEGIN_RING(chan
, RING_3D(MULTISAMPLE_ENABLE
), 1);
734 BEGIN_RING(chan
, RING_3D(MSAA_MASK(0)), 4);
735 OUT_RING (chan
, 0xffff);
736 OUT_RING (chan
, 0xffff);
737 OUT_RING (chan
, 0xffff);
738 OUT_RING (chan
, 0xffff);
739 BEGIN_RING(chan
, RING_3D(POLYGON_MODE_FRONT
), 3);
740 OUT_RING (chan
, NV50_3D_POLYGON_MODE_FRONT_FILL
);
741 OUT_RING (chan
, NV50_3D_POLYGON_MODE_BACK_FILL
);
743 BEGIN_RING(chan
, RING_3D(CULL_FACE_ENABLE
), 1);
745 BEGIN_RING(chan
, RING_3D(POLYGON_STIPPLE_ENABLE
), 1);
747 BEGIN_RING(chan
, RING_3D(POLYGON_OFFSET_FILL_ENABLE
), 1);
751 BEGIN_RING(chan
, RING_3D(DEPTH_TEST_ENABLE
), 1);
753 BEGIN_RING(chan
, RING_3D(STENCIL_ENABLE
), 1);
755 BEGIN_RING(chan
, RING_3D(ALPHA_TEST_ENABLE
), 1);
760 nv50_blitctx_pre_blit(struct nv50_blitctx
*blit
, struct nv50_context
*nv50
)
764 blit
->saved
.fb
.width
= nv50
->framebuffer
.width
;
765 blit
->saved
.fb
.height
= nv50
->framebuffer
.height
;
766 blit
->saved
.fb
.nr_cbufs
= nv50
->framebuffer
.nr_cbufs
;
767 blit
->saved
.fb
.cbufs
[0] = nv50
->framebuffer
.cbufs
[0];
768 blit
->saved
.fb
.zsbuf
= nv50
->framebuffer
.zsbuf
;
770 blit
->saved
.vp
= nv50
->vertprog
;
771 blit
->saved
.gp
= nv50
->gmtyprog
;
772 blit
->saved
.fp
= nv50
->fragprog
;
774 nv50
->vertprog
= &blit
->vp
;
775 nv50
->gmtyprog
= NULL
;
776 nv50
->fragprog
= &blit
->fp
;
778 blit
->saved
.clip_nr
= nv50
->clip
.nr
;
782 for (s
= 0; s
< 3; ++s
) {
783 blit
->saved
.num_textures
[s
] = nv50
->num_textures
[s
];
784 blit
->saved
.num_samplers
[s
] = nv50
->num_samplers
[s
];
786 blit
->saved
.texture
= nv50
->textures
[2][0];
787 blit
->saved
.sampler
= nv50
->samplers
[2][0];
789 nv50
->samplers
[2][0] = &blit
->sampler
[blit
->filter
];
791 nv50
->num_samplers
[0] = nv50
->num_samplers
[1] = 0;
792 nv50
->num_samplers
[2] = 1;
794 blit
->saved
.dirty
= nv50
->dirty
;
797 NV50_NEW_FRAMEBUFFER
|
798 NV50_NEW_VERTPROG
| NV50_NEW_FRAGPROG
| NV50_NEW_GMTYPROG
|
799 NV50_NEW_TEXTURES
| NV50_NEW_SAMPLERS
;
803 nv50_blitctx_post_blit(struct nv50_context
*nv50
, struct nv50_blitctx
*blit
)
807 pipe_surface_reference(&nv50
->framebuffer
.cbufs
[0], NULL
);
809 nv50
->framebuffer
.width
= blit
->saved
.fb
.width
;
810 nv50
->framebuffer
.height
= blit
->saved
.fb
.height
;
811 nv50
->framebuffer
.nr_cbufs
= blit
->saved
.fb
.nr_cbufs
;
812 nv50
->framebuffer
.cbufs
[0] = blit
->saved
.fb
.cbufs
[0];
813 nv50
->framebuffer
.zsbuf
= blit
->saved
.fb
.zsbuf
;
815 nv50
->vertprog
= blit
->saved
.vp
;
816 nv50
->gmtyprog
= blit
->saved
.gp
;
817 nv50
->fragprog
= blit
->saved
.fp
;
819 nv50
->clip
.nr
= blit
->saved
.clip_nr
;
821 pipe_sampler_view_reference(&nv50
->textures
[2][0], NULL
);
823 for (s
= 0; s
< 3; ++s
) {
824 nv50
->num_textures
[s
] = blit
->saved
.num_textures
[s
];
825 nv50
->num_samplers
[s
] = blit
->saved
.num_samplers
[s
];
827 nv50
->textures
[2][0] = blit
->saved
.texture
;
828 nv50
->samplers
[2][0] = blit
->saved
.sampler
;
830 nv50
->dirty
= blit
->saved
.dirty
|
831 (NV50_NEW_FRAMEBUFFER
| NV50_NEW_SCISSOR
| NV50_NEW_SAMPLE_MASK
|
832 NV50_NEW_RASTERIZER
| NV50_NEW_ZSA
| NV50_NEW_BLEND
|
833 NV50_NEW_TEXTURES
| NV50_NEW_SAMPLERS
|
834 NV50_NEW_VERTPROG
| NV50_NEW_GMTYPROG
| NV50_NEW_FRAGPROG
);
838 nv50_resource_resolve(struct pipe_context
*pipe
,
839 const struct pipe_resolve_info
*info
)
841 struct nv50_context
*nv50
= nv50_context(pipe
);
842 struct nv50_screen
*screen
= nv50
->screen
;
843 struct nv50_blitctx
*blit
= screen
->blitctx
;
844 struct nouveau_channel
*chan
= screen
->base
.channel
;
845 struct pipe_resource
*src
= info
->src
.res
;
846 struct pipe_resource
*dst
= info
->dst
.res
;
847 float x0
, x1
, y0
, y1
, z
;
848 float x_range
, y_range
;
850 nv50_blitctx_get_color_mask_and_fp(blit
, dst
->format
, info
->mask
);
852 blit
->filter
= util_format_is_depth_or_stencil(dst
->format
) ? 0 : 1;
854 nv50_blitctx_pre_blit(blit
, nv50
);
856 nv50_blit_set_dst(nv50
, dst
, info
->dst
.level
, info
->dst
.layer
);
857 nv50_blit_set_src(nv50
, src
, 0, info
->src
.layer
);
859 nv50_blitctx_prepare_state(blit
);
861 nv50_state_validate(nv50
, ~0, 36);
864 (float)(info
->src
.x1
- info
->src
.x0
) /
865 (float)(info
->dst
.x1
- info
->dst
.x0
);
867 (float)(info
->src
.y1
- info
->src
.y0
) /
868 (float)(info
->dst
.y1
- info
->dst
.y0
);
870 x0
= (float)info
->src
.x0
- x_range
* (float)info
->dst
.x0
;
871 y0
= (float)info
->src
.y0
- y_range
* (float)info
->dst
.y0
;
873 x1
= x0
+ 16384.0f
* x_range
;
874 y1
= y0
+ 16384.0f
* y_range
;
876 x0
*= (float)(1 << nv50_miptree(src
)->ms_x
);
877 x1
*= (float)(1 << nv50_miptree(src
)->ms_x
);
878 y0
*= (float)(1 << nv50_miptree(src
)->ms_y
);
879 y1
*= (float)(1 << nv50_miptree(src
)->ms_y
);
881 z
= (float)info
->src
.layer
;
883 BEGIN_RING(chan
, RING_3D(FP_START_ID
), 1);
885 blit
->fp
.code_base
+ blit
->fp_offset
);
887 BEGIN_RING(chan
, RING_3D(VIEWPORT_TRANSFORM_EN
), 1);
890 /* Draw a large triangle in screen coordinates covering the whole
891 * render target, with scissors defining the destination region.
892 * The vertex is supplied with non-normalized texture coordinates
893 * arranged in a way to yield the desired offset and scale.
896 BEGIN_RING(chan
, RING_3D(SCISSOR_HORIZ(0)), 2);
897 OUT_RING (chan
, (info
->dst
.x1
<< 16) | info
->dst
.x0
);
898 OUT_RING (chan
, (info
->dst
.y1
<< 16) | info
->dst
.y0
);
900 BEGIN_RING(chan
, RING_3D(VERTEX_BEGIN_GL
), 1);
901 OUT_RING (chan
, NV50_3D_VERTEX_BEGIN_GL_PRIMITIVE_TRIANGLES
);
902 BEGIN_RING(chan
, RING_3D(VTX_ATTR_3F_X(1)), 3);
903 OUT_RINGf (chan
, x0
);
904 OUT_RINGf (chan
, y0
);
906 BEGIN_RING(chan
, RING_3D(VTX_ATTR_2F_X(0)), 2);
907 OUT_RINGf (chan
, 0.0f
);
908 OUT_RINGf (chan
, 0.0f
);
909 BEGIN_RING(chan
, RING_3D(VTX_ATTR_3F_X(1)), 3);
910 OUT_RINGf (chan
, x1
);
911 OUT_RINGf (chan
, y0
);
913 BEGIN_RING(chan
, RING_3D(VTX_ATTR_2F_X(0)), 2);
914 OUT_RINGf (chan
, 16384 << nv50_miptree(dst
)->ms_x
);
915 OUT_RINGf (chan
, 0.0f
);
916 BEGIN_RING(chan
, RING_3D(VTX_ATTR_3F_X(1)), 3);
917 OUT_RINGf (chan
, x0
);
918 OUT_RINGf (chan
, y1
);
920 BEGIN_RING(chan
, RING_3D(VTX_ATTR_2F_X(0)), 2);
921 OUT_RINGf (chan
, 0.0f
);
922 OUT_RINGf (chan
, 16384 << nv50_miptree(dst
)->ms_y
);
923 BEGIN_RING(chan
, RING_3D(VERTEX_END_GL
), 1);
926 /* re-enable normally constant state */
928 BEGIN_RING(chan
, RING_3D(VIEWPORT_TRANSFORM_EN
), 1);
931 nv50_blitctx_post_blit(nv50
, blit
);
935 nv50_blitctx_create(struct nv50_screen
*screen
)
937 screen
->blitctx
= CALLOC_STRUCT(nv50_blitctx
);
938 if (!screen
->blitctx
) {
939 NOUVEAU_ERR("failed to allocate blit context\n");
943 screen
->blitctx
->screen
= screen
;
945 nv50_blitctx_make_vp(screen
->blitctx
);
946 nv50_blitctx_make_fp(screen
->blitctx
);
948 nv50_blitctx_make_sampler(screen
->blitctx
);
950 screen
->blitctx
->color_mask
= 0x1111;
956 nv50_init_surface_functions(struct nv50_context
*nv50
)
958 struct pipe_context
*pipe
= &nv50
->base
.pipe
;
960 pipe
->resource_copy_region
= nv50_resource_copy_region
;
961 pipe
->resource_resolve
= nv50_resource_resolve
;
962 pipe
->clear_render_target
= nv50_clear_render_target
;
963 pipe
->clear_depth_stencil
= nv50_clear_depth_stencil
;