OSDN Git Service

graw: Fix file handle leaks.
[android-x86/external-mesa.git] / src / gallium / tests / graw / gs-test.c
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 #include <stdio.h>              /* for fread(), etc */
12
13 #include "util/u_debug.h"       /* debug_dump_surface_bmp() */
14 #include "util/u_inlines.h"
15 #include "util/u_memory.h"      /* Offset() */
16 #include "util/u_box.h"    
17
18 static const char *filename = NULL;
19 unsigned show_fps = 0;
20
21
22 static void usage(char *name)
23 {
24    fprintf(stderr, "usage: %s [ options ] shader_filename\n", name);
25 #ifndef WIN32
26    fprintf(stderr, "\n" );
27    fprintf(stderr, "options:\n");
28    fprintf(stderr, "    -fps  show frames per second\n");
29 #endif
30 }
31
32
33 enum pipe_format formats[] = {
34    PIPE_FORMAT_R8G8B8A8_UNORM,
35    PIPE_FORMAT_B8G8R8A8_UNORM,
36    PIPE_FORMAT_NONE
37 };
38
39 static const int WIDTH = 250;
40 static const int HEIGHT = 250;
41
42 static struct pipe_screen *screen = NULL;
43 static struct pipe_context *ctx = NULL;
44 static struct pipe_resource *rttex = NULL;
45 static struct pipe_resource *constbuf = NULL;
46 static struct pipe_surface *surf = NULL;
47 static struct pipe_sampler_view *sv = NULL;
48 static void *sampler = NULL;
49 static void *window = NULL;
50 static struct pipe_resource *samptex = NULL;
51
52 struct vertex {
53    float position[4];
54    float color[4];
55    float texcoord[4];
56 };
57
58 /* Vertex data matches progs/fp/fp-tri.c, but flipped in Y dimension
59  * so that the final images are the same.
60  */
61 static struct vertex vertices[] =
62 {
63    { { 0.9, 0.9, 0.0, 1.0 },
64      { 0, 0, 1, 1 },
65      { 1, 1, 0, 1 } },
66
67    { { 0.9,  -0.9, 0.0, 1.0 },
68      { 1, 0, 0, 1 },
69      { 1, -1, 0, 1 } },
70
71    { {-0.9,  0.0, 0.0, 1.0 },
72      { 0, 1, 0, 1 },
73      { -1, 0, 0, 1 } },
74 };
75
76 static float constants[] = 
77 {  0.4, 0, 0,  1,
78    1,   1, 1,  1,
79    2,   2, 2,  2,
80    4,   8, 16, 32,
81
82    3,  0, 0, 0,
83    0, .5, 0, 0,
84    0,  0, 1, 0,
85    0,  0, 0, 1,
86
87    1, 0, 0, 0.5,
88    0, 1, 0, 0.5,
89    0, 0, 1, 0,
90    0, 0, 0, 1,
91 };
92
93 static void init_fs_constbuf( void )
94 {
95    struct pipe_resource templat;
96    struct pipe_box box;
97
98    templat.target = PIPE_BUFFER;
99    templat.format = PIPE_FORMAT_R8_UNORM;
100    templat.width0 = sizeof(constants);
101    templat.height0 = 1;
102    templat.depth0 = 1;
103    templat.last_level = 0;
104    templat.nr_samples = 1;
105    templat.bind = PIPE_BIND_CONSTANT_BUFFER;
106
107    constbuf = screen->resource_create(screen,
108                                       &templat);
109    if (constbuf == NULL)
110       exit(4);
111
112
113    u_box_2d(0,0,sizeof(constants),1, &box);
114
115    ctx->transfer_inline_write(ctx,
116                               constbuf,
117                               u_subresource(0,0),
118                               PIPE_TRANSFER_WRITE,
119                               &box,
120                               constants,
121                               sizeof constants,
122                               sizeof constants);
123
124
125    ctx->set_constant_buffer(ctx,
126                             PIPE_SHADER_FRAGMENT, 0,
127                             constbuf);
128 }
129
130
131 static void set_viewport( float x, float y,
132                           float width, float height,
133                           float near, float far)
134 {
135    float z = far;
136    float half_width = (float)width / 2.0f;
137    float half_height = (float)height / 2.0f;
138    float half_depth = ((float)far - (float)near) / 2.0f;
139    struct pipe_viewport_state vp;
140
141    vp.scale[0] = half_width;
142    vp.scale[1] = half_height;
143    vp.scale[2] = half_depth;
144    vp.scale[3] = 1.0f;
145
146    vp.translate[0] = half_width + x;
147    vp.translate[1] = half_height + y;
148    vp.translate[2] = half_depth + z;
149    vp.translate[3] = 0.0f;
150
151    ctx->set_viewport_state( ctx, &vp );
152 }
153
154 static void set_vertices( void )
155 {
156    struct pipe_vertex_element ve[3];
157    struct pipe_vertex_buffer vbuf;
158    void *handle;
159
160    memset(ve, 0, sizeof ve);
161
162    ve[0].src_offset = Offset(struct vertex, position);
163    ve[0].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
164    ve[1].src_offset = Offset(struct vertex, color);
165    ve[1].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
166    ve[2].src_offset = Offset(struct vertex, texcoord);
167    ve[2].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
168
169    handle = ctx->create_vertex_elements_state(ctx, 3, ve);
170    ctx->bind_vertex_elements_state(ctx, handle);
171
172
173    vbuf.stride = sizeof( struct vertex );
174    vbuf.max_index = sizeof(vertices) / vbuf.stride;
175    vbuf.buffer_offset = 0;
176    vbuf.buffer = screen->user_buffer_create(screen,
177                                             vertices,
178                                             sizeof(vertices),
179                                             PIPE_BIND_VERTEX_BUFFER);
180
181    ctx->set_vertex_buffers(ctx, 1, &vbuf);
182 }
183
184 static void set_vertex_shader( void )
185 {
186    void *handle;
187    const char *text =
188       "VERT\n"
189       "DCL IN[0]\n"
190       "DCL IN[1]\n"
191       "DCL IN[2]\n"
192       "DCL OUT[0], POSITION\n"
193       "DCL OUT[1], COLOR[0]\n"
194       "DCL OUT[2], GENERIC[0]\n"
195       "  MOV OUT[0], IN[0]\n"
196       "  MOV OUT[1], IN[1]\n"
197       "  MOV OUT[2], IN[2]\n"
198       "  END\n";
199
200    handle = graw_parse_vertex_shader(ctx, text);
201    ctx->bind_vs_state(ctx, handle);
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 static void set_geometry_shader( void )
220 {
221    FILE *f;
222    char buf[50000];
223    void *handle;
224    int sz;
225
226    if ((f = fopen(filename, "r")) == NULL) {
227       fprintf(stderr, "Couldn't open %s\n", filename);
228       exit(1);
229    }
230
231    sz = fread(buf, 1, sizeof(buf), f);
232    if (!feof(f)) {
233       printf("file too long\n");
234       exit(1);
235    }
236    printf("%.*s\n", sz, buf);
237    buf[sz] = 0;
238
239    handle = graw_parse_geometry_shader(ctx, buf);
240    ctx->bind_gs_state(ctx, handle);
241    fclose(f);
242 }
243
244
245 static void draw( void )
246 {
247    float clear_color[4] = {.1,.3,.5,0};
248
249    ctx->clear(ctx, PIPE_CLEAR_COLOR, clear_color, 0, 0);
250    ctx->draw_arrays(ctx, PIPE_PRIM_TRIANGLES, 0, 3);
251    ctx->flush(ctx, PIPE_FLUSH_RENDER_CACHE, NULL);
252
253 #if 0
254    /* At the moment, libgraw leaks out/makes available some of the
255     * symbols from gallium/auxiliary, including these debug helpers.
256     * Will eventually want to bless some of these paths, and lock the
257     * others down so they aren't accessible from test programs.
258     *
259     * This currently just happens to work on debug builds - a release
260     * build will probably fail to link here:
261     */
262    debug_dump_surface_bmp(ctx, "result.bmp", surf);
263 #endif
264
265    screen->flush_frontbuffer(screen, surf, window);
266 }
267
268 #define SIZE 16
269
270 static void init_tex( void )
271
272    struct pipe_sampler_view sv_template;
273    struct pipe_sampler_state sampler_desc;
274    struct pipe_resource templat;
275    struct pipe_box box;
276    ubyte tex2d[SIZE][SIZE][4];
277    int s, t;
278
279 #if (SIZE != 2)
280    for (s = 0; s < SIZE; s++) {
281       for (t = 0; t < SIZE; t++) {
282          if (0) {
283             int x = (s ^ t) & 1;
284             tex2d[t][s][0] = (x) ? 0 : 63;
285             tex2d[t][s][1] = (x) ? 0 : 128;
286             tex2d[t][s][2] = 0;
287             tex2d[t][s][3] = 0xff;
288          }
289          else {
290             int x = ((s ^ t) >> 2) & 1;
291             tex2d[t][s][0] = s*255/(SIZE-1);
292             tex2d[t][s][1] = t*255/(SIZE-1);
293             tex2d[t][s][2] = (x) ? 0 : 128;
294             tex2d[t][s][3] = 0xff;
295          }
296       }
297    }
298 #else
299    tex2d[0][0][0] = 0;
300    tex2d[0][0][1] = 255;
301    tex2d[0][0][2] = 255;
302    tex2d[0][0][3] = 0;
303
304    tex2d[0][1][0] = 0;
305    tex2d[0][1][1] = 0;
306    tex2d[0][1][2] = 255;
307    tex2d[0][1][3] = 255;
308
309    tex2d[1][0][0] = 255;
310    tex2d[1][0][1] = 255;
311    tex2d[1][0][2] = 0;
312    tex2d[1][0][3] = 255;
313
314    tex2d[1][1][0] = 255;
315    tex2d[1][1][1] = 0;
316    tex2d[1][1][2] = 0;
317    tex2d[1][1][3] = 255;
318 #endif
319
320    templat.target = PIPE_TEXTURE_2D;
321    templat.format = PIPE_FORMAT_B8G8R8A8_UNORM;
322    templat.width0 = SIZE;
323    templat.height0 = SIZE;
324    templat.depth0 = 1;
325    templat.last_level = 0;
326    templat.nr_samples = 1;
327    templat.bind = PIPE_BIND_SAMPLER_VIEW;
328
329    
330    samptex = screen->resource_create(screen,
331                                  &templat);
332    if (samptex == NULL)
333       exit(4);
334
335    u_box_2d(0,0,SIZE,SIZE, &box);
336
337    ctx->transfer_inline_write(ctx,
338                               samptex,
339                               u_subresource(0,0),
340                               PIPE_TRANSFER_WRITE,
341                               &box,
342                               tex2d,
343                               sizeof tex2d[0],
344                               sizeof tex2d);
345
346    /* Possibly read back & compare against original data:
347     */
348    if (0)
349    {
350       struct pipe_transfer *t;
351       uint32_t *ptr;
352       t = pipe_get_transfer(ctx, samptex,
353                             0, 0, 0, /* face, level, zslice */
354                             PIPE_TRANSFER_READ,
355                             0, 0, SIZE, SIZE); /* x, y, width, height */
356
357       ptr = ctx->transfer_map(ctx, t);
358
359       if (memcmp(ptr, tex2d, sizeof tex2d) != 0) {
360          assert(0);
361          exit(9);
362       }
363
364       ctx->transfer_unmap(ctx, t);
365
366       ctx->transfer_destroy(ctx, t);
367    }
368
369    memset(&sv_template, 0, sizeof sv_template);
370    sv_template.format = samptex->format;
371    sv_template.texture = samptex;
372    sv_template.first_level = 0;
373    sv_template.last_level = 0;
374    sv_template.swizzle_r = 0;
375    sv_template.swizzle_g = 1;
376    sv_template.swizzle_b = 2;
377    sv_template.swizzle_a = 3;
378    sv = ctx->create_sampler_view(ctx, samptex, &sv_template);
379    if (sv == NULL)
380       exit(5);
381
382    ctx->set_fragment_sampler_views(ctx, 1, &sv);
383    
384
385    memset(&sampler_desc, 0, sizeof sampler_desc);
386    sampler_desc.wrap_s = PIPE_TEX_WRAP_REPEAT;
387    sampler_desc.wrap_t = PIPE_TEX_WRAP_REPEAT;
388    sampler_desc.wrap_r = PIPE_TEX_WRAP_REPEAT;
389    sampler_desc.min_img_filter = PIPE_TEX_FILTER_NEAREST;
390    sampler_desc.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
391    sampler_desc.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
392    sampler_desc.compare_mode = PIPE_TEX_COMPARE_NONE;
393    sampler_desc.compare_func = 0;
394    sampler_desc.normalized_coords = 1;
395    sampler_desc.max_anisotropy = 0;
396    
397    sampler = ctx->create_sampler_state(ctx, &sampler_desc);
398    if (sampler == NULL)
399       exit(6);
400
401    ctx->bind_fragment_sampler_states(ctx, 1, &sampler);
402    
403 }
404
405 static void init( void )
406 {
407    struct pipe_framebuffer_state fb;
408    struct pipe_resource templat;
409    int i;
410
411    /* It's hard to say whether window or screen should be created
412     * first.  Different environments would prefer one or the other.
413     *
414     * Also, no easy way of querying supported formats if the screen
415     * cannot be created first.
416     */
417    for (i = 0; 
418         window == NULL && formats[i] != PIPE_FORMAT_NONE;
419         i++) {
420       
421       screen = graw_create_window_and_screen(0,0,WIDTH,HEIGHT,
422                                              formats[i],
423                                              &window);
424    }
425    
426    ctx = screen->context_create(screen, NULL);
427    if (ctx == NULL)
428       exit(3);
429
430    templat.target = PIPE_TEXTURE_2D;
431    templat.format = formats[i];
432    templat.width0 = WIDTH;
433    templat.height0 = HEIGHT;
434    templat.depth0 = 1;
435    templat.last_level = 0;
436    templat.nr_samples = 1;
437    templat.bind = (PIPE_BIND_RENDER_TARGET |
438                    PIPE_BIND_DISPLAY_TARGET);
439    
440    rttex = screen->resource_create(screen,
441                                  &templat);
442    if (rttex == NULL)
443       exit(4);
444
445    surf = screen->get_tex_surface(screen, rttex, 0, 0, 0,
446                                   PIPE_BIND_RENDER_TARGET |
447                                   PIPE_BIND_DISPLAY_TARGET);
448    if (surf == NULL)
449       exit(5);
450
451    memset(&fb, 0, sizeof fb);
452    fb.nr_cbufs = 1;
453    fb.width = WIDTH;
454    fb.height = HEIGHT;
455    fb.cbufs[0] = surf;
456
457    ctx->set_framebuffer_state(ctx, &fb);
458    
459    {
460       struct pipe_blend_state blend;
461       void *handle;
462       memset(&blend, 0, sizeof blend);
463       blend.rt[0].colormask = PIPE_MASK_RGBA;
464       handle = ctx->create_blend_state(ctx, &blend);
465       ctx->bind_blend_state(ctx, handle);
466    }
467
468    {
469       struct pipe_depth_stencil_alpha_state depthstencil;
470       void *handle;
471       memset(&depthstencil, 0, sizeof depthstencil);
472       handle = ctx->create_depth_stencil_alpha_state(ctx, &depthstencil);
473       ctx->bind_depth_stencil_alpha_state(ctx, handle);
474    }
475
476    {
477       struct pipe_rasterizer_state rasterizer;
478       void *handle;
479       memset(&rasterizer, 0, sizeof rasterizer);
480       rasterizer.cull_face = PIPE_FACE_NONE;
481       rasterizer.gl_rasterization_rules = 1;
482       handle = ctx->create_rasterizer_state(ctx, &rasterizer);
483       ctx->bind_rasterizer_state(ctx, handle);
484    }
485
486    set_viewport(0, 0, WIDTH, HEIGHT, 30, 1000);
487
488    init_tex();
489    init_fs_constbuf();
490
491    set_vertices();
492    set_vertex_shader();
493    set_fragment_shader();
494    set_geometry_shader();
495 }
496
497 static void args(int argc, char *argv[])
498 {
499    int i;
500
501    for (i = 1; i < argc; i++) {
502       if (strcmp(argv[i], "-fps") == 0) {
503          show_fps = 1;
504       }
505       else if (i == argc - 1) {
506          filename = argv[i];
507       }
508       else {
509          usage(argv[0]);
510          exit(1);
511       }
512    }
513
514    if (!filename) {
515       usage(argv[0]);
516       exit(1);
517    }
518 }
519
520 int main( int argc, char *argv[] )
521 {
522    args(argc,argv);
523    init();
524
525    graw_set_display_func( draw );
526    graw_main_loop();
527    return 0;
528 }