Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4358 Serge 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_format.h"
46
#include "util/u_math.h"
47
#include "util/u_memory.h"
48
#include "util/u_sampler.h"
49
#include "util/u_simple_shaders.h"
50
 
51
#include "cso_cache/cso_context.h"
52
 
53
 
54
struct blit_state
55
{
56
   struct pipe_context *pipe;
57
   struct cso_context *cso;
58
 
59
   struct pipe_blend_state blend_write_color, blend_keep_color;
60
   struct pipe_depth_stencil_alpha_state dsa_keep_depthstencil;
61
   struct pipe_depth_stencil_alpha_state dsa_write_depthstencil;
62
   struct pipe_depth_stencil_alpha_state dsa_write_depth;
63
   struct pipe_depth_stencil_alpha_state dsa_write_stencil;
64
   struct pipe_rasterizer_state rasterizer;
65
   struct pipe_sampler_state sampler;
66
   struct pipe_viewport_state viewport;
67
   struct pipe_vertex_element velem[2];
68
   enum pipe_texture_target internal_target;
69
 
70
   void *vs;
71
   void *fs[PIPE_MAX_TEXTURE_TYPES][TGSI_WRITEMASK_XYZW + 1];
72
   void *fs_depthstencil[PIPE_MAX_TEXTURE_TYPES];
73
   void *fs_depth[PIPE_MAX_TEXTURE_TYPES];
74
   void *fs_stencil[PIPE_MAX_TEXTURE_TYPES];
75
 
76
   struct pipe_resource *vbuf;  /**< quad vertices */
77
   unsigned vbuf_slot;
78
 
79
   float vertices[4][2][4];   /**< vertex/texcoords for quad */
80
 
81
   boolean has_stencil_export;
82
};
83
 
84
 
85
/**
86
 * Create state object for blit.
87
 * Intended to be created once and re-used for many blit() calls.
88
 */
