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
usage(char * name)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
init_fs_constbuf(void)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
set_viewport(float x,float y,float width,float height,float zNear,float zFar)133 static void set_viewport( float x, float y,
134 float width, float height,
135 float zNear, float zFar)
136 {
137 float z = zFar;
138 float half_width = (float)width / 2.0f;
139 float half_height = (float)height / 2.0f;
140 float half_depth = ((float)zFar - (float)zNear) / 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
147 vp.translate[0] = half_width + x;
148 vp.translate[1] = half_height + y;
149 vp.translate[2] = half_depth + z;
150
151 ctx->set_viewport_states( ctx, 0, 1, &vp );
152 }
153
set_vertices(void)154 static void set_vertices( void )
155 {
156 struct pipe_vertex_element ve[3];
157 struct pipe_vertex_buffer vbuf;
158 void *handle;
159
160 memset(ve, 0, sizeof ve);
161
162 ve[0].src_offset = Offset(struct vertex, position);
163 ve[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
164 ve[1].src_offset = Offset(struct vertex, color);
165 ve[1].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
166 ve[2].src_offset = Offset(struct vertex, texcoord);
167 ve[2].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
168
169 handle = ctx->create_vertex_elements_state(ctx, 3, ve);
170 ctx->bind_vertex_elements_state(ctx, handle);
171
172 memset(&vbuf, 0, sizeof vbuf);
173
174 vbuf.stride = sizeof( struct vertex );
175 vbuf.buffer_offset = 0;
176 vbuf.buffer = pipe_buffer_create_with_data(ctx,
177 PIPE_BIND_VERTEX_BUFFER,
178 PIPE_USAGE_DEFAULT,
179 sizeof(vertices),
180 vertices);
181
182 ctx->set_vertex_buffers(ctx, 0, 1, &vbuf);
183 }
184
set_vertex_shader(void)185 static void set_vertex_shader( void )
186 {
187 void *handle;
188 const char *text =
189 "VERT\n"
190 "DCL IN[0]\n"
191 "DCL IN[1]\n"
192 "DCL IN[2]\n"
193 "DCL OUT[0], POSITION\n"
194 "DCL OUT[1], COLOR[0]\n"
195 "DCL OUT[2], GENERIC[0]\n"
196 " MOV OUT[0], IN[0]\n"
197 " MOV OUT[1], IN[1]\n"
198 " MOV OUT[2], IN[2]\n"
199 " END\n";
200
201 handle = graw_parse_vertex_shader(ctx, text);
202 ctx->bind_vs_state(ctx, handle);
203 }
204
set_fragment_shader(const char * filename)205 static void set_fragment_shader( const char *filename )
206 {
207 FILE *f;
208 char buf[50000];
209 void *handle;
210 int sz;
211
212 if ((f = fopen(filename, "r")) == NULL) {
213 fprintf(stderr, "Couldn't open %s\n", filename);
214 exit(1);
215 }
216
217 sz = fread(buf, 1, sizeof(buf), f);
218 if (!feof(f)) {
219 printf("file too long\n");
220 exit(1);
221 }
222 printf("%.*s\n", sz, buf);
223 buf[sz] = 0;
224
225 handle = graw_parse_fragment_shader(ctx, buf);
226 ctx->bind_fs_state(ctx, handle);
227 fclose(f);
228 }
229
230
draw(void)231 static void draw( void )
232 {
233 union pipe_color_union clear_color = { {.1,.3,.5,0} };
234
235 ctx->clear(ctx, PIPE_CLEAR_COLOR, &clear_color, 0, 0);
236 util_draw_arrays(ctx, PIPE_PRIM_TRIANGLES, 0, 3);
237 ctx->flush(ctx, NULL, 0);
238
239 graw_save_surface_to_file(ctx, surf, NULL);
240
241 screen->flush_frontbuffer(screen, rttex, 0, 0, window, NULL);
242 }
243
244 #define SIZE 16
245
init_tex(void)246 static void init_tex( void )
247 {
248 struct pipe_sampler_view sv_template;
249 struct pipe_sampler_state sampler_desc;
250 struct pipe_resource templat;
251 struct pipe_box box;
252 ubyte tex2d[SIZE][SIZE][4];
253 int s, t;
254
255 #if (SIZE != 2)
256 for (s = 0; s < SIZE; s++) {
257 for (t = 0; t < SIZE; t++) {
258 if (0) {
259 int x = (s ^ t) & 1;
260 tex2d[t][s][0] = (x) ? 0 : 63;
261 tex2d[t][s][1] = (x) ? 0 : 128;
262 tex2d[t][s][2] = 0;
263 tex2d[t][s][3] = 0xff;
264 }
265 else {
266 int x = ((s ^ t) >> 2) & 1;
267 tex2d[t][s][0] = s*255/(SIZE-1);
268 tex2d[t][s][1] = t*255/(SIZE-1);
269 tex2d[t][s][2] = (x) ? 0 : 128;
270 tex2d[t][s][3] = 0xff;
271 }
272 }
273 }
274 #else
275 tex2d[0][0][0] = 0;
276 tex2d[0][0][1] = 255;
277 tex2d[0][0][2] = 255;
278 tex2d[0][0][3] = 0;
279
280 tex2d[0][1][0] = 0;
281 tex2d[0][1][1] = 0;
282 tex2d[0][1][2] = 255;
283 tex2d[0][1][3] = 255;
284
285 tex2d[1][0][0] = 255;
286 tex2d[1][0][1] = 255;
287 tex2d[1][0][2] = 0;
288 tex2d[1][0][3] = 255;
289
290 tex2d[1][1][0] = 255;
291 tex2d[1][1][1] = 0;
292 tex2d[1][1][2] = 0;
293 tex2d[1][1][3] = 255;
294 #endif
295
296 memset(&templat, 0, sizeof(templat));
297 templat.target = PIPE_TEXTURE_2D;
298 templat.format = PIPE_FORMAT_B8G8R8A8_UNORM;
299 templat.width0 = SIZE;
300 templat.height0 = SIZE;
301 templat.depth0 = 1;
302 templat.array_size = 1;
303 templat.last_level = 0;
304 templat.nr_samples = 1;
305 templat.bind = PIPE_BIND_SAMPLER_VIEW;
306
307
308 samptex = screen->resource_create(screen,
309 &templat);
310 if (samptex == NULL)
311 exit(4);
312
313 u_box_2d(0,0,SIZE,SIZE, &box);
314
315 ctx->texture_subdata(ctx,
316 samptex,
317 0,
318 PIPE_TRANSFER_WRITE,
319 &box,
320 tex2d,
321 sizeof tex2d[0],
322 sizeof tex2d);
323
324 /* Possibly read back & compare against original data:
325 */
326 if (0)
327 {
328 struct pipe_transfer *t;
329 uint32_t *ptr;
330 ptr = pipe_transfer_map(ctx, samptex,
331 0, 0, /* level, layer */
332 PIPE_TRANSFER_READ,
333 0, 0, SIZE, SIZE, &t); /* x, y, width, height */
334
335 if (memcmp(ptr, tex2d, sizeof tex2d) != 0) {
336 assert(0);
337 exit(9);
338 }
339
340 ctx->transfer_unmap(ctx, t);
341 }
342
343 memset(&sv_template, 0, sizeof sv_template);
344 sv_template.format = samptex->format;
345 sv_template.texture = samptex;
346 sv_template.swizzle_r = 0;
347 sv_template.swizzle_g = 1;
348 sv_template.swizzle_b = 2;
349 sv_template.swizzle_a = 3;
350 sv = ctx->create_sampler_view(ctx, samptex, &sv_template);
351 if (sv == NULL)
352 exit(5);
353
354 ctx->set_sampler_views(ctx, PIPE_SHADER_FRAGMENT, 0, 1, &sv);
355
356
357 memset(&sampler_desc, 0, sizeof sampler_desc);
358 sampler_desc.wrap_s = PIPE_TEX_WRAP_REPEAT;
359 sampler_desc.wrap_t = PIPE_TEX_WRAP_REPEAT;
360 sampler_desc.wrap_r = PIPE_TEX_WRAP_REPEAT;
361 sampler_desc.min_img_filter = PIPE_TEX_FILTER_NEAREST;
362 sampler_desc.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
363 sampler_desc.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
364 sampler_desc.compare_mode = PIPE_TEX_COMPARE_NONE;
365 sampler_desc.compare_func = 0;
366 sampler_desc.normalized_coords = 1;
367 sampler_desc.max_anisotropy = 0;
368
369 sampler = ctx->create_sampler_state(ctx, &sampler_desc);
370 if (sampler == NULL)
371 exit(6);
372
373 ctx->bind_sampler_states(ctx, PIPE_SHADER_FRAGMENT, 0, 1, &sampler);
374
375 }
376
init(void)377 static void init( void )
378 {
379 struct pipe_framebuffer_state fb;
380 struct pipe_resource templat;
381 struct pipe_surface surf_tmpl;
382 int i;
383
384 /* It's hard to say whether window or screen should be created
385 * first. Different environments would prefer one or the other.
386 *
387 * Also, no easy way of querying supported formats if the screen
388 * cannot be created first.
389 */
390 for (i = 0; formats[i] != PIPE_FORMAT_NONE; i++) {
391 screen = graw_create_window_and_screen(0, 0, 300, 300,
392 formats[i],
393 &window);
394 if (window && screen)
395 break;
396 }
397 if (!screen || !window) {
398 fprintf(stderr, "Unable to create window\n");
399 exit(1);
400 }
401
402 ctx = screen->context_create(screen, NULL, 0);
403 if (ctx == NULL)
404 exit(3);
405
406 memset(&templat, 0, sizeof(templat));
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
args(int argc,char * argv[])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
main(int argc,char * argv[])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 }
515