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