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_pushbuf
*push
, 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 offset
= mt
->level
[level
].offset
;
82 format
= nv50_2d_format(mt
->base
.base
.format
);
84 NOUVEAU_ERR("invalid/unsupported surface format: %s\n",
85 util_format_name(mt
->base
.base
.format
));
89 width
= u_minify(mt
->base
.base
.width0
, level
) << mt
->ms_x
;
90 height
= u_minify(mt
->base
.base
.height0
, level
) << mt
->ms_y
;
92 offset
= mt
->level
[level
].offset
;
94 offset
+= mt
->layer_stride
* layer
;
98 depth
= u_minify(mt
->base
.base
.depth0
, level
);
101 if (!nouveau_bo_memtype(bo
)) {
102 BEGIN_NV04(push
, SUBC_2D(mthd
), 2);
103 PUSH_DATA (push
, format
);
105 BEGIN_NV04(push
, SUBC_2D(mthd
+ 0x14), 5);
106 PUSH_DATA (push
, mt
->level
[level
].pitch
);
107 PUSH_DATA (push
, width
);
108 PUSH_DATA (push
, height
);
109 PUSH_DATAh(push
, bo
->offset
+ offset
);
110 PUSH_DATA (push
, bo
->offset
+ offset
);
112 BEGIN_NV04(push
, SUBC_2D(mthd
), 5);
113 PUSH_DATA (push
, format
);
115 PUSH_DATA (push
, mt
->level
[level
].tile_mode
);
116 PUSH_DATA (push
, depth
);
117 PUSH_DATA (push
, layer
);
118 BEGIN_NV04(push
, SUBC_2D(mthd
+ 0x18), 4);
119 PUSH_DATA (push
, width
);
120 PUSH_DATA (push
, height
);
121 PUSH_DATAh(push
, bo
->offset
+ offset
);
122 PUSH_DATA (push
, bo
->offset
+ offset
);
127 BEGIN_NV04(push
, SUBC_2D(NV50_2D_CLIP_X
), 4);
130 PUSH_DATA (push
, width
);
131 PUSH_DATA (push
, height
);
138 nv50_2d_texture_do_copy(struct nouveau_pushbuf
*push
,
139 struct nv50_miptree
*dst
, unsigned dst_level
,
140 unsigned dx
, unsigned dy
, unsigned dz
,
141 struct nv50_miptree
*src
, unsigned src_level
,
142 unsigned sx
, unsigned sy
, unsigned sz
,
143 unsigned w
, unsigned h
)
145 static const uint32_t duvdxy
[5] =
147 0x40000000, 0x80000000, 0x00000001, 0x00000002, 0x00000004
153 ret
= MARK_RING(chan
, 2 * 16 + 32, 4);
157 ret
= nv50_2d_texture_set(push
, 1, dst
, dst_level
, dz
);
161 ret
= nv50_2d_texture_set(push
, 0, src
, src_level
, sz
);
165 /* NOTE: 2D engine doesn't work for MS8 */
169 /* 0/1 = CENTER/CORNER, 00/10 = POINT/BILINEAR */
170 BEGIN_NV04(push
, NV50_2D(BLIT_CONTROL
), 1);
171 PUSH_DATA (push
, ctrl
);
172 BEGIN_NV04(push
, NV50_2D(BLIT_DST_X
), 4);
173 PUSH_DATA (push
, dx
<< dst
->ms_x
);
174 PUSH_DATA (push
, dy
<< dst
->ms_y
);
175 PUSH_DATA (push
, w
<< dst
->ms_x
);
176 PUSH_DATA (push
, h
<< dst
->ms_y
);
177 BEGIN_NV04(push
, NV50_2D(BLIT_DU_DX_FRACT
), 4);
178 PUSH_DATA (push
, duvdxy
[2 + ((int)src
->ms_x
- (int)dst
->ms_x
)] & 0xf0000000);
179 PUSH_DATA (push
, duvdxy
[2 + ((int)src
->ms_x
- (int)dst
->ms_x
)] & 0x0000000f);
180 PUSH_DATA (push
, duvdxy
[2 + ((int)src
->ms_y
- (int)dst
->ms_y
)] & 0xf0000000);
181 PUSH_DATA (push
, duvdxy
[2 + ((int)src
->ms_y
- (int)dst
->ms_y
)] & 0x0000000f);
182 BEGIN_NV04(push
, NV50_2D(BLIT_SRC_X_FRACT
), 4);
184 PUSH_DATA (push
, sx
<< src
->ms_x
);
186 PUSH_DATA (push
, sy
<< src
->ms_y
);
192 nv50_resource_copy_region(struct pipe_context
*pipe
,
193 struct pipe_resource
*dst
, unsigned dst_level
,
194 unsigned dstx
, unsigned dsty
, unsigned dstz
,
195 struct pipe_resource
*src
, unsigned src_level
,
196 const struct pipe_box
*src_box
)
198 struct nv50_context
*nv50
= nv50_context(pipe
);
201 unsigned dst_layer
= dstz
, src_layer
= src_box
->z
;
203 /* Fallback for buffers. */
204 if (dst
->target
== PIPE_BUFFER
&& src
->target
== PIPE_BUFFER
) {
205 util_resource_copy_region(pipe
, dst
, dst_level
, dstx
, dsty
, dstz
,
206 src
, src_level
, src_box
);
210 assert(src
->nr_samples
== dst
->nr_samples
);
212 m2mf
= (src
->format
== dst
->format
) ||
213 (util_format_get_blocksizebits(src
->format
) ==
214 util_format_get_blocksizebits(dst
->format
));
216 nv04_resource(dst
)->status
|= NOUVEAU_BUFFER_STATUS_GPU_WRITING
;
219 struct nv50_m2mf_rect drect
, srect
;
221 unsigned nx
= util_format_get_nblocksx(src
->format
, src_box
->width
);
222 unsigned ny
= util_format_get_nblocksy(src
->format
, src_box
->height
);
224 nv50_m2mf_rect_setup(&drect
, dst
, dst_level
, dstx
, dsty
, dstz
);
225 nv50_m2mf_rect_setup(&srect
, src
, src_level
,
226 src_box
->x
, src_box
->y
, src_box
->z
);
228 for (i
= 0; i
< src_box
->depth
; ++i
) {
229 nv50_m2mf_transfer_rect(nv50
, &drect
, &srect
, nx
, ny
);
231 if (nv50_miptree(dst
)->layout_3d
)
234 drect
.base
+= nv50_miptree(dst
)->layer_stride
;
236 if (nv50_miptree(src
)->layout_3d
)
239 srect
.base
+= nv50_miptree(src
)->layer_stride
;
244 assert((src
->format
== dst
->format
) ||
245 (nv50_2d_format_faithful(src
->format
) &&
246 nv50_2d_format_faithful(dst
->format
)));
248 BCTX_REFN(nv50
->bufctx
, 2D
, nv04_resource(src
), RD
);
249 BCTX_REFN(nv50
->bufctx
, 2D
, nv04_resource(dst
), WR
);
250 nouveau_pushbuf_bufctx(nv50
->base
.pushbuf
, nv50
->bufctx
);
251 nouveau_pushbuf_validate(nv50
->base
.pushbuf
);
253 for (; dst_layer
< dstz
+ src_box
->depth
; ++dst_layer
, ++src_layer
) {
254 ret
= nv50_2d_texture_do_copy(nv50
->base
.pushbuf
,
255 nv50_miptree(dst
), dst_level
,
256 dstx
, dsty
, dst_layer
,
257 nv50_miptree(src
), src_level
,
258 src_box
->x
, src_box
->y
, src_layer
,
259 src_box
->width
, src_box
->height
);
263 nouveau_bufctx_reset(nv50
->bufctx
, NV50_BIND_2D
);
267 nv50_clear_render_target(struct pipe_context
*pipe
,
268 struct pipe_surface
*dst
,
269 const union pipe_color_union
*color
,
270 unsigned dstx
, unsigned dsty
,
271 unsigned width
, unsigned height
)
273 struct nv50_context
*nv50
= nv50_context(pipe
);
274 struct nouveau_pushbuf
*push
= nv50
->base
.pushbuf
;
275 struct nv50_miptree
*mt
= nv50_miptree(dst
->texture
);
276 struct nv50_surface
*sf
= nv50_surface(dst
);
277 struct nouveau_bo
*bo
= mt
->base
.bo
;
279 BEGIN_NV04(push
, NV50_3D(CLEAR_COLOR(0)), 4);
280 PUSH_DATAf(push
, color
->f
[0]);
281 PUSH_DATAf(push
, color
->f
[1]);
282 PUSH_DATAf(push
, color
->f
[2]);
283 PUSH_DATAf(push
, color
->f
[3]);
285 if (MARK_RING(chan
, 18, 2))
288 BEGIN_NV04(push
, NV50_3D(RT_CONTROL
), 1);
290 BEGIN_NV04(push
, NV50_3D(RT_ADDRESS_HIGH(0)), 5);
291 PUSH_DATAh(push
, bo
->offset
+ sf
->offset
);
292 PUSH_DATA (push
, bo
->offset
+ sf
->offset
);
293 PUSH_DATA (push
, nv50_format_table
[dst
->format
].rt
);
294 PUSH_DATA (push
, mt
->level
[sf
->base
.u
.tex
.level
].tile_mode
);
296 BEGIN_NV04(push
, NV50_3D(RT_HORIZ(0)), 2);
297 if (nouveau_bo_memtype(bo
))
298 PUSH_DATA(push
, sf
->width
);
300 PUSH_DATA(push
, NV50_3D_RT_HORIZ_LINEAR
| mt
->level
[0].pitch
);
301 PUSH_DATA (push
, sf
->height
);
302 BEGIN_NV04(push
, NV50_3D(RT_ARRAY_MODE
), 1);
305 if (!nouveau_bo_memtype(bo
)) {
306 BEGIN_NV04(push
, NV50_3D(ZETA_ENABLE
), 1);
310 /* NOTE: only works with D3D clear flag (5097/0x143c bit 4) */
312 BEGIN_NV04(push
, NV50_3D(VIEWPORT_HORIZ(0)), 2);
313 PUSH_DATA (push
, (width
<< 16) | dstx
);
314 PUSH_DATA (push
, (height
<< 16) | dsty
);
316 BEGIN_NV04(push
, NV50_3D(CLEAR_BUFFERS
), 1);
317 PUSH_DATA (push
, 0x3c);
319 nv50
->dirty
|= NV50_NEW_FRAMEBUFFER
;
323 nv50_clear_depth_stencil(struct pipe_context
*pipe
,
324 struct pipe_surface
*dst
,
325 unsigned clear_flags
,
328 unsigned dstx
, unsigned dsty
,
329 unsigned width
, unsigned height
)
331 struct nv50_context
*nv50
= nv50_context(pipe
);
332 struct nouveau_pushbuf
*push
= nv50
->base
.pushbuf
;
333 struct nv50_miptree
*mt
= nv50_miptree(dst
->texture
);
334 struct nv50_surface
*sf
= nv50_surface(dst
);
335 struct nouveau_bo
*bo
= mt
->base
.bo
;
338 assert(nouveau_bo_memtype(bo
)); /* ZETA cannot be linear */
340 if (clear_flags
& PIPE_CLEAR_DEPTH
) {
341 BEGIN_NV04(push
, NV50_3D(CLEAR_DEPTH
), 1);
342 PUSH_DATAf(push
, depth
);
343 mode
|= NV50_3D_CLEAR_BUFFERS_Z
;
346 if (clear_flags
& PIPE_CLEAR_STENCIL
) {
347 BEGIN_NV04(push
, NV50_3D(CLEAR_STENCIL
), 1);
348 PUSH_DATA (push
, stencil
& 0xff);
349 mode
|= NV50_3D_CLEAR_BUFFERS_S
;
352 if (MARK_RING(chan
, 17, 2))
355 BEGIN_NV04(push
, NV50_3D(ZETA_ADDRESS_HIGH
), 5);
356 PUSH_DATAh(push
, bo
->offset
+ sf
->offset
);
357 PUSH_DATA (push
, bo
->offset
+ sf
->offset
);
358 PUSH_DATA (push
, nv50_format_table
[dst
->format
].rt
);
359 PUSH_DATA (push
, mt
->level
[sf
->base
.u
.tex
.level
].tile_mode
);
361 BEGIN_NV04(push
, NV50_3D(ZETA_ENABLE
), 1);
363 BEGIN_NV04(push
, NV50_3D(ZETA_HORIZ
), 3);
364 PUSH_DATA (push
, sf
->width
);
365 PUSH_DATA (push
, sf
->height
);
366 PUSH_DATA (push
, (1 << 16) | 1);
368 BEGIN_NV04(push
, NV50_3D(VIEWPORT_HORIZ(0)), 2);
369 PUSH_DATA (push
, (width
<< 16) | dstx
);
370 PUSH_DATA (push
, (height
<< 16) | dsty
);
372 BEGIN_NV04(push
, NV50_3D(CLEAR_BUFFERS
), 1);
373 PUSH_DATA (push
, mode
);
375 nv50
->dirty
|= NV50_NEW_FRAMEBUFFER
;
379 nv50_clear(struct pipe_context
*pipe
, unsigned buffers
,
380 const union pipe_color_union
*color
,
381 double depth
, unsigned stencil
)
383 struct nv50_context
*nv50
= nv50_context(pipe
);
384 struct nouveau_pushbuf
*push
= nv50
->base
.pushbuf
;
385 struct pipe_framebuffer_state
*fb
= &nv50
->framebuffer
;
389 /* don't need NEW_BLEND, COLOR_MASK doesn't affect CLEAR_BUFFERS */
390 if (!nv50_state_validate(nv50
, NV50_NEW_FRAMEBUFFER
, 9 + (fb
->nr_cbufs
* 2)))
393 if (buffers
& PIPE_CLEAR_COLOR
&& fb
->nr_cbufs
) {
394 BEGIN_NV04(push
, NV50_3D(CLEAR_COLOR(0)), 4);
395 PUSH_DATAf(push
, color
->f
[0]);
396 PUSH_DATAf(push
, color
->f
[1]);
397 PUSH_DATAf(push
, color
->f
[2]);
398 PUSH_DATAf(push
, color
->f
[3]);
400 NV50_3D_CLEAR_BUFFERS_R
| NV50_3D_CLEAR_BUFFERS_G
|
401 NV50_3D_CLEAR_BUFFERS_B
| NV50_3D_CLEAR_BUFFERS_A
;
404 if (buffers
& PIPE_CLEAR_DEPTH
) {
405 BEGIN_NV04(push
, NV50_3D(CLEAR_DEPTH
), 1);
406 PUSH_DATA (push
, fui(depth
));
407 mode
|= NV50_3D_CLEAR_BUFFERS_Z
;
410 if (buffers
& PIPE_CLEAR_STENCIL
) {
411 BEGIN_NV04(push
, NV50_3D(CLEAR_STENCIL
), 1);
412 PUSH_DATA (push
, stencil
& 0xff);
413 mode
|= NV50_3D_CLEAR_BUFFERS_S
;
416 BEGIN_NV04(push
, NV50_3D(CLEAR_BUFFERS
), 1);
417 PUSH_DATA (push
, mode
);
419 for (i
= 1; i
< fb
->nr_cbufs
; i
++) {
420 BEGIN_NV04(push
, NV50_3D(CLEAR_BUFFERS
), 1);
421 PUSH_DATA (push
, (i
<< 6) | 0x3c);
428 struct nv50_screen
*screen
;
430 struct pipe_framebuffer_state fb
;
431 struct nv50_program
*vp
;
432 struct nv50_program
*gp
;
433 struct nv50_program
*fp
;
434 unsigned num_textures
[3];
435 unsigned num_samplers
[3];
436 struct pipe_sampler_view
*texture
;
437 struct nv50_tsc_entry
*sampler
;
440 struct nv50_program vp
;
441 struct nv50_program fp
;
442 struct nv50_tsc_entry sampler
[2]; /* nearest, bilinear */
449 nv50_blitctx_make_vp(struct nv50_blitctx
*blit
)
451 static const uint32_t code
[] =
453 0x10000001, /* mov b32 o[0x00] s[0x00] */ /* HPOS.x */
455 0x10000205, /* mov b32 o[0x04] s[0x04] */ /* HPOS.y */
457 0x10000409, /* mov b32 o[0x08] s[0x08] */ /* TEXC.x */
459 0x1000060d, /* mov b32 o[0x0c] s[0x0c] */ /* TEXC.y */
461 0x10000811, /* exit mov b32 o[0x10] s[0x10] */ /* TEXC.z */
465 blit
->vp
.type
= PIPE_SHADER_VERTEX
;
466 blit
->vp
.translated
= TRUE
;
467 blit
->vp
.code
= (uint32_t *)code
; /* const_cast */
468 blit
->vp
.code_size
= sizeof(code
);
469 blit
->vp
.max_gpr
= 4;
470 blit
->vp
.max_out
= 5;
472 blit
->vp
.out
[0].mask
= 0x3;
473 blit
->vp
.out
[0].sn
= TGSI_SEMANTIC_POSITION
;
474 blit
->vp
.out
[1].hw
= 2;
475 blit
->vp
.out
[1].mask
= 0x7;
476 blit
->vp
.out
[1].sn
= TGSI_SEMANTIC_GENERIC
;
477 blit
->vp
.vp
.attrs
[0] = 0x73;
478 blit
->vp
.vp
.psiz
= 0x40;
479 blit
->vp
.vp
.edgeflag
= 0x40;
483 nv50_blitctx_make_fp(struct nv50_blitctx
*blit
)
485 static const uint32_t code
[] =
487 /* 3 coords RGBA in, RGBA out, also for Z32_FLOAT(_S8X24_UINT) */
488 0x80000000, /* interp $r0 v[0x0] */
489 0x80010004, /* interp $r1 v[0x4] */
490 0x80020009, /* interp $r2 flat v[0x8] */
492 0xf6800001, /* texauto live { $r0,1,2,3 } $t0 $s0 { $r0,1,2 } */
493 0x0000c785, /* exit */
495 /* 3 coords ZS in, S encoded in R, Z encoded in GBA (8_UNORM) */
496 0x80000000, /* interp $r0 v[0x00] */
497 0x80010004, /* interp $r1 v[0x04] */
498 0x80020009, /* interp $r2 flat v[0x8] */
500 0xf6800001, /* texauto live { $r0,1,#,# } $t0 $s0 { $r0,1,2 } */
502 0xc03f0009, /* mul f32 $r2 $r0 (2^24 - 1) */
504 0xa0000201, /* cvt f32 $r0 s32 $r1 */
506 0xa0000409, /* cvt rni s32 $r2 f32 $r2 */
508 0xc0010001, /* mul f32 $r0 $r0 1/0xff */
510 0xd03f0405, /* and b32 $r1 $r2 0x0000ff */
512 0xd000040d, /* and b32 $r3 $r2 0xff0000 */
514 0xd0000409, /* and b32 $r2 $r2 0x00ff00 */
516 0xa0000205, /* cvt f32 $r1 s32 $r1 */
518 0xa000060d, /* cvt f32 $r3 s32 $r3 */
520 0xa0000409, /* cvt f32 $r2 s32 $r2 */
522 0xc0010205, /* mul f32 $r1 $r1 1/0x0000ff */
524 0xc001060d, /* mul f32 $r3 $r3 1/0x00ff00 */
526 0xc0010409, /* mul f32 $r2 $r2 1/0xff0000 */
528 0xf0000001, /* exit never nop */
531 /* 3 coords ZS in, Z encoded in RGB, S encoded in A (U8_UNORM) */
532 0x80000000, /* interp $r0 v[0x00] */
533 0x80010004, /* interp $r1 v[0x04] */
534 0x80020009, /* interp $r2 flat v[0x8] */
536 0xf6800001, /* texauto live { $r0,1,#,# } $t0 $s0 { $r0,1,2 } */
538 0xc03f0009, /* mul f32 $r2 $r0 (2^24 - 1) */
540 0xa0000281, /* cvt f32 $r3 s32 $r1 */
542 0xa0000409, /* cvt rni s32 $r2 f32 $r2 */
544 0xc001060d, /* mul f32 $r3 $r3 1/0xff */
546 0xd03f0401, /* and b32 $r0 $r2 0x0000ff */
548 0xd0000405, /* and b32 $r1 $r2 0x00ff00 */
550 0xd0000409, /* and b32 $r2 $r2 0xff0000 */
552 0xa0000001, /* cvt f32 $r0 s32 $r0 */
554 0xa0000205, /* cvt f32 $r1 s32 $r1 */
556 0xa0000409, /* cvt f32 $r2 s32 $r2 */
558 0xc0010001, /* mul f32 $r0 $r0 1/0x0000ff */
560 0xc0010205, /* mul f32 $r1 $r1 1/0x00ff00 */
562 0xc0010409, /* mul f32 $r2 $r2 1/0xff0000 */
564 0xf0000001, /* exit never nop */
568 blit
->fp
.type
= PIPE_SHADER_FRAGMENT
;
569 blit
->fp
.translated
= TRUE
;
570 blit
->fp
.code
= (uint32_t *)code
; /* const_cast */
571 blit
->fp
.code_size
= sizeof(code
);
572 blit
->fp
.max_gpr
= 4;
573 blit
->fp
.max_out
= 4;
575 blit
->fp
.in
[0].mask
= 0x7; /* last component flat */
576 blit
->fp
.in
[0].linear
= 1;
577 blit
->fp
.in
[0].sn
= TGSI_SEMANTIC_GENERIC
;
579 blit
->fp
.out
[0].mask
= 0xf;
580 blit
->fp
.out
[0].sn
= TGSI_SEMANTIC_COLOR
;
581 blit
->fp
.fp
.interp
= 0x00020403;
582 blit
->fp
.gp
.primid
= 0x80;
586 nv50_blitctx_make_sampler(struct nv50_blitctx
*blit
)
588 /* clamp to edge, min/max lod = 0, nearest filtering */
590 blit
->sampler
[0].id
= -1;
592 blit
->sampler
[0].tsc
[0] = 0x00000092;
593 blit
->sampler
[0].tsc
[1] = 0x00000051;
595 /* clamp to edge, min/max lod = 0, bilinear filtering */
597 blit
->sampler
[1].id
= -1;
599 blit
->sampler
[1].tsc
[0] = 0x00000092;
600 blit
->sampler
[1].tsc
[1] = 0x00000062;
603 /* Since shaders cannot export stencil, we cannot copy stencil values when
604 * rendering to ZETA, so we attach the ZS surface to a colour render target.
606 static INLINE
enum pipe_format
607 nv50_blit_zeta_to_colour_format(enum pipe_format format
)
610 case PIPE_FORMAT_Z16_UNORM
: return PIPE_FORMAT_R16_UNORM
;
611 case PIPE_FORMAT_Z24_UNORM_S8_UINT
:
612 case PIPE_FORMAT_S8_UINT_Z24_UNORM
:
613 case PIPE_FORMAT_Z24X8_UNORM
: return PIPE_FORMAT_R8G8B8A8_UNORM
;
614 case PIPE_FORMAT_Z32_FLOAT
: return PIPE_FORMAT_R32_FLOAT
;
615 case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT
: return PIPE_FORMAT_R32G32_FLOAT
;
618 return PIPE_FORMAT_NONE
;
623 nv50_blitctx_get_color_mask_and_fp(struct nv50_blitctx
*blit
,
624 enum pipe_format format
, uint8_t mask
)
626 blit
->color_mask
= 0;
629 case PIPE_FORMAT_Z24X8_UNORM
:
630 case PIPE_FORMAT_Z24_UNORM_S8_UINT
:
631 blit
->fp_offset
= 160;
632 if (mask
& PIPE_MASK_Z
)
633 blit
->color_mask
|= 0x0111;
634 if (mask
& PIPE_MASK_S
)
635 blit
->color_mask
|= 0x1000;
637 case PIPE_FORMAT_S8_UINT_Z24_UNORM
:
638 blit
->fp_offset
= 24;
639 if (mask
& PIPE_MASK_Z
)
640 blit
->color_mask
|= 0x1110;
641 if (mask
& PIPE_MASK_S
)
642 blit
->color_mask
|= 0x0001;
646 if (mask
& (PIPE_MASK_R
| PIPE_MASK_Z
)) blit
->color_mask
|= 0x0001;
647 if (mask
& (PIPE_MASK_G
| PIPE_MASK_S
)) blit
->color_mask
|= 0x0010;
648 if (mask
& PIPE_MASK_B
) blit
->color_mask
|= 0x0100;
649 if (mask
& PIPE_MASK_A
) blit
->color_mask
|= 0x1000;
655 nv50_blit_set_dst(struct nv50_context
*nv50
,
656 struct pipe_resource
*res
, unsigned level
, unsigned layer
)
658 struct pipe_context
*pipe
= &nv50
->base
.pipe
;
659 struct pipe_surface templ
;
661 if (util_format_is_depth_or_stencil(res
->format
))
662 templ
.format
= nv50_blit_zeta_to_colour_format(res
->format
);
664 templ
.format
= res
->format
;
666 templ
.usage
= PIPE_USAGE_STREAM
;
667 templ
.u
.tex
.level
= level
;
668 templ
.u
.tex
.first_layer
= templ
.u
.tex
.last_layer
= layer
;
670 nv50
->framebuffer
.cbufs
[0] = nv50_miptree_surface_new(pipe
, res
, &templ
);
671 nv50
->framebuffer
.nr_cbufs
= 1;
672 nv50
->framebuffer
.zsbuf
= NULL
;
673 nv50
->framebuffer
.width
= nv50
->framebuffer
.cbufs
[0]->width
;
674 nv50
->framebuffer
.height
= nv50
->framebuffer
.cbufs
[0]->height
;
678 nv50_blit_fixup_tic_entry(struct pipe_sampler_view
*view
)
680 struct nv50_tic_entry
*ent
= nv50_tic_entry(view
);
682 ent
->tic
[2] &= ~(1 << 31); /* scaled coordinates, ok with 3d textures ? */
686 ent
->tic
[3] = 0x20000000; /* affects quality of near vertical edges in MS8 */
690 nv50_blit_set_src(struct nv50_context
*nv50
,
691 struct pipe_resource
*res
, unsigned level
, unsigned layer
)
693 struct pipe_context
*pipe
= &nv50
->base
.pipe
;
694 struct pipe_sampler_view templ
;
696 templ
.format
= res
->format
;
697 templ
.u
.tex
.first_layer
= templ
.u
.tex
.last_layer
= layer
;
698 templ
.u
.tex
.first_level
= templ
.u
.tex
.last_level
= level
;
699 templ
.swizzle_r
= PIPE_SWIZZLE_RED
;
700 templ
.swizzle_g
= PIPE_SWIZZLE_GREEN
;
701 templ
.swizzle_b
= PIPE_SWIZZLE_BLUE
;
702 templ
.swizzle_a
= PIPE_SWIZZLE_ALPHA
;
704 nv50
->textures
[2][0] = nv50_create_sampler_view(pipe
, res
, &templ
);
706 nv50_blit_fixup_tic_entry(nv50
->textures
[2][0]);
708 nv50
->num_textures
[0] = nv50
->num_textures
[1] = 0;
709 nv50
->num_textures
[2] = 1;
713 nv50_blitctx_prepare_state(struct nv50_blitctx
*blit
)
715 struct nouveau_pushbuf
*push
= blit
->screen
->base
.pushbuf
;
718 BEGIN_NV04(push
, NV50_3D(COLOR_MASK(0)), 1);
719 PUSH_DATA (push
, blit
->color_mask
);
720 BEGIN_NV04(push
, NV50_3D(BLEND_ENABLE(0)), 1);
722 BEGIN_NV04(push
, NV50_3D(LOGIC_OP_ENABLE
), 1);
725 /* rasterizer state */
726 #ifndef NV50_SCISSORS_CLIPPING
727 BEGIN_NV04(push
, NV50_3D(SCISSOR_ENABLE(0)), 1);
730 BEGIN_NV04(push
, NV50_3D(VERTEX_TWO_SIDE_ENABLE
), 1);
732 BEGIN_NV04(push
, NV50_3D(FRAG_COLOR_CLAMP_EN
), 1);
734 BEGIN_NV04(push
, NV50_3D(MULTISAMPLE_ENABLE
), 1);
736 BEGIN_NV04(push
, NV50_3D(MSAA_MASK(0)), 4);
737 PUSH_DATA (push
, 0xffff);
738 PUSH_DATA (push
, 0xffff);
739 PUSH_DATA (push
, 0xffff);
740 PUSH_DATA (push
, 0xffff);
741 BEGIN_NV04(push
, NV50_3D(POLYGON_MODE_FRONT
), 3);
742 PUSH_DATA (push
, NV50_3D_POLYGON_MODE_FRONT_FILL
);
743 PUSH_DATA (push
, NV50_3D_POLYGON_MODE_BACK_FILL
);
745 BEGIN_NV04(push
, NV50_3D(CULL_FACE_ENABLE
), 1);
747 BEGIN_NV04(push
, NV50_3D(POLYGON_STIPPLE_ENABLE
), 1);
749 BEGIN_NV04(push
, NV50_3D(POLYGON_OFFSET_FILL_ENABLE
), 1);
753 BEGIN_NV04(push
, NV50_3D(DEPTH_TEST_ENABLE
), 1);
755 BEGIN_NV04(push
, NV50_3D(STENCIL_ENABLE
), 1);
757 BEGIN_NV04(push
, NV50_3D(ALPHA_TEST_ENABLE
), 1);
762 nv50_blitctx_pre_blit(struct nv50_blitctx
*blit
, struct nv50_context
*nv50
)
766 blit
->saved
.fb
.width
= nv50
->framebuffer
.width
;
767 blit
->saved
.fb
.height
= nv50
->framebuffer
.height
;
768 blit
->saved
.fb
.nr_cbufs
= nv50
->framebuffer
.nr_cbufs
;
769 blit
->saved
.fb
.cbufs
[0] = nv50
->framebuffer
.cbufs
[0];
770 blit
->saved
.fb
.zsbuf
= nv50
->framebuffer
.zsbuf
;
772 blit
->saved
.vp
= nv50
->vertprog
;
773 blit
->saved
.gp
= nv50
->gmtyprog
;
774 blit
->saved
.fp
= nv50
->fragprog
;
776 nv50
->vertprog
= &blit
->vp
;
777 nv50
->gmtyprog
= NULL
;
778 nv50
->fragprog
= &blit
->fp
;
780 for (s
= 0; s
< 3; ++s
) {
781 blit
->saved
.num_textures
[s
] = nv50
->num_textures
[s
];
782 blit
->saved
.num_samplers
[s
] = nv50
->num_samplers
[s
];
784 blit
->saved
.texture
= nv50
->textures
[2][0];
785 blit
->saved
.sampler
= nv50
->samplers
[2][0];
787 nv50
->samplers
[2][0] = &blit
->sampler
[blit
->filter
];
789 nv50
->num_samplers
[0] = nv50
->num_samplers
[1] = 0;
790 nv50
->num_samplers
[2] = 1;
792 blit
->saved
.dirty
= nv50
->dirty
;
795 NV50_NEW_FRAMEBUFFER
|
796 NV50_NEW_VERTPROG
| NV50_NEW_FRAGPROG
| NV50_NEW_GMTYPROG
|
797 NV50_NEW_TEXTURES
| NV50_NEW_SAMPLERS
;
801 nv50_blitctx_post_blit(struct nv50_context
*nv50
, struct nv50_blitctx
*blit
)
805 pipe_surface_reference(&nv50
->framebuffer
.cbufs
[0], NULL
);
807 nv50
->framebuffer
.width
= blit
->saved
.fb
.width
;
808 nv50
->framebuffer
.height
= blit
->saved
.fb
.height
;
809 nv50
->framebuffer
.nr_cbufs
= blit
->saved
.fb
.nr_cbufs
;
810 nv50
->framebuffer
.cbufs
[0] = blit
->saved
.fb
.cbufs
[0];
811 nv50
->framebuffer
.zsbuf
= blit
->saved
.fb
.zsbuf
;
813 nv50
->vertprog
= blit
->saved
.vp
;
814 nv50
->gmtyprog
= blit
->saved
.gp
;
815 nv50
->fragprog
= blit
->saved
.fp
;
817 pipe_sampler_view_reference(&nv50
->textures
[2][0], NULL
);
819 for (s
= 0; s
< 3; ++s
) {
820 nv50
->num_textures
[s
] = blit
->saved
.num_textures
[s
];
821 nv50
->num_samplers
[s
] = blit
->saved
.num_samplers
[s
];
823 nv50
->textures
[2][0] = blit
->saved
.texture
;
824 nv50
->samplers
[2][0] = blit
->saved
.sampler
;
826 nv50
->dirty
= blit
->saved
.dirty
|
827 (NV50_NEW_FRAMEBUFFER
| NV50_NEW_SCISSOR
| NV50_NEW_SAMPLE_MASK
|
828 NV50_NEW_RASTERIZER
| NV50_NEW_ZSA
| NV50_NEW_BLEND
|
829 NV50_NEW_TEXTURES
| NV50_NEW_SAMPLERS
|
830 NV50_NEW_VERTPROG
| NV50_NEW_GMTYPROG
| NV50_NEW_FRAGPROG
);
834 nv50_resource_resolve(struct pipe_context
*pipe
,
835 const struct pipe_resolve_info
*info
)
837 struct nv50_context
*nv50
= nv50_context(pipe
);
838 struct nv50_screen
*screen
= nv50
->screen
;
839 struct nv50_blitctx
*blit
= screen
->blitctx
;
840 struct nouveau_pushbuf
*push
= nv50
->base
.pushbuf
;
841 struct pipe_resource
*src
= info
->src
.res
;
842 struct pipe_resource
*dst
= info
->dst
.res
;
843 float x0
, x1
, y0
, y1
, z
;
844 float x_range
, y_range
;
846 nv50_blitctx_get_color_mask_and_fp(blit
, dst
->format
, info
->mask
);
848 blit
->filter
= util_format_is_depth_or_stencil(dst
->format
) ? 0 : 1;
850 nv50_blitctx_pre_blit(blit
, nv50
);
852 nv50_blit_set_dst(nv50
, dst
, info
->dst
.level
, info
->dst
.layer
);
853 nv50_blit_set_src(nv50
, src
, 0, info
->src
.layer
);
855 nv50_blitctx_prepare_state(blit
);
857 nv50_state_validate(nv50
, ~0, 36);
860 (float)(info
->src
.x1
- info
->src
.x0
) /
861 (float)(info
->dst
.x1
- info
->dst
.x0
);
863 (float)(info
->src
.y1
- info
->src
.y0
) /
864 (float)(info
->dst
.y1
- info
->dst
.y0
);
866 x0
= (float)info
->src
.x0
- x_range
* (float)info
->dst
.x0
;
867 y0
= (float)info
->src
.y0
- y_range
* (float)info
->dst
.y0
;
869 x1
= x0
+ 16384.0f
* x_range
;
870 y1
= y0
+ 16384.0f
* y_range
;
872 x0
*= (float)(1 << nv50_miptree(src
)->ms_x
);
873 x1
*= (float)(1 << nv50_miptree(src
)->ms_x
);
874 y0
*= (float)(1 << nv50_miptree(src
)->ms_y
);
875 y1
*= (float)(1 << nv50_miptree(src
)->ms_y
);
877 z
= (float)info
->src
.layer
;
879 BEGIN_NV04(push
, NV50_3D(FP_START_ID
), 1);
881 blit
->fp
.code_base
+ blit
->fp_offset
);
883 BEGIN_NV04(push
, NV50_3D(VIEWPORT_TRANSFORM_EN
), 1);
886 /* Draw a large triangle in screen coordinates covering the whole
887 * render target, with scissors defining the destination region.
888 * The vertex is supplied with non-normalized texture coordinates
889 * arranged in a way to yield the desired offset and scale.
892 BEGIN_NV04(push
, NV50_3D(SCISSOR_HORIZ(0)), 2);
893 PUSH_DATA (push
, (info
->dst
.x1
<< 16) | info
->dst
.x0
);
894 PUSH_DATA (push
, (info
->dst
.y1
<< 16) | info
->dst
.y0
);
896 BEGIN_NV04(push
, NV50_3D(VERTEX_BEGIN_GL
), 1);
897 PUSH_DATA (push
, NV50_3D_VERTEX_BEGIN_GL_PRIMITIVE_TRIANGLES
);
898 BEGIN_NV04(push
, NV50_3D(VTX_ATTR_3F_X(1)), 3);
899 PUSH_DATAf(push
, x0
);
900 PUSH_DATAf(push
, y0
);
902 BEGIN_NV04(push
, NV50_3D(VTX_ATTR_2F_X(0)), 2);
903 PUSH_DATAf(push
, 0.0f
);
904 PUSH_DATAf(push
, 0.0f
);
905 BEGIN_NV04(push
, NV50_3D(VTX_ATTR_3F_X(1)), 3);
906 PUSH_DATAf(push
, x1
);
907 PUSH_DATAf(push
, y0
);
909 BEGIN_NV04(push
, NV50_3D(VTX_ATTR_2F_X(0)), 2);
910 PUSH_DATAf(push
, 16384 << nv50_miptree(dst
)->ms_x
);
911 PUSH_DATAf(push
, 0.0f
);
912 BEGIN_NV04(push
, NV50_3D(VTX_ATTR_3F_X(1)), 3);
913 PUSH_DATAf(push
, x0
);
914 PUSH_DATAf(push
, y1
);
916 BEGIN_NV04(push
, NV50_3D(VTX_ATTR_2F_X(0)), 2);
917 PUSH_DATAf(push
, 0.0f
);
918 PUSH_DATAf(push
, 16384 << nv50_miptree(dst
)->ms_y
);
919 BEGIN_NV04(push
, NV50_3D(VERTEX_END_GL
), 1);
922 /* re-enable normally constant state */
924 BEGIN_NV04(push
, NV50_3D(VIEWPORT_TRANSFORM_EN
), 1);
927 nv50_blitctx_post_blit(nv50
, blit
);
931 nv50_blitctx_create(struct nv50_screen
*screen
)
933 screen
->blitctx
= CALLOC_STRUCT(nv50_blitctx
);
934 if (!screen
->blitctx
) {
935 NOUVEAU_ERR("failed to allocate blit context\n");
939 screen
->blitctx
->screen
= screen
;
941 nv50_blitctx_make_vp(screen
->blitctx
);
942 nv50_blitctx_make_fp(screen
->blitctx
);
944 nv50_blitctx_make_sampler(screen
->blitctx
);
946 screen
->blitctx
->color_mask
= 0x1111;
952 nv50_init_surface_functions(struct nv50_context
*nv50
)
954 struct pipe_context
*pipe
= &nv50
->base
.pipe
;
956 pipe
->resource_copy_region
= nv50_resource_copy_region
;
957 pipe
->resource_resolve
= nv50_resource_resolve
;
958 pipe
->clear_render_target
= nv50_clear_render_target
;
959 pipe
->clear_depth_stencil
= nv50_clear_depth_stencil
;