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, clear_depth_stencil
30 * 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"
51 #define INVALID_PTR ((void*)~0)
53 struct blitter_context_priv
55 struct blitter_context base
;
57 struct pipe_resource
*vbuf
; /**< quad */
59 float vertices
[4][2][4]; /**< {pos, color} or {pos, texcoord} */
61 /* Templates for various state objects. */
62 struct pipe_sampler_state template_sampler_state
;
64 /* Constant state objects. */
66 void *vs_col
; /**< Vertex shader which passes {pos, color} to the output */
67 void *vs_tex
; /**< Vertex shader which passes {pos, texcoord} 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];
73 /* FS which outputs a color from a texture,
74 where the index is PIPE_TEXTURE_* to be sampled. */
75 void *fs_texfetch_col
[PIPE_MAX_TEXTURE_TYPES
];
77 /* FS which outputs a depth from a texture,
78 where the index is PIPE_TEXTURE_* to be sampled. */
79 void *fs_texfetch_depth
[PIPE_MAX_TEXTURE_TYPES
];
82 void *blend_write_color
; /**< blend state with writemask of RGBA */
83 void *blend_keep_color
; /**< blend state with writemask of 0 */
85 /* Depth stencil alpha state. */
86 void *dsa_write_depth_stencil
;
87 void *dsa_write_depth_keep_stencil
;
88 void *dsa_keep_depth_stencil
;
89 void *dsa_keep_depth_write_stencil
;
90 void *dsa_flush_depth_stencil
;
94 /* Sampler state for clamping to a miplevel. */
95 void *sampler_state
[PIPE_MAX_TEXTURE_LEVELS
* 2];
97 /* Rasterizer state. */
100 /* Viewport state. */
101 struct pipe_viewport_state viewport
;
104 struct pipe_clip_state clip
;
106 /* Destination surface dimensions. */
111 static void blitter_draw_rectangle(struct blitter_context
*blitter
,
112 unsigned x
, unsigned y
,
113 unsigned width
, unsigned height
,
115 enum blitter_attrib_type type
,
116 const float attrib
[4]);
119 struct blitter_context
*util_blitter_create(struct pipe_context
*pipe
)
121 struct blitter_context_priv
*ctx
;
122 struct pipe_blend_state blend
;
123 struct pipe_depth_stencil_alpha_state dsa
;
124 struct pipe_rasterizer_state rs_state
;
125 struct pipe_sampler_state
*sampler_state
;
126 struct pipe_vertex_element velem
[2];
129 ctx
= CALLOC_STRUCT(blitter_context_priv
);
133 ctx
->base
.pipe
= pipe
;
134 ctx
->base
.draw_rectangle
= blitter_draw_rectangle
;
136 /* init state objects for them to be considered invalid */
137 ctx
->base
.saved_blend_state
= INVALID_PTR
;
138 ctx
->base
.saved_dsa_state
= INVALID_PTR
;
139 ctx
->base
.saved_rs_state
= INVALID_PTR
;
140 ctx
->base
.saved_fs
= INVALID_PTR
;
141 ctx
->base
.saved_vs
= INVALID_PTR
;
142 ctx
->base
.saved_velem_state
= INVALID_PTR
;
143 ctx
->base
.saved_fb_state
.nr_cbufs
= ~0;
144 ctx
->base
.saved_num_sampler_views
= ~0;
145 ctx
->base
.saved_num_sampler_states
= ~0;
146 ctx
->base
.saved_num_vertex_buffers
= ~0;
148 /* blend state objects */
149 memset(&blend
, 0, sizeof(blend
));
150 ctx
->blend_keep_color
= pipe
->create_blend_state(pipe
, &blend
);
152 blend
.rt
[0].colormask
= PIPE_MASK_RGBA
;
153 ctx
->blend_write_color
= pipe
->create_blend_state(pipe
, &blend
);
155 /* depth stencil alpha state objects */
156 memset(&dsa
, 0, sizeof(dsa
));
157 ctx
->dsa_keep_depth_stencil
=
158 pipe
->create_depth_stencil_alpha_state(pipe
, &dsa
);
160 dsa
.depth
.writemask
= 1;
161 ctx
->dsa_flush_depth_stencil
=
162 pipe
->create_depth_stencil_alpha_state(pipe
, &dsa
);
164 dsa
.depth
.enabled
= 1;
165 dsa
.depth
.writemask
= 1;
166 dsa
.depth
.func
= PIPE_FUNC_ALWAYS
;
167 ctx
->dsa_write_depth_keep_stencil
=
168 pipe
->create_depth_stencil_alpha_state(pipe
, &dsa
);
170 dsa
.stencil
[0].enabled
= 1;
171 dsa
.stencil
[0].func
= PIPE_FUNC_ALWAYS
;
172 dsa
.stencil
[0].fail_op
= PIPE_STENCIL_OP_REPLACE
;
173 dsa
.stencil
[0].zpass_op
= PIPE_STENCIL_OP_REPLACE
;
174 dsa
.stencil
[0].zfail_op
= PIPE_STENCIL_OP_REPLACE
;
175 dsa
.stencil
[0].valuemask
= 0xff;
176 dsa
.stencil
[0].writemask
= 0xff;
177 ctx
->dsa_write_depth_stencil
=
178 pipe
->create_depth_stencil_alpha_state(pipe
, &dsa
);
181 dsa
.depth
.enabled
= 0;
182 dsa
.depth
.writemask
= 0;
183 ctx
->dsa_keep_depth_write_stencil
=
184 pipe
->create_depth_stencil_alpha_state(pipe
, &dsa
);
187 sampler_state
= &ctx
->template_sampler_state
;
188 sampler_state
->wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
189 sampler_state
->wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
190 sampler_state
->wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
191 sampler_state
->normalized_coords
= TRUE
;
192 /* The sampler state objects which sample from a specified mipmap level
193 * are created on-demand. */
195 /* rasterizer state */
196 memset(&rs_state
, 0, sizeof(rs_state
));
197 rs_state
.cull_face
= PIPE_FACE_NONE
;
198 rs_state
.gl_rasterization_rules
= 1;
199 rs_state
.flatshade
= 1;
200 ctx
->rs_state
= pipe
->create_rasterizer_state(pipe
, &rs_state
);
202 /* vertex elements state */
203 memset(&velem
[0], 0, sizeof(velem
[0]) * 2);
204 for (i
= 0; i
< 2; i
++) {
205 velem
[i
].src_offset
= i
* 4 * sizeof(float);
206 velem
[i
].instance_divisor
= 0;
207 velem
[i
].vertex_buffer_index
= 0;
208 velem
[i
].src_format
= PIPE_FORMAT_R32G32B32A32_FLOAT
;
210 ctx
->velem_state
= pipe
->create_vertex_elements_state(pipe
, 2, &velem
[0]);
212 /* fragment shaders are created on-demand */
216 const uint semantic_names
[] = { TGSI_SEMANTIC_POSITION
,
217 TGSI_SEMANTIC_COLOR
};
218 const uint semantic_indices
[] = { 0, 0 };
220 util_make_vertex_passthrough_shader(pipe
, 2, semantic_names
,
224 const uint semantic_names
[] = { TGSI_SEMANTIC_POSITION
,
225 TGSI_SEMANTIC_GENERIC
};
226 const uint semantic_indices
[] = { 0, 0 };
228 util_make_vertex_passthrough_shader(pipe
, 2, semantic_names
,
232 /* set invariant vertex coordinates */
233 for (i
= 0; i
< 4; i
++)
234 ctx
->vertices
[i
][0][3] = 1; /*v.w*/
236 /* create the vertex buffer */
237 ctx
->vbuf
= pipe_buffer_create(ctx
->base
.pipe
->screen
,
238 PIPE_BIND_VERTEX_BUFFER
,
239 sizeof(ctx
->vertices
));
244 void util_blitter_destroy(struct blitter_context
*blitter
)
246 struct blitter_context_priv
*ctx
= (struct blitter_context_priv
*)blitter
;
247 struct pipe_context
*pipe
= blitter
->pipe
;
250 pipe
->delete_blend_state(pipe
, ctx
->blend_write_color
);
251 pipe
->delete_blend_state(pipe
, ctx
->blend_keep_color
);
252 pipe
->delete_depth_stencil_alpha_state(pipe
, ctx
->dsa_keep_depth_stencil
);
253 pipe
->delete_depth_stencil_alpha_state(pipe
,
254 ctx
->dsa_write_depth_keep_stencil
);
255 pipe
->delete_depth_stencil_alpha_state(pipe
, ctx
->dsa_write_depth_stencil
);
256 pipe
->delete_depth_stencil_alpha_state(pipe
, ctx
->dsa_keep_depth_write_stencil
);
257 pipe
->delete_depth_stencil_alpha_state(pipe
, ctx
->dsa_flush_depth_stencil
);
259 pipe
->delete_rasterizer_state(pipe
, ctx
->rs_state
);
260 pipe
->delete_vs_state(pipe
, ctx
->vs_col
);
261 pipe
->delete_vs_state(pipe
, ctx
->vs_tex
);
262 pipe
->delete_vertex_elements_state(pipe
, ctx
->velem_state
);
264 for (i
= 0; i
< PIPE_MAX_TEXTURE_TYPES
; i
++) {
265 if (ctx
->fs_texfetch_col
[i
])
266 pipe
->delete_fs_state(pipe
, ctx
->fs_texfetch_col
[i
]);
267 if (ctx
->fs_texfetch_depth
[i
])
268 pipe
->delete_fs_state(pipe
, ctx
->fs_texfetch_depth
[i
]);
271 for (i
= 0; i
<= PIPE_MAX_COLOR_BUFS
; i
++)
273 pipe
->delete_fs_state(pipe
, ctx
->fs_col
[i
]);
275 for (i
= 0; i
< PIPE_MAX_TEXTURE_LEVELS
* 2; i
++)
276 if (ctx
->sampler_state
[i
])
277 pipe
->delete_sampler_state(pipe
, ctx
->sampler_state
[i
]);
279 pipe_resource_reference(&ctx
->vbuf
, NULL
);
283 static void blitter_check_saved_CSOs(struct blitter_context_priv
*ctx
)
285 /* make sure these CSOs have been saved */
286 assert(ctx
->base
.saved_blend_state
!= INVALID_PTR
&&
287 ctx
->base
.saved_dsa_state
!= INVALID_PTR
&&
288 ctx
->base
.saved_rs_state
!= INVALID_PTR
&&
289 ctx
->base
.saved_fs
!= INVALID_PTR
&&
290 ctx
->base
.saved_vs
!= INVALID_PTR
&&
291 ctx
->base
.saved_velem_state
!= INVALID_PTR
);
294 static void blitter_restore_CSOs(struct blitter_context_priv
*ctx
)
296 struct pipe_context
*pipe
= ctx
->base
.pipe
;
299 /* restore the state objects which are always required to be saved */
300 pipe
->bind_blend_state(pipe
, ctx
->base
.saved_blend_state
);
301 pipe
->bind_depth_stencil_alpha_state(pipe
, ctx
->base
.saved_dsa_state
);
302 pipe
->bind_rasterizer_state(pipe
, ctx
->base
.saved_rs_state
);
303 pipe
->bind_fs_state(pipe
, ctx
->base
.saved_fs
);
304 pipe
->bind_vs_state(pipe
, ctx
->base
.saved_vs
);
305 pipe
->bind_vertex_elements_state(pipe
, ctx
->base
.saved_velem_state
);
307 ctx
->base
.saved_blend_state
= INVALID_PTR
;
308 ctx
->base
.saved_dsa_state
= INVALID_PTR
;
309 ctx
->base
.saved_rs_state
= INVALID_PTR
;
310 ctx
->base
.saved_fs
= INVALID_PTR
;
311 ctx
->base
.saved_vs
= INVALID_PTR
;
312 ctx
->base
.saved_velem_state
= INVALID_PTR
;
314 pipe
->set_stencil_ref(pipe
, &ctx
->base
.saved_stencil_ref
);
316 pipe
->set_viewport_state(pipe
, &ctx
->base
.saved_viewport
);
317 pipe
->set_clip_state(pipe
, &ctx
->base
.saved_clip
);
319 /* restore the state objects which are required to be saved before copy/fill
321 if (ctx
->base
.saved_fb_state
.nr_cbufs
!= ~0) {
322 pipe
->set_framebuffer_state(pipe
, &ctx
->base
.saved_fb_state
);
323 util_unreference_framebuffer_state(&ctx
->base
.saved_fb_state
);
324 ctx
->base
.saved_fb_state
.nr_cbufs
= ~0;
327 if (ctx
->base
.saved_num_sampler_states
!= ~0) {
328 pipe
->bind_fragment_sampler_states(pipe
,
329 ctx
->base
.saved_num_sampler_states
,
330 ctx
->base
.saved_sampler_states
);
331 ctx
->base
.saved_num_sampler_states
= ~0;
334 if (ctx
->base
.saved_num_sampler_views
!= ~0) {
335 pipe
->set_fragment_sampler_views(pipe
,
336 ctx
->base
.saved_num_sampler_views
,
337 ctx
->base
.saved_sampler_views
);
339 for (i
= 0; i
< ctx
->base
.saved_num_sampler_views
; i
++)
340 pipe_sampler_view_reference(&ctx
->base
.saved_sampler_views
[i
],
343 ctx
->base
.saved_num_sampler_views
= ~0;
346 if (ctx
->base
.saved_num_vertex_buffers
!= ~0) {
347 pipe
->set_vertex_buffers(pipe
,
348 ctx
->base
.saved_num_vertex_buffers
,
349 ctx
->base
.saved_vertex_buffers
);
351 for (i
= 0; i
< ctx
->base
.saved_num_vertex_buffers
; i
++) {
352 if (ctx
->base
.saved_vertex_buffers
[i
].buffer
) {
353 pipe_resource_reference(&ctx
->base
.saved_vertex_buffers
[i
].buffer
,
357 ctx
->base
.saved_num_vertex_buffers
= ~0;
361 static void blitter_set_rectangle(struct blitter_context_priv
*ctx
,
362 unsigned x1
, unsigned y1
,
363 unsigned x2
, unsigned y2
,
368 /* set vertex positions */
369 ctx
->vertices
[0][0][0] = (float)x1
/ ctx
->dst_width
* 2.0f
- 1.0f
; /*v0.x*/
370 ctx
->vertices
[0][0][1] = (float)y1
/ ctx
->dst_height
* 2.0f
- 1.0f
; /*v0.y*/
372 ctx
->vertices
[1][0][0] = (float)x2
/ ctx
->dst_width
* 2.0f
- 1.0f
; /*v1.x*/
373 ctx
->vertices
[1][0][1] = (float)y1
/ ctx
->dst_height
* 2.0f
- 1.0f
; /*v1.y*/
375 ctx
->vertices
[2][0][0] = (float)x2
/ ctx
->dst_width
* 2.0f
- 1.0f
; /*v2.x*/
376 ctx
->vertices
[2][0][1] = (float)y2
/ ctx
->dst_height
* 2.0f
- 1.0f
; /*v2.y*/
378 ctx
->vertices
[3][0][0] = (float)x1
/ ctx
->dst_width
* 2.0f
- 1.0f
; /*v3.x*/
379 ctx
->vertices
[3][0][1] = (float)y2
/ ctx
->dst_height
* 2.0f
- 1.0f
; /*v3.y*/
381 for (i
= 0; i
< 4; i
++)
382 ctx
->vertices
[i
][0][2] = depth
; /*z*/
385 ctx
->viewport
.scale
[0] = 0.5f
* ctx
->dst_width
;
386 ctx
->viewport
.scale
[1] = 0.5f
* ctx
->dst_height
;
387 ctx
->viewport
.scale
[2] = 1.0f
;
388 ctx
->viewport
.scale
[3] = 1.0f
;
389 ctx
->viewport
.translate
[0] = 0.5f
* ctx
->dst_width
;
390 ctx
->viewport
.translate
[1] = 0.5f
* ctx
->dst_height
;
391 ctx
->viewport
.translate
[2] = 0.0f
;
392 ctx
->viewport
.translate
[3] = 0.0f
;
393 ctx
->base
.pipe
->set_viewport_state(ctx
->base
.pipe
, &ctx
->viewport
);
396 ctx
->base
.pipe
->set_clip_state(ctx
->base
.pipe
, &ctx
->clip
);
399 static void blitter_set_clear_color(struct blitter_context_priv
*ctx
,
405 for (i
= 0; i
< 4; i
++) {
406 ctx
->vertices
[i
][1][0] = rgba
[0];
407 ctx
->vertices
[i
][1][1] = rgba
[1];
408 ctx
->vertices
[i
][1][2] = rgba
[2];
409 ctx
->vertices
[i
][1][3] = rgba
[3];
412 for (i
= 0; i
< 4; i
++) {
413 ctx
->vertices
[i
][1][0] = 0;
414 ctx
->vertices
[i
][1][1] = 0;
415 ctx
->vertices
[i
][1][2] = 0;
416 ctx
->vertices
[i
][1][3] = 0;
421 static void get_texcoords(struct pipe_resource
*src
,
422 struct pipe_subresource subsrc
,
423 unsigned x1
, unsigned y1
,
424 unsigned x2
, unsigned y2
,
425 boolean normalized
, float out
[4])
429 out
[0] = x1
/ (float)u_minify(src
->width0
, subsrc
.level
);
430 out
[1] = y1
/ (float)u_minify(src
->height0
, subsrc
.level
);
431 out
[2] = x2
/ (float)u_minify(src
->width0
, subsrc
.level
);
432 out
[3] = y2
/ (float)u_minify(src
->height0
, subsrc
.level
);
443 static void set_texcoords_in_vertices(const float coord
[4],
444 float *out
, unsigned stride
)
446 out
[0] = coord
[0]; /*t0.s*/
447 out
[1] = coord
[1]; /*t0.t*/
449 out
[0] = coord
[2]; /*t1.s*/
450 out
[1] = coord
[1]; /*t1.t*/
452 out
[0] = coord
[2]; /*t2.s*/
453 out
[1] = coord
[3]; /*t2.t*/
455 out
[0] = coord
[0]; /*t3.s*/
456 out
[1] = coord
[3]; /*t3.t*/
459 static void blitter_set_texcoords_2d(struct blitter_context_priv
*ctx
,
460 struct pipe_resource
*src
,
461 struct pipe_subresource subsrc
,
462 unsigned x1
, unsigned y1
,
463 unsigned x2
, unsigned y2
)
468 get_texcoords(src
, subsrc
, x1
, y1
, x2
, y2
, TRUE
, coord
);
469 set_texcoords_in_vertices(coord
, &ctx
->vertices
[0][1][0], 8);
471 for (i
= 0; i
< 4; i
++) {
472 ctx
->vertices
[i
][1][2] = 0; /*r*/
473 ctx
->vertices
[i
][1][3] = 1; /*q*/
477 static void blitter_set_texcoords_3d(struct blitter_context_priv
*ctx
,
478 struct pipe_resource
*src
,
479 struct pipe_subresource subsrc
,
481 unsigned x1
, unsigned y1
,
482 unsigned x2
, unsigned y2
)
485 float r
= zslice
/ (float)u_minify(src
->depth0
, subsrc
.level
);
487 blitter_set_texcoords_2d(ctx
, src
, subsrc
, x1
, y1
, x2
, y2
);
489 for (i
= 0; i
< 4; i
++)
490 ctx
->vertices
[i
][1][2] = r
; /*r*/
493 static void blitter_set_texcoords_cube(struct blitter_context_priv
*ctx
,
494 struct pipe_resource
*src
,
495 struct pipe_subresource subsrc
,
496 unsigned x1
, unsigned y1
,
497 unsigned x2
, unsigned y2
)
503 get_texcoords(src
, subsrc
, x1
, y1
, x2
, y2
, TRUE
, coord
);
504 set_texcoords_in_vertices(coord
, &st
[0][0], 2);
506 util_map_texcoords2d_onto_cubemap(subsrc
.face
,
507 /* pointer, stride in floats */
509 &ctx
->vertices
[0][1][0], 8);
511 for (i
= 0; i
< 4; i
++)
512 ctx
->vertices
[i
][1][3] = 1; /*q*/
515 static void blitter_set_dst_dimensions(struct blitter_context_priv
*ctx
,
516 unsigned width
, unsigned height
)
518 ctx
->dst_width
= width
;
519 ctx
->dst_height
= height
;
522 static void blitter_draw_quad(struct blitter_context_priv
*ctx
)
524 struct pipe_context
*pipe
= ctx
->base
.pipe
;
527 /* write vertices and draw them */
528 u_box_1d(0, sizeof(ctx
->vertices
), &box
);
529 pipe
->transfer_inline_write(pipe
, ctx
->vbuf
, u_subresource(0,0),
530 PIPE_TRANSFER_WRITE
| PIPE_TRANSFER_DISCARD
,
531 &box
, ctx
->vertices
, sizeof(ctx
->vertices
), 0);
533 util_draw_vertex_buffer(pipe
, ctx
->vbuf
, 0, PIPE_PRIM_TRIANGLE_FAN
,
535 2); /* attribs/vert */
539 void **blitter_get_sampler_state(struct blitter_context_priv
*ctx
,
540 int miplevel
, boolean normalized
)
542 struct pipe_context
*pipe
= ctx
->base
.pipe
;
543 struct pipe_sampler_state
*sampler_state
= &ctx
->template_sampler_state
;
545 assert(miplevel
< PIPE_MAX_TEXTURE_LEVELS
);
547 /* Create the sampler state on-demand. */
548 if (!ctx
->sampler_state
[miplevel
* 2 + normalized
]) {
549 sampler_state
->lod_bias
= miplevel
;
550 sampler_state
->min_lod
= miplevel
;
551 sampler_state
->max_lod
= miplevel
;
552 sampler_state
->normalized_coords
= normalized
;
554 ctx
->sampler_state
[miplevel
* 2 + normalized
] = pipe
->create_sampler_state(pipe
,
558 /* Return void** so that it can be passed to bind_fragment_sampler_states
560 return &ctx
->sampler_state
[miplevel
* 2 + normalized
];
564 void *blitter_get_fs_col(struct blitter_context_priv
*ctx
, unsigned num_cbufs
)
566 struct pipe_context
*pipe
= ctx
->base
.pipe
;
568 assert(num_cbufs
<= PIPE_MAX_COLOR_BUFS
);
570 if (!ctx
->fs_col
[num_cbufs
])
571 ctx
->fs_col
[num_cbufs
] =
572 util_make_fragment_clonecolor_shader(pipe
, num_cbufs
);
574 return ctx
->fs_col
[num_cbufs
];
577 /** Convert PIPE_TEXTURE_x to TGSI_TEXTURE_x */
579 pipe_tex_to_tgsi_tex(enum pipe_texture_target pipe_tex_target
)
581 switch (pipe_tex_target
) {
582 case PIPE_TEXTURE_1D
:
583 return TGSI_TEXTURE_1D
;
584 case PIPE_TEXTURE_2D
:
585 return TGSI_TEXTURE_2D
;
586 case PIPE_TEXTURE_RECT
:
587 return TGSI_TEXTURE_RECT
;
588 case PIPE_TEXTURE_3D
:
589 return TGSI_TEXTURE_3D
;
590 case PIPE_TEXTURE_CUBE
:
591 return TGSI_TEXTURE_CUBE
;
593 assert(0 && "unexpected texture target");
594 return TGSI_TEXTURE_UNKNOWN
;
600 void *blitter_get_fs_texfetch_col(struct blitter_context_priv
*ctx
,
603 struct pipe_context
*pipe
= ctx
->base
.pipe
;
605 assert(tex_target
< PIPE_MAX_TEXTURE_TYPES
);
607 /* Create the fragment shader on-demand. */
608 if (!ctx
->fs_texfetch_col
[tex_target
]) {
609 unsigned tgsi_tex
= pipe_tex_to_tgsi_tex(tex_target
);
611 ctx
->fs_texfetch_col
[tex_target
] =
612 util_make_fragment_tex_shader(pipe
, tgsi_tex
, TGSI_INTERPOLATE_LINEAR
);
615 return ctx
->fs_texfetch_col
[tex_target
];
619 void *blitter_get_fs_texfetch_depth(struct blitter_context_priv
*ctx
,
622 struct pipe_context
*pipe
= ctx
->base
.pipe
;
624 assert(tex_target
< PIPE_MAX_TEXTURE_TYPES
);
626 /* Create the fragment shader on-demand. */
627 if (!ctx
->fs_texfetch_depth
[tex_target
]) {
628 unsigned tgsi_tex
= pipe_tex_to_tgsi_tex(tex_target
);
630 ctx
->fs_texfetch_depth
[tex_target
] =
631 util_make_fragment_tex_shader_writedepth(pipe
, tgsi_tex
,
632 TGSI_INTERPOLATE_LINEAR
);
635 return ctx
->fs_texfetch_depth
[tex_target
];
638 static void blitter_draw_rectangle(struct blitter_context
*blitter
,
639 unsigned x1
, unsigned y1
,
640 unsigned x2
, unsigned y2
,
642 enum blitter_attrib_type type
,
643 const float attrib
[4])
645 struct blitter_context_priv
*ctx
= (struct blitter_context_priv
*)blitter
;
648 case UTIL_BLITTER_ATTRIB_COLOR
:
649 blitter_set_clear_color(ctx
, attrib
);
652 case UTIL_BLITTER_ATTRIB_TEXCOORD
:
653 set_texcoords_in_vertices(attrib
, &ctx
->vertices
[0][1][0], 8);
659 blitter_set_rectangle(ctx
, x1
, y1
, x2
, y2
, depth
);
660 blitter_draw_quad(ctx
);
663 void util_blitter_clear(struct blitter_context
*blitter
,
664 unsigned width
, unsigned height
,
666 unsigned clear_buffers
,
668 double depth
, unsigned stencil
)
670 struct blitter_context_priv
*ctx
= (struct blitter_context_priv
*)blitter
;
671 struct pipe_context
*pipe
= ctx
->base
.pipe
;
672 struct pipe_stencil_ref sr
= { { 0 } };
674 assert(num_cbufs
<= PIPE_MAX_COLOR_BUFS
);
676 blitter_check_saved_CSOs(ctx
);
679 if (clear_buffers
& PIPE_CLEAR_COLOR
)
680 pipe
->bind_blend_state(pipe
, ctx
->blend_write_color
);
682 pipe
->bind_blend_state(pipe
, ctx
->blend_keep_color
);
684 if ((clear_buffers
& PIPE_CLEAR_DEPTHSTENCIL
) == PIPE_CLEAR_DEPTHSTENCIL
) {
685 sr
.ref_value
[0] = stencil
& 0xff;
686 pipe
->bind_depth_stencil_alpha_state(pipe
, ctx
->dsa_write_depth_stencil
);
687 pipe
->set_stencil_ref(pipe
, &sr
);
689 else if (clear_buffers
& PIPE_CLEAR_DEPTH
) {
690 pipe
->bind_depth_stencil_alpha_state(pipe
, ctx
->dsa_write_depth_keep_stencil
);
692 else if (clear_buffers
& PIPE_CLEAR_STENCIL
) {
693 sr
.ref_value
[0] = stencil
& 0xff;
694 pipe
->bind_depth_stencil_alpha_state(pipe
, ctx
->dsa_keep_depth_write_stencil
);
695 pipe
->set_stencil_ref(pipe
, &sr
);
698 pipe
->bind_depth_stencil_alpha_state(pipe
, ctx
->dsa_keep_depth_stencil
);
700 pipe
->bind_rasterizer_state(pipe
, ctx
->rs_state
);
701 pipe
->bind_vertex_elements_state(pipe
, ctx
->velem_state
);
702 pipe
->bind_fs_state(pipe
, blitter_get_fs_col(ctx
, num_cbufs
));
703 pipe
->bind_vs_state(pipe
, ctx
->vs_col
);
705 blitter_set_dst_dimensions(ctx
, width
, height
);
706 blitter
->draw_rectangle(blitter
, 0, 0, width
, height
, depth
,
707 UTIL_BLITTER_ATTRIB_COLOR
, rgba
);
708 blitter_restore_CSOs(ctx
);
712 boolean
is_overlap(unsigned sx1
, unsigned sx2
, unsigned sy1
, unsigned sy2
,
713 unsigned dx1
, unsigned dx2
, unsigned dy1
, unsigned dy2
)
715 return sx1
< dx2
&& sx2
> dx1
&& sy1
< dy2
&& sy2
> dy1
;
718 void util_blitter_copy_region(struct blitter_context
*blitter
,
719 struct pipe_resource
*dst
,
720 struct pipe_subresource subdst
,
721 unsigned dstx
, unsigned dsty
, unsigned dstz
,
722 struct pipe_resource
*src
,
723 struct pipe_subresource subsrc
,
724 unsigned srcx
, unsigned srcy
, unsigned srcz
,
725 unsigned width
, unsigned height
,
726 boolean ignore_stencil
)
728 struct blitter_context_priv
*ctx
= (struct blitter_context_priv
*)blitter
;
729 struct pipe_context
*pipe
= ctx
->base
.pipe
;
730 struct pipe_screen
*screen
= pipe
->screen
;
731 struct pipe_surface
*dstsurf
;
732 struct pipe_framebuffer_state fb_state
;
733 struct pipe_sampler_view viewTempl
, *view
;
735 boolean is_stencil
, is_depth
;
738 /* Give up if textures are not set. */
745 assert(!is_overlap(srcx
, srcx
+ width
, srcy
, srcy
+ height
,
746 dstx
, dstx
+ width
, dsty
, dsty
+ height
));
748 assert(dst
->format
== src
->format
);
750 assert(src
->target
< PIPE_MAX_TEXTURE_TYPES
);
752 /* Is this a ZS format? */
753 is_depth
= util_format_get_component_bits(src
->format
, UTIL_FORMAT_COLORSPACE_ZS
, 0) != 0;
754 is_stencil
= util_format_get_component_bits(src
->format
, UTIL_FORMAT_COLORSPACE_ZS
, 1) != 0;
756 if (is_depth
|| is_stencil
)
757 bind
= PIPE_BIND_DEPTH_STENCIL
;
759 bind
= PIPE_BIND_RENDER_TARGET
;
761 /* Check if we can sample from and render to the surfaces. */
762 /* (assuming copying a stencil buffer is not possible) */
763 if ((!ignore_stencil
&& is_stencil
) ||
764 !screen
->is_format_supported(screen
, dst
->format
, dst
->target
,
765 dst
->nr_samples
, bind
, 0) ||
766 !screen
->is_format_supported(screen
, src
->format
, src
->target
,
767 src
->nr_samples
, PIPE_BIND_SAMPLER_VIEW
, 0)) {
768 util_resource_copy_region(pipe
, dst
, subdst
, dstx
, dsty
, dstz
,
769 src
, subsrc
, srcx
, srcy
, srcz
, width
, height
);
774 dstsurf
= screen
->get_tex_surface(screen
, dst
,
775 subdst
.face
, subdst
.level
, dstz
,
778 /* Check whether the states are properly saved. */
779 blitter_check_saved_CSOs(ctx
);
780 assert(blitter
->saved_fb_state
.nr_cbufs
!= ~0);
781 assert(blitter
->saved_num_sampler_views
!= ~0);
782 assert(blitter
->saved_num_sampler_states
!= ~0);
784 /* Initialize framebuffer state. */
785 fb_state
.width
= dstsurf
->width
;
786 fb_state
.height
= dstsurf
->height
;
789 pipe
->bind_blend_state(pipe
, ctx
->blend_keep_color
);
790 pipe
->bind_depth_stencil_alpha_state(pipe
,
791 ctx
->dsa_write_depth_keep_stencil
);
792 pipe
->bind_fs_state(pipe
,
793 blitter_get_fs_texfetch_depth(ctx
, src
->target
));
795 fb_state
.nr_cbufs
= 0;
796 fb_state
.zsbuf
= dstsurf
;
798 pipe
->bind_blend_state(pipe
, ctx
->blend_write_color
);
799 pipe
->bind_depth_stencil_alpha_state(pipe
, ctx
->dsa_keep_depth_stencil
);
800 pipe
->bind_fs_state(pipe
,
801 blitter_get_fs_texfetch_col(ctx
, src
->target
));
803 fb_state
.nr_cbufs
= 1;
804 fb_state
.cbufs
[0] = dstsurf
;
808 normalized
= src
->target
!= PIPE_TEXTURE_RECT
;
810 /* Initialize sampler view. */
811 u_sampler_view_default_template(&viewTempl
, src
, src
->format
);
812 view
= pipe
->create_sampler_view(pipe
, src
, &viewTempl
);
814 /* Set rasterizer state, shaders, and textures. */
815 pipe
->bind_rasterizer_state(pipe
, ctx
->rs_state
);
816 pipe
->bind_vs_state(pipe
, ctx
->vs_tex
);
817 pipe
->bind_fragment_sampler_states(pipe
, 1,
818 blitter_get_sampler_state(ctx
, subsrc
.level
, normalized
));
819 pipe
->bind_vertex_elements_state(pipe
, ctx
->velem_state
);
820 pipe
->set_fragment_sampler_views(pipe
, 1, &view
);
821 pipe
->set_framebuffer_state(pipe
, &fb_state
);
823 blitter_set_dst_dimensions(ctx
, dstsurf
->width
, dstsurf
->height
);
825 switch (src
->target
) {
826 /* Draw the quad with the draw_rectangle callback. */
827 case PIPE_TEXTURE_1D
:
828 case PIPE_TEXTURE_2D
:
829 case PIPE_TEXTURE_RECT
:
831 /* Set texture coordinates. */
833 get_texcoords(src
, subsrc
, srcx
, srcy
,
834 srcx
+width
, srcy
+height
, normalized
, coord
);
837 blitter
->draw_rectangle(blitter
, dstx
, dsty
, dstx
+width
, dsty
+height
, 0,
838 UTIL_BLITTER_ATTRIB_TEXCOORD
, coord
);
842 /* Draw the quad with the generic codepath. */
843 case PIPE_TEXTURE_3D
:
844 case PIPE_TEXTURE_CUBE
:
845 /* Set texture coordinates. */
846 if (src
->target
== PIPE_TEXTURE_3D
)
847 blitter_set_texcoords_3d(ctx
, src
, subsrc
, srcz
,
848 srcx
, srcy
, srcx
+width
, srcy
+height
);
850 blitter_set_texcoords_cube(ctx
, src
, subsrc
,
851 srcx
, srcy
, srcx
+width
, srcy
+height
);
854 blitter_set_rectangle(ctx
, dstx
, dsty
, dstx
+width
, dsty
+height
, 0);
855 blitter_draw_quad(ctx
);
863 blitter_restore_CSOs(ctx
);
865 pipe_surface_reference(&dstsurf
, NULL
);
866 pipe_sampler_view_reference(&view
, NULL
);
869 /* Clear a region of a color surface to a constant value. */
870 void util_blitter_clear_render_target(struct blitter_context
*blitter
,
871 struct pipe_surface
*dstsurf
,
873 unsigned dstx
, unsigned dsty
,
874 unsigned width
, unsigned height
)
876 struct blitter_context_priv
*ctx
= (struct blitter_context_priv
*)blitter
;
877 struct pipe_context
*pipe
= ctx
->base
.pipe
;
878 struct pipe_framebuffer_state fb_state
;
880 assert(dstsurf
->texture
);
881 if (!dstsurf
->texture
)
884 /* check the saved state */
885 blitter_check_saved_CSOs(ctx
);
886 assert(blitter
->saved_fb_state
.nr_cbufs
!= ~0);
889 pipe
->bind_blend_state(pipe
, ctx
->blend_write_color
);
890 pipe
->bind_depth_stencil_alpha_state(pipe
, ctx
->dsa_keep_depth_stencil
);
891 pipe
->bind_rasterizer_state(pipe
, ctx
->rs_state
);
892 pipe
->bind_fs_state(pipe
, blitter_get_fs_col(ctx
, 1));
893 pipe
->bind_vs_state(pipe
, ctx
->vs_col
);
894 pipe
->bind_vertex_elements_state(pipe
, ctx
->velem_state
);
896 /* set a framebuffer state */
897 fb_state
.width
= dstsurf
->width
;
898 fb_state
.height
= dstsurf
->height
;
899 fb_state
.nr_cbufs
= 1;
900 fb_state
.cbufs
[0] = dstsurf
;
902 pipe
->set_framebuffer_state(pipe
, &fb_state
);
904 blitter_set_dst_dimensions(ctx
, dstsurf
->width
, dstsurf
->height
);
905 blitter
->draw_rectangle(blitter
, dstx
, dsty
, dstx
+width
, dsty
+height
, 0,
906 UTIL_BLITTER_ATTRIB_COLOR
, rgba
);
907 blitter_restore_CSOs(ctx
);
910 /* Clear a region of a depth stencil surface. */
911 void util_blitter_clear_depth_stencil(struct blitter_context
*blitter
,
912 struct pipe_surface
*dstsurf
,
913 unsigned clear_flags
,
916 unsigned dstx
, unsigned dsty
,
917 unsigned width
, unsigned height
)
919 struct blitter_context_priv
*ctx
= (struct blitter_context_priv
*)blitter
;
920 struct pipe_context
*pipe
= ctx
->base
.pipe
;
921 struct pipe_framebuffer_state fb_state
;
922 struct pipe_stencil_ref sr
= { { 0 } };
924 assert(dstsurf
->texture
);
925 if (!dstsurf
->texture
)
928 /* check the saved state */
929 blitter_check_saved_CSOs(ctx
);
930 assert(blitter
->saved_fb_state
.nr_cbufs
!= ~0);
933 pipe
->bind_blend_state(pipe
, ctx
->blend_keep_color
);
934 if ((clear_flags
& PIPE_CLEAR_DEPTHSTENCIL
) == PIPE_CLEAR_DEPTHSTENCIL
) {
935 sr
.ref_value
[0] = stencil
& 0xff;
936 pipe
->bind_depth_stencil_alpha_state(pipe
, ctx
->dsa_write_depth_stencil
);
937 pipe
->set_stencil_ref(pipe
, &sr
);
939 else if (clear_flags
& PIPE_CLEAR_DEPTH
) {
940 pipe
->bind_depth_stencil_alpha_state(pipe
, ctx
->dsa_write_depth_keep_stencil
);
942 else if (clear_flags
& PIPE_CLEAR_STENCIL
) {
943 sr
.ref_value
[0] = stencil
& 0xff;
944 pipe
->bind_depth_stencil_alpha_state(pipe
, ctx
->dsa_keep_depth_write_stencil
);
945 pipe
->set_stencil_ref(pipe
, &sr
);
948 /* hmm that should be illegal probably, or make it a no-op somewhere */
949 pipe
->bind_depth_stencil_alpha_state(pipe
, ctx
->dsa_keep_depth_stencil
);
951 pipe
->bind_rasterizer_state(pipe
, ctx
->rs_state
);
952 pipe
->bind_fs_state(pipe
, blitter_get_fs_col(ctx
, 0));
953 pipe
->bind_vs_state(pipe
, ctx
->vs_col
);
954 pipe
->bind_vertex_elements_state(pipe
, ctx
->velem_state
);
956 /* set a framebuffer state */
957 fb_state
.width
= dstsurf
->width
;
958 fb_state
.height
= dstsurf
->height
;
959 fb_state
.nr_cbufs
= 0;
960 fb_state
.cbufs
[0] = 0;
961 fb_state
.zsbuf
= dstsurf
;
962 pipe
->set_framebuffer_state(pipe
, &fb_state
);
964 blitter_set_dst_dimensions(ctx
, dstsurf
->width
, dstsurf
->height
);
965 blitter
->draw_rectangle(blitter
, dstx
, dsty
, dstx
+width
, dsty
+height
, depth
,
966 UTIL_BLITTER_ATTRIB_NONE
, NULL
);
967 blitter_restore_CSOs(ctx
);
970 /* draw a rectangle across a region using a custom dsa stage - for r600g */
971 void util_blitter_custom_depth_stencil(struct blitter_context
*blitter
,
972 struct pipe_surface
*zsurf
,
973 struct pipe_surface
*cbsurf
,
974 void *dsa_stage
, float depth
)
976 struct blitter_context_priv
*ctx
= (struct blitter_context_priv
*)blitter
;
977 struct pipe_context
*pipe
= ctx
->base
.pipe
;
978 struct pipe_framebuffer_state fb_state
;
980 assert(zsurf
->texture
);
984 /* check the saved state */
985 blitter_check_saved_CSOs(ctx
);
986 assert(blitter
->saved_fb_state
.nr_cbufs
!= ~0);
989 pipe
->bind_blend_state(pipe
, ctx
->blend_write_color
);
990 pipe
->bind_depth_stencil_alpha_state(pipe
, dsa_stage
);
992 pipe
->bind_rasterizer_state(pipe
, ctx
->rs_state
);
993 pipe
->bind_fs_state(pipe
, blitter_get_fs_col(ctx
, 0));
994 pipe
->bind_vs_state(pipe
, ctx
->vs_col
);
995 pipe
->bind_vertex_elements_state(pipe
, ctx
->velem_state
);
997 /* set a framebuffer state */
998 fb_state
.width
= zsurf
->width
;
999 fb_state
.height
= zsurf
->height
;
1000 fb_state
.nr_cbufs
= 1;
1002 fb_state
.cbufs
[0] = cbsurf
;
1003 fb_state
.nr_cbufs
= 1;
1005 fb_state
.cbufs
[0] = NULL
;
1006 fb_state
.nr_cbufs
= 0;
1008 fb_state
.zsbuf
= zsurf
;
1009 pipe
->set_framebuffer_state(pipe
, &fb_state
);
1011 blitter_set_dst_dimensions(ctx
, zsurf
->width
, zsurf
->height
);
1012 blitter
->draw_rectangle(blitter
, 0, 0, zsurf
->width
, zsurf
->height
, depth
,
1013 UTIL_BLITTER_ATTRIB_NONE
, NULL
);
1014 blitter_restore_CSOs(ctx
);
1017 /* flush a region of a depth stencil surface for r300g */
1018 void util_blitter_flush_depth_stencil(struct blitter_context
*blitter
,
1019 struct pipe_surface
*dstsurf
)
1021 struct blitter_context_priv
*ctx
= (struct blitter_context_priv
*)blitter
;
1022 util_blitter_custom_depth_stencil(blitter
, dstsurf
, NULL
,
1023 ctx
->dsa_flush_depth_stencil
, 0.0f
);