a2e1a8539958b93c31a83f2616ab92b9aa427617
[mesa.git] / src / gallium / drivers / nvc0 / nvc0_surface.c
1 /*
2 * Copyright 2008 Ben Skeggs
3 *
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:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
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
20 * SOFTWARE.
21 */
22
23 #include <stdint.h>
24
25 #include "pipe/p_defines.h"
26
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"
31
32 #include "nvc0_context.h"
33 #include "nvc0_resource.h"
34
35 #include "nv50/nv50_defs.xml.h"
36
37 #define NVC0_ENG2D_SUPPORTED_FORMATS 0xff9ccfe1cce3ccc9ULL
38
39 /* return TRUE for formats that can be converted among each other by NVC0_2D */
40 static INLINE boolean
41 nvc0_2d_format_faithful(enum pipe_format format)
42 {
43 uint8_t id = nvc0_format_table[format].rt;
44
45 return (id >= 0xc0) && (NVC0_ENG2D_SUPPORTED_FORMATS & (1ULL << (id - 0xc0)));
46 }
47
48 static INLINE uint8_t
49 nvc0_2d_format(enum pipe_format format)
50 {
51 uint8_t id = nvc0_format_table[format].rt;
52
53 /* Hardware values for color formats range from 0xc0 to 0xff,
54 * but the 2D engine doesn't support all of them.
55 */
56 if (nvc0_2d_format_faithful(format))
57 return id;
58
59 switch (util_format_get_blocksize(format)) {
60 case 1:
61 return NV50_SURFACE_FORMAT_R8_UNORM;
62 case 2:
63 return NV50_SURFACE_FORMAT_R16_UNORM;
64 case 4:
65 return NV50_SURFACE_FORMAT_BGRA8_UNORM;
66 case 8:
67 return NV50_SURFACE_FORMAT_RGBA16_UNORM;
68 case 16:
69 return NV50_SURFACE_FORMAT_RGBA32_FLOAT;
70 default:
71 return 0;
72 }
73 }
74
75 static int
76 nvc0_2d_texture_set(struct nouveau_channel *chan, int dst,
77 struct nv50_miptree *mt, unsigned level, unsigned layer)
78 {
79 struct nouveau_bo *bo = mt->base.bo;
80 uint32_t width, height, depth;
81 uint32_t format;
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;
85
86 format = nvc0_2d_format(mt->base.base.format);
87 if (!format) {
88 NOUVEAU_ERR("invalid/unsupported surface format: %s\n",
89 util_format_name(mt->base.base.format));
90 return 1;
91 }
92
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);
96
97 /* layer has to be < depth, and depth > tile depth / 2 */
98
99 if (!mt->layout_3d) {
100 offset += mt->layer_stride * layer;
101 layer = 0;
102 depth = 1;
103 } else
104 if (!dst) {
105 offset += nvc0_mt_zslice_offset(mt, level, layer);
106 layer = 0;
107 }
108
109 if (!(bo->tile_flags & NOUVEAU_BO_TILE_LAYOUT_MASK)) {
110 BEGIN_RING(chan, RING_2D_(mthd), 2);
111 OUT_RING (chan, format);
112 OUT_RING (chan, 1);
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);
119 } else {
120 BEGIN_RING(chan, RING_2D_(mthd), 5);
121 OUT_RING (chan, format);
122 OUT_RING (chan, 0);
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);
131 }
132
133 #if 0
134 if (dst) {
135 BEGIN_RING(chan, RING_2D_(NVC0_2D_CLIP_X), 4);
136 OUT_RING (chan, 0);
137 OUT_RING (chan, 0);
138 OUT_RING (chan, width);
139 OUT_RING (chan, height);
140 }
141 #endif
142 return 0;
143 }
144
145 static int
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)
152 {
153 static const uint32_t duvdxy[5] =
154 {
155 0x40000000, 0x80000000, 0x00000001, 0x00000002, 0x00000004
156 };
157
158 int ret;
159 uint32_t ctrl = 0x00;
160
161 ret = MARK_RING(chan, 2 * 16 + 32, 4);
162 if (ret)
163 return ret;
164
165 ret = nvc0_2d_texture_set(chan, 1, dst, dst_level, dz);
166 if (ret)
167 return ret;
168
169 ret = nvc0_2d_texture_set(chan, 0, src, src_level, sz);
170 if (ret)
171 return ret;
172
173 /* NOTE: 2D engine doesn't work for MS8 */
174 if (src->ms_x)
175 ctrl = 0x11;
176
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);
191 OUT_RING (chan, 0);
192 OUT_RING (chan, sx << src->ms_x);
193 OUT_RING (chan, 0);
194 OUT_RING (chan, sy << src->ms_x);
195
196 return 0;
197 }
198
199 static void
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)
205 {
206 struct nvc0_screen *screen = nvc0_context(pipe)->screen;
207 int ret;
208 boolean m2mf;
209 unsigned dst_layer = dstz, src_layer = src_box->z;
210
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);
215 return;
216 }
217
218 assert(src->nr_samples == dst->nr_samples);
219
220 m2mf = (src->format == dst->format) ||
221 (util_format_get_blocksizebits(src->format) ==
222 util_format_get_blocksizebits(dst->format));
223
224 nv04_resource(dst)->status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING;
225
226 if (m2mf) {
227 struct nv50_m2mf_rect drect, srect;
228 unsigned i;
229 unsigned nx = util_format_get_nblocksx(src->format, src_box->width);
230 unsigned ny = util_format_get_nblocksy(src->format, src_box->height);
231
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);
235
236 for (i = 0; i < src_box->depth; ++i) {
237 nvc0_m2mf_transfer_rect(&screen->base.base, &drect, &srect, nx, ny);
238
239 if (nv50_miptree(dst)->layout_3d)
240 drect.z++;
241 else
242 drect.base += nv50_miptree(dst)->layer_stride;
243
244 if (nv50_miptree(src)->layout_3d)
245 srect.z++;
246 else
247 srect.base += nv50_miptree(src)->layer_stride;
248 }
249 return;
250 }
251
252 assert(nvc0_2d_format_faithful(src->format));
253 assert(nvc0_2d_format_faithful(dst->format));
254
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);
262 if (ret)
263 return;
264 }
265 }
266
267 static void
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)
273 {
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);
279 unsigned z;
280
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]);
286
287 if (MARK_RING(chan, 18, 2))
288 return;
289
290 BEGIN_RING(chan, RING_3D(SCREEN_SCISSOR_HORIZ), 2);
291 OUT_RING (chan, ( width << 16) | dstx);
292 OUT_RING (chan, (height << 16) | dsty);
293
294 BEGIN_RING(chan, RING_3D(RT_CONTROL), 1);
295 OUT_RING (chan, 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);
301
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);
310 } else {
311 if (res->base.target == PIPE_BUFFER) {
312 OUT_RING(chan, 262144);
313 OUT_RING(chan, 1);
314 } else {
315 OUT_RING(chan, nv50_miptree(&res->base)->level[0].pitch);
316 OUT_RING(chan, sf->height);
317 }
318 OUT_RING(chan, nvc0_format_table[sf->base.format].rt);
319 OUT_RING(chan, 1 << 12);
320 OUT_RING(chan, 1);
321 OUT_RING(chan, 0);
322 OUT_RING(chan, 0);
323
324 IMMED_RING(chan, RING_3D(ZETA_ENABLE), 0);
325
326 /* tiled textures don't have to be fenced, they're not mapped directly */
327 nvc0_resource_fence(res, NOUVEAU_BO_WR);
328 }
329
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));
334 }
335
336 nv50->dirty |= NVC0_NEW_FRAMEBUFFER;
337 }
338
339 static void
340 nvc0_clear_depth_stencil(struct pipe_context *pipe,
341 struct pipe_surface *dst,
342 unsigned clear_flags,
343 double depth,
344 unsigned stencil,
345 unsigned dstx, unsigned dsty,
346 unsigned width, unsigned height)
347 {
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;
354 uint32_t mode = 0;
355 int unk = mt->base.base.target == PIPE_TEXTURE_2D;
356 unsigned z;
357
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;
362 }
363
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;
368 }
369
370 if (MARK_RING(chan, 20, 2))
371 return;
372
373 BEGIN_RING(chan, RING_3D(SCREEN_SCISSOR_HORIZ), 2);
374 OUT_RING (chan, ( width << 16) | dstx);
375 OUT_RING (chan, (height << 16) | dsty);
376
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);
384 OUT_RING (chan, 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);
391
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));
396 }
397
398 nv50->dirty |= NVC0_NEW_FRAMEBUFFER;
399 }
400
401 void
402 nvc0_clear(struct pipe_context *pipe, unsigned buffers,
403 const union pipe_color_union *color,
404 double depth, unsigned stencil)
405 {
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;
409 unsigned i;
410 uint32_t mode = 0;
411
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)))
414 return;
415
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]);
422 mode =
423 NVC0_3D_CLEAR_BUFFERS_R | NVC0_3D_CLEAR_BUFFERS_G |
424 NVC0_3D_CLEAR_BUFFERS_B | NVC0_3D_CLEAR_BUFFERS_A;
425 }
426
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;
431 }
432
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;
437 }
438
439 BEGIN_RING(chan, RING_3D(CLEAR_BUFFERS), 1);
440 OUT_RING (chan, mode);
441
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);
445 }
446 }
447
448
449 struct nvc0_blitctx
450 {
451 struct nvc0_screen *screen;
452 struct {
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;
463 unsigned dirty;
464 unsigned clip_nr;
465 } saved;
466 struct nvc0_program vp;
467 struct nvc0_program fp;
468 struct nv50_tsc_entry sampler[2]; /* nearest, bilinear */
469 uint32_t fp_offset;
470 uint16_t color_mask;
471 uint8_t filter;
472 };
473
474 static void
475 nvc0_blitctx_make_vp(struct nvc0_blitctx *blit)
476 {
477 static const uint32_t code[] =
478 {
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 */
484 };
485
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;
492
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] */
497 }
498
499 static void
500 nvc0_blitctx_make_fp(struct nvc0_blitctx *blit)
501 {
502 static const uint32_t code[] = /* use nvc0dis */
503 {
504 /* 2 coords RGBA in, RGBA out, also for Z32_FLOAT(_S8X24_UINT)
505 * NOTE:
506 * NVC0 doesn't like tex 3d on non-3d textures, but there should
507 * only be 2d and 2d-array MS resources anyway.
508 */
509 0xfff01c00, 0xc07e0080,
510 0xfff05c00, 0xc07e0084,
511 0x00001c86, 0x8013c000,
512 0x00001de7, 0x80000000,
513 /* size: 0x70 + padding */
514 0, 0, 0, 0,
515
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.
519 */
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,
529 0x05001c88,
530 0x09009e88,
531 0x04001c02, 0x30ee0202,
532 0xfc205c02, 0x38000003,
533 0x0020dc02, 0x3803fc00,
534 0x00209c02, 0x380003fc,
535 0x05005c88,
536 0x0d00dc88,
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,
544
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,
554 0x05081c88,
555 0x09009e88,
556 0x0430dc02, 0x30ee0202,
557 0xfc201c02, 0x38000003,
558 0x00205c02, 0x380003fc,
559 0x00209c02, 0x3803fc00,
560 0x01001c88,
561 0x05005c88,
562 0x09209e04, 0x18000000,
563 0x04001c02, 0x30ee0202,
564 0x04105c02, 0x30de0202,
565 0x04209c02, 0x30ce0202,
566 0x00001de7, 0x80000000,
567 };
568
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;
574
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 */
579 }
580
581 static void
582 nvc0_blitctx_make_sampler(struct nvc0_blitctx *blit)
583 {
584 /* clamp to edge, min/max lod = 0, nearest filtering */
585
586 blit->sampler[0].id = -1;
587
588 blit->sampler[0].tsc[0] = 0x00000092;
589 blit->sampler[0].tsc[1] = 0x00000051;
590
591 /* clamp to edge, min/max lod = 0, bilinear filtering */
592
593 blit->sampler[1].id = -1;
594
595 blit->sampler[1].tsc[0] = 0x00000092;
596 blit->sampler[1].tsc[1] = 0x00000062;
597 }
598
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.
601 */
602 static INLINE enum pipe_format
603 nvc0_blit_zeta_to_colour_format(enum pipe_format format)
604 {
605 switch (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;
612 default:
613 assert(0);
614 return PIPE_FORMAT_NONE;
615 }
616 }
617
618 static void
619 nvc0_blitctx_get_color_mask_and_fp(struct nvc0_blitctx *blit,
620 enum pipe_format format, uint8_t mask)
621 {
622 blit->color_mask = 0;
623
624 switch (format) {
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;
632 break;
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;
639 break;
640 default:
641 blit->fp_offset = 0;
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;
646 break;
647 }
648 }
649
650 static void
651 nvc0_blit_set_dst(struct nvc0_context *nvc0,
652 struct pipe_resource *res, unsigned level, unsigned layer)
653 {
654 struct pipe_context *pipe = &nvc0->base.pipe;
655 struct pipe_surface templ;
656
657 if (util_format_is_depth_or_stencil(res->format))
658 templ.format = nvc0_blit_zeta_to_colour_format(res->format);
659 else
660 templ.format = res->format;
661
662 templ.usage = PIPE_USAGE_STREAM;
663 templ.u.tex.level = level;
664 templ.u.tex.first_layer = templ.u.tex.last_layer = layer;
665
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;
671 }
672
673 static INLINE void
674 nvc0_blit_fixup_tic_entry(struct pipe_sampler_view *view)
675 {
676 struct nv50_tic_entry *ent = nv50_tic_entry(view);
677
678 ent->tic[2] &= ~(1 << 31); /* scaled coordinates, ok with 3d textures ? */
679
680 /* magic: */
681
682 ent->tic[3] = 0x20000000; /* affects quality of near vertical edges in MS8 */
683 }
684
685 static void
686 nvc0_blit_set_src(struct nvc0_context *nvc0,
687 struct pipe_resource *res, unsigned level, unsigned layer)
688 {
689 struct pipe_context *pipe = &nvc0->base.pipe;
690 struct pipe_sampler_view templ;
691 int s;
692
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;
700
701 nvc0->textures[4][0] = nvc0_create_sampler_view(pipe, res, &templ);
702
703 nvc0_blit_fixup_tic_entry(nvc0->textures[4][0]);
704
705 for (s = 0; s <= 3; ++s)
706 nvc0->num_textures[s] = 0;
707 nvc0->num_textures[4] = 1;
708 }
709
710 static void
711 nvc0_blitctx_prepare_state(struct nvc0_blitctx *blit)
712 {
713 struct nouveau_channel *chan = blit->screen->base.channel;
714
715 /* TODO: maybe make this a MACRO (if we need more logic) ? */
716
717 /* blend state */
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);
721 OUT_RING (chan, 0);
722 IMMED_RING(chan, RING_3D(LOGIC_OP_ENABLE), 0);
723
724 /* rasterizer state */
725 BEGIN_RING(chan, RING_3D(FRAG_COLOR_CLAMP_EN), 1);
726 OUT_RING (chan, 0);
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);
741
742 /* zsa state */
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);
746
747 /* disable transform feedback */
748 IMMED_RING(chan, RING_3D(TFB_ENABLE), 0);
749 }
750
751 static void
752 nvc0_blitctx_pre_blit(struct nvc0_blitctx *blit, struct nvc0_context *nvc0)
753 {
754 int s;
755
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;
761
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;
767
768 nvc0->vertprog = &blit->vp;
769 nvc0->fragprog = &blit->fp;
770 nvc0->tctlprog = NULL;
771 nvc0->tevlprog = NULL;
772 nvc0->gmtyprog = NULL;
773
774 blit->saved.clip_nr = nvc0->clip.nr;
775
776 nvc0->clip.nr = 0;
777
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];
781 }
782 blit->saved.texture = nvc0->textures[4][0];
783 blit->saved.sampler = nvc0->samplers[4][0];
784
785 nvc0->samplers[4][0] = &blit->sampler[blit->filter];
786
787 for (s = 0; s <= 3; ++s)
788 nvc0->num_samplers[s] = 0;
789 nvc0->num_samplers[4] = 1;
790
791 blit->saved.dirty = nvc0->dirty;
792
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;
797 }
798
799 static void
800 nvc0_blitctx_post_blit(struct nvc0_context *nvc0, struct nvc0_blitctx *blit)
801 {
802 int s;
803
804 pipe_surface_reference(&nvc0->framebuffer.cbufs[0], NULL);
805
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;
811
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;
817
818 nvc0->clip.nr = blit->saved.clip_nr;
819
820 pipe_sampler_view_reference(&nvc0->textures[4][0], NULL);
821
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];
825 }
826 nvc0->textures[4][0] = blit->saved.texture;
827 nvc0->samplers[4][0] = blit->saved.sampler;
828
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);
836 }
837
838 static void
839 nvc0_resource_resolve(struct pipe_context *pipe,
840 const struct pipe_resolve_info *info)
841 {
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;
850
851 /* Would need more shader variants or, better, just change the TIC target.
852 * But no API creates 3D MS textures ...
853 */
854 if (src->target == PIPE_TEXTURE_3D)
855 return;
856
857 nvc0_blitctx_get_color_mask_and_fp(blit, dst->format, info->mask);
858
859 blit->filter = util_format_is_depth_or_stencil(dst->format) ? 0 : 1;
860
861 nvc0_blitctx_pre_blit(blit, nvc0);
862
863 nvc0_blit_set_dst(nvc0, dst, info->dst.level, info->dst.layer);
864 nvc0_blit_set_src(nvc0, src, 0, info->src.layer);
865
866 nvc0_blitctx_prepare_state(blit);
867
868 nvc0_state_validate(nvc0, ~0, 36);
869
870 x_range =
871 (float)(info->src.x1 - info->src.x0) /
872 (float)(info->dst.x1 - info->dst.x0);
873 y_range =
874 (float)(info->src.y1 - info->src.y0) /
875 (float)(info->dst.y1 - info->dst.y0);
876
877 x0 = (float)info->src.x0 - x_range * (float)info->dst.x0;
878 y0 = (float)info->src.y0 - y_range * (float)info->dst.y0;
879
880 x1 = x0 + 16384.0f * x_range;
881 y1 = y0 + 16384.0f * y_range;
882
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);
887
888 BEGIN_RING(chan, RING_3D(SP_START_ID(5)), 1);
889 OUT_RING (chan,
890 blit->fp.code_base + blit->fp_offset);
891
892 IMMED_RING(chan, RING_3D(VIEWPORT_TRANSFORM_EN), 0);
893
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.
898 */
899
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);
903
904 IMMED_RING(chan, RING_3D(VERTEX_BEGIN_GL),
905 NVC0_3D_VERTEX_BEGIN_GL_PRIMITIVE_TRIANGLES);
906
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);
931
932 IMMED_RING(chan, RING_3D(VERTEX_END_GL), 0);
933
934 /* re-enable normally constant state */
935
936 IMMED_RING(chan, RING_3D(VIEWPORT_TRANSFORM_EN), 1);
937
938 nvc0_blitctx_post_blit(nvc0, blit);
939 }
940
941 boolean
942 nvc0_blitctx_create(struct nvc0_screen *screen)
943 {
944 screen->blitctx = CALLOC_STRUCT(nvc0_blitctx);
945 if (!screen->blitctx) {
946 NOUVEAU_ERR("failed to allocate blit context\n");
947 return FALSE;
948 }
949
950 screen->blitctx->screen = screen;
951
952 nvc0_blitctx_make_vp(screen->blitctx);
953 nvc0_blitctx_make_fp(screen->blitctx);
954
955 nvc0_blitctx_make_sampler(screen->blitctx);
956
957 screen->blitctx->color_mask = 0x1111;
958
959 return TRUE;
960 }
961
962
963 void
964 nvc0_init_surface_functions(struct nvc0_context *nvc0)
965 {
966 struct pipe_context *pipe = &nvc0->base.pipe;
967
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;
972 }
973