2 * Copyright 2012 Red Hat Inc.
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
26 #include "util/u_format.h"
27 #include "util/u_inlines.h"
28 #include "util/u_surface.h"
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"
36 static INLINE
unsigned
37 layer_offset(struct pipe_resource
*pt
, unsigned level
, unsigned layer
)
39 struct nv30_miptree
*mt
= nv30_miptree(pt
);
40 struct nv30_miptree_level
*lvl
= &mt
->level
[level
];
42 if (pt
->target
== PIPE_TEXTURE_CUBE
)
43 return (layer
* mt
->layer_size
) + lvl
->offset
;
45 return lvl
->offset
+ (layer
* lvl
->zslice_size
);
49 nv30_miptree_get_handle(struct pipe_screen
*pscreen
,
50 struct pipe_resource
*pt
,
51 struct winsys_handle
*handle
)
53 struct nv30_miptree
*mt
= nv30_miptree(pt
);
56 if (!mt
|| !mt
->base
.bo
)
59 stride
= mt
->level
[0].pitch
;
61 return nouveau_screen_bo_get_handle(pscreen
, mt
->base
.bo
, stride
, handle
);
65 nv30_miptree_destroy(struct pipe_screen
*pscreen
, struct pipe_resource
*pt
)
67 struct nv30_miptree
*mt
= nv30_miptree(pt
);
69 nouveau_bo_ref(NULL
, &mt
->base
.bo
);
73 struct nv30_transfer
{
74 struct pipe_transfer base
;
81 static INLINE
struct nv30_transfer
*
82 nv30_transfer(struct pipe_transfer
*ptx
)
84 return (struct nv30_transfer
*)ptx
;
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
)
92 struct nv30_miptree
*mt
= nv30_miptree(pt
);
93 struct nv30_miptree_level
*lvl
= &mt
->level
[level
];
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
);
102 if (pt
->target
== PIPE_TEXTURE_3D
) {
103 rect
->d
= u_minify(pt
->depth0
, level
);
108 rect
->pitch
= lvl
->pitch
;
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
);
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
);
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
)
129 struct nv30_context
*nv30
= nv30_context(pipe
);
130 struct nv30_rect src
, dst
;
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
);
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
);
144 nv30_transfer_rect(nv30
, NEAREST
, &src
, &dst
);
148 nv30_resource_resolve(struct pipe_context
*pipe
,
149 const struct pipe_resolve_info
*info
)
152 struct nv30_context
*nv30
= nv30_context(pipe
);
153 struct nv30_rect src
, dst
;
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
);
160 nv30_transfer_rect(nv30
, BILINEAR
, &src
, &dst
);
165 nv30_blit(struct pipe_context
*pipe
,
166 const struct pipe_blit_info
*blit_info
)
168 struct nv30_context
*nv30
= nv30_context(pipe
);
169 struct pipe_blit_info info
= *blit_info
;
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");
179 if (util_try_blit_via_copy_region(pipe
, &info
)) {
183 if (info
.mask
& PIPE_MASK_S
) {
184 debug_printf("nv30: cannot blit stencil, skipping\n");
185 info
.mask
&= ~PIPE_MASK_S
;
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
));
195 /* XXX turn off occlusion queries */
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
,
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
);
221 nv30_flush_resource(struct pipe_context
*pipe
,
222 struct pipe_resource
*resource
)
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
)
232 struct nv30_context
*nv30
= nv30_context(pipe
);
233 struct nouveau_device
*dev
= nv30
->screen
->base
.device
;
234 struct nv30_transfer
*tx
;
238 tx
= CALLOC_STRUCT(nv30_transfer
);
241 pipe_resource_reference(&tx
->base
.resource
, pt
);
242 tx
->base
.level
= level
;
243 tx
->base
.usage
= usage
;
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
) *
250 tx
->nblocksx
= util_format_get_nblocksx(pt
->format
, box
->width
);
251 tx
->nblocksy
= util_format_get_nblocksy(pt
->format
, box
->height
);
253 define_rect(pt
, level
, box
->z
, box
->x
, box
->y
,
254 tx
->nblocksx
, tx
->nblocksy
, &tx
->img
);
256 ret
= nouveau_bo_new(dev
, NOUVEAU_BO_GART
| NOUVEAU_BO_MAP
, 0,
257 tx
->base
.layer_stride
, NULL
, &tx
->tmp
.bo
);
259 pipe_resource_reference(&tx
->base
.resource
, NULL
);
264 tx
->tmp
.domain
= NOUVEAU_BO_GART
;
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
;
273 tx
->tmp
.x1
= tx
->tmp
.w
;
274 tx
->tmp
.y1
= tx
->tmp
.h
;
277 if (usage
& PIPE_TRANSFER_READ
)
278 nv30_transfer_rect(nv30
, NEAREST
, &tx
->img
, &tx
->tmp
);
280 if (tx
->tmp
.bo
->map
) {
281 *ptransfer
= &tx
->base
;
282 return tx
->tmp
.bo
->map
;
285 if (usage
& PIPE_TRANSFER_READ
)
286 access
|= NOUVEAU_BO_RD
;
287 if (usage
& PIPE_TRANSFER_WRITE
)
288 access
|= NOUVEAU_BO_WR
;
290 ret
= nouveau_bo_map(tx
->tmp
.bo
, access
, nv30
->base
.client
);
292 pipe_resource_reference(&tx
->base
.resource
, NULL
);
297 *ptransfer
= &tx
->base
;
298 return tx
->tmp
.bo
->map
;
302 nv30_miptree_transfer_unmap(struct pipe_context
*pipe
,
303 struct pipe_transfer
*ptx
)
305 struct nv30_context
*nv30
= nv30_context(pipe
);
306 struct nv30_transfer
*tx
= nv30_transfer(ptx
);
308 if (ptx
->usage
& PIPE_TRANSFER_WRITE
)
309 nv30_transfer_rect(nv30
, NEAREST
, &tx
->tmp
, &tx
->img
);
311 nouveau_bo_ref(NULL
, &tx
->tmp
.bo
);
312 pipe_resource_reference(&ptx
->resource
, NULL
);
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
325 struct pipe_resource
*
326 nv30_miptree_create(struct pipe_screen
*pscreen
,
327 const struct pipe_resource
*tmpl
)
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
;
336 switch (tmpl
->nr_samples
) {
338 mt
->ms_mode
= 0x00004000;
343 mt
->ms_mode
= 0x00003000;
348 mt
->ms_mode
= 0x00000000;
354 mt
->base
.vtbl
= &nv30_miptree_vtbl
;
356 pipe_reference_init(&pt
->reference
, 1);
357 pt
->screen
= pscreen
;
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
);
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);
374 if (!mt
->uniform_pitch
)
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
);
384 lvl
->pitch
= mt
->uniform_pitch
;
386 lvl
->pitch
= nbx
* blocksz
;
388 lvl
->zslice_size
= lvl
->pitch
* nby
;
389 size
+= lvl
->zslice_size
* d
;
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;
403 ret
= nouveau_bo_new(dev
, NOUVEAU_BO_VRAM
, 256, size
, NULL
, &mt
->base
.bo
);
409 mt
->base
.domain
= NOUVEAU_BO_VRAM
;
410 return &mt
->base
.base
;
413 struct pipe_resource
*
414 nv30_miptree_from_handle(struct pipe_screen
*pscreen
,
415 const struct pipe_resource
*tmpl
,
416 struct winsys_handle
*handle
)
418 struct nv30_miptree
*mt
;
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 ||
426 tmpl
->array_size
> 1)
429 mt
= CALLOC_STRUCT(nv30_miptree
);
433 mt
->base
.bo
= nouveau_screen_bo_from_handle(pscreen
, handle
, &stride
);
434 if (mt
->base
.bo
== NULL
) {
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;
447 /* no need to adjust bo reference count */
448 return &mt
->base
.base
;
451 struct pipe_surface
*
452 nv30_miptree_surface_new(struct pipe_context
*pipe
,
453 struct pipe_resource
*pt
,
454 const struct pipe_surface
*tmpl
)
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
];
461 ns
= CALLOC_STRUCT(nv30_surface
);
466 pipe_reference_init(&ps
->reference
, 1);
467 pipe_resource_reference(&ps
->texture
, pt
);
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
;
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
);
479 ns
->pitch
= 4096; /* random, just something the hw won't reject.. */
481 ns
->pitch
= lvl
->pitch
;
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
;
490 nv30_miptree_surface_del(struct pipe_context
*pipe
, struct pipe_surface
*ps
)
492 struct nv30_surface
*ns
= nv30_surface(ps
);
494 pipe_resource_reference(&ps
->texture
, NULL
);