89
struct blit_state *
90
util_create_blit(struct pipe_context *pipe, struct cso_context *cso)
91
{
92
   struct blit_state *ctx;
93
   uint i;
94
 
95
   ctx = CALLOC_STRUCT(blit_state);
96
   if (!ctx)
97
      return NULL;
98
 
99
   ctx->pipe = pipe;
100
   ctx->cso = cso;
101
 
102
   /* disabled blending/masking */
103
   ctx->blend_write_color.rt[0].colormask = PIPE_MASK_RGBA;
104
 
105
   /* depth stencil states */
106
   ctx->dsa_write_depth.depth.enabled = 1;
107
   ctx->dsa_write_depth.depth.writemask = 1;
108
   ctx->dsa_write_depth.depth.func = PIPE_FUNC_ALWAYS;
109
   ctx->dsa_write_stencil.stencil[0].enabled = 1;
110
   ctx->dsa_write_stencil.stencil[0].func = PIPE_FUNC_ALWAYS;
111
   ctx->dsa_write_stencil.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
112
   ctx->dsa_write_stencil.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
113
   ctx->dsa_write_stencil.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
114
   ctx->dsa_write_stencil.stencil[0].valuemask = 0xff;
115
   ctx->dsa_write_stencil.stencil[0].writemask = 0xff;
116
   ctx->dsa_write_depthstencil.depth = ctx->dsa_write_depth.depth;
117
   ctx->dsa_write_depthstencil.stencil[0] = ctx->dsa_write_stencil.stencil[0];
118
 
119
   /* rasterizer */
120
   ctx->rasterizer.cull_face = PIPE_FACE_NONE;
121
   ctx->rasterizer.half_pixel_center = 1;
122
   ctx->rasterizer.bottom_edge_rule = 1;
123
   ctx->rasterizer.depth_clip = 1;
124
 
125
   /* samplers */
126
   ctx->sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
127
   ctx->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
128
   ctx->sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
129
   ctx->sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
130
   ctx->sampler.min_img_filter = 0; /* set later */
131
   ctx->sampler.mag_img_filter = 0; /* set later */
132
 
133
   /* vertex elements state */
134
   for (i = 0; i < 2; i++) {
135
      ctx->velem[i].src_offset = i * 4 * sizeof(float);
136
      ctx->velem[i].instance_divisor = 0;
137
      ctx->velem[i].vertex_buffer_index = cso_get_aux_vertex_buffer_slot(cso);
138
      ctx->velem[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
139
   }
140
 
141
   ctx->vbuf = NULL;
142
 
143
   /* init vertex data that doesn't change */
144
   for (i = 0; i < 4; i++) {
145
      ctx->vertices[i][0][3] = 1.0f; /* w */
146
      ctx->vertices[i][1][2] = 0.0f; /* r */
147
      ctx->vertices[i][1][3] = 1.0f; /* q */
148
   }
149
 
150
   if(pipe->screen->get_param(pipe->screen, PIPE_CAP_NPOT_TEXTURES))
151
      ctx->internal_target = PIPE_TEXTURE_2D;
152
   else
153
      ctx->internal_target = PIPE_TEXTURE_RECT;
154
 
155
   ctx->has_stencil_export =
156
      pipe->screen->get_param(pipe->screen, PIPE_CAP_SHADER_STENCIL_EXPORT);
157
 
158
   return ctx;
159
}
160
 
161
 
162
/**
163
 * Destroy a blit context
164
 */
165
void
166
util_destroy_blit(struct blit_state *ctx)
167
{
168
   struct pipe_context *pipe = ctx->pipe;
169
   unsigned i, j;
170
 
171
   if (ctx->vs)
172
      pipe->delete_vs_state(pipe, ctx->vs);
173
 
174
   for (i = 0; i < Elements(ctx->fs); i++) {
175
      for (j = 0; j < Elements(ctx->fs[i]); j++) {
176
         if (ctx->fs[i][j])
177
            pipe->delete_fs_state(pipe, ctx->fs[i][j]);
178
      }
179
   }
180
 
181
   for (i = 0; i < PIPE_MAX_TEXTURE_TYPES; i++) {
182
      if (ctx->fs_depthstencil[i]) {
183
         pipe->delete_fs_state(pipe, ctx->fs_depthstencil[i]);
184
      }
185
      if (ctx->fs_depth[i]) {
186
         pipe->delete_fs_state(pipe, ctx->fs_depth[i]);
187
      }
188
      if (ctx->fs_stencil[i]) {
189
         pipe->delete_fs_state(pipe, ctx->fs_stencil[i]);
190
      }
191
   }
192
 
193
   pipe_resource_reference(&ctx->vbuf, NULL);
194
 
195
   FREE(ctx);
196
}
197
 
198
 
199
/**
200
 * Helper function to set the fragment shaders.
201
 */
202
static INLINE void
203
set_fragment_shader(struct blit_state *ctx, uint writemask,
204
                    enum pipe_texture_target pipe_tex)
205
{
206
   if (!ctx->fs[pipe_tex][writemask]) {
207
      unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(pipe_tex, 0);
208
 
209
      ctx->fs[pipe_tex][writemask] =
210
         util_make_fragment_tex_shader_writemask(ctx->pipe, tgsi_tex,
211
                                                 TGSI_INTERPOLATE_LINEAR,
212
                                                 writemask);
213
   }
214
 
215
   cso_set_fragment_shader_handle(ctx->cso, ctx->fs[pipe_tex][writemask]);
216
}
217
 
218
 
219
/**
220
 * Helper function to set the shader which writes depth and stencil.
221
 */
222
static INLINE void
223
set_depthstencil_fragment_shader(struct blit_state *ctx,
224
                                 enum pipe_texture_target pipe_tex)
225
{
226
   if (!ctx->fs_depthstencil[pipe_tex]) {
227
      unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(pipe_tex, 0);
228
 
229
      ctx->fs_depthstencil[pipe_tex] =
230
         util_make_fragment_tex_shader_writedepthstencil(ctx->pipe, tgsi_tex,
231
                                                  TGSI_INTERPOLATE_LINEAR);
232
   }
233
 
234
   cso_set_fragment_shader_handle(ctx->cso, ctx->fs_depthstencil[pipe_tex]);
235
}
236
 
237
 
238
/**
239
 * Helper function to set the shader which writes depth.
240
 */
241
static INLINE void
242
set_depth_fragment_shader(struct blit_state *ctx,
243
                          enum pipe_texture_target pipe_tex)
244
{
245
   if (!ctx->fs_depth[pipe_tex]) {
246
      unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(pipe_tex, 0);
247
 
248
      ctx->fs_depth[pipe_tex] =
249
         util_make_fragment_tex_shader_writedepth(ctx->pipe, tgsi_tex,
250
                                                  TGSI_INTERPOLATE_LINEAR);
251
   }
252
 
253
   cso_set_fragment_shader_handle(ctx->cso, ctx->fs_depth[pipe_tex]);
254
}
255
 
256
 
257
/**
258
 * Helper function to set the shader which writes stencil.
259
 */
260
static INLINE void
261
set_stencil_fragment_shader(struct blit_state *ctx,
262
                            enum pipe_texture_target pipe_tex)
263
{
264
   if (!ctx->fs_stencil[pipe_tex]) {
265
      unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(pipe_tex, 0);
266
 
267
      ctx->fs_stencil[pipe_tex] =
268
         util_make_fragment_tex_shader_writestencil(ctx->pipe, tgsi_tex,
269
                                                    TGSI_INTERPOLATE_LINEAR);
270
   }
271
 
272
   cso_set_fragment_shader_handle(ctx->cso, ctx->fs_stencil[pipe_tex]);
273
}
274
 
275
 
276
/**
277
 * Helper function to set the vertex shader.
278
 */
279
static INLINE void
280
set_vertex_shader(struct blit_state *ctx)
281
{
282
   /* vertex shader - still required to provide the linkage between
283
    * fragment shader input semantics and vertex_element/buffers.
284
    */
285
   if (!ctx->vs) {
286
      const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
287
                                      TGSI_SEMANTIC_GENERIC };
288
      const uint semantic_indexes[] = { 0, 0 };
289
      ctx->vs = util_make_vertex_passthrough_shader(ctx->pipe, 2,
290
                                                    semantic_names,
291
                                                    semantic_indexes);
292
   }
293
 
294
   cso_set_vertex_shader_handle(ctx->cso, ctx->vs);
295
}
296
 
