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 "frontend/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, false,
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, false,
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 vp.swizzle_x = PIPE_VIEWPORT_SWIZZLE_POSITIVE_X;
152 vp.swizzle_y = PIPE_VIEWPORT_SWIZZLE_POSITIVE_Y;
153 vp.swizzle_z = PIPE_VIEWPORT_SWIZZLE_POSITIVE_Z;
154 vp.swizzle_w = PIPE_VIEWPORT_SWIZZLE_POSITIVE_W;
155
156 ctx->set_viewport_states( ctx, 0, 1, &vp );
157 }
158
set_vertices(void)159 static void set_vertices( void )
160 {
161 struct pipe_vertex_element ve[3];
162 struct pipe_vertex_buffer vbuf;
163 void *handle;
164
165 memset(ve, 0, sizeof ve);
166
167 ve[0].src_offset = Offset(struct vertex, position);
168 ve[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
169 ve[1].src_offset = Offset(struct vertex, color);
170 ve[1].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
171 ve[2].src_offset = Offset(struct vertex, texcoord);
172 ve[2].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
173
174 handle = ctx->create_vertex_elements_state(ctx, 3, ve);
175 ctx->bind_vertex_elements_state(ctx, handle);
176
177 memset(&vbuf, 0, sizeof vbuf);
178
179 vbuf.stride = sizeof( struct vertex );
180 vbuf.buffer_offset = 0;
181 vbuf.buffer.resource = pipe_buffer_create_with_data(ctx,
182 PIPE_BIND_VERTEX_BUFFER,
183 PIPE_USAGE_DEFAULT,
184 sizeof(vertices),
185 vertices);
186
187 ctx->set_vertex_buffers(ctx, 0, 1, 0, false, &vbuf);
188 }
189
set_vertex_shader(void)190 static void set_vertex_shader( void )
191 {
192 void *handle;
193 const char *text =
194 "VERT\n"
195 "DCL IN[0]\n"
196 "DCL IN[1]\n"
197 "DCL IN[2]\n"
198 "DCL OUT[0], POSITION\n"
199 "DCL OUT[1], COLOR[0]\n"
200 "DCL OUT[2], GENERIC[0]\n"
201 " MOV OUT[0], IN[0]\n"
202 " MOV OUT[1], IN[1]\n"
203 " MOV OUT[2], IN[2]\n"
204 " END\n";
205
206 handle = graw_parse_vertex_shader(ctx, text);
207 ctx->bind_vs_state(ctx, handle);
208 }
209
set_fragment_shader(const char * filename)210 static void set_fragment_shader( const char *filename )
211 {
212 FILE *f;
213 char buf[50000];
214 void *handle;
215 int sz;
216
217 if ((f = fopen(filename, "r")) == NULL) {
218 fprintf(stderr, "Couldn't open %s\n", filename);
219 exit(1);
220 }
221
222 sz = fread(buf, 1, sizeof(buf), f);
223 if (!feof(f)) {
224 printf("file too long\n");
225 exit(1);
226 }
227 printf("%.*s\n", sz, buf);
228 buf[sz] = 0;
229
230 handle = graw_parse_fragment_shader(ctx, buf);
231 ctx->bind_fs_state(ctx, handle);
232 fclose(f);
233 }
234
235
draw(void)236 static void draw( void )
237 {
238 union pipe_color_union clear_color = { {.1,.3,.5,0} };
239
240 ctx->clear(ctx, PIPE_CLEAR_COLOR, NULL, &clear_color, 0, 0);
241 util_draw_arrays(ctx, PIPE_PRIM_TRIANGLES, 0, 3);
242 ctx->flush(ctx, NULL, 0);
243
244 graw_save_surface_to_file(ctx, surf, NULL);
245
246 screen->flush_frontbuffer(screen, ctx, rttex, 0, 0, window, NULL);
247 }
248
249 #define SIZE 16
250
init_tex(void)251 static void init_tex( void )
252 {
253 struct pipe_sampler_view sv_template;
254 struct pipe_sampler_state sampler_desc;
255 struct pipe_resource templat;
256 struct pipe_box box;
257 ubyte tex2d[SIZE][SIZE][4];
258 int s, t;
259
260 #if (SIZE != 2)
261 for (s = 0; s < SIZE; s++) {
262 for (t = 0; t < SIZE; t++) {
263 if (0) {
264 int x = (s ^ t) & 1;
265 tex2d[t][s][0] = (x) ? 0 : 63;
266 tex2d[t][s][1] = (x) ? 0 : 128;
267 tex2d[t][s][2] = 0;
268 tex2d[t][s][3] = 0xff;
269 }
270 else {
271 int x = ((s ^ t) >> 2) & 1;
272 tex2d[t][s][0] = s*255/(SIZE-1);
273 tex2d[t][s][1] = t*255/(SIZE-1);
274 tex2d[t][s][2] = (x) ? 0 : 128;
275 tex2d[t][s][3] = 0xff;
276 }
277 }
278 }
279 #else
280 tex2d[0][0][0] = 0;
281 tex2d[0][0][1] = 255;
282 tex2d[0][0][2] = 255;
283 tex2d[0][0][3] = 0;
284
285 tex2d[0][1][0] = 0;
286 tex2d[0][1][1] = 0;
287 tex2d[0][1][2] = 255;
288 tex2d[0][1][3] = 255;
289
290 tex2d[1][0][0] = 255;
291 tex2d[1][0][1] = 255;
292 tex2d[1][0][2] = 0;
293 tex2d[1][0][3] = 255;
294
295 tex2d[1][1][0] = 255;
296 tex2d[1][1][1] = 0;
297 tex2d[1][1][2] = 0;
298 tex2d[1][1][3] = 255;
299 #endif
300
301 memset(&templat, 0, sizeof(templat));
302 templat.target = PIPE_TEXTURE_2D;
303 templat.format = PIPE_FORMAT_B8G8R8A8_UNORM;
304 templat.width0 = SIZE;
305 templat.height0 = SIZE;
306 templat.depth0 = 1;
307 templat.array_size = 1;
308 templat.last_level = 0;
309 templat.bind = PIPE_BIND_SAMPLER_VIEW;
310
311
312 samptex = screen->resource_create(screen,
313 &templat);
314 if (samptex == NULL)
315 exit(4);
316
317 u_box_2d(0,0,SIZE,SIZE, &box);
318
319 ctx->texture_subdata(ctx,
320 samptex,
321 0,
322 PIPE_MAP_WRITE,
323 &box,
324 tex2d,
325 sizeof tex2d[0],
326 sizeof tex2d);
327
328 /* Possibly read back & compare against original data:
329 */
330 if (0)
331 {
332 struct pipe_transfer *t;
333 uint32_t *ptr;
334 ptr = pipe_texture_map(ctx, samptex,
335 0, 0, /* level, layer */
336 PIPE_MAP_READ,
337 0, 0, SIZE, SIZE, &t); /* x, y, width, height */
338
339 if (memcmp(ptr, tex2d, sizeof tex2d) != 0) {
340 assert(0);
341 exit(9);
342 }
343
344 ctx->texture_unmap(ctx, t);
345 }
346
347 memset(&sv_template, 0, sizeof sv_template);
348 sv_template.format = samptex->format;
349 sv_template.texture = samptex;
350 sv_template.swizzle_r = 0;
351 sv_template.swizzle_g = 1;
352 sv_template.swizzle_b = 2;
353 sv_template.swizzle_a = 3;
354 sv = ctx->create_sampler_view(ctx, samptex, &sv_template);
355 if (sv == NULL)
356 exit(5);
357
358 ctx->set_sampler_views(ctx, PIPE_SHADER_FRAGMENT, 0, 1, 0, false, &sv);
359
360
361 memset(&sampler_desc, 0, sizeof sampler_desc);
362 sampler_desc.wrap_s = PIPE_TEX_WRAP_REPEAT;
363 sampler_desc.wrap_t = PIPE_TEX_WRAP_REPEAT;
364 sampler_desc.wrap_r = PIPE_TEX_WRAP_REPEAT;
365 sampler_desc.min_img_filter = PIPE_TEX_FILTER_NEAREST;
366 sampler_desc.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
367 sampler_desc.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
368 sampler_desc.compare_mode = PIPE_TEX_COMPARE_NONE;
369 sampler_desc.compare_func = 0;
370 sampler_desc.normalized_coords = 1;
371 sampler_desc.max_anisotropy = 0;
372
373 sampler = ctx->create_sampler_state(ctx, &sampler_desc);
374 if (sampler == NULL)
375 exit(6);
376
377 ctx->bind_sampler_states(ctx, PIPE_SHADER_FRAGMENT, 0, 1, &sampler);
378
379 }
380
init(void)381 static void init( void )
382 {
383 struct pipe_framebuffer_state fb;
384 struct pipe_resource templat;
385 struct pipe_surface surf_tmpl;
386 int i;
387
388 /* It's hard to say whether window or screen should be created
389 * first. Different environments would prefer one or the other.
390 *
391 * Also, no easy way of querying supported formats if the screen
392 * cannot be created first.
393 */
394 for (i = 0; formats[i] != PIPE_FORMAT_NONE; i++) {
395 screen = graw_create_window_and_screen(0, 0, 300, 300,
396 formats[i],
397 &window);
398 if (window && screen)
399 break;
400 }
401 if (!screen || !window) {
402 fprintf(stderr, "Unable to create window\n");
403 exit(1);
404 }
405
406 ctx = screen->context_create(screen, NULL, 0);
407 if (ctx == NULL)
408 exit(3);
409
410 memset(&templat, 0, sizeof(templat));
411 templat.target = PIPE_TEXTURE_2D;
412 templat.format = formats[i];
413 templat.width0 = WIDTH;
414 templat.height0 = HEIGHT;
415 templat.depth0 = 1;
416 templat.array_size = 1;
417 templat.last_level = 0;
418 templat.bind = (PIPE_BIND_RENDER_TARGET |
419 PIPE_BIND_DISPLAY_TARGET);
420
421 rttex = screen->resource_create(screen,
422 &templat);
423 if (rttex == NULL)
424 exit(4);
425
426 surf_tmpl.format = templat.format;
427 surf_tmpl.u.tex.level = 0;
428 surf_tmpl.u.tex.first_layer = 0;
429 surf_tmpl.u.tex.last_layer = 0;
430 surf = ctx->create_surface(ctx, rttex, &surf_tmpl);
431 if (surf == NULL)
432 exit(5);
433
434 memset(&fb, 0, sizeof fb);
435 fb.nr_cbufs = 1;
436 fb.width = WIDTH;
437 fb.height = HEIGHT;
438 fb.cbufs[0] = surf;
439
440 ctx->set_framebuffer_state(ctx, &fb);
441
442 {
443 struct pipe_blend_state blend;
444 void *handle;
445 memset(&blend, 0, sizeof blend);
446 blend.rt[0].colormask = PIPE_MASK_RGBA;
447 handle = ctx->create_blend_state(ctx, &blend);
448 ctx->bind_blend_state(ctx, handle);
449 }
450
451 {
452 struct pipe_depth_stencil_alpha_state depthstencil;
453 void *handle;
454 memset(&depthstencil, 0, sizeof depthstencil);
455 handle = ctx->create_depth_stencil_alpha_state(ctx, &depthstencil);
456 ctx->bind_depth_stencil_alpha_state(ctx, handle);
457 }
458
459 {
460 struct pipe_rasterizer_state rasterizer;
461 void *handle;
462 memset(&rasterizer, 0, sizeof rasterizer);
463 rasterizer.cull_face = PIPE_FACE_NONE;
464 rasterizer.half_pixel_center = 1;
465 rasterizer.bottom_edge_rule = 1;
466 rasterizer.depth_clip_near = 1;
467 rasterizer.depth_clip_far = 1;
468 handle = ctx->create_rasterizer_state(ctx, &rasterizer);
469 ctx->bind_rasterizer_state(ctx, handle);
470 }
471
472 set_viewport(0, 0, WIDTH, HEIGHT, 30, 1000);
473
474 init_tex();
475 init_fs_constbuf();
476
477 set_vertices();
478 set_vertex_shader();
479 set_fragment_shader(filename);
480 }
481
args(int argc,char * argv[])482 static void args(int argc, char *argv[])
483 {
484 int i;
485
486 for (i = 1; i < argc;) {
487 if (graw_parse_args(&i, argc, argv)) {
488 continue;
489 }
490 if (strcmp(argv[i], "-fps") == 0) {
491 show_fps = 1;
492 i++;
493 }
494 else if (i == argc - 1) {
495 filename = argv[i];
496 i++;
497 }
498 else {
499 usage(argv[0]);
500 exit(1);
501 }
502 }
503
504 if (!filename) {
505 usage(argv[0]);
506 exit(1);
507 }
508 }
509
main(int argc,char * argv[])510 int main( int argc, char *argv[] )
511 {
512 args(argc,argv);
513 init();
514
515 graw_set_display_func( draw );
516 graw_main_loop();
517 return 0;
518 }
519