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