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