1 /**************************************************************************
3 * Copyright 2009 Marek Olšák <maraeo@gmail.com>
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 **************************************************************************/
29 * Blitter utility to facilitate acceleration of the clear, clear_render_target,
30 * clear_depth_stencil, and resource_copy_region functions.
35 #include "pipe/p_context.h"
36 #include "pipe/p_defines.h"
37 #include "util/u_inlines.h"
38 #include "pipe/p_shader_tokens.h"
39 #include "pipe/p_state.h"
41 #include "util/u_format.h"
42 #include "util/u_memory.h"
43 #include "util/u_math.h"
44 #include "util/u_blitter.h"
45 #include "util/u_draw_quad.h"
46 #include "util/u_sampler.h"
47 #include "util/u_simple_shaders.h"
48 #include "util/u_surface.h"
49 #include "util/u_texture.h"
50 #include "util/u_upload_mgr.h"
52 #define INVALID_PTR ((void*)~0)
54 struct blitter_context_priv
56 struct blitter_context base
;
58 struct u_upload_mgr
*upload
;
60 float vertices
[4][2][4]; /**< {pos, color} or {pos, texcoord} */
62 /* Templates for various state objects. */
64 /* Constant state objects. */
66 void *vs
; /**< Vertex shader which passes {pos, generic} to the output.*/
67 void *vs_pos_only
; /**< Vertex shader which passes pos to the output.*/
69 /* Fragment shaders. */
70 /* The shader at index i outputs color to color buffers 0,1,...,i-1. */
71 void *fs_col
[PIPE_MAX_COLOR_BUFS
+1];
72 void *fs_col_int
[PIPE_MAX_COLOR_BUFS
+1];
74 /* FS which outputs a color from a texture,
75 where the index is PIPE_TEXTURE_* to be sampled. */
76 void *fs_texfetch_col
[PIPE_MAX_TEXTURE_TYPES
];
78 /* FS which outputs a depth from a texture,
79 where the index is PIPE_TEXTURE_* to be sampled. */
80 void *fs_texfetch_depth
[PIPE_MAX_TEXTURE_TYPES
];
81 void *fs_texfetch_depthstencil
[PIPE_MAX_TEXTURE_TYPES
];
82 void *fs_texfetch_stencil
[PIPE_MAX_TEXTURE_TYPES
];
85 void *blend_write_color
; /**< blend state with writemask of RGBA */
86 void *blend_keep_color
; /**< blend state with writemask of 0 */
88 /* Depth stencil alpha state. */
89 void *dsa_write_depth_stencil
;
90 void *dsa_write_depth_keep_stencil
;
91 void *dsa_keep_depth_stencil
;
92 void *dsa_keep_depth_write_stencil
;
94 /* Vertex elements states. */
96 void *velem_uint_state
;
97 void *velem_sint_state
;
98 void *velem_state_readbuf
;
103 /* Rasterizer state. */
105 void *rs_discard_state
;
107 /* Viewport state. */
108 struct pipe_viewport_state viewport
;
110 /* Destination surface dimensions. */
114 boolean has_geometry_shader
;
115 boolean vertex_has_integers
;
116 boolean has_stream_out
;
117 boolean has_stencil_export
;
120 static void blitter_draw_rectangle(struct blitter_context
*blitter
,
121 unsigned x
, unsigned y
,
122 unsigned width
, unsigned height
,
124 enum blitter_attrib_type type
,
125 const union pipe_color_union
*attrib
);
128 struct blitter_context
*util_blitter_create(struct pipe_context
*pipe
)
130 struct blitter_context_priv
*ctx
;
131 struct pipe_blend_state blend
;
132 struct pipe_depth_stencil_alpha_state dsa
;
133 struct pipe_rasterizer_state rs_state
;
134 struct pipe_sampler_state sampler_state
;
135 struct pipe_vertex_element velem
[2];
138 ctx
= CALLOC_STRUCT(blitter_context_priv
);
142 ctx
->base
.pipe
= pipe
;
143 ctx
->base
.draw_rectangle
= blitter_draw_rectangle
;
145 /* init state objects for them to be considered invalid */
146 ctx
->base
.saved_blend_state
= INVALID_PTR
;
147 ctx
->base
.saved_dsa_state
= INVALID_PTR
;
148 ctx
->base
.saved_rs_state
= INVALID_PTR
;
149 ctx
->base
.saved_fs
= INVALID_PTR
;
150 ctx
->base
.saved_vs
= INVALID_PTR
;
151 ctx
->base
.saved_gs
= INVALID_PTR
;
152 ctx
->base
.saved_velem_state
= INVALID_PTR
;
153 ctx
->base
.saved_fb_state
.nr_cbufs
= ~0;
154 ctx
->base
.saved_num_sampler_views
= ~0;
155 ctx
->base
.saved_num_sampler_states
= ~0;
156 ctx
->base
.saved_num_vertex_buffers
= ~0;
157 ctx
->base
.saved_num_so_targets
= ~0;
159 ctx
->has_geometry_shader
=
160 pipe
->screen
->get_shader_param(pipe
->screen
, PIPE_SHADER_GEOMETRY
,
161 PIPE_SHADER_CAP_MAX_INSTRUCTIONS
) > 0;
162 ctx
->vertex_has_integers
=
163 pipe
->screen
->get_shader_param(pipe
->screen
, PIPE_SHADER_VERTEX
,
164 PIPE_SHADER_CAP_INTEGERS
);
165 ctx
->has_stream_out
=
166 pipe
->screen
->get_param(pipe
->screen
,
167 PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS
) != 0;
169 ctx
->has_stencil_export
=
170 pipe
->screen
->get_param(pipe
->screen
,
171 PIPE_CAP_SHADER_STENCIL_EXPORT
);
173 /* blend state objects */
174 memset(&blend
, 0, sizeof(blend
));
175 ctx
->blend_keep_color
= pipe
->create_blend_state(pipe
, &blend
);
177 blend
.rt
[0].colormask
= PIPE_MASK_RGBA
;
178 ctx
->blend_write_color
= pipe
->create_blend_state(pipe
, &blend
);
180 /* depth stencil alpha state objects */
181 memset(&dsa
, 0, sizeof(dsa
));
182 ctx
->dsa_keep_depth_stencil
=
183 pipe
->create_depth_stencil_alpha_state(pipe
, &dsa
);
185 dsa
.depth
.enabled
= 1;
186 dsa
.depth
.writemask
= 1;
187 dsa
.depth
.func
= PIPE_FUNC_ALWAYS
;
188 ctx
->dsa_write_depth_keep_stencil
=
189 pipe
->create_depth_stencil_alpha_state(pipe
, &dsa
);
191 dsa
.stencil
[0].enabled
= 1;
192 dsa
.stencil
[0].func
= PIPE_FUNC_ALWAYS
;
193 dsa
.stencil
[0].fail_op
= PIPE_STENCIL_OP_REPLACE
;
194 dsa
.stencil
[0].zpass_op
= PIPE_STENCIL_OP_REPLACE
;
195 dsa
.stencil
[0].zfail_op
= PIPE_STENCIL_OP_REPLACE
;
196 dsa
.stencil
[0].valuemask
= 0xff;
197 dsa
.stencil
[0].writemask
= 0xff;
198 ctx
->dsa_write_depth_stencil
=
199 pipe
->create_depth_stencil_alpha_state(pipe
, &dsa
);
201 dsa
.depth
.enabled
= 0;
202 dsa
.depth
.writemask
= 0;
203 ctx
->dsa_keep_depth_write_stencil
=
204 pipe
->create_depth_stencil_alpha_state(pipe
, &dsa
);
207 memset(&sampler_state
, 0, sizeof(sampler_state
));
208 sampler_state
.wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
209 sampler_state
.wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
210 sampler_state
.wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
211 sampler_state
.normalized_coords
= 1;
212 ctx
->sampler_state
= pipe
->create_sampler_state(pipe
, &sampler_state
);
214 /* rasterizer state */
215 memset(&rs_state
, 0, sizeof(rs_state
));
216 rs_state
.cull_face
= PIPE_FACE_NONE
;
217 rs_state
.gl_rasterization_rules
= 1;
218 rs_state
.flatshade
= 1;
219 rs_state
.depth_clip
= 1;
220 ctx
->rs_state
= pipe
->create_rasterizer_state(pipe
, &rs_state
);
222 if (ctx
->has_stream_out
) {
223 rs_state
.rasterizer_discard
= 1;
224 ctx
->rs_discard_state
= pipe
->create_rasterizer_state(pipe
, &rs_state
);
227 /* vertex elements states */
228 memset(&velem
[0], 0, sizeof(velem
[0]) * 2);
229 for (i
= 0; i
< 2; i
++) {
230 velem
[i
].src_offset
= i
* 4 * sizeof(float);
231 velem
[i
].src_format
= PIPE_FORMAT_R32G32B32A32_FLOAT
;
233 ctx
->velem_state
= pipe
->create_vertex_elements_state(pipe
, 2, &velem
[0]);
235 if (ctx
->vertex_has_integers
) {
236 memset(&velem
[0], 0, sizeof(velem
[0]) * 2);
237 velem
[0].src_offset
= 0;
238 velem
[0].src_format
= PIPE_FORMAT_R32G32B32A32_FLOAT
;
239 velem
[1].src_offset
= 4 * sizeof(float);
240 velem
[1].src_format
= PIPE_FORMAT_R32G32B32A32_SINT
;
241 ctx
->velem_sint_state
= pipe
->create_vertex_elements_state(pipe
, 2, &velem
[0]);
243 memset(&velem
[0], 0, sizeof(velem
[0]) * 2);
244 velem
[0].src_offset
= 0;
245 velem
[0].src_format
= PIPE_FORMAT_R32G32B32A32_FLOAT
;
246 velem
[1].src_offset
= 4 * sizeof(float);
247 velem
[1].src_format
= PIPE_FORMAT_R32G32B32A32_UINT
;
248 ctx
->velem_uint_state
= pipe
->create_vertex_elements_state(pipe
, 2, &velem
[0]);
251 if (ctx
->has_stream_out
) {
252 velem
[0].src_format
= PIPE_FORMAT_R32_UINT
;
253 ctx
->velem_state_readbuf
= pipe
->create_vertex_elements_state(pipe
, 1, &velem
[0]);
256 /* fragment shaders are created on-demand */
260 const uint semantic_names
[] = { TGSI_SEMANTIC_POSITION
,
261 TGSI_SEMANTIC_GENERIC
};
262 const uint semantic_indices
[] = { 0, 0 };
264 util_make_vertex_passthrough_shader(pipe
, 2, semantic_names
,
267 if (ctx
->has_stream_out
) {
268 struct pipe_stream_output_info so
;
269 const uint semantic_names
[] = { TGSI_SEMANTIC_POSITION
};
270 const uint semantic_indices
[] = { 0 };
272 memset(&so
, 0, sizeof(so
));
274 so
.output
[0].num_components
= 1;
278 util_make_vertex_passthrough_shader_with_so(pipe
, 1, semantic_names
,
279 semantic_indices
, &so
);
282 /* set invariant vertex coordinates */
283 for (i
= 0; i
< 4; i
++)
284 ctx
->vertices
[i
][0][3] = 1; /*v.w*/
286 ctx
->upload
= u_upload_create(pipe
, 65536, 4, PIPE_BIND_VERTEX_BUFFER
);
291 void util_blitter_destroy(struct blitter_context
*blitter
)
293 struct blitter_context_priv
*ctx
= (struct blitter_context_priv
*)blitter
;
294 struct pipe_context
*pipe
= blitter
->pipe
;
297 pipe
->delete_blend_state(pipe
, ctx
->blend_write_color
);
298 pipe
->delete_blend_state(pipe
, ctx
->blend_keep_color
);
299 pipe
->delete_depth_stencil_alpha_state(pipe
, ctx
->dsa_keep_depth_stencil
);
300 pipe
->delete_depth_stencil_alpha_state(pipe
,
301 ctx
->dsa_write_depth_keep_stencil
);
302 pipe
->delete_depth_stencil_alpha_state(pipe
, ctx
->dsa_write_depth_stencil
);
303 pipe
->delete_depth_stencil_alpha_state(pipe
, ctx
->dsa_keep_depth_write_stencil
);
305 pipe
->delete_rasterizer_state(pipe
, ctx
->rs_state
);
306 if (ctx
->rs_discard_state
)
307 pipe
->delete_rasterizer_state(pipe
, ctx
->rs_discard_state
);
308 pipe
->delete_vs_state(pipe
, ctx
->vs
);
309 if (ctx
->vs_pos_only
)
310 pipe
->delete_vs_state(pipe
, ctx
->vs_pos_only
);
311 pipe
->delete_vertex_elements_state(pipe
, ctx
->velem_state
);
312 if (ctx
->vertex_has_integers
) {
313 pipe
->delete_vertex_elements_state(pipe
, ctx
->velem_sint_state
);
314 pipe
->delete_vertex_elements_state(pipe
, ctx
->velem_uint_state
);
316 if (ctx
->velem_state_readbuf
)
317 pipe
->delete_vertex_elements_state(pipe
, ctx
->velem_state_readbuf
);
319 for (i
= 0; i
< PIPE_MAX_TEXTURE_TYPES
; i
++) {
320 if (ctx
->fs_texfetch_col
[i
])
321 pipe
->delete_fs_state(pipe
, ctx
->fs_texfetch_col
[i
]);
322 if (ctx
->fs_texfetch_depth
[i
])
323 pipe
->delete_fs_state(pipe
, ctx
->fs_texfetch_depth
[i
]);
324 if (ctx
->fs_texfetch_depthstencil
[i
])
325 pipe
->delete_fs_state(pipe
, ctx
->fs_texfetch_depthstencil
[i
]);
326 if (ctx
->fs_texfetch_stencil
[i
])
327 pipe
->delete_fs_state(pipe
, ctx
->fs_texfetch_stencil
[i
]);
330 for (i
= 0; i
<= PIPE_MAX_COLOR_BUFS
; i
++) {
332 pipe
->delete_fs_state(pipe
, ctx
->fs_col
[i
]);
333 if (ctx
->fs_col_int
[i
])
334 pipe
->delete_fs_state(pipe
, ctx
->fs_col_int
[i
]);
337 pipe
->delete_sampler_state(pipe
, ctx
->sampler_state
);
338 u_upload_destroy(ctx
->upload
);
342 static void blitter_set_running_flag(struct blitter_context_priv
*ctx
)
344 if (ctx
->base
.running
) {
345 _debug_printf("u_blitter:%i: Caught recursion. This is a driver bug.\n",
348 ctx
->base
.running
= TRUE
;
351 static void blitter_unset_running_flag(struct blitter_context_priv
*ctx
)
353 if (!ctx
->base
.running
) {
354 _debug_printf("u_blitter:%i: Caught recursion. This is a driver bug.\n",
357 ctx
->base
.running
= FALSE
;
360 static void blitter_check_saved_vertex_states(struct blitter_context_priv
*ctx
)
362 assert(ctx
->base
.saved_num_vertex_buffers
!= ~0);
363 assert(ctx
->base
.saved_velem_state
!= INVALID_PTR
);
364 assert(ctx
->base
.saved_vs
!= INVALID_PTR
);
365 assert(!ctx
->has_geometry_shader
|| ctx
->base
.saved_gs
!= INVALID_PTR
);
366 assert(!ctx
->has_stream_out
|| ctx
->base
.saved_num_so_targets
!= ~0);
367 assert(ctx
->base
.saved_rs_state
!= INVALID_PTR
);
370 static void blitter_restore_vertex_states(struct blitter_context_priv
*ctx
)
372 struct pipe_context
*pipe
= ctx
->base
.pipe
;
375 /* Vertex buffers. */
376 pipe
->set_vertex_buffers(pipe
,
377 ctx
->base
.saved_num_vertex_buffers
,
378 ctx
->base
.saved_vertex_buffers
);
380 for (i
= 0; i
< ctx
->base
.saved_num_vertex_buffers
; i
++) {
381 if (ctx
->base
.saved_vertex_buffers
[i
].buffer
) {
382 pipe_resource_reference(&ctx
->base
.saved_vertex_buffers
[i
].buffer
,
386 ctx
->base
.saved_num_vertex_buffers
= ~0;
388 /* Vertex elements. */
389 pipe
->bind_vertex_elements_state(pipe
, ctx
->base
.saved_velem_state
);
390 ctx
->base
.saved_velem_state
= INVALID_PTR
;
393 pipe
->bind_vs_state(pipe
, ctx
->base
.saved_vs
);
394 ctx
->base
.saved_vs
= INVALID_PTR
;
396 /* Geometry shader. */
397 if (ctx
->has_geometry_shader
) {
398 pipe
->bind_gs_state(pipe
, ctx
->base
.saved_gs
);
399 ctx
->base
.saved_gs
= INVALID_PTR
;
402 /* Stream outputs. */
403 if (ctx
->has_stream_out
) {
404 pipe
->set_stream_output_targets(pipe
,
405 ctx
->base
.saved_num_so_targets
,
406 ctx
->base
.saved_so_targets
, ~0);
408 for (i
= 0; i
< ctx
->base
.saved_num_so_targets
; i
++)
409 pipe_so_target_reference(&ctx
->base
.saved_so_targets
[i
], NULL
);
411 ctx
->base
.saved_num_so_targets
= ~0;
415 pipe
->bind_rasterizer_state(pipe
, ctx
->base
.saved_rs_state
);
416 ctx
->base
.saved_rs_state
= INVALID_PTR
;
419 static void blitter_check_saved_fragment_states(struct blitter_context_priv
*ctx
)
421 assert(ctx
->base
.saved_fs
!= INVALID_PTR
);
422 assert(ctx
->base
.saved_dsa_state
!= INVALID_PTR
);
423 assert(ctx
->base
.saved_blend_state
!= INVALID_PTR
);
426 static void blitter_restore_fragment_states(struct blitter_context_priv
*ctx
)
428 struct pipe_context
*pipe
= ctx
->base
.pipe
;
430 /* Fragment shader. */
431 pipe
->bind_fs_state(pipe
, ctx
->base
.saved_fs
);
432 ctx
->base
.saved_fs
= INVALID_PTR
;
434 /* Depth, stencil, alpha. */
435 pipe
->bind_depth_stencil_alpha_state(pipe
, ctx
->base
.saved_dsa_state
);
436 ctx
->base
.saved_dsa_state
= INVALID_PTR
;
439 pipe
->bind_blend_state(pipe
, ctx
->base
.saved_blend_state
);
440 ctx
->base
.saved_blend_state
= INVALID_PTR
;
443 if (ctx
->base
.is_sample_mask_saved
) {
444 pipe
->set_sample_mask(pipe
, ctx
->base
.saved_sample_mask
);
445 ctx
->base
.is_sample_mask_saved
= FALSE
;
448 /* Miscellaneous states. */
449 /* XXX check whether these are saved and whether they need to be restored
450 * (depending on the operation) */
451 pipe
->set_stencil_ref(pipe
, &ctx
->base
.saved_stencil_ref
);
452 pipe
->set_viewport_state(pipe
, &ctx
->base
.saved_viewport
);
455 static void blitter_check_saved_fb_state(struct blitter_context_priv
*ctx
)
457 assert(ctx
->base
.saved_fb_state
.nr_cbufs
!= ~0);
460 static void blitter_restore_fb_state(struct blitter_context_priv
*ctx
)
462 struct pipe_context
*pipe
= ctx
->base
.pipe
;
464 pipe
->set_framebuffer_state(pipe
, &ctx
->base
.saved_fb_state
);
465 util_unreference_framebuffer_state(&ctx
->base
.saved_fb_state
);
468 static void blitter_check_saved_textures(struct blitter_context_priv
*ctx
)
470 assert(ctx
->base
.saved_num_sampler_states
!= ~0);
471 assert(ctx
->base
.saved_num_sampler_views
!= ~0);
474 static void blitter_restore_textures(struct blitter_context_priv
*ctx
)
476 struct pipe_context
*pipe
= ctx
->base
.pipe
;
479 /* Fragment sampler states. */
480 pipe
->bind_fragment_sampler_states(pipe
,
481 ctx
->base
.saved_num_sampler_states
,
482 ctx
->base
.saved_sampler_states
);
483 ctx
->base
.saved_num_sampler_states
= ~0;
485 /* Fragment sampler views. */
486 pipe
->set_fragment_sampler_views(pipe
,
487 ctx
->base
.saved_num_sampler_views
,
488 ctx
->base
.saved_sampler_views
);
490 for (i
= 0; i
< ctx
->base
.saved_num_sampler_views
; i
++)
491 pipe_sampler_view_reference(&ctx
->base
.saved_sampler_views
[i
], NULL
);
493 ctx
->base
.saved_num_sampler_views
= ~0;
496 static void blitter_set_rectangle(struct blitter_context_priv
*ctx
,
497 unsigned x1
, unsigned y1
,
498 unsigned x2
, unsigned y2
,
503 /* set vertex positions */
504 ctx
->vertices
[0][0][0] = (float)x1
/ ctx
->dst_width
* 2.0f
- 1.0f
; /*v0.x*/
505 ctx
->vertices
[0][0][1] = (float)y1
/ ctx
->dst_height
* 2.0f
- 1.0f
; /*v0.y*/
507 ctx
->vertices
[1][0][0] = (float)x2
/ ctx
->dst_width
* 2.0f
- 1.0f
; /*v1.x*/
508 ctx
->vertices
[1][0][1] = (float)y1
/ ctx
->dst_height
* 2.0f
- 1.0f
; /*v1.y*/
510 ctx
->vertices
[2][0][0] = (float)x2
/ ctx
->dst_width
* 2.0f
- 1.0f
; /*v2.x*/
511 ctx
->vertices
[2][0][1] = (float)y2
/ ctx
->dst_height
* 2.0f
- 1.0f
; /*v2.y*/
513 ctx
->vertices
[3][0][0] = (float)x1
/ ctx
->dst_width
* 2.0f
- 1.0f
; /*v3.x*/
514 ctx
->vertices
[3][0][1] = (float)y2
/ ctx
->dst_height
* 2.0f
- 1.0f
; /*v3.y*/
516 for (i
= 0; i
< 4; i
++)
517 ctx
->vertices
[i
][0][2] = depth
; /*z*/
520 ctx
->viewport
.scale
[0] = 0.5f
* ctx
->dst_width
;
521 ctx
->viewport
.scale
[1] = 0.5f
* ctx
->dst_height
;
522 ctx
->viewport
.scale
[2] = 1.0f
;
523 ctx
->viewport
.scale
[3] = 1.0f
;
524 ctx
->viewport
.translate
[0] = 0.5f
* ctx
->dst_width
;
525 ctx
->viewport
.translate
[1] = 0.5f
* ctx
->dst_height
;
526 ctx
->viewport
.translate
[2] = 0.0f
;
527 ctx
->viewport
.translate
[3] = 0.0f
;
528 ctx
->base
.pipe
->set_viewport_state(ctx
->base
.pipe
, &ctx
->viewport
);
531 static void blitter_set_clear_color(struct blitter_context_priv
*ctx
,
532 const union pipe_color_union
*color
)
537 for (i
= 0; i
< 4; i
++) {
538 uint32_t *uiverts
= (uint32_t *)ctx
->vertices
[i
][1];
539 uiverts
[0] = color
->ui
[0];
540 uiverts
[1] = color
->ui
[1];
541 uiverts
[2] = color
->ui
[2];
542 uiverts
[3] = color
->ui
[3];
545 for (i
= 0; i
< 4; i
++) {
546 ctx
->vertices
[i
][1][0] = 0;
547 ctx
->vertices
[i
][1][1] = 0;
548 ctx
->vertices
[i
][1][2] = 0;
549 ctx
->vertices
[i
][1][3] = 0;
554 static void get_texcoords(struct pipe_sampler_view
*src
,
555 unsigned src_width0
, unsigned src_height0
,
556 unsigned x1
, unsigned y1
,
557 unsigned x2
, unsigned y2
,
560 struct pipe_resource
*tex
= src
->texture
;
561 unsigned level
= src
->u
.tex
.first_level
;
562 boolean normalized
= tex
->target
!= PIPE_TEXTURE_RECT
;
565 out
[0] = x1
/ (float)u_minify(src_width0
, level
);
566 out
[1] = y1
/ (float)u_minify(src_height0
, level
);
567 out
[2] = x2
/ (float)u_minify(src_width0
, level
);
568 out
[3] = y2
/ (float)u_minify(src_height0
, level
);
577 static void set_texcoords_in_vertices(const float coord
[4],
578 float *out
, unsigned stride
)
580 out
[0] = coord
[0]; /*t0.s*/
581 out
[1] = coord
[1]; /*t0.t*/
583 out
[0] = coord
[2]; /*t1.s*/
584 out
[1] = coord
[1]; /*t1.t*/
586 out
[0] = coord
[2]; /*t2.s*/
587 out
[1] = coord
[3]; /*t2.t*/
589 out
[0] = coord
[0]; /*t3.s*/
590 out
[1] = coord
[3]; /*t3.t*/
593 static void blitter_set_texcoords(struct blitter_context_priv
*ctx
,
594 struct pipe_sampler_view
*src
,
595 unsigned src_width0
, unsigned src_height0
,
597 unsigned x1
, unsigned y1
,
598 unsigned x2
, unsigned y2
)
602 float face_coord
[4][2];
604 get_texcoords(src
, src_width0
, src_height0
, x1
, y1
, x2
, y2
, coord
);
606 if (src
->texture
->target
== PIPE_TEXTURE_CUBE
) {
607 set_texcoords_in_vertices(coord
, &face_coord
[0][0], 2);
608 util_map_texcoords2d_onto_cubemap(layer
,
609 /* pointer, stride in floats */
610 &face_coord
[0][0], 2,
611 &ctx
->vertices
[0][1][0], 8);
613 set_texcoords_in_vertices(coord
, &ctx
->vertices
[0][1][0], 8);
617 switch (src
->texture
->target
) {
618 case PIPE_TEXTURE_3D
:
620 float r
= layer
/ (float)u_minify(src
->texture
->depth0
,
621 src
->u
.tex
.first_level
);
622 for (i
= 0; i
< 4; i
++)
623 ctx
->vertices
[i
][1][2] = r
; /*r*/
627 case PIPE_TEXTURE_1D_ARRAY
:
628 for (i
= 0; i
< 4; i
++)
629 ctx
->vertices
[i
][1][1] = layer
; /*t*/
632 case PIPE_TEXTURE_2D_ARRAY
:
633 for (i
= 0; i
< 4; i
++)
634 ctx
->vertices
[i
][1][2] = layer
; /*r*/
641 static void blitter_set_dst_dimensions(struct blitter_context_priv
*ctx
,
642 unsigned width
, unsigned height
)
644 ctx
->dst_width
= width
;
645 ctx
->dst_height
= height
;
649 void *blitter_get_fs_col(struct blitter_context_priv
*ctx
, unsigned num_cbufs
,
652 struct pipe_context
*pipe
= ctx
->base
.pipe
;
654 assert(num_cbufs
<= PIPE_MAX_COLOR_BUFS
);
657 if (!ctx
->fs_col_int
[num_cbufs
])
658 ctx
->fs_col_int
[num_cbufs
] =
659 util_make_fragment_cloneinput_shader(pipe
, num_cbufs
,
660 TGSI_SEMANTIC_GENERIC
,
661 TGSI_INTERPOLATE_CONSTANT
);
662 return ctx
->fs_col_int
[num_cbufs
];
664 if (!ctx
->fs_col
[num_cbufs
])
665 ctx
->fs_col
[num_cbufs
] =
666 util_make_fragment_cloneinput_shader(pipe
, num_cbufs
,
667 TGSI_SEMANTIC_GENERIC
,
668 TGSI_INTERPOLATE_LINEAR
);
669 return ctx
->fs_col
[num_cbufs
];
674 void *blitter_get_fs_texfetch_col(struct blitter_context_priv
*ctx
,
677 struct pipe_context
*pipe
= ctx
->base
.pipe
;
679 assert(tex_target
< PIPE_MAX_TEXTURE_TYPES
);
681 /* Create the fragment shader on-demand. */
682 if (!ctx
->fs_texfetch_col
[tex_target
]) {
683 unsigned tgsi_tex
= util_pipe_tex_to_tgsi_tex(tex_target
);
685 ctx
->fs_texfetch_col
[tex_target
] =
686 util_make_fragment_tex_shader(pipe
, tgsi_tex
, TGSI_INTERPOLATE_LINEAR
);
689 return ctx
->fs_texfetch_col
[tex_target
];
693 void *blitter_get_fs_texfetch_depth(struct blitter_context_priv
*ctx
,
696 struct pipe_context
*pipe
= ctx
->base
.pipe
;
698 assert(tex_target
< PIPE_MAX_TEXTURE_TYPES
);
700 /* Create the fragment shader on-demand. */
701 if (!ctx
->fs_texfetch_depth
[tex_target
]) {
702 unsigned tgsi_tex
= util_pipe_tex_to_tgsi_tex(tex_target
);
704 ctx
->fs_texfetch_depth
[tex_target
] =
705 util_make_fragment_tex_shader_writedepth(pipe
, tgsi_tex
,
706 TGSI_INTERPOLATE_LINEAR
);
709 return ctx
->fs_texfetch_depth
[tex_target
];
713 void *blitter_get_fs_texfetch_depthstencil(struct blitter_context_priv
*ctx
,
716 struct pipe_context
*pipe
= ctx
->base
.pipe
;
718 assert(tex_target
< PIPE_MAX_TEXTURE_TYPES
);
720 /* Create the fragment shader on-demand. */
721 if (!ctx
->fs_texfetch_depthstencil
[tex_target
]) {
722 unsigned tgsi_tex
= util_pipe_tex_to_tgsi_tex(tex_target
);
724 ctx
->fs_texfetch_depthstencil
[tex_target
] =
725 util_make_fragment_tex_shader_writedepthstencil(pipe
, tgsi_tex
,
726 TGSI_INTERPOLATE_LINEAR
);
729 return ctx
->fs_texfetch_depthstencil
[tex_target
];
733 void *blitter_get_fs_texfetch_stencil(struct blitter_context_priv
*ctx
,
736 struct pipe_context
*pipe
= ctx
->base
.pipe
;
738 assert(tex_target
< PIPE_MAX_TEXTURE_TYPES
);
740 /* Create the fragment shader on-demand. */
741 if (!ctx
->fs_texfetch_stencil
[tex_target
]) {
742 unsigned tgsi_tex
= util_pipe_tex_to_tgsi_tex(tex_target
);
744 ctx
->fs_texfetch_stencil
[tex_target
] =
745 util_make_fragment_tex_shader_writestencil(pipe
, tgsi_tex
,
746 TGSI_INTERPOLATE_LINEAR
);
749 return ctx
->fs_texfetch_stencil
[tex_target
];
752 static void blitter_set_common_draw_rect_state(struct blitter_context_priv
*ctx
)
754 struct pipe_context
*pipe
= ctx
->base
.pipe
;
756 pipe
->bind_rasterizer_state(pipe
, ctx
->rs_state
);
757 pipe
->bind_vs_state(pipe
, ctx
->vs
);
758 if (ctx
->has_geometry_shader
)
759 pipe
->bind_gs_state(pipe
, NULL
);
760 if (ctx
->has_stream_out
)
761 pipe
->set_stream_output_targets(pipe
, 0, NULL
, 0);
764 static void blitter_draw(struct blitter_context_priv
*ctx
,
765 unsigned x1
, unsigned y1
,
766 unsigned x2
, unsigned y2
,
769 struct pipe_resource
*buf
= NULL
;
772 blitter_set_rectangle(ctx
, x1
, y1
, x2
, y2
, depth
);
774 u_upload_data(ctx
->upload
, 0, sizeof(ctx
->vertices
), ctx
->vertices
,
776 u_upload_unmap(ctx
->upload
);
777 util_draw_vertex_buffer(ctx
->base
.pipe
, NULL
, buf
, offset
,
778 PIPE_PRIM_TRIANGLE_FAN
, 4, 2);
779 pipe_resource_reference(&buf
, NULL
);
782 static void blitter_draw_rectangle(struct blitter_context
*blitter
,
783 unsigned x1
, unsigned y1
,
784 unsigned x2
, unsigned y2
,
786 enum blitter_attrib_type type
,
787 const union pipe_color_union
*attrib
)
789 struct blitter_context_priv
*ctx
= (struct blitter_context_priv
*)blitter
;
792 case UTIL_BLITTER_ATTRIB_COLOR
:
793 blitter_set_clear_color(ctx
, attrib
);
796 case UTIL_BLITTER_ATTRIB_TEXCOORD
:
797 set_texcoords_in_vertices(attrib
->f
, &ctx
->vertices
[0][1][0], 8);
803 blitter_draw(ctx
, x1
, y1
, x2
, y2
, depth
);
806 static void util_blitter_clear_custom(struct blitter_context
*blitter
,
807 unsigned width
, unsigned height
,
809 unsigned clear_buffers
,
810 enum pipe_format cbuf_format
,
811 const union pipe_color_union
*color
,
812 double depth
, unsigned stencil
,
813 void *custom_blend
, void *custom_dsa
)
815 struct blitter_context_priv
*ctx
= (struct blitter_context_priv
*)blitter
;
816 struct pipe_context
*pipe
= ctx
->base
.pipe
;
817 struct pipe_stencil_ref sr
= { { 0 } };
818 boolean int_format
= util_format_is_pure_integer(cbuf_format
);
819 assert(num_cbufs
<= PIPE_MAX_COLOR_BUFS
);
821 blitter_set_running_flag(ctx
);
822 blitter_check_saved_vertex_states(ctx
);
823 blitter_check_saved_fragment_states(ctx
);
827 pipe
->bind_blend_state(pipe
, custom_blend
);
828 } else if (clear_buffers
& PIPE_CLEAR_COLOR
) {
829 pipe
->bind_blend_state(pipe
, ctx
->blend_write_color
);
831 pipe
->bind_blend_state(pipe
, ctx
->blend_keep_color
);
835 pipe
->bind_depth_stencil_alpha_state(pipe
, custom_dsa
);
836 } else if ((clear_buffers
& PIPE_CLEAR_DEPTHSTENCIL
) == PIPE_CLEAR_DEPTHSTENCIL
) {
837 pipe
->bind_depth_stencil_alpha_state(pipe
, ctx
->dsa_write_depth_stencil
);
838 } else if (clear_buffers
& PIPE_CLEAR_DEPTH
) {
839 pipe
->bind_depth_stencil_alpha_state(pipe
, ctx
->dsa_write_depth_keep_stencil
);
840 } else if (clear_buffers
& PIPE_CLEAR_STENCIL
) {
841 pipe
->bind_depth_stencil_alpha_state(pipe
, ctx
->dsa_keep_depth_write_stencil
);
843 pipe
->bind_depth_stencil_alpha_state(pipe
, ctx
->dsa_keep_depth_stencil
);
846 sr
.ref_value
[0] = stencil
& 0xff;
847 pipe
->set_stencil_ref(pipe
, &sr
);
849 if (util_format_is_pure_sint(cbuf_format
)) {
850 pipe
->bind_vertex_elements_state(pipe
, ctx
->velem_sint_state
);
851 } else if (util_format_is_pure_uint(cbuf_format
)) {
852 pipe
->bind_vertex_elements_state(pipe
, ctx
->velem_uint_state
);
854 pipe
->bind_vertex_elements_state(pipe
, ctx
->velem_state
);
856 pipe
->bind_fs_state(pipe
, blitter_get_fs_col(ctx
, num_cbufs
, int_format
));
857 pipe
->set_sample_mask(pipe
, ~0);
859 blitter_set_common_draw_rect_state(ctx
);
860 blitter_set_dst_dimensions(ctx
, width
, height
);
861 blitter
->draw_rectangle(blitter
, 0, 0, width
, height
, depth
,
862 UTIL_BLITTER_ATTRIB_COLOR
, color
);
864 blitter_restore_vertex_states(ctx
);
865 blitter_restore_fragment_states(ctx
);
866 blitter_unset_running_flag(ctx
);
869 void util_blitter_clear(struct blitter_context
*blitter
,
870 unsigned width
, unsigned height
,
872 unsigned clear_buffers
,
873 enum pipe_format cbuf_format
,
874 const union pipe_color_union
*color
,
875 double depth
, unsigned stencil
)
877 util_blitter_clear_custom(blitter
, width
, height
, num_cbufs
,
878 clear_buffers
, cbuf_format
, color
, depth
, stencil
,
882 void util_blitter_clear_depth_custom(struct blitter_context
*blitter
,
883 unsigned width
, unsigned height
,
884 double depth
, void *custom_dsa
)
886 static const union pipe_color_union color
;
887 util_blitter_clear_custom(blitter
, width
, height
, 0,
888 0, PIPE_FORMAT_NONE
, &color
, depth
, 0, NULL
, custom_dsa
);
892 boolean
is_overlap(unsigned sx1
, unsigned sx2
, unsigned sy1
, unsigned sy2
,
893 unsigned dx1
, unsigned dx2
, unsigned dy1
, unsigned dy2
)
895 return sx1
< dx2
&& sx2
> dx1
&& sy1
< dy2
&& sy2
> dy1
;
898 void util_blitter_default_dst_texture(struct pipe_surface
*dst_templ
,
899 struct pipe_resource
*dst
,
902 const struct pipe_box
*srcbox
)
904 memset(dst_templ
, 0, sizeof(*dst_templ
));
905 dst_templ
->format
= dst
->format
;
906 if (util_format_is_depth_or_stencil(dst
->format
)) {
907 dst_templ
->usage
= PIPE_BIND_DEPTH_STENCIL
;
909 dst_templ
->usage
= PIPE_BIND_RENDER_TARGET
;
911 dst_templ
->format
= util_format_linear(dst
->format
);
912 dst_templ
->u
.tex
.level
= dstlevel
;
913 dst_templ
->u
.tex
.first_layer
= dstz
;
914 dst_templ
->u
.tex
.last_layer
= dstz
+ srcbox
->depth
- 1;
917 void util_blitter_default_src_texture(struct pipe_sampler_view
*src_templ
,
918 struct pipe_resource
*src
,
921 memset(src_templ
, 0, sizeof(*src_templ
));
922 src_templ
->format
= util_format_linear(src
->format
);
923 src_templ
->u
.tex
.first_level
= srclevel
;
924 src_templ
->u
.tex
.last_level
= srclevel
;
925 src_templ
->u
.tex
.first_layer
= 0;
926 src_templ
->u
.tex
.last_layer
=
927 src
->target
== PIPE_TEXTURE_3D
? u_minify(src
->depth0
, srclevel
) - 1
928 : src
->array_size
- 1;
929 src_templ
->swizzle_r
= PIPE_SWIZZLE_RED
;
930 src_templ
->swizzle_g
= PIPE_SWIZZLE_GREEN
;
931 src_templ
->swizzle_b
= PIPE_SWIZZLE_BLUE
;
932 src_templ
->swizzle_a
= PIPE_SWIZZLE_ALPHA
;
935 void util_blitter_copy_texture(struct blitter_context
*blitter
,
936 struct pipe_resource
*dst
,
938 unsigned dstx
, unsigned dsty
, unsigned dstz
,
939 struct pipe_resource
*src
,
941 const struct pipe_box
*srcbox
,
942 boolean ignore_stencil
)
944 struct blitter_context_priv
*ctx
= (struct blitter_context_priv
*)blitter
;
945 struct pipe_context
*pipe
= ctx
->base
.pipe
;
946 struct pipe_screen
*screen
= pipe
->screen
;
947 struct pipe_surface
*dst_view
, dst_templ
;
948 struct pipe_sampler_view src_templ
, *src_view
;
950 boolean is_stencil
, is_depth
;
951 const struct util_format_description
*src_desc
;
953 /* Give up if textures are not set. */
958 src_desc
= util_format_description(src
->format
);
960 assert(src
->target
< PIPE_MAX_TEXTURE_TYPES
);
962 /* Is this a ZS format? */
963 is_depth
= util_format_has_depth(src_desc
);
964 is_stencil
= util_format_has_stencil(src_desc
);
966 if (is_depth
|| is_stencil
)
967 bind
= PIPE_BIND_DEPTH_STENCIL
;
969 bind
= PIPE_BIND_RENDER_TARGET
;
971 /* Check if we can sample from and render to the surfaces. */
972 /* (assuming copying a stencil buffer is not possible) */
973 if ((!ignore_stencil
&& is_stencil
&& !ctx
->has_stencil_export
) ||
974 !screen
->is_format_supported(screen
, dst
->format
, dst
->target
,
975 dst
->nr_samples
, bind
) ||
976 !screen
->is_format_supported(screen
, src
->format
, src
->target
,
977 src
->nr_samples
, PIPE_BIND_SAMPLER_VIEW
)) {
978 blitter_set_running_flag(ctx
);
979 util_resource_copy_region(pipe
, dst
, dstlevel
, dstx
, dsty
, dstz
,
980 src
, srclevel
, srcbox
);
981 blitter_unset_running_flag(ctx
);
985 /* Initialize the surface. */
986 util_blitter_default_dst_texture(&dst_templ
, dst
, dstlevel
, dstz
, srcbox
);
987 dst_view
= pipe
->create_surface(pipe
, dst
, &dst_templ
);
989 /* Initialize the sampler view. */
990 util_blitter_default_src_texture(&src_templ
, src
, srclevel
);
991 src_view
= pipe
->create_sampler_view(pipe
, src
, &src_templ
);
994 util_blitter_copy_texture_view(blitter
, dst_view
, dstx
, dsty
, src_view
,
995 srcbox
, src
->width0
, src
->height0
);
997 pipe_surface_reference(&dst_view
, NULL
);
998 pipe_sampler_view_reference(&src_view
, NULL
);
1001 void util_blitter_copy_texture_view(struct blitter_context
*blitter
,
1002 struct pipe_surface
*dst
,
1003 unsigned dstx
, unsigned dsty
,
1004 struct pipe_sampler_view
*src
,
1005 const struct pipe_box
*srcbox
,
1006 unsigned src_width0
, unsigned src_height0
)
1008 struct blitter_context_priv
*ctx
= (struct blitter_context_priv
*)blitter
;
1009 struct pipe_context
*pipe
= ctx
->base
.pipe
;
1010 struct pipe_framebuffer_state fb_state
;
1011 enum pipe_texture_target src_target
= src
->texture
->target
;
1012 unsigned width
= srcbox
->width
;
1013 unsigned height
= srcbox
->height
;
1014 boolean is_stencil
, is_depth
;
1015 const struct util_format_description
*src_desc
=
1016 util_format_description(src
->format
);
1018 is_depth
= util_format_has_depth(src_desc
);
1019 is_stencil
= util_format_has_stencil(src_desc
);
1021 /* If you want a fallback for stencil copies,
1022 * use util_blitter_copy_texture. */
1023 if (is_stencil
&& !ctx
->has_stencil_export
) {
1030 /* Sanity checks. */
1031 if (dst
->texture
== src
->texture
&&
1032 dst
->u
.tex
.level
== src
->u
.tex
.first_level
) {
1033 assert(!is_overlap(srcbox
->x
, srcbox
->x
+ width
, srcbox
->y
, srcbox
->y
+ height
,
1034 dstx
, dstx
+ width
, dsty
, dsty
+ height
));
1036 /* XXX should handle 3d regions */
1037 assert(srcbox
->depth
== 1);
1039 /* Check whether the states are properly saved. */
1040 blitter_set_running_flag(ctx
);
1041 blitter_check_saved_vertex_states(ctx
);
1042 blitter_check_saved_fragment_states(ctx
);
1043 blitter_check_saved_textures(ctx
);
1044 blitter_check_saved_fb_state(ctx
);
1046 /* Initialize framebuffer state. */
1047 fb_state
.width
= dst
->width
;
1048 fb_state
.height
= dst
->height
;
1050 if (is_depth
|| is_stencil
) {
1051 pipe
->bind_blend_state(pipe
, ctx
->blend_keep_color
);
1053 if (is_depth
&& is_stencil
) {
1054 pipe
->bind_depth_stencil_alpha_state(pipe
,
1055 ctx
->dsa_write_depth_stencil
);
1056 pipe
->bind_fs_state(pipe
,
1057 blitter_get_fs_texfetch_depthstencil(ctx
, src_target
));
1058 } else if (is_depth
) {
1059 pipe
->bind_depth_stencil_alpha_state(pipe
,
1060 ctx
->dsa_write_depth_keep_stencil
);
1061 pipe
->bind_fs_state(pipe
,
1062 blitter_get_fs_texfetch_depth(ctx
, src_target
));
1063 } else { /* is_stencil */
1064 pipe
->bind_depth_stencil_alpha_state(pipe
,
1065 ctx
->dsa_keep_depth_write_stencil
);
1066 pipe
->bind_fs_state(pipe
,
1067 blitter_get_fs_texfetch_stencil(ctx
, src_target
));
1070 fb_state
.nr_cbufs
= 0;
1071 fb_state
.zsbuf
= dst
;
1073 pipe
->bind_blend_state(pipe
, ctx
->blend_write_color
);
1074 pipe
->bind_depth_stencil_alpha_state(pipe
, ctx
->dsa_keep_depth_stencil
);
1075 pipe
->bind_fs_state(pipe
,
1076 blitter_get_fs_texfetch_col(ctx
, src_target
));
1078 fb_state
.nr_cbufs
= 1;
1079 fb_state
.cbufs
[0] = dst
;
1083 if (is_depth
&& is_stencil
) {
1084 /* Setup two samplers, one for depth and the other one for stencil. */
1085 struct pipe_sampler_view templ
;
1086 struct pipe_sampler_view
*views
[2];
1087 void *samplers
[2] = {ctx
->sampler_state
, ctx
->sampler_state
};
1090 templ
.format
= util_format_stencil_only(templ
.format
);
1091 assert(templ
.format
!= PIPE_FORMAT_NONE
);
1094 views
[1] = pipe
->create_sampler_view(pipe
, src
->texture
, &templ
);
1096 pipe
->set_fragment_sampler_views(pipe
, 2, views
);
1097 pipe
->bind_fragment_sampler_states(pipe
, 2, samplers
);
1099 pipe_sampler_view_reference(&views
[1], NULL
);
1101 pipe
->set_fragment_sampler_views(pipe
, 1, &src
);
1102 pipe
->bind_fragment_sampler_states(pipe
, 1, &ctx
->sampler_state
);
1105 pipe
->bind_vertex_elements_state(pipe
, ctx
->velem_state
);
1106 pipe
->set_framebuffer_state(pipe
, &fb_state
);
1107 pipe
->set_sample_mask(pipe
, ~0);
1109 blitter_set_common_draw_rect_state(ctx
);
1110 blitter_set_dst_dimensions(ctx
, dst
->width
, dst
->height
);
1112 switch (src_target
) {
1113 /* Draw the quad with the draw_rectangle callback. */
1114 case PIPE_TEXTURE_1D
:
1115 case PIPE_TEXTURE_2D
:
1116 case PIPE_TEXTURE_RECT
:
1118 /* Set texture coordinates. - use a pipe color union
1119 * for interface purposes.
1120 * XXX pipe_color_union is a wrong name since we use that to set
1121 * texture coordinates too.
1123 union pipe_color_union coord
;
1124 get_texcoords(src
, src_width0
, src_height0
, srcbox
->x
, srcbox
->y
,
1125 srcbox
->x
+width
, srcbox
->y
+height
, coord
.f
);
1128 blitter
->draw_rectangle(blitter
, dstx
, dsty
, dstx
+width
, dsty
+height
, 0,
1129 UTIL_BLITTER_ATTRIB_TEXCOORD
, &coord
);
1133 /* Draw the quad with the generic codepath. */
1135 /* Set texture coordinates. */
1136 switch (src_target
) {
1137 case PIPE_TEXTURE_1D_ARRAY
:
1138 case PIPE_TEXTURE_2D_ARRAY
:
1139 case PIPE_TEXTURE_3D
:
1140 case PIPE_TEXTURE_CUBE
:
1141 blitter_set_texcoords(ctx
, src
, src_width0
, src_height0
, srcbox
->z
,
1142 srcbox
->y
, srcbox
->x
,
1143 srcbox
->x
+ width
, srcbox
->y
+ height
);
1150 blitter_draw(ctx
, dstx
, dsty
, dstx
+width
, dsty
+height
, 0);
1154 blitter_restore_vertex_states(ctx
);
1155 blitter_restore_fragment_states(ctx
);
1156 blitter_restore_textures(ctx
);
1157 blitter_restore_fb_state(ctx
);
1158 blitter_unset_running_flag(ctx
);
1161 /* Clear a region of a color surface to a constant value. */
1162 void util_blitter_clear_render_target(struct blitter_context
*blitter
,
1163 struct pipe_surface
*dstsurf
,
1164 const union pipe_color_union
*color
,
1165 unsigned dstx
, unsigned dsty
,
1166 unsigned width
, unsigned height
)
1168 struct blitter_context_priv
*ctx
= (struct blitter_context_priv
*)blitter
;
1169 struct pipe_context
*pipe
= ctx
->base
.pipe
;
1170 struct pipe_framebuffer_state fb_state
;
1172 assert(dstsurf
->texture
);
1173 if (!dstsurf
->texture
)
1176 /* check the saved state */
1177 blitter_set_running_flag(ctx
);
1178 blitter_check_saved_vertex_states(ctx
);
1179 blitter_check_saved_fragment_states(ctx
);
1180 blitter_check_saved_fb_state(ctx
);
1183 pipe
->bind_blend_state(pipe
, ctx
->blend_write_color
);
1184 pipe
->bind_depth_stencil_alpha_state(pipe
, ctx
->dsa_keep_depth_stencil
);
1185 pipe
->bind_fs_state(pipe
, blitter_get_fs_col(ctx
, 1, FALSE
));
1186 pipe
->bind_vertex_elements_state(pipe
, ctx
->velem_state
);
1188 /* set a framebuffer state */
1189 fb_state
.width
= dstsurf
->width
;
1190 fb_state
.height
= dstsurf
->height
;
1191 fb_state
.nr_cbufs
= 1;
1192 fb_state
.cbufs
[0] = dstsurf
;
1194 pipe
->set_framebuffer_state(pipe
, &fb_state
);
1195 pipe
->set_sample_mask(pipe
, ~0);
1197 blitter_set_common_draw_rect_state(ctx
);
1198 blitter_set_dst_dimensions(ctx
, dstsurf
->width
, dstsurf
->height
);
1199 blitter
->draw_rectangle(blitter
, dstx
, dsty
, dstx
+width
, dsty
+height
, 0,
1200 UTIL_BLITTER_ATTRIB_COLOR
, color
);
1202 blitter_restore_vertex_states(ctx
);
1203 blitter_restore_fragment_states(ctx
);
1204 blitter_restore_fb_state(ctx
);
1205 blitter_unset_running_flag(ctx
);
1208 /* Clear a region of a depth stencil surface. */
1209 void util_blitter_clear_depth_stencil(struct blitter_context
*blitter
,
1210 struct pipe_surface
*dstsurf
,
1211 unsigned clear_flags
,
1214 unsigned dstx
, unsigned dsty
,
1215 unsigned width
, unsigned height
)
1217 struct blitter_context_priv
*ctx
= (struct blitter_context_priv
*)blitter
;
1218 struct pipe_context
*pipe
= ctx
->base
.pipe
;
1219 struct pipe_framebuffer_state fb_state
;
1220 struct pipe_stencil_ref sr
= { { 0 } };
1222 assert(dstsurf
->texture
);
1223 if (!dstsurf
->texture
)
1226 /* check the saved state */
1227 blitter_set_running_flag(ctx
);
1228 blitter_check_saved_vertex_states(ctx
);
1229 blitter_check_saved_fragment_states(ctx
);
1230 blitter_check_saved_fb_state(ctx
);
1233 pipe
->bind_blend_state(pipe
, ctx
->blend_keep_color
);
1234 if ((clear_flags
& PIPE_CLEAR_DEPTHSTENCIL
) == PIPE_CLEAR_DEPTHSTENCIL
) {
1235 sr
.ref_value
[0] = stencil
& 0xff;
1236 pipe
->bind_depth_stencil_alpha_state(pipe
, ctx
->dsa_write_depth_stencil
);
1237 pipe
->set_stencil_ref(pipe
, &sr
);
1239 else if (clear_flags
& PIPE_CLEAR_DEPTH
) {
1240 pipe
->bind_depth_stencil_alpha_state(pipe
, ctx
->dsa_write_depth_keep_stencil
);
1242 else if (clear_flags
& PIPE_CLEAR_STENCIL
) {
1243 sr
.ref_value
[0] = stencil
& 0xff;
1244 pipe
->bind_depth_stencil_alpha_state(pipe
, ctx
->dsa_keep_depth_write_stencil
);
1245 pipe
->set_stencil_ref(pipe
, &sr
);
1248 /* hmm that should be illegal probably, or make it a no-op somewhere */
1249 pipe
->bind_depth_stencil_alpha_state(pipe
, ctx
->dsa_keep_depth_stencil
);
1251 pipe
->bind_fs_state(pipe
, blitter_get_fs_col(ctx
, 0, FALSE
));
1252 pipe
->bind_vertex_elements_state(pipe
, ctx
->velem_state
);
1254 /* set a framebuffer state */
1255 fb_state
.width
= dstsurf
->width
;
1256 fb_state
.height
= dstsurf
->height
;
1257 fb_state
.nr_cbufs
= 0;
1258 fb_state
.cbufs
[0] = 0;
1259 fb_state
.zsbuf
= dstsurf
;
1260 pipe
->set_framebuffer_state(pipe
, &fb_state
);
1261 pipe
->set_sample_mask(pipe
, ~0);
1263 blitter_set_common_draw_rect_state(ctx
);
1264 blitter_set_dst_dimensions(ctx
, dstsurf
->width
, dstsurf
->height
);
1265 blitter
->draw_rectangle(blitter
, dstx
, dsty
, dstx
+width
, dsty
+height
, depth
,
1266 UTIL_BLITTER_ATTRIB_NONE
, NULL
);
1268 blitter_restore_vertex_states(ctx
);
1269 blitter_restore_fragment_states(ctx
);
1270 blitter_restore_fb_state(ctx
);
1271 blitter_unset_running_flag(ctx
);
1274 /* draw a rectangle across a region using a custom dsa stage - for r600g */
1275 void util_blitter_custom_depth_stencil(struct blitter_context
*blitter
,
1276 struct pipe_surface
*zsurf
,
1277 struct pipe_surface
*cbsurf
,
1278 void *dsa_stage
, float depth
)
1280 struct blitter_context_priv
*ctx
= (struct blitter_context_priv
*)blitter
;
1281 struct pipe_context
*pipe
= ctx
->base
.pipe
;
1282 struct pipe_framebuffer_state fb_state
;
1284 assert(zsurf
->texture
);
1285 if (!zsurf
->texture
)
1288 /* check the saved state */
1289 blitter_set_running_flag(ctx
);
1290 blitter_check_saved_vertex_states(ctx
);
1291 blitter_check_saved_fragment_states(ctx
);
1292 blitter_check_saved_fb_state(ctx
);
1295 pipe
->bind_blend_state(pipe
, ctx
->blend_write_color
);
1296 pipe
->bind_depth_stencil_alpha_state(pipe
, dsa_stage
);
1297 pipe
->bind_fs_state(pipe
, blitter_get_fs_col(ctx
, 0, FALSE
));
1298 pipe
->bind_vertex_elements_state(pipe
, ctx
->velem_state
);
1300 /* set a framebuffer state */
1301 fb_state
.width
= zsurf
->width
;
1302 fb_state
.height
= zsurf
->height
;
1303 fb_state
.nr_cbufs
= 1;
1305 fb_state
.cbufs
[0] = cbsurf
;
1306 fb_state
.nr_cbufs
= 1;
1308 fb_state
.cbufs
[0] = NULL
;
1309 fb_state
.nr_cbufs
= 0;
1311 fb_state
.zsbuf
= zsurf
;
1312 pipe
->set_framebuffer_state(pipe
, &fb_state
);
1314 blitter_set_common_draw_rect_state(ctx
);
1315 blitter_set_dst_dimensions(ctx
, zsurf
->width
, zsurf
->height
);
1316 blitter
->draw_rectangle(blitter
, 0, 0, zsurf
->width
, zsurf
->height
, depth
,
1317 UTIL_BLITTER_ATTRIB_NONE
, NULL
);
1319 blitter_restore_vertex_states(ctx
);
1320 blitter_restore_fragment_states(ctx
);
1321 blitter_restore_fb_state(ctx
);
1322 blitter_unset_running_flag(ctx
);
1325 void util_blitter_copy_buffer(struct blitter_context
*blitter
,
1326 struct pipe_resource
*dst
,
1328 struct pipe_resource
*src
,
1332 struct blitter_context_priv
*ctx
= (struct blitter_context_priv
*)blitter
;
1333 struct pipe_context
*pipe
= ctx
->base
.pipe
;
1334 struct pipe_vertex_buffer vb
;
1335 struct pipe_stream_output_target
*so_target
;
1337 if (srcx
>= src
->width0
||
1338 dstx
>= dst
->width0
) {
1341 if (srcx
+ size
> src
->width0
) {
1342 size
= src
->width0
- srcx
;
1344 if (dstx
+ size
> dst
->width0
) {
1345 size
= dst
->width0
- dstx
;
1348 /* Drivers not capable of Stream Out should not call this function
1349 * in the first place. */
1350 assert(ctx
->has_stream_out
);
1352 /* Some alignment is required. */
1353 if (srcx
% 4 != 0 || dstx
% 4 != 0 || size
% 4 != 0 ||
1354 !ctx
->has_stream_out
) {
1355 struct pipe_box box
;
1356 u_box_1d(srcx
, size
, &box
);
1357 util_resource_copy_region(pipe
, dst
, 0, dstx
, 0, 0, src
, 0, &box
);
1361 blitter_set_running_flag(ctx
);
1362 blitter_check_saved_vertex_states(ctx
);
1365 vb
.buffer_offset
= srcx
;
1368 pipe
->set_vertex_buffers(pipe
, 1, &vb
);
1369 pipe
->bind_vertex_elements_state(pipe
, ctx
->velem_state_readbuf
);
1370 pipe
->bind_vs_state(pipe
, ctx
->vs_pos_only
);
1371 if (ctx
->has_geometry_shader
)
1372 pipe
->bind_gs_state(pipe
, NULL
);
1373 pipe
->bind_rasterizer_state(pipe
, ctx
->rs_discard_state
);
1375 so_target
= pipe
->create_stream_output_target(pipe
, dst
, dstx
, size
);
1376 pipe
->set_stream_output_targets(pipe
, 1, &so_target
, 0);
1378 util_draw_arrays(pipe
, PIPE_PRIM_POINTS
, 0, size
/ 4);
1380 blitter_restore_vertex_states(ctx
);
1381 blitter_unset_running_flag(ctx
);
1382 pipe_so_target_reference(&so_target
, NULL
);