Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
5564 serge 1
/*
2
 * Copyright 2012 Red Hat Inc.
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 OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20
 * OTHER DEALINGS IN THE SOFTWARE.
21
 *
22
 * Authors: Ben Skeggs
23
 *
24
 */
25
 
26
#include "util/u_format.h"
27
#include "util/u_inlines.h"
28
#include "util/u_surface.h"
29
 
30
#include "nv_m2mf.xml.h"
31
#include "nv30/nv30_screen.h"
32
#include "nv30/nv30_context.h"
33
#include "nv30/nv30_resource.h"
34
#include "nv30/nv30_transfer.h"
35
 
36
static INLINE unsigned
37
layer_offset(struct pipe_resource *pt, unsigned level, unsigned layer)
38
{
39
   struct nv30_miptree *mt = nv30_miptree(pt);
40
   struct nv30_miptree_level *lvl = &mt->level[level];
41
 
42
   if (pt->target == PIPE_TEXTURE_CUBE)
43
      return (layer * mt->layer_size) + lvl->offset;
44
 
45
   return lvl->offset + (layer * lvl->zslice_size);
46
}
47
 
48
static boolean
49
nv30_miptree_get_handle(struct pipe_screen *pscreen,
50
                        struct pipe_resource *pt,
51
                        struct winsys_handle *handle)
52
{
53
   struct nv30_miptree *mt = nv30_miptree(pt);
54
   unsigned stride;
55
 
56
   if (!mt || !mt->base.bo)
57
      return FALSE;
58
 
59
   stride = mt->level[0].pitch;
60
 
61
   return nouveau_screen_bo_get_handle(pscreen, mt->base.bo, stride, handle);
62
}
63
 
64
static void
65
nv30_miptree_destroy(struct pipe_screen *pscreen, struct pipe_resource *pt)
66
{
67
   struct nv30_miptree *mt = nv30_miptree(pt);
68
 
69
   nouveau_bo_ref(NULL, &mt->base.bo);
70
   FREE(mt);
71
}
72
 
73
struct nv30_transfer {
74
   struct pipe_transfer base;
75
   struct nv30_rect img;
76
   struct nv30_rect tmp;
77
   unsigned nblocksx;
78
   unsigned nblocksy;
79
};
80
 
81
static INLINE struct nv30_transfer *
82
nv30_transfer(struct pipe_transfer *ptx)
83
{
84
   return (struct nv30_transfer *)ptx;
85
}
86
 
87
static INLINE void
88
define_rect(struct pipe_resource *pt, unsigned level, unsigned z,
89
            unsigned x, unsigned y, unsigned w, unsigned h,
90
            struct nv30_rect *rect)
91
{
92
   struct nv30_miptree *mt = nv30_miptree(pt);
93
   struct nv30_miptree_level *lvl = &mt->level[level];
94
 
95
   rect->w = u_minify(pt->width0, level) << mt->ms_x;
96
   rect->w = util_format_get_nblocksx(pt->format, rect->w);
97
   rect->h = u_minify(pt->height0, level) << mt->ms_y;
98
   rect->h = util_format_get_nblocksy(pt->format, rect->h);
99
   rect->d = 1;
100
   rect->z = 0;
101
   if (mt->swizzled) {
102
      if (pt->target == PIPE_TEXTURE_3D) {
103
         rect->d = u_minify(pt->depth0, level);
104
         rect->z = z; z = 0;
105
      }
106
      rect->pitch = 0;
107
   } else {
108
      rect->pitch = lvl->pitch;
109
   }
110
 
111
   rect->bo     = mt->base.bo;
112
   rect->domain = NOUVEAU_BO_VRAM;
113
   rect->offset = layer_offset(pt, level, z);
114
   rect->cpp    = util_format_get_blocksize(pt->format);
115
 
116
   rect->x0     = util_format_get_nblocksx(pt->format, x) << mt->ms_x;
117
   rect->y0     = util_format_get_nblocksy(pt->format, y) << mt->ms_y;
118
   rect->x1     = rect->x0 + (w << mt->ms_x);
119
   rect->y1     = rect->y0 + (h << mt->ms_y);
120
}
121
 
