update to 9.0.3
[profile/ivi/mesa.git] / src / gallium / tests / graw / gs-test.c
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 }