summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/nouveau/nv50/nv50_blit.h
blob: de490af455796b06f2f4b3f4b6cd52284957249a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230

#ifndef __NV50_BLIT_H__
#define __NV50_BLIT_H__

#include "util/u_inlines.h"
#include "util/u_format.h"

void *
nv50_blitter_make_fp(struct pipe_context *,
                     unsigned mode,
                     enum pipe_texture_target);

unsigned
nv50_blit_select_mode(const struct pipe_blit_info *);

/* Converted to a pipe->blit. */
void
nv50_resource_resolve(struct pipe_context *, const struct pipe_resolve_info *);

#define NV50_BLIT_MODE_PASS  0 /* pass through TEX $t0/$s0 output */
#define NV50_BLIT_MODE_Z24S8 1 /* encode ZS values for RGBA unorm8 */
#define NV50_BLIT_MODE_S8Z24 2
#define NV50_BLIT_MODE_X24S8 3
#define NV50_BLIT_MODE_S8X24 4
#define NV50_BLIT_MODE_Z24X8 5
#define NV50_BLIT_MODE_X8Z24 6
#define NV50_BLIT_MODE_ZS    7 /* put $t0/$s0 into R, $t1/$s1 into G */
#define NV50_BLIT_MODE_XS    8 /* put $t1/$s1 into G */
#define NV50_BLIT_MODES      9

/* CUBE and RECT textures are reinterpreted as 2D(_ARRAY) */
#define NV50_BLIT_TEXTURE_BUFFER    0
#define NV50_BLIT_TEXTURE_1D        1
#define NV50_BLIT_TEXTURE_2D        2
#define NV50_BLIT_TEXTURE_3D        3
#define NV50_BLIT_TEXTURE_1D_ARRAY  4
#define NV50_BLIT_TEXTURE_2D_ARRAY  5
#define NV50_BLIT_MAX_TEXTURE_TYPES 6

static INLINE unsigned
nv50_blit_texture_type(enum pipe_texture_target target)
{
   switch (target) {
   case PIPE_TEXTURE_1D: return NV50_BLIT_TEXTURE_1D;
   case PIPE_TEXTURE_2D: return NV50_BLIT_TEXTURE_2D;
   case PIPE_TEXTURE_3D: return NV50_BLIT_TEXTURE_3D;
   case PIPE_TEXTURE_1D_ARRAY: return NV50_BLIT_TEXTURE_1D_ARRAY;
   case PIPE_TEXTURE_2D_ARRAY: return NV50_BLIT_TEXTURE_2D_ARRAY;
   default:
      assert(target == PIPE_BUFFER);
      return NV50_BLIT_TEXTURE_BUFFER;
   }
}

static INLINE unsigned
nv50_blit_get_tgsi_texture_target(enum pipe_texture_target target)
{
   switch (target) {
   case PIPE_TEXTURE_1D: return TGSI_TEXTURE_1D;
   case PIPE_TEXTURE_2D: return TGSI_TEXTURE_2D;
   case PIPE_TEXTURE_3D: return TGSI_TEXTURE_3D;
   case PIPE_TEXTURE_1D_ARRAY: return TGSI_TEXTURE_1D_ARRAY;
   case PIPE_TEXTURE_2D_ARRAY: return TGSI_TEXTURE_2D_ARRAY;
   default:
      assert(target == PIPE_BUFFER);
      return TGSI_TEXTURE_BUFFER;
   }
}

static INLINE enum pipe_texture_target
nv50_blit_reinterpret_pipe_texture_target(enum pipe_texture_target target)
{
   switch (target) {
   case PIPE_TEXTURE_CUBE:
   case PIPE_TEXTURE_CUBE_ARRAY:
      return PIPE_TEXTURE_2D_ARRAY;
   case PIPE_TEXTURE_RECT:
      return PIPE_TEXTURE_2D;
   default:
      return target;
   }
}

static INLINE unsigned
nv50_blit_get_filter(const struct pipe_blit_info *info)
{
   if (info->dst.resource->nr_samples < info->src.resource->nr_samples)
      return util_format_is_depth_or_stencil(info->src.format) ? 0 : 1;

   if (info->filter != PIPE_TEX_FILTER_LINEAR)
      return 0;

   if ((info->dst.box.width ==  info->src.box.width ||
        info->dst.box.width == -info->src.box.width) &&
       (info->dst.box.height ==  info->src.box.height ||
        info->dst.box.height == -info->src.box.height))
      return 0;

   return 1;
}

/* Since shaders cannot export stencil, we cannot copy stencil values when
 * rendering to ZETA, so we attach the ZS surface to a colour render target.
 */