297
 
298
/**
299
 * Get offset of next free slot in vertex buffer for quad vertices.
300
 */
301
static unsigned
302
get_next_slot( struct blit_state *ctx )
303
{
304
   const unsigned max_slots = 4096 / sizeof ctx->vertices;
305
 
306
   if (ctx->vbuf_slot >= max_slots) {
307
      pipe_resource_reference(&ctx->vbuf, NULL);
308
      ctx->vbuf_slot = 0;
309
   }
310
 
311
   if (!ctx->vbuf) {
312
      ctx->vbuf = pipe_buffer_create(ctx->pipe->screen,
313
                                     PIPE_BIND_VERTEX_BUFFER,
314
                                     PIPE_USAGE_STREAM,
315
                                     max_slots * sizeof ctx->vertices);
316
   }
317
 
318
   return ctx->vbuf_slot++ * sizeof ctx->vertices;
319
}
320
 
321
 
322
 
323
 
324
/**
325
 * Setup vertex data for the textured quad we'll draw.
326
 * Note: y=0=top
327
 */
328
static unsigned
329
setup_vertex_data_tex(struct blit_state *ctx,
330
                      float x0, float y0, float x1, float y1,
331
                      float s0, float t0, float s1, float t1,
332
                      float z)
333
{
334
   unsigned offset;
335
 
336
   ctx->vertices[0][0][0] = x0;
337
   ctx->vertices[0][0][1] = y0;
338
   ctx->vertices[0][0][2] = z;
339
   ctx->vertices[0][1][0] = s0; /*s*/
340
   ctx->vertices[0][1][1] = t0; /*t*/
341
 
342
   ctx->vertices[1][0][0] = x1;
343
   ctx->vertices[1][0][1] = y0;
344
   ctx->vertices[1][0][2] = z;
345
   ctx->vertices[1][1][0] = s1; /*s*/
346
   ctx->vertices[1][1][1] = t0; /*t*/
347
 
348
   ctx->vertices[2][0][0] = x1;
349
   ctx->vertices[2][0][1] = y1;
350
   ctx->vertices[2][0][2] = z;
351
   ctx->vertices[2][1][0] = s1;
352
   ctx->vertices[2][1][1] = t1;
353
 
354
   ctx->vertices[3][0][0] = x0;
355
   ctx->vertices[3][0][1] = y1;
356
   ctx->vertices[3][0][2] = z;
357
   ctx->vertices[3][1][0] = s0;
358
   ctx->vertices[3][1][1] = t1;
359
 
360
   offset = get_next_slot( ctx );
361
 
362
   if (ctx->vbuf) {
363
      pipe_buffer_write_nooverlap(ctx->pipe, ctx->vbuf,
364
                                  offset, sizeof(ctx->vertices), ctx->vertices);
365
   }
366
 
367
   return offset;
368
}
369
 
370
 
371
/**
372
 * \return TRUE if two regions overlap, FALSE otherwise
373
 */
374
static boolean
375
regions_overlap(int srcX0, int srcY0,
376
                int srcX1, int srcY1,
377
                int dstX0, int dstY0,
378
                int dstX1, int dstY1)
379
{
380
   if (MAX2(srcX0, srcX1) < MIN2(dstX0, dstX1))
381
      return FALSE; /* src completely left of dst */
382
 
383
   if (MAX2(dstX0, dstX1) < MIN2(srcX0, srcX1))
384
      return FALSE; /* dst completely left of src */
385
 
386
   if (MAX2(srcY0, srcY1) < MIN2(dstY0, dstY1))
387
      return FALSE; /* src completely above dst */
388
 
389
   if (MAX2(dstY0, dstY1) < MIN2(srcY0, srcY1))
390
      return FALSE; /* dst completely above src */
391
 
392
   return TRUE; /* some overlap */
393
}
394
 
395
 
396
/**
397
 * Can we blit from src format to dest format with a simple copy?
398
 */
399
static boolean
400
formats_compatible(enum pipe_format src_format,
401
                   enum pipe_format dst_format)