122
void
123
nv30_resource_copy_region(struct pipe_context *pipe,
124
                          struct pipe_resource *dstres, unsigned dst_level,
125
                          unsigned dstx, unsigned dsty, unsigned dstz,
126
                          struct pipe_resource *srcres, unsigned src_level,
127
                          const struct pipe_box *src_box)
128
{
129
   struct nv30_context *nv30 = nv30_context(pipe);
130
   struct nv30_rect src, dst;
131
 
132
   if (dstres->target == PIPE_BUFFER && srcres->target == PIPE_BUFFER) {
133
      nouveau_copy_buffer(&nv30->base,
134
                          nv04_resource(dstres), dstx,
135
                          nv04_resource(srcres), src_box->x, src_box->width);
136
      return;
137
   }
138
 
139
   define_rect(srcres, src_level, src_box->z, src_box->x, src_box->y,
140
                       src_box->width, src_box->height, &src);
141
   define_rect(dstres, dst_level, dstz, dstx, dsty,
142
                       src_box->width, src_box->height, &dst);
143
 
144
   nv30_transfer_rect(nv30, NEAREST, &src, &dst);
145
}
146
 
147
void
148
nv30_resource_resolve(struct pipe_context *pipe,
149
                      const struct pipe_resolve_info *info)
150
{
151
#if 0
152
   struct nv30_context *nv30 = nv30_context(pipe);
153
   struct nv30_rect src, dst;
154
 
155
   define_rect(info->src.res, 0, 0, info->src.x0, info->src.y0,
156
               info->src.x1 - info->src.x0, info->src.y1 - info->src.y0, &src);
157
   define_rect(info->dst.res, info->dst.level, 0, info->dst.x0, info->dst.y0,
158
               info->dst.x1 - info->dst.x0, info->dst.y1 - info->dst.y0, &dst);
159
 
160
   nv30_transfer_rect(nv30, BILINEAR, &src, &dst);
161
#endif
162
}
163
 
164
void
165
nv30_blit(struct pipe_context *pipe,
166
          const struct pipe_blit_info *blit_info)
167
{
168
   struct nv30_context *nv30 = nv30_context(pipe);
169
   struct pipe_blit_info info = *blit_info;
170
 
171
   if (info.src.resource->nr_samples > 1 &&
172
       info.dst.resource->nr_samples <= 1 &&
173
       !util_format_is_depth_or_stencil(info.src.resource->format) &&
174
       !util_format_is_pure_integer(info.src.resource->format)) {
175
      debug_printf("nv30: color resolve unimplemented\n");
176
      return;
177
   }
178
 
179
   if (util_try_blit_via_copy_region(pipe, &info)) {
180
      return; /* done */
181
   }
182
 
183
   if (info.mask & PIPE_MASK_S) {
184
      debug_printf("nv30: cannot blit stencil, skipping\n");
185
      info.mask &= ~PIPE_MASK_S;
186
   }
187
 
188
   if (!util_blitter_is_blit_supported(nv30->blitter, &info)) {
189
      debug_printf("nv30: blit unsupported %s -> %s\n",
190
                   util_format_short_name(info.src.resource->format),
191
                   util_format_short_name(info.dst.resource->format));
192
      return;
193
   }
194
 
195
   /* XXX turn off occlusion queries */
196
 
197
   util_blitter_save_vertex_buffer_slot(nv30->blitter, nv30->vtxbuf);
198
   util_blitter_save_vertex_elements(nv30->blitter, nv30->vertex);
199
   util_blitter_save_vertex_shader(nv30->blitter, nv30->vertprog.program);
200
   util_blitter_save_rasterizer(nv30->blitter, nv30->rast);
201
   util_blitter_save_viewport(nv30->blitter, &nv30->viewport);
202
   util_blitter_save_scissor(nv30->blitter, &nv30->scissor);
203
   util_blitter_save_fragment_shader(nv30->blitter, nv30->fragprog.program);
204
   util_blitter_save_blend(nv30->blitter, nv30->blend);
205
   util_blitter_save_depth_stencil_alpha(nv30->blitter,
206
                                         nv30->zsa);
207
   util_blitter_save_stencil_ref(nv30->blitter, &nv30->stencil_ref);
208
   util_blitter_save_sample_mask(nv30->blitter, nv30->sample_mask);
209
   util_blitter_save_framebuffer(nv30->blitter, &nv30->framebuffer);
210
   util_blitter_save_fragment_sampler_states(nv30->blitter,
211
                     nv30->fragprog.num_samplers,
212
                     (void**)nv30->fragprog.samplers);
213
   util_blitter_save_fragment_sampler_views(nv30->blitter,
214
                     nv30->fragprog.num_textures, nv30->fragprog.textures);
215
   util_blitter_save_render_condition(nv30->blitter, nv30->render_cond_query,
216
                                      nv30->render_cond_cond, nv30->render_cond_mode);
217
   util_blitter_blit(nv30->blitter, &info);
218
}
219
 
