gallium: remove PIPE_USAGE_STATIC
[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 pipe_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 pipe_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_states( ctx, 0, 1, &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 memset(&vbuf, 0, sizeof vbuf);
252
253 vbuf.stride = sizeof( struct vertex );
254 vbuf.buffer_offset = 0;
255 if (draw_strip) {
256 vbuf.buffer = pipe_buffer_create_with_data(ctx,
257 PIPE_BIND_VERTEX_BUFFER,
258 PIPE_USAGE_DEFAULT,
259 sizeof(vertices_strip),
260 vertices_strip);
261 } else {
262 vbuf.buffer = pipe_buffer_create_with_data(ctx,
263 PIPE_BIND_VERTEX_BUFFER,
264 PIPE_USAGE_DEFAULT,
265 sizeof(vertices),
266 vertices);
267 }
268
269 ctx->set_vertex_buffers(ctx, 0, 1, &vbuf);
270 }
271
272 static void set_vertex_shader( void )
273 {
274 void *handle;
275 const char *text =
276 "VERT\n"
277 "DCL IN[0]\n"
278 "DCL IN[1]\n"
279 "DCL IN[2]\n"
280 "DCL IN[3]\n"
281 "DCL OUT[0], POSITION\n"
282 "DCL OUT[1], COLOR[0]\n"
283 "DCL OUT[2], GENERIC[0]\n"
284 "DCL OUT[3], GENERIC[1]\n"
285 " MOV OUT[0], IN[0]\n"
286 " MOV OUT[1], IN[1]\n"
287 " MOV OUT[2], IN[2]\n"
288 " MOV OUT[3], IN[3]\n"
289 " END\n";
290
291 handle = graw_parse_vertex_shader(ctx, text);
292 ctx->bind_vs_state(ctx, handle);
293 }
294
295 static void set_fragment_shader( void )
296 {
297 void *handle;
298 const char *text =
299 "FRAG\n"
300 "DCL IN[0], COLOR, LINEAR\n"
301 "DCL OUT[0], COLOR\n"
302 " 0: MOV OUT[0], IN[0]\n"
303 " 1: END\n";
304
305 handle = graw_parse_fragment_shader(ctx, text);
306 ctx->bind_fs_state(ctx, handle);
307 }
308
309
310 static void set_geometry_shader( void )
311 {
312 FILE *f;
313 char buf[50000];
314 void *handle;
315 int sz;
316
317 if ((f = fopen(filename, "r")) == NULL) {
318 fprintf(stderr, "Couldn't open %s\n", filename);
319 exit(1);
320 }
321
322 sz = fread(buf, 1, sizeof(buf), f);
323 if (!feof(f)) {
324 printf("file too long\n");
325 exit(1);
326 }
327 printf("%.*s\n", sz, buf);
328 buf[sz] = 0;
329
330 handle = graw_parse_geometry_shader(ctx, buf);
331 ctx->bind_gs_state(ctx, handle);
332 fclose(f);
333 }
334
335
336 static void draw( void )
337 {
338 union pipe_color_union clear_color = { {.1,.3,.5,0} };
339
340 ctx->clear(ctx, PIPE_CLEAR_COLOR, &clear_color, 0, 0);
341 if (draw_strip)
342 util_draw_arrays(ctx, PIPE_PRIM_TRIANGLE_STRIP, 0, 4);
343 else
344 util_draw_arrays(ctx, PIPE_PRIM_TRIANGLES, 0, 3);
345
346 ctx->flush(ctx, NULL, 0);
347
348 graw_save_surface_to_file(ctx, surf, NULL);
349
350 screen->flush_frontbuffer(screen, rttex, 0, 0, window, NULL);
351 }
352
353 #define SIZE 16
354
355 static void init_tex( void )
356 {
357 struct pipe_sampler_view sv_template;
358 struct pipe_sampler_state sampler_desc;
359 struct pipe_resource templat;
360 struct pipe_box box;
361 ubyte tex2d[SIZE][SIZE][4];
362 int s, t;
363
364 #if (SIZE != 2)
365 for (s = 0; s < SIZE; s++) {
366 for (t = 0; t < SIZE; t++) {
367 if (0) {
368 int x = (s ^ t) & 1;
369 tex2d[t][s][0] = (x) ? 0 : 63;
370 tex2d[t][s][1] = (x) ? 0 : 128;
371 tex2d[t][s][2] = 0;
372 tex2d[t][s][3] = 0xff;
373 }
374 else {
375 int x = ((s ^ t) >> 2) & 1;
376 tex2d[t][s][0] = s*255/(SIZE-1);
377 tex2d[t][s][1] = t*255/(SIZE-1);
378 tex2d[t][s][2] = (x) ? 0 : 128;
379 tex2d[t][s][3] = 0xff;
380 }
381 }
382 }
383 #else
384 tex2d[0][0][0] = 0;
385 tex2d[0][0][1] = 255;
386 tex2d[0][0][2] = 255;
387 tex2d[0][0][3] = 0;
388
389 tex2d[0][1][0] = 0;
390 tex2d[0][1][1] = 0;
391 tex2d[0][1][2] = 255;
392 tex2d[0][1][3] = 255;
393
394 tex2d[1][0][0] = 255;
395 tex2d[1][0][1] = 255;
396 tex2d[1][0][2] = 0;
397 tex2d[1][0][3] = 255;
398
399 tex2d[1][1][0] = 255;
400 tex2d[1][1][1] = 0;
401 tex2d[1][1][2] = 0;
402 tex2d[1][1][3] = 255;
403 #endif
404
405 templat.target = PIPE_TEXTURE_2D;
406 templat.format = PIPE_FORMAT_B8G8R8A8_UNORM;
407 templat.width0 = SIZE;
408 templat.height0 = SIZE;
409 templat.depth0 = 1;
410 templat.array_size = 1;
411 templat.last_level = 0;
412 templat.nr_samples = 1;
413 templat.bind = PIPE_BIND_SAMPLER_VIEW;
414
415
416 samptex = screen->resource_create(screen,
417 &templat);
418 if (samptex == NULL)
419 exit(4);
420
421 u_box_2d(0,0,SIZE,SIZE, &box);
422
423 ctx->transfer_inline_write(ctx,
424 samptex,
425 0,
426 PIPE_TRANSFER_WRITE,
427 &box,
428 tex2d,
429 sizeof tex2d[0],
430 sizeof tex2d);
431
432 /* Possibly read back & compare against original data:
433 */
434 if (0)
435 {
436 struct pipe_transfer *t;
437 uint32_t *ptr;
438 ptr = pipe_transfer_map(ctx, samptex,
439 0, 0, /* level, layer */
440 PIPE_TRANSFER_READ,
441 0, 0, SIZE, SIZE, &t); /* x, y, width, height */
442
443 if (memcmp(ptr, tex2d, sizeof tex2d) != 0) {
444 assert(0);
445 exit(9);
446 }
447
448 ctx->transfer_unmap(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_sampler_views(ctx, PIPE_SHADER_FRAGMENT, 0, 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_sampler_states(ctx, PIPE_SHADER_FRAGMENT, 0, 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.u.tex.level = 0;
532 surf_tmpl.u.tex.first_layer = 0;
533 surf_tmpl.u.tex.last_layer = 0;
534 surf = ctx->create_surface(ctx, rttex, &surf_tmpl);
535 if (surf == NULL)
536 exit(5);
537
538 memset(&fb, 0, sizeof fb);
539 fb.nr_cbufs = 1;
540 fb.width = WIDTH;
541 fb.height = HEIGHT;
542 fb.cbufs[0] = surf;
543
544 ctx->set_framebuffer_state(ctx, &fb);
545
546 {
547 struct pipe_blend_state blend;
548 void *handle;
549 memset(&blend, 0, sizeof blend);
550 blend.rt[0].colormask = PIPE_MASK_RGBA;
551 handle = ctx->create_blend_state(ctx, &blend);
552 ctx->bind_blend_state(ctx, handle);
553 }
554
555 {
556 struct pipe_depth_stencil_alpha_state depthstencil;
557 void *handle;
558 memset(&depthstencil, 0, sizeof depthstencil);
559 handle = ctx->create_depth_stencil_alpha_state(ctx, &depthstencil);
560 ctx->bind_depth_stencil_alpha_state(ctx, handle);
561 }
562
563 {
564 struct pipe_rasterizer_state rasterizer;
565 void *handle;
566 memset(&rasterizer, 0, sizeof rasterizer);
567 rasterizer.cull_face = PIPE_FACE_NONE;
568 rasterizer.half_pixel_center = 1;
569 rasterizer.bottom_edge_rule = 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 }