2 * Copyright 2007 VMware, Inc.
3 * Copyright 2016 Advanced Micro Devices, Inc.
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * on the rights to use, copy, modify, merge, publish, distribute, sub
9 * license, and/or sell copies of the Software, and to permit persons to whom
10 * the Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,
20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22 * USE OR OTHER DEALINGS IN THE SOFTWARE.
28 * Common helper functions for PBO up- and downloads.
31 #include "state_tracker/st_context.h"
32 #include "state_tracker/st_pbo.h"
33 #include "state_tracker/st_cb_bufferobjects.h"
35 #include "pipe/p_context.h"
36 #include "pipe/p_defines.h"
37 #include "pipe/p_screen.h"
38 #include "cso_cache/cso_context.h"
39 #include "tgsi/tgsi_ureg.h"
40 #include "util/u_format.h"
41 #include "util/u_inlines.h"
42 #include "util/u_upload_mgr.h"
44 /* Conversion to apply in the fragment shader. */
45 enum st_pbo_conversion
{
46 ST_PBO_CONVERT_NONE
= 0,
47 ST_PBO_CONVERT_UINT_TO_SINT
,
48 ST_PBO_CONVERT_SINT_TO_UINT
,
50 ST_NUM_PBO_CONVERSIONS
53 /* Final setup of buffer addressing information.
55 * buf_offset is in pixels.
57 * Returns false if something (e.g. alignment) prevents PBO upload/download.
60 st_pbo_addresses_setup(struct st_context
*st
,
61 struct pipe_resource
*buf
, intptr_t buf_offset
,
62 struct st_pbo_addresses
*addr
)
66 /* Check alignment against texture buffer requirements. */
68 unsigned ofs
= (buf_offset
* addr
->bytes_per_pixel
) % st
->ctx
->Const
.TextureBufferOffsetAlignment
;
70 if (ofs
% addr
->bytes_per_pixel
!= 0)
73 skip_pixels
= ofs
/ addr
->bytes_per_pixel
;
74 buf_offset
-= skip_pixels
;
80 assert(buf_offset
>= 0);
83 addr
->first_element
= buf_offset
;
84 addr
->last_element
= buf_offset
+ skip_pixels
+ addr
->width
- 1
85 + (addr
->height
- 1 + (addr
->depth
- 1) * addr
->image_height
) * addr
->pixels_per_row
;
87 if (addr
->last_element
- addr
->first_element
> st
->ctx
->Const
.MaxTextureBufferSize
- 1)
90 /* This should be ensured by Mesa before calling our callbacks */
91 assert((addr
->last_element
+ 1) * addr
->bytes_per_pixel
<= buf
->width0
);
93 addr
->constants
.xoffset
= -addr
->xoffset
+ skip_pixels
;
94 addr
->constants
.yoffset
= -addr
->yoffset
;
95 addr
->constants
.stride
= addr
->pixels_per_row
;
96 addr
->constants
.image_size
= addr
->pixels_per_row
* addr
->image_height
;
97 addr
->constants
.layer_offset
= 0;
102 /* Validate and fill buffer addressing information based on GL pixelstore
105 * Returns false if some aspect of the addressing (e.g. alignment) prevents
106 * PBO upload/download.
109 st_pbo_addresses_pixelstore(struct st_context
*st
,
110 GLenum gl_target
, bool skip_images
,
111 const struct gl_pixelstore_attrib
*store
,
113 struct st_pbo_addresses
*addr
)
115 struct pipe_resource
*buf
= st_buffer_object(store
->BufferObj
)->buffer
;
116 intptr_t buf_offset
= (intptr_t) pixels
;
118 if (buf_offset
% addr
->bytes_per_pixel
)
121 /* Convert to texels */
122 buf_offset
= buf_offset
/ addr
->bytes_per_pixel
;
124 /* Determine image height */
125 if (gl_target
== GL_TEXTURE_1D_ARRAY
) {
126 addr
->image_height
= 1;
128 addr
->image_height
= store
->ImageHeight
> 0 ? store
->ImageHeight
: addr
->height
;
131 /* Compute the stride, taking store->Alignment into account */
133 unsigned pixels_per_row
= store
->RowLength
> 0 ?
134 store
->RowLength
: addr
->width
;
135 unsigned bytes_per_row
= pixels_per_row
* addr
->bytes_per_pixel
;
136 unsigned remainder
= bytes_per_row
% store
->Alignment
;
137 unsigned offset_rows
;
140 bytes_per_row
+= store
->Alignment
- remainder
;
142 if (bytes_per_row
% addr
->bytes_per_pixel
)
145 addr
->pixels_per_row
= bytes_per_row
/ addr
->bytes_per_pixel
;
147 offset_rows
= store
->SkipRows
;
149 offset_rows
+= addr
->image_height
* store
->SkipImages
;
151 buf_offset
+= store
->SkipPixels
+ addr
->pixels_per_row
* offset_rows
;
154 if (!st_pbo_addresses_setup(st
, buf
, buf_offset
, addr
))
157 /* Support GL_PACK_INVERT_MESA */
159 addr
->constants
.xoffset
+= (addr
->height
- 1) * addr
->constants
.stride
;
160 addr
->constants
.stride
= -addr
->constants
.stride
;
166 /* For download from a framebuffer, we may have to invert the Y axis. The
167 * setup is as follows:
168 * - set viewport to inverted, so that the position sysval is correct for
170 * - this function adjusts the fragment shader's constant buffer to compute
171 * the correct destination addresses.
174 st_pbo_addresses_invert_y(struct st_pbo_addresses
*addr
,
175 unsigned viewport_height
)
177 addr
->constants
.xoffset
+=
178 (viewport_height
- 1 + 2 * addr
->constants
.yoffset
) * addr
->constants
.stride
;
179 addr
->constants
.stride
= -addr
->constants
.stride
;
182 /* Setup all vertex pipeline state, rasterizer state, and fragment shader
183 * constants, and issue the draw call for PBO upload/download.
185 * The caller is responsible for saving and restoring state, as well as for
186 * setting other fragment shader state (fragment shader, samplers), and
187 * framebuffer/viewport/DSA/blend state.
190 st_pbo_draw(struct st_context
*st
, const struct st_pbo_addresses
*addr
,
191 unsigned surface_width
, unsigned surface_height
)
193 struct cso_context
*cso
= st
->cso_context
;
195 /* Setup vertex and geometry shaders */
197 st
->pbo
.vs
= st_pbo_create_vs(st
);
202 if (addr
->depth
!= 1 && st
->pbo
.use_gs
&& !st
->pbo
.gs
) {
203 st
->pbo
.gs
= st_pbo_create_gs(st
);
208 cso_set_vertex_shader_handle(cso
, st
->pbo
.vs
);
210 cso_set_geometry_shader_handle(cso
, addr
->depth
!= 1 ? st
->pbo
.gs
: NULL
);
212 cso_set_tessctrl_shader_handle(cso
, NULL
);
214 cso_set_tesseval_shader_handle(cso
, NULL
);
216 /* Upload vertices */
218 struct pipe_vertex_buffer vbo
;
219 struct pipe_vertex_element velem
;
221 float x0
= (float) addr
->xoffset
/ surface_width
* 2.0f
- 1.0f
;
222 float y0
= (float) addr
->yoffset
/ surface_height
* 2.0f
- 1.0f
;
223 float x1
= (float) (addr
->xoffset
+ addr
->width
) / surface_width
* 2.0f
- 1.0f
;
224 float y1
= (float) (addr
->yoffset
+ addr
->height
) / surface_height
* 2.0f
- 1.0f
;
228 vbo
.user_buffer
= NULL
;
230 vbo
.stride
= 2 * sizeof(float);
232 u_upload_alloc(st
->pipe
->stream_uploader
, 0, 8 * sizeof(float), 4,
233 &vbo
.buffer_offset
, &vbo
.buffer
, (void **) &verts
);
246 u_upload_unmap(st
->pipe
->stream_uploader
);
248 velem
.src_offset
= 0;
249 velem
.instance_divisor
= 0;
250 velem
.vertex_buffer_index
= cso_get_aux_vertex_buffer_slot(cso
);
251 velem
.src_format
= PIPE_FORMAT_R32G32_FLOAT
;
253 cso_set_vertex_elements(cso
, 1, &velem
);
255 cso_set_vertex_buffers(cso
, velem
.vertex_buffer_index
, 1, &vbo
);
257 pipe_resource_reference(&vbo
.buffer
, NULL
);
260 /* Upload constants */
262 struct pipe_constant_buffer cb
;
264 if (!st
->has_user_constbuf
) {
266 cb
.user_buffer
= NULL
;
267 u_upload_data(st
->pipe
->const_uploader
, 0, sizeof(addr
->constants
),
268 st
->ctx
->Const
.UniformBufferOffsetAlignment
,
269 &addr
->constants
, &cb
.buffer_offset
, &cb
.buffer
);
273 u_upload_unmap(st
->pipe
->const_uploader
);
276 cb
.user_buffer
= &addr
->constants
;
277 cb
.buffer_offset
= 0;
279 cb
.buffer_size
= sizeof(addr
->constants
);
281 cso_set_constant_buffer(cso
, PIPE_SHADER_FRAGMENT
, 0, &cb
);
283 pipe_resource_reference(&cb
.buffer
, NULL
);
286 /* Rasterizer state */
287 cso_set_rasterizer(cso
, &st
->pbo
.raster
);
289 /* Disable stream output */
290 cso_set_stream_outputs(cso
, 0, NULL
, 0);
292 if (addr
->depth
== 1) {
293 cso_draw_arrays(cso
, PIPE_PRIM_TRIANGLE_STRIP
, 0, 4);
295 cso_draw_arrays_instanced(cso
, PIPE_PRIM_TRIANGLE_STRIP
,
296 0, 4, 0, addr
->depth
);
303 st_pbo_create_vs(struct st_context
*st
)
305 struct ureg_program
*ureg
;
306 struct ureg_src in_pos
;
307 struct ureg_src in_instanceid
;
308 struct ureg_dst out_pos
;
309 struct ureg_dst out_layer
;
311 ureg
= ureg_create(PIPE_SHADER_VERTEX
);
315 in_pos
= ureg_DECL_vs_input(ureg
, TGSI_SEMANTIC_POSITION
);
317 out_pos
= ureg_DECL_output(ureg
, TGSI_SEMANTIC_POSITION
, 0);
319 if (st
->pbo
.layers
) {
320 in_instanceid
= ureg_DECL_system_value(ureg
, TGSI_SEMANTIC_INSTANCEID
, 0);
323 out_layer
= ureg_DECL_output(ureg
, TGSI_SEMANTIC_LAYER
, 0);
326 /* out_pos = in_pos */
327 ureg_MOV(ureg
, out_pos
, in_pos
);
329 if (st
->pbo
.layers
) {
330 if (st
->pbo
.use_gs
) {
331 /* out_pos.z = i2f(gl_InstanceID) */
332 ureg_I2F(ureg
, ureg_writemask(out_pos
, TGSI_WRITEMASK_Z
),
333 ureg_scalar(in_instanceid
, TGSI_SWIZZLE_X
));
335 /* out_layer = gl_InstanceID */
336 ureg_MOV(ureg
, ureg_writemask(out_layer
, TGSI_WRITEMASK_X
),
337 ureg_scalar(in_instanceid
, TGSI_SWIZZLE_X
));
343 return ureg_create_shader_and_destroy(ureg
, st
->pipe
);
347 st_pbo_create_gs(struct st_context
*st
)
349 static const int zero
= 0;
350 struct ureg_program
*ureg
;
351 struct ureg_dst out_pos
;
352 struct ureg_dst out_layer
;
353 struct ureg_src in_pos
;
357 ureg
= ureg_create(PIPE_SHADER_GEOMETRY
);
361 ureg_property(ureg
, TGSI_PROPERTY_GS_INPUT_PRIM
, PIPE_PRIM_TRIANGLES
);
362 ureg_property(ureg
, TGSI_PROPERTY_GS_OUTPUT_PRIM
, PIPE_PRIM_TRIANGLE_STRIP
);
363 ureg_property(ureg
, TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES
, 3);
365 out_pos
= ureg_DECL_output(ureg
, TGSI_SEMANTIC_POSITION
, 0);
366 out_layer
= ureg_DECL_output(ureg
, TGSI_SEMANTIC_LAYER
, 0);
368 in_pos
= ureg_DECL_input(ureg
, TGSI_SEMANTIC_POSITION
, 0, 0, 1);
370 imm
= ureg_DECL_immediate_int(ureg
, &zero
, 1);
372 for (i
= 0; i
< 3; ++i
) {
373 struct ureg_src in_pos_vertex
= ureg_src_dimension(in_pos
, i
);
375 /* out_pos = in_pos[i] */
376 ureg_MOV(ureg
, out_pos
, in_pos_vertex
);
378 /* out_layer.x = f2i(in_pos[i].z) */
379 ureg_F2I(ureg
, ureg_writemask(out_layer
, TGSI_WRITEMASK_X
),
380 ureg_scalar(in_pos_vertex
, TGSI_SWIZZLE_Z
));
382 ureg_EMIT(ureg
, ureg_scalar(imm
, TGSI_SWIZZLE_X
));
387 return ureg_create_shader_and_destroy(ureg
, st
->pipe
);
391 build_conversion(struct ureg_program
*ureg
, const struct ureg_dst
*temp
,
392 enum st_pbo_conversion conversion
)
394 switch (conversion
) {
395 case ST_PBO_CONVERT_SINT_TO_UINT
:
396 ureg_IMAX(ureg
, *temp
, ureg_src(*temp
), ureg_imm1i(ureg
, 0));
398 case ST_PBO_CONVERT_UINT_TO_SINT
:
399 ureg_UMIN(ureg
, *temp
, ureg_src(*temp
), ureg_imm1u(ureg
, (1u << 31) - 1));
408 create_fs(struct st_context
*st
, bool download
, enum pipe_texture_target target
,
409 enum st_pbo_conversion conversion
)
411 struct pipe_context
*pipe
= st
->pipe
;
412 struct pipe_screen
*screen
= pipe
->screen
;
413 struct ureg_program
*ureg
;
416 struct ureg_src sampler
;
418 struct ureg_src layer
;
419 struct ureg_src const0
;
420 struct ureg_src const1
;
421 struct ureg_dst temp0
;
425 (!download
|| target
== PIPE_TEXTURE_1D_ARRAY
426 || target
== PIPE_TEXTURE_2D_ARRAY
427 || target
== PIPE_TEXTURE_3D
428 || target
== PIPE_TEXTURE_CUBE
429 || target
== PIPE_TEXTURE_CUBE_ARRAY
);
431 ureg
= ureg_create(PIPE_SHADER_FRAGMENT
);
436 out
= ureg_DECL_output(ureg
, TGSI_SEMANTIC_COLOR
, 0);
438 struct ureg_src image
;
440 /* writeonly images do not require an explicitly given format. */
441 image
= ureg_DECL_image(ureg
, 0, TGSI_TEXTURE_BUFFER
, PIPE_FORMAT_NONE
,
443 out
= ureg_dst(image
);
446 sampler
= ureg_DECL_sampler(ureg
, 0);
447 if (screen
->get_param(screen
, PIPE_CAP_TGSI_FS_POSITION_IS_SYSVAL
)) {
448 pos
= ureg_DECL_system_value(ureg
, TGSI_SEMANTIC_POSITION
, 0);
450 pos
= ureg_DECL_fs_input(ureg
, TGSI_SEMANTIC_POSITION
, 0,
451 TGSI_INTERPOLATE_LINEAR
);
454 layer
= ureg_DECL_fs_input(ureg
, TGSI_SEMANTIC_LAYER
, 0,
455 TGSI_INTERPOLATE_CONSTANT
);
457 const0
= ureg_DECL_constant(ureg
, 0);
458 const1
= ureg_DECL_constant(ureg
, 1);
459 temp0
= ureg_DECL_temporary(ureg
);
461 /* Note: const0 = [ -xoffset + skip_pixels, -yoffset, stride, image_height ] */
463 /* temp0.xy = f2i(temp0.xy) */
464 ureg_F2I(ureg
, ureg_writemask(temp0
, TGSI_WRITEMASK_XY
),
466 TGSI_SWIZZLE_X
, TGSI_SWIZZLE_Y
,
467 TGSI_SWIZZLE_Y
, TGSI_SWIZZLE_Y
));
469 /* temp0.xy = temp0.xy + const0.xy */
470 ureg_UADD(ureg
, ureg_writemask(temp0
, TGSI_WRITEMASK_XY
),
471 ureg_swizzle(ureg_src(temp0
),
472 TGSI_SWIZZLE_X
, TGSI_SWIZZLE_Y
,
473 TGSI_SWIZZLE_Y
, TGSI_SWIZZLE_Y
),
475 TGSI_SWIZZLE_X
, TGSI_SWIZZLE_Y
,
476 TGSI_SWIZZLE_Y
, TGSI_SWIZZLE_Y
));
478 /* temp0.x = const0.z * temp0.y + temp0.x */
479 ureg_UMAD(ureg
, ureg_writemask(temp0
, TGSI_WRITEMASK_X
),
480 ureg_scalar(const0
, TGSI_SWIZZLE_Z
),
481 ureg_scalar(ureg_src(temp0
), TGSI_SWIZZLE_Y
),
482 ureg_scalar(ureg_src(temp0
), TGSI_SWIZZLE_X
));
485 /* temp0.x = const0.w * layer + temp0.x */
486 ureg_UMAD(ureg
, ureg_writemask(temp0
, TGSI_WRITEMASK_X
),
487 ureg_scalar(const0
, TGSI_SWIZZLE_W
),
488 ureg_scalar(layer
, TGSI_SWIZZLE_X
),
489 ureg_scalar(ureg_src(temp0
), TGSI_SWIZZLE_X
));
493 ureg_MOV(ureg
, ureg_writemask(temp0
, TGSI_WRITEMASK_W
), ureg_imm1u(ureg
, 0));
496 struct ureg_dst temp1
;
497 struct ureg_src op
[2];
499 temp1
= ureg_DECL_temporary(ureg
);
501 /* temp1.xy = pos.xy */
502 ureg_F2I(ureg
, ureg_writemask(temp1
, TGSI_WRITEMASK_XY
), pos
);
505 ureg_MOV(ureg
, ureg_writemask(temp1
, TGSI_WRITEMASK_ZW
), ureg_imm1u(ureg
, 0));
508 struct ureg_dst temp1_layer
=
509 ureg_writemask(temp1
, target
== PIPE_TEXTURE_1D_ARRAY
? TGSI_WRITEMASK_Y
512 /* temp1.y/z = layer */
513 ureg_MOV(ureg
, temp1_layer
, ureg_scalar(layer
, TGSI_SWIZZLE_X
));
515 if (target
== PIPE_TEXTURE_3D
) {
516 /* temp1.z += layer_offset */
517 ureg_UADD(ureg
, temp1_layer
,
518 ureg_scalar(ureg_src(temp1
), TGSI_SWIZZLE_Z
),
519 ureg_scalar(const1
, TGSI_SWIZZLE_X
));
523 /* temp1 = txf(sampler, temp1) */
524 ureg_TXF(ureg
, temp1
, util_pipe_tex_to_tgsi_tex(target
, 1),
525 ureg_src(temp1
), sampler
);
527 build_conversion(ureg
, &temp1
, conversion
);
529 /* store(out, temp0, temp1) */
530 op
[0] = ureg_src(temp0
);
531 op
[1] = ureg_src(temp1
);
532 ureg_memory_insn(ureg
, TGSI_OPCODE_STORE
, &out
, 1, op
, 2, 0,
533 TGSI_TEXTURE_BUFFER
, PIPE_FORMAT_NONE
);
535 ureg_release_temporary(ureg
, temp1
);
537 /* out = txf(sampler, temp0.x) */
538 ureg_TXF(ureg
, temp0
, TGSI_TEXTURE_BUFFER
, ureg_src(temp0
), sampler
);
540 build_conversion(ureg
, &temp0
, conversion
);
542 ureg_MOV(ureg
, out
, ureg_src(temp0
));
545 ureg_release_temporary(ureg
, temp0
);
549 return ureg_create_shader_and_destroy(ureg
, pipe
);
552 static enum st_pbo_conversion
553 get_pbo_conversion(enum pipe_format src_format
, enum pipe_format dst_format
)
555 if (util_format_is_pure_uint(src_format
)) {
556 if (util_format_is_pure_sint(dst_format
))
557 return ST_PBO_CONVERT_UINT_TO_SINT
;
558 } else if (util_format_is_pure_sint(src_format
)) {
559 if (util_format_is_pure_uint(dst_format
))
560 return ST_PBO_CONVERT_SINT_TO_UINT
;
563 return ST_PBO_CONVERT_NONE
;
567 st_pbo_get_upload_fs(struct st_context
*st
,
568 enum pipe_format src_format
,
569 enum pipe_format dst_format
)
571 STATIC_ASSERT(ARRAY_SIZE(st
->pbo
.upload_fs
) == ST_NUM_PBO_CONVERSIONS
);
573 enum st_pbo_conversion conversion
= get_pbo_conversion(src_format
, dst_format
);
575 if (!st
->pbo
.upload_fs
[conversion
])
576 st
->pbo
.upload_fs
[conversion
] = create_fs(st
, false, 0, conversion
);
578 return st
->pbo
.upload_fs
[conversion
];
582 st_pbo_get_download_fs(struct st_context
*st
, enum pipe_texture_target target
,
583 enum pipe_format src_format
,
584 enum pipe_format dst_format
)
586 STATIC_ASSERT(ARRAY_SIZE(st
->pbo
.download_fs
) == ST_NUM_PBO_CONVERSIONS
);
587 assert(target
< PIPE_MAX_TEXTURE_TYPES
);
589 enum st_pbo_conversion conversion
= get_pbo_conversion(src_format
, dst_format
);
591 if (!st
->pbo
.download_fs
[conversion
][target
])
592 st
->pbo
.download_fs
[conversion
][target
] = create_fs(st
, true, target
, conversion
);
594 return st
->pbo
.download_fs
[conversion
][target
];
598 st_init_pbo_helpers(struct st_context
*st
)
600 struct pipe_context
*pipe
= st
->pipe
;
601 struct pipe_screen
*screen
= pipe
->screen
;
603 st
->pbo
.upload_enabled
=
604 screen
->get_param(screen
, PIPE_CAP_TEXTURE_BUFFER_OBJECTS
) &&
605 screen
->get_param(screen
, PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT
) >= 1 &&
606 screen
->get_shader_param(screen
, PIPE_SHADER_FRAGMENT
, PIPE_SHADER_CAP_INTEGERS
);
607 if (!st
->pbo
.upload_enabled
)
610 st
->pbo
.download_enabled
=
611 st
->pbo
.upload_enabled
&&
612 screen
->get_param(screen
, PIPE_CAP_SAMPLER_VIEW_TARGET
) &&
613 screen
->get_param(screen
, PIPE_CAP_FRAMEBUFFER_NO_ATTACHMENT
) &&
614 screen
->get_shader_param(screen
, PIPE_SHADER_FRAGMENT
,
615 PIPE_SHADER_CAP_MAX_SHADER_IMAGES
) >= 1;
618 screen
->get_param(screen
, PIPE_CAP_BUFFER_SAMPLER_VIEW_RGBA_ONLY
);
620 if (screen
->get_param(screen
, PIPE_CAP_TGSI_INSTANCEID
)) {
621 if (screen
->get_param(screen
, PIPE_CAP_TGSI_VS_LAYER_VIEWPORT
)) {
622 st
->pbo
.layers
= true;
623 } else if (screen
->get_param(screen
, PIPE_CAP_MAX_GEOMETRY_OUTPUT_VERTICES
) >= 3) {
624 st
->pbo
.layers
= true;
625 st
->pbo
.use_gs
= true;
630 memset(&st
->pbo
.upload_blend
, 0, sizeof(struct pipe_blend_state
));
631 st
->pbo
.upload_blend
.rt
[0].colormask
= PIPE_MASK_RGBA
;
633 /* Rasterizer state */
634 memset(&st
->pbo
.raster
, 0, sizeof(struct pipe_rasterizer_state
));
635 st
->pbo
.raster
.half_pixel_center
= 1;
639 st_destroy_pbo_helpers(struct st_context
*st
)
643 for (i
= 0; i
< ARRAY_SIZE(st
->pbo
.upload_fs
); ++i
) {
644 if (st
->pbo
.upload_fs
[i
]) {
645 cso_delete_fragment_shader(st
->cso_context
, st
->pbo
.upload_fs
[i
]);
646 st
->pbo
.upload_fs
[i
] = NULL
;
650 for (i
= 0; i
< ARRAY_SIZE(st
->pbo
.download_fs
); ++i
) {
651 for (unsigned j
= 0; j
< ARRAY_SIZE(st
->pbo
.download_fs
[0]); ++j
) {
652 if (st
->pbo
.download_fs
[i
][j
]) {
653 cso_delete_fragment_shader(st
->cso_context
, st
->pbo
.download_fs
[i
][j
]);
654 st
->pbo
.download_fs
[i
][j
] = NULL
;
660 cso_delete_geometry_shader(st
->cso_context
, st
->pbo
.gs
);
665 cso_delete_vertex_shader(st
->cso_context
, st
->pbo
.vs
);