220
void
221
nv30_flush_resource(struct pipe_context *pipe,
222
                    struct pipe_resource *resource)
223
{
224
}
225
 
226
static void *
227
nv30_miptree_transfer_map(struct pipe_context *pipe, struct pipe_resource *pt,
228
                          unsigned level, unsigned usage,
229
                          const struct pipe_box *box,
230
                          struct pipe_transfer **ptransfer)
231
{
232
   struct nv30_context *nv30 = nv30_context(pipe);
233
   struct nouveau_device *dev = nv30->screen->base.device;
234
   struct nv30_transfer *tx;
235
   unsigned access = 0;
236
   int ret;
237
 
238
   tx = CALLOC_STRUCT(nv30_transfer);
239
   if (!tx)
240
      return NULL;
241
   pipe_resource_reference(&tx->base.resource, pt);
242
   tx->base.level = level;
243
   tx->base.usage = usage;
244
   tx->base.box = *box;
245
   tx->base.stride = util_format_get_nblocksx(pt->format, box->width) *
246
                     util_format_get_blocksize(pt->format);
247
   tx->base.layer_stride = util_format_get_nblocksy(pt->format, box->height) *
248
                           tx->base.stride;
249
 
250
   tx->nblocksx = util_format_get_nblocksx(pt->format, box->width);
251
   tx->nblocksy = util_format_get_nblocksy(pt->format, box->height);
252
 
253
   define_rect(pt, level, box->z, box->x, box->y,
254
                   tx->nblocksx, tx->nblocksy, &tx->img);
255
 
256
   ret = nouveau_bo_new(dev, NOUVEAU_BO_GART | NOUVEAU_BO_MAP, 0,
257
                        tx->base.layer_stride, NULL, &tx->tmp.bo);
258
   if (ret) {
259
      pipe_resource_reference(&tx->base.resource, NULL);
260
      FREE(tx);
261
      return NULL;
262
   }
263
 
264
   tx->tmp.domain = NOUVEAU_BO_GART;
265
   tx->tmp.offset = 0;
266
   tx->tmp.pitch  = tx->base.stride;
267
   tx->tmp.cpp    = tx->img.cpp;
268
   tx->tmp.w      = tx->nblocksx;
269
   tx->tmp.h      = tx->nblocksy;
270
   tx->tmp.d      = 1;
271
   tx->tmp.x0     = 0;
272
   tx->tmp.y0     = 0;
273
   tx->tmp.x1     = tx->tmp.w;
274
   tx->tmp.y1     = tx->tmp.h;
275
   tx->tmp.z      = 0;
276
 
277
   if (usage & PIPE_TRANSFER_READ)
278
      nv30_transfer_rect(nv30, NEAREST, &tx->img, &tx->tmp);
279
 
280
   if (tx->tmp.bo->map) {
281
      *ptransfer = &tx->base;
282
      return tx->tmp.bo->map;
283
   }
284
 
285
   if (usage & PIPE_TRANSFER_READ)
286
      access |= NOUVEAU_BO_RD;
287
   if (usage & PIPE_TRANSFER_WRITE)
288
      access |= NOUVEAU_BO_WR;
289
 
290
   ret = nouveau_bo_map(tx->tmp.bo, access, nv30->base.client);
291
   if (ret) {
292
      pipe_resource_reference(&tx->base.resource, NULL);
293
      FREE(tx);
294
      return NULL;
295
   }
296
 
297
   *ptransfer = &tx->base;
298
   return tx->tmp.bo->map;
299
}
300
 
