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