graw: Undo late loading of graw drivers.
[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_debug.h" /* debug_dump_surface_bmp() */
14 #include "util/u_inlines.h"
15 #include "util/u_memory.h" /* Offset() */
16 #include "util/u_draw_quad.h"
17 #include "util/u_box.h"
18
19 static const char *filename = NULL;
20 unsigned show_fps = 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 #endif
31 }
32
33
34 enum pipe_format formats[] = {
35 PIPE_FORMAT_R8G8B8A8_UNORM,
36 PIPE_FORMAT_B8G8R8A8_UNORM,
37 PIPE_FORMAT_NONE
38 };
39
40 static const int WIDTH = 250;
41 static const int HEIGHT = 250;
42
43 static struct pipe_screen *screen = NULL;
44 static struct pipe_context *ctx = NULL;
45 static struct pipe_resource *rttex = NULL;
46 static struct pipe_resource *constbuf1 = NULL;
47 static struct pipe_resource *constbuf2 = NULL;
48 static struct pipe_surface *surf = NULL;
49 static struct pipe_sampler_view *sv = NULL;
50 static void *sampler = NULL;
51 static void *window = NULL;
52 static struct pipe_resource *samptex = NULL;
53
54 struct vertex {
55 float position[4];
56 float color[4];
57 float texcoord[4];
58 };
59
60 /* Vertex data matches progs/fp/fp-tri.c, but flipped in Y dimension
61 * so that the final images are the same.
62 */
63 static struct vertex vertices[] =
64 {
65 { { 0.9, 0.9, 0.0, 1.0 },
66 { 0, 0, 1, 1 },
67 { 1, 1, 0, 1 } },
68
69 { { 0.9, -0.9, 0.0, 1.0 },
70 { 1, 0, 0, 1 },
71 { 1, -1, 0, 1 } },
72
73 { {-0.9, 0.0, 0.0, 1.0 },
74 { 0, 1, 0, 1 },
75 { -1, 0, 0, 1 } },
76 };
77
78 static float constants1[] =
79 { 0.4, 0, 0, 1,
80 1, 1, 1, 1,
81 2, 2, 2, 2,
82 4, 8, 16, 32,
83
84 3, 0, 0, 0,
85 0, .5, 0, 0,
86 1, 0, 0, 1,
87 0, 0, 0, 1,
88
89 1, 0, 0, 0.5,
90 0, 1, 0, 0.5,
91 0, 0, 1, 0,
92 0, 0, 0, 1,
93 };
94
95
96 static float constants2[] =
97 { 1, 0, 0, 1,
98 0, 1, 0, 1,
99 0, 0, 1, 1,
100 0, 0, 0, 0,
101
102 1, 1, 0, 1,
103 1, .5, 0, 1,
104 1, 0, 0, 1,
105 0, 0, 0, 1,
106
107 1, 0, 0, 0.5,
108 0, 1, 0, 0.5,
109 0, 0, 1, 0,
110 0, 0, 0, 1,
111 };
112
113 static void init_fs_constbuf( void )
114 {
115 struct pipe_resource templat;
116 struct pipe_box box;
117
118 templat.target = PIPE_BUFFER;
119 templat.format = PIPE_FORMAT_R8_UNORM;
120 templat.width0 = sizeof(constants1);
121 templat.height0 = 1;
122 templat.depth0 = 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 u_subresource(0,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 u_subresource(0,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.max_index = sizeof(vertices) / vbuf.stride;
219 vbuf.buffer_offset = 0;
220 vbuf.buffer = screen->user_buffer_create(screen,
221 vertices,
222 sizeof(vertices),
223 PIPE_BIND_VERTEX_BUFFER);
224
225 ctx->set_vertex_buffers(ctx, 1, &vbuf);
226 }
227
228 static void set_vertex_shader( void )
229 {
230 void *handle;
231 const char *text =
232 "VERT\n"
233 "DCL IN[0]\n"
234 "DCL IN[1]\n"
235 "DCL IN[2]\n"
236 "DCL OUT[0], POSITION\n"
237 "DCL OUT[1], COLOR[0]\n"
238 "DCL OUT[2], GENERIC[0]\n"
239 " MOV OUT[0], IN[0]\n"
240 " MOV OUT[1], IN[1]\n"
241 " MOV OUT[2], IN[2]\n"
242 " END\n";
243
244 handle = graw_parse_vertex_shader(ctx, text);
245 ctx->bind_vs_state(ctx, handle);
246 }
247
248 static void set_fragment_shader( const char *filename )
249 {
250 FILE *f;
251 char buf[50000];
252 void *handle;
253 int sz;
254
255 if ((f = fopen(filename, "r")) == NULL) {
256 fprintf(stderr, "Couldn't open %s\n", filename);
257 exit(1);
258 }
259
260 sz = fread(buf, 1, sizeof(buf), f);
261 if (!feof(f)) {
262 printf("file too long\n");
263 exit(1);
264 }
265 printf("%.*s\n", sz, buf);
266 buf[sz] = 0;
267
268 handle = graw_parse_fragment_shader(ctx, buf);
269 ctx->bind_fs_state(ctx, handle);
270 fclose(f);
271 }
272
273
274 static void draw( void )
275 {
276 float clear_color[4] = {.1,.3,.5,0};
277
278 ctx->clear(ctx, PIPE_CLEAR_COLOR, clear_color, 0, 0);
279 util_draw_arrays(ctx, PIPE_PRIM_TRIANGLES, 0, 3);
280 ctx->flush(ctx, PIPE_FLUSH_RENDER_CACHE, NULL);
281
282 #if 0
283 /* At the moment, libgraw leaks out/makes available some of the
284 * symbols from gallium/auxiliary, including these debug helpers.
285 * Will eventually want to bless some of these paths, and lock the
286 * others down so they aren't accessible from test programs.
287 *
288 * This currently just happens to work on debug builds - a release
289 * build will probably fail to link here:
290 */
291 debug_dump_surface_bmp(ctx, "result.bmp", surf);
292 #endif
293
294 screen->flush_frontbuffer(screen, surf, window);
295 }
296
297 #define SIZE 16
298
299 static void init_tex( void )
300 {
301 struct pipe_sampler_view sv_template;
302 struct pipe_sampler_state sampler_desc;
303 struct pipe_resource templat;
304 struct pipe_box box;
305 ubyte tex2d[SIZE][SIZE][4];
306 int s, t;
307
308 #if (SIZE != 2)
309 for (s = 0; s < SIZE; s++) {
310 for (t = 0; t < SIZE; t++) {
311 if (0) {
312 int x = (s ^ t) & 1;
313 tex2d[t][s][0] = (x) ? 0 : 63;
314 tex2d[t][s][1] = (x) ? 0 : 128;
315 tex2d[t][s][2] = 0;
316 tex2d[t][s][3] = 0xff;
317 }
318 else {
319 int x = ((s ^ t) >> 2) & 1;
320 tex2d[t][s][0] = s*255/(SIZE-1);
321 tex2d[t][s][1] = t*255/(SIZE-1);
322 tex2d[t][s][2] = (x) ? 0 : 128;
323 tex2d[t][s][3] = 0xff;
324 }
325 }
326 }
327 #else
328 tex2d[0][0][0] = 0;
329 tex2d[0][0][1] = 255;
330 tex2d[0][0][2] = 255;
331 tex2d[0][0][3] = 0;
332
333 tex2d[0][1][0] = 0;
334 tex2d[0][1][1] = 0;
335 tex2d[0][1][2] = 255;
336 tex2d[0][1][3] = 255;
337
338 tex2d[1][0][0] = 255;
339 tex2d[1][0][1] = 255;
340 tex2d[1][0][2] = 0;
341 tex2d[1][0][3] = 255;
342
343 tex2d[1][1][0] = 255;
344 tex2d[1][1][1] = 0;
345 tex2d[1][1][2] = 0;
346 tex2d[1][1][3] = 255;
347 #endif
348
349 templat.target = PIPE_TEXTURE_2D;
350 templat.format = PIPE_FORMAT_B8G8R8A8_UNORM;
351 templat.width0 = SIZE;
352 templat.height0 = SIZE;
353 templat.depth0 = 1;
354 templat.last_level = 0;
355 templat.nr_samples = 1;
356 templat.bind = PIPE_BIND_SAMPLER_VIEW;
357
358
359 samptex = screen->resource_create(screen,
360 &templat);
361 if (samptex == NULL)
362 exit(4);
363
364 u_box_2d(0,0,SIZE,SIZE, &box);
365
366 ctx->transfer_inline_write(ctx,
367 samptex,
368 u_subresource(0,0),
369 PIPE_TRANSFER_WRITE,
370 &box,
371 tex2d,
372 sizeof tex2d[0],
373 sizeof tex2d);
374
375 /* Possibly read back & compare against original data:
376 */
377 if (0)
378 {
379 struct pipe_transfer *t;
380 uint32_t *ptr;
381 t = pipe_get_transfer(ctx, samptex,
382 0, 0, 0, /* face, level, zslice */
383 PIPE_TRANSFER_READ,
384 0, 0, SIZE, SIZE); /* x, y, width, height */
385
386 ptr = ctx->transfer_map(ctx, t);
387
388 if (memcmp(ptr, tex2d, sizeof tex2d) != 0) {
389 assert(0);
390 exit(9);
391 }
392
393 ctx->transfer_unmap(ctx, t);
394
395 ctx->transfer_destroy(ctx, t);
396 }
397
398 memset(&sv_template, 0, sizeof sv_template);
399 sv_template.format = samptex->format;
400 sv_template.texture = samptex;
401 sv_template.first_level = 0;
402 sv_template.last_level = 0;
403 sv_template.swizzle_r = 0;
404 sv_template.swizzle_g = 1;
405 sv_template.swizzle_b = 2;
406 sv_template.swizzle_a = 3;
407 sv = ctx->create_sampler_view(ctx, samptex, &sv_template);
408 if (sv == NULL)
409 exit(5);
410
411 ctx->set_fragment_sampler_views(ctx, 1, &sv);
412
413
414 memset(&sampler_desc, 0, sizeof sampler_desc);
415 sampler_desc.wrap_s = PIPE_TEX_WRAP_REPEAT;
416 sampler_desc.wrap_t = PIPE_TEX_WRAP_REPEAT;
417 sampler_desc.wrap_r = PIPE_TEX_WRAP_REPEAT;
418 sampler_desc.min_img_filter = PIPE_TEX_FILTER_NEAREST;
419 sampler_desc.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
420 sampler_desc.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
421 sampler_desc.compare_mode = PIPE_TEX_COMPARE_NONE;
422 sampler_desc.compare_func = 0;
423 sampler_desc.normalized_coords = 1;
424 sampler_desc.max_anisotropy = 0;
425
426 sampler = ctx->create_sampler_state(ctx, &sampler_desc);
427 if (sampler == NULL)
428 exit(6);
429
430 ctx->bind_fragment_sampler_states(ctx, 1, &sampler);
431
432 }
433
434 static void init( void )
435 {
436 struct pipe_framebuffer_state fb;
437 struct pipe_resource templat;
438 int i;
439
440 /* It's hard to say whether window or screen should be created
441 * first. Different environments would prefer one or the other.
442 *
443 * Also, no easy way of querying supported formats if the screen
444 * cannot be created first.
445 */
446 for (i = 0;
447 window == NULL && formats[i] != PIPE_FORMAT_NONE;
448 i++) {
449
450 screen = graw_create_window_and_screen(0,0,WIDTH,HEIGHT,
451 formats[i],
452 &window);
453 }
454
455 ctx = screen->context_create(screen, NULL);
456 if (ctx == NULL)
457 exit(3);
458
459 templat.target = PIPE_TEXTURE_2D;
460 templat.format = formats[i];
461 templat.width0 = WIDTH;
462 templat.height0 = HEIGHT;
463 templat.depth0 = 1;
464 templat.last_level = 0;
465 templat.nr_samples = 1;
466 templat.bind = (PIPE_BIND_RENDER_TARGET |
467 PIPE_BIND_DISPLAY_TARGET);
468
469 rttex = screen->resource_create(screen,
470 &templat);
471 if (rttex == NULL)
472 exit(4);
473
474 surf = screen->get_tex_surface(screen, rttex, 0, 0, 0,
475 PIPE_BIND_RENDER_TARGET |
476 PIPE_BIND_DISPLAY_TARGET);
477 if (surf == NULL)
478 exit(5);
479
480 memset(&fb, 0, sizeof fb);
481 fb.nr_cbufs = 1;
482 fb.width = WIDTH;
483 fb.height = HEIGHT;
484 fb.cbufs[0] = surf;
485
486 ctx->set_framebuffer_state(ctx, &fb);
487
488 {
489 struct pipe_blend_state blend;
490 void *handle;
491 memset(&blend, 0, sizeof blend);
492 blend.rt[0].colormask = PIPE_MASK_RGBA;
493 handle = ctx->create_blend_state(ctx, &blend);
494 ctx->bind_blend_state(ctx, handle);
495 }
496
497 {
498 struct pipe_depth_stencil_alpha_state depthstencil;
499 void *handle;
500 memset(&depthstencil, 0, sizeof depthstencil);
501 handle = ctx->create_depth_stencil_alpha_state(ctx, &depthstencil);
502 ctx->bind_depth_stencil_alpha_state(ctx, handle);
503 }
504
505 {
506 struct pipe_rasterizer_state rasterizer;
507 void *handle;
508 memset(&rasterizer, 0, sizeof rasterizer);
509 rasterizer.cull_face = PIPE_FACE_NONE;
510 rasterizer.gl_rasterization_rules = 1;
511 handle = ctx->create_rasterizer_state(ctx, &rasterizer);
512 ctx->bind_rasterizer_state(ctx, handle);
513 }
514
515 set_viewport(0, 0, WIDTH, HEIGHT, 30, 1000);
516
517 init_tex();
518 init_fs_constbuf();
519
520 set_vertices();
521 set_vertex_shader();
522 set_fragment_shader(filename);
523 }
524
525 static void args(int argc, char *argv[])
526 {
527 int i;
528
529 for (i = 1; i < argc; i++) {
530 if (strcmp(argv[i], "-fps") == 0) {
531 show_fps = 1;
532 }
533 else if (i == argc - 1) {
534 filename = argv[i];
535 }
536 else {
537 usage(argv[0]);
538 exit(1);
539 }
540 }
541
542 if (!filename) {
543 usage(argv[0]);
544 exit(1);
545 }
546 }
547
548 int main( int argc, char *argv[] )
549 {
550 args(argc,argv);
551 init();
552
553 graw_set_display_func( draw );
554 graw_main_loop();
555 return 0;
556 }