u_blitter.c revision 89ce12a2d20b6662abb7240c1becba11d53b215a
180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/**************************************************************************
280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2009 Marek Olšák <maraeo@gmail.com>
480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Permission is hereby granted, free of charge, to any person obtaining a
680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * copy of this software and associated documentation files (the
780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * "Software"), to deal in the Software without restriction, including
880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * without limitation the rights to use, copy, modify, merge, publish,
980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * distribute, sub license, and/or sell copies of the Software, and to
1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * permit persons to whom the Software is furnished to do so, subject to
1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * the following conditions:
1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * The above copyright notice and this permission notice (including the
1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * next paragraph) shall be included in all copies or substantial portions
1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * of the Software.
1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru **************************************************************************/
2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
2780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/**
2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * @file
2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Blitter utility to facilitate acceleration of the clear, clear_render_target,
3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * clear_depth_stencil, and resource_copy_region functions.
3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *
3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * @author Marek Olšák
3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */
3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "pipe/p_context.h"
3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "pipe/p_defines.h"
3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "util/u_inlines.h"
3880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "pipe/p_shader_tokens.h"
3980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "pipe/p_state.h"
4080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
4180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "util/u_format.h"
4280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "util/u_memory.h"
4380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "util/u_math.h"
4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "util/u_blitter.h"
4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "util/u_draw_quad.h"
4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "util/u_sampler.h"
4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "util/u_simple_shaders.h"
4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "util/u_surface.h"
4980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "util/u_texture.h"
5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define INVALID_PTR ((void*)~0)
5280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustruct blitter_context_priv
5480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
5580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   struct blitter_context base;
5680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   struct pipe_resource *vbuf;  /**< quad */
5880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
5980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   float vertices[4][2][4];   /**< {pos, color} or {pos, texcoord} */
6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   /* Templates for various state objects. */
6280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   /* Constant state objects. */
6480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   /* Vertex shaders. */
6580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   void *vs; /**< Vertex shader which passes {pos, generic} to the output.*/
6680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
6780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   /* Fragment shaders. */
6880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   /* The shader at index i outputs color to color buffers 0,1,...,i-1. */
6980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   void *fs_col[PIPE_MAX_COLOR_BUFS+1];
7080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   void *fs_col_int[PIPE_MAX_COLOR_BUFS+1];
7180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   /* FS which outputs a color from a texture,
7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru      where the index is PIPE_TEXTURE_* to be sampled. */
7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   void *fs_texfetch_col[PIPE_MAX_TEXTURE_TYPES];
7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   /* FS which outputs a depth from a texture,
7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru      where the index is PIPE_TEXTURE_* to be sampled. */
7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   void *fs_texfetch_depth[PIPE_MAX_TEXTURE_TYPES];
7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   /* Blend state. */
8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   void *blend_write_color;   /**< blend state with writemask of RGBA */
8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   void *blend_keep_color;    /**< blend state with writemask of 0 */
8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   /* Depth stencil alpha state. */
8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   void *dsa_write_depth_stencil;
8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   void *dsa_write_depth_keep_stencil;
8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   void *dsa_keep_depth_stencil;
8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   void *dsa_keep_depth_write_stencil;
8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   void *velem_state;
9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   void *velem_uint_state;
9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   void *velem_sint_state;
9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   /* Sampler state. */
9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   void *sampler_state;
9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   /* Rasterizer state. */
9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   void *rs_state;
9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   /* Viewport state. */
10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   struct pipe_viewport_state viewport;
10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   /* Clip state. */
10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   struct pipe_clip_state clip;
10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   /* Destination surface dimensions. */
10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   unsigned dst_width;
10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   unsigned dst_height;
10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   boolean has_geometry_shader;
11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   boolean vertex_has_integers;
11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru};
11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustatic void blitter_draw_rectangle(struct blitter_context *blitter,
11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                   unsigned x, unsigned y,
11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                   unsigned width, unsigned height,
11780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                   float depth,
11880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                   enum blitter_attrib_type type,
11980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                   const union pipe_color_union *attrib);
12080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
12180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
12280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querustruct blitter_context *util_blitter_create(struct pipe_context *pipe)
12380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru{
12480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   struct blitter_context_priv *ctx;
12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   struct pipe_blend_state blend;
12680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   struct pipe_depth_stencil_alpha_state dsa;
12780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   struct pipe_rasterizer_state rs_state;
12880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   struct pipe_sampler_state sampler_state;
12980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   struct pipe_vertex_element velem[2];
13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   unsigned i;
13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   ctx = CALLOC_STRUCT(blitter_context_priv);
13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   if (!ctx)
13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru      return NULL;
13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   ctx->base.pipe = pipe;
13780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   ctx->base.draw_rectangle = blitter_draw_rectangle;
13880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   /* init state objects for them to be considered invalid */
14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   ctx->base.saved_blend_state = INVALID_PTR;
14180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   ctx->base.saved_dsa_state = INVALID_PTR;
14280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   ctx->base.saved_rs_state = INVALID_PTR;
14380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   ctx->base.saved_fs = INVALID_PTR;
14480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   ctx->base.saved_vs = INVALID_PTR;
14580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   ctx->base.saved_gs = INVALID_PTR;
14680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   ctx->base.saved_velem_state = INVALID_PTR;
14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   ctx->base.saved_fb_state.nr_cbufs = ~0;
14880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   ctx->base.saved_num_sampler_views = ~0;
14980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   ctx->base.saved_num_sampler_states = ~0;
15080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   ctx->base.saved_num_vertex_buffers = ~0;
15180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   ctx->has_geometry_shader =
15380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru      pipe->screen->get_shader_param(pipe->screen, PIPE_SHADER_GEOMETRY,
15480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                     PIPE_SHADER_CAP_MAX_INSTRUCTIONS) > 0;
15580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   ctx->vertex_has_integers =
15680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru      pipe->screen->get_shader_param(pipe->screen, PIPE_SHADER_VERTEX,
15780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru                                     PIPE_SHADER_CAP_INTEGERS);
15880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
15980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   /* blend state objects */
16080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   memset(&blend, 0, sizeof(blend));
16180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   ctx->blend_keep_color = pipe->create_blend_state(pipe, &blend);
16280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
16380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   blend.rt[0].colormask = PIPE_MASK_RGBA;
16480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   ctx->blend_write_color = pipe->create_blend_state(pipe, &blend);
16580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
16680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   /* depth stencil alpha state objects */
16780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   memset(&dsa, 0, sizeof(dsa));
16880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   ctx->dsa_keep_depth_stencil =
16980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru      pipe->create_depth_stencil_alpha_state(pipe, &dsa);
17080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru
17180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   dsa.depth.enabled = 1;
17280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   dsa.depth.writemask = 1;
17380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru   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 src_width0, unsigned src_height0,
497                          unsigned x1, unsigned y1,
498                          unsigned x2, unsigned y2,
499                          float out[4])
500{
501   struct pipe_resource *tex = src->texture;
502   unsigned level = src->u.tex.first_level;
503   boolean normalized = tex->target != PIPE_TEXTURE_RECT;
504
505   if (normalized) {
506      out[0] = x1 / (float)u_minify(src_width0,  level);
507      out[1] = y1 / (float)u_minify(src_height0, level);
508      out[2] = x2 / (float)u_minify(src_width0,  level);
509      out[3] = y2 / (float)u_minify(src_height0, level);
510   } else {
511      out[0] = x1;
512      out[1] = y1;
513      out[2] = x2;
514      out[3] = y2;
515   }
516}
517
518static void set_texcoords_in_vertices(const float coord[4],
519                                      float *out, unsigned stride)
520{
521   out[0] = coord[0]; /*t0.s*/
522   out[1] = coord[1]; /*t0.t*/
523   out += stride;
524   out[0] = coord[2]; /*t1.s*/
525   out[1] = coord[1]; /*t1.t*/
526   out += stride;
527   out[0] = coord[2]; /*t2.s*/
528   out[1] = coord[3]; /*t2.t*/
529   out += stride;
530   out[0] = coord[0]; /*t3.s*/
531   out[1] = coord[3]; /*t3.t*/
532}
533
534static void blitter_set_texcoords(struct blitter_context_priv *ctx,
535                                  struct pipe_sampler_view *src,
536                                  unsigned src_width0, unsigned src_height0,
537                                  unsigned layer,
538                                  unsigned x1, unsigned y1,
539                                  unsigned x2, unsigned y2)
540{
541   unsigned i;
542   float coord[4];
543   float face_coord[4][2];
544
545   get_texcoords(src, src_width0, src_height0, x1, y1, x2, y2, coord);
546
547   if (src->texture->target == PIPE_TEXTURE_CUBE) {
548      set_texcoords_in_vertices(coord, &face_coord[0][0], 2);
549      util_map_texcoords2d_onto_cubemap(layer,
550                                        /* pointer, stride in floats */
551                                        &face_coord[0][0], 2,
552                                        &ctx->vertices[0][1][0], 8);
553   } else {
554      set_texcoords_in_vertices(coord, &ctx->vertices[0][1][0], 8);
555   }
556
557   /* Set the layer. */
558   switch (src->texture->target) {
559   case PIPE_TEXTURE_3D:
560      {
561         float r = layer / (float)u_minify(src->texture->depth0,
562                                           src->u.tex.first_level);
563         for (i = 0; i < 4; i++)
564            ctx->vertices[i][1][2] = r; /*r*/
565      }
566      break;
567
568   case PIPE_TEXTURE_1D_ARRAY:
569      for (i = 0; i < 4; i++)
570         ctx->vertices[i][1][1] = layer; /*t*/
571      break;
572
573   case PIPE_TEXTURE_2D_ARRAY:
574      for (i = 0; i < 4; i++)
575         ctx->vertices[i][1][2] = layer; /*r*/
576      break;
577
578   default:;
579   }
580}
581
582static void blitter_set_dst_dimensions(struct blitter_context_priv *ctx,
583                                       unsigned width, unsigned height)
584{
585   ctx->dst_width = width;
586   ctx->dst_height = height;
587}
588
589static INLINE
590void *blitter_get_fs_col(struct blitter_context_priv *ctx, unsigned num_cbufs,
591                         boolean int_format)
592{
593   struct pipe_context *pipe = ctx->base.pipe;
594
595   assert(num_cbufs <= PIPE_MAX_COLOR_BUFS);
596
597   if (int_format) {
598      if (!ctx->fs_col_int[num_cbufs])
599         ctx->fs_col_int[num_cbufs] =
600            util_make_fragment_cloneinput_shader(pipe, num_cbufs,
601                                                 TGSI_SEMANTIC_GENERIC,
602                                                 TGSI_INTERPOLATE_CONSTANT);
603      return ctx->fs_col_int[num_cbufs];
604   } else {
605      if (!ctx->fs_col[num_cbufs])
606         ctx->fs_col[num_cbufs] =
607            util_make_fragment_cloneinput_shader(pipe, num_cbufs,
608                                                 TGSI_SEMANTIC_GENERIC,
609                                                 TGSI_INTERPOLATE_LINEAR);
610      return ctx->fs_col[num_cbufs];
611   }
612}
613
614/** Convert PIPE_TEXTURE_x to TGSI_TEXTURE_x */
615static unsigned
616pipe_tex_to_tgsi_tex(enum pipe_texture_target pipe_tex_target)
617{
618   switch (pipe_tex_target) {
619   case PIPE_TEXTURE_1D:
620      return TGSI_TEXTURE_1D;
621   case PIPE_TEXTURE_2D:
622      return TGSI_TEXTURE_2D;
623   case PIPE_TEXTURE_RECT:
624      return TGSI_TEXTURE_RECT;
625   case PIPE_TEXTURE_3D:
626      return TGSI_TEXTURE_3D;
627   case PIPE_TEXTURE_CUBE:
628      return TGSI_TEXTURE_CUBE;
629   case PIPE_TEXTURE_1D_ARRAY:
630      return TGSI_TEXTURE_1D_ARRAY;
631   case PIPE_TEXTURE_2D_ARRAY:
632      return TGSI_TEXTURE_2D_ARRAY;
633   default:
634      assert(0 && "unexpected texture target");
635      return TGSI_TEXTURE_UNKNOWN;
636   }
637}
638
639
640static INLINE
641void *blitter_get_fs_texfetch_col(struct blitter_context_priv *ctx,
642                                  unsigned tex_target)
643{
644   struct pipe_context *pipe = ctx->base.pipe;
645
646   assert(tex_target < PIPE_MAX_TEXTURE_TYPES);
647
648   /* Create the fragment shader on-demand. */
649   if (!ctx->fs_texfetch_col[tex_target]) {
650      unsigned tgsi_tex = pipe_tex_to_tgsi_tex(tex_target);
651
652      ctx->fs_texfetch_col[tex_target] =
653        util_make_fragment_tex_shader(pipe, tgsi_tex, TGSI_INTERPOLATE_LINEAR);
654   }
655
656   return ctx->fs_texfetch_col[tex_target];
657}
658
659static INLINE
660void *blitter_get_fs_texfetch_depth(struct blitter_context_priv *ctx,
661                                    unsigned tex_target)
662{
663   struct pipe_context *pipe = ctx->base.pipe;
664
665   assert(tex_target < PIPE_MAX_TEXTURE_TYPES);
666
667   /* Create the fragment shader on-demand. */
668   if (!ctx->fs_texfetch_depth[tex_target]) {
669      unsigned tgsi_tex = pipe_tex_to_tgsi_tex(tex_target);
670
671      ctx->fs_texfetch_depth[tex_target] =
672         util_make_fragment_tex_shader_writedepth(pipe, tgsi_tex,
673                                                  TGSI_INTERPOLATE_LINEAR);
674   }
675
676   return ctx->fs_texfetch_depth[tex_target];
677}
678
679static void blitter_draw_rectangle(struct blitter_context *blitter,
680                                   unsigned x1, unsigned y1,
681                                   unsigned x2, unsigned y2,
682                                   float depth,
683                                   enum blitter_attrib_type type,
684                                   const union pipe_color_union *attrib)
685{
686   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
687
688   switch (type) {
689      case UTIL_BLITTER_ATTRIB_COLOR:
690         blitter_set_clear_color(ctx, attrib);
691         break;
692
693      case UTIL_BLITTER_ATTRIB_TEXCOORD:
694         set_texcoords_in_vertices(attrib->f, &ctx->vertices[0][1][0], 8);
695         break;
696
697      default:;
698   }
699
700   blitter_set_rectangle(ctx, x1, y1, x2, y2, depth);
701   ctx->base.pipe->redefine_user_buffer(ctx->base.pipe, ctx->vbuf,
702                                        0, ctx->vbuf->width0);
703   util_draw_vertex_buffer(ctx->base.pipe, NULL, ctx->vbuf, 0,
704                           PIPE_PRIM_TRIANGLE_FAN, 4, 2);
705}
706
707static void util_blitter_clear_custom(struct blitter_context *blitter,
708                                      unsigned width, unsigned height,
709                                      unsigned num_cbufs,
710                                      unsigned clear_buffers,
711                                      enum pipe_format cbuf_format,
712                                      const union pipe_color_union *color,
713                                      double depth, unsigned stencil,
714                                      void *custom_blend, void *custom_dsa)
715{
716   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
717   struct pipe_context *pipe = ctx->base.pipe;
718   struct pipe_stencil_ref sr = { { 0 } };
719   boolean int_format = util_format_is_pure_integer(cbuf_format);
720   assert(num_cbufs <= PIPE_MAX_COLOR_BUFS);
721
722   blitter_set_running_flag(ctx);
723   blitter_check_saved_vertex_states(ctx);
724   blitter_check_saved_fragment_states(ctx);
725
726   /* bind states */
727   if (custom_blend) {
728      pipe->bind_blend_state(pipe, custom_blend);
729   } else if (clear_buffers & PIPE_CLEAR_COLOR) {
730      pipe->bind_blend_state(pipe, ctx->blend_write_color);
731   } else {
732      pipe->bind_blend_state(pipe, ctx->blend_keep_color);
733   }
734
735   if (custom_dsa) {
736      pipe->bind_depth_stencil_alpha_state(pipe, custom_dsa);
737   } else if ((clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) == PIPE_CLEAR_DEPTHSTENCIL) {
738      pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil);
739   } else if (clear_buffers & PIPE_CLEAR_DEPTH) {
740      pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_keep_stencil);
741   } else if (clear_buffers & PIPE_CLEAR_STENCIL) {
742      pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil);
743   } else {
744      pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
745   }
746
747   sr.ref_value[0] = stencil & 0xff;
748   pipe->set_stencil_ref(pipe, &sr);
749
750   pipe->bind_rasterizer_state(pipe, ctx->rs_state);
751   if (util_format_is_pure_sint(cbuf_format)) {
752      pipe->bind_vertex_elements_state(pipe, ctx->velem_sint_state);
753   } else if (util_format_is_pure_uint(cbuf_format)) {
754      pipe->bind_vertex_elements_state(pipe, ctx->velem_uint_state);
755   } else {
756      pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
757   }
758   pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, num_cbufs, int_format));
759   pipe->bind_vs_state(pipe, ctx->vs);
760   if (ctx->has_geometry_shader)
761      pipe->bind_gs_state(pipe, NULL);
762
763   blitter_set_dst_dimensions(ctx, width, height);
764   blitter->draw_rectangle(blitter, 0, 0, width, height, depth,
765                           UTIL_BLITTER_ATTRIB_COLOR, color);
766
767   blitter_restore_vertex_states(ctx);
768   blitter_restore_fragment_states(ctx);
769   blitter_unset_running_flag(ctx);
770}
771
772void util_blitter_clear(struct blitter_context *blitter,
773                        unsigned width, unsigned height,
774                        unsigned num_cbufs,
775                        unsigned clear_buffers,
776                        enum pipe_format cbuf_format,
777                        const union pipe_color_union *color,
778                        double depth, unsigned stencil)
779{
780   util_blitter_clear_custom(blitter, width, height, num_cbufs,
781                             clear_buffers, cbuf_format, color, depth, stencil,
782                             NULL, NULL);
783}
784
785void util_blitter_clear_depth_custom(struct blitter_context *blitter,
786                                     unsigned width, unsigned height,
787                                     double depth, void *custom_dsa)
788{
789    static const union pipe_color_union color;
790    util_blitter_clear_custom(blitter, width, height, 0,
791                              0, PIPE_FORMAT_NONE, &color, depth, 0, NULL, custom_dsa);
792}
793
794static
795boolean is_overlap(unsigned sx1, unsigned sx2, unsigned sy1, unsigned sy2,
796                   unsigned dx1, unsigned dx2, unsigned dy1, unsigned dy2)
797{
798   return sx1 < dx2 && sx2 > dx1 && sy1 < dy2 && sy2 > dy1;
799}
800
801void util_blitter_copy_texture(struct blitter_context *blitter,
802                               struct pipe_resource *dst,
803                               unsigned dstlevel,
804                               unsigned dstx, unsigned dsty, unsigned dstz,
805                               struct pipe_resource *src,
806                               unsigned srclevel,
807                               const struct pipe_box *srcbox,
808                               boolean ignore_stencil)
809{
810   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
811   struct pipe_context *pipe = ctx->base.pipe;
812   struct pipe_screen *screen = pipe->screen;
813   struct pipe_surface *dstsurf, surf_templ;
814   struct pipe_sampler_view viewTempl, *view;
815   unsigned bind;
816   boolean is_stencil, is_depth;
817
818   /* Give up if textures are not set. */
819   assert(dst && src);
820   if (!dst || !src)
821      return;
822
823   assert(src->target < PIPE_MAX_TEXTURE_TYPES);
824
825   /* Is this a ZS format? */
826   is_depth = util_format_get_component_bits(src->format, UTIL_FORMAT_COLORSPACE_ZS, 0) != 0;
827   is_stencil = util_format_get_component_bits(src->format, UTIL_FORMAT_COLORSPACE_ZS, 1) != 0;
828
829   if (is_depth || is_stencil)
830      bind = PIPE_BIND_DEPTH_STENCIL;
831   else
832      bind = PIPE_BIND_RENDER_TARGET;
833
834   /* Check if we can sample from and render to the surfaces. */
835   /* (assuming copying a stencil buffer is not possible) */
836   if ((!ignore_stencil && is_stencil) ||
837       !screen->is_format_supported(screen, dst->format, dst->target,
838                                    dst->nr_samples, bind) ||
839       !screen->is_format_supported(screen, src->format, src->target,
840                                    src->nr_samples, PIPE_BIND_SAMPLER_VIEW)) {
841      blitter_set_running_flag(ctx);
842      util_resource_copy_region(pipe, dst, dstlevel, dstx, dsty, dstz,
843                                src, srclevel, srcbox);
844      blitter_unset_running_flag(ctx);
845      return;
846   }
847
848   /* Initialize the surface. */
849   memset(&surf_templ, 0, sizeof(surf_templ));
850   u_surface_default_template(&surf_templ, dst, bind);
851   surf_templ.format = util_format_linear(dst->format);
852   surf_templ.u.tex.level = dstlevel;
853   surf_templ.u.tex.first_layer = dstz;
854   surf_templ.u.tex.last_layer = dstz + srcbox->depth - 1;
855   dstsurf = pipe->create_surface(pipe, dst, &surf_templ);
856
857   /* Initialize the sampler view. */
858   u_sampler_view_default_template(&viewTempl, src,
859                                   util_format_linear(src->format));
860   viewTempl.u.tex.first_level = srclevel;
861   viewTempl.u.tex.last_level = srclevel;
862   view = pipe->create_sampler_view(pipe, src, &viewTempl);
863
864   /* Copy. */
865   util_blitter_copy_texture_view(blitter, dstsurf, dstx, dsty, view, srcbox,
866                                  src->width0, src->height0);
867
868   pipe_surface_reference(&dstsurf, NULL);
869   pipe_sampler_view_reference(&view, NULL);
870}
871
872void util_blitter_copy_texture_view(struct blitter_context *blitter,
873                                    struct pipe_surface *dst,
874                                    unsigned dstx, unsigned dsty,
875                                    struct pipe_sampler_view *src,
876                                    const struct pipe_box *srcbox,
877                                    unsigned src_width0, unsigned src_height0)
878{
879   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
880   struct pipe_context *pipe = ctx->base.pipe;
881   struct pipe_framebuffer_state fb_state;
882   enum pipe_texture_target src_target = src->texture->target;
883   unsigned width = srcbox->width;
884   unsigned height = srcbox->height;
885
886   /* Sanity checks. */
887   if (dst->texture == src->texture &&
888       dst->u.tex.level == src->u.tex.first_level) {
889      assert(!is_overlap(srcbox->x, srcbox->x + width, srcbox->y, srcbox->y + height,
890                         dstx, dstx + width, dsty, dsty + height));
891   }
892   /* XXX should handle 3d regions */
893   assert(srcbox->depth == 1);
894
895   /* Check whether the states are properly saved. */
896   blitter_set_running_flag(ctx);
897   blitter_check_saved_vertex_states(ctx);
898   blitter_check_saved_fragment_states(ctx);
899   blitter_check_saved_textures(ctx);
900   blitter_check_saved_fb_state(ctx);
901
902   /* Initialize framebuffer state. */
903   fb_state.width = dst->width;
904   fb_state.height = dst->height;
905
906   if (util_format_is_depth_or_stencil(dst->format)) {
907      pipe->bind_blend_state(pipe, ctx->blend_keep_color);
908      pipe->bind_depth_stencil_alpha_state(pipe,
909                                           ctx->dsa_write_depth_keep_stencil);
910      pipe->bind_fs_state(pipe,
911            blitter_get_fs_texfetch_depth(ctx, src_target));
912
913      fb_state.nr_cbufs = 0;
914      fb_state.zsbuf = dst;
915   } else {
916      pipe->bind_blend_state(pipe, ctx->blend_write_color);
917      pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
918      pipe->bind_fs_state(pipe,
919            blitter_get_fs_texfetch_col(ctx, src_target));
920
921      fb_state.nr_cbufs = 1;
922      fb_state.cbufs[0] = dst;
923      fb_state.zsbuf = 0;
924   }
925
926   /* Set rasterizer state, shaders, and textures. */
927   pipe->bind_rasterizer_state(pipe, ctx->rs_state);
928   pipe->bind_vs_state(pipe, ctx->vs);
929   if (ctx->has_geometry_shader)
930      pipe->bind_gs_state(pipe, NULL);
931   pipe->bind_fragment_sampler_states(pipe, 1, &ctx->sampler_state);
932   pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
933   pipe->set_fragment_sampler_views(pipe, 1, &src);
934   pipe->set_framebuffer_state(pipe, &fb_state);
935
936   blitter_set_dst_dimensions(ctx, dst->width, dst->height);
937
938   switch (src_target) {
939      /* Draw the quad with the draw_rectangle callback. */
940      case PIPE_TEXTURE_1D:
941      case PIPE_TEXTURE_2D:
942      case PIPE_TEXTURE_RECT:
943         {
944            /* Set texture coordinates. - use a pipe color union
945             * for interface purposes.
946             * XXX pipe_color_union is a wrong name since we use that to set
947             * texture coordinates too.
948             */
949            union pipe_color_union coord;
950            get_texcoords(src, src_width0, src_height0, srcbox->x, srcbox->y,
951                          srcbox->x+width, srcbox->y+height, coord.f);
952
953            /* Draw. */
954            blitter->draw_rectangle(blitter, dstx, dsty, dstx+width, dsty+height, 0,
955                                    UTIL_BLITTER_ATTRIB_TEXCOORD, &coord);
956         }
957         break;
958
959      /* Draw the quad with the generic codepath. */
960      default:
961         /* Set texture coordinates. */
962         switch (src_target) {
963         case PIPE_TEXTURE_1D_ARRAY:
964         case PIPE_TEXTURE_2D_ARRAY:
965         case PIPE_TEXTURE_3D:
966         case PIPE_TEXTURE_CUBE:
967            blitter_set_texcoords(ctx, src, src_width0, src_height0, srcbox->z,
968                                  srcbox->y, srcbox->x,
969                                  srcbox->x + width, srcbox->y + height);
970            break;
971
972         default:
973            assert(0);
974         }
975
976         /* Draw. */
977         blitter_set_rectangle(ctx, dstx, dsty, dstx+width, dsty+height, 0);
978         ctx->base.pipe->redefine_user_buffer(ctx->base.pipe, ctx->vbuf,
979                                              0, ctx->vbuf->width0);
980         util_draw_vertex_buffer(ctx->base.pipe, NULL, ctx->vbuf, 0,
981                                 PIPE_PRIM_TRIANGLE_FAN, 4, 2);
982         break;
983   }
984
985   blitter_restore_vertex_states(ctx);
986   blitter_restore_fragment_states(ctx);
987   blitter_restore_textures(ctx);
988   blitter_restore_fb_state(ctx);
989   blitter_unset_running_flag(ctx);
990}
991
992/* Clear a region of a color surface to a constant value. */
993void util_blitter_clear_render_target(struct blitter_context *blitter,
994                                      struct pipe_surface *dstsurf,
995                                      const union pipe_color_union *color,
996                                      unsigned dstx, unsigned dsty,
997                                      unsigned width, unsigned height)
998{
999   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
1000   struct pipe_context *pipe = ctx->base.pipe;
1001   struct pipe_framebuffer_state fb_state;
1002
1003   assert(dstsurf->texture);
1004   if (!dstsurf->texture)
1005      return;
1006
1007   /* check the saved state */
1008   blitter_set_running_flag(ctx);
1009   blitter_check_saved_vertex_states(ctx);
1010   blitter_check_saved_fragment_states(ctx);
1011   blitter_check_saved_fb_state(ctx);
1012
1013   /* bind states */
1014   pipe->bind_blend_state(pipe, ctx->blend_write_color);
1015   pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
1016   pipe->bind_rasterizer_state(pipe, ctx->rs_state);
1017   pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 1, FALSE));
1018   pipe->bind_vs_state(pipe, ctx->vs);
1019   if (ctx->has_geometry_shader)
1020      pipe->bind_gs_state(pipe, NULL);
1021   pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
1022
1023   /* set a framebuffer state */
1024   fb_state.width = dstsurf->width;
1025   fb_state.height = dstsurf->height;
1026   fb_state.nr_cbufs = 1;
1027   fb_state.cbufs[0] = dstsurf;
1028   fb_state.zsbuf = 0;
1029   pipe->set_framebuffer_state(pipe, &fb_state);
1030
1031   blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height);
1032   blitter->draw_rectangle(blitter, dstx, dsty, dstx+width, dsty+height, 0,
1033                           UTIL_BLITTER_ATTRIB_COLOR, color);
1034
1035   blitter_restore_vertex_states(ctx);
1036   blitter_restore_fragment_states(ctx);
1037   blitter_restore_fb_state(ctx);
1038   blitter_unset_running_flag(ctx);
1039}
1040
1041/* Clear a region of a depth stencil surface. */
1042void util_blitter_clear_depth_stencil(struct blitter_context *blitter,
1043                                      struct pipe_surface *dstsurf,
1044                                      unsigned clear_flags,
1045                                      double depth,
1046                                      unsigned stencil,
1047                                      unsigned dstx, unsigned dsty,
1048                                      unsigned width, unsigned height)
1049{
1050   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
1051   struct pipe_context *pipe = ctx->base.pipe;
1052   struct pipe_framebuffer_state fb_state;
1053   struct pipe_stencil_ref sr = { { 0 } };
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_keep_color);
1067   if ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) == PIPE_CLEAR_DEPTHSTENCIL) {
1068      sr.ref_value[0] = stencil & 0xff;
1069      pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil);
1070      pipe->set_stencil_ref(pipe, &sr);
1071   }
1072   else if (clear_flags & PIPE_CLEAR_DEPTH) {
1073      pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_keep_stencil);
1074   }
1075   else if (clear_flags & PIPE_CLEAR_STENCIL) {
1076      sr.ref_value[0] = stencil & 0xff;
1077      pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil);
1078      pipe->set_stencil_ref(pipe, &sr);
1079   }
1080   else
1081      /* hmm that should be illegal probably, or make it a no-op somewhere */
1082      pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
1083
1084   pipe->bind_rasterizer_state(pipe, ctx->rs_state);
1085   pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 0, FALSE));
1086   pipe->bind_vs_state(pipe, ctx->vs);
1087   if (ctx->has_geometry_shader)
1088      pipe->bind_gs_state(pipe, NULL);
1089   pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
1090
1091   /* set a framebuffer state */
1092   fb_state.width = dstsurf->width;
1093   fb_state.height = dstsurf->height;
1094   fb_state.nr_cbufs = 0;
1095   fb_state.cbufs[0] = 0;
1096   fb_state.zsbuf = dstsurf;
1097   pipe->set_framebuffer_state(pipe, &fb_state);
1098
1099   blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height);
1100   blitter->draw_rectangle(blitter, dstx, dsty, dstx+width, dsty+height, depth,
1101                           UTIL_BLITTER_ATTRIB_NONE, NULL);
1102
1103   blitter_restore_vertex_states(ctx);
1104   blitter_restore_fragment_states(ctx);
1105   blitter_restore_fb_state(ctx);
1106   blitter_unset_running_flag(ctx);
1107}
1108
1109/* draw a rectangle across a region using a custom dsa stage - for r600g */
1110void util_blitter_custom_depth_stencil(struct blitter_context *blitter,
1111				       struct pipe_surface *zsurf,
1112				       struct pipe_surface *cbsurf,
1113				       void *dsa_stage, float depth)
1114{
1115   struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
1116   struct pipe_context *pipe = ctx->base.pipe;
1117   struct pipe_framebuffer_state fb_state;
1118
1119   assert(zsurf->texture);
1120   if (!zsurf->texture)
1121      return;
1122
1123   /* check the saved state */
1124   blitter_set_running_flag(ctx);
1125   blitter_check_saved_vertex_states(ctx);
1126   blitter_check_saved_fragment_states(ctx);
1127   blitter_check_saved_fb_state(ctx);
1128
1129   /* bind states */
1130   pipe->bind_blend_state(pipe, ctx->blend_write_color);
1131   pipe->bind_depth_stencil_alpha_state(pipe, dsa_stage);
1132
1133   pipe->bind_rasterizer_state(pipe, ctx->rs_state);
1134   pipe->bind_fs_state(pipe, blitter_get_fs_col(ctx, 0, FALSE));
1135   pipe->bind_vs_state(pipe, ctx->vs);
1136   if (ctx->has_geometry_shader)
1137      pipe->bind_gs_state(pipe, NULL);
1138   pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
1139
1140   /* set a framebuffer state */
1141   fb_state.width = zsurf->width;
1142   fb_state.height = zsurf->height;
1143   fb_state.nr_cbufs = 1;
1144   if (cbsurf) {
1145	   fb_state.cbufs[0] = cbsurf;
1146	   fb_state.nr_cbufs = 1;
1147   } else {
1148	   fb_state.cbufs[0] = NULL;
1149	   fb_state.nr_cbufs = 0;
1150   }
1151   fb_state.zsbuf = zsurf;
1152   pipe->set_framebuffer_state(pipe, &fb_state);
1153
1154   blitter_set_dst_dimensions(ctx, zsurf->width, zsurf->height);
1155   blitter->draw_rectangle(blitter, 0, 0, zsurf->width, zsurf->height, depth,
1156                           UTIL_BLITTER_ATTRIB_NONE, NULL);
1157
1158   blitter_restore_vertex_states(ctx);
1159   blitter_restore_fragment_states(ctx);
1160   blitter_restore_fb_state(ctx);
1161   blitter_unset_running_flag(ctx);
1162}
1163