blob: 1d513abf3c75489a751cf7de42e4b6299c655c22 [file] [log] [blame]
/**************************************************************************
*
* 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 <jrfonseca@tungstengraphics.com>
*/
%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;
}
};