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