gallium: standardize api on the prefix "nr"
[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_winsys.h"
41 #include "pipe/p_shader_tokens.h"
42
43 #include "util/u_blit.h"
44 #include "util/u_draw_quad.h"
45 #include "util/u_math.h"
46 #include "util/u_memory.h"
47 #include "util/u_simple_shaders.h"
48
49 #include "cso_cache/cso_context.h"
50
51
52 struct blit_state
53 {
54 struct pipe_context *pipe;
55 struct cso_context *cso;
56
57 struct pipe_blend_state blend;
58 struct pipe_depth_stencil_alpha_state depthstencil;
59 struct pipe_rasterizer_state rasterizer;
60 struct pipe_sampler_state sampler;
61 struct pipe_viewport_state viewport;
62
63 struct pipe_shader_state vert_shader;
64 struct pipe_shader_state frag_shader;
65 void *vs;
66 void *fs;
67
68 struct pipe_buffer *vbuf; /**< quad vertices */
69 unsigned vbuf_slot;
70
71 float vertices[4][2][4]; /**< vertex/texcoords for quad */
72 };
73
74
75 /**
76 * Create state object for blit.
77 * Intended to be created once and re-used for many blit() calls.
78 */
79 struct blit_state *
80 util_create_blit(struct pipe_context *pipe, struct cso_context *cso)
81 {
82 struct blit_state *ctx;
83 uint i;
84
85 ctx = CALLOC_STRUCT(blit_state);
86 if (!ctx)
87 return NULL;
88
89 ctx->pipe = pipe;
90 ctx->cso = cso;
91
92 /* disabled blending/masking */
93 memset(&ctx->blend, 0, sizeof(ctx->blend));
94 ctx->blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
95 ctx->blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
96 ctx->blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
97 ctx->blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
98 ctx->blend.colormask = PIPE_MASK_RGBA;
99
100 /* no-op depth/stencil/alpha */
101 memset(&ctx->depthstencil, 0, sizeof(ctx->depthstencil));
102
103 /* rasterizer */
104 memset(&ctx->rasterizer, 0, sizeof(ctx->rasterizer));
105 ctx->rasterizer.front_winding = PIPE_WINDING_CW;
106 ctx->rasterizer.cull_mode = PIPE_WINDING_NONE;
107 ctx->rasterizer.bypass_clipping = 1;
108 /*ctx->rasterizer.bypass_vs = 1;*/
109 ctx->rasterizer.gl_rasterization_rules = 1;
110
111 /* samplers */
112 memset(&ctx->sampler, 0, sizeof(ctx->sampler));
113 ctx->sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
114 ctx->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
115 ctx->sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
116 ctx->sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
117 ctx->sampler.min_img_filter = 0; /* set later */
118 ctx->sampler.mag_img_filter = 0; /* set later */
119 ctx->sampler.normalized_coords = 1;
120
121 /* viewport (identity, we setup vertices in wincoords) */
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
131 /* vertex shader */
132 {
133 const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
134 TGSI_SEMANTIC_GENERIC };
135 const uint semantic_indexes[] = { 0, 0 };
136 ctx->vs = util_make_vertex_passthrough_shader(pipe, 2, semantic_names,
137 semantic_indexes,
138 &ctx->vert_shader);
139 }
140
141 /* fragment shader */
142 ctx->fs = util_make_fragment_tex_shader(pipe, &ctx->frag_shader);
143 ctx->vbuf = NULL;
144
145 /* init vertex data that doesn't change */
146 for (i = 0; i < 4; i++) {
147 ctx->vertices[i][0][3] = 1.0f; /* w */
148 ctx->vertices[i][1][2] = 0.0f; /* r */
149 ctx->vertices[i][1][3] = 1.0f; /* q */
150 }
151
152 return ctx;
153 }
154
155
156 /**
157 * Destroy a blit context
158 */
159 void
160 util_destroy_blit(struct blit_state *ctx)
161 {
162 struct pipe_context *pipe = ctx->pipe;
163
164 pipe->delete_vs_state(pipe, ctx->vs);
165 pipe->delete_fs_state(pipe, ctx->fs);
166
167 FREE((void*) ctx->vert_shader.tokens);
168 FREE((void*) ctx->frag_shader.tokens);
169
170 pipe_buffer_reference(pipe->screen, &ctx->vbuf, NULL);
171
172 FREE(ctx);
173 }
174
175
176 static unsigned get_next_slot( struct blit_state *ctx )
177 {
178 const unsigned max_slots = 4096 / sizeof ctx->vertices;
179
180 if (ctx->vbuf_slot >= max_slots)
181 util_blit_flush( ctx );
182
183 if (!ctx->vbuf) {
184 ctx->vbuf = pipe_buffer_create(ctx->pipe->screen,
185 32,
186 PIPE_BUFFER_USAGE_VERTEX,
187 max_slots * sizeof ctx->vertices);
188 }
189
190 return ctx->vbuf_slot++ * sizeof ctx->vertices;
191 }
192
193
194
195 /**
196 * Setup vertex data for the textured quad we'll draw.
197 * Note: y=0=top
198 */
199 static unsigned
200 setup_vertex_data(struct blit_state *ctx,
201 float x0, float y0, float x1, float y1, float z)
202 {
203 void *buf;
204 unsigned offset;
205
206 ctx->vertices[0][0][0] = x0;
207 ctx->vertices[0][0][1] = y0;
208 ctx->vertices[0][0][2] = z;
209 ctx->vertices[0][1][0] = 0.0f; /*s*/
210 ctx->vertices[0][1][1] = 0.0f; /*t*/
211
212 ctx->vertices[1][0][0] = x1;
213 ctx->vertices[1][0][1] = y0;
214 ctx->vertices[1][0][2] = z;
215 ctx->vertices[1][1][0] = 1.0f; /*s*/
216 ctx->vertices[1][1][1] = 0.0f; /*t*/
217
218 ctx->vertices[2][0][0] = x1;
219 ctx->vertices[2][0][1] = y1;
220 ctx->vertices[2][0][2] = z;
221 ctx->vertices[2][1][0] = 1.0f;
222 ctx->vertices[2][1][1] = 1.0f;
223
224 ctx->vertices[3][0][0] = x0;
225 ctx->vertices[3][0][1] = y1;
226 ctx->vertices[3][0][2] = z;
227 ctx->vertices[3][1][0] = 0.0f;
228 ctx->vertices[3][1][1] = 1.0f;
229
230 offset = get_next_slot( ctx );
231
232 buf = pipe_buffer_map(ctx->pipe->screen, ctx->vbuf,
233 PIPE_BUFFER_USAGE_CPU_WRITE);
234
235 memcpy((char *)buf + offset, ctx->vertices, sizeof(ctx->vertices));
236
237 pipe_buffer_unmap(ctx->pipe->screen, ctx->vbuf);
238
239 return offset;
240 }
241
242
243 /**
244 * Setup vertex data for the textured quad we'll draw.
245 * Note: y=0=top
246 */
247 static unsigned
248 setup_vertex_data_tex(struct blit_state *ctx,
249 float x0, float y0, float x1, float y1,
250 float s0, float t0, float s1, float t1,
251 float z)
252 {
253 void *buf;
254 unsigned offset;
255
256 ctx->vertices[0][0][0] = x0;
257 ctx->vertices[0][0][1] = y0;
258 ctx->vertices[0][0][2] = z;
259 ctx->vertices[0][1][0] = s0; /*s*/
260 ctx->vertices[0][1][1] = t0; /*t*/
261
262 ctx->vertices[1][0][0] = x1;
263 ctx->vertices[1][0][1] = y0;
264 ctx->vertices[1][0][2] = z;
265 ctx->vertices[1][1][0] = s1; /*s*/
266 ctx->vertices[1][1][1] = t0; /*t*/
267
268 ctx->vertices[2][0][0] = x1;
269 ctx->vertices[2][0][1] = y1;
270 ctx->vertices[2][0][2] = z;
271 ctx->vertices[2][1][0] = s1;
272 ctx->vertices[2][1][1] = t1;
273
274 ctx->vertices[3][0][0] = x0;
275 ctx->vertices[3][0][1] = y1;
276 ctx->vertices[3][0][2] = z;
277 ctx->vertices[3][1][0] = s0;
278 ctx->vertices[3][1][1] = t1;
279
280 offset = get_next_slot( ctx );
281
282 buf = pipe_buffer_map(ctx->pipe->screen, ctx->vbuf,
283 PIPE_BUFFER_USAGE_CPU_WRITE);
284
285 memcpy((char *)buf + offset, ctx->vertices, sizeof(ctx->vertices));
286
287 pipe_buffer_unmap(ctx->pipe->screen, ctx->vbuf);
288
289 return offset;
290 }
291 /**
292 * Copy pixel block from src surface to dst surface.
293 * Overlapping regions are acceptable.
294 * XXX need some control over blitting Z and/or stencil.
295 */
296 void
297 util_blit_pixels(struct blit_state *ctx,
298 struct pipe_surface *src,
299 int srcX0, int srcY0,
300 int srcX1, int srcY1,
301 struct pipe_surface *dst,
302 int dstX0, int dstY0,
303 int dstX1, int dstY1,
304 float z, uint filter)
305 {
306 struct pipe_context *pipe = ctx->pipe;
307 struct pipe_screen *screen = pipe->screen;
308 struct pipe_texture texTemp, *tex;
309 struct pipe_surface *texSurf;
310 struct pipe_framebuffer_state fb;
311 const int srcW = abs(srcX1 - srcX0);
312 const int srcH = abs(srcY1 - srcY0);
313 const int srcLeft = MIN2(srcX0, srcX1);
314 const int srcTop = MIN2(srcY0, srcY1);
315 unsigned offset;
316
317 assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
318 filter == PIPE_TEX_MIPFILTER_LINEAR);
319
320 if (srcLeft != srcX0) {
321 /* left-right flip */
322 int tmp = dstX0;
323 dstX0 = dstX1;
324 dstX1 = tmp;
325 }
326
327 if (srcTop != srcY0) {
328 /* up-down flip */
329 int tmp = dstY0;
330 dstY0 = dstY1;
331 dstY1 = tmp;
332 }
333
334 assert(screen->is_format_supported(screen, src->format, PIPE_TEXTURE_2D,
335 PIPE_TEXTURE_USAGE_SAMPLER, 0));
336 assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
337 PIPE_TEXTURE_USAGE_SAMPLER, 0));
338
339 if(dst->format == src->format && (dstX1 - dstX0) == srcW && (dstY1 - dstY0) == srcH) {
340 /* FIXME: this will most surely fail for overlapping rectangles */
341 pipe->surface_copy(pipe, FALSE,
342 dst, dstX0, dstY0, /* dest */
343 src, srcX0, srcY0, /* src */
344 srcW, srcH); /* size */
345 return;
346 }
347
348 assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
349 PIPE_TEXTURE_USAGE_RENDER_TARGET, 0));
350
351 /*
352 * XXX for now we're always creating a temporary texture.
353 * Strictly speaking that's not always needed.
354 */
355
356 /* create temp texture */
357 memset(&texTemp, 0, sizeof(texTemp));
358 texTemp.target = PIPE_TEXTURE_2D;
359 texTemp.format = src->format;
360 texTemp.last_level = 0;
361 texTemp.width[0] = srcW;
362 texTemp.height[0] = srcH;
363 texTemp.depth[0] = 1;
364 texTemp.compressed = 0;
365 pf_get_block(src->format, &texTemp.block);
366
367 tex = screen->texture_create(screen, &texTemp);
368 if (!tex)
369 return;
370
371 texSurf = screen->get_tex_surface(screen, tex, 0, 0, 0,
372 PIPE_BUFFER_USAGE_GPU_WRITE);
373
374 /* load temp texture */
375 pipe->surface_copy(pipe, FALSE,
376 texSurf, 0, 0, /* dest */
377 src, srcLeft, srcTop, /* src */
378 srcW, srcH); /* size */
379
380 /* free the surface, update the texture if necessary.
381 */
382 screen->tex_surface_release(screen, &texSurf);
383
384 /* save state (restored below) */
385 cso_save_blend(ctx->cso);
386 cso_save_depth_stencil_alpha(ctx->cso);
387 cso_save_rasterizer(ctx->cso);
388 cso_save_samplers(ctx->cso);
389 cso_save_sampler_textures(ctx->cso);
390 cso_save_framebuffer(ctx->cso);
391 cso_save_fragment_shader(ctx->cso);
392 cso_save_vertex_shader(ctx->cso);
393 cso_save_viewport(ctx->cso);
394
395 /* set misc state we care about */
396 cso_set_blend(ctx->cso, &ctx->blend);
397 cso_set_depth_stencil_alpha(ctx->cso, &ctx->depthstencil);
398 cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
399 cso_set_viewport(ctx->cso, &ctx->viewport);
400
401 /* sampler */
402 ctx->sampler.min_img_filter = filter;
403 ctx->sampler.mag_img_filter = filter;
404 cso_single_sampler(ctx->cso, 0, &ctx->sampler);
405 cso_single_sampler_done(ctx->cso);
406
407 /* texture */
408 cso_set_sampler_textures(ctx->cso, 1, &tex);
409
410 /* shaders */
411 cso_set_fragment_shader_handle(ctx->cso, ctx->fs);
412 cso_set_vertex_shader_handle(ctx->cso, ctx->vs);
413
414 /* drawing dest */
415 memset(&fb, 0, sizeof(fb));
416 fb.width = dst->width;
417 fb.height = dst->height;
418 fb.nr_cbufs = 1;
419 fb.cbufs[0] = dst;
420 cso_set_framebuffer(ctx->cso, &fb);
421
422 /* draw quad */
423 offset = setup_vertex_data(ctx,
424 (float) dstX0, (float) dstY0,
425 (float) dstX1, (float) dstY1, z);
426
427 util_draw_vertex_buffer(ctx->pipe, ctx->vbuf, offset,
428 PIPE_PRIM_TRIANGLE_FAN,
429 4, /* verts */
430 2); /* attribs/vert */
431
432 /* restore state we changed */
433 cso_restore_blend(ctx->cso);
434 cso_restore_depth_stencil_alpha(ctx->cso);
435 cso_restore_rasterizer(ctx->cso);
436 cso_restore_samplers(ctx->cso);
437 cso_restore_sampler_textures(ctx->cso);
438 cso_restore_framebuffer(ctx->cso);
439 cso_restore_fragment_shader(ctx->cso);
440 cso_restore_vertex_shader(ctx->cso);
441 cso_restore_viewport(ctx->cso);
442
443 screen->texture_release(screen, &tex);
444 }
445
446
447 /* Release vertex buffer at end of frame to avoid synchronous
448 * rendering.
449 */
450 void util_blit_flush( struct blit_state *ctx )
451 {
452 pipe_buffer_reference(ctx->pipe->screen, &ctx->vbuf, NULL);
453 ctx->vbuf_slot = 0;
454 }
455
456
457
458 /**
459 * Copy pixel block from src texture to dst surface.
460 * Overlapping regions are acceptable.
461 *
462 * XXX Should support selection of level.
463 * XXX need some control over blitting Z and/or stencil.
464 */
465 void
466 util_blit_pixels_tex(struct blit_state *ctx,
467 struct pipe_texture *tex,
468 int srcX0, int srcY0,
469 int srcX1, int srcY1,
470 struct pipe_surface *dst,
471 int dstX0, int dstY0,
472 int dstX1, int dstY1,
473 float z, uint filter)
474 {
475 struct pipe_context *pipe = ctx->pipe;
476 struct pipe_screen *screen = pipe->screen;
477 struct pipe_framebuffer_state fb;
478 float s0, t0, s1, t1;
479 unsigned offset;
480
481 assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
482 filter == PIPE_TEX_MIPFILTER_LINEAR);
483
484 assert(tex->width[0] != 0);
485 assert(tex->height[0] != 0);
486
487 s0 = srcX0 / (float)tex->width[0];
488 s1 = srcX1 / (float)tex->width[0];
489 t0 = srcY0 / (float)tex->height[0];
490 t1 = srcY1 / (float)tex->height[0];
491
492 assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D,
493 PIPE_TEXTURE_USAGE_RENDER_TARGET, 0));
494
495 /* save state (restored below) */
496 cso_save_blend(ctx->cso);
497 cso_save_depth_stencil_alpha(ctx->cso);
498 cso_save_rasterizer(ctx->cso);
499 cso_save_samplers(ctx->cso);
500 cso_save_sampler_textures(ctx->cso);
501 cso_save_framebuffer(ctx->cso);
502 cso_save_fragment_shader(ctx->cso);
503 cso_save_vertex_shader(ctx->cso);
504 cso_save_viewport(ctx->cso);
505
506 /* set misc state we care about */
507 cso_set_blend(ctx->cso, &ctx->blend);
508 cso_set_depth_stencil_alpha(ctx->cso, &ctx->depthstencil);
509 cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
510 cso_set_viewport(ctx->cso, &ctx->viewport);
511
512 /* sampler */
513 ctx->sampler.min_img_filter = filter;
514 ctx->sampler.mag_img_filter = filter;
515 cso_single_sampler(ctx->cso, 0, &ctx->sampler);
516 cso_single_sampler_done(ctx->cso);
517
518 /* texture */
519 cso_set_sampler_textures(ctx->cso, 1, &tex);
520
521 /* shaders */
522 cso_set_fragment_shader_handle(ctx->cso, ctx->fs);
523 cso_set_vertex_shader_handle(ctx->cso, ctx->vs);
524
525 /* drawing dest */
526 memset(&fb, 0, sizeof(fb));
527 fb.width = dst->width;
528 fb.height = dst->height;
529 fb.nr_cbufs = 1;
530 fb.cbufs[0] = dst;
531 cso_set_framebuffer(ctx->cso, &fb);
532
533 /* draw quad */
534 offset = setup_vertex_data_tex(ctx,
535 (float) dstX0, (float) dstY0,
536 (float) dstX1, (float) dstY1,
537 s0, t0, s1, t1,
538 z);
539
540 util_draw_vertex_buffer(ctx->pipe,
541 ctx->vbuf, offset,
542 PIPE_PRIM_TRIANGLE_FAN,
543 4, /* verts */
544 2); /* attribs/vert */
545
546 /* restore state we changed */
547 cso_restore_blend(ctx->cso);
548 cso_restore_depth_stencil_alpha(ctx->cso);
549 cso_restore_rasterizer(ctx->cso);
550 cso_restore_samplers(ctx->cso);
551 cso_restore_sampler_textures(ctx->cso);
552 cso_restore_framebuffer(ctx->cso);
553 cso_restore_fragment_shader(ctx->cso);
554 cso_restore_vertex_shader(ctx->cso);
555 cso_restore_viewport(ctx->cso);
556 }