~ubuntu-branches/ubuntu/precise/mesa/precise-updates

« back to all changes in this revision

Viewing changes to src/gallium/drivers/nvc0/nvc0_miptree.c

  • Committer: Package Import Robot
  • Author(s): Robert Hooker
  • Date: 2012-02-02 12:05:48 UTC
  • mfrom: (1.7.1) (3.3.27 sid)
  • Revision ID: package-import@ubuntu.com-20120202120548-nvkma85jq0h4coix
Tags: 8.0~rc2-0ubuntu4
Drop drisearchdir handling, it is no longer needed with multiarch
and dri-alternates being removed.

Show diffs side-by-side

added added

removed removed

Lines of Context:
27
27
 
28
28
#include "nvc0_context.h"
29
29
#include "nvc0_resource.h"
30
 
#include "nvc0_transfer.h"
31
30
 
32
 
static INLINE uint32_t
33
 
get_tile_dims(unsigned nx, unsigned ny, unsigned nz)
 
31
uint32_t
 
32
nvc0_tex_choose_tile_dims(unsigned nx, unsigned ny, unsigned nz)
34
33
{
35
34
   uint32_t tile_mode = 0x000;
36
35
 
57
56
   return tile_mode | 0x100;
58
57
}
59
58
 
60
 
uint32_t
61
 
nvc0_miptree_zslice_offset(struct nvc0_miptree *mt, unsigned l, unsigned z)
62
 
{
63
 
   unsigned nblocksy; /* height of texture level aligned to tile height */
64
 
 
65
 
   unsigned stride_2d; /* to next slice within a 3D tile */
66
 
   unsigned stride_3d; /* to slice in the next (in z direction !) 3D tile */
67
 
 
68
 
   unsigned tile_d_shift = NVC0_TILE_DIM_SHIFT(mt->level[l].tile_mode, 2);
69
 
   unsigned tile_d = 1 << tile_d_shift;
70
 
 
71
 
   nblocksy = util_format_get_nblocksy(mt->base.base.format,
72
 
                                       u_minify(mt->base.base.height0, l));
73
 
 
74
 
   nblocksy = align(nblocksy, NVC0_TILE_HEIGHT(mt->level[l].tile_mode));
75
 
 
76
 
   stride_2d = NVC0_TILE_SIZE_2D(mt->level[l].tile_mode);
77
 
 
78
 
   stride_3d = (nblocksy * mt->level[l].pitch) << tile_d_shift;
79
 
 
80
 
   return (z & (tile_d - 1)) * stride_2d + (z >> tile_d_shift) * stride_3d;
81
 
}
82
 
 
83
 
static void
84
 
nvc0_miptree_destroy(struct pipe_screen *pscreen, struct pipe_resource *pt)
85
 
{
86
 
   struct nvc0_miptree *mt = nvc0_miptree(pt);
87
 
 
88
 
   nouveau_screen_bo_release(pscreen, mt->base.bo);
89
 
 
90
 
   FREE(mt);
91
 
}
92
 
 
93
 
static boolean
94
 
nvc0_miptree_get_handle(struct pipe_screen *pscreen,
95
 
                        struct pipe_resource *pt,
96
 
                        struct winsys_handle *whandle)
97
 
