/************************************************************************** * * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the * "Software"), to deal in the Software without restriction, including * without limitation the rights to use, copy, modify, merge, publish, * distribute, sub license, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to * the following conditions: * * The above copyright notice and this permission notice (including the * next paragraph) shall be included in all copies or substantial portions * of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * **************************************************************************/ /** * @file * SWIG interface definion for Gallium types. * * @author Jose Fonseca */ %nodefaultctor pipe_texture; %nodefaultctor st_surface; %nodefaultctor pipe_buffer; %nodefaultdtor pipe_texture; %nodefaultdtor st_surface; %nodefaultdtor pipe_buffer; %ignore pipe_texture::screen; %immutable st_surface::texture; %immutable st_surface::face; %immutable st_surface::level; %immutable st_surface::zslice; %newobject pipe_texture::get_surface; %extend pipe_texture { ~pipe_texture() { struct pipe_texture *ptr = $self; pipe_texture_reference(&ptr, NULL); } unsigned get_width(unsigned level=0) { return $self->width[level]; } unsigned get_height(unsigned level=0) { return $self->height[level]; } unsigned get_depth(unsigned level=0) { return $self->depth[level]; } unsigned get_nblocksx(unsigned level=0) { return $self->nblocksx[level]; } unsigned get_nblocksy(unsigned level=0) { return $self->nblocksy[level]; } /** Get a surface which is a "view" into a texture */ struct st_surface * get_surface(unsigned face=0, unsigned level=0, unsigned zslice=0) { struct st_surface *surface; if(face >= ($self->target == PIPE_TEXTURE_CUBE ? 6U : 1U)) SWIG_exception(SWIG_ValueError, "face out of bounds"); if(level > $self->last_level) SWIG_exception(SWIG_ValueError, "level out of bounds"); if(zslice >= $self->depth[level]) SWIG_exception(SWIG_ValueError, "zslice out of bounds"); surface = CALLOC_STRUCT(st_surface); if(!surface) return NULL; pipe_texture_reference(&surface->texture, $self); surface->face = face; surface->level = level; surface->zslice = zslice; return surface; fail: return NULL; } }; struct st_surface { %immutable; struct pipe_texture *texture; unsigned face; unsigned level; unsigned zslice; }; %extend st_surface { %immutable; unsigned format; unsigned width; unsigned height; unsigned nblocksx; unsigned nblocksy; ~st_surface() { pipe_texture_reference(&$self->texture, NULL); FREE($self); } %cstring_output_allocate_size(char **STRING, int *LENGTH, free(*$1)); void get_tile_raw(unsigned x, unsigned y, unsigned w, unsigned h, char **STRING, int *LENGTH) { struct pipe_texture *texture = $self->texture; struct pipe_screen *screen = texture->screen; struct pipe_transfer *transfer; unsigned stride; stride = pf_get_nblocksx(&texture->block, w) * texture->block.size; *LENGTH = pf_get_nblocksy(&texture->block, h) * stride; *STRING = (char *) malloc(*LENGTH); if(!*STRING) return; transfer = screen->get_tex_transfer(screen, $self->texture, $self->face, $self->level, $self->zslice, PIPE_TRANSFER_READ, x, y, w, h); if(transfer) { pipe_get_tile_raw(transfer, 0, 0, w, h, *STRING, stride); screen->tex_transfer_destroy(transfer); } } %cstring_input_binary(const char *STRING, unsigned LENGTH); void put_tile_raw(unsigned x, unsigned y, unsigned w, unsigned h, const char *STRING, unsigned LENGTH, unsigned stride = 0) { struct pipe_texture *texture = $self->texture; struct pipe_screen *screen = texture->screen; struct pipe_transfer *transfer; if(stride == 0) stride = pf_get_nblocksx(&texture->block, w) * texture->block.size; if(LENGTH < pf_get_nblocksy(&texture->block, h) * stride) SWIG_exception(SWIG_ValueError, "offset must be smaller than buffer size"); transfer = screen->get_tex_transfer(screen, $self->texture, $self->face, $self->level, $self->zslice, PIPE_TRANSFER_WRITE, x, y, w, h); if(!transfer) SWIG_exception(SWIG_MemoryError, "couldn't initiate transfer"); pipe_put_tile_raw(transfer, 0, 0, w, h, STRING, stride); screen->tex_transfer_destroy(transfer); fail: return; } void get_tile_rgba(unsigned x, unsigned y, unsigned w, unsigned h, float *rgba) { struct pipe_screen *screen = $self->texture->screen; struct pipe_transfer *transfer; transfer = screen->get_tex_transfer(screen, $self->texture, $self->face, $self->level, $self->zslice, PIPE_TRANSFER_READ, x, y, w, h); if(transfer) { pipe_get_tile_rgba(transfer, 0, 0, w, h, rgba); screen->tex_transfer_destroy(transfer); } } void put_tile_rgba(unsigned x, unsigned y, unsigned w, unsigned h, const float *rgba) { struct pipe_screen *screen = $self->texture->screen; struct pipe_transfer *transfer; transfer = screen->get_tex_transfer(screen, $self->texture, $self->face, $self->level, $self->zslice, PIPE_TRANSFER_WRITE, x, y, w, h); if(transfer) { pipe_put_tile_rgba(transfer, 0, 0, w, h, rgba); screen->tex_transfer_destroy(transfer); } } %cstring_output_allocate_size(char **STRING, int *LENGTH, free(*$1)); void get_tile_rgba8(unsigned x, unsigned y, unsigned w, unsigned h, char **STRING, int *LENGTH) { struct pipe_screen *screen = $self->texture->screen; struct pipe_transfer *transfer; float *rgba; unsigned char *rgba8; unsigned i, j, k; *LENGTH = 0; *STRING = NULL; if (!$self) return; *LENGTH = h*w*4; *STRING = (char *) malloc(*LENGTH); if(!*STRING) return; rgba = malloc(h*w*4*sizeof(float)); if(!rgba) return; rgba8 = (unsigned char *) *STRING; transfer = screen->get_tex_transfer(screen, $self->texture, $self->face, $self->level, $self->zslice, PIPE_TRANSFER_READ, x, y, w, h); if(transfer) { pipe_get_tile_rgba(transfer, 0, 0, w, h, rgba); for(j = 0; j < h; ++j) { for(i = 0; i < w; ++i) for(k = 0; k <4; ++k) rgba8[j*w*4 + i*4 + k] = float_to_ubyte(rgba[j*w*4 + i*4 + k]); } screen->tex_transfer_destroy(transfer); } free(rgba); } void get_tile_z(unsigned x, unsigned y, unsigned w, unsigned h, unsigned *z) { struct pipe_screen *screen = $self->texture->screen; struct pipe_transfer *transfer; transfer = screen->get_tex_transfer(screen, $self->texture, $self->face, $self->level, $self->zslice, PIPE_TRANSFER_READ, x, y, w, h); if(transfer) { pipe_get_tile_z(transfer, 0, 0, w, h, z); screen->tex_transfer_destroy(transfer); } } void put_tile_z(unsigned x, unsigned y, unsigned w, unsigned h, const unsigned *z) { struct pipe_screen *screen = $self->texture->screen; struct pipe_transfer *transfer; transfer = screen->get_tex_transfer(screen, $self->texture, $self->face, $self->level, $self->zslice, PIPE_TRANSFER_WRITE, x, y, w, h); if(transfer) { pipe_put_tile_z(transfer, 0, 0, w, h, z); screen->tex_transfer_destroy(transfer); } } void sample_rgba(float *rgba) { st_sample_surface($self, rgba); } unsigned compare_tile_rgba(unsigned x, unsigned y, unsigned w, unsigned h, const float *rgba, float tol = 0.0) { struct pipe_screen *screen = $self->texture->screen; struct pipe_transfer *transfer; float *rgba2; const float *p1; const float *p2; unsigned i, j, n; rgba2 = MALLOC(h*w*4*sizeof(float)); if(!rgba2) return ~0; transfer = screen->get_tex_transfer(screen, $self->texture, $self->face, $self->level, $self->zslice, PIPE_TRANSFER_READ, x, y, w, h); if(!transfer) { FREE(rgba2); return ~0; } pipe_get_tile_rgba(transfer, 0, 0, w, h, rgba2); screen->tex_transfer_destroy(transfer); p1 = rgba; p2 = rgba2; n = 0; for(i = h*w; i; --i) { unsigned differs = 0; for(j = 4; j; --j) { float delta = *p2++ - *p1++; if (delta < -tol || delta > tol) differs = 1; } n += differs; } FREE(rgba2); return n; } }; %{ static enum pipe_format st_surface_format_get(struct st_surface *surface) { return surface->texture->format; } static unsigned st_surface_width_get(struct st_surface *surface) { return surface->texture->width[surface->level]; } static unsigned st_surface_height_get(struct st_surface *surface) { return surface->texture->height[surface->level]; } static unsigned st_surface_nblocksx_get(struct st_surface *surface) { return surface->texture->nblocksx[surface->level]; } static unsigned st_surface_nblocksy_get(struct st_surface *surface) { return surface->texture->nblocksy[surface->level]; } %} /* Avoid naming conflict with p_inlines.h's pipe_buffer_read/write */ %rename(read) read_; %rename(write) write_; %extend pipe_buffer { ~pipe_buffer() { struct pipe_buffer *ptr = $self; pipe_buffer_reference(&ptr, NULL); } unsigned __len__(void) { assert(p_atomic_read(&$self->reference.count) > 0); return $self->size; } %cstring_output_allocate_size(char **STRING, int *LENGTH, free(*$1)); void read_(char **STRING, int *LENGTH) { struct pipe_screen *screen = $self->screen; assert(p_atomic_read(&$self->reference.count) > 0); *LENGTH = $self->size; *STRING = (char *) malloc($self->size); if(!*STRING) return; pipe_buffer_read(screen, $self, 0, $self->size, STRING); } %cstring_input_binary(const char *STRING, unsigned LENGTH); void write_(const char *STRING, unsigned LENGTH, unsigned offset = 0) { struct pipe_screen *screen = $self->screen; assert(p_atomic_read(&$self->reference.count) > 0); if(offset > $self->size) SWIG_exception(SWIG_ValueError, "offset must be smaller than buffer size"); if(offset + LENGTH > $self->size) SWIG_exception(SWIG_ValueError, "data length must fit inside the buffer"); pipe_buffer_write(screen, $self, offset, LENGTH, STRING); fail: return; } };