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