nvc0_surface.c revision e44089b2f79aa2dcaacf348911433d1e21235c0c
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 */
40static INLINE boolean
41nvc0_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
48static INLINE uint8_t
49nvc0_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
75static int
76nvc0_2d_texture_set(struct nouveau_pushbuf *push, boolean 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 offset = mt->level[level].offset;
84
85   format = nvc0_2d_format(mt->base.base.format);
86   if (!format) {
87      NOUVEAU_ERR("invalid/unsupported surface format: %s\n",
88                  util_format_name(mt->base.base.format));
89      return 1;
90   }
91
92   width = u_minify(mt->base.base.width0, level) << mt->ms_x;
93   height = u_minify(mt->base.base.height0, level) << mt->ms_y;
94   depth = u_minify(mt->base.base.depth0, level);
95
96   /* layer has to be < depth, and depth > tile depth / 2 */
97
98   if (!mt->layout_3d) {
99      offset += mt->layer_stride * layer;
100      layer = 0;
101      depth = 1;
102   } else
103   if (!dst) {
104      offset += nvc0_mt_zslice_offset(mt, level, layer);
105      layer = 0;
106   }
107
108   if (nouveau_bo_memtype(bo)) {
109      BEGIN_NVC0(push, SUBC_2D(mthd), 2);
110      PUSH_DATA (push, format);
111      PUSH_DATA (push, 1);
112      BEGIN_NVC0(push, SUBC_2D(mthd + 0x14), 5);
113      PUSH_DATA (push, mt->level[level].pitch);
114      PUSH_DATA (push, width);
115      PUSH_DATA (push, height);
116      PUSH_DATAh(push, bo->offset + offset);
117      PUSH_DATA (push, bo->offset + offset);
118   } else {
119      BEGIN_NVC0(push, SUBC_2D(mthd), 5);
120      PUSH_DATA (push, format);
121      PUSH_DATA (push, 0);
122      PUSH_DATA (push, mt->level[level].tile_mode);
123      PUSH_DATA (push, depth);
124      PUSH_DATA (push, layer);
125      BEGIN_NVC0(push, SUBC_2D(mthd + 0x18), 4);
126      PUSH_DATA (push, width);
127      PUSH_DATA (push, height);
128      PUSH_DATAh(push, bo->offset + offset);
129      PUSH_DATA (push, bo->offset + offset);
130   }
131
132#if 0
133   if (dst) {
134      BEGIN_NVC0(push, SUBC_2D(NVC0_2D_CLIP_X), 4);
135      PUSH_DATA (push, 0);
136      PUSH_DATA (push, 0);
137      PUSH_DATA (push, width);
138      PUSH_DATA (push, height);
139   }
140#endif
141   return 0;
142}
143
144static int
145nvc0_2d_texture_do_copy(struct nouveau_pushbuf *push,
146                        struct nv50_miptree *dst, unsigned dst_level,
147                        unsigned dx, unsigned dy, unsigned dz,
148                        struct nv50_miptree *src, unsigned src_level,
149                        unsigned sx, unsigned sy, unsigned sz,
150                        unsigned w, unsigned h)
151{
152   static const uint32_t duvdxy[5] =
153   {
154      0x40000000, 0x80000000, 0x00000001, 0x00000002, 0x00000004
155   };
156
157   int ret;
158   uint32_t ctrl = 0x00;
159
160   ret = PUSH_SPACE(push, 2 * 16 + 32);
161   if (ret)
162      return ret;
163
164   ret = nvc0_2d_texture_set(push, TRUE, dst, dst_level, dz);
165   if (ret)
166      return ret;
167
168   ret = nvc0_2d_texture_set(push, FALSE, src, src_level, sz);
169   if (ret)
170      return ret;
171
172   /* NOTE: 2D engine doesn't work for MS8 */
173   if (src->ms_x)
174      ctrl = 0x11;
175
176   /* 0/1 = CENTER/CORNER, 00/10 = POINT/BILINEAR */
177   BEGIN_NVC0(push, NVC0_2D(BLIT_CONTROL), 1);
178   PUSH_DATA (push, ctrl);
179   BEGIN_NVC0(push, NVC0_2D(BLIT_DST_X), 4);
180   PUSH_DATA (push, dx << dst->ms_x);
181   PUSH_DATA (push, dy << dst->ms_y);
182   PUSH_DATA (push, w << dst->ms_x);
183   PUSH_DATA (push, h << dst->ms_y);
184   BEGIN_NVC0(push, NVC0_2D(BLIT_DU_DX_FRACT), 4);
185   PUSH_DATA (push, duvdxy[2 + ((int)src->ms_x - (int)dst->ms_x)] & 0xf0000000);
186   PUSH_DATA (push, duvdxy[2 + ((int)src->ms_x - (int)dst->ms_x)] & 0x0000000f);
187   PUSH_DATA (push, duvdxy[2 + ((int)src->ms_y - (int)dst->ms_y)] & 0xf0000000);
188   PUSH_DATA (push, duvdxy[2 + ((int)src->ms_y - (int)dst->ms_y)] & 0x0000000f);
189   BEGIN_NVC0(push, NVC0_2D(BLIT_SRC_X_FRACT), 4);
190   PUSH_DATA (push, 0);
191   PUSH_DATA (push, sx << src->ms_x);
192   PUSH_DATA (push, 0);
193   PUSH_DATA (push, sy << src->ms_x);
194
195   return 0;
196}
197
198static void
199nvc0_resource_copy_region(struct pipe_context *pipe,
200                          struct pipe_resource *dst, unsigned dst_level,
201                          unsigned dstx, unsigned dsty, unsigned dstz,
202                          struct pipe_resource *src, unsigned src_level,
203                          const struct pipe_box *src_box)
204{
205   struct nvc0_context *nvc0 = nvc0_context(pipe);
206   int ret;
207   boolean m2mf;
208   unsigned dst_layer = dstz, src_layer = src_box->z;
209
210   /* Fallback for buffers. */
211   if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) {
212      util_resource_copy_region(pipe, dst, dst_level, dstx, dsty, dstz,
213                                src, src_level, src_box);
214      return;
215   }
216
217   assert(src->nr_samples == dst->nr_samples);
218
219   m2mf = (src->format == dst->format) ||
220      (util_format_get_blocksizebits(src->format) ==
221       util_format_get_blocksizebits(dst->format));
222
223   nv04_resource(dst)->status |= NOUVEAU_BUFFER_STATUS_GPU_WRITING;
224
225   if (m2mf) {
226      struct nv50_m2mf_rect drect, srect;
227      unsigned i;
228      unsigned nx = util_format_get_nblocksx(src->format, src_box->width);
229      unsigned ny = util_format_get_nblocksy(src->format, src_box->height);
230
231      nv50_m2mf_rect_setup(&drect, dst, dst_level, dstx, dsty, dstz);
232      nv50_m2mf_rect_setup(&srect, src, src_level,
233                           src_box->x, src_box->y, src_box->z);
234
235      for (i = 0; i < src_box->depth; ++i) {
236         nvc0->m2mf_copy_rect(nvc0, &drect, &srect, nx, ny);
237
238         if (nv50_miptree(dst)->layout_3d)
239            drect.z++;
240         else
241            drect.base += nv50_miptree(dst)->layer_stride;
242
243         if (nv50_miptree(src)->layout_3d)
244            srect.z++;
245         else
246            srect.base += nv50_miptree(src)->layer_stride;
247      }
248      return;
249   }
250
251   assert(nvc0_2d_format_faithful(src->format));
252   assert(nvc0_2d_format_faithful(dst->format));
253
254   BCTX_REFN(nvc0->bufctx, 2D, nv04_resource(src), RD);
255   BCTX_REFN(nvc0->bufctx, 2D, nv04_resource(dst), WR);
256   nouveau_pushbuf_bufctx(nvc0->base.pushbuf, nvc0->bufctx);
257   nouveau_pushbuf_validate(nvc0->base.pushbuf);
258
259   for (; dst_layer < dstz + src_box->depth; ++dst_layer, ++src_layer) {
260      ret = nvc0_2d_texture_do_copy(nvc0->base.pushbuf,
261                                    nv50_miptree(dst), dst_level,
262                                    dstx, dsty, dst_layer,
263                                    nv50_miptree(src), src_level,
264                                    src_box->x, src_box->y, src_layer,
265                                    src_box->width, src_box->height);
266      if (ret)
267         break;
268   }
269   nouveau_bufctx_reset(nvc0->bufctx, 0);
270}
271
272static void
273nvc0_clear_render_target(struct pipe_context *pipe,
274                         struct pipe_surface *dst,
275                         const union pipe_color_union *color,
276                         unsigned dstx, unsigned dsty,
277                         unsigned width, unsigned height)
278{
279   struct nvc0_context *nvc0 = nvc0_context(pipe);
280   struct nouveau_pushbuf *push = nvc0->base.pushbuf;
281   struct nv50_surface *sf = nv50_surface(dst);
282   struct nv04_resource *res = nv04_resource(sf->base.texture);
283   unsigned z;
284
285   BEGIN_NVC0(push, NVC0_3D(CLEAR_COLOR(0)), 4);
286   PUSH_DATAf(push, color->f[0]);
287   PUSH_DATAf(push, color->f[1]);
288   PUSH_DATAf(push, color->f[2]);
289   PUSH_DATAf(push, color->f[3]);
290
291   BEGIN_NVC0(push, NVC0_3D(SCREEN_SCISSOR_HORIZ), 2);
292   PUSH_DATA (push, ( width << 16) | dstx);
293   PUSH_DATA (push, (height << 16) | dsty);
294
295   BEGIN_NVC0(push, NVC0_3D(RT_CONTROL), 1);
296   PUSH_DATA (push, 1);
297   BEGIN_NVC0(push, NVC0_3D(RT_ADDRESS_HIGH(0)), 9);
298   PUSH_DATAh(push, res->address + sf->offset);
299   PUSH_DATA (push, res->address + sf->offset);
300   if (likely(nouveau_bo_memtype(res->bo))) {
301      struct nv50_miptree *mt = nv50_miptree(dst->texture);
302
303      PUSH_DATA(push, sf->width);
304      PUSH_DATA(push, sf->height);
305      PUSH_DATA(push, nvc0_format_table[dst->format].rt);
306      PUSH_DATA(push, (mt->layout_3d << 16) |
307               mt->level[sf->base.u.tex.level].tile_mode);
308      PUSH_DATA(push, dst->u.tex.first_layer + sf->depth);
309      PUSH_DATA(push, mt->layer_stride >> 2);
310      PUSH_DATA(push, dst->u.tex.first_layer);
311   } else {
312      if (res->base.target == PIPE_BUFFER) {
313         PUSH_DATA(push, 262144);
314         PUSH_DATA(push, 1);
315      } else {
316         PUSH_DATA(push, nv50_miptree(&res->base)->level[0].pitch);
317         PUSH_DATA(push, sf->height);
318      }
319      PUSH_DATA(push, nvc0_format_table[sf->base.format].rt);
320      PUSH_DATA(push, 1 << 12);
321      PUSH_DATA(push, 1);
322      PUSH_DATA(push, 0);
323      PUSH_DATA(push, 0);
324
325      IMMED_NVC0(push, NVC0_3D(ZETA_ENABLE), 0);
326
327      /* tiled textures don't have to be fenced, they're not mapped directly */
328      nvc0_resource_fence(res, NOUVEAU_BO_WR);
329   }
330
331   for (z = 0; z < sf->depth; ++z) {
332      BEGIN_NVC0(push, NVC0_3D(CLEAR_BUFFERS), 1);
333      PUSH_DATA (push, 0x3c |
334                 (z << NVC0_3D_CLEAR_BUFFERS_LAYER__SHIFT));
335   }
336
337   nvc0->dirty |= NVC0_NEW_FRAMEBUFFER;
338}
339
340static void
341nvc0_clear_depth_stencil(struct pipe_context *pipe,
342                         struct pipe_surface *dst,
343                         unsigned clear_flags,
344                         double depth,
345                         unsigned stencil,
346                         unsigned dstx, unsigned dsty,
347                         unsigned width, unsigned height)
348{
349	struct nvc0_context *nvc0 = nvc0_context(pipe);
350	struct nouveau_pushbuf *push = nvc0->base.pushbuf;
351	struct nv50_miptree *mt = nv50_miptree(dst->texture);
352	struct nv50_surface *sf = nv50_surface(dst);
353	uint32_t mode = 0;
354	int unk = mt->base.base.target == PIPE_TEXTURE_2D;
355	unsigned z;
356
357	if (clear_flags & PIPE_CLEAR_DEPTH) {
358		BEGIN_NVC0(push, NVC0_3D(CLEAR_DEPTH), 1);
359		PUSH_DATAf(push, depth);
360		mode |= NVC0_3D_CLEAR_BUFFERS_Z;
361	}
362
363	if (clear_flags & PIPE_CLEAR_STENCIL) {
364		BEGIN_NVC0(push, NVC0_3D(CLEAR_STENCIL), 1);
365		PUSH_DATA (push, stencil & 0xff);
366		mode |= NVC0_3D_CLEAR_BUFFERS_S;
367	}
368
369	BEGIN_NVC0(push, NVC0_3D(SCREEN_SCISSOR_HORIZ), 2);
370	PUSH_DATA (push, ( width << 16) | dstx);
371	PUSH_DATA (push, (height << 16) | dsty);
372
373	BEGIN_NVC0(push, NVC0_3D(ZETA_ADDRESS_HIGH), 5);
374	PUSH_DATAh(push, mt->base.address + sf->offset);
375	PUSH_DATA (push, mt->base.address + sf->offset);
376	PUSH_DATA (push, nvc0_format_table[dst->format].rt);
377	PUSH_DATA (push, mt->level[sf->base.u.tex.level].tile_mode);
378	PUSH_DATA (push, mt->layer_stride >> 2);
379	BEGIN_NVC0(push, NVC0_3D(ZETA_ENABLE), 1);
380	PUSH_DATA (push, 1);
381	BEGIN_NVC0(push, NVC0_3D(ZETA_HORIZ), 3);
382	PUSH_DATA (push, sf->width);
383	PUSH_DATA (push, sf->height);
384	PUSH_DATA (push, (unk << 16) | (dst->u.tex.first_layer + sf->depth));
385	BEGIN_NVC0(push, NVC0_3D(ZETA_BASE_LAYER), 1);
386	PUSH_DATA (push, dst->u.tex.first_layer);
387
388	for (z = 0; z < sf->depth; ++z) {
389		BEGIN_NVC0(push, NVC0_3D(CLEAR_BUFFERS), 1);
390		PUSH_DATA (push, mode |
391			   (z << NVC0_3D_CLEAR_BUFFERS_LAYER__SHIFT));
392	}
393
394	nvc0->dirty |= NVC0_NEW_FRAMEBUFFER;
395}
396
397void
398nvc0_clear(struct pipe_context *pipe, unsigned buffers,
399           const union pipe_color_union *color,
400           double depth, unsigned stencil)
401{
402   struct nvc0_context *nvc0 = nvc0_context(pipe);
403   struct nouveau_pushbuf *push = nvc0->base.pushbuf;
404   struct pipe_framebuffer_state *fb = &nvc0->framebuffer;
405   unsigned i;
406   uint32_t mode = 0;
407
408   /* don't need NEW_BLEND, COLOR_MASK doesn't affect CLEAR_BUFFERS */
409   if (!nvc0_state_validate(nvc0, NVC0_NEW_FRAMEBUFFER, 9 + (fb->nr_cbufs * 2)))
410      return;
411
412   if (buffers & PIPE_CLEAR_COLOR && fb->nr_cbufs) {
413      BEGIN_NVC0(push, NVC0_3D(CLEAR_COLOR(0)), 4);
414      PUSH_DATAf(push, color->f[0]);
415      PUSH_DATAf(push, color->f[1]);
416      PUSH_DATAf(push, color->f[2]);
417      PUSH_DATAf(push, color->f[3]);
418      mode =
419         NVC0_3D_CLEAR_BUFFERS_R | NVC0_3D_CLEAR_BUFFERS_G |
420         NVC0_3D_CLEAR_BUFFERS_B | NVC0_3D_CLEAR_BUFFERS_A;
421   }
422
423   if (buffers & PIPE_CLEAR_DEPTH) {
424      BEGIN_NVC0(push, NVC0_3D(CLEAR_DEPTH), 1);
425      PUSH_DATA (push, fui(depth));
426      mode |= NVC0_3D_CLEAR_BUFFERS_Z;
427   }
428
429   if (buffers & PIPE_CLEAR_STENCIL) {
430      BEGIN_NVC0(push, NVC0_3D(CLEAR_STENCIL), 1);
431      PUSH_DATA (push, stencil & 0xff);
432      mode |= NVC0_3D_CLEAR_BUFFERS_S;
433   }
434
435   BEGIN_NVC0(push, NVC0_3D(CLEAR_BUFFERS), 1);
436   PUSH_DATA (push, mode);
437
438   for (i = 1; i < fb->nr_cbufs; i++) {
439      BEGIN_NVC0(push, NVC0_3D(CLEAR_BUFFERS), 1);
440      PUSH_DATA (push, (i << 6) | 0x3c);
441   }
442}
443
444
445struct nvc0_blitctx
446{
447   struct nvc0_screen *screen;
448   struct {
449      struct pipe_framebuffer_state fb;
450      struct nvc0_program *vp;
451      struct nvc0_program *tcp;
452      struct nvc0_program *tep;
453      struct nvc0_program *gp;
454      struct nvc0_program *fp;
455      unsigned num_textures[5];
456      unsigned num_samplers[5];
457      struct pipe_sampler_view *texture;
458      struct nv50_tsc_entry *sampler;
459      unsigned dirty;
460   } saved;
461   struct nvc0_program vp;
462   struct nvc0_program fp;
463   struct nv50_tsc_entry sampler[2]; /* nearest, bilinear */
464   uint32_t fp_offset;
465   uint16_t color_mask;
466   uint8_t filter;
467};
468
469static void
470nvc0_blitctx_make_vp(struct nvc0_blitctx *blit)
471{
472   static const uint32_t code[] =
473   {
474      0xfff01c66, 0x06000080, /* vfetch b128 { $r0 $r1 $r2 $r3 } a[0x80] */
475      0xfff11c26, 0x06000090, /* vfetch b64 { $r4 $r5 } a[0x90]*/
476      0x03f01c66, 0x0a7e0070, /* export b128 o[0x70] { $r0 $r1 $r2 $r3 } */
477      0x13f01c26, 0x0a7e0080, /* export b64 o[0x80] { $r4 $r5 } */
478      0x00001de7, 0x80000000, /* exit */
479   };
480
481   blit->vp.type = PIPE_SHADER_VERTEX;
482   blit->vp.translated = TRUE;
483   blit->vp.code = (uint32_t *)code; /* no relocations -> no modification */
484   blit->vp.code_size = sizeof(code);
485   blit->vp.max_gpr = 6;
486   blit->vp.vp.edgeflag = PIPE_MAX_ATTRIBS;
487
488   blit->vp.hdr[0]  = 0x00020461; /* vertprog magic */
489   blit->vp.hdr[4]  = 0x000ff000; /* no outputs read */
490   blit->vp.hdr[6]  = 0x0000003f; /* a[0x80], a[0x90] */
491   blit->vp.hdr[13] = 0x0003f000; /* o[0x70], o[0x80] */
492}
493
494static void
495nvc0_blitctx_make_fp(struct nvc0_blitctx *blit)
496{
497   static const uint32_t code[] = /* use nvc0dis */
498   {
499      /* 2 coords RGBA in, RGBA out, also for Z32_FLOAT(_S8X24_UINT)
500       * NOTE:
501       * NVC0 doesn't like tex 3d on non-3d textures, but there should
502       * only be 2d and 2d-array MS resources anyway.
503       */
504      0xfff01c00, 0xc07e0080,
505      0xfff05c00, 0xc07e0084,
506      0x00001c86, 0x8013c000,
507      0x00001de7, 0x80000000,
508      /* size: 0x70 + padding  */
509      0, 0, 0, 0,
510
511      /* 2 coords ZS in, S encoded in R, Z encoded in GBA (8_UNORM)
512       * Setup float outputs in a way that conversion to UNORM yields the
513       * desired byte value.
514       */
515      /* NOTE: need to repeat header */
516      0x00021462, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
517      0x80000000, 0x0000000f, 0x00000000, 0x00000000, 0x00000000,
518      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
519      0x00000000, 0x00000000, 0x00000000, 0x0000000f, 0x00000000,
520      0xfff01c00, 0xc07e0080,
521      0xfff05c00, 0xc07e0084,
522      0x00001c86, 0x8010c000,
523      0xfc009c02, 0x312dffff,
524      0x05001c88,
525      0x09009e88,
526      0x04001c02, 0x30ee0202,
527      0xfc205c02, 0x38000003,
528      0x0020dc02, 0x3803fc00,
529      0x00209c02, 0x380003fc,
530      0x05005c88,
531      0x0d00dc88,
532      0x09209e04, 0x18000000,
533      0x04105c02, 0x30ee0202,
534      0x0430dc02, 0x30ce0202,
535      0x04209c02, 0x30de0202,
536      0x00001de7, 0x80000000,
537      /* size: 0xc8 + padding */
538      0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
539
540      /* 2 coords ZS in, Z encoded in RGB, S encoded in A (U8_UNORM) */
541      0x00021462, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
542      0x80000000, 0x0000000f, 0x00000000, 0x00000000, 0x00000000,
543      0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
544      0x00000000, 0x00000000, 0x00000000, 0x0000000f, 0x00000000,
545      0xfff01c00, 0xc07e0080,
546      0xfff05c00, 0xc07e0084,
547      0x00001c86, 0x8010c000,
548      0xfc009c02, 0x312dffff,
549      0x05081c88,
550      0x09009e88,
551      0x0430dc02, 0x30ee0202,
552      0xfc201c02, 0x38000003,
553      0x00205c02, 0x380003fc,
554      0x00209c02, 0x3803fc00,
555      0x01001c88,
556      0x05005c88,
557      0x09209e04, 0x18000000,
558      0x04001c02, 0x30ee0202,
559      0x04105c02, 0x30de0202,
560      0x04209c02, 0x30ce0202,
561      0x00001de7, 0x80000000,
562   };
563
564   blit->fp.type = PIPE_SHADER_FRAGMENT;
565   blit->fp.translated = TRUE;
566   blit->fp.code = (uint32_t *)code; /* const_cast */
567   blit->fp.code_size = sizeof(code);
568   blit->fp.max_gpr = 4;
569
570   blit->fp.hdr[0]  = 0x00021462; /* fragprog magic */
571   blit->fp.hdr[5]  = 0x80000000;
572   blit->fp.hdr[6]  = 0x0000000f; /* 2 linear */
573   blit->fp.hdr[18] = 0x0000000f; /* 1 colour output */
574}
575
576static void
577nvc0_blitctx_make_sampler(struct nvc0_blitctx *blit)
578{
579   /* clamp to edge, min/max lod = 0, nearest filtering */
580
581   blit->sampler[0].id = -1;
582
583   blit->sampler[0].tsc[0] = 0x00000092;
584   blit->sampler[0].tsc[1] = 0x00000051;
585
586   /* clamp to edge, min/max lod = 0, bilinear filtering */
587
588   blit->sampler[1].id = -1;
589
590   blit->sampler[1].tsc[0] = 0x00000092;
591   blit->sampler[1].tsc[1] = 0x00000062;
592}
593
594/* Since shaders cannot export stencil, we cannot copy stencil values when
595 * rendering to ZETA, so we attach the ZS surface to a colour render target.
596 */
597static INLINE enum pipe_format
598nvc0_blit_zeta_to_colour_format(enum pipe_format format)
599{
600   switch (format) {
601   case PIPE_FORMAT_Z16_UNORM:               return PIPE_FORMAT_R16_UNORM;
602   case PIPE_FORMAT_Z24_UNORM_S8_UINT:
603   case PIPE_FORMAT_S8_UINT_Z24_UNORM:
604   case PIPE_FORMAT_Z24X8_UNORM:             return PIPE_FORMAT_R8G8B8A8_UNORM;
605   case PIPE_FORMAT_Z32_FLOAT:               return PIPE_FORMAT_R32_FLOAT;
606   case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:    return PIPE_FORMAT_R32G32_FLOAT;
607   default:
608      assert(0);
609      return PIPE_FORMAT_NONE;
610   }
611}
612
613static void
614nvc0_blitctx_get_color_mask_and_fp(struct nvc0_blitctx *blit,
615                                   enum pipe_format format, uint8_t mask)
616{
617   blit->color_mask = 0;
618
619   switch (format) {
620   case PIPE_FORMAT_Z24X8_UNORM:
621   case PIPE_FORMAT_Z24_UNORM_S8_UINT:
622      blit->fp_offset = 0x180;
623      if (mask & PIPE_MASK_Z)
624         blit->color_mask |= 0x0111;
625      if (mask & PIPE_MASK_S)
626         blit->color_mask |= 0x1000;
627      break;
628   case PIPE_FORMAT_S8_UINT_Z24_UNORM:
629      blit->fp_offset = 0x80;
630      if (mask & PIPE_MASK_Z)
631         blit->color_mask |= 0x1110;
632      if (mask & PIPE_MASK_S)
633         blit->color_mask |= 0x0001;
634      break;
635   default:
636      blit->fp_offset = 0;
637      if (mask & (PIPE_MASK_R | PIPE_MASK_Z)) blit->color_mask |= 0x0001;
638      if (mask & (PIPE_MASK_G | PIPE_MASK_S)) blit->color_mask |= 0x0010;
639      if (mask & PIPE_MASK_B) blit->color_mask |= 0x0100;
640      if (mask & PIPE_MASK_A) blit->color_mask |= 0x1000;
641      break;
642   }
643}
644
645static void
646nvc0_blit_set_dst(struct nvc0_context *nvc0,
647                  struct pipe_resource *res, unsigned level, unsigned layer)
648{
649   struct pipe_context *pipe = &nvc0->base.pipe;
650   struct pipe_surface templ;
651
652   if (util_format_is_depth_or_stencil(res->format))
653      templ.format = nvc0_blit_zeta_to_colour_format(res->format);
654   else
655      templ.format = res->format;
656
657   templ.usage = PIPE_USAGE_STREAM;
658   templ.u.tex.level = level;
659   templ.u.tex.first_layer = templ.u.tex.last_layer = layer;
660
661   nvc0->framebuffer.cbufs[0] = nvc0_miptree_surface_new(pipe, res, &templ);
662   nvc0->framebuffer.nr_cbufs = 1;
663   nvc0->framebuffer.zsbuf = NULL;
664   nvc0->framebuffer.width = nvc0->framebuffer.cbufs[0]->width;
665   nvc0->framebuffer.height = nvc0->framebuffer.cbufs[0]->height;
666}
667
668static INLINE void
669nvc0_blit_fixup_tic_entry(struct pipe_sampler_view *view)
670{
671   struct nv50_tic_entry *ent = nv50_tic_entry(view);
672
673   ent->tic[2] &= ~(1 << 31); /* scaled coordinates, ok with 3d textures ? */
674
675   /* magic: */
676
677   ent->tic[3] = 0x20000000; /* affects quality of near vertical edges in MS8 */
678}
679
680static void
681nvc0_blit_set_src(struct nvc0_context *nvc0,
682                  struct pipe_resource *res, unsigned level, unsigned layer)
683{
684   struct pipe_context *pipe = &nvc0->base.pipe;
685   struct pipe_sampler_view templ;
686   int s;
687
688   templ.format = res->format;
689   templ.u.tex.first_layer = templ.u.tex.last_layer = layer;
690   templ.u.tex.first_level = templ.u.tex.last_level = level;
691   templ.swizzle_r = PIPE_SWIZZLE_RED;
692   templ.swizzle_g = PIPE_SWIZZLE_GREEN;
693   templ.swizzle_b = PIPE_SWIZZLE_BLUE;
694   templ.swizzle_a = PIPE_SWIZZLE_ALPHA;
695
696   nvc0->textures[4][0] = nvc0_create_sampler_view(pipe, res, &templ);
697
698   nvc0_blit_fixup_tic_entry(nvc0->textures[4][0]);
699
700   for (s = 0; s <= 3; ++s)
701      nvc0->num_textures[s] = 0;
702   nvc0->num_textures[4] = 1;
703}
704
705static void
706nvc0_blitctx_prepare_state(struct nvc0_blitctx *blit)
707{
708   struct nouveau_pushbuf *push = blit->screen->base.pushbuf;
709
710   /* TODO: maybe make this a MACRO (if we need more logic) ? */
711
712   /* blend state */
713   BEGIN_NVC0(push, NVC0_3D(COLOR_MASK(0)), 1);
714   PUSH_DATA (push, blit->color_mask);
715   BEGIN_NVC0(push, NVC0_3D(BLEND_ENABLE(0)), 1);
716   PUSH_DATA (push, 0);
717   IMMED_NVC0(push, NVC0_3D(LOGIC_OP_ENABLE), 0);
718
719   /* rasterizer state */
720   BEGIN_NVC0(push, NVC0_3D(FRAG_COLOR_CLAMP_EN), 1);
721   PUSH_DATA (push, 0);
722   IMMED_NVC0(push, NVC0_3D(MULTISAMPLE_ENABLE), 0);
723   BEGIN_NVC0(push, NVC0_3D(MSAA_MASK(0)), 4);
724   PUSH_DATA (push, 0xffff);
725   PUSH_DATA (push, 0xffff);
726   PUSH_DATA (push, 0xffff);
727   PUSH_DATA (push, 0xffff);
728   BEGIN_NVC0(push, NVC0_3D(MACRO_POLYGON_MODE_FRONT), 1);
729   PUSH_DATA (push, NVC0_3D_MACRO_POLYGON_MODE_FRONT_FILL);
730   BEGIN_NVC0(push, NVC0_3D(MACRO_POLYGON_MODE_BACK), 1);
731   PUSH_DATA (push, NVC0_3D_MACRO_POLYGON_MODE_BACK_FILL);
732   IMMED_NVC0(push, NVC0_3D(POLYGON_SMOOTH_ENABLE), 0);
733   IMMED_NVC0(push, NVC0_3D(POLYGON_OFFSET_FILL_ENABLE), 0);
734   IMMED_NVC0(push, NVC0_3D(POLYGON_STIPPLE_ENABLE), 0);
735   IMMED_NVC0(push, NVC0_3D(CULL_FACE_ENABLE), 0);
736
737   /* zsa state */
738   IMMED_NVC0(push, NVC0_3D(DEPTH_TEST_ENABLE), 0);
739   IMMED_NVC0(push, NVC0_3D(STENCIL_ENABLE), 0);
740   IMMED_NVC0(push, NVC0_3D(ALPHA_TEST_ENABLE), 0);
741
742   /* disable transform feedback */
743   IMMED_NVC0(push, NVC0_3D(TFB_ENABLE), 0);
744}
745
746static void
747nvc0_blitctx_pre_blit(struct nvc0_blitctx *blit, struct nvc0_context *nvc0)
748{
749   int s;
750
751   blit->saved.fb.width = nvc0->framebuffer.width;
752   blit->saved.fb.height = nvc0->framebuffer.height;
753   blit->saved.fb.nr_cbufs = nvc0->framebuffer.nr_cbufs;
754   blit->saved.fb.cbufs[0] = nvc0->framebuffer.cbufs[0];
755   blit->saved.fb.zsbuf = nvc0->framebuffer.zsbuf;
756
757   blit->saved.vp = nvc0->vertprog;
758   blit->saved.tcp = nvc0->tctlprog;
759   blit->saved.tep = nvc0->tevlprog;
760   blit->saved.gp = nvc0->gmtyprog;
761   blit->saved.fp = nvc0->fragprog;
762
763   nvc0->vertprog = &blit->vp;
764   nvc0->fragprog = &blit->fp;
765   nvc0->tctlprog = NULL;
766   nvc0->tevlprog = NULL;
767   nvc0->gmtyprog = NULL;
768
769   for (s = 0; s <= 4; ++s) {
770      blit->saved.num_textures[s] = nvc0->num_textures[s];
771      blit->saved.num_samplers[s] = nvc0->num_samplers[s];
772      nvc0->textures_dirty[s] = ~0;
773      nvc0->samplers_dirty[s] = ~0;
774   }
775   blit->saved.texture = nvc0->textures[4][0];
776   blit->saved.sampler = nvc0->samplers[4][0];
777
778   nvc0->samplers[4][0] = &blit->sampler[blit->filter];
779
780   for (s = 0; s <= 3; ++s)
781      nvc0->num_samplers[s] = 0;
782   nvc0->num_samplers[4] = 1;
783
784   blit->saved.dirty = nvc0->dirty;
785
786   nvc0->dirty = NVC0_NEW_FRAMEBUFFER |
787      NVC0_NEW_VERTPROG | NVC0_NEW_FRAGPROG |
788      NVC0_NEW_TCTLPROG | NVC0_NEW_TEVLPROG | NVC0_NEW_GMTYPROG |
789      NVC0_NEW_TEXTURES | NVC0_NEW_SAMPLERS;
790}
791
792static void
793nvc0_blitctx_post_blit(struct nvc0_context *nvc0, struct nvc0_blitctx *blit)
794{
795   int s;
796
797   pipe_surface_reference(&nvc0->framebuffer.cbufs[0], NULL);
798
799   nvc0->framebuffer.width = blit->saved.fb.width;
800   nvc0->framebuffer.height = blit->saved.fb.height;
801   nvc0->framebuffer.nr_cbufs = blit->saved.fb.nr_cbufs;
802   nvc0->framebuffer.cbufs[0] = blit->saved.fb.cbufs[0];
803   nvc0->framebuffer.zsbuf = blit->saved.fb.zsbuf;
804
805   nvc0->vertprog = blit->saved.vp;
806   nvc0->tctlprog = blit->saved.tcp;
807   nvc0->tevlprog = blit->saved.tep;
808   nvc0->gmtyprog = blit->saved.gp;
809   nvc0->fragprog = blit->saved.fp;
810
811   pipe_sampler_view_reference(&nvc0->textures[4][0], NULL);
812
813   for (s = 0; s <= 4; ++s) {
814      nvc0->num_textures[s] = blit->saved.num_textures[s];
815      nvc0->num_samplers[s] = blit->saved.num_samplers[s];
816      nvc0->textures_dirty[s] = ~0;
817      nvc0->samplers_dirty[s] = ~0;
818   }
819   nvc0->textures[4][0] = blit->saved.texture;
820   nvc0->samplers[4][0] = blit->saved.sampler;
821
822   nvc0->dirty = blit->saved.dirty |
823      (NVC0_NEW_FRAMEBUFFER | NVC0_NEW_SCISSOR | NVC0_NEW_SAMPLE_MASK |
824       NVC0_NEW_RASTERIZER | NVC0_NEW_ZSA | NVC0_NEW_BLEND |
825       NVC0_NEW_TEXTURES | NVC0_NEW_SAMPLERS |
826       NVC0_NEW_VERTPROG | NVC0_NEW_FRAGPROG |
827       NVC0_NEW_TCTLPROG | NVC0_NEW_TEVLPROG | NVC0_NEW_GMTYPROG |
828       NVC0_NEW_TFB_TARGETS);
829}
830
831static void
832nvc0_resource_resolve(struct pipe_context *pipe,
833                      const struct pipe_resolve_info *info)
834{
835   struct nvc0_context *nvc0 = nvc0_context(pipe);
836   struct nvc0_screen *screen = nvc0->screen;
837   struct nvc0_blitctx *blit = screen->blitctx;
838   struct nouveau_pushbuf *push = screen->base.pushbuf;
839   struct pipe_resource *src = info->src.res;
840   struct pipe_resource *dst = info->dst.res;
841   float x0, x1, y0, y1;
842   float x_range, y_range;
843
844   /* Would need more shader variants or, better, just change the TIC target.
845    * But no API creates 3D MS textures ...
846    */
847   if (src->target == PIPE_TEXTURE_3D)
848      return;
849
850   nvc0_blitctx_get_color_mask_and_fp(blit, dst->format, info->mask);
851
852   blit->filter = util_format_is_depth_or_stencil(dst->format) ? 0 : 1;
853
854   nvc0_blitctx_pre_blit(blit, nvc0);
855
856   nvc0_blit_set_dst(nvc0, dst, info->dst.level, info->dst.layer);
857   nvc0_blit_set_src(nvc0, src, 0,               info->src.layer);
858
859   nvc0_blitctx_prepare_state(blit);
860
861   nvc0_state_validate(nvc0, ~0, 36);
862
863   x_range =
864      (float)(info->src.x1 - info->src.x0) /
865      (float)(info->dst.x1 - info->dst.x0);
866   y_range =
867      (float)(info->src.y1 - info->src.y0) /
868      (float)(info->dst.y1 - info->dst.y0);
869
870   x0 = (float)info->src.x0 - x_range * (float)info->dst.x0;
871   y0 = (float)info->src.y0 - y_range * (float)info->dst.y0;
872
873   x1 = x0 + 16384.0f * x_range;
874   y1 = y0 + 16384.0f * y_range;
875
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);
880
881   BEGIN_NVC0(push, NVC0_3D(SP_START_ID(5)), 1);
882   PUSH_DATA (push,
883              blit->fp.code_base + blit->fp_offset);
884
885   IMMED_NVC0(push, NVC0_3D(VIEWPORT_TRANSFORM_EN), 0);
886
887   /* Draw a large triangle in screen coordinates covering the whole
888    * render target, with scissors defining the destination region.
889    * The vertex is supplied with non-normalized texture coordinates
890    * arranged in a way to yield the desired offset and scale.
891    */
892
893   BEGIN_NVC0(push, NVC0_3D(SCISSOR_HORIZ(0)), 2);
894   PUSH_DATA (push, (info->dst.x1 << 16) | info->dst.x0);
895   PUSH_DATA (push, (info->dst.y1 << 16) | info->dst.y0);
896
897   IMMED_NVC0(push, NVC0_3D(VERTEX_BEGIN_GL),
898              NVC0_3D_VERTEX_BEGIN_GL_PRIMITIVE_TRIANGLES);
899
900   BEGIN_NVC0(push, NVC0_3D(VTX_ATTR_DEFINE), 3);
901   PUSH_DATA (push, 0x74201);
902   PUSH_DATAf(push, x0);
903   PUSH_DATAf(push, y0);
904   BEGIN_NVC0(push, NVC0_3D(VTX_ATTR_DEFINE), 3);
905   PUSH_DATA (push, 0x74200);
906   PUSH_DATAf(push, 0.0f);
907   PUSH_DATAf(push, 0.0f);
908   BEGIN_NVC0(push, NVC0_3D(VTX_ATTR_DEFINE), 3);
909   PUSH_DATA (push, 0x74201);
910   PUSH_DATAf(push, x1);
911   PUSH_DATAf(push, y0);
912   BEGIN_NVC0(push, NVC0_3D(VTX_ATTR_DEFINE), 3);
913   PUSH_DATA (push, 0x74200);
914   PUSH_DATAf(push, 16384 << nv50_miptree(dst)->ms_x);
915   PUSH_DATAf(push, 0.0f);
916   BEGIN_NVC0(push, NVC0_3D(VTX_ATTR_DEFINE), 3);
917   PUSH_DATA (push, 0x74201);
918   PUSH_DATAf(push, x0);
919   PUSH_DATAf(push, y1);
920   BEGIN_NVC0(push, NVC0_3D(VTX_ATTR_DEFINE), 3);
921   PUSH_DATA (push, 0x74200);
922   PUSH_DATAf(push, 0.0f);
923   PUSH_DATAf(push, 16384 << nv50_miptree(dst)->ms_y);
924
925   IMMED_NVC0(push, NVC0_3D(VERTEX_END_GL), 0);
926
927   /* re-enable normally constant state */
928
929   IMMED_NVC0(push, NVC0_3D(VIEWPORT_TRANSFORM_EN), 1);
930
931   nvc0_blitctx_post_blit(nvc0, blit);
932}
933
934boolean
935nvc0_blitctx_create(struct nvc0_screen *screen)
936{
937   screen->blitctx = CALLOC_STRUCT(nvc0_blitctx);
938   if (!screen->blitctx) {
939      NOUVEAU_ERR("failed to allocate blit context\n");
940      return FALSE;
941   }
942
943   screen->blitctx->screen = screen;
944
945   nvc0_blitctx_make_vp(screen->blitctx);
946   nvc0_blitctx_make_fp(screen->blitctx);
947
948   nvc0_blitctx_make_sampler(screen->blitctx);
949
950   screen->blitctx->color_mask = 0x1111;
951
952   return TRUE;
953}
954
955
956void
957nvc0_init_surface_functions(struct nvc0_context *nvc0)
958{
959   struct pipe_context *pipe = &nvc0->base.pipe;
960
961   pipe->resource_copy_region = nvc0_resource_copy_region;
962   pipe->resource_resolve = nvc0_resource_resolve;
963   pipe->clear_render_target = nvc0_clear_render_target;
964   pipe->clear_depth_stencil = nvc0_clear_depth_stencil;
965}
966
967