auxiliary: support using PIPE_TEXTURE_RECT internally
[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 "util/u_debug.h"
38 #include "pipe/p_defines.h"
39 #include "util/u_inlines.h"
40 #include "pipe/p_shader_tokens.h"
41 #include "pipe/p_state.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_sampler.h"
48 #include "util/u_simple_shaders.h"
49
50 #include "cso_cache/cso_context.h"
51
52
53 struct blit_state
54 {
55 struct pipe_context *pipe;
56 struct cso_context *cso;
57
58 struct pipe_blend_state blend;
59 struct pipe_depth_stencil_alpha_state depthstencil;
60 struct pipe_rasterizer_state rasterizer;
61 struct pipe_sampler_state sampler;
62 struct pipe_viewport_state viewport;
63 struct pipe_clip_state clip;
64 struct pipe_vertex_element velem[2];
65 enum pipe_texture_target internal_target;
66
67 void *vs;
68 void *fs[TGSI_WRITEMASK_XYZW + 1];
69
70 struct pipe_resource *vbuf; /**< quad vertices */
71 unsigned vbuf_slot;
72
73 float vertices[4][2][4]; /**< vertex/texcoords for quad */
74 };
75
76
77 /**
78 * Create state object for blit.
79 * Intended to be created once and re-used for many blit() calls.
80 */
81 struct blit_state *
82 util_create_blit(struct pipe_context *pipe, struct cso_context *cso)
83 {
84 struct blit_state *ctx;
85 uint i;
86
87 ctx = CALLOC_STRUCT(blit_state);
88 if (!ctx)
89 return NULL;
90
91 ctx->pipe = pipe;
92 ctx->cso = cso;
93
94 /* disabled blending/masking */
95 memset(&ctx->blend, 0, sizeof(ctx->blend));
96 ctx->blend.rt[0].colormask = PIPE_MASK_RGBA;
97
98 /* no-op depth/stencil/alpha */
99 memset(&ctx->depthstencil, 0, sizeof(ctx->depthstencil));
100
101 /* rasterizer */
102 memset(&ctx->rasterizer, 0, sizeof(ctx->rasterizer));
103 ctx->rasterizer.cull_face = PIPE_FACE_NONE;
104 ctx->rasterizer.gl_rasterization_rules = 1;
105
106 /* samplers */
107 memset(&ctx->sampler, 0, sizeof(ctx->sampler));
108 ctx->sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
109 ctx->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
110 ctx->sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
111 ctx->sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
112 ctx->sampler.min_img_filter = 0; /* set later */
113 ctx->sampler.mag_img_filter = 0; /* set later */
114
115 /* vertex elements state */
116 memset(&ctx->velem[0], 0, sizeof(ctx->velem[0]) * 2);
117 for (i = 0; i < 2; i++) {
118 ctx->velem[i].src_offset = i * 4 * sizeof(float);
119 ctx->velem[i].instance_divisor = 0;
120 ctx->velem[i].vertex_buffer_index = 0;
121 ctx->velem[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
122 }
123
124 /* vertex shader - still required to provide the linkage between
125 * fragment shader input semantics and vertex_element/buffers.
126 */
127 {
128 const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
129 TGSI_SEMANTIC_GENERIC };
130 const uint semantic_indexes[] = { 0, 0 };
131 ctx->vs = util_make_vertex_passthrough_shader(pipe, 2, semantic_names,
132 semantic_indexes);
133 }
134
135 /* fragment shader */
136 ctx->fs[TGSI_WRITEMASK_XYZW] =
137 util_make_fragment_tex_shader(pipe, TGSI_TEXTURE_2D,
138 TGSI_INTERPOLATE_LINEAR);
139 ctx->vbuf = NULL;
140
141 /* init vertex data that doesn't change */
142 for (i = 0; i < 4; i++) {
143 ctx->vertices[i][0][3] = 1.0f; /* w */
144 ctx->vertices[i][1][2] = 0.0f; /* r */
145 ctx->vertices[i][1][3] = 1.0f; /* q */
146 }
147
148 if(pipe->screen->get_param(pipe->screen, PIPE_CAP_NPOT_TEXTURES))
149 ctx->internal_target = PIPE_TEXTURE_2D;
150 else
151 ctx->internal_target = PIPE_TEXTURE_RECT;
152
153 return ctx;
154 }
155
156
157 /**
158 * Destroy a blit context
159 */
160 void
161 util_destroy_blit(struct blit_state *ctx)
162 {
163 struct pipe_context *pipe = ctx->pipe;
164 unsigned i;
165
166 pipe->delete_vs_state(pipe, ctx->vs);
167
168 for (i = 0; i < Elements(ctx->fs); i++)
169 if (ctx->fs[i])
170 pipe->delete_fs_state(pipe, ctx->fs[i]);
171
172 pipe_resource_reference(&ctx->vbuf, NULL);
173
174 FREE(ctx);
175 }
176
177
178 /**
179 * Get offset of next free slot in vertex buffer for quad vertices.
180 */
181 static unsigned
182 get_next_slot( struct blit_state *ctx )
183 {
184 const unsigned max_slots = 4096 / sizeof ctx->vertices;
185
186 if (ctx->vbuf_slot >= max_slots)
187 util_blit_flush( ctx );
188
189 if (!ctx->vbuf) {
190 ctx->vbuf = pipe_buffer_create(ctx->pipe->screen,
191 PIPE_BIND_VERTEX_BUFFER,
192 max_slots * sizeof ctx->vertices);
193 }
194
195 return ctx->vbuf_slot++ * sizeof ctx->vertices;
196 }
197
198
199
200
201 /**
202 * Setup vertex data for the textured quad we'll draw.
203 * Note: y=0=top
204 */
205 static unsigned
206 setup_vertex_data_tex(struct blit_state *ctx,
207 float x0, float y0, float x1, float y1,
208 float s0, float t0, float s1, float t1,
209 float z)
210 {
211 unsigned offset;
212
213 ctx->vertices[0][0][0] = x0;
214 ctx->vertices[0][0][1] = y0;
215 ctx->vertices[0][0][2] = z;
216 ctx->vertices[0][1][0] = s0; /*s*/
217 ctx->vertices[0][1][1] = t0; /*t*/
218
219 ctx->vertices[1][0][0] = x1;
220 ctx->vertices[1][0][1] = y0;
221 ctx->vertices[1][0][2] = z;
222 ctx->vertices[1][1][0] = s1; /*s*/
223 ctx->vertices[1][1][1] = t0; /*t*/
224
225 ctx->vertices[2][0][0] = x1;
226 ctx->vertices[2][0][1] = y1;
227 ctx->vertices[2][0][2] = z;
228 ctx->vertices[2][1][0] = s1;
229 ctx->vertices[2][1][1] = t1;
230
231 ctx->vertices[3][0][0] = x0;
232 ctx->vertices[3][0][1] = y1;
233 ctx->vertices[3][0][2] = z;
234 ctx->vertices[3][1][0] = s0;
235 ctx->vertices[3][1][1] = t1;
236
237 offset = get_next_slot( ctx );
238
239 pipe_buffer_write_nooverlap(ctx->pipe, ctx->vbuf,
240 offset, sizeof(ctx->vertices), ctx->vertices);
241
242 return offset;
243 }
244
245
246 /**
247 * \return TRUE if two regions overlap, FALSE otherwise
248 */
249 static boolean
250 regions_overlap(int srcX0, int srcY0,
251 int srcX1, int srcY1,
252 int dstX0, int dstY0,
253 int dstX1, int dstY1)
254 {
255 if (MAX2(srcX0, srcX1) < MIN2(dstX0, dstX1))
256 return FALSE; /* src completely left of dst */
257
258 if (MAX2(dstX0, dstX1) < MIN2(srcX0, srcX1))
259 return FALSE; /* dst completely left of src */
260
261 if (MAX2(srcY0, srcY1) < MIN2(dstY0, dstY1))
262 return FALSE; /* src completely above dst */
263
264 if (MAX2(dstY0, dstY1) < MIN2(srcY0, srcY1))
265 return FALSE; /* dst completely above src */
266
267 return TRUE; /* some overlap */
268 }
269
270
271 /**
272 * Copy pixel block from src surface to dst surface.
273 * Overlapping regions are acceptable.
274 * Flipping and stretching are supported.
275 * \param filter one of PIPE_TEX_MIPFILTER_NEAREST/LINEAR
276 * \param writemask controls which channels in the dest surface are sourced
277 * from the src surface. Disabled channels are sourced
278 * from (0,0,0,1).
279 * XXX need some control over blitting Z and/or stencil.
280 */
281 void
282 util_blit_pixels_writemask(struct blit_state *ctx,
283 struct pipe_resource *src_tex,
284 struct pipe_subresource srcsub,
285 int srcX0, int srcY0,
286 int srcX1, int srcY1,
287 int srcZ0,
288 struct pipe_surface *dst,
289 int dstX0, int dstY0,
290 int dstX1, int dstY1,
291 float z, uint filter,
292 uint writemask)
293 {
294 struct pipe_context *pipe = ctx->pipe;
295 struct pipe_screen *screen = pipe->screen;
296 struct pipe_sampler_view *sampler_view = NULL;
297 struct pipe_sampler_view sv_templ;
298 struct pipe_framebuffer_state fb;
299 const int srcW = abs(srcX1 - srcX0);
300 const int srcH = abs(srcY1 - srcY0);
301 unsigned offset;
302 boolean overlap;
303 float s0, t0, s1, t1;
304 boolean normalized;
305
306 assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
307 filter == PIPE_TEX_MIPFILTER_LINEAR);
308
309 assert(srcsub.level <= src_tex->last_level);
310
311 /* do the regions overlap? */
312 overlap = src_tex == dst->texture &&
313 dst->face == srcsub.face &&
314 dst->level == srcsub.level &&
315 dst->zslice == srcZ0 &&
316 regions_overlap(srcX0, srcY0, srcX1, srcY1,
317 dstX0, dstY0, dstX1, dstY1);
318
319 /*
320 * Check for simple case: no format conversion, no flipping, no stretching,
321 * no overlapping.
322 * Filter mode should not matter since there's no stretching.
323 */
324 if (dst->format == src_tex->format &&
325 srcX0 < srcX1 &&
326 dstX0 < dstX1 &&
327 srcY0 < srcY1 &&
328 dstY0 < dstY1 &&
329 (dstX1 - dstX0) == (srcX1 - srcX0) &&
330 (dstY1 - dstY0) == (srcY1 - srcY0) &&
331 !overlap) {
332 struct pipe_subresource subdst;
333 subdst.face = dst->face;
334 subdst.level = dst->level;
335 pipe->resource_copy_region(pipe,
336 dst->texture, subdst,
337 dstX0, dstY0, dst->zslice,/* dest */
338 src_tex, srcsub,
339 srcX0, srcY0, srcZ0,/* src */
340 srcW, srcH); /* size */
341 return;
342 }
343
344 /* Create a temporary texture when src and dest alias or when src
345 * is anything other than a 2d texture.
346 * XXX should just use appropriate shader to access 1d / 3d slice / cube face,
347 * much like the u_blitter code does (should be pretty trivial).
348 *
349 * This can still be improved upon.
350 */
351 if ((src_tex == dst->texture &&
352 dst->face == srcsub.face &&
353 dst->level == srcsub.level &&
354 dst->zslice == srcZ0) ||
355 (src_tex->target != PIPE_TEXTURE_2D &&
356 src_tex->target != PIPE_TEXTURE_RECT))
357 {
358 struct pipe_resource texTemp;
359 struct pipe_resource *tex;
360 struct pipe_sampler_view sv_templ;
361 struct pipe_subresource texsub;
362 const int srcLeft = MIN2(srcX0, srcX1);
363 const int srcTop = MIN2(srcY0, srcY1);
364
365 if (srcLeft != srcX0) {
366 /* left-right flip */
367 int tmp = dstX0;
368 dstX0 = dstX1;
369 dstX1 = tmp;
370 }
371
372 if (srcTop != srcY0) {
373 /* up-down flip */
374 int tmp = dstY0;
375 dstY0 = dstY1;
376 dstY1 = tmp;
377 }
378
379 /* create temp texture */
380 memset(&texTemp, 0, sizeof(texTemp));
381 texTemp.target = ctx->internal_target;
382 texTemp.format = src_tex->format;
383 texTemp.last_level = 0;
384 texTemp.width0 = srcW;
385 texTemp.height0 = srcH;
386 texTemp.depth0 = 1;
387 texTemp.bind = PIPE_BIND_SAMPLER_VIEW;
388
389 tex = screen->resource_create(screen, &texTemp);
390 if (!tex)
391 return;
392
393 texsub.face = 0;
394 texsub.level = 0;
395 /* load temp texture */
396 pipe->resource_copy_region(pipe,
397 tex, texsub, 0, 0, 0, /* dest */
398 src_tex, srcsub, srcLeft, srcTop, srcZ0, /* src */
399 srcW, srcH); /* size */
400
401 normalized = tex->target != PIPE_TEXTURE_RECT;
402 if(normalized) {
403 s0 = 0.0f;
404 s1 = 1.0f;
405 t0 = 0.0f;
406 t1 = 1.0f;
407 }
408 else {
409 s0 = 0;
410 s1 = srcW;
411 t0 = 0;
412 t1 = srcH;
413 }
414
415 u_sampler_view_default_template(&sv_templ, tex, tex->format);
416 sampler_view = pipe->create_sampler_view(pipe, tex, &sv_templ);
417
418 if (!sampler_view) {
419 pipe_resource_reference(&tex, NULL);
420 return;
421 }
422 pipe_resource_reference(&tex, NULL);
423 }
424 else {
425 u_sampler_view_default_template(&sv_templ, src_tex, src_tex->format);
426 sv_templ.first_level = sv_templ.last_level = srcsub.level;
427 sampler_view = pipe->create_sampler_view(pipe, src_tex, &sv_templ);
428
429 if (!sampler_view) {
430 return;
431 }
432
433 s0 = srcX0;
434 s1 = srcX1;
435 t0 = srcY0;
436 t1 = srcY1;
437 normalized = sampler_view->texture->target != PIPE_TEXTURE_RECT;
438 if(normalized)
439 {
440 s0 /= (float)(u_minify(sampler_view->texture->width0, srcsub.level));
441 s1 /= (float)(u_minify(sampler_view->texture->width0, srcsub.level));
442 t0 /= (float)(u_minify(sampler_view->texture->height0, srcsub.level));
443 t1 /= (float)(u_minify(sampler_view->texture->height0, srcsub.level));
444 }
445 }
446
447
448 assert(screen->is_format_supported(screen, sampler_view->format, ctx->internal_target,
449 sampler_view->texture->nr_samples,
450 PIPE_BIND_SAMPLER_VIEW, 0));
451 assert(screen->is_format_supported(screen, dst->format, ctx->internal_target,
452 dst->texture->nr_samples,
453 PIPE_BIND_RENDER_TARGET, 0));
454
455 /* save state (restored below) */
456 cso_save_blend(ctx->cso);
457 cso_save_depth_stencil_alpha(ctx->cso);
458 cso_save_rasterizer(ctx->cso);
459 cso_save_samplers(ctx->cso);
460 cso_save_fragment_sampler_views(ctx->cso);
461 cso_save_viewport(ctx->cso);
462 cso_save_framebuffer(ctx->cso);
463 cso_save_fragment_shader(ctx->cso);
464 cso_save_vertex_shader(ctx->cso);
465 cso_save_clip(ctx->cso);
466 cso_save_vertex_elements(ctx->cso);
467
468 /* set misc state we care about */
469 cso_set_blend(ctx->cso, &ctx->blend);
470 cso_set_depth_stencil_alpha(ctx->cso, &ctx->depthstencil);
471 cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
472 cso_set_clip(ctx->cso, &ctx->clip);
473 cso_set_vertex_elements(ctx->cso, 2, ctx->velem);
474
475 /* sampler */
476 ctx->sampler.normalized_coords = normalized;
477 ctx->sampler.min_img_filter = filter;
478 ctx->sampler.mag_img_filter = filter;
479 /* we've limited this already with the sampler view but you never know... */
480 ctx->sampler.min_lod = srcsub.level;
481 ctx->sampler.max_lod = srcsub.level;
482 cso_single_sampler(ctx->cso, 0, &ctx->sampler);
483 cso_single_sampler_done(ctx->cso);
484
485 /* viewport */
486 ctx->viewport.scale[0] = 0.5f * dst->width;
487 ctx->viewport.scale[1] = 0.5f * dst->height;
488 ctx->viewport.scale[2] = 0.5f;
489 ctx->viewport.scale[3] = 1.0f;
490 ctx->viewport.translate[0] = 0.5f * dst->width;
491 ctx->viewport.translate[1] = 0.5f * dst->height;
492 ctx->viewport.translate[2] = 0.5f;
493 ctx->viewport.translate[3] = 0.0f;
494 cso_set_viewport(ctx->cso, &ctx->viewport);
495
496 /* texture */
497 cso_set_fragment_sampler_views(ctx->cso, 1, &sampler_view);
498
499 if (ctx->fs[writemask] == NULL)
500 ctx->fs[writemask] =
501 util_make_fragment_tex_shader_writemask(pipe, TGSI_TEXTURE_2D,
502 TGSI_INTERPOLATE_LINEAR,
503 writemask);
504
505 /* shaders */
506 cso_set_fragment_shader_handle(ctx->cso, ctx->fs[writemask]);
507 cso_set_vertex_shader_handle(ctx->cso, ctx->vs);
508
509 /* drawing dest */
510 memset(&fb, 0, sizeof(fb));
511 fb.width = dst->width;
512 fb.height = dst->height;
513 fb.nr_cbufs = 1;
514 fb.cbufs[0] = dst;
515 cso_set_framebuffer(ctx->cso, &fb);
516
517 /* draw quad */
518 offset = setup_vertex_data_tex(ctx,
519 (float) dstX0 / dst->width * 2.0f - 1.0f,
520 (float) dstY0 / dst->height * 2.0f - 1.0f,
521 (float) dstX1 / dst->width * 2.0f - 1.0f,
522 (float) dstY1 / dst->height * 2.0f - 1.0f,
523 s0, t0,
524 s1, t1,
525 z);
526
527 util_draw_vertex_buffer(ctx->pipe, ctx->vbuf, offset,
528 PIPE_PRIM_TRIANGLE_FAN,
529 4, /* verts */
530 2); /* attribs/vert */
531
532 /* restore state we changed */
533 cso_restore_blend(ctx->cso);
534 cso_restore_depth_stencil_alpha(ctx->cso);
535 cso_restore_rasterizer(ctx->cso);
536 cso_restore_samplers(ctx->cso);
537 cso_restore_fragment_sampler_views(ctx->cso);
538 cso_restore_viewport(ctx->cso);
539 cso_restore_framebuffer(ctx->cso);
540 cso_restore_fragment_shader(ctx->cso);
541 cso_restore_vertex_shader(ctx->cso);
542 cso_restore_clip(ctx->cso);
543 cso_restore_vertex_elements(ctx->cso);
544
545 pipe_sampler_view_reference(&sampler_view, NULL);
546 }
547
548
549 void
550 util_blit_pixels(struct blit_state *ctx,
551 struct pipe_resource *src_tex,
552 struct pipe_subresource srcsub,
553 int srcX0, int srcY0,
554 int srcX1, int srcY1,
555 int srcZ,
556 struct pipe_surface *dst,
557 int dstX0, int dstY0,
558 int dstX1, int dstY1,
559 float z, uint filter )
560 {
561 util_blit_pixels_writemask( ctx, src_tex,
562 srcsub,
563 srcX0, srcY0,
564 srcX1, srcY1,
565 srcZ,
566 dst,
567 dstX0, dstY0,
568 dstX1, dstY1,
569 z, filter,
570 TGSI_WRITEMASK_XYZW );
571 }
572
573
574 /* Release vertex buffer at end of frame to avoid synchronous
575 * rendering.
576 */
577 void util_blit_flush( struct blit_state *ctx )
578 {
579 pipe_resource_reference(&ctx->vbuf, NULL);
580 ctx->vbuf_slot = 0;
581 }
582
583
584
585 /**
586 * Copy pixel block from src texture to dst surface.
587 *
588 * XXX Should support selection of level.
589 * XXX need some control over blitting Z and/or stencil.
590 */
591 void
592 util_blit_pixels_tex(struct blit_state *ctx,
593 struct pipe_sampler_view *src_sampler_view,
594 int srcX0, int srcY0,
595 int srcX1, int srcY1,
596 struct pipe_surface *dst,
597 int dstX0, int dstY0,
598 int dstX1, int dstY1,
599 float z, uint filter)
600 {
601 boolean normalized = src_sampler_view->texture->target != PIPE_TEXTURE_RECT;
602 struct pipe_framebuffer_state fb;
603 float s0, t0, s1, t1;
604 unsigned offset;
605 struct pipe_resource *tex = src_sampler_view->texture;
606
607 assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
608 filter == PIPE_TEX_MIPFILTER_LINEAR);
609
610 assert(tex);
611 assert(tex->width0 != 0);
612 assert(tex->height0 != 0);
613
614 s0 = srcX0;
615 s1 = srcX1;
616 t0 = srcY0;
617 t1 = srcY1;
618
619 if(normalized)
620 {
621 s0 /= (float)tex->width0;
622 s1 /= (float)tex->width0;
623 t0 /= (float)tex->height0;
624 t1 /= (float)tex->height0;
625 }
626
627 assert(ctx->pipe->screen->is_format_supported(ctx->pipe->screen, dst->format,
628 PIPE_TEXTURE_2D,
629 dst->texture->nr_samples,
630 PIPE_BIND_RENDER_TARGET,
631 0));
632
633 /* save state (restored below) */
634 cso_save_blend(ctx->cso);
635 cso_save_depth_stencil_alpha(ctx->cso);
636 cso_save_rasterizer(ctx->cso);
637 cso_save_samplers(ctx->cso);
638 cso_save_fragment_sampler_views(ctx->cso);
639 cso_save_framebuffer(ctx->cso);
640 cso_save_fragment_shader(ctx->cso);
641 cso_save_vertex_shader(ctx->cso);
642 cso_save_clip(ctx->cso);
643 cso_save_vertex_elements(ctx->cso);
644
645 /* set misc state we care about */
646 cso_set_blend(ctx->cso, &ctx->blend);
647 cso_set_depth_stencil_alpha(ctx->cso, &ctx->depthstencil);
648 cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
649 cso_set_clip(ctx->cso, &ctx->clip);
650 cso_set_vertex_elements(ctx->cso, 2, ctx->velem);
651
652 /* sampler */
653 ctx->sampler.normalized_coords = normalized;
654 ctx->sampler.min_img_filter = filter;
655 ctx->sampler.mag_img_filter = filter;
656 cso_single_sampler(ctx->cso, 0, &ctx->sampler);
657 cso_single_sampler_done(ctx->cso);
658
659 /* viewport */
660 ctx->viewport.scale[0] = 0.5f * dst->width;
661 ctx->viewport.scale[1] = 0.5f * dst->height;
662 ctx->viewport.scale[2] = 0.5f;
663 ctx->viewport.scale[3] = 1.0f;
664 ctx->viewport.translate[0] = 0.5f * dst->width;
665 ctx->viewport.translate[1] = 0.5f * dst->height;
666 ctx->viewport.translate[2] = 0.5f;
667 ctx->viewport.translate[3] = 0.0f;
668 cso_set_viewport(ctx->cso, &ctx->viewport);
669
670 /* texture */
671 cso_set_fragment_sampler_views(ctx->cso, 1, &src_sampler_view);
672
673 /* shaders */
674 cso_set_fragment_shader_handle(ctx->cso, ctx->fs[TGSI_WRITEMASK_XYZW]);
675 cso_set_vertex_shader_handle(ctx->cso, ctx->vs);
676
677 /* drawing dest */
678 memset(&fb, 0, sizeof(fb));
679 fb.width = dst->width;
680 fb.height = dst->height;
681 fb.nr_cbufs = 1;
682 fb.cbufs[0] = dst;
683 cso_set_framebuffer(ctx->cso, &fb);
684
685 /* draw quad */
686 offset = setup_vertex_data_tex(ctx,
687 (float) dstX0 / dst->width * 2.0f - 1.0f,
688 (float) dstY0 / dst->height * 2.0f - 1.0f,
689 (float) dstX1 / dst->width * 2.0f - 1.0f,
690 (float) dstY1 / dst->height * 2.0f - 1.0f,
691 s0, t0, s1, t1,
692 z);
693
694 util_draw_vertex_buffer(ctx->pipe,
695 ctx->vbuf, offset,
696 PIPE_PRIM_TRIANGLE_FAN,
697 4, /* verts */
698 2); /* attribs/vert */
699
700 /* restore state we changed */
701 cso_restore_blend(ctx->cso);
702 cso_restore_depth_stencil_alpha(ctx->cso);
703 cso_restore_rasterizer(ctx->cso);
704 cso_restore_samplers(ctx->cso);
705 cso_restore_fragment_sampler_views(ctx->cso);
706 cso_restore_framebuffer(ctx->cso);
707 cso_restore_fragment_shader(ctx->cso);
708 cso_restore_vertex_shader(ctx->cso);
709 cso_restore_clip(ctx->cso);
710 cso_restore_vertex_elements(ctx->cso);
711 }