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, surface_copy,
30 * and surface_fill 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_pack_color.h"
47 #include "util/u_rect.h"
48 #include "util/u_simple_shaders.h"
49 #include "util/u_texture.h"
51 #define INVALID_PTR ((void*)~0)
53 struct blitter_context_priv
55 struct blitter_context blitter
;
57 struct pipe_context
*pipe
; /**< pipe context */
58 struct pipe_buffer
*vbuf
; /**< quad */
60 float vertices
[4][2][4]; /**< {pos, color} or {pos, texcoord} */
62 /* Templates for various state objects. */
63 struct pipe_sampler_state template_sampler_state
;
65 /* Constant state objects. */
67 void *vs_col
; /**< Vertex shader which passes {pos, color} to the output */
68 void *vs_tex
; /**< Vertex shader which passes {pos, texcoord} to the output.*/
70 /* Fragment shaders. */
71 /* FS which outputs a color to multiple color buffers. */
72 void *fs_col
[PIPE_MAX_COLOR_BUFS
];
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
];
83 void *blend_write_color
; /**< blend state with writemask of RGBA */
84 void *blend_keep_color
; /**< blend state with writemask of 0 */
86 /* Depth stencil alpha state. */
87 void *dsa_write_depth_stencil
;
88 void *dsa_write_depth_keep_stencil
;
89 void *dsa_keep_depth_stencil
;
91 /* Sampler state for clamping to a miplevel. */
92 void *sampler_state
[PIPE_MAX_TEXTURE_LEVELS
];
94 /* Rasterizer state. */
98 struct blitter_context
*util_blitter_create(struct pipe_context
*pipe
)
100 struct blitter_context_priv
*ctx
;
101 struct pipe_blend_state blend
;
102 struct pipe_depth_stencil_alpha_state dsa
;
103 struct pipe_rasterizer_state rs_state
;
104 struct pipe_sampler_state
*sampler_state
;
107 ctx
= CALLOC_STRUCT(blitter_context_priv
);
113 /* init state objects for them to be considered invalid */
114 ctx
->blitter
.saved_blend_state
= INVALID_PTR
;
115 ctx
->blitter
.saved_dsa_state
= INVALID_PTR
;
116 ctx
->blitter
.saved_rs_state
= INVALID_PTR
;
117 ctx
->blitter
.saved_fs
= INVALID_PTR
;
118 ctx
->blitter
.saved_vs
= INVALID_PTR
;
119 ctx
->blitter
.saved_fb_state
.nr_cbufs
= ~0;
120 ctx
->blitter
.saved_num_textures
= ~0;
121 ctx
->blitter
.saved_num_sampler_states
= ~0;
123 /* blend state objects */
124 memset(&blend
, 0, sizeof(blend
));
125 ctx
->blend_keep_color
= pipe
->create_blend_state(pipe
, &blend
);
127 blend
.rt
[0].colormask
= PIPE_MASK_RGBA
;
128 ctx
->blend_write_color
= pipe
->create_blend_state(pipe
, &blend
);
130 /* depth stencil alpha state objects */
131 ctx
->dsa_keep_depth_stencil
=
132 pipe
->create_depth_stencil_alpha_state(pipe
, &dsa
);
134 dsa
.depth
.enabled
= 1;
135 dsa
.depth
.writemask
= 1;
136 dsa
.depth
.func
= PIPE_FUNC_ALWAYS
;
137 ctx
->dsa_write_depth_keep_stencil
=
138 pipe
->create_depth_stencil_alpha_state(pipe
, &dsa
);
140 dsa
.stencil
[0].enabled
= 1;
141 dsa
.stencil
[0].func
= PIPE_FUNC_ALWAYS
;
142 dsa
.stencil
[0].fail_op
= PIPE_STENCIL_OP_REPLACE
;
143 dsa
.stencil
[0].zpass_op
= PIPE_STENCIL_OP_REPLACE
;
144 dsa
.stencil
[0].zfail_op
= PIPE_STENCIL_OP_REPLACE
;
145 dsa
.stencil
[0].valuemask
= 0xff;
146 dsa
.stencil
[0].writemask
= 0xff;
147 ctx
->dsa_write_depth_stencil
=
148 pipe
->create_depth_stencil_alpha_state(pipe
, &dsa
);
149 /* The DSA state objects which write depth and stencil are created
153 sampler_state
= &ctx
->template_sampler_state
;
154 sampler_state
->wrap_s
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
155 sampler_state
->wrap_t
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
156 sampler_state
->wrap_r
= PIPE_TEX_WRAP_CLAMP_TO_EDGE
;
157 /* The sampler state objects which sample from a specified mipmap level
158 * are created on-demand. */
160 /* rasterizer state */
161 memset(&rs_state
, 0, sizeof(rs_state
));
162 rs_state
.front_winding
= PIPE_WINDING_CW
;
163 rs_state
.cull_mode
= PIPE_WINDING_NONE
;
164 rs_state
.bypass_vs_clip_and_viewport
= 1;
165 rs_state
.gl_rasterization_rules
= 1;
166 rs_state
.flatshade
= 1;
167 ctx
->rs_state
= pipe
->create_rasterizer_state(pipe
, &rs_state
);
169 /* fragment shaders are created on-demand */
173 const uint semantic_names
[] = { TGSI_SEMANTIC_POSITION
,
174 TGSI_SEMANTIC_COLOR
};
175 const uint semantic_indices
[] = { 0, 0 };
177 util_make_vertex_passthrough_shader(pipe
, 2, semantic_names
,
181 const uint semantic_names
[] = { TGSI_SEMANTIC_POSITION
,
182 TGSI_SEMANTIC_GENERIC
};
183 const uint semantic_indices
[] = { 0, 0 };
185 util_make_vertex_passthrough_shader(pipe
, 2, semantic_names
,
189 /* set invariant vertex coordinates */
190 for (i
= 0; i
< 4; i
++)
191 ctx
->vertices
[i
][0][3] = 1; /*v.w*/
193 /* create the vertex buffer */
194 ctx
->vbuf
= pipe_buffer_create(ctx
->pipe
->screen
,
196 PIPE_BUFFER_USAGE_VERTEX
,
197 sizeof(ctx
->vertices
));
199 return &ctx
->blitter
;
202 void util_blitter_destroy(struct blitter_context
*blitter
)
204 struct blitter_context_priv
*ctx
= (struct blitter_context_priv
*)blitter
;
205 struct pipe_context
*pipe
= ctx
->pipe
;
208 pipe
->delete_blend_state(pipe
, ctx
->blend_write_color
);
209 pipe
->delete_blend_state(pipe
, ctx
->blend_keep_color
);
210 pipe
->delete_depth_stencil_alpha_state(pipe
, ctx
->dsa_keep_depth_stencil
);
211 pipe
->delete_depth_stencil_alpha_state(pipe
,
212 ctx
->dsa_write_depth_keep_stencil
);
213 pipe
->delete_depth_stencil_alpha_state(pipe
, ctx
->dsa_write_depth_stencil
);
215 pipe
->delete_rasterizer_state(pipe
, ctx
->rs_state
);
216 pipe
->delete_vs_state(pipe
, ctx
->vs_col
);
217 pipe
->delete_vs_state(pipe
, ctx
->vs_tex
);
219 for (i
= 0; i
< PIPE_MAX_TEXTURE_TYPES
; i
++) {
220 if (ctx
->fs_texfetch_col
[i
])
221 pipe
->delete_fs_state(pipe
, ctx
->fs_texfetch_col
[i
]);
222 if (ctx
->fs_texfetch_depth
[i
])
223 pipe
->delete_fs_state(pipe
, ctx
->fs_texfetch_depth
[i
]);
226 for (i
= 0; i
< PIPE_MAX_COLOR_BUFS
&& ctx
->fs_col
[i
]; i
++)
228 pipe
->delete_fs_state(pipe
, ctx
->fs_col
[i
]);
230 for (i
= 0; i
< PIPE_MAX_TEXTURE_LEVELS
; i
++)
231 if (ctx
->sampler_state
[i
])
232 pipe
->delete_sampler_state(pipe
, ctx
->sampler_state
[i
]);
234 pipe_buffer_reference(&ctx
->vbuf
, NULL
);
238 static void blitter_check_saved_CSOs(struct blitter_context_priv
*ctx
)
240 /* make sure these CSOs have been saved */
241 assert(ctx
->blitter
.saved_blend_state
!= INVALID_PTR
&&
242 ctx
->blitter
.saved_dsa_state
!= INVALID_PTR
&&
243 ctx
->blitter
.saved_rs_state
!= INVALID_PTR
&&
244 ctx
->blitter
.saved_fs
!= INVALID_PTR
&&
245 ctx
->blitter
.saved_vs
!= INVALID_PTR
);
248 static void blitter_restore_CSOs(struct blitter_context_priv
*ctx
)
250 struct pipe_context
*pipe
= ctx
->pipe
;
252 /* restore the state objects which are always required to be saved */
253 pipe
->bind_blend_state(pipe
, ctx
->blitter
.saved_blend_state
);
254 pipe
->bind_depth_stencil_alpha_state(pipe
, ctx
->blitter
.saved_dsa_state
);
255 pipe
->bind_rasterizer_state(pipe
, ctx
->blitter
.saved_rs_state
);
256 pipe
->bind_fs_state(pipe
, ctx
->blitter
.saved_fs
);
257 pipe
->bind_vs_state(pipe
, ctx
->blitter
.saved_vs
);
259 ctx
->blitter
.saved_blend_state
= INVALID_PTR
;
260 ctx
->blitter
.saved_dsa_state
= INVALID_PTR
;
261 ctx
->blitter
.saved_rs_state
= INVALID_PTR
;
262 ctx
->blitter
.saved_fs
= INVALID_PTR
;
263 ctx
->blitter
.saved_vs
= INVALID_PTR
;
265 pipe
->set_stencil_ref(pipe
, &ctx
->blitter
.saved_stencil_ref
);
267 /* restore the state objects which are required to be saved before copy/fill
269 if (ctx
->blitter
.saved_fb_state
.nr_cbufs
!= ~0) {
270 pipe
->set_framebuffer_state(pipe
, &ctx
->blitter
.saved_fb_state
);
271 ctx
->blitter
.saved_fb_state
.nr_cbufs
= ~0;
274 if (ctx
->blitter
.saved_num_sampler_states
!= ~0) {
275 pipe
->bind_fragment_sampler_states(pipe
,
276 ctx
->blitter
.saved_num_sampler_states
,
277 ctx
->blitter
.saved_sampler_states
);
278 ctx
->blitter
.saved_num_sampler_states
= ~0;
281 if (ctx
->blitter
.saved_num_textures
!= ~0) {
282 pipe
->set_fragment_sampler_textures(pipe
,
283 ctx
->blitter
.saved_num_textures
,
284 ctx
->blitter
.saved_textures
);
285 ctx
->blitter
.saved_num_textures
= ~0;
289 static void blitter_set_rectangle(struct blitter_context_priv
*ctx
,
290 unsigned x1
, unsigned y1
,
291 unsigned x2
, unsigned y2
,
296 /* set vertex positions */
297 ctx
->vertices
[0][0][0] = x1
; /*v0.x*/
298 ctx
->vertices
[0][0][1] = y1
; /*v0.y*/
300 ctx
->vertices
[1][0][0] = x2
; /*v1.x*/
301 ctx
->vertices
[1][0][1] = y1
; /*v1.y*/
303 ctx
->vertices
[2][0][0] = x2
; /*v2.x*/
304 ctx
->vertices
[2][0][1] = y2
; /*v2.y*/
306 ctx
->vertices
[3][0][0] = x1
; /*v3.x*/
307 ctx
->vertices
[3][0][1] = y2
; /*v3.y*/
309 for (i
= 0; i
< 4; i
++)
310 ctx
->vertices
[i
][0][2] = depth
; /*z*/
313 static void blitter_set_clear_color(struct blitter_context_priv
*ctx
,
318 for (i
= 0; i
< 4; i
++) {
319 ctx
->vertices
[i
][1][0] = rgba
[0];
320 ctx
->vertices
[i
][1][1] = rgba
[1];
321 ctx
->vertices
[i
][1][2] = rgba
[2];
322 ctx
->vertices
[i
][1][3] = rgba
[3];
326 static void blitter_set_texcoords_2d(struct blitter_context_priv
*ctx
,
327 struct pipe_surface
*surf
,
328 unsigned x1
, unsigned y1
,
329 unsigned x2
, unsigned y2
)
332 float s1
= x1
/ (float)surf
->width
;
333 float t1
= y1
/ (float)surf
->height
;
334 float s2
= x2
/ (float)surf
->width
;
335 float t2
= y2
/ (float)surf
->height
;
337 ctx
->vertices
[0][1][0] = s1
; /*t0.s*/
338 ctx
->vertices
[0][1][1] = t1
; /*t0.t*/
340 ctx
->vertices
[1][1][0] = s2
; /*t1.s*/
341 ctx
->vertices
[1][1][1] = t1
; /*t1.t*/
343 ctx
->vertices
[2][1][0] = s2
; /*t2.s*/
344 ctx
->vertices
[2][1][1] = t2
; /*t2.t*/
346 ctx
->vertices
[3][1][0] = s1
; /*t3.s*/
347 ctx
->vertices
[3][1][1] = t2
; /*t3.t*/
349 for (i
= 0; i
< 4; i
++) {
350 ctx
->vertices
[i
][1][2] = 0; /*r*/
351 ctx
->vertices
[i
][1][3] = 1; /*q*/
355 static void blitter_set_texcoords_3d(struct blitter_context_priv
*ctx
,
356 struct pipe_surface
*surf
,
357 unsigned x1
, unsigned y1
,
358 unsigned x2
, unsigned y2
)
361 float depth
= u_minify(surf
->texture
->depth0
, surf
->level
);
362 float r
= surf
->zslice
/ depth
;
364 blitter_set_texcoords_2d(ctx
, surf
, x1
, y1
, x2
, y2
);
366 for (i
= 0; i
< 4; i
++)
367 ctx
->vertices
[i
][1][2] = r
; /*r*/
370 static void blitter_set_texcoords_cube(struct blitter_context_priv
*ctx
,
371 struct pipe_surface
*surf
,
372 unsigned x1
, unsigned y1
,
373 unsigned x2
, unsigned y2
)
376 float s1
= x1
/ (float)surf
->width
;
377 float t1
= y1
/ (float)surf
->height
;
378 float s2
= x2
/ (float)surf
->width
;
379 float t2
= y2
/ (float)surf
->height
;
391 util_map_texcoords2d_onto_cubemap(surf
->face
,
392 /* pointer, stride in floats */
394 &ctx
->vertices
[0][1][0], 8);
396 for (i
= 0; i
< 4; i
++)
397 ctx
->vertices
[i
][1][3] = 1; /*q*/
400 static void blitter_draw_quad(struct blitter_context_priv
*ctx
)
402 struct pipe_context
*pipe
= ctx
->pipe
;
404 /* write vertices and draw them */
405 pipe_buffer_write(pipe
->screen
, ctx
->vbuf
,
406 0, sizeof(ctx
->vertices
), ctx
->vertices
);
408 util_draw_vertex_buffer(pipe
, ctx
->vbuf
, 0, PIPE_PRIM_TRIANGLE_FAN
,
410 2); /* attribs/vert */
414 void **blitter_get_sampler_state(struct blitter_context_priv
*ctx
,
417 struct pipe_context
*pipe
= ctx
->pipe
;
418 struct pipe_sampler_state
*sampler_state
= &ctx
->template_sampler_state
;
420 assert(miplevel
< PIPE_MAX_TEXTURE_LEVELS
);
422 /* Create the sampler state on-demand. */
423 if (!ctx
->sampler_state
[miplevel
]) {
424 sampler_state
->lod_bias
= miplevel
;
425 sampler_state
->min_lod
= miplevel
;
426 sampler_state
->max_lod
= miplevel
;
428 ctx
->sampler_state
[miplevel
] = pipe
->create_sampler_state(pipe
,
432 /* Return void** so that it can be passed to bind_fragment_sampler_states
434 return &ctx
->sampler_state
[miplevel
];
438 void *blitter_get_fs_col(struct blitter_context_priv
*ctx
, unsigned num_cbufs
)
440 struct pipe_context
*pipe
= ctx
->pipe
;
441 unsigned index
= num_cbufs
? num_cbufs
- 1 : 0;
443 assert(num_cbufs
<= PIPE_MAX_COLOR_BUFS
);
445 if (!ctx
->fs_col
[index
])
447 util_make_fragment_clonecolor_shader(pipe
, num_cbufs
);
449 return ctx
->fs_col
[index
];
453 void *blitter_get_fs_texfetch_col(struct blitter_context_priv
*ctx
,
456 struct pipe_context
*pipe
= ctx
->pipe
;
458 assert(tex_target
< PIPE_MAX_TEXTURE_TYPES
);
460 /* Create the fragment shader on-demand. */
461 if (!ctx
->fs_texfetch_col
[tex_target
]) {
462 switch (tex_target
) {
463 case PIPE_TEXTURE_1D
:
464 ctx
->fs_texfetch_col
[PIPE_TEXTURE_1D
] =
465 util_make_fragment_tex_shader(pipe
, TGSI_TEXTURE_1D
);
467 case PIPE_TEXTURE_2D
:
468 ctx
->fs_texfetch_col
[PIPE_TEXTURE_2D
] =
469 util_make_fragment_tex_shader(pipe
, TGSI_TEXTURE_2D
);
471 case PIPE_TEXTURE_3D
:
472 ctx
->fs_texfetch_col
[PIPE_TEXTURE_3D
] =
473 util_make_fragment_tex_shader(pipe
, TGSI_TEXTURE_3D
);
475 case PIPE_TEXTURE_CUBE
:
476 ctx
->fs_texfetch_col
[PIPE_TEXTURE_CUBE
] =
477 util_make_fragment_tex_shader(pipe
, TGSI_TEXTURE_CUBE
);
483 return ctx
->fs_texfetch_col
[tex_target
];
487 void *blitter_get_fs_texfetch_depth(struct blitter_context_priv
*ctx
,
490 struct pipe_context
*pipe
= ctx
->pipe
;
492 assert(tex_target
< PIPE_MAX_TEXTURE_TYPES
);
494 /* Create the fragment shader on-demand. */
495 if (!ctx
->fs_texfetch_depth
[tex_target
]) {
496 switch (tex_target
) {
497 case PIPE_TEXTURE_1D
:
498 ctx
->fs_texfetch_depth
[PIPE_TEXTURE_1D
] =
499 util_make_fragment_tex_shader_writedepth(pipe
, TGSI_TEXTURE_1D
);
501 case PIPE_TEXTURE_2D
:
502 ctx
->fs_texfetch_depth
[PIPE_TEXTURE_2D
] =
503 util_make_fragment_tex_shader_writedepth(pipe
, TGSI_TEXTURE_2D
);
505 case PIPE_TEXTURE_3D
:
506 ctx
->fs_texfetch_depth
[PIPE_TEXTURE_3D
] =
507 util_make_fragment_tex_shader_writedepth(pipe
, TGSI_TEXTURE_3D
);
509 case PIPE_TEXTURE_CUBE
:
510 ctx
->fs_texfetch_depth
[PIPE_TEXTURE_CUBE
] =
511 util_make_fragment_tex_shader_writedepth(pipe
,TGSI_TEXTURE_CUBE
);
517 return ctx
->fs_texfetch_depth
[tex_target
];
520 void util_blitter_clear(struct blitter_context
*blitter
,
521 unsigned width
, unsigned height
,
523 unsigned clear_buffers
,
525 double depth
, unsigned stencil
)
527 struct blitter_context_priv
*ctx
= (struct blitter_context_priv
*)blitter
;
528 struct pipe_context
*pipe
= ctx
->pipe
;
530 assert(num_cbufs
<= PIPE_MAX_COLOR_BUFS
);
532 blitter_check_saved_CSOs(ctx
);
535 if (clear_buffers
& PIPE_CLEAR_COLOR
)
536 pipe
->bind_blend_state(pipe
, ctx
->blend_write_color
);
538 pipe
->bind_blend_state(pipe
, ctx
->blend_keep_color
);
540 if (clear_buffers
& PIPE_CLEAR_DEPTHSTENCIL
) {
541 struct pipe_stencil_ref sr
;
542 memset (&sr
, 0, sizeof(sr
));
543 sr
.ref_value
[0] = stencil
& 0xff;
544 pipe
->bind_depth_stencil_alpha_state(pipe
, ctx
->dsa_write_depth_stencil
);
545 pipe
->set_stencil_ref(pipe
, &sr
);
548 pipe
->bind_depth_stencil_alpha_state(pipe
, ctx
->dsa_keep_depth_stencil
);
550 pipe
->bind_rasterizer_state(pipe
, ctx
->rs_state
);
551 pipe
->bind_fs_state(pipe
, blitter_get_fs_col(ctx
, num_cbufs
));
552 pipe
->bind_vs_state(pipe
, ctx
->vs_col
);
554 blitter_set_clear_color(ctx
, rgba
);
555 blitter_set_rectangle(ctx
, 0, 0, width
, height
, depth
);
556 blitter_draw_quad(ctx
);
557 blitter_restore_CSOs(ctx
);
558 /* XXX driver's responsibility to restore stencil refs? */
562 is_overlap(unsigned sx1
, unsigned sx2
, unsigned sy1
, unsigned sy2
,
563 unsigned dx1
, unsigned dx2
, unsigned dy1
, unsigned dy2
)
565 if (sx1
>= dx2
|| sx2
<= dx1
|| sy1
>= dy2
|| sy2
<= dy1
) {
572 static void util_blitter_do_copy(struct blitter_context
*blitter
,
573 struct pipe_surface
*dst
,
574 unsigned dstx
, unsigned dsty
,
575 struct pipe_surface
*src
,
576 unsigned srcx
, unsigned srcy
,
577 unsigned width
, unsigned height
,
580 struct blitter_context_priv
*ctx
= (struct blitter_context_priv
*)blitter
;
581 struct pipe_context
*pipe
= ctx
->pipe
;
582 struct pipe_framebuffer_state fb_state
;
584 assert(blitter
->saved_fb_state
.nr_cbufs
!= ~0);
585 assert(blitter
->saved_num_textures
!= ~0);
586 assert(blitter
->saved_num_sampler_states
!= ~0);
587 assert(src
->texture
->target
< PIPE_MAX_TEXTURE_TYPES
);
590 fb_state
.width
= dst
->width
;
591 fb_state
.height
= dst
->height
;
594 pipe
->bind_blend_state(pipe
, ctx
->blend_keep_color
);
595 pipe
->bind_depth_stencil_alpha_state(pipe
,
596 ctx
->dsa_write_depth_keep_stencil
);
597 pipe
->bind_fs_state(pipe
,
598 blitter_get_fs_texfetch_depth(ctx
, src
->texture
->target
));
600 fb_state
.nr_cbufs
= 0;
601 fb_state
.zsbuf
= dst
;
603 pipe
->bind_blend_state(pipe
, ctx
->blend_write_color
);
604 pipe
->bind_depth_stencil_alpha_state(pipe
, ctx
->dsa_keep_depth_stencil
);
605 pipe
->bind_fs_state(pipe
,
606 blitter_get_fs_texfetch_col(ctx
, src
->texture
->target
));
608 fb_state
.nr_cbufs
= 1;
609 fb_state
.cbufs
[0] = dst
;
613 pipe
->bind_rasterizer_state(pipe
, ctx
->rs_state
);
614 pipe
->bind_vs_state(pipe
, ctx
->vs_tex
);
615 pipe
->bind_fragment_sampler_states(pipe
, 1,
616 blitter_get_sampler_state(ctx
, src
->level
));
617 pipe
->set_fragment_sampler_textures(pipe
, 1, &src
->texture
);
618 pipe
->set_framebuffer_state(pipe
, &fb_state
);
620 /* set texture coordinates */
621 switch (src
->texture
->target
) {
622 case PIPE_TEXTURE_1D
:
623 case PIPE_TEXTURE_2D
:
624 blitter_set_texcoords_2d(ctx
, src
, srcx
, srcy
,
625 srcx
+width
, srcy
+height
);
627 case PIPE_TEXTURE_3D
:
628 blitter_set_texcoords_3d(ctx
, src
, srcx
, srcy
,
629 srcx
+width
, srcy
+height
);
631 case PIPE_TEXTURE_CUBE
:
632 blitter_set_texcoords_cube(ctx
, src
, srcx
, srcy
,
633 srcx
+width
, srcy
+height
);
639 blitter_set_rectangle(ctx
, dstx
, dsty
, dstx
+width
, dsty
+height
, 0);
640 blitter_draw_quad(ctx
);
644 static void util_blitter_overlap_copy(struct blitter_context
*blitter
,
645 struct pipe_surface
*dst
,
646 unsigned dstx
, unsigned dsty
,
647 struct pipe_surface
*src
,
648 unsigned srcx
, unsigned srcy
,
649 unsigned width
, unsigned height
)
651 struct blitter_context_priv
*ctx
= (struct blitter_context_priv
*)blitter
;
652 struct pipe_context
*pipe
= ctx
->pipe
;
653 struct pipe_screen
*screen
= pipe
->screen
;
655 struct pipe_texture texTemp
;
656 struct pipe_texture
*texture
;
657 struct pipe_surface
*tex_surf
;
659 /* check whether the states are properly saved */
660 blitter_check_saved_CSOs(ctx
);
662 memset(&texTemp
, 0, sizeof(texTemp
));
663 texTemp
.target
= PIPE_TEXTURE_2D
;
664 texTemp
.format
= dst
->texture
->format
; /* XXX verify supported by driver! */
665 texTemp
.last_level
= 0;
666 texTemp
.width0
= width
;
667 texTemp
.height0
= height
;
670 texture
= screen
->texture_create(screen
, &texTemp
);
674 tex_surf
= screen
->get_tex_surface(screen
, texture
, 0, 0, 0,
675 PIPE_BUFFER_USAGE_GPU_READ
|
676 PIPE_BUFFER_USAGE_GPU_WRITE
);
678 /* blit from the src to the temp */
679 util_blitter_do_copy(blitter
, tex_surf
, 0, 0,
683 util_blitter_do_copy(blitter
, dst
, dstx
, dsty
,
687 pipe_surface_reference(&tex_surf
, NULL
);
688 pipe_texture_reference(&texture
, NULL
);
689 blitter_restore_CSOs(ctx
);
692 void util_blitter_copy(struct blitter_context
*blitter
,
693 struct pipe_surface
*dst
,
694 unsigned dstx
, unsigned dsty
,
695 struct pipe_surface
*src
,
696 unsigned srcx
, unsigned srcy
,
697 unsigned width
, unsigned height
,
698 boolean ignore_stencil
)
700 struct blitter_context_priv
*ctx
= (struct blitter_context_priv
*)blitter
;
701 struct pipe_context
*pipe
= ctx
->pipe
;
702 struct pipe_screen
*screen
= pipe
->screen
;
703 boolean is_stencil
, is_depth
;
704 unsigned dst_tex_usage
;
706 /* give up if textures are not set */
707 assert(dst
->texture
&& src
->texture
);
708 if (!dst
->texture
|| !src
->texture
)
711 if (dst
->texture
== src
->texture
) {
712 if (is_overlap(srcx
, srcx
+ width
, srcy
, srcy
+ height
,
713 dstx
, dstx
+ width
, dsty
, dsty
+ height
)) {
714 util_blitter_overlap_copy(blitter
, dst
, dstx
, dsty
, src
, srcx
, srcy
,
720 is_depth
= util_format_get_component_bits(src
->format
, UTIL_FORMAT_COLORSPACE_ZS
, 0) != 0;
721 is_stencil
= util_format_get_component_bits(src
->format
, UTIL_FORMAT_COLORSPACE_ZS
, 1) != 0;
722 dst_tex_usage
= is_depth
|| is_stencil
? PIPE_TEXTURE_USAGE_DEPTH_STENCIL
:
723 PIPE_TEXTURE_USAGE_RENDER_TARGET
;
725 /* check if we can sample from and render to the surfaces */
726 /* (assuming copying a stencil buffer is not possible) */
727 if ((!ignore_stencil
&& is_stencil
) ||
728 !screen
->is_format_supported(screen
, dst
->format
, dst
->texture
->target
,
730 !screen
->is_format_supported(screen
, src
->format
, src
->texture
->target
,
731 PIPE_TEXTURE_USAGE_SAMPLER
, 0)) {
732 util_surface_copy(pipe
, FALSE
, dst
, dstx
, dsty
, src
, srcx
, srcy
,
737 /* check whether the states are properly saved */
738 blitter_check_saved_CSOs(ctx
);
739 util_blitter_do_copy(blitter
,
742 width
, height
, is_depth
);
743 blitter_restore_CSOs(ctx
);
746 void util_blitter_fill(struct blitter_context
*blitter
,
747 struct pipe_surface
*dst
,
748 unsigned dstx
, unsigned dsty
,
749 unsigned width
, unsigned height
,
752 struct blitter_context_priv
*ctx
= (struct blitter_context_priv
*)blitter
;
753 struct pipe_context
*pipe
= ctx
->pipe
;
754 struct pipe_screen
*screen
= pipe
->screen
;
755 struct pipe_framebuffer_state fb_state
;
757 ubyte ub_rgba
[4] = {0};
758 union util_color color
;
761 assert(dst
->texture
);
765 /* check if we can render to the surface */
766 if (util_format_is_depth_or_stencil(dst
->format
) || /* unlikely, but you never know */
767 !screen
->is_format_supported(screen
, dst
->format
, dst
->texture
->target
,
768 PIPE_TEXTURE_USAGE_RENDER_TARGET
, 0)) {
769 util_surface_fill(pipe
, dst
, dstx
, dsty
, width
, height
, value
);
773 /* unpack the color */
775 util_unpack_color_ub(dst
->format
, &color
,
776 ub_rgba
, ub_rgba
+1, ub_rgba
+2, ub_rgba
+3);
777 for (i
= 0; i
< 4; i
++)
778 rgba
[i
] = ubyte_to_float(ub_rgba
[i
]);
780 /* check the saved state */
781 blitter_check_saved_CSOs(ctx
);
782 assert(blitter
->saved_fb_state
.nr_cbufs
!= ~0);
785 pipe
->bind_blend_state(pipe
, ctx
->blend_write_color
);
786 pipe
->bind_depth_stencil_alpha_state(pipe
, ctx
->dsa_keep_depth_stencil
);
787 pipe
->bind_rasterizer_state(pipe
, ctx
->rs_state
);
788 pipe
->bind_fs_state(pipe
, blitter_get_fs_col(ctx
, 1));
789 pipe
->bind_vs_state(pipe
, ctx
->vs_col
);
791 /* set a framebuffer state */
792 fb_state
.width
= dst
->width
;
793 fb_state
.height
= dst
->height
;
794 fb_state
.nr_cbufs
= 1;
795 fb_state
.cbufs
[0] = dst
;
797 pipe
->set_framebuffer_state(pipe
, &fb_state
);
799 blitter_set_clear_color(ctx
, rgba
);
800 blitter_set_rectangle(ctx
, 0, 0, width
, height
, 0);
801 blitter_draw_quad(ctx
);
802 blitter_restore_CSOs(ctx
);