• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
usage(char * name)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 
init_fs_constbuf(void)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 
set_viewport(float x,float y,float width,float height,float near,float far)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 
set_vertices(void)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 
set_vertex_shader(void)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 
set_fragment_shader(void)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 
set_geometry_shader(void)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 
draw(void)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 
init_tex(void)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 
init(void)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 
args(int argc,char * argv[])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 
main(int argc,char * argv[])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 }
629