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