13464ebd5Sriastradh/* 23464ebd5Sriastradh * Test draw instancing. 33464ebd5Sriastradh */ 43464ebd5Sriastradh 53464ebd5Sriastradh#include <stdio.h> 63464ebd5Sriastradh#include <string.h> 73464ebd5Sriastradh 87ec681f3Smrg#include "frontend/graw.h" 93464ebd5Sriastradh#include "pipe/p_screen.h" 103464ebd5Sriastradh#include "pipe/p_context.h" 113464ebd5Sriastradh#include "pipe/p_state.h" 123464ebd5Sriastradh#include "pipe/p_defines.h" 133464ebd5Sriastradh 143464ebd5Sriastradh#include "util/u_memory.h" /* Offset() */ 153464ebd5Sriastradh#include "util/u_draw_quad.h" 16af69d88dSmrg#include "util/u_inlines.h" 173464ebd5Sriastradh 183464ebd5Sriastradh 193464ebd5Sriastradhenum pipe_format formats[] = { 20af69d88dSmrg PIPE_FORMAT_RGBA8888_UNORM, 21af69d88dSmrg PIPE_FORMAT_BGRA8888_UNORM, 223464ebd5Sriastradh PIPE_FORMAT_NONE 233464ebd5Sriastradh}; 243464ebd5Sriastradh 253464ebd5Sriastradhstatic const int WIDTH = 300; 263464ebd5Sriastradhstatic const int HEIGHT = 300; 273464ebd5Sriastradh 283464ebd5Sriastradhstatic struct pipe_screen *screen = NULL; 293464ebd5Sriastradhstatic struct pipe_context *ctx = NULL; 303464ebd5Sriastradhstatic struct pipe_surface *surf = NULL; 313464ebd5Sriastradhstatic struct pipe_resource *tex = NULL; 323464ebd5Sriastradhstatic void *window = NULL; 333464ebd5Sriastradh 343464ebd5Sriastradhstruct vertex { 353464ebd5Sriastradh float position[4]; 363464ebd5Sriastradh float color[4]; 373464ebd5Sriastradh}; 383464ebd5Sriastradh 393464ebd5Sriastradh 403464ebd5Sriastradhstatic int draw_elements = 0; 413464ebd5Sriastradh 423464ebd5Sriastradh 433464ebd5Sriastradh/** 443464ebd5Sriastradh * Vertex data. 453464ebd5Sriastradh * Each vertex has three attributes: position, color and translation. 463464ebd5Sriastradh * The translation attribute is a per-instance attribute. See 473464ebd5Sriastradh * "instance_divisor" below. 483464ebd5Sriastradh */ 493464ebd5Sriastradhstatic struct vertex vertices[4] = 503464ebd5Sriastradh{ 513464ebd5Sriastradh { 523464ebd5Sriastradh { 0.0f, -0.3f, 0.0f, 1.0f }, /* pos */ 533464ebd5Sriastradh { 1.0f, 0.0f, 0.0f, 1.0f } /* color */ 543464ebd5Sriastradh }, 553464ebd5Sriastradh { 563464ebd5Sriastradh { -0.2f, 0.3f, 0.0f, 1.0f }, 573464ebd5Sriastradh { 0.0f, 1.0f, 0.0f, 1.0f } 583464ebd5Sriastradh }, 593464ebd5Sriastradh { 603464ebd5Sriastradh { 0.2f, 0.3f, 0.0f, 1.0f }, 613464ebd5Sriastradh { 0.0f, 0.0f, 1.0f, 1.0f } 623464ebd5Sriastradh } 633464ebd5Sriastradh}; 643464ebd5Sriastradh 653464ebd5Sriastradh 663464ebd5Sriastradh#define NUM_INST 5 673464ebd5Sriastradh 683464ebd5Sriastradhstatic float inst_data[NUM_INST][4] = 693464ebd5Sriastradh{ 703464ebd5Sriastradh { -0.50f, 0.4f, 0.0f, 0.0f }, 713464ebd5Sriastradh { -0.25f, 0.1f, 0.0f, 0.0f }, 723464ebd5Sriastradh { 0.00f, 0.2f, 0.0f, 0.0f }, 733464ebd5Sriastradh { 0.25f, 0.1f, 0.0f, 0.0f }, 743464ebd5Sriastradh { 0.50f, 0.3f, 0.0f, 0.0f } 753464ebd5Sriastradh}; 763464ebd5Sriastradh 773464ebd5Sriastradh 783464ebd5Sriastradhstatic ushort indices[3] = { 0, 2, 1 }; 793464ebd5Sriastradh 803464ebd5Sriastradh 813464ebd5Sriastradhstatic void set_viewport( float x, float y, 823464ebd5Sriastradh float width, float height, 8301e04c3fSmrg float zNear, float zFar) 843464ebd5Sriastradh{ 8501e04c3fSmrg float z = zFar; 863464ebd5Sriastradh float half_width = (float)width / 2.0f; 873464ebd5Sriastradh float half_height = (float)height / 2.0f; 8801e04c3fSmrg float half_depth = ((float)zFar - (float)zNear) / 2.0f; 893464ebd5Sriastradh struct pipe_viewport_state vp; 903464ebd5Sriastradh 913464ebd5Sriastradh vp.scale[0] = half_width; 923464ebd5Sriastradh vp.scale[1] = half_height; 933464ebd5Sriastradh vp.scale[2] = half_depth; 943464ebd5Sriastradh 953464ebd5Sriastradh vp.translate[0] = half_width + x; 963464ebd5Sriastradh vp.translate[1] = half_height + y; 973464ebd5Sriastradh vp.translate[2] = half_depth + z; 983464ebd5Sriastradh 997ec681f3Smrg vp.swizzle_x = PIPE_VIEWPORT_SWIZZLE_POSITIVE_X; 1007ec681f3Smrg vp.swizzle_y = PIPE_VIEWPORT_SWIZZLE_POSITIVE_Y; 1017ec681f3Smrg vp.swizzle_z = PIPE_VIEWPORT_SWIZZLE_POSITIVE_Z; 1027ec681f3Smrg vp.swizzle_w = PIPE_VIEWPORT_SWIZZLE_POSITIVE_W; 1037ec681f3Smrg 104af69d88dSmrg ctx->set_viewport_states( ctx, 0, 1, &vp ); 1053464ebd5Sriastradh} 1063464ebd5Sriastradh 1073464ebd5Sriastradh 1083464ebd5Sriastradhstatic void set_vertices( void ) 1093464ebd5Sriastradh{ 1103464ebd5Sriastradh struct pipe_vertex_element ve[3]; 1113464ebd5Sriastradh struct pipe_vertex_buffer vbuf[2]; 1123464ebd5Sriastradh void *handle; 1133464ebd5Sriastradh 1143464ebd5Sriastradh memset(ve, 0, sizeof ve); 1153464ebd5Sriastradh 1163464ebd5Sriastradh /* pos */ 1173464ebd5Sriastradh ve[0].src_offset = Offset(struct vertex, position); 1183464ebd5Sriastradh ve[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; 1193464ebd5Sriastradh ve[0].vertex_buffer_index = 0; 1203464ebd5Sriastradh 1213464ebd5Sriastradh /* color */ 1223464ebd5Sriastradh ve[1].src_offset = Offset(struct vertex, color); 1233464ebd5Sriastradh ve[1].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; 1243464ebd5Sriastradh ve[1].vertex_buffer_index = 0; 1253464ebd5Sriastradh 1263464ebd5Sriastradh /* per-instance info */ 1273464ebd5Sriastradh ve[2].src_offset = 0; 1283464ebd5Sriastradh ve[2].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; 1293464ebd5Sriastradh ve[2].vertex_buffer_index = 1; 1303464ebd5Sriastradh ve[2].instance_divisor = 1; 1313464ebd5Sriastradh 1323464ebd5Sriastradh handle = ctx->create_vertex_elements_state(ctx, 3, ve); 1333464ebd5Sriastradh ctx->bind_vertex_elements_state(ctx, handle); 1343464ebd5Sriastradh 135af69d88dSmrg memset(&vbuf, 0, sizeof vbuf); 1363464ebd5Sriastradh 1373464ebd5Sriastradh /* vertex data */ 1383464ebd5Sriastradh vbuf[0].stride = sizeof( struct vertex ); 1393464ebd5Sriastradh vbuf[0].buffer_offset = 0; 14001e04c3fSmrg vbuf[0].buffer.resource = pipe_buffer_create_with_data(ctx, 141af69d88dSmrg PIPE_BIND_VERTEX_BUFFER, 142af69d88dSmrg PIPE_USAGE_DEFAULT, 143af69d88dSmrg sizeof(vertices), 144af69d88dSmrg vertices); 1453464ebd5Sriastradh 1463464ebd5Sriastradh /* instance data */ 1473464ebd5Sriastradh vbuf[1].stride = sizeof( inst_data[0] ); 1483464ebd5Sriastradh vbuf[1].buffer_offset = 0; 14901e04c3fSmrg vbuf[1].buffer.resource = pipe_buffer_create_with_data(ctx, 150af69d88dSmrg PIPE_BIND_VERTEX_BUFFER, 151af69d88dSmrg PIPE_USAGE_DEFAULT, 152af69d88dSmrg sizeof(inst_data), 153af69d88dSmrg inst_data); 1543464ebd5Sriastradh 1557ec681f3Smrg ctx->set_vertex_buffers(ctx, 0, 2, 0, false, vbuf); 1563464ebd5Sriastradh} 1573464ebd5Sriastradh 1583464ebd5Sriastradhstatic void set_vertex_shader( void ) 1593464ebd5Sriastradh{ 1603464ebd5Sriastradh void *handle; 1613464ebd5Sriastradh const char *text = 1623464ebd5Sriastradh "VERT\n" 1633464ebd5Sriastradh "DCL IN[0]\n" 1643464ebd5Sriastradh "DCL IN[1]\n" 1653464ebd5Sriastradh "DCL IN[2]\n" 1663464ebd5Sriastradh "DCL OUT[0], POSITION\n" 1673464ebd5Sriastradh "DCL OUT[1], COLOR\n" 1683464ebd5Sriastradh " 0: MOV OUT[1], IN[1]\n" 1693464ebd5Sriastradh " 1: ADD OUT[0], IN[0], IN[2]\n" /* add instance pos to vertex pos */ 1703464ebd5Sriastradh " 2: END\n"; 1713464ebd5Sriastradh 1723464ebd5Sriastradh handle = graw_parse_vertex_shader(ctx, text); 1733464ebd5Sriastradh ctx->bind_vs_state(ctx, handle); 1743464ebd5Sriastradh} 1753464ebd5Sriastradh 1763464ebd5Sriastradhstatic void set_fragment_shader( void ) 1773464ebd5Sriastradh{ 1783464ebd5Sriastradh void *handle; 1793464ebd5Sriastradh const char *text = 1803464ebd5Sriastradh "FRAG\n" 1813464ebd5Sriastradh "DCL IN[0], COLOR, LINEAR\n" 1823464ebd5Sriastradh "DCL OUT[0], COLOR\n" 1833464ebd5Sriastradh " 0: MOV OUT[0], IN[0]\n" 1843464ebd5Sriastradh " 1: END\n"; 1853464ebd5Sriastradh 1863464ebd5Sriastradh handle = graw_parse_fragment_shader(ctx, text); 1873464ebd5Sriastradh ctx->bind_fs_state(ctx, handle); 1883464ebd5Sriastradh} 1893464ebd5Sriastradh 1903464ebd5Sriastradh 1913464ebd5Sriastradhstatic void draw( void ) 1923464ebd5Sriastradh{ 193af69d88dSmrg union pipe_color_union clear_color = { {1,0,1,1} }; 1943464ebd5Sriastradh struct pipe_draw_info info; 1957ec681f3Smrg struct pipe_draw_start_count_bias draw; 1963464ebd5Sriastradh 1977ec681f3Smrg ctx->clear(ctx, PIPE_CLEAR_COLOR, NULL, &clear_color, 0, 0); 1983464ebd5Sriastradh 19901e04c3fSmrg 2003464ebd5Sriastradh util_draw_init_info(&info); 20101e04c3fSmrg info.index_size = draw_elements ? 2 : 0; 2023464ebd5Sriastradh info.mode = PIPE_PRIM_TRIANGLES; 2037ec681f3Smrg draw.start = 0; 2047ec681f3Smrg draw.count = 3; 2057ec681f3Smrg draw.index_bias = 0; 2063464ebd5Sriastradh /* draw NUM_INST triangles */ 2073464ebd5Sriastradh info.instance_count = NUM_INST; 2083464ebd5Sriastradh 20901e04c3fSmrg /* index data */ 21001e04c3fSmrg if (info.index_size) { 21101e04c3fSmrg info.index.resource = 21201e04c3fSmrg pipe_buffer_create_with_data(ctx, 21301e04c3fSmrg PIPE_BIND_INDEX_BUFFER, 21401e04c3fSmrg PIPE_USAGE_DEFAULT, 21501e04c3fSmrg sizeof(indices), 21601e04c3fSmrg indices); 21701e04c3fSmrg } 21801e04c3fSmrg 2197ec681f3Smrg ctx->draw_vbo(ctx, &info, 0, NULL, &draw, 1); 2203464ebd5Sriastradh 22101e04c3fSmrg pipe_resource_reference(&info.index.resource, NULL); 22201e04c3fSmrg 223af69d88dSmrg ctx->flush(ctx, NULL, 0); 2243464ebd5Sriastradh 2253464ebd5Sriastradh graw_save_surface_to_file(ctx, surf, NULL); 2263464ebd5Sriastradh 2277ec681f3Smrg screen->flush_frontbuffer(screen, ctx, tex, 0, 0, window, NULL); 2283464ebd5Sriastradh} 2293464ebd5Sriastradh 2303464ebd5Sriastradh 2313464ebd5Sriastradhstatic void init( void ) 2323464ebd5Sriastradh{ 2333464ebd5Sriastradh struct pipe_framebuffer_state fb; 2343464ebd5Sriastradh struct pipe_resource templat; 2353464ebd5Sriastradh struct pipe_surface surf_tmpl; 2363464ebd5Sriastradh int i; 2373464ebd5Sriastradh 2383464ebd5Sriastradh /* It's hard to say whether window or screen should be created 2393464ebd5Sriastradh * first. Different environments would prefer one or the other. 2403464ebd5Sriastradh * 2413464ebd5Sriastradh * Also, no easy way of querying supported formats if the screen 2423464ebd5Sriastradh * cannot be created first. 2433464ebd5Sriastradh */ 2443464ebd5Sriastradh for (i = 0; formats[i] != PIPE_FORMAT_NONE; i++) { 2453464ebd5Sriastradh screen = graw_create_window_and_screen(0, 0, 300, 300, 2463464ebd5Sriastradh formats[i], 2473464ebd5Sriastradh &window); 2483464ebd5Sriastradh if (window && screen) 2493464ebd5Sriastradh break; 2503464ebd5Sriastradh } 2513464ebd5Sriastradh if (!screen || !window) { 2523464ebd5Sriastradh fprintf(stderr, "Unable to create window\n"); 2533464ebd5Sriastradh exit(1); 2543464ebd5Sriastradh } 2553464ebd5Sriastradh 25601e04c3fSmrg ctx = screen->context_create(screen, NULL, 0); 2573464ebd5Sriastradh if (ctx == NULL) 2583464ebd5Sriastradh exit(3); 2593464ebd5Sriastradh 26001e04c3fSmrg memset(&templat, 0, sizeof(templat)); 2613464ebd5Sriastradh templat.target = PIPE_TEXTURE_2D; 2623464ebd5Sriastradh templat.format = formats[i]; 2633464ebd5Sriastradh templat.width0 = WIDTH; 2643464ebd5Sriastradh templat.height0 = HEIGHT; 2653464ebd5Sriastradh templat.depth0 = 1; 2663464ebd5Sriastradh templat.array_size = 1; 2673464ebd5Sriastradh templat.last_level = 0; 2683464ebd5Sriastradh templat.bind = (PIPE_BIND_RENDER_TARGET | 2693464ebd5Sriastradh PIPE_BIND_DISPLAY_TARGET); 2703464ebd5Sriastradh 2713464ebd5Sriastradh tex = screen->resource_create(screen, 2723464ebd5Sriastradh &templat); 2733464ebd5Sriastradh if (tex == NULL) 2743464ebd5Sriastradh exit(4); 2753464ebd5Sriastradh 2763464ebd5Sriastradh surf_tmpl.format = templat.format; 2773464ebd5Sriastradh surf_tmpl.u.tex.level = 0; 2783464ebd5Sriastradh surf_tmpl.u.tex.first_layer = 0; 2793464ebd5Sriastradh surf_tmpl.u.tex.last_layer = 0; 2803464ebd5Sriastradh surf = ctx->create_surface(ctx, tex, &surf_tmpl); 2813464ebd5Sriastradh if (surf == NULL) 2823464ebd5Sriastradh exit(5); 2833464ebd5Sriastradh 2843464ebd5Sriastradh memset(&fb, 0, sizeof fb); 2853464ebd5Sriastradh fb.nr_cbufs = 1; 2863464ebd5Sriastradh fb.width = WIDTH; 2873464ebd5Sriastradh fb.height = HEIGHT; 2883464ebd5Sriastradh fb.cbufs[0] = surf; 2893464ebd5Sriastradh 2903464ebd5Sriastradh ctx->set_framebuffer_state(ctx, &fb); 2913464ebd5Sriastradh 2923464ebd5Sriastradh { 2933464ebd5Sriastradh struct pipe_blend_state blend; 2943464ebd5Sriastradh void *handle; 2953464ebd5Sriastradh memset(&blend, 0, sizeof blend); 2963464ebd5Sriastradh blend.rt[0].colormask = PIPE_MASK_RGBA; 2973464ebd5Sriastradh handle = ctx->create_blend_state(ctx, &blend); 2983464ebd5Sriastradh ctx->bind_blend_state(ctx, handle); 2993464ebd5Sriastradh } 3003464ebd5Sriastradh 3013464ebd5Sriastradh { 3023464ebd5Sriastradh struct pipe_depth_stencil_alpha_state depthstencil; 3033464ebd5Sriastradh void *handle; 3043464ebd5Sriastradh memset(&depthstencil, 0, sizeof depthstencil); 3053464ebd5Sriastradh handle = ctx->create_depth_stencil_alpha_state(ctx, &depthstencil); 3063464ebd5Sriastradh ctx->bind_depth_stencil_alpha_state(ctx, handle); 3073464ebd5Sriastradh } 3083464ebd5Sriastradh 3093464ebd5Sriastradh { 3103464ebd5Sriastradh struct pipe_rasterizer_state rasterizer; 3113464ebd5Sriastradh void *handle; 3123464ebd5Sriastradh memset(&rasterizer, 0, sizeof rasterizer); 3133464ebd5Sriastradh rasterizer.cull_face = PIPE_FACE_NONE; 314af69d88dSmrg rasterizer.half_pixel_center = 1; 315af69d88dSmrg rasterizer.bottom_edge_rule = 1; 31601e04c3fSmrg rasterizer.depth_clip_near = 1; 31701e04c3fSmrg rasterizer.depth_clip_far = 1; 3183464ebd5Sriastradh handle = ctx->create_rasterizer_state(ctx, &rasterizer); 3193464ebd5Sriastradh ctx->bind_rasterizer_state(ctx, handle); 3203464ebd5Sriastradh } 3213464ebd5Sriastradh 3223464ebd5Sriastradh set_viewport(0, 0, WIDTH, HEIGHT, 30, 1000); 3233464ebd5Sriastradh set_vertices(); 3243464ebd5Sriastradh set_vertex_shader(); 3253464ebd5Sriastradh set_fragment_shader(); 3263464ebd5Sriastradh} 3273464ebd5Sriastradh 3283464ebd5Sriastradh 3293464ebd5Sriastradhstatic void options(int argc, char *argv[]) 3303464ebd5Sriastradh{ 3313464ebd5Sriastradh int i; 3323464ebd5Sriastradh 3333464ebd5Sriastradh for (i = 1; i < argc;) { 3343464ebd5Sriastradh if (graw_parse_args(&i, argc, argv)) { 3353464ebd5Sriastradh continue; 3363464ebd5Sriastradh } 3373464ebd5Sriastradh if (strcmp(argv[i], "-e") == 0) { 3383464ebd5Sriastradh draw_elements = 1; 3393464ebd5Sriastradh i++; 3403464ebd5Sriastradh } 3413464ebd5Sriastradh else { 3423464ebd5Sriastradh i++; 3433464ebd5Sriastradh } 3443464ebd5Sriastradh } 3453464ebd5Sriastradh if (draw_elements) 3463464ebd5Sriastradh printf("Using pipe_context::draw_elements_instanced()\n"); 3473464ebd5Sriastradh else 3483464ebd5Sriastradh printf("Using pipe_context::draw_arrays_instanced()\n"); 3493464ebd5Sriastradh} 3503464ebd5Sriastradh 3513464ebd5Sriastradh 3523464ebd5Sriastradhint main( int argc, char *argv[] ) 3533464ebd5Sriastradh{ 3543464ebd5Sriastradh options(argc, argv); 3553464ebd5Sriastradh 3563464ebd5Sriastradh init(); 3573464ebd5Sriastradh 3583464ebd5Sriastradh graw_set_display_func( draw ); 3593464ebd5Sriastradh graw_main_loop(); 3603464ebd5Sriastradh return 0; 3613464ebd5Sriastradh} 362