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 
is_affine(float * matrix)22 static INLINE boolean is_affine(float *matrix)
23 {
24    return floatIsZero(matrix[2]) && floatIsZero(matrix[5])
25       && floatsEqual(matrix[8], 1);
26 }
map_point(float * mat,float x,float y,float * out_x,float * out_y)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
renderer_draw(struct xorg_renderer * r)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
renderer_draw_conditional(struct xorg_renderer * r,int next_batch)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
renderer_init_state(struct xorg_renderer * r)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
add_vertex_color(struct xorg_renderer * r,float x,float y,float color[4])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
add_vertex_1tex(struct xorg_renderer * r,float x,float y,float s,float t)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
add_vertex_data1(struct xorg_renderer * r,float srcX,float srcY,float dstX,float dstY,float width,float height,struct pipe_resource * src,float * src_matrix)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
add_vertex_2tex(struct xorg_renderer * r,float x,float y,float s0,float t0,float s1,float t1)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
add_vertex_data2(struct xorg_renderer * r,float srcX,float srcY,float maskX,float maskY,float dstX,float dstY,float width,float height,struct pipe_resource * src,struct pipe_resource * mask,float * src_matrix,float * mask_matrix)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, src_s2, src_t2, src_s3, src_t3;
217    float mask_s0, mask_t0, mask_s1, mask_t1, mask_s2, mask_t2, mask_s3, mask_t3;
218    float spt0[2], spt1[2], spt2[2], spt3[2];
219    float mpt0[2], mpt1[2], mpt2[2], mpt3[2];
220 
221    spt0[0] = srcX;
222    spt0[1] = srcY;
223    spt1[0] = (srcX + width);
224    spt1[1] = srcY;
225    spt2[0] = (srcX + width);
226    spt2[1] = (srcY + height);
227    spt3[0] = srcX;
228    spt3[1] = (srcY + height);
229 
230    mpt0[0] = maskX;
231    mpt0[1] = maskY;
232    mpt1[0] = (maskX + width);
233    mpt1[1] = maskY;
234    mpt2[0] = (maskX + width);
235    mpt2[1] = (maskY + height);
236    mpt3[0] = maskX;
237    mpt3[1] = (maskY + height);
238 
239    if (src_matrix) {
240       map_point(src_matrix, spt0[0], spt0[1], &spt0[0], &spt0[1]);
241       map_point(src_matrix, spt1[0], spt1[1], &spt1[0], &spt1[1]);
242       map_point(src_matrix, spt2[0], spt2[1], &spt2[0], &spt2[1]);
243       map_point(src_matrix, spt3[0], spt3[1], &spt3[0], &spt3[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       map_point(mask_matrix, mpt2[0], mpt2[1], &mpt2[0], &mpt2[1]);
250       map_point(mask_matrix, mpt3[0], mpt3[1], &mpt3[0], &mpt3[1]);
251    }
252 
253    src_s0 =  spt0[0] / src->width0;
254    src_s1 =  spt1[0] / src->width0;
255    src_s2 =  spt2[0] / src->width0;
256    src_s3 =  spt3[0] / src->width0;
257    src_t0 =  spt0[1] / src->height0;
258    src_t1 =  spt1[1] / src->height0;
259    src_t2 =  spt2[1] / src->height0;
260    src_t3 =  spt3[1] / src->height0;
261 
262    mask_s0 =  mpt0[0] / mask->width0;
263    mask_s1 =  mpt1[0] / mask->width0;
264    mask_s2 =  mpt2[0] / mask->width0;
265    mask_s3 =  mpt3[0] / mask->width0;
266    mask_t0 =  mpt0[1] / mask->height0;
267    mask_t1 =  mpt1[1] / mask->height0;
268    mask_t2 =  mpt2[1] / mask->height0;
269    mask_t3 =  mpt3[1] / mask->height0;
270 
271    /* 1st vertex */
272    add_vertex_2tex(r, dstX, dstY,
273                    src_s0, src_t0, mask_s0, mask_t0);
274    /* 2nd vertex */
275    add_vertex_2tex(r, dstX + width, dstY,
276                    src_s1, src_t1, mask_s1, mask_t1);
277    /* 3rd vertex */
278    add_vertex_2tex(r, dstX + width, dstY + height,
279                    src_s2, src_t2, mask_s2, mask_t2);
280    /* 4th vertex */
281    add_vertex_2tex(r, dstX, dstY + height,
282                    src_s3, src_t3, mask_s3, mask_t3);
283 }
284 
285 static void
setup_vertex_data_yuv(struct xorg_renderer * r,float srcX,float srcY,float srcW,float srcH,float dstX,float dstY,float dstW,float dstH,struct pipe_resource ** tex)286 setup_vertex_data_yuv(struct xorg_renderer *r,
287                       float srcX, float srcY, float srcW, float srcH,
288                       float dstX, float dstY, float dstW, float dstH,
289                       struct pipe_resource **tex)
290 {
291    float s0, t0, s1, t1;
292    float spt0[2], spt1[2];
293 
294    spt0[0] = srcX;
295    spt0[1] = srcY;
296    spt1[0] = srcX + srcW;
297    spt1[1] = srcY + srcH;
298 
299    s0 = spt0[0] / tex[0]->width0;
300    t0 = spt0[1] / tex[0]->height0;
301    s1 = spt1[0] / tex[0]->width0;
302    t1 = spt1[1] / tex[0]->height0;
303 
304    /* 1st vertex */
305    add_vertex_1tex(r, dstX, dstY, s0, t0);
306    /* 2nd vertex */
307    add_vertex_1tex(r, dstX + dstW, dstY,
308                    s1, t0);
309    /* 3rd vertex */
310    add_vertex_1tex(r, dstX + dstW, dstY + dstH,
311                    s1, t1);
312    /* 4th vertex */
313    add_vertex_1tex(r, dstX, dstY + dstH,
314                    s0, t1);
315 }
316 
317 
318 
319 /* Set up framebuffer, viewport and vertex shader constant buffer
320  * state for a particular destinaton surface.  In all our rendering,
321  * these concepts are linked.
322  */
renderer_bind_destination(struct xorg_renderer * r,struct pipe_surface * surface,int width,int height)323 void renderer_bind_destination(struct xorg_renderer *r,
324                                struct pipe_surface *surface,
325                                int width,
326                                int height )
327 {
328 
329    struct pipe_framebuffer_state fb;
330    struct pipe_viewport_state viewport;
331 
332    /* Framebuffer uses actual surface width/height
333     */
334    memset(&fb, 0, sizeof fb);
335    fb.width  = surface->width;
336    fb.height = surface->height;
337    fb.nr_cbufs = 1;
338    fb.cbufs[0] = surface;
339    fb.zsbuf = 0;
340 
341    /* Viewport just touches the bit we're interested in:
342     */
343    viewport.scale[0] =  width / 2.f;
344    viewport.scale[1] =  height / 2.f;
345    viewport.scale[2] =  1.0;
346    viewport.scale[3] =  1.0;
347    viewport.translate[0] = width / 2.f;
348    viewport.translate[1] = height / 2.f;
349    viewport.translate[2] = 0.0;
350    viewport.translate[3] = 0.0;
351 
352    /* Constant buffer set up to match viewport dimensions:
353     */
354    if (r->fb_width != width ||
355        r->fb_height != height)
356    {
357       float vs_consts[8] = {
358          2.f/width, 2.f/height, 1, 1,
359          -1, -1, 0, 0
360       };
361 
362       r->fb_width = width;
363       r->fb_height = height;
364 
365       renderer_set_constants(r, PIPE_SHADER_VERTEX,
366                              vs_consts, sizeof vs_consts);
367    }
368 
369    cso_set_framebuffer(r->cso, &fb);
370    cso_set_viewport(r->cso, &viewport);
371 }
372 
373 
renderer_create(struct pipe_context * pipe)374 struct xorg_renderer * renderer_create(struct pipe_context *pipe)
375 {
376    struct xorg_renderer *renderer = CALLOC_STRUCT(xorg_renderer);
377 
378    renderer->pipe = pipe;
379    renderer->cso = cso_create_context(pipe);
380    renderer->shaders = xorg_shaders_create(renderer);
381 
382    renderer_init_state(renderer);
383 
384    return renderer;
385 }
386 
renderer_destroy(struct xorg_renderer * r)387 void renderer_destroy(struct xorg_renderer *r)
388 {
389    struct pipe_resource **vsbuf = &r->vs_const_buffer;
390    struct pipe_resource **fsbuf = &r->fs_const_buffer;
391 
392    if (*vsbuf)
393       pipe_resource_reference(vsbuf, NULL);
394 
395    if (*fsbuf)
396       pipe_resource_reference(fsbuf, NULL);
397 
398    if (r->shaders) {
399       xorg_shaders_destroy(r->shaders);
400       r->shaders = NULL;
401    }
402 
403    if (r->cso) {
404       cso_release_all(r->cso);
405       cso_destroy_context(r->cso);
406       r->cso = NULL;
407    }
408 }
409 
410 
411 
412 
413 
renderer_set_constants(struct xorg_renderer * r,int shader_type,const float * params,int param_bytes)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_resource **cbuf =
420       (shader_type == PIPE_SHADER_VERTEX) ? &r->vs_const_buffer :
421       &r->fs_const_buffer;
422 
423    pipe_resource_reference(cbuf, NULL);
424    *cbuf = pipe_buffer_create(r->pipe->screen,
425                               PIPE_BIND_CONSTANT_BUFFER,
426                               PIPE_USAGE_STATIC,
427                               param_bytes);
428 
429    if (*cbuf) {
430       pipe_buffer_write(r->pipe, *cbuf,
431                         0, param_bytes, params);
432    }
433    pipe_set_constant_buffer(r->pipe, shader_type, 0, *cbuf);
434 }
435 
436 
437 
renderer_draw_yuv(struct xorg_renderer * r,float src_x,float src_y,float src_w,float src_h,int dst_x,int dst_y,int dst_w,int dst_h,struct pipe_resource ** textures)438 void renderer_draw_yuv(struct xorg_renderer *r,
439                        float src_x, float src_y, float src_w, float src_h,
440                        int dst_x, int dst_y, int dst_w, int dst_h,
441                        struct pipe_resource **textures)
442 {
443    const int num_attribs = 2; /*pos + tex coord*/
444 
445    setup_vertex_data_yuv(r,
446                          src_x, src_y, src_w, src_h,
447                          dst_x, dst_y, dst_w, dst_h,
448                          textures);
449 
450    cso_set_vertex_elements(r->cso, num_attribs, r->velems);
451 
452    util_draw_user_vertex_buffer(r->cso, r->buffer,
453                                 PIPE_PRIM_QUADS,
454                                 4,  /* verts */
455                                 num_attribs); /* attribs/vert */
456 
457    r->buffer_size = 0;
458 }
459 
renderer_begin_solid(struct xorg_renderer * r)460 void renderer_begin_solid(struct xorg_renderer *r)
461 {
462    r->buffer_size = 0;
463    r->attrs_per_vertex = 2;
464 }
465 
renderer_solid(struct xorg_renderer * r,int x0,int y0,int x1,int y1,float * color)466 void renderer_solid(struct xorg_renderer *r,
467                     int x0, int y0,
468                     int x1, int y1,
469                     float *color)
470 {
471    /*
472    debug_printf("solid rect[(%d, %d), (%d, %d)], rgba[%f, %f, %f, %f]\n",
473    x0, y0, x1, y1, color[0], color[1], color[2], color[3]);*/
474 
475    renderer_draw_conditional(r, 4 * 8);
476 
477    /* 1st vertex */
478    add_vertex_color(r, x0, y0, color);
479    /* 2nd vertex */
480    add_vertex_color(r, x1, y0, color);
481    /* 3rd vertex */
482    add_vertex_color(r, x1, y1, color);
483    /* 4th vertex */
484    add_vertex_color(r, x0, y1, color);
485 }
486 
renderer_draw_flush(struct xorg_renderer * r)487 void renderer_draw_flush(struct xorg_renderer *r)
488 {
489    renderer_draw_conditional(r, 0);
490 }
491 
renderer_begin_textures(struct xorg_renderer * r,int num_textures)492 void renderer_begin_textures(struct xorg_renderer *r,
493                              int num_textures)
494 {
495    r->attrs_per_vertex = 1 + num_textures;
496    r->buffer_size = 0;
497 }
498 
renderer_texture(struct xorg_renderer * r,int * pos,int width,int height,struct pipe_sampler_view ** sampler_view,int num_textures,float * src_matrix,float * mask_matrix)499 void renderer_texture(struct xorg_renderer *r,
500                       int *pos,
501                       int width, int height,
502                       struct pipe_sampler_view **sampler_view,
503                       int num_textures,
504                       float *src_matrix,
505                       float *mask_matrix)
506 {
507 
508 #if 0
509    if (src_matrix) {
510       debug_printf("src_matrix = \n");
511       debug_printf("%f, %f, %f\n", src_matrix[0], src_matrix[1], src_matrix[2]);
512       debug_printf("%f, %f, %f\n", src_matrix[3], src_matrix[4], src_matrix[5]);
513       debug_printf("%f, %f, %f\n", src_matrix[6], src_matrix[7], src_matrix[8]);
514    }
515    if (mask_matrix) {
516       debug_printf("mask_matrix = \n");
517       debug_printf("%f, %f, %f\n", mask_matrix[0], mask_matrix[1], mask_matrix[2]);
518       debug_printf("%f, %f, %f\n", mask_matrix[3], mask_matrix[4], mask_matrix[5]);
519       debug_printf("%f, %f, %f\n", mask_matrix[6], mask_matrix[7], mask_matrix[8]);
520    }
521 #endif
522 
523    switch(r->attrs_per_vertex) {
524    case 2:
525       renderer_draw_conditional(r, 4 * 8);
526       add_vertex_data1(r,
527                        pos[0], pos[1], /* src */
528                        pos[4], pos[5], /* dst */
529                        width, height,
530                        sampler_view[0]->texture, src_matrix);
531       break;
532    case 3:
533       renderer_draw_conditional(r, 4 * 12);
534       add_vertex_data2(r,
535                        pos[0], pos[1], /* src */
536                        pos[2], pos[3], /* mask */
537                        pos[4], pos[5], /* dst */
538                        width, height,
539                        sampler_view[0]->texture, sampler_view[1]->texture,
540                        src_matrix, mask_matrix);
541       break;
542    default:
543       debug_assert(!"Unsupported number of textures");
544       break;
545    }
546 }
547