301
static void
302
nv30_miptree_transfer_unmap(struct pipe_context *pipe,
303
                            struct pipe_transfer *ptx)
304
{
305
   struct nv30_context *nv30 = nv30_context(pipe);
306
   struct nv30_transfer *tx = nv30_transfer(ptx);
307
 
308
   if (ptx->usage & PIPE_TRANSFER_WRITE)
309
      nv30_transfer_rect(nv30, NEAREST, &tx->tmp, &tx->img);
310
 
311
   nouveau_bo_ref(NULL, &tx->tmp.bo);
312
   pipe_resource_reference(&ptx->resource, NULL);
313
   FREE(tx);
314
}
315
 
316
const struct u_resource_vtbl nv30_miptree_vtbl = {
317
   nv30_miptree_get_handle,
318
   nv30_miptree_destroy,
319
   nv30_miptree_transfer_map,
320
   u_default_transfer_flush_region,
321
   nv30_miptree_transfer_unmap,
322
   u_default_transfer_inline_write
323
};
324
 
325
struct pipe_resource *
326
nv30_miptree_create(struct pipe_screen *pscreen,
327
                    const struct pipe_resource *tmpl)
328
{
329
   struct nouveau_device *dev = nouveau_screen(pscreen)->device;
330
   struct nv30_miptree *mt = CALLOC_STRUCT(nv30_miptree);
331
   struct pipe_resource *pt = &mt->base.base;
332
   unsigned blocksz, size;
333
   unsigned w, h, d, l;
334
   int ret;
335
 
336
   switch (tmpl->nr_samples) {
337
   case 4:
338
      mt->ms_mode = 0x00004000;
339
      mt->ms_x = 1;
340
      mt->ms_y = 1;
341
      break;
342
   case 2:
343
      mt->ms_mode = 0x00003000;
344
      mt->ms_x = 1;
345
      mt->ms_y = 0;
346
      break;
347
   default:
348
      mt->ms_mode = 0x00000000;
349
      mt->ms_x = 0;
350
      mt->ms_y = 0;
351
      break;
352
   }
353
 
354
   mt->base.vtbl = &nv30_miptree_vtbl;
355
   *pt = *tmpl;
356
   pipe_reference_init(&pt->reference, 1);
357
   pt->screen = pscreen;
358
 
359
   w = pt->width0 << mt->ms_x;
360
   h = pt->height0 << mt->ms_y;
361
   d = (pt->target == PIPE_TEXTURE_3D) ? pt->depth0 : 1;
362
   blocksz = util_format_get_blocksize(pt->format);
363
 
364
   if ((pt->target == PIPE_TEXTURE_RECT) ||
365
       !util_is_power_of_two(pt->width0) ||
366
       !util_is_power_of_two(pt->height0) ||
367
       !util_is_power_of_two(pt->depth0) ||
368
       util_format_is_compressed(pt->format) ||
369
       util_format_is_float(pt->format) || mt->ms_mode) {
370
      mt->uniform_pitch = util_format_get_nblocksx(pt->format, w) * blocksz;
371
      mt->uniform_pitch = align(mt->uniform_pitch, 64);
372
   }
373
 
374
   if (!mt->uniform_pitch)
375
      mt->swizzled = TRUE;
376
 
377
   size = 0;
378
   for (l = 0; l <= pt->last_level; l++) {
379
      struct nv30_miptree_level *lvl = &mt->level[l];
380
      unsigned nbx = util_format_get_nblocksx(pt->format, w);
381
      unsigned nby = util_format_get_nblocksx(pt->format, h);
382
 
383
      lvl->offset = size;
384
      lvl->pitch  = mt->uniform_pitch;
385
      if (!lvl->pitch)
386
         lvl->pitch = nbx * blocksz;
387
 
388
      lvl->zslice_size = lvl->pitch * nby;
389
      size += lvl->zslice_size * d;
390
 
391
      w = u_minify(w, 1);
392
      h = u_minify(h, 1);
393
      d = u_minify(d, 1);
394
   }
395
 
396
   mt->layer_size = size;
397
   if (pt->target == PIPE_TEXTURE_CUBE) {
398
      if (!mt->uniform_pitch)
399
         mt->layer_size = align(mt->layer_size, 128);
400
      size = mt->layer_size * 6;
401
   }
402
 
403
   ret = nouveau_bo_new(dev, NOUVEAU_BO_VRAM, 256, size, NULL, &mt->base.bo);
404
   if (ret) {
405
      FREE(mt);
406
      return NULL;
407
   }
408
 
409
   mt->base.domain = NOUVEAU_BO_VRAM;
410
   return &mt->base.base;
411
}
412
 
