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