• 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 "frontend/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 
153    memset(&templat, 0, sizeof(templat));
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.bind = PIPE_BIND_CONSTANT_BUFFER;
162 
163    constbuf1 = screen->resource_create(screen, &templat);
164    if (constbuf1 == NULL)
165       exit(4);
166    constbuf2 = screen->resource_create(screen, &templat);
167    if (constbuf2 == NULL)
168       exit(4);
169 
170    {
171       ctx->buffer_subdata(ctx, constbuf1,
172                           PIPE_MAP_WRITE,
173                           0, sizeof(constants1), constants1);
174 
175       pipe_set_constant_buffer(ctx,
176                                PIPE_SHADER_GEOMETRY, 0,
177                                constbuf1);
178    }
179    {
180       ctx->buffer_subdata(ctx, constbuf2,
181                           PIPE_MAP_WRITE,
182                           0, sizeof(constants2), constants2);
183 
184       pipe_set_constant_buffer(ctx,
185                                PIPE_SHADER_GEOMETRY, 1,
186                                constbuf2);
187    }
188 }
189 
190 
set_viewport(float x,float y,float width,float height,float zNear,float zFar)191 static void set_viewport( float x, float y,
192                           float width, float height,
193                           float zNear, float zFar)
194 {
195    float z = zFar;
196    float half_width = (float)width / 2.0f;
197    float half_height = (float)height / 2.0f;
198    float half_depth = ((float)zFar - (float)zNear) / 2.0f;
199    struct pipe_viewport_state vp;
200 
201    vp.scale[0] = half_width;
202    vp.scale[1] = half_height;
203    vp.scale[2] = half_depth;
204 
205    vp.translate[0] = half_width + x;
206    vp.translate[1] = half_height + y;
207    vp.translate[2] = half_depth + z;
208 
209    ctx->set_viewport_states( ctx, 0, 1, &vp );
210 }
211 
set_vertices(void)212 static void set_vertices( void )
213 {
214    struct pipe_vertex_element ve[4];
215    struct pipe_vertex_buffer vbuf;
216    void *handle;
217 
218    memset(ve, 0, sizeof ve);
219 
220    ve[0].src_offset = Offset(struct vertex, position);
221    ve[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
222    ve[1].src_offset = Offset(struct vertex, color);
223    ve[1].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
224    ve[2].src_offset = Offset(struct vertex, texcoord);
225    ve[2].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
226    ve[3].src_offset = Offset(struct vertex, generic);
227    ve[3].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
228 
229    handle = ctx->create_vertex_elements_state(ctx, 4, ve);
230    ctx->bind_vertex_elements_state(ctx, handle);
231 
232    memset(&vbuf, 0, sizeof vbuf);
233 
234    vbuf.stride = sizeof( struct vertex );
235    vbuf.buffer_offset = 0;
236    if (draw_strip) {
237       vbuf.buffer.resource = pipe_buffer_create_with_data(ctx,
238                                                  PIPE_BIND_VERTEX_BUFFER,
239                                                  PIPE_USAGE_DEFAULT,
240                                                  sizeof(vertices_strip),
241                                                  vertices_strip);
242    } else {
243       vbuf.buffer.resource = pipe_buffer_create_with_data(ctx,
244                                                  PIPE_BIND_VERTEX_BUFFER,
245                                                  PIPE_USAGE_DEFAULT,
246                                                  sizeof(vertices),
247                                                  vertices);
248    }
249 
250    ctx->set_vertex_buffers(ctx, 0, 1, &vbuf);
251 }
252 
set_vertex_shader(void)253 static void set_vertex_shader( void )
254 {
255    void *handle;
256    const char *text =
257       "VERT\n"
258       "DCL IN[0]\n"
259       "DCL IN[1]\n"
260       "DCL IN[2]\n"
261       "DCL IN[3]\n"
262       "DCL OUT[0], POSITION\n"
263       "DCL OUT[1], COLOR[0]\n"
264       "DCL OUT[2], GENERIC[0]\n"
265       "DCL OUT[3], GENERIC[1]\n"
266       "  MOV OUT[0], IN[0]\n"
267       "  MOV OUT[1], IN[1]\n"
268       "  MOV OUT[2], IN[2]\n"
269       "  MOV OUT[3], IN[3]\n"
270       "  END\n";
271 
272    handle = graw_parse_vertex_shader(ctx, text);
273    ctx->bind_vs_state(ctx, handle);
274 }
275 
set_fragment_shader(void)276 static void set_fragment_shader( void )
277 {
278    void *handle;
279    const char *text =
280       "FRAG\n"
281       "DCL IN[0], COLOR, LINEAR\n"
282       "DCL OUT[0], COLOR\n"
283       "  0: MOV OUT[0], IN[0]\n"
284       "  1: END\n";
285 
286    handle = graw_parse_fragment_shader(ctx, text);
287    ctx->bind_fs_state(ctx, handle);
288 }
289 
290 
set_geometry_shader(void)291 static void set_geometry_shader( void )
292 {
293    FILE *f;
294    char buf[50000];
295    void *handle;
296    int sz;
297 
298    if ((f = fopen(filename, "r")) == NULL) {
299       fprintf(stderr, "Couldn't open %s\n", filename);
300       exit(1);
301    }
302 
303    sz = fread(buf, 1, sizeof(buf), f);
304    if (!feof(f)) {
305       printf("file too long\n");
306       exit(1);
307    }
308    printf("%.*s\n", sz, buf);
309    buf[sz] = 0;
310 
311    handle = graw_parse_geometry_shader(ctx, buf);
312    ctx->bind_gs_state(ctx, handle);
313    fclose(f);
314 }
315 
316 
draw(void)317 static void draw( void )
318 {
319    union pipe_color_union clear_color = { {.1,.3,.5,0} };
320 
321    ctx->clear(ctx, PIPE_CLEAR_COLOR, NULL, &clear_color, 0, 0);
322    if (draw_strip)
323       util_draw_arrays(ctx, PIPE_PRIM_TRIANGLE_STRIP, 0, 4);
324    else
325       util_draw_arrays(ctx, PIPE_PRIM_TRIANGLES, 0, 3);
326 
327    ctx->flush(ctx, NULL, 0);
328 
329    graw_save_surface_to_file(ctx, surf, NULL);
330 
331    screen->flush_frontbuffer(screen, rttex, 0, 0, window, NULL);
332 }
333 
334 #define SIZE 16
335 
init_tex(void)336 static void init_tex( void )
337 {
338    struct pipe_sampler_view sv_template;
339    struct pipe_sampler_state sampler_desc;
340    struct pipe_resource templat;
341    struct pipe_box box;
342    ubyte tex2d[SIZE][SIZE][4];
343    int s, t;
344 
345 #if (SIZE != 2)
346    for (s = 0; s < SIZE; s++) {
347       for (t = 0; t < SIZE; t++) {
348          if (0) {
349             int x = (s ^ t) & 1;
350 	    tex2d[t][s][0] = (x) ? 0 : 63;
351 	    tex2d[t][s][1] = (x) ? 0 : 128;
352 	    tex2d[t][s][2] = 0;
353 	    tex2d[t][s][3] = 0xff;
354          }
355          else {
356             int x = ((s ^ t) >> 2) & 1;
357 	    tex2d[t][s][0] = s*255/(SIZE-1);
358 	    tex2d[t][s][1] = t*255/(SIZE-1);
359 	    tex2d[t][s][2] = (x) ? 0 : 128;
360 	    tex2d[t][s][3] = 0xff;
361          }
362       }
363    }
364 #else
365    tex2d[0][0][0] = 0;
366    tex2d[0][0][1] = 255;
367    tex2d[0][0][2] = 255;
368    tex2d[0][0][3] = 0;
369 
370    tex2d[0][1][0] = 0;
371    tex2d[0][1][1] = 0;
372    tex2d[0][1][2] = 255;
373    tex2d[0][1][3] = 255;
374 
375    tex2d[1][0][0] = 255;
376    tex2d[1][0][1] = 255;
377    tex2d[1][0][2] = 0;
378    tex2d[1][0][3] = 255;
379 
380    tex2d[1][1][0] = 255;
381    tex2d[1][1][1] = 0;
382    tex2d[1][1][2] = 0;
383    tex2d[1][1][3] = 255;
384 #endif
385 
386    memset(&templat, 0, sizeof(templat));
387    templat.target = PIPE_TEXTURE_2D;
388    templat.format = PIPE_FORMAT_B8G8R8A8_UNORM;
389    templat.width0 = SIZE;
390    templat.height0 = SIZE;
391    templat.depth0 = 1;
392    templat.array_size = 1;
393    templat.last_level = 0;
394    templat.bind = PIPE_BIND_SAMPLER_VIEW;
395 
396 
397    samptex = screen->resource_create(screen,
398                                  &templat);
399    if (samptex == NULL)
400       exit(4);
401 
402    u_box_2d(0,0,SIZE,SIZE, &box);
403 
404    ctx->texture_subdata(ctx,
405                         samptex,
406                         0,
407                         PIPE_MAP_WRITE,
408                         &box,
409                         tex2d,
410                         sizeof tex2d[0],
411          sizeof tex2d);
412 
413    /* Possibly read back & compare against original data:
414     */
415    if (0)
416    {
417       struct pipe_transfer *t;
418       uint32_t *ptr;
419       ptr = pipe_transfer_map(ctx, samptex,
420                               0, 0, /* level, layer */
421                               PIPE_MAP_READ,
422                               0, 0, SIZE, SIZE, &t); /* x, y, width, height */
423 
424       if (memcmp(ptr, tex2d, sizeof tex2d) != 0) {
425          assert(0);
426          exit(9);
427       }
428 
429       ctx->transfer_unmap(ctx, t);
430    }
431 
432    memset(&sv_template, 0, sizeof sv_template);
433    sv_template.format = samptex->format;
434    sv_template.texture = samptex;
435    sv_template.swizzle_r = 0;
436    sv_template.swizzle_g = 1;
437    sv_template.swizzle_b = 2;
438    sv_template.swizzle_a = 3;
439    sv = ctx->create_sampler_view(ctx, samptex, &sv_template);
440    if (sv == NULL)
441       exit(5);
442 
443    ctx->set_sampler_views(ctx, PIPE_SHADER_FRAGMENT, 0, 1, &sv);
444 
445 
446    memset(&sampler_desc, 0, sizeof sampler_desc);
447    sampler_desc.wrap_s = PIPE_TEX_WRAP_REPEAT;
448    sampler_desc.wrap_t = PIPE_TEX_WRAP_REPEAT;
449    sampler_desc.wrap_r = PIPE_TEX_WRAP_REPEAT;
450    sampler_desc.min_img_filter = PIPE_TEX_FILTER_NEAREST;
451    sampler_desc.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
452    sampler_desc.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
453    sampler_desc.compare_mode = PIPE_TEX_COMPARE_NONE;
454    sampler_desc.compare_func = 0;
455    sampler_desc.normalized_coords = 1;
456    sampler_desc.max_anisotropy = 0;
457 
458    sampler = ctx->create_sampler_state(ctx, &sampler_desc);
459    if (sampler == NULL)
460       exit(6);
461 
462    ctx->bind_sampler_states(ctx, PIPE_SHADER_FRAGMENT, 0, 1, &sampler);
463 
464 }
465 
init(void)466 static void init( void )
467 {
468    struct pipe_framebuffer_state fb;
469    struct pipe_resource templat;
470    struct pipe_surface surf_tmpl;
471    int i;
472 
473    /* It's hard to say whether window or screen should be created
474     * first.  Different environments would prefer one or the other.
475     *
476     * Also, no easy way of querying supported formats if the screen
477     * cannot be created first.
478     */
479    for (i = 0; formats[i] != PIPE_FORMAT_NONE; i++) {
480       screen = graw_create_window_and_screen(0, 0, 300, 300,
481                                              formats[i],
482                                              &window);
483       if (window && screen)
484          break;
485    }
486    if (!screen || !window) {
487       fprintf(stderr, "Unable to create window\n");
488       exit(1);
489    }
490 
491    ctx = screen->context_create(screen, NULL, 0);
492    if (ctx == NULL)
493       exit(3);
494 
495    memset(&templat, 0, sizeof(templat));
496    templat.target = PIPE_TEXTURE_2D;
497    templat.format = formats[i];
498    templat.width0 = WIDTH;
499    templat.height0 = HEIGHT;
500    templat.depth0 = 1;
501    templat.array_size = 1;
502    templat.last_level = 0;
503    templat.bind = (PIPE_BIND_RENDER_TARGET |
504                    PIPE_BIND_DISPLAY_TARGET);
505 
506    rttex = screen->resource_create(screen,
507                                  &templat);
508    if (rttex == NULL)
509       exit(4);
510 
511    surf_tmpl.format = templat.format;
512    surf_tmpl.u.tex.level = 0;
513    surf_tmpl.u.tex.first_layer = 0;
514    surf_tmpl.u.tex.last_layer = 0;
515    surf = ctx->create_surface(ctx, rttex, &surf_tmpl);
516    if (surf == NULL)
517       exit(5);
518 
519    memset(&fb, 0, sizeof fb);
520    fb.nr_cbufs = 1;
521    fb.width = WIDTH;
522    fb.height = HEIGHT;
523    fb.cbufs[0] = surf;
524 
525    ctx->set_framebuffer_state(ctx, &fb);
526 
527    {
528       struct pipe_blend_state blend;
529       void *handle;
530       memset(&blend, 0, sizeof blend);
531       blend.rt[0].colormask = PIPE_MASK_RGBA;
532       handle = ctx->create_blend_state(ctx, &blend);
533       ctx->bind_blend_state(ctx, handle);
534    }
535 
536    {
537       struct pipe_depth_stencil_alpha_state depthstencil;
538       void *handle;
539       memset(&depthstencil, 0, sizeof depthstencil);
540       handle = ctx->create_depth_stencil_alpha_state(ctx, &depthstencil);
541       ctx->bind_depth_stencil_alpha_state(ctx, handle);
542    }
543 
544    {
545       struct pipe_rasterizer_state rasterizer;
546       void *handle;
547       memset(&rasterizer, 0, sizeof rasterizer);
548       rasterizer.cull_face = PIPE_FACE_NONE;
549       rasterizer.half_pixel_center = 1;
550       rasterizer.bottom_edge_rule = 1;
551       rasterizer.depth_clip_near = 1;
552       rasterizer.depth_clip_far = 1;
553       handle = ctx->create_rasterizer_state(ctx, &rasterizer);
554       ctx->bind_rasterizer_state(ctx, handle);
555    }
556 
557    set_viewport(0, 0, WIDTH, HEIGHT, 30, 1000);
558 
559    init_tex();
560    init_fs_constbuf();
561 
562    set_vertices();
563    set_vertex_shader();
564    set_fragment_shader();
565    set_geometry_shader();
566 }
567 
args(int argc,char * argv[])568 static void args(int argc, char *argv[])
569 {
570    int i;
571 
572    for (i = 1; i < argc;) {
573       if (graw_parse_args(&i, argc, argv)) {
574          continue;
575       }
576       if (strcmp(argv[i], "-fps") == 0) {
577          show_fps = 1;
578          i++;
579       }
580       else if (strcmp(argv[i], "-strip") == 0) {
581          draw_strip = 1;
582          i++;
583       }
584       else if (i == argc - 1) {
585          filename = argv[i];
586          i++;
587       }
588       else {
589          usage(argv[0]);
590          exit(1);
591       }
592    }
593 
594    if (!filename) {
595       usage(argv[0]);
596       exit(1);
597    }
598 }
599 
main(int argc,char * argv[])600 int main( int argc, char *argv[] )
601 {
602    args(argc,argv);
603    init();
604 
605    graw_set_display_func( draw );
606    graw_main_loop();
607    return 0;
608 }
609