static INLINE enum pipe_format
nv50_blit_zeta_to_colour_format(enum pipe_format format)
{
   switch (format) {
   case PIPE_FORMAT_Z16_UNORM:
      return PIPE_FORMAT_R16_UNORM;
   case PIPE_FORMAT_Z24_UNORM_S8_UINT:
   case PIPE_FORMAT_S8_UINT_Z24_UNORM:
   case PIPE_FORMAT_Z24X8_UNORM:
   case PIPE_FORMAT_X8Z24_UNORM:
   case PIPE_FORMAT_X24S8_UINT:
   case PIPE_FORMAT_S8X24_UINT:
      return PIPE_FORMAT_R8G8B8A8_UNORM;
   case PIPE_FORMAT_Z32_FLOAT:
      return PIPE_FORMAT_R32_FLOAT;
   case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
   case PIPE_FORMAT_X32_S8X24_UINT:
      return PIPE_FORMAT_R32G32_FLOAT;
   default:
      assert(0);
      return PIPE_FORMAT_NONE;
   }
}


static INLINE uint16_t
nv50_blit_derive_color_mask(const struct pipe_blit_info *info)
{
   const unsigned mask = info->mask;

   uint16_t color_mask = 0;

   switch (info->dst.format) {
   case PIPE_FORMAT_Z24X8_UNORM:
   case PIPE_FORMAT_X24S8_UINT:
   case PIPE_FORMAT_Z24_UNORM_S8_UINT:
      if (mask & PIPE_MASK_S)
         color_mask |= 0x1000;
      if (mask & PIPE_MASK_Z)
         color_mask |= 0x0111;
      break;
   case PIPE_FORMAT_X8Z24_UNORM:
   case PIPE_FORMAT_S8X24_UINT:
   case PIPE_FORMAT_S8_UINT_Z24_UNORM:
      if (mask & PIPE_MASK_S)
         color_mask |= 0x0001;
      if (mask & PIPE_MASK_Z)
         color_mask |= 0x1110;
      break;
   default:
      if (mask & (PIPE_MASK_R | PIPE_MASK_Z)) color_mask |= 0x0001;
      if (mask & (PIPE_MASK_G | PIPE_MASK_S)) color_mask |= 0x0010;
      if (mask & PIPE_MASK_B) color_mask |= 0x0100;
      if (mask & PIPE_MASK_A) color_mask |= 0x1000;
      break;
   }

   return color_mask;
}

static INLINE uint32_t
nv50_blit_eng2d_get_mask(const struct pipe_blit_info *info)
{
   uint32_t mask = 0;

   switch (info->dst.format) {
   case PIPE_FORMAT_Z24X8_UNORM:
   case PIPE_FORMAT_X24S8_UINT:
   case PIPE_FORMAT_Z24_UNORM_S8_UINT:
      if (info->mask & PIPE_MASK_Z) mask |= 0x00ffffff;
      if (info->mask & PIPE_MASK_S) mask |= 0xff000000;
      break;
   case PIPE_FORMAT_X8Z24_UNORM:
   case PIPE_FORMAT_S8X24_UINT:
   case PIPE_FORMAT_S8_UINT_Z24_UNORM:
      if (info->mask & PIPE_MASK_Z) mask |= 0xffffff00;
      if (info->mask & PIPE_MASK_S) mask |= 0x000000ff;
      break;
   default:
      mask = 0xffffffff;
      break;
   }
   return mask;
}

#if NOUVEAU_DRIVER == 0xc0
# define nv50_format_table nvc0_format_table
#endif

/* return true for formats that can be converted among each other by NVC0_2D */
static INLINE bool
nv50_2d_dst_format_faithful(enum pipe_format format)
{
   const uint64_t mask =
       NV50_ENG2D_SUPPORTED_FORMATS &
      ~NV50_ENG2D_NOCONVERT_FORMATS;
   uint8_t id = nv50_format_table[format].rt;
   return (id >= 0xc0) && (mask & (1ULL << (id - 0xc0)));
}
static INLINE bool
nv50_2d_src_format_faithful(enum pipe_format format)
{
   const uint64_t mask =
      NV50_ENG2D_SUPPORTED_FORMATS &
    ~(NV50_ENG2D_LUMINANCE_FORMATS | NV50_ENG2D_INTENSITY_FORMATS);
   uint8_t id = nv50_format_table[format].rt;
   return (id >= 0xc0) && (mask & (1ULL << (id - 0xc0)));
}

static INLINE bool
nv50_2d_format_supported(enum pipe_format format)
{
   uint8_t id = nv50_format_table[format].rt;
   return (id >= 0xc0) &&
      (NV50_ENG2D_SUPPORTED_FORMATS & (1ULL << (id - 0xc0)));
}

static INLINE bool
nv50_2d_dst_format_ops_supported(enum pipe_format format)
{
   uint8_t id = nv50_format_table[format].rt;
   return (id >= 0xc0) &&
      (NV50_ENG2D_OPERATION_FORMATS & (1ULL << (id - 0xc0)));
}

#endif /* __NV50_BLIT_H__ */