1 /**************************************************************************
3 * Copyright 2007 VMware, Inc.
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 **************************************************************************/
30 #include "st_context.h"
31 #include "st_format.h"
32 #include "st_texture.h"
33 #include "st_cb_fbo.h"
34 #include "main/enums.h"
36 #include "pipe/p_state.h"
37 #include "pipe/p_context.h"
38 #include "pipe/p_defines.h"
39 #include "util/u_inlines.h"
40 #include "util/format/u_format.h"
41 #include "util/u_rect.h"
42 #include "util/u_math.h"
43 #include "util/u_memory.h"
44 #include "tgsi/tgsi_from_mesa.h"
47 #define DBG if(0) printf
51 * Allocate a new pipe_resource object
52 * width0, height0, depth0 are the dimensions of the level 0 image
53 * (the highest resolution). last_level indicates how many mipmap levels
54 * to allocate storage for. For non-mipmapped textures, this will be zero.
56 struct pipe_resource
*
57 st_texture_create(struct st_context
*st
,
58 enum pipe_texture_target target
,
59 enum pipe_format format
,
68 struct pipe_resource pt
, *newtex
;
69 struct pipe_screen
*screen
= st
->pipe
->screen
;
71 assert(target
< PIPE_MAX_TEXTURE_TYPES
);
75 if (target
== PIPE_TEXTURE_CUBE
)
78 DBG("%s target %d format %s last_level %d\n", __func__
,
79 (int) target
, util_format_name(format
), last_level
);
82 assert(screen
->is_format_supported(screen
, format
, target
, 0, 0,
83 PIPE_BIND_SAMPLER_VIEW
));
85 memset(&pt
, 0, sizeof(pt
));
88 pt
.last_level
= last_level
;
92 pt
.array_size
= layers
;
93 pt
.usage
= PIPE_USAGE_DEFAULT
;
95 /* only set this for OpenGL textures, not renderbuffers */
96 pt
.flags
= PIPE_RESOURCE_FLAG_TEXTURING_MORE_LIKELY
;
97 pt
.nr_samples
= nr_samples
;
98 pt
.nr_storage_samples
= nr_samples
;
100 newtex
= screen
->resource_create(screen
, &pt
);
102 assert(!newtex
|| pipe_is_referenced(&newtex
->reference
));
109 * In OpenGL the number of 1D array texture layers is the "height" and
110 * the number of 2D array texture layers is the "depth". In Gallium the
111 * number of layers in an array texture is a separate 'array_size' field.
112 * This function converts dimensions from the former to the later.
115 st_gl_texture_dims_to_pipe_dims(GLenum texture
,
126 case GL_PROXY_TEXTURE_1D
:
127 assert(heightIn
== 1);
128 assert(depthIn
== 1);
134 case GL_TEXTURE_1D_ARRAY
:
135 case GL_PROXY_TEXTURE_1D_ARRAY
:
136 assert(depthIn
== 1);
140 *layersOut
= heightIn
;
143 case GL_PROXY_TEXTURE_2D
:
144 case GL_TEXTURE_RECTANGLE
:
145 case GL_PROXY_TEXTURE_RECTANGLE
:
146 case GL_TEXTURE_EXTERNAL_OES
:
147 case GL_PROXY_TEXTURE_2D_MULTISAMPLE
:
148 case GL_TEXTURE_2D_MULTISAMPLE
:
149 assert(depthIn
== 1);
151 *heightOut
= heightIn
;
155 case GL_TEXTURE_CUBE_MAP
:
156 case GL_PROXY_TEXTURE_CUBE_MAP
:
157 case GL_TEXTURE_CUBE_MAP_POSITIVE_X
:
158 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X
:
159 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y
:
160 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
:
161 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z
:
162 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
:
163 assert(depthIn
== 1);
165 *heightOut
= heightIn
;
169 case GL_TEXTURE_2D_ARRAY
:
170 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY
:
171 case GL_PROXY_TEXTURE_2D_ARRAY
:
172 case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY
:
174 *heightOut
= heightIn
;
176 *layersOut
= depthIn
;
178 case GL_TEXTURE_CUBE_MAP_ARRAY
:
179 case GL_PROXY_TEXTURE_CUBE_MAP_ARRAY
:
181 *heightOut
= heightIn
;
183 *layersOut
= util_align_npot(depthIn
, 6);
186 assert(0 && "Unexpected texture in st_gl_texture_dims_to_pipe_dims()");
189 case GL_PROXY_TEXTURE_3D
:
191 *heightOut
= heightIn
;
200 * Check if a texture image can be pulled into a unified mipmap texture.
203 st_texture_match_image(struct st_context
*st
,
204 const struct pipe_resource
*pt
,
205 const struct gl_texture_image
*image
)
208 uint16_t ptHeight
, ptDepth
, ptLayers
;
210 /* Images with borders are never pulled into mipmap textures.
215 /* Check if this image's format matches the established texture's format.
217 if (st_mesa_format_to_pipe_format(st
, image
->TexFormat
) != pt
->format
)
220 st_gl_texture_dims_to_pipe_dims(image
->TexObject
->Target
,
221 image
->Width
, image
->Height
, image
->Depth
,
222 &ptWidth
, &ptHeight
, &ptDepth
, &ptLayers
);
224 /* Test if this image's size matches what's expected in the
225 * established texture.
227 if (ptWidth
!= u_minify(pt
->width0
, image
->Level
) ||
228 ptHeight
!= u_minify(pt
->height0
, image
->Level
) ||
229 ptDepth
!= u_minify(pt
->depth0
, image
->Level
) ||
230 ptLayers
!= pt
->array_size
)
233 if (image
->Level
> pt
->last_level
)
241 * Map a texture image and return the address for a particular 2D face/slice/
242 * layer. The stImage indicates the cube face and mipmap level. The slice
243 * of the 3D texture is passed in 'zoffset'.
244 * \param usage one of the PIPE_TRANSFER_x values
245 * \param x, y, w, h the region of interest of the 2D image.
246 * \return address of mapping or NULL if any error
249 st_texture_image_map(struct st_context
*st
, struct st_texture_image
*stImage
,
250 enum pipe_transfer_usage usage
,
251 GLuint x
, GLuint y
, GLuint z
,
252 GLuint w
, GLuint h
, GLuint d
,
253 struct pipe_transfer
**transfer
)
255 struct st_texture_object
*stObj
=
256 st_texture_object(stImage
->base
.TexObject
);
260 DBG("%s \n", __func__
);
265 if (stObj
->pt
!= stImage
->pt
)
268 level
= stImage
->base
.Level
;
270 if (stObj
->base
.Immutable
) {
271 level
+= stObj
->base
.MinLevel
;
272 z
+= stObj
->base
.MinLayer
;
273 if (stObj
->pt
->array_size
> 1)
274 d
= MIN2(d
, stObj
->base
.NumLayers
);
277 z
+= stImage
->base
.Face
;
279 map
= pipe_transfer_map_3d(st
->pipe
, stImage
->pt
, level
, usage
,
280 x
, y
, z
, w
, h
, d
, transfer
);
282 /* Enlarge the transfer array if it's not large enough. */
283 if (z
>= stImage
->num_transfers
) {
284 unsigned new_size
= z
+ 1;
286 stImage
->transfer
= realloc(stImage
->transfer
,
287 new_size
* sizeof(struct st_texture_image_transfer
));
288 memset(&stImage
->transfer
[stImage
->num_transfers
], 0,
289 (new_size
- stImage
->num_transfers
) *
290 sizeof(struct st_texture_image_transfer
));
291 stImage
->num_transfers
= new_size
;
294 assert(!stImage
->transfer
[z
].transfer
);
295 stImage
->transfer
[z
].transfer
= *transfer
;
302 st_texture_image_unmap(struct st_context
*st
,
303 struct st_texture_image
*stImage
, unsigned slice
)
305 struct pipe_context
*pipe
= st
->pipe
;
306 struct st_texture_object
*stObj
=
307 st_texture_object(stImage
->base
.TexObject
);
308 struct pipe_transfer
**transfer
;
310 if (stObj
->base
.Immutable
)
311 slice
+= stObj
->base
.MinLayer
;
312 transfer
= &stImage
->transfer
[slice
+ stImage
->base
.Face
].transfer
;
314 DBG("%s\n", __func__
);
316 pipe_transfer_unmap(pipe
, *transfer
);
322 * For debug only: get/print center pixel in the src resource.
325 print_center_pixel(struct pipe_context
*pipe
, struct pipe_resource
*src
)
327 struct pipe_transfer
*xfer
;
328 struct pipe_box region
;
331 region
.x
= src
->width0
/ 2;
332 region
.y
= src
->height0
/ 2;
338 map
= pipe
->transfer_map(pipe
, src
, 0, PIPE_TRANSFER_READ
, ®ion
, &xfer
);
340 printf("center pixel: %d %d %d %d\n", map
[0], map
[1], map
[2], map
[3]);
342 pipe
->transfer_unmap(pipe
, xfer
);
347 * Copy the image at level=0 in 'src' to the 'dst' resource at 'dstLevel'.
348 * This is used to copy mipmap images from one texture buffer to another.
349 * This typically happens when our initial guess at the total texture size
350 * is incorrect (see the guess_and_alloc_texture() function).
353 st_texture_image_copy(struct pipe_context
*pipe
,
354 struct pipe_resource
*dst
, GLuint dstLevel
,
355 struct pipe_resource
*src
, GLuint srcLevel
,
358 GLuint width
= u_minify(dst
->width0
, dstLevel
);
359 GLuint height
= u_minify(dst
->height0
, dstLevel
);
360 GLuint depth
= u_minify(dst
->depth0
, dstLevel
);
361 struct pipe_box src_box
;
364 if (u_minify(src
->width0
, srcLevel
) != width
||
365 u_minify(src
->height0
, srcLevel
) != height
||
366 u_minify(src
->depth0
, srcLevel
) != depth
) {
367 /* The source image size doesn't match the destination image size.
368 * This can happen in some degenerate situations such as rendering to a
369 * cube map face which was set up with mismatched texture sizes.
376 src_box
.width
= width
;
377 src_box
.height
= height
;
380 if (src
->target
== PIPE_TEXTURE_1D_ARRAY
||
381 src
->target
== PIPE_TEXTURE_2D_ARRAY
||
382 src
->target
== PIPE_TEXTURE_CUBE_ARRAY
) {
384 depth
= src
->array_size
;
387 /* Loop over 3D image slices */
388 /* could (and probably should) use "true" 3d box here -
389 but drivers can't quite handle it yet */
390 for (i
= face
; i
< face
+ depth
; i
++) {
394 print_center_pixel(pipe
, src
);
397 pipe
->resource_copy_region(pipe
,
400 0, 0, i
,/* destX, Y, Z */
408 struct pipe_resource
*
409 st_create_color_map_texture(struct gl_context
*ctx
)
411 struct st_context
*st
= st_context(ctx
);
412 struct pipe_resource
*pt
;
413 enum pipe_format format
;
414 const uint texSize
= 256; /* simple, and usually perfect */
416 /* find an RGBA texture format */
417 format
= st_choose_format(st
, GL_RGBA
, GL_NONE
, GL_NONE
,
418 PIPE_TEXTURE_2D
, 0, 0, PIPE_BIND_SAMPLER_VIEW
,
421 /* create texture for color map/table */
422 pt
= st_texture_create(st
, PIPE_TEXTURE_2D
, format
, 0,
423 texSize
, texSize
, 1, 1, 0, PIPE_BIND_SAMPLER_VIEW
);
429 * Destroy bound texture handles for the given stage.
432 st_destroy_bound_texture_handles_per_stage(struct st_context
*st
,
433 enum pipe_shader_type shader
)
435 struct st_bound_handles
*bound_handles
= &st
->bound_texture_handles
[shader
];
436 struct pipe_context
*pipe
= st
->pipe
;
439 if (likely(!bound_handles
->num_handles
))
442 for (i
= 0; i
< bound_handles
->num_handles
; i
++) {
443 uint64_t handle
= bound_handles
->handles
[i
];
445 pipe
->make_texture_handle_resident(pipe
, handle
, false);
446 pipe
->delete_texture_handle(pipe
, handle
);
448 free(bound_handles
->handles
);
449 bound_handles
->handles
= NULL
;
450 bound_handles
->num_handles
= 0;
455 * Destroy all bound texture handles in the context.
458 st_destroy_bound_texture_handles(struct st_context
*st
)
462 for (i
= 0; i
< PIPE_SHADER_TYPES
; i
++) {
463 st_destroy_bound_texture_handles_per_stage(st
, i
);
469 * Destroy bound image handles for the given stage.
472 st_destroy_bound_image_handles_per_stage(struct st_context
*st
,
473 enum pipe_shader_type shader
)
475 struct st_bound_handles
*bound_handles
= &st
->bound_image_handles
[shader
];
476 struct pipe_context
*pipe
= st
->pipe
;
479 if (likely(!bound_handles
->num_handles
))
482 for (i
= 0; i
< bound_handles
->num_handles
; i
++) {
483 uint64_t handle
= bound_handles
->handles
[i
];
485 pipe
->make_image_handle_resident(pipe
, handle
, GL_READ_WRITE
, false);
486 pipe
->delete_image_handle(pipe
, handle
);
488 free(bound_handles
->handles
);
489 bound_handles
->handles
= NULL
;
490 bound_handles
->num_handles
= 0;
495 * Destroy all bound image handles in the context.
498 st_destroy_bound_image_handles(struct st_context
*st
)
502 for (i
= 0; i
< PIPE_SHADER_TYPES
; i
++) {
503 st_destroy_bound_image_handles_per_stage(st
, i
);
509 * Create a texture handle from a texture unit.
512 st_create_texture_handle_from_unit(struct st_context
*st
,
513 struct gl_program
*prog
, GLuint texUnit
)
515 struct pipe_context
*pipe
= st
->pipe
;
516 struct pipe_sampler_view
*view
;
517 struct pipe_sampler_state sampler
= {0};
519 /* TODO: Clarify the interaction of ARB_bindless_texture and EXT_texture_sRGB_decode */
520 st_update_single_texture(st
, &view
, texUnit
, prog
->sh
.data
->Version
>= 130, true);
524 if (view
->target
!= PIPE_BUFFER
)
525 st_convert_sampler_from_unit(st
, &sampler
, texUnit
);
527 assert(st
->ctx
->Texture
.Unit
[texUnit
]._Current
);
529 return pipe
->create_texture_handle(pipe
, view
, &sampler
);
534 * Create an image handle from an image unit.
537 st_create_image_handle_from_unit(struct st_context
*st
,
538 struct gl_program
*prog
, GLuint imgUnit
)
540 struct pipe_context
*pipe
= st
->pipe
;
541 struct pipe_image_view img
;
543 st_convert_image_from_unit(st
, &img
, imgUnit
, GL_READ_WRITE
);
545 return pipe
->create_image_handle(pipe
, &img
);
550 * Make all bindless samplers bound to texture units resident in the context.
553 st_make_bound_samplers_resident(struct st_context
*st
,
554 struct gl_program
*prog
)
556 enum pipe_shader_type shader
= pipe_shader_type_from_mesa(prog
->info
.stage
);
557 struct st_bound_handles
*bound_handles
= &st
->bound_texture_handles
[shader
];
558 struct pipe_context
*pipe
= st
->pipe
;
562 /* Remove previous bound texture handles for this stage. */
563 st_destroy_bound_texture_handles_per_stage(st
, shader
);
565 if (likely(!prog
->sh
.HasBoundBindlessSampler
))
568 for (i
= 0; i
< prog
->sh
.NumBindlessSamplers
; i
++) {
569 struct gl_bindless_sampler
*sampler
= &prog
->sh
.BindlessSamplers
[i
];
574 /* Request a new texture handle from the driver and make it resident. */
575 handle
= st_create_texture_handle_from_unit(st
, prog
, sampler
->unit
);
579 pipe
->make_texture_handle_resident(st
->pipe
, handle
, true);
581 /* Overwrite the texture unit value by the resident handle before
582 * uploading the constant buffer.
584 *(uint64_t *)sampler
->data
= handle
;
586 /* Store the handle in the context. */
587 bound_handles
->handles
= (uint64_t *)
588 realloc(bound_handles
->handles
,
589 (bound_handles
->num_handles
+ 1) * sizeof(uint64_t));
590 bound_handles
->handles
[bound_handles
->num_handles
] = handle
;
591 bound_handles
->num_handles
++;
597 * Make all bindless images bound to image units resident in the context.
600 st_make_bound_images_resident(struct st_context
*st
,
601 struct gl_program
*prog
)
603 enum pipe_shader_type shader
= pipe_shader_type_from_mesa(prog
->info
.stage
);
604 struct st_bound_handles
*bound_handles
= &st
->bound_image_handles
[shader
];
605 struct pipe_context
*pipe
= st
->pipe
;
609 /* Remove previous bound image handles for this stage. */
610 st_destroy_bound_image_handles_per_stage(st
, shader
);
612 if (likely(!prog
->sh
.HasBoundBindlessImage
))
615 for (i
= 0; i
< prog
->sh
.NumBindlessImages
; i
++) {
616 struct gl_bindless_image
*image
= &prog
->sh
.BindlessImages
[i
];
621 /* Request a new image handle from the driver and make it resident. */
622 handle
= st_create_image_handle_from_unit(st
, prog
, image
->unit
);
626 pipe
->make_image_handle_resident(st
->pipe
, handle
, GL_READ_WRITE
, true);
628 /* Overwrite the image unit value by the resident handle before uploading
629 * the constant buffer.
631 *(uint64_t *)image
->data
= handle
;
633 /* Store the handle in the context. */
634 bound_handles
->handles
= (uint64_t *)
635 realloc(bound_handles
->handles
,
636 (bound_handles
->num_handles
+ 1) * sizeof(uint64_t));
637 bound_handles
->handles
[bound_handles
->num_handles
] = handle
;
638 bound_handles
->num_handles
++;