402
{
403
   if (src_format == dst_format) {
404
      return TRUE;
405
   }
406
   else {
407
      const struct util_format_description *src_desc =
408
         util_format_description(src_format);
409
      const struct util_format_description *dst_desc =
410
         util_format_description(dst_format);
411
      return util_is_format_compatible(src_desc, dst_desc);
412
   }
413
}
414
 
415
 
416
/**
417
 * Copy pixel block from src surface to dst surface.
418
 * Overlapping regions are acceptable.
419
 * Flipping and stretching are supported.
420
 * \param filter  one of PIPE_TEX_MIPFILTER_NEAREST/LINEAR
421
 * \param writemask  controls which channels in the dest surface are sourced
422
 *                   from the src surface.  Disabled channels are sourced
423
 *                   from (0,0,0,1).
424
 */
425
void
426
util_blit_pixels(struct blit_state *ctx,
427
                 struct pipe_resource *src_tex,
428
                 unsigned src_level,
429
                 int srcX0, int srcY0,
430
                 int srcX1, int srcY1,
431
                 int srcZ0,
432
                 struct pipe_surface *dst,
433
                 int dstX0, int dstY0,
434
                 int dstX1, int dstY1,
435
                 float z, uint filter,
436
                 uint writemask, uint zs_writemask)
437
{
438
   struct pipe_context *pipe = ctx->pipe;
439
   struct pipe_screen *screen = pipe->screen;
440
   enum pipe_format src_format, dst_format;
441
   struct pipe_sampler_view *sampler_view = NULL;
442
   struct pipe_sampler_view sv_templ;
443
   struct pipe_surface *dst_surface;
444
   struct pipe_framebuffer_state fb;
445
   const int srcW = abs(srcX1 - srcX0);
446
   const int srcH = abs(srcY1 - srcY0);
447
   unsigned offset;
448
   boolean overlap;
449
   float s0, t0, s1, t1;
450
   boolean normalized;
451
   boolean is_stencil, is_depth, blit_depth, blit_stencil;
452
   const struct util_format_description *src_desc =
453
         util_format_description(src_tex->format);
454
 
455
   assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
456
          filter == PIPE_TEX_MIPFILTER_LINEAR);
457
 
458
   assert(src_level <= src_tex->last_level);
459
 
460
   /* do the regions overlap? */
461
   overlap = src_tex == dst->texture &&
462
             dst->u.tex.level == src_level &&
463
             dst->u.tex.first_layer == srcZ0 &&
464
      regions_overlap(srcX0, srcY0, srcX1, srcY1,
465
                      dstX0, dstY0, dstX1, dstY1);
466
 
467
   src_format = util_format_linear(src_tex->format);
468
   dst_format = util_format_linear(dst->texture->format);
469
 
470
   /* See whether we will blit depth or stencil. */
471
   is_depth = util_format_has_depth(src_desc);
472
   is_stencil = util_format_has_stencil(src_desc);
473
 
474
   blit_depth = is_depth && (zs_writemask & BLIT_WRITEMASK_Z);
475
   blit_stencil = is_stencil && (zs_writemask & BLIT_WRITEMASK_STENCIL);
476
 
477
   assert((writemask && !zs_writemask && !is_depth && !is_stencil) ||
478
          (!writemask && (blit_depth || blit_stencil)));
479
 
480
   /*
481
    * Check for simple case:  no format conversion, no flipping, no stretching,
482
    * no overlapping, same number of samples.
483
    * Filter mode should not matter since there's no stretching.
484
    */
485
   if (formats_compatible(src_format, dst_format) &&
486
       src_tex->nr_samples == dst->texture->nr_samples &&
487
       is_stencil == blit_stencil &&
488
       is_depth == blit_depth &&
489
       srcX0 < srcX1 &&
490
       dstX0 < dstX1 &&
491
       srcY0 < srcY1 &&
492
       dstY0 < dstY1 &&
493
       (dstX1 - dstX0) == (srcX1 - srcX0) &&
494
       (dstY1 - dstY0) == (srcY1 - srcY0) &&
495
       !overlap) {
496
      struct pipe_box src_box;
497
      src_box.x = srcX0;
498
      src_box.y = srcY0;
499
      src_box.z = srcZ0;
500
      src_box.width = srcW;
501
      src_box.height = srcH;
502
      src_box.depth = 1;
503
      pipe->resource_copy_region(pipe,
504
                                 dst->texture, dst->u.tex.level,
505
                                 dstX0, dstY0, dst->u.tex.first_layer,/* dest */
506
                                 src_tex, src_level,
507
                                 &src_box);
508
      return;
509
   }
510
 
511
   /* XXX Reading multisample textures is unimplemented. */
512
   assert(src_tex->nr_samples <= 1);
513
   if (src_tex->nr_samples > 1) {
514
      return;
515
   }
516
 
517
   /* It's a mistake to call this function with a stencil format and
518
    * without shader stencil export. We don't do software fallbacks here.
519
    * Ignore stencil and only copy depth.
520
    */
