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