gallium: Give some chance for the table to actually grow.
[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 #include "cso_cache/cso_context.h"
49
50
51 struct blit_state
52 {
53 struct pipe_context *pipe;
54 struct cso_context *cso;
55
56 struct pipe_blend_state blend;
57 struct pipe_depth_stencil_alpha_state depthstencil;
58 struct pipe_rasterizer_state rasterizer;
59 struct pipe_sampler_state sampler;
60
61 /*struct pipe_viewport_state viewport;*/
62 struct pipe_sampler_state *vs;
63 struct pipe_sampler_state *fs;
64 };
65
66
67 /**
68 * Create state object for blit.
69 * Intended to be created once and re-used for many blit() calls.
70 */
71 struct blit_state *
72 util_create_blit(struct pipe_context *pipe, struct cso_context *cso)
73 {
74 struct blit_state *ctx;
75
76 ctx = CALLOC_STRUCT(blit_state);
77 if (!ctx)
78 return NULL;
79
80 ctx->pipe = pipe;
81 ctx->cso = cso;
82
83 /* disabled blending/masking */
84 memset(&ctx->blend, 0, sizeof(ctx->blend));
85 ctx->blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
86 ctx->blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
87 ctx->blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
88 ctx->blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
89 ctx->blend.colormask = PIPE_MASK_RGBA;
90
91 /* no-op depth/stencil/alpha */
92 memset(&ctx->depthstencil, 0, sizeof(ctx->depthstencil));
93
94 /* rasterizer */
95 memset(&ctx->rasterizer, 0, sizeof(ctx->rasterizer));
96 ctx->rasterizer.front_winding = PIPE_WINDING_CW;
97 ctx->rasterizer.cull_mode = PIPE_WINDING_NONE;
98 ctx->rasterizer.bypass_clipping = 1; /* bypasses viewport too */
99 /*ctx->rasterizer.bypass_vs = 1;*/
100
101 /* samplers */
102 memset(&ctx->sampler, 0, sizeof(ctx->sampler));
103 ctx->sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
104 ctx->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
105 ctx->sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
106 ctx->sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
107 ctx->sampler.min_img_filter = 0; /* set later */
108 ctx->sampler.mag_img_filter = 0; /* set later */
109 ctx->sampler.normalized_coords = 1;
110
111 #if 0
112 /* viewport */
113 ctx->viewport.scale[0] = 1.0;
114 ctx->viewport.scale[1] = 1.0;
115 ctx->viewport.scale[2] = 1.0;
116 ctx->viewport.scale[3] = 1.0;
117 ctx->viewport.translate[0] = 0.0;
118 ctx->viewport.translate[1] = 0.0;
119 ctx->viewport.translate[2] = 0.0;
120 ctx->viewport.translate[3] = 0.0;
121 #endif
122
123 /* vertex shader */
124 {
125 const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
126 TGSI_SEMANTIC_GENERIC };
127 const uint semantic_indexes[] = { 0, 0 };
128 ctx->vs = util_make_vertex_passthrough_shader(pipe, 2, semantic_names,
129 semantic_indexes);
130 }
131
132 /* fragment shader */
133 ctx->fs = util_make_fragment_tex_shader(pipe);
134
135 return ctx;
136 }
137
138
139 /**
140 * Destroy a blit context
141 */
142 void
143 util_destroy_blit(struct blit_state *ctx)
144 {
145 struct pipe_context *pipe = ctx->pipe;
146
147 pipe->delete_vs_state(pipe, ctx->vs);
148 pipe->delete_fs_state(pipe, ctx->fs);
149
150 FREE(ctx);
151 }
152
153
154 /**
155 * Copy pixel block from src surface to dst surface.
156 * Overlapping regions are acceptable.
157 * XXX need some control over blitting Z and/or stencil.
158 */
159 void
160 util_blit_pixels(struct blit_state *ctx,
161 struct pipe_surface *src,
162 int srcX0, int srcY0,
163 int srcX1, int srcY1,
164 struct pipe_surface *dst,
165 int dstX0, int dstY0,
166 int dstX1, int dstY1,
167 float z, uint filter)
168 {
169 struct pipe_context *pipe = ctx->pipe;
170 struct pipe_screen *screen = pipe->screen;
171 struct pipe_texture texTemp, *tex;
172 struct pipe_surface *texSurf;
173 struct pipe_framebuffer_state fb;
174 const int srcW = abs(srcX1 - srcX0);
175 const int srcH = abs(srcY1 - srcY0);
176 const int srcLeft = MIN2(srcX0, srcX1);
177 const int srcTop = MIN2(srcY0, srcY1);
178
179 assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
180 filter == PIPE_TEX_MIPFILTER_LINEAR);
181
182 if (srcLeft != srcX0) {
183 /* left-right flip */
184 int tmp = dstX0;
185 dstX0 = dstX1;
186 dstX1 = tmp;
187 }
188
189 if (srcTop != srcY0) {
190 /* up-down flip */
191 int tmp = dstY0;
192 dstY0 = dstY1;
193 dstY1 = tmp;
194 }
195
196 /*
197 * XXX for now we're always creating a temporary texture.
198 * Strictly speaking that's not always needed.
199 */
200
201 /* create temp texture */
202 memset(&texTemp, 0, sizeof(texTemp));
203 texTemp.target = PIPE_TEXTURE_2D;
204 texTemp.format = src->format;
205 texTemp.last_level = 0;
206 texTemp.width[0] = srcW;
207 texTemp.height[0] = srcH;
208 texTemp.depth[0] = 1;
209 texTemp.compressed = 0;
210 texTemp.cpp = pf_get_bits(src->format) / 8;
211
212 tex = screen->texture_create(screen, &texTemp);
213 if (!tex)
214 return;
215
216 texSurf = screen->get_tex_surface(screen, tex, 0, 0, 0);
217
218 /* load temp texture */
219 pipe->surface_copy(pipe, FALSE,
220 texSurf, 0, 0, /* dest */
221 src, srcLeft, srcTop, /* src */
222 srcW, srcH); /* size */
223
224 /* save state (restored below) */
225 cso_save_blend(ctx->cso);
226 cso_save_depth_stencil_alpha(ctx->cso);
227 cso_save_rasterizer(ctx->cso);
228 cso_save_samplers(ctx->cso);
229 cso_save_sampler_textures(ctx->cso);
230 cso_save_framebuffer(ctx->cso);
231
232 /* set misc state we care about */
233 cso_set_blend(ctx->cso, &ctx->blend);
234 cso_set_depth_stencil_alpha(ctx->cso, &ctx->depthstencil);
235 cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
236
237 /* sampler */
238 ctx->sampler.min_img_filter = filter;
239 ctx->sampler.mag_img_filter = filter;
240 cso_single_sampler(ctx->cso, 0, &ctx->sampler);
241 cso_single_sampler_done(ctx->cso);
242
243 /* texture */
244 pipe->set_sampler_textures(pipe, 1, &tex);
245
246 /* shaders */
247 pipe->bind_fs_state(pipe, ctx->fs);
248 pipe->bind_vs_state(pipe, ctx->vs);
249
250 /* drawing dest */
251 memset(&fb, 0, sizeof(fb));
252 fb.num_cbufs = 1;
253 fb.cbufs[0] = dst;
254 cso_set_framebuffer(ctx->cso, &fb);
255
256 /* draw quad */
257 util_draw_texquad(pipe,
258 (float)dstX0,
259 (float)dstY0,
260 (float)dstX1,
261 (float)dstY1, z);
262
263 /* restore state we changed */
264 cso_restore_blend(ctx->cso);
265 cso_restore_depth_stencil_alpha(ctx->cso);
266 cso_restore_rasterizer(ctx->cso);
267 cso_restore_samplers(ctx->cso);
268 cso_restore_sampler_textures(ctx->cso);
269 cso_restore_framebuffer(ctx->cso);
270
271 /* free the texture */
272 pipe_surface_reference(&texSurf, NULL);
273 screen->texture_release(screen, &tex);
274 }
275