1848b8605Smrg/* 2848b8605Smrg * Test draw instancing. 3848b8605Smrg */ 4848b8605Smrg 5848b8605Smrg#include <stdio.h> 6848b8605Smrg#include <string.h> 7848b8605Smrg 8848b8605Smrg#include "state_tracker/graw.h" 9848b8605Smrg#include "pipe/p_screen.h" 10848b8605Smrg#include "pipe/p_context.h" 11848b8605Smrg#include "pipe/p_state.h" 12848b8605Smrg#include "pipe/p_defines.h" 13848b8605Smrg 14848b8605Smrg#include "util/u_memory.h" /* Offset() */ 15848b8605Smrg#include "util/u_draw_quad.h" 16848b8605Smrg#include "util/u_inlines.h" 17848b8605Smrg 18848b8605Smrg 19848b8605Smrgenum pipe_format formats[] = { 20848b8605Smrg PIPE_FORMAT_RGBA8888_UNORM, 21848b8605Smrg PIPE_FORMAT_BGRA8888_UNORM, 22848b8605Smrg PIPE_FORMAT_NONE 23848b8605Smrg}; 24848b8605Smrg 25848b8605Smrgstatic const int WIDTH = 300; 26848b8605Smrgstatic const int HEIGHT = 300; 27848b8605Smrg 28848b8605Smrgstatic struct pipe_screen *screen = NULL; 29848b8605Smrgstatic struct pipe_context *ctx = NULL; 30848b8605Smrgstatic struct pipe_surface *surf = NULL; 31848b8605Smrgstatic struct pipe_resource *tex = NULL; 32848b8605Smrgstatic void *window = NULL; 33848b8605Smrg 34848b8605Smrgstruct vertex { 35848b8605Smrg float position[4]; 36848b8605Smrg float color[4]; 37848b8605Smrg}; 38848b8605Smrg 39848b8605Smrg 40848b8605Smrgstatic int draw_elements = 0; 41848b8605Smrg 42848b8605Smrg 43848b8605Smrg/** 44848b8605Smrg * Vertex data. 45848b8605Smrg * Each vertex has three attributes: position, color and translation. 46848b8605Smrg * The translation attribute is a per-instance attribute. See 47848b8605Smrg * "instance_divisor" below. 48848b8605Smrg */ 49848b8605Smrgstatic struct vertex vertices[4] = 50848b8605Smrg{ 51848b8605Smrg { 52848b8605Smrg { 0.0f, -0.3f, 0.0f, 1.0f }, /* pos */ 53848b8605Smrg { 1.0f, 0.0f, 0.0f, 1.0f } /* color */ 54848b8605Smrg }, 55848b8605Smrg { 56848b8605Smrg { -0.2f, 0.3f, 0.0f, 1.0f }, 57848b8605Smrg { 0.0f, 1.0f, 0.0f, 1.0f } 58848b8605Smrg }, 59848b8605Smrg { 60848b8605Smrg { 0.2f, 0.3f, 0.0f, 1.0f }, 61848b8605Smrg { 0.0f, 0.0f, 1.0f, 1.0f } 62848b8605Smrg } 63848b8605Smrg}; 64848b8605Smrg 65848b8605Smrg 66848b8605Smrg#define NUM_INST 5 67848b8605Smrg 68848b8605Smrgstatic float inst_data[NUM_INST][4] = 69848b8605Smrg{ 70848b8605Smrg { -0.50f, 0.4f, 0.0f, 0.0f }, 71848b8605Smrg { -0.25f, 0.1f, 0.0f, 0.0f }, 72848b8605Smrg { 0.00f, 0.2f, 0.0f, 0.0f }, 73848b8605Smrg { 0.25f, 0.1f, 0.0f, 0.0f }, 74848b8605Smrg { 0.50f, 0.3f, 0.0f, 0.0f } 75848b8605Smrg}; 76848b8605Smrg 77848b8605Smrg 78848b8605Smrgstatic ushort indices[3] = { 0, 2, 1 }; 79848b8605Smrg 80848b8605Smrg 81848b8605Smrgstatic void set_viewport( float x, float y, 82848b8605Smrg float width, float height, 83b8e80941Smrg float zNear, float zFar) 84848b8605Smrg{ 85b8e80941Smrg float z = zFar; 86848b8605Smrg float half_width = (float)width / 2.0f; 87848b8605Smrg float half_height = (float)height / 2.0f; 88b8e80941Smrg float half_depth = ((float)zFar - (float)zNear) / 2.0f; 89848b8605Smrg struct pipe_viewport_state vp; 90848b8605Smrg 91848b8605Smrg vp.scale[0] = half_width; 92848b8605Smrg vp.scale[1] = half_height; 93848b8605Smrg vp.scale[2] = half_depth; 94848b8605Smrg 95848b8605Smrg vp.translate[0] = half_width + x; 96848b8605Smrg vp.translate[1] = half_height + y; 97848b8605Smrg vp.translate[2] = half_depth + z; 98848b8605Smrg 99848b8605Smrg ctx->set_viewport_states( ctx, 0, 1, &vp ); 100848b8605Smrg} 101848b8605Smrg 102848b8605Smrg 103848b8605Smrgstatic void set_vertices( void ) 104848b8605Smrg{ 105848b8605Smrg struct pipe_vertex_element ve[3]; 106848b8605Smrg struct pipe_vertex_buffer vbuf[2]; 107848b8605Smrg void *handle; 108848b8605Smrg 109848b8605Smrg memset(ve, 0, sizeof ve); 110848b8605Smrg 111848b8605Smrg /* pos */ 112848b8605Smrg ve[0].src_offset = Offset(struct vertex, position); 113848b8605Smrg ve[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; 114848b8605Smrg ve[0].vertex_buffer_index = 0; 115848b8605Smrg 116848b8605Smrg /* color */ 117848b8605Smrg ve[1].src_offset = Offset(struct vertex, color); 118848b8605Smrg ve[1].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; 119848b8605Smrg ve[1].vertex_buffer_index = 0; 120848b8605Smrg 121848b8605Smrg /* per-instance info */ 122848b8605Smrg ve[2].src_offset = 0; 123848b8605Smrg ve[2].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; 124848b8605Smrg ve[2].vertex_buffer_index = 1; 125848b8605Smrg ve[2].instance_divisor = 1; 126848b8605Smrg 127848b8605Smrg handle = ctx->create_vertex_elements_state(ctx, 3, ve); 128848b8605Smrg ctx->bind_vertex_elements_state(ctx, handle); 129848b8605Smrg 130848b8605Smrg memset(&vbuf, 0, sizeof vbuf); 131848b8605Smrg 132848b8605Smrg /* vertex data */ 133848b8605Smrg vbuf[0].stride = sizeof( struct vertex ); 134848b8605Smrg vbuf[0].buffer_offset = 0; 135b8e80941Smrg vbuf[0].buffer.resource = pipe_buffer_create_with_data(ctx, 136848b8605Smrg PIPE_BIND_VERTEX_BUFFER, 137848b8605Smrg PIPE_USAGE_DEFAULT, 138848b8605Smrg sizeof(vertices), 139848b8605Smrg vertices); 140848b8605Smrg 141848b8605Smrg /* instance data */ 142848b8605Smrg vbuf[1].stride = sizeof( inst_data[0] ); 143848b8605Smrg vbuf[1].buffer_offset = 0; 144b8e80941Smrg vbuf[1].buffer.resource = pipe_buffer_create_with_data(ctx, 145848b8605Smrg PIPE_BIND_VERTEX_BUFFER, 146848b8605Smrg PIPE_USAGE_DEFAULT, 147848b8605Smrg sizeof(inst_data), 148848b8605Smrg inst_data); 149848b8605Smrg 150848b8605Smrg ctx->set_vertex_buffers(ctx, 0, 2, vbuf); 151848b8605Smrg} 152848b8605Smrg 153848b8605Smrgstatic void set_vertex_shader( void ) 154848b8605Smrg{ 155848b8605Smrg void *handle; 156848b8605Smrg const char *text = 157848b8605Smrg "VERT\n" 158848b8605Smrg "DCL IN[0]\n" 159848b8605Smrg "DCL IN[1]\n" 160848b8605Smrg "DCL IN[2]\n" 161848b8605Smrg "DCL OUT[0], POSITION\n" 162848b8605Smrg "DCL OUT[1], COLOR\n" 163848b8605Smrg " 0: MOV OUT[1], IN[1]\n" 164848b8605Smrg " 1: ADD OUT[0], IN[0], IN[2]\n" /* add instance pos to vertex pos */ 165848b8605Smrg " 2: END\n"; 166848b8605Smrg 167848b8605Smrg handle = graw_parse_vertex_shader(ctx, text); 168848b8605Smrg ctx->bind_vs_state(ctx, handle); 169848b8605Smrg} 170848b8605Smrg 171848b8605Smrgstatic void set_fragment_shader( void ) 172848b8605Smrg{ 173848b8605Smrg void *handle; 174848b8605Smrg const char *text = 175848b8605Smrg "FRAG\n" 176848b8605Smrg "DCL IN[0], COLOR, LINEAR\n" 177848b8605Smrg "DCL OUT[0], COLOR\n" 178848b8605Smrg " 0: MOV OUT[0], IN[0]\n" 179848b8605Smrg " 1: END\n"; 180848b8605Smrg 181848b8605Smrg handle = graw_parse_fragment_shader(ctx, text); 182848b8605Smrg ctx->bind_fs_state(ctx, handle); 183848b8605Smrg} 184848b8605Smrg 185848b8605Smrg 186848b8605Smrgstatic void draw( void ) 187848b8605Smrg{ 188848b8605Smrg union pipe_color_union clear_color = { {1,0,1,1} }; 189848b8605Smrg struct pipe_draw_info info; 190848b8605Smrg 191848b8605Smrg ctx->clear(ctx, PIPE_CLEAR_COLOR, &clear_color, 0, 0); 192848b8605Smrg 193b8e80941Smrg 194848b8605Smrg util_draw_init_info(&info); 195b8e80941Smrg info.index_size = draw_elements ? 2 : 0; 196848b8605Smrg info.mode = PIPE_PRIM_TRIANGLES; 197848b8605Smrg info.start = 0; 198848b8605Smrg info.count = 3; 199848b8605Smrg /* draw NUM_INST triangles */ 200848b8605Smrg info.instance_count = NUM_INST; 201848b8605Smrg 202b8e80941Smrg /* index data */ 203b8e80941Smrg if (info.index_size) { 204b8e80941Smrg info.index.resource = 205b8e80941Smrg pipe_buffer_create_with_data(ctx, 206b8e80941Smrg PIPE_BIND_INDEX_BUFFER, 207b8e80941Smrg PIPE_USAGE_DEFAULT, 208b8e80941Smrg sizeof(indices), 209b8e80941Smrg indices); 210b8e80941Smrg } 211b8e80941Smrg 212848b8605Smrg ctx->draw_vbo(ctx, &info); 213848b8605Smrg 214b8e80941Smrg pipe_resource_reference(&info.index.resource, NULL); 215b8e80941Smrg 216848b8605Smrg ctx->flush(ctx, NULL, 0); 217848b8605Smrg 218848b8605Smrg graw_save_surface_to_file(ctx, surf, NULL); 219848b8605Smrg 220848b8605Smrg screen->flush_frontbuffer(screen, tex, 0, 0, window, NULL); 221848b8605Smrg} 222848b8605Smrg 223848b8605Smrg 224848b8605Smrgstatic void init( void ) 225848b8605Smrg{ 226848b8605Smrg struct pipe_framebuffer_state fb; 227848b8605Smrg struct pipe_resource templat; 228848b8605Smrg struct pipe_surface surf_tmpl; 229848b8605Smrg int i; 230848b8605Smrg 231848b8605Smrg /* It's hard to say whether window or screen should be created 232848b8605Smrg * first. Different environments would prefer one or the other. 233848b8605Smrg * 234848b8605Smrg * Also, no easy way of querying supported formats if the screen 235848b8605Smrg * cannot be created first. 236848b8605Smrg */ 237848b8605Smrg for (i = 0; formats[i] != PIPE_FORMAT_NONE; i++) { 238848b8605Smrg screen = graw_create_window_and_screen(0, 0, 300, 300, 239848b8605Smrg formats[i], 240848b8605Smrg &window); 241848b8605Smrg if (window && screen) 242848b8605Smrg break; 243848b8605Smrg } 244848b8605Smrg if (!screen || !window) { 245848b8605Smrg fprintf(stderr, "Unable to create window\n"); 246848b8605Smrg exit(1); 247848b8605Smrg } 248848b8605Smrg 249b8e80941Smrg ctx = screen->context_create(screen, NULL, 0); 250848b8605Smrg if (ctx == NULL) 251848b8605Smrg exit(3); 252848b8605Smrg 253b8e80941Smrg memset(&templat, 0, sizeof(templat)); 254848b8605Smrg templat.target = PIPE_TEXTURE_2D; 255848b8605Smrg templat.format = formats[i]; 256848b8605Smrg templat.width0 = WIDTH; 257848b8605Smrg templat.height0 = HEIGHT; 258848b8605Smrg templat.depth0 = 1; 259848b8605Smrg templat.array_size = 1; 260848b8605Smrg templat.last_level = 0; 261848b8605Smrg templat.bind = (PIPE_BIND_RENDER_TARGET | 262848b8605Smrg PIPE_BIND_DISPLAY_TARGET); 263848b8605Smrg 264848b8605Smrg tex = screen->resource_create(screen, 265848b8605Smrg &templat); 266848b8605Smrg if (tex == NULL) 267848b8605Smrg exit(4); 268848b8605Smrg 269848b8605Smrg surf_tmpl.format = templat.format; 270848b8605Smrg surf_tmpl.u.tex.level = 0; 271848b8605Smrg surf_tmpl.u.tex.first_layer = 0; 272848b8605Smrg surf_tmpl.u.tex.last_layer = 0; 273848b8605Smrg surf = ctx->create_surface(ctx, tex, &surf_tmpl); 274848b8605Smrg if (surf == NULL) 275848b8605Smrg exit(5); 276848b8605Smrg 277848b8605Smrg memset(&fb, 0, sizeof fb); 278848b8605Smrg fb.nr_cbufs = 1; 279848b8605Smrg fb.width = WIDTH; 280848b8605Smrg fb.height = HEIGHT; 281848b8605Smrg fb.cbufs[0] = surf; 282848b8605Smrg 283848b8605Smrg ctx->set_framebuffer_state(ctx, &fb); 284848b8605Smrg 285848b8605Smrg { 286848b8605Smrg struct pipe_blend_state blend; 287848b8605Smrg void *handle; 288848b8605Smrg memset(&blend, 0, sizeof blend); 289848b8605Smrg blend.rt[0].colormask = PIPE_MASK_RGBA; 290848b8605Smrg handle = ctx->create_blend_state(ctx, &blend); 291848b8605Smrg ctx->bind_blend_state(ctx, handle); 292848b8605Smrg } 293848b8605Smrg 294848b8605Smrg { 295848b8605Smrg struct pipe_depth_stencil_alpha_state depthstencil; 296848b8605Smrg void *handle; 297848b8605Smrg memset(&depthstencil, 0, sizeof depthstencil); 298848b8605Smrg handle = ctx->create_depth_stencil_alpha_state(ctx, &depthstencil); 299848b8605Smrg ctx->bind_depth_stencil_alpha_state(ctx, handle); 300848b8605Smrg } 301848b8605Smrg 302848b8605Smrg { 303848b8605Smrg struct pipe_rasterizer_state rasterizer; 304848b8605Smrg void *handle; 305848b8605Smrg memset(&rasterizer, 0, sizeof rasterizer); 306848b8605Smrg rasterizer.cull_face = PIPE_FACE_NONE; 307848b8605Smrg rasterizer.half_pixel_center = 1; 308848b8605Smrg rasterizer.bottom_edge_rule = 1; 309b8e80941Smrg rasterizer.depth_clip_near = 1; 310b8e80941Smrg rasterizer.depth_clip_far = 1; 311848b8605Smrg handle = ctx->create_rasterizer_state(ctx, &rasterizer); 312848b8605Smrg ctx->bind_rasterizer_state(ctx, handle); 313848b8605Smrg } 314848b8605Smrg 315848b8605Smrg set_viewport(0, 0, WIDTH, HEIGHT, 30, 1000); 316848b8605Smrg set_vertices(); 317848b8605Smrg set_vertex_shader(); 318848b8605Smrg set_fragment_shader(); 319848b8605Smrg} 320848b8605Smrg 321848b8605Smrg 322848b8605Smrgstatic void options(int argc, char *argv[]) 323848b8605Smrg{ 324848b8605Smrg int i; 325848b8605Smrg 326848b8605Smrg for (i = 1; i < argc;) { 327848b8605Smrg if (graw_parse_args(&i, argc, argv)) { 328848b8605Smrg continue; 329848b8605Smrg } 330848b8605Smrg if (strcmp(argv[i], "-e") == 0) { 331848b8605Smrg draw_elements = 1; 332848b8605Smrg i++; 333848b8605Smrg } 334848b8605Smrg else { 335848b8605Smrg i++; 336848b8605Smrg } 337848b8605Smrg } 338848b8605Smrg if (draw_elements) 339848b8605Smrg printf("Using pipe_context::draw_elements_instanced()\n"); 340848b8605Smrg else 341848b8605Smrg printf("Using pipe_context::draw_arrays_instanced()\n"); 342848b8605Smrg} 343848b8605Smrg 344848b8605Smrg 345848b8605Smrgint main( int argc, char *argv[] ) 346848b8605Smrg{ 347848b8605Smrg options(argc, argv); 348848b8605Smrg 349848b8605Smrg init(); 350848b8605Smrg 351848b8605Smrg graw_set_display_func( draw ); 352848b8605Smrg graw_main_loop(); 353848b8605Smrg return 0; 354848b8605Smrg} 355