st/xorg: attach EDID to outputs
[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_sampler.h"
11
12 #include "util/u_inlines.h"
13 #include "util/u_box.h"
14
15 #include <math.h>
16
17 #define floatsEqual(x, y) (fabs(x - y) <= 0.00001f * MIN2(fabs(x), fabs(y)))
18 #define floatIsZero(x) (floatsEqual((x) + 1, 1))
19
20 #define NUM_COMPONENTS 4
21
22 static INLINE boolean is_affine(float *matrix)
23 {
24 return floatIsZero(matrix[2]) && floatIsZero(matrix[5])
25 && floatsEqual(matrix[8], 1);
26 }
27 static INLINE void map_point(float *mat, float x, float y,
28 float *out_x, float *out_y)
29 {
30 if (!mat) {
31 *out_x = x;
32 *out_y = y;
33 return;
34 }
35
36 *out_x = mat[0]*x + mat[3]*y + mat[6];
37 *out_y = mat[1]*x + mat[4]*y + mat[7];
38 if (!is_affine(mat)) {
39 float w = 1/(mat[2]*x + mat[5]*y + mat[8]);
40 *out_x *= w;
41 *out_y *= w;
42 }
43 }
44
45 static INLINE void
46 renderer_draw(struct xorg_renderer *r)
47 {
48 int num_verts = r->buffer_size/(r->attrs_per_vertex * NUM_COMPONENTS);
49
50 if (!r->buffer_size)
51 return;
52
53 cso_set_vertex_elements(r->cso, r->attrs_per_vertex, r->velems);
54 util_draw_user_vertex_buffer(r->cso, r->buffer, PIPE_PRIM_QUADS,
55 num_verts, r->attrs_per_vertex);
56
57 r->buffer_size = 0;
58 }
59
60 static INLINE void
61 renderer_draw_conditional(struct xorg_renderer *r,
62 int next_batch)
63 {
64 if (r->buffer_size + next_batch >= BUF_SIZE ||
65 (next_batch == 0 && r->buffer_size)) {
66 renderer_draw(r);
67 }
68 }
69
70 static void
71 renderer_init_state(struct xorg_renderer *r)
72 {
73 struct pipe_depth_stencil_alpha_state dsa;
74 struct pipe_rasterizer_state raster;
75 unsigned i;
76
77 /* set common initial clip state */
78 memset(&dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state));
79 cso_set_depth_stencil_alpha(r->cso, &dsa);
80
81
82 /* XXX: move to renderer_init_state? */
83 memset(&raster, 0, sizeof(struct pipe_rasterizer_state));
84 raster.gl_rasterization_rules = 1;
85 raster.depth_clip = 1;
86 cso_set_rasterizer(r->cso, &raster);
87
88 /* vertex elements state */
89 memset(&r->velems[0], 0, sizeof(r->velems[0]) * 3);
90 for (i = 0; i < 3; i++) {
91 r->velems[i].src_offset = i * 4 * sizeof(float);
92 r->velems[i].instance_divisor = 0;
93 r->velems[i].vertex_buffer_index = 0;
94 r->velems[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
95 }
96 }
97
98
99 static INLINE void
100 add_vertex_color(struct xorg_renderer *r,
101 float x, float y,
102 float color[4])
103 {
104 float *vertex = r->buffer + r->buffer_size;
105
106 vertex[0] = x;
107 vertex[1] = y;
108 vertex[2] = 0.f; /*z*/
109 vertex[3] = 1.f; /*w*/
110
111 vertex[4] = color[0]; /*r*/
112 vertex[5] = color[1]; /*g*/
113 vertex[6] = color[2]; /*b*/
114 vertex[7] = color[3]; /*a*/
115
116 r->buffer_size += 8;
117 }
118
119 static INLINE void
120 add_vertex_1tex(struct xorg_renderer *r,
121 float x, float y, float s, float t)
122 {
123 float *vertex = r->buffer + r->buffer_size;
124
125 vertex[0] = x;
126 vertex[1] = y;
127 vertex[2] = 0.f; /*z*/
128 vertex[3] = 1.f; /*w*/
129
130 vertex[4] = s; /*s*/
131 vertex[5] = t; /*t*/
132 vertex[6] = 0.f; /*r*/
133 vertex[7] = 1.f; /*q*/
134
135 r->buffer_size += 8;
136 }
137
138 static void
139 add_vertex_data1(struct xorg_renderer *r,
140 float srcX, float srcY, float dstX, float dstY,
141 float width, float height,
142 struct pipe_resource *src, float *src_matrix)
143 {
144 float s0, t0, s1, t1, s2, t2, s3, t3;
145 float pt0[2], pt1[2], pt2[2], pt3[2];
146
147 pt0[0] = srcX;
148 pt0[1] = srcY;
149 pt1[0] = (srcX + width);
150 pt1[1] = srcY;
151 pt2[0] = (srcX + width);
152 pt2[1] = (srcY + height);
153 pt3[0] = srcX;
154 pt3[1] = (srcY + height);
155
156 if (src_matrix) {
157 map_point(src_matrix, pt0[0], pt0[1], &pt0[0], &pt0[1]);
158 map_point(src_matrix, pt1[0], pt1[1], &pt1[0], &pt1[1]);
159 map_point(src_matrix, pt2[0], pt2[1], &pt2[0], &pt2[1]);
160 map_point(src_matrix, pt3[0], pt3[1], &pt3[0], &pt3[1]);
161 }
162
163 s0 = pt0[0] / src->width0;
164 s1 = pt1[0] / src->width0;
165 s2 = pt2[0] / src->width0;
166 s3 = pt3[0] / src->width0;
167 t0 = pt0[1] / src->height0;
168 t1 = pt1[1] / src->height0;
169 t2 = pt2[1] / src->height0;
170 t3 = pt3[1] / src->height0;
171
172 /* 1st vertex */
173 add_vertex_1tex(r, dstX, dstY, s0, t0);
174 /* 2nd vertex */
175 add_vertex_1tex(r, dstX + width, dstY, s1, t1);
176 /* 3rd vertex */
177 add_vertex_1tex(r, dstX + width, dstY + height, s2, t2);
178 /* 4th vertex */
179 add_vertex_1tex(r, dstX, dstY + height, s3, t3);
180 }
181
182
183 static INLINE void
184 add_vertex_2tex(struct xorg_renderer *r,
185 float x, float y,
186 float s0, float t0, float s1, float t1)
187 {
188 float *vertex = r->buffer + r->buffer_size;
189
190 vertex[0] = x;
191 vertex[1] = y;
192 vertex[2] = 0.f; /*z*/
193 vertex[3] = 1.f; /*w*/
194
195 vertex[4] = s0; /*s*/
196 vertex[5] = t0; /*t*/
197 vertex[6] = 0.f; /*r*/
198 vertex[7] = 1.f; /*q*/
199
200 vertex[8] = s1; /*s*/
201 vertex[9] = t1; /*t*/
202 vertex[10] = 0.f; /*r*/
203 vertex[11] = 1.f; /*q*/
204
205 r->buffer_size += 12;
206 }
207
208 static void
209 add_vertex_data2(struct xorg_renderer *r,
210 float srcX, float srcY, float maskX, float maskY,
211 float dstX, float dstY, float width, float height,
212 struct pipe_resource *src,
213 struct pipe_resource *mask,
214 float *src_matrix, float *mask_matrix)
215 {
216 float src_s0, src_t0, src_s1, src_t1;
217 float mask_s0, mask_t0, mask_s1, mask_t1;
218 float spt0[2], spt1[2];
219 float mpt0[2], mpt1[2];
220
221 spt0[0] = srcX;
222 spt0[1] = srcY;
223 spt1[0] = srcX + width;
224 spt1[1] = srcY + height;
225
226 mpt0[0] = maskX;
227 mpt0[1] = maskY;
228 mpt1[0] = maskX + width;
229 mpt1[1] = maskY + height;
230
231 if (src_matrix) {
232 map_point(src_matrix, spt0[0], spt0[1], &spt0[0], &spt0[1]);
233 map_point(src_matrix, spt1[0], spt1[1], &spt1[0], &spt1[1]);
234 }
235
236 if (mask_matrix) {
237 map_point(mask_matrix, mpt0[0], mpt0[1], &mpt0[0], &mpt0[1]);
238 map_point(mask_matrix, mpt1[0], mpt1[1], &mpt1[0], &mpt1[1]);
239 }
240
241 src_s0 = spt0[0] / src->width0;
242 src_t0 = spt0[1] / src->height0;
243 src_s1 = spt1[0] / src->width0;
244 src_t1 = spt1[1] / src->height0;
245
246 mask_s0 = mpt0[0] / mask->width0;
247 mask_t0 = mpt0[1] / mask->height0;
248 mask_s1 = mpt1[0] / mask->width0;
249 mask_t1 = mpt1[1] / mask->height0;
250
251 /* 1st vertex */
252 add_vertex_2tex(r, dstX, dstY,
253 src_s0, src_t0, mask_s0, mask_t0);
254 /* 2nd vertex */
255 add_vertex_2tex(r, dstX + width, dstY,
256 src_s1, src_t0, mask_s1, mask_t0);
257 /* 3rd vertex */
258 add_vertex_2tex(r, dstX + width, dstY + height,
259 src_s1, src_t1, mask_s1, mask_t1);
260 /* 4th vertex */
261 add_vertex_2tex(r, dstX, dstY + height,
262 src_s0, src_t1, mask_s0, mask_t1);
263 }
264
265 static void
266 setup_vertex_data_yuv(struct xorg_renderer *r,
267 float srcX, float srcY, float srcW, float srcH,
268 float dstX, float dstY, float dstW, float dstH,
269 struct pipe_resource **tex)
270 {
271 float s0, t0, s1, t1;
272 float spt0[2], spt1[2];
273
274 spt0[0] = srcX;
275 spt0[1] = srcY;
276 spt1[0] = srcX + srcW;
277 spt1[1] = srcY + srcH;
278
279 s0 = spt0[0] / tex[0]->width0;
280 t0 = spt0[1] / tex[0]->height0;
281 s1 = spt1[0] / tex[0]->width0;
282 t1 = spt1[1] / tex[0]->height0;
283
284 /* 1st vertex */
285 add_vertex_1tex(r, dstX, dstY, s0, t0);
286 /* 2nd vertex */
287 add_vertex_1tex(r, dstX + dstW, dstY,
288 s1, t0);
289 /* 3rd vertex */
290 add_vertex_1tex(r, dstX + dstW, dstY + dstH,
291 s1, t1);
292 /* 4th vertex */
293 add_vertex_1tex(r, dstX, dstY + dstH,
294 s0, t1);
295 }
296
297
298
299 /* Set up framebuffer, viewport and vertex shader constant buffer
300 * state for a particular destinaton surface. In all our rendering,
301 * these concepts are linked.
302 */
303 void renderer_bind_destination(struct xorg_renderer *r,
304 struct pipe_surface *surface,
305 int width,
306 int height )
307 {
308
309 struct pipe_framebuffer_state fb;
310 struct pipe_viewport_state viewport;
311
312 /* Framebuffer uses actual surface width/height
313 */
314 memset(&fb, 0, sizeof fb);
315 fb.width = surface->width;
316 fb.height = surface->height;
317 fb.nr_cbufs = 1;
318 fb.cbufs[0] = surface;
319 fb.zsbuf = 0;
320
321 /* Viewport just touches the bit we're interested in:
322 */
323 viewport.scale[0] = width / 2.f;
324 viewport.scale[1] = height / 2.f;
325 viewport.scale[2] = 1.0;
326 viewport.scale[3] = 1.0;
327 viewport.translate[0] = width / 2.f;
328 viewport.translate[1] = height / 2.f;
329 viewport.translate[2] = 0.0;
330 viewport.translate[3] = 0.0;
331
332 /* Constant buffer set up to match viewport dimensions:
333 */
334 if (r->fb_width != width ||
335 r->fb_height != height)
336 {
337 float vs_consts[8] = {
338 2.f/width, 2.f/height, 1, 1,
339 -1, -1, 0, 0
340 };
341
342 r->fb_width = width;
343 r->fb_height = height;
344
345 renderer_set_constants(r, PIPE_SHADER_VERTEX,
346 vs_consts, sizeof vs_consts);
347 }
348
349 cso_set_framebuffer(r->cso, &fb);
350 cso_set_viewport(r->cso, &viewport);
351 }
352
353
354 struct xorg_renderer * renderer_create(struct pipe_context *pipe)
355 {
356 struct xorg_renderer *renderer = CALLOC_STRUCT(xorg_renderer);
357
358 renderer->pipe = pipe;
359 renderer->cso = cso_create_context(pipe);
360 renderer->shaders = xorg_shaders_create(renderer);
361
362 renderer_init_state(renderer);
363
364 return renderer;
365 }
366
367 void renderer_destroy(struct xorg_renderer *r)
368 {
369 struct pipe_resource **vsbuf = &r->vs_const_buffer;
370 struct pipe_resource **fsbuf = &r->fs_const_buffer;
371
372 if (*vsbuf)
373 pipe_resource_reference(vsbuf, NULL);
374
375 if (*fsbuf)
376 pipe_resource_reference(fsbuf, NULL);
377
378 if (r->shaders) {
379 xorg_shaders_destroy(r->shaders);
380 r->shaders = NULL;
381 }
382
383 if (r->cso) {
384 cso_release_all(r->cso);
385 cso_destroy_context(r->cso);
386 r->cso = NULL;
387 }
388 }
389
390
391
392
393
394 void renderer_set_constants(struct xorg_renderer *r,
395 int shader_type,
396 const float *params,
397 int param_bytes)
398 {
399 struct pipe_resource **cbuf =
400 (shader_type == PIPE_SHADER_VERTEX) ? &r->vs_const_buffer :
401 &r->fs_const_buffer;
402
403 pipe_resource_reference(cbuf, NULL);
404 *cbuf = pipe_buffer_create(r->pipe->screen,
405 PIPE_BIND_CONSTANT_BUFFER,
406 PIPE_USAGE_STATIC,
407 param_bytes);
408
409 if (*cbuf) {
410 pipe_buffer_write(r->pipe, *cbuf,
411 0, param_bytes, params);
412 }
413 pipe_set_constant_buffer(r->pipe, shader_type, 0, *cbuf);
414 }
415
416
417
418 void renderer_draw_yuv(struct xorg_renderer *r,
419 float src_x, float src_y, float src_w, float src_h,
420 int dst_x, int dst_y, int dst_w, int dst_h,
421 struct pipe_resource **textures)
422 {
423 const int num_attribs = 2; /*pos + tex coord*/
424
425 setup_vertex_data_yuv(r,
426 src_x, src_y, src_w, src_h,
427 dst_x, dst_y, dst_w, dst_h,
428 textures);
429
430 cso_set_vertex_elements(r->cso, num_attribs, r->velems);
431
432 util_draw_user_vertex_buffer(r->cso, r->buffer,
433 PIPE_PRIM_QUADS,
434 4, /* verts */
435 num_attribs); /* attribs/vert */
436
437 r->buffer_size = 0;
438 }
439
440 void renderer_begin_solid(struct xorg_renderer *r)
441 {
442 r->buffer_size = 0;
443 r->attrs_per_vertex = 2;
444 }
445
446 void renderer_solid(struct xorg_renderer *r,
447 int x0, int y0,
448 int x1, int y1,
449 float *color)
450 {
451 /*
452 debug_printf("solid rect[(%d, %d), (%d, %d)], rgba[%f, %f, %f, %f]\n",
453 x0, y0, x1, y1, color[0], color[1], color[2], color[3]);*/
454
455 renderer_draw_conditional(r, 4 * 8);
456
457 /* 1st vertex */
458 add_vertex_color(r, x0, y0, color);
459 /* 2nd vertex */
460 add_vertex_color(r, x1, y0, color);
461 /* 3rd vertex */
462 add_vertex_color(r, x1, y1, color);
463 /* 4th vertex */
464 add_vertex_color(r, x0, y1, color);
465 }
466
467 void renderer_draw_flush(struct xorg_renderer *r)
468 {
469 renderer_draw_conditional(r, 0);
470 }
471
472 void renderer_begin_textures(struct xorg_renderer *r,
473 int num_textures)
474 {
475 r->attrs_per_vertex = 1 + num_textures;
476 r->buffer_size = 0;
477 }
478
479 void renderer_texture(struct xorg_renderer *r,
480 int *pos,
481 int width, int height,
482 struct pipe_sampler_view **sampler_view,
483 int num_textures,
484 float *src_matrix,
485 float *mask_matrix)
486 {
487
488 #if 0
489 if (src_matrix) {
490 debug_printf("src_matrix = \n");
491 debug_printf("%f, %f, %f\n", src_matrix[0], src_matrix[1], src_matrix[2]);
492 debug_printf("%f, %f, %f\n", src_matrix[3], src_matrix[4], src_matrix[5]);
493 debug_printf("%f, %f, %f\n", src_matrix[6], src_matrix[7], src_matrix[8]);
494 }
495 if (mask_matrix) {
496 debug_printf("mask_matrix = \n");
497 debug_printf("%f, %f, %f\n", mask_matrix[0], mask_matrix[1], mask_matrix[2]);
498 debug_printf("%f, %f, %f\n", mask_matrix[3], mask_matrix[4], mask_matrix[5]);
499 debug_printf("%f, %f, %f\n", mask_matrix[6], mask_matrix[7], mask_matrix[8]);
500 }
501 #endif
502
503 switch(r->attrs_per_vertex) {
504 case 2:
505 renderer_draw_conditional(r, 4 * 8);
506 add_vertex_data1(r,
507 pos[0], pos[1], /* src */
508 pos[4], pos[5], /* dst */
509 width, height,
510 sampler_view[0]->texture, src_matrix);
511 break;
512 case 3:
513 renderer_draw_conditional(r, 4 * 12);
514 add_vertex_data2(r,
515 pos[0], pos[1], /* src */
516 pos[2], pos[3], /* mask */
517 pos[4], pos[5], /* dst */
518 width, height,
519 sampler_view[0]->texture, sampler_view[1]->texture,
520 src_matrix, mask_matrix);
521 break;
522 default:
523 debug_assert(!"Unsupported number of textures");
524 break;
525 }
526 }