521
   if (blit_stencil && !ctx->has_stencil_export) {
522
      blit_stencil = FALSE;
523
 
524
      if (!blit_depth)
525
         return;
526
   }
527
 
528
   if (dst_format == dst->format) {
529
      dst_surface = dst;
530
   } else {
531
      struct pipe_surface templ = *dst;
532
      templ.format = dst_format;
533
      dst_surface = pipe->create_surface(pipe, dst->texture, &templ);
534
   }
535
 
536
   /* Create a temporary texture when src and dest alias.
537
    */
538
   if (src_tex == dst_surface->texture &&
539
       dst_surface->u.tex.level == src_level &&
540
       dst_surface->u.tex.first_layer == srcZ0) {
541
      /* Make a temporary texture which contains a copy of the source pixels.
542
       * Then we'll sample from the temporary texture.
543
       */
544
      struct pipe_resource texTemp;
545
      struct pipe_resource *tex;
546
      struct pipe_sampler_view sv_templ;
547
      struct pipe_box src_box;
548
      const int srcLeft = MIN2(srcX0, srcX1);
549
      const int srcTop = MIN2(srcY0, srcY1);
550
 
551
      if (srcLeft != srcX0) {
552
         /* left-right flip */
553
         int tmp = dstX0;
554
         dstX0 = dstX1;
555
         dstX1 = tmp;
556
      }
557
 
558
      if (srcTop != srcY0) {
559
         /* up-down flip */
560
         int tmp = dstY0;
561
         dstY0 = dstY1;
562
         dstY1 = tmp;
563
      }
564
 
565
      /* create temp texture */
566
      memset(&texTemp, 0, sizeof(texTemp));
567
      texTemp.target = ctx->internal_target;
568
      texTemp.format = src_format;
569
      texTemp.last_level = 0;
570
      texTemp.width0 = srcW;
571
      texTemp.height0 = srcH;
572
      texTemp.depth0 = 1;
573
      texTemp.array_size = 1;
574
      texTemp.bind = PIPE_BIND_SAMPLER_VIEW;
575
 
576
      tex = screen->resource_create(screen, &texTemp);
577
      if (!tex)
578
         return;
579
 
580
      src_box.x = srcLeft;
581
      src_box.y = srcTop;
582
      src_box.z = srcZ0;
583
      src_box.width = srcW;
584
      src_box.height = srcH;
585
      src_box.depth = 1;
586
      /* load temp texture */
587
      pipe->resource_copy_region(pipe,
588
                                 tex, 0, 0, 0, 0,  /* dest */
589
                                 src_tex, src_level, &src_box);
590
 
591
      normalized = tex->target != PIPE_TEXTURE_RECT;
592
      if(normalized) {
593
         s0 = 0.0f;
594
         s1 = 1.0f;
595
         t0 = 0.0f;
596
         t1 = 1.0f;
597
      }
598
      else {
599
         s0 = 0.0f;
600
         s1 = (float) srcW;
601
         t0 = 0.0f;
602
         t1 = (float) srcH;
603
      }
604
 
605
      u_sampler_view_default_template(&sv_templ, tex, tex->format);
606
      if (!blit_depth && blit_stencil) {
607
         /* set a stencil-only format, e.g. Z24S8 --> X24S8 */
608
         sv_templ.format = util_format_stencil_only(tex->format);
609
         assert(sv_templ.format != PIPE_FORMAT_NONE);
610
      }
611
      sampler_view = pipe->create_sampler_view(pipe, tex, &sv_templ);
612
 
613
      if (!sampler_view) {
614
         pipe_resource_reference(&tex, NULL);
615
         return;
616
      }
617
      pipe_resource_reference(&tex, NULL);
618
   }
619
   else {
620
      /* Directly sample from the source resource/texture */
621
      u_sampler_view_default_template(&sv_templ, src_tex, src_format);
622
      if (!blit_depth && blit_stencil) {
623
         /* set a stencil-only format, e.g. Z24S8 --> X24S8 */
624
         sv_templ.format = util_format_stencil_only(src_format);
625
         assert(sv_templ.format != PIPE_FORMAT_NONE);
626
      }
627
      sampler_view = pipe->create_sampler_view(pipe, src_tex, &sv_templ);
628
 
629
      if (!sampler_view) {
630
         return;
631
      }
632
 
633
      s0 = (float) srcX0;
634
      s1 = (float) srcX1;
635
      t0 = (float) srcY0;
636
      t1 = (float) srcY1;
637
      normalized = sampler_view->texture->target != PIPE_TEXTURE_RECT;
638
      if(normalized)
639
      {
640
         s0 /= (float)(u_minify(sampler_view->texture->width0, src_level));
641
         s1 /= (float)(u_minify(sampler_view->texture->width0, src_level));
642
         t0 /= (float)(u_minify(sampler_view->texture->height0, src_level));
643
         t1 /= (float)(u_minify(sampler_view->texture->height0, src_level));
644
      }
645
   }
