sync with tizen_2.2
[sdk/emulator/qemu.git] / gl / mesa / src / gallium / auxiliary / util / u_blitter.c
1 /**************************************************************************
2  *
3  * Copyright 2009 Marek Olšák <maraeo@gmail.com>
4  *
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:
12  *
13  * The above copyright notice and this permission notice (including the
14  * next paragraph) shall be included in all copies or substantial portions
15  * of the Software.
16  *
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.
24  *
25  **************************************************************************/
26
27 /**
28  * @file
29  * Blitter utility to facilitate acceleration of the clear, clear_render_target,
30  * clear_depth_stencil, and resource_copy_region functions.
31  *
32  * @author Marek Olšák
33  */
34
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"
40
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
51 #define INVALID_PTR ((void*)~0)
52
53 struct blitter_context_priv
54 {
55    struct blitter_context base;
56
57    struct pipe_resource *vbuf;  /**< quad */
58
59    float vertices[4][2][4];   /**< {pos, color} or {pos, texcoord} */
60
61    /* Templates for various state objects. */
62
63    /* Constant state objects. */
64    /* Vertex shaders. */
65    void *vs; /**< Vertex shader which passes {pos, generic} to the output.*/
66    void *vs_pos_only; /**< Vertex shader which passes pos to the output.*/
67
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];
71    void *fs_col_int[PIPE_MAX_COLOR_BUFS+1];
72
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];
76
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];
80
81    /* Blend state. */
82    void *blend_write_color;   /**< blend state with writemask of RGBA */
83    void *blend_keep_color;    /**< blend state with writemask of 0 */
84
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
91    /* Vertex elements states. */
92    void *velem_state;
93    void *velem_uint_state;
94    void *velem_sint_state;
95    void *velem_state_readbuf;
96
97    /* Sampler state. */
98    void *sampler_state;
99
100    /* Rasterizer state. */
101    void *rs_state;
102    void *rs_discard_state;
103
104    /* Viewport state. */
105    struct pipe_viewport_state viewport;
106
107    /* Destination surface dimensions. */
108    unsigned dst_width;
109    unsigned dst_height;
110
111    boolean has_geometry_shader;
112    boolean vertex_has_integers;
113    boolean has_stream_out;
114 };
115
116 static void blitter_draw_rectangle(struct blitter_context *blitter,
117                                    unsigned x, unsigned y,
118                                    unsigned width, unsigned height,
119                                    float depth,
120                                    enum blitter_attrib_type type,
121                                    const union pipe_color_union *attrib);
122
123
124 struct blitter_context *util_blitter_create(struct pipe_context *pipe)
125 {
126    struct blitter_context_priv *ctx;
127    struct pipe_blend_state blend;
128    struct pipe_depth_stencil_alpha_state dsa;
129    struct pipe_rasterizer_state rs_state;
130    struct pipe_sampler_state sampler_state;
131    struct pipe_vertex_element velem[2];
132    unsigned i;
133
134    ctx = CALLOC_STRUCT(blitter_context_priv);
135    if (!ctx)
136       return NULL;
137
138    ctx->base.pipe = pipe;
139    ctx->base.draw_rectangle = blitter_draw_rectangle;
140
141    /* init state objects for them to be considered invalid */
142    ctx->base.saved_blend_state = INVALID_PTR;
143    ctx->base.saved_dsa_state = INVALID_PTR;
144    ctx->base.saved_rs_state = INVALID_PTR;
145    ctx->base.saved_fs = INVALID_PTR;
146    ctx->base.saved_vs = INVALID_PTR;
147    ctx->base.saved_gs = INVALID_PTR;
148    ctx->base.saved_velem_state = INVALID_PTR;
149    ctx->base.saved_fb_state.nr_cbufs = ~0;
150    ctx->base.saved_num_sampler_views = ~0;
151    ctx->base.saved_num_sampler_states = ~0;
152    ctx->base.saved_num_vertex_buffers = ~0;
153    ctx->base.saved_num_so_targets = ~0;
154
155    ctx->has_geometry_shader =
156       pipe->screen->get_shader_param(pipe->screen, PIPE_SHADER_GEOMETRY,
157                                      PIPE_SHADER_CAP_MAX_INSTRUCTIONS) > 0;
158    ctx->vertex_has_integers =
159       pipe->screen->get_shader_param(pipe->screen, PIPE_SHADER_VERTEX,
160                                      PIPE_SHADER_CAP_INTEGERS);
161    ctx->has_stream_out =
162       pipe->screen->get_param(pipe->screen,
163                               PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS) != 0;
164
165    /* blend state objects */
166    memset(&blend, 0, sizeof(blend));
167    ctx->blend_keep_color = pipe->create_blend_state(pipe, &blend);
168
169    blend.rt[0].colormask = PIPE_MASK_RGBA;
170    ctx->blend_write_color = pipe->create_blend_state(pipe, &blend);
171
172    /* depth stencil alpha state objects */
173    memset(&dsa, 0, sizeof(dsa));
174    ctx->dsa_keep_depth_stencil =
175       pipe->create_depth_stencil_alpha_state(pipe, &dsa);
176
177    dsa.depth.enabled = 1;
178    dsa.depth.writemask = 1;
179    dsa.depth.func = PIPE_FUNC_ALWAYS;
180    ctx->dsa_write_depth_keep_stencil =
181       pipe->create_depth_stencil_alpha_state(pipe, &dsa);
182
183    dsa.stencil[0].enabled = 1;
184    dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
185    dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
186    dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
187    dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
188    dsa.stencil[0].valuemask = 0xff;
189    dsa.stencil[0].writemask = 0xff;
190    ctx->dsa_write_depth_stencil =
191       pipe->create_depth_stencil_alpha_state(pipe, &dsa);
192
193    dsa.depth.enabled = 0;
194    dsa.depth.writemask = 0;
195    ctx->dsa_keep_depth_write_stencil =
196       pipe->create_depth_stencil_alpha_state(pipe, &dsa);
197
198    /* sampler state */
199    memset(&sampler_state, 0, sizeof(sampler_state));
200    sampler_state.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
201    sampler_state.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
202    sampler_state.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
203    sampler_state.normalized_coords = 1;
204    ctx->sampler_state = pipe->create_sampler_state(pipe, &sampler_state);
205
206    /* rasterizer state */
207    memset(&rs_state, 0, sizeof(rs_state));
208    rs_state.cull_face = PIPE_FACE_NONE;
209    rs_state.gl_rasterization_rules = 1;
210    rs_state.flatshade = 1;
211    rs_state.depth_clip = 1;
212    ctx->rs_state = pipe->create_rasterizer_state(pipe, &rs_state);
213
214    if (ctx->has_stream_out) {
215       rs_state.rasterizer_discard = 1;
216       ctx->rs_discard_state = pipe->create_rasterizer_state(pipe, &rs_state);
217    }
218
219    /* vertex elements states */
220    memset(&velem[0], 0, sizeof(velem[0]) * 2);
221    for (i = 0; i < 2; i++) {
222       velem[i].src_offset = i * 4 * sizeof(float);
223       velem[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
224    }
225    ctx->velem_state = pipe->create_vertex_elements_state(pipe, 2, &velem[0]);
226
227    if (ctx->vertex_has_integers) {
228       memset(&velem[0], 0, sizeof(velem[0]) * 2);
229       velem[0].src_offset = 0;
230       velem[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
231       velem[1].src_offset = 4 * sizeof(float);
232       velem[1].src_format = PIPE_FORMAT_R32G32B32A32_SINT;
233       ctx->velem_sint_state = pipe->create_vertex_elements_state(pipe, 2, &velem[0]);
234
235       memset(&velem[0], 0, sizeof(velem[0]) * 2);
236       velem[0].src_offset = 0;
237       velem[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
238       velem[1].src_offset = 4 * sizeof(float);
239       velem[1].src_format = PIPE_FORMAT_R32G32B32A32_UINT;
240       ctx->velem_uint_state = pipe->create_vertex_elements_state(pipe, 2, &velem[0]);
241    }
242
243    if (ctx->has_stream_out) {
244       velem[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
245       ctx->velem_state_readbuf = pipe->create_vertex_elements_state(pipe, 1, &velem[0]);
246    }
247
248    /* fragment shaders are created on-demand */
249
250    /* vertex shaders */
251    {
252       const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
253                                       TGSI_SEMANTIC_GENERIC };
254       const uint semantic_indices[] = { 0, 0 };
255       ctx->vs =
256          util_make_vertex_passthrough_shader(pipe, 2, semantic_names,
257                                              semantic_indices);
258    }
259    if (ctx->has_stream_out) {
260       struct pipe_stream_output_info so;
261       const uint semantic_names[] = { TGSI_SEMANTIC_POSITION };
262       const uint semantic_indices[] = { 0 };
263
264       memset(&so, 0, sizeof(so));
265       so.num_outputs = 1;
266       so.output[0].register_mask = TGSI_WRITEMASK_XYZW;
267       so.stride = 4;
268
269       ctx->vs_pos_only =
270          util_make_vertex_passthrough_shader_with_so(pipe, 1, semantic_names,
271                                                      semantic_indices, &so);
272    }
273
274    /* set invariant vertex coordinates */
275    for (i = 0; i < 4; i++)
276       ctx->vertices[i][0][3] = 1; /*v.w*/
277
278    /* create the vertex buffer */
279    ctx->vbuf = pipe_user_buffer_create(ctx->base.pipe->screen,
280                                        ctx->vertices,
281                                        sizeof(ctx->vertices),
282                                        PIPE_BIND_VERTEX_BUFFER);
283
284    return &ctx->base;
285 }
286
287 void util_blitter_destroy(struct blitter_context *blitter)
288 {
289    struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
290    struct pipe_context *pipe = blitter->pipe;
291    int i;
292
293    pipe->delete_blend_state(pipe, ctx->blend_write_color);
294    pipe->delete_blend_state(pipe, ctx->blend_keep_color);
295    pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
296    pipe->delete_depth_stencil_alpha_state(pipe,
297                                           ctx->dsa_write_depth_keep_stencil);
298    pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil);
299    pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil);
300
301    pipe->delete_rasterizer_state(pipe, ctx->rs_state);
302    if (ctx->rs_discard_state)
303       pipe->delete_rasterizer_state(pipe, ctx->rs_discard_state);
304    pipe->delete_vs_state(pipe, ctx->vs);
305    if (ctx->vs_pos_only)
306       pipe->delete_vs_state(pipe, ctx->vs_pos_only);
307    pipe->delete_vertex_elements_state(pipe, ctx->velem_state);
308    if (ctx->vertex_has_integers) {
309       pipe->delete_vertex_elements_state(pipe, ctx->velem_sint_state);
310       pipe->delete_vertex_elements_state(pipe, ctx->velem_uint_state);
311    }
312    if (ctx->velem_state_readbuf)
313       pipe->delete_vertex_elements_state(pipe, ctx->velem_state_readbuf);
314
315    for (i = 0; i < PIPE_MAX_TEXTURE_TYPES; i++) {
316       if (ctx->fs_texfetch_col[i])
317          pipe->delete_fs_state(pipe, ctx->fs_texfetch_col[i]);
318       if (ctx->fs_texfetch_depth[i])
319          pipe->delete_fs_state(pipe, ctx->fs_texfetch_depth[i]);
320    }
321
322    for (i = 0; i <= PIPE_MAX_COLOR_BUFS; i++) {
323       if (ctx->fs_col[i])
324          pipe->delete_fs_state(pipe, ctx->fs_col[i]);
325       if (ctx->fs_col_int[i])
326          pipe->delete_fs_state(pipe, ctx->fs_col_int[i]);
327    }
328
329    pipe->delete_sampler_state(pipe, ctx->sampler_state);
330    pipe_resource_reference(&ctx->vbuf, NULL);
331    FREE(ctx);
332 }
333
334 static void blitter_set_running_flag(struct blitter_context_priv *ctx)
335 {
336    if (ctx->base.running) {
337       _debug_printf("u_blitter:%i: Caught recursion. This is a driver bug.\n",
338                     __LINE__);
339    }
340    ctx->base.running = TRUE;
341 }
342
343 static void blitter_unset_running_flag(struct blitter_context_priv *ctx)
344 {
345    if (!ctx->base.running) {
346       _debug_printf("u_blitter:%i: Caught recursion. This is a driver bug.\n",
347                     __LINE__);
348    }
349    ctx->base.running = FALSE;
350 }
351
352 static void blitter_check_saved_vertex_states(struct blitter_context_priv *ctx)
353 {
354    assert(ctx->base.saved_num_vertex_buffers != ~0 &&
355           ctx->base.saved_velem_state != INVALID_PTR &&
356           ctx->base.saved_vs != INVALID_PTR &&
357           (!ctx->has_geometry_shader || ctx->base.saved_gs != INVALID_PTR) &&
358           (!ctx->has_stream_out || ctx->base.saved_num_so_targets != ~0) &&
359           ctx->base.saved_rs_state != INVALID_PTR);
360 }
361
362 static void blitter_restore_vertex_states(struct blitter_context_priv *ctx)
363 {
364    struct pipe_context *pipe = ctx->base.pipe;
365    unsigned i;
366
367    /* Vertex buffers. */
368    pipe->set_vertex_buffers(pipe,
369                             ctx->base.saved_num_vertex_buffers,
370                             ctx->base.saved_vertex_buffers);
371
372    for (i = 0; i < ctx->base.saved_num_vertex_buffers; i++) {
373       if (ctx->base.saved_vertex_buffers[i].buffer) {
374          pipe_resource_reference(&ctx->base.saved_vertex_buffers[i].buffer,
375                                  NULL);
376       }
377    }
378    ctx->base.saved_num_vertex_buffers = ~0;
379
380    /* Vertex elements. */
381    pipe->bind_vertex_elements_state(pipe, ctx->base.saved_velem_state);
382    ctx->base.saved_velem_state = INVALID_PTR;
383
384    /* Vertex shader. */
385    pipe->bind_vs_state(pipe, ctx->base.saved_vs);
386    ctx->base.saved_vs = INVALID_PTR;
387
388    /* Geometry shader. */
389    if (ctx->has_geometry_shader) {
390       pipe->bind_gs_state(pipe, ctx->base.saved_gs);
391       ctx->base.saved_gs = INVALID_PTR;
392    }
393
394    /* Stream outputs. */
395    if (ctx->has_stream_out) {
396       pipe->set_stream_output_targets(pipe,
397                                       ctx->base.saved_num_so_targets,
398                                       ctx->base.saved_so_targets, ~0);
399
400       for (i = 0; i < ctx->base.saved_num_so_targets; i++)
401          pipe_so_target_reference(&ctx->base.saved_so_targets[i], NULL);
402
403       ctx->base.saved_num_so_targets = ~0;
404    }
405
406    /* Rasterizer. */
407    pipe->bind_rasterizer_state(pipe, ctx->base.saved_rs_state);
408    ctx->base.saved_rs_state = INVALID_PTR;
409 }
410
411 static void blitter_check_saved_fragment_states(struct blitter_context_priv *ctx)
412 {
413    assert(ctx->base.saved_fs != INVALID_PTR &&
414           ctx->base.saved_dsa_state != INVALID_PTR &&
415           ctx->base.saved_blend_state != INVALID_PTR);
416 }
417
418 static void blitter_restore_fragment_states(struct blitter_context_priv *ctx)
419 {
420    struct pipe_context *pipe = ctx->base.pipe;
421
422    /* Fragment shader. */
423    pipe->bind_fs_state(pipe, ctx->base.saved_fs);
424    ctx->base.saved_fs = INVALID_PTR;
425
426    /* Depth, stencil, alpha. */
427    pipe->bind_depth_stencil_alpha_state(pipe, ctx->base.saved_dsa_state);
428    ctx->base.saved_dsa_state = INVALID_PTR;
429
430    /* Blend state. */
431    pipe->bind_blend_state(pipe, ctx->base.saved_blend_state);
432    ctx->base.saved_blend_state = INVALID_PTR;
433
434    /* Miscellaneous states. */
435    /* XXX check whether these are saved and whether they need to be restored
436     * (depending on the operation) */
437    pipe->set_stencil_ref(pipe, &ctx->base.saved_stencil_ref);
438    pipe->set_viewport_state(pipe, &ctx->base.saved_viewport);
439 }
440
441 static void blitter_check_saved_fb_state(struct blitter_context_priv *ctx)
442 {
443    assert(ctx->base.saved_fb_state.nr_cbufs != ~0);
444 }
445
446 static void blitter_restore_fb_state(struct blitter_context_priv *ctx)
447 {
448    struct pipe_context *pipe = ctx->base.pipe;
449
450    pipe->set_framebuffer_state(pipe, &ctx->base.saved_fb_state);
451    util_unreference_framebuffer_state(&ctx->base.saved_fb_state);
452 }
453
454 static void blitter_check_saved_textures(struct blitter_context_priv *ctx)
455 {
456    assert(ctx->base.saved_num_sampler_states != ~0 &&
457           ctx->base.saved_num_sampler_views != ~0);
458 }
459
460 static void blitter_restore_textures(struct blitter_context_priv *ctx)
461 {
462    struct pipe_context *pipe = ctx->base.pipe;
463    unsigned i;
464
465    /* Fragment sampler states. */
466    pipe->bind_fragment_sampler_states(pipe,
467                                       ctx->base.saved_num_sampler_states,
468                                       ctx->base.saved_sampler_states);
469    ctx->base.saved_num_sampler_states = ~0;
470
471    /* Fragment sampler views. */
472    pipe->set_fragment_sampler_views(pipe,
473                                     ctx->base.saved_num_sampler_views,
474                                     ctx->base.saved_sampler_views);
475
476    for (i = 0; i < ctx->base.saved_num_sampler_views; i++)
477       pipe_sampler_view_reference(&ctx->base.saved_sampler_views[i], NULL);
478
479    ctx->base.saved_num_sampler_views = ~0;
480 }
481
482 static void blitter_set_rectangle(struct blitter_context_priv *ctx,
483                                   unsigned x1, unsigned y1,
484                                   unsigned x2, unsigned y2,
485                                   float depth)
486 {
487    int i;
488
489    /* set vertex positions */
490    ctx->vertices[0][0][0] = (float)x1 / ctx->dst_width * 2.0f - 1.0f; /*v0.x*/
491    ctx->vertices[0][0][1] = (float)y1 / ctx->dst_height * 2.0f - 1.0f; /*v0.y*/
492
493    ctx->vertices[1][0][0] = (float)x2 / ctx->dst_width * 2.0f - 1.0f; /*v1.x*/
494    ctx->vertices[1][0][1] = (float)y1 / ctx->dst_height * 2.0f - 1.0f; /*v1.y*/
495
496    ctx->vertices[2][0][0] = (float)x2 / ctx->dst_width * 2.0f - 1.0f; /*v2.x*/
497    ctx->vertices[2][0][1] = (float)y2 / ctx->dst_height * 2.0f - 1.0f; /*v2.y*/
498
499    ctx->vertices[3][0][0] = (float)x1 / ctx->dst_width * 2.0f - 1.0f; /*v3.x*/
500    ctx->vertices[3][0][1] = (float)y2 / ctx->dst_height * 2.0f - 1.0f; /*v3.y*/
501
502    for (i = 0; i < 4; i++)
503       ctx->vertices[i][0][2] = depth; /*z*/
504
505    /* viewport */
506    ctx->viewport.scale[0] = 0.5f * ctx->dst_width;
507    ctx->viewport.scale[1] = 0.5f * ctx->dst_height;
508    ctx->viewport.scale[2] = 1.0f;
509    ctx->viewport.scale[3] = 1.0f;
510    ctx->viewport.translate[0] = 0.5f * ctx->dst_width;
511    ctx->viewport.translate[1] = 0.5f * ctx->dst_height;
512    ctx->viewport.translate[2] = 0.0f;
513    ctx->viewport.translate[3] = 0.0f;
514    ctx->base.pipe->set_viewport_state(ctx->base.pipe, &ctx->viewport);
515 }
516
517 static void blitter_set_clear_color(struct blitter_context_priv *ctx,
518                                     const union pipe_color_union *color)
519 {
520    int i;
521
522    if (color) {
523       for (i = 0; i < 4; i++) {
524          uint32_t *uiverts = (uint32_t *)ctx->vertices[i][1];
525          uiverts[0] = color->ui[0];
526          uiverts[1] = color->ui[1];
527          uiverts[2] = color->ui[2];
528          uiverts[3] = color->ui[3];
529       }
530    } else {
531       for (i = 0; i < 4; i++) {
532          ctx->vertices[i][1][0] = 0;
533          ctx->vertices[i][1][1] = 0;
534          ctx->vertices[i][1][2] = 0;
535          ctx->vertices[i][1][3] = 0;
536       }
537    }
538 }
539
540 static void get_texcoords(struct pipe_sampler_view *src,
541                           unsigned src_width0, unsigned src_height0,
542                           unsigned x1, unsigned y1,
543                           unsigned x2, unsigned y2,
544                           float out[4])
545 {
546    struct pipe_resource *tex = src->texture;
547    unsigned level = src->u.tex.first_level;
548    boolean normalized = tex->target != PIPE_TEXTURE_RECT;
549
550    if (normalized) {
551       out[0] = x1 / (float)u_minify(src_width0,  level);
552       out[1] = y1 / (float)u_minify(src_height0, level);
553       out[2] = x2 / (float)u_minify(src_width0,  level);
554       out[3] = y2 / (float)u_minify(src_height0, level);
555    } else {
556       out[0] = x1;
557       out[1] = y1;
558       out[2] = x2;
559       out[3] = y2;
560    }
561 }
562
563 static void set_texcoords_in_vertices(const float coord[4],
564                                       float *out, unsigned stride)
565 {
566    out[0] = coord[0]; /*t0.s*/
567    out[1] = coord[1]; /*t0.t*/
568    out += stride;
569    out[0] = coord[2]; /*t1.s*/
570    out[1] = coord[1]; /*t1.t*/
571    out += stride;
572    out[0] = coord[2]; /*t2.s*/
573    out[1] = coord[3]; /*t2.t*/
574    out += stride;
575    out[0] = coord[0]; /*t3.s*/
576    out[1] = coord[3]; /*t3.t*/
577 }
578
579 static void blitter_set_texcoords(struct blitter_context_priv *ctx,
580                                   struct pipe_sampler_view *src,
581                                   unsigned src_width0, unsigned src_height0,
582                                   unsigned layer,
583                                   unsigned x1, unsigned y1,
584                                   unsigned x2, unsigned y2)
585 {
586    unsigned i;
587    float coord[4];
588    float face_coord[4][2];
589
590    get_texcoords(src, src_width0, src_height0, x1, y1, x2, y2, coord);
591
592    if (src->texture->target == PIPE_TEXTURE_CUBE) {
593       set_texcoords_in_vertices(coord, &face_coord[0][0], 2);
594       util_map_texcoords2d_onto_cubemap(layer,
595                                         /* pointer, stride in floats */
596                                         &face_coord[0][0], 2,
597                                         &ctx->vertices[0][1][0], 8);
598    } else {
599       set_texcoords_in_vertices(coord, &ctx->vertices[0][1][0], 8);
600    }
601
602    /* Set the layer. */
603    switch (src->texture->target) {
604    case PIPE_TEXTURE_3D:
605       {
606          float r = layer / (float)u_minify(src->texture->depth0,
607                                            src->u.tex.first_level);
608          for (i = 0; i < 4; i++)
609             ctx->vertices[i][1][2] = r; /*r*/
610       }
611       break;
612
613    case PIPE_TEXTURE_1D_ARRAY:
614       for (i = 0; i < 4; i++)
615          ctx->vertices[i][1][1] = layer; /*t*/
616       break;
617
618    case PIPE_TEXTURE_2D_ARRAY:
619       for (i = 0; i < 4; i++)
620          ctx->vertices[i][1][2] = layer; /*r*/
621       break;
622
623    default:;
624    }
625 }
626
627 static void blitter_set_dst_dimensions(struct blitter_context_priv *ctx,
628                                        unsigned width, unsigned height)
629 {
630    ctx->dst_width = width;
631    ctx->dst_height = height;
632 }
633
634 static INLINE
635 void *blitter_get_fs_col(struct blitter_context_priv *ctx, unsigned num_cbufs,
636                          boolean int_format)
637 {
638    struct pipe_context *pipe = ctx->base.pipe;
639
640    assert(num_cbufs <= PIPE_MAX_COLOR_BUFS);
641
642    if (int_format) {
643       if (!ctx->fs_col_int[num_cbufs])
644          ctx->fs_col_int[num_cbufs] =
645             util_make_fragment_cloneinput_shader(pipe, num_cbufs,
646                                                  TGSI_SEMANTIC_GENERIC,
647                                                  TGSI_INTERPOLATE_CONSTANT);
648       return ctx->fs_col_int[num_cbufs];
649    } else {
650       if (!ctx->fs_col[num_cbufs])
651          ctx->fs_col[num_cbufs] =
652             util_make_fragment_cloneinput_shader(pipe, num_cbufs,
653                                                  TGSI_SEMANTIC_GENERIC,
654                                                  TGSI_INTERPOLATE_LINEAR);
655       return ctx->fs_col[num_cbufs];
656    }
657 }
658
659 /** Convert PIPE_TEXTURE_x to TGSI_TEXTURE_x */
660 static unsigned
661 pipe_tex_to_tgsi_tex(enum pipe_texture_target pipe_tex_target)
662 {
663    switch (pipe_tex_target) {
664    case PIPE_TEXTURE_1D:
665       return TGSI_TEXTURE_1D;
666    case PIPE_TEXTURE_2D:
667       return TGSI_TEXTURE_2D;
668    case PIPE_TEXTURE_RECT:
669       return TGSI_TEXTURE_RECT;
670    case PIPE_TEXTURE_3D:
671       return TGSI_TEXTURE_3D;
672    case PIPE_TEXTURE_CUBE:
673       return TGSI_TEXTURE_CUBE;
674    case PIPE_TEXTURE_1D_ARRAY:
675       return TGSI_TEXTURE_1D_ARRAY;
676    case PIPE_TEXTURE_2D_ARRAY:
677       return TGSI_TEXTURE_2D_ARRAY;
678    default:
679       assert(0 && "unexpected texture target");
680       return TGSI_TEXTURE_UNKNOWN;
681    }
682 }
683
684
685 static INLINE
686 void *blitter_get_fs_texfetch_col(struct blitter_context_priv *ctx,
687                                   unsigned tex_target)
688 {
689    struct pipe_context *pipe = ctx->base.pipe;
690
691    assert(tex_target < PIPE_MAX_TEXTURE_TYPES);
692
693    /* Create the fragment shader on-demand. */
694    if (!ctx->fs_texfetch_col[tex_target]) {
695       unsigned tgsi_tex = pipe_tex_to_tgsi_tex(tex_target);
696
697       ctx->fs_texfetch_col[tex_target] =
698         util_make_fragment_tex_shader(pipe, tgsi_tex, TGSI_INTERPOLATE_LINEAR);
699    }
700
701    return ctx->fs_texfetch_col[tex_target];
702 }
703
704 static INLINE
705 void *blitter_get_fs_texfetch_depth(struct blitter_context_priv *ctx,
706                                     unsigned tex_target)
707 {
708    struct pipe_context *pipe = ctx->base.pipe;
709
710    assert(tex_target < PIPE_MAX_TEXTURE_TYPES);
711
712    /* Create the fragment shader on-demand. */
713    if (!ctx->fs_texfetch_depth[tex_target]) {
714       unsigned tgsi_tex = pipe_tex_to_tgsi_tex(tex_target);
715
716       ctx->fs_texfetch_depth[tex_target] =
717          util_make_fragment_tex_shader_writedepth(pipe, tgsi_tex,
718                                                   TGSI_INTERPOLATE_LINEAR);
719    }
720
721    return ctx->fs_texfetch_depth[tex_target];
722 }
723
724 static void blitter_draw_rectangle(struct blitter_context *blitter,
725                                    unsigned x1, unsigned y1,
726                                    unsigned x2, unsigned y2,
727                                    float depth,
728                                    enum blitter_attrib_type type,
729                                    const union pipe_color_union *attrib)
730 {
731    struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
732
733    switch (type) {
734       case UTIL_BLITTER_ATTRIB_COLOR:
735          blitter_set_clear_color(ctx, attrib);
736          break;
737
738       case UTIL_BLITTER_ATTRIB_TEXCOORD:
739          set_texcoords_in_vertices(attrib->f, &ctx->vertices[0][1][0], 8);
740          break;
741
742       default:;
743    }
744
745    blitter_set_rectangle(ctx, x1, y1, x2, y2, depth);
746    ctx->base.pipe->redefine_user_buffer(ctx->base.pipe, ctx->vbuf,
747                                         0, ctx->vbuf->width0);
748    util_draw_vertex_buffer(ctx->base.pipe, NULL, ctx->vbuf, 0,
749                            PIPE_PRIM_TRIANGLE_FAN, 4, 2);
750 }
751
752 static void util_blitter_clear_custom(struct blitter_context *blitter,
753                                       unsigned width, unsigned height,
754                                       unsigned num_cbufs,
755                                       unsigned clear_buffers,
756                                       enum pipe_format cbuf_format,
757                                       const union pipe_color_union *color,
758                                       double depth, unsigned stencil,
759                                       void *custom_blend, void *custom_dsa)
760 {
761    struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
762    struct pipe_context *pipe = ctx->base.pipe;
763    struct pipe_stencil_ref sr = { { 0 } };
764    boolean int_format = util_format_is_pure_integer(cbuf_format);
765    assert(num_cbufs <= PIPE_MAX_COLOR_BUFS);
766
767    blitter_set_running_flag(ctx);
768    blitter_check_saved_vertex_states(ctx);
769    blitter_check_saved_fragment_states(ctx);
770
771    /* bind states */
772    if (custom_blend) {
773       pipe->bind_blend_state(pipe, custom_blend);
774    } else if (clear_buffers & PIPE_CLEAR_COLOR) {
775       pipe->bind_blend_state(pipe, ctx->blend_write_color);
776    } else {
777       pipe->bind_blend_state(pipe, ctx->blend_keep_color);
778    }
779
780    if (custom_dsa) {
781       pipe->bind_depth_stencil_alpha_state(pipe, custom_dsa);
782    } else if ((clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) == PIPE_CLEAR_DEPTHSTENCIL) {
783       pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil);
784    } else if (clear_buffers & PIPE_CLEAR_DEPTH) {
785       pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_keep_stencil);
786    } else if (clear_buffers & PIPE_CLEAR_STENCIL) {
787       pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil);
788    } else {
789       pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
790    }
791
792    sr.ref_value[0] = stencil & 0xff;
793    pipe->set_stencil_ref(pipe, &sr);
794
795    pipe->bind_rasterizer_state(pipe, ctx->rs_state);
796    if (util_format_is_pure_sint(cbuf_format)) {
797       pipe->bind_vertex_elements_state(pipe, ctx->velem_sint_state);
798    } else if (util_format_is_pure_uint(cbuf_format)) {
799       pipe->bind_vertex_elements_state(pipe, ctx->velem_uint_state);
800    } else {
801       pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
802    }
803    pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, num_cbufs, int_format));
804    pipe->bind_vs_state(pipe, ctx->vs);
805    if (ctx->has_geometry_shader)
806       pipe->bind_gs_state(pipe, NULL);
807
808    blitter_set_dst_dimensions(ctx, width, height);
809    blitter->draw_rectangle(blitter, 0, 0, width, height, depth,
810                            UTIL_BLITTER_ATTRIB_COLOR, color);
811
812    blitter_restore_vertex_states(ctx);
813    blitter_restore_fragment_states(ctx);
814    blitter_unset_running_flag(ctx);
815 }
816
817 void util_blitter_clear(struct blitter_context *blitter,
818                         unsigned width, unsigned height,
819                         unsigned num_cbufs,
820                         unsigned clear_buffers,
821                         enum pipe_format cbuf_format,
822                         const union pipe_color_union *color,
823                         double depth, unsigned stencil)
824 {
825    util_blitter_clear_custom(blitter, width, height, num_cbufs,
826                              clear_buffers, cbuf_format, color, depth, stencil,
827                              NULL, NULL);
828 }
829
830 void util_blitter_clear_depth_custom(struct blitter_context *blitter,
831                                      unsigned width, unsigned height,
832                                      double depth, void *custom_dsa)
833 {
834     static const union pipe_color_union color;
835     util_blitter_clear_custom(blitter, width, height, 0,
836                               0, PIPE_FORMAT_NONE, &color, depth, 0, NULL, custom_dsa);
837 }
838
839 static
840 boolean is_overlap(unsigned sx1, unsigned sx2, unsigned sy1, unsigned sy2,
841                    unsigned dx1, unsigned dx2, unsigned dy1, unsigned dy2)
842 {
843    return sx1 < dx2 && sx2 > dx1 && sy1 < dy2 && sy2 > dy1;
844 }
845
846 void util_blitter_default_dst_texture(struct pipe_surface *dst_templ,
847                                       struct pipe_resource *dst,
848                                       unsigned dstlevel,
849                                       unsigned dstz,
850                                       const struct pipe_box *srcbox)
851 {
852     memset(dst_templ, 0, sizeof(*dst_templ));
853     dst_templ->format = dst->format;
854     if (util_format_is_depth_or_stencil(dst->format)) {
855         dst_templ->usage = PIPE_BIND_DEPTH_STENCIL;
856     } else {
857         dst_templ->usage = PIPE_BIND_RENDER_TARGET;
858     }
859     dst_templ->format = util_format_linear(dst->format);
860     dst_templ->u.tex.level = dstlevel;
861     dst_templ->u.tex.first_layer = dstz;
862     dst_templ->u.tex.last_layer = dstz + srcbox->depth - 1;
863 }
864
865 void util_blitter_default_src_texture(struct pipe_sampler_view *src_templ,
866                                       struct pipe_resource *src,
867                                       unsigned srclevel)
868 {
869     memset(src_templ, 0, sizeof(*src_templ));
870     src_templ->format = util_format_linear(src->format);
871     src_templ->u.tex.first_level = srclevel;
872     src_templ->u.tex.last_level = srclevel;
873     src_templ->u.tex.first_layer = 0;
874     src_templ->u.tex.last_layer =
875         src->target == PIPE_TEXTURE_3D ? src->depth0 - 1
876                                        : src->array_size - 1;
877     src_templ->swizzle_r = PIPE_SWIZZLE_RED;
878     src_templ->swizzle_g = PIPE_SWIZZLE_GREEN;
879     src_templ->swizzle_b = PIPE_SWIZZLE_BLUE;
880     src_templ->swizzle_a = PIPE_SWIZZLE_ALPHA;
881 }
882
883 void util_blitter_copy_texture(struct blitter_context *blitter,
884                                struct pipe_resource *dst,
885                                unsigned dstlevel,
886                                unsigned dstx, unsigned dsty, unsigned dstz,
887                                struct pipe_resource *src,
888                                unsigned srclevel,
889                                const struct pipe_box *srcbox,
890                                boolean ignore_stencil)
891 {
892    struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
893    struct pipe_context *pipe = ctx->base.pipe;
894    struct pipe_screen *screen = pipe->screen;
895    struct pipe_surface *dst_view, dst_templ;
896    struct pipe_sampler_view src_templ, *src_view;
897    unsigned bind;
898    boolean is_stencil, is_depth;
899
900    /* Give up if textures are not set. */
901    assert(dst && src);
902    if (!dst || !src)
903       return;
904
905    assert(src->target < PIPE_MAX_TEXTURE_TYPES);
906
907    /* Is this a ZS format? */
908    is_depth = util_format_get_component_bits(src->format, UTIL_FORMAT_COLORSPACE_ZS, 0) != 0;
909    is_stencil = util_format_get_component_bits(src->format, UTIL_FORMAT_COLORSPACE_ZS, 1) != 0;
910
911    if (is_depth || is_stencil)
912       bind = PIPE_BIND_DEPTH_STENCIL;
913    else
914       bind = PIPE_BIND_RENDER_TARGET;
915
916    /* Check if we can sample from and render to the surfaces. */
917    /* (assuming copying a stencil buffer is not possible) */
918    if ((!ignore_stencil && is_stencil) ||
919        !screen->is_format_supported(screen, dst->format, dst->target,
920                                     dst->nr_samples, bind) ||
921        !screen->is_format_supported(screen, src->format, src->target,
922                                     src->nr_samples, PIPE_BIND_SAMPLER_VIEW)) {
923       blitter_set_running_flag(ctx);
924       util_resource_copy_region(pipe, dst, dstlevel, dstx, dsty, dstz,
925                                 src, srclevel, srcbox);
926       blitter_unset_running_flag(ctx);
927       return;
928    }
929
930    /* Initialize the surface. */
931    util_blitter_default_dst_texture(&dst_templ, dst, dstlevel, dstz, srcbox);
932    dst_view = pipe->create_surface(pipe, dst, &dst_templ);
933
934    /* Initialize the sampler view. */
935    util_blitter_default_src_texture(&src_templ, src, srclevel);
936    src_view = pipe->create_sampler_view(pipe, src, &src_templ);
937
938    /* Copy. */
939    util_blitter_copy_texture_view(blitter, dst_view, dstx, dsty, src_view,
940                                   srcbox, src->width0, src->height0);
941
942    pipe_surface_reference(&dst_view, NULL);
943    pipe_sampler_view_reference(&src_view, NULL);
944 }
945
946 void util_blitter_copy_texture_view(struct blitter_context *blitter,
947                                     struct pipe_surface *dst,
948                                     unsigned dstx, unsigned dsty,
949                                     struct pipe_sampler_view *src,
950                                     const struct pipe_box *srcbox,
951                                     unsigned src_width0, unsigned src_height0)
952 {
953    struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
954    struct pipe_context *pipe = ctx->base.pipe;
955    struct pipe_framebuffer_state fb_state;
956    enum pipe_texture_target src_target = src->texture->target;
957    unsigned width = srcbox->width;
958    unsigned height = srcbox->height;
959
960    /* Sanity checks. */
961    if (dst->texture == src->texture &&
962        dst->u.tex.level == src->u.tex.first_level) {
963       assert(!is_overlap(srcbox->x, srcbox->x + width, srcbox->y, srcbox->y + height,
964                          dstx, dstx + width, dsty, dsty + height));
965    }
966    /* XXX should handle 3d regions */
967    assert(srcbox->depth == 1);
968
969    /* Check whether the states are properly saved. */
970    blitter_set_running_flag(ctx);
971    blitter_check_saved_vertex_states(ctx);
972    blitter_check_saved_fragment_states(ctx);
973    blitter_check_saved_textures(ctx);
974    blitter_check_saved_fb_state(ctx);
975
976    /* Initialize framebuffer state. */
977    fb_state.width = dst->width;
978    fb_state.height = dst->height;
979
980    if (util_format_is_depth_or_stencil(dst->format)) {
981       pipe->bind_blend_state(pipe, ctx->blend_keep_color);
982       pipe->bind_depth_stencil_alpha_state(pipe,
983                                            ctx->dsa_write_depth_keep_stencil);
984       pipe->bind_fs_state(pipe,
985             blitter_get_fs_texfetch_depth(ctx, src_target));
986
987       fb_state.nr_cbufs = 0;
988       fb_state.zsbuf = dst;
989    } else {
990       pipe->bind_blend_state(pipe, ctx->blend_write_color);
991       pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
992       pipe->bind_fs_state(pipe,
993             blitter_get_fs_texfetch_col(ctx, src_target));
994
995       fb_state.nr_cbufs = 1;
996       fb_state.cbufs[0] = dst;
997       fb_state.zsbuf = 0;
998    }
999
1000    /* Set rasterizer state, shaders, and textures. */
1001    pipe->bind_rasterizer_state(pipe, ctx->rs_state);
1002    pipe->bind_vs_state(pipe, ctx->vs);
1003    if (ctx->has_geometry_shader)
1004       pipe->bind_gs_state(pipe, NULL);
1005    pipe->bind_fragment_sampler_states(pipe, 1, &ctx->sampler_state);
1006    pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
1007    pipe->set_fragment_sampler_views(pipe, 1, &src);
1008    pipe->set_framebuffer_state(pipe, &fb_state);
1009
1010    blitter_set_dst_dimensions(ctx, dst->width, dst->height);
1011
1012    switch (src_target) {
1013       /* Draw the quad with the draw_rectangle callback. */
1014       case PIPE_TEXTURE_1D:
1015       case PIPE_TEXTURE_2D:
1016       case PIPE_TEXTURE_RECT:
1017          {
1018             /* Set texture coordinates. - use a pipe color union
1019              * for interface purposes.
1020              * XXX pipe_color_union is a wrong name since we use that to set
1021              * texture coordinates too.
1022              */
1023             union pipe_color_union coord;
1024             get_texcoords(src, src_width0, src_height0, srcbox->x, srcbox->y,
1025                           srcbox->x+width, srcbox->y+height, coord.f);
1026
1027             /* Draw. */
1028             blitter->draw_rectangle(blitter, dstx, dsty, dstx+width, dsty+height, 0,
1029                                     UTIL_BLITTER_ATTRIB_TEXCOORD, &coord);
1030          }
1031          break;
1032
1033       /* Draw the quad with the generic codepath. */
1034       default:
1035          /* Set texture coordinates. */
1036          switch (src_target) {
1037          case PIPE_TEXTURE_1D_ARRAY:
1038          case PIPE_TEXTURE_2D_ARRAY:
1039          case PIPE_TEXTURE_3D:
1040          case PIPE_TEXTURE_CUBE:
1041             blitter_set_texcoords(ctx, src, src_width0, src_height0, srcbox->z,
1042                                   srcbox->y, srcbox->x,
1043                                   srcbox->x + width, srcbox->y + height);
1044             break;
1045
1046          default:
1047             assert(0);
1048          }
1049
1050          /* Draw. */
1051          blitter_set_rectangle(ctx, dstx, dsty, dstx+width, dsty+height, 0);
1052          ctx->base.pipe->redefine_user_buffer(ctx->base.pipe, ctx->vbuf,
1053                                               0, ctx->vbuf->width0);
1054          util_draw_vertex_buffer(ctx->base.pipe, NULL, ctx->vbuf, 0,
1055                                  PIPE_PRIM_TRIANGLE_FAN, 4, 2);
1056          break;
1057    }
1058
1059    blitter_restore_vertex_states(ctx);
1060    blitter_restore_fragment_states(ctx);
1061    blitter_restore_textures(ctx);
1062    blitter_restore_fb_state(ctx);
1063    blitter_unset_running_flag(ctx);
1064 }
1065
1066 /* Clear a region of a color surface to a constant value. */
1067 void util_blitter_clear_render_target(struct blitter_context *blitter,
1068                                       struct pipe_surface *dstsurf,
1069                                       const union pipe_color_union *color,
1070                                       unsigned dstx, unsigned dsty,
1071                                       unsigned width, unsigned height)
1072 {
1073    struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
1074    struct pipe_context *pipe = ctx->base.pipe;
1075    struct pipe_framebuffer_state fb_state;
1076
1077    assert(dstsurf->texture);
1078    if (!dstsurf->texture)
1079       return;
1080
1081    /* check the saved state */
1082    blitter_set_running_flag(ctx);
1083    blitter_check_saved_vertex_states(ctx);
1084    blitter_check_saved_fragment_states(ctx);
1085    blitter_check_saved_fb_state(ctx);
1086
1087    /* bind states */
1088    pipe->bind_blend_state(pipe, ctx->blend_write_color);
1089    pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
1090    pipe->bind_rasterizer_state(pipe, ctx->rs_state);
1091    pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 1, FALSE));
1092    pipe->bind_vs_state(pipe, ctx->vs);
1093    if (ctx->has_geometry_shader)
1094       pipe->bind_gs_state(pipe, NULL);
1095    pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
1096
1097    /* set a framebuffer state */
1098    fb_state.width = dstsurf->width;
1099    fb_state.height = dstsurf->height;
1100    fb_state.nr_cbufs = 1;
1101    fb_state.cbufs[0] = dstsurf;
1102    fb_state.zsbuf = 0;
1103    pipe->set_framebuffer_state(pipe, &fb_state);
1104
1105    blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height);
1106    blitter->draw_rectangle(blitter, dstx, dsty, dstx+width, dsty+height, 0,
1107                            UTIL_BLITTER_ATTRIB_COLOR, color);
1108
1109    blitter_restore_vertex_states(ctx);
1110    blitter_restore_fragment_states(ctx);
1111    blitter_restore_fb_state(ctx);
1112    blitter_unset_running_flag(ctx);
1113 }
1114
1115 /* Clear a region of a depth stencil surface. */
1116 void util_blitter_clear_depth_stencil(struct blitter_context *blitter,
1117                                       struct pipe_surface *dstsurf,
1118                                       unsigned clear_flags,
1119                                       double depth,
1120                                       unsigned stencil,
1121                                       unsigned dstx, unsigned dsty,
1122                                       unsigned width, unsigned height)
1123 {
1124    struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
1125    struct pipe_context *pipe = ctx->base.pipe;
1126    struct pipe_framebuffer_state fb_state;
1127    struct pipe_stencil_ref sr = { { 0 } };
1128
1129    assert(dstsurf->texture);
1130    if (!dstsurf->texture)
1131       return;
1132
1133    /* check the saved state */
1134    blitter_set_running_flag(ctx);
1135    blitter_check_saved_vertex_states(ctx);
1136    blitter_check_saved_fragment_states(ctx);
1137    blitter_check_saved_fb_state(ctx);
1138
1139    /* bind states */
1140    pipe->bind_blend_state(pipe, ctx->blend_keep_color);
1141    if ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) == PIPE_CLEAR_DEPTHSTENCIL) {
1142       sr.ref_value[0] = stencil & 0xff;
1143       pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil);
1144       pipe->set_stencil_ref(pipe, &sr);
1145    }
1146    else if (clear_flags & PIPE_CLEAR_DEPTH) {
1147       pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_keep_stencil);
1148    }
1149    else if (clear_flags & PIPE_CLEAR_STENCIL) {
1150       sr.ref_value[0] = stencil & 0xff;
1151       pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil);
1152       pipe->set_stencil_ref(pipe, &sr);
1153    }
1154    else
1155       /* hmm that should be illegal probably, or make it a no-op somewhere */
1156       pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
1157
1158    pipe->bind_rasterizer_state(pipe, ctx->rs_state);
1159    pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 0, FALSE));
1160    pipe->bind_vs_state(pipe, ctx->vs);
1161    if (ctx->has_geometry_shader)
1162       pipe->bind_gs_state(pipe, NULL);
1163    pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
1164
1165    /* set a framebuffer state */
1166    fb_state.width = dstsurf->width;
1167    fb_state.height = dstsurf->height;
1168    fb_state.nr_cbufs = 0;
1169    fb_state.cbufs[0] = 0;
1170    fb_state.zsbuf = dstsurf;
1171    pipe->set_framebuffer_state(pipe, &fb_state);
1172
1173    blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height);
1174    blitter->draw_rectangle(blitter, dstx, dsty, dstx+width, dsty+height, depth,
1175                            UTIL_BLITTER_ATTRIB_NONE, NULL);
1176
1177    blitter_restore_vertex_states(ctx);
1178    blitter_restore_fragment_states(ctx);
1179    blitter_restore_fb_state(ctx);
1180    blitter_unset_running_flag(ctx);
1181 }
1182
1183 /* draw a rectangle across a region using a custom dsa stage - for r600g */
1184 void util_blitter_custom_depth_stencil(struct blitter_context *blitter,
1185                                        struct pipe_surface *zsurf,
1186                                        struct pipe_surface *cbsurf,
1187                                        void *dsa_stage, float depth)
1188 {
1189    struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
1190    struct pipe_context *pipe = ctx->base.pipe;
1191    struct pipe_framebuffer_state fb_state;
1192
1193    assert(zsurf->texture);
1194    if (!zsurf->texture)
1195       return;
1196
1197    /* check the saved state */
1198    blitter_set_running_flag(ctx);
1199    blitter_check_saved_vertex_states(ctx);
1200    blitter_check_saved_fragment_states(ctx);
1201    blitter_check_saved_fb_state(ctx);
1202
1203    /* bind states */
1204    pipe->bind_blend_state(pipe, ctx->blend_write_color);
1205    pipe->bind_depth_stencil_alpha_state(pipe, dsa_stage);
1206
1207    pipe->bind_rasterizer_state(pipe, ctx->rs_state);
1208    pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 0, FALSE));
1209    pipe->bind_vs_state(pipe, ctx->vs);
1210    if (ctx->has_geometry_shader)
1211       pipe->bind_gs_state(pipe, NULL);
1212    pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
1213
1214    /* set a framebuffer state */
1215    fb_state.width = zsurf->width;
1216    fb_state.height = zsurf->height;
1217    fb_state.nr_cbufs = 1;
1218    if (cbsurf) {
1219            fb_state.cbufs[0] = cbsurf;
1220            fb_state.nr_cbufs = 1;
1221    } else {
1222            fb_state.cbufs[0] = NULL;
1223            fb_state.nr_cbufs = 0;
1224    }
1225    fb_state.zsbuf = zsurf;
1226    pipe->set_framebuffer_state(pipe, &fb_state);
1227
1228    blitter_set_dst_dimensions(ctx, zsurf->width, zsurf->height);
1229    blitter->draw_rectangle(blitter, 0, 0, zsurf->width, zsurf->height, depth,
1230                            UTIL_BLITTER_ATTRIB_NONE, NULL);
1231
1232    blitter_restore_vertex_states(ctx);
1233    blitter_restore_fragment_states(ctx);
1234    blitter_restore_fb_state(ctx);
1235    blitter_unset_running_flag(ctx);
1236 }
1237
1238 void util_blitter_copy_buffer(struct blitter_context *blitter,
1239                               struct pipe_resource *dst,
1240                               unsigned dstx,
1241                               struct pipe_resource *src,
1242                               unsigned srcx,
1243                               unsigned size)
1244 {
1245    struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
1246    struct pipe_context *pipe = ctx->base.pipe;
1247    struct pipe_vertex_buffer vb;
1248    struct pipe_stream_output_target *so_target;
1249
1250    /* Drivers not capable of Stream Out should not call this function
1251     * in the first place. */
1252    assert(ctx->has_stream_out);
1253
1254    /* Some alignment is required. */
1255    if (srcx % 4 != 0 || dstx % 4 != 0 || size % 16 != 0 ||
1256        !ctx->has_stream_out) {
1257       struct pipe_box box;
1258       u_box_1d(srcx, size, &box);
1259       util_resource_copy_region(pipe, dst, 0, dstx, 0, 0, src, 0, &box);
1260       return;
1261    }
1262
1263    blitter_set_running_flag(ctx);
1264    blitter_check_saved_vertex_states(ctx);
1265
1266    vb.buffer = src;
1267    vb.buffer_offset = srcx;
1268    vb.stride = 4;
1269
1270    pipe->set_vertex_buffers(pipe, 1, &vb);
1271    pipe->bind_vertex_elements_state(pipe, ctx->velem_state_readbuf);
1272    pipe->bind_vs_state(pipe, ctx->vs_pos_only);
1273    if (ctx->has_geometry_shader)
1274       pipe->bind_gs_state(pipe, NULL);
1275    pipe->bind_rasterizer_state(pipe, ctx->rs_discard_state);
1276
1277    so_target = pipe->create_stream_output_target(pipe, dst, dstx, size);
1278    pipe->set_stream_output_targets(pipe, 1, &so_target, 0);
1279
1280    util_draw_arrays(pipe, PIPE_PRIM_POINTS, 0, size / 16);
1281
1282    blitter_restore_vertex_states(ctx);
1283    blitter_unset_running_flag(ctx);
1284    pipe_so_target_reference(&so_target, NULL);
1285 }