nouveau: use bool instead of boolean
[mesa.git] / src / gallium / drivers / nouveau / nv30 / nv30_miptree.c
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 = align(util_format_get_nblocksx(pt->format, box->width) *
246 util_format_get_blocksize(pt->format), 64);
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 }