Tizen 2.1 base
[sdk/emulator/qemu.git] / gl / mesa / src / gallium / tests / graw / tri-instanced.c
1 /*
2  * Test draw instancing.
3  */
4
5 #include <stdio.h>
6 #include <string.h>
7
8 #include "state_tracker/graw.h"
9 #include "pipe/p_screen.h"
10 #include "pipe/p_context.h"
11 #include "pipe/p_state.h"
12 #include "pipe/p_defines.h"
13
14 #include "util/u_memory.h"      /* Offset() */
15 #include "util/u_draw_quad.h"
16
17
18 enum pipe_format formats[] = {
19    PIPE_FORMAT_R8G8B8A8_UNORM,
20    PIPE_FORMAT_B8G8R8A8_UNORM,
21    PIPE_FORMAT_NONE
22 };
23
24 static const int WIDTH = 300;
25 static const int HEIGHT = 300;
26
27 static struct pipe_screen *screen = NULL;
28 static struct pipe_context *ctx = NULL;
29 static struct pipe_surface *surf = NULL;
30 static struct pipe_resource *tex = NULL;
31 static void *window = NULL;
32
33 struct vertex {
34    float position[4];
35    float color[4];
36 };
37
38
39 static int draw_elements = 0;
40
41
42 /**
43  * Vertex data.
44  * Each vertex has three attributes: position, color and translation.
45  * The translation attribute is a per-instance attribute.  See
46  * "instance_divisor" below.
47  */
48 static struct vertex vertices[4] =
49 {
50    {
51       { 0.0f, -0.3f, 0.0f, 1.0f },  /* pos */
52       { 1.0f, 0.0f, 0.0f, 1.0f }    /* color */
53    },
54    {
55       { -0.2f, 0.3f, 0.0f, 1.0f },
56       { 0.0f, 1.0f, 0.0f, 1.0f }
57    },
58    {
59       { 0.2f, 0.3f, 0.0f, 1.0f },
60       { 0.0f, 0.0f, 1.0f, 1.0f }
61    }
62 };
63
64
65 #define NUM_INST 5
66
67 static float inst_data[NUM_INST][4] =
68 {
69    { -0.50f, 0.4f, 0.0f, 0.0f },
70    { -0.25f, 0.1f, 0.0f, 0.0f },
71    { 0.00f, 0.2f, 0.0f, 0.0f },
72    { 0.25f, 0.1f, 0.0f, 0.0f },
73    { 0.50f, 0.3f, 0.0f, 0.0f }
74 };
75
76
77 static ushort indices[3] = { 0, 2, 1 };
78
79
80 static void set_viewport( float x, float y,
81                           float width, float height,
82                           float near, float far)
83 {
84    float z = far;
85    float half_width = (float)width / 2.0f;
86    float half_height = (float)height / 2.0f;
87    float half_depth = ((float)far - (float)near) / 2.0f;
88    struct pipe_viewport_state vp;
89
90    vp.scale[0] = half_width;
91    vp.scale[1] = half_height;
92    vp.scale[2] = half_depth;
93    vp.scale[3] = 1.0f;
94
95    vp.translate[0] = half_width + x;
96    vp.translate[1] = half_height + y;
97    vp.translate[2] = half_depth + z;
98    vp.translate[3] = 0.0f;
99
100    ctx->set_viewport_state( ctx, &vp );
101 }
102
103
104 static void set_vertices( void )
105 {
106    struct pipe_vertex_element ve[3];
107    struct pipe_vertex_buffer vbuf[2];
108    struct pipe_index_buffer ibuf;
109    void *handle;
110
111    memset(ve, 0, sizeof ve);
112
113    /* pos */
114    ve[0].src_offset = Offset(struct vertex, position);
115    ve[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
116    ve[0].vertex_buffer_index = 0;
117
118    /* color */
119    ve[1].src_offset = Offset(struct vertex, color);
120    ve[1].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
121    ve[1].vertex_buffer_index = 0;
122
123    /* per-instance info */
124    ve[2].src_offset = 0;
125    ve[2].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
126    ve[2].vertex_buffer_index = 1;
127    ve[2].instance_divisor = 1;
128
129    handle = ctx->create_vertex_elements_state(ctx, 3, ve);
130    ctx->bind_vertex_elements_state(ctx, handle);
131
132
133    /* vertex data */
134    vbuf[0].stride = sizeof( struct vertex );
135    vbuf[0].buffer_offset = 0;
136    vbuf[0].buffer = screen->user_buffer_create(screen,
137                                                vertices,
138                                                sizeof(vertices),
139                                                PIPE_BIND_VERTEX_BUFFER);
140
141    /* instance data */
142    vbuf[1].stride = sizeof( inst_data[0] );
143    vbuf[1].buffer_offset = 0;
144    vbuf[1].buffer = screen->user_buffer_create(screen,
145                                                inst_data,
146                                                sizeof(inst_data),
147                                                PIPE_BIND_VERTEX_BUFFER);
148
149
150    ctx->set_vertex_buffers(ctx, 2, vbuf);
151
152    /* index data */
153    ibuf.buffer = screen->user_buffer_create(screen,
154                                             indices,
155                                             sizeof(indices),
156                                             PIPE_BIND_VERTEX_BUFFER);
157    ibuf.offset = 0;
158    ibuf.index_size = 2;
159
160    ctx->set_index_buffer(ctx, &ibuf);
161
162 }
163
164 static void set_vertex_shader( void )
165 {
166    void *handle;
167    const char *text =
168       "VERT\n"
169       "DCL IN[0]\n"
170       "DCL IN[1]\n"
171       "DCL IN[2]\n"
172       "DCL OUT[0], POSITION\n"
173       "DCL OUT[1], COLOR\n"
174       "  0: MOV OUT[1], IN[1]\n"
175       "  1: ADD OUT[0], IN[0], IN[2]\n"  /* add instance pos to vertex pos */
176       "  2: END\n";
177
178    handle = graw_parse_vertex_shader(ctx, text);
179    ctx->bind_vs_state(ctx, handle);
180 }
181
182 static void set_fragment_shader( void )
183 {
184    void *handle;
185    const char *text =
186       "FRAG\n"
187       "DCL IN[0], COLOR, LINEAR\n"
188       "DCL OUT[0], COLOR\n"
189       "  0: MOV OUT[0], IN[0]\n"
190       "  1: END\n";
191
192    handle = graw_parse_fragment_shader(ctx, text);
193    ctx->bind_fs_state(ctx, handle);
194 }
195
196
197 static void draw( void )
198 {
199    union pipe_color_union clear_color = { {1,0,1,1} };
200    struct pipe_draw_info info;
201
202    ctx->clear(ctx, PIPE_CLEAR_COLOR, &clear_color, 0, 0);
203
204    util_draw_init_info(&info);
205    info.indexed = (draw_elements != 0);
206    info.mode = PIPE_PRIM_TRIANGLES;
207    info.start = 0;
208    info.count = 3;
209    /* draw NUM_INST triangles */
210    info.instance_count = NUM_INST;
211
212    ctx->draw_vbo(ctx, &info);
213
214    ctx->flush(ctx, NULL);
215
216    graw_save_surface_to_file(ctx, surf, NULL);
217
218    screen->flush_frontbuffer(screen, tex, 0, 0, window);
219 }
220
221
222 static void init( void )
223 {
224    struct pipe_framebuffer_state fb;
225    struct pipe_resource templat;
226    struct pipe_surface surf_tmpl;
227    int i;
228
229    /* It's hard to say whether window or screen should be created
230     * first.  Different environments would prefer one or the other.
231     *
232     * Also, no easy way of querying supported formats if the screen
233     * cannot be created first.
234     */
235    for (i = 0; formats[i] != PIPE_FORMAT_NONE; i++) {
236       screen = graw_create_window_and_screen(0, 0, 300, 300,
237                                              formats[i],
238                                              &window);
239       if (window && screen)
240          break;
241    }
242    if (!screen || !window) {
243       fprintf(stderr, "Unable to create window\n");
244       exit(1);
245    }
246    
247    ctx = screen->context_create(screen, NULL);
248    if (ctx == NULL)
249       exit(3);
250
251    templat.target = PIPE_TEXTURE_2D;
252    templat.format = formats[i];
253    templat.width0 = WIDTH;
254    templat.height0 = HEIGHT;
255    templat.depth0 = 1;
256    templat.array_size = 1;
257    templat.last_level = 0;
258    templat.nr_samples = 1;
259    templat.bind = (PIPE_BIND_RENDER_TARGET |
260                    PIPE_BIND_DISPLAY_TARGET);
261    
262    tex = screen->resource_create(screen,
263                                  &templat);
264    if (tex == NULL)
265       exit(4);
266
267    surf_tmpl.format = templat.format;
268    surf_tmpl.usage = PIPE_BIND_RENDER_TARGET;
269    surf_tmpl.u.tex.level = 0;
270    surf_tmpl.u.tex.first_layer = 0;
271    surf_tmpl.u.tex.last_layer = 0;
272    surf = ctx->create_surface(ctx, tex, &surf_tmpl);
273    if (surf == NULL)
274       exit(5);
275
276    memset(&fb, 0, sizeof fb);
277    fb.nr_cbufs = 1;
278    fb.width = WIDTH;
279    fb.height = HEIGHT;
280    fb.cbufs[0] = surf;
281
282    ctx->set_framebuffer_state(ctx, &fb);
283    
284    {
285       struct pipe_blend_state blend;
286       void *handle;
287       memset(&blend, 0, sizeof blend);
288       blend.rt[0].colormask = PIPE_MASK_RGBA;
289       handle = ctx->create_blend_state(ctx, &blend);
290       ctx->bind_blend_state(ctx, handle);
291    }
292
293    {
294       struct pipe_depth_stencil_alpha_state depthstencil;
295       void *handle;
296       memset(&depthstencil, 0, sizeof depthstencil);
297       handle = ctx->create_depth_stencil_alpha_state(ctx, &depthstencil);
298       ctx->bind_depth_stencil_alpha_state(ctx, handle);
299    }
300
301    {
302       struct pipe_rasterizer_state rasterizer;
303       void *handle;
304       memset(&rasterizer, 0, sizeof rasterizer);
305       rasterizer.cull_face = PIPE_FACE_NONE;
306       rasterizer.gl_rasterization_rules = 1;
307       rasterizer.depth_clip = 1;
308       handle = ctx->create_rasterizer_state(ctx, &rasterizer);
309       ctx->bind_rasterizer_state(ctx, handle);
310    }
311
312    set_viewport(0, 0, WIDTH, HEIGHT, 30, 1000);
313    set_vertices();
314    set_vertex_shader();
315    set_fragment_shader();
316 }
317
318
319 static void options(int argc, char *argv[])
320 {
321    int i;
322
323    for (i = 1; i < argc;) {
324       if (graw_parse_args(&i, argc, argv)) {
325          continue;
326       }
327       if (strcmp(argv[i], "-e") == 0) {
328          draw_elements = 1;
329          i++;
330       }
331       else {
332          i++;
333       }
334    }
335    if (draw_elements)
336       printf("Using pipe_context::draw_elements_instanced()\n");
337    else
338       printf("Using pipe_context::draw_arrays_instanced()\n");
339 }
340
341
342 int main( int argc, char *argv[] )
343 {
344    options(argc, argv);
345
346    init();
347
348    graw_set_display_func( draw );
349    graw_main_loop();
350    return 0;
351 }