ef2440291fc28f95bbee360eca596c353bd0b638
[mesa.git] / src / gallium / tests / graw / gs-test.c
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
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
149 static 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
208 static 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
231 static 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
268 static 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
291 static 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
306 static 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
332 static void draw( void )
333 {
334 union pipe_color_union clear_color = { {.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
351 static 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
485 static 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 rasterizer.depth_clip = 1;
571 handle = ctx->create_rasterizer_state(ctx, &rasterizer);
572 ctx->bind_rasterizer_state(ctx, handle);
573 }
574
575 set_viewport(0, 0, WIDTH, HEIGHT, 30, 1000);
576
577 init_tex();
578 init_fs_constbuf();
579
580 set_vertices();
581 set_vertex_shader();
582 set_fragment_shader();
583 set_geometry_shader();
584 }
585
586 static void args(int argc, char *argv[])
587 {
588 int i;
589
590 for (i = 1; i < argc;) {
591 if (graw_parse_args(&i, argc, argv)) {
592 continue;
593 }
594 if (strcmp(argv[i], "-fps") == 0) {
595 show_fps = 1;
596 i++;
597 }
598 else if (strcmp(argv[i], "-strip") == 0) {
599 draw_strip = 1;
600 i++;
601 }
602 else if (i == argc - 1) {
603 filename = argv[i];
604 i++;
605 }
606 else {
607 usage(argv[0]);
608 exit(1);
609 }
610 }
611
612 if (!filename) {
613 usage(argv[0]);
614 exit(1);
615 }
616 }
617
618 int main( int argc, char *argv[] )
619 {
620 args(argc,argv);
621 init();
622
623 graw_set_display_func( draw );
624 graw_main_loop();
625 return 0;
626 }