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