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