gs-test.c revision 7e02303497237cde958c28608477d0c355a8038b
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
18static const char *filename = NULL;
19unsigned show_fps = 0;
20unsigned draw_strip = 0;
21
22
23static 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
35enum pipe_format formats[] = {
36   PIPE_FORMAT_R8G8B8A8_UNORM,
37   PIPE_FORMAT_B8G8R8A8_UNORM,
38   PIPE_FORMAT_NONE
39};
40
41static const int WIDTH = 250;
42static const int HEIGHT = 250;
43
44static struct pipe_screen *screen = NULL;
45static struct pipe_context *ctx = NULL;
46static struct pipe_resource *rttex = NULL;
47static struct pipe_resource *constbuf1 = NULL;
48static struct pipe_resource *constbuf2 = NULL;
49static struct pipe_surface *surf = NULL;
50static struct pipe_sampler_view *sv = NULL;
51static void *sampler = NULL;
52static void *window = NULL;
53static struct pipe_resource *samptex = NULL;
54
55struct 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 */
65static 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
86static 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
113static 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
131static 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
149static 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      ctx->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      ctx->set_constant_buffer(ctx,
202                               PIPE_SHADER_GEOMETRY, 1,
203                               constbuf2);
204   }
205}
206
207
208static 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
231static 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 = screen->user_buffer_create(screen,
255                                               vertices_strip,
256                                               sizeof(vertices_strip),
257                                               PIPE_BIND_VERTEX_BUFFER);
258   } else {
259      vbuf.buffer = screen->user_buffer_create(screen,
260                                               vertices,
261                                               sizeof(vertices),
262                                               PIPE_BIND_VERTEX_BUFFER);
263   }
264
265   ctx->set_vertex_buffers(ctx, 1, &vbuf);
266}
267
268static void set_vertex_shader( void )
269{
270   void *handle;
271   const char *text =
272      "VERT\n"
273      "DCL IN[0]\n"
274      "DCL IN[1]\n"
275      "DCL IN[2]\n"
276      "DCL IN[3]\n"
277      "DCL OUT[0], POSITION\n"
278      "DCL OUT[1], COLOR[0]\n"
279      "DCL OUT[2], GENERIC[0]\n"
280      "DCL OUT[3], GENERIC[1]\n"
281      "  MOV OUT[0], IN[0]\n"
282      "  MOV OUT[1], IN[1]\n"
283      "  MOV OUT[2], IN[2]\n"
284      "  MOV OUT[3], IN[3]\n"
285      "  END\n";
286
287   handle = graw_parse_vertex_shader(ctx, text);
288   ctx->bind_vs_state(ctx, handle);
289}
290
291static void set_fragment_shader( void )
292{
293   void *handle;
294   const char *text =
295      "FRAG\n"
296      "DCL IN[0], COLOR, LINEAR\n"
297      "DCL OUT[0], COLOR\n"
298      "  0: MOV OUT[0], IN[0]\n"
299      "  1: END\n";
300
301   handle = graw_parse_fragment_shader(ctx, text);
302   ctx->bind_fs_state(ctx, handle);
303}
304
305
306static void set_geometry_shader( void )
307{
308   FILE *f;
309   char buf[50000];
310   void *handle;
311   int sz;
312
313   if ((f = fopen(filename, "r")) == NULL) {
314      fprintf(stderr, "Couldn't open %s\n", filename);
315      exit(1);
316   }
317
318   sz = fread(buf, 1, sizeof(buf), f);
319   if (!feof(f)) {
320      printf("file too long\n");
321      exit(1);
322   }
323   printf("%.*s\n", sz, buf);
324   buf[sz] = 0;
325
326   handle = graw_parse_geometry_shader(ctx, buf);
327   ctx->bind_gs_state(ctx, handle);
328   fclose(f);
329}
330
331
332static void draw( void )
333{
334   float clear_color[4] = {.1,.3,.5,0};
335
336   ctx->clear(ctx, PIPE_CLEAR_COLOR, clear_color, 0, 0);
337   if (draw_strip)
338      util_draw_arrays(ctx, PIPE_PRIM_TRIANGLE_STRIP, 0, 4);
339   else
340      util_draw_arrays(ctx, PIPE_PRIM_TRIANGLES, 0, 3);
341
342   ctx->flush(ctx, NULL);
343
344   graw_save_surface_to_file(ctx, surf, NULL);
345
346   screen->flush_frontbuffer(screen, rttex, 0, 0, window);
347}
348
349#define SIZE 16
350
351static void init_tex( void )
352{
353   struct pipe_sampler_view sv_template;
354   struct pipe_sampler_state sampler_desc;
355   struct pipe_resource templat;
356   struct pipe_box box;
357   ubyte tex2d[SIZE][SIZE][4];
358   int s, t;
359
360#if (SIZE != 2)
361   for (s = 0; s < SIZE; s++) {
362      for (t = 0; t < SIZE; t++) {
363         if (0) {
364            int x = (s ^ t) & 1;
365	    tex2d[t][s][0] = (x) ? 0 : 63;
366	    tex2d[t][s][1] = (x) ? 0 : 128;
367	    tex2d[t][s][2] = 0;
368	    tex2d[t][s][3] = 0xff;
369         }
370         else {
371            int x = ((s ^ t) >> 2) & 1;
372	    tex2d[t][s][0] = s*255/(SIZE-1);
373	    tex2d[t][s][1] = t*255/(SIZE-1);
374	    tex2d[t][s][2] = (x) ? 0 : 128;
375	    tex2d[t][s][3] = 0xff;
376         }
377      }
378   }
379#else
380   tex2d[0][0][0] = 0;
381   tex2d[0][0][1] = 255;
382   tex2d[0][0][2] = 255;
383   tex2d[0][0][3] = 0;
384
385   tex2d[0][1][0] = 0;
386   tex2d[0][1][1] = 0;
387   tex2d[0][1][2] = 255;
388   tex2d[0][1][3] = 255;
389
390   tex2d[1][0][0] = 255;
391   tex2d[1][0][1] = 255;
392   tex2d[1][0][2] = 0;
393   tex2d[1][0][3] = 255;
394
395   tex2d[1][1][0] = 255;
396   tex2d[1][1][1] = 0;
397   tex2d[1][1][2] = 0;
398   tex2d[1][1][3] = 255;
399#endif
400
401   templat.target = PIPE_TEXTURE_2D;
402   templat.format = PIPE_FORMAT_B8G8R8A8_UNORM;
403   templat.width0 = SIZE;
404   templat.height0 = SIZE;
405   templat.depth0 = 1;
406   templat.array_size = 1;
407   templat.last_level = 0;
408   templat.nr_samples = 1;
409   templat.bind = PIPE_BIND_SAMPLER_VIEW;
410
411
412   samptex = screen->resource_create(screen,
413                                 &templat);
414   if (samptex == NULL)
415      exit(4);
416
417   u_box_2d(0,0,SIZE,SIZE, &box);
418
419   ctx->transfer_inline_write(ctx,
420                              samptex,
421                              0,
422                              PIPE_TRANSFER_WRITE,
423                              &box,
424                              tex2d,
425                              sizeof tex2d[0],
426                              sizeof tex2d);
427
428   /* Possibly read back & compare against original data:
429    */
430   if (0)
431   {
432      struct pipe_transfer *t;
433      uint32_t *ptr;
434      t = pipe_get_transfer(ctx, samptex,
435                            0, 0, /* level, layer */
436                            PIPE_TRANSFER_READ,
437                            0, 0, SIZE, SIZE); /* x, y, width, height */
438
439      ptr = ctx->transfer_map(ctx, t);
440
441      if (memcmp(ptr, tex2d, sizeof tex2d) != 0) {
442         assert(0);
443         exit(9);
444      }
445
446      ctx->transfer_unmap(ctx, t);
447
448      ctx->transfer_destroy(ctx, t);
449   }
450
451   memset(&sv_template, 0, sizeof sv_template);
452   sv_template.format = samptex->format;
453   sv_template.texture = samptex;
454   sv_template.swizzle_r = 0;
455   sv_template.swizzle_g = 1;
456   sv_template.swizzle_b = 2;
457   sv_template.swizzle_a = 3;
458   sv = ctx->create_sampler_view(ctx, samptex, &sv_template);
459   if (sv == NULL)
460      exit(5);
461
462   ctx->set_fragment_sampler_views(ctx, 1, &sv);
463
464
465   memset(&sampler_desc, 0, sizeof sampler_desc);
466   sampler_desc.wrap_s = PIPE_TEX_WRAP_REPEAT;
467   sampler_desc.wrap_t = PIPE_TEX_WRAP_REPEAT;
468   sampler_desc.wrap_r = PIPE_TEX_WRAP_REPEAT;
469   sampler_desc.min_img_filter = PIPE_TEX_FILTER_NEAREST;
470   sampler_desc.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
471   sampler_desc.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
472   sampler_desc.compare_mode = PIPE_TEX_COMPARE_NONE;
473   sampler_desc.compare_func = 0;
474   sampler_desc.normalized_coords = 1;
475   sampler_desc.max_anisotropy = 0;
476
477   sampler = ctx->create_sampler_state(ctx, &sampler_desc);
478   if (sampler == NULL)
479      exit(6);
480
481   ctx->bind_fragment_sampler_states(ctx, 1, &sampler);
482
483}
484
485static void init( void )
486{
487   struct pipe_framebuffer_state fb;
488   struct pipe_resource templat;
489   struct pipe_surface surf_tmpl;
490   int i;
491
492   /* It's hard to say whether window or screen should be created
493    * first.  Different environments would prefer one or the other.
494    *
495    * Also, no easy way of querying supported formats if the screen
496    * cannot be created first.
497    */
498   for (i = 0; formats[i] != PIPE_FORMAT_NONE; i++) {
499      screen = graw_create_window_and_screen(0, 0, 300, 300,
500                                             formats[i],
501                                             &window);
502      if (window && screen)
503         break;
504   }
505   if (!screen || !window) {
506      fprintf(stderr, "Unable to create window\n");
507      exit(1);
508   }
509
510   ctx = screen->context_create(screen, NULL);
511   if (ctx == NULL)
512      exit(3);
513
514   templat.target = PIPE_TEXTURE_2D;
515   templat.format = formats[i];
516   templat.width0 = WIDTH;
517   templat.height0 = HEIGHT;
518   templat.depth0 = 1;
519   templat.array_size = 1;
520   templat.last_level = 0;
521   templat.nr_samples = 1;
522   templat.bind = (PIPE_BIND_RENDER_TARGET |
523                   PIPE_BIND_DISPLAY_TARGET);
524
525   rttex = screen->resource_create(screen,
526                                 &templat);
527   if (rttex == NULL)
528      exit(4);
529
530   surf_tmpl.format = templat.format;
531   surf_tmpl.usage = PIPE_BIND_RENDER_TARGET;
532   surf_tmpl.u.tex.level = 0;
533   surf_tmpl.u.tex.first_layer = 0;
534   surf_tmpl.u.tex.last_layer = 0;
535   surf = ctx->create_surface(ctx, rttex, &surf_tmpl);
536   if (surf == NULL)
537      exit(5);
538
539   memset(&fb, 0, sizeof fb);
540   fb.nr_cbufs = 1;
541   fb.width = WIDTH;
542   fb.height = HEIGHT;
543   fb.cbufs[0] = surf;
544
545   ctx->set_framebuffer_state(ctx, &fb);
546
547   {
548      struct pipe_blend_state blend;
549      void *handle;
550      memset(&blend, 0, sizeof blend);
551      blend.rt[0].colormask = PIPE_MASK_RGBA;
552      handle = ctx->create_blend_state(ctx, &blend);
553      ctx->bind_blend_state(ctx, handle);
554   }
555
556   {
557      struct pipe_depth_stencil_alpha_state depthstencil;
558      void *handle;
559      memset(&depthstencil, 0, sizeof depthstencil);
560      handle = ctx->create_depth_stencil_alpha_state(ctx, &depthstencil);
561      ctx->bind_depth_stencil_alpha_state(ctx, handle);
562   }
563
564   {
565      struct pipe_rasterizer_state rasterizer;
566      void *handle;
567      memset(&rasterizer, 0, sizeof rasterizer);
568      rasterizer.cull_face = PIPE_FACE_NONE;
569      rasterizer.gl_rasterization_rules = 1;
570      handle = ctx->create_rasterizer_state(ctx, &rasterizer);
571      ctx->bind_rasterizer_state(ctx, handle);
572   }
573
574   set_viewport(0, 0, WIDTH, HEIGHT, 30, 1000);
575
576   init_tex();
577   init_fs_constbuf();
578
579   set_vertices();
580   set_vertex_shader();
581   set_fragment_shader();
582   set_geometry_shader();
583}
584
585static void args(int argc, char *argv[])
586{
587   int i;
588
589   for (i = 1; i < argc;) {
590      if (graw_parse_args(&i, argc, argv)) {
591         continue;
592      }
593      if (strcmp(argv[i], "-fps") == 0) {
594         show_fps = 1;
595         i++;
596      }
597      else if (strcmp(argv[i], "-strip") == 0) {
598         draw_strip = 1;
599         i++;
600      }
601      else if (i == argc - 1) {
602         filename = argv[i];
603         i++;
604      }
605      else {
606         usage(argv[0]);
607         exit(1);
608      }
609   }
610
611   if (!filename) {
612      usage(argv[0]);
613      exit(1);
614   }
615}
616
617int main( int argc, char *argv[] )
618{
619   args(argc,argv);
620   init();
621
622   graw_set_display_func( draw );
623   graw_main_loop();
624   return 0;
625}
626