413
struct pipe_resource *
414
nv30_miptree_from_handle(struct pipe_screen *pscreen,
415
                         const struct pipe_resource *tmpl,
416
                         struct winsys_handle *handle)
417
{
418
   struct nv30_miptree *mt;
419
   unsigned stride;
420
 
421
   /* only supports 2D, non-mipmapped textures for the moment */
422
   if ((tmpl->target != PIPE_TEXTURE_2D &&
423
        tmpl->target != PIPE_TEXTURE_RECT) ||
424
       tmpl->last_level != 0 ||
425
       tmpl->depth0 != 1 ||
426
       tmpl->array_size > 1)
427
      return NULL;
428
 
429
   mt = CALLOC_STRUCT(nv30_miptree);
430
   if (!mt)
431
      return NULL;
432
 
433
   mt->base.bo = nouveau_screen_bo_from_handle(pscreen, handle, &stride);
434
   if (mt->base.bo == NULL) {
435
      FREE(mt);
436
      return NULL;
437
   }
438
 
439
   mt->base.base = *tmpl;
440
   mt->base.vtbl = &nv30_miptree_vtbl;
441
   pipe_reference_init(&mt->base.base.reference, 1);
442
   mt->base.base.screen = pscreen;
443
   mt->uniform_pitch = stride;
444
   mt->level[0].pitch = mt->uniform_pitch;
445
   mt->level[0].offset = 0;
446
 
447
   /* no need to adjust bo reference count */
448
   return &mt->base.base;
449
}
450
 
451
struct pipe_surface *
452
nv30_miptree_surface_new(struct pipe_context *pipe,
453
                         struct pipe_resource *pt,
454
                         const struct pipe_surface *tmpl)
455
{
456
   struct nv30_miptree *mt = nv30_miptree(pt); /* guaranteed */
457
   struct nv30_surface *ns;
458
   struct pipe_surface *ps;
459
   struct nv30_miptree_level *lvl = &mt->level[tmpl->u.tex.level];
460
 
461
   ns = CALLOC_STRUCT(nv30_surface);
462
   if (!ns)
463
      return NULL;
464
   ps = &ns->base;
465
 
466
   pipe_reference_init(&ps->reference, 1);
467
   pipe_resource_reference(&ps->texture, pt);
468
   ps->context = pipe;
469
   ps->format = tmpl->format;
470
   ps->u.tex.level = tmpl->u.tex.level;
471
   ps->u.tex.first_layer = tmpl->u.tex.first_layer;
472
   ps->u.tex.last_layer = tmpl->u.tex.last_layer;
473
 
474
   ns->width = u_minify(pt->width0, ps->u.tex.level);
475
   ns->height = u_minify(pt->height0, ps->u.tex.level);
476
   ns->depth = ps->u.tex.last_layer - ps->u.tex.first_layer + 1;
477
   ns->offset = layer_offset(pt, ps->u.tex.level, ps->u.tex.first_layer);
478
   if (mt->swizzled)
479
      ns->pitch = 4096; /* random, just something the hw won't reject.. */
480
   else
481
      ns->pitch = lvl->pitch;
482
 
483
   /* comment says there are going to be removed, but they're used by the st */
484
   ps->width = ns->width;
485
   ps->height = ns->height;
486
   return ps;
487
}
488
 
489
void
490
nv30_miptree_surface_del(struct pipe_context *pipe, struct pipe_surface *ps)
491
{
492
   struct nv30_surface *ns = nv30_surface(ps);
493
 
494
   pipe_resource_reference(&ps->texture, NULL);
495
   FREE(ns);
496
}