st/xorg: lots of rendering and xv changes
[mesa.git] / src / gallium / state_trackers / xorg / xorg_composite.c
1 #include "xorg_composite.h"
2
3 #include "xorg_renderer.h"
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
10 #include "pipe/p_inlines.h"
11
12 struct xorg_composite_blend {
13 int op:8;
14
15 unsigned rgb_src_factor:5; /**< PIPE_BLENDFACTOR_x */
16 unsigned alpha_src_factor:5; /**< PIPE_BLENDFACTOR_x */
17
18 unsigned rgb_dst_factor:5; /**< PIPE_BLENDFACTOR_x */
19 unsigned alpha_dst_factor:5; /**< PIPE_BLENDFACTOR_x */
20 };
21
22 #define BLEND_OP_OVER 3
23 static const struct xorg_composite_blend xorg_blends[] = {
24 { PictOpClear,
25 PIPE_BLENDFACTOR_CONST_COLOR, PIPE_BLENDFACTOR_CONST_ALPHA,
26 PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO },
27
28 { PictOpSrc,
29 PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ONE,
30 PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO },
31
32 { PictOpDst,
33 PIPE_BLENDFACTOR_ZERO, PIPE_BLENDFACTOR_ZERO,
34 PIPE_BLENDFACTOR_ONE, PIPE_BLENDFACTOR_ONE },
35
36 { PictOpOver,
37 PIPE_BLENDFACTOR_SRC_ALPHA, PIPE_BLENDFACTOR_ONE,
38 PIPE_BLENDFACTOR_INV_SRC_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA },
39
40 { PictOpOverReverse,
41 PIPE_BLENDFACTOR_SRC_ALPHA, PIPE_BLENDFACTOR_ONE,
42 PIPE_BLENDFACTOR_INV_SRC_ALPHA, PIPE_BLENDFACTOR_INV_SRC_ALPHA },
43 };
44
45
46 static INLINE void
47 pixel_to_float4(Pixel pixel, float *color)
48 {
49 CARD32 r, g, b, a;
50
51 a = (pixel >> 24) & 0xff;
52 r = (pixel >> 16) & 0xff;
53 g = (pixel >> 8) & 0xff;
54 b = (pixel >> 0) & 0xff;
55 color[0] = ((float)r) / 255.;
56 color[1] = ((float)g) / 255.;
57 color[2] = ((float)b) / 255.;
58 color[3] = ((float)a) / 255.;
59 }
60
61 struct acceleration_info {
62 int op : 16;
63 int with_mask : 1;
64 int component_alpha : 1;
65 };
66 static const struct acceleration_info accelerated_ops[] = {
67 {PictOpClear, 1, 0},
68 {PictOpSrc, 1, 0},
69 {PictOpDst, 1, 0},
70 {PictOpOver, 1, 0},
71 {PictOpOverReverse, 1, 0},
72 {PictOpIn, 1, 0},
73 {PictOpInReverse, 1, 0},
74 {PictOpOut, 1, 0},
75 {PictOpOutReverse, 1, 0},
76 {PictOpAtop, 1, 0},
77 {PictOpAtopReverse, 1, 0},
78 {PictOpXor, 1, 0},
79 {PictOpAdd, 1, 0},
80 {PictOpSaturate, 1, 0},
81 };
82
83 static struct xorg_composite_blend
84 blend_for_op(int op)
85 {
86 const int num_blends =
87 sizeof(xorg_blends)/sizeof(struct xorg_composite_blend);
88 int i;
89
90 for (i = 0; i < num_blends; ++i) {
91 if (xorg_blends[i].op == op)
92 return xorg_blends[i];
93 }
94 return xorg_blends[BLEND_OP_OVER];
95 }
96
97 static INLINE int
98 render_repeat_to_gallium(int mode)
99 {
100 switch(mode) {
101 case RepeatNone:
102 return PIPE_TEX_WRAP_CLAMP;
103 case RepeatNormal:
104 return PIPE_TEX_WRAP_REPEAT;
105 case RepeatReflect:
106 return PIPE_TEX_WRAP_MIRROR_REPEAT;
107 case RepeatPad:
108 return PIPE_TEX_WRAP_CLAMP_TO_EDGE;
109 default:
110 debug_printf("Unsupported repeat mode\n");
111 }
112 return PIPE_TEX_WRAP_REPEAT;
113 }
114
115 boolean xorg_composite_accelerated(int op,
116 PicturePtr pSrcPicture,
117 PicturePtr pMaskPicture,
118 PicturePtr pDstPicture)
119 {
120 ScreenPtr pScreen = pDstPicture->pDrawable->pScreen;
121 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum];
122 modesettingPtr ms = modesettingPTR(pScrn);
123 unsigned i;
124 unsigned accel_ops_count =
125 sizeof(accelerated_ops)/sizeof(struct acceleration_info);
126
127 if (pSrcPicture->pSourcePict) {
128 /* Gradients not yet supported */
129 if (pSrcPicture->pSourcePict->type != SourcePictTypeSolidFill)
130 XORG_FALLBACK("gradients not yet supported");
131
132 /* Solid source with mask not yet handled properly */
133 if (pMaskPicture)
134 XORG_FALLBACK("solid source with mask not yet handled properly");
135 }
136
137 for (i = 0; i < accel_ops_count; ++i) {
138 if (op == accelerated_ops[i].op) {
139 /* Check for unsupported component alpha */
140 if ((pSrcPicture->componentAlpha &&
141 !accelerated_ops[i].component_alpha) ||
142 (pMaskPicture &&
143 (!accelerated_ops[i].with_mask ||
144 (pMaskPicture->componentAlpha &&
145 !accelerated_ops[i].component_alpha))))
146 XORG_FALLBACK("component alpha unsupported");
147 return TRUE;
148 }
149 }
150 XORG_FALLBACK("unsupported operation");
151 }
152
153 static void
154 bind_blend_state(struct exa_context *exa, int op,
155 PicturePtr pSrcPicture, PicturePtr pMaskPicture)
156 {
157 struct xorg_composite_blend blend_opt;
158 struct pipe_blend_state blend;
159
160 blend_opt = blend_for_op(op);
161
162 memset(&blend, 0, sizeof(struct pipe_blend_state));
163 blend.blend_enable = 1;
164 blend.colormask |= PIPE_MASK_R;
165 blend.colormask |= PIPE_MASK_G;
166 blend.colormask |= PIPE_MASK_B;
167 blend.colormask |= PIPE_MASK_A;
168
169 blend.rgb_src_factor = blend_opt.rgb_src_factor;
170 blend.alpha_src_factor = blend_opt.alpha_src_factor;
171 blend.rgb_dst_factor = blend_opt.rgb_dst_factor;
172 blend.alpha_dst_factor = blend_opt.alpha_dst_factor;
173
174 cso_set_blend(exa->renderer->cso, &blend);
175 }
176
177
178 static void
179 bind_shaders(struct exa_context *exa, int op,
180 PicturePtr pSrcPicture, PicturePtr pMaskPicture)
181 {
182 unsigned vs_traits = 0, fs_traits = 0;
183 struct xorg_shader shader;
184
185 exa->has_solid_color = FALSE;
186
187 if (pSrcPicture) {
188 if (pSrcPicture->pSourcePict) {
189 if (pSrcPicture->pSourcePict->type == SourcePictTypeSolidFill) {
190 fs_traits |= FS_SOLID_FILL;
191 vs_traits |= VS_SOLID_FILL;
192 debug_assert(pSrcPicture->format == PICT_a8r8g8b8);
193 pixel_to_float4(pSrcPicture->pSourcePict->solidFill.color,
194 exa->solid_color);
195 exa->has_solid_color = TRUE;
196 } else {
197 debug_assert("!gradients not supported");
198 }
199 } else {
200 fs_traits |= FS_COMPOSITE;
201 vs_traits |= VS_COMPOSITE;
202 }
203 }
204
205 if (pMaskPicture) {
206 vs_traits |= VS_MASK;
207 fs_traits |= FS_MASK;
208 }
209
210 shader = xorg_shaders_get(exa->renderer->shaders, vs_traits, fs_traits);
211 cso_set_vertex_shader_handle(exa->renderer->cso, shader.vs);
212 cso_set_fragment_shader_handle(exa->renderer->cso, shader.fs);
213 }
214
215
216 static void
217 bind_samplers(struct exa_context *exa, int op,
218 PicturePtr pSrcPicture, PicturePtr pMaskPicture,
219 PicturePtr pDstPicture,
220 struct exa_pixmap_priv *pSrc,
221 struct exa_pixmap_priv *pMask,
222 struct exa_pixmap_priv *pDst)
223 {
224 struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
225 struct pipe_sampler_state src_sampler, mask_sampler;
226
227 exa->num_bound_samplers = 0;
228
229 memset(&src_sampler, 0, sizeof(struct pipe_sampler_state));
230 memset(&mask_sampler, 0, sizeof(struct pipe_sampler_state));
231
232 if ((pSrc && exa->pipe->is_texture_referenced(exa->pipe, pSrc->tex, 0, 0) &
233 PIPE_REFERENCED_FOR_WRITE) ||
234 (pMask && exa->pipe->is_texture_referenced(exa->pipe, pMask->tex, 0, 0) &
235 PIPE_REFERENCED_FOR_WRITE))
236 exa->pipe->flush(exa->pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
237
238 if (pSrcPicture && pSrc) {
239 unsigned src_wrap = render_repeat_to_gallium(
240 pSrcPicture->repeatType);
241 src_sampler.wrap_s = src_wrap;
242 src_sampler.wrap_t = src_wrap;
243 src_sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
244 src_sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
245 src_sampler.normalized_coords = 1;
246 samplers[0] = &src_sampler;
247 exa->bound_textures[0] = pSrc->tex;
248 ++exa->num_bound_samplers;
249 }
250
251 if (pMaskPicture && pMask) {
252 unsigned mask_wrap = render_repeat_to_gallium(
253 pMaskPicture->repeatType);
254 mask_sampler.wrap_s = mask_wrap;
255 mask_sampler.wrap_t = mask_wrap;
256 mask_sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
257 mask_sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST;
258 mask_sampler.normalized_coords = 1;
259 samplers[1] = &mask_sampler;
260 exa->bound_textures[1] = pMask->tex;
261 ++exa->num_bound_samplers;
262 }
263
264 cso_set_samplers(exa->renderer->cso, exa->num_bound_samplers,
265 (const struct pipe_sampler_state **)samplers);
266 cso_set_sampler_textures(exa->renderer->cso, exa->num_bound_samplers,
267 exa->bound_textures);
268 }
269
270 static void
271 setup_vs_constant_buffer(struct exa_context *exa,
272 int width, int height)
273 {
274 const int param_bytes = 8 * sizeof(float);
275 float vs_consts[8] = {
276 2.f/width, 2.f/height, 1, 1,
277 -1, -1, 0, 0
278 };
279 renderer_set_constants(exa->renderer, PIPE_SHADER_VERTEX,
280 vs_consts, param_bytes);
281 }
282
283
284 static void
285 setup_fs_constant_buffer(struct exa_context *exa)
286 {
287 const int param_bytes = 4 * sizeof(float);
288 const float fs_consts[8] = {
289 0, 0, 0, 1,
290 };
291 renderer_set_constants(exa->renderer, PIPE_SHADER_FRAGMENT,
292 fs_consts, param_bytes);
293 }
294
295 static void
296 setup_constant_buffers(struct exa_context *exa, struct exa_pixmap_priv *pDst)
297 {
298 int width = pDst->tex->width[0];
299 int height = pDst->tex->height[0];
300
301 setup_vs_constant_buffer(exa, width, height);
302 setup_fs_constant_buffer(exa);
303 }
304
305 boolean xorg_composite_bind_state(struct exa_context *exa,
306 int op,
307 PicturePtr pSrcPicture,
308 PicturePtr pMaskPicture,
309 PicturePtr pDstPicture,
310 struct exa_pixmap_priv *pSrc,
311 struct exa_pixmap_priv *pMask,
312 struct exa_pixmap_priv *pDst)
313 {
314 renderer_bind_framebuffer(exa->renderer, pDst);
315 renderer_bind_viewport(exa->renderer, pDst);
316 bind_blend_state(exa, op, pSrcPicture, pMaskPicture);
317 renderer_bind_rasterizer(exa->renderer);
318 bind_shaders(exa, op, pSrcPicture, pMaskPicture);
319 bind_samplers(exa, op, pSrcPicture, pMaskPicture,
320 pDstPicture, pSrc, pMask, pDst);
321 setup_constant_buffers(exa, pDst);
322
323 return FALSE;
324 }
325
326 void xorg_composite(struct exa_context *exa,
327 struct exa_pixmap_priv *dst,
328 int srcX, int srcY, int maskX, int maskY,
329 int dstX, int dstY, int width, int height)
330 {
331 if (exa->num_bound_samplers == 0 ) { /* solid fill */
332 renderer_draw_solid_rect(exa->renderer,
333 dstX, dstY, dstX + width, dstY + height,
334 exa->solid_color);
335 } else {
336 int pos[6] = {srcX, srcY, maskX, maskY, dstX, dstY};
337 renderer_draw_textures(exa->renderer,
338 pos, width, height,
339 exa->bound_textures,
340 exa->num_bound_samplers);
341 }
342 }
343
344 boolean xorg_solid_bind_state(struct exa_context *exa,
345 struct exa_pixmap_priv *pixmap,
346 Pixel fg)
347 {
348 unsigned vs_traits, fs_traits;
349 struct xorg_shader shader;
350
351 pixel_to_float4(fg, exa->solid_color);
352 exa->has_solid_color = TRUE;
353
354 exa->solid_color[3] = 1.f;
355
356 #if 0
357 debug_printf("Color Pixel=(%d, %d, %d, %d), RGBA=(%f, %f, %f, %f)\n",
358 (fg >> 24) & 0xff, (fg >> 16) & 0xff,
359 (fg >> 8) & 0xff, (fg >> 0) & 0xff,
360 exa->solid_color[0], exa->solid_color[1],
361 exa->solid_color[2], exa->solid_color[3]);
362 #endif
363
364 vs_traits = VS_SOLID_FILL;
365 fs_traits = FS_SOLID_FILL;
366
367 renderer_bind_framebuffer(exa->renderer, pixmap);
368 renderer_bind_viewport(exa->renderer, pixmap);
369 renderer_bind_rasterizer(exa->renderer);
370 bind_blend_state(exa, PictOpSrc, NULL, NULL);
371 setup_constant_buffers(exa, pixmap);
372
373 shader = xorg_shaders_get(exa->renderer->shaders, vs_traits, fs_traits);
374 cso_set_vertex_shader_handle(exa->renderer->cso, shader.vs);
375 cso_set_fragment_shader_handle(exa->renderer->cso, shader.fs);
376
377 return TRUE;
378 }
379
380 void xorg_solid(struct exa_context *exa,
381 struct exa_pixmap_priv *pixmap,
382 int x0, int y0, int x1, int y1)
383 {
384 renderer_draw_solid_rect(exa->renderer,
385 x0, y0, x1, y1, exa->solid_color);
386 }
387