Home | History | Annotate | Download | only in xorg
      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, 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
    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  */
    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 
    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 
    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 
    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 
    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 
    460 void renderer_begin_solid(struct xorg_renderer *r)
    461 {
    462    r->buffer_size = 0;
    463    r->attrs_per_vertex = 2;
    464 }
    465 
    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 
    487 void renderer_draw_flush(struct xorg_renderer *r)
    488 {
    489    renderer_draw_conditional(r, 0);
    490 }
    491 
    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 
    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