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