{
98
 
   struct nvc0_miptree *mt = nvc0_miptree(pt);
99
 
   unsigned stride;
100
 
 
101
 
   if (!mt || !mt->base.bo)
 
59
static uint32_t
 
60
nvc0_mt_choose_storage_type(struct nv50_miptree *mt, boolean compressed)
 
61
{
 
62
   const unsigned ms = util_logbase2(mt->base.base.nr_samples);
 
63
 
 
64
   uint32_t tile_flags;
 
65
 
 
66
   compressed = FALSE; /* not yet supported */
 
67
 
 
68
   if (mt->base.base.bind & PIPE_BIND_CURSOR)
 
69
      return NOUVEAU_BO_TILE_SCANOUT;
 
70
 
 
71
   switch (mt->base.base.format) {
 
72
   case PIPE_FORMAT_Z16_UNORM:
 
73
      if (compressed)
 
74
         tile_flags = 0x0200 + (ms << 8);
 
75
      else
 
76
         tile_flags = 0x0100;
 
77
      break;
 
78
   case PIPE_FORMAT_S8_UINT_Z24_UNORM:
 
79
      if (compressed)
 
80
         tile_flags = 0x5100 + (ms << 8);
 
81
      else
 
82
         tile_flags = 0x4600;
 
83
      break;
 
84
   case PIPE_FORMAT_Z24X8_UNORM:
 
85
   case PIPE_FORMAT_Z24_UNORM_S8_UINT:
 
86
      if (compressed)
 
87
         tile_flags = 0x1700 + (ms << 8);
 
88
      else
 
89
         tile_flags = 0x1100;
 
90
      break;
 
91
   case PIPE_FORMAT_Z32_FLOAT:
 
92
      if (compressed)
 
93
         tile_flags = 0x8600 + (ms << 8);
 
94
      else
 
95
         tile_flags = 0x7b00;
 
96
      break;
 
97
   case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
 
98
      if (compressed)
 
99
         tile_flags = 0xce00 + (ms << 8);
 
100
      else
 
101
         tile_flags = 0xc300;
 
102
      break;
 
103
   default:
 
104
      switch (util_format_get_blocksizebits(mt->base.base.format)) {
 
105
      case 128:
 
106
         if (compressed)
 
107
            tile_flags = 0xf400 + (ms << 9);
 
108
         else
 
109
            tile_flags = 0xfe00;
 
110
         break;
 
111
      case 64:
 
112
         if (compressed) {
 
113
            switch (ms) {
 
114
            case 0: tile_flags = 0xe600; break;
 
115
            case 1: tile_flags = 0xeb00; break;
 
116
            case 2: tile_flags = 0xed00; break;
 
117
            case 3: tile_flags = 0xf200; break;
 
118
            default:
 
119
               return 0;
 
120
            }
 
121
         } else {
 
122
            tile_flags = 0xfe00;
 
123
         }
 
124
         break;
 
125
      case 32:
 
126
         if (compressed) {
 
127
            switch (ms) {
 
128
            case 0: tile_flags = 0xdb00; break;
 
129
            case 1: tile_flags = 0xdd00; break;
 
130
            case 2: tile_flags = 0xdf00; break;
 
131
            case 3: tile_flags = 0xe400; break;
 
132
            default:
 
133
               return 0;
 
134
            }
 
135
         } else {
 
136
            tile_flags = 0xfe00;
 
137
         }
 
138
         break;
 
139
      case 16:
 
140
      case 8:
 
141
         tile_flags = 0xfe00;
 
142
         break;
 
143
      default:
 
144
         return 0;
 
145
      }
 
146
      break;
 
147
   }
 
148
 
 
149
   if (mt->base.base.bind & PIPE_BIND_SCANOUT)
 
150
      tile_flags |= NOUVEAU_BO_TILE_SCANOUT;
 
151
 
 
152
   if (unlikely(mt->base.base.flags & NOUVEAU_RESOURCE_FLAG_LINEAR))
 
153
      tile_flags &= ~0xff00;
 
154
 
 
155
   return tile_flags;
 
156
}
 
157
 
 
158
static INLINE boolean
 
159
nvc0_miptree_init_ms_mode(struct nv50_miptree *mt)
 
160
{
 
161
   switch (mt->base.base.nr_samples) {
 
162
   case 8:
 
163
      mt->ms_mode = NVC0_3D_MULTISAMPLE_MODE_MS8;
 
164
      mt->ms_x = 2;
 
165
      mt->ms_y = 1;
 
166
      break;
 
167
   case 4:
 
168
      mt->ms_mode = NVC0_3D_MULTISAMPLE_MODE_MS4;
 
169
      mt->ms_x = 1;
 
170
      mt->ms_y = 1;
 
171
      break;
 
172
   case 2:
 
173
      mt->ms_mode = NVC0_3D_MULTISAMPLE_MODE_MS2;
 
174
      mt->ms_x = 1;
 
175
      break;
 
176
   case 1:
 
177
   case 0:
 
178
      mt->ms_mode = NVC0_3D_MULTISAMPLE_MODE_MS1;
 
179
      break;
 
180
   default:
 
181
      NOUVEAU_ERR("invalid nr_samples: %u\n", mt->base.base.nr_samples);
102
182
      return FALSE;
103
 
 
104
 
   stride = util_format_get_stride(mt->base.base.format,
105
 
                                   mt->base.base.width0);
106
 
 
107
 
   return nouveau_screen_bo_get_handle(pscreen,
108
 
                                       mt->base.bo,
109
 
                                       stride,
110
 
                                       whandle);
 
183
   }
 
184
   return TRUE;
 
185
}
 
186
 
 
187
boolean
 
188
nv50_miptree_init_layout_linear(struct nv50_miptree *);
 
189
 
 
190
static void
 
191
nvc0_miptree_init_layout_video(struct nv50_miptree *mt)
 
192
{
 
193
   const struct pipe_resource *pt = &mt->base.base;
 
194
   const unsigned blocksize = util_format_get_blocksize(pt->format);
 
195
 
 
196
   unsigned nbx = util_format_get_nblocksx(pt->format, pt->width0);
 
197
   unsigned nby = util_format_get_nblocksy(pt->format, pt->height0);
 
198
 
 
199
   assert(pt->last_level == 0);
 
200
   assert(mt->ms_x == 0 &&
 
201
          mt->ms_y == 0);
 
202
   assert(!util_format_is_compressed(pt->format));
 
203
 
 
204
   assert(nby > 8);
 
205
   mt->level[0].tile_mode = 0x10;
 
206
   mt->level[0].pitch = align(nbx * blocksize, 64);
 
207
   mt->total_size = align(nby, 16) * mt->level[0].pitch;
 
208
 
 
209
   if (pt->array_size > 1) {
 
210
      mt->layer_stride = align(mt->total_size, NVC0_TILE_SIZE(0x10));
 
211
      mt->total_size = mt->layer_stride * pt->array_size;
 
212
   }
 
213
}
 
214
 
 
215
static void
 
216
nvc0_miptree_init_layout_tiled(struct nv50_miptree *mt)
 
217
{
 
218
   struct pipe_resource *pt = &mt->base.base;
 
219
   unsigned w, h, d, l;
 
220
   const unsigned blocksize = util_format_get_blocksize(pt->format);
 
221
 
 
222
   mt->layout_3d = pt->target == PIPE_TEXTURE_3D;
 
223
 
 
224
   w = pt->width0 << mt->ms_x;
 
225
   h = pt->height0 << mt->ms_y;
 
226
 
 
227
   /* For 3D textures, a mipmap is spanned by all the layers, for array
 
228
    * textures and cube maps, each layer contains its own mipmaps.
 
229
    */
 
230
   d = mt->layout_3d ? pt->depth0 : 1;
 
231
 
 
232
   for (l = 0; l <= pt->last_level; ++l) {
 
233
      struct nv50_miptree_level *lvl = &mt->level[l];
 
234
      unsigned tsx, tsy, tsz;
 
235
      unsigned nbx = util_format_get_nblocksx(pt->format, w);
 
236
      unsigned nby = util_format_get_nblocksy(pt->format, h);
 
237
 
 
238
      lvl->offset = mt->total_size;
 
239
 
 
240
      lvl->tile_mode = nvc0_tex_choose_tile_dims(nbx, nby, d);
 
241
 
 
242
      tsx = NVC0_TILE_SIZE_X(lvl->tile_mode); /* x is tile row pitch in bytes */
 
243
      tsy = NVC0_TILE_SIZE_Y(lvl->tile_mode);
 
244
      tsz = NVC0_TILE_SIZE_Z(lvl->tile_mode);
 
245
 
 
246
      lvl->pitch = align(nbx * blocksize, tsx);
 
247
 
 
248
      mt->total_size += lvl->pitch * align(nby, tsy) * align(d, tsz);
 
249
 
 
250
      w = u_minify(w, 1);
 
251
      h = u_minify(h, 1);
 
252
      d = u_minify(d, 1);
 
253
   }
 
254
 
 
255
   if (pt->array_size > 1) {
 
256
      mt->layer_stride = align(mt->total_size,
 
257
                               NVC0_TILE_SIZE(mt->level[0].tile_mode));
 
258
      mt->total_size = mt->layer_stride * pt->array_size;
 
259
   }
111
260
}
112
261
 
113
262
const struct u_resource_vtbl nvc0_miptree_vtbl =
114
263
{
115
 
   nvc0_miptree_get_handle,         /* get_handle */
116
 
   nvc0_miptree_destroy,            /* resource_destroy */
 
264
   nv50_miptree_get_handle,         /* get_handle */
 
265
   nv50_miptree_destroy,            /* resource_destroy */
117
266
   nvc0_miptree_transfer_new,       /* get_transfer */
118
267
   nvc0_miptree_transfer_del,       /* transfer_destroy */
119
 
   nvc0_miptree_transfer_map,         /* transfer_map */
 
268
   nvc0_miptree_transfer_map,       /* transfer_map */
120
269
   u_default_transfer_flush_region, /* transfer_flush_region */
121
270
   nvc0_miptree_transfer_unmap,     /* transfer_unmap */
122
271
   u_default_transfer_inline_write  /* transfer_inline_write */
127
276
                    const struct pipe_resource *templ)
128
277
{
129
278
   struct nouveau_device *dev = nouveau_screen(pscreen)->device;
130
 
   struct nvc0_miptree *mt = CALLOC_STRUCT(nvc0_miptree);
 
279
   struct nv50_miptree *mt = CALLOC_STRUCT(nv50_miptree);
131
280
   struct pipe_resource *pt = &mt->base.base;
132
281
   int ret;
133
 
   unsigned w, h, d, l, alloc_size;
134
282
   uint32_t tile_flags;
135
283
 
136
284
   if (!mt)
141
289
   pipe_reference_init(&pt->reference, 1);
142
290
   pt->screen = pscreen;
143
291
 
144
 
   mt->layout_3d = pt->target == PIPE_TEXTURE_3D;
145
 
 
146
 
   w = pt->width0;
147
 
   h = pt->height0;
148
 
   d = mt->layout_3d ? pt->depth0 : 1;
149
 
 
150
 
   switch (pt->format) {
151
 
   case PIPE_FORMAT_Z16_UNORM:
152
 
      tile_flags = 0x0700; /* COMPRESSED */
153
 
      tile_flags = 0x0100; /* NORMAL */
154
 
      break;
155
 
   case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
156
 
      tile_flags = 0x5300; /* MSAA 4, COMPRESSED */
157
 
      tile_flags = 0x4600; /* NORMAL */
158
 
      break;
159
 
   case PIPE_FORMAT_Z24X8_UNORM:
160
 
   case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
161
 
      tile_flags = 0x1100; /* NORMAL */
162
 
      if (w * h >= 128 * 128 && 0)
163
 
         tile_flags = 0x1700; /* COMPRESSED, requires magic */
164
 
      break;
165
 
   case PIPE_FORMAT_R32G32B32A32_FLOAT:
166
 
      tile_flags = 0xf500; /* COMPRESSED */
167
 
      tile_flags = 0xf700; /* MSAA 2 */
168
 
      tile_flags = 0xf900; /* MSAA 4 */
169
 
      tile_flags = 0xfe00; /* NORMAL */
170
 
      break;
171
 
   case PIPE_FORMAT_Z32_FLOAT:
172
 
      tile_flags = 0x7b00;
173
 
      break;
174
 
   case PIPE_FORMAT_Z32_FLOAT_S8X24_USCALED:
175
 
      tile_flags = 0xce00; /* COMPRESSED */
176
 
      tile_flags = 0xcf00; /* MSAA 2, COMPRESSED */
177
 
      tile_flags = 0xd000; /* MSAA 4, COMPRESSED */
178
 
      tile_flags = 0xc300; /* NORMAL */
179
 
      break;
180
 
   case PIPE_FORMAT_R16G16B16A16_UNORM:
181
 
      tile_flags = 0xe900; /* COMPRESSED */
182
 
      tile_flags = 0xfe00; /* NORMAL */
183
 
      break;
184
 
   default:
185
 
      tile_flags = 0xe000; /* MSAA 4, COMPRESSED 32 BIT */
186
 
      tile_flags = 0xfe00; /* NORMAL 32 BIT */
187
 
      if (w * h >= 128 * 128 && 0)
188
 
         tile_flags = 0xdb00; /* COMPRESSED 32 BIT, requires magic */
189
 
      break;
190
 
   }
191
 
 
192
 
   /* For 3D textures, a mipmap is spanned by all the layers, for array
193
 
    * textures and cube maps, each layer contains its own mipmaps.
194
 
    */
195
 
   for (l = 0; l <= pt->last_level; ++l) {
196
 
      struct nvc0_miptree_level *lvl = &mt->level[l];
197
 
      unsigned nbx = util_format_get_nblocksx(pt->format, w);
198
 
      unsigned nby = util_format_get_nblocksy(pt->format, h);
199
 
      unsigned blocksize = util_format_get_blocksize(pt->format);
200
 
 
201
 
      lvl->offset = mt->total_size;
202
 
      lvl->tile_mode = get_tile_dims(nbx, nby, d);
203
 
      lvl->pitch = align(nbx * blocksize, NVC0_TILE_PITCH(lvl->tile_mode));
204
 
 
205
 
      mt->total_size += lvl->pitch *
206
 
         align(nby, NVC0_TILE_HEIGHT(lvl->tile_mode)) *
207
 
         align(d, NVC0_TILE_DEPTH(lvl->tile_mode));
208
 
 
209
 
      w = u_minify(w, 1);
210
 
      h = u_minify(h, 1);
211
 
      d = u_minify(d, 1);
212
 
   }
213
 
 
214
 
   if (pt->array_size > 1) {
215
 
      mt->layer_stride = align(mt->total_size,
216
 
                               NVC0_TILE_SIZE(mt->level[0].tile_mode));
217
 
      mt->total_size = mt->layer_stride * pt->array_size;
218
 
   }
219
 
 
220
 
   alloc_size = mt->total_size;
221
 
   if (tile_flags == 0x1700)
222
 
      alloc_size *= 3; /* HiZ, XXX: correct size */
223
 
 
224
 
   ret = nouveau_bo_new_tile(dev, NOUVEAU_BO_VRAM, 256, alloc_size,
 
292
   tile_flags = nvc0_mt_choose_storage_type(mt, TRUE);
 
293
 
 
294
   if (!nvc0_miptree_init_ms_mode(mt)) {
 
295
      FREE(mt);
 
296
      return NULL;
 
297
   }
 
298
 
 
299
   if (unlikely(pt->flags & NVC0_RESOURCE_FLAG_VIDEO)) {
 
300
      nvc0_miptree_init_layout_video(mt);
 
301
   } else
 
302
   if (tile_flags & NOUVEAU_BO_TILE_LAYOUT_MASK) {
 
303
      nvc0_miptree_init_layout_tiled(mt);
 
304
   } else
 
305
   if (!nv50_miptree_init_layout_linear(mt)) {
 
306
      FREE(mt);
 
307
      return NULL;
 
308
   }
 
309
 
 
310
   ret = nouveau_bo_new_tile(dev, NOUVEAU_BO_VRAM, 4096,
 
311
                             mt->total_size,
225
312
                             mt->level[0].tile_mode, tile_flags,
226
313
                             &mt->base.bo);
227
314
   if (ret) {
233
320
   return pt;
234
321
}
235
322
 
236
 
struct pipe_resource *
237
 
nvc0_miptree_from_handle(struct pipe_screen *pscreen,
238
 
                         const struct pipe_resource *templ,
239
 
                         struct winsys_handle *whandle)
 
323
/* Offset of zslice @z from start of level @l. */
 
324
INLINE unsigned
 
325
nvc0_mt_zslice_offset(const struct nv50_miptree *mt, unsigned l, unsigned z)
240
326
{
241
 
   struct nvc0_miptree *mt;
242
 
   unsigned stride;
243
 
 
244
 
   /* only supports 2D, non-mipmapped textures for the moment */
245
 
   if ((templ->target != PIPE_TEXTURE_2D &&
246
 
        templ->target != PIPE_TEXTURE_RECT) ||
247
 
       templ->last_level != 0 ||
248
 
       templ->depth0 != 1 ||
249
 
       templ->array_size > 1)
250
 
      return NULL;
251
 
 
252
 
   mt = CALLOC_STRUCT(nvc0_miptree);
253
 
   if (!mt)
254
 
      return NULL;
255
 
 
256
 
   mt->base.bo = nouveau_screen_bo_from_handle(pscreen, whandle, &stride);
257
 
   if (mt->base.bo == NULL) {
258
 
      FREE(mt);
259
 
      return NULL;
260
 
   }
261
 
 
262
 
   mt->base.base = *templ;
263
 
   mt->base.vtbl = &nvc0_miptree_vtbl;
264
 
   pipe_reference_init(&mt->base.base.reference, 1);
265
 
   mt->base.base.screen = pscreen;
266
 
   mt->level[0].pitch = stride;
267
 
   mt->level[0].offset = 0;
268
 
   mt->level[0].tile_mode = mt->base.bo->tile_mode;
269
 
 
270
 
   /* no need to adjust bo reference count */
271
 
   return &mt->base.base;
 
327
   const struct pipe_resource *pt = &mt->base.base;
 
328
 
 
329
   unsigned tds = NVC0_TILE_SHIFT_Z(mt->level[l].tile_mode);
 
330
   unsigned ths = NVC0_TILE_SHIFT_Y(mt->level[l].tile_mode);
 
331
 
 
332
   unsigned nby = util_format_get_nblocksy(pt->format,
 
333
                                           u_minify(pt->height0, l));
 
334
 
 
335
   /* to next 2D tile slice within a 3D tile */
 
336
   unsigned stride_2d = NVC0_TILE_SIZE_2D(mt->level[l].tile_mode);
 
337
 
 
338
   /* to slice in the next (in z direction) 3D tile */
 
339
   unsigned stride_3d = (align(nby, (1 << ths)) * mt->level[l].pitch) << tds;
 
340
 
 
341
   return (z & (1 << (tds - 1))) * stride_2d + (z >> tds) * stride_3d;
272
342
}
273
343
 
274
 
 
275
344
/* Surface functions.
276
345
 */
277
346
 
280
349
                         struct pipe_resource *pt,
281
350
                         const struct pipe_surface *templ)
282
351
{
283
 
   struct nvc0_miptree *mt = nvc0_miptree(pt); /* guaranteed */
284
 
   struct nvc0_surface *ns;
285
 
   struct pipe_surface *ps;
286
 
   struct nvc0_miptree_level *lvl = &mt->level[templ->u.tex.level];
287
 
 
288
 
   ns = CALLOC_STRUCT(nvc0_surface);
 
352
   struct nv50_surface *ns = nv50_surface_from_miptree(nv50_miptree(pt), templ);
289
353
   if (!ns)
290
354
      return NULL;
291
 
   ps = &ns->base;
292
 
 
293
 
   pipe_reference_init(&ps->reference, 1);
294
 
   pipe_resource_reference(&ps->texture, pt);
295
 
   ps->context = pipe;
296
 
   ps->format = templ->format;
297
 
   ps->usage = templ->usage;
298
 
   ps->u.tex.level = templ->u.tex.level;
299
 
   ps->u.tex.first_layer = templ->u.tex.first_layer;
300
 
   ps->u.tex.last_layer = templ->u.tex.last_layer;
301
 
 
302
 
   ns->width = u_minify(pt->width0, ps->u.tex.level);
303
 
   ns->height = u_minify(pt->height0, ps->u.tex.level);
304
 
   ns->depth = ps->u.tex.last_layer - ps->u.tex.first_layer + 1;
305
 
   ns->offset = lvl->offset;
306
 
 
307
 
   /* comment says there are going to be removed, but they're used by the st */
308
 
   ps->width = ns->width;
309
 
   ps->height = ns->height;
310
 
 
311
 
   return ps;
312
 
}
313
 
 
314
 
void
315
 
nvc0_miptree_surface_del(struct pipe_context *pipe, struct pipe_surface *ps)
316
 
{
317
 
   struct nvc0_surface *s = nvc0_surface(ps);
318
 
 
319
 
   pipe_resource_reference(&ps->texture, NULL);
320
 
 
321
 
   FREE(s);
 
355
   ns->base.context = pipe;
 
356
   return &ns->base;
322
357
}