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