gallium: s/copy_pixels_state/blit_state
[mesa.git] / src / gallium / auxiliary / util / u_blit.c
1 /**************************************************************************
2 *
3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
28 /**
29 * @file
30 * Copy/blit pixel rect between surfaces
31 *
32 * @author Brian Paul
33 */
34
35
36 #include "pipe/p_context.h"
37 #include "pipe/p_debug.h"
38 #include "pipe/p_defines.h"
39 #include "pipe/p_inlines.h"
40 #include "pipe/p_util.h"
41 #include "pipe/p_winsys.h"
42 #include "pipe/p_shader_tokens.h"
43
44 #include "util/u_draw_quad.h"
45 #include "util/u_blit.h"
46 #include "util/u_simple_shaders.h"
47
48
49 struct blit_state
50 {
51 struct pipe_context *pipe;
52
53 void *blend;
54 void *depthstencil;
55 void *rasterizer;
56 void *samplers[2]; /* one for linear, one for nearest sampling */
57
58 /*struct pipe_viewport_state viewport;*/
59 struct pipe_sampler_state *vs;
60 struct pipe_sampler_state *fs;
61 };
62
63
64 /**
65 * Create state object for blit.
66 * Intended to be created once and re-used for many blit() calls.
67 */
68 struct blit_state *
69 util_create_blit(struct pipe_context *pipe)
70 {
71 struct pipe_blend_state blend;
72 struct pipe_depth_stencil_alpha_state depthstencil;
73 struct pipe_rasterizer_state rasterizer;
74 struct blit_state *ctx;
75 struct pipe_sampler_state sampler;
76
77 ctx = CALLOC_STRUCT(blit_state);
78 if (!ctx)
79 return NULL;
80
81 ctx->pipe = pipe;
82
83 /* we don't use blending, but need to set valid values */
84 memset(&blend, 0, sizeof(blend));
85 blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
86 blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
87 blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
88 blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
89 blend.colormask = PIPE_MASK_RGBA;
90 ctx->blend = pipe->create_blend_state(pipe, &blend);
91
92 /* depth/stencil/alpha */
93 memset(&depthstencil, 0, sizeof(depthstencil));
94 ctx->depthstencil = pipe->create_depth_stencil_alpha_state(pipe, &depthstencil);
95
96 /* rasterizer */
97 memset(&rasterizer, 0, sizeof(rasterizer));
98 rasterizer.front_winding = PIPE_WINDING_CW;
99 rasterizer.cull_mode = PIPE_WINDING_NONE;
100 rasterizer.bypass_clipping = 1; /* bypasses viewport too */
101 /*rasterizer.bypass_vs = 1;*/
102 ctx->rasterizer = pipe->create_rasterizer_state(pipe, &rasterizer);
103
104 /* samplers */
105 memset(&sampler, 0, sizeof(sampler));
106 sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
107 sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
108 sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
109 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
110 sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
111 sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
112 sampler.normalized_coords = 1;
113 ctx->samplers[0] = pipe->create_sampler_state(pipe, &sampler);
114
115 sampler.min_img_filter = PIPE_TEX_MIPFILTER_LINEAR;
116 sampler.mag_img_filter = PIPE_TEX_MIPFILTER_LINEAR;
117 ctx->samplers[1] = pipe->create_sampler_state(pipe, &sampler);
118
119
120 #if 0
121 /* viewport */
122 ctx->viewport.scale[0] = 1.0;
123 ctx->viewport.scale[1] = 1.0;
124 ctx->viewport.scale[2] = 1.0;
125 ctx->viewport.scale[3] = 1.0;
126 ctx->viewport.translate[0] = 0.0;
127 ctx->viewport.translate[1] = 0.0;
128 ctx->viewport.translate[2] = 0.0;
129 ctx->viewport.translate[3] = 0.0;
130 #endif
131
132 /* vertex shader */
133 {
134 const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
135 TGSI_SEMANTIC_GENERIC };
136 const uint semantic_indexes[] = { 0, 0 };
137 ctx->vs = util_make_vertex_passthrough_shader(pipe, 2, semantic_names,
138 semantic_indexes);
139 }
140
141 /* fragment shader */
142 ctx->fs = util_make_fragment_tex_shader(pipe);
143
144 return ctx;
145 }
146
147
148 /**
149 * Destroy a blit context
150 */
151 void
152 util_destroy_blit(struct blit_state *ctx)
153 {
154 struct pipe_context *pipe = ctx->pipe;
155
156 pipe->delete_blend_state(pipe, ctx->blend);
157 pipe->delete_depth_stencil_alpha_state(pipe, ctx->depthstencil);
158 pipe->delete_rasterizer_state(pipe, ctx->rasterizer);
159 pipe->delete_sampler_state(pipe, ctx->samplers[0]);
160 pipe->delete_sampler_state(pipe, ctx->samplers[1]);
161
162 pipe->delete_vs_state(pipe, ctx->vs);
163 pipe->delete_fs_state(pipe, ctx->fs);
164
165 FREE(ctx);
166 }
167
168
169 /**
170 * Copy pixel block from src surface to dst surface.
171 * Overlapping regions are acceptable.
172 * XXX need some control over blitting Z and/or stencil.
173 */
174 void
175 util_blit_pixels(struct blit_state *ctx,
176 struct pipe_surface *src,
177 int srcX0, int srcY0,
178 int srcX1, int srcY1,
179 struct pipe_surface *dst,
180 int dstX0, int dstY0,
181 int dstX1, int dstY1,
182 float z, uint filter)
183 {
184 struct pipe_context *pipe = ctx->pipe;
185 struct pipe_screen *screen = pipe->screen;
186 struct pipe_texture texTemp, *tex;
187 struct pipe_surface *texSurf;
188 struct pipe_framebuffer_state fb;
189 const int srcW = abs(srcX1 - srcX0);
190 const int srcH = abs(srcY1 - srcY0);
191 const int srcLeft = MIN2(srcX0, srcX1);
192 const int srcTop = MIN2(srcY0, srcY1);
193
194 assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
195 filter == PIPE_TEX_MIPFILTER_LINEAR);
196
197 if (srcLeft != srcX0) {
198 /* left-right flip */
199 int tmp = dstX0;
200 dstX0 = dstX1;
201 dstX1 = tmp;
202 }
203
204 if (srcTop != srcY0) {
205 /* up-down flip */
206 int tmp = dstY0;
207 dstY0 = dstY1;
208 dstY1 = tmp;
209 }
210
211 /*
212 * XXX for now we're always creating a temporary texture.
213 * Strictly speaking that's not always needed.
214 */
215
216 /* create temp texture */
217 memset(&texTemp, 0, sizeof(texTemp));
218 texTemp.target = PIPE_TEXTURE_2D;
219 texTemp.format = src->format;
220 texTemp.last_level = 0;
221 texTemp.width[0] = srcW;
222 texTemp.height[0] = srcH;
223 texTemp.depth[0] = 1;
224 texTemp.compressed = 0;
225 texTemp.cpp = pf_get_bits(src->format) / 8;
226
227 tex = screen->texture_create(screen, &texTemp);
228 if (!tex)
229 return;
230
231 texSurf = screen->get_tex_surface(screen, tex, 0, 0, 0);
232
233 /* load temp texture */
234 pipe->surface_copy(pipe, FALSE,
235 texSurf, 0, 0, /* dest */
236 src, srcLeft, srcTop, /* src */
237 srcW, srcH); /* size */
238
239 /* drawing dest */
240 memset(&fb, 0, sizeof(fb));
241 fb.num_cbufs = 1;
242 fb.cbufs[0] = dst;
243 pipe->set_framebuffer_state(pipe, &fb);
244
245 /* sampler */
246 if (filter == PIPE_TEX_MIPFILTER_NEAREST)
247 pipe->bind_sampler_states(pipe, 1, &ctx->samplers[0]);
248 else
249 pipe->bind_sampler_states(pipe, 1, &ctx->samplers[1]);
250
251 /* texture */
252 pipe->set_sampler_textures(pipe, 1, &tex);
253
254 /* shaders */
255 pipe->bind_fs_state(pipe, ctx->fs);
256 pipe->bind_vs_state(pipe, ctx->vs);
257
258 /* misc state */
259 pipe->bind_blend_state(pipe, ctx->blend);
260 pipe->bind_depth_stencil_alpha_state(pipe, ctx->depthstencil);
261 pipe->bind_rasterizer_state(pipe, ctx->rasterizer);
262
263 /* draw quad */
264 util_draw_texquad(pipe, dstX0, dstY0, dstX1, dstY1, z);
265
266 /* unbind */
267 pipe->set_sampler_textures(pipe, 0, NULL);
268 pipe->bind_sampler_states(pipe, 0, NULL);
269
270 /* free stuff */
271 pipe_surface_reference(&texSurf, NULL);
272 screen->texture_release(screen, &tex);
273
274 /* Note: caller must restore pipe/gallium state at this time */
275 }
276