r600: document some of the missing shader constants.
[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
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
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
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.resource = 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.resource = 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
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
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
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
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
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
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
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
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 }