646
 
647
   assert(screen->is_format_supported(screen, sampler_view->format,
648
                     ctx->internal_target, sampler_view->texture->nr_samples,
649
                     PIPE_BIND_SAMPLER_VIEW));
650
   assert(screen->is_format_supported(screen, dst_format, ctx->internal_target,
651
                     dst_surface->texture->nr_samples,
652
                     is_depth || is_stencil ? PIPE_BIND_DEPTH_STENCIL :
653
                                              PIPE_BIND_RENDER_TARGET));
654
 
655
   /* save state (restored below) */
656
   cso_save_blend(ctx->cso);
657
   cso_save_depth_stencil_alpha(ctx->cso);
658
   cso_save_rasterizer(ctx->cso);
659
   cso_save_sample_mask(ctx->cso);
660
   cso_save_samplers(ctx->cso, PIPE_SHADER_FRAGMENT);
661
   cso_save_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT);
662
   cso_save_stream_outputs(ctx->cso);
663
   cso_save_viewport(ctx->cso);
664
   cso_save_framebuffer(ctx->cso);
665
   cso_save_fragment_shader(ctx->cso);
666
   cso_save_vertex_shader(ctx->cso);
667
   cso_save_geometry_shader(ctx->cso);
668
   cso_save_vertex_elements(ctx->cso);
669
   cso_save_aux_vertex_buffer_slot(ctx->cso);
670
   cso_save_render_condition(ctx->cso);
671
 
672
   /* set misc state we care about */
673
   if (writemask)
674
      cso_set_blend(ctx->cso, &ctx->blend_write_color);
675
   else
676
      cso_set_blend(ctx->cso, &ctx->blend_keep_color);
677
 
678
   cso_set_sample_mask(ctx->cso, ~0);
679
   cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
680
   cso_set_vertex_elements(ctx->cso, 2, ctx->velem);
681
   cso_set_stream_outputs(ctx->cso, 0, NULL, 0);
682
   cso_set_render_condition(ctx->cso, NULL, FALSE, 0);
683
 
684
   /* default sampler state */
685
   ctx->sampler.normalized_coords = normalized;
686
   ctx->sampler.min_img_filter = filter;
687
   ctx->sampler.mag_img_filter = filter;
688
   ctx->sampler.min_lod = (float) src_level;
689
   ctx->sampler.max_lod = (float) src_level;
690
 
691
   /* Depth stencil state, fragment shader and sampler setup depending on what
692
    * we blit.
693
    */
694
   if (blit_depth && blit_stencil) {
695
      cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler);
696
      /* don't filter stencil */
697
      ctx->sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
698
      ctx->sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
699
      cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 1, &ctx->sampler);
700
 
701
      cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_write_depthstencil);
702
      set_depthstencil_fragment_shader(ctx, sampler_view->texture->target);
703
   }
704
   else if (blit_depth) {
705
      cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler);
706
      cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_write_depth);
707
      set_depth_fragment_shader(ctx, sampler_view->texture->target);
708
   }
709
   else if (blit_stencil) {
710
      /* don't filter stencil */
711
      ctx->sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
712
      ctx->sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
713
      cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler);
714
 
715
      cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_write_stencil);
716
      set_stencil_fragment_shader(ctx, sampler_view->texture->target);
717
   }
718
   else { /* color */
719
      cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler);
720
      cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_keep_depthstencil);
721
      set_fragment_shader(ctx, writemask, sampler_view->texture->target);
722
   }
723
   cso_single_sampler_done(ctx->cso, PIPE_SHADER_FRAGMENT);
724
 
725
   /* textures */
726
   if (blit_depth && blit_stencil) {
727
      /* Setup two samplers, one for depth and the other one for stencil. */
728
      struct pipe_sampler_view templ;
729
      struct pipe_sampler_view *views[2];
730
 
731
      templ = *sampler_view;
732
      templ.format = util_format_stencil_only(templ.format);
733
      assert(templ.format != PIPE_FORMAT_NONE);
734
 
735
      views[0] = sampler_view;
736
      views[1] = pipe->create_sampler_view(pipe, views[0]->texture, &templ);
737
      cso_set_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT, 2, views);
738
 
739
      pipe_sampler_view_reference(&views[1], NULL);
740
   }
741
   else {
742
      cso_set_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT, 1, &sampler_view);
743
   }
744
 
745
   /* viewport */
746
   ctx->viewport.scale[0] = 0.5f * dst_surface->width;
747
   ctx->viewport.scale[1] = 0.5f * dst_surface->height;
748
   ctx->viewport.scale[2] = 0.5f;
749
   ctx->viewport.scale[3] = 1.0f;
