02ce5647eb6c4c0ba91952ed076cadbccf0baae7
[profile/ivi/mesa.git] / src / gallium / state_trackers / python / p_context.i
1  /**************************************************************************
2  * 
3  * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
4  * All Rights Reserved.
5  * 
6  * Permission is hereby granted, free of charge, to any person obtaining a
7  * copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation the rights to use, copy, modify, merge, publish,
10  * distribute, sub license, and/or sell copies of the Software, and to
11  * permit persons to whom the Software is furnished to do so, subject to
12  * the following conditions:
13  * 
14  * The above copyright notice and this permission notice (including the
15  * next paragraph) shall be included in all copies or substantial portions
16  * of the Software.
17  * 
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25  * 
26  **************************************************************************/
27
28 /**
29  * @file
30  * SWIG interface definion for Gallium types.
31  *
32  * @author Jose Fonseca <jrfonseca@tungstengraphics.com>
33  */
34
35 %nodefaultctor st_context;
36 %nodefaultdtor st_context;
37
38 struct st_context {
39 };
40
41 %extend st_context {
42    
43    ~st_context() {
44       st_context_destroy($self);
45    }
46    
47    /*
48     * State functions (create/bind/destroy state objects)
49     */
50
51    void set_blend( const struct pipe_blend_state *state ) {
52       cso_set_blend($self->cso, state);
53    }
54
55    void set_fragment_sampler( unsigned index, const struct pipe_sampler_state *state ) {
56       cso_single_sampler($self->cso, index, state);
57       cso_single_sampler_done($self->cso);
58    }
59
60    void set_vertex_sampler( unsigned index, const struct pipe_sampler_state *state ) {
61       cso_single_vertex_sampler($self->cso, index, state);
62       cso_single_vertex_sampler_done($self->cso);
63    }
64
65    void set_rasterizer( const struct pipe_rasterizer_state *state ) {
66       cso_set_rasterizer($self->cso, state);
67    }
68
69    void set_depth_stencil_alpha(const struct pipe_depth_stencil_alpha_state *state) {
70       cso_set_depth_stencil_alpha($self->cso, state);
71    }
72
73    void set_fragment_shader( const struct pipe_shader_state *state ) {
74       void *fs;
75       
76       if(!state) {
77          cso_set_fragment_shader_handle($self->cso, NULL);
78          return;
79       }
80       
81       fs = $self->pipe->create_fs_state($self->pipe, state);
82       if(!fs)
83          return;
84       
85       if(cso_set_fragment_shader_handle($self->cso, fs) != PIPE_OK)
86          return;
87
88       cso_delete_fragment_shader($self->cso, $self->fs);
89       $self->fs = fs;
90    }
91
92    void set_vertex_shader( const struct pipe_shader_state *state ) {
93       void *vs;
94       
95       if(!state) {
96          cso_set_vertex_shader_handle($self->cso, NULL);
97          return;
98       }
99       
100       vs = $self->pipe->create_vs_state($self->pipe, state);
101       if(!vs)
102          return;
103       
104       if(cso_set_vertex_shader_handle($self->cso, vs) != PIPE_OK)
105          return;
106
107       cso_delete_vertex_shader($self->cso, $self->vs);
108       $self->vs = vs;
109    }
110
111    void set_geometry_shader( const struct pipe_shader_state *state ) {
112       void *gs;
113
114       if(!state) {
115          cso_set_geometry_shader_handle($self->cso, NULL);
116          return;
117       }
118
119       gs = $self->pipe->create_gs_state($self->pipe, state);
120       if(!gs)
121          return;
122
123       if(cso_set_geometry_shader_handle($self->cso, gs) != PIPE_OK)
124          return;
125
126       cso_delete_geometry_shader($self->cso, $self->gs);
127       $self->gs = gs;
128    }
129
130    /*
131     * Parameter-like state (or properties)
132     */
133
134    void set_blend_color(const struct pipe_blend_color *state ) {
135       cso_set_blend_color($self->cso, state);
136    }
137
138    void set_stencil_ref(const struct pipe_stencil_ref *state ) {
139       cso_set_stencil_ref($self->cso, state);
140    }
141
142    void set_clip(const struct pipe_clip_state *state ) {
143       $self->pipe->set_clip_state($self->pipe, state);
144    }
145
146    void set_constant_buffer(unsigned shader, unsigned index,
147                             struct pipe_buffer *buffer ) 
148    {
149       $self->pipe->set_constant_buffer($self->pipe, shader, index, buffer);
150    }
151
152    void set_framebuffer(const struct pipe_framebuffer_state *state ) 
153    {
154       memcpy(&$self->framebuffer, state, sizeof *state);
155       cso_set_framebuffer($self->cso, state);
156    }
157
158    void set_polygon_stipple(const struct pipe_poly_stipple *state ) {
159       $self->pipe->set_polygon_stipple($self->pipe, state);
160    }
161
162    void set_scissor(const struct pipe_scissor_state *state ) {
163       $self->pipe->set_scissor_state($self->pipe, state);
164    }
165
166    void set_viewport(const struct pipe_viewport_state *state) {
167       cso_set_viewport($self->cso, state);
168    }
169
170    void set_fragment_sampler_texture(unsigned index,
171                                      struct pipe_texture *texture) {
172       struct pipe_sampler_view templ;
173
174       if(!texture)
175          texture = $self->default_texture;
176       pipe_sampler_view_reference(&$self->fragment_sampler_views[index], NULL);
177       u_sampler_view_default_template(&templ,
178                                       texture,
179                                       texture->format);
180       $self->fragment_sampler_views[index] = $self->pipe->create_sampler_view($self->pipe,
181                                                                               texture,
182                                                                               &templ);
183       $self->pipe->set_fragment_sampler_views($self->pipe,
184                                               PIPE_MAX_SAMPLERS,
185                                               $self->fragment_sampler_views);
186    }
187
188    void set_vertex_sampler_texture(unsigned index,
189                                    struct pipe_texture *texture) {
190       struct pipe_sampler_view templ;
191
192       if(!texture)
193          texture = $self->default_texture;
194       pipe_sampler_view_reference(&$self->vertex_sampler_views[index], NULL);
195       u_sampler_view_default_template(&templ,
196                                       texture,
197                                       texture->format);
198       $self->vertex_sampler_views[index] = $self->pipe->create_sampler_view($self->pipe,
199                                                                             texture,
200                                                                             &templ);
201       
202       $self->pipe->set_vertex_sampler_views($self->pipe,
203                                             PIPE_MAX_VERTEX_SAMPLERS,
204                                             $self->vertex_sampler_views);
205    }
206
207    void set_vertex_buffer(unsigned index,
208                           unsigned stride, 
209                           unsigned max_index,
210                           unsigned buffer_offset,
211                           struct pipe_buffer *buffer)
212    {
213       unsigned i;
214       struct pipe_vertex_buffer state;
215       
216       memset(&state, 0, sizeof(state));
217       state.stride = stride;
218       state.max_index = max_index;
219       state.buffer_offset = buffer_offset;
220       state.buffer = buffer;
221
222       memcpy(&$self->vertex_buffers[index], &state, sizeof(state));
223       
224       for(i = 0; i < PIPE_MAX_ATTRIBS; ++i)
225          if(self->vertex_buffers[i].buffer)
226             $self->num_vertex_buffers = i + 1;
227       
228       $self->pipe->set_vertex_buffers($self->pipe, 
229                                       $self->num_vertex_buffers, 
230                                       $self->vertex_buffers);
231    }
232
233    void set_vertex_element(unsigned index,
234                            const struct pipe_vertex_element *element) 
235    {
236       memcpy(&$self->vertex_elements[index], element, sizeof(*element));
237    }
238
239    void set_vertex_elements(unsigned num) 
240    {
241       $self->num_vertex_elements = num;
242       cso_set_vertex_elements($self->cso,
243                               $self->num_vertex_elements, 
244                               $self->vertex_elements);
245    }
246
247    /*
248     * Draw functions
249     */
250    
251    void draw_arrays(unsigned mode, unsigned start, unsigned count) {
252       $self->pipe->draw_arrays($self->pipe, mode, start, count);
253    }
254
255    void draw_elements( struct pipe_buffer *indexBuffer,
256                        unsigned indexSize,
257                        unsigned mode, unsigned start, unsigned count) 
258    {
259       $self->pipe->draw_elements($self->pipe, 
260                                  indexBuffer, 
261                                  indexSize, 
262                                  mode, start, count);
263    }
264
265    void draw_range_elements( struct pipe_buffer *indexBuffer,
266                              unsigned indexSize, unsigned minIndex, unsigned maxIndex,
267                              unsigned mode, unsigned start, unsigned count)
268    {
269       $self->pipe->draw_range_elements($self->pipe, 
270                                        indexBuffer, 
271                                        indexSize, minIndex, maxIndex,
272                                        mode, start, count);
273    }
274
275    void draw_vertices(unsigned prim,
276                       unsigned num_verts,
277                       unsigned num_attribs,
278                       const float *vertices) 
279    {
280       struct pipe_context *pipe = $self->pipe;
281       struct pipe_screen *screen = pipe->screen;
282       struct pipe_buffer *vbuf;
283       struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS];
284       struct pipe_vertex_buffer vbuffer;
285       float *map;
286       unsigned size;
287       unsigned i;
288
289       size = num_verts * num_attribs * 4 * sizeof(float);
290
291       vbuf = pipe_buffer_create(screen,
292                                 32,
293                                 PIPE_BUFFER_USAGE_VERTEX, 
294                                 size);
295       if(!vbuf)
296          goto error1;
297       
298       map = pipe_buffer_map(screen, vbuf, PIPE_BUFFER_USAGE_CPU_WRITE);
299       if (!map)
300          goto error2;
301       memcpy(map, vertices, size);
302       pipe_buffer_unmap(screen, vbuf);
303
304       cso_save_vertex_elements($self->cso);
305
306       /* tell pipe about the vertex attributes */
307       for (i = 0; i < num_attribs; i++) {
308          velements[i].src_offset = i * 4 * sizeof(float);
309          velements[i].instance_divisor = 0;
310          velements[i].vertex_buffer_index = 0;
311          velements[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
312       }
313       cso_set_vertex_elements($self->cso, num_attribs, velements);
314
315       /* tell pipe about the vertex buffer */
316       memset(&vbuffer, 0, sizeof(vbuffer));
317       vbuffer.buffer = vbuf;
318       vbuffer.stride = num_attribs * 4 * sizeof(float);  /* vertex size */
319       vbuffer.buffer_offset = 0;
320       vbuffer.max_index = num_verts - 1;
321       pipe->set_vertex_buffers(pipe, 1, &vbuffer);
322
323       /* draw */
324       pipe->draw_arrays(pipe, prim, 0, num_verts);
325
326       cso_restore_vertex_elements($self->cso);
327
328 error2:
329       pipe_buffer_reference(&vbuf, NULL);
330 error1:
331       ;
332    }
333    
334    void
335    clear(unsigned buffers, const float *rgba, double depth = 0.0f,
336          unsigned stencil = 0)
337    {
338       $self->pipe->clear($self->pipe, buffers, rgba, depth, stencil);
339    }
340
341    void
342    flush(unsigned flags = 0) {
343       struct pipe_fence_handle *fence = NULL; 
344       $self->pipe->flush($self->pipe, flags | PIPE_FLUSH_RENDER_CACHE, &fence);
345       if(fence) {
346          /* TODO: allow asynchronous operation */ 
347          $self->pipe->screen->fence_finish( $self->pipe->screen, fence, 0 );
348          $self->pipe->screen->fence_reference( $self->pipe->screen, &fence, NULL );
349       }
350    }
351
352    /*
353     * Surface functions
354     */
355    
356    void surface_copy(struct st_surface *dst,
357                      unsigned destx, unsigned desty,
358                      struct st_surface *src,
359                      unsigned srcx, unsigned srcy,
360                      unsigned width, unsigned height) 
361    {
362       struct pipe_surface *_dst = NULL;
363       struct pipe_surface *_src = NULL;
364       
365       _dst = st_pipe_surface(dst, PIPE_BUFFER_USAGE_GPU_WRITE);
366       if(!_dst)
367          SWIG_exception(SWIG_ValueError, "couldn't acquire destination surface for writing");
368
369       _src = st_pipe_surface(src, PIPE_BUFFER_USAGE_GPU_READ);
370       if(!_src)
371          SWIG_exception(SWIG_ValueError, "couldn't acquire source surface for reading");
372       
373       $self->pipe->surface_copy($self->pipe, _dst, destx, desty, _src, srcx, srcy, width, height);
374       
375    fail:
376       pipe_surface_reference(&_src, NULL);
377       pipe_surface_reference(&_dst, NULL);
378    }
379
380    void surface_fill(struct st_surface *dst,
381                      unsigned x, unsigned y,
382                      unsigned width, unsigned height,
383                      unsigned value) 
384    {
385       struct pipe_surface *_dst = NULL;
386       
387       _dst = st_pipe_surface(dst, PIPE_BUFFER_USAGE_GPU_WRITE);
388       if(!_dst)
389          SWIG_exception(SWIG_ValueError, "couldn't acquire destination surface for writing");
390
391       $self->pipe->surface_fill($self->pipe, _dst, x, y, width, height, value);
392       
393    fail:
394       pipe_surface_reference(&_dst, NULL);
395    }
396
397    %cstring_output_allocate_size(char **STRING, int *LENGTH, free(*$1));
398    void
399    surface_read_raw(struct st_surface *surface,
400                     unsigned x, unsigned y, unsigned w, unsigned h,
401                     char **STRING, int *LENGTH)
402    {
403       struct pipe_texture *texture = surface->texture;
404       struct pipe_context *pipe = $self->pipe;
405       struct pipe_transfer *transfer;
406       unsigned stride;
407
408       stride = util_format_get_stride(texture->format, w);
409       *LENGTH = util_format_get_nblocksy(texture->format, h) * stride;
410       *STRING = (char *) malloc(*LENGTH);
411       if(!*STRING)
412          return;
413
414       transfer = pipe->get_tex_transfer(pipe,
415                                           surface->texture,
416                                           surface->face,
417                                           surface->level,
418                                           surface->zslice,
419                                           PIPE_TRANSFER_READ,
420                                           x, y, w, h);
421       if(transfer) {
422          pipe_get_tile_raw(pipe, transfer, 0, 0, w, h, *STRING, stride);
423          pipe->tex_transfer_destroy(pipe, transfer);
424       }
425    }
426
427    %cstring_input_binary(const char *STRING, unsigned LENGTH);
428    void
429    surface_write_raw(struct st_surface *surface,
430                      unsigned x, unsigned y, unsigned w, unsigned h,
431                      const char *STRING, unsigned LENGTH, unsigned stride = 0)
432    {
433       struct pipe_texture *texture = surface->texture;
434       struct pipe_context *pipe = $self->pipe;
435       struct pipe_transfer *transfer;
436
437       if(stride == 0)
438          stride = util_format_get_stride(texture->format, w);
439
440       if(LENGTH < util_format_get_nblocksy(texture->format, h) * stride)
441          SWIG_exception(SWIG_ValueError, "offset must be smaller than buffer size");
442
443       transfer = pipe->get_tex_transfer(pipe,
444                                           surface->texture,
445                                           surface->face,
446                                           surface->level,
447                                           surface->zslice,
448                                           PIPE_TRANSFER_WRITE,
449                                           x, y, w, h);
450       if(!transfer)
451          SWIG_exception(SWIG_MemoryError, "couldn't initiate transfer");
452
453       pipe_put_tile_raw(pipe, transfer, 0, 0, w, h, STRING, stride);
454       pipe->tex_transfer_destroy(pipe, transfer);
455
456    fail:
457       return;
458    }
459
460    void
461    surface_read_rgba(struct st_surface *surface,
462                      unsigned x, unsigned y, unsigned w, unsigned h,
463                      float *rgba)
464    {
465       struct pipe_context *pipe = $self->pipe;
466       struct pipe_transfer *transfer;
467       transfer = pipe->get_tex_transfer(pipe,
468                                           surface->texture,
469                                           surface->face,
470                                           surface->level,
471                                           surface->zslice,
472                                           PIPE_TRANSFER_READ,
473                                           x, y, w, h);
474       if(transfer) {
475          pipe_get_tile_rgba(pipe, transfer, 0, 0, w, h, rgba);
476          pipe->tex_transfer_destroy(pipe, transfer);
477       }
478    }
479
480    void
481    surface_write_rgba(struct st_surface *surface,
482                       unsigned x, unsigned y, unsigned w, unsigned h,
483                       const float *rgba)
484    {
485       struct pipe_context *pipe = $self->pipe;
486       struct pipe_transfer *transfer;
487       transfer = pipe->get_tex_transfer(pipe,
488                                           surface->texture,
489                                           surface->face,
490                                           surface->level,
491                                           surface->zslice,
492                                           PIPE_TRANSFER_WRITE,
493                                           x, y, w, h);
494       if(transfer) {
495          pipe_put_tile_rgba(pipe, transfer, 0, 0, w, h, rgba);
496          pipe->tex_transfer_destroy(pipe, transfer);
497       }
498    }
499
500    %cstring_output_allocate_size(char **STRING, int *LENGTH, free(*$1));
501    void
502    surface_read_rgba8(struct st_surface *surface,
503                       unsigned x, unsigned y, unsigned w, unsigned h,
504                       char **STRING, int *LENGTH)
505    {
506       struct pipe_context *pipe = $self->pipe;
507       struct pipe_transfer *transfer;
508       float *rgba;
509       unsigned char *rgba8;
510       unsigned i, j, k;
511
512       *LENGTH = 0;
513       *STRING = NULL;
514
515       if (!surface)
516          return;
517
518       *LENGTH = h*w*4;
519       *STRING = (char *) malloc(*LENGTH);
520       if(!*STRING)
521          return;
522
523       rgba = malloc(h*w*4*sizeof(float));
524       if(!rgba)
525          return;
526
527       rgba8 = (unsigned char *) *STRING;
528
529       transfer = pipe->get_tex_transfer(pipe,
530                                           surface->texture,
531                                           surface->face,
532                                           surface->level,
533                                           surface->zslice,
534                                           PIPE_TRANSFER_READ,
535                                           x, y,
536                                           w, h);
537       if(transfer) {
538          pipe_get_tile_rgba(pipe, transfer, 0, 0, w, h, rgba);
539          for(j = 0; j < h; ++j) {
540             for(i = 0; i < w; ++i)
541                for(k = 0; k <4; ++k)
542                   rgba8[j*w*4 + i*4 + k] = float_to_ubyte(rgba[j*w*4 + i*4 + k]);
543          }
544          pipe->tex_transfer_destroy(pipe, transfer);
545       }
546
547       free(rgba);
548    }
549
550    void
551    surface_read_z(struct st_surface *surface,
552                   unsigned x, unsigned y, unsigned w, unsigned h,
553                   unsigned *z)
554    {
555       struct pipe_context *pipe = $self->pipe;
556       struct pipe_transfer *transfer;
557       transfer = pipe->get_tex_transfer(pipe,
558                                           surface->texture,
559                                           surface->face,
560                                           surface->level,
561                                           surface->zslice,
562                                           PIPE_TRANSFER_READ,
563                                           x, y, w, h);
564       if(transfer) {
565          pipe_get_tile_z(pipe, transfer, 0, 0, w, h, z);
566          pipe->tex_transfer_destroy(pipe, transfer);
567       }
568    }
569
570    void
571    surface_write_z(struct st_surface *surface,
572                    unsigned x, unsigned y, unsigned w, unsigned h,
573                    const unsigned *z)
574    {
575       struct pipe_context *pipe = $self->pipe;
576       struct pipe_transfer *transfer;
577       transfer = pipe->get_tex_transfer(pipe,
578                                           surface->texture,
579                                           surface->face,
580                                           surface->level,
581                                           surface->zslice,
582                                           PIPE_TRANSFER_WRITE,
583                                           x, y, w, h);
584       if(transfer) {
585          pipe_put_tile_z(pipe, transfer, 0, 0, w, h, z);
586          pipe->tex_transfer_destroy(pipe, transfer);
587       }
588    }
589
590    void
591    surface_sample_rgba(struct st_surface *surface,
592                        float *rgba,
593                        int norm = 0)
594    {
595       st_sample_surface($self->pipe, surface, rgba, norm != 0);
596    }
597
598    unsigned
599    surface_compare_rgba(struct st_surface *surface,
600                         unsigned x, unsigned y, unsigned w, unsigned h,
601                         const float *rgba, float tol = 0.0)
602    {
603       struct pipe_context *pipe = $self->pipe;
604       struct pipe_transfer *transfer;
605       float *rgba2;
606       const float *p1;
607       const float *p2;
608       unsigned i, j, n;
609
610       rgba2 = MALLOC(h*w*4*sizeof(float));
611       if(!rgba2)
612          return ~0;
613
614       transfer = pipe->get_tex_transfer(pipe,
615                                           surface->texture,
616                                           surface->face,
617                                           surface->level,
618                                           surface->zslice,
619                                           PIPE_TRANSFER_READ,
620                                           x, y, w, h);
621       if(!transfer) {
622          FREE(rgba2);
623          return ~0;
624       }
625
626       pipe_get_tile_rgba(pipe, transfer, 0, 0, w, h, rgba2);
627       pipe->tex_transfer_destroy(pipe, transfer);
628
629       p1 = rgba;
630       p2 = rgba2;
631       n = 0;
632       for(i = h*w; i; --i) {
633          unsigned differs = 0;
634          for(j = 4; j; --j) {
635             float delta = *p2++ - *p1++;
636             if (delta < -tol || delta > tol)
637                 differs = 1;
638          }
639          n += differs;
640       }
641
642       FREE(rgba2);
643
644       return n;
645    }
646
647 };