xorg_composite.c revision 8adcad0c703a9d339b6630ceaba5f96981c524d9
1#include "xorg_composite.h"
2
3#include "xorg_exa_tgsi.h"
4
5#include "cso_cache/cso_context.h"
6#include "util/u_draw_quad.h"
7#include "util/u_math.h"
8
9#include "pipe/p_inlines.h"
10
11struct xorg_composite_blend {
12   int op:8;
13
14   unsigned rgb_src_factor:5;    /**< PIPE_BLENDFACTOR_x */
15   unsigned alpha_src_factor:5;  /**< PIPE_BLENDFACTOR_x */
16
17   unsigned rgb_dst_factor:5;    /**< PIPE_BLENDFACTOR_x */
18   unsigned alpha_dst_factor:5;  /**< PIPE_BLENDFACTOR_x */
19};
20
21#define BLEND_OP_OVER 3
22static const struct xorg_composite_blend xorg_blends[] = {
23   { PictOpClear,
24     PIPE_BLENDFACTOR_CONST_COLOR, PIPE_BLENDFACTOR_CONST_ALPHA,
25     PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO },
26
27   { PictOpSrc,
28     PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ONE,
29     PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO },
30
31   { PictOpDst,
32     PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO,
33     PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ONE },
34
35   { PictOpOver,
36     PIPE_BLENDFACTOR_SRC_ALPHA, PIPE_BLENDFACTOR_ONE,
37     PIPE_BLENDFACTOR_INV_SRC_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA },
38
39   { PictOpOverReverse,
40     PIPE_BLENDFACTOR_SRC_ALPHA, PIPE_BLENDFACTOR_ONE,
41     PIPE_BLENDFACTOR_INV_SRC_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA },
42};
43
44
45static INLINE void
46pixel_to_float4(Pixel pixel, float *color)
47{
48   CARD32	    r, g, b, a;
49
50   a = (pixel >> 24) & 0xff;
51   r = (pixel >> 16) & 0xff;
52   g = (pixel >>  8) & 0xff;
53   b = (pixel >>  0) & 0xff;
54   color[0] = ((float)r) / 255.;
55   color[1] = ((float)g) / 255.;
56   color[2] = ((float)b) / 255.;
57   color[3] = ((float)a) / 255.;
58}
59
60static INLINE void
61render_pixel_to_float4(PictFormatPtr format,
62                       CARD32 pixel, float *color)
63{
64   CARD32	    r, g, b, a;
65
66   debug_assert(format->type == PictTypeDirect);
67
68   r = (pixel >> format->direct.red) & format->direct.redMask;
69   g = (pixel >> format->direct.green) & format->direct.greenMask;
70   b = (pixel >> format->direct.blue) & format->direct.blueMask;
71   a = (pixel >> format->direct.alpha) & format->direct.alphaMask;
72   color[0] = ((float)r) / ((float)format->direct.redMask);
73   color[1] = ((float)g) / ((float)format->direct.greenMask);
74   color[2] = ((float)b) / ((float)format->direct.blueMask);
75   color[3] = ((float)a) / ((float)format->direct.alphaMask);
76}
77
78struct acceleration_info {
79   int op : 16;
80   int with_mask : 1;
81   int component_alpha : 1;
82};
83static const struct acceleration_info accelerated_ops[] = {
84   {PictOpClear,       1, 0},
85   {PictOpSrc,         1, 0},
86   {PictOpDst,         1, 0},
87   {PictOpOver,        1, 0},
88   {PictOpOverReverse, 1, 0},
89   {PictOpIn,          1, 0},
90   {PictOpInReverse,   1, 0},
91   {PictOpOut,         1, 0},
92   {PictOpOutReverse,  1, 0},
93   {PictOpAtop,        1, 0},
94   {PictOpAtopReverse, 1, 0},
95   {PictOpXor,         1, 0},
96   {PictOpAdd,         1, 0},
97   {PictOpSaturate,    1, 0},
98};
99
100static struct xorg_composite_blend
101blend_for_op(int op)
102{
103   const int num_blends =
104      sizeof(xorg_blends)/sizeof(struct xorg_composite_blend);
105   int i;
106
107   for (i = 0; i < num_blends; ++i) {
108      if (xorg_blends[i].op == op)
109         return xorg_blends[i];
110   }
111   return xorg_blends[BLEND_OP_OVER];
112}
113
114static INLINE int
115render_repeat_to_gallium(int mode)
116{
117   switch(mode) {
118   case RepeatNone:
119      return PIPE_TEX_WRAP_CLAMP;
120   case RepeatNormal:
121      return PIPE_TEX_WRAP_REPEAT;
122   case RepeatReflect:
123      return PIPE_TEX_WRAP_MIRROR_REPEAT;
124   case RepeatPad:
125      return PIPE_TEX_WRAP_CLAMP_TO_EDGE;
126   default:
127      debug_printf("Unsupported repeat mode\n");
128   }
129   return PIPE_TEX_WRAP_REPEAT;
130}
131
132
133static INLINE void
134setup_vertex0(float vertex[2][4], float x, float y,
135              float color[4])
136{
137   vertex[0][0] = x;
138   vertex[0][1] = y;
139   vertex[0][2] = 0.f; /*z*/
140   vertex[0][3] = 1.f; /*w*/
141
142   vertex[1][0] = color[0]; /*r*/
143   vertex[1][1] = color[1]; /*g*/
144   vertex[1][2] = color[2]; /*b*/
145   vertex[1][3] = color[3]; /*a*/
146}
147
148static struct pipe_buffer *
149setup_vertex_data0(struct exa_context *ctx,
150                   int srcX, int srcY, int maskX, int maskY,
151                   int dstX, int dstY, int width, int height)
152{
153   float vertices[4][2][4];
154
155   /* 1st vertex */
156   setup_vertex0(vertices[0], dstX, dstY,
157                 ctx->solid_color);
158   /* 2nd vertex */
159   setup_vertex0(vertices[1], dstX + width, dstY,
160                 ctx->solid_color);
161   /* 3rd vertex */
162   setup_vertex0(vertices[2], dstX + width, dstY + height,
163                 ctx->solid_color);
164   /* 4th vertex */
165   setup_vertex0(vertices[3], dstX, dstY + height,
166                 ctx->solid_color);
167
168   return pipe_user_buffer_create(ctx->pipe->screen,
169                                  vertices,
170                                  sizeof(vertices));
171}
172
173static INLINE void
174setup_vertex1(float vertex[2][4], float x, float y, float s, float t)
175{
176   vertex[0][0] = x;
177   vertex[0][1] = y;
178   vertex[0][2] = 0.f; /*z*/
179   vertex[0][3] = 1.f; /*w*/
180
181   vertex[1][0] = s;   /*s*/
182   vertex[1][1] = t;   /*t*/
183   vertex[1][2] = 0.f; /*r*/
184   vertex[1][3] = 1.f; /*q*/
185}
186
187static struct pipe_buffer *
188setup_vertex_data1(struct exa_context *ctx,
189                   int srcX, int srcY, int maskX, int maskY,
190                   int dstX, int dstY, int width, int height)
191{
192   float vertices[4][2][4];
193   float s0, t0, s1, t1;
194   struct pipe_texture *src = ctx->bound_textures[0];
195
196   s0 = srcX / src->width[0];
197   s1 = srcX + width / src->width[0];
198   t0 = srcY / src->height[0];
199   t1 = srcY + height / src->height[0];
200
201   /* 1st vertex */
202   setup_vertex1(vertices[0], dstX, dstY,
203                 s0, t0);
204   /* 2nd vertex */
205   setup_vertex1(vertices[1], dstX + width, dstY,
206                 s1, t0);
207   /* 3rd vertex */
208   setup_vertex1(vertices[2], dstX + width, dstY + height,
209                 s1, t1);
210   /* 4th vertex */
211   setup_vertex1(vertices[3], dstX, dstY + height,
212                 s0, t1);
213
214   return pipe_user_buffer_create(ctx->pipe->screen,
215                                  vertices,
216                                  sizeof(vertices));
217}
218
219static struct pipe_buffer *
220setup_vertex_data_tex(struct exa_context *ctx,
221                      float x0, float y0, float x1, float y1,
222                      float s0, float t0, float s1, float t1,
223                      float z)
224{
225   float vertices[4][2][4];
226
227   /* 1st vertex */
228   setup_vertex1(vertices[0], x0, y0,
229                 s0, t0);
230   /* 2nd vertex */
231   setup_vertex1(vertices[1], x1, y0,
232                 s1, t0);
233   /* 3rd vertex */
234   setup_vertex1(vertices[2], x1, y1,
235                 s1, t1);
236   /* 4th vertex */
237   setup_vertex1(vertices[3], x0, y1,
238                 s0, t1);
239
240   return pipe_user_buffer_create(ctx->pipe->screen,
241                                  vertices,
242                                  sizeof(vertices));
243}
244
245
246
247static INLINE void
248setup_vertex2(float vertex[3][4], float x, float y,
249              float s0, float t0, float s1, float t1)
250{
251   vertex[0][0] = x;
252   vertex[0][1] = y;
253   vertex[0][2] = 0.f; /*z*/
254   vertex[0][3] = 1.f; /*w*/
255
256   vertex[1][0] = s0;  /*s*/
257   vertex[1][1] = t0;  /*t*/
258   vertex[1][2] = 0.f; /*r*/
259   vertex[1][3] = 1.f; /*q*/
260
261   vertex[2][0] = s1;  /*s*/
262   vertex[2][1] = t1;  /*t*/
263   vertex[2][2] = 0.f; /*r*/
264   vertex[2][3] = 1.f; /*q*/
265}
266
267static struct pipe_buffer *
268setup_vertex_data2(struct exa_context *ctx,
269                   int srcX, int srcY, int maskX, int maskY,
270                   int dstX, int dstY, int width, int height)
271{
272   float vertices[4][3][4];
273   float st0[4], st1[4];
274   struct pipe_texture *src = ctx->bound_textures[0];
275   struct pipe_texture *mask = ctx->bound_textures[0];
276
277   st0[0] = srcX / src->width[0];
278   st0[1] = srcY / src->height[0];
279   st0[2] = srcX + width / src->width[0];
280   st0[3] = srcY + height / src->height[0];
281
282   st1[0] = maskX / mask->width[0];
283   st1[1] = maskY / mask->height[0];
284   st1[2] = maskX + width / mask->width[0];
285   st1[3] = maskY + height / mask->height[0];
286
287   /* 1st vertex */
288   setup_vertex2(vertices[0], dstX, dstY,
289                 st0[0], st0[1], st1[0], st1[1]);
290   /* 2nd vertex */
291   setup_vertex2(vertices[1], dstX + width, dstY,
292                 st0[2], st0[1], st1[2], st1[1]);
293   /* 3rd vertex */
294   setup_vertex2(vertices[2], dstX + width, dstY + height,
295                 st0[2], st0[3], st1[2], st1[3]);
296   /* 4th vertex */
297   setup_vertex2(vertices[3], dstX, dstY + height,
298                 st0[0], st0[3], st1[0], st1[3]);
299
300   return pipe_user_buffer_create(ctx->pipe->screen,
301                                  vertices,
302                                  sizeof(vertices));
303}
304
305boolean xorg_composite_accelerated(int op,
306                                   PicturePtr pSrcPicture,
307                                   PicturePtr pMaskPicture,
308                                   PicturePtr pDstPicture)
309{
310   unsigned i;
311   unsigned accel_ops_count =
312      sizeof(accelerated_ops)/sizeof(struct acceleration_info);
313
314
315   /*FIXME: currently accel is disabled */
316   return FALSE;
317
318   if (pSrcPicture) {
319      /* component alpha not supported */
320      if (pSrcPicture->componentAlpha)
321         return FALSE;
322      /* fills not supported */
323      if (pSrcPicture->pSourcePict)
324         return FALSE;
325   }
326
327   for (i = 0; i < accel_ops_count; ++i) {
328      if (op == accelerated_ops[i].op) {
329         if (pMaskPicture && !accelerated_ops[i].with_mask)
330            return FALSE;
331         return TRUE;
332      }
333   }
334   return FALSE;
335}
336
337static void
338bind_clip_state(struct exa_context *exa)
339{
340}
341
342static void
343bind_framebuffer_state(struct exa_context *exa, struct exa_pixmap_priv *pDst)
344{
345   unsigned i;
346   struct pipe_framebuffer_state state;
347   struct pipe_surface *surface = exa_gpu_surface(exa, pDst);
348   memset(&state, 0, sizeof(struct pipe_framebuffer_state));
349
350   state.width  = pDst->tex->width[0];
351   state.height = pDst->tex->height[0];
352
353   state.nr_cbufs = 1;
354   state.cbufs[0] = surface;
355   for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i)
356      state.cbufs[i] = 0;
357
358   /* currently we don't use depth/stencil */
359   state.zsbuf = 0;
360
361   cso_set_framebuffer(exa->cso, &state);
362}
363
364enum AxisOrientation {
365   Y0_BOTTOM,
366   Y0_TOP
367};
368
369static void
370set_viewport(struct exa_context *exa, int width, int height,
371             enum AxisOrientation orientation)
372{
373   struct pipe_viewport_state viewport;
374   float y_scale = (orientation == Y0_BOTTOM) ? -2.f : 2.f;
375
376   viewport.scale[0] =  width / 2.f;
377   viewport.scale[1] =  height / y_scale;
378   viewport.scale[2] =  1.0;
379   viewport.scale[3] =  1.0;
380   viewport.translate[0] = width / 2.f;
381   viewport.translate[1] = height / 2.f;
382   viewport.translate[2] = 0.0;
383   viewport.translate[3] = 0.0;
384
385   cso_set_viewport(exa->cso, &viewport);
386}
387
388static void
389bind_viewport_state(struct exa_context *exa, struct exa_pixmap_priv *pDst)
390{
391   int width = pDst->tex->width[0];
392   int height = pDst->tex->height[0];
393
394   debug_printf("Bind viewport (%d, %d)\n", width, height);
395
396   set_viewport(exa, width, height, Y0_TOP);
397}
398
399static void
400bind_blend_state(struct exa_context *exa, int op,
401                 PicturePtr pSrcPicture, PicturePtr pMaskPicture)
402{
403   boolean component_alpha = (pSrcPicture) ?
404                             pSrcPicture->componentAlpha : FALSE;
405   struct xorg_composite_blend blend_opt;
406   struct pipe_blend_state blend;
407
408   if (component_alpha) {
409      op = PictOpOver;
410   }
411   blend_opt = blend_for_op(op);
412
413   memset(&blend, 0, sizeof(struct pipe_blend_state));
414   blend.blend_enable = 1;
415   blend.colormask |= PIPE_MASK_R;
416   blend.colormask |= PIPE_MASK_G;
417   blend.colormask |= PIPE_MASK_B;
418   blend.colormask |= PIPE_MASK_A;
419
420   blend.rgb_src_factor   = blend_opt.rgb_src_factor;
421   blend.alpha_src_factor = blend_opt.alpha_src_factor;
422   blend.rgb_dst_factor   = blend_opt.rgb_dst_factor;
423   blend.alpha_dst_factor = blend_opt.alpha_dst_factor;
424
425   cso_set_blend(exa->cso, &blend);
426}
427
428static void
429bind_rasterizer_state(struct exa_context *exa)
430{
431   struct pipe_rasterizer_state raster;
432   memset(&raster, 0, sizeof(struct pipe_rasterizer_state));
433   raster.gl_rasterization_rules = 1;
434   cso_set_rasterizer(exa->cso, &raster);
435}
436
437static void
438bind_shaders(struct exa_context *exa, int op,
439             PicturePtr pSrcPicture, PicturePtr pMaskPicture)
440{
441   unsigned vs_traits = 0, fs_traits = 0;
442   struct xorg_shader shader;
443
444   exa->has_solid_color = FALSE;
445
446   if (pSrcPicture) {
447      if (pSrcPicture->pSourcePict) {
448         if (pSrcPicture->pSourcePict->type == SourcePictTypeSolidFill) {
449            fs_traits |= FS_SOLID_FILL;
450            vs_traits |= VS_SOLID_FILL;
451            render_pixel_to_float4(pSrcPicture->pFormat,
452                                   pSrcPicture->pSourcePict->solidFill.color,
453                                   exa->solid_color);
454            exa->has_solid_color = TRUE;
455         } else {
456            debug_assert("!gradients not supported");
457         }
458      } else {
459         fs_traits |= FS_COMPOSITE;
460         vs_traits |= VS_COMPOSITE;
461      }
462   }
463
464   if (pMaskPicture) {
465      vs_traits |= VS_MASK;
466      fs_traits |= FS_MASK;
467   }
468
469   shader = xorg_shaders_get(exa->shaders, vs_traits, fs_traits);
470   cso_set_vertex_shader_handle(exa->cso, shader.vs);
471   cso_set_fragment_shader_handle(exa->cso, shader.fs);
472}
473
474
475static void
476bind_samplers(struct exa_context *exa, int op,
477              PicturePtr pSrcPicture, PicturePtr pMaskPicture,
478              PicturePtr pDstPicture,
479              struct exa_pixmap_priv *pSrc,
480              struct exa_pixmap_priv *pMask,
481              struct exa_pixmap_priv *pDst)
482{
483   struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
484   struct pipe_sampler_state src_sampler, mask_sampler;
485
486   exa->num_bound_samplers = 0;
487
488   memset(&src_sampler, 0, sizeof(struct pipe_sampler_state));
489   memset(&mask_sampler, 0, sizeof(struct pipe_sampler_state));
490
491   if (pSrcPicture && pSrc) {
492      unsigned src_wrap = render_repeat_to_gallium(
493         pSrcPicture->repeatType);
494      src_sampler.wrap_s = src_wrap;
495      src_sampler.wrap_t = src_wrap;
496      src_sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
497      src_sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
498      src_sampler.normalized_coords = 1;
499      samplers[0] = &src_sampler;
500      exa->bound_textures[0] = pSrc->tex;
501      ++exa->num_bound_samplers;
502   }
503
504   if (pMaskPicture && pMask) {
505      unsigned mask_wrap = render_repeat_to_gallium(
506         pMaskPicture->repeatType);
507      mask_sampler.wrap_s = mask_wrap;
508      mask_sampler.wrap_t = mask_wrap;
509      mask_sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
510      mask_sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
511      mask_sampler.normalized_coords = 1;
512      samplers[1] = &mask_sampler;
513      exa->bound_textures[1] = pMask->tex;
514      ++exa->num_bound_samplers;
515   }
516
517   cso_set_samplers(exa->cso, exa->num_bound_samplers,
518                    (const struct pipe_sampler_state **)samplers);
519   cso_set_sampler_textures(exa->cso, exa->num_bound_samplers,
520                            exa->bound_textures);
521}
522
523static void
524setup_vs_constant_buffer(struct exa_context *exa,
525                         int width, int height)
526{
527   const int param_bytes = 8 * sizeof(float);
528   float vs_consts[8] = {
529      2.f/width, 2.f/height, 1, 1,
530      -1, -1, 0, 0
531   };
532   struct pipe_constant_buffer *cbuf = &exa->vs_const_buffer;
533
534   pipe_buffer_reference(&cbuf->buffer, NULL);
535   cbuf->buffer = pipe_buffer_create(exa->pipe->screen, 16,
536                                     PIPE_BUFFER_USAGE_CONSTANT,
537                                     param_bytes);
538
539   if (cbuf->buffer) {
540      pipe_buffer_write(exa->pipe->screen, cbuf->buffer,
541                        0, param_bytes, vs_consts);
542   }
543   exa->pipe->set_constant_buffer(exa->pipe, PIPE_SHADER_VERTEX, 0, cbuf);
544}
545
546
547static void
548setup_fs_constant_buffer(struct exa_context *exa)
549{
550   const int param_bytes = 4 * sizeof(float);
551   float fs_consts[8] = {
552      0, 0, 0, 1,
553   };
554   struct pipe_constant_buffer *cbuf = &exa->fs_const_buffer;
555
556   pipe_buffer_reference(&cbuf->buffer, NULL);
557   cbuf->buffer = pipe_buffer_create(exa->pipe->screen, 16,
558                                     PIPE_BUFFER_USAGE_CONSTANT,
559                                     param_bytes);
560
561   if (cbuf->buffer) {
562      pipe_buffer_write(exa->pipe->screen, cbuf->buffer,
563                        0, param_bytes, fs_consts);
564   }
565   exa->pipe->set_constant_buffer(exa->pipe, PIPE_SHADER_FRAGMENT, 0, cbuf);
566}
567
568static void
569setup_constant_buffers(struct exa_context *exa, struct exa_pixmap_priv *pDst)
570{
571   int width = pDst->tex->width[0];
572   int height = pDst->tex->height[0];
573
574   setup_vs_constant_buffer(exa, width, height);
575   setup_fs_constant_buffer(exa);
576}
577
578boolean xorg_composite_bind_state(struct exa_context *exa,
579                                  int op,
580                                  PicturePtr pSrcPicture,
581                                  PicturePtr pMaskPicture,
582                                  PicturePtr pDstPicture,
583                                  struct exa_pixmap_priv *pSrc,
584                                  struct exa_pixmap_priv *pMask,
585                                  struct exa_pixmap_priv *pDst)
586{
587   bind_framebuffer_state(exa, pDst);
588   bind_viewport_state(exa, pDst);
589   bind_blend_state(exa, op, pSrcPicture, pMaskPicture);
590   bind_rasterizer_state(exa);
591   bind_shaders(exa, op, pSrcPicture, pMaskPicture);
592   bind_samplers(exa, op, pSrcPicture, pMaskPicture,
593                 pDstPicture, pSrc, pMask, pDst);
594   bind_clip_state(exa);
595   setup_constant_buffers(exa, pDst);
596
597   return FALSE;
598}
599
600void xorg_composite(struct exa_context *exa,
601                    struct exa_pixmap_priv *dst,
602                    int srcX, int srcY, int maskX, int maskY,
603                    int dstX, int dstY, int width, int height)
604{
605   struct pipe_context *pipe = exa->pipe;
606   struct pipe_buffer *buf = 0;
607
608   if (exa->num_bound_samplers == 0 ) { /* solid fill */
609      buf = setup_vertex_data0(exa,
610                               srcX, srcY, maskX, maskY,
611                               dstX, dstY, width, height);
612   } else if (exa->num_bound_samplers == 1 ) /* src */
613      buf = setup_vertex_data1(exa,
614                               srcX, srcY, maskX, maskY,
615                               dstX, dstY, width, height);
616   else if (exa->num_bound_samplers == 2) /* src + mask */
617      buf = setup_vertex_data2(exa,
618                               srcX, srcY, maskX, maskY,
619                               dstX, dstY, width, height);
620   else if (exa->num_bound_samplers == 3) { /* src + mask + dst */
621      debug_assert(!"src/mask/dst not handled right now");
622#if 0
623      buf = setup_vertex_data2(exa,
624                               srcX, srcY, maskX, maskY,
625                               dstX, dstY, width, height);
626#endif
627   }
628
629   if (buf) {
630      int num_attribs = 1; /*pos*/
631      num_attribs += exa->num_bound_samplers;
632      if (exa->has_solid_color)
633         ++num_attribs;
634
635      util_draw_vertex_buffer(pipe, buf, 0,
636                              PIPE_PRIM_TRIANGLE_FAN,
637                              4,  /* verts */
638                              num_attribs); /* attribs/vert */
639
640      pipe_buffer_reference(&buf, NULL);
641   }
642}
643
644boolean xorg_solid_bind_state(struct exa_context *exa,
645                              struct exa_pixmap_priv *pixmap,
646                              Pixel fg)
647{
648   unsigned vs_traits, fs_traits;
649   struct xorg_shader shader;
650
651   pixel_to_float4(fg, exa->solid_color);
652   exa->has_solid_color = TRUE;
653
654   exa->solid_color[3] = 1.f;
655
656#if 0
657   debug_printf("Color Pixel=(%d, %d, %d, %d), RGBA=(%f, %f, %f, %f)\n",
658                (fg >> 24) & 0xff, (fg >> 16) & 0xff,
659                (fg >> 8) & 0xff,  (fg >> 0) & 0xff,
660                exa->solid_color[0], exa->solid_color[1],
661                exa->solid_color[2], exa->solid_color[3]);
662#endif
663
664   vs_traits = VS_SOLID_FILL;
665   fs_traits = FS_SOLID_FILL;
666
667   bind_framebuffer_state(exa, pixmap);
668   bind_viewport_state(exa, pixmap);
669   bind_rasterizer_state(exa);
670   bind_blend_state(exa, PictOpSrc, NULL, NULL);
671   setup_constant_buffers(exa, pixmap);
672   bind_clip_state(exa);
673
674   shader = xorg_shaders_get(exa->shaders, vs_traits, fs_traits);
675   cso_set_vertex_shader_handle(exa->cso, shader.vs);
676   cso_set_fragment_shader_handle(exa->cso, shader.fs);
677
678   return FALSE;
679}
680
681void xorg_solid(struct exa_context *exa,
682                struct exa_pixmap_priv *pixmap,
683                int x0, int y0, int x1, int y1)
684{
685   struct pipe_context *pipe = exa->pipe;
686   struct pipe_buffer *buf = 0;
687   float vertices[4][2][4];
688
689   /* 1st vertex */
690   setup_vertex0(vertices[0], x0, y0,
691                 exa->solid_color);
692   /* 2nd vertex */
693   setup_vertex0(vertices[1], x1, y0,
694                 exa->solid_color);
695   /* 3rd vertex */
696   setup_vertex0(vertices[2], x1, y1,
697                 exa->solid_color);
698   /* 4th vertex */
699   setup_vertex0(vertices[3], x0, y1,
700                 exa->solid_color);
701
702   buf = pipe_user_buffer_create(exa->pipe->screen,
703                                 vertices,
704                                 sizeof(vertices));
705
706
707   if (buf) {
708      debug_printf("Drawing buf is %p\n", buf);
709      util_draw_vertex_buffer(pipe, buf, 0,
710                              PIPE_PRIM_TRIANGLE_FAN,
711                              4,  /* verts */
712                              2); /* attribs/vert */
713
714      pipe_buffer_reference(&buf, NULL);
715   }
716}
717
718
719static INLINE void shift_rectx(float coords[4],
720                               const float *bounds,
721                               const float shift)
722{
723   coords[0] += shift;
724   coords[2] -= shift;
725   if (bounds) {
726      coords[2] = MIN2(coords[2], bounds[2]);
727      /* bound x/y + width/height */
728      if ((coords[0] + coords[2]) > (bounds[0] + bounds[2])) {
729         coords[2] = (bounds[0] + bounds[2]) - coords[0];
730      }
731   }
732}
733
734static INLINE void shift_recty(float coords[4],
735                               const float *bounds,
736                               const float shift)
737{
738   coords[1] += shift;
739   coords[3] -= shift;
740   if (bounds) {
741      coords[3] = MIN2(coords[3], bounds[3]);
742      if ((coords[1] + coords[3]) > (bounds[1] + bounds[3])) {
743         coords[3] = (bounds[1] + bounds[3]) - coords[1];
744      }
745   }
746}
747
748static INLINE void bound_rect(float coords[4],
749                              const float bounds[4],
750                              float shift[4])
751{
752   /* if outside the bounds */
753   if (coords[0] > (bounds[0] + bounds[2]) ||
754       coords[1] > (bounds[1] + bounds[3]) ||
755       (coords[0] + coords[2]) < bounds[0] ||
756       (coords[1] + coords[3]) < bounds[1]) {
757      coords[0] = 0.f;
758      coords[1] = 0.f;
759      coords[2] = 0.f;
760      coords[3] = 0.f;
761      shift[0] = 0.f;
762      shift[1] = 0.f;
763      return;
764   }
765
766   /* bound x */
767   if (coords[0] < bounds[0]) {
768      shift[0] = bounds[0] - coords[0];
769      coords[2] -= shift[0];
770      coords[0] = bounds[0];
771   } else
772      shift[0] = 0.f;
773
774   /* bound y */
775   if (coords[1] < bounds[1]) {
776      shift[1] = bounds[1] - coords[1];
777      coords[3] -= shift[1];
778      coords[1] = bounds[1];
779   } else
780      shift[1] = 0.f;
781
782   shift[2] = bounds[2] - coords[2];
783   shift[3] = bounds[3] - coords[3];
784   /* bound width/height */
785   coords[2] = MIN2(coords[2], bounds[2]);
786   coords[3] = MIN2(coords[3], bounds[3]);
787
788   /* bound x/y + width/height */
789   if ((coords[0] + coords[2]) > (bounds[0] + bounds[2])) {
790      coords[2] = (bounds[0] + bounds[2]) - coords[0];
791   }
792   if ((coords[1] + coords[3]) > (bounds[1] + bounds[3])) {
793      coords[3] = (bounds[1] + bounds[3]) - coords[1];
794   }
795
796   /* if outside the bounds */
797   if ((coords[0] + coords[2]) < bounds[0] ||
798       (coords[1] + coords[3]) < bounds[1]) {
799      coords[0] = 0.f;
800      coords[1] = 0.f;
801      coords[2] = 0.f;
802      coords[3] = 0.f;
803      return;
804   }
805}
806
807static INLINE void sync_size(float *src_loc, float *dst_loc)
808{
809   src_loc[2] = MIN2(src_loc[2], dst_loc[2]);
810   src_loc[3] = MIN2(src_loc[3], dst_loc[3]);
811   dst_loc[2] = src_loc[2];
812   dst_loc[3] = src_loc[3];
813}
814
815
816static void renderer_copy_texture(struct exa_context *exa,
817                                  struct pipe_texture *src,
818                                  float sx1, float sy1,
819                                  float sx2, float sy2,
820                                  struct pipe_texture *dst,
821                                  float dx1, float dy1,
822                                  float dx2, float dy2)
823{
824   struct pipe_context *pipe = exa->pipe;
825   struct pipe_screen *screen = pipe->screen;
826   struct pipe_buffer *buf;
827   struct pipe_surface *dst_surf = screen->get_tex_surface(
828      screen, dst, 0, 0, 0,
829      PIPE_BUFFER_USAGE_GPU_WRITE);
830   struct pipe_framebuffer_state fb;
831   float s0, t0, s1, t1;
832   struct xorg_shader shader;
833
834   assert(src->width[0] != 0);
835   assert(src->height[0] != 0);
836   assert(dst->width[0] != 0);
837   assert(dst->height[0] != 0);
838
839#if 1
840   s0 = sx1 / src->width[0];
841   s1 = sx2 / src->width[0];
842   t0 = sy1 / src->height[0];
843   t1 = sy2 / src->height[0];
844#else
845   s0 = 0;
846   s1 = 1;
847   t0 = 0;
848   t1 = 1;
849#endif
850
851#if 1
852   debug_printf("copy texture src=[%f, %f, %f, %f], dst=[%f, %f, %f, %f], tex=[%f, %f, %f, %f]\n",
853                sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2,
854                s0, t0, s1, t1);
855#endif
856
857   assert(screen->is_format_supported(screen, dst_surf->format,
858                                      PIPE_TEXTURE_2D,
859                                      PIPE_TEXTURE_USAGE_RENDER_TARGET,
860                                      0));
861
862   /* save state (restored below) */
863   cso_save_blend(exa->cso);
864   cso_save_samplers(exa->cso);
865   cso_save_sampler_textures(exa->cso);
866   cso_save_framebuffer(exa->cso);
867   cso_save_fragment_shader(exa->cso);
868   cso_save_vertex_shader(exa->cso);
869
870   cso_save_viewport(exa->cso);
871
872
873   /* set misc state we care about */
874   {
875      struct pipe_blend_state blend;
876      memset(&blend, 0, sizeof(blend));
877      blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
878      blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
879      blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
880      blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
881      blend.colormask = PIPE_MASK_RGBA;
882      cso_set_blend(exa->cso, &blend);
883   }
884
885   /* sampler */
886   {
887      struct pipe_sampler_state sampler;
888      memset(&sampler, 0, sizeof(sampler));
889      sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
890      sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
891      sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
892      sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
893      sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
894      sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
895      sampler.normalized_coords = 1;
896      cso_single_sampler(exa->cso, 0, &sampler);
897      cso_single_sampler_done(exa->cso);
898   }
899
900   set_viewport(exa, dst_surf->width, dst_surf->height, Y0_TOP);
901
902   /* texture */
903   cso_set_sampler_textures(exa->cso, 1, &src);
904
905   /* shaders */
906   shader = xorg_shaders_get(exa->shaders,
907                             VS_COMPOSITE,
908                             FS_COMPOSITE);
909   cso_set_vertex_shader_handle(exa->cso, shader.vs);
910   cso_set_fragment_shader_handle(exa->cso, shader.fs);
911
912   /* drawing dest */
913   memset(&fb, 0, sizeof(fb));
914   fb.width = dst_surf->width;
915   fb.height = dst_surf->height;
916   fb.nr_cbufs = 1;
917   fb.cbufs[0] = dst_surf;
918   {
919      int i;
920      for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i)
921         fb.cbufs[i] = 0;
922   }
923   cso_set_framebuffer(exa->cso, &fb);
924   setup_vs_constant_buffer(exa, fb.width, fb.height);
925   setup_fs_constant_buffer(exa);
926
927   /* draw quad */
928   buf = setup_vertex_data_tex(exa,
929                               dx1, dy1,
930                               dx2, dy2,
931                               s0, t0, s1, t1,
932                               0.0f);
933
934   if (buf) {
935      util_draw_vertex_buffer(exa->pipe, buf, 0,
936                              PIPE_PRIM_TRIANGLE_FAN,
937                              4,  /* verts */
938                              2); /* attribs/vert */
939
940      pipe_buffer_reference(&buf, NULL);
941   }
942
943   /* restore state we changed */
944   cso_restore_blend(exa->cso);
945   cso_restore_samplers(exa->cso);
946   cso_restore_sampler_textures(exa->cso);
947   cso_restore_framebuffer(exa->cso);
948   cso_restore_vertex_shader(exa->cso);
949   cso_restore_fragment_shader(exa->cso);
950   cso_restore_viewport(exa->cso);
951
952   pipe_surface_reference(&dst_surf, NULL);
953}
954
955void xorg_copy_pixmap(struct exa_context *ctx,
956                      struct exa_pixmap_priv *dst_priv, int dx, int dy,
957                      struct exa_pixmap_priv *src_priv, int sx, int sy,
958                      int width, int height)
959{
960   float dst_loc[4], src_loc[4];
961   float dst_bounds[4], src_bounds[4];
962   float src_shift[4], dst_shift[4], shift[4];
963   struct pipe_texture *dst = dst_priv->tex;
964   struct pipe_texture *src = src_priv->tex;
965
966   xorg_exa_finish(ctx);
967
968   dst_loc[0] = dx;
969   dst_loc[1] = dy;
970   dst_loc[2] = width;
971   dst_loc[3] = height;
972   dst_bounds[0] = 0.f;
973   dst_bounds[1] = 0.f;
974   dst_bounds[2] = dst->width[0];
975   dst_bounds[3] = dst->height[0];
976
977   src_loc[0] = sx;
978   src_loc[1] = sy;
979   src_loc[2] = width;
980   src_loc[3] = height;
981   src_bounds[0] = 0.f;
982   src_bounds[1] = 0.f;
983   src_bounds[2] = src->width[0];
984   src_bounds[3] = src->height[0];
985
986   bound_rect(src_loc, src_bounds, src_shift);
987   bound_rect(dst_loc, dst_bounds, dst_shift);
988   shift[0] = src_shift[0] - dst_shift[0];
989   shift[1] = src_shift[1] - dst_shift[1];
990
991   if (shift[0] < 0)
992      shift_rectx(src_loc, src_bounds, -shift[0]);
993   else
994      shift_rectx(dst_loc, dst_bounds, shift[0]);
995
996   if (shift[1] < 0)
997      shift_recty(src_loc, src_bounds, -shift[1]);
998   else
999      shift_recty(dst_loc, dst_bounds, shift[1]);
1000
1001   sync_size(src_loc, dst_loc);
1002
1003   if (src_loc[2] >= 0 && src_loc[3] >= 0 &&
1004       dst_loc[2] >= 0 && dst_loc[3] >= 0) {
1005      renderer_copy_texture(ctx,
1006                            src,
1007                            src_loc[0],
1008                            src_loc[1],
1009                            src_loc[0] + src_loc[2],
1010                            src_loc[1] + src_loc[3],
1011                            dst,
1012                            dst_loc[0],
1013                            dst_loc[1],
1014                            dst_loc[0] + dst_loc[2],
1015                            dst_loc[1] + dst_loc[3]);
1016   }
1017}
1018
1019