750
   ctx->viewport.translate[0] = 0.5f * dst_surface->width;
751
   ctx->viewport.translate[1] = 0.5f * dst_surface->height;
752
   ctx->viewport.translate[2] = 0.5f;
753
   ctx->viewport.translate[3] = 0.0f;
754
   cso_set_viewport(ctx->cso, &ctx->viewport);
755
 
756
   set_vertex_shader(ctx);
757
   cso_set_geometry_shader_handle(ctx->cso, NULL);
758
 
759
   /* drawing dest */
760
   memset(&fb, 0, sizeof(fb));
761
   fb.width = dst_surface->width;
762
   fb.height = dst_surface->height;
763
   if (blit_depth || blit_stencil) {
764
      fb.zsbuf = dst_surface;
765
   } else {
766
      fb.nr_cbufs = 1;
767
      fb.cbufs[0] = dst_surface;
768
   }
769
   cso_set_framebuffer(ctx->cso, &fb);
770
 
771
   /* draw quad */
772
   offset = setup_vertex_data_tex(ctx,
773
                                  (float) dstX0 / dst_surface->width * 2.0f - 1.0f,
774
                                  (float) dstY0 / dst_surface->height * 2.0f - 1.0f,
775
                                  (float) dstX1 / dst_surface->width * 2.0f - 1.0f,
776
                                  (float) dstY1 / dst_surface->height * 2.0f - 1.0f,
777
                                  s0, t0,
778
                                  s1, t1,
779
                                  z);
780
 
781
   if (ctx->vbuf) {
782
      util_draw_vertex_buffer(ctx->pipe, ctx->cso, ctx->vbuf,
783
                              cso_get_aux_vertex_buffer_slot(ctx->cso),
784
                              offset,
785
                              PIPE_PRIM_TRIANGLE_FAN,
786
                              4,  /* verts */
787
                              2); /* attribs/vert */
788
   }
789
 
790
   /* restore state we changed */
791
   cso_restore_blend(ctx->cso);
792
   cso_restore_depth_stencil_alpha(ctx->cso);
793
   cso_restore_rasterizer(ctx->cso);
794
   cso_restore_sample_mask(ctx->cso);
795
   cso_restore_samplers(ctx->cso, PIPE_SHADER_FRAGMENT);
796
   cso_restore_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT);
797
   cso_restore_viewport(ctx->cso);
798
   cso_restore_framebuffer(ctx->cso);
799
   cso_restore_fragment_shader(ctx->cso);
800
   cso_restore_vertex_shader(ctx->cso);
801
   cso_restore_geometry_shader(ctx->cso);
802
   cso_restore_vertex_elements(ctx->cso);
803
   cso_restore_aux_vertex_buffer_slot(ctx->cso);
804
   cso_restore_stream_outputs(ctx->cso);
805
   cso_restore_render_condition(ctx->cso);
806
 
807
   pipe_sampler_view_reference(&sampler_view, NULL);
808
   if (dst_surface != dst)
809
      pipe_surface_reference(&dst_surface, NULL);
810
}
811
 
812
 
813
/**
814
 * Copy pixel block from src texture to dst surface.
815
 * The sampler view's first_level field indicates the source
816
 * mipmap level to use.
817
 * XXX need some control over blitting Z and/or stencil.
818
 */
819
void
820
util_blit_pixels_tex(struct blit_state *ctx,
821
                     struct pipe_sampler_view *src_sampler_view,
822
                     int srcX0, int srcY0,
823
                     int srcX1, int srcY1,
824
                     struct pipe_surface *dst,
825
                     int dstX0, int dstY0,
826
                     int dstX1, int dstY1,
827
                     float z, uint filter)
828
{
829
   boolean normalized = src_sampler_view->texture->target != PIPE_TEXTURE_RECT;
830
   struct pipe_framebuffer_state fb;
831
   float s0, t0, s1, t1;
832
   unsigned offset;
833
   struct pipe_resource *tex = src_sampler_view->texture;
834
 
835
   assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
836
          filter == PIPE_TEX_MIPFILTER_LINEAR);
837
 
838
   assert(tex);
839
   assert(tex->width0 != 0);
840
   assert(tex->height0 != 0);
841
 
842
   s0 = (float) srcX0;
843
   s1 = (float) srcX1;
844
   t0 = (float) srcY0;
845
   t1 = (float) srcY1;
846
 
847
   if(normalized)
848
   {
849
      /* normalize according to the mipmap level's size */
850
      int level = src_sampler_view->u.tex.first_level;
851
      float w = (float) u_minify(tex->width0, level);
852
      float h = (float) u_minify(tex->height0, level);
853
      s0 /= w;
854
      s1 /= w;
855
      t0 /= h;
856
      t1 /= h;
857
   }
858
 
