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