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