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 
usage(char * name)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_RGBA8888_UNORM,
35    PIPE_FORMAT_BGRA8888_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_surface *surf = NULL;
46 static struct pipe_sampler_view *sv = NULL;
47 static void *sampler = NULL;
48 static void *window = NULL;
49 static struct pipe_resource *samptex = NULL;
50 
51 struct vertex {
52    float position[4];
53    float color[4];
54    float texcoord[4];
55 };
56 
57 /* Vertex data matches progs/fp/fp-tri.c, but flipped in Y dimension
58  * so that the final images are the same.
59  */
60 static struct vertex vertices[] =
61 {
62    { { 0.9, 0.9, 0.0, 1.0 },
63      { 0, 0, 1, 1 },
64      { 1, 1, 0, 1 } },
65 
66    { { 0.9,  -0.9, 0.0, 1.0 },
67      { 1, 0, 0, 1 },
68      { 1, -1, 0, 1 } },
69 
70    { {-0.9,  0.0, 0.0, 1.0 },
71      { 0, 1, 0, 1 },
72      { -1, 0, 0, 1 } },
73 };
74 
75 static float constants1[] =
76 {  0.4, 0, 0,  1,
77    1,   1, 1,  1,
78    2,   2, 2,  2,
79    4,   8, 16, 32,
80 
81    3,  0, 0, 0,
82    0, .5, 0, 0,
83    1,  0, 0, 1,
84    0,  0, 0, 1,
85 
86    1, 0, 0, 0.5,
87    0, 1, 0, 0.5,
88    0, 0, 1, 0,
89    0, 0, 0, 1,
90 };
91 
92 
93 static float constants2[] =
94 {  1, 0, 0,  1,
95    0, 1, 0,  1,
96    0, 0, 1,  1,
97    0, 0, 0,  0,
98 
99    1,  1, 0, 1,
100    1, .5, 0, 1,
101    1,  0, 0, 1,
102    0,  0, 0, 1,
103 
104    1, 0, 0, 0.5,
105    0, 1, 0, 0.5,
106    0, 0, 1, 0,
107    0, 0, 0, 1,
108 };
109 
init_fs_constbuf(void)110 static void init_fs_constbuf( void )
111 {
112    struct pipe_constant_buffer cb1;
113    struct pipe_constant_buffer cb2;
114 
115    memset(&cb1, 0, sizeof cb1);
116    cb1.buffer_size = sizeof constants1;
117    cb1.user_buffer = constants1;
118 
119    ctx->set_constant_buffer(ctx,
120                             PIPE_SHADER_FRAGMENT, 0,
121                             &cb1);
122 
123    memset(&cb2, 0, sizeof cb2);
124    cb2.buffer_size = sizeof constants2;
125    cb2.user_buffer = constants2;
126 
127    ctx->set_constant_buffer(ctx,
128                             PIPE_SHADER_FRAGMENT, 1,
129                             &cb2);
130 }
131 
132 
set_viewport(float x,float y,float width,float height,float zNear,float zFar)133 static void set_viewport( float x, float y,
134                           float width, float height,
135                           float zNear, float zFar)
136 {
137    float z = zFar;
138    float half_width = (float)width / 2.0f;
139    float half_height = (float)height / 2.0f;
140    float half_depth = ((float)zFar - (float)zNear) / 2.0f;
141    struct pipe_viewport_state vp;
142 
143    vp.scale[0] = half_width;
144    vp.scale[1] = half_height;
145    vp.scale[2] = half_depth;
146 
147    vp.translate[0] = half_width + x;
148    vp.translate[1] = half_height + y;
149    vp.translate[2] = half_depth + z;
150 
151    ctx->set_viewport_states( ctx, 0, 1, &vp );
152 }
153 
set_vertices(void)154 static void set_vertices( void )
155 {
156    struct pipe_vertex_element ve[3];
157    struct pipe_vertex_buffer vbuf;
158    void *handle;
159 
160    memset(ve, 0, sizeof ve);
161 
162    ve[0].src_offset = Offset(struct vertex, position);
163    ve[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
164    ve[1].src_offset = Offset(struct vertex, color);
165    ve[1].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
166    ve[2].src_offset = Offset(struct vertex, texcoord);
167    ve[2].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
168 
169    handle = ctx->create_vertex_elements_state(ctx, 3, ve);
170    ctx->bind_vertex_elements_state(ctx, handle);
171 
172    memset(&vbuf, 0, sizeof vbuf);
173 
174    vbuf.stride = sizeof( struct vertex );
175    vbuf.buffer_offset = 0;
176    vbuf.buffer = pipe_buffer_create_with_data(ctx,
177                                               PIPE_BIND_VERTEX_BUFFER,
178                                               PIPE_USAGE_DEFAULT,
179                                               sizeof(vertices),
180                                               vertices);
181 
182    ctx->set_vertex_buffers(ctx, 0, 1, &vbuf);
183 }
184 
set_vertex_shader(void)185 static void set_vertex_shader( void )
186 {
187    void *handle;
188    const char *text =
189       "VERT\n"
190       "DCL IN[0]\n"
191       "DCL IN[1]\n"
192       "DCL IN[2]\n"
193       "DCL OUT[0], POSITION\n"
194       "DCL OUT[1], COLOR[0]\n"
195       "DCL OUT[2], GENERIC[0]\n"
196       "  MOV OUT[0], IN[0]\n"
197       "  MOV OUT[1], IN[1]\n"
198       "  MOV OUT[2], IN[2]\n"
199       "  END\n";
200 
201    handle = graw_parse_vertex_shader(ctx, text);
202    ctx->bind_vs_state(ctx, handle);
203 }
204 
set_fragment_shader(const char * filename)205 static void set_fragment_shader( const char *filename )
206 {
207    FILE *f;
208    char buf[50000];
209    void *handle;
210    int sz;
211 
212    if ((f = fopen(filename, "r")) == NULL) {
213       fprintf(stderr, "Couldn't open %s\n", filename);
214       exit(1);
215    }
216 
217    sz = fread(buf, 1, sizeof(buf), f);
218    if (!feof(f)) {
219       printf("file too long\n");
220       exit(1);
221    }
222    printf("%.*s\n", sz, buf);
223    buf[sz] = 0;
224 
225    handle = graw_parse_fragment_shader(ctx, buf);
226    ctx->bind_fs_state(ctx, handle);
227    fclose(f);
228 }
229 
230 
draw(void)231 static void draw( void )
232 {
233    union pipe_color_union clear_color = { {.1,.3,.5,0} };
234 
235    ctx->clear(ctx, PIPE_CLEAR_COLOR, &clear_color, 0, 0);
236    util_draw_arrays(ctx, PIPE_PRIM_TRIANGLES, 0, 3);
237    ctx->flush(ctx, NULL, 0);
238 
239    graw_save_surface_to_file(ctx, surf, NULL);
240 
241    screen->flush_frontbuffer(screen, rttex, 0, 0, window, NULL);
242 }
243 
244 #define SIZE 16
245 
init_tex(void)246 static void init_tex( void )
247 {
248    struct pipe_sampler_view sv_template;
249    struct pipe_sampler_state sampler_desc;
250    struct pipe_resource templat;
251    struct pipe_box box;
252    ubyte tex2d[SIZE][SIZE][4];
253    int s, t;
254 
255 #if (SIZE != 2)
256    for (s = 0; s < SIZE; s++) {
257       for (t = 0; t < SIZE; t++) {
258          if (0) {
259             int x = (s ^ t) & 1;
260 	    tex2d[t][s][0] = (x) ? 0 : 63;
261 	    tex2d[t][s][1] = (x) ? 0 : 128;
262 	    tex2d[t][s][2] = 0;
263 	    tex2d[t][s][3] = 0xff;
264          }
265          else {
266             int x = ((s ^ t) >> 2) & 1;
267 	    tex2d[t][s][0] = s*255/(SIZE-1);
268 	    tex2d[t][s][1] = t*255/(SIZE-1);
269 	    tex2d[t][s][2] = (x) ? 0 : 128;
270 	    tex2d[t][s][3] = 0xff;
271          }
272       }
273    }
274 #else
275    tex2d[0][0][0] = 0;
276    tex2d[0][0][1] = 255;
277    tex2d[0][0][2] = 255;
278    tex2d[0][0][3] = 0;
279 
280    tex2d[0][1][0] = 0;
281    tex2d[0][1][1] = 0;
282    tex2d[0][1][2] = 255;
283    tex2d[0][1][3] = 255;
284 
285    tex2d[1][0][0] = 255;
286    tex2d[1][0][1] = 255;
287    tex2d[1][0][2] = 0;
288    tex2d[1][0][3] = 255;
289 
290    tex2d[1][1][0] = 255;
291    tex2d[1][1][1] = 0;
292    tex2d[1][1][2] = 0;
293    tex2d[1][1][3] = 255;
294 #endif
295 
296    memset(&templat, 0, sizeof(templat));
297    templat.target = PIPE_TEXTURE_2D;
298    templat.format = PIPE_FORMAT_B8G8R8A8_UNORM;
299    templat.width0 = SIZE;
300    templat.height0 = SIZE;
301    templat.depth0 = 1;
302    templat.array_size = 1;
303    templat.last_level = 0;
304    templat.nr_samples = 1;
305    templat.bind = PIPE_BIND_SAMPLER_VIEW;
306 
307 
308    samptex = screen->resource_create(screen,
309                                  &templat);
310    if (samptex == NULL)
311       exit(4);
312 
313    u_box_2d(0,0,SIZE,SIZE, &box);
314 
315    ctx->texture_subdata(ctx,
316                         samptex,
317                         0,
318                         PIPE_TRANSFER_WRITE,
319                         &box,
320                         tex2d,
321                         sizeof tex2d[0],
322                         sizeof tex2d);
323 
324    /* Possibly read back & compare against original data:
325     */
326    if (0)
327    {
328       struct pipe_transfer *t;
329       uint32_t *ptr;
330       ptr = pipe_transfer_map(ctx, samptex,
331                               0, 0, /* level, layer */
332                               PIPE_TRANSFER_READ,
333                               0, 0, SIZE, SIZE, &t); /* x, y, width, height */
334 
335       if (memcmp(ptr, tex2d, sizeof tex2d) != 0) {
336          assert(0);
337          exit(9);
338       }
339 
340       ctx->transfer_unmap(ctx, t);
341    }
342 
343    memset(&sv_template, 0, sizeof sv_template);
344    sv_template.format = samptex->format;
345    sv_template.texture = samptex;
346    sv_template.swizzle_r = 0;
347    sv_template.swizzle_g = 1;
348    sv_template.swizzle_b = 2;
349    sv_template.swizzle_a = 3;
350    sv = ctx->create_sampler_view(ctx, samptex, &sv_template);
351    if (sv == NULL)
352       exit(5);
353 
354    ctx->set_sampler_views(ctx, PIPE_SHADER_FRAGMENT, 0, 1, &sv);
355 
356 
357    memset(&sampler_desc, 0, sizeof sampler_desc);
358    sampler_desc.wrap_s = PIPE_TEX_WRAP_REPEAT;
359    sampler_desc.wrap_t = PIPE_TEX_WRAP_REPEAT;
360    sampler_desc.wrap_r = PIPE_TEX_WRAP_REPEAT;
361    sampler_desc.min_img_filter = PIPE_TEX_FILTER_NEAREST;
362    sampler_desc.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
363    sampler_desc.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
364    sampler_desc.compare_mode = PIPE_TEX_COMPARE_NONE;
365    sampler_desc.compare_func = 0;
366    sampler_desc.normalized_coords = 1;
367    sampler_desc.max_anisotropy = 0;
368 
369    sampler = ctx->create_sampler_state(ctx, &sampler_desc);
370    if (sampler == NULL)
371       exit(6);
372 
373    ctx->bind_sampler_states(ctx, PIPE_SHADER_FRAGMENT, 0, 1, &sampler);
374 
375 }
376 
init(void)377 static void init( void )
378 {
379    struct pipe_framebuffer_state fb;
380    struct pipe_resource templat;
381    struct pipe_surface surf_tmpl;
382    int i;
383 
384    /* It's hard to say whether window or screen should be created
385     * first.  Different environments would prefer one or the other.
386     *
387     * Also, no easy way of querying supported formats if the screen
388     * cannot be created first.
389     */
390    for (i = 0; formats[i] != PIPE_FORMAT_NONE; i++) {
391       screen = graw_create_window_and_screen(0, 0, 300, 300,
392                                              formats[i],
393                                              &window);
394       if (window && screen)
395          break;
396    }
397    if (!screen || !window) {
398       fprintf(stderr, "Unable to create window\n");
399       exit(1);
400    }
401 
402    ctx = screen->context_create(screen, NULL, 0);
403    if (ctx == NULL)
404       exit(3);
405 
406    memset(&templat, 0, sizeof(templat));
407    templat.target = PIPE_TEXTURE_2D;
408    templat.format = formats[i];
409    templat.width0 = WIDTH;
410    templat.height0 = HEIGHT;
411    templat.depth0 = 1;
412    templat.array_size = 1;
413    templat.last_level = 0;
414    templat.nr_samples = 1;
415    templat.bind = (PIPE_BIND_RENDER_TARGET |
416                    PIPE_BIND_DISPLAY_TARGET);
417 
418    rttex = screen->resource_create(screen,
419                                  &templat);
420    if (rttex == NULL)
421       exit(4);
422 
423    surf_tmpl.format = templat.format;
424    surf_tmpl.u.tex.level = 0;
425    surf_tmpl.u.tex.first_layer = 0;
426    surf_tmpl.u.tex.last_layer = 0;
427    surf = ctx->create_surface(ctx, rttex, &surf_tmpl);
428    if (surf == NULL)
429       exit(5);
430 
431    memset(&fb, 0, sizeof fb);
432    fb.nr_cbufs = 1;
433    fb.width = WIDTH;
434    fb.height = HEIGHT;
435    fb.cbufs[0] = surf;
436 
437    ctx->set_framebuffer_state(ctx, &fb);
438 
439    {
440       struct pipe_blend_state blend;
441       void *handle;
442       memset(&blend, 0, sizeof blend);
443       blend.rt[0].colormask = PIPE_MASK_RGBA;
444       handle = ctx->create_blend_state(ctx, &blend);
445       ctx->bind_blend_state(ctx, handle);
446    }
447 
448    {
449       struct pipe_depth_stencil_alpha_state depthstencil;
450       void *handle;
451       memset(&depthstencil, 0, sizeof depthstencil);
452       handle = ctx->create_depth_stencil_alpha_state(ctx, &depthstencil);
453       ctx->bind_depth_stencil_alpha_state(ctx, handle);
454    }
455 
456    {
457       struct pipe_rasterizer_state rasterizer;
458       void *handle;
459       memset(&rasterizer, 0, sizeof rasterizer);
460       rasterizer.cull_face = PIPE_FACE_NONE;
461       rasterizer.half_pixel_center = 1;
462       rasterizer.bottom_edge_rule = 1;
463       rasterizer.depth_clip = 1;
464       handle = ctx->create_rasterizer_state(ctx, &rasterizer);
465       ctx->bind_rasterizer_state(ctx, handle);
466    }
467 
468    set_viewport(0, 0, WIDTH, HEIGHT, 30, 1000);
469 
470    init_tex();
471    init_fs_constbuf();
472 
473    set_vertices();
474    set_vertex_shader();
475    set_fragment_shader(filename);
476 }
477 
args(int argc,char * argv[])478 static void args(int argc, char *argv[])
479 {
480    int i;
481 
482    for (i = 1; i < argc;) {
483       if (graw_parse_args(&i, argc, argv)) {
484          continue;
485       }
486       if (strcmp(argv[i], "-fps") == 0) {
487          show_fps = 1;
488          i++;
489       }
490       else if (i == argc - 1) {
491          filename = argv[i];
492          i++;
493       }
494       else {
495          usage(argv[0]);
496          exit(1);
497       }
498    }
499 
500    if (!filename) {
501       usage(argv[0]);
502       exit(1);
503    }
504 }
505 
main(int argc,char * argv[])506 int main( int argc, char *argv[] )
507 {
508    args(argc,argv);
509    init();
510 
511    graw_set_display_func( draw );
512    graw_main_loop();
513    return 0;
514 }
515