Home | History | Annotate | Download | only in graw
      1 /* Display a cleared blue window.  This demo has no dependencies on
      2  * any utility code, just the graw interface and gallium.
      3  */
      4 
      5 #include "state_tracker/graw.h"
      6 #include "pipe/p_screen.h"
      7 #include "pipe/p_context.h"
      8 #include "pipe/p_shader_tokens.h"
      9 #include "pipe/p_state.h"
     10 #include "pipe/p_defines.h"
     11 #include <stdio.h>              /* for fread(), etc */
     12 
     13 #include "util/u_inlines.h"
     14 #include "util/u_memory.h"      /* Offset() */
     15 #include "util/u_draw_quad.h"
     16 #include "util/u_box.h"
     17 
     18 static const char *filename = NULL;
     19 unsigned show_fps = 0;
     20 unsigned draw_strip = 0;
     21 
     22 
     23 static void usage(char *name)
     24 {
     25    fprintf(stderr, "usage: %s [ options ] shader_filename\n", name);
     26 #ifndef WIN32
     27    fprintf(stderr, "\n" );
     28    fprintf(stderr, "options:\n");
     29    fprintf(stderr, "    -fps  show frames per second\n");
     30    fprintf(stderr, "    -strip renders a triangle strip\n");
     31 #endif
     32 }
     33 
     34 
     35 enum pipe_format formats[] = {
     36    PIPE_FORMAT_R8G8B8A8_UNORM,
     37    PIPE_FORMAT_B8G8R8A8_UNORM,
     38    PIPE_FORMAT_NONE
     39 };
     40 
     41 static const int WIDTH = 250;
     42 static const int HEIGHT = 250;
     43 
     44 static struct pipe_screen *screen = NULL;
     45 static struct pipe_context *ctx = NULL;
     46 static struct pipe_resource *rttex = NULL;
     47 static struct pipe_resource *constbuf1 = NULL;
     48 static struct pipe_resource *constbuf2 = NULL;
     49 static struct pipe_surface *surf = NULL;
     50 static struct pipe_sampler_view *sv = NULL;
     51 static void *sampler = NULL;
     52 static void *window = NULL;
     53 static struct pipe_resource *samptex = NULL;
     54 
     55 struct vertex {
     56    float position[4];
     57    float color[4];
     58    float texcoord[4];
     59    float generic[4];
     60 };
     61 
     62 /* Vertex data matches progs/fp/fp-tri.c, but flipped in Y dimension
     63  * so that the final images are the same.
     64  */
     65 static struct vertex vertices[] =
     66 {
     67    { { 0.9, 0.9, 0.0, 1.0 },
     68      { 0, 0, 1, 1 },
     69      { 1, 1, 0, 1 },
     70      { 1, 0, 1, 0 }
     71    },
     72 
     73    { { 0.9,  -0.9, 0.0, 1.0 },
     74      { 1, 0, 0, 1 },
     75      { 1, -1, 0, 1 },
     76      { 0, 1, 0, 1 }
     77    },
     78 
     79    { {-0.9,  0.0, 0.0, 1.0 },
     80      { 0, 1, 0, 1 },
     81      { -1, 0, 0, 1 },
     82      { 0, 0, 1, 1 }
     83    },
     84 };
     85 
     86 static struct vertex vertices_strip[] =
     87 {
     88    { { 0.9, 0.9, 0.0, 1.0 },
     89      { 0, 0, 1, 1 },
     90      { 1, 1, 0, 1 },
     91      { 1, 0, 0, 1 }
     92    },
     93 
     94    { { 0.9,  -0.9, 0.0, 1.0 },
     95      { 1, 0, 0, 1 },
     96      { 1, -1, 0, 1 },
     97      { 0, 1, 0, 1 }
     98    },
     99 
    100    { {-0.9,  0.9, 0.0, 1.0 },
    101      { 0, 1, 0, 1 },
    102      { -1, 1, 0, 1 },
    103      { 0, 0, 1, 1 }
    104    },
    105 
    106    { {-0.9,  -0.9, 0.0, 1.0 },
    107      { 1, 1, 0, 1 },
    108      { -1, -1, 0, 1 },
    109      { 1, 1, 0, 1 }
    110    },
    111 };
    112 
    113 static float constants1[] =
    114 {  0.4, 0, 0,  1,
    115    1,   1, 1,  1,
    116    2,   2, 2,  2,
    117    4,   8, 16, 32,
    118 
    119    3,  0, 0, 0,
    120    0, .5, 0, 0,
    121    0,  0, 1, 0,
    122    0,  0, 0, 1,
    123 
    124    1, 0, 0, 0.5,
    125    0, 1, 0, 0.5,
    126    0, 0, 1, 0,
    127    0, 0, 0, 1,
    128 };
    129 
    130 
    131 static float constants2[] =
    132 {  1, 0, 0,  1,
    133    0, 1, 0,  1,
    134    0, 0, 1,  1,
    135    0, 0, 0,  1,
    136 
    137    1,  1, 0, 1,
    138    1, .5, 0, 1,
    139    0,  1, 1, 1,
    140    1,  0, 1, 1,
    141 
    142    1, 0, 0, 0.5,
    143    0, 1, 0, 0.5,
    144    0, 0, 1, 0,
    145    0, 0, 0, 1,
    146 };
    147 
    148 
    149 static void init_fs_constbuf( void )
    150 {
    151    struct pipe_resource templat;
    152    struct pipe_box box;
    153 
    154    templat.target = PIPE_BUFFER;
    155    templat.format = PIPE_FORMAT_R8_UNORM;
    156    templat.width0 = sizeof(constants1);
    157    templat.height0 = 1;
    158    templat.depth0 = 1;
    159    templat.array_size = 1;
    160    templat.last_level = 0;
    161    templat.nr_samples = 1;
    162    templat.bind = PIPE_BIND_CONSTANT_BUFFER;
    163 
    164    constbuf1 = screen->resource_create(screen, &templat);
    165    if (constbuf1 == NULL)
    166       exit(4);
    167    constbuf2 = screen->resource_create(screen, &templat);
    168    if (constbuf2 == NULL)
    169       exit(4);
    170 
    171    {
    172       u_box_2d(0,0,sizeof(constants1),1, &box);
    173 
    174       ctx->transfer_inline_write(ctx,
    175                                  constbuf1,
    176                                  0,
    177                                  PIPE_TRANSFER_WRITE,
    178                                  &box,
    179                                  constants1,
    180                                  sizeof constants1,
    181                                  sizeof constants1);
    182 
    183 
    184       pipe_set_constant_buffer(ctx,
    185                                PIPE_SHADER_GEOMETRY, 0,
    186                                constbuf1);
    187    }
    188    {
    189       u_box_2d(0,0,sizeof(constants2),1, &box);
    190 
    191       ctx->transfer_inline_write(ctx,
    192                                  constbuf2,
    193                                  0,
    194                                  PIPE_TRANSFER_WRITE,
    195                                  &box,
    196                                  constants2,
    197                                  sizeof constants2,
    198                                  sizeof constants2);
    199 
    200 
    201       pipe_set_constant_buffer(ctx,
    202                                PIPE_SHADER_GEOMETRY, 1,
    203                                constbuf2);
    204    }
    205 }
    206 
    207 
    208 static void set_viewport( float x, float y,
    209                           float width, float height,
    210                           float near, float far)
    211 {
    212    float z = far;
    213    float half_width = (float)width / 2.0f;
    214    float half_height = (float)height / 2.0f;
    215    float half_depth = ((float)far - (float)near) / 2.0f;
    216    struct pipe_viewport_state vp;
    217 
    218    vp.scale[0] = half_width;
    219    vp.scale[1] = half_height;
    220    vp.scale[2] = half_depth;
    221    vp.scale[3] = 1.0f;
    222 
    223    vp.translate[0] = half_width + x;
    224    vp.translate[1] = half_height + y;
    225    vp.translate[2] = half_depth + z;
    226    vp.translate[3] = 0.0f;
    227 
    228    ctx->set_viewport_state( ctx, &vp );
    229 }
    230 
    231 static void set_vertices( void )
    232 {
    233    struct pipe_vertex_element ve[4];
    234    struct pipe_vertex_buffer vbuf;
    235    void *handle;
    236 
    237    memset(ve, 0, sizeof ve);
    238 
    239    ve[0].src_offset = Offset(struct vertex, position);
    240    ve[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
    241    ve[1].src_offset = Offset(struct vertex, color);
    242    ve[1].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
    243    ve[2].src_offset = Offset(struct vertex, texcoord);
    244    ve[2].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
    245    ve[3].src_offset = Offset(struct vertex, generic);
    246    ve[3].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
    247 
    248    handle = ctx->create_vertex_elements_state(ctx, 4, ve);
    249    ctx->bind_vertex_elements_state(ctx, handle);
    250 
    251    vbuf.stride = sizeof( struct vertex );
    252    vbuf.buffer_offset = 0;
    253    if (draw_strip) {
    254       vbuf.buffer = pipe_buffer_create_with_data(ctx,
    255                                                  PIPE_BIND_VERTEX_BUFFER,
    256                                                  PIPE_USAGE_STATIC,
    257                                                  sizeof(vertices_strip),
    258                                                  vertices_strip);
    259    } else {
    260       vbuf.buffer = pipe_buffer_create_with_data(ctx,
    261                                                  PIPE_BIND_VERTEX_BUFFER,
    262                                                  PIPE_USAGE_STATIC,
    263                                                  sizeof(vertices),
    264                                                  vertices);
    265    }
    266 
    267    ctx->set_vertex_buffers(ctx, 1, &vbuf);
    268 }
    269 
    270 static void set_vertex_shader( void )
    271 {
    272    void *handle;
    273    const char *text =
    274       "VERT\n"
    275       "DCL IN[0]\n"
    276       "DCL IN[1]\n"
    277       "DCL IN[2]\n"
    278       "DCL IN[3]\n"
    279       "DCL OUT[0], POSITION\n"
    280       "DCL OUT[1], COLOR[0]\n"
    281       "DCL OUT[2], GENERIC[0]\n"
    282       "DCL OUT[3], GENERIC[1]\n"
    283       "  MOV OUT[0], IN[0]\n"
    284       "  MOV OUT[1], IN[1]\n"
    285       "  MOV OUT[2], IN[2]\n"
    286       "  MOV OUT[3], IN[3]\n"
    287       "  END\n";
    288 
    289    handle = graw_parse_vertex_shader(ctx, text);
    290    ctx->bind_vs_state(ctx, handle);
    291 }
    292 
    293 static void set_fragment_shader( void )
    294 {
    295    void *handle;
    296    const char *text =
    297       "FRAG\n"
    298       "DCL IN[0], COLOR, LINEAR\n"
    299       "DCL OUT[0], COLOR\n"
    300       "  0: MOV OUT[0], IN[0]\n"
    301       "  1: END\n";
    302 
    303    handle = graw_parse_fragment_shader(ctx, text);
    304    ctx->bind_fs_state(ctx, handle);
    305 }
    306 
    307 
    308 static void set_geometry_shader( void )
    309 {
    310    FILE *f;
    311    char buf[50000];
    312    void *handle;
    313    int sz;
    314 
    315    if ((f = fopen(filename, "r")) == NULL) {
    316       fprintf(stderr, "Couldn't open %s\n", filename);
    317       exit(1);
    318    }
    319 
    320    sz = fread(buf, 1, sizeof(buf), f);
    321    if (!feof(f)) {
    322       printf("file too long\n");
    323       exit(1);
    324    }
    325    printf("%.*s\n", sz, buf);
    326    buf[sz] = 0;
    327 
    328    handle = graw_parse_geometry_shader(ctx, buf);
    329    ctx->bind_gs_state(ctx, handle);
    330    fclose(f);
    331 }
    332 
    333 
    334 static void draw( void )
    335 {
    336    union pipe_color_union clear_color = { {.1,.3,.5,0} };
    337 
    338    ctx->clear(ctx, PIPE_CLEAR_COLOR, &clear_color, 0, 0);
    339    if (draw_strip)
    340       util_draw_arrays(ctx, PIPE_PRIM_TRIANGLE_STRIP, 0, 4);
    341    else
    342       util_draw_arrays(ctx, PIPE_PRIM_TRIANGLES, 0, 3);
    343 
    344    ctx->flush(ctx, NULL);
    345 
    346    graw_save_surface_to_file(ctx, surf, NULL);
    347 
    348    screen->flush_frontbuffer(screen, rttex, 0, 0, window);
    349 }
    350 
    351 #define SIZE 16
    352 
    353 static void init_tex( void )
    354 {
    355    struct pipe_sampler_view sv_template;
    356    struct pipe_sampler_state sampler_desc;
    357    struct pipe_resource templat;
    358    struct pipe_box box;
    359    ubyte tex2d[SIZE][SIZE][4];
    360    int s, t;
    361 
    362 #if (SIZE != 2)
    363    for (s = 0; s < SIZE; s++) {
    364       for (t = 0; t < SIZE; t++) {
    365          if (0) {
    366             int x = (s ^ t) & 1;
    367 	    tex2d[t][s][0] = (x) ? 0 : 63;
    368 	    tex2d[t][s][1] = (x) ? 0 : 128;
    369 	    tex2d[t][s][2] = 0;
    370 	    tex2d[t][s][3] = 0xff;
    371          }
    372          else {
    373             int x = ((s ^ t) >> 2) & 1;
    374 	    tex2d[t][s][0] = s*255/(SIZE-1);
    375 	    tex2d[t][s][1] = t*255/(SIZE-1);
    376 	    tex2d[t][s][2] = (x) ? 0 : 128;
    377 	    tex2d[t][s][3] = 0xff;
    378          }
    379       }
    380    }
    381 #else
    382    tex2d[0][0][0] = 0;
    383    tex2d[0][0][1] = 255;
    384    tex2d[0][0][2] = 255;
    385    tex2d[0][0][3] = 0;
    386 
    387    tex2d[0][1][0] = 0;
    388    tex2d[0][1][1] = 0;
    389    tex2d[0][1][2] = 255;
    390    tex2d[0][1][3] = 255;
    391 
    392    tex2d[1][0][0] = 255;
    393    tex2d[1][0][1] = 255;
    394    tex2d[1][0][2] = 0;
    395    tex2d[1][0][3] = 255;
    396 
    397    tex2d[1][1][0] = 255;
    398    tex2d[1][1][1] = 0;
    399    tex2d[1][1][2] = 0;
    400    tex2d[1][1][3] = 255;
    401 #endif
    402 
    403    templat.target = PIPE_TEXTURE_2D;
    404    templat.format = PIPE_FORMAT_B8G8R8A8_UNORM;
    405    templat.width0 = SIZE;
    406    templat.height0 = SIZE;
    407    templat.depth0 = 1;
    408    templat.array_size = 1;
    409    templat.last_level = 0;
    410    templat.nr_samples = 1;
    411    templat.bind = PIPE_BIND_SAMPLER_VIEW;
    412 
    413 
    414    samptex = screen->resource_create(screen,
    415                                  &templat);
    416    if (samptex == NULL)
    417       exit(4);
    418 
    419    u_box_2d(0,0,SIZE,SIZE, &box);
    420 
    421    ctx->transfer_inline_write(ctx,
    422                               samptex,
    423                               0,
    424                               PIPE_TRANSFER_WRITE,
    425                               &box,
    426                               tex2d,
    427                               sizeof tex2d[0],
    428                               sizeof tex2d);
    429 
    430    /* Possibly read back & compare against original data:
    431     */
    432    if (0)
    433    {
    434       struct pipe_transfer *t;
    435       uint32_t *ptr;
    436       t = pipe_get_transfer(ctx, samptex,
    437                             0, 0, /* level, layer */
    438                             PIPE_TRANSFER_READ,
    439                             0, 0, SIZE, SIZE); /* x, y, width, height */
    440 
    441       ptr = ctx->transfer_map(ctx, t);
    442 
    443       if (memcmp(ptr, tex2d, sizeof tex2d) != 0) {
    444          assert(0);
    445          exit(9);
    446       }
    447 
    448       ctx->transfer_unmap(ctx, t);
    449 
    450       ctx->transfer_destroy(ctx, t);
    451    }
    452 
    453    memset(&sv_template, 0, sizeof sv_template);
    454    sv_template.format = samptex->format;
    455    sv_template.texture = samptex;
    456    sv_template.swizzle_r = 0;
    457    sv_template.swizzle_g = 1;
    458    sv_template.swizzle_b = 2;
    459    sv_template.swizzle_a = 3;
    460    sv = ctx->create_sampler_view(ctx, samptex, &sv_template);
    461    if (sv == NULL)
    462       exit(5);
    463 
    464    ctx->set_fragment_sampler_views(ctx, 1, &sv);
    465 
    466 
    467    memset(&sampler_desc, 0, sizeof sampler_desc);
    468    sampler_desc.wrap_s = PIPE_TEX_WRAP_REPEAT;
    469    sampler_desc.wrap_t = PIPE_TEX_WRAP_REPEAT;
    470    sampler_desc.wrap_r = PIPE_TEX_WRAP_REPEAT;
    471    sampler_desc.min_img_filter = PIPE_TEX_FILTER_NEAREST;
    472    sampler_desc.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
    473    sampler_desc.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
    474    sampler_desc.compare_mode = PIPE_TEX_COMPARE_NONE;
    475    sampler_desc.compare_func = 0;
    476    sampler_desc.normalized_coords = 1;
    477    sampler_desc.max_anisotropy = 0;
    478 
    479    sampler = ctx->create_sampler_state(ctx, &sampler_desc);
    480    if (sampler == NULL)
    481       exit(6);
    482 
    483    ctx->bind_fragment_sampler_states(ctx, 1, &sampler);
    484 
    485 }
    486 
    487 static void init( void )
    488 {
    489    struct pipe_framebuffer_state fb;
    490    struct pipe_resource templat;
    491    struct pipe_surface surf_tmpl;
    492    int i;
    493 
    494    /* It's hard to say whether window or screen should be created
    495     * first.  Different environments would prefer one or the other.
    496     *
    497     * Also, no easy way of querying supported formats if the screen
    498     * cannot be created first.
    499     */
    500    for (i = 0; formats[i] != PIPE_FORMAT_NONE; i++) {
    501       screen = graw_create_window_and_screen(0, 0, 300, 300,
    502                                              formats[i],
    503                                              &window);
    504       if (window && screen)
    505          break;
    506    }
    507    if (!screen || !window) {
    508       fprintf(stderr, "Unable to create window\n");
    509       exit(1);
    510    }
    511 
    512    ctx = screen->context_create(screen, NULL);
    513    if (ctx == NULL)
    514       exit(3);
    515 
    516    templat.target = PIPE_TEXTURE_2D;
    517    templat.format = formats[i];
    518    templat.width0 = WIDTH;
    519    templat.height0 = HEIGHT;
    520    templat.depth0 = 1;
    521    templat.array_size = 1;
    522    templat.last_level = 0;
    523    templat.nr_samples = 1;
    524    templat.bind = (PIPE_BIND_RENDER_TARGET |
    525                    PIPE_BIND_DISPLAY_TARGET);
    526 
    527    rttex = screen->resource_create(screen,
    528                                  &templat);
    529    if (rttex == NULL)
    530       exit(4);
    531 
    532    surf_tmpl.format = templat.format;
    533    surf_tmpl.usage = PIPE_BIND_RENDER_TARGET;
    534    surf_tmpl.u.tex.level = 0;
    535    surf_tmpl.u.tex.first_layer = 0;
    536    surf_tmpl.u.tex.last_layer = 0;
    537    surf = ctx->create_surface(ctx, rttex, &surf_tmpl);
    538    if (surf == NULL)
    539       exit(5);
    540 
    541    memset(&fb, 0, sizeof fb);
    542    fb.nr_cbufs = 1;
    543    fb.width = WIDTH;
    544    fb.height = HEIGHT;
    545    fb.cbufs[0] = surf;
    546 
    547    ctx->set_framebuffer_state(ctx, &fb);
    548 
    549    {
    550       struct pipe_blend_state blend;
    551       void *handle;
    552       memset(&blend, 0, sizeof blend);
    553       blend.rt[0].colormask = PIPE_MASK_RGBA;
    554       handle = ctx->create_blend_state(ctx, &blend);
    555       ctx->bind_blend_state(ctx, handle);
    556    }
    557 
    558    {
    559       struct pipe_depth_stencil_alpha_state depthstencil;
    560       void *handle;
    561       memset(&depthstencil, 0, sizeof depthstencil);
    562       handle = ctx->create_depth_stencil_alpha_state(ctx, &depthstencil);
    563       ctx->bind_depth_stencil_alpha_state(ctx, handle);
    564    }
    565 
    566    {
    567       struct pipe_rasterizer_state rasterizer;
    568       void *handle;
    569       memset(&rasterizer, 0, sizeof rasterizer);
    570       rasterizer.cull_face = PIPE_FACE_NONE;
    571       rasterizer.gl_rasterization_rules = 1;
    572       rasterizer.depth_clip = 1;
    573       handle = ctx->create_rasterizer_state(ctx, &rasterizer);
    574       ctx->bind_rasterizer_state(ctx, handle);
    575    }
    576 
    577    set_viewport(0, 0, WIDTH, HEIGHT, 30, 1000);
    578 
    579    init_tex();
    580    init_fs_constbuf();
    581 
    582    set_vertices();
    583    set_vertex_shader();
    584    set_fragment_shader();
    585    set_geometry_shader();
    586 }
    587 
    588 static void args(int argc, char *argv[])
    589 {
    590    int i;
    591 
    592    for (i = 1; i < argc;) {
    593       if (graw_parse_args(&i, argc, argv)) {
    594          continue;
    595       }
    596       if (strcmp(argv[i], "-fps") == 0) {
    597          show_fps = 1;
    598          i++;
    599       }
    600       else if (strcmp(argv[i], "-strip") == 0) {
    601          draw_strip = 1;
    602          i++;
    603       }
    604       else if (i == argc - 1) {
    605          filename = argv[i];
    606          i++;
    607       }
    608       else {
    609          usage(argv[0]);
    610          exit(1);
    611       }
    612    }
    613 
    614    if (!filename) {
    615       usage(argv[0]);
    616       exit(1);
    617    }
    618 }
    619 
    620 int main( int argc, char *argv[] )
    621 {
    622    args(argc,argv);
    623    init();
    624 
    625    graw_set_display_func( draw );
    626    graw_main_loop();
    627    return 0;
    628 }
    629