859
   assert(ctx->pipe->screen->is_format_supported(ctx->pipe->screen, dst->format,
860
                                                 PIPE_TEXTURE_2D,
861
                                                 dst->texture->nr_samples,
862
                                                 PIPE_BIND_RENDER_TARGET));
863
 
864
   /* save state (restored below) */
865
   cso_save_blend(ctx->cso);
866
   cso_save_depth_stencil_alpha(ctx->cso);
867
   cso_save_rasterizer(ctx->cso);
868
   cso_save_sample_mask(ctx->cso);
869
   cso_save_samplers(ctx->cso, PIPE_SHADER_FRAGMENT);
870
   cso_save_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT);
871
   cso_save_stream_outputs(ctx->cso);
872
   cso_save_viewport(ctx->cso);
873
   cso_save_framebuffer(ctx->cso);
874
   cso_save_fragment_shader(ctx->cso);
875
   cso_save_vertex_shader(ctx->cso);
876
   cso_save_geometry_shader(ctx->cso);
877
   cso_save_vertex_elements(ctx->cso);
878
   cso_save_aux_vertex_buffer_slot(ctx->cso);
879
 
880
   /* set misc state we care about */
881
   cso_set_blend(ctx->cso, &ctx->blend_write_color);
882
   cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_keep_depthstencil);
883
   cso_set_sample_mask(ctx->cso, ~0);
884
   cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
885
   cso_set_vertex_elements(ctx->cso, 2, ctx->velem);
886
   cso_set_stream_outputs(ctx->cso, 0, NULL, 0);
887
 
888
   /* sampler */
889
   ctx->sampler.normalized_coords = normalized;
890
   ctx->sampler.min_img_filter = filter;
891
   ctx->sampler.mag_img_filter = filter;
892
   cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler);
893
   cso_single_sampler_done(ctx->cso, PIPE_SHADER_FRAGMENT);
894
 
895
   /* viewport */
896
   ctx->viewport.scale[0] = 0.5f * dst->width;
897
   ctx->viewport.scale[1] = 0.5f * dst->height;
898
   ctx->viewport.scale[2] = 0.5f;
899
   ctx->viewport.scale[3] = 1.0f;
900
   ctx->viewport.translate[0] = 0.5f * dst->width;
901
   ctx->viewport.translate[1] = 0.5f * dst->height;
902
   ctx->viewport.translate[2] = 0.5f;
903
   ctx->viewport.translate[3] = 0.0f;
904
   cso_set_viewport(ctx->cso, &ctx->viewport);
905
 
906
   /* texture */
907
   cso_set_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT, 1, &src_sampler_view);
908
 
909
   /* shaders */
910
   set_fragment_shader(ctx, TGSI_WRITEMASK_XYZW,
911
                       src_sampler_view->texture->target);
912
   set_vertex_shader(ctx);
913
   cso_set_geometry_shader_handle(ctx->cso, NULL);
914
 
915
   /* drawing dest */
916
   memset(&fb, 0, sizeof(fb));
917
   fb.width = dst->width;
918
   fb.height = dst->height;
919
   fb.nr_cbufs = 1;
920
   fb.cbufs[0] = dst;
921
   cso_set_framebuffer(ctx->cso, &fb);
922
 
923
   /* draw quad */
924
   offset = setup_vertex_data_tex(ctx,
925
                                  (float) dstX0 / dst->width * 2.0f - 1.0f,
926
                                  (float) dstY0 / dst->height * 2.0f - 1.0f,
927
                                  (float) dstX1 / dst->width * 2.0f - 1.0f,
928
                                  (float) dstY1 / dst->height * 2.0f - 1.0f,
929
                                  s0, t0, s1, t1,
930
                                  z);
931
 
932
   util_draw_vertex_buffer(ctx->pipe, ctx->cso, ctx->vbuf,
933
                           cso_get_aux_vertex_buffer_slot(ctx->cso),
934
                           offset,
935
                           PIPE_PRIM_TRIANGLE_FAN,
936
                           4,  /* verts */
937
                           2); /* attribs/vert */
938
 
939
   /* restore state we changed */
940
   cso_restore_blend(ctx->cso);
941
   cso_restore_depth_stencil_alpha(ctx->cso);
942
   cso_restore_rasterizer(ctx->cso);
943
   cso_restore_sample_mask(ctx->cso);
944
   cso_restore_samplers(ctx->cso, PIPE_SHADER_FRAGMENT);
945
   cso_restore_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT);
946
   cso_restore_viewport(ctx->cso);
947
   cso_restore_framebuffer(ctx->cso);
948
   cso_restore_fragment_shader(ctx->cso);
949
   cso_restore_vertex_shader(ctx->cso);
950
   cso_restore_geometry_shader(ctx->cso);
951
   cso_restore_vertex_elements(ctx->cso);
952
   cso_restore_aux_vertex_buffer_slot(ctx->cso);
953
   cso_restore_stream_outputs(ctx->cso);
954
}