Tizen 2.0 Release
[profile/ivi/osmesa.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       ctx->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       ctx->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 = screen->user_buffer_create(screen,
255                                                vertices_strip,
256                                                sizeof(vertices_strip),
257                                                PIPE_BIND_VERTEX_BUFFER);
258    } else {
259       vbuf.buffer = screen->user_buffer_create(screen,
260                                                vertices,
261                                                sizeof(vertices),
262                                                PIPE_BIND_VERTEX_BUFFER);
263    }
264
265    ctx->set_vertex_buffers(ctx, 1, &vbuf);
266 }
267
268 static void set_vertex_shader( void )
269 {
270    void *handle;
271    const char *text =
272       "VERT\n"
273       "DCL IN[0]\n"
274       "DCL IN[1]\n"
275       "DCL IN[2]\n"
276       "DCL IN[3]\n"
277       "DCL OUT[0], POSITION\n"
278       "DCL OUT[1], COLOR[0]\n"
279       "DCL OUT[2], GENERIC[0]\n"
280       "DCL OUT[3], GENERIC[1]\n"
281       "  MOV OUT[0], IN[0]\n"
282       "  MOV OUT[1], IN[1]\n"
283       "  MOV OUT[2], IN[2]\n"
284       "  MOV OUT[3], IN[3]\n"
285       "  END\n";
286
287    handle = graw_parse_vertex_shader(ctx, text);
288    ctx->bind_vs_state(ctx, handle);
289 }
290
291 static void set_fragment_shader( void )
292 {
293    void *handle;
294    const char *text =
295       "FRAG\n"
296       "DCL IN[0], COLOR, LINEAR\n"
297       "DCL OUT[0], COLOR\n"
298       "  0: MOV OUT[0], IN[0]\n"
299       "  1: END\n";
300
301    handle = graw_parse_fragment_shader(ctx, text);
302    ctx->bind_fs_state(ctx, handle);
303 }
304
305
306 static void set_geometry_shader( void )
307 {
308    FILE *f;
309    char buf[50000];
310    void *handle;
311    int sz;
312
313    if ((f = fopen(filename, "r")) == NULL) {
314       fprintf(stderr, "Couldn't open %s\n", filename);
315       exit(1);
316    }
317
318    sz = fread(buf, 1, sizeof(buf), f);
319    if (!feof(f)) {
320       printf("file too long\n");
321       exit(1);
322    }
323    printf("%.*s\n", sz, buf);
324    buf[sz] = 0;
325
326    handle = graw_parse_geometry_shader(ctx, buf);
327    ctx->bind_gs_state(ctx, handle);
328    fclose(f);
329 }
330
331
332 static void draw( void )
333 {
334    float clear_color[4] = {.1,.3,.5,0};
335
336    ctx->clear(ctx, PIPE_CLEAR_COLOR, clear_color, 0, 0);
337    if (draw_strip)
338       util_draw_arrays(ctx, PIPE_PRIM_TRIANGLE_STRIP, 0, 4);
339    else
340       util_draw_arrays(ctx, PIPE_PRIM_TRIANGLES, 0, 3);
341
342    ctx->flush(ctx, NULL);
343
344    graw_save_surface_to_file(ctx, surf, NULL);
345
346    screen->flush_frontbuffer(screen, rttex, 0, 0, window);
347 }
348
349 #define SIZE 16
350
351 static void init_tex( void )
352
353    struct pipe_sampler_view sv_template;
354    struct pipe_sampler_state sampler_desc;
355    struct pipe_resource templat;
356    struct pipe_box box;
357    ubyte tex2d[SIZE][SIZE][4];
358    int s, t;
359
360 #if (SIZE != 2)
361    for (s = 0; s < SIZE; s++) {
362       for (t = 0; t < SIZE; t++) {
363          if (0) {
364             int x = (s ^ t) & 1;
365             tex2d[t][s][0] = (x) ? 0 : 63;
366             tex2d[t][s][1] = (x) ? 0 : 128;
367             tex2d[t][s][2] = 0;
368             tex2d[t][s][3] = 0xff;
369          }
370          else {
371             int x = ((s ^ t) >> 2) & 1;
372             tex2d[t][s][0] = s*255/(SIZE-1);
373             tex2d[t][s][1] = t*255/(SIZE-1);
374             tex2d[t][s][2] = (x) ? 0 : 128;
375             tex2d[t][s][3] = 0xff;
376          }
377       }
378    }
379 #else
380    tex2d[0][0][0] = 0;
381    tex2d[0][0][1] = 255;
382    tex2d[0][0][2] = 255;
383    tex2d[0][0][3] = 0;
384
385    tex2d[0][1][0] = 0;
386    tex2d[0][1][1] = 0;
387    tex2d[0][1][2] = 255;
388    tex2d[0][1][3] = 255;
389
390    tex2d[1][0][0] = 255;
391    tex2d[1][0][1] = 255;
392    tex2d[1][0][2] = 0;
393    tex2d[1][0][3] = 255;
394
395    tex2d[1][1][0] = 255;
396    tex2d[1][1][1] = 0;
397    tex2d[1][1][2] = 0;
398    tex2d[1][1][3] = 255;
399 #endif
400
401    templat.target = PIPE_TEXTURE_2D;
402    templat.format = PIPE_FORMAT_B8G8R8A8_UNORM;
403    templat.width0 = SIZE;
404    templat.height0 = SIZE;
405    templat.depth0 = 1;
406    templat.array_size = 1;
407    templat.last_level = 0;
408    templat.nr_samples = 1;
409    templat.bind = PIPE_BIND_SAMPLER_VIEW;
410
411    
412    samptex = screen->resource_create(screen,
413                                  &templat);
414    if (samptex == NULL)
415       exit(4);
416
417    u_box_2d(0,0,SIZE,SIZE, &box);
418
419    ctx->transfer_inline_write(ctx,
420                               samptex,
421                               0,
422                               PIPE_TRANSFER_WRITE,
423                               &box,
424                               tex2d,
425                               sizeof tex2d[0],
426                               sizeof tex2d);
427
428    /* Possibly read back & compare against original data:
429     */
430    if (0)
431    {
432       struct pipe_transfer *t;
433       uint32_t *ptr;
434       t = pipe_get_transfer(ctx, samptex,
435                             0, 0, /* level, layer */
436                             PIPE_TRANSFER_READ,
437                             0, 0, SIZE, SIZE); /* x, y, width, height */
438
439       ptr = ctx->transfer_map(ctx, t);
440
441       if (memcmp(ptr, tex2d, sizeof tex2d) != 0) {
442          assert(0);
443          exit(9);
444       }
445
446       ctx->transfer_unmap(ctx, t);
447
448       ctx->transfer_destroy(ctx, t);
449    }
450
451    memset(&sv_template, 0, sizeof sv_template);
452    sv_template.format = samptex->format;
453    sv_template.texture = samptex;
454    sv_template.swizzle_r = 0;
455    sv_template.swizzle_g = 1;
456    sv_template.swizzle_b = 2;
457    sv_template.swizzle_a = 3;
458    sv = ctx->create_sampler_view(ctx, samptex, &sv_template);
459    if (sv == NULL)
460       exit(5);
461
462    ctx->set_fragment_sampler_views(ctx, 1, &sv);
463    
464
465    memset(&sampler_desc, 0, sizeof sampler_desc);
466    sampler_desc.wrap_s = PIPE_TEX_WRAP_REPEAT;
467    sampler_desc.wrap_t = PIPE_TEX_WRAP_REPEAT;
468    sampler_desc.wrap_r = PIPE_TEX_WRAP_REPEAT;
469    sampler_desc.min_img_filter = PIPE_TEX_FILTER_NEAREST;
470    sampler_desc.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
471    sampler_desc.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
472    sampler_desc.compare_mode = PIPE_TEX_COMPARE_NONE;
473    sampler_desc.compare_func = 0;
474    sampler_desc.normalized_coords = 1;
475    sampler_desc.max_anisotropy = 0;
476    
477    sampler = ctx->create_sampler_state(ctx, &sampler_desc);
478    if (sampler == NULL)
479       exit(6);
480
481    ctx->bind_fragment_sampler_states(ctx, 1, &sampler);
482    
483 }
484
485 static void init( void )
486 {
487    struct pipe_framebuffer_state fb;
488    struct pipe_resource templat;
489    struct pipe_surface surf_tmpl;
490    int i;
491
492    /* It's hard to say whether window or screen should be created
493     * first.  Different environments would prefer one or the other.
494     *
495     * Also, no easy way of querying supported formats if the screen
496     * cannot be created first.
497     */
498    for (i = 0; formats[i] != PIPE_FORMAT_NONE; i++) {
499       screen = graw_create_window_and_screen(0, 0, 300, 300,
500                                              formats[i],
501                                              &window);
502       if (window && screen)
503          break;
504    }
505    if (!screen || !window) {
506       fprintf(stderr, "Unable to create window\n");
507       exit(1);
508    }
509
510    ctx = screen->context_create(screen, NULL);
511    if (ctx == NULL)
512       exit(3);
513
514    templat.target = PIPE_TEXTURE_2D;
515    templat.format = formats[i];
516    templat.width0 = WIDTH;
517    templat.height0 = HEIGHT;
518    templat.depth0 = 1;
519    templat.array_size = 1;
520    templat.last_level = 0;
521    templat.nr_samples = 1;
522    templat.bind = (PIPE_BIND_RENDER_TARGET |
523                    PIPE_BIND_DISPLAY_TARGET);
524    
525    rttex = screen->resource_create(screen,
526                                  &templat);
527    if (rttex == NULL)
528       exit(4);
529
530    surf_tmpl.format = templat.format;
531    surf_tmpl.usage = PIPE_BIND_RENDER_TARGET;
532    surf_tmpl.u.tex.level = 0;
533    surf_tmpl.u.tex.first_layer = 0;
534    surf_tmpl.u.tex.last_layer = 0;
535    surf = ctx->create_surface(ctx, rttex, &surf_tmpl);
536    if (surf == NULL)
537       exit(5);
538
539    memset(&fb, 0, sizeof fb);
540    fb.nr_cbufs = 1;
541    fb.width = WIDTH;
542    fb.height = HEIGHT;
543    fb.cbufs[0] = surf;
544
545    ctx->set_framebuffer_state(ctx, &fb);
546    
547    {
548       struct pipe_blend_state blend;
549       void *handle;
550       memset(&blend, 0, sizeof blend);
551       blend.rt[0].colormask = PIPE_MASK_RGBA;
552       handle = ctx->create_blend_state(ctx, &blend);
553       ctx->bind_blend_state(ctx, handle);
554    }
555
556    {
557       struct pipe_depth_stencil_alpha_state depthstencil;
558       void *handle;
559       memset(&depthstencil, 0, sizeof depthstencil);
560       handle = ctx->create_depth_stencil_alpha_state(ctx, &depthstencil);
561       ctx->bind_depth_stencil_alpha_state(ctx, handle);
562    }
563
564    {
565       struct pipe_rasterizer_state rasterizer;
566       void *handle;
567       memset(&rasterizer, 0, sizeof rasterizer);
568       rasterizer.cull_face = PIPE_FACE_NONE;
569       rasterizer.gl_rasterization_rules = 1;
570       handle = ctx->create_rasterizer_state(ctx, &rasterizer);
571       ctx->bind_rasterizer_state(ctx, handle);
572    }
573
574    set_viewport(0, 0, WIDTH, HEIGHT, 30, 1000);
575
576    init_tex();
577    init_fs_constbuf();
578
579    set_vertices();
580    set_vertex_shader();
581    set_fragment_shader();
582    set_geometry_shader();
583 }
584
585 static void args(int argc, char *argv[])
586 {
587    int i;
588
589    for (i = 1; i < argc;) {
590       if (graw_parse_args(&i, argc, argv)) {
591          continue;
592       }
593       if (strcmp(argv[i], "-fps") == 0) {
594          show_fps = 1;
595          i++;
596       }
597       else if (strcmp(argv[i], "-strip") == 0) {
598          draw_strip = 1;
599          i++;
600       }
601       else if (i == argc - 1) {
602          filename = argv[i];
603          i++;
604       }
605       else {
606          usage(argv[0]);
607          exit(1);
608       }
609    }
610
611    if (!filename) {
612       usage(argv[0]);
613       exit(1);
614    }
615 }
616
617 int main( int argc, char *argv[] )
618 {
619    args(argc,argv);
620    init();
621
622    graw_set_display_func( draw );
623    graw_main_loop();
624    return 0;
625 }