xorg_renderer.c revision a9f8baf00b264a9b370ecb611334af3063674ce5
1#include "xorg_exa.h"
2#include "xorg_renderer.h"
3
4#include "xorg_exa_tgsi.h"
5
6#include "cso_cache/cso_context.h"
7#include "util/u_draw_quad.h"
8#include "util/u_math.h"
9#include "util/u_memory.h"
10#include "util/u_rect.h"
11
12#include "pipe/p_inlines.h"
13
14#include <math.h>
15
16enum AxisOrientation {
17   Y0_BOTTOM,
18   Y0_TOP
19};
20
21#define floatsEqual(x, y) (fabs(x - y) <= 0.00001f * MIN2(fabs(x), fabs(y)))
22#define floatIsZero(x) (floatsEqual((x) + 1, 1))
23
24static INLINE boolean is_affine(float *matrix)
25{
26   return floatIsZero(matrix[2]) && floatIsZero(matrix[5])
27      && floatsEqual(matrix[8], 1);
28}
29static INLINE void map_point(float *mat, float x, float y,
30                             float *out_x, float *out_y)
31{
32   if (!mat) {
33      *out_x = x;
34      *out_y = y;
35      return;
36   }
37
38   *out_x = mat[0]*x + mat[3]*y + mat[6];
39   *out_y = mat[1]*x + mat[4]*y + mat[7];
40   if (!is_affine(mat)) {
41      float w = 1/(mat[2]*x + mat[5]*y + mat[8]);
42      *out_x *= w;
43      *out_y *= w;
44   }
45}
46
47static void
48renderer_init_state(struct xorg_renderer *r)
49{
50   struct pipe_depth_stencil_alpha_state dsa;
51
52   /* set common initial clip state */
53   memset(&dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state));
54   cso_set_depth_stencil_alpha(r->cso, &dsa);
55}
56
57
58static INLINE void
59setup_vertex0(float vertex[2][4], float x, float y,
60              float color[4])
61{
62   vertex[0][0] = x;
63   vertex[0][1] = y;
64   vertex[0][2] = 0.f; /*z*/
65   vertex[0][3] = 1.f; /*w*/
66
67   vertex[1][0] = color[0]; /*r*/
68   vertex[1][1] = color[1]; /*g*/
69   vertex[1][2] = color[2]; /*b*/
70   vertex[1][3] = color[3]; /*a*/
71}
72
73static INLINE void
74setup_vertex1(float vertex[2][4], float x, float y, float s, float t)
75{
76   vertex[0][0] = x;
77   vertex[0][1] = y;
78   vertex[0][2] = 0.f; /*z*/
79   vertex[0][3] = 1.f; /*w*/
80
81   vertex[1][0] = s;   /*s*/
82   vertex[1][1] = t;   /*t*/
83   vertex[1][2] = 0.f; /*r*/
84   vertex[1][3] = 1.f; /*q*/
85}
86
87static struct pipe_buffer *
88setup_vertex_data1(struct xorg_renderer *r,
89                   float srcX, float srcY,  float dstX, float dstY,
90                   float width, float height,
91                   struct pipe_texture *src, float *src_matrix)
92{
93   float s0, t0, s1, t1;
94   float pt0[2], pt1[2];
95
96   pt0[0] = srcX;
97   pt0[1] = srcY;
98   pt1[0] = (srcX + width);
99   pt1[1] = (srcY + height);
100
101   if (src_matrix) {
102      map_point(src_matrix, pt0[0], pt0[1], &pt0[0], &pt0[1]);
103      map_point(src_matrix, pt1[0], pt1[1], &pt1[0], &pt1[1]);
104   }
105
106   s0 =  pt0[0] / src->width[0];
107   s1 =  pt1[0] / src->width[0];
108   t0 =  pt0[1] / src->height[0];
109   t1 =  pt1[1] / src->height[0];
110
111   /* 1st vertex */
112   setup_vertex1(r->vertices2[0], dstX, dstY, s0, t0);
113   /* 2nd vertex */
114   setup_vertex1(r->vertices2[1], dstX + width, dstY, s1, t0);
115   /* 3rd vertex */
116   setup_vertex1(r->vertices2[2], dstX + width, dstY + height, s1, t1);
117   /* 4th vertex */
118   setup_vertex1(r->vertices2[3], dstX, dstY + height, s0, t1);
119
120   return pipe_user_buffer_create(r->pipe->screen,
121                                  r->vertices2,
122                                  sizeof(r->vertices2));
123}
124
125static struct pipe_buffer *
126setup_vertex_data_tex(struct xorg_renderer *r,
127                      float x0, float y0, float x1, float y1,
128                      float s0, float t0, float s1, float t1,
129                      float z)
130{
131   /* 1st vertex */
132   setup_vertex1(r->vertices2[0], x0, y0, s0, t0);
133   /* 2nd vertex */
134   setup_vertex1(r->vertices2[1], x1, y0, s1, t0);
135   /* 3rd vertex */
136   setup_vertex1(r->vertices2[2], x1, y1, s1, t1);
137   /* 4th vertex */
138   setup_vertex1(r->vertices2[3], x0, y1, s0, t1);
139
140   return pipe_user_buffer_create(r->pipe->screen,
141                                  r->vertices2,
142                                  sizeof(r->vertices2));
143}
144
145static INLINE void
146setup_vertex2(float vertex[3][4], float x, float y,
147              float s0, float t0, float s1, float t1)
148{
149   vertex[0][0] = x;
150   vertex[0][1] = y;
151   vertex[0][2] = 0.f; /*z*/
152   vertex[0][3] = 1.f; /*w*/
153
154   vertex[1][0] = s0;  /*s*/
155   vertex[1][1] = t0;  /*t*/
156   vertex[1][2] = 0.f; /*r*/
157   vertex[1][3] = 1.f; /*q*/
158
159   vertex[2][0] = s1;  /*s*/
160   vertex[2][1] = t1;  /*t*/
161   vertex[2][2] = 0.f; /*r*/
162   vertex[2][3] = 1.f; /*q*/
163}
164
165static struct pipe_buffer *
166setup_vertex_data2(struct xorg_renderer *r,
167                   float srcX, float srcY, float maskX, float maskY,
168                   float dstX, float dstY, float width, float height,
169                   struct pipe_texture *src,
170                   struct pipe_texture *mask,
171                   float *src_matrix, float *mask_matrix)
172{
173   float src_s0, src_t0, src_s1, src_t1;
174   float mask_s0, mask_t0, mask_s1, mask_t1;
175   float spt0[2], spt1[2];
176   float mpt0[2], mpt1[2];
177
178   spt0[0] = srcX;
179   spt0[1] = srcY;
180   spt1[0] = srcX + width;
181   spt1[1] = srcY + height;
182
183   mpt0[0] = maskX;
184   mpt0[1] = maskY;
185   mpt1[0] = maskX + width;
186   mpt1[1] = maskY + height;
187
188   if (src_matrix) {
189      map_point(src_matrix, spt0[0], spt0[1], &spt0[0], &spt0[1]);
190      map_point(src_matrix, spt1[0], spt1[1], &spt1[0], &spt1[1]);
191   }
192
193   if (mask_matrix) {
194      map_point(mask_matrix, mpt0[0], mpt0[1], &mpt0[0], &mpt0[1]);
195      map_point(mask_matrix, mpt1[0], mpt1[1], &mpt1[0], &mpt1[1]);
196   }
197
198   src_s0 = spt0[0] / src->width[0];
199   src_t0 = spt0[1] / src->height[0];
200   src_s1 = spt1[0] / src->width[0];
201   src_t1 = spt1[1] / src->height[0];
202
203   mask_s0 = mpt0[0] / mask->width[0];
204   mask_t0 = mpt0[1] / mask->height[0];
205   mask_s1 = mpt1[0] / mask->width[0];
206   mask_t1 = mpt1[1] / mask->height[0];
207
208   /* 1st vertex */
209   setup_vertex2(r->vertices3[0], dstX, dstY,
210                 src_s0, src_t0, mask_s0, mask_t0);
211   /* 2nd vertex */
212   setup_vertex2(r->vertices3[1], dstX + width, dstY,
213                 src_s1, src_t0, mask_s1, mask_t0);
214   /* 3rd vertex */
215   setup_vertex2(r->vertices3[2], dstX + width, dstY + height,
216                 src_s1, src_t1, mask_s1, mask_t1);
217   /* 4th vertex */
218   setup_vertex2(r->vertices3[3], dstX, dstY + height,
219                 src_s0, src_t1, mask_s0, mask_t1);
220
221
222   return pipe_user_buffer_create(r->pipe->screen,
223                                  r->vertices3,
224                                  sizeof(r->vertices3));
225}
226
227static struct pipe_buffer *
228setup_vertex_data_yuv(struct xorg_renderer *r,
229                      float srcX, float srcY,
230                      float dstX, float dstY,
231                      float width, float height,
232                      struct pipe_texture **tex)
233{
234   float s0, t0, s1, t1;
235   float spt0[2], spt1[2];
236
237   spt0[0] = srcX;
238   spt0[1] = srcY;
239   spt1[0] = srcX + width;
240   spt1[1] = srcY + height;
241
242   s0 = spt0[0] / tex[0]->width[0];
243   t0 = spt0[1] / tex[0]->height[0];
244   s1 = spt1[0] / tex[0]->width[0];
245   t1 = spt1[1] / tex[0]->height[0];
246
247   /* 1st vertex */
248   setup_vertex1(r->vertices2[0], dstX, dstY, s0, t0);
249   /* 2nd vertex */
250   setup_vertex1(r->vertices2[1], dstX + width, dstY,
251                 s1, t0);
252   /* 3rd vertex */
253   setup_vertex1(r->vertices2[2], dstX + width, dstY + height,
254                 s1, t1);
255   /* 4th vertex */
256   setup_vertex1(r->vertices2[3], dstX, dstY + height,
257                 s0, t1);
258
259
260   return pipe_user_buffer_create(r->pipe->screen,
261                                  r->vertices2,
262                                  sizeof(r->vertices2));
263}
264
265
266
267static void
268set_viewport(struct xorg_renderer *r, int width, int height,
269             enum AxisOrientation orientation)
270{
271   struct pipe_viewport_state viewport;
272   float y_scale = (orientation == Y0_BOTTOM) ? -2.f : 2.f;
273
274   viewport.scale[0] =  width / 2.f;
275   viewport.scale[1] =  height / y_scale;
276   viewport.scale[2] =  1.0;
277   viewport.scale[3] =  1.0;
278   viewport.translate[0] = width / 2.f;
279   viewport.translate[1] = height / 2.f;
280   viewport.translate[2] = 0.0;
281   viewport.translate[3] = 0.0;
282
283   cso_set_viewport(r->cso, &viewport);
284}
285
286
287
288struct xorg_renderer * renderer_create(struct pipe_context *pipe)
289{
290   struct xorg_renderer *renderer = CALLOC_STRUCT(xorg_renderer);
291
292   renderer->pipe = pipe;
293   renderer->cso = cso_create_context(pipe);
294   renderer->shaders = xorg_shaders_create(renderer);
295
296   renderer_init_state(renderer);
297
298   return renderer;
299}
300
301void renderer_destroy(struct xorg_renderer *r)
302{
303   struct pipe_constant_buffer *vsbuf = &r->vs_const_buffer;
304   struct pipe_constant_buffer *fsbuf = &r->fs_const_buffer;
305
306   if (vsbuf && vsbuf->buffer)
307      pipe_buffer_reference(&vsbuf->buffer, NULL);
308
309   if (fsbuf && fsbuf->buffer)
310      pipe_buffer_reference(&fsbuf->buffer, NULL);
311
312   if (r->shaders) {
313      xorg_shaders_destroy(r->shaders);
314      r->shaders = NULL;
315   }
316
317   if (r->cso) {
318      cso_release_all(r->cso);
319      cso_destroy_context(r->cso);
320      r->cso = NULL;
321   }
322}
323
324void renderer_bind_framebuffer(struct xorg_renderer *r,
325                               struct exa_pixmap_priv *priv)
326{
327   unsigned i;
328   struct pipe_framebuffer_state state;
329   struct pipe_surface *surface = xorg_gpu_surface(r->pipe->screen, priv);
330   memset(&state, 0, sizeof(struct pipe_framebuffer_state));
331
332   state.width  = priv->tex->width[0];
333   state.height = priv->tex->height[0];
334
335   state.nr_cbufs = 1;
336   state.cbufs[0] = surface;
337   for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i)
338      state.cbufs[i] = 0;
339
340   /* currently we don't use depth/stencil */
341   state.zsbuf = 0;
342
343   cso_set_framebuffer(r->cso, &state);
344
345   /* we do fire and forget for the framebuffer, this is the forget part */
346   pipe_surface_reference(&surface, NULL);
347}
348
349void renderer_bind_viewport(struct xorg_renderer *r,
350                            struct exa_pixmap_priv *dst)
351{
352   int width = dst->tex->width[0];
353   int height = dst->tex->height[0];
354
355   /*debug_printf("Bind viewport (%d, %d)\n", width, height);*/
356
357   set_viewport(r, width, height, Y0_TOP);
358}
359
360void renderer_bind_rasterizer(struct xorg_renderer *r)
361{
362   struct pipe_rasterizer_state raster;
363
364   /* XXX: move to renderer_init_state? */
365   memset(&raster, 0, sizeof(struct pipe_rasterizer_state));
366   raster.gl_rasterization_rules = 1;
367   cso_set_rasterizer(r->cso, &raster);
368}
369
370void renderer_set_constants(struct xorg_renderer *r,
371                            int shader_type,
372                            const float *params,
373                            int param_bytes)
374{
375   struct pipe_constant_buffer *cbuf =
376      (shader_type == PIPE_SHADER_VERTEX) ? &r->vs_const_buffer :
377      &r->fs_const_buffer;
378
379   pipe_buffer_reference(&cbuf->buffer, NULL);
380   cbuf->buffer = pipe_buffer_create(r->pipe->screen, 16,
381                                     PIPE_BUFFER_USAGE_CONSTANT,
382                                     param_bytes);
383
384   if (cbuf->buffer) {
385      pipe_buffer_write(r->pipe->screen, cbuf->buffer,
386                        0, param_bytes, params);
387   }
388   r->pipe->set_constant_buffer(r->pipe, shader_type, 0, cbuf);
389}
390
391static void
392setup_vs_constant_buffer(struct xorg_renderer *r,
393                         int width, int height)
394{
395   const int param_bytes = 8 * sizeof(float);
396   float vs_consts[8] = {
397      2.f/width, 2.f/height, 1, 1,
398      -1, -1, 0, 0
399   };
400   renderer_set_constants(r, PIPE_SHADER_VERTEX,
401                          vs_consts, param_bytes);
402}
403
404static void
405setup_fs_constant_buffer(struct xorg_renderer *r)
406{
407   const int param_bytes = 4 * sizeof(float);
408   const float fs_consts[8] = {
409      0, 0, 0, 1,
410   };
411   renderer_set_constants(r, PIPE_SHADER_FRAGMENT,
412                          fs_consts, param_bytes);
413}
414
415static INLINE void shift_rectx(float coords[4],
416                               const float *bounds,
417                               const float shift)
418{
419   coords[0] += shift;
420   coords[2] -= shift;
421   if (bounds) {
422      coords[2] = MIN2(coords[2], bounds[2]);
423      /* bound x/y + width/height */
424      if ((coords[0] + coords[2]) > (bounds[0] + bounds[2])) {
425         coords[2] = (bounds[0] + bounds[2]) - coords[0];
426      }
427   }
428}
429
430static INLINE void shift_recty(float coords[4],
431                               const float *bounds,
432                               const float shift)
433{
434   coords[1] += shift;
435   coords[3] -= shift;
436   if (bounds) {
437      coords[3] = MIN2(coords[3], bounds[3]);
438      if ((coords[1] + coords[3]) > (bounds[1] + bounds[3])) {
439         coords[3] = (bounds[1] + bounds[3]) - coords[1];
440      }
441   }
442}
443
444static INLINE void bound_rect(float coords[4],
445                              const float bounds[4],
446                              float shift[4])
447{
448   /* if outside the bounds */
449   if (coords[0] > (bounds[0] + bounds[2]) ||
450       coords[1] > (bounds[1] + bounds[3]) ||
451       (coords[0] + coords[2]) < bounds[0] ||
452       (coords[1] + coords[3]) < bounds[1]) {
453      coords[0] = 0.f;
454      coords[1] = 0.f;
455      coords[2] = 0.f;
456      coords[3] = 0.f;
457      shift[0] = 0.f;
458      shift[1] = 0.f;
459      return;
460   }
461
462   /* bound x */
463   if (coords[0] < bounds[0]) {
464      shift[0] = bounds[0] - coords[0];
465      coords[2] -= shift[0];
466      coords[0] = bounds[0];
467   } else
468      shift[0] = 0.f;
469
470   /* bound y */
471   if (coords[1] < bounds[1]) {
472      shift[1] = bounds[1] - coords[1];
473      coords[3] -= shift[1];
474      coords[1] = bounds[1];
475   } else
476      shift[1] = 0.f;
477
478   shift[2] = bounds[2] - coords[2];
479   shift[3] = bounds[3] - coords[3];
480   /* bound width/height */
481   coords[2] = MIN2(coords[2], bounds[2]);
482   coords[3] = MIN2(coords[3], bounds[3]);
483
484   /* bound x/y + width/height */
485   if ((coords[0] + coords[2]) > (bounds[0] + bounds[2])) {
486      coords[2] = (bounds[0] + bounds[2]) - coords[0];
487   }
488   if ((coords[1] + coords[3]) > (bounds[1] + bounds[3])) {
489      coords[3] = (bounds[1] + bounds[3]) - coords[1];
490   }
491
492   /* if outside the bounds */
493   if ((coords[0] + coords[2]) < bounds[0] ||
494       (coords[1] + coords[3]) < bounds[1]) {
495      coords[0] = 0.f;
496      coords[1] = 0.f;
497      coords[2] = 0.f;
498      coords[3] = 0.f;
499      return;
500   }
501}
502
503static INLINE void sync_size(float *src_loc, float *dst_loc)
504{
505   src_loc[2] = MIN2(src_loc[2], dst_loc[2]);
506   src_loc[3] = MIN2(src_loc[3], dst_loc[3]);
507   dst_loc[2] = src_loc[2];
508   dst_loc[3] = src_loc[3];
509}
510
511static void renderer_copy_texture(struct xorg_renderer *r,
512                                  struct pipe_texture *src,
513                                  float sx1, float sy1,
514                                  float sx2, float sy2,
515                                  struct pipe_texture *dst,
516                                  float dx1, float dy1,
517                                  float dx2, float dy2)
518{
519   struct pipe_context *pipe = r->pipe;
520   struct pipe_screen *screen = pipe->screen;
521   struct pipe_buffer *buf;
522   struct pipe_surface *dst_surf = screen->get_tex_surface(
523      screen, dst, 0, 0, 0,
524      PIPE_BUFFER_USAGE_GPU_WRITE);
525   struct pipe_framebuffer_state fb;
526   float s0, t0, s1, t1;
527   struct xorg_shader shader;
528
529   assert(src->width[0] != 0);
530   assert(src->height[0] != 0);
531   assert(dst->width[0] != 0);
532   assert(dst->height[0] != 0);
533
534#if 1
535   s0 = sx1 / src->width[0];
536   s1 = sx2 / src->width[0];
537   t0 = sy1 / src->height[0];
538   t1 = sy2 / src->height[0];
539#else
540   s0 = 0;
541   s1 = 1;
542   t0 = 0;
543   t1 = 1;
544#endif
545
546#if 0
547   debug_printf("copy texture src=[%f, %f, %f, %f], dst=[%f, %f, %f, %f], tex=[%f, %f, %f, %f]\n",
548                sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2,
549                s0, t0, s1, t1);
550#endif
551
552   assert(screen->is_format_supported(screen, dst_surf->format,
553                                      PIPE_TEXTURE_2D,
554                                      PIPE_TEXTURE_USAGE_RENDER_TARGET,
555                                      0));
556
557   /* save state (restored below) */
558   cso_save_blend(r->cso);
559   cso_save_samplers(r->cso);
560   cso_save_sampler_textures(r->cso);
561   cso_save_framebuffer(r->cso);
562   cso_save_fragment_shader(r->cso);
563   cso_save_vertex_shader(r->cso);
564
565   cso_save_viewport(r->cso);
566
567
568   /* set misc state we care about */
569   {
570      struct pipe_blend_state blend;
571      memset(&blend, 0, sizeof(blend));
572      blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
573      blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
574      blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
575      blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
576      blend.colormask = PIPE_MASK_RGBA;
577      cso_set_blend(r->cso, &blend);
578   }
579
580   /* sampler */
581   {
582      struct pipe_sampler_state sampler;
583      memset(&sampler, 0, sizeof(sampler));
584      sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
585      sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
586      sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
587      sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
588      sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
589      sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
590      sampler.normalized_coords = 1;
591      cso_single_sampler(r->cso, 0, &sampler);
592      cso_single_sampler_done(r->cso);
593   }
594
595   set_viewport(r, dst_surf->width, dst_surf->height, Y0_TOP);
596
597   /* texture */
598   cso_set_sampler_textures(r->cso, 1, &src);
599
600   renderer_bind_rasterizer(r);
601
602   /* shaders */
603   shader = xorg_shaders_get(r->shaders,
604                             VS_COMPOSITE,
605                             FS_COMPOSITE);
606   cso_set_vertex_shader_handle(r->cso, shader.vs);
607   cso_set_fragment_shader_handle(r->cso, shader.fs);
608
609   /* drawing dest */
610   memset(&fb, 0, sizeof(fb));
611   fb.width = dst_surf->width;
612   fb.height = dst_surf->height;
613   fb.nr_cbufs = 1;
614   fb.cbufs[0] = dst_surf;
615   {
616      int i;
617      for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i)
618         fb.cbufs[i] = 0;
619   }
620   cso_set_framebuffer(r->cso, &fb);
621   setup_vs_constant_buffer(r, fb.width, fb.height);
622   setup_fs_constant_buffer(r);
623
624   /* draw quad */
625   buf = setup_vertex_data_tex(r,
626                               dx1, dy1,
627                               dx2, dy2,
628                               s0, t0, s1, t1,
629                               0.0f);
630
631   if (buf) {
632      util_draw_vertex_buffer(r->pipe, buf, 0,
633                              PIPE_PRIM_TRIANGLE_FAN,
634                              4,  /* verts */
635                              2); /* attribs/vert */
636
637      pipe_buffer_reference(&buf, NULL);
638   }
639
640   /* restore state we changed */
641   cso_restore_blend(r->cso);
642   cso_restore_samplers(r->cso);
643   cso_restore_sampler_textures(r->cso);
644   cso_restore_framebuffer(r->cso);
645   cso_restore_vertex_shader(r->cso);
646   cso_restore_fragment_shader(r->cso);
647   cso_restore_viewport(r->cso);
648
649   pipe_surface_reference(&dst_surf, NULL);
650}
651
652static struct pipe_texture *
653create_sampler_texture(struct xorg_renderer *r,
654                       struct pipe_texture *src)
655{
656   enum pipe_format format;
657   struct pipe_context *pipe = r->pipe;
658   struct pipe_screen *screen = pipe->screen;
659   struct pipe_texture *pt;
660   struct pipe_texture templ;
661
662   pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
663
664   /* the coming in texture should already have that invariance */
665   debug_assert(screen->is_format_supported(screen, src->format,
666                                            PIPE_TEXTURE_2D,
667                                            PIPE_TEXTURE_USAGE_SAMPLER, 0));
668
669   format = src->format;
670
671   memset(&templ, 0, sizeof(templ));
672   templ.target = PIPE_TEXTURE_2D;
673   templ.format = format;
674   templ.last_level = 0;
675   templ.width[0] = src->width[0];
676   templ.height[0] = src->height[0];
677   templ.depth[0] = 1;
678   pf_get_block(format, &templ.block);
679   templ.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER;
680
681   pt = screen->texture_create(screen, &templ);
682
683   debug_assert(!pt || pipe_is_referenced(&pt->reference));
684
685   if (!pt)
686      return NULL;
687
688   {
689      /* copy source framebuffer surface into texture */
690      struct pipe_surface *ps_read = screen->get_tex_surface(
691         screen, src, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ);
692      struct pipe_surface *ps_tex = screen->get_tex_surface(
693         screen, pt, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE );
694      if (pipe->surface_copy) {
695         pipe->surface_copy(pipe,
696                ps_tex, /* dest */
697                0, 0, /* destx/y */
698                ps_read,
699                0, 0, src->width[0], src->height[0]);
700      } else {
701          util_surface_copy(pipe, FALSE,
702                ps_tex, /* dest */
703                0, 0, /* destx/y */
704                ps_read,
705                0, 0, src->width[0], src->height[0]);
706      }
707      pipe_surface_reference(&ps_read, NULL);
708      pipe_surface_reference(&ps_tex, NULL);
709   }
710
711   return pt;
712}
713
714
715void renderer_copy_pixmap(struct xorg_renderer *r,
716                          struct exa_pixmap_priv *dst_priv, int dx, int dy,
717                          struct exa_pixmap_priv *src_priv, int sx, int sy,
718                          int width, int height)
719{
720   float dst_loc[4], src_loc[4];
721   float dst_bounds[4], src_bounds[4];
722   float src_shift[4], dst_shift[4], shift[4];
723   struct pipe_texture *dst = dst_priv->tex;
724   struct pipe_texture *src = src_priv->tex;
725
726   if (r->pipe->is_texture_referenced(r->pipe, src, 0, 0) &
727       PIPE_REFERENCED_FOR_WRITE)
728      r->pipe->flush(r->pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
729
730   dst_loc[0] = dx;
731   dst_loc[1] = dy;
732   dst_loc[2] = width;
733   dst_loc[3] = height;
734   dst_bounds[0] = 0.f;
735   dst_bounds[1] = 0.f;
736   dst_bounds[2] = dst->width[0];
737   dst_bounds[3] = dst->height[0];
738
739   src_loc[0] = sx;
740   src_loc[1] = sy;
741   src_loc[2] = width;
742   src_loc[3] = height;
743   src_bounds[0] = 0.f;
744   src_bounds[1] = 0.f;
745   src_bounds[2] = src->width[0];
746   src_bounds[3] = src->height[0];
747
748   bound_rect(src_loc, src_bounds, src_shift);
749   bound_rect(dst_loc, dst_bounds, dst_shift);
750   shift[0] = src_shift[0] - dst_shift[0];
751   shift[1] = src_shift[1] - dst_shift[1];
752
753   if (shift[0] < 0)
754      shift_rectx(src_loc, src_bounds, -shift[0]);
755   else
756      shift_rectx(dst_loc, dst_bounds, shift[0]);
757
758   if (shift[1] < 0)
759      shift_recty(src_loc, src_bounds, -shift[1]);
760   else
761      shift_recty(dst_loc, dst_bounds, shift[1]);
762
763   sync_size(src_loc, dst_loc);
764
765   if (src_loc[2] >= 0 && src_loc[3] >= 0 &&
766       dst_loc[2] >= 0 && dst_loc[3] >= 0) {
767      struct pipe_texture *temp_src = src;
768
769      if (src == dst)
770         temp_src = create_sampler_texture(r, src);
771
772      renderer_copy_texture(r,
773                            temp_src,
774                            src_loc[0],
775                            src_loc[1],
776                            src_loc[0] + src_loc[2],
777                            src_loc[1] + src_loc[3],
778                            dst,
779                            dst_loc[0],
780                            dst_loc[1],
781                            dst_loc[0] + dst_loc[2],
782                            dst_loc[1] + dst_loc[3]);
783
784      if (src == dst)
785         pipe_texture_reference(&temp_src, NULL);
786   }
787}
788
789void renderer_draw_solid_rect(struct xorg_renderer *r,
790                              int x0, int y0,
791                              int x1, int y1,
792                              float *color)
793{
794   struct pipe_context *pipe = r->pipe;
795   struct pipe_buffer *buf = 0;
796
797   /*
798   debug_printf("solid rect[(%d, %d), (%d, %d)], rgba[%f, %f, %f, %f]\n",
799   x0, y0, x1, y1, color[0], color[1], color[2], color[3]);*/
800   /* 1st vertex */
801   setup_vertex0(r->vertices2[0], x0, y0, color);
802   /* 2nd vertex */
803   setup_vertex0(r->vertices2[1], x1, y0, color);
804   /* 3rd vertex */
805   setup_vertex0(r->vertices2[2], x1, y1, color);
806   /* 4th vertex */
807   setup_vertex0(r->vertices2[3], x0, y1, color);
808
809   buf = pipe_user_buffer_create(pipe->screen,
810                                 r->vertices2,
811                                 sizeof(r->vertices2));
812
813
814   if (buf) {
815      util_draw_vertex_buffer(pipe, buf, 0,
816                              PIPE_PRIM_TRIANGLE_FAN,
817                              4,  /* verts */
818                              2); /* attribs/vert */
819
820      pipe_buffer_reference(&buf, NULL);
821   }
822}
823
824void renderer_draw_textures(struct xorg_renderer *r,
825                            int *pos,
826                            int width, int height,
827                            struct pipe_texture **textures,
828                            int num_textures,
829                            float *src_matrix, float *mask_matrix)
830{
831   struct pipe_context *pipe = r->pipe;
832   struct pipe_buffer *buf = 0;
833
834#if 0
835   if (src_matrix) {
836      debug_printf("src_matrix = \n");
837      debug_printf("%f, %f, %f\n", src_matrix[0], src_matrix[1], src_matrix[2]);
838      debug_printf("%f, %f, %f\n", src_matrix[3], src_matrix[4], src_matrix[5]);
839      debug_printf("%f, %f, %f\n", src_matrix[6], src_matrix[7], src_matrix[8]);
840   }
841   if (mask_matrix) {
842      debug_printf("mask_matrix = \n");
843      debug_printf("%f, %f, %f\n", mask_matrix[0], mask_matrix[1], mask_matrix[2]);
844      debug_printf("%f, %f, %f\n", mask_matrix[3], mask_matrix[4], mask_matrix[5]);
845      debug_printf("%f, %f, %f\n", mask_matrix[6], mask_matrix[7], mask_matrix[8]);
846   }
847#endif
848
849   switch(num_textures) {
850   case 1:
851      buf = setup_vertex_data1(r,
852                               pos[0], pos[1], /* src */
853                               pos[4], pos[5], /* dst */
854                               width, height,
855                               textures[0], src_matrix);
856      break;
857   case 2:
858      buf = setup_vertex_data2(r,
859                               pos[0], pos[1], /* src */
860                               pos[2], pos[3], /* mask */
861                               pos[4], pos[5], /* dst */
862                               width, height,
863                               textures[0], textures[1],
864                               src_matrix, mask_matrix);
865      break;
866   case 3:
867      buf = setup_vertex_data_yuv(r,
868                                  pos[0], pos[1],
869                                  pos[2], pos[3],
870                                  width, height,
871                                  textures);
872      break;
873   default:
874      debug_assert(!"Unsupported number of textures");
875      break;
876   }
877
878   if (buf) {
879      int num_attribs = 1; /*pos*/
880      num_attribs += num_textures;
881
882      util_draw_vertex_buffer(pipe, buf, 0,
883                              PIPE_PRIM_TRIANGLE_FAN,
884                              4,  /* verts */
885                              num_attribs); /* attribs/vert */
886
887      pipe_buffer_reference(&buf, NULL);
888   }
889}
890