xorg_composite.c revision 8c37a4c8fd133f3cddc6798a0834038730acc213
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 rgb_dst_factor:5;    /**< PIPE_BLENDFACTOR_x */
16
17   unsigned alpha_src_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   debug_printf("Color Pixel=(%d, %d, %d, %d), RGBA=(%f, %f, %f, %f)\n",
657                (fg >> 24) & 0xff, (fg >> 16) & 0xff,
658                (fg >> 8) & 0xff,  (fg >> 0) & 0xff,
659                exa->solid_color[0], exa->solid_color[1],
660                exa->solid_color[2], exa->solid_color[3]);
661
662#if 0
663   exa->solid_color[0] = 1.f;
664   exa->solid_color[1] = 0.f;
665   exa->solid_color[2] = 0.f;
666   exa->solid_color[3] = 1.f;
667#endif
668
669   vs_traits = VS_SOLID_FILL;
670   fs_traits = FS_SOLID_FILL;
671
672   bind_framebuffer_state(exa, pixmap);
673   bind_viewport_state(exa, pixmap);
674   bind_rasterizer_state(exa);
675   bind_blend_state(exa, PictOpSrc, NULL, NULL);
676   setup_constant_buffers(exa, pixmap);
677   bind_clip_state(exa);
678
679   shader = xorg_shaders_get(exa->shaders, vs_traits, fs_traits);
680   cso_set_vertex_shader_handle(exa->cso, shader.vs);
681   cso_set_fragment_shader_handle(exa->cso, shader.fs);
682
683   return FALSE;
684}
685
686void xorg_solid(struct exa_context *exa,
687                struct exa_pixmap_priv *pixmap,
688                int x0, int y0, int x1, int y1)
689{
690   struct pipe_context *pipe = exa->pipe;
691   struct pipe_buffer *buf = 0;
692   float vertices[4][2][4];
693
694   x0 = 10; y0 = 10;
695   x1 = 300; y1 = 300;
696
697   /* 1st vertex */
698   setup_vertex0(vertices[0], x0, y0,
699                 exa->solid_color);
700   /* 2nd vertex */
701   setup_vertex0(vertices[1], x1, y0,
702                 exa->solid_color);
703   /* 3rd vertex */
704   setup_vertex0(vertices[2], x1, y1,
705                 exa->solid_color);
706   /* 4th vertex */
707   setup_vertex0(vertices[3], x0, y1,
708                 exa->solid_color);
709
710   buf = pipe_user_buffer_create(exa->pipe->screen,
711                                 vertices,
712                                 sizeof(vertices));
713
714
715   if (buf) {
716      debug_printf("Drawing buf is %p\n", buf);
717      util_draw_vertex_buffer(pipe, buf, 0,
718                              PIPE_PRIM_TRIANGLE_FAN,
719                              4,  /* verts */
720                              2); /* attribs/vert */
721
722      pipe_buffer_reference(&buf, NULL);
723   }
724}
725
726
727static INLINE void shift_rectx(float coords[4],
728                               const float *bounds,
729                               const float shift)
730{
731   coords[0] += shift;
732   coords[2] -= shift;
733   if (bounds) {
734      coords[2] = MIN2(coords[2], bounds[2]);
735      /* bound x/y + width/height */
736      if ((coords[0] + coords[2]) > (bounds[0] + bounds[2])) {
737         coords[2] = (bounds[0] + bounds[2]) - coords[0];
738      }
739   }
740}
741
742static INLINE void shift_recty(float coords[4],
743                               const float *bounds,
744                               const float shift)
745{
746   coords[1] += shift;
747   coords[3] -= shift;
748   if (bounds) {
749      coords[3] = MIN2(coords[3], bounds[3]);
750      if ((coords[1] + coords[3]) > (bounds[1] + bounds[3])) {
751         coords[3] = (bounds[1] + bounds[3]) - coords[1];
752      }
753   }
754}
755
756static INLINE void bound_rect(float coords[4],
757                              const float bounds[4],
758                              float shift[4])
759{
760   /* if outside the bounds */
761   if (coords[0] > (bounds[0] + bounds[2]) ||
762       coords[1] > (bounds[1] + bounds[3]) ||
763       (coords[0] + coords[2]) < bounds[0] ||
764       (coords[1] + coords[3]) < bounds[1]) {
765      coords[0] = 0.f;
766      coords[1] = 0.f;
767      coords[2] = 0.f;
768      coords[3] = 0.f;
769      shift[0] = 0.f;
770      shift[1] = 0.f;
771      return;
772   }
773
774   /* bound x */
775   if (coords[0] < bounds[0]) {
776      shift[0] = bounds[0] - coords[0];
777      coords[2] -= shift[0];
778      coords[0] = bounds[0];
779   } else
780      shift[0] = 0.f;
781
782   /* bound y */
783   if (coords[1] < bounds[1]) {
784      shift[1] = bounds[1] - coords[1];
785      coords[3] -= shift[1];
786      coords[1] = bounds[1];
787   } else
788      shift[1] = 0.f;
789
790   shift[2] = bounds[2] - coords[2];
791   shift[3] = bounds[3] - coords[3];
792   /* bound width/height */
793   coords[2] = MIN2(coords[2], bounds[2]);
794   coords[3] = MIN2(coords[3], bounds[3]);
795
796   /* bound x/y + width/height */
797   if ((coords[0] + coords[2]) > (bounds[0] + bounds[2])) {
798      coords[2] = (bounds[0] + bounds[2]) - coords[0];
799   }
800   if ((coords[1] + coords[3]) > (bounds[1] + bounds[3])) {
801      coords[3] = (bounds[1] + bounds[3]) - coords[1];
802   }
803
804   /* if outside the bounds */
805   if ((coords[0] + coords[2]) < bounds[0] ||
806       (coords[1] + coords[3]) < bounds[1]) {
807      coords[0] = 0.f;
808      coords[1] = 0.f;
809      coords[2] = 0.f;
810      coords[3] = 0.f;
811      return;
812   }
813}
814
815static INLINE void sync_size(float *src_loc, float *dst_loc)
816{
817   src_loc[2] = MIN2(src_loc[2], dst_loc[2]);
818   src_loc[3] = MIN2(src_loc[3], dst_loc[3]);
819   dst_loc[2] = src_loc[2];
820   dst_loc[3] = src_loc[3];
821}
822
823
824static void renderer_copy_texture(struct exa_context *exa,
825                                  struct pipe_texture *src,
826                                  float sx1, float sy1,
827                                  float sx2, float sy2,
828                                  struct pipe_texture *dst,
829                                  float dx1, float dy1,
830                                  float dx2, float dy2)
831{
832   struct pipe_context *pipe = exa->pipe;
833   struct pipe_screen *screen = pipe->screen;
834   struct pipe_buffer *buf;
835   struct pipe_surface *dst_surf = screen->get_tex_surface(
836      screen, dst, 0, 0, 0,
837      PIPE_BUFFER_USAGE_GPU_WRITE);
838   struct pipe_framebuffer_state fb;
839   float s0, t0, s1, t1;
840   struct xorg_shader shader;
841
842   assert(src->width[0] != 0);
843   assert(src->height[0] != 0);
844   assert(dst->width[0] != 0);
845   assert(dst->height[0] != 0);
846
847#if 0
848   debug_printf("copy texture [%f, %f, %f, %f], [%f, %f, %f, %f]\n",
849                sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2);
850#endif
851
852#if 1
853   s0 = sx1 / src->width[0];
854   s1 = sx2 / src->width[0];
855   t0 = sy1 / src->height[0];
856   t1 = sy2 / src->height[0];
857#else
858   s0 = 0;
859   s1 = 1;
860   t0 = 0;
861   t1 = 1;
862#endif
863
864   assert(screen->is_format_supported(screen, dst_surf->format, PIPE_TEXTURE_2D,
865                                      PIPE_TEXTURE_USAGE_RENDER_TARGET, 0));
866
867   /* save state (restored below) */
868   cso_save_blend(exa->cso);
869   cso_save_samplers(exa->cso);
870   cso_save_sampler_textures(exa->cso);
871   cso_save_framebuffer(exa->cso);
872   cso_save_fragment_shader(exa->cso);
873   cso_save_vertex_shader(exa->cso);
874
875   cso_save_viewport(exa->cso);
876
877
878   /* set misc state we care about */
879   {
880      struct pipe_blend_state blend;
881      memset(&blend, 0, sizeof(blend));
882      blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
883      blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
884      blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
885      blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
886      blend.colormask = PIPE_MASK_RGBA;
887      cso_set_blend(exa->cso, &blend);
888   }
889
890   /* sampler */
891   {
892      struct pipe_sampler_state sampler;
893      memset(&sampler, 0, sizeof(sampler));
894      sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
895      sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
896      sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
897      sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
898      sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
899      sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
900      sampler.normalized_coords = 1;
901      cso_single_sampler(exa->cso, 0, &sampler);
902      cso_single_sampler_done(exa->cso);
903   }
904
905   set_viewport(exa, dst_surf->width, dst_surf->height, Y0_TOP);
906
907   /* texture */
908   cso_set_sampler_textures(exa->cso, 1, &src);
909
910   /* shaders */
911   shader = xorg_shaders_get(exa->shaders,
912                             VS_COMPOSITE,
913                             FS_COMPOSITE);
914   cso_set_vertex_shader_handle(exa->cso, shader.vs);
915   cso_set_fragment_shader_handle(exa->cso, shader.fs);
916
917   /* drawing dest */
918   memset(&fb, 0, sizeof(fb));
919   fb.width = dst_surf->width;
920   fb.height = dst_surf->height;
921   fb.nr_cbufs = 1;
922   fb.cbufs[0] = dst_surf;
923   {
924      int i;
925      for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i)
926         fb.cbufs[i] = 0;
927   }
928   cso_set_framebuffer(exa->cso, &fb);
929
930   /* draw quad */
931   buf = setup_vertex_data_tex(exa,
932                               dx1, dy1,
933                               dx2, dy2,
934                               s0, t0, s1, t1,
935                               0.0f);
936
937   if (buf) {
938      util_draw_vertex_buffer(exa->pipe, buf, 0,
939                              PIPE_PRIM_TRIANGLE_FAN,
940                              4,  /* verts */
941                              2); /* attribs/vert */
942
943      pipe_buffer_reference(&buf, NULL);
944   }
945
946   /* restore state we changed */
947   cso_restore_blend(exa->cso);
948   cso_restore_samplers(exa->cso);
949   cso_restore_sampler_textures(exa->cso);
950   cso_restore_framebuffer(exa->cso);
951   cso_restore_vertex_shader(exa->cso);
952   cso_restore_fragment_shader(exa->cso);
953   cso_restore_viewport(exa->cso);
954
955   pipe_surface_reference(&dst_surf, NULL);
956}
957
958void xorg_copy_pixmap(struct exa_context *ctx,
959                      struct exa_pixmap_priv *dst_priv, int dx, int dy,
960                      struct exa_pixmap_priv *src_priv, int sx, int sy,
961                      int width, int height)
962{
963   float dst_loc[4], src_loc[4];
964   float dst_bounds[4], src_bounds[4];
965   float src_shift[4], dst_shift[4], shift[4];
966   struct pipe_texture *dst = dst_priv->tex;
967   struct pipe_texture *src = src_priv->tex;
968
969   dst_loc[0] = dx;
970   dst_loc[1] = dy;
971   dst_loc[2] = width;
972   dst_loc[3] = height;
973   dst_bounds[0] = 0.f;
974   dst_bounds[1] = 0.f;
975   dst_bounds[2] = dst->width[0];
976   dst_bounds[3] = dst->height[0];
977
978   src_loc[0] = sx;
979   src_loc[1] = sy;
980   src_loc[2] = width;
981   src_loc[3] = height;
982   src_bounds[0] = 0.f;
983   src_bounds[1] = 0.f;
984   src_bounds[2] = src->width[0];
985   src_bounds[3] = src->height[0];
986
987   bound_rect(src_loc, src_bounds, src_shift);
988   bound_rect(dst_loc, dst_bounds, dst_shift);
989   shift[0] = src_shift[0] - dst_shift[0];
990   shift[1] = src_shift[1] - dst_shift[1];
991
992   if (shift[0] < 0)
993      shift_rectx(src_loc, src_bounds, -shift[0]);
994   else
995      shift_rectx(dst_loc, dst_bounds, shift[0]);
996
997   if (shift[1] < 0)
998      shift_recty(src_loc, src_bounds, -shift[1]);
999   else
1000      shift_recty(dst_loc, dst_bounds, shift[1]);
1001
1002   sync_size(src_loc, dst_loc);
1003
1004   if (src_loc[2] >= 0 && src_loc[3] >= 0 &&
1005       dst_loc[2] >= 0 && dst_loc[3] >= 0) {
1006      renderer_copy_texture(ctx,
1007                            src,
1008                            src_loc[0],
1009                            src_loc[1] + src_loc[3],
1010                            src_loc[0] + src_loc[2],
1011                            src_loc[1],
1012                            dst,
1013                            dst_loc[0],
1014                            dst_loc[1] + dst_loc[3],
1015                            dst_loc[0] + dst_loc[2],
1016                            dst_loc[1]);
1017   }
1018}
1019
1020