13464ebd5Sriastradh/* Display a cleared blue window. This demo has no dependencies on 23464ebd5Sriastradh * any utility code, just the graw interface and gallium. 33464ebd5Sriastradh */ 43464ebd5Sriastradh 57ec681f3Smrg#include "frontend/graw.h" 63464ebd5Sriastradh#include "pipe/p_screen.h" 73464ebd5Sriastradh#include "pipe/p_context.h" 83464ebd5Sriastradh#include "pipe/p_shader_tokens.h" 93464ebd5Sriastradh#include "pipe/p_state.h" 103464ebd5Sriastradh#include "pipe/p_defines.h" 113464ebd5Sriastradh 123464ebd5Sriastradh#include "util/u_debug.h" /* debug_dump_surface_bmp() */ 133464ebd5Sriastradh#include "util/u_inlines.h" 143464ebd5Sriastradh#include "util/u_memory.h" /* Offset() */ 153464ebd5Sriastradh#include "util/u_draw_quad.h" 163464ebd5Sriastradh#include "util/u_box.h" 173464ebd5Sriastradh 183464ebd5Sriastradh#include <stdio.h> 193464ebd5Sriastradh 203464ebd5Sriastradhenum pipe_format formats[] = { 21af69d88dSmrg PIPE_FORMAT_RGBA8888_UNORM, 22af69d88dSmrg PIPE_FORMAT_BGRA8888_UNORM, 233464ebd5Sriastradh PIPE_FORMAT_NONE 243464ebd5Sriastradh}; 253464ebd5Sriastradh 263464ebd5Sriastradhstatic const int WIDTH = 300; 273464ebd5Sriastradhstatic const int HEIGHT = 300; 283464ebd5Sriastradh 293464ebd5Sriastradhstatic struct pipe_screen *screen = NULL; 303464ebd5Sriastradhstatic struct pipe_context *ctx = NULL; 313464ebd5Sriastradhstatic struct pipe_resource *rttex = NULL; 323464ebd5Sriastradhstatic struct pipe_resource *samptex = NULL; 333464ebd5Sriastradhstatic struct pipe_surface *surf = NULL; 343464ebd5Sriastradhstatic struct pipe_sampler_view *sv = NULL; 353464ebd5Sriastradhstatic void *sampler = NULL; 363464ebd5Sriastradhstatic void *window = NULL; 373464ebd5Sriastradh 383464ebd5Sriastradhstruct vertex { 393464ebd5Sriastradh float position[4]; 403464ebd5Sriastradh float color[4]; 413464ebd5Sriastradh}; 423464ebd5Sriastradh 433464ebd5Sriastradhstatic struct vertex vertices[] = 443464ebd5Sriastradh{ 453464ebd5Sriastradh { { 0.9, -0.9, 0.0, 1.0 }, 463464ebd5Sriastradh { 1, 0, 0, 1 } }, 473464ebd5Sriastradh 483464ebd5Sriastradh { { 0.9, 0.9, 0.0, 1.0 }, 493464ebd5Sriastradh { 1, 1, 0, 1 } }, 503464ebd5Sriastradh 513464ebd5Sriastradh { {-0.9, 0.9, 0.0, 1.0 }, 523464ebd5Sriastradh { 0, 1, 0, 1 } }, 533464ebd5Sriastradh 543464ebd5Sriastradh { {-0.9, -0.9, 0.0, 1.0 }, 553464ebd5Sriastradh { 0, 0, 0, 1 } }, 563464ebd5Sriastradh}; 573464ebd5Sriastradh 583464ebd5Sriastradh 593464ebd5Sriastradh 603464ebd5Sriastradh 613464ebd5Sriastradhstatic void set_viewport( float x, float y, 623464ebd5Sriastradh float width, float height, 6301e04c3fSmrg float zNear, float zFar) 643464ebd5Sriastradh{ 6501e04c3fSmrg float z = zFar; 663464ebd5Sriastradh float half_width = (float)width / 2.0f; 673464ebd5Sriastradh float half_height = (float)height / 2.0f; 6801e04c3fSmrg float half_depth = ((float)zFar - (float)zNear) / 2.0f; 693464ebd5Sriastradh struct pipe_viewport_state vp; 703464ebd5Sriastradh 713464ebd5Sriastradh vp.scale[0] = half_width; 723464ebd5Sriastradh vp.scale[1] = half_height; 733464ebd5Sriastradh vp.scale[2] = half_depth; 743464ebd5Sriastradh 753464ebd5Sriastradh vp.translate[0] = half_width + x; 763464ebd5Sriastradh vp.translate[1] = half_height + y; 773464ebd5Sriastradh vp.translate[2] = half_depth + z; 783464ebd5Sriastradh 797ec681f3Smrg vp.swizzle_x = PIPE_VIEWPORT_SWIZZLE_POSITIVE_X; 807ec681f3Smrg vp.swizzle_y = PIPE_VIEWPORT_SWIZZLE_POSITIVE_Y; 817ec681f3Smrg vp.swizzle_z = PIPE_VIEWPORT_SWIZZLE_POSITIVE_Z; 827ec681f3Smrg vp.swizzle_w = PIPE_VIEWPORT_SWIZZLE_POSITIVE_W; 837ec681f3Smrg 84af69d88dSmrg ctx->set_viewport_states( ctx, 0, 1, &vp ); 853464ebd5Sriastradh} 863464ebd5Sriastradh 873464ebd5Sriastradhstatic void set_vertices( void ) 883464ebd5Sriastradh{ 893464ebd5Sriastradh struct pipe_vertex_element ve[2]; 903464ebd5Sriastradh struct pipe_vertex_buffer vbuf; 913464ebd5Sriastradh void *handle; 923464ebd5Sriastradh 933464ebd5Sriastradh memset(ve, 0, sizeof ve); 943464ebd5Sriastradh 953464ebd5Sriastradh ve[0].src_offset = Offset(struct vertex, position); 963464ebd5Sriastradh ve[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; 973464ebd5Sriastradh ve[1].src_offset = Offset(struct vertex, color); 983464ebd5Sriastradh ve[1].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; 993464ebd5Sriastradh 1003464ebd5Sriastradh handle = ctx->create_vertex_elements_state(ctx, 2, ve); 1013464ebd5Sriastradh ctx->bind_vertex_elements_state(ctx, handle); 1023464ebd5Sriastradh 103af69d88dSmrg memset(&vbuf, 0, sizeof vbuf); 1043464ebd5Sriastradh 1053464ebd5Sriastradh vbuf.stride = sizeof( struct vertex ); 1063464ebd5Sriastradh vbuf.buffer_offset = 0; 10701e04c3fSmrg vbuf.buffer.resource = pipe_buffer_create_with_data(ctx, 108af69d88dSmrg PIPE_BIND_VERTEX_BUFFER, 109af69d88dSmrg PIPE_USAGE_DEFAULT, 110af69d88dSmrg sizeof(vertices), 111af69d88dSmrg vertices); 1123464ebd5Sriastradh 1137ec681f3Smrg ctx->set_vertex_buffers(ctx, 0, 1, 0, false, &vbuf); 1143464ebd5Sriastradh} 1153464ebd5Sriastradh 1163464ebd5Sriastradhstatic void set_vertex_shader( void ) 1173464ebd5Sriastradh{ 1183464ebd5Sriastradh void *handle; 1193464ebd5Sriastradh const char *text = 1203464ebd5Sriastradh "VERT\n" 1213464ebd5Sriastradh "DCL IN[0]\n" 1223464ebd5Sriastradh "DCL IN[1]\n" 1233464ebd5Sriastradh "DCL OUT[0], POSITION\n" 1243464ebd5Sriastradh "DCL OUT[1], GENERIC[0]\n" 1253464ebd5Sriastradh " 0: MOV OUT[1], IN[1]\n" 1263464ebd5Sriastradh " 1: MOV OUT[0], IN[0]\n" 1273464ebd5Sriastradh " 2: END\n"; 1283464ebd5Sriastradh 1293464ebd5Sriastradh handle = graw_parse_vertex_shader(ctx, text); 1303464ebd5Sriastradh ctx->bind_vs_state(ctx, handle); 1313464ebd5Sriastradh} 1323464ebd5Sriastradh 1333464ebd5Sriastradhstatic void set_fragment_shader( void ) 1343464ebd5Sriastradh{ 1353464ebd5Sriastradh void *handle; 1363464ebd5Sriastradh const char *text = 1373464ebd5Sriastradh "FRAG\n" 1383464ebd5Sriastradh "DCL IN[0], GENERIC[0], PERSPECTIVE\n" 1393464ebd5Sriastradh "DCL OUT[0], COLOR\n" 1403464ebd5Sriastradh "DCL TEMP[0]\n" 1413464ebd5Sriastradh "DCL SAMP[0]\n" 1423464ebd5Sriastradh "DCL RES[0], 2D, FLOAT\n" 1433464ebd5Sriastradh " 0: SAMPLE TEMP[0], IN[0], RES[0], SAMP[0]\n" 1443464ebd5Sriastradh " 1: MOV OUT[0], TEMP[0]\n" 1453464ebd5Sriastradh " 2: END\n"; 1463464ebd5Sriastradh 1473464ebd5Sriastradh handle = graw_parse_fragment_shader(ctx, text); 1483464ebd5Sriastradh ctx->bind_fs_state(ctx, handle); 1493464ebd5Sriastradh} 1503464ebd5Sriastradh 1513464ebd5Sriastradh 1523464ebd5Sriastradhstatic void draw( void ) 1533464ebd5Sriastradh{ 154af69d88dSmrg union pipe_color_union clear_color = { {.5,.5,.5,1} }; 1553464ebd5Sriastradh 1567ec681f3Smrg ctx->clear(ctx, PIPE_CLEAR_COLOR, NULL, &clear_color, 0, 0); 1573464ebd5Sriastradh util_draw_arrays(ctx, PIPE_PRIM_QUADS, 0, 4); 158af69d88dSmrg ctx->flush(ctx, NULL, 0); 1593464ebd5Sriastradh 1603464ebd5Sriastradh graw_save_surface_to_file(ctx, surf, NULL); 1613464ebd5Sriastradh 1627ec681f3Smrg screen->flush_frontbuffer(screen, ctx, rttex, 0, 0, window, NULL); 1633464ebd5Sriastradh} 1643464ebd5Sriastradh 1653464ebd5Sriastradh#define SIZE 16 1663464ebd5Sriastradh 1673464ebd5Sriastradhstatic void init_tex( void ) 1683464ebd5Sriastradh{ 1693464ebd5Sriastradh struct pipe_sampler_view sv_template; 1703464ebd5Sriastradh struct pipe_sampler_state sampler_desc; 1713464ebd5Sriastradh struct pipe_resource templat; 1723464ebd5Sriastradh struct pipe_box box; 1733464ebd5Sriastradh ubyte tex2d[SIZE][SIZE][4]; 1743464ebd5Sriastradh int s, t; 1753464ebd5Sriastradh 1763464ebd5Sriastradh#if (SIZE != 2) 1773464ebd5Sriastradh for (s = 0; s < SIZE; s++) { 1783464ebd5Sriastradh for (t = 0; t < SIZE; t++) { 1793464ebd5Sriastradh if (0) { 1803464ebd5Sriastradh int x = (s ^ t) & 1; 1813464ebd5Sriastradh tex2d[t][s][0] = (x) ? 0 : 63; 1823464ebd5Sriastradh tex2d[t][s][1] = (x) ? 0 : 128; 1833464ebd5Sriastradh tex2d[t][s][2] = 0; 1843464ebd5Sriastradh tex2d[t][s][3] = 0xff; 1853464ebd5Sriastradh } 1863464ebd5Sriastradh else { 1873464ebd5Sriastradh int x = ((s ^ t) >> 2) & 1; 1883464ebd5Sriastradh tex2d[t][s][0] = s*255/(SIZE-1); 1893464ebd5Sriastradh tex2d[t][s][1] = t*255/(SIZE-1); 1903464ebd5Sriastradh tex2d[t][s][2] = (x) ? 0 : 128; 1913464ebd5Sriastradh tex2d[t][s][3] = 0xff; 1923464ebd5Sriastradh } 1933464ebd5Sriastradh } 1943464ebd5Sriastradh } 1953464ebd5Sriastradh#else 1963464ebd5Sriastradh tex2d[0][0][0] = 0; 1973464ebd5Sriastradh tex2d[0][0][1] = 255; 1983464ebd5Sriastradh tex2d[0][0][2] = 255; 1993464ebd5Sriastradh tex2d[0][0][3] = 0; 2003464ebd5Sriastradh 2013464ebd5Sriastradh tex2d[0][1][0] = 0; 2023464ebd5Sriastradh tex2d[0][1][1] = 0; 2033464ebd5Sriastradh tex2d[0][1][2] = 255; 2043464ebd5Sriastradh tex2d[0][1][3] = 255; 2053464ebd5Sriastradh 2063464ebd5Sriastradh tex2d[1][0][0] = 255; 2073464ebd5Sriastradh tex2d[1][0][1] = 255; 2083464ebd5Sriastradh tex2d[1][0][2] = 0; 2093464ebd5Sriastradh tex2d[1][0][3] = 255; 2103464ebd5Sriastradh 2113464ebd5Sriastradh tex2d[1][1][0] = 255; 2123464ebd5Sriastradh tex2d[1][1][1] = 0; 2133464ebd5Sriastradh tex2d[1][1][2] = 0; 2143464ebd5Sriastradh tex2d[1][1][3] = 255; 2153464ebd5Sriastradh#endif 2163464ebd5Sriastradh 21701e04c3fSmrg memset(&templat, 0, sizeof(templat)); 2183464ebd5Sriastradh templat.target = PIPE_TEXTURE_2D; 2193464ebd5Sriastradh templat.format = PIPE_FORMAT_B8G8R8A8_UNORM; 2203464ebd5Sriastradh templat.width0 = SIZE; 2213464ebd5Sriastradh templat.height0 = SIZE; 2223464ebd5Sriastradh templat.depth0 = 1; 2233464ebd5Sriastradh templat.last_level = 0; 2243464ebd5Sriastradh templat.bind = PIPE_BIND_SAMPLER_VIEW; 2253464ebd5Sriastradh 2263464ebd5Sriastradh 2273464ebd5Sriastradh samptex = screen->resource_create(screen, 2283464ebd5Sriastradh &templat); 2293464ebd5Sriastradh if (samptex == NULL) 2303464ebd5Sriastradh exit(4); 2313464ebd5Sriastradh 2323464ebd5Sriastradh u_box_2d(0,0,SIZE,SIZE, &box); 2333464ebd5Sriastradh 23401e04c3fSmrg ctx->texture_subdata(ctx, 23501e04c3fSmrg samptex, 23601e04c3fSmrg 0, 2377ec681f3Smrg PIPE_MAP_WRITE, 23801e04c3fSmrg &box, 23901e04c3fSmrg tex2d, 24001e04c3fSmrg sizeof tex2d[0], 24101e04c3fSmrg sizeof tex2d); 2423464ebd5Sriastradh 2433464ebd5Sriastradh /* Possibly read back & compare against original data: 2443464ebd5Sriastradh */ 2453464ebd5Sriastradh if (0) 2463464ebd5Sriastradh { 2473464ebd5Sriastradh struct pipe_transfer *t; 2483464ebd5Sriastradh uint32_t *ptr; 2497ec681f3Smrg ptr = pipe_texture_map(ctx, samptex, 250af69d88dSmrg 0, 0, /* level, layer */ 2517ec681f3Smrg PIPE_MAP_READ, 252af69d88dSmrg 0, 0, SIZE, SIZE, &t); /* x, y, width, height */ 2533464ebd5Sriastradh 2543464ebd5Sriastradh if (memcmp(ptr, tex2d, sizeof tex2d) != 0) { 2553464ebd5Sriastradh assert(0); 2563464ebd5Sriastradh exit(9); 2573464ebd5Sriastradh } 2583464ebd5Sriastradh 2597ec681f3Smrg ctx->texture_unmap(ctx, t); 2603464ebd5Sriastradh } 2613464ebd5Sriastradh 2623464ebd5Sriastradh memset(&sv_template, 0, sizeof sv_template); 2633464ebd5Sriastradh sv_template.format = samptex->format; 2643464ebd5Sriastradh sv_template.texture = samptex; 2653464ebd5Sriastradh sv_template.swizzle_r = 0; 2663464ebd5Sriastradh sv_template.swizzle_g = 1; 2673464ebd5Sriastradh sv_template.swizzle_b = 2; 2683464ebd5Sriastradh sv_template.swizzle_a = 3; 2693464ebd5Sriastradh sv = ctx->create_sampler_view(ctx, samptex, &sv_template); 2703464ebd5Sriastradh if (sv == NULL) 2713464ebd5Sriastradh exit(5); 2723464ebd5Sriastradh 2737ec681f3Smrg ctx->set_sampler_views(ctx, PIPE_SHADER_FRAGMENT, 0, 1, 0, false, &sv); 2743464ebd5Sriastradh 2753464ebd5Sriastradh 2763464ebd5Sriastradh memset(&sampler_desc, 0, sizeof sampler_desc); 2773464ebd5Sriastradh sampler_desc.wrap_s = PIPE_TEX_WRAP_REPEAT; 2783464ebd5Sriastradh sampler_desc.wrap_t = PIPE_TEX_WRAP_REPEAT; 2793464ebd5Sriastradh sampler_desc.wrap_r = PIPE_TEX_WRAP_REPEAT; 2803464ebd5Sriastradh sampler_desc.min_img_filter = PIPE_TEX_FILTER_NEAREST; 2813464ebd5Sriastradh sampler_desc.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; 2823464ebd5Sriastradh sampler_desc.mag_img_filter = PIPE_TEX_FILTER_NEAREST; 2833464ebd5Sriastradh sampler_desc.compare_mode = PIPE_TEX_COMPARE_NONE; 2843464ebd5Sriastradh sampler_desc.compare_func = 0; 2853464ebd5Sriastradh sampler_desc.normalized_coords = 1; 2863464ebd5Sriastradh sampler_desc.max_anisotropy = 0; 2873464ebd5Sriastradh 2883464ebd5Sriastradh sampler = ctx->create_sampler_state(ctx, &sampler_desc); 2893464ebd5Sriastradh if (sampler == NULL) 2903464ebd5Sriastradh exit(6); 2913464ebd5Sriastradh 292af69d88dSmrg ctx->bind_sampler_states(ctx, PIPE_SHADER_FRAGMENT, 0, 1, &sampler); 2933464ebd5Sriastradh 2943464ebd5Sriastradh} 2953464ebd5Sriastradh 2963464ebd5Sriastradhstatic void init( void ) 2973464ebd5Sriastradh{ 2983464ebd5Sriastradh struct pipe_framebuffer_state fb; 2993464ebd5Sriastradh struct pipe_resource templat; 3003464ebd5Sriastradh struct pipe_surface surf_tmpl; 3013464ebd5Sriastradh int i; 3023464ebd5Sriastradh 3033464ebd5Sriastradh /* It's hard to say whether window or screen should be created 3043464ebd5Sriastradh * first. Different environments would prefer one or the other. 3053464ebd5Sriastradh * 3063464ebd5Sriastradh * Also, no easy way of querying supported formats if the screen 3073464ebd5Sriastradh * cannot be created first. 3083464ebd5Sriastradh */ 3093464ebd5Sriastradh for (i = 0; formats[i] != PIPE_FORMAT_NONE; i++) { 3103464ebd5Sriastradh screen = graw_create_window_and_screen(0, 0, 300, 300, 3113464ebd5Sriastradh formats[i], 3123464ebd5Sriastradh &window); 3133464ebd5Sriastradh if (window && screen) 3143464ebd5Sriastradh break; 3153464ebd5Sriastradh } 3163464ebd5Sriastradh if (!screen || !window) { 3173464ebd5Sriastradh fprintf(stderr, "Unable to create window\n"); 3183464ebd5Sriastradh exit(1); 3193464ebd5Sriastradh } 3203464ebd5Sriastradh 32101e04c3fSmrg ctx = screen->context_create(screen, NULL, 0); 3223464ebd5Sriastradh if (ctx == NULL) 3233464ebd5Sriastradh exit(3); 3243464ebd5Sriastradh 32501e04c3fSmrg memset(&templat, 0, sizeof(templat)); 3263464ebd5Sriastradh templat.target = PIPE_TEXTURE_2D; 3273464ebd5Sriastradh templat.format = formats[i]; 3283464ebd5Sriastradh templat.width0 = WIDTH; 3293464ebd5Sriastradh templat.height0 = HEIGHT; 3303464ebd5Sriastradh templat.depth0 = 1; 3313464ebd5Sriastradh templat.array_size = 1; 3323464ebd5Sriastradh templat.last_level = 0; 3333464ebd5Sriastradh templat.bind = (PIPE_BIND_RENDER_TARGET | 3343464ebd5Sriastradh PIPE_BIND_DISPLAY_TARGET); 3353464ebd5Sriastradh 3363464ebd5Sriastradh rttex = screen->resource_create(screen, 3373464ebd5Sriastradh &templat); 3383464ebd5Sriastradh if (rttex == NULL) 3393464ebd5Sriastradh exit(4); 3403464ebd5Sriastradh 3413464ebd5Sriastradh surf_tmpl.format = templat.format; 3423464ebd5Sriastradh surf_tmpl.u.tex.level = 0; 3433464ebd5Sriastradh surf_tmpl.u.tex.first_layer = 0; 3443464ebd5Sriastradh surf_tmpl.u.tex.last_layer = 0; 3453464ebd5Sriastradh surf = ctx->create_surface(ctx, rttex, &surf_tmpl); 3463464ebd5Sriastradh if (surf == NULL) 3473464ebd5Sriastradh exit(5); 3483464ebd5Sriastradh 3493464ebd5Sriastradh memset(&fb, 0, sizeof fb); 3503464ebd5Sriastradh fb.nr_cbufs = 1; 3513464ebd5Sriastradh fb.width = WIDTH; 3523464ebd5Sriastradh fb.height = HEIGHT; 3533464ebd5Sriastradh fb.cbufs[0] = surf; 3543464ebd5Sriastradh 3553464ebd5Sriastradh ctx->set_framebuffer_state(ctx, &fb); 3563464ebd5Sriastradh 3573464ebd5Sriastradh { 3583464ebd5Sriastradh struct pipe_blend_state blend; 3593464ebd5Sriastradh void *handle; 3603464ebd5Sriastradh memset(&blend, 0, sizeof blend); 3613464ebd5Sriastradh blend.rt[0].colormask = PIPE_MASK_RGBA; 3623464ebd5Sriastradh handle = ctx->create_blend_state(ctx, &blend); 3633464ebd5Sriastradh ctx->bind_blend_state(ctx, handle); 3643464ebd5Sriastradh } 3653464ebd5Sriastradh 3663464ebd5Sriastradh { 3673464ebd5Sriastradh struct pipe_depth_stencil_alpha_state depthstencil; 3683464ebd5Sriastradh void *handle; 3693464ebd5Sriastradh memset(&depthstencil, 0, sizeof depthstencil); 3703464ebd5Sriastradh handle = ctx->create_depth_stencil_alpha_state(ctx, &depthstencil); 3713464ebd5Sriastradh ctx->bind_depth_stencil_alpha_state(ctx, handle); 3723464ebd5Sriastradh } 3733464ebd5Sriastradh 3743464ebd5Sriastradh { 3753464ebd5Sriastradh struct pipe_rasterizer_state rasterizer; 3763464ebd5Sriastradh void *handle; 3773464ebd5Sriastradh memset(&rasterizer, 0, sizeof rasterizer); 3783464ebd5Sriastradh rasterizer.cull_face = PIPE_FACE_NONE; 379af69d88dSmrg rasterizer.half_pixel_center = 1; 380af69d88dSmrg rasterizer.bottom_edge_rule = 1; 38101e04c3fSmrg rasterizer.depth_clip_near = 1; 38201e04c3fSmrg rasterizer.depth_clip_far = 1; 3833464ebd5Sriastradh handle = ctx->create_rasterizer_state(ctx, &rasterizer); 3843464ebd5Sriastradh ctx->bind_rasterizer_state(ctx, handle); 3853464ebd5Sriastradh } 3863464ebd5Sriastradh 3873464ebd5Sriastradh set_viewport(0, 0, WIDTH, HEIGHT, 30, 1000); 3883464ebd5Sriastradh 3893464ebd5Sriastradh init_tex(); 3903464ebd5Sriastradh 3913464ebd5Sriastradh set_vertices(); 3923464ebd5Sriastradh set_vertex_shader(); 3933464ebd5Sriastradh set_fragment_shader(); 3943464ebd5Sriastradh} 3953464ebd5Sriastradh 3963464ebd5Sriastradhstatic void args(int argc, char *argv[]) 3973464ebd5Sriastradh{ 3983464ebd5Sriastradh int i; 3993464ebd5Sriastradh 4003464ebd5Sriastradh for (i = 1; i < argc;) { 4013464ebd5Sriastradh if (graw_parse_args(&i, argc, argv)) { 4023464ebd5Sriastradh continue; 4033464ebd5Sriastradh } 4043464ebd5Sriastradh exit(1); 4053464ebd5Sriastradh } 4063464ebd5Sriastradh} 4073464ebd5Sriastradh 4083464ebd5Sriastradh 4093464ebd5Sriastradhint main( int argc, char *argv[] ) 4103464ebd5Sriastradh{ 4113464ebd5Sriastradh args(argc, argv); 4123464ebd5Sriastradh init(); 4133464ebd5Sriastradh 4143464ebd5Sriastradh graw_set_display_func( draw ); 4153464ebd5Sriastradh graw_main_loop(); 4163464ebd5Sriastradh return 0; 4173464ebd5Sriastradh} 418