gallium: rename clearRT / clearDS to clear_render_target / clear_depth_stencil
[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    struct pipe_sampler_view *
131    create_sampler_view(struct pipe_resource *texture,
132                        enum pipe_format format = PIPE_FORMAT_NONE,
133                        unsigned first_level = 0,
134                        unsigned last_level = ~0,
135                        unsigned swizzle_r = 0,
136                        unsigned swizzle_g = 1,
137                        unsigned swizzle_b = 2,
138                        unsigned swizzle_a = 3)
139    {
140       struct pipe_context *pipe = $self->pipe;
141       struct pipe_sampler_view templat;
142
143       memset(&templat, 0, sizeof templat);
144       if (format == PIPE_FORMAT_NONE) {
145          templat.format = texture->format;
146       } else {
147          templat.format = format;
148       }
149       templat.last_level = MIN2(last_level, texture->last_level);
150       templat.first_level = first_level;
151       templat.last_level = last_level;
152       templat.swizzle_r = swizzle_r;
153       templat.swizzle_g = swizzle_g;
154       templat.swizzle_b = swizzle_b;
155       templat.swizzle_a = swizzle_a;
156
157       return pipe->create_sampler_view(pipe, texture, &templat);
158    }
159
160    void
161    sampler_view_destroy(struct pipe_context *ctx,
162                         struct pipe_sampler_view *view)
163    {
164       struct pipe_context *pipe = $self->pipe;
165
166       pipe->sampler_view_destroy(pipe, view);
167    }
168
169    /*
170     * Parameter-like state (or properties)
171     */
172
173    void set_blend_color(const struct pipe_blend_color *state ) {
174       cso_set_blend_color($self->cso, state);
175    }
176
177    void set_stencil_ref(const struct pipe_stencil_ref *state ) {
178       cso_set_stencil_ref($self->cso, state);
179    }
180
181    void set_clip(const struct pipe_clip_state *state ) {
182       $self->pipe->set_clip_state($self->pipe, state);
183    }
184
185    void set_constant_buffer(unsigned shader, unsigned index,
186                             struct pipe_resource *buffer ) 
187    {
188       $self->pipe->set_constant_buffer($self->pipe, shader, index, buffer);
189    }
190
191    void set_framebuffer(const struct pipe_framebuffer_state *state ) 
192    {
193       memcpy(&$self->framebuffer, state, sizeof *state);
194       cso_set_framebuffer($self->cso, state);
195    }
196
197    void set_polygon_stipple(const struct pipe_poly_stipple *state ) {
198       $self->pipe->set_polygon_stipple($self->pipe, state);
199    }
200
201    void set_scissor(const struct pipe_scissor_state *state ) {
202       $self->pipe->set_scissor_state($self->pipe, state);
203    }
204
205    void set_viewport(const struct pipe_viewport_state *state) {
206       cso_set_viewport($self->cso, state);
207    }
208
209    void set_fragment_sampler_view(unsigned index,
210                                   struct pipe_sampler_view *view)
211    {
212       pipe_sampler_view_reference(&$self->fragment_sampler_views[index], view);
213
214       $self->pipe->set_fragment_sampler_views($self->pipe,
215                                               PIPE_MAX_SAMPLERS,
216                                               $self->fragment_sampler_views);
217    }
218
219    void set_vertex_sampler_view(unsigned index,
220                                 struct pipe_sampler_view *view)
221    {
222       pipe_sampler_view_reference(&$self->vertex_sampler_views[index], view);
223
224       $self->pipe->set_vertex_sampler_views($self->pipe,
225                                             PIPE_MAX_VERTEX_SAMPLERS,
226                                             $self->vertex_sampler_views);
227    }
228
229    void set_fragment_sampler_texture(unsigned index,
230                                      struct pipe_resource *texture) {
231       struct pipe_sampler_view templ;
232
233       if(!texture)
234          texture = $self->default_texture;
235       pipe_sampler_view_reference(&$self->fragment_sampler_views[index], NULL);
236       u_sampler_view_default_template(&templ,
237                                       texture,
238                                       texture->format);
239       $self->fragment_sampler_views[index] = $self->pipe->create_sampler_view($self->pipe,
240                                                                               texture,
241                                                                               &templ);
242       $self->pipe->set_fragment_sampler_views($self->pipe,
243                                               PIPE_MAX_SAMPLERS,
244                                               $self->fragment_sampler_views);
245    }
246
247    void set_vertex_sampler_texture(unsigned index,
248                                    struct pipe_resource *texture) {
249       struct pipe_sampler_view templ;
250
251       if(!texture)
252          texture = $self->default_texture;
253       pipe_sampler_view_reference(&$self->vertex_sampler_views[index], NULL);
254       u_sampler_view_default_template(&templ,
255                                       texture,
256                                       texture->format);
257       $self->vertex_sampler_views[index] = $self->pipe->create_sampler_view($self->pipe,
258                                                                             texture,
259                                                                             &templ);
260       
261       $self->pipe->set_vertex_sampler_views($self->pipe,
262                                             PIPE_MAX_VERTEX_SAMPLERS,
263                                             $self->vertex_sampler_views);
264    }
265
266    void set_vertex_buffer(unsigned index,
267                           unsigned stride, 
268                           unsigned max_index,
269                           unsigned buffer_offset,
270                           struct pipe_resource *buffer)
271    {
272       unsigned i;
273       struct pipe_vertex_buffer state;
274       
275       memset(&state, 0, sizeof(state));
276       state.stride = stride;
277       state.max_index = max_index;
278       state.buffer_offset = buffer_offset;
279       state.buffer = buffer;
280
281       memcpy(&$self->vertex_buffers[index], &state, sizeof(state));
282       
283       for(i = 0; i < PIPE_MAX_ATTRIBS; ++i)
284          if(self->vertex_buffers[i].buffer)
285             $self->num_vertex_buffers = i + 1;
286       
287       $self->pipe->set_vertex_buffers($self->pipe, 
288                                       $self->num_vertex_buffers, 
289                                       $self->vertex_buffers);
290    }
291
292    void set_vertex_element(unsigned index,
293                            const struct pipe_vertex_element *element) 
294    {
295       memcpy(&$self->vertex_elements[index], element, sizeof(*element));
296    }
297
298    void set_vertex_elements(unsigned num) 
299    {
300       $self->num_vertex_elements = num;
301       cso_set_vertex_elements($self->cso,
302                               $self->num_vertex_elements, 
303                               $self->vertex_elements);
304    }
305
306    /*
307     * Draw functions
308     */
309    
310    void draw_arrays(unsigned mode, unsigned start, unsigned count) {
311       $self->pipe->draw_arrays($self->pipe, mode, start, count);
312    }
313
314    void draw_elements( struct pipe_resource *indexBuffer,
315                        unsigned indexSize, int indexBias,
316                        unsigned mode, unsigned start, unsigned count) 
317    {
318       $self->pipe->draw_elements($self->pipe, 
319                                  indexBuffer, 
320                                  indexSize, 
321                                  indexBias,
322                                  mode, start, count);
323    }
324
325    void draw_range_elements( struct pipe_resource *indexBuffer,
326                              unsigned indexSize, int indexBias,
327                              unsigned minIndex, unsigned maxIndex,
328                              unsigned mode, unsigned start, unsigned count)
329    {
330       $self->pipe->draw_range_elements($self->pipe, 
331                                        indexBuffer, indexSize, indexBias,
332                                        minIndex, maxIndex,
333                                        mode, start, count);
334    }
335
336    void draw_vertices(unsigned prim,
337                       unsigned num_verts,
338                       unsigned num_attribs,
339                       const float *vertices) 
340    {
341       struct pipe_context *pipe = $self->pipe;
342       struct pipe_screen *screen = pipe->screen;
343       struct pipe_resource *vbuf;
344       struct pipe_transfer *transfer;
345       struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS];
346       struct pipe_vertex_buffer vbuffer;
347       float *map;
348       unsigned size;
349       unsigned i;
350
351       size = num_verts * num_attribs * 4 * sizeof(float);
352
353       vbuf = pipe_buffer_create(screen,
354                                 PIPE_BIND_VERTEX_BUFFER, 
355                                 size);
356       if(!vbuf)
357          goto error1;
358
359       map = pipe_buffer_map(pipe, vbuf, PIPE_TRANSFER_WRITE, &transfer);
360       if (!map)
361          goto error2;
362       memcpy(map, vertices, size);
363       pipe_buffer_unmap(pipe, vbuf, transfer);
364
365       cso_save_vertex_elements($self->cso);
366
367       /* tell pipe about the vertex attributes */
368       for (i = 0; i < num_attribs; i++) {
369          velements[i].src_offset = i * 4 * sizeof(float);
370          velements[i].instance_divisor = 0;
371          velements[i].vertex_buffer_index = 0;
372          velements[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
373       }
374       cso_set_vertex_elements($self->cso, num_attribs, velements);
375
376       /* tell pipe about the vertex buffer */
377       memset(&vbuffer, 0, sizeof(vbuffer));
378       vbuffer.buffer = vbuf;
379       vbuffer.stride = num_attribs * 4 * sizeof(float);  /* vertex size */
380       vbuffer.buffer_offset = 0;
381       vbuffer.max_index = num_verts - 1;
382       pipe->set_vertex_buffers(pipe, 1, &vbuffer);
383
384       /* draw */
385       pipe->draw_arrays(pipe, prim, 0, num_verts);
386
387       cso_restore_vertex_elements($self->cso);
388
389 error2:
390       pipe_resource_reference(&vbuf, NULL);
391 error1:
392       ;
393    }
394    
395    void
396    clear(unsigned buffers, const float *rgba, double depth = 0.0f,
397          unsigned stencil = 0)
398    {
399       $self->pipe->clear($self->pipe, buffers, rgba, depth, stencil);
400    }
401
402    void
403    flush(unsigned flags = 0) {
404       struct pipe_fence_handle *fence = NULL; 
405       $self->pipe->flush($self->pipe, flags | PIPE_FLUSH_RENDER_CACHE, &fence);
406       if(fence) {
407          /* TODO: allow asynchronous operation */ 
408          $self->pipe->screen->fence_finish( $self->pipe->screen, fence, 0 );
409          $self->pipe->screen->fence_reference( $self->pipe->screen, &fence, NULL );
410       }
411    }
412
413    /*
414     * Surface functions
415     */
416
417    void surface_copy(struct st_surface *dst,
418                      unsigned destx, unsigned desty,
419                      struct st_surface *src,
420                      unsigned srcx, unsigned srcy,
421                      unsigned width, unsigned height) 
422    {
423 /* XXX
424       struct pipe_surface *_dst = NULL;
425       struct pipe_surface *_src = NULL;
426
427       _dst = st_pipe_surface(dst, PIPE_BIND_BLIT_DESTINATION);
428       if(!_dst)
429          SWIG_exception(SWIG_ValueError, "couldn't acquire destination surface for writing");
430
431       _src = st_pipe_surface(src, PIPE_BIND_BLIT_SOURCE);
432       if(!_src)
433          SWIG_exception(SWIG_ValueError, "couldn't acquire source surface for reading");
434
435       $self->pipe->surface_copy($self->pipe, _dst, destx, desty, _src, srcx, srcy, width, height);
436
437    fail:
438       pipe_surface_reference(&_src, NULL);
439       pipe_surface_reference(&_dst, NULL);
440 */
441    struct pipe_subresource subdst, subsrc;
442    subsrc.face = src->face;
443    subsrc.level = src->level;
444    subdst.face = dst->face;
445    subdst.level = dst->level;
446    $self->pipe->resource_copy_region($self->pipe, dst->texture, subdst, destx, desty, dst->zslice,
447                                      src->texture, subsrc, srcx, srcy, src->zslice, width, height);
448    }
449
450    void clear_render_target(struct st_surface *dst,
451                             float *rgba,
452                             unsigned x, unsigned y,
453                             unsigned width, unsigned height)
454    {
455       struct pipe_surface *_dst = NULL;
456
457      _dst = st_pipe_surface(dst, PIPE_BIND_RENDER_TARGET);
458       if(!_dst)
459          SWIG_exception(SWIG_ValueError, "couldn't acquire destination surface for writing");
460
461       $self->pipe->clear_render_target($self->pipe, _dst, rgba, x, y, width, height);
462
463    fail:
464       pipe_surface_reference(&_dst, NULL);
465    }
466
467    void clear_depth_stencil(struct st_surface *dst,
468                             unsigned clear_flags,
469                             double depth,
470                             unsigned stencil,
471                             unsigned x, unsigned y,
472                             unsigned width, unsigned height)
473    {
474       struct pipe_surface *_dst = NULL;
475
476      _dst = st_pipe_surface(dst, PIPE_BIND_DEPTH_STENCIL);
477       if(!_dst)
478          SWIG_exception(SWIG_ValueError, "couldn't acquire destination surface for writing");
479
480       $self->pipe->clear_depth_stencil($self->pipe, _dst, clear_flags, depth, stencil,
481                                        x, y, width, height);
482
483    fail:
484       pipe_surface_reference(&_dst, NULL);
485    }
486
487    %cstring_output_allocate_size(char **STRING, int *LENGTH, free(*$1));
488    void
489    surface_read_raw(struct st_surface *surface,
490                     unsigned x, unsigned y, unsigned w, unsigned h,
491                     char **STRING, int *LENGTH)
492    {
493       struct pipe_resource *texture = surface->texture;
494       struct pipe_context *pipe = $self->pipe;
495       struct pipe_transfer *transfer;
496       unsigned stride;
497
498       stride = util_format_get_stride(texture->format, w);
499       *LENGTH = util_format_get_nblocksy(texture->format, h) * stride;
500       *STRING = (char *) malloc(*LENGTH);
501       if(!*STRING)
502          return;
503
504       transfer = pipe_get_transfer(pipe,
505                                    surface->texture,
506                                    surface->face,
507                                    surface->level,
508                                    surface->zslice,
509                                    PIPE_TRANSFER_READ,
510                                    x, y, w, h);
511       if(transfer) {
512          pipe_get_tile_raw(pipe, transfer, 0, 0, w, h, *STRING, stride);
513          pipe->transfer_destroy(pipe, transfer);
514       }
515    }
516
517    %cstring_input_binary(const char *STRING, unsigned LENGTH);
518    void
519    surface_write_raw(struct st_surface *surface,
520                      unsigned x, unsigned y, unsigned w, unsigned h,
521                      const char *STRING, unsigned LENGTH, unsigned stride = 0)
522    {
523       struct pipe_resource *texture = surface->texture;
524       struct pipe_context *pipe = $self->pipe;
525       struct pipe_transfer *transfer;
526
527       if(stride == 0)
528          stride = util_format_get_stride(texture->format, w);
529
530       if(LENGTH < util_format_get_nblocksy(texture->format, h) * stride)
531          SWIG_exception(SWIG_ValueError, "offset must be smaller than buffer size");
532
533       transfer = pipe_get_transfer(pipe,
534                                    surface->texture,
535                                    surface->face,
536                                    surface->level,
537                                    surface->zslice,
538                                    PIPE_TRANSFER_WRITE,
539                                    x, y, w, h);
540       if(!transfer)
541          SWIG_exception(SWIG_MemoryError, "couldn't initiate transfer");
542
543       pipe_put_tile_raw(pipe, transfer, 0, 0, w, h, STRING, stride);
544       pipe->transfer_destroy(pipe, transfer);
545
546    fail:
547       return;
548    }
549
550    void
551    surface_read_rgba(struct st_surface *surface,
552                      unsigned x, unsigned y, unsigned w, unsigned h,
553                      float *rgba)
554    {
555       struct pipe_context *pipe = $self->pipe;
556       struct pipe_transfer *transfer;
557       transfer = pipe_get_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_rgba(pipe, transfer, 0, 0, w, h, rgba);
566          pipe->transfer_destroy(pipe, transfer);
567       }
568    }
569
570    void
571    surface_write_rgba(struct st_surface *surface,
572                       unsigned x, unsigned y, unsigned w, unsigned h,
573                       const float *rgba)
574    {
575       struct pipe_context *pipe = $self->pipe;
576       struct pipe_transfer *transfer;
577       transfer = pipe_get_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_rgba(pipe, transfer, 0, 0, w, h, rgba);
586          pipe->transfer_destroy(pipe, transfer);
587       }
588    }
589
590    %cstring_output_allocate_size(char **STRING, int *LENGTH, free(*$1));
591    void
592    surface_read_rgba8(struct st_surface *surface,
593                       unsigned x, unsigned y, unsigned w, unsigned h,
594                       char **STRING, int *LENGTH)
595    {
596       struct pipe_context *pipe = $self->pipe;
597       struct pipe_transfer *transfer;
598       float *rgba;
599       unsigned char *rgba8;
600       unsigned i, j, k;
601
602       *LENGTH = 0;
603       *STRING = NULL;
604
605       if (!surface)
606          return;
607
608       *LENGTH = h*w*4;
609       *STRING = (char *) malloc(*LENGTH);
610       if(!*STRING)
611          return;
612
613       rgba = malloc(h*w*4*sizeof(float));
614       if(!rgba)
615          return;
616
617       rgba8 = (unsigned char *) *STRING;
618
619       transfer = pipe_get_transfer(pipe,
620                                    surface->texture,
621                                    surface->face,
622                                    surface->level,
623                                    surface->zslice,
624                                    PIPE_TRANSFER_READ,
625                                    x, y, w, h);
626       if(transfer) {
627          pipe_get_tile_rgba(pipe, transfer, 0, 0, w, h, rgba);
628          for(j = 0; j < h; ++j) {
629             for(i = 0; i < w; ++i)
630                for(k = 0; k <4; ++k)
631                   rgba8[j*w*4 + i*4 + k] = float_to_ubyte(rgba[j*w*4 + i*4 + k]);
632          }
633          pipe->transfer_destroy(pipe, transfer);
634       }
635
636       free(rgba);
637    }
638
639    void
640    surface_read_z(struct st_surface *surface,
641                   unsigned x, unsigned y, unsigned w, unsigned h,
642                   unsigned *z)
643    {
644       struct pipe_context *pipe = $self->pipe;
645       struct pipe_transfer *transfer;
646       transfer = pipe_get_transfer(pipe,
647                                    surface->texture,
648                                    surface->face,
649                                    surface->level,
650                                    surface->zslice,
651                                    PIPE_TRANSFER_READ,
652                                    x, y, w, h);
653       if(transfer) {
654          pipe_get_tile_z(pipe, transfer, 0, 0, w, h, z);
655          pipe->transfer_destroy(pipe, transfer);
656       }
657    }
658
659    void
660    surface_write_z(struct st_surface *surface,
661                    unsigned x, unsigned y, unsigned w, unsigned h,
662                    const unsigned *z)
663    {
664       struct pipe_context *pipe = $self->pipe;
665       struct pipe_transfer *transfer;
666       transfer = pipe_get_transfer(pipe,
667                                    surface->texture,
668                                    surface->face,
669                                    surface->level,
670                                    surface->zslice,
671                                    PIPE_TRANSFER_WRITE,
672                                    x, y, w, h);
673       if(transfer) {
674          pipe_put_tile_z(pipe, transfer, 0, 0, w, h, z);
675          pipe->transfer_destroy(pipe, transfer);
676       }
677    }
678
679    void
680    surface_sample_rgba(struct st_surface *surface,
681                        float *rgba,
682                        int norm = 0)
683    {
684       st_sample_surface($self->pipe, surface, rgba, norm != 0);
685    }
686
687    unsigned
688    surface_compare_rgba(struct st_surface *surface,
689                         unsigned x, unsigned y, unsigned w, unsigned h,
690                         const float *rgba, float tol = 0.0)
691    {
692       struct pipe_context *pipe = $self->pipe;
693       struct pipe_transfer *transfer;
694       float *rgba2;
695       const float *p1;
696       const float *p2;
697       unsigned i, j, n;
698
699       rgba2 = MALLOC(h*w*4*sizeof(float));
700       if(!rgba2)
701          return ~0;
702
703       transfer = pipe_get_transfer(pipe,
704                                    surface->texture,
705                                    surface->face,
706                                    surface->level,
707                                    surface->zslice,
708                                    PIPE_TRANSFER_READ,
709                                    x, y, w, h);
710       if(!transfer) {
711          FREE(rgba2);
712          return ~0;
713       }
714
715       pipe_get_tile_rgba(pipe, transfer, 0, 0, w, h, rgba2);
716       pipe->transfer_destroy(pipe, transfer);
717
718       p1 = rgba;
719       p2 = rgba2;
720       n = 0;
721       for(i = h*w; i; --i) {
722          unsigned differs = 0;
723          for(j = 4; j; --j) {
724             float delta = *p2++ - *p1++;
725             if (delta < -tol || delta > tol)
726                 differs = 1;
727          }
728          n += differs;
729       }
730
731       FREE(rgba2);
732
733       return n;
734    }
735
736    %cstring_input_binary(const char *STRING, unsigned LENGTH);
737    void
738    transfer_inline_write(struct pipe_resource *resource,
739                          struct pipe_subresource *sr,
740                          unsigned usage,
741                          const struct pipe_box *box,
742                          const char *STRING, unsigned LENGTH,
743                          unsigned stride,
744                          unsigned slice_stride)
745    {
746       struct pipe_context *pipe = $self->pipe;
747
748       pipe->transfer_inline_write(pipe, resource, *sr, usage, box, STRING, stride, slice_stride);
749    }
750
751    %cstring_output_allocate_size(char **STRING, int *LENGTH, free(*$1));
752    void buffer_read(struct pipe_resource *buffer,
753                     char **STRING, int *LENGTH)
754    {
755       struct pipe_context *pipe = $self->pipe;
756
757       assert(buffer->target == PIPE_BUFFER);
758
759       *LENGTH = buffer->width0;
760       *STRING = (char *) malloc(buffer->width0);
761       if(!*STRING)
762          return;
763
764       pipe_buffer_read(pipe, buffer, 0, buffer->width0, *STRING);
765    }
766
767    void buffer_write(struct pipe_resource *buffer,
768                      const char *STRING, unsigned LENGTH, unsigned offset = 0)
769    {
770       struct pipe_context *pipe = $self->pipe;
771
772       assert(buffer->target == PIPE_BUFFER);
773
774       if(offset > buffer->width0)
775          SWIG_exception(SWIG_ValueError, "offset must be smaller than buffer size");
776
777       if(offset + LENGTH > buffer->width0)
778          SWIG_exception(SWIG_ValueError, "data length must fit inside the buffer");
779
780       pipe_buffer_write(pipe, buffer, offset, LENGTH, STRING);
781
782 fail:
783       return;
784    }
785
786 };