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