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