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"
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
; /**< Vertex shader which passes {pos, generic} to the output.*/
68 /* Fragment shaders. */
69 /* The shader at index i outputs color to color buffers 0,1,...,i-1. */
70 void *fs_col
[PIPE_MAX_COLOR_BUFS
+1];
72 /* FS which outputs a color from a texture,
73 where the index is PIPE_TEXTURE_* to be sampled. */
74 void *fs_texfetch_col
[PIPE_MAX_TEXTURE_TYPES
];
76 /* FS which outputs a depth from a texture,
77 where the index is PIPE_TEXTURE_* to be sampled. */
78 void *fs_texfetch_depth
[PIPE_MAX_TEXTURE_TYPES
];
81 void *blend_write_color
; /**< blend state with writemask of RGBA */
82 void *blend_keep_color
; /**< blend state with writemask of 0 */
84 /* Depth stencil alpha state. */
85 void *dsa_write_depth_stencil
;
86 void *dsa_write_depth_keep_stencil
;
87 void *dsa_keep_depth_stencil
;
88 void *dsa_keep_depth_write_stencil
;
92 /* Sampler state for clamping to a miplevel. */
93 void *sampler_state
[PIPE_MAX_TEXTURE_LEVELS
* 2];
95 /* Rasterizer state. */
99 struct pipe_viewport_state viewport
;
102 struct pipe_clip_state clip
;
104 /* Destination surface dimensions. */
109 static void blitter_draw_rectangle(struct blitter_context
*blitter
,
110 unsigned x
, unsigned y
,
111 unsigned width
, unsigned height
,
113 enum blitter_attrib_type type
,
114 const union pipe_color_union
*attrib
);
117 struct blitter_context
*util_blitter_create(struct pipe_context
*pipe
)
119 struct blitter_context_priv
*ctx
;
120 struct pipe_blend_state blend
;
121 struct pipe_depth_stencil_alpha_state dsa
;
122 struct pipe_rasterizer_state rs_state
;
123 struct pipe_sampler_state
*sampler_state
;
124 struct pipe_vertex_element velem
[2];
127 ctx
= CALLOC_STRUCT(blitter_context_priv
);
131 ctx
->base
.pipe
= pipe
;
132 ctx
->base
.draw_rectangle
= blitter_draw_rectangle
;
134 /* init state objects for them to be considered invalid */
135 ctx
->base
.saved_blend_state
= INVALID_PTR
;
136 ctx
->base
.saved_dsa_state
= INVALID_PTR
;
137 ctx
->base
.saved_rs_state
= INVALID_PTR
;
138 ctx
->base
.saved_fs
= INVALID_PTR
;
139 ctx
->base
.saved_vs
= INVALID_PTR
;
140 ctx
->base
.saved_velem_state
= INVALID_PTR
;
141 ctx
->base
.saved_fb_state
.nr_cbufs
= ~0;
142 ctx
->base
.saved_num_sampler_views
= ~0;
143 ctx
->base
.saved_num_sampler_states
= ~0;
144 ctx
->base
.saved_num_vertex_buffers
= ~0;
146 /* blend state objects */
147 memset(&blend
, 0, sizeof(blend
));
148 ctx
->blend_keep_color
= pipe
->create_blend_state(pipe
, &blend
);
150 blend
.rt
[0].colormask
= PIPE_MASK_RGBA
;
151 ctx
->blend_write_color
= pipe
->create_blend_state(pipe
, &blend
);
153 /* depth stencil alpha state objects */
154 memset(&dsa
, 0, sizeof(dsa
));
155 ctx
->dsa_keep_depth_stencil
=
156 pipe
->create_depth_stencil_alpha_state(pipe
, &dsa
);
158 dsa
.depth
.enabled
= 1;
159 dsa
.depth
.writemask
= 1;
160 dsa
.depth
.func
= PIPE_FUNC_ALWAYS
;
161 ctx
->dsa_write_depth_keep_stencil
=
162 pipe
->create_depth_stencil_alpha_state(pipe
, &dsa
);
164 dsa
.stencil
[0].enabled
= 1;
165 dsa
.stencil
[0].func
= PIPE_FUNC_ALWAYS
;
166 dsa
.stencil
[0].fail_op
= PIPE_STENCIL_OP_REPLACE
;
167 dsa
.stencil
[0].zpass_op
= PIPE_STENCIL_OP_REPLACE
;
168 dsa
.stencil
[0].zfail_op
= PIPE_STENCIL_OP_REPLACE
;
169 dsa
.stencil
[0].valuemask
= 0xff;
170 dsa
.stencil
[0].writemask
= 0xff;
171 ctx
->dsa_write_depth_stencil
=
172 pipe
->create_depth_stencil_alpha_state(pipe
, &dsa
);
175 dsa
.depth
.enabled
= 0;
176 dsa
.depth
.writemask
= 0;
177 ctx
->dsa_keep_depth_write_stencil
=
178 pipe
->create_depth_stencil_alpha_state(pipe
, &dsa
);
181 sampler_state
= &ctx
->template_sampler_state
;
182 sampler_state
->wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
183 sampler_state
->wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
184 sampler_state
->wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
185 sampler_state
->normalized_coords
= TRUE
;
186 /* The sampler state objects which sample from a specified mipmap level
187 * are created on-demand. */
189 /* rasterizer state */
190 memset(&rs_state
, 0, sizeof(rs_state
));
191 rs_state
.cull_face
= PIPE_FACE_NONE
;
192 rs_state
.gl_rasterization_rules
= 1;
193 rs_state
.flatshade
= 1;
194 ctx
->rs_state
= pipe
->create_rasterizer_state(pipe
, &rs_state
);
196 /* vertex elements state */
197 memset(&velem
[0], 0, sizeof(velem
[0]) * 2);
198 for (i
= 0; i
< 2; i
++) {
199 velem
[i
].src_offset
= i
* 4 * sizeof(float);
200 velem
[i
].src_format
= PIPE_FORMAT_R32G32B32A32_FLOAT
;
202 ctx
->velem_state
= pipe
->create_vertex_elements_state(pipe
, 2, &velem
[0]);
204 /* fragment shaders are created on-demand */
208 const uint semantic_names
[] = { TGSI_SEMANTIC_POSITION
,
209 TGSI_SEMANTIC_GENERIC
};
210 const uint semantic_indices
[] = { 0, 0 };
212 util_make_vertex_passthrough_shader(pipe
, 2, semantic_names
,
216 /* set invariant vertex coordinates */
217 for (i
= 0; i
< 4; i
++)
218 ctx
->vertices
[i
][0][3] = 1; /*v.w*/
220 /* create the vertex buffer */
221 ctx
->vbuf
= pipe_user_buffer_create(ctx
->base
.pipe
->screen
,
223 sizeof(ctx
->vertices
),
224 PIPE_BIND_VERTEX_BUFFER
);
229 void util_blitter_destroy(struct blitter_context
*blitter
)
231 struct blitter_context_priv
*ctx
= (struct blitter_context_priv
*)blitter
;
232 struct pipe_context
*pipe
= blitter
->pipe
;
235 pipe
->delete_blend_state(pipe
, ctx
->blend_write_color
);
236 pipe
->delete_blend_state(pipe
, ctx
->blend_keep_color
);
237 pipe
->delete_depth_stencil_alpha_state(pipe
, ctx
->dsa_keep_depth_stencil
);
238 pipe
->delete_depth_stencil_alpha_state(pipe
,
239 ctx
->dsa_write_depth_keep_stencil
);
240 pipe
->delete_depth_stencil_alpha_state(pipe
, ctx
->dsa_write_depth_stencil
);
241 pipe
->delete_depth_stencil_alpha_state(pipe
, ctx
->dsa_keep_depth_write_stencil
);
243 pipe
->delete_rasterizer_state(pipe
, ctx
->rs_state
);
244 pipe
->delete_vs_state(pipe
, ctx
->vs
);
245 pipe
->delete_vertex_elements_state(pipe
, ctx
->velem_state
);
247 for (i
= 0; i
< PIPE_MAX_TEXTURE_TYPES
; i
++) {
248 if (ctx
->fs_texfetch_col
[i
])
249 pipe
->delete_fs_state(pipe
, ctx
->fs_texfetch_col
[i
]);
250 if (ctx
->fs_texfetch_depth
[i
])
251 pipe
->delete_fs_state(pipe
, ctx
->fs_texfetch_depth
[i
]);
254 for (i
= 0; i
<= PIPE_MAX_COLOR_BUFS
; i
++)
256 pipe
->delete_fs_state(pipe
, ctx
->fs_col
[i
]);
258 for (i
= 0; i
< PIPE_MAX_TEXTURE_LEVELS
* 2; i
++)
259 if (ctx
->sampler_state
[i
])
260 pipe
->delete_sampler_state(pipe
, ctx
->sampler_state
[i
]);
262 pipe_resource_reference(&ctx
->vbuf
, NULL
);
266 static void blitter_check_saved_CSOs(struct blitter_context_priv
*ctx
)
268 if (ctx
->base
.running
) {
269 _debug_printf("u_blitter: Caught recursion on save. "
270 "This is a driver bug.\n");
272 ctx
->base
.running
= TRUE
;
274 /* make sure these CSOs have been saved */
275 assert(ctx
->base
.saved_blend_state
!= INVALID_PTR
&&
276 ctx
->base
.saved_dsa_state
!= INVALID_PTR
&&
277 ctx
->base
.saved_rs_state
!= INVALID_PTR
&&
278 ctx
->base
.saved_fs
!= INVALID_PTR
&&
279 ctx
->base
.saved_vs
!= INVALID_PTR
&&
280 ctx
->base
.saved_velem_state
!= INVALID_PTR
);
283 static void blitter_restore_CSOs(struct blitter_context_priv
*ctx
)
285 struct pipe_context
*pipe
= ctx
->base
.pipe
;
288 /* restore the state objects which are always required to be saved */
289 pipe
->bind_rasterizer_state(pipe
, ctx
->base
.saved_rs_state
);
290 pipe
->bind_vs_state(pipe
, ctx
->base
.saved_vs
);
291 pipe
->bind_vertex_elements_state(pipe
, ctx
->base
.saved_velem_state
);
293 ctx
->base
.saved_rs_state
= INVALID_PTR
;
294 ctx
->base
.saved_vs
= INVALID_PTR
;
295 ctx
->base
.saved_velem_state
= INVALID_PTR
;
297 /* restore the state objects which are required to be saved for clear/copy
299 if (ctx
->base
.saved_blend_state
!= INVALID_PTR
) {
300 pipe
->bind_blend_state(pipe
, ctx
->base
.saved_blend_state
);
301 ctx
->base
.saved_blend_state
= INVALID_PTR
;
303 if (ctx
->base
.saved_dsa_state
!= INVALID_PTR
) {
304 pipe
->bind_depth_stencil_alpha_state(pipe
, ctx
->base
.saved_dsa_state
);
305 ctx
->base
.saved_dsa_state
= INVALID_PTR
;
307 if (ctx
->base
.saved_fs
!= INVALID_PTR
) {
308 pipe
->bind_fs_state(pipe
, ctx
->base
.saved_fs
);
309 ctx
->base
.saved_fs
= INVALID_PTR
;
312 pipe
->set_stencil_ref(pipe
, &ctx
->base
.saved_stencil_ref
);
313 pipe
->set_viewport_state(pipe
, &ctx
->base
.saved_viewport
);
314 pipe
->set_clip_state(pipe
, &ctx
->base
.saved_clip
);
316 if (ctx
->base
.saved_fb_state
.nr_cbufs
!= ~0) {
317 pipe
->set_framebuffer_state(pipe
, &ctx
->base
.saved_fb_state
);
318 util_unreference_framebuffer_state(&ctx
->base
.saved_fb_state
);
319 ctx
->base
.saved_fb_state
.nr_cbufs
= ~0;
322 if (ctx
->base
.saved_num_sampler_states
!= ~0) {
323 pipe
->bind_fragment_sampler_states(pipe
,
324 ctx
->base
.saved_num_sampler_states
,
325 ctx
->base
.saved_sampler_states
);
326 ctx
->base
.saved_num_sampler_states
= ~0;
329 if (ctx
->base
.saved_num_sampler_views
!= ~0) {
330 pipe
->set_fragment_sampler_views(pipe
,
331 ctx
->base
.saved_num_sampler_views
,
332 ctx
->base
.saved_sampler_views
);
334 for (i
= 0; i
< ctx
->base
.saved_num_sampler_views
; i
++)
335 pipe_sampler_view_reference(&ctx
->base
.saved_sampler_views
[i
],
338 ctx
->base
.saved_num_sampler_views
= ~0;
341 if (ctx
->base
.saved_num_vertex_buffers
!= ~0) {
342 pipe
->set_vertex_buffers(pipe
,
343 ctx
->base
.saved_num_vertex_buffers
,
344 ctx
->base
.saved_vertex_buffers
);
346 for (i
= 0; i
< ctx
->base
.saved_num_vertex_buffers
; i
++) {
347 if (ctx
->base
.saved_vertex_buffers
[i
].buffer
) {
348 pipe_resource_reference(&ctx
->base
.saved_vertex_buffers
[i
].buffer
,
352 ctx
->base
.saved_num_vertex_buffers
= ~0;
355 if (!ctx
->base
.running
) {
356 _debug_printf("u_blitter: Caught recursion on restore. "
357 "This is a driver bug.\n");
359 ctx
->base
.running
= FALSE
;
362 static void blitter_set_rectangle(struct blitter_context_priv
*ctx
,
363 unsigned x1
, unsigned y1
,
364 unsigned x2
, unsigned y2
,
369 /* set vertex positions */
370 ctx
->vertices
[0][0][0] = (float)x1
/ ctx
->dst_width
* 2.0f
- 1.0f
; /*v0.x*/
371 ctx
->vertices
[0][0][1] = (float)y1
/ ctx
->dst_height
* 2.0f
- 1.0f
; /*v0.y*/
373 ctx
->vertices
[1][0][0] = (float)x2
/ ctx
->dst_width
* 2.0f
- 1.0f
; /*v1.x*/
374 ctx
->vertices
[1][0][1] = (float)y1
/ ctx
->dst_height
* 2.0f
- 1.0f
; /*v1.y*/
376 ctx
->vertices
[2][0][0] = (float)x2
/ ctx
->dst_width
* 2.0f
- 1.0f
; /*v2.x*/
377 ctx
->vertices
[2][0][1] = (float)y2
/ ctx
->dst_height
* 2.0f
- 1.0f
; /*v2.y*/
379 ctx
->vertices
[3][0][0] = (float)x1
/ ctx
->dst_width
* 2.0f
- 1.0f
; /*v3.x*/
380 ctx
->vertices
[3][0][1] = (float)y2
/ ctx
->dst_height
* 2.0f
- 1.0f
; /*v3.y*/
382 for (i
= 0; i
< 4; i
++)
383 ctx
->vertices
[i
][0][2] = depth
; /*z*/
386 ctx
->viewport
.scale
[0] = 0.5f
* ctx
->dst_width
;
387 ctx
->viewport
.scale
[1] = 0.5f
* ctx
->dst_height
;
388 ctx
->viewport
.scale
[2] = 1.0f
;
389 ctx
->viewport
.scale
[3] = 1.0f
;
390 ctx
->viewport
.translate
[0] = 0.5f
* ctx
->dst_width
;
391 ctx
->viewport
.translate
[1] = 0.5f
* ctx
->dst_height
;
392 ctx
->viewport
.translate
[2] = 0.0f
;
393 ctx
->viewport
.translate
[3] = 0.0f
;
394 ctx
->base
.pipe
->set_viewport_state(ctx
->base
.pipe
, &ctx
->viewport
);
397 ctx
->base
.pipe
->set_clip_state(ctx
->base
.pipe
, &ctx
->clip
);
400 static void blitter_set_clear_color(struct blitter_context_priv
*ctx
,
401 const union pipe_color_union
*color
)
406 for (i
= 0; i
< 4; i
++) {
407 ctx
->vertices
[i
][1][0] = color
->f
[0];
408 ctx
->vertices
[i
][1][1] = color
->f
[1];
409 ctx
->vertices
[i
][1][2] = color
->f
[2];
410 ctx
->vertices
[i
][1][3] = color
->f
[3];
413 for (i
= 0; i
< 4; i
++) {
414 ctx
->vertices
[i
][1][0] = 0;
415 ctx
->vertices
[i
][1][1] = 0;
416 ctx
->vertices
[i
][1][2] = 0;
417 ctx
->vertices
[i
][1][3] = 0;
422 static void get_texcoords(struct pipe_resource
*src
,
424 unsigned x1
, unsigned y1
,
425 unsigned x2
, unsigned y2
,
426 boolean normalized
, float out
[4])
430 out
[0] = x1
/ (float)u_minify(src
->width0
, level
);
431 out
[1] = y1
/ (float)u_minify(src
->height0
, level
);
432 out
[2] = x2
/ (float)u_minify(src
->width0
, level
);
433 out
[3] = y2
/ (float)u_minify(src
->height0
, level
);
444 static void set_texcoords_in_vertices(const float coord
[4],
445 float *out
, unsigned stride
)
447 out
[0] = coord
[0]; /*t0.s*/
448 out
[1] = coord
[1]; /*t0.t*/
450 out
[0] = coord
[2]; /*t1.s*/
451 out
[1] = coord
[1]; /*t1.t*/
453 out
[0] = coord
[2]; /*t2.s*/
454 out
[1] = coord
[3]; /*t2.t*/
456 out
[0] = coord
[0]; /*t3.s*/
457 out
[1] = coord
[3]; /*t3.t*/
460 static void blitter_set_texcoords_2d(struct blitter_context_priv
*ctx
,
461 struct pipe_resource
*src
,
463 unsigned x1
, unsigned y1
,
464 unsigned x2
, unsigned y2
)
469 get_texcoords(src
, level
, x1
, y1
, x2
, y2
, TRUE
, coord
);
470 set_texcoords_in_vertices(coord
, &ctx
->vertices
[0][1][0], 8);
472 for (i
= 0; i
< 4; i
++) {
473 ctx
->vertices
[i
][1][2] = 0; /*r*/
474 ctx
->vertices
[i
][1][3] = 1; /*q*/
478 static void blitter_set_texcoords_3d(struct blitter_context_priv
*ctx
,
479 struct pipe_resource
*src
,
482 unsigned x1
, unsigned y1
,
483 unsigned x2
, unsigned y2
,
487 float r
= normalized
? zslice
/ (float)u_minify(src
->depth0
, level
) : zslice
;
489 blitter_set_texcoords_2d(ctx
, src
, level
, x1
, y1
, x2
, y2
);
491 for (i
= 0; i
< 4; i
++)
492 ctx
->vertices
[i
][1][2] = r
; /*r*/
495 static void blitter_set_texcoords_1d_array(struct blitter_context_priv
*ctx
,
496 struct pipe_resource
*src
,
499 unsigned x1
, unsigned x2
)
504 blitter_set_texcoords_2d(ctx
, src
, level
, x1
, 0, x2
, 0);
506 for (i
= 0; i
< 4; i
++)
507 ctx
->vertices
[i
][1][1] = r
; /*r*/
510 static void blitter_set_texcoords_cube(struct blitter_context_priv
*ctx
,
511 struct pipe_resource
*src
,
512 unsigned level
, unsigned face
,
513 unsigned x1
, unsigned y1
,
514 unsigned x2
, unsigned y2
)
520 get_texcoords(src
, level
, x1
, y1
, x2
, y2
, TRUE
, coord
);
521 set_texcoords_in_vertices(coord
, &st
[0][0], 2);
523 util_map_texcoords2d_onto_cubemap(face
,
524 /* pointer, stride in floats */
526 &ctx
->vertices
[0][1][0], 8);
528 for (i
= 0; i
< 4; i
++)
529 ctx
->vertices
[i
][1][3] = 1; /*q*/
532 static void blitter_set_dst_dimensions(struct blitter_context_priv
*ctx
,
533 unsigned width
, unsigned height
)
535 ctx
->dst_width
= width
;
536 ctx
->dst_height
= height
;
540 void **blitter_get_sampler_state(struct blitter_context_priv
*ctx
,
541 int miplevel
, boolean normalized
)
543 struct pipe_context
*pipe
= ctx
->base
.pipe
;
544 struct pipe_sampler_state
*sampler_state
= &ctx
->template_sampler_state
;
546 assert(miplevel
< PIPE_MAX_TEXTURE_LEVELS
);
548 /* Create the sampler state on-demand. */
549 if (!ctx
->sampler_state
[miplevel
* 2 + normalized
]) {
550 sampler_state
->lod_bias
= miplevel
;
551 sampler_state
->min_lod
= miplevel
;
552 sampler_state
->max_lod
= miplevel
;
553 sampler_state
->normalized_coords
= normalized
;
555 ctx
->sampler_state
[miplevel
* 2 + normalized
] = pipe
->create_sampler_state(pipe
,
559 /* Return void** so that it can be passed to bind_fragment_sampler_states
561 return &ctx
->sampler_state
[miplevel
* 2 + normalized
];
565 void *blitter_get_fs_col(struct blitter_context_priv
*ctx
, unsigned num_cbufs
)
567 struct pipe_context
*pipe
= ctx
->base
.pipe
;
569 assert(num_cbufs
<= PIPE_MAX_COLOR_BUFS
);
571 if (!ctx
->fs_col
[num_cbufs
])
572 ctx
->fs_col
[num_cbufs
] =
573 util_make_fragment_cloneinput_shader(pipe
, num_cbufs
,
574 TGSI_SEMANTIC_GENERIC
,
575 TGSI_INTERPOLATE_LINEAR
);
577 return ctx
->fs_col
[num_cbufs
];
580 /** Convert PIPE_TEXTURE_x to TGSI_TEXTURE_x */
582 pipe_tex_to_tgsi_tex(enum pipe_texture_target pipe_tex_target
)
584 switch (pipe_tex_target
) {
585 case PIPE_TEXTURE_1D
:
586 return TGSI_TEXTURE_1D
;
587 case PIPE_TEXTURE_2D
:
588 return TGSI_TEXTURE_2D
;
589 case PIPE_TEXTURE_RECT
:
590 return TGSI_TEXTURE_RECT
;
591 case PIPE_TEXTURE_3D
:
592 return TGSI_TEXTURE_3D
;
593 case PIPE_TEXTURE_CUBE
:
594 return TGSI_TEXTURE_CUBE
;
595 case PIPE_TEXTURE_1D_ARRAY
:
596 return TGSI_TEXTURE_1D_ARRAY
;
597 case PIPE_TEXTURE_2D_ARRAY
:
598 return TGSI_TEXTURE_2D_ARRAY
;
600 assert(0 && "unexpected texture target");
601 return TGSI_TEXTURE_UNKNOWN
;
607 void *blitter_get_fs_texfetch_col(struct blitter_context_priv
*ctx
,
610 struct pipe_context
*pipe
= ctx
->base
.pipe
;
612 assert(tex_target
< PIPE_MAX_TEXTURE_TYPES
);
614 /* Create the fragment shader on-demand. */
615 if (!ctx
->fs_texfetch_col
[tex_target
]) {
616 unsigned tgsi_tex
= pipe_tex_to_tgsi_tex(tex_target
);
618 ctx
->fs_texfetch_col
[tex_target
] =
619 util_make_fragment_tex_shader(pipe
, tgsi_tex
, TGSI_INTERPOLATE_LINEAR
);
622 return ctx
->fs_texfetch_col
[tex_target
];
626 void *blitter_get_fs_texfetch_depth(struct blitter_context_priv
*ctx
,
629 struct pipe_context
*pipe
= ctx
->base
.pipe
;
631 assert(tex_target
< PIPE_MAX_TEXTURE_TYPES
);
633 /* Create the fragment shader on-demand. */
634 if (!ctx
->fs_texfetch_depth
[tex_target
]) {
635 unsigned tgsi_tex
= pipe_tex_to_tgsi_tex(tex_target
);
637 ctx
->fs_texfetch_depth
[tex_target
] =
638 util_make_fragment_tex_shader_writedepth(pipe
, tgsi_tex
,
639 TGSI_INTERPOLATE_LINEAR
);
642 return ctx
->fs_texfetch_depth
[tex_target
];
645 static void blitter_draw_rectangle(struct blitter_context
*blitter
,
646 unsigned x1
, unsigned y1
,
647 unsigned x2
, unsigned y2
,
649 enum blitter_attrib_type type
,
650 const union pipe_color_union
*attrib
)
652 struct blitter_context_priv
*ctx
= (struct blitter_context_priv
*)blitter
;
655 case UTIL_BLITTER_ATTRIB_COLOR
:
656 blitter_set_clear_color(ctx
, attrib
);
659 case UTIL_BLITTER_ATTRIB_TEXCOORD
:
660 set_texcoords_in_vertices(attrib
->f
, &ctx
->vertices
[0][1][0], 8);
666 blitter_set_rectangle(ctx
, x1
, y1
, x2
, y2
, depth
);
667 ctx
->base
.pipe
->redefine_user_buffer(ctx
->base
.pipe
, ctx
->vbuf
,
668 0, ctx
->vbuf
->width0
);
669 util_draw_vertex_buffer(ctx
->base
.pipe
, NULL
, ctx
->vbuf
, 0,
670 PIPE_PRIM_TRIANGLE_FAN
, 4, 2);
673 static void util_blitter_clear_custom(struct blitter_context
*blitter
,
674 unsigned width
, unsigned height
,
676 unsigned clear_buffers
,
677 const union pipe_color_union
*color
,
678 double depth
, unsigned stencil
,
679 void *custom_blend
, void *custom_dsa
)
681 struct blitter_context_priv
*ctx
= (struct blitter_context_priv
*)blitter
;
682 struct pipe_context
*pipe
= ctx
->base
.pipe
;
683 struct pipe_stencil_ref sr
= { { 0 } };
685 assert(num_cbufs
<= PIPE_MAX_COLOR_BUFS
);
687 blitter_check_saved_CSOs(ctx
);
691 pipe
->bind_blend_state(pipe
, custom_blend
);
692 } else if (clear_buffers
& PIPE_CLEAR_COLOR
) {
693 pipe
->bind_blend_state(pipe
, ctx
->blend_write_color
);
695 pipe
->bind_blend_state(pipe
, ctx
->blend_keep_color
);
699 pipe
->bind_depth_stencil_alpha_state(pipe
, custom_dsa
);
700 } else if ((clear_buffers
& PIPE_CLEAR_DEPTHSTENCIL
) == PIPE_CLEAR_DEPTHSTENCIL
) {
701 pipe
->bind_depth_stencil_alpha_state(pipe
, ctx
->dsa_write_depth_stencil
);
702 } else if (clear_buffers
& PIPE_CLEAR_DEPTH
) {
703 pipe
->bind_depth_stencil_alpha_state(pipe
, ctx
->dsa_write_depth_keep_stencil
);
704 } else if (clear_buffers
& PIPE_CLEAR_STENCIL
) {
705 pipe
->bind_depth_stencil_alpha_state(pipe
, ctx
->dsa_keep_depth_write_stencil
);
707 pipe
->bind_depth_stencil_alpha_state(pipe
, ctx
->dsa_keep_depth_stencil
);
710 sr
.ref_value
[0] = stencil
& 0xff;
711 pipe
->set_stencil_ref(pipe
, &sr
);
713 pipe
->bind_rasterizer_state(pipe
, ctx
->rs_state
);
714 pipe
->bind_vertex_elements_state(pipe
, ctx
->velem_state
);
715 pipe
->bind_fs_state(pipe
, blitter_get_fs_col(ctx
, num_cbufs
));
716 pipe
->bind_vs_state(pipe
, ctx
->vs
);
718 blitter_set_dst_dimensions(ctx
, width
, height
);
719 blitter
->draw_rectangle(blitter
, 0, 0, width
, height
, depth
,
720 UTIL_BLITTER_ATTRIB_COLOR
, color
);
721 blitter_restore_CSOs(ctx
);
724 void util_blitter_clear(struct blitter_context
*blitter
,
725 unsigned width
, unsigned height
,
727 unsigned clear_buffers
,
728 const union pipe_color_union
*color
,
729 double depth
, unsigned stencil
)
731 util_blitter_clear_custom(blitter
, width
, height
, num_cbufs
,
732 clear_buffers
, color
, depth
, stencil
,
736 void util_blitter_clear_depth_custom(struct blitter_context
*blitter
,
737 unsigned width
, unsigned height
,
738 double depth
, void *custom_dsa
)
740 static const union pipe_color_union color
;
741 util_blitter_clear_custom(blitter
, width
, height
, 0,
742 0, &color
, depth
, 0, NULL
, custom_dsa
);
746 boolean
is_overlap(unsigned sx1
, unsigned sx2
, unsigned sy1
, unsigned sy2
,
747 unsigned dx1
, unsigned dx2
, unsigned dy1
, unsigned dy2
)
749 return sx1
< dx2
&& sx2
> dx1
&& sy1
< dy2
&& sy2
> dy1
;
752 void util_blitter_copy_texture(struct blitter_context
*blitter
,
753 struct pipe_resource
*dst
,
755 unsigned dstx
, unsigned dsty
, unsigned dstz
,
756 struct pipe_resource
*src
,
758 const struct pipe_box
*srcbox
,
759 boolean ignore_stencil
)
761 struct blitter_context_priv
*ctx
= (struct blitter_context_priv
*)blitter
;
762 struct pipe_context
*pipe
= ctx
->base
.pipe
;
763 struct pipe_screen
*screen
= pipe
->screen
;
764 struct pipe_surface
*dstsurf
, surf_templ
;
765 struct pipe_framebuffer_state fb_state
;
766 struct pipe_sampler_view viewTempl
, *view
;
768 unsigned width
= srcbox
->width
;
769 unsigned height
= srcbox
->height
;
770 boolean is_stencil
, is_depth
;
773 /* Give up if textures are not set. */
780 assert(!is_overlap(srcbox
->x
, srcbox
->x
+ width
, srcbox
->y
, srcbox
->y
+ height
,
781 dstx
, dstx
+ width
, dsty
, dsty
+ height
));
783 assert(src
->target
< PIPE_MAX_TEXTURE_TYPES
);
784 /* XXX should handle 3d regions */
785 assert(srcbox
->depth
== 1);
787 /* Is this a ZS format? */
788 is_depth
= util_format_get_component_bits(src
->format
, UTIL_FORMAT_COLORSPACE_ZS
, 0) != 0;
789 is_stencil
= util_format_get_component_bits(src
->format
, UTIL_FORMAT_COLORSPACE_ZS
, 1) != 0;
791 if (is_depth
|| is_stencil
)
792 bind
= PIPE_BIND_DEPTH_STENCIL
;
794 bind
= PIPE_BIND_RENDER_TARGET
;
796 /* Check if we can sample from and render to the surfaces. */
797 /* (assuming copying a stencil buffer is not possible) */
798 if ((!ignore_stencil
&& is_stencil
) ||
799 !screen
->is_format_supported(screen
, dst
->format
, dst
->target
,
800 dst
->nr_samples
, bind
) ||
801 !screen
->is_format_supported(screen
, src
->format
, src
->target
,
802 src
->nr_samples
, PIPE_BIND_SAMPLER_VIEW
)) {
803 ctx
->base
.running
= TRUE
;
804 util_resource_copy_region(pipe
, dst
, dstlevel
, dstx
, dsty
, dstz
,
805 src
, srclevel
, srcbox
);
806 ctx
->base
.running
= FALSE
;
811 memset(&surf_templ
, 0, sizeof(surf_templ
));
812 u_surface_default_template(&surf_templ
, dst
, bind
);
813 surf_templ
.format
= util_format_linear(dst
->format
);
814 surf_templ
.u
.tex
.level
= dstlevel
;
815 surf_templ
.u
.tex
.first_layer
= dstz
;
816 surf_templ
.u
.tex
.last_layer
= dstz
;
817 dstsurf
= pipe
->create_surface(pipe
, dst
, &surf_templ
);
819 /* Check whether the states are properly saved. */
820 blitter_check_saved_CSOs(ctx
);
821 assert(blitter
->saved_fb_state
.nr_cbufs
!= ~0);
822 assert(blitter
->saved_num_sampler_views
!= ~0);
823 assert(blitter
->saved_num_sampler_states
!= ~0);
825 /* Initialize framebuffer state. */
826 fb_state
.width
= dstsurf
->width
;
827 fb_state
.height
= dstsurf
->height
;
830 pipe
->bind_blend_state(pipe
, ctx
->blend_keep_color
);
831 pipe
->bind_depth_stencil_alpha_state(pipe
,
832 ctx
->dsa_write_depth_keep_stencil
);
833 pipe
->bind_fs_state(pipe
,
834 blitter_get_fs_texfetch_depth(ctx
, src
->target
));
836 fb_state
.nr_cbufs
= 0;
837 fb_state
.zsbuf
= dstsurf
;
839 pipe
->bind_blend_state(pipe
, ctx
->blend_write_color
);
840 pipe
->bind_depth_stencil_alpha_state(pipe
, ctx
->dsa_keep_depth_stencil
);
841 pipe
->bind_fs_state(pipe
,
842 blitter_get_fs_texfetch_col(ctx
, src
->target
));
844 fb_state
.nr_cbufs
= 1;
845 fb_state
.cbufs
[0] = dstsurf
;
849 normalized
= src
->target
!= PIPE_TEXTURE_RECT
;
851 /* Initialize sampler view. */
852 u_sampler_view_default_template(&viewTempl
, src
, util_format_linear(src
->format
));
853 view
= pipe
->create_sampler_view(pipe
, src
, &viewTempl
);
855 /* Set rasterizer state, shaders, and textures. */
856 pipe
->bind_rasterizer_state(pipe
, ctx
->rs_state
);
857 pipe
->bind_vs_state(pipe
, ctx
->vs
);
858 pipe
->bind_fragment_sampler_states(pipe
, 1,
859 blitter_get_sampler_state(ctx
, srclevel
, normalized
));
860 pipe
->bind_vertex_elements_state(pipe
, ctx
->velem_state
);
861 pipe
->set_fragment_sampler_views(pipe
, 1, &view
);
862 pipe
->set_framebuffer_state(pipe
, &fb_state
);
864 blitter_set_dst_dimensions(ctx
, dstsurf
->width
, dstsurf
->height
);
866 switch (src
->target
) {
867 /* Draw the quad with the draw_rectangle callback. */
868 case PIPE_TEXTURE_1D
:
869 case PIPE_TEXTURE_2D
:
870 case PIPE_TEXTURE_RECT
:
872 /* Set texture coordinates. - use a pipe color union
873 * for interface purposes
875 union pipe_color_union coord
;
876 get_texcoords(src
, srclevel
, srcbox
->x
, srcbox
->y
,
877 srcbox
->x
+width
, srcbox
->y
+height
, normalized
, coord
.f
);
880 blitter
->draw_rectangle(blitter
, dstx
, dsty
, dstx
+width
, dsty
+height
, 0,
881 UTIL_BLITTER_ATTRIB_TEXCOORD
, &coord
);
885 /* Draw the quad with the generic codepath. */
887 /* Set texture coordinates. */
888 switch (src
->target
) {
889 case PIPE_TEXTURE_1D_ARRAY
:
890 blitter_set_texcoords_1d_array(ctx
, src
, srclevel
, srcbox
->y
,
891 srcbox
->x
, srcbox
->x
+ width
);
894 case PIPE_TEXTURE_2D_ARRAY
:
895 case PIPE_TEXTURE_3D
:
896 blitter_set_texcoords_3d(ctx
, src
, srclevel
, srcbox
->z
,
897 srcbox
->x
, srcbox
->y
,
898 srcbox
->x
+ width
, srcbox
->y
+ height
,
899 src
->target
== PIPE_TEXTURE_3D
);
902 case PIPE_TEXTURE_CUBE
:
903 blitter_set_texcoords_cube(ctx
, src
, srclevel
, srcbox
->z
,
904 srcbox
->x
, srcbox
->y
,
905 srcbox
->x
+ width
, srcbox
->y
+ height
);
913 blitter_set_rectangle(ctx
, dstx
, dsty
, dstx
+width
, dsty
+height
, 0);
914 ctx
->base
.pipe
->redefine_user_buffer(ctx
->base
.pipe
, ctx
->vbuf
,
915 0, ctx
->vbuf
->width0
);
916 util_draw_vertex_buffer(ctx
->base
.pipe
, NULL
, ctx
->vbuf
, 0,
917 PIPE_PRIM_TRIANGLE_FAN
, 4, 2);
921 blitter_restore_CSOs(ctx
);
923 pipe_surface_reference(&dstsurf
, NULL
);
924 pipe_sampler_view_reference(&view
, NULL
);
927 /* Clear a region of a color surface to a constant value. */
928 void util_blitter_clear_render_target(struct blitter_context
*blitter
,
929 struct pipe_surface
*dstsurf
,
930 const union pipe_color_union
*color
,
931 unsigned dstx
, unsigned dsty
,
932 unsigned width
, unsigned height
)
934 struct blitter_context_priv
*ctx
= (struct blitter_context_priv
*)blitter
;
935 struct pipe_context
*pipe
= ctx
->base
.pipe
;
936 struct pipe_framebuffer_state fb_state
;
938 assert(dstsurf
->texture
);
939 if (!dstsurf
->texture
)
942 /* check the saved state */
943 blitter_check_saved_CSOs(ctx
);
944 assert(blitter
->saved_fb_state
.nr_cbufs
!= ~0);
947 pipe
->bind_blend_state(pipe
, ctx
->blend_write_color
);
948 pipe
->bind_depth_stencil_alpha_state(pipe
, ctx
->dsa_keep_depth_stencil
);
949 pipe
->bind_rasterizer_state(pipe
, ctx
->rs_state
);
950 pipe
->bind_fs_state(pipe
, blitter_get_fs_col(ctx
, 1));
951 pipe
->bind_vs_state(pipe
, ctx
->vs
);
952 pipe
->bind_vertex_elements_state(pipe
, ctx
->velem_state
);
954 /* set a framebuffer state */
955 fb_state
.width
= dstsurf
->width
;
956 fb_state
.height
= dstsurf
->height
;
957 fb_state
.nr_cbufs
= 1;
958 fb_state
.cbufs
[0] = dstsurf
;
960 pipe
->set_framebuffer_state(pipe
, &fb_state
);
962 blitter_set_dst_dimensions(ctx
, dstsurf
->width
, dstsurf
->height
);
963 blitter
->draw_rectangle(blitter
, dstx
, dsty
, dstx
+width
, dsty
+height
, 0,
964 UTIL_BLITTER_ATTRIB_COLOR
, color
);
965 blitter_restore_CSOs(ctx
);
968 /* Clear a region of a depth stencil surface. */
969 void util_blitter_clear_depth_stencil(struct blitter_context
*blitter
,
970 struct pipe_surface
*dstsurf
,
971 unsigned clear_flags
,
974 unsigned dstx
, unsigned dsty
,
975 unsigned width
, unsigned height
)
977 struct blitter_context_priv
*ctx
= (struct blitter_context_priv
*)blitter
;
978 struct pipe_context
*pipe
= ctx
->base
.pipe
;
979 struct pipe_framebuffer_state fb_state
;
980 struct pipe_stencil_ref sr
= { { 0 } };
982 assert(dstsurf
->texture
);
983 if (!dstsurf
->texture
)
986 /* check the saved state */
987 blitter_check_saved_CSOs(ctx
);
988 assert(blitter
->saved_fb_state
.nr_cbufs
!= ~0);
991 pipe
->bind_blend_state(pipe
, ctx
->blend_keep_color
);
992 if ((clear_flags
& PIPE_CLEAR_DEPTHSTENCIL
) == PIPE_CLEAR_DEPTHSTENCIL
) {
993 sr
.ref_value
[0] = stencil
& 0xff;
994 pipe
->bind_depth_stencil_alpha_state(pipe
, ctx
->dsa_write_depth_stencil
);
995 pipe
->set_stencil_ref(pipe
, &sr
);
997 else if (clear_flags
& PIPE_CLEAR_DEPTH
) {
998 pipe
->bind_depth_stencil_alpha_state(pipe
, ctx
->dsa_write_depth_keep_stencil
);
1000 else if (clear_flags
& PIPE_CLEAR_STENCIL
) {
1001 sr
.ref_value
[0] = stencil
& 0xff;
1002 pipe
->bind_depth_stencil_alpha_state(pipe
, ctx
->dsa_keep_depth_write_stencil
);
1003 pipe
->set_stencil_ref(pipe
, &sr
);
1006 /* hmm that should be illegal probably, or make it a no-op somewhere */
1007 pipe
->bind_depth_stencil_alpha_state(pipe
, ctx
->dsa_keep_depth_stencil
);
1009 pipe
->bind_rasterizer_state(pipe
, ctx
->rs_state
);
1010 pipe
->bind_fs_state(pipe
, blitter_get_fs_col(ctx
, 0));
1011 pipe
->bind_vs_state(pipe
, ctx
->vs
);
1012 pipe
->bind_vertex_elements_state(pipe
, ctx
->velem_state
);
1014 /* set a framebuffer state */
1015 fb_state
.width
= dstsurf
->width
;
1016 fb_state
.height
= dstsurf
->height
;
1017 fb_state
.nr_cbufs
= 0;
1018 fb_state
.cbufs
[0] = 0;
1019 fb_state
.zsbuf
= dstsurf
;
1020 pipe
->set_framebuffer_state(pipe
, &fb_state
);
1022 blitter_set_dst_dimensions(ctx
, dstsurf
->width
, dstsurf
->height
);
1023 blitter
->draw_rectangle(blitter
, dstx
, dsty
, dstx
+width
, dsty
+height
, depth
,
1024 UTIL_BLITTER_ATTRIB_NONE
, NULL
);
1025 blitter_restore_CSOs(ctx
);
1028 /* draw a rectangle across a region using a custom dsa stage - for r600g */
1029 void util_blitter_custom_depth_stencil(struct blitter_context
*blitter
,
1030 struct pipe_surface
*zsurf
,
1031 struct pipe_surface
*cbsurf
,
1032 void *dsa_stage
, float depth
)
1034 struct blitter_context_priv
*ctx
= (struct blitter_context_priv
*)blitter
;
1035 struct pipe_context
*pipe
= ctx
->base
.pipe
;
1036 struct pipe_framebuffer_state fb_state
;
1038 assert(zsurf
->texture
);
1039 if (!zsurf
->texture
)
1042 /* check the saved state */
1043 blitter_check_saved_CSOs(ctx
);
1044 assert(blitter
->saved_fb_state
.nr_cbufs
!= ~0);
1047 pipe
->bind_blend_state(pipe
, ctx
->blend_write_color
);
1048 pipe
->bind_depth_stencil_alpha_state(pipe
, dsa_stage
);
1050 pipe
->bind_rasterizer_state(pipe
, ctx
->rs_state
);
1051 pipe
->bind_fs_state(pipe
, blitter_get_fs_col(ctx
, 0));
1052 pipe
->bind_vs_state(pipe
, ctx
->vs
);
1053 pipe
->bind_vertex_elements_state(pipe
, ctx
->velem_state
);
1055 /* set a framebuffer state */
1056 fb_state
.width
= zsurf
->width
;
1057 fb_state
.height
= zsurf
->height
;
1058 fb_state
.nr_cbufs
= 1;
1060 fb_state
.cbufs
[0] = cbsurf
;
1061 fb_state
.nr_cbufs
= 1;
1063 fb_state
.cbufs
[0] = NULL
;
1064 fb_state
.nr_cbufs
= 0;
1066 fb_state
.zsbuf
= zsurf
;
1067 pipe
->set_framebuffer_state(pipe
, &fb_state
);
1069 blitter_set_dst_dimensions(ctx
, zsurf
->width
, zsurf
->height
);
1070 blitter
->draw_rectangle(blitter
, 0, 0, zsurf
->width
, zsurf
->height
, depth
,
1071 UTIL_BLITTER_ATTRIB_NONE
, NULL
);
1072 blitter_restore_CSOs(ctx
);