st/xorg: More fallback debugging
[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 ScreenPtr pScreen = pDstPicture->pDrawable->pScreen;
287 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
288 modesettingPtr ms = modesettingPTR(pScrn);
289 unsigned i;
290 unsigned accel_ops_count =
291 sizeof(accelerated_ops)/sizeof(struct acceleration_info);
292
293 if (pSrcPicture->pSourcePict) {
294 /* Gradients not yet supported */
295 if (pSrcPicture->pSourcePict->type != SourcePictTypeSolidFill)
296 XORG_FALLBACK("gradients not yet supported");
297
298 /* Solid source with mask not yet handled properly */
299 if (pMaskPicture)
300 XORG_FALLBACK("solid source with mask not yet handled properly");
301 }
302
303 for (i = 0; i < accel_ops_count; ++i) {
304 if (op == accelerated_ops[i].op) {
305 /* Check for unsupported component alpha */
306 if ((pSrcPicture->componentAlpha &&
307 !accelerated_ops[i].component_alpha) ||
308 (pMaskPicture &&
309 (!accelerated_ops[i].with_mask ||
310 (pMaskPicture->componentAlpha &&
311 !accelerated_ops[i].component_alpha))))
312 XORG_FALLBACK("component alpha unsupported");
313 return TRUE;
314 }
315 }
316 XORG_FALLBACK("unsupported operation");
317 }
318
319 static void
320 bind_clip_state(struct exa_context *exa)
321 {
322 }
323
324 static void
325 bind_framebuffer_state(struct exa_context *exa, struct exa_pixmap_priv *pDst)
326 {
327 unsigned i;
328 struct pipe_framebuffer_state state;
329 struct pipe_surface *surface = exa_gpu_surface(exa, pDst);
330 memset(&state, 0, sizeof(struct pipe_framebuffer_state));
331
332 state.width = pDst->tex->width[0];
333 state.height = pDst->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(exa->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
349 enum AxisOrientation {
350 Y0_BOTTOM,
351 Y0_TOP
352 };
353
354 static void
355 set_viewport(struct exa_context *exa, int width, int height,
356 enum AxisOrientation orientation)
357 {
358 struct pipe_viewport_state viewport;
359 float y_scale = (orientation == Y0_BOTTOM) ? -2.f : 2.f;
360
361 viewport.scale[0] = width / 2.f;
362 viewport.scale[1] = height / y_scale;
363 viewport.scale[2] = 1.0;
364 viewport.scale[3] = 1.0;
365 viewport.translate[0] = width / 2.f;
366 viewport.translate[1] = height / 2.f;
367 viewport.translate[2] = 0.0;
368 viewport.translate[3] = 0.0;
369
370 cso_set_viewport(exa->cso, &viewport);
371 }
372
373 static void
374 bind_viewport_state(struct exa_context *exa, struct exa_pixmap_priv *pDst)
375 {
376 int width = pDst->tex->width[0];
377 int height = pDst->tex->height[0];
378
379 /*debug_printf("Bind viewport (%d, %d)\n", width, height);*/
380
381 set_viewport(exa, width, height, Y0_TOP);
382 }
383
384 static void
385 bind_blend_state(struct exa_context *exa, int op,
386 PicturePtr pSrcPicture, PicturePtr pMaskPicture)
387 {
388 struct xorg_composite_blend blend_opt;
389 struct pipe_blend_state blend;
390
391 blend_opt = blend_for_op(op);
392
393 memset(&blend, 0, sizeof(struct pipe_blend_state));
394 blend.blend_enable = 1;
395 blend.colormask |= PIPE_MASK_R;
396 blend.colormask |= PIPE_MASK_G;
397 blend.colormask |= PIPE_MASK_B;
398 blend.colormask |= PIPE_MASK_A;
399
400 blend.rgb_src_factor = blend_opt.rgb_src_factor;
401 blend.alpha_src_factor = blend_opt.alpha_src_factor;
402 blend.rgb_dst_factor = blend_opt.rgb_dst_factor;
403 blend.alpha_dst_factor = blend_opt.alpha_dst_factor;
404
405 cso_set_blend(exa->cso, &blend);
406 }
407
408 static void
409 bind_rasterizer_state(struct exa_context *exa)
410 {
411 struct pipe_rasterizer_state raster;
412 memset(&raster, 0, sizeof(struct pipe_rasterizer_state));
413 raster.gl_rasterization_rules = 1;
414 cso_set_rasterizer(exa->cso, &raster);
415 }
416
417 static void
418 bind_shaders(struct exa_context *exa, int op,
419 PicturePtr pSrcPicture, PicturePtr pMaskPicture)
420 {
421 unsigned vs_traits = 0, fs_traits = 0;
422 struct xorg_shader shader;
423
424 exa->has_solid_color = FALSE;
425
426 if (pSrcPicture) {
427 if (pSrcPicture->pSourcePict) {
428 if (pSrcPicture->pSourcePict->type == SourcePictTypeSolidFill) {
429 fs_traits |= FS_SOLID_FILL;
430 vs_traits |= VS_SOLID_FILL;
431 debug_assert(pSrcPicture->format == PICT_a8r8g8b8);
432 pixel_to_float4(pSrcPicture->pSourcePict->solidFill.color,
433 exa->solid_color);
434 exa->has_solid_color = TRUE;
435 } else {
436 debug_assert("!gradients not supported");
437 }
438 } else {
439 fs_traits |= FS_COMPOSITE;
440 vs_traits |= VS_COMPOSITE;
441 }
442 }
443
444 if (pMaskPicture) {
445 vs_traits |= VS_MASK;
446 fs_traits |= FS_MASK;
447 }
448
449 shader = xorg_shaders_get(exa->shaders, vs_traits, fs_traits);
450 cso_set_vertex_shader_handle(exa->cso, shader.vs);
451 cso_set_fragment_shader_handle(exa->cso, shader.fs);
452 }
453
454
455 static void
456 bind_samplers(struct exa_context *exa, int op,
457 PicturePtr pSrcPicture, PicturePtr pMaskPicture,
458 PicturePtr pDstPicture,
459 struct exa_pixmap_priv *pSrc,
460 struct exa_pixmap_priv *pMask,
461 struct exa_pixmap_priv *pDst)
462 {
463 struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
464 struct pipe_sampler_state src_sampler, mask_sampler;
465
466 exa->num_bound_samplers = 0;
467
468 memset(&src_sampler, 0, sizeof(struct pipe_sampler_state));
469 memset(&mask_sampler, 0, sizeof(struct pipe_sampler_state));
470
471 if ((pSrc && exa->pipe->is_texture_referenced(exa->pipe, pSrc->tex, 0, 0) &
472 PIPE_REFERENCED_FOR_WRITE) ||
473 (pMask && exa->pipe->is_texture_referenced(exa->pipe, pMask->tex, 0, 0) &
474 PIPE_REFERENCED_FOR_WRITE))
475 exa->pipe->flush(exa->pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
476
477 if (pSrcPicture && pSrc) {
478 unsigned src_wrap = render_repeat_to_gallium(
479 pSrcPicture->repeatType);
480 src_sampler.wrap_s = src_wrap;
481 src_sampler.wrap_t = src_wrap;
482 src_sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
483 src_sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
484 src_sampler.normalized_coords = 1;
485 samplers[0] = &src_sampler;
486 exa->bound_textures[0] = pSrc->tex;
487 ++exa->num_bound_samplers;
488 }
489
490 if (pMaskPicture && pMask) {
491 unsigned mask_wrap = render_repeat_to_gallium(
492 pMaskPicture->repeatType);
493 mask_sampler.wrap_s = mask_wrap;
494 mask_sampler.wrap_t = mask_wrap;
495 mask_sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
496 mask_sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
497 mask_sampler.normalized_coords = 1;
498 samplers[1] = &mask_sampler;
499 exa->bound_textures[1] = pMask->tex;
500 ++exa->num_bound_samplers;
501 }
502
503 cso_set_samplers(exa->cso, exa->num_bound_samplers,
504 (const struct pipe_sampler_state **)samplers);
505 cso_set_sampler_textures(exa->cso, exa->num_bound_samplers,
506 exa->bound_textures);
507 }
508
509 static void
510 setup_vs_constant_buffer(struct exa_context *exa,
511 int width, int height)
512 {
513 const int param_bytes = 8 * sizeof(float);
514 float vs_consts[8] = {
515 2.f/width, 2.f/height, 1, 1,
516 -1, -1, 0, 0
517 };
518 struct pipe_constant_buffer *cbuf = &exa->vs_const_buffer;
519
520 pipe_buffer_reference(&cbuf->buffer, NULL);
521 cbuf->buffer = pipe_buffer_create(exa->pipe->screen, 16,
522 PIPE_BUFFER_USAGE_CONSTANT,
523 param_bytes);
524
525 if (cbuf->buffer) {
526 pipe_buffer_write(exa->pipe->screen, cbuf->buffer,
527 0, param_bytes, vs_consts);
528 }
529 exa->pipe->set_constant_buffer(exa->pipe, PIPE_SHADER_VERTEX, 0, cbuf);
530 }
531
532
533 static void
534 setup_fs_constant_buffer(struct exa_context *exa)
535 {
536 const int param_bytes = 4 * sizeof(float);
537 float fs_consts[8] = {
538 0, 0, 0, 1,
539 };
540 struct pipe_constant_buffer *cbuf = &exa->fs_const_buffer;
541
542 pipe_buffer_reference(&cbuf->buffer, NULL);
543 cbuf->buffer = pipe_buffer_create(exa->pipe->screen, 16,
544 PIPE_BUFFER_USAGE_CONSTANT,
545 param_bytes);
546
547 if (cbuf->buffer) {
548 pipe_buffer_write(exa->pipe->screen, cbuf->buffer,
549 0, param_bytes, fs_consts);
550 }
551 exa->pipe->set_constant_buffer(exa->pipe, PIPE_SHADER_FRAGMENT, 0, cbuf);
552 }
553
554 static void
555 setup_constant_buffers(struct exa_context *exa, struct exa_pixmap_priv *pDst)
556 {
557 int width = pDst->tex->width[0];
558 int height = pDst->tex->height[0];
559
560 setup_vs_constant_buffer(exa, width, height);
561 setup_fs_constant_buffer(exa);
562 }
563
564 boolean xorg_composite_bind_state(struct exa_context *exa,
565 int op,
566 PicturePtr pSrcPicture,
567 PicturePtr pMaskPicture,
568 PicturePtr pDstPicture,
569 struct exa_pixmap_priv *pSrc,
570 struct exa_pixmap_priv *pMask,
571 struct exa_pixmap_priv *pDst)
572 {
573 bind_framebuffer_state(exa, pDst);
574 bind_viewport_state(exa, pDst);
575 bind_blend_state(exa, op, pSrcPicture, pMaskPicture);
576 bind_rasterizer_state(exa);
577 bind_shaders(exa, op, pSrcPicture, pMaskPicture);
578 bind_samplers(exa, op, pSrcPicture, pMaskPicture,
579 pDstPicture, pSrc, pMask, pDst);
580 bind_clip_state(exa);
581 setup_constant_buffers(exa, pDst);
582
583 return FALSE;
584 }
585
586 void xorg_composite(struct exa_context *exa,
587 struct exa_pixmap_priv *dst,
588 int srcX, int srcY, int maskX, int maskY,
589 int dstX, int dstY, int width, int height)
590 {
591 struct pipe_context *pipe = exa->pipe;
592 struct pipe_buffer *buf = 0;
593
594 if (exa->num_bound_samplers == 0 ) { /* solid fill */
595 buf = setup_vertex_data0(exa,
596 srcX, srcY, maskX, maskY,
597 dstX, dstY, width, height);
598 } else if (exa->num_bound_samplers == 1 ) /* src */
599 buf = setup_vertex_data1(exa,
600 srcX, srcY, maskX, maskY,
601 dstX, dstY, width, height);
602 else if (exa->num_bound_samplers == 2) /* src + mask */
603 buf = setup_vertex_data2(exa,
604 srcX, srcY, maskX, maskY,
605 dstX, dstY, width, height);
606 else if (exa->num_bound_samplers == 3) { /* src + mask + dst */
607 debug_assert(!"src/mask/dst not handled right now");
608 #if 0
609 buf = setup_vertex_data2(exa,
610 srcX, srcY, maskX, maskY,
611 dstX, dstY, width, height);
612 #endif
613 }
614
615 if (buf) {
616 int num_attribs = 1; /*pos*/
617 num_attribs += exa->num_bound_samplers;
618 if (exa->has_solid_color)
619 ++num_attribs;
620
621 util_draw_vertex_buffer(pipe, buf, 0,
622 PIPE_PRIM_TRIANGLE_FAN,
623 4, /* verts */
624 num_attribs); /* attribs/vert */
625
626 pipe_buffer_reference(&buf, NULL);
627 }
628 }
629
630 boolean xorg_solid_bind_state(struct exa_context *exa,
631 struct exa_pixmap_priv *pixmap,
632 Pixel fg)
633 {
634 unsigned vs_traits, fs_traits;
635 struct xorg_shader shader;
636
637 pixel_to_float4(fg, exa->solid_color);
638 exa->has_solid_color = TRUE;
639
640 exa->solid_color[3] = 1.f;
641
642 #if 0
643 debug_printf("Color Pixel=(%d, %d, %d, %d), RGBA=(%f, %f, %f, %f)\n",
644 (fg >> 24) & 0xff, (fg >> 16) & 0xff,
645 (fg >> 8) & 0xff, (fg >> 0) & 0xff,
646 exa->solid_color[0], exa->solid_color[1],
647 exa->solid_color[2], exa->solid_color[3]);
648 #endif
649
650 vs_traits = VS_SOLID_FILL;
651 fs_traits = FS_SOLID_FILL;
652
653 bind_framebuffer_state(exa, pixmap);
654 bind_viewport_state(exa, pixmap);
655 bind_rasterizer_state(exa);
656 bind_blend_state(exa, PictOpSrc, NULL, NULL);
657 setup_constant_buffers(exa, pixmap);
658 bind_clip_state(exa);
659
660 shader = xorg_shaders_get(exa->shaders, vs_traits, fs_traits);
661 cso_set_vertex_shader_handle(exa->cso, shader.vs);
662 cso_set_fragment_shader_handle(exa->cso, shader.fs);
663
664 return TRUE;
665 }
666
667 void xorg_solid(struct exa_context *exa,
668 struct exa_pixmap_priv *pixmap,
669 int x0, int y0, int x1, int y1)
670 {
671 struct pipe_context *pipe = exa->pipe;
672 struct pipe_buffer *buf = 0;
673
674 /* 1st vertex */
675 setup_vertex0(exa->vertices2[0], x0, y0,
676 exa->solid_color);
677 /* 2nd vertex */
678 setup_vertex0(exa->vertices2[1], x1, y0,
679 exa->solid_color);
680 /* 3rd vertex */
681 setup_vertex0(exa->vertices2[2], x1, y1,
682 exa->solid_color);
683 /* 4th vertex */
684 setup_vertex0(exa->vertices2[3], x0, y1,
685 exa->solid_color);
686
687 buf = pipe_user_buffer_create(exa->pipe->screen,
688 exa->vertices2,
689 sizeof(exa->vertices2));
690
691
692 if (buf) {
693 util_draw_vertex_buffer(pipe, buf, 0,
694 PIPE_PRIM_TRIANGLE_FAN,
695 4, /* verts */
696 2); /* attribs/vert */
697
698 pipe_buffer_reference(&buf, NULL);
699 }
700 }
701
702
703 static INLINE void shift_rectx(float coords[4],
704 const float *bounds,
705 const float shift)
706 {
707 coords[0] += shift;
708 coords[2] -= shift;
709 if (bounds) {
710 coords[2] = MIN2(coords[2], bounds[2]);
711 /* bound x/y + width/height */
712 if ((coords[0] + coords[2]) > (bounds[0] + bounds[2])) {
713 coords[2] = (bounds[0] + bounds[2]) - coords[0];
714 }
715 }
716 }
717
718 static INLINE void shift_recty(float coords[4],
719 const float *bounds,
720 const float shift)
721 {
722 coords[1] += shift;
723 coords[3] -= shift;
724 if (bounds) {
725 coords[3] = MIN2(coords[3], bounds[3]);
726 if ((coords[1] + coords[3]) > (bounds[1] + bounds[3])) {
727 coords[3] = (bounds[1] + bounds[3]) - coords[1];
728 }
729 }
730 }
731
732 static INLINE void bound_rect(float coords[4],
733 const float bounds[4],
734 float shift[4])
735 {
736 /* if outside the bounds */
737 if (coords[0] > (bounds[0] + bounds[2]) ||
738 coords[1] > (bounds[1] + bounds[3]) ||
739 (coords[0] + coords[2]) < bounds[0] ||
740 (coords[1] + coords[3]) < bounds[1]) {
741 coords[0] = 0.f;
742 coords[1] = 0.f;
743 coords[2] = 0.f;
744 coords[3] = 0.f;
745 shift[0] = 0.f;
746 shift[1] = 0.f;
747 return;
748 }
749
750 /* bound x */
751 if (coords[0] < bounds[0]) {
752 shift[0] = bounds[0] - coords[0];
753 coords[2] -= shift[0];
754 coords[0] = bounds[0];
755 } else
756 shift[0] = 0.f;
757
758 /* bound y */
759 if (coords[1] < bounds[1]) {
760 shift[1] = bounds[1] - coords[1];
761 coords[3] -= shift[1];
762 coords[1] = bounds[1];
763 } else
764 shift[1] = 0.f;
765
766 shift[2] = bounds[2] - coords[2];
767 shift[3] = bounds[3] - coords[3];
768 /* bound width/height */
769 coords[2] = MIN2(coords[2], bounds[2]);
770 coords[3] = MIN2(coords[3], bounds[3]);
771
772 /* bound x/y + width/height */
773 if ((coords[0] + coords[2]) > (bounds[0] + bounds[2])) {
774 coords[2] = (bounds[0] + bounds[2]) - coords[0];
775 }
776 if ((coords[1] + coords[3]) > (bounds[1] + bounds[3])) {
777 coords[3] = (bounds[1] + bounds[3]) - coords[1];
778 }
779
780 /* if outside the bounds */
781 if ((coords[0] + coords[2]) < bounds[0] ||
782 (coords[1] + coords[3]) < bounds[1]) {
783 coords[0] = 0.f;
784 coords[1] = 0.f;
785 coords[2] = 0.f;
786 coords[3] = 0.f;
787 return;
788 }
789 }
790
791 static INLINE void sync_size(float *src_loc, float *dst_loc)
792 {
793 src_loc[2] = MIN2(src_loc[2], dst_loc[2]);
794 src_loc[3] = MIN2(src_loc[3], dst_loc[3]);
795 dst_loc[2] = src_loc[2];
796 dst_loc[3] = src_loc[3];
797 }
798
799
800 static void renderer_copy_texture(struct exa_context *exa,
801 struct pipe_texture *src,
802 float sx1, float sy1,
803 float sx2, float sy2,
804 struct pipe_texture *dst,
805 float dx1, float dy1,
806 float dx2, float dy2)
807 {
808 struct pipe_context *pipe = exa->pipe;
809 struct pipe_screen *screen = pipe->screen;
810 struct pipe_buffer *buf;
811 struct pipe_surface *dst_surf = screen->get_tex_surface(
812 screen, dst, 0, 0, 0,
813 PIPE_BUFFER_USAGE_GPU_WRITE);
814 struct pipe_framebuffer_state fb;
815 float s0, t0, s1, t1;
816 struct xorg_shader shader;
817
818 assert(src->width[0] != 0);
819 assert(src->height[0] != 0);
820 assert(dst->width[0] != 0);
821 assert(dst->height[0] != 0);
822
823 #if 1
824 s0 = sx1 / src->width[0];
825 s1 = sx2 / src->width[0];
826 t0 = sy1 / src->height[0];
827 t1 = sy2 / src->height[0];
828 #else
829 s0 = 0;
830 s1 = 1;
831 t0 = 0;
832 t1 = 1;
833 #endif
834
835 #if 0
836 debug_printf("copy texture src=[%f, %f, %f, %f], dst=[%f, %f, %f, %f], tex=[%f, %f, %f, %f]\n",
837 sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2,
838 s0, t0, s1, t1);
839 #endif
840
841 assert(screen->is_format_supported(screen, dst_surf->format,
842 PIPE_TEXTURE_2D,
843 PIPE_TEXTURE_USAGE_RENDER_TARGET,
844 0));
845
846 /* save state (restored below) */
847 cso_save_blend(exa->cso);
848 cso_save_samplers(exa->cso);
849 cso_save_sampler_textures(exa->cso);
850 cso_save_framebuffer(exa->cso);
851 cso_save_fragment_shader(exa->cso);
852 cso_save_vertex_shader(exa->cso);
853
854 cso_save_viewport(exa->cso);
855
856
857 /* set misc state we care about */
858 {
859 struct pipe_blend_state blend;
860 memset(&blend, 0, sizeof(blend));
861 blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE;
862 blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE;
863 blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
864 blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
865 blend.colormask = PIPE_MASK_RGBA;
866 cso_set_blend(exa->cso, &blend);
867 }
868
869 /* sampler */
870 {
871 struct pipe_sampler_state sampler;
872 memset(&sampler, 0, sizeof(sampler));
873 sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
874 sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
875 sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
876 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
877 sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
878 sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
879 sampler.normalized_coords = 1;
880 cso_single_sampler(exa->cso, 0, &sampler);
881 cso_single_sampler_done(exa->cso);
882 }
883
884 set_viewport(exa, dst_surf->width, dst_surf->height, Y0_TOP);
885
886 /* texture */
887 cso_set_sampler_textures(exa->cso, 1, &src);
888
889 bind_rasterizer_state(exa);
890
891 /* shaders */
892 shader = xorg_shaders_get(exa->shaders,
893 VS_COMPOSITE,
894 FS_COMPOSITE);
895 cso_set_vertex_shader_handle(exa->cso, shader.vs);
896 cso_set_fragment_shader_handle(exa->cso, shader.fs);
897
898 /* drawing dest */
899 memset(&fb, 0, sizeof(fb));
900 fb.width = dst_surf->width;
901 fb.height = dst_surf->height;
902 fb.nr_cbufs = 1;
903 fb.cbufs[0] = dst_surf;
904 {
905 int i;
906 for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i)
907 fb.cbufs[i] = 0;
908 }
909 cso_set_framebuffer(exa->cso, &fb);
910 setup_vs_constant_buffer(exa, fb.width, fb.height);
911 setup_fs_constant_buffer(exa);
912
913 /* draw quad */
914 buf = setup_vertex_data_tex(exa,
915 dx1, dy1,
916 dx2, dy2,
917 s0, t0, s1, t1,
918 0.0f);
919
920 if (buf) {
921 util_draw_vertex_buffer(exa->pipe, buf, 0,
922 PIPE_PRIM_TRIANGLE_FAN,
923 4, /* verts */
924 2); /* attribs/vert */
925
926 pipe_buffer_reference(&buf, NULL);
927 }
928
929 /* restore state we changed */
930 cso_restore_blend(exa->cso);
931 cso_restore_samplers(exa->cso);
932 cso_restore_sampler_textures(exa->cso);
933 cso_restore_framebuffer(exa->cso);
934 cso_restore_vertex_shader(exa->cso);
935 cso_restore_fragment_shader(exa->cso);
936 cso_restore_viewport(exa->cso);
937
938 pipe_surface_reference(&dst_surf, NULL);
939 }
940
941
942 static struct pipe_texture *
943 create_sampler_texture(struct exa_context *ctx,
944 struct pipe_texture *src)
945 {
946 enum pipe_format format;
947 struct pipe_context *pipe = ctx->pipe;
948 struct pipe_screen *screen = pipe->screen;
949 struct pipe_texture *pt;
950 struct pipe_texture templ;
951
952 pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
953
954 /* the coming in texture should already have that invariance */
955 debug_assert(screen->is_format_supported(screen, src->format,
956 PIPE_TEXTURE_2D,
957 PIPE_TEXTURE_USAGE_SAMPLER, 0));
958
959 format = src->format;
960
961 memset(&templ, 0, sizeof(templ));
962 templ.target = PIPE_TEXTURE_2D;
963 templ.format = format;
964 templ.last_level = 0;
965 templ.width[0] = src->width[0];
966 templ.height[0] = src->height[0];
967 templ.depth[0] = 1;
968 pf_get_block(format, &templ.block);
969 templ.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER;
970
971 pt = screen->texture_create(screen, &templ);
972
973 debug_assert(!pt || pipe_is_referenced(&pt->reference));
974
975 if (!pt)
976 return NULL;
977
978 {
979 /* copy source framebuffer surface into texture */
980 struct pipe_surface *ps_read = screen->get_tex_surface(
981 screen, src, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ);
982 struct pipe_surface *ps_tex = screen->get_tex_surface(
983 screen, pt, 0, 0, 0, PIPE_BUFFER_USAGE_GPU_WRITE );
984 pipe->surface_copy(pipe,
985 ps_tex, /* dest */
986 0, 0, /* destx/y */
987 ps_read,
988 0, 0, src->width[0], src->height[0]);
989 pipe_surface_reference(&ps_read, NULL);
990 pipe_surface_reference(&ps_tex, NULL);
991 }
992
993 return pt;
994 }
995
996 void xorg_copy_pixmap(struct exa_context *ctx,
997 struct exa_pixmap_priv *dst_priv, int dx, int dy,
998 struct exa_pixmap_priv *src_priv, int sx, int sy,
999 int width, int height)
1000 {
1001 float dst_loc[4], src_loc[4];
1002 float dst_bounds[4], src_bounds[4];
1003 float src_shift[4], dst_shift[4], shift[4];
1004 struct pipe_texture *dst = dst_priv->tex;
1005 struct pipe_texture *src = src_priv->tex;
1006
1007 if (ctx->pipe->is_texture_referenced(ctx->pipe, src, 0, 0) &
1008 PIPE_REFERENCED_FOR_WRITE)
1009 ctx->pipe->flush(ctx->pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
1010
1011 dst_loc[0] = dx;
1012 dst_loc[1] = dy;
1013 dst_loc[2] = width;
1014 dst_loc[3] = height;
1015 dst_bounds[0] = 0.f;
1016 dst_bounds[1] = 0.f;
1017 dst_bounds[2] = dst->width[0];
1018 dst_bounds[3] = dst->height[0];
1019
1020 src_loc[0] = sx;
1021 src_loc[1] = sy;
1022 src_loc[2] = width;
1023 src_loc[3] = height;
1024 src_bounds[0] = 0.f;
1025 src_bounds[1] = 0.f;
1026 src_bounds[2] = src->width[0];
1027 src_bounds[3] = src->height[0];
1028
1029 bound_rect(src_loc, src_bounds, src_shift);
1030 bound_rect(dst_loc, dst_bounds, dst_shift);
1031 shift[0] = src_shift[0] - dst_shift[0];
1032 shift[1] = src_shift[1] - dst_shift[1];
1033
1034 if (shift[0] < 0)
1035 shift_rectx(src_loc, src_bounds, -shift[0]);
1036 else
1037 shift_rectx(dst_loc, dst_bounds, shift[0]);
1038
1039 if (shift[1] < 0)
1040 shift_recty(src_loc, src_bounds, -shift[1]);
1041 else
1042 shift_recty(dst_loc, dst_bounds, shift[1]);
1043
1044 sync_size(src_loc, dst_loc);
1045
1046 if (src_loc[2] >= 0 && src_loc[3] >= 0 &&
1047 dst_loc[2] >= 0 && dst_loc[3] >= 0) {
1048 struct pipe_texture *temp_src = src;
1049
1050 if (src == dst)
1051 temp_src = create_sampler_texture(ctx, src);
1052
1053 renderer_copy_texture(ctx,
1054 temp_src,
1055 src_loc[0],
1056 src_loc[1],
1057 src_loc[0] + src_loc[2],
1058 src_loc[1] + src_loc[3],
1059 dst,
1060 dst_loc[0],
1061 dst_loc[1],
1062 dst_loc[0] + dst_loc[2],
1063 dst_loc[1] + dst_loc[3]);
1064
1065 if (src == dst)
1066 pipe_texture_reference(&temp_src, NULL);
1067 }
1068 }
1069