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