u_blitter.c revision 36d66f8d4ad1e2b18bb28d0b08e98f968ad6137e
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   void *vs_pos_only; /**< Vertex shader which passes pos to the output.*/
67
68   /* Fragment shaders. */
69   /* The shader at index i outputs color to color buffers 0,1,...,i-1. */
70   void *fs_col[PIPE_MAX_COLOR_BUFS+1];
71   void *fs_col_int[PIPE_MAX_COLOR_BUFS+1];
72
73   /* FS which outputs a color from a texture,
74      where the index is PIPE_TEXTURE_* to be sampled. */
75   void *fs_texfetch_col[PIPE_MAX_TEXTURE_TYPES];
76
77   /* FS which outputs a depth from a texture,
78      where the index is PIPE_TEXTURE_* to be sampled. */
79   void *fs_texfetch_depth[PIPE_MAX_TEXTURE_TYPES];
80
81   /* Blend state. */
82   void *blend_write_color;   /**< blend state with writemask of RGBA */
83   void *blend_keep_color;    /**< blend state with writemask of 0 */
84
85   /* Depth stencil alpha state. */
86   void *dsa_write_depth_stencil;
87   void *dsa_write_depth_keep_stencil;
88   void *dsa_keep_depth_stencil;
89   void *dsa_keep_depth_write_stencil;
90
91   /* Vertex elements states. */
92   void *velem_state;
93   void *velem_uint_state;
94   void *velem_sint_state;
95   void *velem_state_readbuf;
96
97   /* Sampler state. */
98   void *sampler_state;
99
100   /* Rasterizer state. */
101   void *rs_state;
102   void *rs_discard_state;
103
104   /* Viewport state. */
105   struct pipe_viewport_state viewport;
106
107   /* Clip state. */
108   struct pipe_clip_state clip;
109
110   /* Destination surface dimensions. */
111   unsigned dst_width;
112   unsigned dst_height;
113
114   boolean has_geometry_shader;
115   boolean vertex_has_integers;
116   boolean has_stream_out;
117};
118
119static void blitter_draw_rectangle(struct blitter_context *blitter,
120                                   unsigned x, unsigned y,
121                                   unsigned width, unsigned height,
122                                   float depth,
123                                   enum blitter_attrib_type type,
124                                   const union pipe_color_union *attrib);
125
126
127struct blitter_context *util_blitter_create(struct pipe_context *pipe)
128{
129   struct blitter_context_priv *ctx;
130   struct pipe_blend_state blend;
131   struct pipe_depth_stencil_alpha_state dsa;
132   struct pipe_rasterizer_state rs_state;
133   struct pipe_sampler_state sampler_state;
134   struct pipe_vertex_element velem[2];
135   unsigned i;
136
137   ctx = CALLOC_STRUCT(blitter_context_priv);
138   if (!ctx)
139      return NULL;
140
141   ctx->base.pipe = pipe;
142   ctx->base.draw_rectangle = blitter_draw_rectangle;
143
144   /* init state objects for them to be considered invalid */
145   ctx->base.saved_blend_state = INVALID_PTR;
146   ctx->base.saved_dsa_state = INVALID_PTR;
147   ctx->base.saved_rs_state = INVALID_PTR;
148   ctx->base.saved_fs = INVALID_PTR;
149   ctx->base.saved_vs = INVALID_PTR;
150   ctx->base.saved_gs = INVALID_PTR;
151   ctx->base.saved_velem_state = INVALID_PTR;
152   ctx->base.saved_fb_state.nr_cbufs = ~0;
153   ctx->base.saved_num_sampler_views = ~0;
154   ctx->base.saved_num_sampler_states = ~0;
155   ctx->base.saved_num_vertex_buffers = ~0;
156   ctx->base.saved_num_so_targets = ~0;
157
158   ctx->has_geometry_shader =
159      pipe->screen->get_shader_param(pipe->screen, PIPE_SHADER_GEOMETRY,
160                                     PIPE_SHADER_CAP_MAX_INSTRUCTIONS) > 0;
161   ctx->vertex_has_integers =
162      pipe->screen->get_shader_param(pipe->screen, PIPE_SHADER_VERTEX,
163                                     PIPE_SHADER_CAP_INTEGERS);
164   ctx->has_stream_out =
165      pipe->screen->get_param(pipe->screen,
166                              PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS) != 0;
167
168   /* blend state objects */
169   memset(&blend, 0, sizeof(blend));
170   ctx->blend_keep_color = pipe->create_blend_state(pipe, &blend);
171
172   blend.rt[0].colormask = PIPE_MASK_RGBA;
173   ctx->blend_write_color = pipe->create_blend_state(pipe, &blend);
174
175   /* depth stencil alpha state objects */
176   memset(&dsa, 0, sizeof(dsa));
177   ctx->dsa_keep_depth_stencil =
178      pipe->create_depth_stencil_alpha_state(pipe, &dsa);
179
180   dsa.depth.enabled = 1;
181   dsa.depth.writemask = 1;
182   dsa.depth.func = PIPE_FUNC_ALWAYS;
183   ctx->dsa_write_depth_keep_stencil =
184      pipe->create_depth_stencil_alpha_state(pipe, &dsa);
185
186   dsa.stencil[0].enabled = 1;
187   dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
188   dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
189   dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
190   dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
191   dsa.stencil[0].valuemask = 0xff;
192   dsa.stencil[0].writemask = 0xff;
193   ctx->dsa_write_depth_stencil =
194      pipe->create_depth_stencil_alpha_state(pipe, &dsa);
195
196
197   dsa.depth.enabled = 0;
198   dsa.depth.writemask = 0;
199   ctx->dsa_keep_depth_write_stencil =
200      pipe->create_depth_stencil_alpha_state(pipe, &dsa);
201
202   /* sampler state */
203   memset(&sampler_state, 0, sizeof(sampler_state));
204   sampler_state.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
205   sampler_state.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
206   sampler_state.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
207   sampler_state.normalized_coords = 1;
208   ctx->sampler_state = pipe->create_sampler_state(pipe, &sampler_state);
209
210   /* rasterizer state */
211   memset(&rs_state, 0, sizeof(rs_state));
212   rs_state.cull_face = PIPE_FACE_NONE;
213   rs_state.gl_rasterization_rules = 1;
214   rs_state.flatshade = 1;
215   ctx->rs_state = pipe->create_rasterizer_state(pipe, &rs_state);
216
217   if (ctx->has_stream_out) {
218      rs_state.rasterizer_discard = 1;
219      ctx->rs_discard_state = pipe->create_rasterizer_state(pipe, &rs_state);
220   }
221
222   /* vertex elements states */
223   memset(&velem[0], 0, sizeof(velem[0]) * 2);
224   for (i = 0; i < 2; i++) {
225      velem[i].src_offset = i * 4 * sizeof(float);
226      velem[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
227   }
228   ctx->velem_state = pipe->create_vertex_elements_state(pipe, 2, &velem[0]);
229
230   if (ctx->vertex_has_integers) {
231      memset(&velem[0], 0, sizeof(velem[0]) * 2);
232      velem[0].src_offset = 0;
233      velem[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
234      velem[1].src_offset = 4 * sizeof(float);
235      velem[1].src_format = PIPE_FORMAT_R32G32B32A32_SINT;
236      ctx->velem_sint_state = pipe->create_vertex_elements_state(pipe, 2, &velem[0]);
237
238      memset(&velem[0], 0, sizeof(velem[0]) * 2);
239      velem[0].src_offset = 0;
240      velem[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
241      velem[1].src_offset = 4 * sizeof(float);
242      velem[1].src_format = PIPE_FORMAT_R32G32B32A32_UINT;
243      ctx->velem_uint_state = pipe->create_vertex_elements_state(pipe, 2, &velem[0]);
244   }
245
246   if (ctx->has_stream_out) {
247      velem[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
248      ctx->velem_state_readbuf = pipe->create_vertex_elements_state(pipe, 1, &velem[0]);
249   }
250
251   /* fragment shaders are created on-demand */
252
253   /* vertex shaders */
254   {
255      const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
256                                      TGSI_SEMANTIC_GENERIC };
257      const uint semantic_indices[] = { 0, 0 };
258      ctx->vs =
259         util_make_vertex_passthrough_shader(pipe, 2, semantic_names,
260                                             semantic_indices);
261   }
262   if (ctx->has_stream_out) {
263      struct pipe_stream_output_info so;
264      const uint semantic_names[] = { TGSI_SEMANTIC_POSITION };
265      const uint semantic_indices[] = { 0 };
266
267      memset(&so, 0, sizeof(so));
268      so.num_outputs = 1;
269      so.output[0].register_mask = TGSI_WRITEMASK_XYZW;
270      so.stride = 4;
271
272      ctx->vs_pos_only =
273         util_make_vertex_passthrough_shader_with_so(pipe, 1, semantic_names,
274                                                     semantic_indices, &so);
275   }
276
277   /* set invariant vertex coordinates */
278   for (i = 0; i < 4; i++)
279      ctx->vertices[i][0][3] = 1; /*v.w*/
280
281   /* create the vertex buffer */
282   ctx->vbuf = pipe_user_buffer_create(ctx->base.pipe->screen,
283                                       ctx->vertices,
284                                       sizeof(ctx->vertices),
285                                       PIPE_BIND_VERTEX_BUFFER);
286
287   return &ctx->base;
288}
289
290void util_blitter_destroy(struct blitter_context *blitter)
291{
292   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
293   struct pipe_context *pipe = blitter->pipe;
294   int i;
295
296   pipe->delete_blend_state(pipe, ctx->blend_write_color);
297   pipe->delete_blend_state(pipe, ctx->blend_keep_color);
298   pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
299   pipe->delete_depth_stencil_alpha_state(pipe,
300                                          ctx->dsa_write_depth_keep_stencil);
301   pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil);
302   pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil);
303
304   pipe->delete_rasterizer_state(pipe, ctx->rs_state);
305   if (ctx->rs_discard_state)
306      pipe->delete_rasterizer_state(pipe, ctx->rs_discard_state);
307   pipe->delete_vs_state(pipe, ctx->vs);
308   if (ctx->vs_pos_only)
309      pipe->delete_vs_state(pipe, ctx->vs_pos_only);
310   pipe->delete_vertex_elements_state(pipe, ctx->velem_state);
311   if (ctx->vertex_has_integers) {
312      pipe->delete_vertex_elements_state(pipe, ctx->velem_sint_state);
313      pipe->delete_vertex_elements_state(pipe, ctx->velem_uint_state);
314   }
315   if (ctx->velem_state_readbuf)
316      pipe->delete_vertex_elements_state(pipe, ctx->velem_state_readbuf);
317
318   for (i = 0; i < PIPE_MAX_TEXTURE_TYPES; i++) {
319      if (ctx->fs_texfetch_col[i])
320         pipe->delete_fs_state(pipe, ctx->fs_texfetch_col[i]);
321      if (ctx->fs_texfetch_depth[i])
322         pipe->delete_fs_state(pipe, ctx->fs_texfetch_depth[i]);
323   }
324
325   for (i = 0; i <= PIPE_MAX_COLOR_BUFS; i++) {
326      if (ctx->fs_col[i])
327         pipe->delete_fs_state(pipe, ctx->fs_col[i]);
328      if (ctx->fs_col_int[i])
329         pipe->delete_fs_state(pipe, ctx->fs_col_int[i]);
330   }
331
332   pipe->delete_sampler_state(pipe, ctx->sampler_state);
333   pipe_resource_reference(&ctx->vbuf, NULL);
334   FREE(ctx);
335}
336
337static void blitter_set_running_flag(struct blitter_context_priv *ctx)
338{
339   if (ctx->base.running) {
340      _debug_printf("u_blitter:%i: Caught recursion. This is a driver bug.\n",
341                    __LINE__);
342   }
343   ctx->base.running = TRUE;
344}
345
346static void blitter_unset_running_flag(struct blitter_context_priv *ctx)
347{
348   if (!ctx->base.running) {
349      _debug_printf("u_blitter:%i: Caught recursion. This is a driver bug.\n",
350                    __LINE__);
351   }
352   ctx->base.running = FALSE;
353}
354
355static void blitter_check_saved_vertex_states(struct blitter_context_priv *ctx)
356{
357   assert(ctx->base.saved_num_vertex_buffers != ~0 &&
358          ctx->base.saved_velem_state != INVALID_PTR &&
359          ctx->base.saved_vs != INVALID_PTR &&
360          (!ctx->has_geometry_shader || ctx->base.saved_gs != INVALID_PTR) &&
361          (!ctx->has_stream_out || ctx->base.saved_num_so_targets != ~0) &&
362          ctx->base.saved_rs_state != INVALID_PTR);
363}
364
365static void blitter_restore_vertex_states(struct blitter_context_priv *ctx)
366{
367   struct pipe_context *pipe = ctx->base.pipe;
368   unsigned i;
369
370   /* Vertex buffers. */
371   pipe->set_vertex_buffers(pipe,
372                            ctx->base.saved_num_vertex_buffers,
373                            ctx->base.saved_vertex_buffers);
374
375   for (i = 0; i < ctx->base.saved_num_vertex_buffers; i++) {
376      if (ctx->base.saved_vertex_buffers[i].buffer) {
377         pipe_resource_reference(&ctx->base.saved_vertex_buffers[i].buffer,
378                                 NULL);
379      }
380   }
381   ctx->base.saved_num_vertex_buffers = ~0;
382
383   /* Vertex elements. */
384   pipe->bind_vertex_elements_state(pipe, ctx->base.saved_velem_state);
385   ctx->base.saved_velem_state = INVALID_PTR;
386
387   /* Vertex shader. */
388   pipe->bind_vs_state(pipe, ctx->base.saved_vs);
389   ctx->base.saved_vs = INVALID_PTR;
390
391   /* Geometry shader. */
392   if (ctx->has_geometry_shader) {
393      pipe->bind_gs_state(pipe, ctx->base.saved_gs);
394      ctx->base.saved_gs = INVALID_PTR;
395   }
396
397   /* Stream outputs. */
398   if (ctx->has_stream_out) {
399      pipe->set_stream_output_targets(pipe,
400                                      ctx->base.saved_num_so_targets,
401                                      ctx->base.saved_so_targets, ~0);
402
403      for (i = 0; i < ctx->base.saved_num_so_targets; i++)
404         pipe_so_target_reference(&ctx->base.saved_so_targets[i], NULL);
405
406      ctx->base.saved_num_so_targets = ~0;
407   }
408
409   /* Rasterizer. */
410   pipe->bind_rasterizer_state(pipe, ctx->base.saved_rs_state);
411   ctx->base.saved_rs_state = INVALID_PTR;
412}
413
414static void blitter_check_saved_fragment_states(struct blitter_context_priv *ctx)
415{
416   assert(ctx->base.saved_fs != INVALID_PTR &&
417          ctx->base.saved_dsa_state != INVALID_PTR &&
418          ctx->base.saved_blend_state != INVALID_PTR);
419}
420
421static void blitter_restore_fragment_states(struct blitter_context_priv *ctx)
422{
423   struct pipe_context *pipe = ctx->base.pipe;
424
425   /* Fragment shader. */
426   pipe->bind_fs_state(pipe, ctx->base.saved_fs);
427   ctx->base.saved_fs = INVALID_PTR;
428
429   /* Depth, stencil, alpha. */
430   pipe->bind_depth_stencil_alpha_state(pipe, ctx->base.saved_dsa_state);
431   ctx->base.saved_dsa_state = INVALID_PTR;
432
433   /* Blend state. */
434   pipe->bind_blend_state(pipe, ctx->base.saved_blend_state);
435   ctx->base.saved_blend_state = INVALID_PTR;
436
437   /* Miscellaneous states. */
438   /* XXX check whether these are saved and whether they need to be restored
439    * (depending on the operation) */
440   pipe->set_stencil_ref(pipe, &ctx->base.saved_stencil_ref);
441   pipe->set_viewport_state(pipe, &ctx->base.saved_viewport);
442   pipe->set_clip_state(pipe, &ctx->base.saved_clip);
443}
444
445static void blitter_check_saved_fb_state(struct blitter_context_priv *ctx)
446{
447   assert(ctx->base.saved_fb_state.nr_cbufs != ~0);
448}
449
450static void blitter_restore_fb_state(struct blitter_context_priv *ctx)
451{
452   struct pipe_context *pipe = ctx->base.pipe;
453
454   pipe->set_framebuffer_state(pipe, &ctx->base.saved_fb_state);
455   util_unreference_framebuffer_state(&ctx->base.saved_fb_state);
456}
457
458static void blitter_check_saved_textures(struct blitter_context_priv *ctx)
459{
460   assert(ctx->base.saved_num_sampler_states != ~0 &&
461          ctx->base.saved_num_sampler_views != ~0);
462}
463
464static void blitter_restore_textures(struct blitter_context_priv *ctx)
465{
466   struct pipe_context *pipe = ctx->base.pipe;
467   unsigned i;
468
469   /* Fragment sampler states. */
470   pipe->bind_fragment_sampler_states(pipe,
471                                      ctx->base.saved_num_sampler_states,
472                                      ctx->base.saved_sampler_states);
473   ctx->base.saved_num_sampler_states = ~0;
474
475   /* Fragment sampler views. */
476   pipe->set_fragment_sampler_views(pipe,
477                                    ctx->base.saved_num_sampler_views,
478                                    ctx->base.saved_sampler_views);
479
480   for (i = 0; i < ctx->base.saved_num_sampler_views; i++)
481      pipe_sampler_view_reference(&ctx->base.saved_sampler_views[i], NULL);
482
483   ctx->base.saved_num_sampler_views = ~0;
484}
485
486static void blitter_set_rectangle(struct blitter_context_priv *ctx,
487                                  unsigned x1, unsigned y1,
488                                  unsigned x2, unsigned y2,
489                                  float depth)
490{
491   int i;
492
493   /* set vertex positions */
494   ctx->vertices[0][0][0] = (float)x1 / ctx->dst_width * 2.0f - 1.0f; /*v0.x*/
495   ctx->vertices[0][0][1] = (float)y1 / ctx->dst_height * 2.0f - 1.0f; /*v0.y*/
496
497   ctx->vertices[1][0][0] = (float)x2 / ctx->dst_width * 2.0f - 1.0f; /*v1.x*/
498   ctx->vertices[1][0][1] = (float)y1 / ctx->dst_height * 2.0f - 1.0f; /*v1.y*/
499
500   ctx->vertices[2][0][0] = (float)x2 / ctx->dst_width * 2.0f - 1.0f; /*v2.x*/
501   ctx->vertices[2][0][1] = (float)y2 / ctx->dst_height * 2.0f - 1.0f; /*v2.y*/
502
503   ctx->vertices[3][0][0] = (float)x1 / ctx->dst_width * 2.0f - 1.0f; /*v3.x*/
504   ctx->vertices[3][0][1] = (float)y2 / ctx->dst_height * 2.0f - 1.0f; /*v3.y*/
505
506   for (i = 0; i < 4; i++)
507      ctx->vertices[i][0][2] = depth; /*z*/
508
509   /* viewport */
510   ctx->viewport.scale[0] = 0.5f * ctx->dst_width;
511   ctx->viewport.scale[1] = 0.5f * ctx->dst_height;
512   ctx->viewport.scale[2] = 1.0f;
513   ctx->viewport.scale[3] = 1.0f;
514   ctx->viewport.translate[0] = 0.5f * ctx->dst_width;
515   ctx->viewport.translate[1] = 0.5f * ctx->dst_height;
516   ctx->viewport.translate[2] = 0.0f;
517   ctx->viewport.translate[3] = 0.0f;
518   ctx->base.pipe->set_viewport_state(ctx->base.pipe, &ctx->viewport);
519
520   /* clip */
521   ctx->base.pipe->set_clip_state(ctx->base.pipe, &ctx->clip);
522}
523
524static void blitter_set_clear_color(struct blitter_context_priv *ctx,
525                                    const union pipe_color_union *color)
526{
527   int i;
528
529   if (color) {
530      for (i = 0; i < 4; i++) {
531         uint32_t *uiverts = (uint32_t *)ctx->vertices[i][1];
532         uiverts[0] = color->ui[0];
533         uiverts[1] = color->ui[1];
534         uiverts[2] = color->ui[2];
535         uiverts[3] = color->ui[3];
536      }
537   } else {
538      for (i = 0; i < 4; i++) {
539         ctx->vertices[i][1][0] = 0;
540         ctx->vertices[i][1][1] = 0;
541         ctx->vertices[i][1][2] = 0;
542         ctx->vertices[i][1][3] = 0;
543      }
544   }
545}
546
547static void get_texcoords(struct pipe_sampler_view *src,
548                          unsigned src_width0, unsigned src_height0,
549                          unsigned x1, unsigned y1,
550                          unsigned x2, unsigned y2,
551                          float out[4])
552{
553   struct pipe_resource *tex = src->texture;
554   unsigned level = src->u.tex.first_level;
555   boolean normalized = tex->target != PIPE_TEXTURE_RECT;
556
557   if (normalized) {
558      out[0] = x1 / (float)u_minify(src_width0,  level);
559      out[1] = y1 / (float)u_minify(src_height0, level);
560      out[2] = x2 / (float)u_minify(src_width0,  level);
561      out[3] = y2 / (float)u_minify(src_height0, level);
562   } else {
563      out[0] = x1;
564      out[1] = y1;
565      out[2] = x2;
566      out[3] = y2;
567   }
568}
569
570static void set_texcoords_in_vertices(const float coord[4],
571                                      float *out, unsigned stride)
572{
573   out[0] = coord[0]; /*t0.s*/
574   out[1] = coord[1]; /*t0.t*/
575   out += stride;
576   out[0] = coord[2]; /*t1.s*/
577   out[1] = coord[1]; /*t1.t*/
578   out += stride;
579   out[0] = coord[2]; /*t2.s*/
580   out[1] = coord[3]; /*t2.t*/
581   out += stride;
582   out[0] = coord[0]; /*t3.s*/
583   out[1] = coord[3]; /*t3.t*/
584}
585
586static void blitter_set_texcoords(struct blitter_context_priv *ctx,
587                                  struct pipe_sampler_view *src,
588                                  unsigned src_width0, unsigned src_height0,
589                                  unsigned layer,
590                                  unsigned x1, unsigned y1,
591                                  unsigned x2, unsigned y2)
592{
593   unsigned i;
594   float coord[4];
595   float face_coord[4][2];
596
597   get_texcoords(src, src_width0, src_height0, x1, y1, x2, y2, coord);
598
599   if (src->texture->target == PIPE_TEXTURE_CUBE) {
600      set_texcoords_in_vertices(coord, &face_coord[0][0], 2);
601      util_map_texcoords2d_onto_cubemap(layer,
602                                        /* pointer, stride in floats */
603                                        &face_coord[0][0], 2,
604                                        &ctx->vertices[0][1][0], 8);
605   } else {
606      set_texcoords_in_vertices(coord, &ctx->vertices[0][1][0], 8);
607   }
608
609   /* Set the layer. */
610   switch (src->texture->target) {
611   case PIPE_TEXTURE_3D:
612      {
613         float r = layer / (float)u_minify(src->texture->depth0,
614                                           src->u.tex.first_level);
615         for (i = 0; i < 4; i++)
616            ctx->vertices[i][1][2] = r; /*r*/
617      }
618      break;
619
620   case PIPE_TEXTURE_1D_ARRAY:
621      for (i = 0; i < 4; i++)
622         ctx->vertices[i][1][1] = layer; /*t*/
623      break;
624
625   case PIPE_TEXTURE_2D_ARRAY:
626      for (i = 0; i < 4; i++)
627         ctx->vertices[i][1][2] = layer; /*r*/
628      break;
629
630   default:;
631   }
632}
633
634static void blitter_set_dst_dimensions(struct blitter_context_priv *ctx,
635                                       unsigned width, unsigned height)
636{
637   ctx->dst_width = width;
638   ctx->dst_height = height;
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_sampler_view viewTempl, *view;
867   unsigned bind;
868   boolean is_stencil, is_depth;
869
870   /* Give up if textures are not set. */
871   assert(dst && src);
872   if (!dst || !src)
873      return;
874
875   assert(src->target < PIPE_MAX_TEXTURE_TYPES);
876
877   /* Is this a ZS format? */
878   is_depth = util_format_get_component_bits(src->format, UTIL_FORMAT_COLORSPACE_ZS, 0) != 0;
879   is_stencil = util_format_get_component_bits(src->format, UTIL_FORMAT_COLORSPACE_ZS, 1) != 0;
880
881   if (is_depth || is_stencil)
882      bind = PIPE_BIND_DEPTH_STENCIL;
883   else
884      bind = PIPE_BIND_RENDER_TARGET;
885
886   /* Check if we can sample from and render to the surfaces. */
887   /* (assuming copying a stencil buffer is not possible) */
888   if ((!ignore_stencil && is_stencil) ||
889       !screen->is_format_supported(screen, dst->format, dst->target,
890                                    dst->nr_samples, bind) ||
891       !screen->is_format_supported(screen, src->format, src->target,
892                                    src->nr_samples, PIPE_BIND_SAMPLER_VIEW)) {
893      blitter_set_running_flag(ctx);
894      util_resource_copy_region(pipe, dst, dstlevel, dstx, dsty, dstz,
895                                src, srclevel, srcbox);
896      blitter_unset_running_flag(ctx);
897      return;
898   }
899
900   /* Initialize the surface. */
901   memset(&surf_templ, 0, sizeof(surf_templ));
902   u_surface_default_template(&surf_templ, dst, bind);
903   surf_templ.format = util_format_linear(dst->format);
904   surf_templ.u.tex.level = dstlevel;
905   surf_templ.u.tex.first_layer = dstz;
906   surf_templ.u.tex.last_layer = dstz + srcbox->depth - 1;
907   dstsurf = pipe->create_surface(pipe, dst, &surf_templ);
908
909   /* Initialize the sampler view. */
910   u_sampler_view_default_template(&viewTempl, src,
911                                   util_format_linear(src->format));
912   viewTempl.u.tex.first_level = srclevel;
913   viewTempl.u.tex.last_level = srclevel;
914   view = pipe->create_sampler_view(pipe, src, &viewTempl);
915
916   /* Copy. */
917   util_blitter_copy_texture_view(blitter, dstsurf, dstx, dsty, view, srcbox,
918                                  src->width0, src->height0);
919
920   pipe_surface_reference(&dstsurf, NULL);
921   pipe_sampler_view_reference(&view, NULL);
922}
923
924void util_blitter_copy_texture_view(struct blitter_context *blitter,
925                                    struct pipe_surface *dst,
926                                    unsigned dstx, unsigned dsty,
927                                    struct pipe_sampler_view *src,
928                                    const struct pipe_box *srcbox,
929                                    unsigned src_width0, unsigned src_height0)
930{
931   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
932   struct pipe_context *pipe = ctx->base.pipe;
933   struct pipe_framebuffer_state fb_state;
934   enum pipe_texture_target src_target = src->texture->target;
935   unsigned width = srcbox->width;
936   unsigned height = srcbox->height;
937
938   /* Sanity checks. */
939   if (dst->texture == src->texture &&
940       dst->u.tex.level == src->u.tex.first_level) {
941      assert(!is_overlap(srcbox->x, srcbox->x + width, srcbox->y, srcbox->y + height,
942                         dstx, dstx + width, dsty, dsty + height));
943   }
944   /* XXX should handle 3d regions */
945   assert(srcbox->depth == 1);
946
947   /* Check whether the states are properly saved. */
948   blitter_set_running_flag(ctx);
949   blitter_check_saved_vertex_states(ctx);
950   blitter_check_saved_fragment_states(ctx);
951   blitter_check_saved_textures(ctx);
952   blitter_check_saved_fb_state(ctx);
953
954   /* Initialize framebuffer state. */
955   fb_state.width = dst->width;
956   fb_state.height = dst->height;
957
958   if (util_format_is_depth_or_stencil(dst->format)) {
959      pipe->bind_blend_state(pipe, ctx->blend_keep_color);
960      pipe->bind_depth_stencil_alpha_state(pipe,
961                                           ctx->dsa_write_depth_keep_stencil);
962      pipe->bind_fs_state(pipe,
963            blitter_get_fs_texfetch_depth(ctx, src_target));
964
965      fb_state.nr_cbufs = 0;
966      fb_state.zsbuf = dst;
967   } else {
968      pipe->bind_blend_state(pipe, ctx->blend_write_color);
969      pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
970      pipe->bind_fs_state(pipe,
971            blitter_get_fs_texfetch_col(ctx, src_target));
972
973      fb_state.nr_cbufs = 1;
974      fb_state.cbufs[0] = dst;
975      fb_state.zsbuf = 0;
976   }
977
978   /* Set rasterizer state, shaders, and textures. */
979   pipe->bind_rasterizer_state(pipe, ctx->rs_state);
980   pipe->bind_vs_state(pipe, ctx->vs);
981   if (ctx->has_geometry_shader)
982      pipe->bind_gs_state(pipe, NULL);
983   pipe->bind_fragment_sampler_states(pipe, 1, &ctx->sampler_state);
984   pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
985   pipe->set_fragment_sampler_views(pipe, 1, &src);
986   pipe->set_framebuffer_state(pipe, &fb_state);
987
988   blitter_set_dst_dimensions(ctx, dst->width, dst->height);
989
990   switch (src_target) {
991      /* Draw the quad with the draw_rectangle callback. */
992      case PIPE_TEXTURE_1D:
993      case PIPE_TEXTURE_2D:
994      case PIPE_TEXTURE_RECT:
995         {
996            /* Set texture coordinates. - use a pipe color union
997             * for interface purposes.
998             * XXX pipe_color_union is a wrong name since we use that to set
999             * texture coordinates too.
1000             */
1001            union pipe_color_union coord;
1002            get_texcoords(src, src_width0, src_height0, srcbox->x, srcbox->y,
1003                          srcbox->x+width, srcbox->y+height, coord.f);
1004
1005            /* Draw. */
1006            blitter->draw_rectangle(blitter, dstx, dsty, dstx+width, dsty+height, 0,
1007                                    UTIL_BLITTER_ATTRIB_TEXCOORD, &coord);
1008         }
1009         break;
1010
1011      /* Draw the quad with the generic codepath. */
1012      default:
1013         /* Set texture coordinates. */
1014         switch (src_target) {
1015         case PIPE_TEXTURE_1D_ARRAY:
1016         case PIPE_TEXTURE_2D_ARRAY:
1017         case PIPE_TEXTURE_3D:
1018         case PIPE_TEXTURE_CUBE:
1019            blitter_set_texcoords(ctx, src, src_width0, src_height0, srcbox->z,
1020                                  srcbox->y, srcbox->x,
1021                                  srcbox->x + width, srcbox->y + height);
1022            break;
1023
1024         default:
1025            assert(0);
1026         }
1027
1028         /* Draw. */
1029         blitter_set_rectangle(ctx, dstx, dsty, dstx+width, dsty+height, 0);
1030         ctx->base.pipe->redefine_user_buffer(ctx->base.pipe, ctx->vbuf,
1031                                              0, ctx->vbuf->width0);
1032         util_draw_vertex_buffer(ctx->base.pipe, NULL, ctx->vbuf, 0,
1033                                 PIPE_PRIM_TRIANGLE_FAN, 4, 2);
1034         break;
1035   }
1036
1037   blitter_restore_vertex_states(ctx);
1038   blitter_restore_fragment_states(ctx);
1039   blitter_restore_textures(ctx);
1040   blitter_restore_fb_state(ctx);
1041   blitter_unset_running_flag(ctx);
1042}
1043
1044/* Clear a region of a color surface to a constant value. */
1045void util_blitter_clear_render_target(struct blitter_context *blitter,
1046                                      struct pipe_surface *dstsurf,
1047                                      const union pipe_color_union *color,
1048                                      unsigned dstx, unsigned dsty,
1049                                      unsigned width, unsigned height)
1050{
1051   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
1052   struct pipe_context *pipe = ctx->base.pipe;
1053   struct pipe_framebuffer_state fb_state;
1054
1055   assert(dstsurf->texture);
1056   if (!dstsurf->texture)
1057      return;
1058
1059   /* check the saved state */
1060   blitter_set_running_flag(ctx);
1061   blitter_check_saved_vertex_states(ctx);
1062   blitter_check_saved_fragment_states(ctx);
1063   blitter_check_saved_fb_state(ctx);
1064
1065   /* bind states */
1066   pipe->bind_blend_state(pipe, ctx->blend_write_color);
1067   pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
1068   pipe->bind_rasterizer_state(pipe, ctx->rs_state);
1069   pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 1, FALSE));
1070   pipe->bind_vs_state(pipe, ctx->vs);
1071   if (ctx->has_geometry_shader)
1072      pipe->bind_gs_state(pipe, NULL);
1073   pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
1074
1075   /* set a framebuffer state */
1076   fb_state.width = dstsurf->width;
1077   fb_state.height = dstsurf->height;
1078   fb_state.nr_cbufs = 1;
1079   fb_state.cbufs[0] = dstsurf;
1080   fb_state.zsbuf = 0;
1081   pipe->set_framebuffer_state(pipe, &fb_state);
1082
1083   blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height);
1084   blitter->draw_rectangle(blitter, dstx, dsty, dstx+width, dsty+height, 0,
1085                           UTIL_BLITTER_ATTRIB_COLOR, color);
1086
1087   blitter_restore_vertex_states(ctx);
1088   blitter_restore_fragment_states(ctx);
1089   blitter_restore_fb_state(ctx);
1090   blitter_unset_running_flag(ctx);
1091}
1092
1093/* Clear a region of a depth stencil surface. */
1094void util_blitter_clear_depth_stencil(struct blitter_context *blitter,
1095                                      struct pipe_surface *dstsurf,
1096                                      unsigned clear_flags,
1097                                      double depth,
1098                                      unsigned stencil,
1099                                      unsigned dstx, unsigned dsty,
1100                                      unsigned width, unsigned height)
1101{
1102   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
1103   struct pipe_context *pipe = ctx->base.pipe;
1104   struct pipe_framebuffer_state fb_state;
1105   struct pipe_stencil_ref sr = { { 0 } };
1106
1107   assert(dstsurf->texture);
1108   if (!dstsurf->texture)
1109      return;
1110
1111   /* check the saved state */
1112   blitter_set_running_flag(ctx);
1113   blitter_check_saved_vertex_states(ctx);
1114   blitter_check_saved_fragment_states(ctx);
1115   blitter_check_saved_fb_state(ctx);
1116
1117   /* bind states */
1118   pipe->bind_blend_state(pipe, ctx->blend_keep_color);
1119   if ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) == PIPE_CLEAR_DEPTHSTENCIL) {
1120      sr.ref_value[0] = stencil & 0xff;
1121      pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil);
1122      pipe->set_stencil_ref(pipe, &sr);
1123   }
1124   else if (clear_flags & PIPE_CLEAR_DEPTH) {
1125      pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_keep_stencil);
1126   }
1127   else if (clear_flags & PIPE_CLEAR_STENCIL) {
1128      sr.ref_value[0] = stencil & 0xff;
1129      pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil);
1130      pipe->set_stencil_ref(pipe, &sr);
1131   }
1132   else
1133      /* hmm that should be illegal probably, or make it a no-op somewhere */
1134      pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
1135
1136   pipe->bind_rasterizer_state(pipe, ctx->rs_state);
1137   pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 0, FALSE));
1138   pipe->bind_vs_state(pipe, ctx->vs);
1139   if (ctx->has_geometry_shader)
1140      pipe->bind_gs_state(pipe, NULL);
1141   pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
1142
1143   /* set a framebuffer state */
1144   fb_state.width = dstsurf->width;
1145   fb_state.height = dstsurf->height;
1146   fb_state.nr_cbufs = 0;
1147   fb_state.cbufs[0] = 0;
1148   fb_state.zsbuf = dstsurf;
1149   pipe->set_framebuffer_state(pipe, &fb_state);
1150
1151   blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height);
1152   blitter->draw_rectangle(blitter, dstx, dsty, dstx+width, dsty+height, depth,
1153                           UTIL_BLITTER_ATTRIB_NONE, NULL);
1154
1155   blitter_restore_vertex_states(ctx);
1156   blitter_restore_fragment_states(ctx);
1157   blitter_restore_fb_state(ctx);
1158   blitter_unset_running_flag(ctx);
1159}
1160
1161/* draw a rectangle across a region using a custom dsa stage - for r600g */
1162void util_blitter_custom_depth_stencil(struct blitter_context *blitter,
1163				       struct pipe_surface *zsurf,
1164				       struct pipe_surface *cbsurf,
1165				       void *dsa_stage, float depth)
1166{
1167   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
1168   struct pipe_context *pipe = ctx->base.pipe;
1169   struct pipe_framebuffer_state fb_state;
1170
1171   assert(zsurf->texture);
1172   if (!zsurf->texture)
1173      return;
1174
1175   /* check the saved state */
1176   blitter_set_running_flag(ctx);
1177   blitter_check_saved_vertex_states(ctx);
1178   blitter_check_saved_fragment_states(ctx);
1179   blitter_check_saved_fb_state(ctx);
1180
1181   /* bind states */
1182   pipe->bind_blend_state(pipe, ctx->blend_write_color);
1183   pipe->bind_depth_stencil_alpha_state(pipe, dsa_stage);
1184
1185   pipe->bind_rasterizer_state(pipe, ctx->rs_state);
1186   pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 0, FALSE));
1187   pipe->bind_vs_state(pipe, ctx->vs);
1188   if (ctx->has_geometry_shader)
1189      pipe->bind_gs_state(pipe, NULL);
1190   pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
1191
1192   /* set a framebuffer state */
1193   fb_state.width = zsurf->width;
1194   fb_state.height = zsurf->height;
1195   fb_state.nr_cbufs = 1;
1196   if (cbsurf) {
1197	   fb_state.cbufs[0] = cbsurf;
1198	   fb_state.nr_cbufs = 1;
1199   } else {
1200	   fb_state.cbufs[0] = NULL;
1201	   fb_state.nr_cbufs = 0;
1202   }
1203   fb_state.zsbuf = zsurf;
1204   pipe->set_framebuffer_state(pipe, &fb_state);
1205
1206   blitter_set_dst_dimensions(ctx, zsurf->width, zsurf->height);
1207   blitter->draw_rectangle(blitter, 0, 0, zsurf->width, zsurf->height, depth,
1208                           UTIL_BLITTER_ATTRIB_NONE, NULL);
1209
1210   blitter_restore_vertex_states(ctx);
1211   blitter_restore_fragment_states(ctx);
1212   blitter_restore_fb_state(ctx);
1213   blitter_unset_running_flag(ctx);
1214}
1215
1216void util_blitter_copy_buffer(struct blitter_context *blitter,
1217                              struct pipe_resource *dst,
1218                              unsigned dstx,
1219                              struct pipe_resource *src,
1220                              unsigned srcx,
1221                              unsigned size)
1222{
1223   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
1224   struct pipe_context *pipe = ctx->base.pipe;
1225   struct pipe_vertex_buffer vb;
1226   struct pipe_stream_output_target *so_target;
1227
1228   /* Drivers not capable of Stream Out should not call this function
1229    * in the first place. */
1230   assert(ctx->has_stream_out);
1231
1232   /* Some alignment is required. */
1233   if (srcx % 4 != 0 || dstx % 4 != 0 || size % 16 != 0 ||
1234       !ctx->has_stream_out) {
1235      struct pipe_box box;
1236      u_box_1d(srcx, size, &box);
1237      util_resource_copy_region(pipe, dst, 0, dstx, 0, 0, src, 0, &box);
1238      return;
1239   }
1240
1241   blitter_set_running_flag(ctx);
1242   blitter_check_saved_vertex_states(ctx);
1243
1244   vb.buffer = src;
1245   vb.buffer_offset = srcx;
1246   vb.stride = 4;
1247
1248   pipe->set_vertex_buffers(pipe, 1, &vb);
1249   pipe->bind_vertex_elements_state(pipe, ctx->velem_state_readbuf);
1250   pipe->bind_vs_state(pipe, ctx->vs_pos_only);
1251   if (ctx->has_geometry_shader)
1252      pipe->bind_gs_state(pipe, NULL);
1253   pipe->bind_rasterizer_state(pipe, ctx->rs_discard_state);
1254
1255   so_target = pipe->create_stream_output_target(pipe, dst, dstx, size);
1256   pipe->set_stream_output_targets(pipe, 1, &so_target, 0);
1257
1258   util_draw_arrays(pipe, PIPE_PRIM_POINTS, 0, size / 16);
1259
1260   blitter_restore_vertex_states(ctx);
1261   blitter_unset_running_flag(ctx);
1262   pipe_so_target_reference(&so_target, NULL);
1263}
1264