2 * Copyright 2010 Jerome Glisse <glisse@freedesktop.org>
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 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
19 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
20 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
21 * USE OR OTHER DEALINGS IN THE SOFTWARE.
28 #include "pipe/p_screen.h"
29 #include "util/u_format.h"
30 #include "util/u_format_s3tc.h"
31 #include "util/u_math.h"
32 #include "util/u_inlines.h"
33 #include "util/u_memory.h"
34 #include "pipebuffer/pb_buffer.h"
35 #include "radeonsi_pipe.h"
36 #include "r600_resource.h"
39 /* Copy from a full GPU texture to a transfer's staging one. */
40 static void r600_copy_to_staging_texture(struct pipe_context
*ctx
, struct r600_transfer
*rtransfer
)
42 struct pipe_transfer
*transfer
= (struct pipe_transfer
*)rtransfer
;
43 struct pipe_resource
*texture
= transfer
->resource
;
45 ctx
->resource_copy_region(ctx
, rtransfer
->staging
,
46 0, 0, 0, 0, texture
, transfer
->level
,
50 /* Copy from a transfer's staging texture to a full GPU one. */
51 static void r600_copy_from_staging_texture(struct pipe_context
*ctx
, struct r600_transfer
*rtransfer
)
53 struct pipe_transfer
*transfer
= (struct pipe_transfer
*)rtransfer
;
54 struct pipe_resource
*texture
= transfer
->resource
;
57 u_box_3d(0, 0, 0, transfer
->box
.width
, transfer
->box
.height
, transfer
->box
.depth
, &sbox
);
59 ctx
->resource_copy_region(ctx
, texture
, transfer
->level
,
60 transfer
->box
.x
, transfer
->box
.y
, transfer
->box
.z
,
65 static unsigned r600_texture_get_offset(struct r600_resource_texture
*rtex
,
66 unsigned level
, unsigned layer
)
68 return rtex
->surface
.level
[level
].offset
+
69 layer
* rtex
->surface
.level
[level
].slice_size
;
72 static int r600_init_surface(struct r600_screen
*rscreen
,
73 struct radeon_surface
*surface
,
74 const struct pipe_resource
*ptex
,
76 bool is_flushed_depth
)
78 const struct util_format_description
*desc
=
79 util_format_description(ptex
->format
);
80 bool is_depth
, is_stencil
;
82 is_depth
= util_format_has_depth(desc
);
83 is_stencil
= util_format_has_stencil(desc
);
85 surface
->npix_x
= ptex
->width0
;
86 surface
->npix_y
= ptex
->height0
;
87 surface
->npix_z
= ptex
->depth0
;
88 surface
->blk_w
= util_format_get_blockwidth(ptex
->format
);
89 surface
->blk_h
= util_format_get_blockheight(ptex
->format
);
91 surface
->array_size
= 1;
92 surface
->last_level
= ptex
->last_level
;
94 if (!is_flushed_depth
&&
95 ptex
->format
== PIPE_FORMAT_Z32_FLOAT_S8X24_UINT
) {
96 surface
->bpe
= 4; /* stencil is allocated separately on evergreen */
98 surface
->bpe
= util_format_get_blocksize(ptex
->format
);
99 /* align byte per element on dword */
100 if (surface
->bpe
== 3) {
105 surface
->nsamples
= 1;
107 switch (array_mode
) {
108 case V_009910_ARRAY_1D_TILED_THIN1
:
109 surface
->flags
|= RADEON_SURF_SET(RADEON_SURF_MODE_1D
, MODE
);
111 case V_009910_ARRAY_2D_TILED_THIN1
:
112 surface
->flags
|= RADEON_SURF_SET(RADEON_SURF_MODE_2D
, MODE
);
114 case V_009910_ARRAY_LINEAR_ALIGNED
:
115 surface
->flags
|= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR_ALIGNED
, MODE
);
117 case V_009910_ARRAY_LINEAR_GENERAL
:
119 surface
->flags
|= RADEON_SURF_SET(RADEON_SURF_MODE_LINEAR
, MODE
);
122 switch (ptex
->target
) {
123 case PIPE_TEXTURE_1D
:
124 surface
->flags
|= RADEON_SURF_SET(RADEON_SURF_TYPE_1D
, TYPE
);
126 case PIPE_TEXTURE_RECT
:
127 case PIPE_TEXTURE_2D
:
128 surface
->flags
|= RADEON_SURF_SET(RADEON_SURF_TYPE_2D
, TYPE
);
130 case PIPE_TEXTURE_3D
:
131 surface
->flags
|= RADEON_SURF_SET(RADEON_SURF_TYPE_3D
, TYPE
);
133 case PIPE_TEXTURE_1D_ARRAY
:
134 surface
->flags
|= RADEON_SURF_SET(RADEON_SURF_TYPE_1D_ARRAY
, TYPE
);
135 surface
->array_size
= ptex
->array_size
;
137 case PIPE_TEXTURE_2D_ARRAY
:
138 surface
->flags
|= RADEON_SURF_SET(RADEON_SURF_TYPE_2D_ARRAY
, TYPE
);
139 surface
->array_size
= ptex
->array_size
;
141 case PIPE_TEXTURE_CUBE
:
142 surface
->flags
|= RADEON_SURF_SET(RADEON_SURF_TYPE_CUBEMAP
, TYPE
);
148 if (ptex
->bind
& PIPE_BIND_SCANOUT
) {
149 surface
->flags
|= RADEON_SURF_SCANOUT
;
152 if (!is_flushed_depth
&& is_depth
) {
153 surface
->flags
|= RADEON_SURF_ZBUFFER
;
155 surface
->flags
|= RADEON_SURF_SBUFFER
|
156 RADEON_SURF_HAS_SBUFFER_MIPTREE
;
159 surface
->flags
|= RADEON_SURF_HAS_TILE_MODE_INDEX
;
163 static int r600_setup_surface(struct pipe_screen
*screen
,
164 struct r600_resource_texture
*rtex
,
166 unsigned pitch_in_bytes_override
)
168 struct r600_screen
*rscreen
= (struct r600_screen
*)screen
;
171 r
= rscreen
->ws
->surface_init(rscreen
->ws
, &rtex
->surface
);
175 if (pitch_in_bytes_override
&& pitch_in_bytes_override
!= rtex
->surface
.level
[0].pitch_bytes
) {
176 /* old ddx on evergreen over estimate alignment for 1d, only 1 level
179 rtex
->surface
.level
[0].nblk_x
= pitch_in_bytes_override
/ rtex
->surface
.bpe
;
180 rtex
->surface
.level
[0].pitch_bytes
= pitch_in_bytes_override
;
181 rtex
->surface
.level
[0].slice_size
= pitch_in_bytes_override
* rtex
->surface
.level
[0].nblk_y
;
182 if (rtex
->surface
.flags
& RADEON_SURF_SBUFFER
) {
183 rtex
->surface
.stencil_offset
=
184 rtex
->surface
.stencil_level
[0].offset
= rtex
->surface
.level
[0].slice_size
;
190 static boolean
r600_texture_get_handle(struct pipe_screen
* screen
,
191 struct pipe_resource
*ptex
,
192 struct winsys_handle
*whandle
)
194 struct r600_resource_texture
*rtex
= (struct r600_resource_texture
*)ptex
;
195 struct si_resource
*resource
= &rtex
->resource
;
196 struct radeon_surface
*surface
= &rtex
->surface
;
197 struct r600_screen
*rscreen
= (struct r600_screen
*)screen
;
199 rscreen
->ws
->buffer_set_tiling(resource
->buf
,
201 surface
->level
[0].mode
>= RADEON_SURF_MODE_1D
?
202 RADEON_LAYOUT_TILED
: RADEON_LAYOUT_LINEAR
,
203 surface
->level
[0].mode
>= RADEON_SURF_MODE_2D
?
204 RADEON_LAYOUT_TILED
: RADEON_LAYOUT_LINEAR
,
205 surface
->bankw
, surface
->bankh
,
207 surface
->stencil_tile_split
,
209 surface
->level
[0].pitch_bytes
);
211 return rscreen
->ws
->buffer_get_handle(resource
->buf
,
212 surface
->level
[0].pitch_bytes
, whandle
);
215 static void r600_texture_destroy(struct pipe_screen
*screen
,
216 struct pipe_resource
*ptex
)
218 struct r600_resource_texture
*rtex
= (struct r600_resource_texture
*)ptex
;
219 struct si_resource
*resource
= &rtex
->resource
;
221 if (rtex
->flushed_depth_texture
)
222 si_resource_reference((struct si_resource
**)&rtex
->flushed_depth_texture
, NULL
);
224 pb_reference(&resource
->buf
, NULL
);
228 static void *si_texture_transfer_map(struct pipe_context
*ctx
,
229 struct pipe_resource
*texture
,
232 const struct pipe_box
*box
,
233 struct pipe_transfer
**ptransfer
)
235 struct r600_context
*rctx
= (struct r600_context
*)ctx
;
236 struct r600_resource_texture
*rtex
= (struct r600_resource_texture
*)texture
;
237 struct r600_transfer
*trans
;
238 boolean use_staging_texture
= FALSE
;
239 struct radeon_winsys_cs_handle
*buf
;
240 enum pipe_format format
= texture
->format
;
244 /* We cannot map a tiled texture directly because the data is
245 * in a different order, therefore we do detiling using a blit.
247 * Also, use a temporary in GTT memory for read transfers, as
248 * the CPU is much happier reading out of cached system memory
249 * than uncached VRAM.
251 if (rtex
->surface
.level
[level
].mode
!= RADEON_SURF_MODE_LINEAR_ALIGNED
&&
252 rtex
->surface
.level
[level
].mode
!= RADEON_SURF_MODE_LINEAR
)
253 use_staging_texture
= TRUE
;
255 /* XXX: Use a staging texture for uploads if the underlying BO
256 * is busy. No interface for checking that currently? so do
257 * it eagerly whenever the transfer doesn't require a readback
260 if ((usage
& PIPE_TRANSFER_WRITE
) &&
261 !(usage
& (PIPE_TRANSFER_READ
|
262 PIPE_TRANSFER_DONTBLOCK
|
263 PIPE_TRANSFER_UNSYNCHRONIZED
)))
264 use_staging_texture
= TRUE
;
266 if (texture
->flags
& R600_RESOURCE_FLAG_TRANSFER
)
267 use_staging_texture
= FALSE
;
269 if (use_staging_texture
&& (usage
& PIPE_TRANSFER_MAP_DIRECTLY
))
272 trans
= CALLOC_STRUCT(r600_transfer
);
275 pipe_resource_reference(&trans
->transfer
.resource
, texture
);
276 trans
->transfer
.level
= level
;
277 trans
->transfer
.usage
= usage
;
278 trans
->transfer
.box
= *box
;
279 if (rtex
->is_depth
) {
280 /* XXX: only readback the rectangle which is being mapped?
282 /* XXX: when discard is true, no need to read back from depth texture
284 struct r600_resource_texture
*staging_depth
;
286 if (!r600_init_flushed_depth_texture(ctx
, texture
, &staging_depth
)) {
287 R600_ERR("failed to create temporary texture to hold untiled copy\n");
288 pipe_resource_reference(&trans
->transfer
.resource
, NULL
);
292 si_blit_uncompress_depth(ctx
, rtex
, staging_depth
,
294 box
->z
, box
->z
+ box
->depth
- 1);
295 trans
->transfer
.stride
= staging_depth
->surface
.level
[level
].pitch_bytes
;
296 trans
->transfer
.layer_stride
= staging_depth
->surface
.level
[level
].slice_size
;
297 trans
->offset
= r600_texture_get_offset(staging_depth
, level
, box
->z
);
299 trans
->staging
= &staging_depth
->resource
.b
.b
;
300 } else if (use_staging_texture
) {
301 struct pipe_resource resource
;
302 struct r600_resource_texture
*staging
;
304 memset(&resource
, 0, sizeof(resource
));
305 resource
.format
= texture
->format
;
306 resource
.width0
= box
->width
;
307 resource
.height0
= box
->height
;
309 resource
.array_size
= 1;
310 resource
.usage
= PIPE_USAGE_STAGING
;
311 resource
.flags
= R600_RESOURCE_FLAG_TRANSFER
;
313 /* We must set the correct texture target and dimensions if needed for a 3D transfer. */
314 if (box
->depth
> 1 && util_max_layer(texture
, level
) > 0)
315 resource
.target
= texture
->target
;
317 resource
.target
= PIPE_TEXTURE_2D
;
319 switch (resource
.target
) {
320 case PIPE_TEXTURE_1D_ARRAY
:
321 case PIPE_TEXTURE_2D_ARRAY
:
322 case PIPE_TEXTURE_CUBE_ARRAY
:
323 resource
.array_size
= box
->depth
;
325 case PIPE_TEXTURE_3D
:
326 resource
.depth0
= box
->depth
;
330 /* Create the temporary texture. */
331 staging
= (struct r600_resource_texture
*)ctx
->screen
->resource_create(ctx
->screen
, &resource
);
332 if (staging
== NULL
) {
333 R600_ERR("failed to create temporary texture to hold untiled copy\n");
334 pipe_resource_reference(&trans
->transfer
.resource
, NULL
);
339 trans
->staging
= &staging
->resource
.b
.b
;
340 trans
->transfer
.stride
= staging
->surface
.level
[0].pitch_bytes
;
341 trans
->transfer
.layer_stride
= staging
->surface
.level
[0].slice_size
;
342 if (usage
& PIPE_TRANSFER_READ
) {
343 r600_copy_to_staging_texture(ctx
, trans
);
344 /* Always referenced in the blit. */
345 radeonsi_flush(ctx
, NULL
, 0);
348 trans
->transfer
.stride
= rtex
->surface
.level
[level
].pitch_bytes
;
349 trans
->transfer
.layer_stride
= rtex
->surface
.level
[level
].slice_size
;
350 trans
->offset
= r600_texture_get_offset(rtex
, level
, box
->z
);
353 if (trans
->staging
) {
354 buf
= si_resource(trans
->staging
)->cs_buf
;
356 buf
= rtex
->resource
.cs_buf
;
359 if (rtex
->is_depth
|| !trans
->staging
)
360 offset
= trans
->offset
+
361 box
->y
/ util_format_get_blockheight(format
) * trans
->transfer
.stride
+
362 box
->x
/ util_format_get_blockwidth(format
) * util_format_get_blocksize(format
);
364 if (!(map
= rctx
->ws
->buffer_map(buf
, rctx
->cs
, usage
))) {
365 pipe_resource_reference(&trans
->staging
, NULL
);
366 pipe_resource_reference(&trans
->transfer
.resource
, NULL
);
371 *ptransfer
= &trans
->transfer
;
375 static void si_texture_transfer_unmap(struct pipe_context
*ctx
,
376 struct pipe_transfer
* transfer
)
378 struct r600_transfer
*rtransfer
= (struct r600_transfer
*)transfer
;
379 struct r600_context
*rctx
= (struct r600_context
*)ctx
;
380 struct radeon_winsys_cs_handle
*buf
;
381 struct pipe_resource
*texture
= transfer
->resource
;
382 struct r600_resource_texture
*rtex
= (struct r600_resource_texture
*)texture
;
384 if (rtransfer
->staging
) {
385 buf
= si_resource(rtransfer
->staging
)->cs_buf
;
387 buf
= si_resource(transfer
->resource
)->cs_buf
;
389 rctx
->ws
->buffer_unmap(buf
);
391 if ((transfer
->usage
& PIPE_TRANSFER_WRITE
) && rtransfer
->staging
) {
392 if (rtex
->is_depth
) {
393 ctx
->resource_copy_region(ctx
, texture
, transfer
->level
,
394 transfer
->box
.x
, transfer
->box
.y
, transfer
->box
.z
,
395 &si_resource(rtransfer
->staging
)->b
.b
, transfer
->level
,
398 r600_copy_from_staging_texture(ctx
, rtransfer
);
402 if (rtransfer
->staging
)
403 pipe_resource_reference((struct pipe_resource
**)&rtransfer
->staging
, NULL
);
405 pipe_resource_reference(&transfer
->resource
, NULL
);
409 static const struct u_resource_vtbl r600_texture_vtbl
=
411 r600_texture_get_handle
, /* get_handle */
412 r600_texture_destroy
, /* resource_destroy */
413 si_texture_transfer_map
, /* transfer_map */
414 u_default_transfer_flush_region
,/* transfer_flush_region */
415 si_texture_transfer_unmap
, /* transfer_unmap */
416 NULL
/* transfer_inline_write */
419 DEBUG_GET_ONCE_BOOL_OPTION(print_texdepth
, "RADEON_PRINT_TEXDEPTH", FALSE
);
421 static struct r600_resource_texture
*
422 r600_texture_create_object(struct pipe_screen
*screen
,
423 const struct pipe_resource
*base
,
425 unsigned pitch_in_bytes_override
,
426 unsigned max_buffer_size
,
427 struct pb_buffer
*buf
,
429 struct radeon_surface
*surface
)
431 struct r600_resource_texture
*rtex
;
432 struct si_resource
*resource
;
433 struct r600_screen
*rscreen
= (struct r600_screen
*)screen
;
436 rtex
= CALLOC_STRUCT(r600_resource_texture
);
440 resource
= &rtex
->resource
;
441 resource
->b
.b
= *base
;
442 resource
->b
.vtbl
= &r600_texture_vtbl
;
443 pipe_reference_init(&resource
->b
.b
.reference
, 1);
444 resource
->b
.b
.screen
= screen
;
445 rtex
->pitch_override
= pitch_in_bytes_override
;
446 rtex
->real_format
= base
->format
;
448 /* don't include stencil-only formats which we don't support for rendering */
449 rtex
->is_depth
= util_format_has_depth(util_format_description(rtex
->resource
.b
.b
.format
));
451 rtex
->surface
= *surface
;
452 r
= r600_setup_surface(screen
, rtex
, array_mode
, pitch_in_bytes_override
);
458 /* Now create the backing buffer. */
459 if (!buf
&& alloc_bo
) {
460 unsigned base_align
= rtex
->surface
.bo_alignment
;
461 unsigned size
= rtex
->surface
.bo_size
;
463 base_align
= rtex
->surface
.bo_alignment
;
464 if (!si_init_resource(rscreen
, resource
, size
, base_align
, FALSE
, base
->usage
)) {
470 resource
->cs_buf
= rscreen
->ws
->buffer_get_cs_handle(buf
);
471 resource
->domains
= RADEON_DOMAIN_GTT
| RADEON_DOMAIN_VRAM
;
474 if (debug_get_option_print_texdepth() && rtex
->is_depth
) {
475 printf("Texture: npix_x=%u, npix_y=%u, npix_z=%u, blk_w=%u, "
476 "blk_h=%u, blk_d=%u, array_size=%u, last_level=%u, "
477 "bpe=%u, nsamples=%u, flags=%u\n",
478 rtex
->surface
.npix_x
, rtex
->surface
.npix_y
,
479 rtex
->surface
.npix_z
, rtex
->surface
.blk_w
,
480 rtex
->surface
.blk_h
, rtex
->surface
.blk_d
,
481 rtex
->surface
.array_size
, rtex
->surface
.last_level
,
482 rtex
->surface
.bpe
, rtex
->surface
.nsamples
,
483 rtex
->surface
.flags
);
484 if (rtex
->surface
.flags
& RADEON_SURF_ZBUFFER
) {
485 for (int i
= 0; i
<= rtex
->surface
.last_level
; i
++) {
486 printf(" Z %i: offset=%llu, slice_size=%llu, npix_x=%u, "
487 "npix_y=%u, npix_z=%u, nblk_x=%u, nblk_y=%u, "
488 "nblk_z=%u, pitch_bytes=%u, mode=%u\n",
489 i
, rtex
->surface
.level
[i
].offset
,
490 rtex
->surface
.level
[i
].slice_size
,
491 rtex
->surface
.level
[i
].npix_x
,
492 rtex
->surface
.level
[i
].npix_y
,
493 rtex
->surface
.level
[i
].npix_z
,
494 rtex
->surface
.level
[i
].nblk_x
,
495 rtex
->surface
.level
[i
].nblk_y
,
496 rtex
->surface
.level
[i
].nblk_z
,
497 rtex
->surface
.level
[i
].pitch_bytes
,
498 rtex
->surface
.level
[i
].mode
);
501 if (rtex
->surface
.flags
& RADEON_SURF_SBUFFER
) {
502 for (int i
= 0; i
<= rtex
->surface
.last_level
; i
++) {
503 printf(" S %i: offset=%llu, slice_size=%llu, npix_x=%u, "
504 "npix_y=%u, npix_z=%u, nblk_x=%u, nblk_y=%u, "
505 "nblk_z=%u, pitch_bytes=%u, mode=%u\n",
506 i
, rtex
->surface
.stencil_level
[i
].offset
,
507 rtex
->surface
.stencil_level
[i
].slice_size
,
508 rtex
->surface
.stencil_level
[i
].npix_x
,
509 rtex
->surface
.stencil_level
[i
].npix_y
,
510 rtex
->surface
.stencil_level
[i
].npix_z
,
511 rtex
->surface
.stencil_level
[i
].nblk_x
,
512 rtex
->surface
.stencil_level
[i
].nblk_y
,
513 rtex
->surface
.stencil_level
[i
].nblk_z
,
514 rtex
->surface
.stencil_level
[i
].pitch_bytes
,
515 rtex
->surface
.stencil_level
[i
].mode
);
522 struct pipe_resource
*si_texture_create(struct pipe_screen
*screen
,
523 const struct pipe_resource
*templ
)
525 struct r600_screen
*rscreen
= (struct r600_screen
*)screen
;
526 struct radeon_surface surface
;
527 unsigned array_mode
= V_009910_ARRAY_LINEAR_ALIGNED
;
530 if (!(templ
->flags
& R600_RESOURCE_FLAG_TRANSFER
) &&
531 !(templ
->bind
& PIPE_BIND_SCANOUT
)) {
532 if (util_format_is_compressed(templ
->format
)) {
533 array_mode
= V_009910_ARRAY_1D_TILED_THIN1
;
535 array_mode
= V_009910_ARRAY_2D_TILED_THIN1
;
539 r
= r600_init_surface(rscreen
, &surface
, templ
, array_mode
,
540 templ
->flags
& R600_RESOURCE_FLAG_FLUSHED_DEPTH
);
544 r
= rscreen
->ws
->surface_best(rscreen
->ws
, &surface
);
548 return (struct pipe_resource
*)r600_texture_create_object(screen
, templ
, array_mode
,
549 0, 0, NULL
, TRUE
, &surface
);
552 static struct pipe_surface
*r600_create_surface(struct pipe_context
*pipe
,
553 struct pipe_resource
*texture
,
554 const struct pipe_surface
*surf_tmpl
)
556 struct r600_resource_texture
*rtex
= (struct r600_resource_texture
*)texture
;
557 struct r600_surface
*surface
= CALLOC_STRUCT(r600_surface
);
558 unsigned level
= surf_tmpl
->u
.tex
.level
;
560 assert(surf_tmpl
->u
.tex
.first_layer
<= util_max_layer(texture
, surf_tmpl
->u
.tex
.level
));
561 assert(surf_tmpl
->u
.tex
.last_layer
<= util_max_layer(texture
, surf_tmpl
->u
.tex
.level
));
562 assert(surf_tmpl
->u
.tex
.first_layer
== surf_tmpl
->u
.tex
.last_layer
);
566 /* offset = r600_texture_get_offset(rtex, level, surf_tmpl->u.tex.first_layer);*/
567 pipe_reference_init(&surface
->base
.reference
, 1);
568 pipe_resource_reference(&surface
->base
.texture
, texture
);
569 surface
->base
.context
= pipe
;
570 surface
->base
.format
= surf_tmpl
->format
;
571 surface
->base
.width
= rtex
->surface
.level
[level
].npix_x
;
572 surface
->base
.height
= rtex
->surface
.level
[level
].npix_y
;
573 surface
->base
.texture
= texture
;
574 surface
->base
.u
.tex
.first_layer
= surf_tmpl
->u
.tex
.first_layer
;
575 surface
->base
.u
.tex
.last_layer
= surf_tmpl
->u
.tex
.last_layer
;
576 surface
->base
.u
.tex
.level
= level
;
578 return &surface
->base
;
581 static void r600_surface_destroy(struct pipe_context
*pipe
,
582 struct pipe_surface
*surface
)
584 pipe_resource_reference(&surface
->texture
, NULL
);
588 struct pipe_resource
*si_texture_from_handle(struct pipe_screen
*screen
,
589 const struct pipe_resource
*templ
,
590 struct winsys_handle
*whandle
)
592 struct r600_screen
*rscreen
= (struct r600_screen
*)screen
;
593 struct pb_buffer
*buf
= NULL
;
595 unsigned array_mode
= V_009910_ARRAY_LINEAR_ALIGNED
;
596 enum radeon_bo_layout micro
, macro
;
597 struct radeon_surface surface
;
600 /* Support only 2D textures without mipmaps */
601 if ((templ
->target
!= PIPE_TEXTURE_2D
&& templ
->target
!= PIPE_TEXTURE_RECT
) ||
602 templ
->depth0
!= 1 || templ
->last_level
!= 0)
605 buf
= rscreen
->ws
->buffer_from_handle(rscreen
->ws
, whandle
, &stride
);
609 rscreen
->ws
->buffer_get_tiling(buf
, µ
, ¯o
,
610 &surface
.bankw
, &surface
.bankh
,
612 &surface
.stencil_tile_split
,
615 if (macro
== RADEON_LAYOUT_TILED
)
616 array_mode
= V_009910_ARRAY_2D_TILED_THIN1
;
617 else if (micro
== RADEON_LAYOUT_TILED
)
618 array_mode
= V_009910_ARRAY_1D_TILED_THIN1
;
620 array_mode
= V_009910_ARRAY_LINEAR_ALIGNED
;
622 r
= r600_init_surface(rscreen
, &surface
, templ
, array_mode
, false);
626 /* always set the scanout flags */
627 surface
.flags
|= RADEON_SURF_SCANOUT
;
628 return (struct pipe_resource
*)r600_texture_create_object(screen
, templ
, array_mode
,
629 stride
, 0, buf
, FALSE
, &surface
);
632 bool r600_init_flushed_depth_texture(struct pipe_context
*ctx
,
633 struct pipe_resource
*texture
,
634 struct r600_resource_texture
**staging
)
636 struct r600_resource_texture
*rtex
= (struct r600_resource_texture
*)texture
;
637 struct pipe_resource resource
;
638 struct r600_resource_texture
**flushed_depth_texture
= staging
?
639 staging
: &rtex
->flushed_depth_texture
;
641 if (!staging
&& rtex
->flushed_depth_texture
)
642 return true; /* it's ready */
644 resource
.target
= texture
->target
;
645 resource
.format
= texture
->format
;
646 resource
.width0
= texture
->width0
;
647 resource
.height0
= texture
->height0
;
648 resource
.depth0
= texture
->depth0
;
649 resource
.array_size
= texture
->array_size
;
650 resource
.last_level
= texture
->last_level
;
651 resource
.nr_samples
= texture
->nr_samples
;
652 resource
.usage
= staging
? PIPE_USAGE_DYNAMIC
: PIPE_USAGE_DEFAULT
;
653 resource
.bind
= texture
->bind
& ~PIPE_BIND_DEPTH_STENCIL
;
654 resource
.flags
= texture
->flags
| R600_RESOURCE_FLAG_FLUSHED_DEPTH
;
657 resource
.flags
|= R600_RESOURCE_FLAG_TRANSFER
;
659 rtex
->dirty_db_mask
= (1 << (resource
.last_level
+1)) - 1;
661 *flushed_depth_texture
= (struct r600_resource_texture
*)ctx
->screen
->resource_create(ctx
->screen
, &resource
);
662 if (*flushed_depth_texture
== NULL
) {
663 R600_ERR("failed to create temporary texture to hold flushed depth\n");
667 (*flushed_depth_texture
)->is_flushing_texture
= TRUE
;
671 void si_init_surface_functions(struct r600_context
*r600
)
673 r600
->context
.create_surface
= r600_create_surface
;
674 r600
->context
.surface_destroy
= r600_surface_destroy
;