Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 3769 → Rev 3770

/drivers/video/Gallium/auxiliary/draw/draw_cliptest_tmp.h
0,0 → 1,198
/**************************************************************************
*
* Copyright 2010, VMware, inc.
* 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 VMWARE 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.
*
**************************************************************************/
 
static boolean TAG(do_cliptest)( struct pt_post_vs *pvs,
struct draw_vertex_info *info,
const struct draw_prim_info *prim_info )
{
struct vertex_header *out = info->verts;
/* const */ float (*plane)[4] = pvs->draw->plane;
const unsigned pos = draw_current_shader_position_output(pvs->draw);
const unsigned cv = draw_current_shader_clipvertex_output(pvs->draw);
unsigned cd[2];
const unsigned ef = pvs->draw->vs.edgeflag_output;
unsigned ucp_enable = pvs->draw->rasterizer->clip_plane_enable;
unsigned flags = (FLAGS);
unsigned need_pipeline = 0;
unsigned j;
unsigned i;
bool have_cd = false;
unsigned viewport_index_output =
draw_current_shader_viewport_index_output(pvs->draw);
int viewport_index =
draw_current_shader_uses_viewport_index(pvs->draw) ?
*((unsigned*)out->data[viewport_index_output]): 0;
int num_written_clipdistance =
draw_current_shader_num_written_clipdistances(pvs->draw);
 
cd[0] = draw_current_shader_clipdistance_output(pvs->draw, 0);
cd[1] = draw_current_shader_clipdistance_output(pvs->draw, 1);
 
if (cd[0] != pos || cd[1] != pos)
have_cd = true;
 
/* If clipdistance semantic has been written by the shader
* that means we're expected to do 'user plane clipping' */
if (num_written_clipdistance && !(flags & DO_CLIP_USER)) {
flags |= DO_CLIP_USER;
ucp_enable = (1 << num_written_clipdistance) - 1;
}
 
for (j = 0; j < info->count; j++) {
float *position = out->data[pos];
unsigned mask = 0x0;
float *scale = pvs->draw->viewports[0].scale;
float *trans = pvs->draw->viewports[0].translate;
if (draw_current_shader_uses_viewport_index(pvs->draw)) {
unsigned verts_per_prim = u_vertices_per_prim(prim_info->prim);
/* only change the viewport_index for the leading vertex */
if (!(j % verts_per_prim)) {
viewport_index = *((unsigned*)out->data[viewport_index_output]);
viewport_index = draw_clamp_viewport_idx(viewport_index);
}
scale = pvs->draw->viewports[viewport_index].scale;
trans = pvs->draw->viewports[viewport_index].translate;
}
initialize_vertex_header(out);
 
if (flags & (DO_CLIP_XY | DO_CLIP_XY_GUARD_BAND |
DO_CLIP_FULL_Z | DO_CLIP_HALF_Z | DO_CLIP_USER)) {
float *clipvertex = position;
 
if ((flags & DO_CLIP_USER) && cv != pos)
clipvertex = out->data[cv];
 
for (i = 0; i < 4; i++) {
out->clip[i] = clipvertex[i];
out->pre_clip_pos[i] = position[i];
}
 
/* Do the hardwired planes first:
*/
if (flags & DO_CLIP_XY_GUARD_BAND) {
if (-0.50 * position[0] + position[3] < 0) mask |= (1<<0);
if ( 0.50 * position[0] + position[3] < 0) mask |= (1<<1);
if (-0.50 * position[1] + position[3] < 0) mask |= (1<<2);
if ( 0.50 * position[1] + position[3] < 0) mask |= (1<<3);
}
else if (flags & DO_CLIP_XY) {
if (-position[0] + position[3] < 0) mask |= (1<<0);
if ( position[0] + position[3] < 0) mask |= (1<<1);
if (-position[1] + position[3] < 0) mask |= (1<<2);
if ( position[1] + position[3] < 0) mask |= (1<<3);
}
 
/* Clip Z planes according to full cube, half cube or none.
*/
if (flags & DO_CLIP_FULL_Z) {
if ( position[2] + position[3] < 0) mask |= (1<<4);
if (-position[2] + position[3] < 0) mask |= (1<<5);
}
else if (flags & DO_CLIP_HALF_Z) {
if ( position[2] < 0) mask |= (1<<4);
if (-position[2] + position[3] < 0) mask |= (1<<5);
}
 
if (flags & DO_CLIP_USER) {
unsigned ucp_mask = ucp_enable;
 
while (ucp_mask) {
unsigned plane_idx = ffs(ucp_mask)-1;
ucp_mask &= ~(1 << plane_idx);
plane_idx += 6;
 
/*
* for user clipping check if we have a clip distance output
* and the shader has written to it, otherwise use clipvertex
* to decide when the plane is clipping.
*/
if (have_cd && num_written_clipdistance) {
float clipdist;
i = plane_idx - 6;
out->have_clipdist = 1;
/* first four clip distance in first vector etc. */
if (i < 4)
clipdist = out->data[cd[0]][i];
else
clipdist = out->data[cd[1]][i-4];
if (clipdist < 0)
mask |= 1 << plane_idx;
} else {
if (dot4(clipvertex, plane[plane_idx]) < 0)
mask |= 1 << plane_idx;
}
}
}
 
out->clipmask = mask;
need_pipeline |= out->clipmask;
}
 
/*
* Transform the vertex position from clip coords to window coords,
* if the vertex is unclipped.
*/
if ((flags & DO_VIEWPORT) && mask == 0)
{
/* divide by w */
float w = 1.0f / position[3];
 
/* Viewport mapping */
position[0] = position[0] * w * scale[0] + trans[0];
position[1] = position[1] * w * scale[1] + trans[1];
position[2] = position[2] * w * scale[2] + trans[2];
position[3] = w;
}
#ifdef DEBUG
/* For debug builds, set the clipped vertex's window coordinate
* to NaN to help catch potential errors later.
*/
else {
float zero = 0.0f;
position[0] =
position[1] =
position[2] =
position[3] = zero / zero; /* MSVC doesn't accept 0.0 / 0.0 */
}
#endif
 
if ((flags & DO_EDGEFLAG) && ef) {
const float *edgeflag = out->data[ef];
out->edgeflag = !(edgeflag[0] != 1.0f);
need_pipeline |= !out->edgeflag;
}
 
out = (struct vertex_header *)( (char *)out + info->stride );
}
 
return need_pipeline != 0;
}
 
 
#undef FLAGS
#undef TAG
/drivers/video/Gallium/auxiliary/draw/draw_context.c
0,0 → 1,972
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
 
#include "pipe/p_context.h"
#include "util/u_memory.h"
#include "util/u_math.h"
#include "util/u_cpu_detect.h"
#include "util/u_inlines.h"
#include "util/u_helpers.h"
#include "util/u_prim.h"
#include "draw_context.h"
#include "draw_vs.h"
#include "draw_gs.h"
 
#if HAVE_LLVM
#include "gallivm/lp_bld_init.h"
#include "gallivm/lp_bld_limits.h"
#include "draw_llvm.h"
 
boolean
draw_get_option_use_llvm(void)
{
static boolean first = TRUE;
static boolean value;
if (first) {
first = FALSE;
value = debug_get_bool_option("DRAW_USE_LLVM", TRUE);
 
#ifdef PIPE_ARCH_X86
util_cpu_detect();
/* require SSE2 due to LLVM PR6960. */
if (!util_cpu_caps.has_sse2)
value = FALSE;
#endif
}
return value;
}
#endif
 
 
/**
* Create new draw module context with gallivm state for LLVM JIT.
*/
static struct draw_context *
draw_create_context(struct pipe_context *pipe, boolean try_llvm)
{
struct draw_context *draw = CALLOC_STRUCT( draw_context );
if (draw == NULL)
goto err_out;
 
#if HAVE_LLVM
if (try_llvm && draw_get_option_use_llvm()) {
draw->llvm = draw_llvm_create(draw);
if (!draw->llvm)
goto err_destroy;
}
#endif
 
draw->pipe = pipe;
 
if (!draw_init(draw))
goto err_destroy;
 
return draw;
 
err_destroy:
draw_destroy( draw );
err_out:
return NULL;
}
 
 
/**
* Create new draw module context, with LLVM JIT.
*/
struct draw_context *
draw_create(struct pipe_context *pipe)
{
return draw_create_context(pipe, TRUE);
}
 
 
/**
* Create a new draw context, without LLVM JIT.
*/
struct draw_context *
draw_create_no_llvm(struct pipe_context *pipe)
{
return draw_create_context(pipe, FALSE);
}
 
 
boolean draw_init(struct draw_context *draw)
{
/*
* Note that several functions compute the clipmask of the predefined
* formats with hardcoded formulas instead of using these. So modifications
* here must be reflected there too.
*/
 
ASSIGN_4V( draw->plane[0], -1, 0, 0, 1 );
ASSIGN_4V( draw->plane[1], 1, 0, 0, 1 );
ASSIGN_4V( draw->plane[2], 0, -1, 0, 1 );
ASSIGN_4V( draw->plane[3], 0, 1, 0, 1 );
ASSIGN_4V( draw->plane[4], 0, 0, 1, 1 ); /* yes these are correct */
ASSIGN_4V( draw->plane[5], 0, 0, -1, 1 ); /* mesa's a bit wonky */
draw->clip_xy = TRUE;
draw->clip_z = TRUE;
 
draw->pt.user.planes = (float (*) [DRAW_TOTAL_CLIP_PLANES][4]) &(draw->plane[0]);
draw->pt.user.eltMax = ~0;
 
if (!draw_pipeline_init( draw ))
return FALSE;
 
if (!draw_pt_init( draw ))
return FALSE;
 
if (!draw_vs_init( draw ))
return FALSE;
 
if (!draw_gs_init( draw ))
return FALSE;
 
draw->quads_always_flatshade_last = !draw->pipe->screen->get_param(
draw->pipe->screen, PIPE_CAP_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION);
 
return TRUE;
}
 
/*
* Called whenever we're starting to draw a new instance.
* Some internal structures don't want to have to reset internal
* members on each invocation (because their state might have to persist
* between multiple primitive restart rendering call) but might have to
* for each new instance.
* This is particularly the case for primitive id's in geometry shader.
*/
void draw_new_instance(struct draw_context *draw)
{
draw_geometry_shader_new_instance(draw->gs.geometry_shader);
}
 
 
void draw_destroy( struct draw_context *draw )
{
struct pipe_context *pipe;
unsigned i, j;
 
if (!draw)
return;
 
pipe = draw->pipe;
 
/* free any rasterizer CSOs that we may have created.
*/
for (i = 0; i < 2; i++) {
for (j = 0; j < 2; j++) {
if (draw->rasterizer_no_cull[i][j]) {
pipe->delete_rasterizer_state(pipe, draw->rasterizer_no_cull[i][j]);
}
}
}
 
for (i = 0; i < draw->pt.nr_vertex_buffers; i++) {
pipe_resource_reference(&draw->pt.vertex_buffer[i].buffer, NULL);
}
 
/* Not so fast -- we're just borrowing this at the moment.
*
if (draw->render)
draw->render->destroy( draw->render );
*/
 
draw_pipeline_destroy( draw );
draw_pt_destroy( draw );
draw_vs_destroy( draw );
draw_gs_destroy( draw );
#ifdef HAVE_LLVM
if (draw->llvm)
draw_llvm_destroy( draw->llvm );
#endif
 
FREE( draw );
}
 
 
 
void draw_flush( struct draw_context *draw )
{
draw_do_flush( draw, DRAW_FLUSH_BACKEND );
}
 
 
/**
* Specify the Minimum Resolvable Depth factor for polygon offset.
* This factor potentially depends on the number of Z buffer bits,
* the rasterization algorithm and the arithmetic performed on Z
* values between vertex shading and rasterization. It will vary
* from one driver to another.
*/
void draw_set_mrd(struct draw_context *draw, double mrd)
{
draw->mrd = mrd;
}
 
 
static void update_clip_flags( struct draw_context *draw )
{
draw->clip_xy = !draw->driver.bypass_clip_xy;
draw->guard_band_xy = (!draw->driver.bypass_clip_xy &&
draw->driver.guard_band_xy);
draw->clip_z = (!draw->driver.bypass_clip_z &&
draw->rasterizer && draw->rasterizer->depth_clip);
draw->clip_user = draw->rasterizer &&
draw->rasterizer->clip_plane_enable != 0;
}
 
/**
* Register new primitive rasterization/rendering state.
* This causes the drawing pipeline to be rebuilt.
*/
void draw_set_rasterizer_state( struct draw_context *draw,
const struct pipe_rasterizer_state *raster,
void *rast_handle )
{
if (!draw->suspend_flushing) {
draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
 
draw->rasterizer = raster;
draw->rast_handle = rast_handle;
update_clip_flags(draw);
}
}
 
/* With a little more work, llvmpipe will be able to turn this off and
* do its own x/y clipping.
*
* Some hardware can turn off clipping altogether - in particular any
* hardware with a TNL unit can do its own clipping, even if it is
* relying on the draw module for some other reason.
*/
void draw_set_driver_clipping( struct draw_context *draw,
boolean bypass_clip_xy,
boolean bypass_clip_z,
boolean guard_band_xy)
{
draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
 
draw->driver.bypass_clip_xy = bypass_clip_xy;
draw->driver.bypass_clip_z = bypass_clip_z;
draw->driver.guard_band_xy = guard_band_xy;
update_clip_flags(draw);
}
 
 
/**
* Plug in the primitive rendering/rasterization stage (which is the last
* stage in the drawing pipeline).
* This is provided by the device driver.
*/
void draw_set_rasterize_stage( struct draw_context *draw,
struct draw_stage *stage )
{
draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
 
draw->pipeline.rasterize = stage;
}
 
 
/**
* Set the draw module's clipping state.
*/
void draw_set_clip_state( struct draw_context *draw,
const struct pipe_clip_state *clip )
{
draw_do_flush(draw, DRAW_FLUSH_PARAMETER_CHANGE);
 
memcpy(&draw->plane[6], clip->ucp, sizeof(clip->ucp));
}
 
 
/**
* Set the draw module's viewport state.
*/
void draw_set_viewport_states( struct draw_context *draw,
unsigned start_slot,
unsigned num_viewports,
const struct pipe_viewport_state *vps )
{
const struct pipe_viewport_state *viewport = vps;
draw_do_flush(draw, DRAW_FLUSH_PARAMETER_CHANGE);
 
debug_assert(start_slot < PIPE_MAX_VIEWPORTS);
debug_assert((start_slot + num_viewports) <= PIPE_MAX_VIEWPORTS);
 
memcpy(draw->viewports + start_slot, vps,
sizeof(struct pipe_viewport_state) * num_viewports);
 
draw->identity_viewport = (num_viewports == 1) &&
(viewport->scale[0] == 1.0f &&
viewport->scale[1] == 1.0f &&
viewport->scale[2] == 1.0f &&
viewport->scale[3] == 1.0f &&
viewport->translate[0] == 0.0f &&
viewport->translate[1] == 0.0f &&
viewport->translate[2] == 0.0f &&
viewport->translate[3] == 0.0f);
}
 
 
 
void
draw_set_vertex_buffers(struct draw_context *draw,
unsigned start_slot, unsigned count,
const struct pipe_vertex_buffer *buffers)
{
assert(start_slot + count <= PIPE_MAX_ATTRIBS);
 
util_set_vertex_buffers_count(draw->pt.vertex_buffer,
&draw->pt.nr_vertex_buffers,
buffers, start_slot, count);
}
 
 
void
draw_set_vertex_elements(struct draw_context *draw,
unsigned count,
const struct pipe_vertex_element *elements)
{
assert(count <= PIPE_MAX_ATTRIBS);
 
/* We could improve this by only flushing the frontend and the fetch part
* of the middle. This would avoid recalculating the emit keys.*/
draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
 
memcpy(draw->pt.vertex_element, elements, count * sizeof(elements[0]));
draw->pt.nr_vertex_elements = count;
}
 
 
/**
* Tell drawing context where to find mapped vertex buffers.
*/
void
draw_set_mapped_vertex_buffer(struct draw_context *draw,
unsigned attr, const void *buffer,
size_t size)
{
draw->pt.user.vbuffer[attr].map = buffer;
draw->pt.user.vbuffer[attr].size = size;
}
 
 
void
draw_set_mapped_constant_buffer(struct draw_context *draw,
unsigned shader_type,
unsigned slot,
const void *buffer,
unsigned size )
{
debug_assert(shader_type == PIPE_SHADER_VERTEX ||
shader_type == PIPE_SHADER_GEOMETRY);
debug_assert(slot < PIPE_MAX_CONSTANT_BUFFERS);
 
draw_do_flush(draw, DRAW_FLUSH_PARAMETER_CHANGE);
 
switch (shader_type) {
case PIPE_SHADER_VERTEX:
draw->pt.user.vs_constants[slot] = buffer;
draw->pt.user.vs_constants_size[slot] = size;
break;
case PIPE_SHADER_GEOMETRY:
draw->pt.user.gs_constants[slot] = buffer;
draw->pt.user.gs_constants_size[slot] = size;
break;
default:
assert(0 && "invalid shader type in draw_set_mapped_constant_buffer");
}
}
 
 
/**
* Tells the draw module to draw points with triangles if their size
* is greater than this threshold.
*/
void
draw_wide_point_threshold(struct draw_context *draw, float threshold)
{
draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
draw->pipeline.wide_point_threshold = threshold;
}
 
 
/**
* Should the draw module handle point->quad conversion for drawing sprites?
*/
void
draw_wide_point_sprites(struct draw_context *draw, boolean draw_sprite)
{
draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
draw->pipeline.wide_point_sprites = draw_sprite;
}
 
 
/**
* Tells the draw module to draw lines with triangles if their width
* is greater than this threshold.
*/
void
draw_wide_line_threshold(struct draw_context *draw, float threshold)
{
draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
draw->pipeline.wide_line_threshold = roundf(threshold);
}
 
 
/**
* Tells the draw module whether or not to implement line stipple.
*/
void
draw_enable_line_stipple(struct draw_context *draw, boolean enable)
{
draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
draw->pipeline.line_stipple = enable;
}
 
 
/**
* Tells draw module whether to convert points to quads for sprite mode.
*/
void
draw_enable_point_sprites(struct draw_context *draw, boolean enable)
{
draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
draw->pipeline.point_sprite = enable;
}
 
 
void
draw_set_force_passthrough( struct draw_context *draw, boolean enable )
{
draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
draw->force_passthrough = enable;
}
 
 
 
/**
* Allocate an extra vertex/geometry shader vertex attribute, if it doesn't
* exist already.
*
* This is used by some of the optional draw module stages such
* as wide_point which may need to allocate additional generic/texcoord
* attributes.
*/
int
draw_alloc_extra_vertex_attrib(struct draw_context *draw,
uint semantic_name, uint semantic_index)
{
int slot;
uint num_outputs;
uint n;
 
slot = draw_find_shader_output(draw, semantic_name, semantic_index);
if (slot >= 0) {
return slot;
}
 
num_outputs = draw_current_shader_outputs(draw);
n = draw->extra_shader_outputs.num;
 
assert(n < Elements(draw->extra_shader_outputs.semantic_name));
 
draw->extra_shader_outputs.semantic_name[n] = semantic_name;
draw->extra_shader_outputs.semantic_index[n] = semantic_index;
draw->extra_shader_outputs.slot[n] = num_outputs + n;
draw->extra_shader_outputs.num++;
 
return draw->extra_shader_outputs.slot[n];
}
 
 
/**
* Remove all extra vertex attributes that were allocated with
* draw_alloc_extra_vertex_attrib().
*/
void
draw_remove_extra_vertex_attribs(struct draw_context *draw)
{
draw->extra_shader_outputs.num = 0;
}
 
 
/**
* If a geometry shader is present, return its info, else the vertex shader's
* info.
*/
struct tgsi_shader_info *
draw_get_shader_info(const struct draw_context *draw)
{
 
if (draw->gs.geometry_shader) {
return &draw->gs.geometry_shader->info;
} else {
return &draw->vs.vertex_shader->info;
}
}
 
 
/**
* Ask the draw module for the location/slot of the given vertex attribute in
* a post-transformed vertex.
*
* With this function, drivers that use the draw module should have no reason
* to track the current vertex/geometry shader.
*
* Note that the draw module may sometimes generate vertices with extra
* attributes (such as texcoords for AA lines). The driver can call this
* function to find those attributes.
*
* -1 is returned if the attribute is not found since this is
* an undefined situation. Note, that zero is valid and can
* be used by any of the attributes, because position is not
* required to be attribute 0 or even at all present.
*/
int
draw_find_shader_output(const struct draw_context *draw,
uint semantic_name, uint semantic_index)
{
const struct tgsi_shader_info *info = draw_get_shader_info(draw);
uint i;
 
for (i = 0; i < info->num_outputs; i++) {
if (info->output_semantic_name[i] == semantic_name &&
info->output_semantic_index[i] == semantic_index)
return i;
}
 
/* Search the extra vertex attributes */
for (i = 0; i < draw->extra_shader_outputs.num; i++) {
if (draw->extra_shader_outputs.semantic_name[i] == semantic_name &&
draw->extra_shader_outputs.semantic_index[i] == semantic_index) {
return draw->extra_shader_outputs.slot[i];
}
}
 
return -1;
}
 
 
/**
* Return total number of the shader outputs. This function is similar to
* draw_current_shader_outputs() but this function also counts any extra
* vertex/geometry output attributes that may be filled in by some draw
* stages (such as AA point, AA line).
*
* If geometry shader is present, its output will be returned,
* if not vertex shader is used.
*/
uint
draw_num_shader_outputs(const struct draw_context *draw)
{
const struct tgsi_shader_info *info = draw_get_shader_info(draw);
uint count;
 
count = info->num_outputs;
count += draw->extra_shader_outputs.num;
 
return count;
}
 
 
/**
* Provide TGSI sampler objects for vertex/geometry shaders that use
* texture fetches. This state only needs to be set once per context.
* This might only be used by software drivers for the time being.
*/
void
draw_texture_sampler(struct draw_context *draw,
uint shader,
struct tgsi_sampler *sampler)
{
if (shader == PIPE_SHADER_VERTEX) {
draw->vs.tgsi.sampler = sampler;
} else {
debug_assert(shader == PIPE_SHADER_GEOMETRY);
draw->gs.tgsi.sampler = sampler;
}
}
 
 
 
 
void draw_set_render( struct draw_context *draw,
struct vbuf_render *render )
{
draw->render = render;
}
 
 
/**
* Tell the draw module where vertex indexes/elements are located, and
* their size (in bytes).
*
* Note: the caller must apply the pipe_index_buffer::offset value to
* the address. The draw module doesn't do that.
*/
void
draw_set_indexes(struct draw_context *draw,
const void *elements, unsigned elem_size,
unsigned elem_buffer_space)
{
assert(elem_size == 0 ||
elem_size == 1 ||
elem_size == 2 ||
elem_size == 4);
draw->pt.user.elts = elements;
draw->pt.user.eltSizeIB = elem_size;
if (elem_size)
draw->pt.user.eltMax = elem_buffer_space / elem_size;
else
draw->pt.user.eltMax = 0;
}
 
 
/* Revamp me please:
*/
void draw_do_flush( struct draw_context *draw, unsigned flags )
{
if (!draw->suspend_flushing)
{
assert(!draw->flushing); /* catch inadvertant recursion */
 
draw->flushing = TRUE;
 
draw_pipeline_flush( draw, flags );
 
draw_pt_flush( draw, flags );
 
draw->flushing = FALSE;
}
}
 
 
/**
* Return the number of output attributes produced by the geometry
* shader, if present. If no geometry shader, return the number of
* outputs from the vertex shader.
* \sa draw_num_shader_outputs
*/
uint
draw_current_shader_outputs(const struct draw_context *draw)
{
if (draw->gs.geometry_shader)
return draw->gs.num_gs_outputs;
return draw->vs.num_vs_outputs;
}
 
 
/**
* Return the index of the shader output which will contain the
* vertex position.
*/
uint
draw_current_shader_position_output(const struct draw_context *draw)
{
if (draw->gs.geometry_shader)
return draw->gs.position_output;
return draw->vs.position_output;
}
 
 
/**
* Return the index of the shader output which will contain the
* viewport index.
*/
uint
draw_current_shader_viewport_index_output(const struct draw_context *draw)
{
if (draw->gs.geometry_shader)
return draw->gs.geometry_shader->viewport_index_output;
return 0;
}
 
/**
* Returns true if there's a geometry shader bound and the geometry
* shader writes out a viewport index.
*/
boolean
draw_current_shader_uses_viewport_index(const struct draw_context *draw)
{
if (draw->gs.geometry_shader)
return draw->gs.geometry_shader->info.writes_viewport_index;
return FALSE;
}
 
 
/**
* Return the index of the shader output which will contain the
* vertex position.
*/
uint
draw_current_shader_clipvertex_output(const struct draw_context *draw)
{
return draw->vs.clipvertex_output;
}
 
uint
draw_current_shader_clipdistance_output(const struct draw_context *draw, int index)
{
debug_assert(index < PIPE_MAX_CLIP_OR_CULL_DISTANCE_ELEMENT_COUNT);
if (draw->gs.geometry_shader)
return draw->gs.geometry_shader->clipdistance_output[index];
return draw->vs.clipdistance_output[index];
}
 
 
uint
draw_current_shader_num_written_clipdistances(const struct draw_context *draw)
{
if (draw->gs.geometry_shader)
return draw->gs.geometry_shader->info.num_written_clipdistance;
return draw->vs.vertex_shader->info.num_written_clipdistance;
}
 
 
uint
draw_current_shader_culldistance_output(const struct draw_context *draw, int index)
{
debug_assert(index < PIPE_MAX_CLIP_OR_CULL_DISTANCE_ELEMENT_COUNT);
if (draw->gs.geometry_shader)
return draw->gs.geometry_shader->culldistance_output[index];
return draw->vs.vertex_shader->culldistance_output[index];
}
 
uint
draw_current_shader_num_written_culldistances(const struct draw_context *draw)
{
if (draw->gs.geometry_shader)
return draw->gs.geometry_shader->info.num_written_culldistance;
return draw->vs.vertex_shader->info.num_written_culldistance;
}
 
/**
* Return a pointer/handle for a driver/CSO rasterizer object which
* disabled culling, stippling, unfilled tris, etc.
* This is used by some pipeline stages (such as wide_point, aa_line
* and aa_point) which convert points/lines into triangles. In those
* cases we don't want to accidentally cull the triangles.
*
* \param scissor should the rasterizer state enable scissoring?
* \param flatshade should the rasterizer state use flat shading?
* \return rasterizer CSO handle
*/
void *
draw_get_rasterizer_no_cull( struct draw_context *draw,
boolean scissor,
boolean flatshade )
{
if (!draw->rasterizer_no_cull[scissor][flatshade]) {
/* create now */
struct pipe_context *pipe = draw->pipe;
struct pipe_rasterizer_state rast;
 
memset(&rast, 0, sizeof(rast));
rast.scissor = scissor;
rast.flatshade = flatshade;
rast.front_ccw = 1;
rast.half_pixel_center = draw->rasterizer->half_pixel_center;
rast.bottom_edge_rule = draw->rasterizer->bottom_edge_rule;
rast.clip_halfz = draw->rasterizer->clip_halfz;
 
draw->rasterizer_no_cull[scissor][flatshade] =
pipe->create_rasterizer_state(pipe, &rast);
}
return draw->rasterizer_no_cull[scissor][flatshade];
}
 
void
draw_set_mapped_so_targets(struct draw_context *draw,
int num_targets,
struct draw_so_target *targets[PIPE_MAX_SO_BUFFERS])
{
int i;
 
for (i = 0; i < num_targets; i++)
draw->so.targets[i] = targets[i];
for (i = num_targets; i < PIPE_MAX_SO_BUFFERS; i++)
draw->so.targets[i] = NULL;
 
draw->so.num_targets = num_targets;
}
 
void
draw_set_sampler_views(struct draw_context *draw,
unsigned shader_stage,
struct pipe_sampler_view **views,
unsigned num)
{
unsigned i;
 
debug_assert(shader_stage < PIPE_SHADER_TYPES);
debug_assert(num <= PIPE_MAX_SHADER_SAMPLER_VIEWS);
 
draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
 
for (i = 0; i < num; ++i)
draw->sampler_views[shader_stage][i] = views[i];
for (i = num; i < PIPE_MAX_SHADER_SAMPLER_VIEWS; ++i)
draw->sampler_views[shader_stage][i] = NULL;
 
draw->num_sampler_views[shader_stage] = num;
}
 
void
draw_set_samplers(struct draw_context *draw,
unsigned shader_stage,
struct pipe_sampler_state **samplers,
unsigned num)
{
unsigned i;
 
debug_assert(shader_stage < PIPE_SHADER_TYPES);
debug_assert(num <= PIPE_MAX_SAMPLERS);
 
draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
 
for (i = 0; i < num; ++i)
draw->samplers[shader_stage][i] = samplers[i];
for (i = num; i < PIPE_MAX_SAMPLERS; ++i)
draw->samplers[shader_stage][i] = NULL;
 
draw->num_samplers[shader_stage] = num;
 
#ifdef HAVE_LLVM
if (draw->llvm)
draw_llvm_set_sampler_state(draw, shader_stage);
#endif
}
 
void
draw_set_mapped_texture(struct draw_context *draw,
unsigned shader_stage,
unsigned sview_idx,
uint32_t width, uint32_t height, uint32_t depth,
uint32_t first_level, uint32_t last_level,
const void *base_ptr,
uint32_t row_stride[PIPE_MAX_TEXTURE_LEVELS],
uint32_t img_stride[PIPE_MAX_TEXTURE_LEVELS],
uint32_t mip_offsets[PIPE_MAX_TEXTURE_LEVELS])
{
#ifdef HAVE_LLVM
if (draw->llvm)
draw_llvm_set_mapped_texture(draw,
shader_stage,
sview_idx,
width, height, depth, first_level,
last_level, base_ptr,
row_stride, img_stride, mip_offsets);
#endif
}
 
/**
* XXX: Results for PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS because there are two
* different ways of setting textures, and drivers typically only support one.
*/
int
draw_get_shader_param_no_llvm(unsigned shader, enum pipe_shader_cap param)
{
switch(shader) {
case PIPE_SHADER_VERTEX:
case PIPE_SHADER_GEOMETRY:
return tgsi_exec_get_shader_param(param);
default:
return 0;
}
}
 
/**
* XXX: Results for PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS because there are two
* different ways of setting textures, and drivers typically only support one.
*/
int
draw_get_shader_param(unsigned shader, enum pipe_shader_cap param)
{
 
#ifdef HAVE_LLVM
if (draw_get_option_use_llvm()) {
switch(shader) {
case PIPE_SHADER_VERTEX:
case PIPE_SHADER_GEOMETRY:
return gallivm_get_shader_param(param);
default:
return 0;
}
}
#endif
 
return draw_get_shader_param_no_llvm(shader, param);
}
 
/**
* Enables or disables collection of statistics.
*
* Draw module is capable of generating statistics for the vertex
* processing pipeline. Collection of that data isn't free and so
* it's disabled by default. The users of the module can enable
* (or disable) this functionality through this function.
* The actual data will be emitted through the VBUF interface,
* the 'pipeline_statistics' callback to be exact.
*/
void
draw_collect_pipeline_statistics(struct draw_context *draw,
boolean enable)
{
draw->collect_statistics = enable;
}
 
/**
* Computes clipper invocation statistics.
*
* Figures out how many primitives would have been
* sent to the clipper given the specified
* prim info data.
*/
void
draw_stats_clipper_primitives(struct draw_context *draw,
const struct draw_prim_info *prim_info)
{
if (draw->collect_statistics) {
unsigned start, i;
for (start = i = 0;
i < prim_info->primitive_count;
start += prim_info->primitive_lengths[i], i++)
{
draw->statistics.c_invocations +=
u_decomposed_prims_for_vertices(prim_info->prim,
prim_info->primitive_lengths[i]);
}
}
}
/drivers/video/Gallium/auxiliary/draw/draw_context.h
0,0 → 1,285
 
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/**
* \brief Public interface into the drawing module.
*/
 
/* Authors: Keith Whitwell <keith@tungstengraphics.com>
*/
 
 
#ifndef DRAW_CONTEXT_H
#define DRAW_CONTEXT_H
 
 
#include "pipe/p_state.h"
#include "tgsi/tgsi_exec.h"
 
struct pipe_context;
struct draw_context;
struct draw_stage;
struct draw_vertex_shader;
struct draw_geometry_shader;
struct draw_fragment_shader;
struct tgsi_sampler;
 
/*
* structure to contain driver internal information
* for stream out support. mapping stores the pointer
* to the buffer contents, and internal offset stores
* stores an internal counter to how much of the stream
* out buffer is used (in bytes).
*/
struct draw_so_target {
struct pipe_stream_output_target target;
void *mapping;
int internal_offset;
int emitted_vertices;
};
 
struct draw_context *draw_create( struct pipe_context *pipe );
 
struct draw_context *draw_create_no_llvm(struct pipe_context *pipe);
 
void draw_destroy( struct draw_context *draw );
 
void draw_flush(struct draw_context *draw);
 
void draw_set_viewport_states( struct draw_context *draw,
unsigned start_slot,
unsigned num_viewports,
const struct pipe_viewport_state *viewports );
 
void draw_set_clip_state( struct draw_context *pipe,
const struct pipe_clip_state *clip );
 
/**
* Sets the rasterization state used by the draw module.
* The rast_handle is used to pass the driver specific representation
* of the rasterization state. It's going to be used when the
* draw module sets the state back on the driver itself using the
* pipe::bind_rasterizer_state method.
*
* NOTE: if you're calling this function from within the pipe's
* bind_rasterizer_state you should always call it before binding
* the actual state - that's because the draw module can try to
* bind its own rasterizer state which would reset your newly
* set state. i.e. always do
* draw_set_rasterizer_state(driver->draw, state->pipe_state, state);
* driver->state.raster = state;
*/
void draw_set_rasterizer_state( struct draw_context *draw,
const struct pipe_rasterizer_state *raster,
void *rast_handle );
 
void draw_set_rasterize_stage( struct draw_context *draw,
struct draw_stage *stage );
 
void draw_wide_point_threshold(struct draw_context *draw, float threshold);
 
void draw_wide_point_sprites(struct draw_context *draw, boolean draw_sprite);
 
void draw_wide_line_threshold(struct draw_context *draw, float threshold);
 
void draw_enable_line_stipple(struct draw_context *draw, boolean enable);
 
void draw_enable_point_sprites(struct draw_context *draw, boolean enable);
 
void draw_set_mrd(struct draw_context *draw, double mrd);
 
boolean
draw_install_aaline_stage(struct draw_context *draw, struct pipe_context *pipe);
 
boolean
draw_install_aapoint_stage(struct draw_context *draw, struct pipe_context *pipe);
 
boolean
draw_install_pstipple_stage(struct draw_context *draw, struct pipe_context *pipe);
 
 
struct tgsi_shader_info *
draw_get_shader_info(const struct draw_context *draw);
 
int
draw_find_shader_output(const struct draw_context *draw,
uint semantic_name, uint semantic_index);
 
uint
draw_num_shader_outputs(const struct draw_context *draw);
 
 
void
draw_texture_sampler(struct draw_context *draw,
uint shader_type,
struct tgsi_sampler *sampler);
 
void
draw_set_sampler_views(struct draw_context *draw,
unsigned shader_stage,
struct pipe_sampler_view **views,
unsigned num);
void
draw_set_samplers(struct draw_context *draw,
unsigned shader_stage,
struct pipe_sampler_state **samplers,
unsigned num);
 
void
draw_set_mapped_texture(struct draw_context *draw,
unsigned shader_stage,
unsigned sview_idx,
uint32_t width, uint32_t height, uint32_t depth,
uint32_t first_level, uint32_t last_level,
const void *base,
uint32_t row_stride[PIPE_MAX_TEXTURE_LEVELS],
uint32_t img_stride[PIPE_MAX_TEXTURE_LEVELS],
uint32_t mip_offsets[PIPE_MAX_TEXTURE_LEVELS]);
 
 
/*
* Vertex shader functions
*/
 
struct draw_vertex_shader *
draw_create_vertex_shader(struct draw_context *draw,
const struct pipe_shader_state *shader);
void draw_bind_vertex_shader(struct draw_context *draw,
struct draw_vertex_shader *dvs);
void draw_delete_vertex_shader(struct draw_context *draw,
struct draw_vertex_shader *dvs);
void draw_vs_attach_so(struct draw_vertex_shader *dvs,
const struct pipe_stream_output_info *info);
void draw_vs_reset_so(struct draw_vertex_shader *dvs);
 
 
/*
* Fragment shader functions
*/
struct draw_fragment_shader *
draw_create_fragment_shader(struct draw_context *draw,
const struct pipe_shader_state *shader);
void draw_bind_fragment_shader(struct draw_context *draw,
struct draw_fragment_shader *dvs);
void draw_delete_fragment_shader(struct draw_context *draw,
struct draw_fragment_shader *dvs);
 
/*
* Geometry shader functions
*/
struct draw_geometry_shader *
draw_create_geometry_shader(struct draw_context *draw,
const struct pipe_shader_state *shader);
void draw_bind_geometry_shader(struct draw_context *draw,
struct draw_geometry_shader *dvs);
void draw_delete_geometry_shader(struct draw_context *draw,
struct draw_geometry_shader *dvs);
 
 
/*
* Vertex data functions
*/
 
void draw_set_vertex_buffers(struct draw_context *draw,
unsigned start_slot, unsigned count,
const struct pipe_vertex_buffer *buffers);
 
void draw_set_vertex_elements(struct draw_context *draw,
unsigned count,
const struct pipe_vertex_element *elements);
 
void draw_set_indexes(struct draw_context *draw,
const void *elements, unsigned elem_size,
unsigned available_space);
 
void draw_set_mapped_vertex_buffer(struct draw_context *draw,
unsigned attr, const void *buffer,
size_t size);
 
void
draw_set_mapped_constant_buffer(struct draw_context *draw,
unsigned shader_type,
unsigned slot,
const void *buffer,
unsigned size);
 
void
draw_set_mapped_so_targets(struct draw_context *draw,
int num_targets,
struct draw_so_target *targets[PIPE_MAX_SO_BUFFERS]);
 
 
/***********************************************************************
* draw_pt.c
*/
 
void draw_vbo(struct draw_context *draw,
const struct pipe_draw_info *info);
 
 
/*******************************************************************************
* Driver backend interface
*/
struct vbuf_render;
void draw_set_render( struct draw_context *draw,
struct vbuf_render *render );
 
void draw_set_driver_clipping( struct draw_context *draw,
boolean bypass_clip_xy,
boolean bypass_clip_z,
boolean guard_band_xy);
 
void draw_set_force_passthrough( struct draw_context *draw,
boolean enable );
 
 
/*******************************************************************************
* Draw statistics
*/
void draw_collect_pipeline_statistics(struct draw_context *draw,
boolean enable);
 
/*******************************************************************************
* Draw pipeline
*/
boolean draw_need_pipeline(const struct draw_context *draw,
const struct pipe_rasterizer_state *rasterizer,
unsigned prim );
 
int
draw_get_shader_param(unsigned shader, enum pipe_shader_cap param);
 
int
draw_get_shader_param_no_llvm(unsigned shader, enum pipe_shader_cap param);
 
#ifdef HAVE_LLVM
boolean
draw_get_option_use_llvm(void);
#endif
 
#endif /* DRAW_CONTEXT_H */
/drivers/video/Gallium/auxiliary/draw/draw_decompose_tmp.h
0,0 → 1,440
/*
* Mesa 3-D graphics library
*
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* Copyright (C) 2010 LunarG Inc.
*
* 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, sublicense,
* 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
* Chia-I Wu <olv@lunarg.com>
*/
 
/* these macros are optional */
#ifndef LOCAL_VARS
#define LOCAL_VARS
#endif
#ifndef FUNC_ENTER
#define FUNC_ENTER do {} while (0)
#endif
#ifndef FUNC_EXIT
#define FUNC_EXIT do {} while (0)
#endif
#ifndef LINE_ADJ
#define LINE_ADJ(flags, a0, i0, i1, a1) LINE(flags, i0, i1)
#endif
#ifndef TRIANGLE_ADJ
#define TRIANGLE_ADJ(flags, i0, a0, i1, a1, i2, a2) TRIANGLE(flags, i0, i1, i2)
#endif
 
static void
FUNC(FUNC_VARS)
{
unsigned idx[6], i;
ushort flags;
LOCAL_VARS
 
FUNC_ENTER;
 
/* prim, prim_flags, count, and last_vertex_last should have been defined */
if (0) {
debug_printf("%s: prim 0x%x, prim_flags 0x%x, count %d, last_vertex_last %d\n",
__FUNCTION__, prim, prim_flags, count, last_vertex_last);
}
 
switch (prim) {
case PIPE_PRIM_POINTS:
for (i = 0; i < count; i++) {
idx[0] = GET_ELT(i);
POINT(idx[0]);
}
break;
 
case PIPE_PRIM_LINES:
flags = DRAW_PIPE_RESET_STIPPLE;
for (i = 0; i + 1 < count; i += 2) {
idx[0] = GET_ELT(i);
idx[1] = GET_ELT(i + 1);
LINE(flags, idx[0], idx[1]);
}
break;
 
case PIPE_PRIM_LINE_LOOP:
case PIPE_PRIM_LINE_STRIP:
if (count >= 2) {
flags = (prim_flags & DRAW_SPLIT_BEFORE) ? 0 : DRAW_PIPE_RESET_STIPPLE;
idx[1] = GET_ELT(0);
idx[2] = idx[1];
 
for (i = 1; i < count; i++, flags = 0) {
idx[0] = idx[1];
idx[1] = GET_ELT(i);
LINE(flags, idx[0], idx[1]);
}
/* close the loop */
if (prim == PIPE_PRIM_LINE_LOOP && !prim_flags)
LINE(flags, idx[1], idx[2]);
}
break;
 
case PIPE_PRIM_TRIANGLES:
flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL;
for (i = 0; i + 2 < count; i += 3) {
idx[0] = GET_ELT(i);
idx[1] = GET_ELT(i + 1);
idx[2] = GET_ELT(i + 2);
TRIANGLE(flags, idx[0], idx[1], idx[2]);
}
break;
 
case PIPE_PRIM_TRIANGLE_STRIP:
if (count >= 3) {
flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL;
idx[1] = GET_ELT(0);
idx[2] = GET_ELT(1);
 
if (last_vertex_last) {
for (i = 0; i + 2 < count; i++) {
idx[0] = idx[1];
idx[1] = idx[2];
idx[2] = GET_ELT(i + 2);
/* always emit idx[2] last */
if (i & 1)
TRIANGLE(flags, idx[1], idx[0], idx[2]);
else
TRIANGLE(flags, idx[0], idx[1], idx[2]);
}
}
else {
for (i = 0; i + 2 < count; i++) {
idx[0] = idx[1];
idx[1] = idx[2];
idx[2] = GET_ELT(i + 2);
/* always emit idx[0] first */
if (i & 1)
TRIANGLE(flags, idx[0], idx[2], idx[1]);
else
TRIANGLE(flags, idx[0], idx[1], idx[2]);
}
}
}
break;
 
case PIPE_PRIM_TRIANGLE_FAN:
if (count >= 3) {
flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL;
idx[0] = GET_ELT(0);
idx[2] = GET_ELT(1);
 
/* idx[0] is neither the first nor the last vertex */
if (last_vertex_last) {
for (i = 0; i + 2 < count; i++) {
idx[1] = idx[2];
idx[2] = GET_ELT(i + 2);
/* always emit idx[2] last */
TRIANGLE(flags, idx[0], idx[1], idx[2]);
}
}
else {
for (i = 0; i + 2 < count; i++) {
idx[1] = idx[2];
idx[2] = GET_ELT(i + 2);
/* always emit idx[1] first */
TRIANGLE(flags, idx[1], idx[2], idx[0]);
}
}
}
break;
 
case PIPE_PRIM_QUADS:
if (last_vertex_last) {
for (i = 0; i + 3 < count; i += 4) {
idx[0] = GET_ELT(i);
idx[1] = GET_ELT(i + 1);
idx[2] = GET_ELT(i + 2);
idx[3] = GET_ELT(i + 3);
 
flags = DRAW_PIPE_RESET_STIPPLE |
DRAW_PIPE_EDGE_FLAG_0 |
DRAW_PIPE_EDGE_FLAG_2;
/* always emit idx[3] last */
TRIANGLE(flags, idx[0], idx[1], idx[3]);
 
flags = DRAW_PIPE_EDGE_FLAG_0 |
DRAW_PIPE_EDGE_FLAG_1;
TRIANGLE(flags, idx[1], idx[2], idx[3]);
}
}
else {
for (i = 0; i + 3 < count; i += 4) {
idx[0] = GET_ELT(i);
idx[1] = GET_ELT(i + 1);
idx[2] = GET_ELT(i + 2);
idx[3] = GET_ELT(i + 3);
 
flags = DRAW_PIPE_RESET_STIPPLE |
DRAW_PIPE_EDGE_FLAG_0 |
DRAW_PIPE_EDGE_FLAG_1;
/* always emit idx[3] / idx[0] first */
if (quads_flatshade_last)
TRIANGLE(flags, idx[3], idx[0], idx[1]);
else
TRIANGLE(flags, idx[0], idx[1], idx[2]);
 
flags = DRAW_PIPE_EDGE_FLAG_1 |
DRAW_PIPE_EDGE_FLAG_2;
if (quads_flatshade_last)
TRIANGLE(flags, idx[3], idx[1], idx[2]);
else
TRIANGLE(flags, idx[0], idx[2], idx[3]);
}
}
break;
 
case PIPE_PRIM_QUAD_STRIP:
if (count >= 4) {
idx[2] = GET_ELT(0);
idx[3] = GET_ELT(1);
 
if (last_vertex_last) {
for (i = 0; i + 3 < count; i += 2) {
idx[0] = idx[2];
idx[1] = idx[3];
idx[2] = GET_ELT(i + 2);
idx[3] = GET_ELT(i + 3);
 
/* always emit idx[3] last */
flags = DRAW_PIPE_RESET_STIPPLE |
DRAW_PIPE_EDGE_FLAG_0 |
DRAW_PIPE_EDGE_FLAG_2;
TRIANGLE(flags, idx[2], idx[0], idx[3]);
 
flags = DRAW_PIPE_EDGE_FLAG_0 |
DRAW_PIPE_EDGE_FLAG_1;
TRIANGLE(flags, idx[0], idx[1], idx[3]);
}
}
else {
for (i = 0; i + 3 < count; i += 2) {
idx[0] = idx[2];
idx[1] = idx[3];
idx[2] = GET_ELT(i + 2);
idx[3] = GET_ELT(i + 3);
 
flags = DRAW_PIPE_RESET_STIPPLE |
DRAW_PIPE_EDGE_FLAG_0 |
DRAW_PIPE_EDGE_FLAG_1;
/* always emit idx[3] / idx[0 first */
if (quads_flatshade_last)
TRIANGLE(flags, idx[3], idx[2], idx[0]);
else
TRIANGLE(flags, idx[0], idx[3], idx[2]);
 
flags = DRAW_PIPE_EDGE_FLAG_1 |
DRAW_PIPE_EDGE_FLAG_2;
if (quads_flatshade_last)
TRIANGLE(flags, idx[3], idx[0], idx[1]);
else
TRIANGLE(flags, idx[0], idx[1], idx[3]);
}
}
}
break;
 
case PIPE_PRIM_POLYGON:
if (count >= 3) {
ushort edge_next, edge_finish;
 
if (last_vertex_last) {
flags = (DRAW_PIPE_RESET_STIPPLE |
DRAW_PIPE_EDGE_FLAG_0);
if (!(prim_flags & DRAW_SPLIT_BEFORE))
flags |= DRAW_PIPE_EDGE_FLAG_2;
 
edge_next = DRAW_PIPE_EDGE_FLAG_0;
edge_finish =
(prim_flags & DRAW_SPLIT_AFTER) ? 0 : DRAW_PIPE_EDGE_FLAG_1;
}
else {
flags = (DRAW_PIPE_RESET_STIPPLE |
DRAW_PIPE_EDGE_FLAG_1);
if (!(prim_flags & DRAW_SPLIT_BEFORE))
flags |= DRAW_PIPE_EDGE_FLAG_0;
 
edge_next = DRAW_PIPE_EDGE_FLAG_1;
edge_finish =
(prim_flags & DRAW_SPLIT_AFTER) ? 0 : DRAW_PIPE_EDGE_FLAG_2;
}
 
idx[0] = GET_ELT(0);
idx[2] = GET_ELT(1);
 
for (i = 0; i + 2 < count; i++, flags = edge_next) {
idx[1] = idx[2];
idx[2] = GET_ELT(i + 2);
 
if (i + 3 == count)
flags |= edge_finish;
 
/* idx[0] is both the first and the last vertex */
if (last_vertex_last)
TRIANGLE(flags, idx[1], idx[2], idx[0]);
else
TRIANGLE(flags, idx[0], idx[1], idx[2]);
}
}
break;
 
case PIPE_PRIM_LINES_ADJACENCY:
flags = DRAW_PIPE_RESET_STIPPLE;
for (i = 0; i + 3 < count; i += 4) {
idx[0] = GET_ELT(i);
idx[1] = GET_ELT(i + 1);
idx[2] = GET_ELT(i + 2);
idx[3] = GET_ELT(i + 3);
LINE_ADJ(flags, idx[0], idx[1], idx[2], idx[3]);
}
break;
 
case PIPE_PRIM_LINE_STRIP_ADJACENCY:
if (count >= 4) {
flags = (prim_flags & DRAW_SPLIT_BEFORE) ? 0 : DRAW_PIPE_RESET_STIPPLE;
idx[1] = GET_ELT(0);
idx[2] = GET_ELT(1);
idx[3] = GET_ELT(2);
 
for (i = 1; i + 2 < count; i++, flags = 0) {
idx[0] = idx[1];
idx[1] = idx[2];
idx[2] = idx[3];
idx[3] = GET_ELT(i + 2);
LINE_ADJ(flags, idx[0], idx[1], idx[2], idx[3]);
}
}
break;
 
case PIPE_PRIM_TRIANGLES_ADJACENCY:
flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL;
for (i = 0; i + 5 < count; i += 6) {
idx[0] = GET_ELT(i);
idx[1] = GET_ELT(i + 1);
idx[2] = GET_ELT(i + 2);
idx[3] = GET_ELT(i + 3);
idx[4] = GET_ELT(i + 4);
idx[5] = GET_ELT(i + 5);
TRIANGLE_ADJ(flags, idx[0], idx[1], idx[2], idx[3], idx[4], idx[5]);
}
break;
 
case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
if (count >= 6) {
flags = DRAW_PIPE_RESET_STIPPLE | DRAW_PIPE_EDGE_FLAG_ALL;
idx[0] = GET_ELT(1);
idx[2] = GET_ELT(0);
idx[4] = GET_ELT(2);
idx[3] = GET_ELT(4);
 
/*
* The vertices of the i-th triangle are stored in
* idx[0,2,4] = { 2*i, 2*i+2, 2*i+4 };
*
* The adjacent vertices are stored in
* idx[1,3,5] = { 2*i-2, 2*i+6, 2*i+3 }.
*
* However, there are two exceptions:
*
* For the first triangle, idx[1] = 1;
* For the last triangle, idx[3] = 2*i+5.
*/
if (last_vertex_last) {
for (i = 0; i + 5 < count; i += 2) {
idx[1] = idx[0];
 
idx[0] = idx[2];
idx[2] = idx[4];
idx[4] = idx[3];
 
idx[3] = GET_ELT(i + ((i + 7 < count) ? 6 : 5));
idx[5] = GET_ELT(i + 3);
 
/*
* alternate the first two vertices (idx[0] and idx[2]) and the
* corresponding adjacent vertices (idx[3] and idx[5]) to have
* the correct orientation
*/
if (i & 2) {
TRIANGLE_ADJ(flags,
idx[2], idx[1], idx[0], idx[5], idx[4], idx[3]);
}
else {
TRIANGLE_ADJ(flags,
idx[0], idx[1], idx[2], idx[3], idx[4], idx[5]);
}
}
}
else {
for (i = 0; i + 5 < count; i += 2) {
idx[1] = idx[0];
 
idx[0] = idx[2];
idx[2] = idx[4];
idx[4] = idx[3];
 
idx[3] = GET_ELT(i + ((i + 7 < count) ? 6 : 5));
idx[5] = GET_ELT(i + 3);
 
/*
* alternate the last two vertices (idx[2] and idx[4]) and the
* corresponding adjacent vertices (idx[1] and idx[5]) to have
* the correct orientation
*/
if (i & 2) {
TRIANGLE_ADJ(flags,
idx[0], idx[5], idx[4], idx[3], idx[2], idx[1]);
}
else {
TRIANGLE_ADJ(flags,
idx[0], idx[1], idx[2], idx[3], idx[4], idx[5]);
}
}
}
}
break;
 
default:
assert(0);
break;
}
 
FUNC_EXIT;
}
 
#undef LOCAL_VARS
#undef FUNC_ENTER
#undef FUNC_EXIT
#undef LINE_ADJ
#undef TRIANGLE_ADJ
 
#undef FUNC
#undef FUNC_VARS
#undef GET_ELT
#undef POINT
#undef LINE
#undef TRIANGLE
/drivers/video/Gallium/auxiliary/draw/draw_fs.c
0,0 → 1,73
/**************************************************************************
*
* Copyright 2010 VMware, Inc.
* 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 VMWARE 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.
*
**************************************************************************/
 
#include "pipe/p_shader_tokens.h"
 
#include "util/u_math.h"
#include "util/u_memory.h"
#include "util/u_prim.h"
 
#include "tgsi/tgsi_parse.h"
 
#include "draw_fs.h"
#include "draw_private.h"
#include "draw_context.h"
 
 
struct draw_fragment_shader *
draw_create_fragment_shader(struct draw_context *draw,
const struct pipe_shader_state *shader)
{
struct draw_fragment_shader *dfs;
 
dfs = CALLOC_STRUCT(draw_fragment_shader);
if (dfs) {
dfs->base = *shader;
tgsi_scan_shader(shader->tokens, &dfs->info);
}
 
return dfs;
}
 
 
void
draw_bind_fragment_shader(struct draw_context *draw,
struct draw_fragment_shader *dfs)
{
draw_do_flush(draw, DRAW_FLUSH_STATE_CHANGE);
 
draw->fs.fragment_shader = dfs;
}
 
 
void
draw_delete_fragment_shader(struct draw_context *draw,
struct draw_fragment_shader *dfs)
{
FREE(dfs);
}
 
/drivers/video/Gallium/auxiliary/draw/draw_fs.h
0,0 → 1,42
/**************************************************************************
*
* Copyright 2010 VMware, Inc.
* 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 VMWARE 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.
*
**************************************************************************/
 
#ifndef DRAW_FS_H
#define DRAW_FS_H
 
 
#include "tgsi/tgsi_scan.h"
 
 
struct draw_fragment_shader
{
struct pipe_shader_state base;
struct tgsi_shader_info info;
};
 
 
#endif /* DRAW_FS_H */
/drivers/video/Gallium/auxiliary/draw/draw_gs.c
0,0 → 1,920
/**************************************************************************
*
* Copyright 2009 VMware, Inc.
* 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.
*
**************************************************************************/
 
#include "draw_gs.h"
 
#include "draw_private.h"
#include "draw_context.h"
#ifdef HAVE_LLVM
#include "draw_llvm.h"
#endif
 
#include "tgsi/tgsi_parse.h"
#include "tgsi/tgsi_exec.h"
 
#include "pipe/p_shader_tokens.h"
 
#include "util/u_math.h"
#include "util/u_memory.h"
#include "util/u_prim.h"
 
/* fixme: move it from here */
#define MAX_PRIMITIVES 64
 
static INLINE int
draw_gs_get_input_index(int semantic, int index,
const struct tgsi_shader_info *input_info)
{
int i;
const ubyte *input_semantic_names = input_info->output_semantic_name;
const ubyte *input_semantic_indices = input_info->output_semantic_index;
for (i = 0; i < PIPE_MAX_SHADER_OUTPUTS; i++) {
if (input_semantic_names[i] == semantic &&
input_semantic_indices[i] == index)
return i;
}
return -1;
}
 
/**
* We execute geometry shaders in the SOA mode, so ideally we want to
* flush when the number of currently fetched primitives is equal to
* the number of elements in the SOA vector. This ensures that the
* throughput is optimized for the given vector instrunction set.
*/
static INLINE boolean
draw_gs_should_flush(struct draw_geometry_shader *shader)
{
return (shader->fetched_prim_count == shader->vector_length);
}
 
/*#define DEBUG_OUTPUTS 1*/
static void
tgsi_fetch_gs_outputs(struct draw_geometry_shader *shader,
unsigned num_primitives,
float (**p_output)[4])
{
struct tgsi_exec_machine *machine = shader->machine;
unsigned prim_idx, j, slot;
unsigned current_idx = 0;
float (*output)[4];
 
output = *p_output;
 
/* Unswizzle all output results.
*/
 
for (prim_idx = 0; prim_idx < num_primitives; ++prim_idx) {
unsigned num_verts_per_prim = machine->Primitives[prim_idx];
shader->primitive_lengths[prim_idx + shader->emitted_primitives] =
machine->Primitives[prim_idx];
shader->emitted_vertices += num_verts_per_prim;
for (j = 0; j < num_verts_per_prim; j++, current_idx++) {
int idx = current_idx * shader->info.num_outputs;
#ifdef DEBUG_OUTPUTS
debug_printf("%d) Output vert:\n", idx / shader->info.num_outputs);
#endif
for (slot = 0; slot < shader->info.num_outputs; slot++) {
output[slot][0] = machine->Outputs[idx + slot].xyzw[0].f[0];
output[slot][1] = machine->Outputs[idx + slot].xyzw[1].f[0];
output[slot][2] = machine->Outputs[idx + slot].xyzw[2].f[0];
output[slot][3] = machine->Outputs[idx + slot].xyzw[3].f[0];
#ifdef DEBUG_OUTPUTS
debug_printf("\t%d: %f %f %f %f\n", slot,
output[slot][0],
output[slot][1],
output[slot][2],
output[slot][3]);
#endif
debug_assert(!util_is_inf_or_nan(output[slot][0]));
}
output = (float (*)[4])((char *)output + shader->vertex_size);
}
}
*p_output = output;
shader->emitted_primitives += num_primitives;
}
 
/*#define DEBUG_INPUTS 1*/
static void tgsi_fetch_gs_input(struct draw_geometry_shader *shader,
unsigned *indices,
unsigned num_vertices,
unsigned prim_idx)
{
struct tgsi_exec_machine *machine = shader->machine;
unsigned slot, vs_slot, i;
unsigned input_vertex_stride = shader->input_vertex_stride;
const float (*input_ptr)[4];
 
input_ptr = shader->input;
 
for (i = 0; i < num_vertices; ++i) {
const float (*input)[4];
#if DEBUG_INPUTS
debug_printf("%d) vertex index = %d (prim idx = %d)\n",
i, indices[i], prim_idx);
#endif
input = (const float (*)[4])(
(const char *)input_ptr + (indices[i] * input_vertex_stride));
for (slot = 0, vs_slot = 0; slot < shader->info.num_inputs; ++slot) {
unsigned idx = i * TGSI_EXEC_MAX_INPUT_ATTRIBS + slot;
if (shader->info.input_semantic_name[slot] == TGSI_SEMANTIC_PRIMID) {
machine->Inputs[idx].xyzw[0].f[prim_idx] =
(float)shader->in_prim_idx;
machine->Inputs[idx].xyzw[1].f[prim_idx] =
(float)shader->in_prim_idx;
machine->Inputs[idx].xyzw[2].f[prim_idx] =
(float)shader->in_prim_idx;
machine->Inputs[idx].xyzw[3].f[prim_idx] =
(float)shader->in_prim_idx;
} else {
vs_slot = draw_gs_get_input_index(
shader->info.input_semantic_name[slot],
shader->info.input_semantic_index[slot],
shader->input_info);
if (vs_slot < 0) {
debug_printf("VS/GS signature mismatch!\n");
machine->Inputs[idx].xyzw[0].f[prim_idx] = 0;
machine->Inputs[idx].xyzw[1].f[prim_idx] = 0;
machine->Inputs[idx].xyzw[2].f[prim_idx] = 0;
machine->Inputs[idx].xyzw[3].f[prim_idx] = 0;
} else {
#if DEBUG_INPUTS
debug_printf("\tSlot = %d, vs_slot = %d, idx = %d:\n",
slot, vs_slot, idx);
assert(!util_is_inf_or_nan(input[vs_slot][0]));
assert(!util_is_inf_or_nan(input[vs_slot][1]));
assert(!util_is_inf_or_nan(input[vs_slot][2]));
assert(!util_is_inf_or_nan(input[vs_slot][3]));
#endif
machine->Inputs[idx].xyzw[0].f[prim_idx] = input[vs_slot][0];
machine->Inputs[idx].xyzw[1].f[prim_idx] = input[vs_slot][1];
machine->Inputs[idx].xyzw[2].f[prim_idx] = input[vs_slot][2];
machine->Inputs[idx].xyzw[3].f[prim_idx] = input[vs_slot][3];
#if DEBUG_INPUTS
debug_printf("\t\t%f %f %f %f\n",
machine->Inputs[idx].xyzw[0].f[prim_idx],
machine->Inputs[idx].xyzw[1].f[prim_idx],
machine->Inputs[idx].xyzw[2].f[prim_idx],
machine->Inputs[idx].xyzw[3].f[prim_idx]);
#endif
++vs_slot;
}
}
}
}
}
 
static void tgsi_gs_prepare(struct draw_geometry_shader *shader,
const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
const unsigned constants_size[PIPE_MAX_CONSTANT_BUFFERS])
{
struct tgsi_exec_machine *machine = shader->machine;
 
tgsi_exec_set_constant_buffers(machine, PIPE_MAX_CONSTANT_BUFFERS,
constants, constants_size);
}
 
static unsigned tgsi_gs_run(struct draw_geometry_shader *shader,
unsigned input_primitives)
{
struct tgsi_exec_machine *machine = shader->machine;
 
tgsi_set_exec_mask(machine,
1,
input_primitives > 1,
input_primitives > 2,
input_primitives > 3);
 
/* run interpreter */
tgsi_exec_machine_run(machine);
 
return
machine->Temps[TGSI_EXEC_TEMP_PRIMITIVE_I].xyzw[TGSI_EXEC_TEMP_PRIMITIVE_C].u[0];
}
 
#ifdef HAVE_LLVM
 
static void
llvm_fetch_gs_input(struct draw_geometry_shader *shader,
unsigned *indices,
unsigned num_vertices,
unsigned prim_idx)
{
unsigned slot, vs_slot, i;
unsigned input_vertex_stride = shader->input_vertex_stride;
const float (*input_ptr)[4];
float (*input_data)[6][PIPE_MAX_SHADER_INPUTS][TGSI_NUM_CHANNELS][TGSI_NUM_CHANNELS] = &shader->gs_input->data;
 
shader->llvm_prim_ids[shader->fetched_prim_count] =
shader->in_prim_idx;
 
input_ptr = shader->input;
 
for (i = 0; i < num_vertices; ++i) {
const float (*input)[4];
#if DEBUG_INPUTS
debug_printf("%d) vertex index = %d (prim idx = %d)\n",
i, indices[i], prim_idx);
#endif
input = (const float (*)[4])(
(const char *)input_ptr + (indices[i] * input_vertex_stride));
for (slot = 0, vs_slot = 0; slot < shader->info.num_inputs; ++slot) {
if (shader->info.input_semantic_name[slot] == TGSI_SEMANTIC_PRIMID) {
/* skip. we handle system values through gallivm */
} else {
vs_slot = draw_gs_get_input_index(
shader->info.input_semantic_name[slot],
shader->info.input_semantic_index[slot],
shader->input_info);
if (vs_slot < 0) {
debug_printf("VS/GS signature mismatch!\n");
(*input_data)[i][slot][0][prim_idx] = 0;
(*input_data)[i][slot][1][prim_idx] = 0;
(*input_data)[i][slot][2][prim_idx] = 0;
(*input_data)[i][slot][3][prim_idx] = 0;
} else {
#if DEBUG_INPUTS
debug_printf("\tSlot = %d, vs_slot = %d, i = %d:\n",
slot, vs_slot, i);
assert(!util_is_inf_or_nan(input[vs_slot][0]));
assert(!util_is_inf_or_nan(input[vs_slot][1]));
assert(!util_is_inf_or_nan(input[vs_slot][2]));
assert(!util_is_inf_or_nan(input[vs_slot][3]));
#endif
(*input_data)[i][slot][0][prim_idx] = input[vs_slot][0];
(*input_data)[i][slot][1][prim_idx] = input[vs_slot][1];
(*input_data)[i][slot][2][prim_idx] = input[vs_slot][2];
(*input_data)[i][slot][3][prim_idx] = input[vs_slot][3];
#if DEBUG_INPUTS
debug_printf("\t\t%f %f %f %f\n",
(*input_data)[i][slot][0][prim_idx],
(*input_data)[i][slot][1][prim_idx],
(*input_data)[i][slot][2][prim_idx],
(*input_data)[i][slot][3][prim_idx]);
#endif
++vs_slot;
}
}
}
}
}
 
static void
llvm_fetch_gs_outputs(struct draw_geometry_shader *shader,
unsigned num_primitives,
float (**p_output)[4])
{
int total_verts = 0;
int vertex_count = 0;
int total_prims = 0;
int max_prims_per_invocation = 0;
char *output_ptr = (char*)shader->gs_output;
int i, j, prim_idx;
unsigned next_prim_boundary = shader->primitive_boundary;
 
for (i = 0; i < shader->vector_length; ++i) {
int prims = shader->llvm_emitted_primitives[i];
total_prims += prims;
max_prims_per_invocation = MAX2(max_prims_per_invocation, prims);
}
for (i = 0; i < shader->vector_length; ++i) {
total_verts += shader->llvm_emitted_vertices[i];
}
 
output_ptr += shader->emitted_vertices * shader->vertex_size;
for (i = 0; i < shader->vector_length - 1; ++i) {
int current_verts = shader->llvm_emitted_vertices[i];
int next_verts = shader->llvm_emitted_vertices[i + 1];
#if 0
int j;
for (j = 0; j < current_verts; ++j) {
struct vertex_header *vh = (struct vertex_header *)
(output_ptr + shader->vertex_size * (i * next_prim_boundary + j));
debug_printf("--- %d) [%f, %f, %f, %f]\n", j + vertex_count,
vh->data[0][0], vh->data[0][1], vh->data[0][2], vh->data[0][3]);
}
#endif
debug_assert(current_verts <= shader->max_output_vertices);
debug_assert(next_verts <= shader->max_output_vertices);
if (next_verts) {
memmove(output_ptr + (vertex_count + current_verts) * shader->vertex_size,
output_ptr + ((i + 1) * next_prim_boundary) * shader->vertex_size,
shader->vertex_size * next_verts);
}
vertex_count += current_verts;
}
 
#if 0
{
int i;
for (i = 0; i < total_verts; ++i) {
struct vertex_header *vh = (struct vertex_header *)(output_ptr + shader->vertex_size * i);
debug_printf("%d) Vertex:\n", i);
for (j = 0; j < shader->info.num_outputs; ++j) {
unsigned *udata = (unsigned*)vh->data[j];
debug_printf(" %d) [%f, %f, %f, %f] [%d, %d, %d, %d]\n", j,
vh->data[j][0], vh->data[j][1], vh->data[j][2], vh->data[j][3],
udata[0], udata[1], udata[2], udata[3]);
}
}
}
#endif
 
prim_idx = 0;
for (i = 0; i < shader->vector_length; ++i) {
int num_prims = shader->llvm_emitted_primitives[i];
for (j = 0; j < num_prims; ++j) {
int prim_length =
shader->llvm_prim_lengths[j][i];
shader->primitive_lengths[shader->emitted_primitives + prim_idx] =
prim_length;
++prim_idx;
}
}
 
shader->emitted_primitives += total_prims;
shader->emitted_vertices += total_verts;
}
 
static void
llvm_gs_prepare(struct draw_geometry_shader *shader,
const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
const unsigned constants_size[PIPE_MAX_CONSTANT_BUFFERS])
{
}
 
static unsigned
llvm_gs_run(struct draw_geometry_shader *shader,
unsigned input_primitives)
{
unsigned ret;
char *input = (char*)shader->gs_output;
 
input += (shader->emitted_vertices * shader->vertex_size);
 
ret = shader->current_variant->jit_func(
shader->jit_context, shader->gs_input->data,
(struct vertex_header*)input,
input_primitives,
shader->draw->instance_id,
shader->llvm_prim_ids);
 
return ret;
}
 
#endif
 
static void gs_flush(struct draw_geometry_shader *shader)
{
unsigned out_prim_count;
 
unsigned input_primitives = shader->fetched_prim_count;
 
if (shader->draw->collect_statistics) {
shader->draw->statistics.gs_invocations += input_primitives;
}
 
debug_assert(input_primitives > 0 &&
input_primitives <= 4);
 
out_prim_count = shader->run(shader, input_primitives);
shader->fetch_outputs(shader, out_prim_count,
&shader->tmp_output);
 
#if 0
debug_printf("PRIM emitted prims = %d (verts=%d), cur prim count = %d\n",
shader->emitted_primitives, shader->emitted_vertices,
out_prim_count);
#endif
 
shader->fetched_prim_count = 0;
}
 
static void gs_point(struct draw_geometry_shader *shader,
int idx)
{
unsigned indices[1];
 
indices[0] = idx;
 
shader->fetch_inputs(shader, indices, 1,
shader->fetched_prim_count);
++shader->in_prim_idx;
++shader->fetched_prim_count;
 
if (draw_gs_should_flush(shader))
gs_flush(shader);
}
 
static void gs_line(struct draw_geometry_shader *shader,
int i0, int i1)
{
unsigned indices[2];
 
indices[0] = i0;
indices[1] = i1;
 
shader->fetch_inputs(shader, indices, 2,
shader->fetched_prim_count);
++shader->in_prim_idx;
++shader->fetched_prim_count;
if (draw_gs_should_flush(shader))
gs_flush(shader);
}
 
static void gs_line_adj(struct draw_geometry_shader *shader,
int i0, int i1, int i2, int i3)
{
unsigned indices[4];
 
indices[0] = i0;
indices[1] = i1;
indices[2] = i2;
indices[3] = i3;
 
shader->fetch_inputs(shader, indices, 4,
shader->fetched_prim_count);
++shader->in_prim_idx;
++shader->fetched_prim_count;
 
if (draw_gs_should_flush(shader))
gs_flush(shader);
}
 
static void gs_tri(struct draw_geometry_shader *shader,
int i0, int i1, int i2)
{
unsigned indices[3];
 
indices[0] = i0;
indices[1] = i1;
indices[2] = i2;
 
shader->fetch_inputs(shader, indices, 3,
shader->fetched_prim_count);
++shader->in_prim_idx;
++shader->fetched_prim_count;
 
if (draw_gs_should_flush(shader))
gs_flush(shader);
}
 
static void gs_tri_adj(struct draw_geometry_shader *shader,
int i0, int i1, int i2,
int i3, int i4, int i5)
{
unsigned indices[6];
 
indices[0] = i0;
indices[1] = i1;
indices[2] = i2;
indices[3] = i3;
indices[4] = i4;
indices[5] = i5;
 
shader->fetch_inputs(shader, indices, 6,
shader->fetched_prim_count);
++shader->in_prim_idx;
++shader->fetched_prim_count;
 
if (draw_gs_should_flush(shader))
gs_flush(shader);
}
 
#define FUNC gs_run
#define GET_ELT(idx) (idx)
#include "draw_gs_tmp.h"
 
 
#define FUNC gs_run_elts
#define LOCAL_VARS const ushort *elts = input_prims->elts;
#define GET_ELT(idx) (elts[idx])
#include "draw_gs_tmp.h"
 
 
/**
* Execute geometry shader.
*/
int draw_geometry_shader_run(struct draw_geometry_shader *shader,
const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
const unsigned constants_size[PIPE_MAX_CONSTANT_BUFFERS],
const struct draw_vertex_info *input_verts,
const struct draw_prim_info *input_prim,
const struct tgsi_shader_info *input_info,
struct draw_vertex_info *output_verts,
struct draw_prim_info *output_prims )
{
const float (*input)[4] = (const float (*)[4])input_verts->verts->data;
unsigned input_stride = input_verts->vertex_size;
unsigned num_outputs = shader->info.num_outputs;
unsigned vertex_size = sizeof(struct vertex_header) + num_outputs * 4 * sizeof(float);
unsigned num_input_verts = input_prim->linear ?
input_verts->count :
input_prim->count;
unsigned num_in_primitives =
align(
MAX2(u_decomposed_prims_for_vertices(input_prim->prim,
num_input_verts),
u_decomposed_prims_for_vertices(shader->input_primitive,
num_input_verts)),
shader->vector_length);
unsigned max_out_prims =
u_decomposed_prims_for_vertices(shader->output_primitive,
shader->max_output_vertices)
* num_in_primitives;
 
//Assume at least one primitive
max_out_prims = MAX2(max_out_prims, 1);
 
 
output_verts->vertex_size = vertex_size;
output_verts->stride = output_verts->vertex_size;
/* we allocate exactly one extra vertex per primitive to allow the GS to emit
* overflown vertices into some area where they won't harm anyone */
output_verts->verts =
(struct vertex_header *)MALLOC(output_verts->vertex_size *
max_out_prims *
shader->primitive_boundary);
 
#if 0
debug_printf("%s count = %d (in prims # = %d)\n",
__FUNCTION__, num_input_verts, num_in_primitives);
debug_printf("\tlinear = %d, prim_info->count = %d\n",
input_prim->linear, input_prim->count);
debug_printf("\tprim pipe = %s, shader in = %s, shader out = %s, max out = %d\n",
u_prim_name(input_prim->prim),
u_prim_name(shader->input_primitive),
u_prim_name(shader->output_primitive),
shader->max_output_vertices);
#endif
 
shader->emitted_vertices = 0;
shader->emitted_primitives = 0;
shader->vertex_size = vertex_size;
shader->tmp_output = (float (*)[4])output_verts->verts->data;
shader->fetched_prim_count = 0;
shader->input_vertex_stride = input_stride;
shader->input = input;
shader->input_info = input_info;
FREE(shader->primitive_lengths);
shader->primitive_lengths = MALLOC(max_out_prims * sizeof(unsigned));
 
 
#ifdef HAVE_LLVM
if (draw_get_option_use_llvm()) {
shader->gs_output = output_verts->verts;
if (max_out_prims > shader->max_out_prims) {
unsigned i;
if (shader->llvm_prim_lengths) {
for (i = 0; i < shader->max_out_prims; ++i) {
align_free(shader->llvm_prim_lengths[i]);
}
FREE(shader->llvm_prim_lengths);
}
 
shader->llvm_prim_lengths = MALLOC(max_out_prims * sizeof(unsigned*));
for (i = 0; i < max_out_prims; ++i) {
int vector_size = shader->vector_length * sizeof(unsigned);
shader->llvm_prim_lengths[i] =
align_malloc(vector_size, vector_size);
}
 
shader->max_out_prims = max_out_prims;
}
shader->jit_context->prim_lengths = shader->llvm_prim_lengths;
shader->jit_context->emitted_vertices = shader->llvm_emitted_vertices;
shader->jit_context->emitted_prims = shader->llvm_emitted_primitives;
}
#endif
 
shader->prepare(shader, constants, constants_size);
 
if (input_prim->linear)
gs_run(shader, input_prim, input_verts,
output_prims, output_verts);
else
gs_run_elts(shader, input_prim, input_verts,
output_prims, output_verts);
 
/* Flush the remaining primitives. Will happen if
* num_input_primitives % 4 != 0
*/
if (shader->fetched_prim_count > 0) {
gs_flush(shader);
}
 
debug_assert(shader->fetched_prim_count == 0);
 
/* Update prim_info:
*/
output_prims->linear = TRUE;
output_prims->elts = NULL;
output_prims->start = 0;
output_prims->count = shader->emitted_vertices;
output_prims->prim = shader->output_primitive;
output_prims->flags = 0x0;
output_prims->primitive_lengths = shader->primitive_lengths;
output_prims->primitive_count = shader->emitted_primitives;
output_verts->count = shader->emitted_vertices;
 
if (shader->draw->collect_statistics) {
unsigned i;
for (i = 0; i < shader->emitted_primitives; ++i) {
shader->draw->statistics.gs_primitives +=
u_decomposed_prims_for_vertices(shader->output_primitive,
shader->primitive_lengths[i]);
}
}
 
#if 0
debug_printf("GS finished, prims = %d, verts = %d\n",
output_prims->primitive_count,
output_verts->count);
#endif
 
return shader->emitted_vertices;
}
 
void draw_geometry_shader_prepare(struct draw_geometry_shader *shader,
struct draw_context *draw)
{
#ifdef HAVE_LLVM
boolean use_llvm = draw_get_option_use_llvm();
#else
boolean use_llvm = FALSE;
#endif
if (!use_llvm && shader && shader->machine->Tokens != shader->state.tokens) {
tgsi_exec_machine_bind_shader(shader->machine,
shader->state.tokens,
draw->gs.tgsi.sampler);
}
}
 
 
boolean
draw_gs_init( struct draw_context *draw )
{
draw->gs.tgsi.machine = tgsi_exec_machine_create();
if (!draw->gs.tgsi.machine)
return FALSE;
 
draw->gs.tgsi.machine->Primitives = align_malloc(
MAX_PRIMITIVES * sizeof(struct tgsi_exec_vector), 16);
if (!draw->gs.tgsi.machine->Primitives)
return FALSE;
memset(draw->gs.tgsi.machine->Primitives, 0,
MAX_PRIMITIVES * sizeof(struct tgsi_exec_vector));
 
return TRUE;
}
 
void draw_gs_destroy( struct draw_context *draw )
{
if (draw->gs.tgsi.machine) {
align_free(draw->gs.tgsi.machine->Primitives);
tgsi_exec_machine_destroy(draw->gs.tgsi.machine);
}
}
 
struct draw_geometry_shader *
draw_create_geometry_shader(struct draw_context *draw,
const struct pipe_shader_state *state)
{
#ifdef HAVE_LLVM
boolean use_llvm = draw_get_option_use_llvm();
struct llvm_geometry_shader *llvm_gs;
#endif
struct draw_geometry_shader *gs;
unsigned i;
 
#ifdef HAVE_LLVM
if (use_llvm) {
llvm_gs = CALLOC_STRUCT(llvm_geometry_shader);
 
if (llvm_gs == NULL)
return NULL;
 
gs = &llvm_gs->base;
 
make_empty_list(&llvm_gs->variants);
} else
#endif
{
gs = CALLOC_STRUCT(draw_geometry_shader);
}
 
if (!gs)
return NULL;
 
gs->draw = draw;
gs->state = *state;
gs->state.tokens = tgsi_dup_tokens(state->tokens);
if (!gs->state.tokens) {
FREE(gs);
return NULL;
}
 
tgsi_scan_shader(state->tokens, &gs->info);
 
/* setup the defaults */
gs->input_primitive = PIPE_PRIM_TRIANGLES;
gs->output_primitive = PIPE_PRIM_TRIANGLE_STRIP;
gs->max_output_vertices = 32;
gs->max_out_prims = 0;
 
#ifdef HAVE_LLVM
if (use_llvm) {
/* TODO: change the input array to handle the following
vector length, instead of the currently hardcoded
TGSI_NUM_CHANNELS
gs->vector_length = lp_native_vector_width / 32;*/
gs->vector_length = TGSI_NUM_CHANNELS;
} else
#endif
{
gs->vector_length = 1;
}
 
for (i = 0; i < gs->info.num_properties; ++i) {
if (gs->info.properties[i].name ==
TGSI_PROPERTY_GS_INPUT_PRIM)
gs->input_primitive = gs->info.properties[i].data[0];
else if (gs->info.properties[i].name ==
TGSI_PROPERTY_GS_OUTPUT_PRIM)
gs->output_primitive = gs->info.properties[i].data[0];
else if (gs->info.properties[i].name ==
TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES)
gs->max_output_vertices = gs->info.properties[i].data[0];
}
/* Primitive boundary is bigger than max_output_vertices by one, because
* the specification says that the geometry shader should exit if the
* number of emitted vertices is bigger or equal to max_output_vertices and
* we can't do that because we're running in the SoA mode, which means that
* our storing routines will keep getting called on channels that have
* overflown.
* So we need some scratch area where we can keep writing the overflown
* vertices without overwriting anything important or crashing.
*/
gs->primitive_boundary = gs->max_output_vertices + 1;
 
for (i = 0; i < gs->info.num_outputs; i++) {
if (gs->info.output_semantic_name[i] == TGSI_SEMANTIC_POSITION &&
gs->info.output_semantic_index[i] == 0)
gs->position_output = i;
if (gs->info.output_semantic_name[i] == TGSI_SEMANTIC_VIEWPORT_INDEX)
gs->viewport_index_output = i;
if (gs->info.output_semantic_name[i] == TGSI_SEMANTIC_CLIPDIST) {
debug_assert(gs->info.output_semantic_index[i] <
PIPE_MAX_CLIP_OR_CULL_DISTANCE_ELEMENT_COUNT);
gs->clipdistance_output[gs->info.output_semantic_index[i]] = i;
}
if (gs->info.output_semantic_name[i] == TGSI_SEMANTIC_CULLDIST) {
debug_assert(gs->info.output_semantic_index[i] <
PIPE_MAX_CLIP_OR_CULL_DISTANCE_ELEMENT_COUNT);
gs->culldistance_output[gs->info.output_semantic_index[i]] = i;
}
}
 
gs->machine = draw->gs.tgsi.machine;
 
#ifdef HAVE_LLVM
if (use_llvm) {
int vector_size = gs->vector_length * sizeof(float);
gs->gs_input = align_malloc(sizeof(struct draw_gs_inputs), 16);
memset(gs->gs_input, 0, sizeof(struct draw_gs_inputs));
gs->llvm_prim_lengths = 0;
 
gs->llvm_emitted_primitives = align_malloc(vector_size, vector_size);
gs->llvm_emitted_vertices = align_malloc(vector_size, vector_size);
gs->llvm_prim_ids = align_malloc(vector_size, vector_size);
 
gs->fetch_outputs = llvm_fetch_gs_outputs;
gs->fetch_inputs = llvm_fetch_gs_input;
gs->prepare = llvm_gs_prepare;
gs->run = llvm_gs_run;
 
gs->jit_context = &draw->llvm->gs_jit_context;
 
 
llvm_gs->variant_key_size =
draw_gs_llvm_variant_key_size(
MAX2(gs->info.file_max[TGSI_FILE_SAMPLER]+1,
gs->info.file_max[TGSI_FILE_SAMPLER_VIEW]+1));
} else
#endif
{
gs->fetch_outputs = tgsi_fetch_gs_outputs;
gs->fetch_inputs = tgsi_fetch_gs_input;
gs->prepare = tgsi_gs_prepare;
gs->run = tgsi_gs_run;
}
 
return gs;
}
 
void draw_bind_geometry_shader(struct draw_context *draw,
struct draw_geometry_shader *dgs)
{
draw_do_flush(draw, DRAW_FLUSH_STATE_CHANGE);
 
if (dgs) {
draw->gs.geometry_shader = dgs;
draw->gs.num_gs_outputs = dgs->info.num_outputs;
draw->gs.position_output = dgs->position_output;
draw_geometry_shader_prepare(dgs, draw);
}
else {
draw->gs.geometry_shader = NULL;
draw->gs.num_gs_outputs = 0;
}
}
 
void draw_delete_geometry_shader(struct draw_context *draw,
struct draw_geometry_shader *dgs)
{
if (!dgs) {
return;
}
#ifdef HAVE_LLVM
if (draw_get_option_use_llvm()) {
struct llvm_geometry_shader *shader = llvm_geometry_shader(dgs);
struct draw_gs_llvm_variant_list_item *li;
 
li = first_elem(&shader->variants);
while(!at_end(&shader->variants, li)) {
struct draw_gs_llvm_variant_list_item *next = next_elem(li);
draw_gs_llvm_destroy_variant(li->base);
li = next;
}
 
assert(shader->variants_cached == 0);
 
if (dgs->llvm_prim_lengths) {
unsigned i;
for (i = 0; i < dgs->max_out_prims; ++i) {
align_free(dgs->llvm_prim_lengths[i]);
}
FREE(dgs->llvm_prim_lengths);
}
align_free(dgs->llvm_emitted_primitives);
align_free(dgs->llvm_emitted_vertices);
align_free(dgs->llvm_prim_ids);
 
align_free(dgs->gs_input);
}
#endif
 
FREE(dgs->primitive_lengths);
FREE((void*) dgs->state.tokens);
FREE(dgs);
}
 
 
#ifdef HAVE_LLVM
void draw_gs_set_current_variant(struct draw_geometry_shader *shader,
struct draw_gs_llvm_variant *variant)
{
shader->current_variant = variant;
}
#endif
 
/*
* Called at the very begin of the draw call with a new instance
* Used to reset state that should persist between primitive restart.
*/
void
draw_geometry_shader_new_instance(struct draw_geometry_shader *gs)
{
if (!gs)
return;
 
gs->in_prim_idx = 0;
}
/drivers/video/Gallium/auxiliary/draw/draw_gs.h
0,0 → 1,147
/**************************************************************************
*
* Copyright 2009 VMware, Inc.
* 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.
*
**************************************************************************/
 
#ifndef DRAW_GS_H
#define DRAW_GS_H
 
#include "draw_context.h"
#include "draw_private.h"
 
#define MAX_TGSI_PRIMITIVES 4
 
struct draw_context;
 
#ifdef HAVE_LLVM
struct draw_gs_jit_context;
struct draw_gs_llvm_variant;
 
/**
* Structure holding the inputs to the geometry shader. It uses SOA layout.
* The dimensions are as follows:
* - maximum number of vertices for a geometry shader input primitive
* (6 for triangle_adjacency)
* - maximum number of attributes for each vertex
* - four channels per each attribute (x,y,z,w)
* - number of input primitives equal to the SOA vector length
*/
struct draw_gs_inputs {
float data[6][PIPE_MAX_SHADER_INPUTS][TGSI_NUM_CHANNELS][TGSI_NUM_CHANNELS];
};
#endif
 
/**
* Private version of the compiled geometry shader
*/
struct draw_geometry_shader {
struct draw_context *draw;
 
struct tgsi_exec_machine *machine;
 
/* This member will disappear shortly:*/
struct pipe_shader_state state;
 
struct tgsi_shader_info info;
unsigned position_output;
unsigned viewport_index_output;
unsigned clipdistance_output[PIPE_MAX_CLIP_OR_CULL_DISTANCE_ELEMENT_COUNT];
unsigned culldistance_output[PIPE_MAX_CLIP_OR_CULL_DISTANCE_ELEMENT_COUNT];
 
unsigned max_output_vertices;
unsigned primitive_boundary;
unsigned input_primitive;
unsigned output_primitive;
 
unsigned *primitive_lengths;
unsigned emitted_vertices;
unsigned emitted_primitives;
 
float (*tmp_output)[4];
unsigned vertex_size;
 
unsigned in_prim_idx;
unsigned input_vertex_stride;
unsigned fetched_prim_count;
const float (*input)[4];
const struct tgsi_shader_info *input_info;
unsigned vector_length;
unsigned max_out_prims;
 
#ifdef HAVE_LLVM
struct draw_gs_inputs *gs_input;
struct draw_gs_jit_context *jit_context;
struct draw_gs_llvm_variant *current_variant;
struct vertex_header *gs_output;
 
int **llvm_prim_lengths;
int *llvm_emitted_primitives;
int *llvm_emitted_vertices;
int *llvm_prim_ids;
#endif
 
void (*fetch_inputs)(struct draw_geometry_shader *shader,
unsigned *indices,
unsigned num_vertices,
unsigned prim_idx);
void (*fetch_outputs)(struct draw_geometry_shader *shader,
unsigned num_primitives,
float (**p_output)[4]);
 
void (*prepare)(struct draw_geometry_shader *shader,
const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
const unsigned constants_size[PIPE_MAX_CONSTANT_BUFFERS]);
unsigned (*run)(struct draw_geometry_shader *shader,
unsigned input_primitives);
};
 
void draw_geometry_shader_new_instance(struct draw_geometry_shader *gs);
 
/*
* Returns the number of vertices emitted.
* The vertex shader can emit any number of vertices as long as it's
* smaller than the GS_MAX_OUTPUT_VERTICES shader property.
*/
int draw_geometry_shader_run(struct draw_geometry_shader *shader,
const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
const unsigned constants_size[PIPE_MAX_CONSTANT_BUFFERS],
const struct draw_vertex_info *input_verts,
const struct draw_prim_info *input_prim,
const struct tgsi_shader_info *input_info,
struct draw_vertex_info *output_verts,
struct draw_prim_info *output_prims );
 
void draw_geometry_shader_prepare(struct draw_geometry_shader *shader,
struct draw_context *draw);
 
int draw_gs_max_output_vertices(struct draw_geometry_shader *shader,
unsigned pipe_prim);
 
#ifdef HAVE_LLVM
void draw_gs_set_current_variant(struct draw_geometry_shader *shader,
struct draw_gs_llvm_variant *variant);
#endif
 
#endif
/drivers/video/Gallium/auxiliary/draw/draw_gs_tmp.h
0,0 → 1,33
#define FUNC_VARS struct draw_geometry_shader *gs, \
const struct draw_prim_info *input_prims, \
const struct draw_vertex_info *input_verts, \
struct draw_prim_info *output_prims, \
struct draw_vertex_info *output_verts
 
#define FUNC_ENTER \
/* declare more local vars */ \
const unsigned prim = input_prims->prim; \
const unsigned prim_flags = input_prims->flags; \
const unsigned count = input_prims->count; \
const boolean quads_flatshade_last = FALSE; \
const boolean last_vertex_last = !gs->draw->rasterizer->flatshade_first; \
do { \
debug_assert(input_prims->primitive_count == 1); \
switch (prim) { \
case PIPE_PRIM_QUADS: \
case PIPE_PRIM_QUAD_STRIP: \
case PIPE_PRIM_POLYGON: \
debug_assert(!"unexpected primitive type in GS"); \
return; \
default: \
break; \
} \
} while (0) \
 
#define POINT(i0) gs_point(gs,i0)
#define LINE(flags,i0,i1) gs_line(gs,i0,i1)
#define TRIANGLE(flags,i0,i1,i2) gs_tri(gs,i0,i1,i2)
#define LINE_ADJ(flags,i0,i1,i2,i3) gs_line_adj(gs,i0,i1,i2,i3)
#define TRIANGLE_ADJ(flags,i0,i1,i2,i3,i4,i5) gs_tri_adj(gs,i0,i1,i2,i3,i4,i5)
 
#include "draw_decompose_tmp.h"
/drivers/video/Gallium/auxiliary/draw/draw_llvm.c
0,0 → 1,2289
/**************************************************************************
*
* Copyright 2010 VMware, Inc.
* 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 VMWARE 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.
*
**************************************************************************/
 
#include "draw_llvm.h"
 
#include "draw_context.h"
#include "draw_vs.h"
#include "draw_gs.h"
 
#include "gallivm/lp_bld_arit.h"
#include "gallivm/lp_bld_arit_overflow.h"
#include "gallivm/lp_bld_logic.h"
#include "gallivm/lp_bld_const.h"
#include "gallivm/lp_bld_swizzle.h"
#include "gallivm/lp_bld_struct.h"
#include "gallivm/lp_bld_type.h"
#include "gallivm/lp_bld_flow.h"
#include "gallivm/lp_bld_debug.h"
#include "gallivm/lp_bld_tgsi.h"
#include "gallivm/lp_bld_printf.h"
#include "gallivm/lp_bld_intr.h"
#include "gallivm/lp_bld_init.h"
#include "gallivm/lp_bld_type.h"
#include "gallivm/lp_bld_pack.h"
#include "gallivm/lp_bld_format.h"
 
#include "tgsi/tgsi_exec.h"
#include "tgsi/tgsi_dump.h"
 
#include "util/u_math.h"
#include "util/u_pointer.h"
#include "util/u_string.h"
#include "util/u_simple_list.h"
 
 
#define DEBUG_STORE 0
 
 
static void
draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *var,
boolean elts);
 
 
struct draw_gs_llvm_iface {
struct lp_build_tgsi_gs_iface base;
 
struct draw_gs_llvm_variant *variant;
LLVMValueRef input;
};
 
static INLINE const struct draw_gs_llvm_iface *
draw_gs_llvm_iface(const struct lp_build_tgsi_gs_iface *iface)
{
return (const struct draw_gs_llvm_iface *)iface;
}
 
/**
* Create LLVM type for draw_vertex_buffer.
*/
static LLVMTypeRef
create_jit_dvbuffer_type(struct gallivm_state *gallivm,
const char *struct_name)
{
LLVMTargetDataRef target = gallivm->target;
LLVMTypeRef dvbuffer_type;
LLVMTypeRef elem_types[DRAW_JIT_DVBUFFER_NUM_FIELDS];
LLVMTypeRef int32_type = LLVMInt32TypeInContext(gallivm->context);
 
elem_types[DRAW_JIT_DVBUFFER_MAP] =
LLVMPointerType(LLVMIntTypeInContext(gallivm->context, 8), 0);
elem_types[DRAW_JIT_DVBUFFER_SIZE] = int32_type;
 
dvbuffer_type = LLVMStructTypeInContext(gallivm->context, elem_types,
Elements(elem_types), 0);
 
#if HAVE_LLVM < 0x0300
LLVMAddTypeName(gallivm->module, struct_name, dvbuffer_type);
 
/* Make sure the target's struct layout cache doesn't return
* stale/invalid data.
*/
LLVMInvalidateStructLayout(gallivm->target, dvbuffer_type);
#endif
 
LP_CHECK_MEMBER_OFFSET(struct draw_vertex_buffer, map,
target, dvbuffer_type,
DRAW_JIT_DVBUFFER_MAP);
LP_CHECK_MEMBER_OFFSET(struct draw_vertex_buffer, size,
target, dvbuffer_type,
DRAW_JIT_DVBUFFER_SIZE);
 
return dvbuffer_type;
}
 
/**
* Create LLVM type for struct draw_jit_texture
*/
static LLVMTypeRef
create_jit_texture_type(struct gallivm_state *gallivm, const char *struct_name)
{
LLVMTargetDataRef target = gallivm->target;
LLVMTypeRef texture_type;
LLVMTypeRef elem_types[DRAW_JIT_TEXTURE_NUM_FIELDS];
LLVMTypeRef int32_type = LLVMInt32TypeInContext(gallivm->context);
 
elem_types[DRAW_JIT_TEXTURE_WIDTH] =
elem_types[DRAW_JIT_TEXTURE_HEIGHT] =
elem_types[DRAW_JIT_TEXTURE_DEPTH] =
elem_types[DRAW_JIT_TEXTURE_FIRST_LEVEL] =
elem_types[DRAW_JIT_TEXTURE_LAST_LEVEL] = int32_type;
elem_types[DRAW_JIT_TEXTURE_BASE] =
LLVMPointerType(LLVMInt8TypeInContext(gallivm->context), 0);
elem_types[DRAW_JIT_TEXTURE_ROW_STRIDE] =
elem_types[DRAW_JIT_TEXTURE_IMG_STRIDE] =
elem_types[DRAW_JIT_TEXTURE_MIP_OFFSETS] =
LLVMArrayType(int32_type, PIPE_MAX_TEXTURE_LEVELS);
 
texture_type = LLVMStructTypeInContext(gallivm->context, elem_types,
Elements(elem_types), 0);
 
#if HAVE_LLVM < 0x0300
LLVMAddTypeName(gallivm->module, struct_name, texture_type);
 
/* Make sure the target's struct layout cache doesn't return
* stale/invalid data.
*/
LLVMInvalidateStructLayout(gallivm->target, texture_type);
#endif
 
LP_CHECK_MEMBER_OFFSET(struct draw_jit_texture, width,
target, texture_type,
DRAW_JIT_TEXTURE_WIDTH);
LP_CHECK_MEMBER_OFFSET(struct draw_jit_texture, height,
target, texture_type,
DRAW_JIT_TEXTURE_HEIGHT);
LP_CHECK_MEMBER_OFFSET(struct draw_jit_texture, depth,
target, texture_type,
DRAW_JIT_TEXTURE_DEPTH);
LP_CHECK_MEMBER_OFFSET(struct draw_jit_texture, first_level,
target, texture_type,
DRAW_JIT_TEXTURE_FIRST_LEVEL);
LP_CHECK_MEMBER_OFFSET(struct draw_jit_texture, last_level,
target, texture_type,
DRAW_JIT_TEXTURE_LAST_LEVEL);
LP_CHECK_MEMBER_OFFSET(struct draw_jit_texture, base,
target, texture_type,
DRAW_JIT_TEXTURE_BASE);
LP_CHECK_MEMBER_OFFSET(struct draw_jit_texture, row_stride,
target, texture_type,
DRAW_JIT_TEXTURE_ROW_STRIDE);
LP_CHECK_MEMBER_OFFSET(struct draw_jit_texture, img_stride,
target, texture_type,
DRAW_JIT_TEXTURE_IMG_STRIDE);
LP_CHECK_MEMBER_OFFSET(struct draw_jit_texture, mip_offsets,
target, texture_type,
DRAW_JIT_TEXTURE_MIP_OFFSETS);
 
LP_CHECK_STRUCT_SIZE(struct draw_jit_texture, target, texture_type);
 
return texture_type;
}
 
 
/**
* Create LLVM type for struct draw_jit_sampler
*/
static LLVMTypeRef
create_jit_sampler_type(struct gallivm_state *gallivm, const char *struct_name)
{
LLVMTargetDataRef target = gallivm->target;
LLVMTypeRef sampler_type;
LLVMTypeRef elem_types[DRAW_JIT_SAMPLER_NUM_FIELDS];
 
elem_types[DRAW_JIT_SAMPLER_MIN_LOD] =
elem_types[DRAW_JIT_SAMPLER_MAX_LOD] =
elem_types[DRAW_JIT_SAMPLER_LOD_BIAS] = LLVMFloatTypeInContext(gallivm->context);
elem_types[DRAW_JIT_SAMPLER_BORDER_COLOR] =
LLVMArrayType(LLVMFloatTypeInContext(gallivm->context), 4);
 
sampler_type = LLVMStructTypeInContext(gallivm->context, elem_types,
Elements(elem_types), 0);
 
#if HAVE_LLVM < 0x0300
LLVMAddTypeName(gallivm->module, struct_name, sampler_type);
 
/* Make sure the target's struct layout cache doesn't return
* stale/invalid data.
*/
LLVMInvalidateStructLayout(gallivm->target, sampler_type);
#endif
 
LP_CHECK_MEMBER_OFFSET(struct draw_jit_sampler, min_lod,
target, sampler_type,
DRAW_JIT_SAMPLER_MIN_LOD);
LP_CHECK_MEMBER_OFFSET(struct draw_jit_sampler, max_lod,
target, sampler_type,
DRAW_JIT_SAMPLER_MAX_LOD);
LP_CHECK_MEMBER_OFFSET(struct draw_jit_sampler, lod_bias,
target, sampler_type,
DRAW_JIT_SAMPLER_LOD_BIAS);
LP_CHECK_MEMBER_OFFSET(struct draw_jit_sampler, border_color,
target, sampler_type,
DRAW_JIT_SAMPLER_BORDER_COLOR);
 
LP_CHECK_STRUCT_SIZE(struct draw_jit_sampler, target, sampler_type);
 
return sampler_type;
}
 
 
/**
* Create LLVM type for struct draw_jit_context
*/
static LLVMTypeRef
create_jit_context_type(struct gallivm_state *gallivm,
LLVMTypeRef texture_type, LLVMTypeRef sampler_type,
const char *struct_name)
{
LLVMTargetDataRef target = gallivm->target;
LLVMTypeRef float_type = LLVMFloatTypeInContext(gallivm->context);
LLVMTypeRef elem_types[DRAW_JIT_CTX_NUM_FIELDS];
LLVMTypeRef context_type;
 
elem_types[0] = LLVMArrayType(LLVMPointerType(float_type, 0), /* vs_constants */
LP_MAX_TGSI_CONST_BUFFERS);
elem_types[1] = LLVMPointerType(LLVMArrayType(LLVMArrayType(float_type, 4),
DRAW_TOTAL_CLIP_PLANES), 0);
elem_types[2] = LLVMPointerType(float_type, 0); /* viewport */
elem_types[3] = LLVMArrayType(texture_type,
PIPE_MAX_SHADER_SAMPLER_VIEWS); /* textures */
elem_types[4] = LLVMArrayType(sampler_type,
PIPE_MAX_SAMPLERS); /* samplers */
context_type = LLVMStructTypeInContext(gallivm->context, elem_types,
Elements(elem_types), 0);
#if HAVE_LLVM < 0x0300
LLVMAddTypeName(gallivm->module, struct_name, context_type);
 
LLVMInvalidateStructLayout(gallivm->target, context_type);
#endif
 
LP_CHECK_MEMBER_OFFSET(struct draw_jit_context, vs_constants,
target, context_type, DRAW_JIT_CTX_CONSTANTS);
LP_CHECK_MEMBER_OFFSET(struct draw_jit_context, planes,
target, context_type, DRAW_JIT_CTX_PLANES);
LP_CHECK_MEMBER_OFFSET(struct draw_jit_context, viewport,
target, context_type, DRAW_JIT_CTX_VIEWPORT);
LP_CHECK_MEMBER_OFFSET(struct draw_jit_context, textures,
target, context_type,
DRAW_JIT_CTX_TEXTURES);
LP_CHECK_MEMBER_OFFSET(struct draw_jit_context, samplers,
target, context_type,
DRAW_JIT_CTX_SAMPLERS);
LP_CHECK_STRUCT_SIZE(struct draw_jit_context,
target, context_type);
 
return context_type;
}
 
 
/**
* Create LLVM type for struct draw_gs_jit_context
*/
static LLVMTypeRef
create_gs_jit_context_type(struct gallivm_state *gallivm,
unsigned vector_length,
LLVMTypeRef texture_type, LLVMTypeRef sampler_type,
const char *struct_name)
{
LLVMTargetDataRef target = gallivm->target;
LLVMTypeRef float_type = LLVMFloatTypeInContext(gallivm->context);
LLVMTypeRef int_type = LLVMInt32TypeInContext(gallivm->context);
LLVMTypeRef elem_types[DRAW_GS_JIT_CTX_NUM_FIELDS];
LLVMTypeRef context_type;
 
elem_types[0] = LLVMArrayType(LLVMPointerType(float_type, 0), /* constants */
LP_MAX_TGSI_CONST_BUFFERS);
elem_types[1] = LLVMPointerType(LLVMArrayType(LLVMArrayType(float_type, 4),
DRAW_TOTAL_CLIP_PLANES), 0);
elem_types[2] = LLVMPointerType(float_type, 0); /* viewport */
 
elem_types[3] = LLVMArrayType(texture_type,
PIPE_MAX_SHADER_SAMPLER_VIEWS); /* textures */
elem_types[4] = LLVMArrayType(sampler_type,
PIPE_MAX_SAMPLERS); /* samplers */
elem_types[5] = LLVMPointerType(LLVMPointerType(int_type, 0), 0);
elem_types[6] = LLVMPointerType(LLVMVectorType(int_type,
vector_length), 0);
elem_types[7] = LLVMPointerType(LLVMVectorType(int_type,
vector_length), 0);
 
context_type = LLVMStructTypeInContext(gallivm->context, elem_types,
Elements(elem_types), 0);
#if HAVE_LLVM < 0x0300
LLVMAddTypeName(gallivm->module, struct_name, context_type);
 
LLVMInvalidateStructLayout(gallivm->target, context_type);
#endif
 
LP_CHECK_MEMBER_OFFSET(struct draw_gs_jit_context, constants,
target, context_type, DRAW_GS_JIT_CTX_CONSTANTS);
LP_CHECK_MEMBER_OFFSET(struct draw_gs_jit_context, planes,
target, context_type, DRAW_GS_JIT_CTX_PLANES);
LP_CHECK_MEMBER_OFFSET(struct draw_gs_jit_context, viewport,
target, context_type, DRAW_GS_JIT_CTX_VIEWPORT);
LP_CHECK_MEMBER_OFFSET(struct draw_gs_jit_context, textures,
target, context_type,
DRAW_GS_JIT_CTX_TEXTURES);
LP_CHECK_MEMBER_OFFSET(struct draw_gs_jit_context, samplers,
target, context_type,
DRAW_GS_JIT_CTX_SAMPLERS);
LP_CHECK_MEMBER_OFFSET(struct draw_gs_jit_context, prim_lengths,
target, context_type,
DRAW_GS_JIT_CTX_PRIM_LENGTHS);
LP_CHECK_MEMBER_OFFSET(struct draw_gs_jit_context, emitted_vertices,
target, context_type,
DRAW_GS_JIT_CTX_EMITTED_VERTICES);
LP_CHECK_MEMBER_OFFSET(struct draw_gs_jit_context, emitted_prims,
target, context_type,
DRAW_GS_JIT_CTX_EMITTED_PRIMS);
LP_CHECK_STRUCT_SIZE(struct draw_gs_jit_context,
target, context_type);
 
return context_type;
}
 
 
static LLVMTypeRef
create_gs_jit_input_type(struct gallivm_state *gallivm)
{
LLVMTypeRef float_type = LLVMFloatTypeInContext(gallivm->context);
LLVMTypeRef input_array;
 
input_array = LLVMVectorType(float_type, TGSI_NUM_CHANNELS); /* num primitives */
input_array = LLVMArrayType(input_array, TGSI_NUM_CHANNELS); /* num channels */
input_array = LLVMArrayType(input_array, PIPE_MAX_SHADER_INPUTS); /* num attrs per vertex */
input_array = LLVMPointerType(input_array, 0); /* num vertices per prim */
 
return input_array;
}
 
/**
* Create LLVM type for struct pipe_vertex_buffer
*/
static LLVMTypeRef
create_jit_vertex_buffer_type(struct gallivm_state *gallivm,
const char *struct_name)
{
LLVMTargetDataRef target = gallivm->target;
LLVMTypeRef elem_types[4];
LLVMTypeRef vb_type;
 
elem_types[0] =
elem_types[1] = LLVMInt32TypeInContext(gallivm->context);
elem_types[2] =
elem_types[3] = LLVMPointerType(LLVMInt8TypeInContext(gallivm->context), 0);
 
vb_type = LLVMStructTypeInContext(gallivm->context, elem_types,
Elements(elem_types), 0);
#if HAVE_LLVM < 0x0300
LLVMAddTypeName(gallivm->module, struct_name, vb_type);
 
LLVMInvalidateStructLayout(gallivm->target, vb_type);
#endif
 
LP_CHECK_MEMBER_OFFSET(struct pipe_vertex_buffer, stride,
target, vb_type, 0);
LP_CHECK_MEMBER_OFFSET(struct pipe_vertex_buffer, buffer_offset,
target, vb_type, 1);
 
LP_CHECK_STRUCT_SIZE(struct pipe_vertex_buffer, target, vb_type);
 
return vb_type;
}
 
 
/**
* Create LLVM type for struct vertex_header;
*/
static LLVMTypeRef
create_jit_vertex_header(struct gallivm_state *gallivm, int data_elems)
{
LLVMTargetDataRef target = gallivm->target;
LLVMTypeRef elem_types[4];
LLVMTypeRef vertex_header;
char struct_name[24];
 
util_snprintf(struct_name, 23, "vertex_header%d", data_elems);
 
elem_types[DRAW_JIT_VERTEX_VERTEX_ID] = LLVMIntTypeInContext(gallivm->context, 32);
elem_types[DRAW_JIT_VERTEX_CLIP] = LLVMArrayType(LLVMFloatTypeInContext(gallivm->context), 4);
elem_types[DRAW_JIT_VERTEX_PRE_CLIP_POS] = LLVMArrayType(LLVMFloatTypeInContext(gallivm->context), 4);
elem_types[DRAW_JIT_VERTEX_DATA] = LLVMArrayType(elem_types[1], data_elems);
 
vertex_header = LLVMStructTypeInContext(gallivm->context, elem_types,
Elements(elem_types), 0);
#if HAVE_LLVM < 0x0300
LLVMAddTypeName(gallivm->module, struct_name, vertex_header);
 
LLVMInvalidateStructLayout(gallivm->target, vertex_header);
#endif
 
/* these are bit-fields and we can't take address of them
LP_CHECK_MEMBER_OFFSET(struct vertex_header, clipmask,
target, vertex_header,
DRAW_JIT_VERTEX_CLIPMASK);
LP_CHECK_MEMBER_OFFSET(struct vertex_header, edgeflag,
target, vertex_header,
DRAW_JIT_VERTEX_EDGEFLAG);
LP_CHECK_MEMBER_OFFSET(struct vertex_header, pad,
target, vertex_header,
DRAW_JIT_VERTEX_PAD);
LP_CHECK_MEMBER_OFFSET(struct vertex_header, vertex_id,
target, vertex_header,
DRAW_JIT_VERTEX_VERTEX_ID);
*/
LP_CHECK_MEMBER_OFFSET(struct vertex_header, clip,
target, vertex_header,
DRAW_JIT_VERTEX_CLIP);
LP_CHECK_MEMBER_OFFSET(struct vertex_header, pre_clip_pos,
target, vertex_header,
DRAW_JIT_VERTEX_PRE_CLIP_POS);
LP_CHECK_MEMBER_OFFSET(struct vertex_header, data,
target, vertex_header,
DRAW_JIT_VERTEX_DATA);
 
assert(LLVMABISizeOfType(target, vertex_header) ==
offsetof(struct vertex_header, data[data_elems]));
 
return vertex_header;
}
 
 
/**
* Create LLVM types for various structures.
*/
static void
create_jit_types(struct draw_llvm_variant *variant)
{
struct gallivm_state *gallivm = variant->gallivm;
LLVMTypeRef texture_type, sampler_type, context_type, buffer_type,
vb_type;
 
texture_type = create_jit_texture_type(gallivm, "texture");
sampler_type = create_jit_sampler_type(gallivm, "sampler");
 
context_type = create_jit_context_type(gallivm, texture_type, sampler_type,
"draw_jit_context");
variant->context_ptr_type = LLVMPointerType(context_type, 0);
 
buffer_type = create_jit_dvbuffer_type(gallivm, "draw_vertex_buffer");
variant->buffer_ptr_type = LLVMPointerType(buffer_type, 0);
vb_type = create_jit_vertex_buffer_type(gallivm, "pipe_vertex_buffer");
variant->vb_ptr_type = LLVMPointerType(vb_type, 0);
}
 
 
static LLVMTypeRef
get_context_ptr_type(struct draw_llvm_variant *variant)
{
if (!variant->context_ptr_type)
create_jit_types(variant);
return variant->context_ptr_type;
}
 
 
static LLVMTypeRef
get_buffer_ptr_type(struct draw_llvm_variant *variant)
{
if (!variant->buffer_ptr_type)
create_jit_types(variant);
return variant->buffer_ptr_type;
}
 
 
static LLVMTypeRef
get_vb_ptr_type(struct draw_llvm_variant *variant)
{
if (!variant->vb_ptr_type)
create_jit_types(variant);
return variant->vb_ptr_type;
}
 
static LLVMTypeRef
get_vertex_header_ptr_type(struct draw_llvm_variant *variant)
{
if (!variant->vertex_header_ptr_type)
create_jit_types(variant);
return variant->vertex_header_ptr_type;
}
 
 
/**
* Create per-context LLVM info.
*/
struct draw_llvm *
draw_llvm_create(struct draw_context *draw)
{
struct draw_llvm *llvm;
 
llvm = CALLOC_STRUCT( draw_llvm );
if (!llvm)
return NULL;
 
lp_build_init();
 
llvm->draw = draw;
 
llvm->nr_variants = 0;
make_empty_list(&llvm->vs_variants_list);
 
llvm->nr_gs_variants = 0;
make_empty_list(&llvm->gs_variants_list);
 
return llvm;
}
 
 
/**
* Free per-context LLVM info.
*/
void
draw_llvm_destroy(struct draw_llvm *llvm)
{
/* XXX free other draw_llvm data? */
FREE(llvm);
}
 
 
/**
* Create LLVM-generated code for a vertex shader.
*/
struct draw_llvm_variant *
draw_llvm_create_variant(struct draw_llvm *llvm,
unsigned num_inputs,
const struct draw_llvm_variant_key *key)
{
struct draw_llvm_variant *variant;
struct llvm_vertex_shader *shader =
llvm_vertex_shader(llvm->draw->vs.vertex_shader);
LLVMTypeRef vertex_header;
 
variant = MALLOC(sizeof *variant +
shader->variant_key_size -
sizeof variant->key);
if (variant == NULL)
return NULL;
 
variant->llvm = llvm;
 
variant->gallivm = gallivm_create();
 
create_jit_types(variant);
 
memcpy(&variant->key, key, shader->variant_key_size);
 
vertex_header = create_jit_vertex_header(variant->gallivm, num_inputs);
 
variant->vertex_header_ptr_type = LLVMPointerType(vertex_header, 0);
 
draw_llvm_generate(llvm, variant, FALSE); /* linear */
draw_llvm_generate(llvm, variant, TRUE); /* elts */
 
gallivm_compile_module(variant->gallivm);
 
variant->jit_func = (draw_jit_vert_func)
gallivm_jit_function(variant->gallivm, variant->function);
 
variant->jit_func_elts = (draw_jit_vert_func_elts)
gallivm_jit_function(variant->gallivm, variant->function_elts);
 
variant->shader = shader;
variant->list_item_global.base = variant;
variant->list_item_local.base = variant;
/*variant->no = */shader->variants_created++;
variant->list_item_global.base = variant;
 
return variant;
}
 
 
static void
generate_vs(struct draw_llvm_variant *variant,
LLVMBuilderRef builder,
struct lp_type vs_type,
LLVMValueRef (*outputs)[TGSI_NUM_CHANNELS],
const LLVMValueRef (*inputs)[TGSI_NUM_CHANNELS],
const struct lp_bld_tgsi_system_values *system_values,
LLVMValueRef context_ptr,
struct lp_build_sampler_soa *draw_sampler,
boolean clamp_vertex_color)
{
struct draw_llvm *llvm = variant->llvm;
const struct tgsi_token *tokens = llvm->draw->vs.vertex_shader->state.tokens;
LLVMValueRef consts_ptr = draw_jit_context_vs_constants(variant->gallivm, context_ptr);
struct lp_build_sampler_soa *sampler = 0;
 
if (gallivm_debug & (GALLIVM_DEBUG_TGSI | GALLIVM_DEBUG_IR)) {
tgsi_dump(tokens, 0);
draw_llvm_dump_variant_key(&variant->key);
}
 
if (llvm->draw->num_sampler_views && llvm->draw->num_samplers)
sampler = draw_sampler;
 
lp_build_tgsi_soa(variant->gallivm,
tokens,
vs_type,
NULL /*struct lp_build_mask_context *mask*/,
consts_ptr,
system_values,
inputs,
outputs,
sampler,
&llvm->draw->vs.vertex_shader->info,
NULL);
 
{
LLVMValueRef out;
unsigned chan, attrib;
struct lp_build_context bld;
struct tgsi_shader_info* info = &llvm->draw->vs.vertex_shader->info;
lp_build_context_init(&bld, variant->gallivm, vs_type);
 
for (attrib = 0; attrib < info->num_outputs; ++attrib) {
for (chan = 0; chan < TGSI_NUM_CHANNELS; ++chan) {
if (outputs[attrib][chan]) {
switch (info->output_semantic_name[attrib]) {
case TGSI_SEMANTIC_COLOR:
case TGSI_SEMANTIC_BCOLOR:
if (clamp_vertex_color) {
out = LLVMBuildLoad(builder, outputs[attrib][chan], "");
out = lp_build_clamp(&bld, out, bld.zero, bld.one);
LLVMBuildStore(builder, out, outputs[attrib][chan]);
}
break;
case TGSI_SEMANTIC_FOG:
if (chan == 1 || chan == 2)
LLVMBuildStore(builder, bld.zero, outputs[attrib][chan]);
else if (chan == 3)
LLVMBuildStore(builder, bld.one, outputs[attrib][chan]);
break;
}
}
}
}
}
}
 
static void
generate_fetch(struct gallivm_state *gallivm,
struct draw_context *draw,
LLVMValueRef vbuffers_ptr,
LLVMValueRef *res,
struct pipe_vertex_element *velem,
LLVMValueRef vbuf,
LLVMValueRef index,
LLVMValueRef instance_id)
{
const struct util_format_description *format_desc =
util_format_description(velem->src_format);
LLVMValueRef zero = LLVMConstNull(LLVMInt32TypeInContext(gallivm->context));
LLVMBuilderRef builder = gallivm->builder;
LLVMValueRef indices =
LLVMConstInt(LLVMInt64TypeInContext(gallivm->context),
velem->vertex_buffer_index, 0);
LLVMValueRef vbuffer_ptr = LLVMBuildGEP(builder, vbuffers_ptr,
&indices, 1, "");
LLVMValueRef vb_stride = draw_jit_vbuffer_stride(gallivm, vbuf);
LLVMValueRef vb_buffer_offset = draw_jit_vbuffer_offset(gallivm, vbuf);
LLVMValueRef map_ptr = draw_jit_dvbuffer_map(gallivm, vbuffer_ptr);
LLVMValueRef buffer_size = draw_jit_dvbuffer_size(gallivm, vbuffer_ptr);
LLVMValueRef stride;
LLVMValueRef buffer_overflowed;
LLVMValueRef needed_buffer_size;
LLVMValueRef temp_ptr =
lp_build_alloca(gallivm,
lp_build_vec_type(gallivm, lp_float32_vec4_type()), "");
LLVMValueRef ofbit = NULL;
struct lp_build_if_state if_ctx;
 
if (velem->instance_divisor) {
/* Index is equal to the start instance plus the number of current
* instance divided by the divisor. In this case we compute it as:
* index = start_instance + ((instance_id - start_instance) / divisor)
*/
LLVMValueRef current_instance;
index = lp_build_const_int32(gallivm, draw->start_instance);
current_instance = LLVMBuildSub(builder, instance_id, index, "");
current_instance = LLVMBuildUDiv(builder, current_instance,
lp_build_const_int32(gallivm, velem->instance_divisor),
"instance_divisor");
index = LLVMBuildAdd(builder, index, current_instance, "instance");
}
 
stride = lp_build_umul_overflow(gallivm, vb_stride, index, &ofbit);
stride = lp_build_uadd_overflow(gallivm, stride, vb_buffer_offset, &ofbit);
stride = lp_build_uadd_overflow(
gallivm, stride,
lp_build_const_int32(gallivm, velem->src_offset), &ofbit);
needed_buffer_size = lp_build_uadd_overflow(
gallivm, stride,
lp_build_const_int32(gallivm,
util_format_get_blocksize(velem->src_format)),
&ofbit);
 
buffer_overflowed = LLVMBuildICmp(builder, LLVMIntUGT,
needed_buffer_size, buffer_size,
"buffer_overflowed");
buffer_overflowed = LLVMBuildOr(builder, buffer_overflowed, ofbit, "");
#if 0
lp_build_printf(gallivm, "vbuf index = %u, vb_stride is %u\n",
index, vb_stride);
lp_build_printf(gallivm, " vb_buffer_offset = %u, src_offset is %u\n",
vb_buffer_offset,
lp_build_const_int32(gallivm, velem->src_offset));
lp_build_print_value(gallivm, " blocksize = ",
lp_build_const_int32(
gallivm,
util_format_get_blocksize(velem->src_format)));
lp_build_printf(gallivm, " instance_id = %u\n", instance_id);
lp_build_printf(gallivm, " stride = %u\n", stride);
lp_build_printf(gallivm, " buffer size = %u\n", buffer_size);
lp_build_printf(gallivm, " needed_buffer_size = %u\n", needed_buffer_size);
lp_build_print_value(gallivm, " buffer overflowed = ", buffer_overflowed);
#endif
 
lp_build_if(&if_ctx, gallivm, buffer_overflowed);
{
LLVMValueRef val =
lp_build_const_vec(gallivm, lp_float32_vec4_type(), 0);
LLVMBuildStore(builder, val, temp_ptr);
}
lp_build_else(&if_ctx);
{
LLVMValueRef val;
map_ptr = LLVMBuildGEP(builder, map_ptr, &stride, 1, "");
 
val = lp_build_fetch_rgba_aos(gallivm,
format_desc,
lp_float32_vec4_type(),
map_ptr,
zero, zero, zero);
LLVMBuildStore(builder, val, temp_ptr);
}
lp_build_endif(&if_ctx);
 
*res = LLVMBuildLoad(builder, temp_ptr, "aos");
}
 
static void
convert_to_soa(struct gallivm_state *gallivm,
LLVMValueRef (*src_aos)[LP_MAX_VECTOR_WIDTH / 32],
LLVMValueRef (*dst_soa)[TGSI_NUM_CHANNELS],
unsigned num_attribs, const struct lp_type soa_type)
{
unsigned i, j, k;
struct lp_type aos_channel_type = soa_type;
 
debug_assert(TGSI_NUM_CHANNELS == 4);
debug_assert((soa_type.length % TGSI_NUM_CHANNELS) == 0);
 
aos_channel_type.length >>= 1;
 
for (i = 0; i < num_attribs; ++i) {
LLVMValueRef aos_channels[TGSI_NUM_CHANNELS];
unsigned pixels_per_channel = soa_type.length / TGSI_NUM_CHANNELS;
 
for (j = 0; j < TGSI_NUM_CHANNELS; ++j) {
LLVMValueRef channel[LP_MAX_VECTOR_LENGTH] = { 0 };
 
assert(pixels_per_channel <= LP_MAX_VECTOR_LENGTH);
 
for (k = 0; k < pixels_per_channel; ++k) {
channel[k] = src_aos[i][j + TGSI_NUM_CHANNELS * k];
}
 
aos_channels[j] = lp_build_concat(gallivm, channel, aos_channel_type, pixels_per_channel);
}
 
lp_build_transpose_aos(gallivm, soa_type, aos_channels, dst_soa[i]);
}
}
 
 
static void
store_aos(struct gallivm_state *gallivm,
LLVMValueRef io_ptr,
LLVMValueRef index,
LLVMValueRef value)
{
LLVMTypeRef data_ptr_type = LLVMPointerType(lp_build_vec_type(gallivm, lp_float32_vec4_type()), 0);
LLVMBuilderRef builder = gallivm->builder;
LLVMValueRef data_ptr = draw_jit_header_data(gallivm, io_ptr);
LLVMValueRef indices[3];
 
indices[0] = lp_build_const_int32(gallivm, 0);
indices[1] = index;
indices[2] = lp_build_const_int32(gallivm, 0);
 
data_ptr = LLVMBuildGEP(builder, data_ptr, indices, 3, "");
data_ptr = LLVMBuildPointerCast(builder, data_ptr, data_ptr_type, "");
 
#if DEBUG_STORE
lp_build_printf(gallivm, " ---- %p storing attribute %d (io = %p)\n", data_ptr, index, io_ptr);
#endif
 
/* Unaligned store due to the vertex header */
lp_set_store_alignment(LLVMBuildStore(builder, value, data_ptr), sizeof(float));
}
 
/**
* Adjust the mask to architecture endianess. The mask will the store in struct:
*
* struct vertex_header {
* unsigned clipmask:DRAW_TOTAL_CLIP_PLANES;
* unsigned edgeflag:1;
* unsigned have_clipdist:1;
* unsigned vertex_id:16;
* [...]
* }
*
* On little-endian machine nothing needs to done, however on bit-endian machine
* the mask's fields need to be adjusted with the algorithm:
*
* uint32_t reverse (uint32_t x)
* {
* return (x >> 16) | // vertex_id
* ((x & 0x3fff) << 18) | // clipmask
* ((x & 0x4000) << 3) | // have_clipdist
* ((x & 0x8000) << 1); // edgeflag
* }
*/
static LLVMValueRef
adjust_mask(struct gallivm_state *gallivm,
LLVMValueRef mask)
{
#ifdef PIPE_ARCH_BIG_ENDIAN
LLVMBuilderRef builder = gallivm->builder;
LLVMValueRef vertex_id;
LLVMValueRef clipmask;
LLVMValueRef have_clipdist;
LLVMValueRef edgeflag;
 
vertex_id = LLVMBuildLShr(builder, mask, lp_build_const_int32(gallivm, 16), "");
clipmask = LLVMBuildAnd(builder, mask, lp_build_const_int32(gallivm, 0x3fff), "");
clipmask = LLVMBuildShl(builder, clipmask, lp_build_const_int32(gallivm, 18), "");
have_clipdist = LLVMBuildAnd(builder, mask, lp_build_const_int32(gallivm, 0x4000), "");
have_clipdist = LLVMBuildShl(builder, have_clipdist, lp_build_const_int32(gallivm, 3), "");
edgeflag = LLVMBuildAnd(builder, mask, lp_build_const_int32(gallivm, 0x8000), "");
edgeflag = LLVMBuildShl(builder, edgeflag, lp_build_const_int32(gallivm, 1), "");
 
mask = LLVMBuildOr(builder, vertex_id, clipmask, "");
mask = LLVMBuildOr(builder, mask, have_clipdist, "");
mask = LLVMBuildOr(builder, mask, edgeflag, "");
#endif
return mask;
}
 
static void
store_aos_array(struct gallivm_state *gallivm,
struct lp_type soa_type,
LLVMValueRef io_ptr,
LLVMValueRef *indices,
LLVMValueRef* aos,
int attrib,
int num_outputs,
LLVMValueRef clipmask,
boolean have_clipdist)
{
LLVMBuilderRef builder = gallivm->builder;
LLVMValueRef attr_index = lp_build_const_int32(gallivm, attrib);
LLVMValueRef inds[LP_MAX_VECTOR_WIDTH / 32];
LLVMValueRef linear_inds[LP_MAX_VECTOR_WIDTH / 32];
LLVMValueRef io_ptrs[LP_MAX_VECTOR_WIDTH / 32];
int vector_length = soa_type.length;
int i;
 
debug_assert(TGSI_NUM_CHANNELS == 4);
 
for (i = 0; i < vector_length; i++) {
linear_inds[i] = lp_build_const_int32(gallivm, i);
if (indices) {
inds[i] = indices[i];
} else {
inds[i] = linear_inds[i];
}
io_ptrs[i] = LLVMBuildGEP(builder, io_ptr, &inds[i], 1, "");
}
 
if (attrib == 0) {
/* store vertex header for each of the n vertices */
LLVMValueRef val, cliptmp;
int vertex_id_pad_edgeflag;
 
/* If this assertion fails, it means we need to update the bit twidding
* code here. See struct vertex_header in draw_private.h.
*/
assert(DRAW_TOTAL_CLIP_PLANES==14);
/* initialize vertex id:16 = 0xffff, have_clipdist:1 = 0, edgeflag:1 = 1 */
vertex_id_pad_edgeflag = (0xffff << 16) | (1 << DRAW_TOTAL_CLIP_PLANES);
if (have_clipdist)
vertex_id_pad_edgeflag |= 1 << (DRAW_TOTAL_CLIP_PLANES+1);
val = lp_build_const_int_vec(gallivm, lp_int_type(soa_type), vertex_id_pad_edgeflag);
/* OR with the clipmask */
cliptmp = LLVMBuildOr(builder, val, clipmask, "");
for (i = 0; i < vector_length; i++) {
LLVMValueRef id_ptr = draw_jit_header_id(gallivm, io_ptrs[i]);
val = LLVMBuildExtractElement(builder, cliptmp, linear_inds[i], "");
val = adjust_mask(gallivm, val);
LLVMBuildStore(builder, val, id_ptr);
#if DEBUG_STORE
lp_build_printf(gallivm, "io = %p, index %d, clipmask = %x\n",
io_ptrs[i], inds[i], val);
#endif
}
}
 
/* store for each of the n vertices */
for (i = 0; i < vector_length; i++) {
store_aos(gallivm, io_ptrs[i], attr_index, aos[i]);
}
}
 
 
static void
convert_to_aos(struct gallivm_state *gallivm,
LLVMValueRef io,
LLVMValueRef *indices,
LLVMValueRef (*outputs)[TGSI_NUM_CHANNELS],
LLVMValueRef clipmask,
int num_outputs,
struct lp_type soa_type,
boolean have_clipdist)
{
LLVMBuilderRef builder = gallivm->builder;
unsigned chan, attrib, i;
 
#if DEBUG_STORE
lp_build_printf(gallivm, " # storing begin\n");
#endif
for (attrib = 0; attrib < num_outputs; ++attrib) {
LLVMValueRef soa[TGSI_NUM_CHANNELS];
LLVMValueRef aos[LP_MAX_VECTOR_WIDTH / 32];
for (chan = 0; chan < TGSI_NUM_CHANNELS; ++chan) {
if (outputs[attrib][chan]) {
LLVMValueRef out = LLVMBuildLoad(builder, outputs[attrib][chan], "");
lp_build_name(out, "output%u.%c", attrib, "xyzw"[chan]);
#if DEBUG_STORE
lp_build_printf(gallivm, "output %d : %d ",
LLVMConstInt(LLVMInt32TypeInContext(gallivm->context),
attrib, 0),
LLVMConstInt(LLVMInt32TypeInContext(gallivm->context),
chan, 0));
lp_build_print_value(gallivm, "val = ", out);
#endif
soa[chan] = out;
}
else {
soa[chan] = 0;
}
}
 
 
if (soa_type.length == TGSI_NUM_CHANNELS) {
lp_build_transpose_aos(gallivm, soa_type, soa, aos);
} else {
lp_build_transpose_aos(gallivm, soa_type, soa, soa);
 
for (i = 0; i < soa_type.length; ++i) {
aos[i] = lp_build_extract_range(gallivm,
soa[i % TGSI_NUM_CHANNELS],
(i / TGSI_NUM_CHANNELS) * TGSI_NUM_CHANNELS,
TGSI_NUM_CHANNELS);
}
}
 
store_aos_array(gallivm,
soa_type,
io, indices,
aos,
attrib,
num_outputs,
clipmask, have_clipdist);
}
#if DEBUG_STORE
lp_build_printf(gallivm, " # storing end\n");
#endif
}
 
 
/**
* Stores original vertex positions in clip coordinates
*/
static void
store_clip(struct gallivm_state *gallivm,
const struct lp_type vs_type,
LLVMValueRef io_ptr,
LLVMValueRef (*outputs)[TGSI_NUM_CHANNELS],
boolean pre_clip_pos, int idx)
{
LLVMBuilderRef builder = gallivm->builder;
LLVMValueRef soa[4];
LLVMValueRef aos[LP_MAX_VECTOR_LENGTH];
LLVMValueRef indices[2];
LLVMValueRef io_ptrs[LP_MAX_VECTOR_WIDTH / 32];
LLVMValueRef inds[LP_MAX_VECTOR_WIDTH / 32];
LLVMValueRef clip_ptrs[LP_MAX_VECTOR_WIDTH / 32];
int i, j;
 
indices[0] =
indices[1] = lp_build_const_int32(gallivm, 0);
 
for (i = 0; i < vs_type.length; i++) {
inds[i] = lp_build_const_int32(gallivm, i);
io_ptrs[i] = LLVMBuildGEP(builder, io_ptr, &inds[i], 1, "");
}
 
soa[0] = LLVMBuildLoad(builder, outputs[idx][0], ""); /*x0 x1 .. xn*/
soa[1] = LLVMBuildLoad(builder, outputs[idx][1], ""); /*y0 y1 .. yn*/
soa[2] = LLVMBuildLoad(builder, outputs[idx][2], ""); /*z0 z1 .. zn*/
soa[3] = LLVMBuildLoad(builder, outputs[idx][3], ""); /*w0 w1 .. wn*/
 
if (!pre_clip_pos) {
for (i = 0; i < vs_type.length; i++) {
clip_ptrs[i] = draw_jit_header_clip(gallivm, io_ptrs[i]);
}
} else {
for (i = 0; i < vs_type.length; i++) {
clip_ptrs[i] = draw_jit_header_pre_clip_pos(gallivm, io_ptrs[i]);
}
}
 
lp_build_transpose_aos(gallivm, vs_type, soa, soa);
for (i = 0; i < vs_type.length; ++i) {
aos[i] = lp_build_extract_range(gallivm,
soa[i % TGSI_NUM_CHANNELS],
(i / TGSI_NUM_CHANNELS) * TGSI_NUM_CHANNELS,
TGSI_NUM_CHANNELS);
}
 
for (j = 0; j < vs_type.length; j++) {
LLVMTypeRef clip_ptr_type = LLVMPointerType(LLVMVectorType(LLVMFloatTypeInContext(gallivm->context), 4), 0);
LLVMValueRef clip_ptr;
 
clip_ptr = LLVMBuildGEP(builder, clip_ptrs[j], indices, 2, "clipo");
clip_ptr = LLVMBuildPointerCast(builder, clip_ptr, clip_ptr_type, "");
 
/* Unaligned store */
lp_set_store_alignment(LLVMBuildStore(builder, aos[j], clip_ptr), sizeof(float));
}
}
 
 
/**
* Transforms the outputs for viewport mapping
*/
static void
generate_viewport(struct draw_llvm_variant *variant,
LLVMBuilderRef builder,
struct lp_type vs_type,
LLVMValueRef (*outputs)[TGSI_NUM_CHANNELS],
LLVMValueRef context_ptr)
{
int i;
struct gallivm_state *gallivm = variant->gallivm;
struct lp_type f32_type = vs_type;
const unsigned pos = draw_current_shader_position_output(variant->llvm->draw);
LLVMTypeRef vs_type_llvm = lp_build_vec_type(gallivm, vs_type);
LLVMValueRef out3 = LLVMBuildLoad(builder, outputs[pos][3], ""); /*w0 w1 .. wn*/
LLVMValueRef const1 = lp_build_const_vec(gallivm, f32_type, 1.0); /*1.0 1.0 1.0 1.0*/
LLVMValueRef vp_ptr = draw_jit_context_viewport(gallivm, context_ptr);
 
/* for 1/w convention*/
out3 = LLVMBuildFDiv(builder, const1, out3, "");
LLVMBuildStore(builder, out3, outputs[pos][3]);
 
/* Viewport Mapping */
for (i=0; i<3; i++) {
LLVMValueRef out = LLVMBuildLoad(builder, outputs[pos][i], ""); /*x0 x1 .. xn*/
LLVMValueRef scale;
LLVMValueRef trans;
LLVMValueRef scale_i;
LLVMValueRef trans_i;
LLVMValueRef index;
 
index = lp_build_const_int32(gallivm, i);
scale_i = LLVMBuildGEP(builder, vp_ptr, &index, 1, "");
 
index = lp_build_const_int32(gallivm, i+4);
trans_i = LLVMBuildGEP(builder, vp_ptr, &index, 1, "");
 
scale = lp_build_broadcast(gallivm, vs_type_llvm,
LLVMBuildLoad(builder, scale_i, "scale"));
trans = lp_build_broadcast(gallivm, vs_type_llvm,
LLVMBuildLoad(builder, trans_i, "trans"));
 
/* divide by w */
out = LLVMBuildFMul(builder, out, out3, "");
/* mult by scale */
out = LLVMBuildFMul(builder, out, scale, "");
/* add translation */
out = LLVMBuildFAdd(builder, out, trans, "");
 
/* store transformed outputs */
LLVMBuildStore(builder, out, outputs[pos][i]);
}
 
}
 
 
/**
* Returns clipmask as nxi32 bitmask for the n vertices
*/
static LLVMValueRef
generate_clipmask(struct draw_llvm *llvm,
struct gallivm_state *gallivm,
struct lp_type vs_type,
LLVMValueRef (*outputs)[TGSI_NUM_CHANNELS],
boolean clip_xy,
boolean clip_z,
boolean clip_user,
boolean clip_halfz,
unsigned ucp_enable,
LLVMValueRef context_ptr,
boolean *have_clipdist)
{
LLVMBuilderRef builder = gallivm->builder;
LLVMValueRef mask; /* stores the <nxi32> clipmasks */
LLVMValueRef test, temp;
LLVMValueRef zero, shift;
LLVMValueRef pos_x, pos_y, pos_z, pos_w;
LLVMValueRef cv_x, cv_y, cv_z, cv_w;
LLVMValueRef plane1, planes, plane_ptr, sum;
struct lp_type f32_type = vs_type;
struct lp_type i32_type = lp_int_type(vs_type);
const unsigned pos = draw_current_shader_position_output(llvm->draw);
const unsigned cv = draw_current_shader_clipvertex_output(llvm->draw);
int num_written_clipdistance = llvm->draw->vs.vertex_shader->info.num_written_clipdistance;
bool have_cd = false;
unsigned cd[2];
 
cd[0] = draw_current_shader_clipdistance_output(llvm->draw, 0);
cd[1] = draw_current_shader_clipdistance_output(llvm->draw, 1);
 
if (cd[0] != pos || cd[1] != pos)
have_cd = true;
 
if (num_written_clipdistance && !clip_user) {
clip_user = true;
ucp_enable = (1 << num_written_clipdistance) - 1;
}
 
mask = lp_build_const_int_vec(gallivm, i32_type, 0);
temp = lp_build_const_int_vec(gallivm, i32_type, 0);
zero = lp_build_const_vec(gallivm, f32_type, 0); /* 0.0f 0.0f 0.0f 0.0f */
shift = lp_build_const_int_vec(gallivm, i32_type, 1); /* 1 1 1 1 */
 
/*
* load clipvertex and position from correct locations.
* if they are the same just load them once.
*/
pos_x = LLVMBuildLoad(builder, outputs[pos][0], ""); /*x0 x1 .. xn */
pos_y = LLVMBuildLoad(builder, outputs[pos][1], ""); /*y0 y1 .. yn */
pos_z = LLVMBuildLoad(builder, outputs[pos][2], ""); /*z0 z1 .. zn */
pos_w = LLVMBuildLoad(builder, outputs[pos][3], ""); /*w0 w1 .. wn */
 
if (clip_user && cv != pos) {
cv_x = LLVMBuildLoad(builder, outputs[cv][0], ""); /*x0 x1 .. xn */
cv_y = LLVMBuildLoad(builder, outputs[cv][1], ""); /*y0 y1 .. yn */
cv_z = LLVMBuildLoad(builder, outputs[cv][2], ""); /*z0 z1 .. zn */
cv_w = LLVMBuildLoad(builder, outputs[cv][3], ""); /*w0 w1 .. wn */
} else {
cv_x = pos_x;
cv_y = pos_y;
cv_z = pos_z;
cv_w = pos_w;
}
 
/* Cliptest, for hardwired planes */
if (clip_xy) {
/* plane 1 */
test = lp_build_compare(gallivm, f32_type, PIPE_FUNC_GREATER, pos_x , pos_w);
temp = shift;
test = LLVMBuildAnd(builder, test, temp, "");
mask = test;
 
/* plane 2 */
test = LLVMBuildFAdd(builder, pos_x, pos_w, "");
test = lp_build_compare(gallivm, f32_type, PIPE_FUNC_GREATER, zero, test);
temp = LLVMBuildShl(builder, temp, shift, "");
test = LLVMBuildAnd(builder, test, temp, "");
mask = LLVMBuildOr(builder, mask, test, "");
 
/* plane 3 */
test = lp_build_compare(gallivm, f32_type, PIPE_FUNC_GREATER, pos_y, pos_w);
temp = LLVMBuildShl(builder, temp, shift, "");
test = LLVMBuildAnd(builder, test, temp, "");
mask = LLVMBuildOr(builder, mask, test, "");
 
/* plane 4 */
test = LLVMBuildFAdd(builder, pos_y, pos_w, "");
test = lp_build_compare(gallivm, f32_type, PIPE_FUNC_GREATER, zero, test);
temp = LLVMBuildShl(builder, temp, shift, "");
test = LLVMBuildAnd(builder, test, temp, "");
mask = LLVMBuildOr(builder, mask, test, "");
}
 
if (clip_z) {
temp = lp_build_const_int_vec(gallivm, i32_type, 16);
if (clip_halfz) {
/* plane 5 */
test = lp_build_compare(gallivm, f32_type, PIPE_FUNC_GREATER, zero, pos_z);
test = LLVMBuildAnd(builder, test, temp, "");
mask = LLVMBuildOr(builder, mask, test, "");
}
else {
/* plane 5 */
test = LLVMBuildFAdd(builder, pos_z, pos_w, "");
test = lp_build_compare(gallivm, f32_type, PIPE_FUNC_GREATER, zero, test);
test = LLVMBuildAnd(builder, test, temp, "");
mask = LLVMBuildOr(builder, mask, test, "");
}
/* plane 6 */
test = lp_build_compare(gallivm, f32_type, PIPE_FUNC_GREATER, pos_z, pos_w);
temp = LLVMBuildShl(builder, temp, shift, "");
test = LLVMBuildAnd(builder, test, temp, "");
mask = LLVMBuildOr(builder, mask, test, "");
}
 
if (clip_user) {
LLVMValueRef planes_ptr = draw_jit_context_planes(gallivm, context_ptr);
LLVMValueRef indices[3];
 
/* userclip planes */
while (ucp_enable) {
unsigned plane_idx = ffs(ucp_enable)-1;
ucp_enable &= ~(1 << plane_idx);
plane_idx += 6;
 
if (have_cd && num_written_clipdistance) {
LLVMValueRef clipdist;
int i;
i = plane_idx - 6;
 
*have_clipdist = TRUE;
if (i < 4) {
clipdist = LLVMBuildLoad(builder, outputs[cd[0]][i], "");
} else {
clipdist = LLVMBuildLoad(builder, outputs[cd[1]][i-4], "");
}
test = lp_build_compare(gallivm, f32_type, PIPE_FUNC_GREATER, zero, clipdist);
temp = lp_build_const_int_vec(gallivm, i32_type, 1 << plane_idx);
test = LLVMBuildAnd(builder, test, temp, "");
mask = LLVMBuildOr(builder, mask, test, "");
} else {
LLVMTypeRef vs_type_llvm = lp_build_vec_type(gallivm, vs_type);
indices[0] = lp_build_const_int32(gallivm, 0);
indices[1] = lp_build_const_int32(gallivm, plane_idx);
 
indices[2] = lp_build_const_int32(gallivm, 0);
plane_ptr = LLVMBuildGEP(builder, planes_ptr, indices, 3, "");
plane1 = LLVMBuildLoad(builder, plane_ptr, "plane_x");
planes = lp_build_broadcast(gallivm, vs_type_llvm, plane1);
sum = LLVMBuildFMul(builder, planes, cv_x, "");
 
indices[2] = lp_build_const_int32(gallivm, 1);
plane_ptr = LLVMBuildGEP(builder, planes_ptr, indices, 3, "");
plane1 = LLVMBuildLoad(builder, plane_ptr, "plane_y");
planes = lp_build_broadcast(gallivm, vs_type_llvm, plane1);
test = LLVMBuildFMul(builder, planes, cv_y, "");
sum = LLVMBuildFAdd(builder, sum, test, "");
 
indices[2] = lp_build_const_int32(gallivm, 2);
plane_ptr = LLVMBuildGEP(builder, planes_ptr, indices, 3, "");
plane1 = LLVMBuildLoad(builder, plane_ptr, "plane_z");
planes = lp_build_broadcast(gallivm, vs_type_llvm, plane1);
test = LLVMBuildFMul(builder, planes, cv_z, "");
sum = LLVMBuildFAdd(builder, sum, test, "");
 
indices[2] = lp_build_const_int32(gallivm, 3);
plane_ptr = LLVMBuildGEP(builder, planes_ptr, indices, 3, "");
plane1 = LLVMBuildLoad(builder, plane_ptr, "plane_w");
planes = lp_build_broadcast(gallivm, vs_type_llvm, plane1);
test = LLVMBuildFMul(builder, planes, cv_w, "");
sum = LLVMBuildFAdd(builder, sum, test, "");
 
test = lp_build_compare(gallivm, f32_type, PIPE_FUNC_GREATER, zero, sum);
temp = lp_build_const_int_vec(gallivm, i32_type, 1 << plane_idx);
test = LLVMBuildAnd(builder, test, temp, "");
mask = LLVMBuildOr(builder, mask, test, "");
}
}
}
return mask;
}
 
 
/**
* Returns boolean if any clipping has occurred
* Used zero/non-zero i32 value to represent boolean
*/
static LLVMValueRef
clipmask_booli32(struct gallivm_state *gallivm,
const struct lp_type vs_type,
LLVMValueRef clipmask_bool_ptr)
{
LLVMBuilderRef builder = gallivm->builder;
LLVMTypeRef int32_type = LLVMInt32TypeInContext(gallivm->context);
LLVMValueRef clipmask_bool = LLVMBuildLoad(builder, clipmask_bool_ptr, "");
LLVMValueRef ret = LLVMConstNull(int32_type);
LLVMValueRef temp;
int i;
 
/*
* Can do this with log2(vector length) pack instructions and one extract
* (as we don't actually need a or) with sse2 which would be way better.
*/
for (i=0; i < vs_type.length; i++) {
temp = LLVMBuildExtractElement(builder, clipmask_bool,
lp_build_const_int32(gallivm, i) , "");
ret = LLVMBuildOr(builder, ret, temp, "");
}
return ret;
}
 
static LLVMValueRef
draw_gs_llvm_fetch_input(const struct lp_build_tgsi_gs_iface *gs_iface,
struct lp_build_tgsi_context * bld_base,
boolean is_indirect,
LLVMValueRef vertex_index,
LLVMValueRef attrib_index,
LLVMValueRef swizzle_index)
{
const struct draw_gs_llvm_iface *gs = draw_gs_llvm_iface(gs_iface);
struct gallivm_state *gallivm = bld_base->base.gallivm;
LLVMBuilderRef builder = gallivm->builder;
LLVMValueRef indices[3];
LLVMValueRef res;
struct lp_type type = bld_base->base.type;
 
if (is_indirect) {
int i;
res = bld_base->base.zero;
for (i = 0; i < type.length; ++i) {
LLVMValueRef idx = lp_build_const_int32(gallivm, i);
LLVMValueRef vert_chan_index = LLVMBuildExtractElement(builder,
vertex_index, idx, "");
LLVMValueRef channel_vec, value;
indices[0] = vert_chan_index;
indices[1] = attrib_index;
indices[2] = swizzle_index;
channel_vec = LLVMBuildGEP(builder, gs->input, indices, 3, "");
channel_vec = LLVMBuildLoad(builder, channel_vec, "");
value = LLVMBuildExtractElement(builder, channel_vec, idx, "");
 
res = LLVMBuildInsertElement(builder, res, value, idx, "");
}
} else {
indices[0] = vertex_index;
indices[1] = attrib_index;
indices[2] = swizzle_index;
 
res = LLVMBuildGEP(builder, gs->input, indices, 3, "");
res = LLVMBuildLoad(builder, res, "");
}
 
return res;
}
 
static void
draw_gs_llvm_emit_vertex(const struct lp_build_tgsi_gs_iface *gs_base,
struct lp_build_tgsi_context * bld_base,
LLVMValueRef (*outputs)[4],
LLVMValueRef emitted_vertices_vec)
{
const struct draw_gs_llvm_iface *gs_iface = draw_gs_llvm_iface(gs_base);
struct draw_gs_llvm_variant *variant = gs_iface->variant;
struct gallivm_state *gallivm = variant->gallivm;
LLVMBuilderRef builder = gallivm->builder;
struct lp_type gs_type = bld_base->base.type;
LLVMValueRef clipmask = lp_build_const_int_vec(gallivm,
lp_int_type(gs_type), 0);
LLVMValueRef indices[LP_MAX_VECTOR_LENGTH];
LLVMValueRef next_prim_offset =
lp_build_const_int32(gallivm, variant->shader->base.primitive_boundary);
LLVMValueRef io = variant->io_ptr;
unsigned i;
const struct tgsi_shader_info *gs_info = &variant->shader->base.info;
 
for (i = 0; i < gs_type.length; ++i) {
LLVMValueRef ind = lp_build_const_int32(gallivm, i);
LLVMValueRef currently_emitted =
LLVMBuildExtractElement(builder, emitted_vertices_vec, ind, "");
indices[i] = LLVMBuildMul(builder, ind, next_prim_offset, "");
indices[i] = LLVMBuildAdd(builder, indices[i], currently_emitted, "");
}
 
convert_to_aos(gallivm, io, indices,
outputs, clipmask,
gs_info->num_outputs, gs_type,
FALSE);
}
 
static void
draw_gs_llvm_end_primitive(const struct lp_build_tgsi_gs_iface *gs_base,
struct lp_build_tgsi_context * bld_base,
LLVMValueRef verts_per_prim_vec,
LLVMValueRef emitted_prims_vec)
{
const struct draw_gs_llvm_iface *gs_iface = draw_gs_llvm_iface(gs_base);
struct draw_gs_llvm_variant *variant = gs_iface->variant;
struct gallivm_state *gallivm = variant->gallivm;
LLVMBuilderRef builder = gallivm->builder;
LLVMValueRef prim_lengts_ptr =
draw_gs_jit_prim_lengths(variant->gallivm, variant->context_ptr);
unsigned i;
 
for (i = 0; i < bld_base->base.type.length; ++i) {
LLVMValueRef ind = lp_build_const_int32(gallivm, i);
LLVMValueRef prims_emitted =
LLVMBuildExtractElement(builder, emitted_prims_vec, ind, "");
LLVMValueRef store_ptr;
LLVMValueRef num_vertices =
LLVMBuildExtractElement(builder, verts_per_prim_vec, ind, "");
 
store_ptr = LLVMBuildGEP(builder, prim_lengts_ptr, &prims_emitted, 1, "");
store_ptr = LLVMBuildLoad(builder, store_ptr, "");
store_ptr = LLVMBuildGEP(builder, store_ptr, &ind, 1, "");
LLVMBuildStore(builder, num_vertices, store_ptr);
}
}
 
static void
draw_gs_llvm_epilogue(const struct lp_build_tgsi_gs_iface *gs_base,
struct lp_build_tgsi_context * bld_base,
LLVMValueRef total_emitted_vertices_vec,
LLVMValueRef emitted_prims_vec)
{
const struct draw_gs_llvm_iface *gs_iface = draw_gs_llvm_iface(gs_base);
struct draw_gs_llvm_variant *variant = gs_iface->variant;
struct gallivm_state *gallivm = variant->gallivm;
LLVMBuilderRef builder = gallivm->builder;
LLVMValueRef emitted_verts_ptr =
draw_gs_jit_emitted_vertices(gallivm, variant->context_ptr);
LLVMValueRef emitted_prims_ptr =
draw_gs_jit_emitted_prims(gallivm, variant->context_ptr);
LLVMValueRef zero = lp_build_const_int32(gallivm, 0);
emitted_verts_ptr = LLVMBuildGEP(builder, emitted_verts_ptr, &zero, 0, "");
emitted_prims_ptr = LLVMBuildGEP(builder, emitted_prims_ptr, &zero, 0, "");
 
LLVMBuildStore(builder, total_emitted_vertices_vec, emitted_verts_ptr);
LLVMBuildStore(builder, emitted_prims_vec, emitted_prims_ptr);
}
 
static void
draw_llvm_generate(struct draw_llvm *llvm, struct draw_llvm_variant *variant,
boolean elts)
{
struct gallivm_state *gallivm = variant->gallivm;
LLVMContextRef context = gallivm->context;
LLVMTypeRef int32_type = LLVMInt32TypeInContext(context);
LLVMTypeRef arg_types[9];
unsigned num_arg_types =
elts ? Elements(arg_types) : Elements(arg_types) - 1;
LLVMTypeRef func_type;
LLVMValueRef context_ptr;
LLVMBasicBlockRef block;
LLVMBuilderRef builder;
struct lp_type vs_type;
LLVMValueRef end, start;
LLVMValueRef count, fetch_elts, fetch_elt_max, fetch_count;
LLVMValueRef stride, step, io_itr;
LLVMValueRef io_ptr, vbuffers_ptr, vb_ptr;
LLVMValueRef zero = lp_build_const_int32(gallivm, 0);
LLVMValueRef one = lp_build_const_int32(gallivm, 1);
struct draw_context *draw = llvm->draw;
const struct tgsi_shader_info *vs_info = &draw->vs.vertex_shader->info;
unsigned i, j;
struct lp_build_context bld;
struct lp_build_loop_state lp_loop;
const int vector_length = lp_native_vector_width / 32;
LLVMValueRef outputs[PIPE_MAX_SHADER_OUTPUTS][TGSI_NUM_CHANNELS];
LLVMValueRef fetch_max;
struct lp_build_sampler_soa *sampler = 0;
LLVMValueRef ret, clipmask_bool_ptr;
const struct draw_geometry_shader *gs = draw->gs.geometry_shader;
struct draw_llvm_variant_key *key = &variant->key;
/* If geometry shader is present we need to skip both the viewport
* transformation and clipping otherwise the inputs to the geometry
* shader will be incorrect.
*/
const boolean bypass_viewport = gs || key->bypass_viewport;
const boolean enable_cliptest = !gs && (key->clip_xy ||
key->clip_z ||
key->clip_user);
LLVMValueRef variant_func;
const unsigned pos = draw_current_shader_position_output(llvm->draw);
const unsigned cv = draw_current_shader_clipvertex_output(llvm->draw);
boolean have_clipdist = FALSE;
struct lp_bld_tgsi_system_values system_values;
 
memset(&system_values, 0, sizeof(system_values));
 
i = 0;
arg_types[i++] = get_context_ptr_type(variant); /* context */
arg_types[i++] = get_vertex_header_ptr_type(variant); /* vertex_header */
arg_types[i++] = get_buffer_ptr_type(variant); /* vbuffers */
if (elts) {
arg_types[i++] = LLVMPointerType(int32_type, 0);/* fetch_elts */
arg_types[i++] = int32_type; /* fetch_elt_max */
} else
arg_types[i++] = int32_type; /* start */
arg_types[i++] = int32_type; /* fetch_count / count */
arg_types[i++] = int32_type; /* stride */
arg_types[i++] = get_vb_ptr_type(variant); /* pipe_vertex_buffer's */
arg_types[i++] = int32_type; /* instance_id */
 
func_type = LLVMFunctionType(int32_type, arg_types, num_arg_types, 0);
 
variant_func = LLVMAddFunction(gallivm->module,
elts ? "draw_llvm_shader_elts" : "draw_llvm_shader",
func_type);
 
if (elts)
variant->function_elts = variant_func;
else
variant->function = variant_func;
 
LLVMSetFunctionCallConv(variant_func, LLVMCCallConv);
for (i = 0; i < num_arg_types; ++i)
if (LLVMGetTypeKind(arg_types[i]) == LLVMPointerTypeKind)
LLVMAddAttribute(LLVMGetParam(variant_func, i),
LLVMNoAliasAttribute);
 
context_ptr = LLVMGetParam(variant_func, 0);
io_ptr = LLVMGetParam(variant_func, 1);
vbuffers_ptr = LLVMGetParam(variant_func, 2);
stride = LLVMGetParam(variant_func, 5 + (elts ? 1 : 0));
vb_ptr = LLVMGetParam(variant_func, 6 + (elts ? 1 : 0));
system_values.instance_id = LLVMGetParam(variant_func, 7 + (elts ? 1 : 0));
 
lp_build_name(context_ptr, "context");
lp_build_name(io_ptr, "io");
lp_build_name(vbuffers_ptr, "vbuffers");
lp_build_name(stride, "stride");
lp_build_name(vb_ptr, "vb");
lp_build_name(system_values.instance_id, "instance_id");
 
if (elts) {
fetch_elts = LLVMGetParam(variant_func, 3);
fetch_elt_max = LLVMGetParam(variant_func, 4);
fetch_count = LLVMGetParam(variant_func, 5);
lp_build_name(fetch_elts, "fetch_elts");
lp_build_name(fetch_elt_max, "fetch_elt_max");
lp_build_name(fetch_count, "fetch_count");
start = count = NULL;
}
else {
start = LLVMGetParam(variant_func, 3);
count = LLVMGetParam(variant_func, 4);
lp_build_name(start, "start");
lp_build_name(count, "count");
fetch_elts = fetch_count = NULL;
}
 
/*
* Function body
*/
 
block = LLVMAppendBasicBlockInContext(gallivm->context, variant_func, "entry");
builder = gallivm->builder;
LLVMPositionBuilderAtEnd(builder, block);
 
lp_build_context_init(&bld, gallivm, lp_type_int(32));
 
memset(&vs_type, 0, sizeof vs_type);
vs_type.floating = TRUE; /* floating point values */
vs_type.sign = TRUE; /* values are signed */
vs_type.norm = FALSE; /* values are not limited to [0,1] or [-1,1] */
vs_type.width = 32; /* 32-bit float */
vs_type.length = vector_length;
 
/* hold temporary "bool" clipmask */
clipmask_bool_ptr = lp_build_alloca(gallivm, lp_build_int_vec_type(gallivm, vs_type), "");
LLVMBuildStore(builder, lp_build_zero(gallivm, lp_int_type(vs_type)), clipmask_bool_ptr);
 
/* code generated texture sampling */
sampler = draw_llvm_sampler_soa_create(
draw_llvm_variant_key_samplers(key),
context_ptr);
 
if (elts) {
start = zero;
end = fetch_count;
count = fetch_count;
}
else {
end = lp_build_add(&bld, start, count);
}
 
step = lp_build_const_int32(gallivm, vector_length);
 
fetch_max = LLVMBuildSub(builder, end, one, "fetch_max");
 
lp_build_loop_begin(&lp_loop, gallivm, zero);
{
LLVMValueRef inputs[PIPE_MAX_SHADER_INPUTS][TGSI_NUM_CHANNELS];
LLVMValueRef aos_attribs[PIPE_MAX_SHADER_INPUTS][LP_MAX_VECTOR_WIDTH / 32] = { { 0 } };
LLVMValueRef io;
LLVMValueRef clipmask; /* holds the clipmask value */
const LLVMValueRef (*ptr_aos)[TGSI_NUM_CHANNELS];
 
io_itr = lp_loop.counter;
 
io = LLVMBuildGEP(builder, io_ptr, &io_itr, 1, "");
#if DEBUG_STORE
lp_build_printf(gallivm, " --- io %d = %p, loop counter %d\n",
io_itr, io, lp_loop.counter);
#endif
system_values.vertex_id = lp_build_zero(gallivm, lp_type_uint_vec(32, 32*vector_length));
for (i = 0; i < vector_length; ++i) {
LLVMValueRef true_index =
LLVMBuildAdd(builder,
lp_loop.counter,
lp_build_const_int32(gallivm, i), "");
true_index = LLVMBuildAdd(builder, start, true_index, "");
 
/* make sure we're not out of bounds which can happen
* if fetch_count % 4 != 0, because on the last iteration
* a few of the 4 vertex fetches will be out of bounds */
true_index = lp_build_min(&bld, true_index, fetch_max);
 
system_values.vertex_id = LLVMBuildInsertElement(
gallivm->builder,
system_values.vertex_id, true_index,
lp_build_const_int32(gallivm, i), "");
 
if (elts) {
LLVMValueRef fetch_ptr;
LLVMValueRef index_overflowed;
LLVMValueRef index_ptr =
lp_build_alloca(
gallivm,
lp_build_vec_type(gallivm, lp_type_int(32)), "");
struct lp_build_if_state if_ctx;
index_overflowed = LLVMBuildICmp(builder, LLVMIntUGT,
true_index, fetch_elt_max,
"index_overflowed");
lp_build_if(&if_ctx, gallivm, index_overflowed);
{
/* Generate maximum possible index so that
* generate_fetch can treat it just like
* any other overflow and return zeros.
* We don't have to worry about the restart
* primitive index because it has already been
* handled
*/
LLVMValueRef val =
lp_build_const_int32(gallivm, 0xffffffff);
LLVMBuildStore(builder, val, index_ptr);
}
lp_build_else(&if_ctx);
{
LLVMValueRef val;
fetch_ptr = LLVMBuildGEP(builder, fetch_elts,
&true_index, 1, "");
val = LLVMBuildLoad(builder, fetch_ptr, "");
LLVMBuildStore(builder, val, index_ptr);
}
lp_build_endif(&if_ctx);
true_index = LLVMBuildLoad(builder, index_ptr, "true_index");
}
 
for (j = 0; j < draw->pt.nr_vertex_elements; ++j) {
struct pipe_vertex_element *velem = &draw->pt.vertex_element[j];
LLVMValueRef vb_index =
lp_build_const_int32(gallivm, velem->vertex_buffer_index);
LLVMValueRef vb = LLVMBuildGEP(builder, vb_ptr, &vb_index, 1, "");
generate_fetch(gallivm, draw, vbuffers_ptr,
&aos_attribs[j][i], velem, vb, true_index,
system_values.instance_id);
}
}
convert_to_soa(gallivm, aos_attribs, inputs,
draw->pt.nr_vertex_elements, vs_type);
 
ptr_aos = (const LLVMValueRef (*)[TGSI_NUM_CHANNELS]) inputs;
generate_vs(variant,
builder,
vs_type,
outputs,
ptr_aos,
&system_values,
context_ptr,
sampler,
key->clamp_vertex_color);
 
if (pos != -1 && cv != -1) {
/* store original positions in clip before further manipulation */
store_clip(gallivm, vs_type, io, outputs, 0, cv);
store_clip(gallivm, vs_type, io, outputs, 1, pos);
 
/* do cliptest */
if (enable_cliptest) {
LLVMValueRef temp = LLVMBuildLoad(builder, clipmask_bool_ptr, "");
/* allocate clipmask, assign it integer type */
clipmask = generate_clipmask(llvm,
gallivm,
vs_type,
outputs,
key->clip_xy,
key->clip_z,
key->clip_user,
key->clip_halfz,
key->ucp_enable,
context_ptr, &have_clipdist);
temp = LLVMBuildOr(builder, clipmask, temp, "");
/* store temporary clipping boolean value */
LLVMBuildStore(builder, temp, clipmask_bool_ptr);
}
else {
clipmask = lp_build_const_int_vec(gallivm, lp_int_type(vs_type), 0);
}
 
/* do viewport mapping */
if (!bypass_viewport) {
generate_viewport(variant, builder, vs_type, outputs, context_ptr);
}
}
else {
clipmask = lp_build_const_int_vec(gallivm, lp_int_type(vs_type), 0);
}
 
/* store clipmask in vertex header,
* original positions in clip
* and transformed positions in data
*/
convert_to_aos(gallivm, io, NULL, outputs, clipmask,
vs_info->num_outputs, vs_type,
have_clipdist);
}
lp_build_loop_end_cond(&lp_loop, count, step, LLVMIntUGE);
 
sampler->destroy(sampler);
 
/* return clipping boolean value for function */
ret = clipmask_booli32(gallivm, vs_type, clipmask_bool_ptr);
 
LLVMBuildRet(builder, ret);
 
gallivm_verify_function(gallivm, variant_func);
}
 
 
struct draw_llvm_variant_key *
draw_llvm_make_variant_key(struct draw_llvm *llvm, char *store)
{
unsigned i;
struct draw_llvm_variant_key *key;
struct draw_sampler_static_state *draw_sampler;
 
key = (struct draw_llvm_variant_key *)store;
 
key->clamp_vertex_color = llvm->draw->rasterizer->clamp_vertex_color; /**/
 
/* Presumably all variants of the shader should have the same
* number of vertex elements - ie the number of shader inputs.
* NOTE: we NEED to store the needed number of needed inputs
* here, not the number of provided elements to match keysize
* (and the offset of sampler state in the key).
*/
key->nr_vertex_elements = llvm->draw->vs.vertex_shader->info.file_max[TGSI_FILE_INPUT] + 1;
assert(key->nr_vertex_elements <= llvm->draw->pt.nr_vertex_elements);
 
/* will have to rig this up properly later */
key->clip_xy = llvm->draw->clip_xy;
key->clip_z = llvm->draw->clip_z;
key->clip_user = llvm->draw->clip_user;
key->bypass_viewport = llvm->draw->identity_viewport;
key->clip_halfz = llvm->draw->rasterizer->clip_halfz;
key->need_edgeflags = (llvm->draw->vs.edgeflag_output ? TRUE : FALSE);
key->ucp_enable = llvm->draw->rasterizer->clip_plane_enable;
key->has_gs = llvm->draw->gs.geometry_shader != NULL;
key->pad1 = 0;
 
/* All variants of this shader will have the same value for
* nr_samplers. Not yet trying to compact away holes in the
* sampler array.
*/
key->nr_samplers = llvm->draw->vs.vertex_shader->info.file_max[TGSI_FILE_SAMPLER] + 1;
if (llvm->draw->vs.vertex_shader->info.file_max[TGSI_FILE_SAMPLER_VIEW] != -1) {
key->nr_sampler_views =
llvm->draw->vs.vertex_shader->info.file_max[TGSI_FILE_SAMPLER_VIEW] + 1;
}
else {
key->nr_sampler_views = key->nr_samplers;
}
 
draw_sampler = draw_llvm_variant_key_samplers(key);
 
memcpy(key->vertex_element,
llvm->draw->pt.vertex_element,
sizeof(struct pipe_vertex_element) * key->nr_vertex_elements);
 
memset(draw_sampler, 0, MAX2(key->nr_samplers, key->nr_sampler_views) * sizeof *draw_sampler);
 
for (i = 0 ; i < key->nr_samplers; i++) {
lp_sampler_static_sampler_state(&draw_sampler[i].sampler_state,
llvm->draw->samplers[PIPE_SHADER_VERTEX][i]);
}
for (i = 0 ; i < key->nr_sampler_views; i++) {
lp_sampler_static_texture_state(&draw_sampler[i].texture_state,
llvm->draw->sampler_views[PIPE_SHADER_VERTEX][i]);
}
 
return key;
}
 
 
void
draw_llvm_dump_variant_key(struct draw_llvm_variant_key *key)
{
unsigned i;
struct draw_sampler_static_state *sampler = draw_llvm_variant_key_samplers(key);
 
debug_printf("clamp_vertex_color = %u\n", key->clamp_vertex_color);
debug_printf("clip_xy = %u\n", key->clip_xy);
debug_printf("clip_z = %u\n", key->clip_z);
debug_printf("clip_user = %u\n", key->clip_user);
debug_printf("bypass_viewport = %u\n", key->bypass_viewport);
debug_printf("clip_halfz = %u\n", key->clip_halfz);
debug_printf("need_edgeflags = %u\n", key->need_edgeflags);
debug_printf("has_gs = %u\n", key->has_gs);
debug_printf("ucp_enable = %u\n", key->ucp_enable);
 
for (i = 0 ; i < key->nr_vertex_elements; i++) {
debug_printf("vertex_element[%i].src_offset = %u\n", i, key->vertex_element[i].src_offset);
debug_printf("vertex_element[%i].instance_divisor = %u\n", i, key->vertex_element[i].instance_divisor);
debug_printf("vertex_element[%i].vertex_buffer_index = %u\n", i, key->vertex_element[i].vertex_buffer_index);
debug_printf("vertex_element[%i].src_format = %s\n", i, util_format_name(key->vertex_element[i].src_format));
}
 
for (i = 0 ; i < key->nr_sampler_views; i++) {
debug_printf("sampler[%i].src_format = %s\n", i, util_format_name(sampler[i].texture_state.format));
}
}
 
 
void
draw_llvm_set_mapped_texture(struct draw_context *draw,
unsigned shader_stage,
unsigned sview_idx,
uint32_t width, uint32_t height, uint32_t depth,
uint32_t first_level, uint32_t last_level,
const void *base_ptr,
uint32_t row_stride[PIPE_MAX_TEXTURE_LEVELS],
uint32_t img_stride[PIPE_MAX_TEXTURE_LEVELS],
uint32_t mip_offsets[PIPE_MAX_TEXTURE_LEVELS])
{
unsigned j;
struct draw_jit_texture *jit_tex;
 
assert(shader_stage == PIPE_SHADER_VERTEX ||
shader_stage == PIPE_SHADER_GEOMETRY);
 
if (shader_stage == PIPE_SHADER_VERTEX) {
assert(sview_idx < Elements(draw->llvm->jit_context.textures));
 
jit_tex = &draw->llvm->jit_context.textures[sview_idx];
} else if (shader_stage == PIPE_SHADER_GEOMETRY) {
assert(sview_idx < Elements(draw->llvm->gs_jit_context.textures));
 
jit_tex = &draw->llvm->gs_jit_context.textures[sview_idx];
} else {
assert(0);
return;
}
 
jit_tex->width = width;
jit_tex->height = height;
jit_tex->depth = depth;
jit_tex->first_level = first_level;
jit_tex->last_level = last_level;
jit_tex->base = base_ptr;
 
for (j = first_level; j <= last_level; j++) {
jit_tex->mip_offsets[j] = mip_offsets[j];
jit_tex->row_stride[j] = row_stride[j];
jit_tex->img_stride[j] = img_stride[j];
}
}
 
 
void
draw_llvm_set_sampler_state(struct draw_context *draw,
unsigned shader_type)
{
unsigned i;
 
if (shader_type == PIPE_SHADER_VERTEX) {
for (i = 0; i < draw->num_samplers[PIPE_SHADER_VERTEX]; i++) {
struct draw_jit_sampler *jit_sam = &draw->llvm->jit_context.samplers[i];
 
if (draw->samplers[i]) {
const struct pipe_sampler_state *s
= draw->samplers[PIPE_SHADER_VERTEX][i];
jit_sam->min_lod = s->min_lod;
jit_sam->max_lod = s->max_lod;
jit_sam->lod_bias = s->lod_bias;
COPY_4V(jit_sam->border_color, s->border_color.f);
}
}
} else if (shader_type == PIPE_SHADER_GEOMETRY) {
for (i = 0; i < draw->num_samplers[PIPE_SHADER_GEOMETRY]; i++) {
struct draw_jit_sampler *jit_sam = &draw->llvm->gs_jit_context.samplers[i];
 
if (draw->samplers[i]) {
const struct pipe_sampler_state *s
= draw->samplers[PIPE_SHADER_GEOMETRY][i];
jit_sam->min_lod = s->min_lod;
jit_sam->max_lod = s->max_lod;
jit_sam->lod_bias = s->lod_bias;
COPY_4V(jit_sam->border_color, s->border_color.f);
}
}
}
}
 
 
void
draw_llvm_destroy_variant(struct draw_llvm_variant *variant)
{
struct draw_llvm *llvm = variant->llvm;
 
if (variant->function_elts) {
gallivm_free_function(variant->gallivm,
variant->function_elts, variant->jit_func_elts);
}
 
if (variant->function) {
gallivm_free_function(variant->gallivm,
variant->function, variant->jit_func);
}
 
gallivm_destroy(variant->gallivm);
 
remove_from_list(&variant->list_item_local);
variant->shader->variants_cached--;
remove_from_list(&variant->list_item_global);
llvm->nr_variants--;
FREE(variant);
}
 
 
/**
* Create LLVM types for various structures.
*/
static void
create_gs_jit_types(struct draw_gs_llvm_variant *var)
{
struct gallivm_state *gallivm = var->gallivm;
LLVMTypeRef texture_type, sampler_type, context_type;
 
texture_type = create_jit_texture_type(gallivm, "texture");
sampler_type = create_jit_sampler_type(gallivm, "sampler");
 
context_type = create_gs_jit_context_type(gallivm,
var->shader->base.vector_length,
texture_type, sampler_type,
"draw_gs_jit_context");
var->context_ptr_type = LLVMPointerType(context_type, 0);
 
var->input_array_type = create_gs_jit_input_type(gallivm);
}
 
static LLVMTypeRef
get_gs_context_ptr_type(struct draw_gs_llvm_variant *variant)
{
if (!variant->context_ptr_type)
create_gs_jit_types(variant);
return variant->context_ptr_type;
}
 
static LLVMValueRef
generate_mask_value(struct draw_gs_llvm_variant *variant,
struct lp_type gs_type)
{
struct gallivm_state *gallivm = variant->gallivm;
LLVMBuilderRef builder = gallivm->builder;
LLVMValueRef bits[16];
struct lp_type mask_type = lp_int_type(gs_type);
struct lp_type mask_elem_type = lp_elem_type(mask_type);
LLVMValueRef mask_val = lp_build_const_vec(gallivm,
mask_type,
0);
unsigned i;
 
assert(gs_type.length <= Elements(bits));
 
for (i = gs_type.length; i >= 1; --i) {
int idx = i - 1;
LLVMValueRef ind = lp_build_const_int32(gallivm, i);
bits[idx] = lp_build_compare(gallivm,
mask_elem_type, PIPE_FUNC_GEQUAL,
variant->num_prims, ind);
}
for (i = 0; i < gs_type.length; ++i) {
LLVMValueRef ind = lp_build_const_int32(gallivm, i);
mask_val = LLVMBuildInsertElement(builder, mask_val, bits[i], ind, "");
}
mask_val = lp_build_compare(gallivm,
mask_type, PIPE_FUNC_NOTEQUAL,
mask_val,
lp_build_const_int_vec(gallivm, mask_type, 0));
 
return mask_val;
}
 
static void
draw_gs_llvm_generate(struct draw_llvm *llvm,
struct draw_gs_llvm_variant *variant)
{
struct gallivm_state *gallivm = variant->gallivm;
LLVMContextRef context = gallivm->context;
LLVMTypeRef int32_type = LLVMInt32TypeInContext(context);
LLVMTypeRef arg_types[6];
LLVMTypeRef func_type;
LLVMValueRef variant_func;
LLVMValueRef context_ptr;
LLVMValueRef prim_id_ptr;
LLVMBasicBlockRef block;
LLVMBuilderRef builder;
LLVMValueRef io_ptr, input_array, num_prims, mask_val;
struct lp_build_sampler_soa *sampler = 0;
struct lp_build_context bld;
struct lp_bld_tgsi_system_values system_values;
struct lp_type gs_type;
unsigned i;
struct draw_gs_llvm_iface gs_iface;
const struct tgsi_token *tokens = variant->shader->base.state.tokens;
LLVMValueRef consts_ptr;
LLVMValueRef outputs[PIPE_MAX_SHADER_OUTPUTS][TGSI_NUM_CHANNELS];
struct lp_build_mask_context mask;
const struct tgsi_shader_info *gs_info = &variant->shader->base.info;
unsigned vector_length = variant->shader->base.vector_length;
 
memset(&system_values, 0, sizeof(system_values));
 
assert(variant->vertex_header_ptr_type);
 
arg_types[0] = get_gs_context_ptr_type(variant); /* context */
arg_types[1] = variant->input_array_type; /* input */
arg_types[2] = variant->vertex_header_ptr_type; /* vertex_header */
arg_types[3] = int32_type; /* num_prims */
arg_types[4] = int32_type; /* instance_id */
arg_types[5] = LLVMPointerType(
LLVMVectorType(int32_type, vector_length), 0); /* prim_id_ptr */
 
func_type = LLVMFunctionType(int32_type, arg_types, Elements(arg_types), 0);
 
variant_func = LLVMAddFunction(gallivm->module, "draw_geometry_shader",
func_type);
variant->function = variant_func;
 
LLVMSetFunctionCallConv(variant_func, LLVMCCallConv);
 
for (i = 0; i < Elements(arg_types); ++i)
if (LLVMGetTypeKind(arg_types[i]) == LLVMPointerTypeKind)
LLVMAddAttribute(LLVMGetParam(variant_func, i),
LLVMNoAliasAttribute);
 
context_ptr = LLVMGetParam(variant_func, 0);
input_array = LLVMGetParam(variant_func, 1);
io_ptr = LLVMGetParam(variant_func, 2);
num_prims = LLVMGetParam(variant_func, 3);
system_values.instance_id = LLVMGetParam(variant_func, 4);
prim_id_ptr = LLVMGetParam(variant_func, 5);
 
lp_build_name(context_ptr, "context");
lp_build_name(input_array, "input");
lp_build_name(io_ptr, "io");
lp_build_name(num_prims, "num_prims");
lp_build_name(system_values.instance_id, "instance_id");
lp_build_name(prim_id_ptr, "prim_id_ptr");
 
variant->context_ptr = context_ptr;
variant->io_ptr = io_ptr;
variant->num_prims = num_prims;
 
gs_iface.base.fetch_input = draw_gs_llvm_fetch_input;
gs_iface.base.emit_vertex = draw_gs_llvm_emit_vertex;
gs_iface.base.end_primitive = draw_gs_llvm_end_primitive;
gs_iface.base.gs_epilogue = draw_gs_llvm_epilogue;
gs_iface.input = input_array;
gs_iface.variant = variant;
 
/*
* Function body
*/
 
block = LLVMAppendBasicBlockInContext(gallivm->context, variant_func, "entry");
builder = gallivm->builder;
LLVMPositionBuilderAtEnd(builder, block);
 
lp_build_context_init(&bld, gallivm, lp_type_int(32));
 
memset(&gs_type, 0, sizeof gs_type);
gs_type.floating = TRUE; /* floating point values */
gs_type.sign = TRUE; /* values are signed */
gs_type.norm = FALSE; /* values are not limited to [0,1] or [-1,1] */
gs_type.width = 32; /* 32-bit float */
gs_type.length = vector_length;
 
consts_ptr = draw_gs_jit_context_constants(variant->gallivm, context_ptr);
 
/* code generated texture sampling */
sampler = draw_llvm_sampler_soa_create(variant->key.samplers,
context_ptr);
 
mask_val = generate_mask_value(variant, gs_type);
lp_build_mask_begin(&mask, gallivm, gs_type, mask_val);
 
if (gs_info->uses_primid) {
system_values.prim_id = LLVMBuildLoad(builder, prim_id_ptr, "prim_id");;
}
 
lp_build_tgsi_soa(variant->gallivm,
tokens,
gs_type,
&mask,
consts_ptr,
&system_values,
NULL,
outputs,
sampler,
&llvm->draw->gs.geometry_shader->info,
(const struct lp_build_tgsi_gs_iface *)&gs_iface);
 
sampler->destroy(sampler);
 
lp_build_mask_end(&mask);
 
LLVMBuildRet(builder, lp_build_zero(gallivm, lp_type_uint(32)));
 
gallivm_verify_function(gallivm, variant_func);
}
 
 
struct draw_gs_llvm_variant *
draw_gs_llvm_create_variant(struct draw_llvm *llvm,
unsigned num_outputs,
const struct draw_gs_llvm_variant_key *key)
{
struct draw_gs_llvm_variant *variant;
struct llvm_geometry_shader *shader =
llvm_geometry_shader(llvm->draw->gs.geometry_shader);
LLVMTypeRef vertex_header;
 
variant = MALLOC(sizeof *variant +
shader->variant_key_size -
sizeof variant->key);
if (variant == NULL)
return NULL;
 
variant->llvm = llvm;
variant->shader = shader;
 
variant->gallivm = gallivm_create();
 
create_gs_jit_types(variant);
 
memcpy(&variant->key, key, shader->variant_key_size);
 
vertex_header = create_jit_vertex_header(variant->gallivm, num_outputs);
 
variant->vertex_header_ptr_type = LLVMPointerType(vertex_header, 0);
 
draw_gs_llvm_generate(llvm, variant);
 
gallivm_compile_module(variant->gallivm);
 
variant->jit_func = (draw_gs_jit_func)
gallivm_jit_function(variant->gallivm, variant->function);
 
variant->list_item_global.base = variant;
variant->list_item_local.base = variant;
/*variant->no = */shader->variants_created++;
variant->list_item_global.base = variant;
 
return variant;
}
 
void
draw_gs_llvm_destroy_variant(struct draw_gs_llvm_variant *variant)
{
struct draw_llvm *llvm = variant->llvm;
 
if (variant->function) {
gallivm_free_function(variant->gallivm,
variant->function, variant->jit_func);
}
 
gallivm_destroy(variant->gallivm);
 
remove_from_list(&variant->list_item_local);
variant->shader->variants_cached--;
remove_from_list(&variant->list_item_global);
llvm->nr_gs_variants--;
FREE(variant);
}
 
struct draw_gs_llvm_variant_key *
draw_gs_llvm_make_variant_key(struct draw_llvm *llvm, char *store)
{
unsigned i;
struct draw_gs_llvm_variant_key *key;
struct draw_sampler_static_state *draw_sampler;
 
key = (struct draw_gs_llvm_variant_key *)store;
 
/* All variants of this shader will have the same value for
* nr_samplers. Not yet trying to compact away holes in the
* sampler array.
*/
key->nr_samplers = llvm->draw->gs.geometry_shader->info.file_max[TGSI_FILE_SAMPLER] + 1;
if (llvm->draw->gs.geometry_shader->info.file_max[TGSI_FILE_SAMPLER_VIEW] != -1) {
key->nr_sampler_views =
llvm->draw->gs.geometry_shader->info.file_max[TGSI_FILE_SAMPLER_VIEW] + 1;
}
else {
key->nr_sampler_views = key->nr_samplers;
}
 
draw_sampler = key->samplers;
 
memset(draw_sampler, 0, MAX2(key->nr_samplers, key->nr_sampler_views) * sizeof *draw_sampler);
 
for (i = 0 ; i < key->nr_samplers; i++) {
lp_sampler_static_sampler_state(&draw_sampler[i].sampler_state,
llvm->draw->samplers[PIPE_SHADER_GEOMETRY][i]);
}
for (i = 0 ; i < key->nr_sampler_views; i++) {
lp_sampler_static_texture_state(&draw_sampler[i].texture_state,
llvm->draw->sampler_views[PIPE_SHADER_GEOMETRY][i]);
}
 
return key;
}
 
void
draw_gs_llvm_dump_variant_key(struct draw_gs_llvm_variant_key *key)
{
unsigned i;
struct draw_sampler_static_state *sampler = key->samplers;
 
for (i = 0 ; i < key->nr_sampler_views; i++) {
debug_printf("sampler[%i].src_format = %s\n", i,
util_format_name(sampler[i].texture_state.format));
}
}
/drivers/video/Gallium/auxiliary/draw/draw_llvm.h
0,0 → 1,527
/**************************************************************************
*
* Copyright 2010 VMware, Inc.
* 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 VMWARE 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.
*
**************************************************************************/
 
#ifndef DRAW_LLVM_H
#define DRAW_LLVM_H
 
#include "draw/draw_private.h"
 
#include "draw/draw_vs.h"
#include "draw/draw_gs.h"
 
#include "gallivm/lp_bld_sample.h"
#include "gallivm/lp_bld_limits.h"
 
#include "pipe/p_context.h"
#include "util/u_simple_list.h"
 
 
struct draw_llvm;
struct llvm_vertex_shader;
struct llvm_geometry_shader;
 
struct draw_jit_texture
{
uint32_t width;
uint32_t height;
uint32_t depth;
uint32_t first_level;
uint32_t last_level;
const void *base;
uint32_t row_stride[PIPE_MAX_TEXTURE_LEVELS];
uint32_t img_stride[PIPE_MAX_TEXTURE_LEVELS];
uint32_t mip_offsets[PIPE_MAX_TEXTURE_LEVELS];
};
 
 
struct draw_sampler_static_state
{
/*
* These attributes are effectively interleaved for more sane key handling.
* However, there might be lots of null space if the amount of samplers and
* textures isn't the same.
*/
struct lp_static_sampler_state sampler_state;
struct lp_static_texture_state texture_state;
};
 
 
struct draw_jit_sampler
{
float min_lod;
float max_lod;
float lod_bias;
float border_color[4];
};
 
 
enum {
DRAW_JIT_TEXTURE_WIDTH = 0,
DRAW_JIT_TEXTURE_HEIGHT,
DRAW_JIT_TEXTURE_DEPTH,
DRAW_JIT_TEXTURE_FIRST_LEVEL,
DRAW_JIT_TEXTURE_LAST_LEVEL,
DRAW_JIT_TEXTURE_BASE,
DRAW_JIT_TEXTURE_ROW_STRIDE,
DRAW_JIT_TEXTURE_IMG_STRIDE,
DRAW_JIT_TEXTURE_MIP_OFFSETS,
DRAW_JIT_TEXTURE_NUM_FIELDS /* number of fields above */
};
 
 
enum {
DRAW_JIT_SAMPLER_MIN_LOD,
DRAW_JIT_SAMPLER_MAX_LOD,
DRAW_JIT_SAMPLER_LOD_BIAS,
DRAW_JIT_SAMPLER_BORDER_COLOR,
DRAW_JIT_SAMPLER_NUM_FIELDS /* number of fields above */
};
 
 
enum {
DRAW_JIT_VERTEX_VERTEX_ID = 0,
DRAW_JIT_VERTEX_CLIP,
DRAW_JIT_VERTEX_PRE_CLIP_POS,
DRAW_JIT_VERTEX_DATA
};
 
/**
* This structure is passed directly to the generated vertex shader.
*
* It contains the derived state.
*
* Changes here must be reflected in the draw_jit_context_* macros.
* Changes to the ordering should be avoided.
*
* Only use types with a clear size and padding here, in particular prefer the
* stdint.h types to the basic integer types.
*/
struct draw_jit_context
{
const float *vs_constants[LP_MAX_TGSI_CONST_BUFFERS];
float (*planes) [DRAW_TOTAL_CLIP_PLANES][4];
float *viewport;
 
struct draw_jit_texture textures[PIPE_MAX_SHADER_SAMPLER_VIEWS];
struct draw_jit_sampler samplers[PIPE_MAX_SAMPLERS];
};
 
enum {
DRAW_JIT_CTX_CONSTANTS = 0,
DRAW_JIT_CTX_PLANES = 1,
DRAW_JIT_CTX_VIEWPORT = 2,
DRAW_JIT_CTX_TEXTURES = 3,
DRAW_JIT_CTX_SAMPLERS = 4,
DRAW_JIT_CTX_NUM_FIELDS
};
 
#define draw_jit_context_vs_constants(_gallivm, _ptr) \
lp_build_struct_get_ptr(_gallivm, _ptr, DRAW_JIT_CTX_CONSTANTS, "vs_constants")
 
#define draw_jit_context_planes(_gallivm, _ptr) \
lp_build_struct_get(_gallivm, _ptr, DRAW_JIT_CTX_PLANES, "planes")
 
#define draw_jit_context_viewport(_gallivm, _ptr) \
lp_build_struct_get(_gallivm, _ptr, DRAW_JIT_CTX_VIEWPORT, "viewport")
 
#define draw_jit_context_textures(_gallivm, _ptr) \
lp_build_struct_get_ptr(_gallivm, _ptr, DRAW_JIT_CTX_TEXTURES, "textures")
 
#define draw_jit_context_samplers(_gallivm, _ptr) \
lp_build_struct_get_ptr(_gallivm, _ptr, DRAW_JIT_CTX_SAMPLERS, "samplers")
 
#define draw_jit_header_id(_gallivm, _ptr) \
lp_build_struct_get_ptr(_gallivm, _ptr, DRAW_JIT_VERTEX_VERTEX_ID, "id")
 
#define draw_jit_header_clip(_gallivm, _ptr) \
lp_build_struct_get_ptr(_gallivm, _ptr, DRAW_JIT_VERTEX_CLIP, "clip")
 
#define draw_jit_header_pre_clip_pos(_gallivm, _ptr) \
lp_build_struct_get_ptr(_gallivm, _ptr, DRAW_JIT_VERTEX_PRE_CLIP_POS, "pre_clip_pos")
 
#define draw_jit_header_data(_gallivm, _ptr) \
lp_build_struct_get_ptr(_gallivm, _ptr, DRAW_JIT_VERTEX_DATA, "data")
 
 
#define draw_jit_vbuffer_stride(_gallivm, _ptr) \
lp_build_struct_get(_gallivm, _ptr, 0, "stride")
 
#define draw_jit_vbuffer_offset(_gallivm, _ptr) \
lp_build_struct_get(_gallivm, _ptr, 1, "buffer_offset")
 
enum {
DRAW_JIT_DVBUFFER_MAP = 0,
DRAW_JIT_DVBUFFER_SIZE,
DRAW_JIT_DVBUFFER_NUM_FIELDS /* number of fields above */
};
 
#define draw_jit_dvbuffer_map(_gallivm, _ptr) \
lp_build_struct_get(_gallivm, _ptr, DRAW_JIT_DVBUFFER_MAP, "map")
 
#define draw_jit_dvbuffer_size(_gallivm, _ptr) \
lp_build_struct_get(_gallivm, _ptr, DRAW_JIT_DVBUFFER_SIZE, "size")
 
 
/**
* This structure is passed directly to the generated geometry shader.
*
* It contains the derived state.
*
* Changes here must be reflected in the draw_gs_jit_context_* macros.
* Changes to the ordering should be avoided.
*
* Only use types with a clear size and padding here, in particular prefer the
* stdint.h types to the basic integer types.
*/
struct draw_gs_jit_context
{
const float *constants[LP_MAX_TGSI_CONST_BUFFERS];
float (*planes) [DRAW_TOTAL_CLIP_PLANES][4];
float *viewport;
 
/* There two need to be exactly at DRAW_JIT_CTX_TEXTURES and
* DRAW_JIT_CTX_SAMPLERS positions in the struct */
struct draw_jit_texture textures[PIPE_MAX_SHADER_SAMPLER_VIEWS];
struct draw_jit_sampler samplers[PIPE_MAX_SAMPLERS];
int **prim_lengths;
int *emitted_vertices;
int *emitted_prims;
};
 
enum {
DRAW_GS_JIT_CTX_CONSTANTS = 0,
DRAW_GS_JIT_CTX_PLANES = 1,
DRAW_GS_JIT_CTX_VIEWPORT = 2,
/* Textures and samples are reserved for DRAW_JIT_CTX_TEXTURES
* and DRAW_JIT_CTX_SAMPLERS, because they both need
* to be at exactly the same locations as they are in the
* VS ctx structure for sampling to work. */
DRAW_GS_JIT_CTX_TEXTURES = DRAW_JIT_CTX_TEXTURES,
DRAW_GS_JIT_CTX_SAMPLERS = DRAW_JIT_CTX_SAMPLERS,
DRAW_GS_JIT_CTX_PRIM_LENGTHS = 5,
DRAW_GS_JIT_CTX_EMITTED_VERTICES = 6,
DRAW_GS_JIT_CTX_EMITTED_PRIMS = 7,
DRAW_GS_JIT_CTX_NUM_FIELDS = 8
};
 
#define draw_gs_jit_context_constants(_gallivm, _ptr) \
lp_build_struct_get_ptr(_gallivm, _ptr, DRAW_GS_JIT_CTX_CONSTANTS, "constants")
 
#define draw_gs_jit_context_planes(_gallivm, _ptr) \
lp_build_struct_get(_gallivm, _ptr, DRAW_GS_JIT_CTX_PLANES, "planes")
 
#define draw_gs_jit_context_viewport(_gallivm, _ptr) \
lp_build_struct_get(_gallivm, _ptr, DRAW_GS_JIT_CTX_VIEWPORT, "viewport")
 
#define draw_gs_jit_context_textures(_gallivm, _ptr) \
lp_build_struct_get_ptr(_gallivm, _ptr, DRAW_GS_JIT_CTX_TEXTURES, "textures")
 
#define draw_gs_jit_context_samplers(_gallivm, _ptr) \
lp_build_struct_get_ptr(_gallivm, _ptr, DRAW_GS_JIT_CTX_SAMPLERS, "samplers")
 
#define draw_gs_jit_prim_lengths(_gallivm, _ptr) \
lp_build_struct_get(_gallivm, _ptr, DRAW_GS_JIT_CTX_PRIM_LENGTHS, "prim_lengths")
 
#define draw_gs_jit_emitted_vertices(_gallivm, _ptr) \
lp_build_struct_get(_gallivm, _ptr, DRAW_GS_JIT_CTX_EMITTED_VERTICES, "emitted_vertices")
 
#define draw_gs_jit_emitted_prims(_gallivm, _ptr) \
lp_build_struct_get(_gallivm, _ptr, DRAW_GS_JIT_CTX_EMITTED_PRIMS, "emitted_prims")
 
 
 
typedef int
(*draw_jit_vert_func)(struct draw_jit_context *context,
struct vertex_header *io,
const struct draw_vertex_buffer vbuffers[PIPE_MAX_ATTRIBS],
unsigned start,
unsigned count,
unsigned stride,
struct pipe_vertex_buffer *vertex_buffers,
unsigned instance_id);
 
 
typedef int
(*draw_jit_vert_func_elts)(struct draw_jit_context *context,
struct vertex_header *io,
const struct draw_vertex_buffer vbuffers[PIPE_MAX_ATTRIBS],
const unsigned *fetch_elts,
unsigned fetch_max_elt,
unsigned fetch_count,
unsigned stride,
struct pipe_vertex_buffer *vertex_buffers,
unsigned instance_id);
 
 
typedef int
(*draw_gs_jit_func)(struct draw_gs_jit_context *context,
float inputs[6][PIPE_MAX_SHADER_INPUTS][TGSI_NUM_CHANNELS][TGSI_NUM_CHANNELS],
struct vertex_header *output,
unsigned num_prims,
unsigned instance_id,
int *prim_ids);
 
struct draw_llvm_variant_key
{
unsigned nr_vertex_elements:8;
unsigned nr_samplers:8;
unsigned nr_sampler_views:8;
unsigned clamp_vertex_color:1;
unsigned clip_xy:1;
unsigned clip_z:1;
unsigned clip_user:1;
unsigned clip_halfz:1;
unsigned bypass_viewport:1;
unsigned need_edgeflags:1;
unsigned has_gs:1;
/*
* it is important there are no holes in this struct
* (and all padding gets zeroed).
*/
unsigned ucp_enable:PIPE_MAX_CLIP_PLANES;
unsigned pad1:32-PIPE_MAX_CLIP_PLANES;
 
/* Variable number of vertex elements:
*/
struct pipe_vertex_element vertex_element[1];
 
/* Followed by variable number of samplers:
*/
/* struct draw_sampler_static_state sampler; */
};
 
struct draw_gs_llvm_variant_key
{
unsigned nr_samplers:8;
unsigned nr_sampler_views:8;
 
struct draw_sampler_static_state samplers[1];
};
 
#define DRAW_LLVM_MAX_VARIANT_KEY_SIZE \
(sizeof(struct draw_llvm_variant_key) + \
PIPE_MAX_SHADER_SAMPLER_VIEWS * sizeof(struct draw_sampler_static_state) + \
(PIPE_MAX_ATTRIBS-1) * sizeof(struct pipe_vertex_element))
 
#define DRAW_GS_LLVM_MAX_VARIANT_KEY_SIZE \
(sizeof(struct draw_gs_llvm_variant_key) + \
PIPE_MAX_SHADER_SAMPLER_VIEWS * sizeof(struct draw_sampler_static_state))
 
 
static INLINE size_t
draw_llvm_variant_key_size(unsigned nr_vertex_elements,
unsigned nr_samplers)
{
return (sizeof(struct draw_llvm_variant_key) +
nr_samplers * sizeof(struct draw_sampler_static_state) +
(nr_vertex_elements - 1) * sizeof(struct pipe_vertex_element));
}
 
 
static INLINE size_t
draw_gs_llvm_variant_key_size(unsigned nr_samplers)
{
return (sizeof(struct draw_gs_llvm_variant_key) +
(nr_samplers - 1) * sizeof(struct draw_sampler_static_state));
}
 
 
static INLINE struct draw_sampler_static_state *
draw_llvm_variant_key_samplers(struct draw_llvm_variant_key *key)
{
return (struct draw_sampler_static_state *)
&key->vertex_element[key->nr_vertex_elements];
}
 
 
struct draw_llvm_variant_list_item
{
struct draw_llvm_variant *base;
struct draw_llvm_variant_list_item *next, *prev;
};
 
struct draw_gs_llvm_variant_list_item
{
struct draw_gs_llvm_variant *base;
struct draw_gs_llvm_variant_list_item *next, *prev;
};
 
 
struct draw_llvm_variant
{
struct gallivm_state *gallivm;
 
/* LLVM JIT builder types */
LLVMTypeRef context_ptr_type;
LLVMTypeRef buffer_ptr_type;
LLVMTypeRef vb_ptr_type;
LLVMTypeRef vertex_header_ptr_type;
 
LLVMValueRef function;
LLVMValueRef function_elts;
draw_jit_vert_func jit_func;
draw_jit_vert_func_elts jit_func_elts;
 
struct llvm_vertex_shader *shader;
 
struct draw_llvm *llvm;
struct draw_llvm_variant_list_item list_item_global;
struct draw_llvm_variant_list_item list_item_local;
 
/* key is variable-sized, must be last */
struct draw_llvm_variant_key key;
};
 
 
struct draw_gs_llvm_variant
{
struct gallivm_state *gallivm;
 
/* LLVM JIT builder types */
LLVMTypeRef context_ptr_type;
LLVMTypeRef vertex_header_ptr_type;
LLVMTypeRef input_array_type;
 
LLVMValueRef context_ptr;
LLVMValueRef io_ptr;
LLVMValueRef num_prims;
LLVMValueRef function;
draw_gs_jit_func jit_func;
 
struct llvm_geometry_shader *shader;
 
struct draw_llvm *llvm;
struct draw_gs_llvm_variant_list_item list_item_global;
struct draw_gs_llvm_variant_list_item list_item_local;
 
/* key is variable-sized, must be last */
struct draw_gs_llvm_variant_key key;
};
 
struct llvm_vertex_shader {
struct draw_vertex_shader base;
 
unsigned variant_key_size;
struct draw_llvm_variant_list_item variants;
unsigned variants_created;
unsigned variants_cached;
};
 
struct llvm_geometry_shader {
struct draw_geometry_shader base;
 
unsigned variant_key_size;
struct draw_gs_llvm_variant_list_item variants;
unsigned variants_created;
unsigned variants_cached;
};
 
 
struct draw_llvm {
struct draw_context *draw;
 
struct draw_jit_context jit_context;
struct draw_gs_jit_context gs_jit_context;
 
struct draw_llvm_variant_list_item vs_variants_list;
int nr_variants;
 
struct draw_gs_llvm_variant_list_item gs_variants_list;
int nr_gs_variants;
};
 
 
static INLINE struct llvm_vertex_shader *
llvm_vertex_shader(struct draw_vertex_shader *vs)
{
return (struct llvm_vertex_shader *)vs;
}
 
static INLINE struct llvm_geometry_shader *
llvm_geometry_shader(struct draw_geometry_shader *gs)
{
return (struct llvm_geometry_shader *)gs;
}
 
 
 
 
struct draw_llvm *
draw_llvm_create(struct draw_context *draw);
 
void
draw_llvm_destroy(struct draw_llvm *llvm);
 
struct draw_llvm_variant *
draw_llvm_create_variant(struct draw_llvm *llvm,
unsigned num_vertex_header_attribs,
const struct draw_llvm_variant_key *key);
 
void
draw_llvm_destroy_variant(struct draw_llvm_variant *variant);
 
struct draw_llvm_variant_key *
draw_llvm_make_variant_key(struct draw_llvm *llvm, char *store);
 
void
draw_llvm_dump_variant_key(struct draw_llvm_variant_key *key);
 
 
struct draw_gs_llvm_variant *
draw_gs_llvm_create_variant(struct draw_llvm *llvm,
unsigned num_vertex_header_attribs,
const struct draw_gs_llvm_variant_key *key);
 
void
draw_gs_llvm_destroy_variant(struct draw_gs_llvm_variant *variant);
 
struct draw_gs_llvm_variant_key *
draw_gs_llvm_make_variant_key(struct draw_llvm *llvm, char *store);
 
void
draw_gs_llvm_dump_variant_key(struct draw_gs_llvm_variant_key *key);
 
struct lp_build_sampler_soa *
draw_llvm_sampler_soa_create(const struct draw_sampler_static_state *static_state,
LLVMValueRef context_ptr);
 
void
draw_llvm_set_sampler_state(struct draw_context *draw, unsigned shader_stage);
 
void
draw_llvm_set_mapped_texture(struct draw_context *draw,
unsigned shader_stage,
unsigned sview_idx,
uint32_t width, uint32_t height, uint32_t depth,
uint32_t first_level, uint32_t last_level,
const void *base_ptr,
uint32_t row_stride[PIPE_MAX_TEXTURE_LEVELS],
uint32_t img_stride[PIPE_MAX_TEXTURE_LEVELS],
uint32_t mip_offsets[PIPE_MAX_TEXTURE_LEVELS]);
 
#endif
/drivers/video/Gallium/auxiliary/draw/draw_llvm_sample.c
0,0 → 1,322
/**************************************************************************
*
* Copyright 2010 VMware, Inc.
* 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 VMWARE 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.
*
**************************************************************************/
 
/**
* Texture sampling code generation
* @author Jose Fonseca <jfonseca@vmware.com>
*/
 
#include "pipe/p_defines.h"
#include "pipe/p_shader_tokens.h"
#include "gallivm/lp_bld_const.h"
#include "gallivm/lp_bld_debug.h"
#include "gallivm/lp_bld_type.h"
#include "gallivm/lp_bld_sample.h"
#include "gallivm/lp_bld_tgsi.h"
 
 
#include "util/u_debug.h"
#include "util/u_memory.h"
#include "util/u_pointer.h"
#include "util/u_string.h"
 
#include "draw_llvm.h"
 
 
/**
* This provides the bridge between the sampler state store in
* lp_jit_context and lp_jit_texture and the sampler code
* generator. It provides the texture layout information required by
* the texture sampler code generator in terms of the state stored in
* lp_jit_context and lp_jit_texture in runtime.
*/
struct draw_llvm_sampler_dynamic_state
{
struct lp_sampler_dynamic_state base;
 
const struct draw_sampler_static_state *static_state;
 
LLVMValueRef context_ptr;
};
 
 
/**
* This is the bridge between our sampler and the TGSI translator.
*/
struct draw_llvm_sampler_soa
{
struct lp_build_sampler_soa base;
 
struct draw_llvm_sampler_dynamic_state dynamic_state;
};
 
 
/**
* Fetch the specified member of the lp_jit_texture structure.
* \param emit_load if TRUE, emit the LLVM load instruction to actually
* fetch the field's value. Otherwise, just emit the
* GEP code to address the field.
*
* @sa http://llvm.org/docs/GetElementPtr.html
*/
static LLVMValueRef
draw_llvm_texture_member(const struct lp_sampler_dynamic_state *base,
struct gallivm_state *gallivm,
unsigned texture_unit,
unsigned member_index,
const char *member_name,
boolean emit_load)
{
LLVMBuilderRef builder = gallivm->builder;
struct draw_llvm_sampler_dynamic_state *state =
(struct draw_llvm_sampler_dynamic_state *)base;
LLVMValueRef indices[4];
LLVMValueRef ptr;
LLVMValueRef res;
 
debug_assert(texture_unit < PIPE_MAX_SHADER_SAMPLER_VIEWS);
 
/* context[0] */
indices[0] = lp_build_const_int32(gallivm, 0);
/* context[0].textures */
indices[1] = lp_build_const_int32(gallivm, DRAW_JIT_CTX_TEXTURES);
/* context[0].textures[unit] */
indices[2] = lp_build_const_int32(gallivm, texture_unit);
/* context[0].textures[unit].member */
indices[3] = lp_build_const_int32(gallivm, member_index);
 
ptr = LLVMBuildGEP(builder, state->context_ptr, indices, Elements(indices), "");
 
if (emit_load)
res = LLVMBuildLoad(builder, ptr, "");
else
res = ptr;
 
lp_build_name(res, "context.texture%u.%s", texture_unit, member_name);
 
return res;
}
 
 
/**
* Fetch the specified member of the lp_jit_sampler structure.
* \param emit_load if TRUE, emit the LLVM load instruction to actually
* fetch the field's value. Otherwise, just emit the
* GEP code to address the field.
*
* @sa http://llvm.org/docs/GetElementPtr.html
*/
static LLVMValueRef
draw_llvm_sampler_member(const struct lp_sampler_dynamic_state *base,
struct gallivm_state *gallivm,
unsigned sampler_unit,
unsigned member_index,
const char *member_name,
boolean emit_load)
{
LLVMBuilderRef builder = gallivm->builder;
struct draw_llvm_sampler_dynamic_state *state =
(struct draw_llvm_sampler_dynamic_state *)base;
LLVMValueRef indices[4];
LLVMValueRef ptr;
LLVMValueRef res;
 
debug_assert(sampler_unit < PIPE_MAX_SAMPLERS);
 
/* context[0] */
indices[0] = lp_build_const_int32(gallivm, 0);
/* context[0].samplers */
indices[1] = lp_build_const_int32(gallivm, DRAW_JIT_CTX_SAMPLERS);
/* context[0].samplers[unit] */
indices[2] = lp_build_const_int32(gallivm, sampler_unit);
/* context[0].samplers[unit].member */
indices[3] = lp_build_const_int32(gallivm, member_index);
 
ptr = LLVMBuildGEP(builder, state->context_ptr, indices, Elements(indices), "");
 
if (emit_load)
res = LLVMBuildLoad(builder, ptr, "");
else
res = ptr;
 
lp_build_name(res, "context.sampler%u.%s", sampler_unit, member_name);
 
return res;
}
 
 
/**
* Helper macro to instantiate the functions that generate the code to
* fetch the members of lp_jit_texture to fulfill the sampler code
* generator requests.
*
* This complexity is the price we have to pay to keep the texture
* sampler code generator a reusable module without dependencies to
* llvmpipe internals.
*/
#define DRAW_LLVM_TEXTURE_MEMBER(_name, _index, _emit_load) \
static LLVMValueRef \
draw_llvm_texture_##_name( const struct lp_sampler_dynamic_state *base, \
struct gallivm_state *gallivm, \
unsigned texture_unit) \
{ \
return draw_llvm_texture_member(base, gallivm, texture_unit, _index, #_name, _emit_load ); \
}
 
 
DRAW_LLVM_TEXTURE_MEMBER(width, DRAW_JIT_TEXTURE_WIDTH, TRUE)
DRAW_LLVM_TEXTURE_MEMBER(height, DRAW_JIT_TEXTURE_HEIGHT, TRUE)
DRAW_LLVM_TEXTURE_MEMBER(depth, DRAW_JIT_TEXTURE_DEPTH, TRUE)
DRAW_LLVM_TEXTURE_MEMBER(first_level,DRAW_JIT_TEXTURE_FIRST_LEVEL, TRUE)
DRAW_LLVM_TEXTURE_MEMBER(last_level, DRAW_JIT_TEXTURE_LAST_LEVEL, TRUE)
DRAW_LLVM_TEXTURE_MEMBER(base_ptr, DRAW_JIT_TEXTURE_BASE, TRUE)
DRAW_LLVM_TEXTURE_MEMBER(row_stride, DRAW_JIT_TEXTURE_ROW_STRIDE, FALSE)
DRAW_LLVM_TEXTURE_MEMBER(img_stride, DRAW_JIT_TEXTURE_IMG_STRIDE, FALSE)
DRAW_LLVM_TEXTURE_MEMBER(mip_offsets, DRAW_JIT_TEXTURE_MIP_OFFSETS, FALSE)
 
 
#define DRAW_LLVM_SAMPLER_MEMBER(_name, _index, _emit_load) \
static LLVMValueRef \
draw_llvm_sampler_##_name( const struct lp_sampler_dynamic_state *base, \
struct gallivm_state *gallivm, \
unsigned sampler_unit) \
{ \
return draw_llvm_sampler_member(base, gallivm, sampler_unit, _index, #_name, _emit_load ); \
}
 
 
DRAW_LLVM_SAMPLER_MEMBER(min_lod, DRAW_JIT_SAMPLER_MIN_LOD, TRUE)
DRAW_LLVM_SAMPLER_MEMBER(max_lod, DRAW_JIT_SAMPLER_MAX_LOD, TRUE)
DRAW_LLVM_SAMPLER_MEMBER(lod_bias, DRAW_JIT_SAMPLER_LOD_BIAS, TRUE)
DRAW_LLVM_SAMPLER_MEMBER(border_color, DRAW_JIT_SAMPLER_BORDER_COLOR, FALSE)
 
 
static void
draw_llvm_sampler_soa_destroy(struct lp_build_sampler_soa *sampler)
{
FREE(sampler);
}
 
 
/**
* Fetch filtered values from texture.
* The 'texel' parameter returns four vectors corresponding to R, G, B, A.
*/
static void
draw_llvm_sampler_soa_emit_fetch_texel(const struct lp_build_sampler_soa *base,
struct gallivm_state *gallivm,
struct lp_type type,
boolean is_fetch,
unsigned texture_index,
unsigned sampler_index,
const LLVMValueRef *coords,
const LLVMValueRef *offsets,
const struct lp_derivatives *derivs,
LLVMValueRef lod_bias, /* optional */
LLVMValueRef explicit_lod, /* optional */
boolean scalar_lod,
LLVMValueRef *texel)
{
struct draw_llvm_sampler_soa *sampler = (struct draw_llvm_sampler_soa *)base;
 
assert(texture_index < PIPE_MAX_SHADER_SAMPLER_VIEWS);
assert(sampler_index < PIPE_MAX_SAMPLERS);
 
lp_build_sample_soa(gallivm,
&sampler->dynamic_state.static_state[texture_index].texture_state,
&sampler->dynamic_state.static_state[sampler_index].sampler_state,
&sampler->dynamic_state.base,
type,
is_fetch,
texture_index,
sampler_index,
coords,
offsets,
derivs,
lod_bias, explicit_lod, scalar_lod,
texel);
}
 
 
/**
* Fetch the texture size.
*/
static void
draw_llvm_sampler_soa_emit_size_query(const struct lp_build_sampler_soa *base,
struct gallivm_state *gallivm,
struct lp_type type,
unsigned texture_unit,
boolean need_nr_mips,
LLVMValueRef explicit_lod, /* optional */
LLVMValueRef *sizes_out)
{
struct draw_llvm_sampler_soa *sampler = (struct draw_llvm_sampler_soa *)base;
 
assert(texture_unit < PIPE_MAX_SHADER_SAMPLER_VIEWS);
 
lp_build_size_query_soa(gallivm,
&sampler->dynamic_state.static_state[texture_unit].texture_state,
&sampler->dynamic_state.base,
type,
texture_unit,
need_nr_mips,
explicit_lod,
sizes_out);
}
 
struct lp_build_sampler_soa *
draw_llvm_sampler_soa_create(const struct draw_sampler_static_state *static_state,
LLVMValueRef context_ptr)
{
struct draw_llvm_sampler_soa *sampler;
 
sampler = CALLOC_STRUCT(draw_llvm_sampler_soa);
if(!sampler)
return NULL;
 
sampler->base.destroy = draw_llvm_sampler_soa_destroy;
sampler->base.emit_fetch_texel = draw_llvm_sampler_soa_emit_fetch_texel;
sampler->base.emit_size_query = draw_llvm_sampler_soa_emit_size_query;
sampler->dynamic_state.base.width = draw_llvm_texture_width;
sampler->dynamic_state.base.height = draw_llvm_texture_height;
sampler->dynamic_state.base.depth = draw_llvm_texture_depth;
sampler->dynamic_state.base.first_level = draw_llvm_texture_first_level;
sampler->dynamic_state.base.last_level = draw_llvm_texture_last_level;
sampler->dynamic_state.base.row_stride = draw_llvm_texture_row_stride;
sampler->dynamic_state.base.img_stride = draw_llvm_texture_img_stride;
sampler->dynamic_state.base.base_ptr = draw_llvm_texture_base_ptr;
sampler->dynamic_state.base.mip_offsets = draw_llvm_texture_mip_offsets;
sampler->dynamic_state.base.min_lod = draw_llvm_sampler_min_lod;
sampler->dynamic_state.base.max_lod = draw_llvm_sampler_max_lod;
sampler->dynamic_state.base.lod_bias = draw_llvm_sampler_lod_bias;
sampler->dynamic_state.base.border_color = draw_llvm_sampler_border_color;
sampler->dynamic_state.static_state = static_state;
sampler->dynamic_state.context_ptr = context_ptr;
 
return &sampler->base;
}
 
/drivers/video/Gallium/auxiliary/draw/draw_pipe.c
0,0 → 1,352
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
#include "draw/draw_private.h"
#include "draw/draw_pipe.h"
#include "util/u_debug.h"
#include "util/u_math.h"
 
 
 
boolean draw_pipeline_init( struct draw_context *draw )
{
/* create pipeline stages */
draw->pipeline.wide_line = draw_wide_line_stage( draw );
draw->pipeline.wide_point = draw_wide_point_stage( draw );
draw->pipeline.stipple = draw_stipple_stage( draw );
draw->pipeline.unfilled = draw_unfilled_stage( draw );
draw->pipeline.twoside = draw_twoside_stage( draw );
draw->pipeline.offset = draw_offset_stage( draw );
draw->pipeline.clip = draw_clip_stage( draw );
draw->pipeline.flatshade = draw_flatshade_stage( draw );
draw->pipeline.cull = draw_cull_stage( draw );
draw->pipeline.validate = draw_validate_stage( draw );
draw->pipeline.first = draw->pipeline.validate;
 
if (!draw->pipeline.wide_line ||
!draw->pipeline.wide_point ||
!draw->pipeline.stipple ||
!draw->pipeline.unfilled ||
!draw->pipeline.twoside ||
!draw->pipeline.offset ||
!draw->pipeline.clip ||
!draw->pipeline.flatshade ||
!draw->pipeline.cull ||
!draw->pipeline.validate)
return FALSE;
 
/* these defaults are oriented toward the needs of softpipe */
draw->pipeline.wide_point_threshold = 1000000.0f; /* infinity */
draw->pipeline.wide_line_threshold = 1.0f;
draw->pipeline.wide_point_sprites = FALSE;
draw->pipeline.line_stipple = TRUE;
draw->pipeline.point_sprite = TRUE;
 
return TRUE;
}
 
 
void draw_pipeline_destroy( struct draw_context *draw )
{
if (draw->pipeline.wide_line)
draw->pipeline.wide_line->destroy( draw->pipeline.wide_line );
if (draw->pipeline.wide_point)
draw->pipeline.wide_point->destroy( draw->pipeline.wide_point );
if (draw->pipeline.stipple)
draw->pipeline.stipple->destroy( draw->pipeline.stipple );
if (draw->pipeline.unfilled)
draw->pipeline.unfilled->destroy( draw->pipeline.unfilled );
if (draw->pipeline.twoside)
draw->pipeline.twoside->destroy( draw->pipeline.twoside );
if (draw->pipeline.offset)
draw->pipeline.offset->destroy( draw->pipeline.offset );
if (draw->pipeline.clip)
draw->pipeline.clip->destroy( draw->pipeline.clip );
if (draw->pipeline.flatshade)
draw->pipeline.flatshade->destroy( draw->pipeline.flatshade );
if (draw->pipeline.cull)
draw->pipeline.cull->destroy( draw->pipeline.cull );
if (draw->pipeline.validate)
draw->pipeline.validate->destroy( draw->pipeline.validate );
if (draw->pipeline.aaline)
draw->pipeline.aaline->destroy( draw->pipeline.aaline );
if (draw->pipeline.aapoint)
draw->pipeline.aapoint->destroy( draw->pipeline.aapoint );
if (draw->pipeline.pstipple)
draw->pipeline.pstipple->destroy( draw->pipeline.pstipple );
if (draw->pipeline.rasterize)
draw->pipeline.rasterize->destroy( draw->pipeline.rasterize );
}
 
 
 
/**
* Build primitive to render a point with vertex at v0.
*/
static void do_point( struct draw_context *draw,
const char *v0 )
{
struct prim_header prim;
prim.flags = 0;
prim.pad = 0;
prim.v[0] = (struct vertex_header *)v0;
 
draw->pipeline.first->point( draw->pipeline.first, &prim );
}
 
 
/**
* Build primitive to render a line with vertices at v0, v1.
* \param flags bitmask of DRAW_PIPE_EDGE_x, DRAW_PIPE_RESET_STIPPLE
*/
static void do_line( struct draw_context *draw,
ushort flags,
const char *v0,
const char *v1 )
{
struct prim_header prim;
prim.flags = flags;
prim.pad = 0;
prim.v[0] = (struct vertex_header *)v0;
prim.v[1] = (struct vertex_header *)v1;
 
draw->pipeline.first->line( draw->pipeline.first, &prim );
}
 
 
/**
* Build primitive to render a triangle with vertices at v0, v1, v2.
* \param flags bitmask of DRAW_PIPE_EDGE_x, DRAW_PIPE_RESET_STIPPLE
*/
static void do_triangle( struct draw_context *draw,
ushort flags,
char *v0,
char *v1,
char *v2 )
{
struct prim_header prim;
prim.v[0] = (struct vertex_header *)v0;
prim.v[1] = (struct vertex_header *)v1;
prim.v[2] = (struct vertex_header *)v2;
prim.flags = flags;
prim.pad = 0;
 
draw->pipeline.first->tri( draw->pipeline.first, &prim );
}
 
 
/*
* Set up macros for draw_pt_decompose.h template code.
* This code uses vertex indexes / elements.
*/
 
#define TRIANGLE(flags,i0,i1,i2) \
do { \
do_triangle( draw, \
flags, \
verts + stride * (i0), \
verts + stride * (i1), \
verts + stride * (i2) ); \
} while (0)
 
#define LINE(flags,i0,i1) \
do { \
do_line( draw, \
flags, \
verts + stride * (i0), \
verts + stride * (i1) ); \
} while (0)
 
#define POINT(i0) \
do { \
do_point( draw, verts + stride * (i0) ); \
} while (0)
 
#define GET_ELT(idx) (MIN2(elts[idx], max_index))
 
#define FUNC pipe_run_elts
#define FUNC_VARS \
struct draw_context *draw, \
unsigned prim, \
unsigned prim_flags, \
struct vertex_header *vertices, \
unsigned stride, \
const ushort *elts, \
unsigned count, \
unsigned max_index
 
#include "draw_pt_decompose.h"
 
 
 
/**
* Code to run the pipeline on a fairly arbitrary collection of vertices.
* For drawing indexed primitives.
*
* Vertex headers must be pre-initialized with the
* UNDEFINED_VERTEX_ID, this code will cause that id to become
* overwritten, so it may have to be reset if there is the intention
* to reuse the vertices.
*
* This code provides a callback to reset the vertex id's which the
* draw_vbuf.c code uses when it has to perform a flush.
*/
void draw_pipeline_run( struct draw_context *draw,
const struct draw_vertex_info *vert_info,
const struct draw_prim_info *prim_info)
{
unsigned i, start;
 
draw->pipeline.verts = (char *)vert_info->verts;
draw->pipeline.vertex_stride = vert_info->stride;
draw->pipeline.vertex_count = vert_info->count;
 
for (start = i = 0;
i < prim_info->primitive_count;
start += prim_info->primitive_lengths[i], i++)
{
const unsigned count = prim_info->primitive_lengths[i];
 
#if DEBUG
/* Warn if one of the element indexes go outside the vertex buffer */
{
unsigned max_index = 0x0, i;
/* find the largest element index */
for (i = 0; i < count; i++) {
unsigned int index = prim_info->elts[start + i];
if (index > max_index)
max_index = index;
}
if (max_index >= vert_info->count) {
debug_printf("%s: max_index (%u) outside vertex buffer (%u)\n",
__FUNCTION__,
max_index,
vert_info->count);
}
}
#endif
 
pipe_run_elts(draw,
prim_info->prim,
prim_info->flags,
vert_info->verts,
vert_info->stride,
prim_info->elts + start,
count,
vert_info->count - 1);
}
 
draw->pipeline.verts = NULL;
draw->pipeline.vertex_count = 0;
}
 
 
/*
* Set up macros for draw_pt_decompose.h template code.
* This code is for non-indexed (aka linear) rendering (no elts).
*/
 
#define TRIANGLE(flags,i0,i1,i2) \
do_triangle( draw, flags, \
verts + stride * (i0), \
verts + stride * (i1), \
verts + stride * (i2) )
 
#define LINE(flags,i0,i1) \
do_line( draw, flags, \
verts + stride * (i0), \
verts + stride * (i1) )
 
#define POINT(i0) \
do_point( draw, verts + stride * (i0) )
 
 
#define GET_ELT(idx) (idx)
 
#define FUNC pipe_run_linear
#define FUNC_VARS \
struct draw_context *draw, \
unsigned prim, \
unsigned prim_flags, \
struct vertex_header *vertices, \
unsigned stride, \
unsigned count
 
#include "draw_pt_decompose.h"
 
 
/*
* For drawing non-indexed primitives.
*/
void draw_pipeline_run_linear( struct draw_context *draw,
const struct draw_vertex_info *vert_info,
const struct draw_prim_info *prim_info)
{
unsigned i, start;
 
for (start = i = 0;
i < prim_info->primitive_count;
start += prim_info->primitive_lengths[i], i++)
{
unsigned count = prim_info->primitive_lengths[i];
char *verts = ((char*)vert_info->verts) +
(start * vert_info->stride);
 
draw->pipeline.verts = verts;
draw->pipeline.vertex_stride = vert_info->stride;
draw->pipeline.vertex_count = count;
 
assert(count <= vert_info->count);
 
pipe_run_linear(draw,
prim_info->prim,
prim_info->flags,
(struct vertex_header*)verts,
vert_info->stride,
count);
}
 
draw->pipeline.verts = NULL;
draw->pipeline.vertex_count = 0;
}
 
 
void draw_pipeline_flush( struct draw_context *draw,
unsigned flags )
{
draw->pipeline.first->flush( draw->pipeline.first, flags );
if (flags & DRAW_FLUSH_STATE_CHANGE)
draw->pipeline.first = draw->pipeline.validate;
}
/drivers/video/Gallium/auxiliary/draw/draw_pipe.h
0,0 → 1,126
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
#ifndef DRAW_PIPE_H
#define DRAW_PIPE_H
 
#include "pipe/p_compiler.h"
#include "draw_private.h" /* for sizeof(vertex_header) */
 
 
/**
* Basic info for a point/line/triangle primitive.
*/
struct prim_header {
float det; /**< front/back face determinant */
ushort flags;
ushort pad;
struct vertex_header *v[3]; /**< 1 to 3 vertex pointers */
};
 
 
 
/**
* Base class for all primitive drawing stages.
*/
struct draw_stage
{
struct draw_context *draw; /**< parent context */
 
struct draw_stage *next; /**< next stage in pipeline */
const char *name; /**< for debugging */
 
struct vertex_header **tmp; /**< temp vert storage, such as for clipping */
unsigned nr_tmps;
 
void (*point)( struct draw_stage *,
struct prim_header * );
 
void (*line)( struct draw_stage *,
struct prim_header * );
 
void (*tri)( struct draw_stage *,
struct prim_header * );
 
void (*flush)( struct draw_stage *,
unsigned flags );
 
void (*reset_stipple_counter)( struct draw_stage * );
 
void (*destroy)( struct draw_stage * );
};
 
 
extern struct draw_stage *draw_unfilled_stage( struct draw_context *context );
extern struct draw_stage *draw_twoside_stage( struct draw_context *context );
extern struct draw_stage *draw_offset_stage( struct draw_context *context );
extern struct draw_stage *draw_clip_stage( struct draw_context *context );
extern struct draw_stage *draw_flatshade_stage( struct draw_context *context );
extern struct draw_stage *draw_cull_stage( struct draw_context *context );
extern struct draw_stage *draw_stipple_stage( struct draw_context *context );
extern struct draw_stage *draw_wide_line_stage( struct draw_context *context );
extern struct draw_stage *draw_wide_point_stage( struct draw_context *context );
extern struct draw_stage *draw_validate_stage( struct draw_context *context );
 
 
extern void draw_free_temp_verts( struct draw_stage *stage );
extern boolean draw_alloc_temp_verts( struct draw_stage *stage, unsigned nr );
 
extern void draw_reset_vertex_ids( struct draw_context *draw );
 
void draw_pipe_passthrough_tri(struct draw_stage *stage, struct prim_header *header);
void draw_pipe_passthrough_line(struct draw_stage *stage, struct prim_header *header);
void draw_pipe_passthrough_point(struct draw_stage *stage, struct prim_header *header);
 
 
 
/**
* Get a writeable copy of a vertex.
* \param stage drawing stage info
* \param vert the vertex to copy (source)
* \param idx index into stage's tmp[] array to put the copy (dest)
* \return pointer to the copied vertex
*/
static INLINE struct vertex_header *
dup_vert( struct draw_stage *stage,
const struct vertex_header *vert,
unsigned idx )
{
struct vertex_header *tmp = stage->tmp[idx];
const uint vsize = sizeof(struct vertex_header)
+ stage->draw->vs.num_vs_outputs * 4 * sizeof(float);
memcpy(tmp, vert, vsize);
tmp->vertex_id = UNDEFINED_VERTEX_ID;
return tmp;
}
 
#endif
/drivers/video/Gallium/auxiliary/draw/draw_pipe_aaline.c
0,0 → 1,1009
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/**
* AA line stage: AA lines are converted to texture mapped triangles.
*
* Authors: Brian Paul
*/
 
 
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "pipe/p_shader_tokens.h"
#include "util/u_inlines.h"
 
#include "util/u_format.h"
#include "util/u_math.h"
#include "util/u_memory.h"
#include "util/u_sampler.h"
 
#include "tgsi/tgsi_transform.h"
#include "tgsi/tgsi_dump.h"
 
#include "draw_context.h"
#include "draw_private.h"
#include "draw_pipe.h"
 
 
/** Approx number of new tokens for instructions in aa_transform_inst() */
#define NUM_NEW_TOKENS 50
 
 
/**
* Size for the alpha texture used for antialiasing
*/
#define TEXTURE_SIZE_LOG2 5 /* 32 x 32 */
 
/**
* Max texture level for the alpha texture used for antialiasing
*
* Don't use the 1x1 and 2x2 mipmap levels.
*/
#define MAX_TEXTURE_LEVEL (TEXTURE_SIZE_LOG2 - 2)
 
 
/**
* Subclass of pipe_shader_state to carry extra fragment shader info.
*/
struct aaline_fragment_shader
{
struct pipe_shader_state state;
void *driver_fs;
void *aaline_fs;
uint sampler_unit;
int generic_attrib; /**< texcoord/generic used for texture */
};
 
 
/**
* Subclass of draw_stage
*/
struct aaline_stage
{
struct draw_stage stage;
 
float half_line_width;
 
/** For AA lines, this is the vertex attrib slot for the new texcoords */
uint tex_slot;
/** position, not necessarily output zero */
uint pos_slot;
 
void *sampler_cso;
struct pipe_resource *texture;
struct pipe_sampler_view *sampler_view;
uint num_samplers;
uint num_sampler_views;
 
 
/*
* Currently bound state
*/
struct aaline_fragment_shader *fs;
struct {
void *sampler[PIPE_MAX_SAMPLERS];
struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS];
} state;
 
/*
* Driver interface/override functions
*/
void * (*driver_create_fs_state)(struct pipe_context *,
const struct pipe_shader_state *);
void (*driver_bind_fs_state)(struct pipe_context *, void *);
void (*driver_delete_fs_state)(struct pipe_context *, void *);
 
void (*driver_bind_sampler_states)(struct pipe_context *, unsigned,
void **);
 
void (*driver_set_sampler_views)(struct pipe_context *,
unsigned,
struct pipe_sampler_view **);
};
 
 
 
/**
* Subclass of tgsi_transform_context, used for transforming the
* user's fragment shader to add the special AA instructions.
*/
struct aa_transform_context {
struct tgsi_transform_context base;
uint tempsUsed; /**< bitmask */
int colorOutput; /**< which output is the primary color */
uint samplersUsed; /**< bitfield of samplers used */
int freeSampler; /** an available sampler for the pstipple */
int maxInput, maxGeneric; /**< max input index found */
int colorTemp, texTemp; /**< temp registers */
boolean firstInstruction;
};
 
 
/**
* TGSI declaration transform callback.
* Look for a free sampler, a free input attrib, and two free temp regs.
*/
static void
aa_transform_decl(struct tgsi_transform_context *ctx,
struct tgsi_full_declaration *decl)
{
struct aa_transform_context *aactx = (struct aa_transform_context *) ctx;
 
if (decl->Declaration.File == TGSI_FILE_OUTPUT &&
decl->Semantic.Name == TGSI_SEMANTIC_COLOR &&
decl->Semantic.Index == 0) {
aactx->colorOutput = decl->Range.First;
}
else if (decl->Declaration.File == TGSI_FILE_SAMPLER) {
uint i;
for (i = decl->Range.First;
i <= decl->Range.Last; i++) {
aactx->samplersUsed |= 1 << i;
}
}
else if (decl->Declaration.File == TGSI_FILE_INPUT) {
if ((int) decl->Range.Last > aactx->maxInput)
aactx->maxInput = decl->Range.Last;
if (decl->Semantic.Name == TGSI_SEMANTIC_GENERIC &&
(int) decl->Semantic.Index > aactx->maxGeneric) {
aactx->maxGeneric = decl->Semantic.Index;
}
}
else if (decl->Declaration.File == TGSI_FILE_TEMPORARY) {
uint i;
for (i = decl->Range.First;
i <= decl->Range.Last; i++) {
aactx->tempsUsed |= (1 << i);
}
}
 
ctx->emit_declaration(ctx, decl);
}
 
 
/**
* Find the lowest zero bit in the given word, or -1 if bitfield is all ones.
*/
static int
free_bit(uint bitfield)
{
return ffs(~bitfield) - 1;
}
 
 
/**
* TGSI instruction transform callback.
* Replace writes to result.color w/ a temp reg.
* Upon END instruction, insert texture sampling code for antialiasing.
*/
static void
aa_transform_inst(struct tgsi_transform_context *ctx,
struct tgsi_full_instruction *inst)
{
struct aa_transform_context *aactx = (struct aa_transform_context *) ctx;
 
if (aactx->firstInstruction) {
/* emit our new declarations before the first instruction */
 
struct tgsi_full_declaration decl;
uint i;
 
/* find free sampler */
aactx->freeSampler = free_bit(aactx->samplersUsed);
if (aactx->freeSampler >= PIPE_MAX_SAMPLERS)
aactx->freeSampler = PIPE_MAX_SAMPLERS - 1;
 
/* find two free temp regs */
for (i = 0; i < 32; i++) {
if ((aactx->tempsUsed & (1 << i)) == 0) {
/* found a free temp */
if (aactx->colorTemp < 0)
aactx->colorTemp = i;
else if (aactx->texTemp < 0)
aactx->texTemp = i;
else
break;
}
}
assert(aactx->colorTemp >= 0);
assert(aactx->texTemp >= 0);
 
/* declare new generic input/texcoord */
decl = tgsi_default_full_declaration();
decl.Declaration.File = TGSI_FILE_INPUT;
/* XXX this could be linear... */
decl.Declaration.Interpolate = 1;
decl.Declaration.Semantic = 1;
decl.Semantic.Name = TGSI_SEMANTIC_GENERIC;
decl.Semantic.Index = aactx->maxGeneric + 1;
decl.Range.First =
decl.Range.Last = aactx->maxInput + 1;
decl.Interp.Interpolate = TGSI_INTERPOLATE_PERSPECTIVE;
ctx->emit_declaration(ctx, &decl);
 
/* declare new sampler */
decl = tgsi_default_full_declaration();
decl.Declaration.File = TGSI_FILE_SAMPLER;
decl.Range.First =
decl.Range.Last = aactx->freeSampler;
ctx->emit_declaration(ctx, &decl);
 
/* declare new temp regs */
decl = tgsi_default_full_declaration();
decl.Declaration.File = TGSI_FILE_TEMPORARY;
decl.Range.First =
decl.Range.Last = aactx->texTemp;
ctx->emit_declaration(ctx, &decl);
 
decl = tgsi_default_full_declaration();
decl.Declaration.File = TGSI_FILE_TEMPORARY;
decl.Range.First =
decl.Range.Last = aactx->colorTemp;
ctx->emit_declaration(ctx, &decl);
 
aactx->firstInstruction = FALSE;
}
 
if (inst->Instruction.Opcode == TGSI_OPCODE_END &&
aactx->colorOutput != -1) {
struct tgsi_full_instruction newInst;
 
/* TEX */
newInst = tgsi_default_full_instruction();
newInst.Instruction.Opcode = TGSI_OPCODE_TEX;
newInst.Instruction.NumDstRegs = 1;
newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY;
newInst.Dst[0].Register.Index = aactx->texTemp;
newInst.Instruction.NumSrcRegs = 2;
newInst.Instruction.Texture = TRUE;
newInst.Texture.Texture = TGSI_TEXTURE_2D;
newInst.Src[0].Register.File = TGSI_FILE_INPUT;
newInst.Src[0].Register.Index = aactx->maxInput + 1;
newInst.Src[1].Register.File = TGSI_FILE_SAMPLER;
newInst.Src[1].Register.Index = aactx->freeSampler;
 
ctx->emit_instruction(ctx, &newInst);
 
/* MOV rgb */
newInst = tgsi_default_full_instruction();
newInst.Instruction.Opcode = TGSI_OPCODE_MOV;
newInst.Instruction.NumDstRegs = 1;
newInst.Dst[0].Register.File = TGSI_FILE_OUTPUT;
newInst.Dst[0].Register.Index = aactx->colorOutput;
newInst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XYZ;
newInst.Instruction.NumSrcRegs = 1;
newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY;
newInst.Src[0].Register.Index = aactx->colorTemp;
ctx->emit_instruction(ctx, &newInst);
 
/* MUL alpha */
newInst = tgsi_default_full_instruction();
newInst.Instruction.Opcode = TGSI_OPCODE_MUL;
newInst.Instruction.NumDstRegs = 1;
newInst.Dst[0].Register.File = TGSI_FILE_OUTPUT;
newInst.Dst[0].Register.Index = aactx->colorOutput;
newInst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_W;
newInst.Instruction.NumSrcRegs = 2;
newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY;
newInst.Src[0].Register.Index = aactx->colorTemp;
newInst.Src[1].Register.File = TGSI_FILE_TEMPORARY;
newInst.Src[1].Register.Index = aactx->texTemp;
ctx->emit_instruction(ctx, &newInst);
 
/* END */
newInst = tgsi_default_full_instruction();
newInst.Instruction.Opcode = TGSI_OPCODE_END;
newInst.Instruction.NumDstRegs = 0;
newInst.Instruction.NumSrcRegs = 0;
ctx->emit_instruction(ctx, &newInst);
}
else {
/* Not an END instruction.
* Look for writes to result.color and replace with colorTemp reg.
*/
uint i;
 
for (i = 0; i < inst->Instruction.NumDstRegs; i++) {
struct tgsi_full_dst_register *dst = &inst->Dst[i];
if (dst->Register.File == TGSI_FILE_OUTPUT &&
dst->Register.Index == aactx->colorOutput) {
dst->Register.File = TGSI_FILE_TEMPORARY;
dst->Register.Index = aactx->colorTemp;
}
}
 
ctx->emit_instruction(ctx, inst);
}
}
 
 
/**
* Generate the frag shader we'll use for drawing AA lines.
* This will be the user's shader plus some texture/modulate instructions.
*/
static boolean
generate_aaline_fs(struct aaline_stage *aaline)
{
struct pipe_context *pipe = aaline->stage.draw->pipe;
const struct pipe_shader_state *orig_fs = &aaline->fs->state;
struct pipe_shader_state aaline_fs;
struct aa_transform_context transform;
const uint newLen = tgsi_num_tokens(orig_fs->tokens) + NUM_NEW_TOKENS;
 
aaline_fs = *orig_fs; /* copy to init */
aaline_fs.tokens = tgsi_alloc_tokens(newLen);
if (aaline_fs.tokens == NULL)
return FALSE;
 
memset(&transform, 0, sizeof(transform));
transform.colorOutput = -1;
transform.maxInput = -1;
transform.maxGeneric = -1;
transform.colorTemp = -1;
transform.texTemp = -1;
transform.firstInstruction = TRUE;
transform.base.transform_instruction = aa_transform_inst;
transform.base.transform_declaration = aa_transform_decl;
 
tgsi_transform_shader(orig_fs->tokens,
(struct tgsi_token *) aaline_fs.tokens,
newLen, &transform.base);
 
#if 0 /* DEBUG */
debug_printf("draw_aaline, orig shader:\n");
tgsi_dump(orig_fs->tokens, 0);
debug_printf("draw_aaline, new shader:\n");
tgsi_dump(aaline_fs.tokens, 0);
#endif
 
aaline->fs->sampler_unit = transform.freeSampler;
 
aaline->fs->aaline_fs = aaline->driver_create_fs_state(pipe, &aaline_fs);
if (aaline->fs->aaline_fs == NULL)
goto fail;
 
aaline->fs->generic_attrib = transform.maxGeneric + 1;
FREE((void *)aaline_fs.tokens);
return TRUE;
 
fail:
FREE((void *)aaline_fs.tokens);
return FALSE;
}
 
 
/**
* Create the texture map we'll use for antialiasing the lines.
*/
static boolean
aaline_create_texture(struct aaline_stage *aaline)
{
struct pipe_context *pipe = aaline->stage.draw->pipe;
struct pipe_screen *screen = pipe->screen;
struct pipe_resource texTemp;
struct pipe_sampler_view viewTempl;
uint level;
 
memset(&texTemp, 0, sizeof(texTemp));
texTemp.target = PIPE_TEXTURE_2D;
texTemp.format = PIPE_FORMAT_A8_UNORM; /* XXX verify supported by driver! */
texTemp.last_level = MAX_TEXTURE_LEVEL;
texTemp.width0 = 1 << TEXTURE_SIZE_LOG2;
texTemp.height0 = 1 << TEXTURE_SIZE_LOG2;
texTemp.depth0 = 1;
texTemp.array_size = 1;
texTemp.bind = PIPE_BIND_SAMPLER_VIEW;
 
aaline->texture = screen->resource_create(screen, &texTemp);
if (!aaline->texture)
return FALSE;
 
u_sampler_view_default_template(&viewTempl,
aaline->texture,
aaline->texture->format);
aaline->sampler_view = pipe->create_sampler_view(pipe,
aaline->texture,
&viewTempl);
if (!aaline->sampler_view) {
return FALSE;
}
 
/* Fill in mipmap images.
* Basically each level is solid opaque, except for the outermost
* texels which are zero. Special case the 1x1 and 2x2 levels
* (though, those levels shouldn't be used - see the max_lod setting).
*/
for (level = 0; level <= MAX_TEXTURE_LEVEL; level++) {
struct pipe_transfer *transfer;
struct pipe_box box;
const uint size = u_minify(aaline->texture->width0, level);
ubyte *data;
uint i, j;
 
assert(aaline->texture->width0 == aaline->texture->height0);
 
u_box_origin_2d( size, size, &box );
 
/* This texture is new, no need to flush.
*/
data = pipe->transfer_map(pipe,
aaline->texture,
level,
PIPE_TRANSFER_WRITE,
&box, &transfer);
 
if (data == NULL)
return FALSE;
 
for (i = 0; i < size; i++) {
for (j = 0; j < size; j++) {
ubyte d;
if (size == 1) {
d = 255;
}
else if (size == 2) {
d = 200; /* tuneable */
}
else if (i == 0 || j == 0 || i == size - 1 || j == size - 1) {
d = 35; /* edge texel */
}
else {
d = 255;
}
data[i * transfer->stride + j] = d;
}
}
 
/* unmap */
pipe->transfer_unmap(pipe, transfer);
}
return TRUE;
}
 
 
/**
* Create the sampler CSO that'll be used for antialiasing.
* By using a mipmapped texture, we don't have to generate a different
* texture image for each line size.
*/
static boolean
aaline_create_sampler(struct aaline_stage *aaline)
{
struct pipe_sampler_state sampler;
struct pipe_context *pipe = aaline->stage.draw->pipe;
 
memset(&sampler, 0, sizeof(sampler));
sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
sampler.min_mip_filter = PIPE_TEX_MIPFILTER_LINEAR;
sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR;
sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR;
sampler.normalized_coords = 1;
sampler.min_lod = 0.0f;
sampler.max_lod = MAX_TEXTURE_LEVEL;
 
aaline->sampler_cso = pipe->create_sampler_state(pipe, &sampler);
if (aaline->sampler_cso == NULL)
return FALSE;
 
return TRUE;
}
 
 
/**
* When we're about to draw our first AA line in a batch, this function is
* called to tell the driver to bind our modified fragment shader.
*/
static boolean
bind_aaline_fragment_shader(struct aaline_stage *aaline)
{
struct draw_context *draw = aaline->stage.draw;
struct pipe_context *pipe = draw->pipe;
 
if (!aaline->fs->aaline_fs &&
!generate_aaline_fs(aaline))
return FALSE;
 
draw->suspend_flushing = TRUE;
aaline->driver_bind_fs_state(pipe, aaline->fs->aaline_fs);
draw->suspend_flushing = FALSE;
 
return TRUE;
}
 
 
 
static INLINE struct aaline_stage *
aaline_stage( struct draw_stage *stage )
{
return (struct aaline_stage *) stage;
}
 
 
/**
* Draw a wide line by drawing a quad, using geometry which will
* fullfill GL's antialiased line requirements.
*/
static void
aaline_line(struct draw_stage *stage, struct prim_header *header)
{
const struct aaline_stage *aaline = aaline_stage(stage);
const float half_width = aaline->half_line_width;
struct prim_header tri;
struct vertex_header *v[8];
uint texPos = aaline->tex_slot;
uint posPos = aaline->pos_slot;
float *pos, *tex;
float dx = header->v[1]->data[posPos][0] - header->v[0]->data[posPos][0];
float dy = header->v[1]->data[posPos][1] - header->v[0]->data[posPos][1];
double a = atan2(dy, dx);
float c_a = (float) cos(a), s_a = (float) sin(a);
uint i;
 
/* XXX the ends of lines aren't quite perfect yet, but probably passable */
dx = 0.5F * half_width;
dy = half_width;
 
/* allocate/dup new verts */
for (i = 0; i < 8; i++) {
v[i] = dup_vert(stage, header->v[i/4], i);
}
 
/*
* Quad strip for line from v0 to v1 (*=endpoints):
*
* 1 3 5 7
* +---+---------------------+---+
* | |
* | *v0 v1* |
* | |
* +---+---------------------+---+
* 0 2 4 6
*/
 
/* new verts */
pos = v[0]->data[posPos];
pos[0] += (-dx * c_a - dy * s_a);
pos[1] += (-dx * s_a + dy * c_a);
 
pos = v[1]->data[posPos];
pos[0] += (-dx * c_a - -dy * s_a);
pos[1] += (-dx * s_a + -dy * c_a);
 
pos = v[2]->data[posPos];
pos[0] += ( dx * c_a - dy * s_a);
pos[1] += ( dx * s_a + dy * c_a);
 
pos = v[3]->data[posPos];
pos[0] += ( dx * c_a - -dy * s_a);
pos[1] += ( dx * s_a + -dy * c_a);
 
pos = v[4]->data[posPos];
pos[0] += (-dx * c_a - dy * s_a);
pos[1] += (-dx * s_a + dy * c_a);
 
pos = v[5]->data[posPos];
pos[0] += (-dx * c_a - -dy * s_a);
pos[1] += (-dx * s_a + -dy * c_a);
 
pos = v[6]->data[posPos];
pos[0] += ( dx * c_a - dy * s_a);
pos[1] += ( dx * s_a + dy * c_a);
 
pos = v[7]->data[posPos];
pos[0] += ( dx * c_a - -dy * s_a);
pos[1] += ( dx * s_a + -dy * c_a);
 
/* new texcoords */
tex = v[0]->data[texPos];
ASSIGN_4V(tex, 0, 0, 0, 1);
 
tex = v[1]->data[texPos];
ASSIGN_4V(tex, 0, 1, 0, 1);
 
tex = v[2]->data[texPos];
ASSIGN_4V(tex, .5, 0, 0, 1);
 
tex = v[3]->data[texPos];
ASSIGN_4V(tex, .5, 1, 0, 1);
 
tex = v[4]->data[texPos];
ASSIGN_4V(tex, .5, 0, 0, 1);
 
tex = v[5]->data[texPos];
ASSIGN_4V(tex, .5, 1, 0, 1);
 
tex = v[6]->data[texPos];
ASSIGN_4V(tex, 1, 0, 0, 1);
 
tex = v[7]->data[texPos];
ASSIGN_4V(tex, 1, 1, 0, 1);
 
/* emit 6 tris for the quad strip */
tri.v[0] = v[2]; tri.v[1] = v[1]; tri.v[2] = v[0];
stage->next->tri( stage->next, &tri );
 
tri.v[0] = v[3]; tri.v[1] = v[1]; tri.v[2] = v[2];
stage->next->tri( stage->next, &tri );
 
tri.v[0] = v[4]; tri.v[1] = v[3]; tri.v[2] = v[2];
stage->next->tri( stage->next, &tri );
 
tri.v[0] = v[5]; tri.v[1] = v[3]; tri.v[2] = v[4];
stage->next->tri( stage->next, &tri );
 
tri.v[0] = v[6]; tri.v[1] = v[5]; tri.v[2] = v[4];
stage->next->tri( stage->next, &tri );
 
tri.v[0] = v[7]; tri.v[1] = v[5]; tri.v[2] = v[6];
stage->next->tri( stage->next, &tri );
}
 
 
static void
aaline_first_line(struct draw_stage *stage, struct prim_header *header)
{
auto struct aaline_stage *aaline = aaline_stage(stage);
struct draw_context *draw = stage->draw;
struct pipe_context *pipe = draw->pipe;
const struct pipe_rasterizer_state *rast = draw->rasterizer;
uint num_samplers;
void *r;
 
assert(draw->rasterizer->line_smooth);
 
if (draw->rasterizer->line_width <= 2.2)
aaline->half_line_width = 1.1f;
else
aaline->half_line_width = 0.5f * draw->rasterizer->line_width;
 
/*
* Bind (generate) our fragprog, sampler and texture
*/
if (!bind_aaline_fragment_shader(aaline)) {
stage->line = draw_pipe_passthrough_line;
stage->line(stage, header);
return;
}
 
/* update vertex attrib info */
aaline->pos_slot = draw_current_shader_position_output(draw);;
 
/* allocate the extra post-transformed vertex attribute */
aaline->tex_slot = draw_alloc_extra_vertex_attrib(draw,
TGSI_SEMANTIC_GENERIC,
aaline->fs->generic_attrib);
 
/* how many samplers? */
/* we'll use sampler/texture[pstip->sampler_unit] for the stipple */
num_samplers = MAX2(aaline->num_sampler_views, aaline->num_samplers);
num_samplers = MAX2(num_samplers, aaline->fs->sampler_unit + 1);
 
aaline->state.sampler[aaline->fs->sampler_unit] = aaline->sampler_cso;
pipe_sampler_view_reference(&aaline->state.sampler_views[aaline->fs->sampler_unit],
aaline->sampler_view);
 
draw->suspend_flushing = TRUE;
aaline->driver_bind_sampler_states(pipe, num_samplers, aaline->state.sampler);
aaline->driver_set_sampler_views(pipe, num_samplers, aaline->state.sampler_views);
 
/* Disable triangle culling, stippling, unfilled mode etc. */
r = draw_get_rasterizer_no_cull(draw, rast->scissor, rast->flatshade);
pipe->bind_rasterizer_state(pipe, r);
 
draw->suspend_flushing = FALSE;
 
/* now really draw first line */
stage->line = aaline_line;
stage->line(stage, header);
}
 
 
static void
aaline_flush(struct draw_stage *stage, unsigned flags)
{
struct draw_context *draw = stage->draw;
struct aaline_stage *aaline = aaline_stage(stage);
struct pipe_context *pipe = draw->pipe;
 
stage->line = aaline_first_line;
stage->next->flush( stage->next, flags );
 
/* restore original frag shader, texture, sampler state */
draw->suspend_flushing = TRUE;
aaline->driver_bind_fs_state(pipe, aaline->fs ? aaline->fs->driver_fs : NULL);
aaline->driver_bind_sampler_states(pipe, aaline->num_samplers,
aaline->state.sampler);
aaline->driver_set_sampler_views(pipe,
aaline->num_sampler_views,
aaline->state.sampler_views);
 
/* restore original rasterizer state */
if (draw->rast_handle) {
pipe->bind_rasterizer_state(pipe, draw->rast_handle);
}
 
draw->suspend_flushing = FALSE;
 
draw_remove_extra_vertex_attribs(draw);
}
 
 
static void
aaline_reset_stipple_counter(struct draw_stage *stage)
{
stage->next->reset_stipple_counter( stage->next );
}
 
 
static void
aaline_destroy(struct draw_stage *stage)
{
struct aaline_stage *aaline = aaline_stage(stage);
struct pipe_context *pipe = stage->draw->pipe;
uint i;
 
for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
pipe_sampler_view_reference(&aaline->state.sampler_views[i], NULL);
}
 
if (aaline->sampler_cso)
pipe->delete_sampler_state(pipe, aaline->sampler_cso);
 
if (aaline->texture)
pipe_resource_reference(&aaline->texture, NULL);
 
if (aaline->sampler_view) {
pipe_sampler_view_reference(&aaline->sampler_view, NULL);
}
 
draw_free_temp_verts( stage );
 
/* restore the old entry points */
pipe->create_fs_state = aaline->driver_create_fs_state;
pipe->bind_fs_state = aaline->driver_bind_fs_state;
pipe->delete_fs_state = aaline->driver_delete_fs_state;
 
pipe->bind_fragment_sampler_states = aaline->driver_bind_sampler_states;
pipe->set_fragment_sampler_views = aaline->driver_set_sampler_views;
 
FREE( stage );
}
 
 
static struct aaline_stage *
draw_aaline_stage(struct draw_context *draw)
{
struct aaline_stage *aaline = CALLOC_STRUCT(aaline_stage);
if (aaline == NULL)
return NULL;
 
aaline->stage.draw = draw;
aaline->stage.name = "aaline";
aaline->stage.next = NULL;
aaline->stage.point = draw_pipe_passthrough_point;
aaline->stage.line = aaline_first_line;
aaline->stage.tri = draw_pipe_passthrough_tri;
aaline->stage.flush = aaline_flush;
aaline->stage.reset_stipple_counter = aaline_reset_stipple_counter;
aaline->stage.destroy = aaline_destroy;
 
if (!draw_alloc_temp_verts( &aaline->stage, 8 ))
goto fail;
 
return aaline;
 
fail:
if (aaline)
aaline->stage.destroy(&aaline->stage);
 
return NULL;
}
 
 
static struct aaline_stage *
aaline_stage_from_pipe(struct pipe_context *pipe)
{
struct draw_context *draw = (struct draw_context *) pipe->draw;
 
if (draw) {
return aaline_stage(draw->pipeline.aaline);
} else {
return NULL;
}
}
 
 
/**
* This function overrides the driver's create_fs_state() function and
* will typically be called by the state tracker.
*/
static void *
aaline_create_fs_state(struct pipe_context *pipe,
const struct pipe_shader_state *fs)
{
struct aaline_stage *aaline = aaline_stage_from_pipe(pipe);
struct aaline_fragment_shader *aafs = NULL;
 
if (aaline == NULL)
return NULL;
 
aafs = CALLOC_STRUCT(aaline_fragment_shader);
 
if (aafs == NULL)
return NULL;
 
aafs->state.tokens = tgsi_dup_tokens(fs->tokens);
 
/* pass-through */
aafs->driver_fs = aaline->driver_create_fs_state(pipe, fs);
 
return aafs;
}
 
 
static void
aaline_bind_fs_state(struct pipe_context *pipe, void *fs)
{
struct aaline_stage *aaline = aaline_stage_from_pipe(pipe);
struct aaline_fragment_shader *aafs = (struct aaline_fragment_shader *) fs;
 
if (aaline == NULL) {
return;
}
 
/* save current */
aaline->fs = aafs;
/* pass-through */
aaline->driver_bind_fs_state(pipe, (aafs ? aafs->driver_fs : NULL));
}
 
 
static void
aaline_delete_fs_state(struct pipe_context *pipe, void *fs)
{
struct aaline_stage *aaline = aaline_stage_from_pipe(pipe);
struct aaline_fragment_shader *aafs = (struct aaline_fragment_shader *) fs;
 
if (aafs == NULL) {
return;
}
 
if (aaline != NULL) {
/* pass-through */
aaline->driver_delete_fs_state(pipe, aafs->driver_fs);
 
if (aafs->aaline_fs)
aaline->driver_delete_fs_state(pipe, aafs->aaline_fs);
}
 
FREE((void*)aafs->state.tokens);
FREE(aafs);
}
 
 
static void
aaline_bind_sampler_states(struct pipe_context *pipe,
unsigned num, void **sampler)
{
struct aaline_stage *aaline = aaline_stage_from_pipe(pipe);
 
if (aaline == NULL) {
return;
}
 
/* save current */
memcpy(aaline->state.sampler, sampler, num * sizeof(void *));
aaline->num_samplers = num;
 
/* pass-through */
aaline->driver_bind_sampler_states(pipe, num, sampler);
}
 
 
static void
aaline_set_sampler_views(struct pipe_context *pipe,
unsigned num,
struct pipe_sampler_view **views)
{
struct aaline_stage *aaline = aaline_stage_from_pipe(pipe);
uint i;
 
if (aaline == NULL) {
return;
}
 
/* save current */
for (i = 0; i < num; i++) {
pipe_sampler_view_reference(&aaline->state.sampler_views[i], views[i]);
}
for ( ; i < PIPE_MAX_SAMPLERS; i++) {
pipe_sampler_view_reference(&aaline->state.sampler_views[i], NULL);
}
aaline->num_sampler_views = num;
 
/* pass-through */
aaline->driver_set_sampler_views(pipe, num, views);
}
 
 
/**
* Called by drivers that want to install this AA line prim stage
* into the draw module's pipeline. This will not be used if the
* hardware has native support for AA lines.
*/
boolean
draw_install_aaline_stage(struct draw_context *draw, struct pipe_context *pipe)
{
struct aaline_stage *aaline;
 
pipe->draw = (void *) draw;
 
/*
* Create / install AA line drawing / prim stage
*/
aaline = draw_aaline_stage( draw );
if (!aaline)
goto fail;
 
/* create special texture, sampler state */
if (!aaline_create_texture(aaline))
goto fail;
 
if (!aaline_create_sampler(aaline))
goto fail;
 
/* save original driver functions */
aaline->driver_create_fs_state = pipe->create_fs_state;
aaline->driver_bind_fs_state = pipe->bind_fs_state;
aaline->driver_delete_fs_state = pipe->delete_fs_state;
 
aaline->driver_bind_sampler_states = pipe->bind_fragment_sampler_states;
aaline->driver_set_sampler_views = pipe->set_fragment_sampler_views;
 
/* override the driver's functions */
pipe->create_fs_state = aaline_create_fs_state;
pipe->bind_fs_state = aaline_bind_fs_state;
pipe->delete_fs_state = aaline_delete_fs_state;
 
pipe->bind_fragment_sampler_states = aaline_bind_sampler_states;
pipe->set_fragment_sampler_views = aaline_set_sampler_views;
/* Install once everything is known to be OK:
*/
draw->pipeline.aaline = &aaline->stage;
 
return TRUE;
 
fail:
if (aaline)
aaline->stage.destroy( &aaline->stage );
return FALSE;
}
/drivers/video/Gallium/auxiliary/draw/draw_pipe_aapoint.c
0,0 → 1,910
/**************************************************************************
*
* 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.
*
**************************************************************************/
 
/**
* AA point stage: AA points are converted to quads and rendered with a
* special fragment shader. Another approach would be to use a texture
* map image of a point, but experiments indicate the quality isn't nearly
* as good as this approach.
*
* Note: this looks a lot like draw_aaline.c but there's actually little
* if any code that can be shared.
*
* Authors: Brian Paul
*/
 
 
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "pipe/p_shader_tokens.h"
 
#include "tgsi/tgsi_transform.h"
#include "tgsi/tgsi_dump.h"
 
#include "util/u_math.h"
#include "util/u_memory.h"
 
#include "draw_context.h"
#include "draw_vs.h"
#include "draw_pipe.h"
 
 
/** Approx number of new tokens for instructions in aa_transform_inst() */
#define NUM_NEW_TOKENS 200
 
 
/*
* Enabling NORMALIZE might give _slightly_ better results.
* Basically, it controls whether we compute distance as d=sqrt(x*x+y*y) or
* d=x*x+y*y. Since we're working with a unit circle, the later seems
* close enough and saves some costly instructions.
*/
#define NORMALIZE 0
 
 
/**
* Subclass of pipe_shader_state to carry extra fragment shader info.
*/
struct aapoint_fragment_shader
{
struct pipe_shader_state state;
void *driver_fs; /**< the regular shader */
void *aapoint_fs; /**< the aa point-augmented shader */
int generic_attrib; /**< The generic input attrib/texcoord we'll use */
};
 
 
/**
* Subclass of draw_stage
*/
struct aapoint_stage
{
struct draw_stage stage;
 
/** half of pipe_rasterizer_state::point_size */
float radius;
 
/** vertex attrib slot containing point size */
int psize_slot;
 
/** this is the vertex attrib slot for the new texcoords */
uint tex_slot;
 
/** vertex attrib slot containing position */
uint pos_slot;
 
/** Currently bound fragment shader */
struct aapoint_fragment_shader *fs;
 
/*
* Driver interface/override functions
*/
void * (*driver_create_fs_state)(struct pipe_context *,
const struct pipe_shader_state *);
void (*driver_bind_fs_state)(struct pipe_context *, void *);
void (*driver_delete_fs_state)(struct pipe_context *, void *);
};
 
 
 
/**
* Subclass of tgsi_transform_context, used for transforming the
* user's fragment shader to add the special AA instructions.
*/
struct aa_transform_context {
struct tgsi_transform_context base;
uint tempsUsed; /**< bitmask */
int colorOutput; /**< which output is the primary color */
int maxInput, maxGeneric; /**< max input index found */
int tmp0, colorTemp; /**< temp registers */
boolean firstInstruction;
};
 
 
/**
* TGSI declaration transform callback.
* Look for two free temp regs and available input reg for new texcoords.
*/
static void
aa_transform_decl(struct tgsi_transform_context *ctx,
struct tgsi_full_declaration *decl)
{
struct aa_transform_context *aactx = (struct aa_transform_context *) ctx;
 
if (decl->Declaration.File == TGSI_FILE_OUTPUT &&
decl->Semantic.Name == TGSI_SEMANTIC_COLOR &&
decl->Semantic.Index == 0) {
aactx->colorOutput = decl->Range.First;
}
else if (decl->Declaration.File == TGSI_FILE_INPUT) {
if ((int) decl->Range.Last > aactx->maxInput)
aactx->maxInput = decl->Range.Last;
if (decl->Semantic.Name == TGSI_SEMANTIC_GENERIC &&
(int) decl->Semantic.Index > aactx->maxGeneric) {
aactx->maxGeneric = decl->Semantic.Index;
}
}
else if (decl->Declaration.File == TGSI_FILE_TEMPORARY) {
uint i;
for (i = decl->Range.First;
i <= decl->Range.Last; i++) {
aactx->tempsUsed |= (1 << i);
}
}
 
ctx->emit_declaration(ctx, decl);
}
 
 
/**
* TGSI instruction transform callback.
* Replace writes to result.color w/ a temp reg.
* Upon END instruction, insert texture sampling code for antialiasing.
*/
static void
aa_transform_inst(struct tgsi_transform_context *ctx,
struct tgsi_full_instruction *inst)
{
struct aa_transform_context *aactx = (struct aa_transform_context *) ctx;
struct tgsi_full_instruction newInst;
 
if (aactx->firstInstruction) {
/* emit our new declarations before the first instruction */
 
struct tgsi_full_declaration decl;
const int texInput = aactx->maxInput + 1;
int tmp0;
uint i;
 
/* find two free temp regs */
for (i = 0; i < 32; i++) {
if ((aactx->tempsUsed & (1 << i)) == 0) {
/* found a free temp */
if (aactx->tmp0 < 0)
aactx->tmp0 = i;
else if (aactx->colorTemp < 0)
aactx->colorTemp = i;
else
break;
}
}
 
assert(aactx->colorTemp != aactx->tmp0);
 
tmp0 = aactx->tmp0;
 
/* declare new generic input/texcoord */
decl = tgsi_default_full_declaration();
decl.Declaration.File = TGSI_FILE_INPUT;
/* XXX this could be linear... */
decl.Declaration.Interpolate = 1;
decl.Declaration.Semantic = 1;
decl.Semantic.Name = TGSI_SEMANTIC_GENERIC;
decl.Semantic.Index = aactx->maxGeneric + 1;
decl.Range.First =
decl.Range.Last = texInput;
decl.Interp.Interpolate = TGSI_INTERPOLATE_PERSPECTIVE;
ctx->emit_declaration(ctx, &decl);
 
/* declare new temp regs */
decl = tgsi_default_full_declaration();
decl.Declaration.File = TGSI_FILE_TEMPORARY;
decl.Range.First =
decl.Range.Last = tmp0;
ctx->emit_declaration(ctx, &decl);
 
decl = tgsi_default_full_declaration();
decl.Declaration.File = TGSI_FILE_TEMPORARY;
decl.Range.First =
decl.Range.Last = aactx->colorTemp;
ctx->emit_declaration(ctx, &decl);
 
aactx->firstInstruction = FALSE;
 
 
/*
* Emit code to compute fragment coverage, kill if outside point radius
*
* Temp reg0 usage:
* t0.x = distance of fragment from center point
* t0.y = boolean, is t0.x > 1.0, also misc temp usage
* t0.z = temporary for computing 1/(1-k) value
* t0.w = final coverage value
*/
 
/* MUL t0.xy, tex, tex; # compute x^2, y^2 */
newInst = tgsi_default_full_instruction();
newInst.Instruction.Opcode = TGSI_OPCODE_MUL;
newInst.Instruction.NumDstRegs = 1;
newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY;
newInst.Dst[0].Register.Index = tmp0;
newInst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XY;
newInst.Instruction.NumSrcRegs = 2;
newInst.Src[0].Register.File = TGSI_FILE_INPUT;
newInst.Src[0].Register.Index = texInput;
newInst.Src[1].Register.File = TGSI_FILE_INPUT;
newInst.Src[1].Register.Index = texInput;
ctx->emit_instruction(ctx, &newInst);
 
/* ADD t0.x, t0.x, t0.y; # x^2 + y^2 */
newInst = tgsi_default_full_instruction();
newInst.Instruction.Opcode = TGSI_OPCODE_ADD;
newInst.Instruction.NumDstRegs = 1;
newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY;
newInst.Dst[0].Register.Index = tmp0;
newInst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_X;
newInst.Instruction.NumSrcRegs = 2;
newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY;
newInst.Src[0].Register.Index = tmp0;
newInst.Src[0].Register.SwizzleX = TGSI_SWIZZLE_X;
newInst.Src[1].Register.File = TGSI_FILE_TEMPORARY;
newInst.Src[1].Register.Index = tmp0;
newInst.Src[1].Register.SwizzleX = TGSI_SWIZZLE_Y;
ctx->emit_instruction(ctx, &newInst);
 
#if NORMALIZE /* OPTIONAL normalization of length */
/* RSQ t0.x, t0.x; */
newInst = tgsi_default_full_instruction();
newInst.Instruction.Opcode = TGSI_OPCODE_RSQ;
newInst.Instruction.NumDstRegs = 1;
newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY;
newInst.Dst[0].Register.Index = tmp0;
newInst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_X;
newInst.Instruction.NumSrcRegs = 1;
newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY;
newInst.Src[0].Register.Index = tmp0;
ctx->emit_instruction(ctx, &newInst);
 
/* RCP t0.x, t0.x; */
newInst = tgsi_default_full_instruction();
newInst.Instruction.Opcode = TGSI_OPCODE_RCP;
newInst.Instruction.NumDstRegs = 1;
newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY;
newInst.Dst[0].Register.Index = tmp0;
newInst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_X;
newInst.Instruction.NumSrcRegs = 1;
newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY;
newInst.Src[0].Register.Index = tmp0;
ctx->emit_instruction(ctx, &newInst);
#endif
 
/* SGT t0.y, t0.xxxx, tex.wwww; # bool b = d > 1 (NOTE tex.w == 1) */
newInst = tgsi_default_full_instruction();
newInst.Instruction.Opcode = TGSI_OPCODE_SGT;
newInst.Instruction.NumDstRegs = 1;
newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY;
newInst.Dst[0].Register.Index = tmp0;
newInst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_Y;
newInst.Instruction.NumSrcRegs = 2;
newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY;
newInst.Src[0].Register.Index = tmp0;
newInst.Src[0].Register.SwizzleY = TGSI_SWIZZLE_X;
newInst.Src[1].Register.File = TGSI_FILE_INPUT;
newInst.Src[1].Register.Index = texInput;
newInst.Src[1].Register.SwizzleY = TGSI_SWIZZLE_W;
ctx->emit_instruction(ctx, &newInst);
 
/* KIL -tmp0.yyyy; # if -tmp0.y < 0, KILL */
newInst = tgsi_default_full_instruction();
newInst.Instruction.Opcode = TGSI_OPCODE_KIL;
newInst.Instruction.NumDstRegs = 0;
newInst.Instruction.NumSrcRegs = 1;
newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY;
newInst.Src[0].Register.Index = tmp0;
newInst.Src[0].Register.SwizzleX = TGSI_SWIZZLE_Y;
newInst.Src[0].Register.SwizzleY = TGSI_SWIZZLE_Y;
newInst.Src[0].Register.SwizzleZ = TGSI_SWIZZLE_Y;
newInst.Src[0].Register.SwizzleW = TGSI_SWIZZLE_Y;
newInst.Src[0].Register.Negate = 1;
ctx->emit_instruction(ctx, &newInst);
 
 
/* compute coverage factor = (1-d)/(1-k) */
 
/* SUB t0.z, tex.w, tex.z; # m = 1 - k */
newInst = tgsi_default_full_instruction();
newInst.Instruction.Opcode = TGSI_OPCODE_SUB;
newInst.Instruction.NumDstRegs = 1;
newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY;
newInst.Dst[0].Register.Index = tmp0;
newInst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_Z;
newInst.Instruction.NumSrcRegs = 2;
newInst.Src[0].Register.File = TGSI_FILE_INPUT;
newInst.Src[0].Register.Index = texInput;
newInst.Src[0].Register.SwizzleZ = TGSI_SWIZZLE_W;
newInst.Src[1].Register.File = TGSI_FILE_INPUT;
newInst.Src[1].Register.Index = texInput;
newInst.Src[1].Register.SwizzleZ = TGSI_SWIZZLE_Z;
ctx->emit_instruction(ctx, &newInst);
 
/* RCP t0.z, t0.z; # t0.z = 1 / m */
newInst = tgsi_default_full_instruction();
newInst.Instruction.Opcode = TGSI_OPCODE_RCP;
newInst.Instruction.NumDstRegs = 1;
newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY;
newInst.Dst[0].Register.Index = tmp0;
newInst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_Z;
newInst.Instruction.NumSrcRegs = 1;
newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY;
newInst.Src[0].Register.Index = tmp0;
newInst.Src[0].Register.SwizzleX = TGSI_SWIZZLE_Z;
ctx->emit_instruction(ctx, &newInst);
 
/* SUB t0.y, 1, t0.x; # d = 1 - d */
newInst = tgsi_default_full_instruction();
newInst.Instruction.Opcode = TGSI_OPCODE_SUB;
newInst.Instruction.NumDstRegs = 1;
newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY;
newInst.Dst[0].Register.Index = tmp0;
newInst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_Y;
newInst.Instruction.NumSrcRegs = 2;
newInst.Src[0].Register.File = TGSI_FILE_INPUT;
newInst.Src[0].Register.Index = texInput;
newInst.Src[0].Register.SwizzleY = TGSI_SWIZZLE_W;
newInst.Src[1].Register.File = TGSI_FILE_TEMPORARY;
newInst.Src[1].Register.Index = tmp0;
newInst.Src[1].Register.SwizzleY = TGSI_SWIZZLE_X;
ctx->emit_instruction(ctx, &newInst);
 
/* MUL t0.w, t0.y, t0.z; # coverage = d * m */
newInst = tgsi_default_full_instruction();
newInst.Instruction.Opcode = TGSI_OPCODE_MUL;
newInst.Instruction.NumDstRegs = 1;
newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY;
newInst.Dst[0].Register.Index = tmp0;
newInst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_W;
newInst.Instruction.NumSrcRegs = 2;
newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY;
newInst.Src[0].Register.Index = tmp0;
newInst.Src[0].Register.SwizzleW = TGSI_SWIZZLE_Y;
newInst.Src[1].Register.File = TGSI_FILE_TEMPORARY;
newInst.Src[1].Register.Index = tmp0;
newInst.Src[1].Register.SwizzleW = TGSI_SWIZZLE_Z;
ctx->emit_instruction(ctx, &newInst);
 
/* SLE t0.y, t0.x, tex.z; # bool b = distance <= k */
newInst = tgsi_default_full_instruction();
newInst.Instruction.Opcode = TGSI_OPCODE_SLE;
newInst.Instruction.NumDstRegs = 1;
newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY;
newInst.Dst[0].Register.Index = tmp0;
newInst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_Y;
newInst.Instruction.NumSrcRegs = 2;
newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY;
newInst.Src[0].Register.Index = tmp0;
newInst.Src[0].Register.SwizzleY = TGSI_SWIZZLE_X;
newInst.Src[1].Register.File = TGSI_FILE_INPUT;
newInst.Src[1].Register.Index = texInput;
newInst.Src[1].Register.SwizzleY = TGSI_SWIZZLE_Z;
ctx->emit_instruction(ctx, &newInst);
 
/* CMP t0.w, -t0.y, tex.w, t0.w;
* # if -t0.y < 0 then
* t0.w = 1
* else
* t0.w = t0.w
*/
newInst = tgsi_default_full_instruction();
newInst.Instruction.Opcode = TGSI_OPCODE_CMP;
newInst.Instruction.NumDstRegs = 1;
newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY;
newInst.Dst[0].Register.Index = tmp0;
newInst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_W;
newInst.Instruction.NumSrcRegs = 3;
newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY;
newInst.Src[0].Register.Index = tmp0;
newInst.Src[0].Register.SwizzleX = TGSI_SWIZZLE_Y;
newInst.Src[0].Register.SwizzleY = TGSI_SWIZZLE_Y;
newInst.Src[0].Register.SwizzleZ = TGSI_SWIZZLE_Y;
newInst.Src[0].Register.SwizzleW = TGSI_SWIZZLE_Y;
newInst.Src[0].Register.Negate = 1;
newInst.Src[1].Register.File = TGSI_FILE_INPUT;
newInst.Src[1].Register.Index = texInput;
newInst.Src[1].Register.SwizzleX = TGSI_SWIZZLE_W;
newInst.Src[1].Register.SwizzleY = TGSI_SWIZZLE_W;
newInst.Src[1].Register.SwizzleZ = TGSI_SWIZZLE_W;
newInst.Src[1].Register.SwizzleW = TGSI_SWIZZLE_W;
newInst.Src[2].Register.File = TGSI_FILE_TEMPORARY;
newInst.Src[2].Register.Index = tmp0;
newInst.Src[2].Register.SwizzleX = TGSI_SWIZZLE_W;
newInst.Src[2].Register.SwizzleY = TGSI_SWIZZLE_W;
newInst.Src[2].Register.SwizzleZ = TGSI_SWIZZLE_W;
newInst.Src[2].Register.SwizzleW = TGSI_SWIZZLE_W;
ctx->emit_instruction(ctx, &newInst);
 
}
 
if (inst->Instruction.Opcode == TGSI_OPCODE_END) {
/* add alpha modulation code at tail of program */
 
/* MOV result.color.xyz, colorTemp; */
newInst = tgsi_default_full_instruction();
newInst.Instruction.Opcode = TGSI_OPCODE_MOV;
newInst.Instruction.NumDstRegs = 1;
newInst.Dst[0].Register.File = TGSI_FILE_OUTPUT;
newInst.Dst[0].Register.Index = aactx->colorOutput;
newInst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_XYZ;
newInst.Instruction.NumSrcRegs = 1;
newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY;
newInst.Src[0].Register.Index = aactx->colorTemp;
ctx->emit_instruction(ctx, &newInst);
 
/* MUL result.color.w, colorTemp, tmp0.w; */
newInst = tgsi_default_full_instruction();
newInst.Instruction.Opcode = TGSI_OPCODE_MUL;
newInst.Instruction.NumDstRegs = 1;
newInst.Dst[0].Register.File = TGSI_FILE_OUTPUT;
newInst.Dst[0].Register.Index = aactx->colorOutput;
newInst.Dst[0].Register.WriteMask = TGSI_WRITEMASK_W;
newInst.Instruction.NumSrcRegs = 2;
newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY;
newInst.Src[0].Register.Index = aactx->colorTemp;
newInst.Src[1].Register.File = TGSI_FILE_TEMPORARY;
newInst.Src[1].Register.Index = aactx->tmp0;
ctx->emit_instruction(ctx, &newInst);
}
else {
/* Not an END instruction.
* Look for writes to result.color and replace with colorTemp reg.
*/
uint i;
 
for (i = 0; i < inst->Instruction.NumDstRegs; i++) {
struct tgsi_full_dst_register *dst = &inst->Dst[i];
if (dst->Register.File == TGSI_FILE_OUTPUT &&
dst->Register.Index == aactx->colorOutput) {
dst->Register.File = TGSI_FILE_TEMPORARY;
dst->Register.Index = aactx->colorTemp;
}
}
}
 
ctx->emit_instruction(ctx, inst);
}
 
 
/**
* Generate the frag shader we'll use for drawing AA points.
* This will be the user's shader plus some texture/modulate instructions.
*/
static boolean
generate_aapoint_fs(struct aapoint_stage *aapoint)
{
const struct pipe_shader_state *orig_fs = &aapoint->fs->state;
struct pipe_shader_state aapoint_fs;
struct aa_transform_context transform;
const uint newLen = tgsi_num_tokens(orig_fs->tokens) + NUM_NEW_TOKENS;
struct pipe_context *pipe = aapoint->stage.draw->pipe;
 
aapoint_fs = *orig_fs; /* copy to init */
aapoint_fs.tokens = tgsi_alloc_tokens(newLen);
if (aapoint_fs.tokens == NULL)
return FALSE;
 
memset(&transform, 0, sizeof(transform));
transform.colorOutput = -1;
transform.maxInput = -1;
transform.maxGeneric = -1;
transform.colorTemp = -1;
transform.tmp0 = -1;
transform.firstInstruction = TRUE;
transform.base.transform_instruction = aa_transform_inst;
transform.base.transform_declaration = aa_transform_decl;
 
tgsi_transform_shader(orig_fs->tokens,
(struct tgsi_token *) aapoint_fs.tokens,
newLen, &transform.base);
 
#if 0 /* DEBUG */
debug_printf("draw_aapoint, orig shader:\n");
tgsi_dump(orig_fs->tokens, 0);
debug_printf("draw_aapoint, new shader:\n");
tgsi_dump(aapoint_fs.tokens, 0);
#endif
 
aapoint->fs->aapoint_fs
= aapoint->driver_create_fs_state(pipe, &aapoint_fs);
if (aapoint->fs->aapoint_fs == NULL)
goto fail;
 
aapoint->fs->generic_attrib = transform.maxGeneric + 1;
FREE((void *)aapoint_fs.tokens);
return TRUE;
 
fail:
FREE((void *)aapoint_fs.tokens);
return FALSE;
}
 
 
/**
* When we're about to draw our first AA point in a batch, this function is
* called to tell the driver to bind our modified fragment shader.
*/
static boolean
bind_aapoint_fragment_shader(struct aapoint_stage *aapoint)
{
struct draw_context *draw = aapoint->stage.draw;
struct pipe_context *pipe = draw->pipe;
 
if (!aapoint->fs->aapoint_fs &&
!generate_aapoint_fs(aapoint))
return FALSE;
 
draw->suspend_flushing = TRUE;
aapoint->driver_bind_fs_state(pipe, aapoint->fs->aapoint_fs);
draw->suspend_flushing = FALSE;
 
return TRUE;
}
 
 
 
static INLINE struct aapoint_stage *
aapoint_stage( struct draw_stage *stage )
{
return (struct aapoint_stage *) stage;
}
 
 
 
 
/**
* Draw an AA point by drawing a quad.
*/
static void
aapoint_point(struct draw_stage *stage, struct prim_header *header)
{
const struct aapoint_stage *aapoint = aapoint_stage(stage);
struct prim_header tri;
struct vertex_header *v[4];
const uint tex_slot = aapoint->tex_slot;
const uint pos_slot = aapoint->pos_slot;
float radius, *pos, *tex;
uint i;
float k;
 
if (aapoint->psize_slot >= 0) {
radius = 0.5f * header->v[0]->data[aapoint->psize_slot][0];
}
else {
radius = aapoint->radius;
}
 
/*
* Note: the texcoords (generic attrib, really) we use are special:
* The S and T components simply vary from -1 to +1.
* The R component is k, below.
* The Q component is 1.0 and will used as a handy constant in the
* fragment shader.
*/
 
/*
* k is the threshold distance from the point's center at which
* we begin alpha attenuation (the coverage value).
* Operating within a unit circle, we'll compute the fragment's
* distance 'd' from the center point using the texcoords.
* IF d > 1.0 THEN
* KILL fragment
* ELSE IF d > k THEN
* compute coverage in [0,1] proportional to d in [k, 1].
* ELSE
* coverage = 1.0; // full coverage
* ENDIF
*
* Note: the ELSEIF and ELSE clauses are actually implemented with CMP to
* avoid using IF/ELSE/ENDIF TGSI opcodes.
*/
 
#if !NORMALIZE
k = 1.0f / radius;
k = 1.0f - 2.0f * k + k * k;
#else
k = 1.0f - 1.0f / radius;
#endif
 
/* allocate/dup new verts */
for (i = 0; i < 4; i++) {
v[i] = dup_vert(stage, header->v[0], i);
}
 
/* new verts */
pos = v[0]->data[pos_slot];
pos[0] -= radius;
pos[1] -= radius;
 
pos = v[1]->data[pos_slot];
pos[0] += radius;
pos[1] -= radius;
 
pos = v[2]->data[pos_slot];
pos[0] += radius;
pos[1] += radius;
 
pos = v[3]->data[pos_slot];
pos[0] -= radius;
pos[1] += radius;
 
/* new texcoords */
tex = v[0]->data[tex_slot];
ASSIGN_4V(tex, -1, -1, k, 1);
 
tex = v[1]->data[tex_slot];
ASSIGN_4V(tex, 1, -1, k, 1);
 
tex = v[2]->data[tex_slot];
ASSIGN_4V(tex, 1, 1, k, 1);
 
tex = v[3]->data[tex_slot];
ASSIGN_4V(tex, -1, 1, k, 1);
 
/* emit 2 tris for the quad strip */
tri.v[0] = v[0];
tri.v[1] = v[1];
tri.v[2] = v[2];
stage->next->tri( stage->next, &tri );
 
tri.v[0] = v[0];
tri.v[1] = v[2];
tri.v[2] = v[3];
stage->next->tri( stage->next, &tri );
}
 
 
static void
aapoint_first_point(struct draw_stage *stage, struct prim_header *header)
{
auto struct aapoint_stage *aapoint = aapoint_stage(stage);
struct draw_context *draw = stage->draw;
struct pipe_context *pipe = draw->pipe;
const struct pipe_rasterizer_state *rast = draw->rasterizer;
void *r;
 
assert(draw->rasterizer->point_smooth);
 
if (draw->rasterizer->point_size <= 2.0)
aapoint->radius = 1.0;
else
aapoint->radius = 0.5f * draw->rasterizer->point_size;
 
/*
* Bind (generate) our fragprog.
*/
bind_aapoint_fragment_shader(aapoint);
 
/* update vertex attrib info */
aapoint->pos_slot = draw_current_shader_position_output(draw);
 
/* allocate the extra post-transformed vertex attribute */
aapoint->tex_slot = draw_alloc_extra_vertex_attrib(draw,
TGSI_SEMANTIC_GENERIC,
aapoint->fs->generic_attrib);
assert(aapoint->tex_slot > 0); /* output[0] is vertex pos */
 
/* find psize slot in post-transform vertex */
aapoint->psize_slot = -1;
if (draw->rasterizer->point_size_per_vertex) {
const struct tgsi_shader_info *info = draw_get_shader_info(draw);
uint i;
/* find PSIZ vertex output */
for (i = 0; i < info->num_outputs; i++) {
if (info->output_semantic_name[i] == TGSI_SEMANTIC_PSIZE) {
aapoint->psize_slot = i;
break;
}
}
}
 
draw->suspend_flushing = TRUE;
 
/* Disable triangle culling, stippling, unfilled mode etc. */
r = draw_get_rasterizer_no_cull(draw, rast->scissor, rast->flatshade);
pipe->bind_rasterizer_state(pipe, r);
 
draw->suspend_flushing = FALSE;
 
/* now really draw first point */
stage->point = aapoint_point;
stage->point(stage, header);
}
 
 
static void
aapoint_flush(struct draw_stage *stage, unsigned flags)
{
struct draw_context *draw = stage->draw;
struct aapoint_stage *aapoint = aapoint_stage(stage);
struct pipe_context *pipe = draw->pipe;
 
stage->point = aapoint_first_point;
stage->next->flush( stage->next, flags );
 
/* restore original frag shader */
draw->suspend_flushing = TRUE;
aapoint->driver_bind_fs_state(pipe, aapoint->fs ? aapoint->fs->driver_fs : NULL);
 
/* restore original rasterizer state */
if (draw->rast_handle) {
pipe->bind_rasterizer_state(pipe, draw->rast_handle);
}
 
draw->suspend_flushing = FALSE;
 
draw_remove_extra_vertex_attribs(draw);
}
 
 
static void
aapoint_reset_stipple_counter(struct draw_stage *stage)
{
stage->next->reset_stipple_counter( stage->next );
}
 
 
static void
aapoint_destroy(struct draw_stage *stage)
{
struct aapoint_stage* aapoint = aapoint_stage(stage);
struct pipe_context *pipe = stage->draw->pipe;
 
draw_free_temp_verts( stage );
 
/* restore the old entry points */
pipe->create_fs_state = aapoint->driver_create_fs_state;
pipe->bind_fs_state = aapoint->driver_bind_fs_state;
pipe->delete_fs_state = aapoint->driver_delete_fs_state;
 
FREE( stage );
}
 
 
static struct aapoint_stage *
draw_aapoint_stage(struct draw_context *draw)
{
struct aapoint_stage *aapoint = CALLOC_STRUCT(aapoint_stage);
if (aapoint == NULL)
goto fail;
 
aapoint->stage.draw = draw;
aapoint->stage.name = "aapoint";
aapoint->stage.next = NULL;
aapoint->stage.point = aapoint_first_point;
aapoint->stage.line = draw_pipe_passthrough_line;
aapoint->stage.tri = draw_pipe_passthrough_tri;
aapoint->stage.flush = aapoint_flush;
aapoint->stage.reset_stipple_counter = aapoint_reset_stipple_counter;
aapoint->stage.destroy = aapoint_destroy;
 
if (!draw_alloc_temp_verts( &aapoint->stage, 4 ))
goto fail;
 
return aapoint;
 
fail:
if (aapoint)
aapoint->stage.destroy(&aapoint->stage);
 
return NULL;
 
}
 
 
static struct aapoint_stage *
aapoint_stage_from_pipe(struct pipe_context *pipe)
{
struct draw_context *draw = (struct draw_context *) pipe->draw;
return aapoint_stage(draw->pipeline.aapoint);
}
 
 
/**
* This function overrides the driver's create_fs_state() function and
* will typically be called by the state tracker.
*/
static void *
aapoint_create_fs_state(struct pipe_context *pipe,
const struct pipe_shader_state *fs)
{
struct aapoint_stage *aapoint = aapoint_stage_from_pipe(pipe);
struct aapoint_fragment_shader *aafs = CALLOC_STRUCT(aapoint_fragment_shader);
if (aafs == NULL)
return NULL;
 
aafs->state.tokens = tgsi_dup_tokens(fs->tokens);
 
/* pass-through */
aafs->driver_fs = aapoint->driver_create_fs_state(pipe, fs);
 
return aafs;
}
 
 
static void
aapoint_bind_fs_state(struct pipe_context *pipe, void *fs)
{
struct aapoint_stage *aapoint = aapoint_stage_from_pipe(pipe);
struct aapoint_fragment_shader *aafs = (struct aapoint_fragment_shader *) fs;
/* save current */
aapoint->fs = aafs;
/* pass-through */
aapoint->driver_bind_fs_state(pipe,
(aafs ? aafs->driver_fs : NULL));
}
 
 
static void
aapoint_delete_fs_state(struct pipe_context *pipe, void *fs)
{
struct aapoint_stage *aapoint = aapoint_stage_from_pipe(pipe);
struct aapoint_fragment_shader *aafs = (struct aapoint_fragment_shader *) fs;
 
/* pass-through */
aapoint->driver_delete_fs_state(pipe, aafs->driver_fs);
 
if (aafs->aapoint_fs)
aapoint->driver_delete_fs_state(pipe, aafs->aapoint_fs);
 
FREE((void*)aafs->state.tokens);
 
FREE(aafs);
}
 
 
/**
* Called by drivers that want to install this AA point prim stage
* into the draw module's pipeline. This will not be used if the
* hardware has native support for AA points.
*/
boolean
draw_install_aapoint_stage(struct draw_context *draw,
struct pipe_context *pipe)
{
struct aapoint_stage *aapoint;
 
pipe->draw = (void *) draw;
 
/*
* Create / install AA point drawing / prim stage
*/
aapoint = draw_aapoint_stage( draw );
if (aapoint == NULL)
return FALSE;
 
/* save original driver functions */
aapoint->driver_create_fs_state = pipe->create_fs_state;
aapoint->driver_bind_fs_state = pipe->bind_fs_state;
aapoint->driver_delete_fs_state = pipe->delete_fs_state;
 
/* override the driver's functions */
pipe->create_fs_state = aapoint_create_fs_state;
pipe->bind_fs_state = aapoint_bind_fs_state;
pipe->delete_fs_state = aapoint_delete_fs_state;
 
draw->pipeline.aapoint = &aapoint->stage;
 
return TRUE;
}
/drivers/video/Gallium/auxiliary/draw/draw_pipe_clip.c
0,0 → 1,777
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/**
* \brief Clipping stage
*
* \author Keith Whitwell <keith@tungstengraphics.com>
*/
 
 
#include "util/u_memory.h"
#include "util/u_math.h"
 
#include "pipe/p_shader_tokens.h"
 
#include "draw_vs.h"
#include "draw_pipe.h"
#include "draw_fs.h"
#include "draw_gs.h"
 
 
/** Set to 1 to enable printing of coords before/after clipping */
#define DEBUG_CLIP 0
 
 
#ifndef IS_NEGATIVE
#define IS_NEGATIVE(X) ((X) < 0.0)
#endif
 
#ifndef DIFFERENT_SIGNS
#define DIFFERENT_SIGNS(x, y) ((x) * (y) <= 0.0F && (x) - (y) != 0.0F)
#endif
 
#define MAX_CLIPPED_VERTICES ((2 * (6 + PIPE_MAX_CLIP_PLANES))+1)
 
 
 
struct clip_stage {
struct draw_stage stage; /**< base class */
 
/* List of the attributes to be flatshaded. */
uint num_flat_attribs;
uint flat_attribs[PIPE_MAX_SHADER_OUTPUTS];
 
/* Mask of attributes in noperspective mode */
boolean noperspective_attribs[PIPE_MAX_SHADER_OUTPUTS];
 
float (*plane)[4];
};
 
 
/** Cast wrapper */
static INLINE struct clip_stage *clip_stage( struct draw_stage *stage )
{
return (struct clip_stage *)stage;
}
 
static INLINE unsigned
draw_viewport_index(struct draw_context *draw,
const struct vertex_header *leading_vertex)
{
if (draw_current_shader_uses_viewport_index(draw)) {
unsigned viewport_index_output =
draw_current_shader_viewport_index_output(draw);
unsigned viewport_index =
*((unsigned*)leading_vertex->data[viewport_index_output]);
return draw_clamp_viewport_idx(viewport_index);
} else {
return 0;
}
}
 
 
#define LINTERP(T, OUT, IN) ((OUT) + (T) * ((IN) - (OUT)))
 
 
/* All attributes are float[4], so this is easy:
*/
static void interp_attr( float dst[4],
float t,
const float in[4],
const float out[4] )
{
dst[0] = LINTERP( t, out[0], in[0] );
dst[1] = LINTERP( t, out[1], in[1] );
dst[2] = LINTERP( t, out[2], in[2] );
dst[3] = LINTERP( t, out[3], in[3] );
}
 
 
/**
* Copy flat shaded attributes src vertex to dst vertex.
*/
static void copy_flat( struct draw_stage *stage,
struct vertex_header *dst,
const struct vertex_header *src )
{
const struct clip_stage *clipper = clip_stage(stage);
uint i;
for (i = 0; i < clipper->num_flat_attribs; i++) {
const uint attr = clipper->flat_attribs[i];
COPY_4FV(dst->data[attr], src->data[attr]);
}
}
 
/* Interpolate between two vertices to produce a third.
*/
static void interp( const struct clip_stage *clip,
struct vertex_header *dst,
float t,
const struct vertex_header *out,
const struct vertex_header *in,
unsigned viewport_index )
{
const unsigned nr_attrs = draw_current_shader_outputs(clip->stage.draw);
const unsigned pos_attr = draw_current_shader_position_output(clip->stage.draw);
const unsigned clip_attr = draw_current_shader_clipvertex_output(clip->stage.draw);
unsigned j;
float t_nopersp;
 
/* Vertex header.
*/
dst->clipmask = 0;
dst->edgeflag = 0; /* will get overwritten later */
dst->have_clipdist = in->have_clipdist;
dst->vertex_id = UNDEFINED_VERTEX_ID;
 
/* Interpolate the clip-space coords.
*/
interp_attr(dst->clip, t, in->clip, out->clip);
/* interpolate the clip-space position */
interp_attr(dst->pre_clip_pos, t, in->pre_clip_pos, out->pre_clip_pos);
 
/* Do the projective divide and viewport transformation to get
* new window coordinates:
*/
{
const float *pos = dst->pre_clip_pos;
const float *scale =
clip->stage.draw->viewports[viewport_index].scale;
const float *trans =
clip->stage.draw->viewports[viewport_index].translate;
const float oow = 1.0f / pos[3];
 
dst->data[pos_attr][0] = pos[0] * oow * scale[0] + trans[0];
dst->data[pos_attr][1] = pos[1] * oow * scale[1] + trans[1];
dst->data[pos_attr][2] = pos[2] * oow * scale[2] + trans[2];
dst->data[pos_attr][3] = oow;
}
/**
* Compute the t in screen-space instead of 3d space to use
* for noperspective interpolation.
*
* The points can be aligned with the X axis, so in that case try
* the Y. When both points are at the same screen position, we can
* pick whatever value (the interpolated point won't be in front
* anyway), so just use the 3d t.
*/
{
int k;
t_nopersp = t;
/* find either in.x != out.x or in.y != out.y */
for (k = 0; k < 2; k++) {
if (in->clip[k] != out->clip[k]) {
/* do divide by W, then compute linear interpolation factor */
float in_coord = in->clip[k] / in->clip[3];
float out_coord = out->clip[k] / out->clip[3];
float dst_coord = dst->clip[k] / dst->clip[3];
t_nopersp = (dst_coord - out_coord) / (in_coord - out_coord);
break;
}
}
}
 
/* Other attributes
*/
for (j = 0; j < nr_attrs; j++) {
if (j != pos_attr && j != clip_attr) {
if (clip->noperspective_attribs[j])
interp_attr(dst->data[j], t_nopersp, in->data[j], out->data[j]);
else
interp_attr(dst->data[j], t, in->data[j], out->data[j]);
}
}
}
 
 
/**
* Emit a post-clip polygon to the next pipeline stage. The polygon
* will be convex and the provoking vertex will always be vertex[0].
*/
static void emit_poly( struct draw_stage *stage,
struct vertex_header **inlist,
const boolean *edgeflags,
unsigned n,
const struct prim_header *origPrim)
{
struct prim_header header;
unsigned i;
ushort edge_first, edge_middle, edge_last;
 
if (stage->draw->rasterizer->flatshade_first) {
edge_first = DRAW_PIPE_EDGE_FLAG_0;
edge_middle = DRAW_PIPE_EDGE_FLAG_1;
edge_last = DRAW_PIPE_EDGE_FLAG_2;
}
else {
edge_first = DRAW_PIPE_EDGE_FLAG_2;
edge_middle = DRAW_PIPE_EDGE_FLAG_0;
edge_last = DRAW_PIPE_EDGE_FLAG_1;
}
 
if (!edgeflags[0])
edge_first = 0;
 
/* later stages may need the determinant, but only the sign matters */
header.det = origPrim->det;
header.flags = DRAW_PIPE_RESET_STIPPLE | edge_first | edge_middle;
header.pad = 0;
 
for (i = 2; i < n; i++, header.flags = edge_middle) {
/* order the triangle verts to respect the provoking vertex mode */
if (stage->draw->rasterizer->flatshade_first) {
header.v[0] = inlist[0]; /* the provoking vertex */
header.v[1] = inlist[i-1];
header.v[2] = inlist[i];
}
else {
header.v[0] = inlist[i-1];
header.v[1] = inlist[i];
header.v[2] = inlist[0]; /* the provoking vertex */
}
 
if (!edgeflags[i-1]) {
header.flags &= ~edge_middle;
}
 
if (i == n - 1 && edgeflags[i])
header.flags |= edge_last;
 
if (DEBUG_CLIP) {
const struct draw_vertex_shader *vs = stage->draw->vs.vertex_shader;
uint j, k;
debug_printf("Clipped tri: (flat-shade-first = %d)\n",
stage->draw->rasterizer->flatshade_first);
for (j = 0; j < 3; j++) {
debug_printf(" Vert %d: clip: %f %f %f %f\n", j,
header.v[j]->clip[0],
header.v[j]->clip[1],
header.v[j]->clip[2],
header.v[j]->clip[3]);
for (k = 0; k < vs->info.num_outputs; k++) {
debug_printf(" Vert %d: Attr %d: %f %f %f %f\n", j, k,
header.v[j]->data[k][0],
header.v[j]->data[k][1],
header.v[j]->data[k][2],
header.v[j]->data[k][3]);
}
}
}
 
stage->next->tri( stage->next, &header );
}
}
 
 
static INLINE float
dot4(const float *a, const float *b)
{
return (a[0] * b[0] +
a[1] * b[1] +
a[2] * b[2] +
a[3] * b[3]);
}
 
/*
* this function extracts the clip distance for the current plane,
* it first checks if the shader provided a clip distance, otherwise
* it works out the value using the clipvertex
*/
static INLINE float getclipdist(const struct clip_stage *clipper,
struct vertex_header *vert,
int plane_idx)
{
const float *plane;
float dp;
if (vert->have_clipdist && plane_idx >= 6) {
/* pick the correct clipdistance element from the output vectors */
int _idx = plane_idx - 6;
int cdi = _idx >= 4;
int vidx = cdi ? _idx - 4 : _idx;
dp = vert->data[draw_current_shader_clipdistance_output(clipper->stage.draw, cdi)][vidx];
} else {
plane = clipper->plane[plane_idx];
dp = dot4(vert->clip, plane);
}
return dp;
}
 
/* Clip a triangle against the viewport and user clip planes.
*/
static void
do_clip_tri( struct draw_stage *stage,
struct prim_header *header,
unsigned clipmask )
{
struct clip_stage *clipper = clip_stage( stage );
struct vertex_header *a[MAX_CLIPPED_VERTICES];
struct vertex_header *b[MAX_CLIPPED_VERTICES];
struct vertex_header **inlist = a;
struct vertex_header **outlist = b;
unsigned tmpnr = 0;
unsigned n = 3;
unsigned i;
boolean aEdges[MAX_CLIPPED_VERTICES];
boolean bEdges[MAX_CLIPPED_VERTICES];
boolean *inEdges = aEdges;
boolean *outEdges = bEdges;
int viewport_index = 0;
 
inlist[0] = header->v[0];
inlist[1] = header->v[1];
inlist[2] = header->v[2];
 
viewport_index = draw_viewport_index(clipper->stage.draw, inlist[0]);
 
if (DEBUG_CLIP) {
const float *v0 = header->v[0]->clip;
const float *v1 = header->v[1]->clip;
const float *v2 = header->v[2]->clip;
debug_printf("Clip triangle:\n");
debug_printf(" %f, %f, %f, %f\n", v0[0], v0[1], v0[2], v0[3]);
debug_printf(" %f, %f, %f, %f\n", v1[0], v1[1], v1[2], v1[3]);
debug_printf(" %f, %f, %f, %f\n", v2[0], v2[1], v2[2], v2[3]);
}
 
/*
* Note: at this point we can't just use the per-vertex edge flags.
* We have to observe the edge flag bits set in header->flags which
* were set during primitive decomposition. Put those flags into
* an edge flags array which parallels the vertex array.
* Later, in the 'unfilled' pipeline stage we'll draw the edge if both
* the header.flags bit is set AND the per-vertex edgeflag field is set.
*/
inEdges[0] = !!(header->flags & DRAW_PIPE_EDGE_FLAG_0);
inEdges[1] = !!(header->flags & DRAW_PIPE_EDGE_FLAG_1);
inEdges[2] = !!(header->flags & DRAW_PIPE_EDGE_FLAG_2);
 
while (clipmask && n >= 3) {
const unsigned plane_idx = ffs(clipmask)-1;
const boolean is_user_clip_plane = plane_idx >= 6;
struct vertex_header *vert_prev = inlist[0];
boolean *edge_prev = &inEdges[0];
float dp_prev;
unsigned outcount = 0;
 
dp_prev = getclipdist(clipper, vert_prev, plane_idx);
clipmask &= ~(1<<plane_idx);
 
assert(n < MAX_CLIPPED_VERTICES);
if (n >= MAX_CLIPPED_VERTICES)
return;
inlist[n] = inlist[0]; /* prevent rotation of vertices */
inEdges[n] = inEdges[0];
 
for (i = 1; i <= n; i++) {
struct vertex_header *vert = inlist[i];
boolean *edge = &inEdges[i];
 
float dp = getclipdist(clipper, vert, plane_idx);
 
if (!IS_NEGATIVE(dp_prev)) {
assert(outcount < MAX_CLIPPED_VERTICES);
if (outcount >= MAX_CLIPPED_VERTICES)
return;
outEdges[outcount] = *edge_prev;
outlist[outcount++] = vert_prev;
}
 
if (DIFFERENT_SIGNS(dp, dp_prev)) {
struct vertex_header *new_vert;
boolean *new_edge;
 
assert(tmpnr < MAX_CLIPPED_VERTICES + 1);
if (tmpnr >= MAX_CLIPPED_VERTICES + 1)
return;
new_vert = clipper->stage.tmp[tmpnr++];
 
assert(outcount < MAX_CLIPPED_VERTICES);
if (outcount >= MAX_CLIPPED_VERTICES)
return;
 
new_edge = &outEdges[outcount];
outlist[outcount++] = new_vert;
 
if (IS_NEGATIVE(dp)) {
/* Going out of bounds. Avoid division by zero as we
* know dp != dp_prev from DIFFERENT_SIGNS, above.
*/
float t = dp / (dp - dp_prev);
interp( clipper, new_vert, t, vert, vert_prev, viewport_index );
/* Whether or not to set edge flag for the new vert depends
* on whether it's a user-defined clipping plane. We're
* copying NVIDIA's behaviour here.
*/
if (is_user_clip_plane) {
/* we want to see an edge along the clip plane */
*new_edge = TRUE;
new_vert->edgeflag = TRUE;
}
else {
/* we don't want to see an edge along the frustum clip plane */
*new_edge = *edge_prev;
new_vert->edgeflag = FALSE;
}
}
else {
/* Coming back in.
*/
float t = dp_prev / (dp_prev - dp);
interp( clipper, new_vert, t, vert_prev, vert, viewport_index );
 
/* Copy starting vert's edgeflag:
*/
new_vert->edgeflag = vert_prev->edgeflag;
*new_edge = *edge_prev;
}
}
 
vert_prev = vert;
edge_prev = edge;
dp_prev = dp;
}
 
/* swap in/out lists */
{
struct vertex_header **tmp = inlist;
inlist = outlist;
outlist = tmp;
n = outcount;
}
{
boolean *tmp = inEdges;
inEdges = outEdges;
outEdges = tmp;
}
 
}
 
/* If flat-shading, copy provoking vertex color to polygon vertex[0]
*/
if (n >= 3) {
if (clipper->num_flat_attribs) {
if (stage->draw->rasterizer->flatshade_first) {
if (inlist[0] != header->v[0]) {
assert(tmpnr < MAX_CLIPPED_VERTICES + 1);
if (tmpnr >= MAX_CLIPPED_VERTICES + 1)
return;
inlist[0] = dup_vert(stage, inlist[0], tmpnr++);
copy_flat(stage, inlist[0], header->v[0]);
}
}
else {
if (inlist[0] != header->v[2]) {
assert(tmpnr < MAX_CLIPPED_VERTICES + 1);
if (tmpnr >= MAX_CLIPPED_VERTICES + 1)
return;
inlist[0] = dup_vert(stage, inlist[0], tmpnr++);
copy_flat(stage, inlist[0], header->v[2]);
}
}
}
/* Emit the polygon as triangles to the setup stage:
*/
emit_poly( stage, inlist, inEdges, n, header );
}
}
 
 
/* Clip a line against the viewport and user clip planes.
*/
static void
do_clip_line( struct draw_stage *stage,
struct prim_header *header,
unsigned clipmask )
{
const struct clip_stage *clipper = clip_stage( stage );
struct vertex_header *v0 = header->v[0];
struct vertex_header *v1 = header->v[1];
float t0 = 0.0F;
float t1 = 0.0F;
struct prim_header newprim;
int viewport_index = draw_viewport_index(clipper->stage.draw, v0);
 
while (clipmask) {
const unsigned plane_idx = ffs(clipmask)-1;
const float dp0 = getclipdist(clipper, v0, plane_idx);
const float dp1 = getclipdist(clipper, v1, plane_idx);
 
if (dp1 < 0.0F) {
float t = dp1 / (dp1 - dp0);
t1 = MAX2(t1, t);
}
 
if (dp0 < 0.0F) {
float t = dp0 / (dp0 - dp1);
t0 = MAX2(t0, t);
}
 
if (t0 + t1 >= 1.0F)
return; /* discard */
 
clipmask &= ~(1 << plane_idx); /* turn off this plane's bit */
}
 
if (v0->clipmask) {
interp( clipper, stage->tmp[0], t0, v0, v1, viewport_index );
copy_flat(stage, stage->tmp[0], v0);
newprim.v[0] = stage->tmp[0];
}
else {
newprim.v[0] = v0;
}
 
if (v1->clipmask) {
interp( clipper, stage->tmp[1], t1, v1, v0, viewport_index );
newprim.v[1] = stage->tmp[1];
}
else {
newprim.v[1] = v1;
}
 
stage->next->line( stage->next, &newprim );
}
 
 
static void
clip_point( struct draw_stage *stage,
struct prim_header *header )
{
if (header->v[0]->clipmask == 0)
stage->next->point( stage->next, header );
}
 
 
static void
clip_line( struct draw_stage *stage,
struct prim_header *header )
{
unsigned clipmask = (header->v[0]->clipmask |
header->v[1]->clipmask);
if (clipmask == 0) {
/* no clipping needed */
stage->next->line( stage->next, header );
}
else if ((header->v[0]->clipmask &
header->v[1]->clipmask) == 0) {
do_clip_line(stage, header, clipmask);
}
/* else, totally clipped */
}
 
 
static void
clip_tri( struct draw_stage *stage,
struct prim_header *header )
{
unsigned clipmask = (header->v[0]->clipmask |
header->v[1]->clipmask |
header->v[2]->clipmask);
if (clipmask == 0) {
/* no clipping needed */
stage->next->tri( stage->next, header );
}
else if ((header->v[0]->clipmask &
header->v[1]->clipmask &
header->v[2]->clipmask) == 0) {
do_clip_tri(stage, header, clipmask);
}
}
 
 
/* Update state. Could further delay this until we hit the first
* primitive that really requires clipping.
*/
static void
clip_init_state( struct draw_stage *stage )
{
struct clip_stage *clipper = clip_stage( stage );
const struct draw_vertex_shader *vs = stage->draw->vs.vertex_shader;
const struct draw_geometry_shader *gs = stage->draw->gs.geometry_shader;
const struct draw_fragment_shader *fs = stage->draw->fs.fragment_shader;
uint i;
const struct tgsi_shader_info *vs_info = gs ? &gs->info : &vs->info;
 
/* We need to know for each attribute what kind of interpolation is
* done on it (flat, smooth or noperspective). But the information
* is not directly accessible for outputs, only for inputs. So we
* have to match semantic name and index between the VS (or GS/ES)
* outputs and the FS inputs to get to the interpolation mode.
*
* The only hitch is with gl_FrontColor/gl_BackColor which map to
* gl_Color, and their Secondary versions. First there are (up to)
* two outputs for one input, so we tuck the information in a
* specific array. Second if they don't have qualifiers, the
* default value has to be picked from the global shade mode.
*
* Of course, if we don't have a fragment shader in the first
* place, defaults should be used.
*/
 
/* First pick up the interpolation mode for
* gl_Color/gl_SecondaryColor, with the correct default.
*/
int indexed_interp[2];
indexed_interp[0] = indexed_interp[1] = stage->draw->rasterizer->flatshade ?
TGSI_INTERPOLATE_CONSTANT : TGSI_INTERPOLATE_PERSPECTIVE;
 
if (fs) {
for (i = 0; i < fs->info.num_inputs; i++) {
if (fs->info.input_semantic_name[i] == TGSI_SEMANTIC_COLOR) {
if (fs->info.input_interpolate[i] != TGSI_INTERPOLATE_COLOR)
indexed_interp[fs->info.input_semantic_index[i]] = fs->info.input_interpolate[i];
}
}
}
 
/* Then resolve the interpolation mode for every output attribute.
*
* Given how the rest of the code, the most efficient way is to
* have a vector of flat-mode attributes, and a mask for
* noperspective attributes.
*/
 
clipper->num_flat_attribs = 0;
memset(clipper->noperspective_attribs, 0, sizeof(clipper->noperspective_attribs));
for (i = 0; i < vs_info->num_outputs; i++) {
/* Find the interpolation mode for a specific attribute
*/
int interp;
 
/* If it's gl_{Front,Back}{,Secondary}Color, pick up the mode
* from the array we've filled before. */
if (vs_info->output_semantic_name[i] == TGSI_SEMANTIC_COLOR ||
vs_info->output_semantic_name[i] == TGSI_SEMANTIC_BCOLOR) {
interp = indexed_interp[vs_info->output_semantic_index[i]];
} else {
/* Otherwise, search in the FS inputs, with a decent default
* if we don't find it.
*/
uint j;
interp = TGSI_INTERPOLATE_PERSPECTIVE;
if (fs) {
for (j = 0; j < fs->info.num_inputs; j++) {
if (vs_info->output_semantic_name[i] == fs->info.input_semantic_name[j] &&
vs_info->output_semantic_index[i] == fs->info.input_semantic_index[j]) {
interp = fs->info.input_interpolate[j];
break;
}
}
}
}
 
/* If it's flat, add it to the flat vector. Otherwise update
* the noperspective mask.
*/
if (interp == TGSI_INTERPOLATE_CONSTANT) {
clipper->flat_attribs[clipper->num_flat_attribs] = i;
clipper->num_flat_attribs++;
} else
clipper->noperspective_attribs[i] = interp == TGSI_INTERPOLATE_LINEAR;
}
stage->tri = clip_tri;
stage->line = clip_line;
}
 
 
 
static void clip_first_tri( struct draw_stage *stage,
struct prim_header *header )
{
clip_init_state( stage );
stage->tri( stage, header );
}
 
static void clip_first_line( struct draw_stage *stage,
struct prim_header *header )
{
clip_init_state( stage );
stage->line( stage, header );
}
 
 
static void clip_flush( struct draw_stage *stage,
unsigned flags )
{
stage->tri = clip_first_tri;
stage->line = clip_first_line;
stage->next->flush( stage->next, flags );
}
 
 
static void clip_reset_stipple_counter( struct draw_stage *stage )
{
stage->next->reset_stipple_counter( stage->next );
}
 
 
static void clip_destroy( struct draw_stage *stage )
{
draw_free_temp_verts( stage );
FREE( stage );
}
 
 
/**
* Allocate a new clipper stage.
* \return pointer to new stage object
*/
struct draw_stage *draw_clip_stage( struct draw_context *draw )
{
struct clip_stage *clipper = CALLOC_STRUCT(clip_stage);
if (clipper == NULL)
goto fail;
 
clipper->stage.draw = draw;
clipper->stage.name = "clipper";
clipper->stage.point = clip_point;
clipper->stage.line = clip_first_line;
clipper->stage.tri = clip_first_tri;
clipper->stage.flush = clip_flush;
clipper->stage.reset_stipple_counter = clip_reset_stipple_counter;
clipper->stage.destroy = clip_destroy;
 
clipper->plane = draw->plane;
 
if (!draw_alloc_temp_verts( &clipper->stage, MAX_CLIPPED_VERTICES+1 ))
goto fail;
 
return &clipper->stage;
 
fail:
if (clipper)
clipper->stage.destroy( &clipper->stage );
 
return NULL;
}
/drivers/video/Gallium/auxiliary/draw/draw_pipe_cull.c
0,0 → 1,277
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/**
* \brief Drawing stage for polygon culling
*/
 
/* Authors: Keith Whitwell <keith@tungstengraphics.com>
*/
 
 
#include "util/u_math.h"
#include "util/u_memory.h"
#include "pipe/p_defines.h"
#include "draw_pipe.h"
 
 
struct cull_stage {
struct draw_stage stage;
unsigned cull_face; /**< which face(s) to cull (one of PIPE_FACE_x) */
unsigned front_ccw;
};
 
 
static INLINE struct cull_stage *cull_stage( struct draw_stage *stage )
{
return (struct cull_stage *)stage;
}
 
static INLINE boolean
cull_distance_is_out(float dist)
{
return (dist < 0.0f) || util_is_inf_or_nan(dist);
}
 
/*
* If the shader writes the culldistance then we can
* perform distance based culling. Distance based
* culling doesn't require a face and can be performed
* on primitives without faces (e.g. points and lines)
*/
static void cull_point( struct draw_stage *stage,
struct prim_header *header )
{
const unsigned num_written_culldistances =
draw_current_shader_num_written_culldistances(stage->draw);
unsigned i;
 
debug_assert(num_written_culldistances);
 
for (i = 0; i < num_written_culldistances; ++i) {
unsigned cull_idx = i / 4;
unsigned out_idx =
draw_current_shader_culldistance_output(stage->draw, cull_idx);
unsigned idx = i % 4;
float cull1 = header->v[0]->data[out_idx][idx];
boolean vert1_out = cull_distance_is_out(cull1);
if (vert1_out)
return;
}
stage->next->point( stage->next, header );
}
 
/*
* If the shader writes the culldistance then we can
* perform distance based culling. Distance based
* culling doesn't require a face and can be performed
* on primitives without faces (e.g. points and lines)
*/
static void cull_line( struct draw_stage *stage,
struct prim_header *header )
{
const unsigned num_written_culldistances =
draw_current_shader_num_written_culldistances(stage->draw);
unsigned i;
 
debug_assert(num_written_culldistances);
 
for (i = 0; i < num_written_culldistances; ++i) {
unsigned cull_idx = i / 4;
unsigned out_idx =
draw_current_shader_culldistance_output(stage->draw, cull_idx);
unsigned idx = i % 4;
float cull1 = header->v[0]->data[out_idx][idx];
float cull2 = header->v[1]->data[out_idx][idx];
boolean vert1_out = cull_distance_is_out(cull1);
boolean vert2_out = cull_distance_is_out(cull2);
if (vert1_out && vert2_out)
return;
}
stage->next->line( stage->next, header );
}
 
/*
* Triangles can be culled either using the cull distance
* shader outputs or the regular face culling. If required
* this function performs both, starting with distance culling.
*/
static void cull_tri( struct draw_stage *stage,
struct prim_header *header )
{
const unsigned num_written_culldistances =
draw_current_shader_num_written_culldistances(stage->draw);
 
/* Do the distance culling */
if (num_written_culldistances) {
unsigned i;
for (i = 0; i < num_written_culldistances; ++i) {
unsigned cull_idx = i / 4;
unsigned out_idx =
draw_current_shader_culldistance_output(stage->draw, cull_idx);
unsigned idx = i % 4;
float cull1 = header->v[0]->data[out_idx][idx];
float cull2 = header->v[1]->data[out_idx][idx];
float cull3 = header->v[2]->data[out_idx][idx];
boolean vert1_out = cull_distance_is_out(cull1);
boolean vert2_out = cull_distance_is_out(cull2);
boolean vert3_out = cull_distance_is_out(cull3);
if (vert1_out && vert2_out && vert3_out)
return;
}
}
 
/* Do the regular face culling */
{
const unsigned pos = draw_current_shader_position_output(stage->draw);
/* Window coords: */
const float *v0 = header->v[0]->data[pos];
const float *v1 = header->v[1]->data[pos];
const float *v2 = header->v[2]->data[pos];
 
/* edge vectors: e = v0 - v2, f = v1 - v2 */
const float ex = v0[0] - v2[0];
const float ey = v0[1] - v2[1];
const float fx = v1[0] - v2[0];
const float fy = v1[1] - v2[1];
 
 
/* det = cross(e,f).z */
header->det = ex * fy - ey * fx;
 
if (header->det != 0) {
/* if det < 0 then Z points toward the camera and the triangle is
* counter-clockwise winding.
*/
unsigned ccw = (header->det < 0);
unsigned face = ((ccw == cull_stage(stage)->front_ccw) ?
PIPE_FACE_FRONT :
PIPE_FACE_BACK);
 
if ((face & cull_stage(stage)->cull_face) == 0) {
/* triangle is not culled, pass to next stage */
stage->next->tri( stage->next, header );
}
}
}
}
 
static void cull_first_point( struct draw_stage *stage,
struct prim_header *header )
{
const unsigned num_written_culldistances =
draw_current_shader_num_written_culldistances(stage->draw);
 
if (num_written_culldistances) {
stage->point = cull_point;
stage->point( stage, header );
} else {
stage->point = draw_pipe_passthrough_point;
stage->point( stage, header );
}
}
 
static void cull_first_line( struct draw_stage *stage,
struct prim_header *header )
{
const unsigned num_written_culldistances =
draw_current_shader_num_written_culldistances(stage->draw);
 
if (num_written_culldistances) {
stage->line = cull_line;
stage->line( stage, header );
} else {
stage->line = draw_pipe_passthrough_line;
stage->line( stage, header );
}
}
 
static void cull_first_tri( struct draw_stage *stage,
struct prim_header *header )
{
struct cull_stage *cull = cull_stage(stage);
 
cull->cull_face = stage->draw->rasterizer->cull_face;
cull->front_ccw = stage->draw->rasterizer->front_ccw;
 
stage->tri = cull_tri;
stage->tri( stage, header );
}
 
 
static void cull_flush( struct draw_stage *stage, unsigned flags )
{
stage->point = cull_first_point;
stage->line = cull_first_line;
stage->tri = cull_first_tri;
stage->next->flush( stage->next, flags );
}
 
 
static void cull_reset_stipple_counter( struct draw_stage *stage )
{
stage->next->reset_stipple_counter( stage->next );
}
 
 
static void cull_destroy( struct draw_stage *stage )
{
draw_free_temp_verts( stage );
FREE( stage );
}
 
 
/**
* Create a new polygon culling stage.
*/
struct draw_stage *draw_cull_stage( struct draw_context *draw )
{
struct cull_stage *cull = CALLOC_STRUCT(cull_stage);
if (cull == NULL)
goto fail;
 
cull->stage.draw = draw;
cull->stage.name = "cull";
cull->stage.next = NULL;
cull->stage.point = cull_first_point;
cull->stage.line = cull_first_line;
cull->stage.tri = cull_first_tri;
cull->stage.flush = cull_flush;
cull->stage.reset_stipple_counter = cull_reset_stipple_counter;
cull->stage.destroy = cull_destroy;
 
if (!draw_alloc_temp_verts( &cull->stage, 0 ))
goto fail;
 
return &cull->stage;
 
fail:
if (cull)
cull->stage.destroy( &cull->stage );
 
return NULL;
}
/drivers/video/Gallium/auxiliary/draw/draw_pipe_flatshade.c
0,0 → 1,282
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/* Authors: Keith Whitwell <keith@tungstengraphics.com>
*/
 
#include "util/u_math.h"
#include "util/u_memory.h"
 
#include "pipe/p_shader_tokens.h"
#include "draw_vs.h"
#include "draw_pipe.h"
 
 
/** subclass of draw_stage */
struct flat_stage
{
struct draw_stage stage;
 
uint num_color_attribs;
uint color_attribs[2]; /* front/back primary colors */
 
uint num_spec_attribs;
uint spec_attribs[2]; /* front/back secondary colors */
};
 
#define COPY_3FV( DST, SRC ) \
do { \
(DST)[0] = (SRC)[0]; \
(DST)[1] = (SRC)[1]; \
(DST)[2] = (SRC)[2]; \
} while (0)
 
 
static INLINE struct flat_stage *
flat_stage(struct draw_stage *stage)
{
return (struct flat_stage *) stage;
}
 
 
/** Copy all the color attributes from 'src' vertex to 'dst' vertex */
static INLINE void copy_colors( struct draw_stage *stage,
struct vertex_header *dst,
const struct vertex_header *src )
{
const struct flat_stage *flat = flat_stage(stage);
uint i;
 
for (i = 0; i < flat->num_color_attribs; i++) {
const uint attr = flat->color_attribs[i];
COPY_4FV(dst->data[attr], src->data[attr]);
}
 
for (i = 0; i < flat->num_spec_attribs; i++) {
const uint attr = flat->spec_attribs[i];
COPY_3FV(dst->data[attr], src->data[attr]);
}
}
 
 
/** Copy all the color attributes from src vertex to dst0 & dst1 vertices */
static INLINE void copy_colors2( struct draw_stage *stage,
struct vertex_header *dst0,
struct vertex_header *dst1,
const struct vertex_header *src )
{
const struct flat_stage *flat = flat_stage(stage);
uint i;
for (i = 0; i < flat->num_color_attribs; i++) {
const uint attr = flat->color_attribs[i];
COPY_4FV(dst0->data[attr], src->data[attr]);
COPY_4FV(dst1->data[attr], src->data[attr]);
}
 
for (i = 0; i < flat->num_spec_attribs; i++) {
const uint attr = flat->spec_attribs[i];
COPY_3FV(dst0->data[attr], src->data[attr]);
COPY_3FV(dst1->data[attr], src->data[attr]);
}
}
 
 
/**
* Flatshade tri. Required for clipping and when unfilled tris are
* active, otherwise handled by hardware.
*/
static void flatshade_tri_0( struct draw_stage *stage,
struct prim_header *header )
{
struct prim_header tmp;
 
tmp.det = header->det;
tmp.flags = header->flags;
tmp.pad = header->pad;
tmp.v[0] = header->v[0];
tmp.v[1] = dup_vert(stage, header->v[1], 0);
tmp.v[2] = dup_vert(stage, header->v[2], 1);
 
copy_colors2(stage, tmp.v[1], tmp.v[2], tmp.v[0]);
stage->next->tri( stage->next, &tmp );
}
 
 
static void flatshade_tri_2( struct draw_stage *stage,
struct prim_header *header )
{
struct prim_header tmp;
 
tmp.det = header->det;
tmp.flags = header->flags;
tmp.pad = header->pad;
tmp.v[0] = dup_vert(stage, header->v[0], 0);
tmp.v[1] = dup_vert(stage, header->v[1], 1);
tmp.v[2] = header->v[2];
 
copy_colors2(stage, tmp.v[0], tmp.v[1], tmp.v[2]);
stage->next->tri( stage->next, &tmp );
}
 
 
 
 
 
/**
* Flatshade line. Required for clipping.
*/
static void flatshade_line_0( struct draw_stage *stage,
struct prim_header *header )
{
struct prim_header tmp;
 
tmp.v[0] = header->v[0];
tmp.v[1] = dup_vert(stage, header->v[1], 0);
 
copy_colors(stage, tmp.v[1], tmp.v[0]);
stage->next->line( stage->next, &tmp );
}
 
static void flatshade_line_1( struct draw_stage *stage,
struct prim_header *header )
{
struct prim_header tmp;
 
tmp.v[0] = dup_vert(stage, header->v[0], 0);
tmp.v[1] = header->v[1];
 
copy_colors(stage, tmp.v[0], tmp.v[1]);
stage->next->line( stage->next, &tmp );
}
 
 
 
 
static void flatshade_init_state( struct draw_stage *stage )
{
struct flat_stage *flat = flat_stage(stage);
const struct draw_vertex_shader *vs = stage->draw->vs.vertex_shader;
uint i;
 
/* Find which vertex shader outputs are colors, make a list */
flat->num_color_attribs = 0;
flat->num_spec_attribs = 0;
for (i = 0; i < vs->info.num_outputs; i++) {
if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_COLOR ||
vs->info.output_semantic_name[i] == TGSI_SEMANTIC_BCOLOR) {
if (vs->info.output_semantic_index[i] == 0)
flat->color_attribs[flat->num_color_attribs++] = i;
else
flat->spec_attribs[flat->num_spec_attribs++] = i;
}
}
 
/* Choose flatshade routine according to provoking vertex:
*/
if (stage->draw->rasterizer->flatshade_first) {
stage->line = flatshade_line_0;
stage->tri = flatshade_tri_0;
}
else {
stage->line = flatshade_line_1;
stage->tri = flatshade_tri_2;
}
}
 
static void flatshade_first_tri( struct draw_stage *stage,
struct prim_header *header )
{
flatshade_init_state( stage );
stage->tri( stage, header );
}
 
static void flatshade_first_line( struct draw_stage *stage,
struct prim_header *header )
{
flatshade_init_state( stage );
stage->line( stage, header );
}
 
 
static void flatshade_flush( struct draw_stage *stage,
unsigned flags )
{
stage->tri = flatshade_first_tri;
stage->line = flatshade_first_line;
stage->next->flush( stage->next, flags );
}
 
 
static void flatshade_reset_stipple_counter( struct draw_stage *stage )
{
stage->next->reset_stipple_counter( stage->next );
}
 
 
static void flatshade_destroy( struct draw_stage *stage )
{
draw_free_temp_verts( stage );
FREE( stage );
}
 
 
/**
* Create flatshading drawing stage.
*/
struct draw_stage *draw_flatshade_stage( struct draw_context *draw )
{
struct flat_stage *flatshade = CALLOC_STRUCT(flat_stage);
if (flatshade == NULL)
goto fail;
 
flatshade->stage.draw = draw;
flatshade->stage.name = "flatshade";
flatshade->stage.next = NULL;
flatshade->stage.point = draw_pipe_passthrough_point;
flatshade->stage.line = flatshade_first_line;
flatshade->stage.tri = flatshade_first_tri;
flatshade->stage.flush = flatshade_flush;
flatshade->stage.reset_stipple_counter = flatshade_reset_stipple_counter;
flatshade->stage.destroy = flatshade_destroy;
 
if (!draw_alloc_temp_verts( &flatshade->stage, 2 ))
goto fail;
 
return &flatshade->stage;
 
fail:
if (flatshade)
flatshade->stage.destroy( &flatshade->stage );
 
return NULL;
}
 
 
/drivers/video/Gallium/auxiliary/draw/draw_pipe_offset.c
0,0 → 1,226
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/**
* \brief polygon offset state
*
* \author Keith Whitwell <keith@tungstengraphics.com>
* \author Brian Paul
*/
 
#include "util/u_math.h"
#include "util/u_memory.h"
#include "draw_pipe.h"
 
 
 
struct offset_stage {
struct draw_stage stage;
 
float scale;
float units;
float clamp;
};
 
 
 
static INLINE struct offset_stage *offset_stage( struct draw_stage *stage )
{
return (struct offset_stage *) stage;
}
 
 
 
 
 
/**
* Offset tri Z. Some hardware can handle this, but not usually when
* doing unfilled rendering.
*/
static void do_offset_tri( struct draw_stage *stage,
struct prim_header *header )
{
const unsigned pos = draw_current_shader_position_output(stage->draw);
struct offset_stage *offset = offset_stage(stage);
float inv_det = 1.0f / header->det;
 
/* Window coords:
*/
float *v0 = header->v[0]->data[pos];
float *v1 = header->v[1]->data[pos];
float *v2 = header->v[2]->data[pos];
 
/* edge vectors e = v0 - v2, f = v1 - v2 */
float ex = v0[0] - v2[0];
float ey = v0[1] - v2[1];
float ez = v0[2] - v2[2];
float fx = v1[0] - v2[0];
float fy = v1[1] - v2[1];
float fz = v1[2] - v2[2];
 
/* (a,b) = cross(e,f).xy */
float a = ey*fz - ez*fy;
float b = ez*fx - ex*fz;
 
float dzdx = fabsf(a * inv_det);
float dzdy = fabsf(b * inv_det);
 
float zoffset = offset->units + MAX2(dzdx, dzdy) * offset->scale;
 
if (offset->clamp)
zoffset = (offset->clamp < 0.0f) ? MAX2(zoffset, offset->clamp) :
MIN2(zoffset, offset->clamp);
 
/*
* Note: we're applying the offset and clamping per-vertex.
* Ideally, the offset is applied per-fragment prior to fragment shading.
*/
v0[2] = CLAMP(v0[2] + zoffset, 0.0f, 1.0f);
v1[2] = CLAMP(v1[2] + zoffset, 0.0f, 1.0f);
v2[2] = CLAMP(v2[2] + zoffset, 0.0f, 1.0f);
 
stage->next->tri( stage->next, header );
}
 
 
static void offset_tri( struct draw_stage *stage,
struct prim_header *header )
{
struct prim_header tmp;
 
tmp.det = header->det;
tmp.flags = header->flags;
tmp.pad = header->pad;
tmp.v[0] = dup_vert(stage, header->v[0], 0);
tmp.v[1] = dup_vert(stage, header->v[1], 1);
tmp.v[2] = dup_vert(stage, header->v[2], 2);
 
do_offset_tri( stage, &tmp );
}
 
 
static void offset_first_tri( struct draw_stage *stage,
struct prim_header *header )
{
struct offset_stage *offset = offset_stage(stage);
const struct pipe_rasterizer_state *rast = stage->draw->rasterizer;
unsigned fill_mode = rast->fill_front;
boolean do_offset;
 
if (rast->fill_back != rast->fill_front) {
/* Need to check for back-facing triangle */
boolean ccw = header->det < 0.0f;
if (ccw != rast->front_ccw)
fill_mode = rast->fill_back;
}
 
/* Now determine if we need to do offsetting for the point/line/fill mode */
switch (fill_mode) {
case PIPE_POLYGON_MODE_FILL:
do_offset = rast->offset_tri;
break;
case PIPE_POLYGON_MODE_LINE:
do_offset = rast->offset_line;
break;
case PIPE_POLYGON_MODE_POINT:
do_offset = rast->offset_point;
break;
default:
assert(!"invalid fill_mode in offset_first_tri()");
do_offset = rast->offset_tri;
}
 
if (do_offset) {
offset->scale = rast->offset_scale;
offset->clamp = rast->offset_clamp;
offset->units = (float) (rast->offset_units * stage->draw->mrd);
}
else {
offset->scale = 0.0f;
offset->clamp = 0.0f;
offset->units = 0.0f;
}
 
 
stage->tri = offset_tri;
stage->tri( stage, header );
}
 
 
 
 
static void offset_flush( struct draw_stage *stage,
unsigned flags )
{
stage->tri = offset_first_tri;
stage->next->flush( stage->next, flags );
}
 
 
static void offset_reset_stipple_counter( struct draw_stage *stage )
{
stage->next->reset_stipple_counter( stage->next );
}
 
 
static void offset_destroy( struct draw_stage *stage )
{
draw_free_temp_verts( stage );
FREE( stage );
}
 
 
/**
* Create polygon offset drawing stage.
*/
struct draw_stage *draw_offset_stage( struct draw_context *draw )
{
struct offset_stage *offset = CALLOC_STRUCT(offset_stage);
if (offset == NULL)
goto fail;
 
offset->stage.draw = draw;
offset->stage.name = "offset";
offset->stage.next = NULL;
offset->stage.point = draw_pipe_passthrough_point;
offset->stage.line = draw_pipe_passthrough_line;
offset->stage.tri = offset_first_tri;
offset->stage.flush = offset_flush;
offset->stage.reset_stipple_counter = offset_reset_stipple_counter;
offset->stage.destroy = offset_destroy;
 
if (!draw_alloc_temp_verts( &offset->stage, 3 ))
goto fail;
 
return &offset->stage;
 
fail:
if (offset)
offset->stage.destroy( &offset->stage );
 
return NULL;
}
/drivers/video/Gallium/auxiliary/draw/draw_pipe_pstipple.c
0,0 → 1,815
/**************************************************************************
*
* 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.
*
**************************************************************************/
 
/**
* Polygon stipple stage: implement polygon stipple with texture map and
* fragment program. The fragment program samples the texture using the
* fragment window coordinate register and does a fragment kill for the
* stipple-failing fragments.
*
* Authors: Brian Paul
*/
 
 
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "pipe/p_shader_tokens.h"
#include "util/u_inlines.h"
 
#include "util/u_format.h"
#include "util/u_math.h"
#include "util/u_memory.h"
#include "util/u_sampler.h"
 
#include "tgsi/tgsi_transform.h"
#include "tgsi/tgsi_dump.h"
 
#include "draw_context.h"
#include "draw_pipe.h"
 
 
/** Approx number of new tokens for instructions in pstip_transform_inst() */
#define NUM_NEW_TOKENS 50
 
 
/**
* Subclass of pipe_shader_state to carry extra fragment shader info.
*/
struct pstip_fragment_shader
{
struct pipe_shader_state state;
void *driver_fs;
void *pstip_fs;
uint sampler_unit;
};
 
 
/**
* Subclass of draw_stage
*/
struct pstip_stage
{
struct draw_stage stage;
 
void *sampler_cso;
struct pipe_resource *texture;
struct pipe_sampler_view *sampler_view;
uint num_samplers;
uint num_sampler_views;
 
/*
* Currently bound state
*/
struct pstip_fragment_shader *fs;
struct {
void *samplers[PIPE_MAX_SAMPLERS];
struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS];
const struct pipe_poly_stipple *stipple;
} state;
 
/*
* Driver interface/override functions
*/
void * (*driver_create_fs_state)(struct pipe_context *,
const struct pipe_shader_state *);
void (*driver_bind_fs_state)(struct pipe_context *, void *);
void (*driver_delete_fs_state)(struct pipe_context *, void *);
 
void (*driver_bind_sampler_states)(struct pipe_context *, unsigned, void **);
 
void (*driver_set_sampler_views)(struct pipe_context *,
unsigned,
struct pipe_sampler_view **);
 
void (*driver_set_polygon_stipple)(struct pipe_context *,
const struct pipe_poly_stipple *);
 
struct pipe_context *pipe;
};
 
 
 
/**
* Subclass of tgsi_transform_context, used for transforming the
* user's fragment shader to add the extra texture sample and fragment kill
* instructions.
*/
struct pstip_transform_context {
struct tgsi_transform_context base;
uint tempsUsed; /**< bitmask */
int wincoordInput;
int maxInput;
uint samplersUsed; /**< bitfield of samplers used */
int freeSampler; /** an available sampler for the pstipple */
int texTemp; /**< temp registers */
int numImmed;
boolean firstInstruction;
};
 
 
/**
* TGSI declaration transform callback.
* Look for a free sampler, a free input attrib, and two free temp regs.
*/
static void
pstip_transform_decl(struct tgsi_transform_context *ctx,
struct tgsi_full_declaration *decl)
{
struct pstip_transform_context *pctx = (struct pstip_transform_context *) ctx;
 
if (decl->Declaration.File == TGSI_FILE_SAMPLER) {
uint i;
for (i = decl->Range.First;
i <= decl->Range.Last; i++) {
pctx->samplersUsed |= 1 << i;
}
}
else if (decl->Declaration.File == TGSI_FILE_INPUT) {
pctx->maxInput = MAX2(pctx->maxInput, (int) decl->Range.Last);
if (decl->Semantic.Name == TGSI_SEMANTIC_POSITION)
pctx->wincoordInput = (int) decl->Range.First;
}
else if (decl->Declaration.File == TGSI_FILE_TEMPORARY) {
uint i;
for (i = decl->Range.First;
i <= decl->Range.Last; i++) {
pctx->tempsUsed |= (1 << i);
}
}
 
ctx->emit_declaration(ctx, decl);
}
 
 
/**
* TGSI immediate declaration transform callback.
* We're just counting the number of immediates here.
*/
static void
pstip_transform_immed(struct tgsi_transform_context *ctx,
struct tgsi_full_immediate *immed)
{
struct pstip_transform_context *pctx = (struct pstip_transform_context *) ctx;
ctx->emit_immediate(ctx, immed); /* emit to output shader */
pctx->numImmed++;
}
 
 
/**
* Find the lowest zero bit in the given word, or -1 if bitfield is all ones.
*/
static int
free_bit(uint bitfield)
{
return ffs(~bitfield) - 1;
}
 
 
/**
* TGSI instruction transform callback.
* Replace writes to result.color w/ a temp reg.
* Upon END instruction, insert texture sampling code for antialiasing.
*/
static void
pstip_transform_inst(struct tgsi_transform_context *ctx,
struct tgsi_full_instruction *inst)
{
struct pstip_transform_context *pctx = (struct pstip_transform_context *) ctx;
 
if (pctx->firstInstruction) {
/* emit our new declarations before the first instruction */
 
struct tgsi_full_declaration decl;
struct tgsi_full_instruction newInst;
uint i;
int wincoordInput;
 
/* find free sampler */
pctx->freeSampler = free_bit(pctx->samplersUsed);
if (pctx->freeSampler >= PIPE_MAX_SAMPLERS)
pctx->freeSampler = PIPE_MAX_SAMPLERS - 1;
 
if (pctx->wincoordInput < 0)
wincoordInput = pctx->maxInput + 1;
else
wincoordInput = pctx->wincoordInput;
 
/* find one free temp reg */
for (i = 0; i < 32; i++) {
if ((pctx->tempsUsed & (1 << i)) == 0) {
/* found a free temp */
if (pctx->texTemp < 0)
pctx->texTemp = i;
else
break;
}
}
assert(pctx->texTemp >= 0);
 
if (pctx->wincoordInput < 0) {
/* declare new position input reg */
decl = tgsi_default_full_declaration();
decl.Declaration.File = TGSI_FILE_INPUT;
decl.Declaration.Interpolate = 1;
decl.Declaration.Semantic = 1;
decl.Semantic.Name = TGSI_SEMANTIC_POSITION;
decl.Semantic.Index = 0;
decl.Range.First =
decl.Range.Last = wincoordInput;
decl.Interp.Interpolate = TGSI_INTERPOLATE_LINEAR; /* XXX? */
ctx->emit_declaration(ctx, &decl);
}
 
/* declare new sampler */
decl = tgsi_default_full_declaration();
decl.Declaration.File = TGSI_FILE_SAMPLER;
decl.Range.First =
decl.Range.Last = pctx->freeSampler;
ctx->emit_declaration(ctx, &decl);
 
/* declare new temp regs */
decl = tgsi_default_full_declaration();
decl.Declaration.File = TGSI_FILE_TEMPORARY;
decl.Range.First =
decl.Range.Last = pctx->texTemp;
ctx->emit_declaration(ctx, &decl);
 
/* emit immediate = {1/32, 1/32, 1, 1}
* The index/position of this immediate will be pctx->numImmed
*/
{
static const float value[4] = { 1.0/32, 1.0/32, 1.0, 1.0 };
struct tgsi_full_immediate immed;
uint size = 4;
immed = tgsi_default_full_immediate();
immed.Immediate.NrTokens = 1 + size; /* one for the token itself */
immed.u[0].Float = value[0];
immed.u[1].Float = value[1];
immed.u[2].Float = value[2];
immed.u[3].Float = value[3];
ctx->emit_immediate(ctx, &immed);
}
 
pctx->firstInstruction = FALSE;
 
 
/*
* Insert new MUL/TEX/KILP instructions at start of program
* Take gl_FragCoord, divide by 32 (stipple size), sample the
* texture and kill fragment if needed.
*
* We'd like to use non-normalized texcoords to index into a RECT
* texture, but we can only use GL_REPEAT wrap mode with normalized
* texcoords. Darn.
*/
 
/* MUL texTemp, INPUT[wincoord], 1/32; */
newInst = tgsi_default_full_instruction();
newInst.Instruction.Opcode = TGSI_OPCODE_MUL;
newInst.Instruction.NumDstRegs = 1;
newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY;
newInst.Dst[0].Register.Index = pctx->texTemp;
newInst.Instruction.NumSrcRegs = 2;
newInst.Src[0].Register.File = TGSI_FILE_INPUT;
newInst.Src[0].Register.Index = wincoordInput;
newInst.Src[1].Register.File = TGSI_FILE_IMMEDIATE;
newInst.Src[1].Register.Index = pctx->numImmed;
ctx->emit_instruction(ctx, &newInst);
 
/* TEX texTemp, texTemp, sampler; */
newInst = tgsi_default_full_instruction();
newInst.Instruction.Opcode = TGSI_OPCODE_TEX;
newInst.Instruction.NumDstRegs = 1;
newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY;
newInst.Dst[0].Register.Index = pctx->texTemp;
newInst.Instruction.NumSrcRegs = 2;
newInst.Instruction.Texture = TRUE;
newInst.Texture.Texture = TGSI_TEXTURE_2D;
newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY;
newInst.Src[0].Register.Index = pctx->texTemp;
newInst.Src[1].Register.File = TGSI_FILE_SAMPLER;
newInst.Src[1].Register.Index = pctx->freeSampler;
ctx->emit_instruction(ctx, &newInst);
 
/* KIL -texTemp; # if -texTemp < 0, KILL fragment */
newInst = tgsi_default_full_instruction();
newInst.Instruction.Opcode = TGSI_OPCODE_KIL;
newInst.Instruction.NumDstRegs = 0;
newInst.Instruction.NumSrcRegs = 1;
newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY;
newInst.Src[0].Register.Index = pctx->texTemp;
newInst.Src[0].Register.Negate = 1;
ctx->emit_instruction(ctx, &newInst);
}
 
/* emit this instruction */
ctx->emit_instruction(ctx, inst);
}
 
 
/**
* Generate the frag shader we'll use for doing polygon stipple.
* This will be the user's shader prefixed with a TEX and KIL instruction.
*/
static boolean
generate_pstip_fs(struct pstip_stage *pstip)
{
const struct pipe_shader_state *orig_fs = &pstip->fs->state;
/*struct draw_context *draw = pstip->stage.draw;*/
struct pipe_shader_state pstip_fs;
struct pstip_transform_context transform;
const uint newLen = tgsi_num_tokens(orig_fs->tokens) + NUM_NEW_TOKENS;
 
pstip_fs = *orig_fs; /* copy to init */
pstip_fs.tokens = tgsi_alloc_tokens(newLen);
if (pstip_fs.tokens == NULL)
return FALSE;
 
memset(&transform, 0, sizeof(transform));
transform.wincoordInput = -1;
transform.maxInput = -1;
transform.texTemp = -1;
transform.firstInstruction = TRUE;
transform.base.transform_instruction = pstip_transform_inst;
transform.base.transform_declaration = pstip_transform_decl;
transform.base.transform_immediate = pstip_transform_immed;
 
tgsi_transform_shader(orig_fs->tokens,
(struct tgsi_token *) pstip_fs.tokens,
newLen, &transform.base);
 
#if 0 /* DEBUG */
tgsi_dump(orig_fs->tokens, 0);
tgsi_dump(pstip_fs.tokens, 0);
#endif
 
assert(pstip->fs);
 
pstip->fs->sampler_unit = transform.freeSampler;
assert(pstip->fs->sampler_unit < PIPE_MAX_SAMPLERS);
 
pstip->fs->pstip_fs = pstip->driver_create_fs_state(pstip->pipe, &pstip_fs);
FREE((void *)pstip_fs.tokens);
 
if (!pstip->fs->pstip_fs)
return FALSE;
 
return TRUE;
}
 
 
/**
* Load texture image with current stipple pattern.
*/
static void
pstip_update_texture(struct pstip_stage *pstip)
{
static const uint bit31 = 1 << 31;
struct pipe_context *pipe = pstip->pipe;
struct pipe_transfer *transfer;
const uint *stipple = pstip->state.stipple->stipple;
uint i, j;
ubyte *data;
 
data = pipe_transfer_map(pipe, pstip->texture, 0, 0,
PIPE_TRANSFER_WRITE, 0, 0, 32, 32, &transfer);
 
/*
* Load alpha texture.
* Note: 0 means keep the fragment, 255 means kill it.
* We'll negate the texel value and use KILP which kills if value
* is negative.
*/
for (i = 0; i < 32; i++) {
for (j = 0; j < 32; j++) {
if (stipple[i] & (bit31 >> j)) {
/* fragment "on" */
data[i * transfer->stride + j] = 0;
}
else {
/* fragment "off" */
data[i * transfer->stride + j] = 255;
}
}
}
 
/* unmap */
pipe_transfer_unmap(pipe, transfer);
}
 
 
/**
* Create the texture map we'll use for stippling.
*/
static boolean
pstip_create_texture(struct pstip_stage *pstip)
{
struct pipe_context *pipe = pstip->pipe;
struct pipe_screen *screen = pipe->screen;
struct pipe_resource texTemp;
struct pipe_sampler_view viewTempl;
 
memset(&texTemp, 0, sizeof(texTemp));
texTemp.target = PIPE_TEXTURE_2D;
texTemp.format = PIPE_FORMAT_A8_UNORM; /* XXX verify supported by driver! */
texTemp.last_level = 0;
texTemp.width0 = 32;
texTemp.height0 = 32;
texTemp.depth0 = 1;
texTemp.array_size = 1;
texTemp.bind = PIPE_BIND_SAMPLER_VIEW;
 
pstip->texture = screen->resource_create(screen, &texTemp);
if (pstip->texture == NULL)
return FALSE;
 
u_sampler_view_default_template(&viewTempl,
pstip->texture,
pstip->texture->format);
pstip->sampler_view = pipe->create_sampler_view(pipe,
pstip->texture,
&viewTempl);
if (!pstip->sampler_view) {
return FALSE;
}
 
return TRUE;
}
 
 
/**
* Create the sampler CSO that'll be used for stippling.
*/
static boolean
pstip_create_sampler(struct pstip_stage *pstip)
{
struct pipe_sampler_state sampler;
struct pipe_context *pipe = pstip->pipe;
 
memset(&sampler, 0, sizeof(sampler));
sampler.wrap_s = PIPE_TEX_WRAP_REPEAT;
sampler.wrap_t = PIPE_TEX_WRAP_REPEAT;
sampler.wrap_r = PIPE_TEX_WRAP_REPEAT;
sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
sampler.normalized_coords = 1;
sampler.min_lod = 0.0f;
sampler.max_lod = 0.0f;
 
pstip->sampler_cso = pipe->create_sampler_state(pipe, &sampler);
if (pstip->sampler_cso == NULL)
return FALSE;
return TRUE;
}
 
 
/**
* When we're about to draw our first stipple polygon in a batch, this function
* is called to tell the driver to bind our modified fragment shader.
*/
static boolean
bind_pstip_fragment_shader(struct pstip_stage *pstip)
{
struct draw_context *draw = pstip->stage.draw;
if (!pstip->fs->pstip_fs &&
!generate_pstip_fs(pstip))
return FALSE;
 
draw->suspend_flushing = TRUE;
pstip->driver_bind_fs_state(pstip->pipe, pstip->fs->pstip_fs);
draw->suspend_flushing = FALSE;
return TRUE;
}
 
 
static INLINE struct pstip_stage *
pstip_stage( struct draw_stage *stage )
{
return (struct pstip_stage *) stage;
}
 
 
static void
pstip_first_tri(struct draw_stage *stage, struct prim_header *header)
{
struct pstip_stage *pstip = pstip_stage(stage);
struct pipe_context *pipe = pstip->pipe;
struct draw_context *draw = stage->draw;
uint num_samplers;
 
assert(stage->draw->rasterizer->poly_stipple_enable);
 
/* bind our fragprog */
if (!bind_pstip_fragment_shader(pstip)) {
stage->tri = draw_pipe_passthrough_tri;
stage->tri(stage, header);
return;
}
 
/* how many samplers? */
/* we'll use sampler/texture[pstip->sampler_unit] for the stipple */
num_samplers = MAX2(pstip->num_sampler_views, pstip->num_samplers);
num_samplers = MAX2(num_samplers, pstip->fs->sampler_unit + 1);
 
/* plug in our sampler, texture */
pstip->state.samplers[pstip->fs->sampler_unit] = pstip->sampler_cso;
pipe_sampler_view_reference(&pstip->state.sampler_views[pstip->fs->sampler_unit],
pstip->sampler_view);
 
assert(num_samplers <= PIPE_MAX_SAMPLERS);
 
draw->suspend_flushing = TRUE;
pstip->driver_bind_sampler_states(pipe, num_samplers, pstip->state.samplers);
pstip->driver_set_sampler_views(pipe, num_samplers, pstip->state.sampler_views);
draw->suspend_flushing = FALSE;
 
/* now really draw first triangle */
stage->tri = draw_pipe_passthrough_tri;
stage->tri(stage, header);
}
 
 
static void
pstip_flush(struct draw_stage *stage, unsigned flags)
{
struct draw_context *draw = stage->draw;
struct pstip_stage *pstip = pstip_stage(stage);
struct pipe_context *pipe = pstip->pipe;
 
stage->tri = pstip_first_tri;
stage->next->flush( stage->next, flags );
 
/* restore original frag shader, texture, sampler state */
draw->suspend_flushing = TRUE;
pstip->driver_bind_fs_state(pipe, pstip->fs ? pstip->fs->driver_fs : NULL);
pstip->driver_bind_sampler_states(pipe, pstip->num_samplers,
pstip->state.samplers);
pstip->driver_set_sampler_views(pipe,
pstip->num_sampler_views,
pstip->state.sampler_views);
draw->suspend_flushing = FALSE;
}
 
 
static void
pstip_reset_stipple_counter(struct draw_stage *stage)
{
stage->next->reset_stipple_counter( stage->next );
}
 
 
static void
pstip_destroy(struct draw_stage *stage)
{
struct pstip_stage *pstip = pstip_stage(stage);
uint i;
 
for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
pipe_sampler_view_reference(&pstip->state.sampler_views[i], NULL);
}
 
pstip->pipe->delete_sampler_state(pstip->pipe, pstip->sampler_cso);
 
pipe_resource_reference(&pstip->texture, NULL);
 
if (pstip->sampler_view) {
pipe_sampler_view_reference(&pstip->sampler_view, NULL);
}
 
draw_free_temp_verts( stage );
FREE( stage );
}
 
 
/** Create a new polygon stipple drawing stage object */
static struct pstip_stage *
draw_pstip_stage(struct draw_context *draw, struct pipe_context *pipe)
{
struct pstip_stage *pstip = CALLOC_STRUCT(pstip_stage);
if (pstip == NULL)
goto fail;
 
pstip->pipe = pipe;
 
pstip->stage.draw = draw;
pstip->stage.name = "pstip";
pstip->stage.next = NULL;
pstip->stage.point = draw_pipe_passthrough_point;
pstip->stage.line = draw_pipe_passthrough_line;
pstip->stage.tri = pstip_first_tri;
pstip->stage.flush = pstip_flush;
pstip->stage.reset_stipple_counter = pstip_reset_stipple_counter;
pstip->stage.destroy = pstip_destroy;
 
if (!draw_alloc_temp_verts( &pstip->stage, 8 ))
goto fail;
 
return pstip;
 
fail:
if (pstip)
pstip->stage.destroy( &pstip->stage );
 
return NULL;
}
 
 
static struct pstip_stage *
pstip_stage_from_pipe(struct pipe_context *pipe)
{
struct draw_context *draw = (struct draw_context *) pipe->draw;
return pstip_stage(draw->pipeline.pstipple);
}
 
 
/**
* This function overrides the driver's create_fs_state() function and
* will typically be called by the state tracker.
*/
static void *
pstip_create_fs_state(struct pipe_context *pipe,
const struct pipe_shader_state *fs)
{
struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
struct pstip_fragment_shader *pstipfs = CALLOC_STRUCT(pstip_fragment_shader);
 
if (pstipfs) {
pstipfs->state = *fs;
 
/* pass-through */
pstipfs->driver_fs = pstip->driver_create_fs_state(pstip->pipe, fs);
}
 
return pstipfs;
}
 
 
static void
pstip_bind_fs_state(struct pipe_context *pipe, void *fs)
{
struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
struct pstip_fragment_shader *pstipfs = (struct pstip_fragment_shader *) fs;
/* save current */
pstip->fs = pstipfs;
/* pass-through */
pstip->driver_bind_fs_state(pstip->pipe,
(pstipfs ? pstipfs->driver_fs : NULL));
}
 
 
static void
pstip_delete_fs_state(struct pipe_context *pipe, void *fs)
{
struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
struct pstip_fragment_shader *pstipfs = (struct pstip_fragment_shader *) fs;
/* pass-through */
pstip->driver_delete_fs_state(pstip->pipe, pstipfs->driver_fs);
 
if (pstipfs->pstip_fs)
pstip->driver_delete_fs_state(pstip->pipe, pstipfs->pstip_fs);
 
FREE(pstipfs);
}
 
 
static void
pstip_bind_sampler_states(struct pipe_context *pipe,
unsigned num, void **sampler)
{
struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
uint i;
 
/* save current */
memcpy(pstip->state.samplers, sampler, num * sizeof(void *));
for (i = num; i < PIPE_MAX_SAMPLERS; i++) {
pstip->state.samplers[i] = NULL;
}
 
pstip->num_samplers = num;
/* pass-through */
pstip->driver_bind_sampler_states(pstip->pipe, num, sampler);
}
 
 
static void
pstip_set_sampler_views(struct pipe_context *pipe,
unsigned num,
struct pipe_sampler_view **views)
{
struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
uint i;
 
/* save current */
for (i = 0; i < num; i++) {
pipe_sampler_view_reference(&pstip->state.sampler_views[i], views[i]);
}
for (; i < PIPE_MAX_SAMPLERS; i++) {
pipe_sampler_view_reference(&pstip->state.sampler_views[i], NULL);
}
 
pstip->num_sampler_views = num;
 
/* pass-through */
pstip->driver_set_sampler_views(pstip->pipe, num, views);
}
 
 
static void
pstip_set_polygon_stipple(struct pipe_context *pipe,
const struct pipe_poly_stipple *stipple)
{
struct pstip_stage *pstip = pstip_stage_from_pipe(pipe);
 
/* save current */
pstip->state.stipple = stipple;
 
/* pass-through */
pstip->driver_set_polygon_stipple(pstip->pipe, stipple);
 
pstip_update_texture(pstip);
}
 
 
/**
* Called by drivers that want to install this polygon stipple stage
* into the draw module's pipeline. This will not be used if the
* hardware has native support for polygon stipple.
*/
boolean
draw_install_pstipple_stage(struct draw_context *draw,
struct pipe_context *pipe)
{
struct pstip_stage *pstip;
 
pipe->draw = (void *) draw;
 
/*
* Create / install pgon stipple drawing / prim stage
*/
pstip = draw_pstip_stage( draw, pipe );
if (pstip == NULL)
goto fail;
 
draw->pipeline.pstipple = &pstip->stage;
 
/* create special texture, sampler state */
if (!pstip_create_texture(pstip))
goto fail;
 
if (!pstip_create_sampler(pstip))
goto fail;
 
/* save original driver functions */
pstip->driver_create_fs_state = pipe->create_fs_state;
pstip->driver_bind_fs_state = pipe->bind_fs_state;
pstip->driver_delete_fs_state = pipe->delete_fs_state;
 
pstip->driver_bind_sampler_states = pipe->bind_fragment_sampler_states;
pstip->driver_set_sampler_views = pipe->set_fragment_sampler_views;
pstip->driver_set_polygon_stipple = pipe->set_polygon_stipple;
 
/* override the driver's functions */
pipe->create_fs_state = pstip_create_fs_state;
pipe->bind_fs_state = pstip_bind_fs_state;
pipe->delete_fs_state = pstip_delete_fs_state;
 
pipe->bind_fragment_sampler_states = pstip_bind_sampler_states;
pipe->set_fragment_sampler_views = pstip_set_sampler_views;
pipe->set_polygon_stipple = pstip_set_polygon_stipple;
 
return TRUE;
 
fail:
if (pstip)
pstip->stage.destroy( &pstip->stage );
 
return FALSE;
}
/drivers/video/Gallium/auxiliary/draw/draw_pipe_stipple.c
0,0 → 1,261
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/* Authors: Keith Whitwell <keith@tungstengraphics.com>
*/
 
/* Implement line stipple by cutting lines up into smaller lines.
* There are hundreds of ways to implement line stipple, this is one
* choice that should work in all situations, requires no state
* manipulations, but with a penalty in terms of large amounts of
* generated geometry.
*/
 
 
#include "pipe/p_defines.h"
#include "pipe/p_shader_tokens.h"
#include "util/u_math.h"
#include "util/u_memory.h"
 
#include "draw/draw_pipe.h"
 
 
/** Subclass of draw_stage */
struct stipple_stage {
struct draw_stage stage;
float counter;
uint pattern;
uint factor;
};
 
 
static INLINE struct stipple_stage *
stipple_stage(struct draw_stage *stage)
{
return (struct stipple_stage *) stage;
}
 
 
/**
* Compute interpolated vertex attributes for 'dst' at position 't'
* between 'v0' and 'v1'.
* XXX using linear interpolation for all attribs at this time.
*/
static void
screen_interp( struct draw_context *draw,
struct vertex_header *dst,
float t,
const struct vertex_header *v0,
const struct vertex_header *v1 )
{
uint attr;
uint num_outputs = draw_current_shader_outputs(draw);
for (attr = 0; attr < num_outputs; attr++) {
const float *val0 = v0->data[attr];
const float *val1 = v1->data[attr];
float *newv = dst->data[attr];
uint i;
for (i = 0; i < 4; i++) {
newv[i] = val0[i] + t * (val1[i] - val0[i]);
}
}
}
 
 
static void
emit_segment(struct draw_stage *stage, struct prim_header *header,
float t0, float t1)
{
struct vertex_header *v0new = dup_vert(stage, header->v[0], 0);
struct vertex_header *v1new = dup_vert(stage, header->v[1], 1);
struct prim_header newprim = *header;
 
if (t0 > 0.0) {
screen_interp( stage->draw, v0new, t0, header->v[0], header->v[1] );
newprim.v[0] = v0new;
}
 
if (t1 < 1.0) {
screen_interp( stage->draw, v1new, t1, header->v[0], header->v[1] );
newprim.v[1] = v1new;
}
 
stage->next->line( stage->next, &newprim );
}
 
 
static INLINE unsigned
stipple_test(int counter, ushort pattern, int factor)
{
int b = (counter / factor) & 0xf;
return (1 << b) & pattern;
}
 
 
static void
stipple_line(struct draw_stage *stage, struct prim_header *header)
{
struct stipple_stage *stipple = stipple_stage(stage);
struct vertex_header *v0 = header->v[0];
struct vertex_header *v1 = header->v[1];
const unsigned pos = draw_current_shader_position_output(stage->draw);
const float *pos0 = v0->data[pos];
const float *pos1 = v1->data[pos];
float start = 0;
int state = 0;
 
float x0 = pos0[0];
float x1 = pos1[0];
float y0 = pos0[1];
float y1 = pos1[1];
 
float dx = x0 > x1 ? x0 - x1 : x1 - x0;
float dy = y0 > y1 ? y0 - y1 : y1 - y0;
 
float length = MAX2(dx, dy);
int i;
 
if (header->flags & DRAW_PIPE_RESET_STIPPLE)
stipple->counter = 0;
 
 
/* XXX ToDo: intead of iterating pixel-by-pixel, use a look-up table.
*/
for (i = 0; i < length; i++) {
int result = stipple_test( (int) stipple->counter+i,
(ushort) stipple->pattern, stipple->factor );
if (result != state) {
/* changing from "off" to "on" or vice versa */
if (state) {
if (start != i) {
/* finishing an "on" segment */
emit_segment( stage, header, start / length, i / length );
}
}
else {
/* starting an "on" segment */
start = (float) i;
}
state = result;
}
}
 
if (state && start < length)
emit_segment( stage, header, start / length, 1.0 );
 
stipple->counter += length;
}
 
 
static void
reset_stipple_counter(struct draw_stage *stage)
{
struct stipple_stage *stipple = stipple_stage(stage);
stipple->counter = 0;
stage->next->reset_stipple_counter( stage->next );
}
 
static void
stipple_reset_point(struct draw_stage *stage, struct prim_header *header)
{
struct stipple_stage *stipple = stipple_stage(stage);
stipple->counter = 0;
stage->next->point(stage->next, header);
}
 
static void
stipple_reset_tri(struct draw_stage *stage, struct prim_header *header)
{
struct stipple_stage *stipple = stipple_stage(stage);
stipple->counter = 0;
stage->next->tri(stage->next, header);
}
 
 
static void
stipple_first_line(struct draw_stage *stage,
struct prim_header *header)
{
struct stipple_stage *stipple = stipple_stage(stage);
struct draw_context *draw = stage->draw;
 
stipple->pattern = draw->rasterizer->line_stipple_pattern;
stipple->factor = draw->rasterizer->line_stipple_factor + 1;
 
stage->line = stipple_line;
stage->line( stage, header );
}
 
 
static void
stipple_flush(struct draw_stage *stage, unsigned flags)
{
stage->line = stipple_first_line;
stage->next->flush( stage->next, flags );
}
 
 
 
 
static void
stipple_destroy( struct draw_stage *stage )
{
draw_free_temp_verts( stage );
FREE( stage );
}
 
 
/**
* Create line stippler stage
*/
struct draw_stage *draw_stipple_stage( struct draw_context *draw )
{
struct stipple_stage *stipple = CALLOC_STRUCT(stipple_stage);
if (stipple == NULL)
goto fail;
 
stipple->stage.draw = draw;
stipple->stage.name = "stipple";
stipple->stage.next = NULL;
stipple->stage.point = stipple_reset_point;
stipple->stage.line = stipple_first_line;
stipple->stage.tri = stipple_reset_tri;
stipple->stage.reset_stipple_counter = reset_stipple_counter;
stipple->stage.flush = stipple_flush;
stipple->stage.destroy = stipple_destroy;
 
if (!draw_alloc_temp_verts( &stipple->stage, 2 ))
goto fail;
 
return &stipple->stage;
 
fail:
if (stipple)
stipple->stage.destroy( &stipple->stage );
 
return NULL;
}
/drivers/video/Gallium/auxiliary/draw/draw_pipe_twoside.c
0,0 → 1,191
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/* Authors: Keith Whitwell <keith@tungstengraphics.com>
*/
 
#include "util/u_math.h"
#include "util/u_memory.h"
#include "pipe/p_defines.h"
#include "pipe/p_shader_tokens.h"
#include "draw_vs.h"
#include "draw_pipe.h"
 
struct twoside_stage {
struct draw_stage stage;
float sign; /**< +1 or -1 */
int attrib_front0, attrib_back0;
int attrib_front1, attrib_back1;
};
 
 
static INLINE struct twoside_stage *twoside_stage( struct draw_stage *stage )
{
return (struct twoside_stage *)stage;
}
 
/**
* Copy back color(s) to front color(s).
*/
static INLINE struct vertex_header *
copy_bfc( struct twoside_stage *twoside,
const struct vertex_header *v,
unsigned idx )
{
struct vertex_header *tmp = dup_vert( &twoside->stage, v, idx );
 
if (twoside->attrib_back0 >= 0 && twoside->attrib_front0 >= 0) {
COPY_4FV(tmp->data[twoside->attrib_front0],
tmp->data[twoside->attrib_back0]);
}
if (twoside->attrib_back1 >= 0 && twoside->attrib_front1 >= 0) {
COPY_4FV(tmp->data[twoside->attrib_front1],
tmp->data[twoside->attrib_back1]);
}
 
return tmp;
}
 
 
/* Twoside tri:
*/
static void twoside_tri( struct draw_stage *stage,
struct prim_header *header )
{
struct twoside_stage *twoside = twoside_stage(stage);
 
if (header->det * twoside->sign < 0.0) {
/* this is a back-facing triangle */
struct prim_header tmp;
 
tmp.det = header->det;
tmp.flags = header->flags;
tmp.pad = header->pad;
/* copy back attribs to front attribs */
tmp.v[0] = copy_bfc(twoside, header->v[0], 0);
tmp.v[1] = copy_bfc(twoside, header->v[1], 1);
tmp.v[2] = copy_bfc(twoside, header->v[2], 2);
 
stage->next->tri( stage->next, &tmp );
}
else {
stage->next->tri( stage->next, header );
}
}
 
 
 
static void twoside_first_tri( struct draw_stage *stage,
struct prim_header *header )
{
struct twoside_stage *twoside = twoside_stage(stage);
const struct draw_vertex_shader *vs = stage->draw->vs.vertex_shader;
uint i;
 
twoside->attrib_front0 = -1;
twoside->attrib_front1 = -1;
twoside->attrib_back0 = -1;
twoside->attrib_back1 = -1;
 
/* Find which vertex shader outputs are front/back colors */
for (i = 0; i < vs->info.num_outputs; i++) {
if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_COLOR) {
if (vs->info.output_semantic_index[i] == 0)
twoside->attrib_front0 = i;
else
twoside->attrib_front1 = i;
}
if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_BCOLOR) {
if (vs->info.output_semantic_index[i] == 0)
twoside->attrib_back0 = i;
else
twoside->attrib_back1 = i;
}
}
 
/*
* We'll multiply the primitive's determinant by this sign to determine
* if the triangle is back-facing (negative).
* sign = -1 for CCW, +1 for CW
*/
twoside->sign = stage->draw->rasterizer->front_ccw ? -1.0f : 1.0f;
 
stage->tri = twoside_tri;
stage->tri( stage, header );
}
 
 
static void twoside_flush( struct draw_stage *stage, unsigned flags )
{
stage->tri = twoside_first_tri;
stage->next->flush( stage->next, flags );
}
 
 
static void twoside_reset_stipple_counter( struct draw_stage *stage )
{
stage->next->reset_stipple_counter( stage->next );
}
 
 
static void twoside_destroy( struct draw_stage *stage )
{
draw_free_temp_verts( stage );
FREE( stage );
}
 
 
/**
* Create twoside pipeline stage.
*/
struct draw_stage *draw_twoside_stage( struct draw_context *draw )
{
struct twoside_stage *twoside = CALLOC_STRUCT(twoside_stage);
if (twoside == NULL)
goto fail;
 
twoside->stage.draw = draw;
twoside->stage.name = "twoside";
twoside->stage.next = NULL;
twoside->stage.point = draw_pipe_passthrough_point;
twoside->stage.line = draw_pipe_passthrough_line;
twoside->stage.tri = twoside_first_tri;
twoside->stage.flush = twoside_flush;
twoside->stage.reset_stipple_counter = twoside_reset_stipple_counter;
twoside->stage.destroy = twoside_destroy;
 
if (!draw_alloc_temp_verts( &twoside->stage, 3 ))
goto fail;
 
return &twoside->stage;
 
fail:
if (twoside)
twoside->stage.destroy( &twoside->stage );
 
return NULL;
}
/drivers/video/Gallium/auxiliary/draw/draw_pipe_unfilled.c
0,0 → 1,226
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/**
* \brief Drawing stage for handling glPolygonMode(line/point).
* Convert triangles to points or lines as needed.
*/
 
/* Authors: Keith Whitwell <keith@tungstengraphics.com>
*/
 
#include "util/u_memory.h"
#include "pipe/p_defines.h"
#include "draw_private.h"
#include "draw_pipe.h"
 
 
struct unfilled_stage {
struct draw_stage stage;
 
/** [0] = front face, [1] = back face.
* legal values: PIPE_POLYGON_MODE_FILL, PIPE_POLYGON_MODE_LINE,
* and PIPE_POLYGON_MODE_POINT,
*/
unsigned mode[2];
};
 
 
static INLINE struct unfilled_stage *unfilled_stage( struct draw_stage *stage )
{
return (struct unfilled_stage *)stage;
}
 
 
 
static void point( struct draw_stage *stage,
struct vertex_header *v0 )
{
struct prim_header tmp;
tmp.v[0] = v0;
stage->next->point( stage->next, &tmp );
}
 
static void line( struct draw_stage *stage,
struct vertex_header *v0,
struct vertex_header *v1 )
{
struct prim_header tmp;
tmp.v[0] = v0;
tmp.v[1] = v1;
stage->next->line( stage->next, &tmp );
}
 
 
static void points( struct draw_stage *stage,
struct prim_header *header )
{
struct vertex_header *v0 = header->v[0];
struct vertex_header *v1 = header->v[1];
struct vertex_header *v2 = header->v[2];
 
if ((header->flags & DRAW_PIPE_EDGE_FLAG_0) && v0->edgeflag) point( stage, v0 );
if ((header->flags & DRAW_PIPE_EDGE_FLAG_1) && v1->edgeflag) point( stage, v1 );
if ((header->flags & DRAW_PIPE_EDGE_FLAG_2) && v2->edgeflag) point( stage, v2 );
}
 
 
static void lines( struct draw_stage *stage,
struct prim_header *header )
{
struct vertex_header *v0 = header->v[0];
struct vertex_header *v1 = header->v[1];
struct vertex_header *v2 = header->v[2];
 
if (header->flags & DRAW_PIPE_RESET_STIPPLE)
stage->next->reset_stipple_counter( stage->next );
 
if ((header->flags & DRAW_PIPE_EDGE_FLAG_2) && v2->edgeflag) line( stage, v2, v0 );
if ((header->flags & DRAW_PIPE_EDGE_FLAG_0) && v0->edgeflag) line( stage, v0, v1 );
if ((header->flags & DRAW_PIPE_EDGE_FLAG_1) && v1->edgeflag) line( stage, v1, v2 );
}
 
 
/** For debugging */
static void
print_header_flags(unsigned flags)
{
debug_printf("header->flags = ");
if (flags & DRAW_PIPE_RESET_STIPPLE)
debug_printf("RESET_STIPPLE ");
if (flags & DRAW_PIPE_EDGE_FLAG_0)
debug_printf("EDGE_FLAG_0 ");
if (flags & DRAW_PIPE_EDGE_FLAG_1)
debug_printf("EDGE_FLAG_1 ");
if (flags & DRAW_PIPE_EDGE_FLAG_2)
debug_printf("EDGE_FLAG_2 ");
debug_printf("\n");
}
 
 
/* Unfilled tri:
*
* Note edgeflags in the vertex struct is not sufficient as we will
* need to manipulate them when decomposing primitives.
*
* We currently keep the vertex edgeflag and primitive edgeflag mask
* separate until the last possible moment.
*/
static void unfilled_tri( struct draw_stage *stage,
struct prim_header *header )
{
struct unfilled_stage *unfilled = unfilled_stage(stage);
unsigned cw = header->det >= 0.0;
unsigned mode = unfilled->mode[cw];
if (0)
print_header_flags(header->flags);
 
switch (mode) {
case PIPE_POLYGON_MODE_FILL:
stage->next->tri( stage->next, header );
break;
case PIPE_POLYGON_MODE_LINE:
lines( stage, header );
break;
case PIPE_POLYGON_MODE_POINT:
points( stage, header );
break;
default:
assert(0);
}
}
 
 
static void unfilled_first_tri( struct draw_stage *stage,
struct prim_header *header )
{
struct unfilled_stage *unfilled = unfilled_stage(stage);
const struct pipe_rasterizer_state *rast = stage->draw->rasterizer;
 
unfilled->mode[0] = rast->front_ccw ? rast->fill_front : rast->fill_back;
unfilled->mode[1] = rast->front_ccw ? rast->fill_back : rast->fill_front;
 
stage->tri = unfilled_tri;
stage->tri( stage, header );
}
 
 
 
static void unfilled_flush( struct draw_stage *stage,
unsigned flags )
{
stage->next->flush( stage->next, flags );
 
stage->tri = unfilled_first_tri;
}
 
 
static void unfilled_reset_stipple_counter( struct draw_stage *stage )
{
stage->next->reset_stipple_counter( stage->next );
}
 
 
static void unfilled_destroy( struct draw_stage *stage )
{
draw_free_temp_verts( stage );
FREE( stage );
}
 
 
/**
* Create unfilled triangle stage.
*/
struct draw_stage *draw_unfilled_stage( struct draw_context *draw )
{
struct unfilled_stage *unfilled = CALLOC_STRUCT(unfilled_stage);
if (unfilled == NULL)
goto fail;
 
unfilled->stage.draw = draw;
unfilled->stage.name = "unfilled";
unfilled->stage.next = NULL;
unfilled->stage.tmp = NULL;
unfilled->stage.point = draw_pipe_passthrough_point;
unfilled->stage.line = draw_pipe_passthrough_line;
unfilled->stage.tri = unfilled_first_tri;
unfilled->stage.flush = unfilled_flush;
unfilled->stage.reset_stipple_counter = unfilled_reset_stipple_counter;
unfilled->stage.destroy = unfilled_destroy;
 
if (!draw_alloc_temp_verts( &unfilled->stage, 0 ))
goto fail;
 
return &unfilled->stage;
 
fail:
if (unfilled)
unfilled->stage.destroy( &unfilled->stage );
 
return NULL;
}
/drivers/video/Gallium/auxiliary/draw/draw_pipe_util.c
0,0 → 1,137
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
#include "util/u_memory.h"
#include "draw/draw_private.h"
#include "draw/draw_pipe.h"
 
 
 
void
draw_pipe_passthrough_point(struct draw_stage *stage, struct prim_header *header)
{
stage->next->point(stage->next, header);
}
 
void
draw_pipe_passthrough_line(struct draw_stage *stage, struct prim_header *header)
{
stage->next->line(stage->next, header);
}
 
void
draw_pipe_passthrough_tri(struct draw_stage *stage, struct prim_header *header)
{
stage->next->tri(stage->next, header);
}
 
 
 
 
 
/* This is only used for temporary verts.
*/
#define MAX_VERTEX_SIZE ((2 + PIPE_MAX_SHADER_OUTPUTS) * 4 * sizeof(float))
 
 
/**
* Allocate space for temporary post-transform vertices, such as for clipping.
*/
boolean draw_alloc_temp_verts( struct draw_stage *stage, unsigned nr )
{
assert(!stage->tmp);
 
stage->tmp = NULL;
stage->nr_tmps = nr;
 
if (nr != 0)
{
unsigned i;
ubyte *store = (ubyte *) MALLOC( MAX_VERTEX_SIZE * nr );
 
if (store == NULL)
return FALSE;
 
stage->tmp = (struct vertex_header **) MALLOC( sizeof(struct vertex_header *) * nr );
if (stage->tmp == NULL) {
FREE(store);
return FALSE;
}
for (i = 0; i < nr; i++)
stage->tmp[i] = (struct vertex_header *)(store + i * MAX_VERTEX_SIZE);
}
 
return TRUE;
}
 
 
void draw_free_temp_verts( struct draw_stage *stage )
{
if (stage->tmp) {
FREE( stage->tmp[0] );
FREE( stage->tmp );
stage->tmp = NULL;
}
}
 
 
/* Reset vertex ids. This is basically a type of flush.
*
* Called only from draw_pipe_vbuf.c
*/
void draw_reset_vertex_ids(struct draw_context *draw)
{
struct draw_stage *stage = draw->pipeline.first;
while (stage) {
unsigned i;
 
for (i = 0; i < stage->nr_tmps; i++)
stage->tmp[i]->vertex_id = UNDEFINED_VERTEX_ID;
 
stage = stage->next;
}
 
if (draw->pipeline.verts)
{
unsigned i;
char *verts = draw->pipeline.verts;
unsigned stride = draw->pipeline.vertex_stride;
 
for (i = 0; i < draw->pipeline.vertex_count; i++) {
((struct vertex_header *)verts)->vertex_id = UNDEFINED_VERTEX_ID;
verts += stride;
}
}
}
 
/drivers/video/Gallium/auxiliary/draw/draw_pipe_validate.c
0,0 → 1,359
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/* Authors: Keith Whitwell <keith@tungstengraphics.com>
*/
 
#include "util/u_memory.h"
#include "util/u_math.h"
#include "pipe/p_defines.h"
#include "draw_private.h"
#include "draw_pipe.h"
#include "draw_context.h"
#include "draw_vbuf.h"
 
static boolean points( unsigned prim )
{
return (prim == PIPE_PRIM_POINTS);
}
 
static boolean lines( unsigned prim )
{
return (prim == PIPE_PRIM_LINES ||
prim == PIPE_PRIM_LINE_STRIP ||
prim == PIPE_PRIM_LINE_LOOP);
}
 
static boolean triangles( unsigned prim )
{
return prim >= PIPE_PRIM_TRIANGLES;
}
 
/**
* Default version of a function to check if we need any special
* pipeline stages, or whether prims/verts can go through untouched.
* Don't test for bypass clipping or vs modes, this function is just
* about the primitive pipeline stages.
*
* This can be overridden by the driver.
*/
boolean
draw_need_pipeline(const struct draw_context *draw,
const struct pipe_rasterizer_state *rasterizer,
unsigned int prim )
{
/* If the driver has overridden this, use that version:
*/
if (draw->render &&
draw->render->need_pipeline)
{
return draw->render->need_pipeline( draw->render,
rasterizer,
prim );
}
 
/* Don't have to worry about triangles turning into lines/points
* and triggering the pipeline, because we have to trigger the
* pipeline *anyway* if unfilled mode is active.
*/
if (lines(prim))
{
/* line stipple */
if (rasterizer->line_stipple_enable && draw->pipeline.line_stipple)
return TRUE;
 
/* wide lines */
if (roundf(rasterizer->line_width) > draw->pipeline.wide_line_threshold)
return TRUE;
 
/* AA lines */
if (rasterizer->line_smooth && draw->pipeline.aaline)
return TRUE;
 
if (draw_current_shader_num_written_culldistances(draw))
return TRUE;
}
 
if (points(prim))
{
/* large points */
if (rasterizer->point_size > draw->pipeline.wide_point_threshold)
return TRUE;
 
/* sprite points */
if (rasterizer->point_quad_rasterization
&& draw->pipeline.wide_point_sprites)
return TRUE;
 
/* AA points */
if (rasterizer->point_smooth && draw->pipeline.aapoint)
return TRUE;
 
/* point sprites */
if (rasterizer->sprite_coord_enable && draw->pipeline.point_sprite)
return TRUE;
}
 
 
if (triangles(prim))
{
/* polygon stipple */
if (rasterizer->poly_stipple_enable && draw->pipeline.pstipple)
return TRUE;
 
/* unfilled polygons */
if (rasterizer->fill_front != PIPE_POLYGON_MODE_FILL ||
rasterizer->fill_back != PIPE_POLYGON_MODE_FILL)
return TRUE;
/* polygon offset */
if (rasterizer->offset_point ||
rasterizer->offset_line ||
rasterizer->offset_tri)
return TRUE;
 
/* two-side lighting */
if (rasterizer->light_twoside)
return TRUE;
 
if (draw_current_shader_num_written_culldistances(draw))
return TRUE;
}
 
/* polygon cull - this is difficult - hardware can cull just fine
* most of the time (though sometimes CULL_NEITHER is unsupported.
*
* Generally this isn't a reason to require the pipeline, though.
*
if (rasterizer->cull_mode)
return TRUE;
*/
 
return FALSE;
}
 
 
 
/**
* Rebuild the rendering pipeline.
*/
static struct draw_stage *validate_pipeline( struct draw_stage *stage )
{
struct draw_context *draw = stage->draw;
struct draw_stage *next = draw->pipeline.rasterize;
boolean need_det = FALSE;
boolean precalc_flat = FALSE;
boolean wide_lines, wide_points;
const struct pipe_rasterizer_state *rast = draw->rasterizer;
 
/* Set the validate's next stage to the rasterize stage, so that it
* can be found later if needed for flushing.
*/
stage->next = next;
 
/* drawing wide lines? */
wide_lines = (roundf(rast->line_width) > draw->pipeline.wide_line_threshold
&& !rast->line_smooth);
 
/* drawing large/sprite points (but not AA points)? */
if (rast->sprite_coord_enable && draw->pipeline.point_sprite)
wide_points = TRUE;
else if (rast->point_smooth && draw->pipeline.aapoint)
wide_points = FALSE;
else if (rast->point_size > draw->pipeline.wide_point_threshold)
wide_points = TRUE;
else if (rast->point_quad_rasterization && draw->pipeline.wide_point_sprites)
wide_points = TRUE;
else
wide_points = FALSE;
 
/*
* NOTE: we build up the pipeline in end-to-start order.
*
* TODO: make the current primitive part of the state and build
* shorter pipelines for lines & points.
*/
 
if (rast->line_smooth && draw->pipeline.aaline) {
draw->pipeline.aaline->next = next;
next = draw->pipeline.aaline;
precalc_flat = TRUE;
}
 
if (rast->point_smooth && draw->pipeline.aapoint) {
draw->pipeline.aapoint->next = next;
next = draw->pipeline.aapoint;
}
 
if (wide_lines) {
draw->pipeline.wide_line->next = next;
next = draw->pipeline.wide_line;
precalc_flat = TRUE;
}
 
if (wide_points) {
draw->pipeline.wide_point->next = next;
next = draw->pipeline.wide_point;
}
 
if (rast->line_stipple_enable && draw->pipeline.line_stipple) {
draw->pipeline.stipple->next = next;
next = draw->pipeline.stipple;
precalc_flat = TRUE; /* only needed for lines really */
}
 
if (rast->poly_stipple_enable
&& draw->pipeline.pstipple) {
draw->pipeline.pstipple->next = next;
next = draw->pipeline.pstipple;
}
 
if (rast->fill_front != PIPE_POLYGON_MODE_FILL ||
rast->fill_back != PIPE_POLYGON_MODE_FILL) {
draw->pipeline.unfilled->next = next;
next = draw->pipeline.unfilled;
precalc_flat = TRUE; /* only needed for triangles really */
need_det = TRUE;
}
 
if (rast->flatshade && precalc_flat) {
draw->pipeline.flatshade->next = next;
next = draw->pipeline.flatshade;
}
if (rast->offset_point ||
rast->offset_line ||
rast->offset_tri) {
draw->pipeline.offset->next = next;
next = draw->pipeline.offset;
need_det = TRUE;
}
 
if (rast->light_twoside) {
draw->pipeline.twoside->next = next;
next = draw->pipeline.twoside;
need_det = TRUE;
}
 
/* Always run the cull stage as we calculate determinant there
* also.
*
* This can actually be a win as culling out the triangles can lead
* to less work emitting vertices, smaller vertex buffers, etc.
* It's difficult to say whether this will be true in general.
*/
if (need_det || rast->cull_face != PIPE_FACE_NONE ||
draw_current_shader_num_written_culldistances(draw)) {
draw->pipeline.cull->next = next;
next = draw->pipeline.cull;
}
 
/* Clip stage
*/
if (draw->clip_xy || draw->clip_z || draw->clip_user)
{
draw->pipeline.clip->next = next;
next = draw->pipeline.clip;
}
 
draw->pipeline.first = next;
 
if (0) {
debug_printf("draw pipeline:\n");
for (next = draw->pipeline.first; next ; next = next->next )
debug_printf(" %s\n", next->name);
debug_printf("\n");
}
return draw->pipeline.first;
}
 
static void validate_tri( struct draw_stage *stage,
struct prim_header *header )
{
struct draw_stage *pipeline = validate_pipeline( stage );
pipeline->tri( pipeline, header );
}
 
static void validate_line( struct draw_stage *stage,
struct prim_header *header )
{
struct draw_stage *pipeline = validate_pipeline( stage );
pipeline->line( pipeline, header );
}
 
static void validate_point( struct draw_stage *stage,
struct prim_header *header )
{
struct draw_stage *pipeline = validate_pipeline( stage );
pipeline->point( pipeline, header );
}
 
static void validate_reset_stipple_counter( struct draw_stage *stage )
{
struct draw_stage *pipeline = validate_pipeline( stage );
pipeline->reset_stipple_counter( pipeline );
}
 
static void validate_flush( struct draw_stage *stage,
unsigned flags )
{
/* May need to pass a backend flush on to the rasterize stage.
*/
if (stage->next)
stage->next->flush( stage->next, flags );
}
 
 
static void validate_destroy( struct draw_stage *stage )
{
FREE( stage );
}
 
 
/**
* Create validate pipeline stage.
*/
struct draw_stage *draw_validate_stage( struct draw_context *draw )
{
struct draw_stage *stage = CALLOC_STRUCT(draw_stage);
if (stage == NULL)
return NULL;
 
stage->draw = draw;
stage->name = "validate";
stage->next = NULL;
stage->point = validate_point;
stage->line = validate_line;
stage->tri = validate_tri;
stage->flush = validate_flush;
stage->reset_stipple_counter = validate_reset_stipple_counter;
stage->destroy = validate_destroy;
 
return stage;
}
/drivers/video/Gallium/auxiliary/draw/draw_pipe_vbuf.c
0,0 → 1,465
/**************************************************************************
*
* Copyright 2007 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
* Vertex buffer drawing stage.
*
* \author Jose Fonseca <jrfonsec@tungstengraphics.com>
* \author Keith Whitwell <keith@tungstengraphics.com>
*/
 
 
#include "util/u_debug.h"
#include "util/u_math.h"
#include "util/u_memory.h"
 
#include "draw_vbuf.h"
#include "draw_private.h"
#include "draw_vertex.h"
#include "draw_pipe.h"
#include "translate/translate.h"
#include "translate/translate_cache.h"
 
 
/**
* Vertex buffer emit stage.
*/
struct vbuf_stage {
struct draw_stage stage; /**< This must be first (base class) */
 
struct vbuf_render *render;
const struct vertex_info *vinfo;
/** Vertex size in bytes */
unsigned vertex_size;
 
struct translate *translate;
/* FIXME: we have no guarantee that 'unsigned' is 32bit */
 
/** Vertices in hardware format */
unsigned *vertices;
unsigned *vertex_ptr;
unsigned max_vertices;
unsigned nr_vertices;
/** Indices */
ushort *indices;
unsigned max_indices;
unsigned nr_indices;
 
/* Cache point size somewhere it's address won't change:
*/
float point_size;
 
struct translate_cache *cache;
};
 
 
/**
* Basically a cast wrapper.
*/
static INLINE struct vbuf_stage *
vbuf_stage( struct draw_stage *stage )
{
assert(stage);
return (struct vbuf_stage *)stage;
}
 
 
static void vbuf_flush_vertices( struct vbuf_stage *vbuf );
static void vbuf_alloc_vertices( struct vbuf_stage *vbuf );
 
 
static INLINE boolean
overflow( void *map, void *ptr, unsigned bytes, unsigned bufsz )
{
unsigned long used = (unsigned long) ((char *)ptr - (char *)map);
return (used + bytes) > bufsz;
}
 
 
static INLINE void
check_space( struct vbuf_stage *vbuf, unsigned nr )
{
if (vbuf->nr_vertices + nr > vbuf->max_vertices ||
vbuf->nr_indices + nr > vbuf->max_indices)
{
vbuf_flush_vertices( vbuf );
vbuf_alloc_vertices( vbuf );
}
}
 
 
 
 
/**
* Extract the needed fields from post-transformed vertex and emit
* a hardware(driver) vertex.
* Recall that the vertices are constructed by the 'draw' module and
* have a couple of slots at the beginning (1-dword header, 4-dword
* clip pos) that we ignore here. We only use the vertex->data[] fields.
*/
static INLINE ushort
emit_vertex( struct vbuf_stage *vbuf,
struct vertex_header *vertex )
{
if (vertex->vertex_id == UNDEFINED_VERTEX_ID && vbuf->vertex_ptr) {
/* Hmm - vertices are emitted one at a time - better make sure
* set_buffer is efficient. Consider a special one-shot mode for
* translate.
*/
/* Note: we really do want data[0] here, not data[pos]:
*/
vbuf->translate->set_buffer(vbuf->translate, 0, vertex->data[0], 0, ~0);
vbuf->translate->run(vbuf->translate, 0, 1, 0, 0, vbuf->vertex_ptr);
 
if (0) draw_dump_emitted_vertex(vbuf->vinfo, (uint8_t *)vbuf->vertex_ptr);
vbuf->vertex_ptr += vbuf->vertex_size/4;
vertex->vertex_id = vbuf->nr_vertices++;
}
 
return (ushort)vertex->vertex_id;
}
 
 
static void
vbuf_tri( struct draw_stage *stage,
struct prim_header *prim )
{
struct vbuf_stage *vbuf = vbuf_stage( stage );
unsigned i;
 
check_space( vbuf, 3 );
 
for (i = 0; i < 3; i++) {
vbuf->indices[vbuf->nr_indices++] = emit_vertex( vbuf, prim->v[i] );
}
}
 
 
static void
vbuf_line( struct draw_stage *stage,
struct prim_header *prim )
{
struct vbuf_stage *vbuf = vbuf_stage( stage );
unsigned i;
 
check_space( vbuf, 2 );
 
for (i = 0; i < 2; i++) {
vbuf->indices[vbuf->nr_indices++] = emit_vertex( vbuf, prim->v[i] );
}
}
 
 
static void
vbuf_point( struct draw_stage *stage,
struct prim_header *prim )
{
struct vbuf_stage *vbuf = vbuf_stage( stage );
 
check_space( vbuf, 1 );
 
vbuf->indices[vbuf->nr_indices++] = emit_vertex( vbuf, prim->v[0] );
}
 
 
 
 
/**
* Set the prim type for subsequent vertices.
* This may result in a new vertex size. The existing vbuffer (if any)
* will be flushed if needed and a new one allocated.
*/
static void
vbuf_start_prim( struct vbuf_stage *vbuf, uint prim )
{
struct translate_key hw_key;
unsigned dst_offset;
unsigned i;
 
vbuf->render->set_primitive(vbuf->render, prim);
 
/* Must do this after set_primitive() above:
*
* XXX: need some state managment to track when this needs to be
* recalculated. The driver should tell us whether there was a
* state change.
*/
vbuf->vinfo = vbuf->render->get_vertex_info(vbuf->render);
vbuf->vertex_size = vbuf->vinfo->size * sizeof(float);
 
/* Translate from pipeline vertices to hw vertices.
*/
dst_offset = 0;
 
for (i = 0; i < vbuf->vinfo->num_attribs; i++) {
unsigned emit_sz = 0;
unsigned src_buffer = 0;
enum pipe_format output_format;
unsigned src_offset = (vbuf->vinfo->attrib[i].src_index * 4 * sizeof(float) );
 
output_format = draw_translate_vinfo_format(vbuf->vinfo->attrib[i].emit);
emit_sz = draw_translate_vinfo_size(vbuf->vinfo->attrib[i].emit);
 
/* doesn't handle EMIT_OMIT */
assert(emit_sz != 0);
 
if (vbuf->vinfo->attrib[i].emit == EMIT_1F_PSIZE) {
src_buffer = 1;
src_offset = 0;
}
 
hw_key.element[i].type = TRANSLATE_ELEMENT_NORMAL;
hw_key.element[i].input_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
hw_key.element[i].input_buffer = src_buffer;
hw_key.element[i].input_offset = src_offset;
hw_key.element[i].instance_divisor = 0;
hw_key.element[i].output_format = output_format;
hw_key.element[i].output_offset = dst_offset;
 
dst_offset += emit_sz;
}
 
hw_key.nr_elements = vbuf->vinfo->num_attribs;
hw_key.output_stride = vbuf->vinfo->size * 4;
 
/* Don't bother with caching at this stage:
*/
if (!vbuf->translate ||
translate_key_compare(&vbuf->translate->key, &hw_key) != 0)
{
translate_key_sanitize(&hw_key);
vbuf->translate = translate_cache_find(vbuf->cache, &hw_key);
 
vbuf->translate->set_buffer(vbuf->translate, 1, &vbuf->point_size, 0, ~0);
}
 
vbuf->point_size = vbuf->stage.draw->rasterizer->point_size;
 
/* Allocate new buffer?
*/
assert(vbuf->vertices == NULL);
vbuf_alloc_vertices(vbuf);
}
 
 
static void
vbuf_first_tri( struct draw_stage *stage,
struct prim_header *prim )
{
struct vbuf_stage *vbuf = vbuf_stage( stage );
 
vbuf_flush_vertices( vbuf );
vbuf_start_prim(vbuf, PIPE_PRIM_TRIANGLES);
stage->tri = vbuf_tri;
stage->tri( stage, prim );
}
 
 
static void
vbuf_first_line( struct draw_stage *stage,
struct prim_header *prim )
{
struct vbuf_stage *vbuf = vbuf_stage( stage );
 
vbuf_flush_vertices( vbuf );
vbuf_start_prim(vbuf, PIPE_PRIM_LINES);
stage->line = vbuf_line;
stage->line( stage, prim );
}
 
 
static void
vbuf_first_point( struct draw_stage *stage,
struct prim_header *prim )
{
struct vbuf_stage *vbuf = vbuf_stage( stage );
 
vbuf_flush_vertices(vbuf);
vbuf_start_prim(vbuf, PIPE_PRIM_POINTS);
stage->point = vbuf_point;
stage->point( stage, prim );
}
 
 
 
/**
* Flush existing vertex buffer and allocate a new one.
*/
static void
vbuf_flush_vertices( struct vbuf_stage *vbuf )
{
if(vbuf->vertices) {
 
vbuf->render->unmap_vertices( vbuf->render, 0, vbuf->nr_vertices - 1 );
 
if (vbuf->nr_indices)
{
vbuf->render->draw_elements(vbuf->render,
vbuf->indices,
vbuf->nr_indices );
vbuf->nr_indices = 0;
}
/* Reset temporary vertices ids */
if(vbuf->nr_vertices)
draw_reset_vertex_ids( vbuf->stage.draw );
/* Free the vertex buffer */
vbuf->render->release_vertices( vbuf->render );
 
vbuf->max_vertices = vbuf->nr_vertices = 0;
vbuf->vertex_ptr = vbuf->vertices = NULL;
}
 
/* Reset point/line/tri function pointers.
* If (for example) we transition from points to tris and back to points
* again, we need to call the vbuf_first_point() function again to flush
* the triangles before drawing more points. This can happen when drawing
* with front polygon mode = filled and back polygon mode = line or point.
*/
vbuf->stage.point = vbuf_first_point;
vbuf->stage.line = vbuf_first_line;
vbuf->stage.tri = vbuf_first_tri;
}
 
static void
vbuf_alloc_vertices( struct vbuf_stage *vbuf )
{
if (vbuf->vertex_ptr) {
assert(!vbuf->nr_indices);
assert(!vbuf->vertices);
}
/* Allocate a new vertex buffer */
vbuf->max_vertices = vbuf->render->max_vertex_buffer_bytes / vbuf->vertex_size;
 
if(vbuf->max_vertices >= UNDEFINED_VERTEX_ID)
vbuf->max_vertices = UNDEFINED_VERTEX_ID - 1;
 
/* Must always succeed -- driver gives us a
* 'max_vertex_buffer_bytes' which it guarantees it can allocate,
* and it will flush itself if necessary to do so. If this does
* fail, we are basically without usable hardware.
*/
vbuf->render->allocate_vertices(vbuf->render,
(ushort) vbuf->vertex_size,
(ushort) vbuf->max_vertices);
 
vbuf->vertices = (uint *) vbuf->render->map_vertices( vbuf->render );
vbuf->vertex_ptr = vbuf->vertices;
}
 
 
 
static void
vbuf_flush( struct draw_stage *stage, unsigned flags )
{
struct vbuf_stage *vbuf = vbuf_stage( stage );
 
vbuf_flush_vertices( vbuf );
}
 
 
static void
vbuf_reset_stipple_counter( struct draw_stage *stage )
{
/* XXX: Need to do something here for hardware with linestipple.
*/
(void) stage;
}
 
 
static void vbuf_destroy( struct draw_stage *stage )
{
struct vbuf_stage *vbuf = vbuf_stage( stage );
 
if(vbuf->indices)
align_free( vbuf->indices );
if (vbuf->render)
vbuf->render->destroy( vbuf->render );
 
if (vbuf->cache)
translate_cache_destroy(vbuf->cache);
 
FREE( stage );
}
 
 
/**
* Create a new primitive vbuf/render stage.
*/
struct draw_stage *draw_vbuf_stage( struct draw_context *draw,
struct vbuf_render *render )
{
struct vbuf_stage *vbuf = CALLOC_STRUCT(vbuf_stage);
if (vbuf == NULL)
goto fail;
vbuf->stage.draw = draw;
vbuf->stage.name = "vbuf";
vbuf->stage.point = vbuf_first_point;
vbuf->stage.line = vbuf_first_line;
vbuf->stage.tri = vbuf_first_tri;
vbuf->stage.flush = vbuf_flush;
vbuf->stage.reset_stipple_counter = vbuf_reset_stipple_counter;
vbuf->stage.destroy = vbuf_destroy;
vbuf->render = render;
vbuf->max_indices = MIN2(render->max_indices, UNDEFINED_VERTEX_ID-1);
 
vbuf->indices = (ushort *) align_malloc( vbuf->max_indices *
sizeof(vbuf->indices[0]),
16 );
if (!vbuf->indices)
goto fail;
 
vbuf->cache = translate_cache_create();
if (!vbuf->cache)
goto fail;
vbuf->vertices = NULL;
vbuf->vertex_ptr = vbuf->vertices;
return &vbuf->stage;
 
fail:
if (vbuf)
vbuf_destroy(&vbuf->stage);
return NULL;
}
/drivers/video/Gallium/auxiliary/draw/draw_pipe_wide_line.c
0,0 → 1,228
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/* Authors: Keith Whitwell <keith@tungstengraphics.com>
*/
 
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "pipe/p_shader_tokens.h"
#include "util/u_math.h"
#include "util/u_memory.h"
#include "draw_private.h"
#include "draw_pipe.h"
 
 
struct wideline_stage {
struct draw_stage stage;
 
float half_line_width;
};
 
 
 
static INLINE struct wideline_stage *wideline_stage( struct draw_stage *stage )
{
return (struct wideline_stage *)stage;
}
 
 
 
/**
* Draw a wide line by drawing a quad (two triangles).
*/
static void wideline_line( struct draw_stage *stage,
struct prim_header *header )
{
/*const struct wideline_stage *wide = wideline_stage(stage);*/
const unsigned pos = draw_current_shader_position_output(stage->draw);
const float half_width = 0.5f * stage->draw->rasterizer->line_width;
 
struct prim_header tri;
 
struct vertex_header *v0 = dup_vert(stage, header->v[0], 0);
struct vertex_header *v1 = dup_vert(stage, header->v[0], 1);
struct vertex_header *v2 = dup_vert(stage, header->v[1], 2);
struct vertex_header *v3 = dup_vert(stage, header->v[1], 3);
 
float *pos0 = v0->data[pos];
float *pos1 = v1->data[pos];
float *pos2 = v2->data[pos];
float *pos3 = v3->data[pos];
 
const float dx = fabsf(pos0[0] - pos2[0]);
const float dy = fabsf(pos0[1] - pos2[1]);
 
const boolean half_pixel_center =
stage->draw->rasterizer->half_pixel_center;
 
/* small tweak to meet GL specification */
const float bias = half_pixel_center ? 0.125f : 0.0f;
 
/*
* Draw wide line as a quad (two tris) by "stretching" the line along
* X or Y.
* We need to tweak coords in several ways to be conformant here.
*/
 
if (dx > dy) {
/* x-major line */
pos0[1] = pos0[1] - half_width - bias;
pos1[1] = pos1[1] + half_width - bias;
pos2[1] = pos2[1] - half_width - bias;
pos3[1] = pos3[1] + half_width - bias;
if (half_pixel_center) {
if (pos0[0] < pos2[0]) {
/* left to right line */
pos0[0] -= 0.5f;
pos1[0] -= 0.5f;
pos2[0] -= 0.5f;
pos3[0] -= 0.5f;
}
else {
/* right to left line */
pos0[0] += 0.5f;
pos1[0] += 0.5f;
pos2[0] += 0.5f;
pos3[0] += 0.5f;
}
}
}
else {
/* y-major line */
pos0[0] = pos0[0] - half_width + bias;
pos1[0] = pos1[0] + half_width + bias;
pos2[0] = pos2[0] - half_width + bias;
pos3[0] = pos3[0] + half_width + bias;
if (half_pixel_center) {
if (pos0[1] < pos2[1]) {
/* top to bottom line */
pos0[1] -= 0.5f;
pos1[1] -= 0.5f;
pos2[1] -= 0.5f;
pos3[1] -= 0.5f;
}
else {
/* bottom to top line */
pos0[1] += 0.5f;
pos1[1] += 0.5f;
pos2[1] += 0.5f;
pos3[1] += 0.5f;
}
}
}
 
tri.det = header->det; /* only the sign matters */
tri.v[0] = v0;
tri.v[1] = v2;
tri.v[2] = v3;
stage->next->tri( stage->next, &tri );
 
tri.v[0] = v0;
tri.v[1] = v3;
tri.v[2] = v1;
stage->next->tri( stage->next, &tri );
}
 
 
static void wideline_first_line( struct draw_stage *stage,
struct prim_header *header )
{
struct draw_context *draw = stage->draw;
struct pipe_context *pipe = draw->pipe;
const struct pipe_rasterizer_state *rast = draw->rasterizer;
void *r;
 
/* Disable triangle culling, stippling, unfilled mode etc. */
r = draw_get_rasterizer_no_cull(draw, rast->scissor, rast->flatshade);
draw->suspend_flushing = TRUE;
pipe->bind_rasterizer_state(pipe, r);
draw->suspend_flushing = FALSE;
 
stage->line = wideline_line;
 
wideline_line(stage, header);
}
 
 
static void wideline_flush( struct draw_stage *stage, unsigned flags )
{
struct draw_context *draw = stage->draw;
struct pipe_context *pipe = draw->pipe;
 
stage->line = wideline_first_line;
stage->next->flush( stage->next, flags );
 
/* restore original rasterizer state */
if (draw->rast_handle) {
draw->suspend_flushing = TRUE;
pipe->bind_rasterizer_state(pipe, draw->rast_handle);
draw->suspend_flushing = FALSE;
}
}
 
 
static void wideline_reset_stipple_counter( struct draw_stage *stage )
{
stage->next->reset_stipple_counter( stage->next );
}
 
 
static void wideline_destroy( struct draw_stage *stage )
{
draw_free_temp_verts( stage );
FREE( stage );
}
 
 
struct draw_stage *draw_wide_line_stage( struct draw_context *draw )
{
struct wideline_stage *wide = CALLOC_STRUCT(wideline_stage);
if (wide == NULL)
goto fail;
 
wide->stage.draw = draw;
wide->stage.name = "wide-line";
wide->stage.next = NULL;
wide->stage.point = draw_pipe_passthrough_point;
wide->stage.line = wideline_first_line;
wide->stage.tri = draw_pipe_passthrough_tri;
wide->stage.flush = wideline_flush;
wide->stage.reset_stipple_counter = wideline_reset_stipple_counter;
wide->stage.destroy = wideline_destroy;
 
if (!draw_alloc_temp_verts( &wide->stage, 4 ))
goto fail;
 
return &wide->stage;
 
fail:
if (wide)
wide->stage.destroy( &wide->stage );
 
return NULL;
}
/drivers/video/Gallium/auxiliary/draw/draw_pipe_wide_point.c
0,0 → 1,346
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/* Authors: Keith Whitwell <keith@tungstengraphics.com>
*/
 
/**
* Notes on wide points and sprite mode:
*
* In wide point/sprite mode we effectively need to convert each incoming
* vertex into four outgoing vertices specifying the corners of a quad.
* Since we don't (yet) have geometry shaders, we have to handle this here
* in the draw module.
*
* For sprites, it also means that this is where we have to handle texcoords
* for the vertices of the quad. OpenGL's GL_COORD_REPLACE state specifies
* if/how enabled texcoords are automatically generated for sprites. We pass
* that info through gallium in the pipe_rasterizer_state::sprite_coord_mode
* array.
*
* Additionally, GLSL's gl_PointCoord fragment attribute has to be handled
* here as well. This is basically an additional texture/generic attribute
* that varies .x from 0 to 1 horizontally across the point and varies .y
* vertically from 0 to 1 down the sprite.
*
* With geometry shaders, the state tracker could create a GS to do
* most/all of this.
*/
 
 
#include "pipe/p_screen.h"
#include "pipe/p_context.h"
#include "util/u_math.h"
#include "util/u_memory.h"
#include "pipe/p_defines.h"
#include "pipe/p_shader_tokens.h"
#include "draw_fs.h"
#include "draw_vs.h"
#include "draw_pipe.h"
 
 
struct widepoint_stage {
struct draw_stage stage; /**< base class */
 
float half_point_size;
 
float xbias;
float ybias;
 
/** for automatic texcoord generation/replacement */
uint num_texcoord_gen;
uint texcoord_gen_slot[PIPE_MAX_SHADER_OUTPUTS];
 
/* TGSI_SEMANTIC to which sprite_coord_enable applies */
unsigned sprite_coord_semantic;
 
int psize_slot;
};
 
 
 
static INLINE struct widepoint_stage *
widepoint_stage( struct draw_stage *stage )
{
return (struct widepoint_stage *)stage;
}
 
 
/**
* Set the vertex texcoords for sprite mode.
* Coords may be left untouched or set to a right-side-up or upside-down
* orientation.
*/
static void set_texcoords(const struct widepoint_stage *wide,
struct vertex_header *v, const float tc[4])
{
const struct draw_context *draw = wide->stage.draw;
const struct pipe_rasterizer_state *rast = draw->rasterizer;
const uint texcoord_mode = rast->sprite_coord_mode;
uint i;
 
for (i = 0; i < wide->num_texcoord_gen; i++) {
const uint slot = wide->texcoord_gen_slot[i];
v->data[slot][0] = tc[0];
if (texcoord_mode == PIPE_SPRITE_COORD_LOWER_LEFT)
v->data[slot][1] = 1.0f - tc[1];
else
v->data[slot][1] = tc[1];
v->data[slot][2] = tc[2];
v->data[slot][3] = tc[3];
}
}
 
 
/* If there are lots of sprite points (and why wouldn't there be?) it
* would probably be more sensible to change hardware setup to
* optimize this rather than doing the whole thing in software like
* this.
*/
static void widepoint_point( struct draw_stage *stage,
struct prim_header *header )
{
const struct widepoint_stage *wide = widepoint_stage(stage);
const unsigned pos = draw_current_shader_position_output(stage->draw);
const boolean sprite = (boolean) stage->draw->rasterizer->point_quad_rasterization;
float half_size;
float left_adj, right_adj, bot_adj, top_adj;
 
struct prim_header tri;
 
/* four dups of original vertex */
struct vertex_header *v0 = dup_vert(stage, header->v[0], 0);
struct vertex_header *v1 = dup_vert(stage, header->v[0], 1);
struct vertex_header *v2 = dup_vert(stage, header->v[0], 2);
struct vertex_header *v3 = dup_vert(stage, header->v[0], 3);
 
float *pos0 = v0->data[pos];
float *pos1 = v1->data[pos];
float *pos2 = v2->data[pos];
float *pos3 = v3->data[pos];
 
/* point size is either per-vertex or fixed size */
if (wide->psize_slot >= 0) {
half_size = header->v[0]->data[wide->psize_slot][0];
half_size *= 0.5f;
}
else {
half_size = wide->half_point_size;
}
 
left_adj = -half_size + wide->xbias;
right_adj = half_size + wide->xbias;
bot_adj = half_size + wide->ybias;
top_adj = -half_size + wide->ybias;
 
pos0[0] += left_adj;
pos0[1] += top_adj;
 
pos1[0] += left_adj;
pos1[1] += bot_adj;
 
pos2[0] += right_adj;
pos2[1] += top_adj;
 
pos3[0] += right_adj;
pos3[1] += bot_adj;
 
if (sprite) {
static const float tex00[4] = { 0, 0, 0, 1 };
static const float tex01[4] = { 0, 1, 0, 1 };
static const float tex11[4] = { 1, 1, 0, 1 };
static const float tex10[4] = { 1, 0, 0, 1 };
set_texcoords( wide, v0, tex00 );
set_texcoords( wide, v1, tex01 );
set_texcoords( wide, v2, tex10 );
set_texcoords( wide, v3, tex11 );
}
 
tri.det = header->det; /* only the sign matters */
tri.v[0] = v0;
tri.v[1] = v2;
tri.v[2] = v3;
stage->next->tri( stage->next, &tri );
 
tri.v[0] = v0;
tri.v[1] = v3;
tri.v[2] = v1;
stage->next->tri( stage->next, &tri );
}
 
 
static void
widepoint_first_point(struct draw_stage *stage,
struct prim_header *header)
{
struct widepoint_stage *wide = widepoint_stage(stage);
struct draw_context *draw = stage->draw;
struct pipe_context *pipe = draw->pipe;
const struct pipe_rasterizer_state *rast = draw->rasterizer;
void *r;
 
wide->half_point_size = 0.5f * rast->point_size;
wide->xbias = 0.0;
wide->ybias = 0.0;
 
if (rast->half_pixel_center) {
wide->xbias = 0.125;
wide->ybias = -0.125;
}
 
/* Disable triangle culling, stippling, unfilled mode etc. */
r = draw_get_rasterizer_no_cull(draw, rast->scissor, rast->flatshade);
draw->suspend_flushing = TRUE;
pipe->bind_rasterizer_state(pipe, r);
draw->suspend_flushing = FALSE;
 
/* XXX we won't know the real size if it's computed by the vertex shader! */
if ((rast->point_size > draw->pipeline.wide_point_threshold) ||
(rast->point_quad_rasterization && draw->pipeline.point_sprite)) {
stage->point = widepoint_point;
}
else {
stage->point = draw_pipe_passthrough_point;
}
 
draw_remove_extra_vertex_attribs(draw);
 
if (rast->point_quad_rasterization) {
const struct draw_fragment_shader *fs = draw->fs.fragment_shader;
uint i;
 
assert(fs);
 
wide->num_texcoord_gen = 0;
 
/* Loop over fragment shader inputs looking for the PCOORD input or inputs
* for which bit 'k' in sprite_coord_enable is set.
*/
for (i = 0; i < fs->info.num_inputs; i++) {
int slot;
const unsigned sn = fs->info.input_semantic_name[i];
const unsigned si = fs->info.input_semantic_index[i];
 
if (sn == wide->sprite_coord_semantic) {
/* Note that sprite_coord_enable is a bitfield of 32 bits. */
if (si >= 32 || !(rast->sprite_coord_enable & (1 << si)))
continue;
} else if (sn != TGSI_SEMANTIC_PCOORD) {
continue;
}
 
/* OK, this generic attribute needs to be replaced with a
* sprite coord (see above).
*/
slot = draw_alloc_extra_vertex_attrib(draw, sn, si);
 
/* add this slot to the texcoord-gen list */
wide->texcoord_gen_slot[wide->num_texcoord_gen++] = slot;
}
}
 
wide->psize_slot = -1;
if (rast->point_size_per_vertex) {
/* find PSIZ vertex output */
const struct draw_vertex_shader *vs = draw->vs.vertex_shader;
uint i;
for (i = 0; i < vs->info.num_outputs; i++) {
if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_PSIZE) {
wide->psize_slot = i;
break;
}
}
}
stage->point( stage, header );
}
 
 
static void widepoint_flush( struct draw_stage *stage, unsigned flags )
{
struct draw_context *draw = stage->draw;
struct pipe_context *pipe = draw->pipe;
 
stage->point = widepoint_first_point;
stage->next->flush( stage->next, flags );
 
draw_remove_extra_vertex_attribs(draw);
 
/* restore original rasterizer state */
if (draw->rast_handle) {
draw->suspend_flushing = TRUE;
pipe->bind_rasterizer_state(pipe, draw->rast_handle);
draw->suspend_flushing = FALSE;
}
}
 
 
static void widepoint_reset_stipple_counter( struct draw_stage *stage )
{
stage->next->reset_stipple_counter( stage->next );
}
 
 
static void widepoint_destroy( struct draw_stage *stage )
{
draw_free_temp_verts( stage );
FREE( stage );
}
 
 
struct draw_stage *draw_wide_point_stage( struct draw_context *draw )
{
struct widepoint_stage *wide = CALLOC_STRUCT(widepoint_stage);
if (wide == NULL)
goto fail;
 
wide->stage.draw = draw;
wide->stage.name = "wide-point";
wide->stage.next = NULL;
wide->stage.point = widepoint_first_point;
wide->stage.line = draw_pipe_passthrough_line;
wide->stage.tri = draw_pipe_passthrough_tri;
wide->stage.flush = widepoint_flush;
wide->stage.reset_stipple_counter = widepoint_reset_stipple_counter;
wide->stage.destroy = widepoint_destroy;
 
if (!draw_alloc_temp_verts( &wide->stage, 4 ))
goto fail;
 
wide->sprite_coord_semantic =
draw->pipe->screen->get_param(draw->pipe->screen, PIPE_CAP_TGSI_TEXCOORD)
?
TGSI_SEMANTIC_TEXCOORD : TGSI_SEMANTIC_GENERIC;
 
return &wide->stage;
 
fail:
if (wide)
wide->stage.destroy( &wide->stage );
return NULL;
}
/drivers/video/Gallium/auxiliary/draw/draw_prim_assembler.c
0,0 → 1,225
/**************************************************************************
*
* Copyright 2013 VMware, Inc.
* 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 VMWARE 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.
*
**************************************************************************/
 
#include "draw_prim_assembler.h"
 
#include "util/u_debug.h"
#include "util/u_memory.h"
#include "util/u_prim.h"
 
#include "pipe/p_defines.h"
 
struct draw_assembler
{
struct draw_context *draw;
 
struct draw_prim_info *output_prims;
struct draw_vertex_info *output_verts;
 
const struct draw_prim_info *input_prims;
const struct draw_vertex_info *input_verts;
};
 
boolean
draw_prim_assembler_is_required(const struct draw_context *draw,
const struct draw_prim_info *prim_info,
const struct draw_vertex_info *vert_info)
{
switch (prim_info->prim) {
case PIPE_PRIM_LINES_ADJACENCY:
case PIPE_PRIM_LINE_STRIP_ADJACENCY:
case PIPE_PRIM_TRIANGLES_ADJACENCY:
case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
return TRUE;
default:
return FALSE;
}
}
 
/*
* Copy the vertex header along with its data from the current
* vertex buffer into a buffer holding vertices arranged
* into decomposed primitives (i.e. buffer without the
* adjacency vertices)
*/
static void
copy_verts(struct draw_assembler *asmblr,
unsigned *indices, unsigned num_indices)
{
unsigned i;
 
char *output = (char*)asmblr->output_verts->verts;
const char *input = (const char*)asmblr->input_verts->verts;
 
for (i = 0; i < num_indices; ++i) {
unsigned idx = indices[i];
unsigned output_offset =
asmblr->output_verts->count * asmblr->output_verts->stride;
unsigned input_offset = asmblr->input_verts->stride * idx;
memcpy(output + output_offset, input + input_offset,
asmblr->input_verts->vertex_size);
asmblr->output_verts->count += 1;
}
}
 
static void
prim_point(struct draw_assembler *asmblr,
unsigned idx)
{
unsigned indices[1];
 
indices[0] = idx;
 
copy_verts(asmblr, indices, 1);
}
 
static void
prim_line(struct draw_assembler *asmblr,
unsigned i0, unsigned i1)
{
unsigned indices[2];
 
indices[0] = i0;
indices[1] = i1;
 
copy_verts(asmblr, indices, 2);
}
 
static void
prim_line_adj(struct draw_assembler *asmblr,
unsigned i0, unsigned i1, unsigned i2, unsigned i3)
{
unsigned indices[2];
 
indices[0] = i1;
indices[1] = i2;
 
copy_verts(asmblr, indices, 2);
}
 
static void
prim_tri(struct draw_assembler *asmblr,
unsigned i0, unsigned i1, unsigned i2)
{
unsigned indices[3];
 
indices[0] = i0;
indices[1] = i1;
indices[2] = i2;
 
copy_verts(asmblr, indices, 3);
}
 
static void
prim_tri_adj(struct draw_assembler *asmblr,
unsigned i0, unsigned i1, unsigned i2,
unsigned i3, unsigned i4, unsigned i5)
{
unsigned indices[3];
 
indices[0] = i0;
indices[1] = i2;
indices[2] = i4;
 
copy_verts(asmblr, indices, 3);
}
 
 
 
#define FUNC assembler_run_linear
#define GET_ELT(idx) (start + (idx))
#include "draw_prim_assembler_tmp.h"
 
#define FUNC assembler_run_elts
#define LOCAL_VARS const ushort *elts = input_prims->elts;
#define GET_ELT(idx) (elts[start + (idx)])
#include "draw_prim_assembler_tmp.h"
 
 
 
/*
* Primitive assembler breaks up adjacency primitives and assembles
* the base primitives they represent, e.g. vertices forming
* PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY
* become vertices forming PIPE_PRIM_TRIANGLES
* This is needed because specification says that the adjacency
* primitives are only visible in the geometry shader so we need
* to get rid of them so that the rest of the pipeline can
* process the inputs.
*/
void
draw_prim_assembler_run(struct draw_context *draw,
const struct draw_prim_info *input_prims,
const struct draw_vertex_info *input_verts,
struct draw_prim_info *output_prims,
struct draw_vertex_info *output_verts)
{
struct draw_assembler asmblr;
unsigned start, i;
unsigned assembled_prim = u_assembled_prim(input_prims->prim);
unsigned max_primitives = u_decomposed_prims_for_vertices(
input_prims->prim, input_prims->count);
unsigned max_verts = u_vertices_per_prim(assembled_prim) * max_primitives;
 
asmblr.draw = draw;
asmblr.output_prims = output_prims;
asmblr.output_verts = output_verts;
asmblr.input_prims = input_prims;
asmblr.input_verts = input_verts;
 
output_prims->linear = TRUE;
output_prims->elts = NULL;
output_prims->start = 0;
output_prims->prim = u_assembled_prim(input_prims->prim);
output_prims->flags = 0x0;
output_prims->primitive_lengths = MALLOC(sizeof(unsigned));
output_prims->primitive_lengths[0] = 0;
output_prims->primitive_count = 1;
 
output_verts->vertex_size = input_verts->vertex_size;
output_verts->stride = input_verts->stride;
output_verts->verts = (struct vertex_header*)MALLOC(
input_verts->vertex_size * max_verts);
output_verts->count = 0;
 
 
for (start = i = 0; i < input_prims->primitive_count;
start += input_prims->primitive_lengths[i], i++)
{
unsigned count = input_prims->primitive_lengths[i];
if (input_prims->linear) {
assembler_run_linear(&asmblr, input_prims, input_verts,
start, count);
} else {
assembler_run_elts(&asmblr, input_prims, input_verts,
start, count);
}
}
 
output_prims->primitive_lengths[0] = output_verts->count;
output_prims->count = output_verts->count;
}
/drivers/video/Gallium/auxiliary/draw/draw_prim_assembler.h
0,0 → 1,62
/**************************************************************************
*
* Copyright 2013 VMware, Inc.
* 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 VMWARE 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.
*
**************************************************************************/
 
/*
* Input assembler needs to be able to decompose adjacency primitives
* into something that can be understood by the rest of the pipeline.
* The specs say that the adjacency primitives are *only* visible
* in the geometry shader, for everything else they need to be
* decomposed. Which in most of the cases is not an issue, because the
* geometry shader always decomposes them for us, but without geometry
* shader we were passing unchanged adjacency primitives to the
* rest of the pipeline and causing crashes everywhere.
* If geometry shader is missing and the input primitive is one of
* the adjacency primitives we use the code from this file to
* decompose them into something that the rest of the pipeline can
* understand.
*
*/
 
#ifndef DRAW_PRIM_ASSEMBLER_H
#define DRAW_PRIM_ASSEMBLER_H
 
#include "draw/draw_private.h"
 
boolean
draw_prim_assembler_is_required(const struct draw_context *draw,
const struct draw_prim_info *prim_info,
const struct draw_vertex_info *vert_info);
 
void
draw_prim_assembler_run(struct draw_context *draw,
const struct draw_prim_info *in_prim_info,
const struct draw_vertex_info *in_vert_info,
struct draw_prim_info *out_prim_info,
struct draw_vertex_info *out_vert_info);
 
 
#endif
/drivers/video/Gallium/auxiliary/draw/draw_prim_assembler_tmp.h
0,0 → 1,31
#define FUNC_VARS \
struct draw_assembler *asmblr, \
const struct draw_prim_info *input_prims, \
const struct draw_vertex_info *input_verts, \
unsigned start, \
unsigned count
 
#define FUNC_ENTER \
/* declare more local vars */ \
const unsigned prim = input_prims->prim; \
const unsigned prim_flags = input_prims->flags; \
const boolean quads_flatshade_last = FALSE; \
const boolean last_vertex_last = !asmblr->draw->rasterizer->flatshade_first; \
switch (prim) { \
case PIPE_PRIM_QUADS: \
case PIPE_PRIM_QUAD_STRIP: \
case PIPE_PRIM_POLYGON: \
debug_assert(!"unexpected primitive type in prim assembler"); \
return; \
default: \
break; \
} \
 
 
#define POINT(i0) prim_point(asmblr, i0)
#define LINE(flags, i0, i1) prim_line(asmblr, i0, i1)
#define TRIANGLE(flags, i0, i1, i2) prim_tri(asmblr, i0, i1, i2)
#define LINE_ADJ(flags, i0, i1, i2, i3) prim_line_adj(asmblr, i0, i1, i2, i3)
#define TRIANGLE_ADJ(flags,i0,i1,i2,i3,i4,i5) prim_tri_adj(asmblr,i0,i1,i2,i3,i4,i5)
 
#include "draw_decompose_tmp.h"
/drivers/video/Gallium/auxiliary/draw/draw_private.h
0,0 → 1,509
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/**
* Private data structures, etc for the draw module.
*/
 
 
/**
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
* Brian Paul
*/
 
 
#ifndef DRAW_PRIVATE_H
#define DRAW_PRIVATE_H
 
 
#include "pipe/p_state.h"
#include "pipe/p_defines.h"
 
#include "tgsi/tgsi_scan.h"
 
#ifdef HAVE_LLVM
struct draw_llvm;
struct gallivm_state;
#endif
 
 
/** Sum of frustum planes and user-defined planes */
#define DRAW_TOTAL_CLIP_PLANES (6 + PIPE_MAX_CLIP_PLANES)
 
/**
* The largest possible index of a vertex that can be fetched.
*/
#define DRAW_MAX_FETCH_IDX 0xffffffff
 
struct pipe_context;
struct draw_vertex_shader;
struct draw_context;
struct draw_stage;
struct vbuf_render;
struct tgsi_exec_machine;
struct tgsi_sampler;
struct draw_pt_front_end;
 
 
/**
* Represents the mapped vertex buffer.
*/
struct draw_vertex_buffer {
const void *map;
uint32_t size;
};
 
/**
* Basic vertex info.
* Carry some useful information around with the vertices in the prim pipe.
*/
struct vertex_header {
unsigned clipmask:DRAW_TOTAL_CLIP_PLANES;
unsigned edgeflag:1;
unsigned have_clipdist:1;
unsigned vertex_id:16;
 
float clip[4];
float pre_clip_pos[4];
 
/* This will probably become float (*data)[4] soon:
*/
float data[][4];
};
 
/* NOTE: It should match vertex_id size above */
#define UNDEFINED_VERTEX_ID 0xffff
 
 
/* maximum number of shader variants we can cache */
#define DRAW_MAX_SHADER_VARIANTS 128
 
/**
* Private context for the drawing module.
*/
struct draw_context
{
struct pipe_context *pipe;
 
/** Drawing/primitive pipeline stages */
struct {
struct draw_stage *first; /**< one of the following */
 
struct draw_stage *validate;
 
/* stages (in logical order) */
struct draw_stage *flatshade;
struct draw_stage *clip;
struct draw_stage *cull;
struct draw_stage *twoside;
struct draw_stage *offset;
struct draw_stage *unfilled;
struct draw_stage *stipple;
struct draw_stage *aapoint;
struct draw_stage *aaline;
struct draw_stage *pstipple;
struct draw_stage *wide_line;
struct draw_stage *wide_point;
struct draw_stage *rasterize;
 
float wide_point_threshold; /**< convert pnts to tris if larger than this */
float wide_line_threshold; /**< convert lines to tris if wider than this */
boolean wide_point_sprites; /**< convert points to tris for sprite mode */
boolean line_stipple; /**< do line stipple? */
boolean point_sprite; /**< convert points to quads for sprites? */
 
/* Temporary storage while the pipeline is being run:
*/
char *verts;
unsigned vertex_stride;
unsigned vertex_count;
} pipeline;
 
 
struct vbuf_render *render;
 
/* Support prototype passthrough path:
*/
struct {
/* Current active frontend */
struct draw_pt_front_end *frontend;
unsigned prim;
unsigned opt; /**< bitmask of PT_x flags */
unsigned eltSize; /* saved eltSize for flushing */
 
boolean rebind_parameters;
 
struct {
struct draw_pt_middle_end *fetch_emit;
struct draw_pt_middle_end *fetch_shade_emit;
struct draw_pt_middle_end *general;
struct draw_pt_middle_end *llvm;
} middle;
 
struct {
struct draw_pt_front_end *vsplit;
} front;
 
struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
unsigned nr_vertex_buffers;
 
/*
* This is the largest legal index value for the current set of
* bound vertex buffers. Regardless of any other consideration,
* all vertex lookups need to be clamped to 0..max_index to
* prevent out-of-bound access.
*/
unsigned max_index;
 
struct pipe_vertex_element vertex_element[PIPE_MAX_ATTRIBS];
unsigned nr_vertex_elements;
 
/* user-space vertex data, buffers */
struct {
/** vertex element/index buffer (ex: glDrawElements) */
const void *elts;
/** bytes per index (0, 1, 2 or 4) */
unsigned eltSizeIB;
unsigned eltSize;
unsigned eltMax;
int eltBias;
unsigned min_index;
unsigned max_index;
/** vertex arrays */
struct draw_vertex_buffer vbuffer[PIPE_MAX_ATTRIBS];
/** constant buffers (for vertex/geometry shader) */
const void *vs_constants[PIPE_MAX_CONSTANT_BUFFERS];
unsigned vs_constants_size[PIPE_MAX_CONSTANT_BUFFERS];
const void *gs_constants[PIPE_MAX_CONSTANT_BUFFERS];
unsigned gs_constants_size[PIPE_MAX_CONSTANT_BUFFERS];
/* pointer to planes */
float (*planes)[DRAW_TOTAL_CLIP_PLANES][4];
} user;
 
boolean test_fse; /* enable FSE even though its not correct (eg for softpipe) */
boolean no_fse; /* disable FSE even when it is correct */
} pt;
 
struct {
boolean bypass_clip_xy;
boolean bypass_clip_z;
boolean guard_band_xy;
} driver;
 
boolean quads_always_flatshade_last;
 
boolean flushing; /**< debugging/sanity */
boolean suspend_flushing; /**< internally set */
 
/* Flags set if API requires clipping in these planes and the
* driver doesn't indicate that it can do it for us.
*/
boolean clip_xy;
boolean clip_z;
boolean clip_user;
boolean guard_band_xy;
 
boolean force_passthrough; /**< never clip or shade */
 
boolean dump_vs;
 
double mrd; /**< minimum resolvable depth value, for polygon offset */
 
/** Current rasterizer state given to us by the driver */
const struct pipe_rasterizer_state *rasterizer;
/** Driver CSO handle for the current rasterizer state */
void *rast_handle;
 
/** Rasterizer CSOs without culling/stipple/etc */
void *rasterizer_no_cull[2][2];
 
struct pipe_viewport_state viewports[PIPE_MAX_VIEWPORTS];
boolean identity_viewport;
 
/** Vertex shader state */
struct {
struct draw_vertex_shader *vertex_shader;
uint num_vs_outputs; /**< convenience, from vertex_shader */
uint position_output;
uint edgeflag_output;
uint clipvertex_output;
uint clipdistance_output[2];
 
/** Fields for TGSI interpreter / execution */
struct {
struct tgsi_exec_machine *machine;
 
struct tgsi_sampler *sampler;
} tgsi;
 
struct translate *fetch;
struct translate_cache *fetch_cache;
struct translate *emit;
struct translate_cache *emit_cache;
} vs;
 
/** Geometry shader state */
struct {
struct draw_geometry_shader *geometry_shader;
uint num_gs_outputs; /**< convenience, from geometry_shader */
uint position_output;
 
/** Fields for TGSI interpreter / execution */
struct {
struct tgsi_exec_machine *machine;
 
struct tgsi_sampler *sampler;
} tgsi;
 
} gs;
 
/** Fragment shader state */
struct {
struct draw_fragment_shader *fragment_shader;
} fs;
 
/** Stream output (vertex feedback) state */
struct {
struct draw_so_target *targets[PIPE_MAX_SO_BUFFERS];
uint num_targets;
} so;
 
/* Clip derived state:
*/
float plane[DRAW_TOTAL_CLIP_PLANES][4];
 
/* If a prim stage introduces new vertex attributes, they'll be stored here
*/
struct {
uint num;
uint semantic_name[10];
uint semantic_index[10];
uint slot[10];
} extra_shader_outputs;
 
unsigned instance_id;
unsigned start_instance;
 
#ifdef HAVE_LLVM
struct draw_llvm *llvm;
#endif
 
/** Texture sampler and sampler view state.
* Note that we have arrays indexed by shader type. At this time
* we only handle vertex and geometry shaders in the draw module, but
* there may be more in the future (ex: hull and tessellation).
*/
struct pipe_sampler_view *sampler_views[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_SAMPLER_VIEWS];
unsigned num_sampler_views[PIPE_SHADER_TYPES];
const struct pipe_sampler_state *samplers[PIPE_SHADER_TYPES][PIPE_MAX_SAMPLERS];
unsigned num_samplers[PIPE_SHADER_TYPES];
 
struct pipe_query_data_pipeline_statistics statistics;
boolean collect_statistics;
 
void *driver_private;
};
 
 
struct draw_fetch_info {
boolean linear;
unsigned start;
const unsigned *elts;
unsigned count;
};
 
struct draw_vertex_info {
struct vertex_header *verts;
unsigned vertex_size;
unsigned stride;
unsigned count;
};
 
/* these flags are set if the primitive is a segment of a larger one */
#define DRAW_SPLIT_BEFORE 0x1
#define DRAW_SPLIT_AFTER 0x2
 
struct draw_prim_info {
boolean linear;
unsigned start;
 
const ushort *elts;
unsigned count;
 
unsigned prim;
unsigned flags;
unsigned *primitive_lengths;
unsigned primitive_count;
};
 
 
/*******************************************************************************
* Draw common initialization code
*/
boolean draw_init(struct draw_context *draw);
void draw_new_instance(struct draw_context *draw);
 
/*******************************************************************************
* Vertex shader code:
*/
boolean draw_vs_init( struct draw_context *draw );
void draw_vs_destroy( struct draw_context *draw );
 
 
/*******************************************************************************
* Geometry shading code:
*/
boolean draw_gs_init( struct draw_context *draw );
 
 
void draw_gs_destroy( struct draw_context *draw );
 
/*******************************************************************************
* Common shading code:
*/
uint draw_current_shader_outputs(const struct draw_context *draw);
uint draw_current_shader_position_output(const struct draw_context *draw);
uint draw_current_shader_viewport_index_output(const struct draw_context *draw);
uint draw_current_shader_clipvertex_output(const struct draw_context *draw);
uint draw_current_shader_clipdistance_output(const struct draw_context *draw, int index);
uint draw_current_shader_num_written_clipdistances(const struct draw_context *draw);
uint draw_current_shader_culldistance_output(const struct draw_context *draw, int index);
uint draw_current_shader_num_written_culldistances(const struct draw_context *draw);
int draw_alloc_extra_vertex_attrib(struct draw_context *draw,
uint semantic_name, uint semantic_index);
void draw_remove_extra_vertex_attribs(struct draw_context *draw);
boolean draw_current_shader_uses_viewport_index(
const struct draw_context *draw);
 
 
/*******************************************************************************
* Vertex processing (was passthrough) code:
*/
boolean draw_pt_init( struct draw_context *draw );
void draw_pt_destroy( struct draw_context *draw );
void draw_pt_reset_vertex_ids( struct draw_context *draw );
void draw_pt_flush( struct draw_context *draw, unsigned flags );
 
 
/*******************************************************************************
* Primitive processing (pipeline) code:
*/
 
boolean draw_pipeline_init( struct draw_context *draw );
void draw_pipeline_destroy( struct draw_context *draw );
 
 
 
 
 
/*
* These flags are used by the pipeline when unfilled and/or line stipple modes
* are operational.
*/
#define DRAW_PIPE_EDGE_FLAG_0 0x1
#define DRAW_PIPE_EDGE_FLAG_1 0x2
#define DRAW_PIPE_EDGE_FLAG_2 0x4
#define DRAW_PIPE_EDGE_FLAG_ALL 0x7
#define DRAW_PIPE_RESET_STIPPLE 0x8
 
void draw_pipeline_run( struct draw_context *draw,
const struct draw_vertex_info *vert,
const struct draw_prim_info *prim);
 
void draw_pipeline_run_linear( struct draw_context *draw,
const struct draw_vertex_info *vert,
const struct draw_prim_info *prim);
 
 
 
 
void draw_pipeline_flush( struct draw_context *draw,
unsigned flags );
 
 
 
/*******************************************************************************
* Flushing
*/
 
#define DRAW_FLUSH_PARAMETER_CHANGE 0x1 /**< Constants, viewport, etc */
#define DRAW_FLUSH_STATE_CHANGE 0x2 /**< Other/heavy state changes */
#define DRAW_FLUSH_BACKEND 0x4 /**< Flush the output buffer */
 
 
void draw_do_flush( struct draw_context *draw, unsigned flags );
 
 
 
void *
draw_get_rasterizer_no_cull( struct draw_context *draw,
boolean scissor,
boolean flatshade );
 
void
draw_stats_clipper_primitives(struct draw_context *draw,
const struct draw_prim_info *prim_info);
 
/**
* Return index i from the index buffer.
* If the index buffer would overflow we return the
* maximum possible index.
*/
#define DRAW_GET_IDX(_elts, _i) \
(((_i) >= draw->pt.user.eltMax) ? DRAW_MAX_FETCH_IDX : (_elts)[_i])
 
/**
* Return index of the given viewport clamping it
* to be between 0 <= and < PIPE_MAX_VIEWPORTS
*/
static INLINE unsigned
draw_clamp_viewport_idx(int idx)
{
return ((PIPE_MAX_VIEWPORTS > idx || idx < 0) ? idx : 0);
}
 
/**
* Adds two unsigned integers and if the addition
* overflows then it returns the value from
* from the overflow_value variable.
*/
static INLINE unsigned
draw_overflow_uadd(unsigned a, unsigned b,
unsigned overflow_value)
{
unsigned res = a + b;
if (res < a || res < b) {
res = overflow_value;
}
return res;
}
 
#endif /* DRAW_PRIVATE_H */
/drivers/video/Gallium/auxiliary/draw/draw_pt.c
0,0 → 1,561
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
#include "draw/draw_context.h"
#include "draw/draw_gs.h"
#include "draw/draw_private.h"
#include "draw/draw_pt.h"
#include "draw/draw_vbuf.h"
#include "draw/draw_vs.h"
#include "tgsi/tgsi_dump.h"
#include "util/u_math.h"
#include "util/u_prim.h"
#include "util/u_format.h"
#include "util/u_draw.h"
 
 
DEBUG_GET_ONCE_BOOL_OPTION(draw_fse, "DRAW_FSE", FALSE)
DEBUG_GET_ONCE_BOOL_OPTION(draw_no_fse, "DRAW_NO_FSE", FALSE)
 
/* Overall we split things into:
* - frontend -- prepare fetch_elts, draw_elts - eg vsplit
* - middle -- fetch, shade, cliptest, viewport
* - pipeline -- the prim pipeline: clipping, wide lines, etc
* - backend -- the vbuf_render provided by the driver.
*/
static boolean
draw_pt_arrays(struct draw_context *draw,
unsigned prim,
unsigned start,
unsigned count)
{
struct draw_pt_front_end *frontend = NULL;
struct draw_pt_middle_end *middle = NULL;
unsigned opt = 0;
 
/* Sanitize primitive length:
*/
{
unsigned first, incr;
draw_pt_split_prim(prim, &first, &incr);
count = draw_pt_trim_count(count, first, incr);
if (count < first)
return TRUE;
}
 
if (!draw->force_passthrough) {
unsigned gs_out_prim = (draw->gs.geometry_shader ?
draw->gs.geometry_shader->output_primitive :
prim);
 
if (!draw->render) {
opt |= PT_PIPELINE;
}
 
if (draw_need_pipeline(draw,
draw->rasterizer,
gs_out_prim)) {
opt |= PT_PIPELINE;
}
 
if ((draw->clip_xy ||
draw->clip_z ||
draw->clip_user) && !draw->pt.test_fse) {
opt |= PT_CLIPTEST;
}
 
opt |= PT_SHADE;
}
 
if (draw->pt.middle.llvm) {
middle = draw->pt.middle.llvm;
} else {
if (opt == 0)
middle = draw->pt.middle.fetch_emit;
else if (opt == PT_SHADE && !draw->pt.no_fse)
middle = draw->pt.middle.fetch_shade_emit;
else
middle = draw->pt.middle.general;
}
 
frontend = draw->pt.frontend;
 
if (frontend ) {
if (draw->pt.prim != prim || draw->pt.opt != opt) {
/* In certain conditions switching primitives requires us to flush
* and validate the different stages. One example is when smooth
* lines are active but first drawn with triangles and then with
* lines.
*/
draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
frontend = NULL;
} else if (draw->pt.eltSize != draw->pt.user.eltSize) {
/* Flush draw state if eltSize changed.
* This could be improved so only the frontend is flushed since it
* converts all indices to ushorts and the fetch part of the middle
* always prepares both linear and indexed.
*/
frontend->flush( frontend, DRAW_FLUSH_STATE_CHANGE );
frontend = NULL;
}
}
 
if (!frontend) {
frontend = draw->pt.front.vsplit;
 
frontend->prepare( frontend, prim, middle, opt );
 
draw->pt.frontend = frontend;
draw->pt.eltSize = draw->pt.user.eltSize;
draw->pt.prim = prim;
draw->pt.opt = opt;
}
 
if (draw->pt.rebind_parameters) {
/* update constants, viewport dims, clip planes, etc */
middle->bind_parameters(middle);
draw->pt.rebind_parameters = FALSE;
}
 
frontend->run( frontend, start, count );
 
return TRUE;
}
 
void draw_pt_flush( struct draw_context *draw, unsigned flags )
{
assert(flags);
 
if (draw->pt.frontend) {
draw->pt.frontend->flush( draw->pt.frontend, flags );
 
/* don't prepare if we only are flushing the backend */
if (flags & DRAW_FLUSH_STATE_CHANGE)
draw->pt.frontend = NULL;
}
 
if (flags & DRAW_FLUSH_PARAMETER_CHANGE) {
draw->pt.rebind_parameters = TRUE;
}
}
 
 
 
boolean draw_pt_init( struct draw_context *draw )
{
draw->pt.test_fse = debug_get_option_draw_fse();
draw->pt.no_fse = debug_get_option_draw_no_fse();
 
draw->pt.front.vsplit = draw_pt_vsplit(draw);
if (!draw->pt.front.vsplit)
return FALSE;
 
draw->pt.middle.fetch_emit = draw_pt_fetch_emit( draw );
if (!draw->pt.middle.fetch_emit)
return FALSE;
 
draw->pt.middle.fetch_shade_emit = draw_pt_middle_fse( draw );
if (!draw->pt.middle.fetch_shade_emit)
return FALSE;
 
draw->pt.middle.general = draw_pt_fetch_pipeline_or_emit( draw );
if (!draw->pt.middle.general)
return FALSE;
 
#if HAVE_LLVM
if (draw->llvm)
draw->pt.middle.llvm = draw_pt_fetch_pipeline_or_emit_llvm( draw );
#endif
 
return TRUE;
}
 
 
void draw_pt_destroy( struct draw_context *draw )
{
if (draw->pt.middle.llvm) {
draw->pt.middle.llvm->destroy( draw->pt.middle.llvm );
draw->pt.middle.llvm = NULL;
}
 
if (draw->pt.middle.general) {
draw->pt.middle.general->destroy( draw->pt.middle.general );
draw->pt.middle.general = NULL;
}
 
if (draw->pt.middle.fetch_emit) {
draw->pt.middle.fetch_emit->destroy( draw->pt.middle.fetch_emit );
draw->pt.middle.fetch_emit = NULL;
}
 
if (draw->pt.middle.fetch_shade_emit) {
draw->pt.middle.fetch_shade_emit->destroy( draw->pt.middle.fetch_shade_emit );
draw->pt.middle.fetch_shade_emit = NULL;
}
 
if (draw->pt.front.vsplit) {
draw->pt.front.vsplit->destroy( draw->pt.front.vsplit );
draw->pt.front.vsplit = NULL;
}
}
 
 
/**
* Debug- print the first 'count' vertices.
*/
static void
draw_print_arrays(struct draw_context *draw, uint prim, int start, uint count)
{
uint i;
 
debug_printf("Draw arrays(prim = %u, start = %u, count = %u)\n",
prim, start, count);
 
for (i = 0; i < count; i++) {
uint ii = 0;
uint j;
 
if (draw->pt.user.eltSize) {
/* indexed arrays */
 
switch (draw->pt.user.eltSize) {
case 1:
{
const ubyte *elem = (const ubyte *) draw->pt.user.elts;
ii = elem[start + i];
}
break;
case 2:
{
const ushort *elem = (const ushort *) draw->pt.user.elts;
ii = elem[start + i];
}
break;
case 4:
{
const uint *elem = (const uint *) draw->pt.user.elts;
ii = elem[start + i];
}
break;
default:
assert(0);
return;
}
ii += draw->pt.user.eltBias;
debug_printf("Element[%u + %u] + %i -> Vertex %u:\n", start, i,
draw->pt.user.eltBias, ii);
}
else {
/* non-indexed arrays */
ii = start + i;
debug_printf("Vertex %u:\n", ii);
}
 
for (j = 0; j < draw->pt.nr_vertex_elements; j++) {
uint buf = draw->pt.vertex_element[j].vertex_buffer_index;
ubyte *ptr = (ubyte *) draw->pt.user.vbuffer[buf].map;
 
if (draw->pt.vertex_element[j].instance_divisor) {
ii = draw->instance_id / draw->pt.vertex_element[j].instance_divisor;
}
 
ptr += draw->pt.vertex_buffer[buf].buffer_offset;
ptr += draw->pt.vertex_buffer[buf].stride * ii;
ptr += draw->pt.vertex_element[j].src_offset;
 
debug_printf(" Attr %u: ", j);
switch (draw->pt.vertex_element[j].src_format) {
case PIPE_FORMAT_R32_FLOAT:
{
float *v = (float *) ptr;
debug_printf("R %f @ %p\n", v[0], (void *) v);
}
break;
case PIPE_FORMAT_R32G32_FLOAT:
{
float *v = (float *) ptr;
debug_printf("RG %f %f @ %p\n", v[0], v[1], (void *) v);
}
break;
case PIPE_FORMAT_R32G32B32_FLOAT:
{
float *v = (float *) ptr;
debug_printf("RGB %f %f %f @ %p\n", v[0], v[1], v[2], (void *) v);
}
break;
case PIPE_FORMAT_R32G32B32A32_FLOAT:
{
float *v = (float *) ptr;
debug_printf("RGBA %f %f %f %f @ %p\n", v[0], v[1], v[2], v[3],
(void *) v);
}
break;
case PIPE_FORMAT_B8G8R8A8_UNORM:
{
ubyte *u = (ubyte *) ptr;
debug_printf("BGRA %d %d %d %d @ %p\n", u[0], u[1], u[2], u[3],
(void *) u);
}
break;
case PIPE_FORMAT_A8R8G8B8_UNORM:
{
ubyte *u = (ubyte *) ptr;
debug_printf("ARGB %d %d %d %d @ %p\n", u[0], u[1], u[2], u[3],
(void *) u);
}
break;
default:
debug_printf("other format %s (fix me)\n",
util_format_name(draw->pt.vertex_element[j].src_format));
}
}
}
}
 
 
/** Helper code for below */
#define PRIM_RESTART_LOOP(elements) \
do { \
for (j = 0; j < count; j++) { \
i = draw_overflow_uadd(start, j, MAX_LOOP_IDX); \
if (i < elt_max && elements[i] == info->restart_index) { \
if (cur_count > 0) { \
/* draw elts up to prev pos */ \
draw_pt_arrays(draw, prim, cur_start, cur_count); \
} \
/* begin new prim at next elt */ \
cur_start = i + 1; \
cur_count = 0; \
} \
else { \
cur_count++; \
} \
} \
if (cur_count > 0) { \
draw_pt_arrays(draw, prim, cur_start, cur_count); \
} \
} while (0)
 
 
/**
* For drawing prims with primitive restart enabled.
* Scan for restart indexes and draw the runs of elements/vertices between
* the restarts.
*/
static void
draw_pt_arrays_restart(struct draw_context *draw,
const struct pipe_draw_info *info)
{
const unsigned prim = info->mode;
const unsigned start = info->start;
const unsigned count = info->count;
const unsigned elt_max = draw->pt.user.eltMax;
unsigned i, j, cur_start, cur_count;
/* The largest index within a loop using the i variable as the index.
* Used for overflow detection */
const unsigned MAX_LOOP_IDX = 0xffffffff;
 
assert(info->primitive_restart);
 
if (draw->pt.user.eltSize) {
/* indexed prims (draw_elements) */
cur_start = start;
cur_count = 0;
 
switch (draw->pt.user.eltSize) {
case 1:
{
const ubyte *elt_ub = (const ubyte *) draw->pt.user.elts;
PRIM_RESTART_LOOP(elt_ub);
}
break;
case 2:
{
const ushort *elt_us = (const ushort *) draw->pt.user.elts;
PRIM_RESTART_LOOP(elt_us);
}
break;
case 4:
{
const uint *elt_ui = (const uint *) draw->pt.user.elts;
PRIM_RESTART_LOOP(elt_ui);
}
break;
default:
assert(0 && "bad eltSize in draw_arrays()");
}
}
else {
/* Non-indexed prims (draw_arrays).
* Primitive restart should have been handled in the state tracker.
*/
draw_pt_arrays(draw, prim, start, count);
}
}
 
 
/**
* Resolve true values within pipe_draw_info.
* If we're rendering from transform feedback/stream output
* buffers both the count and max_index need to be computed
* from the attached stream output target.
*/
static void
resolve_draw_info(const struct pipe_draw_info *raw_info,
struct pipe_draw_info *info)
{
memcpy(info, raw_info, sizeof(struct pipe_draw_info));
 
if (raw_info->count_from_stream_output) {
struct draw_so_target *target =
(struct draw_so_target *)info->count_from_stream_output;
info->count = target->emitted_vertices;
 
/* Stream output draw can not be indexed */
debug_assert(!info->indexed);
info->max_index = info->count - 1;
}
}
 
/**
* Draw vertex arrays.
* This is the main entrypoint into the drawing module. If drawing an indexed
* primitive, the draw_set_indexes() function should have already been called
* to specify the element/index buffer information.
*/
void
draw_vbo(struct draw_context *draw,
const struct pipe_draw_info *info)
{
unsigned instance;
unsigned index_limit;
unsigned count;
struct pipe_draw_info resolved_info;
 
resolve_draw_info(info, &resolved_info);
info = &resolved_info;
 
assert(info->instance_count > 0);
if (info->indexed)
assert(draw->pt.user.elts);
 
count = info->count;
 
draw->pt.user.eltBias = info->index_bias;
draw->pt.user.min_index = info->min_index;
draw->pt.user.max_index = info->max_index;
draw->pt.user.eltSize = info->indexed ? draw->pt.user.eltSizeIB : 0;
 
if (0)
debug_printf("draw_vbo(mode=%u start=%u count=%u):\n",
info->mode, info->start, count);
 
if (0)
tgsi_dump(draw->vs.vertex_shader->state.tokens, 0);
 
if (0) {
unsigned int i;
debug_printf("Elements:\n");
for (i = 0; i < draw->pt.nr_vertex_elements; i++) {
debug_printf(" %u: src_offset=%u inst_div=%u vbuf=%u format=%s\n",
i,
draw->pt.vertex_element[i].src_offset,
draw->pt.vertex_element[i].instance_divisor,
draw->pt.vertex_element[i].vertex_buffer_index,
util_format_name(draw->pt.vertex_element[i].src_format));
}
debug_printf("Buffers:\n");
for (i = 0; i < draw->pt.nr_vertex_buffers; i++) {
debug_printf(" %u: stride=%u offset=%u size=%d ptr=%p\n",
i,
draw->pt.vertex_buffer[i].stride,
draw->pt.vertex_buffer[i].buffer_offset,
(int) draw->pt.user.vbuffer[i].size,
draw->pt.user.vbuffer[i].map);
}
}
 
if (0)
draw_print_arrays(draw, info->mode, info->start, MIN2(count, 20));
 
index_limit = util_draw_max_index(draw->pt.vertex_buffer,
draw->pt.vertex_element,
draw->pt.nr_vertex_elements,
info);
#if HAVE_LLVM
if (!draw->llvm)
#endif
{
if (index_limit == 0) {
/* one of the buffers is too small to do any valid drawing */
debug_warning("draw: VBO too small to draw anything\n");
return;
}
}
 
/* If we're collecting stats then make sure we start from scratch */
if (draw->collect_statistics) {
memset(&draw->statistics, 0, sizeof(draw->statistics));
}
 
draw->pt.max_index = index_limit - 1;
 
/*
* TODO: We could use draw->pt.max_index to further narrow
* the min_index/max_index hints given by the state tracker.
*/
 
for (instance = 0; instance < info->instance_count; instance++) {
draw->instance_id = instance + info->start_instance;
draw->start_instance = info->start_instance;
/* check for overflow */
if (draw->instance_id < instance ||
draw->instance_id < info->start_instance) {
/* if we overflown just set the instance id to the max */
draw->instance_id = 0xffffffff;
}
 
draw_new_instance(draw);
 
if (info->primitive_restart) {
draw_pt_arrays_restart(draw, info);
}
else {
draw_pt_arrays(draw, info->mode, info->start, count);
}
}
 
/* If requested emit the pipeline statistics for this run */
if (draw->collect_statistics) {
draw->render->pipeline_statistics(draw->render, &draw->statistics);
}
}
/drivers/video/Gallium/auxiliary/draw/draw_pt.h
0,0 → 1,252
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
#ifndef DRAW_PT_H
#define DRAW_PT_H
 
#include "pipe/p_compiler.h"
 
struct draw_pt_middle_end;
struct draw_context;
struct draw_prim_info;
struct draw_vertex_info;
 
 
#define PT_SHADE 0x1
#define PT_CLIPTEST 0x2
#define PT_PIPELINE 0x4
#define PT_MAX_MIDDLE 0x8
 
 
/* The "front end" - prepare sets of fetch, draw elements for the
* middle end.
*
* The fetch elements are indices to the vertices. The draw elements are
* indices to the fetched vertices. When both arrays of elements are both
* linear, middle->run_linear is called; When only the fetch elements are
* linear, middle->run_linear_elts is called; Otherwise, middle->run is
* called.
*
* When the number of the draw elements exceeds max_vertex of the middle end,
* the draw elements (as well as the fetch elements) are splitted and the
* middle end is called multiple times.
*
* Currenly there is:
* - vsplit - catchall implementation, splits big prims
*/
struct draw_pt_front_end {
void (*prepare)( struct draw_pt_front_end *,
unsigned prim,
struct draw_pt_middle_end *,
unsigned opt );
 
void (*run)( struct draw_pt_front_end *,
unsigned start,
unsigned count );
 
void (*flush)( struct draw_pt_front_end *, unsigned flags );
void (*destroy)( struct draw_pt_front_end * );
};
 
 
/* The "middle end" - prepares actual hardware vertices for the
* hardware backend.
*
* prim_flags is as defined by pipe_draw_info::flags.
*
* Currently two versions of this:
* - fetch, vertex shade, cliptest, prim-pipeline
* - fetch, emit (ie passthrough)
*/
struct draw_pt_middle_end {
void (*prepare)( struct draw_pt_middle_end *,
unsigned prim,
unsigned opt,
unsigned *max_vertices );
 
/**
* Bind/update parameter state such as constants, viewport dims
* and clip planes. Basically, stuff which isn't "baked" into the
* shader or pipeline state.
*/
void (*bind_parameters)(struct draw_pt_middle_end *);
 
void (*run)( struct draw_pt_middle_end *,
const unsigned *fetch_elts,
unsigned fetch_count,
const ushort *draw_elts,
unsigned draw_count,
unsigned prim_flags );
 
void (*run_linear)(struct draw_pt_middle_end *,
unsigned start,
unsigned count,
unsigned prim_flags );
 
/* Transform all vertices in a linear range and then draw them with
* the supplied element list. May fail and return FALSE.
*/
boolean (*run_linear_elts)( struct draw_pt_middle_end *,
unsigned fetch_start,
unsigned fetch_count,
const ushort *draw_elts,
unsigned draw_count,
unsigned prim_flags );
 
int (*get_max_vertex_count)( struct draw_pt_middle_end * );
 
void (*finish)( struct draw_pt_middle_end * );
void (*destroy)( struct draw_pt_middle_end * );
};
 
 
/* The "back end" - supplied by the driver, defined in draw_vbuf.h.
*/
struct vbuf_render;
struct vertex_header;
 
 
/* Frontends:
*
* Currently only the general-purpose vsplit implementation.
*/
struct draw_pt_front_end *draw_pt_vsplit(struct draw_context *draw);
 
 
/* Middle-ends:
*
* Currently one general-purpose case which can do all possibilities,
* at the slight expense of creating a vertex_header in some cases
* unecessarily.
*
* The special case fetch_emit code avoids pipeline vertices
* altogether and builds hardware vertices directly from API
* vertex_elements.
*/
struct draw_pt_middle_end *draw_pt_fetch_emit( struct draw_context *draw );
struct draw_pt_middle_end *draw_pt_middle_fse( struct draw_context *draw );
struct draw_pt_middle_end *draw_pt_fetch_pipeline_or_emit(struct draw_context *draw);
struct draw_pt_middle_end *draw_pt_fetch_pipeline_or_emit_llvm(struct draw_context *draw);
 
 
 
/*******************************************************************************
* HW vertex emit:
*/
struct pt_emit;
 
void draw_pt_emit_prepare( struct pt_emit *emit,
unsigned prim,
unsigned *max_vertices );
 
void draw_pt_emit( struct pt_emit *emit,
const struct draw_vertex_info *vert_info,
const struct draw_prim_info *prim_info);
 
void draw_pt_emit_linear( struct pt_emit *emit,
const struct draw_vertex_info *vert_info,
const struct draw_prim_info *prim_info);
 
void draw_pt_emit_destroy( struct pt_emit *emit );
 
struct pt_emit *draw_pt_emit_create( struct draw_context *draw );
 
/*******************************************************************************
* HW stream output emit:
*/
struct pt_so_emit;
 
void draw_pt_so_emit_prepare(struct pt_so_emit *emit, boolean use_pre_clip_pos);
 
void draw_pt_so_emit( struct pt_so_emit *emit,
const struct draw_vertex_info *vert_info,
const struct draw_prim_info *prim_info );
 
void draw_pt_so_emit_destroy( struct pt_so_emit *emit );
 
struct pt_so_emit *draw_pt_so_emit_create( struct draw_context *draw );
 
/*******************************************************************************
* API vertex fetch:
*/
 
struct pt_fetch;
void draw_pt_fetch_prepare( struct pt_fetch *fetch,
unsigned vertex_input_count,
unsigned vertex_size,
unsigned instance_id_index );
 
void draw_pt_fetch_run( struct pt_fetch *fetch,
const unsigned *elts,
unsigned count,
char *verts );
 
void draw_pt_fetch_run_linear( struct pt_fetch *fetch,
unsigned start,
unsigned count,
char *verts );
 
void draw_pt_fetch_destroy( struct pt_fetch *fetch );
 
struct pt_fetch *draw_pt_fetch_create( struct draw_context *draw );
 
/*******************************************************************************
* Post-VS: cliptest, rhw, viewport
*/
struct pt_post_vs;
 
boolean draw_pt_post_vs_run( struct pt_post_vs *pvs,
struct draw_vertex_info *info,
const struct draw_prim_info *prim_info );
 
void draw_pt_post_vs_prepare( struct pt_post_vs *pvs,
boolean clip_xy,
boolean clip_z,
boolean clip_user,
boolean guard_band,
boolean bypass_viewport,
boolean clip_halfz,
boolean need_edgeflags );
 
struct pt_post_vs *draw_pt_post_vs_create( struct draw_context *draw );
 
void draw_pt_post_vs_destroy( struct pt_post_vs *pvs );
 
 
/*******************************************************************************
* Utils:
*/
void draw_pt_split_prim(unsigned prim, unsigned *first, unsigned *incr);
unsigned draw_pt_trim_count(unsigned count, unsigned first, unsigned incr);
 
 
#endif
/drivers/video/Gallium/auxiliary/draw/draw_pt_decompose.h
0,0 → 1,9
#define LOCAL_VARS \
char *verts = (char *) vertices; \
const boolean quads_flatshade_last = \
draw->quads_always_flatshade_last; \
const boolean last_vertex_last = \
!(draw->rasterizer->flatshade && \
draw->rasterizer->flatshade_first);
 
#include "draw_decompose_tmp.h"
/drivers/video/Gallium/auxiliary/draw/draw_pt_emit.c
0,0 → 1,298
/**************************************************************************
*
* 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.
*
**************************************************************************/
 
#include "util/u_memory.h"
#include "draw/draw_context.h"
#include "draw/draw_private.h"
#include "draw/draw_vbuf.h"
#include "draw/draw_vertex.h"
#include "draw/draw_pt.h"
#include "translate/translate.h"
#include "translate/translate_cache.h"
#include "util/u_prim.h"
 
struct pt_emit {
struct draw_context *draw;
 
struct translate *translate;
 
struct translate_cache *cache;
unsigned prim;
 
const struct vertex_info *vinfo;
};
 
 
void
draw_pt_emit_prepare(struct pt_emit *emit,
unsigned prim,
unsigned *max_vertices)
{
struct draw_context *draw = emit->draw;
const struct vertex_info *vinfo;
unsigned dst_offset;
struct translate_key hw_key;
unsigned i;
 
/* XXX: need to flush to get prim_vbuf.c to release its allocation??
*/
draw_do_flush( draw, DRAW_FLUSH_BACKEND );
 
/* XXX: may need to defensively reset this later on as clipping can
* clobber this state in the render backend.
*/
emit->prim = prim;
 
draw->render->set_primitive(draw->render, emit->prim);
 
/* Must do this after set_primitive() above:
*/
emit->vinfo = vinfo = draw->render->get_vertex_info(draw->render);
 
/* Translate from pipeline vertices to hw vertices.
*/
dst_offset = 0;
for (i = 0; i < vinfo->num_attribs; i++) {
unsigned emit_sz = 0;
unsigned src_buffer = 0;
unsigned output_format;
unsigned src_offset = (vinfo->attrib[i].src_index * 4 * sizeof(float) );
 
output_format = draw_translate_vinfo_format(vinfo->attrib[i].emit);
emit_sz = draw_translate_vinfo_size(vinfo->attrib[i].emit);
 
/* doesn't handle EMIT_OMIT */
assert(emit_sz != 0);
 
if (vinfo->attrib[i].emit == EMIT_1F_PSIZE) {
src_buffer = 1;
src_offset = 0;
}
 
hw_key.element[i].type = TRANSLATE_ELEMENT_NORMAL;
hw_key.element[i].input_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
hw_key.element[i].input_buffer = src_buffer;
hw_key.element[i].input_offset = src_offset;
hw_key.element[i].instance_divisor = 0;
hw_key.element[i].output_format = output_format;
hw_key.element[i].output_offset = dst_offset;
 
dst_offset += emit_sz;
}
 
hw_key.nr_elements = vinfo->num_attribs;
hw_key.output_stride = vinfo->size * 4;
 
if (!emit->translate ||
translate_key_compare(&emit->translate->key, &hw_key) != 0) {
translate_key_sanitize(&hw_key);
emit->translate = translate_cache_find(emit->cache, &hw_key);
}
 
*max_vertices = (draw->render->max_vertex_buffer_bytes /
(vinfo->size * 4));
}
 
 
void
draw_pt_emit(struct pt_emit *emit,
const struct draw_vertex_info *vert_info,
const struct draw_prim_info *prim_info)
{
const float (*vertex_data)[4] = (const float (*)[4])vert_info->verts->data;
unsigned vertex_count = vert_info->count;
unsigned stride = vert_info->stride;
const ushort *elts = prim_info->elts;
struct draw_context *draw = emit->draw;
struct translate *translate = emit->translate;
struct vbuf_render *render = draw->render;
unsigned start, i;
void *hw_verts;
 
/* XXX: need to flush to get prim_vbuf.c to release its allocation??
*/
draw_do_flush( draw, DRAW_FLUSH_BACKEND );
 
if (vertex_count == 0)
return;
 
/* XXX: and work out some way to coordinate the render primitive
* between vbuf.c and here...
*/
draw->render->set_primitive(draw->render, emit->prim);
 
render->allocate_vertices(render,
(ushort)translate->key.output_stride,
(ushort)vertex_count);
 
hw_verts = render->map_vertices( render );
if (!hw_verts) {
debug_warn_once("map of vertex buffer failed (out of memory?)");
return;
}
 
translate->set_buffer(translate,
0,
vertex_data,
stride,
~0);
 
translate->set_buffer(translate,
1,
&draw->rasterizer->point_size,
0,
~0);
 
/* fetch/translate vertex attribs to fill hw_verts[] */
translate->run(translate,
0,
vertex_count,
draw->start_instance,
draw->instance_id,
hw_verts );
 
render->unmap_vertices(render, 0, vertex_count - 1);
 
for (start = i = 0;
i < prim_info->primitive_count;
start += prim_info->primitive_lengths[i], i++)
{
render->draw_elements(render,
elts + start,
prim_info->primitive_lengths[i]);
}
 
render->release_vertices(render);
}
 
 
void
draw_pt_emit_linear(struct pt_emit *emit,
const struct draw_vertex_info *vert_info,
const struct draw_prim_info *prim_info)
{
const float (*vertex_data)[4] = (const float (*)[4])vert_info->verts->data;
unsigned stride = vert_info->stride;
unsigned count = vert_info->count;
struct draw_context *draw = emit->draw;
struct translate *translate = emit->translate;
struct vbuf_render *render = draw->render;
void *hw_verts;
unsigned start, i;
 
#if 0
debug_printf("Linear emit\n");
#endif
/* XXX: need to flush to get prim_vbuf.c to release its allocation??
*/
draw_do_flush( draw, DRAW_FLUSH_BACKEND );
 
/* XXX: and work out some way to coordinate the render primitive
* between vbuf.c and here...
*/
draw->render->set_primitive(draw->render, emit->prim);
 
if (!render->allocate_vertices(render,
(ushort)translate->key.output_stride,
(ushort)count))
goto fail;
 
hw_verts = render->map_vertices( render );
if (!hw_verts)
goto fail;
 
translate->set_buffer(translate, 0,
vertex_data, stride, count - 1);
 
translate->set_buffer(translate, 1,
&draw->rasterizer->point_size,
0, ~0);
 
translate->run(translate,
0,
count,
draw->start_instance,
draw->instance_id,
hw_verts);
 
if (0) {
unsigned i;
for (i = 0; i < count; i++) {
debug_printf("\n\n%s vertex %d:\n", __FUNCTION__, i);
draw_dump_emitted_vertex( emit->vinfo,
(const uint8_t *)hw_verts +
translate->key.output_stride * i );
}
}
 
render->unmap_vertices( render, 0, count - 1 );
 
for (start = i = 0;
i < prim_info->primitive_count;
start += prim_info->primitive_lengths[i], i++)
{
render->draw_arrays(render,
start,
prim_info->primitive_lengths[i]);
}
render->release_vertices(render);
 
return;
 
fail:
debug_warn_once("allocate or map of vertex buffer failed (out of memory?)");
return;
}
 
 
struct pt_emit *
draw_pt_emit_create(struct draw_context *draw)
{
struct pt_emit *emit = CALLOC_STRUCT(pt_emit);
if (!emit)
return NULL;
 
emit->draw = draw;
emit->cache = translate_cache_create();
if (!emit->cache) {
FREE(emit);
return NULL;
}
 
return emit;
}
 
 
void
draw_pt_emit_destroy(struct pt_emit *emit)
{
if (emit->cache)
translate_cache_destroy(emit->cache);
 
FREE(emit);
}
/drivers/video/Gallium/auxiliary/draw/draw_pt_fetch.c
0,0 → 1,230
/**************************************************************************
*
* 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.
*
**************************************************************************/
 
#include "util/u_memory.h"
#include "util/u_math.h"
#include "util/u_format.h"
#include "draw/draw_context.h"
#include "draw/draw_private.h"
#include "draw/draw_pt.h"
#include "translate/translate.h"
#include "translate/translate_cache.h"
 
 
struct pt_fetch {
struct draw_context *draw;
 
struct translate *translate;
 
unsigned vertex_size;
 
struct translate_cache *cache;
};
 
 
/**
* Perform the fetch from API vertex elements & vertex buffers, to a
* contiguous set of float[4] attributes as required for the
* vertex_shader->run_linear() method.
*
* This is used in all cases except pure passthrough
* (draw_pt_fetch_emit.c) which has its own version to translate
* directly to hw vertices.
*
*/
void
draw_pt_fetch_prepare(struct pt_fetch *fetch,
unsigned vs_input_count,
unsigned vertex_size,
unsigned instance_id_index)
{
struct draw_context *draw = fetch->draw;
unsigned nr_inputs;
unsigned i, nr = 0, ei = 0;
unsigned dst_offset = 0;
unsigned num_extra_inputs = 0;
struct translate_key key;
 
fetch->vertex_size = vertex_size;
 
/* Leave the clipmask/edgeflags/pad/vertex_id untouched
*/
dst_offset += 1 * sizeof(float);
/* Just leave the clip[] and pre_clip_pos[] array untouched.
*/
dst_offset += 8 * sizeof(float);
 
if (instance_id_index != ~0) {
num_extra_inputs++;
}
 
assert(draw->pt.nr_vertex_elements + num_extra_inputs >= vs_input_count);
 
nr_inputs = MIN2(vs_input_count, draw->pt.nr_vertex_elements + num_extra_inputs);
 
for (i = 0; i < nr_inputs; i++) {
if (i == instance_id_index) {
key.element[nr].type = TRANSLATE_ELEMENT_INSTANCE_ID;
key.element[nr].input_format = PIPE_FORMAT_R32_USCALED;
key.element[nr].output_format = PIPE_FORMAT_R32_USCALED;
key.element[nr].output_offset = dst_offset;
 
dst_offset += sizeof(uint);
} else if (util_format_is_pure_sint(draw->pt.vertex_element[i].src_format)) {
key.element[nr].type = TRANSLATE_ELEMENT_NORMAL;
key.element[nr].input_format = draw->pt.vertex_element[ei].src_format;
key.element[nr].input_buffer = draw->pt.vertex_element[ei].vertex_buffer_index;
key.element[nr].input_offset = draw->pt.vertex_element[ei].src_offset;
key.element[nr].instance_divisor = draw->pt.vertex_element[ei].instance_divisor;
key.element[nr].output_format = PIPE_FORMAT_R32G32B32A32_SINT;
key.element[nr].output_offset = dst_offset;
 
ei++;
dst_offset += 4 * sizeof(int);
} else if (util_format_is_pure_uint(draw->pt.vertex_element[i].src_format)) {
key.element[nr].type = TRANSLATE_ELEMENT_NORMAL;
key.element[nr].input_format = draw->pt.vertex_element[ei].src_format;
key.element[nr].input_buffer = draw->pt.vertex_element[ei].vertex_buffer_index;
key.element[nr].input_offset = draw->pt.vertex_element[ei].src_offset;
key.element[nr].instance_divisor = draw->pt.vertex_element[ei].instance_divisor;
key.element[nr].output_format = PIPE_FORMAT_R32G32B32A32_UINT;
key.element[nr].output_offset = dst_offset;
 
ei++;
dst_offset += 4 * sizeof(unsigned);
} else {
key.element[nr].type = TRANSLATE_ELEMENT_NORMAL;
key.element[nr].input_format = draw->pt.vertex_element[ei].src_format;
key.element[nr].input_buffer = draw->pt.vertex_element[ei].vertex_buffer_index;
key.element[nr].input_offset = draw->pt.vertex_element[ei].src_offset;
key.element[nr].instance_divisor = draw->pt.vertex_element[ei].instance_divisor;
key.element[nr].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
key.element[nr].output_offset = dst_offset;
 
ei++;
dst_offset += 4 * sizeof(float);
}
 
nr++;
}
 
assert(dst_offset <= vertex_size);
 
key.nr_elements = nr;
key.output_stride = vertex_size;
 
if (!fetch->translate ||
translate_key_compare(&fetch->translate->key, &key) != 0)
{
translate_key_sanitize(&key);
fetch->translate = translate_cache_find(fetch->cache, &key);
}
}
 
 
void
draw_pt_fetch_run(struct pt_fetch *fetch,
const unsigned *elts,
unsigned count,
char *verts)
{
struct draw_context *draw = fetch->draw;
struct translate *translate = fetch->translate;
unsigned i;
 
for (i = 0; i < draw->pt.nr_vertex_buffers; i++) {
translate->set_buffer(translate,
i,
((char *)draw->pt.user.vbuffer[i].map +
draw->pt.vertex_buffer[i].buffer_offset),
draw->pt.vertex_buffer[i].stride,
draw->pt.max_index);
}
 
translate->run_elts( translate,
elts,
count,
draw->start_instance,
draw->instance_id,
verts );
}
 
 
void
draw_pt_fetch_run_linear(struct pt_fetch *fetch,
unsigned start,
unsigned count,
char *verts)
{
struct draw_context *draw = fetch->draw;
struct translate *translate = fetch->translate;
unsigned i;
 
for (i = 0; i < draw->pt.nr_vertex_buffers; i++) {
translate->set_buffer(translate,
i,
((char *)draw->pt.user.vbuffer[i].map +
draw->pt.vertex_buffer[i].buffer_offset),
draw->pt.vertex_buffer[i].stride,
draw->pt.max_index);
}
 
translate->run( translate,
start,
count,
draw->start_instance,
draw->instance_id,
verts );
}
 
 
struct pt_fetch *
draw_pt_fetch_create(struct draw_context *draw)
{
struct pt_fetch *fetch = CALLOC_STRUCT(pt_fetch);
if (!fetch)
return NULL;
 
fetch->draw = draw;
fetch->cache = translate_cache_create();
if (!fetch->cache) {
FREE(fetch);
return NULL;
}
 
return fetch;
}
 
 
void
draw_pt_fetch_destroy(struct pt_fetch *fetch)
{
if (fetch->cache)
translate_cache_destroy(fetch->cache);
 
FREE(fetch);
}
/drivers/video/Gallium/auxiliary/draw/draw_pt_fetch_emit.c
0,0 → 1,392
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
#include "util/u_memory.h"
#include "draw/draw_context.h"
#include "draw/draw_private.h"
#include "draw/draw_vbuf.h"
#include "draw/draw_vertex.h"
#include "draw/draw_pt.h"
#include "draw/draw_gs.h"
#include "translate/translate.h"
#include "translate/translate_cache.h"
 
/* The simplest 'middle end' in the new vertex code.
*
* The responsibilities of a middle end are to:
* - perform vertex fetch using
* - draw vertex element/buffer state
* - a list of fetch indices we received as an input
* - run the vertex shader
* - cliptest,
* - clip coord calculation
* - viewport transformation
* - if necessary, run the primitive pipeline, passing it:
* - a linear array of vertex_header vertices constructed here
* - a set of draw indices we received as an input
* - otherwise, drive the hw backend,
* - allocate space for hardware format vertices
* - translate the vertex-shader output vertices to hw format
* - calling the backend draw functions.
*
* For convenience, we provide a helper function to drive the hardware
* backend given similar inputs to those required to run the pipeline.
*
* In the case of passthrough mode, many of these actions are disabled
* or noops, so we end up doing:
*
* - perform vertex fetch
* - drive the hw backend
*
* IE, basically just vertex fetch to post-vs-format vertices,
* followed by a call to the backend helper function.
*/
 
 
struct fetch_emit_middle_end {
struct draw_pt_middle_end base;
struct draw_context *draw;
 
struct translate *translate;
const struct vertex_info *vinfo;
 
/* Cache point size somewhere it's address won't change:
*/
float point_size;
 
struct translate_cache *cache;
};
 
 
static void fetch_emit_prepare( struct draw_pt_middle_end *middle,
unsigned prim,
unsigned opt,
unsigned *max_vertices )
{
struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle;
struct draw_context *draw = feme->draw;
const struct vertex_info *vinfo;
unsigned i, dst_offset;
struct translate_key key;
unsigned gs_out_prim = (draw->gs.geometry_shader ?
draw->gs.geometry_shader->output_primitive :
prim);
 
draw->render->set_primitive(draw->render, gs_out_prim);
 
/* Must do this after set_primitive() above:
*/
vinfo = feme->vinfo = draw->render->get_vertex_info(draw->render);
 
/* Transform from API vertices to HW vertices, skipping the
* pipeline_vertex intermediate step.
*/
dst_offset = 0;
memset(&key, 0, sizeof(key));
 
for (i = 0; i < vinfo->num_attribs; i++) {
const struct pipe_vertex_element *src = &draw->pt.vertex_element[vinfo->attrib[i].src_index];
 
unsigned emit_sz = 0;
unsigned input_format = src->src_format;
unsigned input_buffer = src->vertex_buffer_index;
unsigned input_offset = src->src_offset;
unsigned output_format;
 
output_format = draw_translate_vinfo_format(vinfo->attrib[i].emit);
emit_sz = draw_translate_vinfo_size(vinfo->attrib[i].emit);
 
if (vinfo->attrib[i].emit == EMIT_OMIT)
continue;
 
if (vinfo->attrib[i].emit == EMIT_1F_PSIZE) {
input_format = PIPE_FORMAT_R32_FLOAT;
input_buffer = draw->pt.nr_vertex_buffers;
input_offset = 0;
}
 
key.element[i].type = TRANSLATE_ELEMENT_NORMAL;
key.element[i].input_format = input_format;
key.element[i].input_buffer = input_buffer;
key.element[i].input_offset = input_offset;
key.element[i].instance_divisor = src->instance_divisor;
key.element[i].output_format = output_format;
key.element[i].output_offset = dst_offset;
 
dst_offset += emit_sz;
}
 
key.nr_elements = vinfo->num_attribs;
key.output_stride = vinfo->size * 4;
 
/* Don't bother with caching at this stage:
*/
if (!feme->translate ||
translate_key_compare(&feme->translate->key, &key) != 0)
{
translate_key_sanitize(&key);
feme->translate = translate_cache_find(feme->cache,
&key);
 
feme->translate->set_buffer(feme->translate,
draw->pt.nr_vertex_buffers,
&feme->point_size,
0,
~0);
}
 
feme->point_size = draw->rasterizer->point_size;
 
for (i = 0; i < draw->pt.nr_vertex_buffers; i++) {
feme->translate->set_buffer(feme->translate,
i,
((char *)draw->pt.user.vbuffer[i].map +
draw->pt.vertex_buffer[i].buffer_offset),
draw->pt.vertex_buffer[i].stride,
draw->pt.max_index);
}
 
*max_vertices = (draw->render->max_vertex_buffer_bytes /
(vinfo->size * 4));
}
 
 
static void fetch_emit_run( struct draw_pt_middle_end *middle,
const unsigned *fetch_elts,
unsigned fetch_count,
const ushort *draw_elts,
unsigned draw_count,
unsigned prim_flags )
{
struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle;
struct draw_context *draw = feme->draw;
void *hw_verts;
 
/* XXX: need to flush to get prim_vbuf.c to release its allocation??
*/
draw_do_flush( draw, DRAW_FLUSH_BACKEND );
 
draw->render->allocate_vertices( draw->render,
(ushort)feme->translate->key.output_stride,
(ushort)fetch_count );
 
hw_verts = draw->render->map_vertices( draw->render );
if (!hw_verts) {
debug_warn_once("vertex buffer allocation failed (out of memory?)");
return;
}
 
/* Single routine to fetch vertices and emit HW verts.
*/
feme->translate->run_elts( feme->translate,
fetch_elts,
fetch_count,
draw->start_instance,
draw->instance_id,
hw_verts );
 
if (0) {
unsigned i;
for (i = 0; i < fetch_count; i++) {
debug_printf("\n\nvertex %d:\n", i);
draw_dump_emitted_vertex( feme->vinfo,
(const uint8_t *)hw_verts + feme->vinfo->size * 4 * i );
}
}
 
draw->render->unmap_vertices( draw->render,
0,
(ushort)(fetch_count - 1) );
 
/* XXX: Draw arrays path to avoid re-emitting index list again and
* again.
*/
draw->render->draw_elements( draw->render,
draw_elts,
draw_count );
 
/* Done -- that was easy, wasn't it:
*/
draw->render->release_vertices( draw->render );
 
}
 
 
static void fetch_emit_run_linear( struct draw_pt_middle_end *middle,
unsigned start,
unsigned count,
unsigned prim_flags )
{
struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle;
struct draw_context *draw = feme->draw;
void *hw_verts;
 
/* XXX: need to flush to get prim_vbuf.c to release its allocation??
*/
draw_do_flush( draw, DRAW_FLUSH_BACKEND );
 
if (!draw->render->allocate_vertices( draw->render,
(ushort)feme->translate->key.output_stride,
(ushort)count ))
goto fail;
 
hw_verts = draw->render->map_vertices( draw->render );
if (!hw_verts)
goto fail;
 
/* Single routine to fetch vertices and emit HW verts.
*/
feme->translate->run( feme->translate,
start,
count,
draw->start_instance,
draw->instance_id,
hw_verts );
 
if (0) {
unsigned i;
for (i = 0; i < count; i++) {
debug_printf("\n\nvertex %d:\n", i);
draw_dump_emitted_vertex( feme->vinfo,
(const uint8_t *)hw_verts + feme->vinfo->size * 4 * i );
}
}
 
draw->render->unmap_vertices( draw->render, 0, count - 1 );
 
/* XXX: Draw arrays path to avoid re-emitting index list again and
* again.
*/
draw->render->draw_arrays( draw->render, 0, count );
 
/* Done -- that was easy, wasn't it:
*/
draw->render->release_vertices( draw->render );
return;
 
fail:
debug_warn_once("allocate or map of vertex buffer failed (out of memory?)");
return;
}
 
 
static boolean fetch_emit_run_linear_elts( struct draw_pt_middle_end *middle,
unsigned start,
unsigned count,
const ushort *draw_elts,
unsigned draw_count,
unsigned prim_flags )
{
struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle;
struct draw_context *draw = feme->draw;
void *hw_verts;
 
/* XXX: need to flush to get prim_vbuf.c to release its allocation??
*/
draw_do_flush( draw, DRAW_FLUSH_BACKEND );
 
if (!draw->render->allocate_vertices( draw->render,
(ushort)feme->translate->key.output_stride,
(ushort)count ))
return FALSE;
 
hw_verts = draw->render->map_vertices( draw->render );
if (!hw_verts)
return FALSE;
 
/* Single routine to fetch vertices and emit HW verts.
*/
feme->translate->run( feme->translate,
start,
count,
draw->start_instance,
draw->instance_id,
hw_verts );
 
draw->render->unmap_vertices( draw->render, 0, (ushort)(count - 1) );
 
/* XXX: Draw arrays path to avoid re-emitting index list again and
* again.
*/
draw->render->draw_elements( draw->render,
draw_elts,
draw_count );
 
/* Done -- that was easy, wasn't it:
*/
draw->render->release_vertices( draw->render );
 
return TRUE;
}
 
 
static void fetch_emit_finish( struct draw_pt_middle_end *middle )
{
/* nothing to do */
}
 
 
static void fetch_emit_destroy( struct draw_pt_middle_end *middle )
{
struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle;
 
if (feme->cache)
translate_cache_destroy(feme->cache);
 
FREE(middle);
}
 
 
struct draw_pt_middle_end *draw_pt_fetch_emit( struct draw_context *draw )
{
struct fetch_emit_middle_end *fetch_emit = CALLOC_STRUCT( fetch_emit_middle_end );
if (fetch_emit == NULL)
return NULL;
 
fetch_emit->cache = translate_cache_create();
if (!fetch_emit->cache) {
FREE(fetch_emit);
return NULL;
}
 
fetch_emit->base.prepare = fetch_emit_prepare;
fetch_emit->base.run = fetch_emit_run;
fetch_emit->base.run_linear = fetch_emit_run_linear;
fetch_emit->base.run_linear_elts = fetch_emit_run_linear_elts;
fetch_emit->base.finish = fetch_emit_finish;
fetch_emit->base.destroy = fetch_emit_destroy;
 
fetch_emit->draw = draw;
 
return &fetch_emit->base;
}
 
/drivers/video/Gallium/auxiliary/draw/draw_pt_fetch_shade_emit.c
0,0 → 1,377
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
 
#include "util/u_math.h"
#include "util/u_memory.h"
#include "draw/draw_context.h"
#include "draw/draw_private.h"
#include "draw/draw_vbuf.h"
#include "draw/draw_vertex.h"
#include "draw/draw_pt.h"
#include "draw/draw_vs.h"
 
 
struct fetch_shade_emit;
 
 
/* Prototype fetch, shade, emit-hw-verts all in one go.
*/
struct fetch_shade_emit {
struct draw_pt_middle_end base;
struct draw_context *draw;
 
/* Temporaries:
*/
const float *constants;
unsigned pitch[PIPE_MAX_ATTRIBS];
const ubyte *src[PIPE_MAX_ATTRIBS];
unsigned prim;
 
struct draw_vs_variant_key key;
struct draw_vs_variant *active;
 
const struct vertex_info *vinfo;
};
 
 
 
static void
fse_prepare(struct draw_pt_middle_end *middle,
unsigned prim,
unsigned opt,
unsigned *max_vertices)
{
struct fetch_shade_emit *fse = (struct fetch_shade_emit *)middle;
struct draw_context *draw = fse->draw;
unsigned num_vs_inputs = draw->vs.vertex_shader->info.num_inputs;
const struct vertex_info *vinfo;
unsigned i;
unsigned nr_vbs = 0;
 
/* Can't support geometry shader on this path.
*/
assert(!draw->gs.geometry_shader);
 
draw->render->set_primitive(draw->render, prim);
 
/* Must do this after set_primitive() above:
*/
fse->vinfo = vinfo = draw->render->get_vertex_info(draw->render);
 
fse->key.output_stride = vinfo->size * 4;
fse->key.nr_outputs = vinfo->num_attribs;
fse->key.nr_inputs = num_vs_inputs;
 
fse->key.nr_elements = MAX2(fse->key.nr_outputs, /* outputs - translate to hw format */
fse->key.nr_inputs); /* inputs - fetch from api format */
 
fse->key.viewport = !draw->identity_viewport;
fse->key.clip = draw->clip_xy || draw->clip_z || draw->clip_user;
fse->key.const_vbuffers = 0;
 
memset(fse->key.element, 0,
fse->key.nr_elements * sizeof(fse->key.element[0]));
 
for (i = 0; i < num_vs_inputs; i++) {
const struct pipe_vertex_element *src = &draw->pt.vertex_element[i];
fse->key.element[i].in.format = src->src_format;
 
/* Consider ignoring these, ie make generated programs
* independent of this state:
*/
fse->key.element[i].in.buffer = src->vertex_buffer_index;
fse->key.element[i].in.offset = src->src_offset;
nr_vbs = MAX2(nr_vbs, src->vertex_buffer_index + 1);
}
 
for (i = 0; i < 5 && i < nr_vbs; i++) {
if (draw->pt.vertex_buffer[i].stride == 0)
fse->key.const_vbuffers |= (1<<i);
}
 
if (0) debug_printf("%s: lookup const_vbuffers: %x\n", __FUNCTION__, fse->key.const_vbuffers);
 
{
unsigned dst_offset = 0;
 
for (i = 0; i < vinfo->num_attribs; i++) {
unsigned emit_sz = draw_translate_vinfo_size(vinfo->attrib[i].emit);
 
/* doesn't handle EMIT_OMIT */
assert(emit_sz != 0);
 
/* The elements in the key correspond to vertex shader output
* numbers, not to positions in the hw vertex description --
* that's handled by the output_offset field.
*/
fse->key.element[i].out.format = vinfo->attrib[i].emit;
fse->key.element[i].out.vs_output = vinfo->attrib[i].src_index;
fse->key.element[i].out.offset = dst_offset;
 
dst_offset += emit_sz;
assert(fse->key.output_stride >= dst_offset);
}
}
 
fse->active = draw_vs_lookup_variant( draw->vs.vertex_shader,
&fse->key );
 
if (!fse->active) {
assert(0);
return ;
}
 
if (0) debug_printf("%s: found const_vbuffers: %x\n", __FUNCTION__,
fse->active->key.const_vbuffers);
 
/* Now set buffer pointers:
*/
for (i = 0; i < draw->pt.nr_vertex_buffers; i++) {
fse->active->set_buffer( fse->active,
i,
((const ubyte *) draw->pt.user.vbuffer[i].map +
draw->pt.vertex_buffer[i].buffer_offset),
draw->pt.vertex_buffer[i].stride,
draw->pt.max_index );
}
 
*max_vertices = (draw->render->max_vertex_buffer_bytes /
(vinfo->size * 4));
 
/* Probably need to do this somewhere (or fix exec shader not to
* need it):
*/
if (1) {
struct draw_vertex_shader *vs = draw->vs.vertex_shader;
vs->prepare(vs, draw);
}
}
 
 
 
static void
fse_run_linear(struct draw_pt_middle_end *middle,
unsigned start,
unsigned count,
unsigned prim_flags)
{
struct fetch_shade_emit *fse = (struct fetch_shade_emit *)middle;
struct draw_context *draw = fse->draw;
char *hw_verts;
 
/* XXX: need to flush to get prim_vbuf.c to release its allocation??
*/
draw_do_flush( draw, DRAW_FLUSH_BACKEND );
 
if (!draw->render->allocate_vertices( draw->render,
(ushort)fse->key.output_stride,
(ushort)count ))
goto fail;
 
hw_verts = draw->render->map_vertices( draw->render );
if (!hw_verts)
goto fail;
 
/* Single routine to fetch vertices, run shader and emit HW verts.
* Clipping is done elsewhere -- either by the API or on hardware,
* or for some other reason not required...
*/
fse->active->run_linear( fse->active,
start, count,
hw_verts );
 
if (0) {
unsigned i;
for (i = 0; i < count; i++) {
debug_printf("\n\n%s vertex %d: (stride %d, offset %d)\n", __FUNCTION__, i,
fse->key.output_stride,
fse->key.output_stride * i);
 
draw_dump_emitted_vertex( fse->vinfo,
(const uint8_t *)hw_verts + fse->key.output_stride * i );
}
}
 
draw->render->unmap_vertices( draw->render, 0, (ushort)(count - 1) );
 
/* Draw arrays path to avoid re-emitting index list again and
* again.
*/
draw->render->draw_arrays( draw->render,
0,
count );
 
draw->render->release_vertices( draw->render );
 
return;
 
fail:
debug_warn_once("allocate or map of vertex buffer failed (out of memory?)");
return;
}
 
 
static void
fse_run(struct draw_pt_middle_end *middle,
const unsigned *fetch_elts,
unsigned fetch_count,
const ushort *draw_elts,
unsigned draw_count,
unsigned prim_flags )
{
struct fetch_shade_emit *fse = (struct fetch_shade_emit *)middle;
struct draw_context *draw = fse->draw;
void *hw_verts;
 
/* XXX: need to flush to get prim_vbuf.c to release its allocation??
*/
draw_do_flush( draw, DRAW_FLUSH_BACKEND );
 
if (!draw->render->allocate_vertices( draw->render,
(ushort)fse->key.output_stride,
(ushort)fetch_count ))
goto fail;
 
hw_verts = draw->render->map_vertices( draw->render );
if (!hw_verts)
goto fail;
 
/* Single routine to fetch vertices, run shader and emit HW verts.
*/
fse->active->run_elts( fse->active,
fetch_elts,
fetch_count,
hw_verts );
 
if (0) {
unsigned i;
for (i = 0; i < fetch_count; i++) {
debug_printf("\n\n%s vertex %d:\n", __FUNCTION__, i);
draw_dump_emitted_vertex( fse->vinfo,
(const uint8_t *)hw_verts +
fse->key.output_stride * i );
}
}
 
draw->render->unmap_vertices( draw->render, 0, (ushort)(fetch_count - 1) );
 
draw->render->draw_elements( draw->render,
draw_elts,
draw_count );
 
draw->render->release_vertices( draw->render );
return;
 
fail:
debug_warn_once("allocate or map of vertex buffer failed (out of memory?)");
return;
}
 
 
 
static boolean
fse_run_linear_elts(struct draw_pt_middle_end *middle,
unsigned start,
unsigned count,
const ushort *draw_elts,
unsigned draw_count,
unsigned prim_flags)
{
struct fetch_shade_emit *fse = (struct fetch_shade_emit *)middle;
struct draw_context *draw = fse->draw;
char *hw_verts;
 
/* XXX: need to flush to get prim_vbuf.c to release its allocation??
*/
draw_do_flush( draw, DRAW_FLUSH_BACKEND );
 
if (!draw->render->allocate_vertices( draw->render,
(ushort)fse->key.output_stride,
(ushort)count ))
return FALSE;
 
hw_verts = draw->render->map_vertices( draw->render );
if (!hw_verts)
return FALSE;
 
/* Single routine to fetch vertices, run shader and emit HW verts.
* Clipping is done elsewhere -- either by the API or on hardware,
* or for some other reason not required...
*/
fse->active->run_linear( fse->active,
start, count,
hw_verts );
 
draw->render->draw_elements( draw->render,
draw_elts,
draw_count );
 
draw->render->unmap_vertices( draw->render, 0, (ushort)(count - 1) );
 
draw->render->release_vertices( draw->render );
 
return TRUE;
}
 
 
 
static void
fse_finish(struct draw_pt_middle_end *middle)
{
}
 
 
static void
fse_destroy(struct draw_pt_middle_end *middle)
{
FREE(middle);
}
 
 
struct draw_pt_middle_end *
draw_pt_middle_fse(struct draw_context *draw)
{
struct fetch_shade_emit *fse = CALLOC_STRUCT(fetch_shade_emit);
if (!fse)
return NULL;
 
fse->base.prepare = fse_prepare;
fse->base.run = fse_run;
fse->base.run_linear = fse_run_linear;
fse->base.run_linear_elts = fse_run_linear_elts;
fse->base.finish = fse_finish;
fse->base.destroy = fse_destroy;
fse->draw = draw;
 
return &fse->base;
}
/drivers/video/Gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline.c
0,0 → 1,501
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
#include "util/u_math.h"
#include "util/u_memory.h"
#include "util/u_prim.h"
#include "draw/draw_context.h"
#include "draw/draw_vbuf.h"
#include "draw/draw_vertex.h"
#include "draw/draw_prim_assembler.h"
#include "draw/draw_pt.h"
#include "draw/draw_vs.h"
#include "draw/draw_gs.h"
 
 
struct fetch_pipeline_middle_end {
struct draw_pt_middle_end base;
struct draw_context *draw;
 
struct pt_emit *emit;
struct pt_so_emit *so_emit;
struct pt_fetch *fetch;
struct pt_post_vs *post_vs;
 
unsigned vertex_data_offset;
unsigned vertex_size;
unsigned input_prim;
unsigned opt;
};
 
 
/**
* Prepare/validate middle part of the vertex pipeline.
* NOTE: if you change this function, also look at the LLVM
* function llvm_middle_end_prepare() for similar changes.
*/
static void fetch_pipeline_prepare( struct draw_pt_middle_end *middle,
unsigned prim,
unsigned opt,
unsigned *max_vertices )
{
struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
struct draw_context *draw = fpme->draw;
struct draw_vertex_shader *vs = draw->vs.vertex_shader;
struct draw_geometry_shader *gs = draw->gs.geometry_shader;
unsigned i;
unsigned instance_id_index = ~0;
 
const unsigned gs_out_prim = (gs ? gs->output_primitive :
u_assembled_prim(prim));
 
/* Add one to num_outputs because the pipeline occasionally tags on
* an additional texcoord, eg for AA lines.
*/
unsigned nr = MAX2( vs->info.num_inputs,
vs->info.num_outputs + 1 );
 
if (gs) {
nr = MAX2(nr, gs->info.num_outputs + 1);
}
 
/* Scan for instanceID system value.
*/
for (i = 0; i < vs->info.num_inputs; i++) {
if (vs->info.input_semantic_name[i] == TGSI_SEMANTIC_INSTANCEID) {
instance_id_index = i;
break;
}
}
 
fpme->input_prim = prim;
fpme->opt = opt;
 
/* Always leave room for the vertex header whether we need it or
* not. It's hard to get rid of it in particular because of the
* viewport code in draw_pt_post_vs.c.
*/
fpme->vertex_size = sizeof(struct vertex_header) + nr * 4 * sizeof(float);
 
 
draw_pt_fetch_prepare( fpme->fetch,
vs->info.num_inputs,
fpme->vertex_size,
instance_id_index );
draw_pt_post_vs_prepare( fpme->post_vs,
draw->clip_xy,
draw->clip_z,
draw->clip_user,
draw->guard_band_xy,
draw->identity_viewport,
draw->rasterizer->clip_halfz,
(draw->vs.edgeflag_output ? TRUE : FALSE) );
 
draw_pt_so_emit_prepare( fpme->so_emit, FALSE );
 
if (!(opt & PT_PIPELINE)) {
draw_pt_emit_prepare( fpme->emit,
gs_out_prim,
max_vertices );
 
*max_vertices = MAX2( *max_vertices, 4096 );
}
else {
/* limit max fetches by limiting max_vertices */
*max_vertices = 4096;
}
 
/* No need to prepare the shader.
*/
vs->prepare(vs, draw);
}
 
 
static void
fetch_pipeline_bind_parameters(struct draw_pt_middle_end *middle)
{
/* No-op since the vertex shader executor and drawing pipeline
* just grab the constants, viewport, etc. from the draw context state.
*/
}
 
 
static void fetch( struct pt_fetch *fetch,
const struct draw_fetch_info *fetch_info,
char *output)
{
if (fetch_info->linear) {
draw_pt_fetch_run_linear( fetch,
fetch_info->start,
fetch_info->count,
output );
}
else {
draw_pt_fetch_run( fetch,
fetch_info->elts,
fetch_info->count,
output );
}
}
 
 
static void pipeline(struct fetch_pipeline_middle_end *fpme,
const struct draw_vertex_info *vert_info,
const struct draw_prim_info *prim_info)
{
if (prim_info->linear)
draw_pipeline_run_linear( fpme->draw,
vert_info,
prim_info);
else
draw_pipeline_run( fpme->draw,
vert_info,
prim_info );
}
 
static void emit(struct pt_emit *emit,
const struct draw_vertex_info *vert_info,
const struct draw_prim_info *prim_info)
{
if (prim_info->linear) {
draw_pt_emit_linear(emit, vert_info, prim_info);
}
else {
draw_pt_emit(emit, vert_info, prim_info);
}
}
 
 
static void draw_vertex_shader_run(struct draw_vertex_shader *vshader,
const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
unsigned const_size[PIPE_MAX_CONSTANT_BUFFERS],
const struct draw_vertex_info *input_verts,
struct draw_vertex_info *output_verts )
{
output_verts->vertex_size = input_verts->vertex_size;
output_verts->stride = input_verts->vertex_size;
output_verts->count = input_verts->count;
output_verts->verts =
(struct vertex_header *)MALLOC(output_verts->vertex_size *
align(output_verts->count, 4));
 
vshader->run_linear(vshader,
(const float (*)[4])input_verts->verts->data,
( float (*)[4])output_verts->verts->data,
constants,
const_size,
input_verts->count,
input_verts->vertex_size,
input_verts->vertex_size);
}
 
static void fetch_pipeline_generic( struct draw_pt_middle_end *middle,
const struct draw_fetch_info *fetch_info,
const struct draw_prim_info *in_prim_info )
{
struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
struct draw_context *draw = fpme->draw;
struct draw_vertex_shader *vshader = draw->vs.vertex_shader;
struct draw_geometry_shader *gshader = draw->gs.geometry_shader;
struct draw_prim_info gs_prim_info;
struct draw_vertex_info fetched_vert_info;
struct draw_vertex_info vs_vert_info;
struct draw_vertex_info gs_vert_info;
struct draw_vertex_info *vert_info;
struct draw_prim_info ia_prim_info;
struct draw_vertex_info ia_vert_info;
const struct draw_prim_info *prim_info = in_prim_info;
boolean free_prim_info = FALSE;
unsigned opt = fpme->opt;
 
fetched_vert_info.count = fetch_info->count;
fetched_vert_info.vertex_size = fpme->vertex_size;
fetched_vert_info.stride = fpme->vertex_size;
fetched_vert_info.verts =
(struct vertex_header *)MALLOC(fpme->vertex_size *
align(fetch_info->count, 4));
if (!fetched_vert_info.verts) {
assert(0);
return;
}
if (draw->collect_statistics) {
draw->statistics.ia_vertices += prim_info->count;
draw->statistics.ia_primitives +=
u_decomposed_prims_for_vertices(prim_info->prim, fetch_info->count);
draw->statistics.vs_invocations += fetch_info->count;
}
 
/* Fetch into our vertex buffer.
*/
fetch( fpme->fetch, fetch_info, (char *)fetched_vert_info.verts );
 
/* Finished with fetch:
*/
fetch_info = NULL;
vert_info = &fetched_vert_info;
 
/* Run the shader, note that this overwrites the data[] parts of
* the pipeline verts.
*/
if (fpme->opt & PT_SHADE) {
draw_vertex_shader_run(vshader,
draw->pt.user.vs_constants,
draw->pt.user.vs_constants_size,
vert_info,
&vs_vert_info);
 
FREE(vert_info->verts);
vert_info = &vs_vert_info;
}
 
if ((fpme->opt & PT_SHADE) && gshader) {
draw_geometry_shader_run(gshader,
draw->pt.user.gs_constants,
draw->pt.user.gs_constants_size,
vert_info,
prim_info,
&vshader->info,
&gs_vert_info,
&gs_prim_info);
 
FREE(vert_info->verts);
vert_info = &gs_vert_info;
prim_info = &gs_prim_info;
} else {
if (draw_prim_assembler_is_required(draw, prim_info, vert_info)) {
draw_prim_assembler_run(draw, prim_info, vert_info,
&ia_prim_info, &ia_vert_info);
 
if (ia_vert_info.count) {
FREE(vert_info->verts);
vert_info = &ia_vert_info;
prim_info = &ia_prim_info;
free_prim_info = TRUE;
}
}
}
if (prim_info->count == 0) {
debug_printf("GS/IA didn't emit any vertices!\n");
FREE(vert_info->verts);
if (free_prim_info) {
FREE(prim_info->primitive_lengths);
}
return;
}
 
 
/* Stream output needs to be done before clipping.
*
* XXX: Stream output surely needs to respect the prim_info->elt
* lists.
*/
draw_pt_so_emit( fpme->so_emit, vert_info, prim_info );
 
draw_stats_clipper_primitives(draw, prim_info);
 
/*
* if there's no position, need to stop now, or the latter stages
* will try to access non-existent position output.
*/
if (draw_current_shader_position_output(draw) != -1) {
 
if (draw_pt_post_vs_run( fpme->post_vs, vert_info, prim_info ))
{
opt |= PT_PIPELINE;
}
 
/* Do we need to run the pipeline?
*/
if (opt & PT_PIPELINE) {
pipeline( fpme, vert_info, prim_info );
}
else {
emit( fpme->emit, vert_info, prim_info );
}
}
FREE(vert_info->verts);
if (free_prim_info) {
FREE(prim_info->primitive_lengths);
}
}
 
static void fetch_pipeline_run( struct draw_pt_middle_end *middle,
const unsigned *fetch_elts,
unsigned fetch_count,
const ushort *draw_elts,
unsigned draw_count,
unsigned prim_flags )
{
struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
struct draw_fetch_info fetch_info;
struct draw_prim_info prim_info;
 
fetch_info.linear = FALSE;
fetch_info.start = 0;
fetch_info.elts = fetch_elts;
fetch_info.count = fetch_count;
 
prim_info.linear = FALSE;
prim_info.start = 0;
prim_info.count = draw_count;
prim_info.elts = draw_elts;
prim_info.prim = fpme->input_prim;
prim_info.flags = prim_flags;
prim_info.primitive_count = 1;
prim_info.primitive_lengths = &draw_count;
 
fetch_pipeline_generic( middle, &fetch_info, &prim_info );
}
 
 
static void fetch_pipeline_linear_run( struct draw_pt_middle_end *middle,
unsigned start,
unsigned count,
unsigned prim_flags)
{
struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
struct draw_fetch_info fetch_info;
struct draw_prim_info prim_info;
 
fetch_info.linear = TRUE;
fetch_info.start = start;
fetch_info.count = count;
fetch_info.elts = NULL;
 
prim_info.linear = TRUE;
prim_info.start = 0;
prim_info.count = count;
prim_info.elts = NULL;
prim_info.prim = fpme->input_prim;
prim_info.flags = prim_flags;
prim_info.primitive_count = 1;
prim_info.primitive_lengths = &count;
 
fetch_pipeline_generic( middle, &fetch_info, &prim_info );
}
 
 
 
static boolean fetch_pipeline_linear_run_elts( struct draw_pt_middle_end *middle,
unsigned start,
unsigned count,
const ushort *draw_elts,
unsigned draw_count,
unsigned prim_flags )
{
struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
struct draw_fetch_info fetch_info;
struct draw_prim_info prim_info;
 
fetch_info.linear = TRUE;
fetch_info.start = start;
fetch_info.count = count;
fetch_info.elts = NULL;
 
prim_info.linear = FALSE;
prim_info.start = 0;
prim_info.count = draw_count;
prim_info.elts = draw_elts;
prim_info.prim = fpme->input_prim;
prim_info.flags = prim_flags;
prim_info.primitive_count = 1;
prim_info.primitive_lengths = &draw_count;
 
fetch_pipeline_generic( middle, &fetch_info, &prim_info );
 
return TRUE;
}
 
 
 
static void fetch_pipeline_finish( struct draw_pt_middle_end *middle )
{
/* nothing to do */
}
 
static void fetch_pipeline_destroy( struct draw_pt_middle_end *middle )
{
struct fetch_pipeline_middle_end *fpme = (struct fetch_pipeline_middle_end *)middle;
 
if (fpme->fetch)
draw_pt_fetch_destroy( fpme->fetch );
 
if (fpme->emit)
draw_pt_emit_destroy( fpme->emit );
 
if (fpme->so_emit)
draw_pt_so_emit_destroy( fpme->so_emit );
 
if (fpme->post_vs)
draw_pt_post_vs_destroy( fpme->post_vs );
 
FREE(middle);
}
 
 
struct draw_pt_middle_end *draw_pt_fetch_pipeline_or_emit( struct draw_context *draw )
{
struct fetch_pipeline_middle_end *fpme = CALLOC_STRUCT( fetch_pipeline_middle_end );
if (!fpme)
goto fail;
 
fpme->base.prepare = fetch_pipeline_prepare;
fpme->base.bind_parameters = fetch_pipeline_bind_parameters;
fpme->base.run = fetch_pipeline_run;
fpme->base.run_linear = fetch_pipeline_linear_run;
fpme->base.run_linear_elts = fetch_pipeline_linear_run_elts;
fpme->base.finish = fetch_pipeline_finish;
fpme->base.destroy = fetch_pipeline_destroy;
 
fpme->draw = draw;
 
fpme->fetch = draw_pt_fetch_create( draw );
if (!fpme->fetch)
goto fail;
 
fpme->post_vs = draw_pt_post_vs_create( draw );
if (!fpme->post_vs)
goto fail;
 
fpme->emit = draw_pt_emit_create( draw );
if (!fpme->emit)
goto fail;
 
fpme->so_emit = draw_pt_so_emit_create( draw );
if (!fpme->so_emit)
goto fail;
 
return &fpme->base;
 
fail:
if (fpme)
fetch_pipeline_destroy( &fpme->base );
 
return NULL;
}
/drivers/video/Gallium/auxiliary/draw/draw_pt_fetch_shade_pipeline_llvm.c
0,0 → 1,610
/**************************************************************************
*
* Copyright 2010 VMware, Inc.
* 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.
*
**************************************************************************/
 
#include "util/u_math.h"
#include "util/u_memory.h"
#include "util/u_prim.h"
#include "draw/draw_context.h"
#include "draw/draw_gs.h"
#include "draw/draw_vbuf.h"
#include "draw/draw_vertex.h"
#include "draw/draw_pt.h"
#include "draw/draw_prim_assembler.h"
#include "draw/draw_vs.h"
#include "draw/draw_llvm.h"
#include "gallivm/lp_bld_init.h"
 
 
struct llvm_middle_end {
struct draw_pt_middle_end base;
struct draw_context *draw;
 
struct pt_emit *emit;
struct pt_so_emit *so_emit;
struct pt_fetch *fetch;
struct pt_post_vs *post_vs;
 
 
unsigned vertex_data_offset;
unsigned vertex_size;
unsigned input_prim;
unsigned opt;
 
struct draw_llvm *llvm;
struct draw_llvm_variant *current_variant;
};
 
 
static void
llvm_middle_end_prepare_gs(struct llvm_middle_end *fpme)
{
struct draw_context *draw = fpme->draw;
struct draw_geometry_shader *gs = draw->gs.geometry_shader;
struct draw_gs_llvm_variant_key *key;
struct draw_gs_llvm_variant *variant = NULL;
struct draw_gs_llvm_variant_list_item *li;
struct llvm_geometry_shader *shader = llvm_geometry_shader(gs);
char store[DRAW_GS_LLVM_MAX_VARIANT_KEY_SIZE];
unsigned i;
 
key = draw_gs_llvm_make_variant_key(fpme->llvm, store);
 
/* Search shader's list of variants for the key */
li = first_elem(&shader->variants);
while (!at_end(&shader->variants, li)) {
if (memcmp(&li->base->key, key, shader->variant_key_size) == 0) {
variant = li->base;
break;
}
li = next_elem(li);
}
 
if (variant) {
/* found the variant, move to head of global list (for LRU) */
move_to_head(&fpme->llvm->gs_variants_list,
&variant->list_item_global);
}
else {
/* Need to create new variant */
 
/* First check if we've created too many variants. If so, free
* 25% of the LRU to avoid using too much memory.
*/
if (fpme->llvm->nr_gs_variants >= DRAW_MAX_SHADER_VARIANTS) {
/*
* XXX: should we flush here ?
*/
for (i = 0; i < DRAW_MAX_SHADER_VARIANTS / 4; i++) {
struct draw_gs_llvm_variant_list_item *item;
if (is_empty_list(&fpme->llvm->gs_variants_list)) {
break;
}
item = last_elem(&fpme->llvm->gs_variants_list);
assert(item);
assert(item->base);
draw_gs_llvm_destroy_variant(item->base);
}
}
 
variant = draw_gs_llvm_create_variant(fpme->llvm, gs->info.num_outputs, key);
 
if (variant) {
insert_at_head(&shader->variants, &variant->list_item_local);
insert_at_head(&fpme->llvm->gs_variants_list,
&variant->list_item_global);
fpme->llvm->nr_gs_variants++;
shader->variants_cached++;
}
}
 
gs->current_variant = variant;
}
 
/**
* Prepare/validate middle part of the vertex pipeline.
* NOTE: if you change this function, also look at the non-LLVM
* function fetch_pipeline_prepare() for similar changes.
*/
static void
llvm_middle_end_prepare( struct draw_pt_middle_end *middle,
unsigned in_prim,
unsigned opt,
unsigned *max_vertices )
{
struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle;
struct draw_context *draw = fpme->draw;
struct draw_vertex_shader *vs = draw->vs.vertex_shader;
struct draw_geometry_shader *gs = draw->gs.geometry_shader;
const unsigned out_prim = gs ? gs->output_primitive :
u_assembled_prim(in_prim);
 
/* Add one to num_outputs because the pipeline occasionally tags on
* an additional texcoord, eg for AA lines.
*/
const unsigned nr = MAX2( vs->info.num_inputs,
vs->info.num_outputs + 1 );
 
fpme->input_prim = in_prim;
fpme->opt = opt;
 
/* Always leave room for the vertex header whether we need it or
* not. It's hard to get rid of it in particular because of the
* viewport code in draw_pt_post_vs.c.
*/
fpme->vertex_size = sizeof(struct vertex_header) + nr * 4 * sizeof(float);
 
 
draw_pt_post_vs_prepare( fpme->post_vs,
draw->clip_xy,
draw->clip_z,
draw->clip_user,
draw->guard_band_xy,
draw->identity_viewport,
draw->rasterizer->clip_halfz,
(draw->vs.edgeflag_output ? TRUE : FALSE) );
 
draw_pt_so_emit_prepare( fpme->so_emit, gs == NULL );
 
if (!(opt & PT_PIPELINE)) {
draw_pt_emit_prepare( fpme->emit,
out_prim,
max_vertices );
 
*max_vertices = MAX2( *max_vertices, 4096 );
}
else {
/* limit max fetches by limiting max_vertices */
*max_vertices = 4096;
}
 
/* return even number */
*max_vertices = *max_vertices & ~1;
 
/* Find/create the vertex shader variant */
{
struct draw_llvm_variant_key *key;
struct draw_llvm_variant *variant = NULL;
struct draw_llvm_variant_list_item *li;
struct llvm_vertex_shader *shader = llvm_vertex_shader(vs);
char store[DRAW_LLVM_MAX_VARIANT_KEY_SIZE];
unsigned i;
 
key = draw_llvm_make_variant_key(fpme->llvm, store);
 
/* Search shader's list of variants for the key */
li = first_elem(&shader->variants);
while (!at_end(&shader->variants, li)) {
if (memcmp(&li->base->key, key, shader->variant_key_size) == 0) {
variant = li->base;
break;
}
li = next_elem(li);
}
 
if (variant) {
/* found the variant, move to head of global list (for LRU) */
move_to_head(&fpme->llvm->vs_variants_list,
&variant->list_item_global);
}
else {
/* Need to create new variant */
 
/* First check if we've created too many variants. If so, free
* 25% of the LRU to avoid using too much memory.
*/
if (fpme->llvm->nr_variants >= DRAW_MAX_SHADER_VARIANTS) {
/*
* XXX: should we flush here ?
*/
for (i = 0; i < DRAW_MAX_SHADER_VARIANTS / 4; i++) {
struct draw_llvm_variant_list_item *item;
if (is_empty_list(&fpme->llvm->vs_variants_list)) {
break;
}
item = last_elem(&fpme->llvm->vs_variants_list);
assert(item);
assert(item->base);
draw_llvm_destroy_variant(item->base);
}
}
 
variant = draw_llvm_create_variant(fpme->llvm, nr, key);
 
if (variant) {
insert_at_head(&shader->variants, &variant->list_item_local);
insert_at_head(&fpme->llvm->vs_variants_list,
&variant->list_item_global);
fpme->llvm->nr_variants++;
shader->variants_cached++;
}
}
 
fpme->current_variant = variant;
}
 
if (gs) {
llvm_middle_end_prepare_gs(fpme);
}
}
 
 
/**
* Bind/update constant buffer pointers, clip planes and viewport dims.
* These are "light weight" parameters which aren't baked into the
* generated code. Updating these items is much cheaper than revalidating
* and rebuilding the generated pipeline code.
*/
static void
llvm_middle_end_bind_parameters(struct draw_pt_middle_end *middle)
{
struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle;
struct draw_context *draw = fpme->draw;
unsigned i;
 
for (i = 0; i < Elements(fpme->llvm->jit_context.vs_constants); ++i) {
fpme->llvm->jit_context.vs_constants[i] = draw->pt.user.vs_constants[i];
}
for (i = 0; i < Elements(fpme->llvm->gs_jit_context.constants); ++i) {
fpme->llvm->gs_jit_context.constants[i] = draw->pt.user.gs_constants[i];
}
 
fpme->llvm->jit_context.planes =
(float (*)[DRAW_TOTAL_CLIP_PLANES][4]) draw->pt.user.planes[0];
fpme->llvm->gs_jit_context.planes =
(float (*)[DRAW_TOTAL_CLIP_PLANES][4]) draw->pt.user.planes[0];
 
fpme->llvm->jit_context.viewport = (float *) draw->viewports[0].scale;
fpme->llvm->gs_jit_context.viewport = (float *) draw->viewports[0].scale;
}
 
 
static void pipeline(struct llvm_middle_end *llvm,
const struct draw_vertex_info *vert_info,
const struct draw_prim_info *prim_info)
{
if (prim_info->linear)
draw_pipeline_run_linear( llvm->draw,
vert_info,
prim_info);
else
draw_pipeline_run( llvm->draw,
vert_info,
prim_info );
}
 
static void emit(struct pt_emit *emit,
const struct draw_vertex_info *vert_info,
const struct draw_prim_info *prim_info)
{
if (prim_info->linear) {
draw_pt_emit_linear(emit, vert_info, prim_info);
}
else {
draw_pt_emit(emit, vert_info, prim_info);
}
}
 
static void
llvm_pipeline_generic( struct draw_pt_middle_end *middle,
const struct draw_fetch_info *fetch_info,
const struct draw_prim_info *in_prim_info )
{
struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle;
struct draw_context *draw = fpme->draw;
struct draw_geometry_shader *gshader = draw->gs.geometry_shader;
struct draw_prim_info gs_prim_info;
struct draw_vertex_info llvm_vert_info;
struct draw_vertex_info gs_vert_info;
struct draw_vertex_info *vert_info;
struct draw_prim_info ia_prim_info;
struct draw_vertex_info ia_vert_info;
const struct draw_prim_info *prim_info = in_prim_info;
boolean free_prim_info = FALSE;
unsigned opt = fpme->opt;
unsigned clipped = 0;
 
llvm_vert_info.count = fetch_info->count;
llvm_vert_info.vertex_size = fpme->vertex_size;
llvm_vert_info.stride = fpme->vertex_size;
llvm_vert_info.verts =
(struct vertex_header *)MALLOC(fpme->vertex_size *
align(fetch_info->count, lp_native_vector_width / 32));
if (!llvm_vert_info.verts) {
assert(0);
return;
}
 
if (draw->collect_statistics) {
draw->statistics.ia_vertices += prim_info->count;
draw->statistics.ia_primitives +=
u_decomposed_prims_for_vertices(prim_info->prim, prim_info->count);
draw->statistics.vs_invocations += fetch_info->count;
}
 
if (fetch_info->linear)
clipped = fpme->current_variant->jit_func( &fpme->llvm->jit_context,
llvm_vert_info.verts,
draw->pt.user.vbuffer,
fetch_info->start,
fetch_info->count,
fpme->vertex_size,
draw->pt.vertex_buffer,
draw->instance_id);
else
clipped = fpme->current_variant->jit_func_elts( &fpme->llvm->jit_context,
llvm_vert_info.verts,
draw->pt.user.vbuffer,
fetch_info->elts,
draw->pt.user.eltMax,
fetch_info->count,
fpme->vertex_size,
draw->pt.vertex_buffer,
draw->instance_id);
 
/* Finished with fetch and vs:
*/
fetch_info = NULL;
vert_info = &llvm_vert_info;
 
 
if ((opt & PT_SHADE) && gshader) {
struct draw_vertex_shader *vshader = draw->vs.vertex_shader;
draw_geometry_shader_run(gshader,
draw->pt.user.gs_constants,
draw->pt.user.gs_constants_size,
vert_info,
prim_info,
&vshader->info,
&gs_vert_info,
&gs_prim_info);
 
FREE(vert_info->verts);
vert_info = &gs_vert_info;
prim_info = &gs_prim_info;
} else {
if (draw_prim_assembler_is_required(draw, prim_info, vert_info)) {
draw_prim_assembler_run(draw, prim_info, vert_info,
&ia_prim_info, &ia_vert_info);
 
if (ia_vert_info.count) {
FREE(vert_info->verts);
vert_info = &ia_vert_info;
prim_info = &ia_prim_info;
free_prim_info = TRUE;
}
}
}
if (prim_info->count == 0) {
debug_printf("GS/IA didn't emit any vertices!\n");
FREE(vert_info->verts);
if (free_prim_info) {
FREE(prim_info->primitive_lengths);
}
return;
}
 
/* stream output needs to be done before clipping */
draw_pt_so_emit( fpme->so_emit, vert_info, prim_info );
 
draw_stats_clipper_primitives(draw, prim_info);
 
/*
* if there's no position, need to stop now, or the latter stages
* will try to access non-existent position output.
*/
if (draw_current_shader_position_output(draw) != -1) {
if ((opt & PT_SHADE) && gshader) {
clipped = draw_pt_post_vs_run( fpme->post_vs, vert_info, prim_info );
}
if (clipped) {
opt |= PT_PIPELINE;
}
 
/* Do we need to run the pipeline? Now will come here if clipped
*/
if (opt & PT_PIPELINE) {
pipeline( fpme, vert_info, prim_info );
}
else {
emit( fpme->emit, vert_info, prim_info );
}
}
FREE(vert_info->verts);
if (free_prim_info) {
FREE(prim_info->primitive_lengths);
}
}
 
 
static void llvm_middle_end_run( struct draw_pt_middle_end *middle,
const unsigned *fetch_elts,
unsigned fetch_count,
const ushort *draw_elts,
unsigned draw_count,
unsigned prim_flags )
{
struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle;
struct draw_fetch_info fetch_info;
struct draw_prim_info prim_info;
 
fetch_info.linear = FALSE;
fetch_info.start = 0;
fetch_info.elts = fetch_elts;
fetch_info.count = fetch_count;
 
prim_info.linear = FALSE;
prim_info.start = 0;
prim_info.count = draw_count;
prim_info.elts = draw_elts;
prim_info.prim = fpme->input_prim;
prim_info.flags = prim_flags;
prim_info.primitive_count = 1;
prim_info.primitive_lengths = &draw_count;
 
llvm_pipeline_generic( middle, &fetch_info, &prim_info );
}
 
 
static void llvm_middle_end_linear_run( struct draw_pt_middle_end *middle,
unsigned start,
unsigned count,
unsigned prim_flags)
{
struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle;
struct draw_fetch_info fetch_info;
struct draw_prim_info prim_info;
 
fetch_info.linear = TRUE;
fetch_info.start = start;
fetch_info.count = count;
fetch_info.elts = NULL;
 
prim_info.linear = TRUE;
prim_info.start = 0;
prim_info.count = count;
prim_info.elts = NULL;
prim_info.prim = fpme->input_prim;
prim_info.flags = prim_flags;
prim_info.primitive_count = 1;
prim_info.primitive_lengths = &count;
 
llvm_pipeline_generic( middle, &fetch_info, &prim_info );
}
 
 
 
static boolean
llvm_middle_end_linear_run_elts( struct draw_pt_middle_end *middle,
unsigned start,
unsigned count,
const ushort *draw_elts,
unsigned draw_count,
unsigned prim_flags )
{
struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle;
struct draw_fetch_info fetch_info;
struct draw_prim_info prim_info;
 
fetch_info.linear = TRUE;
fetch_info.start = start;
fetch_info.count = count;
fetch_info.elts = NULL;
 
prim_info.linear = FALSE;
prim_info.start = 0;
prim_info.count = draw_count;
prim_info.elts = draw_elts;
prim_info.prim = fpme->input_prim;
prim_info.flags = prim_flags;
prim_info.primitive_count = 1;
prim_info.primitive_lengths = &draw_count;
 
llvm_pipeline_generic( middle, &fetch_info, &prim_info );
 
return TRUE;
}
 
 
 
static void llvm_middle_end_finish( struct draw_pt_middle_end *middle )
{
/* nothing to do */
}
 
static void llvm_middle_end_destroy( struct draw_pt_middle_end *middle )
{
struct llvm_middle_end *fpme = (struct llvm_middle_end *)middle;
 
if (fpme->fetch)
draw_pt_fetch_destroy( fpme->fetch );
 
if (fpme->emit)
draw_pt_emit_destroy( fpme->emit );
 
if (fpme->so_emit)
draw_pt_so_emit_destroy( fpme->so_emit );
 
if (fpme->post_vs)
draw_pt_post_vs_destroy( fpme->post_vs );
 
FREE(middle);
}
 
 
struct draw_pt_middle_end *
draw_pt_fetch_pipeline_or_emit_llvm(struct draw_context *draw)
{
struct llvm_middle_end *fpme = 0;
 
if (!draw->llvm)
return NULL;
 
fpme = CALLOC_STRUCT( llvm_middle_end );
if (!fpme)
goto fail;
 
fpme->base.prepare = llvm_middle_end_prepare;
fpme->base.bind_parameters = llvm_middle_end_bind_parameters;
fpme->base.run = llvm_middle_end_run;
fpme->base.run_linear = llvm_middle_end_linear_run;
fpme->base.run_linear_elts = llvm_middle_end_linear_run_elts;
fpme->base.finish = llvm_middle_end_finish;
fpme->base.destroy = llvm_middle_end_destroy;
 
fpme->draw = draw;
 
fpme->fetch = draw_pt_fetch_create( draw );
if (!fpme->fetch)
goto fail;
 
fpme->post_vs = draw_pt_post_vs_create( draw );
if (!fpme->post_vs)
goto fail;
 
fpme->emit = draw_pt_emit_create( draw );
if (!fpme->emit)
goto fail;
 
fpme->so_emit = draw_pt_so_emit_create( draw );
if (!fpme->so_emit)
goto fail;
 
fpme->llvm = draw->llvm;
if (!fpme->llvm)
goto fail;
 
fpme->current_variant = NULL;
 
return &fpme->base;
 
fail:
if (fpme)
llvm_middle_end_destroy( &fpme->base );
 
return NULL;
}
/drivers/video/Gallium/auxiliary/draw/draw_pt_post_vs.c
0,0 → 1,234
/**************************************************************************
*
* 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.
*
**************************************************************************/
 
#include "util/u_memory.h"
#include "util/u_math.h"
#include "util/u_prim.h"
#include "pipe/p_context.h"
#include "draw/draw_context.h"
#include "draw/draw_private.h"
#include "draw/draw_pt.h"
#include "draw/draw_vs.h"
 
#define DO_CLIP_XY 0x1
#define DO_CLIP_FULL_Z 0x2
#define DO_CLIP_HALF_Z 0x4
#define DO_CLIP_USER 0x8
#define DO_VIEWPORT 0x10
#define DO_EDGEFLAG 0x20
#define DO_CLIP_XY_GUARD_BAND 0x40
 
 
struct pt_post_vs {
struct draw_context *draw;
 
unsigned flags;
 
boolean (*run)( struct pt_post_vs *pvs,
struct draw_vertex_info *info,
const struct draw_prim_info *prim_info );
};
 
static INLINE void
initialize_vertex_header(struct vertex_header *header)
{
header->clipmask = 0;
header->edgeflag = 1;
header->have_clipdist = 0;
header->vertex_id = UNDEFINED_VERTEX_ID;
}
 
static INLINE float
dot4(const float *a, const float *b)
{
return (a[0]*b[0] +
a[1]*b[1] +
a[2]*b[2] +
a[3]*b[3]);
}
 
#define FLAGS (0)
#define TAG(x) x##_none
#include "draw_cliptest_tmp.h"
 
#define FLAGS (DO_CLIP_XY | DO_CLIP_FULL_Z | DO_VIEWPORT)
#define TAG(x) x##_xy_fullz_viewport
#include "draw_cliptest_tmp.h"
 
#define FLAGS (DO_CLIP_XY | DO_CLIP_HALF_Z | DO_VIEWPORT)
#define TAG(x) x##_xy_halfz_viewport
#include "draw_cliptest_tmp.h"
 
#define FLAGS (DO_CLIP_XY_GUARD_BAND | DO_CLIP_HALF_Z | DO_VIEWPORT)
#define TAG(x) x##_xy_gb_halfz_viewport
#include "draw_cliptest_tmp.h"
 
#define FLAGS (DO_CLIP_FULL_Z | DO_VIEWPORT)
#define TAG(x) x##_fullz_viewport
#include "draw_cliptest_tmp.h"
 
#define FLAGS (DO_CLIP_HALF_Z | DO_VIEWPORT)
#define TAG(x) x##_halfz_viewport
#include "draw_cliptest_tmp.h"
 
#define FLAGS (DO_CLIP_XY | DO_CLIP_FULL_Z | DO_CLIP_USER | DO_VIEWPORT)
#define TAG(x) x##_xy_fullz_user_viewport
#include "draw_cliptest_tmp.h"
 
#define FLAGS (DO_CLIP_XY | DO_CLIP_FULL_Z | DO_CLIP_USER | DO_VIEWPORT | DO_EDGEFLAG)
#define TAG(x) x##_xy_fullz_user_viewport_edgeflag
#include "draw_cliptest_tmp.h"
 
 
 
/* Don't want to create 64 versions of this function, so catch the
* less common ones here. This is looking like something which should
* be code-generated, perhaps appended to the end of the vertex
* shader.
*/
#define FLAGS (pvs->flags)
#define TAG(x) x##_generic
#include "draw_cliptest_tmp.h"
 
 
 
boolean draw_pt_post_vs_run( struct pt_post_vs *pvs,
struct draw_vertex_info *info,
const struct draw_prim_info *prim_info )
{
return pvs->run( pvs, info, prim_info );
}
 
 
void draw_pt_post_vs_prepare( struct pt_post_vs *pvs,
boolean clip_xy,
boolean clip_z,
boolean clip_user,
boolean guard_band,
boolean bypass_viewport,
boolean clip_halfz,
boolean need_edgeflags )
{
pvs->flags = 0;
 
/* This combination not currently tested/in use:
*/
if (!clip_halfz)
guard_band = FALSE;
 
if (clip_xy && !guard_band) {
pvs->flags |= DO_CLIP_XY;
ASSIGN_4V( pvs->draw->plane[0], -1, 0, 0, 1 );
ASSIGN_4V( pvs->draw->plane[1], 1, 0, 0, 1 );
ASSIGN_4V( pvs->draw->plane[2], 0, -1, 0, 1 );
ASSIGN_4V( pvs->draw->plane[3], 0, 1, 0, 1 );
}
else if (clip_xy && guard_band) {
pvs->flags |= DO_CLIP_XY_GUARD_BAND;
ASSIGN_4V( pvs->draw->plane[0], -0.5, 0, 0, 1 );
ASSIGN_4V( pvs->draw->plane[1], 0.5, 0, 0, 1 );
ASSIGN_4V( pvs->draw->plane[2], 0, -0.5, 0, 1 );
ASSIGN_4V( pvs->draw->plane[3], 0, 0.5, 0, 1 );
}
 
if (clip_z) {
if (clip_halfz) {
pvs->flags |= DO_CLIP_HALF_Z;
ASSIGN_4V( pvs->draw->plane[4], 0, 0, 1, 0 );
} else {
pvs->flags |= DO_CLIP_FULL_Z;
ASSIGN_4V( pvs->draw->plane[4], 0, 0, 1, 1 );
}
}
 
if (clip_user)
pvs->flags |= DO_CLIP_USER;
 
if (!bypass_viewport)
pvs->flags |= DO_VIEWPORT;
 
if (need_edgeflags)
pvs->flags |= DO_EDGEFLAG;
 
/* Now select the relevant function:
*/
switch (pvs->flags) {
case 0:
pvs->run = do_cliptest_none;
break;
 
case DO_CLIP_XY | DO_CLIP_FULL_Z | DO_VIEWPORT:
pvs->run = do_cliptest_xy_fullz_viewport;
break;
 
case DO_CLIP_XY | DO_CLIP_HALF_Z | DO_VIEWPORT:
pvs->run = do_cliptest_xy_halfz_viewport;
break;
 
case DO_CLIP_XY_GUARD_BAND | DO_CLIP_HALF_Z | DO_VIEWPORT:
pvs->run = do_cliptest_xy_gb_halfz_viewport;
break;
 
case DO_CLIP_FULL_Z | DO_VIEWPORT:
pvs->run = do_cliptest_fullz_viewport;
break;
 
case DO_CLIP_HALF_Z | DO_VIEWPORT:
pvs->run = do_cliptest_halfz_viewport;
break;
 
case DO_CLIP_XY | DO_CLIP_FULL_Z | DO_CLIP_USER | DO_VIEWPORT:
pvs->run = do_cliptest_xy_fullz_user_viewport;
break;
 
case (DO_CLIP_XY | DO_CLIP_FULL_Z | DO_CLIP_USER |
DO_VIEWPORT | DO_EDGEFLAG):
pvs->run = do_cliptest_xy_fullz_user_viewport_edgeflag;
break;
default:
pvs->run = do_cliptest_generic;
break;
}
}
 
 
struct pt_post_vs *draw_pt_post_vs_create( struct draw_context *draw )
{
struct pt_post_vs *pvs = CALLOC_STRUCT( pt_post_vs );
if (!pvs)
return NULL;
 
pvs->draw = draw;
 
return pvs;
}
 
void draw_pt_post_vs_destroy( struct pt_post_vs *pvs )
{
FREE(pvs);
}
/drivers/video/Gallium/auxiliary/draw/draw_pt_so_emit.c
0,0 → 1,324
/**************************************************************************
*
* Copyright 2010 VMware, Inc.
* 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 VMWARE 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.
*
**************************************************************************/
 
#include "draw/draw_private.h"
#include "draw/draw_vs.h"
#include "draw/draw_gs.h"
#include "draw/draw_context.h"
#include "draw/draw_vbuf.h"
#include "draw/draw_vertex.h"
#include "draw/draw_pt.h"
 
#include "pipe/p_state.h"
 
#include "util/u_math.h"
#include "util/u_memory.h"
 
struct pt_so_emit {
struct draw_context *draw;
 
unsigned input_vertex_stride;
const float (*inputs)[4];
const float *pre_clip_pos;
boolean has_so;
boolean use_pre_clip_pos;
int pos_idx;
unsigned emitted_primitives;
unsigned emitted_vertices;
unsigned generated_primitives;
};
 
static const struct pipe_stream_output_info *
draw_so_info(const struct draw_context *draw)
{
const struct pipe_stream_output_info *state = NULL;
 
if (draw->gs.geometry_shader) {
state = &draw->gs.geometry_shader->state.stream_output;
} else {
state = &draw->vs.vertex_shader->state.stream_output;
}
 
return state;
}
 
static INLINE boolean
draw_has_so(const struct draw_context *draw)
{
const struct pipe_stream_output_info *state = draw_so_info(draw);
 
if (state && state->num_outputs > 0)
return TRUE;
 
return FALSE;
}
 
void draw_pt_so_emit_prepare(struct pt_so_emit *emit, boolean use_pre_clip_pos)
{
struct draw_context *draw = emit->draw;
 
emit->use_pre_clip_pos = use_pre_clip_pos;
emit->has_so = draw_has_so(draw);
if (use_pre_clip_pos)
emit->pos_idx = draw_current_shader_position_output(draw);
 
/* if we have a state with outputs make sure we have
* buffers to output to */
if (emit->has_so) {
boolean has_valid_buffer = FALSE;
unsigned i;
for (i = 0; i < draw->so.num_targets; ++i) {
if (draw->so.targets[i]) {
has_valid_buffer = TRUE;
break;
}
}
emit->has_so = has_valid_buffer;
}
 
if (!emit->has_so)
return;
 
/* XXX: need to flush to get prim_vbuf.c to release its allocation??
*/
draw_do_flush( draw, DRAW_FLUSH_BACKEND );
}
 
static void so_emit_prim(struct pt_so_emit *so,
unsigned *indices,
unsigned num_vertices)
{
unsigned slot, i;
unsigned input_vertex_stride = so->input_vertex_stride;
struct draw_context *draw = so->draw;
const float (*input_ptr)[4];
const float *pcp_ptr = NULL;
const struct pipe_stream_output_info *state = draw_so_info(draw);
float *buffer;
int buffer_total_bytes[PIPE_MAX_SO_BUFFERS];
boolean buffer_written[PIPE_MAX_SO_BUFFERS] = {0};
 
input_ptr = so->inputs;
if (so->use_pre_clip_pos)
pcp_ptr = so->pre_clip_pos;
 
++so->generated_primitives;
 
for (i = 0; i < draw->so.num_targets; i++) {
struct draw_so_target *target = draw->so.targets[i];
if (target) {
buffer_total_bytes[i] = target->internal_offset;
} else {
buffer_total_bytes[i] = 0;
}
}
 
/* check have we space to emit prim first - if not don't do anything */
for (i = 0; i < num_vertices; ++i) {
unsigned ob;
for (slot = 0; slot < state->num_outputs; ++slot) {
unsigned num_comps = state->output[slot].num_components;
int ob = state->output[slot].output_buffer;
unsigned dst_offset = state->output[slot].dst_offset * sizeof(float);
unsigned write_size = num_comps * sizeof(float);
/* If a buffer is missing then that's equivalent to
* an overflow */
if (!draw->so.targets[ob]) {
return;
}
if ((buffer_total_bytes[ob] + write_size + dst_offset) >
draw->so.targets[ob]->target.buffer_size) {
return;
}
}
for (ob = 0; ob < draw->so.num_targets; ++ob) {
buffer_total_bytes[ob] += state->stride[ob] * sizeof(float);
}
}
 
for (i = 0; i < num_vertices; ++i) {
const float (*input)[4];
const float *pre_clip_pos = NULL;
int ob;
 
input = (const float (*)[4])(
(const char *)input_ptr + (indices[i] * input_vertex_stride));
 
if (pcp_ptr)
pre_clip_pos = (const float *)(
(const char *)pcp_ptr + (indices[i] * input_vertex_stride));
 
for (slot = 0; slot < state->num_outputs; ++slot) {
unsigned idx = state->output[slot].register_index;
unsigned start_comp = state->output[slot].start_component;
unsigned num_comps = state->output[slot].num_components;
 
ob = state->output[slot].output_buffer;
buffer_written[ob] = TRUE;
 
buffer = (float *)((char *)draw->so.targets[ob]->mapping +
draw->so.targets[ob]->target.buffer_offset +
draw->so.targets[ob]->internal_offset) +
state->output[slot].dst_offset;
if (idx == so->pos_idx && pcp_ptr)
memcpy(buffer, &pre_clip_pos[start_comp],
num_comps * sizeof(float));
else
memcpy(buffer, &input[idx][start_comp],
num_comps * sizeof(float));
#if 0
{
int j;
debug_printf("VERT[%d], offset = %d, slot[%d] sc = %d, num_c = %d, idx = %d = [",
i + draw->so.targets[ob]->emitted_vertices,
draw->so.targets[ob]->internal_offset,
slot, start_comp, num_comps, idx);
for (j = 0; j < num_comps; ++j) {
unsigned *ubuffer = (unsigned*)buffer;
debug_printf("%d (0x%x), ", ubuffer[j], ubuffer[j]);
}
debug_printf("]\n");
}
#endif
}
for (ob = 0; ob < draw->so.num_targets; ++ob) {
struct draw_so_target *target = draw->so.targets[ob];
if (target && buffer_written[ob]) {
target->internal_offset += state->stride[ob] * sizeof(float);
target->emitted_vertices += 1;
}
}
}
so->emitted_vertices += num_vertices;
++so->emitted_primitives;
}
 
static void so_point(struct pt_so_emit *so, int idx)
{
unsigned indices[1];
 
indices[0] = idx;
 
so_emit_prim(so, indices, 1);
}
 
static void so_line(struct pt_so_emit *so, int i0, int i1)
{
unsigned indices[2];
 
indices[0] = i0;
indices[1] = i1;
 
so_emit_prim(so, indices, 2);
}
 
static void so_tri(struct pt_so_emit *so, int i0, int i1, int i2)
{
unsigned indices[3];
 
indices[0] = i0;
indices[1] = i1;
indices[2] = i2;
 
so_emit_prim(so, indices, 3);
}
 
 
#define FUNC so_run_linear
#define GET_ELT(idx) (start + (idx))
#include "draw_so_emit_tmp.h"
 
 
#define FUNC so_run_elts
#define LOCAL_VARS const ushort *elts = input_prims->elts;
#define GET_ELT(idx) (elts[start + (idx)])
#include "draw_so_emit_tmp.h"
 
 
void draw_pt_so_emit( struct pt_so_emit *emit,
const struct draw_vertex_info *input_verts,
const struct draw_prim_info *input_prims )
{
struct draw_context *draw = emit->draw;
struct vbuf_render *render = draw->render;
unsigned start, i;
 
if (!emit->has_so)
return;
 
if (!draw->so.num_targets)
return;
 
emit->emitted_vertices = 0;
emit->emitted_primitives = 0;
emit->generated_primitives = 0;
emit->input_vertex_stride = input_verts->stride;
if (emit->use_pre_clip_pos)
emit->pre_clip_pos = input_verts->verts->pre_clip_pos;
 
emit->inputs = (const float (*)[4])input_verts->verts->data;
 
/* XXX: need to flush to get prim_vbuf.c to release its allocation??*/
draw_do_flush( draw, DRAW_FLUSH_BACKEND );
 
for (start = i = 0; i < input_prims->primitive_count;
start += input_prims->primitive_lengths[i], i++)
{
unsigned count = input_prims->primitive_lengths[i];
 
if (input_prims->linear) {
so_run_linear(emit, input_prims, input_verts,
start, count);
} else {
so_run_elts(emit, input_prims, input_verts,
start, count);
}
}
 
render->set_stream_output_info(render,
emit->emitted_primitives,
emit->emitted_vertices,
emit->generated_primitives);
}
 
 
struct pt_so_emit *draw_pt_so_emit_create( struct draw_context *draw )
{
struct pt_so_emit *emit = CALLOC_STRUCT(pt_so_emit);
if (!emit)
return NULL;
 
emit->draw = draw;
 
return emit;
}
 
void draw_pt_so_emit_destroy( struct pt_so_emit *emit )
{
FREE(emit);
}
/drivers/video/Gallium/auxiliary/draw/draw_pt_util.c
0,0 → 1,101
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
#include "draw/draw_context.h"
#include "draw/draw_private.h"
#include "draw/draw_pt.h"
#include "util/u_debug.h"
 
void draw_pt_split_prim(unsigned prim, unsigned *first, unsigned *incr)
{
switch (prim) {
case PIPE_PRIM_POINTS:
*first = 1;
*incr = 1;
break;
case PIPE_PRIM_LINES:
*first = 2;
*incr = 2;
break;
case PIPE_PRIM_LINE_STRIP:
case PIPE_PRIM_LINE_LOOP:
*first = 2;
*incr = 1;
break;
case PIPE_PRIM_LINES_ADJACENCY:
*first = 4;
*incr = 4;
break;
case PIPE_PRIM_LINE_STRIP_ADJACENCY:
*first = 4;
*incr = 1;
break;
case PIPE_PRIM_TRIANGLES:
*first = 3;
*incr = 3;
break;
case PIPE_PRIM_TRIANGLES_ADJACENCY:
*first = 6;
*incr = 6;
break;
case PIPE_PRIM_TRIANGLE_STRIP:
case PIPE_PRIM_TRIANGLE_FAN:
case PIPE_PRIM_POLYGON:
*first = 3;
*incr = 1;
break;
case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
*first = 6;
*incr = 2;
break;
case PIPE_PRIM_QUADS:
*first = 4;
*incr = 4;
break;
case PIPE_PRIM_QUAD_STRIP:
*first = 4;
*incr = 2;
break;
default:
assert(0);
*first = 0;
*incr = 1; /* set to one so that count % incr works */
break;
}
}
 
unsigned draw_pt_trim_count(unsigned count, unsigned first, unsigned incr)
{
if (count < first)
return 0;
return count - (count - first) % incr;
}
/drivers/video/Gallium/auxiliary/draw/draw_pt_vsplit.c
0,0 → 1,304
/*
* Mesa 3-D graphics library
*
* Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* Copyright (C) 2010 LunarG Inc.
*
* 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, sublicense,
* 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
*/
 
#include "util/u_math.h"
#include "util/u_memory.h"
 
#include "draw/draw_context.h"
#include "draw/draw_private.h"
#include "draw/draw_pt.h"
 
#define SEGMENT_SIZE 1024
#define MAP_SIZE 256
 
/* The largest possible index withing an index buffer */
#define MAX_ELT_IDX 0xffffffff
 
struct vsplit_frontend {
struct draw_pt_front_end base;
struct draw_context *draw;
 
unsigned prim;
 
struct draw_pt_middle_end *middle;
 
unsigned max_vertices;
ushort segment_size;
 
/* buffers for splitting */
unsigned fetch_elts[SEGMENT_SIZE];
ushort draw_elts[SEGMENT_SIZE];
ushort identity_draw_elts[SEGMENT_SIZE];
 
struct {
/* map a fetch element to a draw element */
unsigned fetches[MAP_SIZE];
ushort draws[MAP_SIZE];
boolean has_max_fetch;
 
ushort num_fetch_elts;
ushort num_draw_elts;
} cache;
};
 
 
static void
vsplit_clear_cache(struct vsplit_frontend *vsplit)
{
memset(vsplit->cache.fetches, 0xff, sizeof(vsplit->cache.fetches));
vsplit->cache.has_max_fetch = FALSE;
vsplit->cache.num_fetch_elts = 0;
vsplit->cache.num_draw_elts = 0;
}
 
static void
vsplit_flush_cache(struct vsplit_frontend *vsplit, unsigned flags)
{
vsplit->middle->run(vsplit->middle,
vsplit->fetch_elts, vsplit->cache.num_fetch_elts,
vsplit->draw_elts, vsplit->cache.num_draw_elts, flags);
}
 
/**
* Add a fetch element and add it to the draw elements.
*/
static INLINE void
vsplit_add_cache(struct vsplit_frontend *vsplit, unsigned fetch, unsigned ofbias)
{
unsigned hash;
 
hash = fetch % MAP_SIZE;
 
/* If the value isn't in the cache of it's an overflow due to the
* element bias */
if (vsplit->cache.fetches[hash] != fetch || ofbias) {
/* update cache */
vsplit->cache.fetches[hash] = fetch;
vsplit->cache.draws[hash] = vsplit->cache.num_fetch_elts;
 
/* add fetch */
assert(vsplit->cache.num_fetch_elts < vsplit->segment_size);
vsplit->fetch_elts[vsplit->cache.num_fetch_elts++] = fetch;
}
 
vsplit->draw_elts[vsplit->cache.num_draw_elts++] = vsplit->cache.draws[hash];
}
 
/**
* Returns the base index to the elements array.
* The value is checked for overflows (both integer overflows
* and the elements array overflow).
*/
static INLINE unsigned
vsplit_get_base_idx(struct vsplit_frontend *vsplit,
unsigned start, unsigned fetch, unsigned *ofbit)
{
struct draw_context *draw = vsplit->draw;
unsigned elt_idx = draw_overflow_uadd(start, fetch, MAX_ELT_IDX);
if (ofbit)
*ofbit = 0;
 
/* Overflown indices need to wrap to the first element
* in the index buffer */
if (elt_idx >= draw->pt.user.eltMax) {
if (ofbit)
*ofbit = 1;
elt_idx = 0;
}
 
return elt_idx;
}
 
/**
* Returns the element index adjust for the element bias.
* The final element index is created from the actual element
* index, plus the element bias, clamped to maximum elememt
* index if that addition overflows.
*/
static INLINE unsigned
vsplit_get_bias_idx(struct vsplit_frontend *vsplit,
int idx, int bias, unsigned *ofbias)
{
int res = idx + bias;
 
if (ofbias)
*ofbias = 0;
 
if (idx > 0 && bias > 0) {
if (res < idx || res < bias) {
res = DRAW_MAX_FETCH_IDX;
if (ofbias)
*ofbias = 1;
}
} else if (idx < 0 && bias < 0) {
if (res > idx || res > bias) {
res = DRAW_MAX_FETCH_IDX;
if (ofbias)
*ofbias = 1;
}
}
 
return res;
}
 
#define VSPLIT_CREATE_IDX(elts, start, fetch, elt_bias) \
unsigned elt_idx; \
unsigned ofbit; \
unsigned ofbias; \
elt_idx = vsplit_get_base_idx(vsplit, start, fetch, &ofbit); \
elt_idx = vsplit_get_bias_idx(vsplit, ofbit ? 0 : DRAW_GET_IDX(elts, elt_idx), elt_bias, &ofbias)
 
static INLINE void
vsplit_add_cache_ubyte(struct vsplit_frontend *vsplit, const ubyte *elts,
unsigned start, unsigned fetch, int elt_bias)
{
struct draw_context *draw = vsplit->draw;
VSPLIT_CREATE_IDX(elts, start, fetch, elt_bias);
vsplit_add_cache(vsplit, elt_idx, ofbias);
}
 
static INLINE void
vsplit_add_cache_ushort(struct vsplit_frontend *vsplit, const ushort *elts,
unsigned start, unsigned fetch, int elt_bias)
{
struct draw_context *draw = vsplit->draw;
VSPLIT_CREATE_IDX(elts, start, fetch, elt_bias);
vsplit_add_cache(vsplit, elt_idx, ofbias);
}
 
 
/**
* Add a fetch element and add it to the draw elements. The fetch element is
* in full range (uint).
*/
static INLINE void
vsplit_add_cache_uint(struct vsplit_frontend *vsplit, const uint *elts,
unsigned start, unsigned fetch, int elt_bias)
{
struct draw_context *draw = vsplit->draw;
unsigned raw_elem_idx = start + fetch + elt_bias;
VSPLIT_CREATE_IDX(elts, start, fetch, elt_bias);
 
/* special care for DRAW_MAX_FETCH_IDX */
if (raw_elem_idx == DRAW_MAX_FETCH_IDX && !vsplit->cache.has_max_fetch) {
unsigned hash = fetch % MAP_SIZE;
vsplit->cache.fetches[hash] = raw_elem_idx - 1; /* force update */
vsplit->cache.has_max_fetch = TRUE;
}
 
vsplit_add_cache(vsplit, elt_idx, ofbias);
}
 
 
#define FUNC vsplit_run_linear
#include "draw_pt_vsplit_tmp.h"
 
#define FUNC vsplit_run_ubyte
#define ELT_TYPE ubyte
#define ADD_CACHE(vsplit, ib, start, fetch, bias) vsplit_add_cache_ubyte(vsplit,ib,start,fetch,bias)
#include "draw_pt_vsplit_tmp.h"
 
#define FUNC vsplit_run_ushort
#define ELT_TYPE ushort
#define ADD_CACHE(vsplit, ib, start, fetch, bias) vsplit_add_cache_ushort(vsplit,ib,start,fetch, bias)
#include "draw_pt_vsplit_tmp.h"
 
#define FUNC vsplit_run_uint
#define ELT_TYPE uint
#define ADD_CACHE(vsplit, ib, start, fetch, bias) vsplit_add_cache_uint(vsplit, ib, start, fetch, bias)
#include "draw_pt_vsplit_tmp.h"
 
 
static void vsplit_prepare(struct draw_pt_front_end *frontend,
unsigned in_prim,
struct draw_pt_middle_end *middle,
unsigned opt)
{
struct vsplit_frontend *vsplit = (struct vsplit_frontend *) frontend;
 
switch (vsplit->draw->pt.user.eltSize) {
case 0:
vsplit->base.run = vsplit_run_linear;
break;
case 1:
vsplit->base.run = vsplit_run_ubyte;
break;
case 2:
vsplit->base.run = vsplit_run_ushort;
break;
case 4:
vsplit->base.run = vsplit_run_uint;
break;
default:
assert(0);
break;
}
 
/* split only */
vsplit->prim = in_prim;
 
vsplit->middle = middle;
middle->prepare(middle, vsplit->prim, opt, &vsplit->max_vertices);
 
vsplit->segment_size = MIN2(SEGMENT_SIZE, vsplit->max_vertices);
}
 
 
static void vsplit_flush(struct draw_pt_front_end *frontend, unsigned flags)
{
struct vsplit_frontend *vsplit = (struct vsplit_frontend *) frontend;
 
if (flags & DRAW_FLUSH_STATE_CHANGE) {
vsplit->middle->finish(vsplit->middle);
vsplit->middle = NULL;
}
}
 
 
static void vsplit_destroy(struct draw_pt_front_end *frontend)
{
FREE(frontend);
}
 
 
struct draw_pt_front_end *draw_pt_vsplit(struct draw_context *draw)
{
struct vsplit_frontend *vsplit = CALLOC_STRUCT(vsplit_frontend);
ushort i;
 
if (!vsplit)
return NULL;
 
vsplit->base.prepare = vsplit_prepare;
vsplit->base.run = NULL;
vsplit->base.flush = vsplit_flush;
vsplit->base.destroy = vsplit_destroy;
vsplit->draw = draw;
 
for (i = 0; i < SEGMENT_SIZE; i++)
vsplit->identity_draw_elts[i] = i;
 
return &vsplit->base;
}
/drivers/video/Gallium/auxiliary/draw/draw_pt_vsplit_tmp.h
0,0 → 1,321
/*
* Mesa 3-D graphics library
*
* Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* Copyright (C) 2010 LunarG Inc.
*
* 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, sublicense,
* 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
*/
 
#define CONCAT2(name, elt_type) name ## elt_type
#define CONCAT(name, elt_type) CONCAT2(name, elt_type)
 
#ifdef ELT_TYPE
 
/**
* Fetch all elements in [min_index, max_index] with bias, and use the
* (rebased) index buffer as the draw elements.
*/
static boolean
CONCAT(vsplit_primitive_, ELT_TYPE)(struct vsplit_frontend *vsplit,
unsigned istart, unsigned icount)
{
struct draw_context *draw = vsplit->draw;
const ELT_TYPE *ib = (const ELT_TYPE *) draw->pt.user.elts;
const unsigned min_index = draw->pt.user.min_index;
const unsigned max_index = draw->pt.user.max_index;
const int elt_bias = draw->pt.user.eltBias;
unsigned fetch_start, fetch_count;
const ushort *draw_elts = NULL;
unsigned i;
const unsigned start = istart;
const unsigned end = istart + icount;
 
/* If the index buffer overflows we'll need to run
* through the normal paths */
if (start >= draw->pt.user.eltMax ||
end > draw->pt.user.eltMax ||
end < istart || end < icount)
return FALSE;
 
/* use the ib directly */
if (min_index == 0 && sizeof(ib[0]) == sizeof(draw_elts[0])) {
if (icount > vsplit->max_vertices)
return FALSE;
 
for (i = 0; i < icount; i++) {
ELT_TYPE idx = DRAW_GET_IDX(ib, start + i);
if (idx < min_index || idx > max_index) {
debug_printf("warning: index out of range\n");
}
}
draw_elts = (const ushort *) (ib + istart);
}
else {
/* have to go through vsplit->draw_elts */
if (icount > vsplit->segment_size)
return FALSE;
}
 
/* this is faster only when we fetch less elements than the normal path */
if (max_index - min_index > icount - 1)
return FALSE;
 
if (elt_bias < 0 && (int) min_index < -elt_bias)
return FALSE;
 
/* why this check? */
for (i = 0; i < draw->pt.nr_vertex_elements; i++) {
if (draw->pt.vertex_element[i].instance_divisor)
return FALSE;
}
 
fetch_start = min_index + elt_bias;
fetch_count = max_index - min_index + 1;
 
/* Check for overflow in the fetch_start */
if (fetch_start < min_index || fetch_start < elt_bias)
return FALSE;
 
if (!draw_elts) {
if (min_index == 0) {
for (i = 0; i < icount; i++) {
ELT_TYPE idx = DRAW_GET_IDX(ib, i + start);
 
if (idx < min_index || idx > max_index) {
debug_printf("warning: index out of range\n");
}
vsplit->draw_elts[i] = (ushort) idx;
}
}
else {
for (i = 0; i < icount; i++) {
ELT_TYPE idx = DRAW_GET_IDX(ib, i + start);
 
if (idx < min_index || idx > max_index) {
debug_printf("warning: index out of range\n");
}
vsplit->draw_elts[i] = (ushort) (idx - min_index);
}
}
 
draw_elts = vsplit->draw_elts;
}
 
return vsplit->middle->run_linear_elts(vsplit->middle,
fetch_start, fetch_count,
draw_elts, icount, 0x0);
}
 
/**
* Use the cache to prepare the fetch and draw elements, and flush.
*
* When spoken is TRUE, ispoken replaces istart; When close is TRUE, iclose is
* appended.
*/
static INLINE void
CONCAT(vsplit_segment_cache_, ELT_TYPE)(struct vsplit_frontend *vsplit,
unsigned flags,
unsigned istart, unsigned icount,
boolean spoken, unsigned ispoken,
boolean close, unsigned iclose)
{
struct draw_context *draw = vsplit->draw;
const ELT_TYPE *ib = (const ELT_TYPE *) draw->pt.user.elts;
const int ibias = draw->pt.user.eltBias;
unsigned i;
 
assert(icount + !!close <= vsplit->segment_size);
 
vsplit_clear_cache(vsplit);
 
spoken = !!spoken;
if (ibias == 0) {
if (spoken)
ADD_CACHE(vsplit, ib, 0, ispoken, 0);
 
for (i = spoken; i < icount; i++) {
ADD_CACHE(vsplit, ib, istart, i, 0);
}
 
if (close)
ADD_CACHE(vsplit, ib, 0, iclose, 0);
}
else if (ibias > 0) {
if (spoken)
ADD_CACHE(vsplit, ib, 0, ispoken, ibias);
 
for (i = spoken; i < icount; i++)
ADD_CACHE(vsplit, ib, istart, i, ibias);
 
if (close)
ADD_CACHE(vsplit, ib, 0, iclose, ibias);
}
else {
if (spoken) {
ADD_CACHE(vsplit, ib, 0, ispoken, ibias);
}
 
for (i = spoken; i < icount; i++) {
ADD_CACHE(vsplit, ib, istart, i, ibias);
}
 
if (close) {
ADD_CACHE(vsplit, ib, 0, iclose, ibias);
}
}
 
vsplit_flush_cache(vsplit, flags);
}
 
static void
CONCAT(vsplit_segment_simple_, ELT_TYPE)(struct vsplit_frontend *vsplit,
unsigned flags,
unsigned istart,
unsigned icount)
{
CONCAT(vsplit_segment_cache_, ELT_TYPE)(vsplit,
flags, istart, icount, FALSE, 0, FALSE, 0);
}
 
static void
CONCAT(vsplit_segment_loop_, ELT_TYPE)(struct vsplit_frontend *vsplit,
unsigned flags,
unsigned istart,
unsigned icount,
unsigned i0)
{
const boolean close_loop = ((flags) == DRAW_SPLIT_BEFORE);
 
CONCAT(vsplit_segment_cache_, ELT_TYPE)(vsplit,
flags, istart, icount, FALSE, 0, close_loop, i0);
}
 
static void
CONCAT(vsplit_segment_fan_, ELT_TYPE)(struct vsplit_frontend *vsplit,
unsigned flags,
unsigned istart,
unsigned icount,
unsigned i0)
{
const boolean use_spoken = (((flags) & DRAW_SPLIT_BEFORE) != 0);
 
CONCAT(vsplit_segment_cache_, ELT_TYPE)(vsplit,
flags, istart, icount, use_spoken, i0, FALSE, 0);
}
 
#define LOCAL_VARS \
struct vsplit_frontend *vsplit = (struct vsplit_frontend *) frontend; \
const unsigned prim = vsplit->prim; \
const unsigned max_count_simple = vsplit->segment_size; \
const unsigned max_count_loop = vsplit->segment_size - 1; \
const unsigned max_count_fan = vsplit->segment_size;
 
#define PRIMITIVE(istart, icount) \
CONCAT(vsplit_primitive_, ELT_TYPE)(vsplit, istart, icount)
 
#else /* ELT_TYPE */
 
static void
vsplit_segment_simple_linear(struct vsplit_frontend *vsplit, unsigned flags,
unsigned istart, unsigned icount)
{
assert(icount <= vsplit->max_vertices);
vsplit->middle->run_linear(vsplit->middle, istart, icount, flags);
}
 
static void
vsplit_segment_loop_linear(struct vsplit_frontend *vsplit, unsigned flags,
unsigned istart, unsigned icount, unsigned i0)
{
boolean close_loop = (flags == DRAW_SPLIT_BEFORE);
unsigned nr;
 
assert(icount + !!close_loop <= vsplit->segment_size);
 
if (close_loop) {
for (nr = 0; nr < icount; nr++)
vsplit->fetch_elts[nr] = istart + nr;
vsplit->fetch_elts[nr++] = i0;
 
vsplit->middle->run(vsplit->middle, vsplit->fetch_elts, nr,
vsplit->identity_draw_elts, nr, flags);
}
else {
vsplit->middle->run_linear(vsplit->middle, istart, icount, flags);
}
}
 
static void
vsplit_segment_fan_linear(struct vsplit_frontend *vsplit, unsigned flags,
unsigned istart, unsigned icount, unsigned i0)
{
boolean use_spoken = ((flags & DRAW_SPLIT_BEFORE) != 0);
unsigned nr = 0, i;
 
assert(icount <= vsplit->segment_size);
 
if (use_spoken) {
/* replace istart by i0 */
vsplit->fetch_elts[nr++] = i0;
for (i = 1 ; i < icount; i++)
vsplit->fetch_elts[nr++] = istart + i;
 
vsplit->middle->run(vsplit->middle, vsplit->fetch_elts, nr,
vsplit->identity_draw_elts, nr, flags);
}
else {
vsplit->middle->run_linear(vsplit->middle, istart, icount, flags);
}
}
 
#define LOCAL_VARS \
struct vsplit_frontend *vsplit = (struct vsplit_frontend *) frontend; \
const unsigned prim = vsplit->prim; \
const unsigned max_count_simple = vsplit->max_vertices; \
const unsigned max_count_loop = vsplit->segment_size - 1; \
const unsigned max_count_fan = vsplit->segment_size;
 
#define PRIMITIVE(istart, icount) FALSE
 
#define ELT_TYPE linear
 
#endif /* ELT_TYPE */
 
#define FUNC_VARS \
struct draw_pt_front_end *frontend, \
unsigned start, \
unsigned count
 
#define SEGMENT_SIMPLE(flags, istart, icount) \
CONCAT(vsplit_segment_simple_, ELT_TYPE)(vsplit, flags, istart, icount)
 
#define SEGMENT_LOOP(flags, istart, icount, i0) \
CONCAT(vsplit_segment_loop_, ELT_TYPE)(vsplit, flags, istart, icount, i0)
 
#define SEGMENT_FAN(flags, istart, icount, i0) \
CONCAT(vsplit_segment_fan_, ELT_TYPE)(vsplit, flags, istart, icount, i0)
 
#include "draw_split_tmp.h"
 
#undef CONCAT2
#undef CONCAT
 
#undef ELT_TYPE
#undef ADD_CACHE
/drivers/video/Gallium/auxiliary/draw/draw_so_emit_tmp.h
0,0 → 1,31
#define FUNC_VARS \
struct pt_so_emit *so, \
const struct draw_prim_info *input_prims, \
const struct draw_vertex_info *input_verts, \
unsigned start, \
unsigned count
 
#define FUNC_ENTER \
/* declare more local vars */ \
const unsigned prim = input_prims->prim; \
const unsigned prim_flags = input_prims->flags; \
const boolean quads_flatshade_last = FALSE; \
const boolean last_vertex_last = !so->draw->rasterizer->flatshade_first; \
do { \
switch (prim) { \
case PIPE_PRIM_LINES_ADJACENCY: \
case PIPE_PRIM_LINE_STRIP_ADJACENCY: \
case PIPE_PRIM_TRIANGLES_ADJACENCY: \
case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY: \
debug_assert(!"unexpected primitive type in stream output"); \
return; \
default: \
break; \
} \
} while (0) \
 
#define POINT(i0) so_point(so,i0)
#define LINE(flags,i0,i1) so_line(so,i0,i1)
#define TRIANGLE(flags,i0,i1,i2) so_tri(so,i0,i1,i2)
 
#include "draw_decompose_tmp.h"
/drivers/video/Gallium/auxiliary/draw/draw_split_tmp.h
0,0 → 1,175
/*
* Mesa 3-D graphics library
*
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* Copyright (C) 2010 LunarG Inc.
*
* 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, sublicense,
* 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
*/
 
static void
FUNC(FUNC_VARS)
{
unsigned first, incr;
LOCAL_VARS
 
/*
* prim, start, count, and max_count_{simple,loop,fan} should have been
* defined
*/
if (0) {
debug_printf("%s: prim 0x%x, start %d, count %d, max_count_simple %d, "
"max_count_loop %d, max_count_fan %d\n",
__FUNCTION__, prim, start, count, max_count_simple,
max_count_loop, max_count_fan);
}
 
draw_pt_split_prim(prim, &first, &incr);
/* sanitize primitive length */
count = draw_pt_trim_count(count, first, incr);
if (count < first)
return;
 
/* try flushing the entire primitive */
if (PRIMITIVE(start, count))
return;
 
/* must be able to at least flush two complete primitives */
assert(max_count_simple >= first + incr &&
max_count_loop >= first + incr &&
max_count_fan >= first + incr);
 
/* no splitting required */
if (count <= max_count_simple) {
SEGMENT_SIMPLE(0x0, start, count);
}
else {
const unsigned rollback = first - incr;
unsigned flags = DRAW_SPLIT_AFTER, seg_start = 0, seg_max;
 
/*
* Both count and seg_max below are explicitly trimmed. Because
*
* seg_start = N * (seg_max - rollback) = N' * incr,
*
* we have
*
* remaining = count - seg_start = first + N'' * incr.
*
* That is, remaining is implicitly trimmed.
*/
switch (prim) {
case PIPE_PRIM_POINTS:
case PIPE_PRIM_LINES:
case PIPE_PRIM_LINE_STRIP:
case PIPE_PRIM_TRIANGLES:
case PIPE_PRIM_TRIANGLE_STRIP:
case PIPE_PRIM_QUADS:
case PIPE_PRIM_QUAD_STRIP:
case PIPE_PRIM_LINES_ADJACENCY:
case PIPE_PRIM_LINE_STRIP_ADJACENCY:
case PIPE_PRIM_TRIANGLES_ADJACENCY:
case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
seg_max =
draw_pt_trim_count(MIN2(max_count_simple, count), first, incr);
if (prim == PIPE_PRIM_TRIANGLE_STRIP ||
prim == PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY) {
/* make sure we flush even number of triangles at a time */
if (seg_max < count && !(((seg_max - first) / incr) & 1))
seg_max -= incr;
}
 
do {
const unsigned remaining = count - seg_start;
 
if (remaining > seg_max) {
SEGMENT_SIMPLE(flags, start + seg_start, seg_max);
seg_start += seg_max - rollback;
 
flags |= DRAW_SPLIT_BEFORE;
}
else {
flags &= ~DRAW_SPLIT_AFTER;
 
SEGMENT_SIMPLE(flags, start + seg_start, remaining);
seg_start += remaining;
}
} while (seg_start < count);
break;
 
case PIPE_PRIM_LINE_LOOP:
seg_max =
draw_pt_trim_count(MIN2(max_count_loop, count), first, incr);
 
do {
const unsigned remaining = count - seg_start;
 
if (remaining > seg_max) {
SEGMENT_LOOP(flags, start + seg_start, seg_max, start);
seg_start += seg_max - rollback;
 
flags |= DRAW_SPLIT_BEFORE;
}
else {
flags &= ~DRAW_SPLIT_AFTER;
 
SEGMENT_LOOP(flags, start + seg_start, remaining, start);
seg_start += remaining;
}
} while (seg_start < count);
break;
 
case PIPE_PRIM_TRIANGLE_FAN:
case PIPE_PRIM_POLYGON:
seg_max =
draw_pt_trim_count(MIN2(max_count_fan, count), first, incr);
 
do {
const unsigned remaining = count - seg_start;
 
if (remaining > seg_max) {
SEGMENT_FAN(flags, start + seg_start, seg_max, start);
seg_start += seg_max - rollback;
 
flags |= DRAW_SPLIT_BEFORE;
}
else {
flags &= ~DRAW_SPLIT_AFTER;
 
SEGMENT_FAN(flags, start + seg_start, remaining, start);
seg_start += remaining;
}
} while (seg_start < count);
break;
 
default:
assert(0);
break;
}
}
}
 
#undef FUNC
#undef FUNC_VARS
#undef LOCAL_VARS
 
#undef PRIMITIVE
#undef SEGMENT_SIMPLE
#undef SEGMENT_LOOP
#undef SEGMENT_FAN
/drivers/video/Gallium/auxiliary/draw/draw_vbuf.h
0,0 → 1,146
/**************************************************************************
*
* Copyright 2007 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
* Vertex buffer drawing stage.
*
* \author Keith Whitwell <keith@tungstengraphics.com>
* \author Jose Fonseca <jrfonsec@tungstengraphics.com>
*/
 
#ifndef DRAW_VBUF_H_
#define DRAW_VBUF_H_
 
 
#include "pipe/p_compiler.h"
 
 
struct pipe_rasterizer_state;
struct draw_context;
struct vertex_info;
struct pipe_query_data_pipeline_statistics;
 
 
/**
* Interface for hardware vertex buffer rendering.
*/
struct vbuf_render {
 
/**
* Driver limits. May be tuned lower to improve cache hits on
* index list.
*/
unsigned max_indices;
unsigned max_vertex_buffer_bytes;
 
/**
* Query if the hardware driver needs assistance for a particular
* combination of rasterizer state and primitive.
*
* Currently optional.
*/
boolean (*need_pipeline)(const struct vbuf_render *render,
const struct pipe_rasterizer_state *rasterizer,
unsigned int prim );
 
 
/**
* Get the hardware vertex format.
*
* XXX: have this in draw_context instead?
*/
const struct vertex_info *(*get_vertex_info)( struct vbuf_render * );
/**
* Request a destination for vertices.
* Hardware renderers will use ttm memory, others will just malloc
* something.
*/
boolean (*allocate_vertices)( struct vbuf_render *,
ushort vertex_size,
ushort nr_vertices );
void *(*map_vertices)( struct vbuf_render * );
void (*unmap_vertices)( struct vbuf_render *,
ushort min_index,
ushort max_index );
 
/**
* Notify the renderer of the current primitive when it changes.
* Must succeed for TRIANGLES, LINES and POINTS. Other prims at
* the discretion of the driver, for the benefit of the passthrough
* path.
*/
void (*set_primitive)( struct vbuf_render *, unsigned prim );
 
/**
* Draw indexed primitives. Note that indices are ushort. The driver
* must complete this call, if necessary splitting the index list itself.
*/
void (*draw_elements)( struct vbuf_render *,
const ushort *indices,
uint nr_indices );
 
/* Draw non-indexed primitives.
*/
void (*draw_arrays)( struct vbuf_render *,
unsigned start,
uint nr );
 
/**
* Called when vbuf is done with this set of vertices:
*/
void (*release_vertices)( struct vbuf_render * );
 
void (*destroy)( struct vbuf_render * );
 
 
/**
* Called after writing data to the stream out buffers
*/
void (*set_stream_output_info)( struct vbuf_render *vbufr,
unsigned primitive_count,
unsigned vertices_count,
unsigned primitive_generated );
 
/**
* Called after all relevant statistics have been accumulated.
*/
void (*pipeline_statistics)(
struct vbuf_render *vbufr,
const struct pipe_query_data_pipeline_statistics *stats );
};
 
 
 
struct draw_stage *
draw_vbuf_stage( struct draw_context *draw,
struct vbuf_render *render );
 
 
#endif /*DRAW_VBUF_H_*/
/drivers/video/Gallium/auxiliary/draw/draw_vertex.c
0,0 → 1,117
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/*
* Functions for specifying the post-transformation vertex layout.
*
* Author:
* Brian Paul
* Keith Whitwell
*/
 
 
#include "draw/draw_private.h"
#include "draw/draw_vertex.h"
 
 
/**
* Compute the size of a vertex, in dwords/floats, to update the
* vinfo->size field.
*/
void
draw_compute_vertex_size(struct vertex_info *vinfo)
{
uint i;
 
vinfo->size = 0;
for (i = 0; i < vinfo->num_attribs; i++)
vinfo->size += draw_translate_vinfo_size(vinfo->attrib[i].emit);
 
assert(vinfo->size % 4 == 0);
/* in dwords */
vinfo->size /= 4;
}
 
 
void
draw_dump_emitted_vertex(const struct vertex_info *vinfo, const uint8_t *data)
{
unsigned i;
 
for (i = 0; i < vinfo->num_attribs; i++) {
switch (vinfo->attrib[i].emit) {
case EMIT_OMIT:
debug_printf("EMIT_OMIT:");
break;
case EMIT_1F:
debug_printf("EMIT_1F:\t");
debug_printf("%f ", *(float *)data); data += sizeof(float);
break;
case EMIT_1F_PSIZE:
debug_printf("EMIT_1F_PSIZE:\t");
debug_printf("%f ", *(float *)data); data += sizeof(float);
break;
case EMIT_2F:
debug_printf("EMIT_2F:\t");
debug_printf("%f ", *(float *)data); data += sizeof(float);
debug_printf("%f ", *(float *)data); data += sizeof(float);
break;
case EMIT_3F:
debug_printf("EMIT_3F:\t");
debug_printf("%f ", *(float *)data); data += sizeof(float);
debug_printf("%f ", *(float *)data); data += sizeof(float);
debug_printf("%f ", *(float *)data); data += sizeof(float);
data += sizeof(float);
break;
case EMIT_4F:
debug_printf("EMIT_4F:\t");
debug_printf("%f ", *(float *)data); data += sizeof(float);
debug_printf("%f ", *(float *)data); data += sizeof(float);
debug_printf("%f ", *(float *)data); data += sizeof(float);
debug_printf("%f ", *(float *)data); data += sizeof(float);
break;
case EMIT_4UB:
debug_printf("EMIT_4UB:\t");
debug_printf("%u ", *data++);
debug_printf("%u ", *data++);
debug_printf("%u ", *data++);
debug_printf("%u ", *data++);
break;
case EMIT_4UB_BGRA:
debug_printf("EMIT_4UB_BGRA:\t");
debug_printf("%u ", *data++);
debug_printf("%u ", *data++);
debug_printf("%u ", *data++);
debug_printf("%u ", *data++);
break;
default:
assert(0);
}
debug_printf("\n");
}
debug_printf("\n");
}
/drivers/video/Gallium/auxiliary/draw/draw_vertex.h
0,0 → 1,201
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/**
* Post-transform vertex format info. The vertex_info struct is used by
* the draw_vbuf code to emit hardware-specific vertex layouts into hw
* vertex buffers.
*
* Author:
* Brian Paul
*/
 
 
#ifndef DRAW_VERTEX_H
#define DRAW_VERTEX_H
 
 
#include "pipe/p_compiler.h"
#include "pipe/p_state.h"
#include "util/u_debug.h"
#include "util/u_memory.h"
 
 
/**
* Vertex attribute emit modes
*/
enum attrib_emit {
EMIT_OMIT, /**< don't emit the attribute */
EMIT_1F,
EMIT_1F_PSIZE, /**< insert constant point size */
EMIT_2F,
EMIT_3F,
EMIT_4F,
EMIT_4UB, /**< is RGBA like the rest */
EMIT_4UB_BGRA
};
 
 
/**
* Attribute interpolation mode
*/
enum interp_mode {
INTERP_NONE, /**< never interpolate vertex header info */
INTERP_POS, /**< special case for frag position */
INTERP_CONSTANT,
INTERP_LINEAR,
INTERP_PERSPECTIVE
};
 
 
/**
* Information about hardware/rasterization vertex layout.
*/
struct vertex_info
{
uint num_attribs;
uint hwfmt[4]; /**< hardware format info for this format */
uint size; /**< total vertex size in dwords */
/* Keep this small and at the end of the struct to allow quick
* memcmp() comparisons.
*/
struct {
unsigned interp_mode:4; /**< INTERP_x */
unsigned emit:4; /**< EMIT_x */
unsigned src_index:8; /**< map to post-xform attribs */
} attrib[PIPE_MAX_SHADER_OUTPUTS];
};
 
static INLINE size_t
draw_vinfo_size( const struct vertex_info *a )
{
return offsetof(const struct vertex_info, attrib[a->num_attribs]);
}
 
static INLINE int
draw_vinfo_compare( const struct vertex_info *a,
const struct vertex_info *b )
{
size_t sizea = draw_vinfo_size( a );
return memcmp( a, b, sizea );
}
 
static INLINE void
draw_vinfo_copy( struct vertex_info *dst,
const struct vertex_info *src )
{
size_t size = draw_vinfo_size( src );
memcpy( dst, src, size );
}
 
 
 
/**
* Add another attribute to the given vertex_info object.
* \param src_index indicates which post-transformed vertex attrib slot
* corresponds to this attribute.
* \return slot in which the attribute was added
*/
static INLINE uint
draw_emit_vertex_attr(struct vertex_info *vinfo,
enum attrib_emit emit,
enum interp_mode interp, /* only used by softpipe??? */
int src_index)
{
const uint n = vinfo->num_attribs;
 
/* If the src_index is negative, meaning it hasn't been found
* lets just redirect it to the first output slot */
if (src_index < 0) {
src_index = 0;
}
 
assert(n < Elements(vinfo->attrib));
vinfo->attrib[n].emit = emit;
vinfo->attrib[n].interp_mode = interp;
vinfo->attrib[n].src_index = src_index;
vinfo->num_attribs++;
return n;
}
 
 
extern void draw_compute_vertex_size(struct vertex_info *vinfo);
 
void draw_dump_emitted_vertex(const struct vertex_info *vinfo,
const uint8_t *data);
 
 
static INLINE enum pipe_format draw_translate_vinfo_format(enum attrib_emit emit)
{
switch (emit) {
case EMIT_OMIT:
return PIPE_FORMAT_NONE;
case EMIT_1F:
case EMIT_1F_PSIZE:
return PIPE_FORMAT_R32_FLOAT;
case EMIT_2F:
return PIPE_FORMAT_R32G32_FLOAT;
case EMIT_3F:
return PIPE_FORMAT_R32G32B32_FLOAT;
case EMIT_4F:
return PIPE_FORMAT_R32G32B32A32_FLOAT;
case EMIT_4UB:
return PIPE_FORMAT_R8G8B8A8_UNORM;
case EMIT_4UB_BGRA:
return PIPE_FORMAT_B8G8R8A8_UNORM;
default:
assert(!"unexpected format");
return PIPE_FORMAT_NONE;
}
}
 
static INLINE unsigned draw_translate_vinfo_size(enum attrib_emit emit)
{
switch (emit) {
case EMIT_OMIT:
return 0;
case EMIT_1F:
case EMIT_1F_PSIZE:
return 1 * sizeof(float);
case EMIT_2F:
return 2 * sizeof(float);
case EMIT_3F:
return 3 * sizeof(float);
case EMIT_4F:
return 4 * sizeof(float);
case EMIT_4UB:
return 4 * sizeof(unsigned char);
case EMIT_4UB_BGRA:
return 4 * sizeof(unsigned char);
default:
assert(!"unexpected format");
return 0;
}
}
 
#endif /* DRAW_VERTEX_H */
/drivers/video/Gallium/auxiliary/draw/draw_vs.c
0,0 → 1,256
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
* Brian Paul
*/
 
#include "util/u_math.h"
#include "util/u_memory.h"
 
#include "pipe/p_shader_tokens.h"
 
#include "draw_private.h"
#include "draw_context.h"
#include "draw_vs.h"
 
#include "translate/translate.h"
#include "translate/translate_cache.h"
 
#include "tgsi/tgsi_dump.h"
#include "tgsi/tgsi_exec.h"
 
DEBUG_GET_ONCE_BOOL_OPTION(gallium_dump_vs, "GALLIUM_DUMP_VS", FALSE)
 
 
struct draw_vertex_shader *
draw_create_vertex_shader(struct draw_context *draw,
const struct pipe_shader_state *shader)
{
struct draw_vertex_shader *vs = NULL;
 
if (draw->dump_vs) {
tgsi_dump(shader->tokens, 0);
}
 
#if HAVE_LLVM
if (draw->pt.middle.llvm) {
vs = draw_create_vs_llvm(draw, shader);
}
#endif
 
if (!vs) {
vs = draw_create_vs_exec( draw, shader );
}
 
if (vs)
{
uint i;
bool found_clipvertex = FALSE;
vs->position_output = -1;
for (i = 0; i < vs->info.num_outputs; i++) {
if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_POSITION &&
vs->info.output_semantic_index[i] == 0)
vs->position_output = i;
else if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_EDGEFLAG &&
vs->info.output_semantic_index[i] == 0)
vs->edgeflag_output = i;
else if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_CLIPVERTEX &&
vs->info.output_semantic_index[i] == 0) {
found_clipvertex = TRUE;
vs->clipvertex_output = i;
} else if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_CLIPDIST) {
debug_assert(vs->info.output_semantic_index[i] <
PIPE_MAX_CLIP_OR_CULL_DISTANCE_ELEMENT_COUNT);
vs->clipdistance_output[vs->info.output_semantic_index[i]] = i;
} else if (vs->info.output_semantic_name[i] == TGSI_SEMANTIC_CULLDIST) {
debug_assert(vs->info.output_semantic_index[i] <
PIPE_MAX_CLIP_OR_CULL_DISTANCE_ELEMENT_COUNT);
vs->culldistance_output[vs->info.output_semantic_index[i]] = i;
}
}
if (!found_clipvertex)
vs->clipvertex_output = vs->position_output;
}
 
assert(vs);
return vs;
}
 
 
void
draw_bind_vertex_shader(struct draw_context *draw,
struct draw_vertex_shader *dvs)
{
draw_do_flush( draw, DRAW_FLUSH_STATE_CHANGE );
if (dvs)
{
draw->vs.vertex_shader = dvs;
draw->vs.num_vs_outputs = dvs->info.num_outputs;
draw->vs.position_output = dvs->position_output;
draw->vs.edgeflag_output = dvs->edgeflag_output;
draw->vs.clipvertex_output = dvs->clipvertex_output;
draw->vs.clipdistance_output[0] = dvs->clipdistance_output[0];
draw->vs.clipdistance_output[1] = dvs->clipdistance_output[1];
dvs->prepare( dvs, draw );
}
else {
draw->vs.vertex_shader = NULL;
draw->vs.num_vs_outputs = 0;
}
}
 
 
void
draw_delete_vertex_shader(struct draw_context *draw,
struct draw_vertex_shader *dvs)
{
unsigned i;
 
for (i = 0; i < dvs->nr_variants; i++)
dvs->variant[i]->destroy( dvs->variant[i] );
 
dvs->nr_variants = 0;
 
dvs->delete( dvs );
}
 
 
 
boolean
draw_vs_init( struct draw_context *draw )
{
draw->dump_vs = debug_get_option_gallium_dump_vs();
 
draw->vs.tgsi.machine = tgsi_exec_machine_create();
if (!draw->vs.tgsi.machine)
return FALSE;
 
draw->vs.emit_cache = translate_cache_create();
if (!draw->vs.emit_cache)
return FALSE;
draw->vs.fetch_cache = translate_cache_create();
if (!draw->vs.fetch_cache)
return FALSE;
 
return TRUE;
}
 
void
draw_vs_destroy( struct draw_context *draw )
{
if (draw->vs.fetch_cache)
translate_cache_destroy(draw->vs.fetch_cache);
 
if (draw->vs.emit_cache)
translate_cache_destroy(draw->vs.emit_cache);
 
tgsi_exec_machine_destroy(draw->vs.tgsi.machine);
}
 
 
struct draw_vs_variant *
draw_vs_lookup_variant( struct draw_vertex_shader *vs,
const struct draw_vs_variant_key *key )
{
struct draw_vs_variant *variant;
unsigned i;
 
/* Lookup existing variant:
*/
for (i = 0; i < vs->nr_variants; i++)
if (draw_vs_variant_key_compare(key, &vs->variant[i]->key) == 0)
return vs->variant[i];
/* Else have to create a new one:
*/
variant = vs->create_variant( vs, key );
if (variant == NULL)
return NULL;
 
/* Add it to our list, could be smarter:
*/
if (vs->nr_variants < Elements(vs->variant)) {
vs->variant[vs->nr_variants++] = variant;
}
else {
vs->last_variant++;
vs->last_variant %= Elements(vs->variant);
vs->variant[vs->last_variant]->destroy(vs->variant[vs->last_variant]);
vs->variant[vs->last_variant] = variant;
}
 
/* Done
*/
return variant;
}
 
 
struct translate *
draw_vs_get_fetch( struct draw_context *draw,
struct translate_key *key )
{
if (!draw->vs.fetch ||
translate_key_compare(&draw->vs.fetch->key, key) != 0)
{
translate_key_sanitize(key);
draw->vs.fetch = translate_cache_find(draw->vs.fetch_cache, key);
}
return draw->vs.fetch;
}
 
struct translate *
draw_vs_get_emit( struct draw_context *draw,
struct translate_key *key )
{
if (!draw->vs.emit ||
translate_key_compare(&draw->vs.emit->key, key) != 0)
{
translate_key_sanitize(key);
draw->vs.emit = translate_cache_find(draw->vs.emit_cache, key);
}
return draw->vs.emit;
}
 
void
draw_vs_attach_so(struct draw_vertex_shader *dvs,
const struct pipe_stream_output_info *info)
{
dvs->state.stream_output = *info;
}
 
void
draw_vs_reset_so(struct draw_vertex_shader *dvs)
{
memset(&dvs->state.stream_output, 0, sizeof(dvs->state.stream_output));
}
/drivers/video/Gallium/auxiliary/draw/draw_vs.h
0,0 → 1,210
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/* Authors: Keith Whitwell <keith@tungstengraphics.com>
*/
 
#ifndef DRAW_VS_H
#define DRAW_VS_H
 
#include "draw_context.h"
#include "draw_private.h"
#include "draw_vertex.h"
 
 
struct draw_context;
struct pipe_shader_state;
 
struct draw_variant_input
{
enum pipe_format format;
unsigned buffer;
unsigned offset;
unsigned instance_divisor;
};
 
struct draw_variant_output
{
enum attrib_emit format; /* output format */
unsigned vs_output:8; /* which vertex shader output is this? */
unsigned offset:24; /* offset into output vertex */
};
 
struct draw_variant_element {
struct draw_variant_input in;
struct draw_variant_output out;
};
 
struct draw_vs_variant_key {
unsigned output_stride;
unsigned nr_elements:8; /* max2(nr_inputs, nr_outputs) */
unsigned nr_inputs:8;
unsigned nr_outputs:8;
unsigned viewport:1;
unsigned clip:1;
unsigned const_vbuffers:5;
struct draw_variant_element element[PIPE_MAX_ATTRIBS];
};
 
struct draw_vs_variant;
 
 
struct draw_vs_variant {
struct draw_vs_variant_key key;
 
struct draw_vertex_shader *vs;
 
void (*set_buffer)( struct draw_vs_variant *,
unsigned i,
const void *ptr,
unsigned stride,
unsigned max_stride );
 
void (PIPE_CDECL *run_linear)( struct draw_vs_variant *shader,
unsigned start,
unsigned count,
void *output_buffer );
 
void (PIPE_CDECL *run_elts)( struct draw_vs_variant *shader,
const unsigned *elts,
unsigned count,
void *output_buffer );
 
void (*destroy)( struct draw_vs_variant * );
};
 
 
/**
* Private version of the compiled vertex_shader
*/
struct draw_vertex_shader {
struct draw_context *draw;
 
/* This member will disappear shortly:
*/
struct pipe_shader_state state;
 
struct tgsi_shader_info info;
unsigned position_output;
unsigned edgeflag_output;
unsigned clipvertex_output;
unsigned clipdistance_output[PIPE_MAX_CLIP_OR_CULL_DISTANCE_ELEMENT_COUNT];
unsigned culldistance_output[PIPE_MAX_CLIP_OR_CULL_DISTANCE_ELEMENT_COUNT];
/* Extracted from shader:
*/
const float (*immediates)[4];
 
/*
*/
struct draw_vs_variant *variant[16];
unsigned nr_variants;
unsigned last_variant;
struct draw_vs_variant *(*create_variant)( struct draw_vertex_shader *shader,
const struct draw_vs_variant_key *key );
 
 
void (*prepare)( struct draw_vertex_shader *shader,
struct draw_context *draw );
 
/* Run the shader - this interface will get cleaned up in the
* future:
*/
void (*run_linear)( struct draw_vertex_shader *shader,
const float (*input)[4],
float (*output)[4],
const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
const unsigned const_size[PIPE_MAX_CONSTANT_BUFFERS],
unsigned count,
unsigned input_stride,
unsigned output_stride );
 
 
void (*delete)( struct draw_vertex_shader * );
};
 
 
struct draw_vs_variant *
draw_vs_lookup_variant( struct draw_vertex_shader *base,
const struct draw_vs_variant_key *key );
 
 
/********************************************************************************
* Internal functions:
*/
 
struct draw_vertex_shader *
draw_create_vs_exec(struct draw_context *draw,
const struct pipe_shader_state *templ);
 
struct draw_vs_variant_key;
struct draw_vertex_shader;
 
#if HAVE_LLVM
struct draw_vertex_shader *
draw_create_vs_llvm(struct draw_context *draw,
const struct pipe_shader_state *state);
#endif
 
 
/********************************************************************************
* Helpers for vs implementations that don't do their own fetch/emit variants.
* Means these can be shared between shaders.
*/
struct translate;
struct translate_key;
 
struct translate *draw_vs_get_fetch( struct draw_context *draw,
struct translate_key *key );
 
 
struct translate *draw_vs_get_emit( struct draw_context *draw,
struct translate_key *key );
 
struct draw_vs_variant *
draw_vs_create_variant_generic( struct draw_vertex_shader *vs,
const struct draw_vs_variant_key *key );
 
 
 
static INLINE int draw_vs_variant_keysize( const struct draw_vs_variant_key *key )
{
return 2 * sizeof(int) + key->nr_elements * sizeof(struct draw_variant_element);
}
 
static INLINE int draw_vs_variant_key_compare( const struct draw_vs_variant_key *a,
const struct draw_vs_variant_key *b )
{
int keysize = draw_vs_variant_keysize(a);
return memcmp(a, b, keysize);
}
 
 
#define MAX_TGSI_VERTICES 4
 
 
#endif
/drivers/video/Gallium/auxiliary/draw/draw_vs_exec.c
0,0 → 1,240
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
* Brian Paul
*/
 
#include "util/u_math.h"
#include "util/u_memory.h"
#include "pipe/p_shader_tokens.h"
 
#include "draw_private.h"
#include "draw_context.h"
#include "draw_vs.h"
 
#include "tgsi/tgsi_parse.h"
#include "tgsi/tgsi_scan.h"
#include "tgsi/tgsi_exec.h"
 
 
struct exec_vertex_shader {
struct draw_vertex_shader base;
struct tgsi_exec_machine *machine;
};
 
static struct exec_vertex_shader *exec_vertex_shader( struct draw_vertex_shader *vs )
{
return (struct exec_vertex_shader *)vs;
}
 
 
/* Not required for run_linear.
*/
static void
vs_exec_prepare( struct draw_vertex_shader *shader,
struct draw_context *draw )
{
struct exec_vertex_shader *evs = exec_vertex_shader(shader);
 
/* Specify the vertex program to interpret/execute.
* Avoid rebinding when possible.
*/
if (evs->machine->Tokens != shader->state.tokens) {
tgsi_exec_machine_bind_shader(evs->machine,
shader->state.tokens,
draw->vs.tgsi.sampler);
}
}
 
 
 
 
/* Simplified vertex shader interface for the pt paths. Given the
* complexity of code-generating all the above operations together,
* it's time to try doing all the other stuff separately.
*/
static void
vs_exec_run_linear( struct draw_vertex_shader *shader,
const float (*input)[4],
float (*output)[4],
const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
const unsigned const_size[PIPE_MAX_CONSTANT_BUFFERS],
unsigned count,
unsigned input_stride,
unsigned output_stride )
{
struct exec_vertex_shader *evs = exec_vertex_shader(shader);
struct tgsi_exec_machine *machine = evs->machine;
unsigned int i, j;
unsigned slot;
boolean clamp_vertex_color = shader->draw->rasterizer->clamp_vertex_color;
 
tgsi_exec_set_constant_buffers(machine, PIPE_MAX_CONSTANT_BUFFERS,
constants, const_size);
 
if (shader->info.uses_instanceid) {
unsigned i = machine->SysSemanticToIndex[TGSI_SEMANTIC_INSTANCEID];
assert(i < Elements(machine->SystemValue));
for (j = 0; j < TGSI_QUAD_SIZE; j++)
machine->SystemValue[i].i[j] = shader->draw->instance_id;
}
 
for (i = 0; i < count; i += MAX_TGSI_VERTICES) {
unsigned int max_vertices = MIN2(MAX_TGSI_VERTICES, count - i);
 
/* Swizzle inputs.
*/
for (j = 0; j < max_vertices; j++) {
#if 0
debug_printf("%d) Input vert:\n", i + j);
for (slot = 0; slot < shader->info.num_inputs; slot++) {
debug_printf("\t%d: %f %f %f %f\n", slot,
input[slot][0],
input[slot][1],
input[slot][2],
input[slot][3]);
}
#endif
 
if (shader->info.uses_vertexid) {
unsigned vid = machine->SysSemanticToIndex[TGSI_SEMANTIC_VERTEXID];
assert(vid < Elements(machine->SystemValue));
machine->SystemValue[vid].i[j] = i + j;
}
 
for (slot = 0; slot < shader->info.num_inputs; slot++) {
#if 0
assert(!util_is_inf_or_nan(input[slot][0]));
assert(!util_is_inf_or_nan(input[slot][1]));
assert(!util_is_inf_or_nan(input[slot][2]));
assert(!util_is_inf_or_nan(input[slot][3]));
#endif
machine->Inputs[slot].xyzw[0].f[j] = input[slot][0];
machine->Inputs[slot].xyzw[1].f[j] = input[slot][1];
machine->Inputs[slot].xyzw[2].f[j] = input[slot][2];
machine->Inputs[slot].xyzw[3].f[j] = input[slot][3];
}
 
input = (const float (*)[4])((const char *)input + input_stride);
}
 
tgsi_set_exec_mask(machine,
1,
max_vertices > 1,
max_vertices > 2,
max_vertices > 3);
 
/* run interpreter */
tgsi_exec_machine_run( machine );
 
/* Unswizzle all output results.
*/
for (j = 0; j < max_vertices; j++) {
for (slot = 0; slot < shader->info.num_outputs; slot++) {
unsigned name = shader->info.output_semantic_name[slot];
if(clamp_vertex_color &&
(name == TGSI_SEMANTIC_COLOR || name == TGSI_SEMANTIC_BCOLOR))
{
output[slot][0] = CLAMP(machine->Outputs[slot].xyzw[0].f[j], 0.0f, 1.0f);
output[slot][1] = CLAMP(machine->Outputs[slot].xyzw[1].f[j], 0.0f, 1.0f);
output[slot][2] = CLAMP(machine->Outputs[slot].xyzw[2].f[j], 0.0f, 1.0f);
output[slot][3] = CLAMP(machine->Outputs[slot].xyzw[3].f[j], 0.0f, 1.0f);
}
else if (name == TGSI_SEMANTIC_FOG) {
output[slot][0] = machine->Outputs[slot].xyzw[0].f[j];
output[slot][1] = 0;
output[slot][2] = 0;
output[slot][3] = 1;
} else
{
output[slot][0] = machine->Outputs[slot].xyzw[0].f[j];
output[slot][1] = machine->Outputs[slot].xyzw[1].f[j];
output[slot][2] = machine->Outputs[slot].xyzw[2].f[j];
output[slot][3] = machine->Outputs[slot].xyzw[3].f[j];
}
}
 
#if 0
debug_printf("%d) Post xform vert:\n", i + j);
for (slot = 0; slot < shader->info.num_outputs; slot++) {
debug_printf("\t%d: %f %f %f %f\n", slot,
output[slot][0],
output[slot][1],
output[slot][2],
output[slot][3]);
assert(!util_is_inf_or_nan(output[slot][0]));
}
#endif
 
output = (float (*)[4])((char *)output + output_stride);
}
 
}
}
 
 
 
 
static void
vs_exec_delete( struct draw_vertex_shader *dvs )
{
FREE((void*) dvs->state.tokens);
FREE( dvs );
}
 
 
struct draw_vertex_shader *
draw_create_vs_exec(struct draw_context *draw,
const struct pipe_shader_state *state)
{
struct exec_vertex_shader *vs = CALLOC_STRUCT( exec_vertex_shader );
 
if (vs == NULL)
return NULL;
 
/* we make a private copy of the tokens */
vs->base.state.tokens = tgsi_dup_tokens(state->tokens);
if (!vs->base.state.tokens) {
FREE(vs);
return NULL;
}
 
tgsi_scan_shader(state->tokens, &vs->base.info);
 
vs->base.state.stream_output = state->stream_output;
vs->base.draw = draw;
vs->base.prepare = vs_exec_prepare;
vs->base.run_linear = vs_exec_run_linear;
vs->base.delete = vs_exec_delete;
vs->base.create_variant = draw_vs_create_variant_generic;
vs->machine = draw->vs.tgsi.machine;
 
return &vs->base;
}
/drivers/video/Gallium/auxiliary/draw/draw_vs_llvm.c
0,0 → 1,117
/**************************************************************************
*
* Copyright 2010 VMware, Inc.
* 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 VMWARE 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.
*
**************************************************************************/
 
#include "util/u_math.h"
#include "util/u_memory.h"
#include "pipe/p_shader_tokens.h"
#include "pipe/p_screen.h"
 
#include "draw_private.h"
#include "draw_context.h"
#include "draw_vs.h"
#include "draw_llvm.h"
 
#include "tgsi/tgsi_parse.h"
#include "tgsi/tgsi_scan.h"
 
static void
vs_llvm_prepare(struct draw_vertex_shader *shader,
struct draw_context *draw)
{
/*struct llvm_vertex_shader *evs = llvm_vertex_shader(shader);*/
}
 
static void
vs_llvm_run_linear( struct draw_vertex_shader *shader,
const float (*input)[4],
float (*output)[4],
const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
const unsigned constants_size[PIPE_MAX_CONSTANT_BUFFERS],
unsigned count,
unsigned input_stride,
unsigned output_stride )
{
/* we should never get here since the entire pipeline is
* generated in draw_pt_fetch_shade_pipeline_llvm.c */
debug_assert(0);
}
 
 
static void
vs_llvm_delete( struct draw_vertex_shader *dvs )
{
struct llvm_vertex_shader *shader = llvm_vertex_shader(dvs);
struct draw_llvm_variant_list_item *li;
 
li = first_elem(&shader->variants);
while(!at_end(&shader->variants, li)) {
struct draw_llvm_variant_list_item *next = next_elem(li);
draw_llvm_destroy_variant(li->base);
li = next;
}
 
assert(shader->variants_cached == 0);
FREE((void*) dvs->state.tokens);
FREE( dvs );
}
 
 
struct draw_vertex_shader *
draw_create_vs_llvm(struct draw_context *draw,
const struct pipe_shader_state *state)
{
struct llvm_vertex_shader *vs = CALLOC_STRUCT( llvm_vertex_shader );
 
if (vs == NULL)
return NULL;
 
/* we make a private copy of the tokens */
vs->base.state.tokens = tgsi_dup_tokens(state->tokens);
if (!vs->base.state.tokens) {
FREE(vs);
return NULL;
}
 
tgsi_scan_shader(state->tokens, &vs->base.info);
 
vs->variant_key_size =
draw_llvm_variant_key_size(
vs->base.info.file_max[TGSI_FILE_INPUT]+1,
MAX2(vs->base.info.file_max[TGSI_FILE_SAMPLER]+1,
vs->base.info.file_max[TGSI_FILE_SAMPLER_VIEW]+1));
 
vs->base.state.stream_output = state->stream_output;
vs->base.draw = draw;
vs->base.prepare = vs_llvm_prepare;
vs->base.run_linear = vs_llvm_run_linear;
vs->base.delete = vs_llvm_delete;
vs->base.create_variant = draw_vs_create_variant_generic;
 
make_empty_list(&vs->variants);
 
return &vs->base;
}
/drivers/video/Gallium/auxiliary/draw/draw_vs_variant.c
0,0 → 1,370
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
#include "util/u_memory.h"
#include "util/u_math.h"
#include "draw/draw_context.h"
#include "draw/draw_private.h"
#include "draw/draw_vbuf.h"
#include "draw/draw_vertex.h"
#include "draw/draw_vs.h"
#include "translate/translate.h"
 
/* A first pass at incorporating vertex fetch/emit functionality into
*/
struct draw_vs_variant_generic {
struct draw_vs_variant base;
 
struct draw_vertex_shader *shader;
struct draw_context *draw;
/* Basic plan is to run these two translate functions before/after
* the vertex shader's existing run_linear() routine to simulate
* the inclusion of this functionality into the shader...
*
* Next will look at actually including it.
*/
struct translate *fetch;
struct translate *emit;
 
unsigned temp_vertex_stride;
};
 
 
 
 
 
static void vsvg_set_buffer( struct draw_vs_variant *variant,
unsigned buffer,
const void *ptr,
unsigned stride,
unsigned max_index )
{
struct draw_vs_variant_generic *vsvg = (struct draw_vs_variant_generic *)variant;
 
vsvg->fetch->set_buffer(vsvg->fetch,
buffer,
ptr,
stride,
max_index );
}
 
static const struct pipe_viewport_state *
find_viewport(struct draw_context *draw,
char *buffer,
unsigned vertex_idx,
unsigned stride)
{
int viewport_index_output =
draw_current_shader_viewport_index_output(draw);
char *ptr = buffer + vertex_idx * stride;
unsigned *data = (unsigned *)ptr;
int viewport_index =
draw_current_shader_uses_viewport_index(draw) ?
data[viewport_index_output * 4] : 0;
 
viewport_index = draw_clamp_viewport_idx(viewport_index);
 
return &draw->viewports[viewport_index];
}
 
/* Mainly for debug at this stage:
*/
static void do_rhw_viewport( struct draw_vs_variant_generic *vsvg,
unsigned count,
void *output_buffer )
{
char *ptr = (char *)output_buffer;
unsigned stride = vsvg->temp_vertex_stride;
unsigned j;
 
ptr += vsvg->base.vs->position_output * 4 * sizeof(float);
 
for (j = 0; j < count; j++, ptr += stride) {
const struct pipe_viewport_state *viewport =
find_viewport(vsvg->base.vs->draw, (char*)output_buffer,
j, stride);
const float *scale = viewport->scale;
const float *trans = viewport->translate;
float *data = (float *)ptr;
float w = 1.0f / data[3];
 
data[0] = data[0] * w * scale[0] + trans[0];
data[1] = data[1] * w * scale[1] + trans[1];
data[2] = data[2] * w * scale[2] + trans[2];
data[3] = w;
}
}
 
static void do_viewport( struct draw_vs_variant_generic *vsvg,
unsigned count,
void *output_buffer )
{
char *ptr = (char *)output_buffer;
unsigned stride = vsvg->temp_vertex_stride;
unsigned j;
 
ptr += vsvg->base.vs->position_output * 4 * sizeof(float);
 
for (j = 0; j < count; j++, ptr += stride) {
const struct pipe_viewport_state *viewport =
find_viewport(vsvg->base.vs->draw, (char*)output_buffer,
j, stride);
const float *scale = viewport->scale;
const float *trans = viewport->translate;
float *data = (float *)ptr;
 
data[0] = data[0] * scale[0] + trans[0];
data[1] = data[1] * scale[1] + trans[1];
data[2] = data[2] * scale[2] + trans[2];
}
}
 
static void PIPE_CDECL vsvg_run_elts( struct draw_vs_variant *variant,
const unsigned *elts,
unsigned count,
void *output_buffer)
{
struct draw_vs_variant_generic *vsvg = (struct draw_vs_variant_generic *)variant;
unsigned temp_vertex_stride = vsvg->temp_vertex_stride;
void *temp_buffer = MALLOC( align(count,4) * temp_vertex_stride );
if (0) debug_printf("%s %d \n", __FUNCTION__, count);
/* Want to do this in small batches for cache locality?
*/
vsvg->fetch->run_elts( vsvg->fetch,
elts,
count,
vsvg->draw->start_instance,
vsvg->draw->instance_id,
temp_buffer );
 
vsvg->base.vs->run_linear( vsvg->base.vs,
temp_buffer,
temp_buffer,
vsvg->base.vs->draw->pt.user.vs_constants,
vsvg->base.vs->draw->pt.user.vs_constants_size,
count,
temp_vertex_stride,
temp_vertex_stride);
 
/* FIXME: geometry shading? */
 
if (vsvg->base.key.clip) {
/* not really handling clipping, just do the rhw so we can
* see the results...
*/
do_rhw_viewport( vsvg,
count,
temp_buffer );
}
else if (vsvg->base.key.viewport) {
do_viewport( vsvg,
count,
temp_buffer );
}
 
 
vsvg->emit->set_buffer( vsvg->emit,
0,
temp_buffer,
temp_vertex_stride,
~0 );
 
vsvg->emit->set_buffer( vsvg->emit,
1,
&vsvg->draw->rasterizer->point_size,
0,
~0 );
 
vsvg->emit->run( vsvg->emit,
0, count,
vsvg->draw->start_instance,
vsvg->draw->instance_id,
output_buffer );
 
FREE(temp_buffer);
}
 
 
static void PIPE_CDECL vsvg_run_linear( struct draw_vs_variant *variant,
unsigned start,
unsigned count,
void *output_buffer )
{
struct draw_vs_variant_generic *vsvg = (struct draw_vs_variant_generic *)variant;
unsigned temp_vertex_stride = vsvg->temp_vertex_stride;
void *temp_buffer = MALLOC( align(count,4) * temp_vertex_stride );
if (0) debug_printf("%s %d %d (sz %d, %d)\n", __FUNCTION__, start, count,
vsvg->base.key.output_stride,
temp_vertex_stride);
 
vsvg->fetch->run( vsvg->fetch,
start,
count,
vsvg->draw->start_instance,
vsvg->draw->instance_id,
temp_buffer );
 
vsvg->base.vs->run_linear( vsvg->base.vs,
temp_buffer,
temp_buffer,
vsvg->base.vs->draw->pt.user.vs_constants,
vsvg->base.vs->draw->pt.user.vs_constants_size,
count,
temp_vertex_stride,
temp_vertex_stride);
 
if (vsvg->base.key.clip) {
/* not really handling clipping, just do the rhw so we can
* see the results...
*/
do_rhw_viewport( vsvg,
count,
temp_buffer );
}
else if (vsvg->base.key.viewport) {
do_viewport( vsvg,
count,
temp_buffer );
}
 
vsvg->emit->set_buffer( vsvg->emit,
0,
temp_buffer,
temp_vertex_stride,
~0 );
vsvg->emit->set_buffer( vsvg->emit,
1,
&vsvg->draw->rasterizer->point_size,
0,
~0 );
vsvg->emit->run( vsvg->emit,
0, count,
vsvg->draw->start_instance,
vsvg->draw->instance_id,
output_buffer );
 
FREE(temp_buffer);
}
 
 
 
 
 
static void vsvg_destroy( struct draw_vs_variant *variant )
{
FREE(variant);
}
 
 
struct draw_vs_variant *
draw_vs_create_variant_generic( struct draw_vertex_shader *vs,
const struct draw_vs_variant_key *key )
{
unsigned i;
struct translate_key fetch, emit;
 
struct draw_vs_variant_generic *vsvg = CALLOC_STRUCT( draw_vs_variant_generic );
if (vsvg == NULL)
return NULL;
 
vsvg->base.key = *key;
vsvg->base.vs = vs;
vsvg->base.set_buffer = vsvg_set_buffer;
vsvg->base.run_elts = vsvg_run_elts;
vsvg->base.run_linear = vsvg_run_linear;
vsvg->base.destroy = vsvg_destroy;
 
vsvg->draw = vs->draw;
 
vsvg->temp_vertex_stride = MAX2(key->nr_inputs,
vsvg->base.vs->info.num_outputs) * 4 * sizeof(float);
 
/* Build free-standing fetch and emit functions:
*/
fetch.nr_elements = key->nr_inputs;
fetch.output_stride = vsvg->temp_vertex_stride;
for (i = 0; i < key->nr_inputs; i++) {
fetch.element[i].type = TRANSLATE_ELEMENT_NORMAL;
fetch.element[i].input_format = key->element[i].in.format;
fetch.element[i].input_buffer = key->element[i].in.buffer;
fetch.element[i].input_offset = key->element[i].in.offset;
fetch.element[i].instance_divisor = 0;
fetch.element[i].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
fetch.element[i].output_offset = i * 4 * sizeof(float);
assert(fetch.element[i].output_offset < fetch.output_stride);
}
 
 
emit.nr_elements = key->nr_outputs;
emit.output_stride = key->output_stride;
for (i = 0; i < key->nr_outputs; i++) {
if (key->element[i].out.format != EMIT_1F_PSIZE)
{
emit.element[i].type = TRANSLATE_ELEMENT_NORMAL;
emit.element[i].input_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
emit.element[i].input_buffer = 0;
emit.element[i].input_offset = key->element[i].out.vs_output * 4 * sizeof(float);
emit.element[i].instance_divisor = 0;
emit.element[i].output_format = draw_translate_vinfo_format(key->element[i].out.format);
emit.element[i].output_offset = key->element[i].out.offset;
assert(emit.element[i].input_offset <= fetch.output_stride);
}
else {
emit.element[i].type = TRANSLATE_ELEMENT_NORMAL;
emit.element[i].input_format = PIPE_FORMAT_R32_FLOAT;
emit.element[i].input_buffer = 1;
emit.element[i].input_offset = 0;
emit.element[i].instance_divisor = 0;
emit.element[i].output_format = PIPE_FORMAT_R32_FLOAT;
emit.element[i].output_offset = key->element[i].out.offset;
}
}
 
vsvg->fetch = draw_vs_get_fetch( vs->draw, &fetch );
vsvg->emit = draw_vs_get_emit( vs->draw, &emit );
 
return &vsvg->base;
}
 
 
 
 
 
/drivers/video/Gallium/auxiliary/os/os_memory.h
0,0 → 1,80
/**************************************************************************
*
* Copyright 2010 Vmware, Inc.
* 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 VMWARE 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.
*
**************************************************************************/
 
 
/*
* OS memory management abstractions
*/
 
 
#ifndef _OS_MEMORY_H_
#define _OS_MEMORY_H_
 
 
#include "pipe/p_config.h"
#include "pipe/p_compiler.h"
 
 
#if defined(PIPE_SUBSYSTEM_EMBEDDED)
 
#ifdef __cplusplus
extern "C" {
#endif
 
void *
os_malloc(size_t size);
 
void *
os_calloc(size_t count, size_t size);
 
void
os_free(void *ptr);
 
void *
os_realloc(void *ptr, size_t old_size, size_t new_size);
 
void *
os_malloc_aligned(size_t size, size_t alignment);
 
void
os_free_aligned(void *ptr);
 
#ifdef __cplusplus
}
#endif
 
#elif defined(PIPE_OS_WINDOWS) && defined(DEBUG) && !defined(DEBUG_MEMORY_IMPLEMENTATION)
 
# include "os_memory_debug.h"
 
#else
 
# include "os_memory_stdc.h"
 
#endif
 
#endif /* _OS_MEMORY_H_ */
/drivers/video/Gallium/auxiliary/os/os_memory_aligned.h
0,0 → 1,72
/**************************************************************************
*
* Copyright 2008-2010 VMware, Inc.
* 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 VMWARE 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.
*
**************************************************************************/
 
 
/*
* Memory alignment wrappers.
*/
 
 
#ifndef _OS_MEMORY_H_
#error "Must not be included directly. Include os_memory.h instead"
#endif
 
 
#include "pipe/p_compiler.h"
 
 
/**
* Return memory on given byte alignment
*/
static INLINE void *
os_malloc_aligned(size_t size, size_t alignment)
{
char *ptr, *buf;
 
ptr = (char *) os_malloc(size + alignment + sizeof(void *));
if (!ptr)
return NULL;
 
buf = (char *)(((uintptr_t)ptr + sizeof(void *) + alignment - 1) & ~((uintptr_t)(alignment - 1)));
*(char **)(buf - sizeof(void *)) = ptr;
 
return buf;
}
 
 
/**
* Free memory returned by align_malloc().
*/
static INLINE void
os_free_aligned(void *ptr)
{
if (ptr) {
void **cubbyHole = (void **) ((char *) ptr - sizeof(void *));
void *realAddr = *cubbyHole;
os_free(realAddr);
}
}
/drivers/video/Gallium/auxiliary/os/os_memory_debug.h
0,0 → 1,92
/**************************************************************************
*
* Copyright 2008-2010 VMware, Inc.
* 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 VMWARE 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.
*
**************************************************************************/
 
 
/*
* Debugging wrappers for OS memory management abstractions.
*/
 
 
#ifndef _OS_MEMORY_H_
#error "Must not be included directly. Include os_memory.h instead"
#endif
 
 
#include "pipe/p_compiler.h"
 
 
#ifdef __cplusplus
extern "C" {
#endif
 
 
void *
debug_malloc(const char *file, unsigned line, const char *function,
size_t size);
 
void *
debug_calloc(const char *file, unsigned line, const char *function,
size_t count, size_t size );
 
void
debug_free(const char *file, unsigned line, const char *function,
void *ptr);
 
void *
debug_realloc(const char *file, unsigned line, const char *function,
void *old_ptr, size_t old_size, size_t new_size );
 
void
debug_memory_tag(void *ptr, unsigned tag);
 
void
debug_memory_check_block(void *ptr);
 
void
debug_memory_check(void);
 
 
#ifdef __cplusplus
}
#endif
 
 
#ifndef DEBUG_MEMORY_IMPLEMENTATION
 
#define os_malloc( _size ) \
debug_malloc( __FILE__, __LINE__, __FUNCTION__, _size )
#define os_calloc( _count, _size ) \
debug_calloc(__FILE__, __LINE__, __FUNCTION__, _count, _size )
#define os_free( _ptr ) \
debug_free( __FILE__, __LINE__, __FUNCTION__, _ptr )
#define os_realloc( _ptr, _old_size, _new_size ) \
debug_realloc( __FILE__, __LINE__, __FUNCTION__, _ptr, _old_size, _new_size )
 
/* TODO: wrap os_malloc_aligned() and os_free_aligned() too */
#include "os_memory_aligned.h"
 
#endif /* !DEBUG_MEMORY_IMPLEMENTATION */
/drivers/video/Gallium/auxiliary/os/os_memory_stdc.h
0,0 → 1,76
/**************************************************************************
*
* Copyright 2008-2010 VMware, Inc.
* 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 VMWARE 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.
*
**************************************************************************/
 
 
/*
* OS memory management abstractions for the standard C library.
*/
 
 
#ifndef _OS_MEMORY_H_
#error "Must not be included directly. Include os_memory.h instead"
#endif
 
#include <stdlib.h>
 
#include "pipe/p_compiler.h"
 
 
#define os_malloc(_size) malloc(_size)
#define os_calloc(_count, _size ) calloc(_count, _size )
#define os_free(_ptr) free(_ptr)
 
#define os_realloc( _old_ptr, _old_size, _new_size) \
realloc(_old_ptr, _new_size + 0*(_old_size))
 
 
#if defined(HAVE_POSIX_MEMALIGN)
 
static INLINE void *
os_malloc_aligned(size_t size, size_t alignment)
{
void *ptr;
alignment = (alignment + sizeof(void*) - 1) & ~(sizeof(void*) - 1);
if(posix_memalign(&ptr, alignment, size) != 0)
return NULL;
return ptr;
}
 
#define os_free_aligned(_ptr) free(_ptr)
 
#elif defined(PIPE_OS_WINDOWS)
 
#include <malloc.h>
 
#define os_malloc_aligned(_size, _align) _aligned_malloc(_size, _align)
#define os_free_aligned(_ptr) _aligned_free(_ptr)
 
#else
 
#include "os_memory_aligned.h"
 
#endif
/drivers/video/Gallium/auxiliary/os/os_misc.c
0,0 → 1,91
/**************************************************************************
*
* Copyright 2008-2010 Vmware, Inc.
* 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 VMWARE 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.
*
**************************************************************************/
 
 
#include "os_misc.h"
 
#include <stdarg.h>
 
 
#if defined(PIPE_SUBSYSTEM_WINDOWS_USER)
 
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
#endif
#include <windows.h>
#include <stdio.h>
 
#else
 
#include <stdio.h>
#include <stdlib.h>
 
#endif
 
 
void
os_log_message(const char *message)
{
/* If the GALLIUM_LOG_FILE environment variable is set to a valid filename,
* write all messages to that file.
*/
static FILE *fout = NULL;
 
if (!fout) {
/* one-time init */
const char *filename = os_get_option("GALLIUM_LOG_FILE");
if (filename)
fout = fopen(filename, "w");
if (!fout)
fout = stderr;
}
 
#if defined(PIPE_SUBSYSTEM_WINDOWS_USER)
OutputDebugStringA(message);
if(GetConsoleWindow() && !IsDebuggerPresent()) {
fflush(stdout);
fputs(message, fout);
fflush(fout);
}
else if (fout != stderr) {
fputs(message, fout);
fflush(fout);
}
#else /* !PIPE_SUBSYSTEM_WINDOWS */
fflush(stdout);
fputs(message, fout);
fflush(fout);
#endif
}
 
 
const char *
os_get_option(const char *name)
{
return getenv(name);
}
 
/drivers/video/Gallium/auxiliary/os/os_misc.h
0,0 → 1,95
/**************************************************************************
*
* Copyright 2010 Vmware, Inc.
* 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 VMWARE 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.
*
**************************************************************************/
 
 
/*
* Miscellaneous OS services.
*/
 
 
#ifndef _OS_MISC_H_
#define _OS_MISC_H_
 
 
#include "pipe/p_compiler.h"
 
 
#if defined(PIPE_OS_UNIX)
# include <signal.h> /* for kill() */
# include <unistd.h> /* getpid() */
#endif
 
 
#ifdef __cplusplus
extern "C" {
#endif
 
 
/*
* Trap into the debugger.
*/
#if (defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)) && defined(PIPE_CC_GCC)
# define os_break() __asm("int3")
#elif defined(PIPE_CC_MSVC)
# define os_break() __debugbreak()
#elif defined(PIPE_OS_UNIX)
# define os_break() kill(getpid(), SIGTRAP)
#else
# define os_break() abort()
#endif
 
 
/*
* Abort the program.
*/
#if defined(DEBUG)
# define os_abort() os_break()
#else
# define os_abort() abort()
#endif
 
 
/*
* Output a message. Message should preferably end in a newline.
*/
void
os_log_message(const char *message);
 
 
/*
* Get an option. Should return NULL if specified option is not set.
*/
const char *
os_get_option(const char *name);
 
 
#ifdef __cplusplus
}
#endif
 
 
#endif /* _OS_MISC_H_ */
/drivers/video/Gallium/auxiliary/os/os_mman.h
0,0 → 1,87
/**************************************************************************
*
* Copyright 2011 LunarG, Inc.
* 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 VMWARE 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
* OS independent memory mapping (with large file support).
*
* @author Chia-I Wu <olvaffe@gmail.com>
*/
 
#ifndef _OS_MMAN_H_
#define _OS_MMAN_H_
 
 
#include "pipe/p_config.h"
#include "pipe/p_compiler.h"
 
#if defined(PIPE_OS_UNIX)
# ifndef _FILE_OFFSET_BITS
# error _FILE_OFFSET_BITS must be defined to 64
# endif
# include <sys/mman.h>
#else
# error Unsupported OS
#endif
 
#if defined(PIPE_OS_ANDROID)
# include <errno.h> /* for EINVAL */
#endif
 
#ifdef __cplusplus
extern "C" {
#endif
 
 
#if defined(PIPE_OS_ANDROID)
 
extern void *__mmap2(void *, size_t, int, int, int, size_t);
 
static INLINE void *os_mmap(void *addr, size_t length, int prot, int flags, int fd, loff_t offset)
{
/* offset must be aligned to 4096 (not necessarily the page size) */
if (unlikely(offset & 4095)) {
errno = EINVAL;
return MAP_FAILED;
}
 
return __mmap2(addr, length, prot, flags, fd, (size_t) (offset >> 12));
}
 
#else
/* assume large file support exists */
# define os_mmap(addr, length, prot, flags, fd, offset) mmap(addr, length, prot, flags, fd, offset)
#endif
 
#define os_munmap(addr, length) munmap(addr, length)
 
 
#ifdef __cplusplus
}
#endif
 
#endif /* _OS_MMAN_H_ */
/drivers/video/Gallium/auxiliary/os/os_thread.h
0,0 → 1,510
/**************************************************************************
*
* Copyright 1999-2006 Brian Paul
* 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, sublicense,
* 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS 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
*
* Thread, mutex, condition variable, barrier, semaphore and
* thread-specific data functions.
*/
 
 
#ifndef OS_THREAD_H_
#define OS_THREAD_H_
 
 
#include "pipe/p_compiler.h"
#include "util/u_debug.h" /* for assert */
 
 
#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_HAIKU) || defined(PIPE_OS_CYGWIN)
 
#include <pthread.h> /* POSIX threads headers */
#include <stdio.h> /* for perror() */
#include <signal.h>
 
 
/* pipe_thread
*/
typedef pthread_t pipe_thread;
 
#define PIPE_THREAD_ROUTINE( name, param ) \
void *name( void *param )
 
static INLINE pipe_thread pipe_thread_create( void *(* routine)( void *), void *param )
{
pipe_thread thread;
sigset_t saved_set, new_set;
int ret;
 
sigfillset(&new_set);
pthread_sigmask(SIG_SETMASK, &new_set, &saved_set);
ret = pthread_create( &thread, NULL, routine, param );
pthread_sigmask(SIG_SETMASK, &saved_set, NULL);
if (ret)
return 0;
return thread;
}
 
static INLINE int pipe_thread_wait( pipe_thread thread )
{
return pthread_join( thread, NULL );
}
 
static INLINE int pipe_thread_destroy( pipe_thread thread )
{
return pthread_detach( thread );
}
 
 
/* pipe_mutex
*/
typedef pthread_mutex_t pipe_mutex;
 
#define pipe_static_mutex(mutex) \
static pipe_mutex mutex = PTHREAD_MUTEX_INITIALIZER
 
#define pipe_mutex_init(mutex) \
(void) pthread_mutex_init(&(mutex), NULL)
 
#define pipe_mutex_destroy(mutex) \
pthread_mutex_destroy(&(mutex))
 
#define pipe_mutex_lock(mutex) \
(void) pthread_mutex_lock(&(mutex))
 
#define pipe_mutex_unlock(mutex) \
(void) pthread_mutex_unlock(&(mutex))
 
 
/* pipe_condvar
*/
typedef pthread_cond_t pipe_condvar;
 
#define pipe_static_condvar(mutex) \
static pipe_condvar mutex = PTHREAD_COND_INITIALIZER
 
#define pipe_condvar_init(cond) \
pthread_cond_init(&(cond), NULL)
 
#define pipe_condvar_destroy(cond) \
pthread_cond_destroy(&(cond))
 
#define pipe_condvar_wait(cond, mutex) \
pthread_cond_wait(&(cond), &(mutex))
 
#define pipe_condvar_signal(cond) \
pthread_cond_signal(&(cond))
 
#define pipe_condvar_broadcast(cond) \
pthread_cond_broadcast(&(cond))
 
 
 
#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
 
#include <windows.h>
 
/* pipe_thread
*/
typedef HANDLE pipe_thread;
 
#define PIPE_THREAD_ROUTINE( name, param ) \
void * WINAPI name( void *param )
 
static INLINE pipe_thread pipe_thread_create( void *(WINAPI * routine)( void *), void *param )
{
DWORD id;
return CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE) routine, param, 0, &id );
}
 
static INLINE int pipe_thread_wait( pipe_thread thread )
{
if (WaitForSingleObject( thread, INFINITE ) == WAIT_OBJECT_0)
return 0;
return -1;
}
 
static INLINE int pipe_thread_destroy( pipe_thread thread )
{
if (CloseHandle( thread ))
return 0;
return -1;
}
 
 
/* pipe_mutex
*/
typedef CRITICAL_SECTION pipe_mutex;
 
/* http://locklessinc.com/articles/pthreads_on_windows/ */
#define pipe_static_mutex(mutex) \
static pipe_mutex mutex = {(PCRITICAL_SECTION_DEBUG)-1, -1, 0, 0, 0, 0}
 
#define pipe_mutex_init(mutex) \
InitializeCriticalSection(&mutex)
 
#define pipe_mutex_destroy(mutex) \
DeleteCriticalSection(&mutex)
 
#define pipe_mutex_lock(mutex) \
EnterCriticalSection(&mutex)
 
#define pipe_mutex_unlock(mutex) \
LeaveCriticalSection(&mutex)
 
/* TODO: Need a macro to declare "I don't care about WinXP compatibilty" */
#if 0 && defined (_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)
/* CONDITION_VARIABLE is only available on newer versions of Windows
* (Server 2008/Vista or later).
* http://msdn.microsoft.com/en-us/library/ms682052(VS.85).aspx
*
* pipe_condvar
*/
typedef CONDITION_VARIABLE pipe_condvar;
 
#define pipe_static_condvar(cond) \
/*static*/ pipe_condvar cond = CONDITION_VARIABLE_INIT
 
#define pipe_condvar_init(cond) \
InitializeConditionVariable(&(cond))
 
#define pipe_condvar_destroy(cond) \
(void) cond /* nothing to do */
 
#define pipe_condvar_wait(cond, mutex) \
SleepConditionVariableCS(&(cond), &(mutex), INFINITE)
 
#define pipe_condvar_signal(cond) \
WakeConditionVariable(&(cond))
 
#define pipe_condvar_broadcast(cond) \
WakeAllConditionVariable(&(cond))
 
#else /* need compatibility with pre-Vista Win32 */
 
/* pipe_condvar (XXX FIX THIS)
* See http://www.cs.wustl.edu/~schmidt/win32-cv-1.html
* for potential pitfalls in implementation.
*/
typedef DWORD pipe_condvar;
 
#define pipe_static_condvar(cond) \
/*static*/ pipe_condvar cond = 1
 
#define pipe_condvar_init(cond) \
(void) (cond = 1)
 
#define pipe_condvar_destroy(cond) \
(void) cond
 
/* Poor man's pthread_cond_wait():
Just release the mutex and sleep for one millisecond.
The caller's while() loop does all the work. */
#define pipe_condvar_wait(cond, mutex) \
do { pipe_mutex_unlock(mutex); \
Sleep(cond); \
pipe_mutex_lock(mutex); \
} while (0)
 
#define pipe_condvar_signal(cond) \
(void) cond
 
#define pipe_condvar_broadcast(cond) \
(void) cond
 
#endif /* pre-Vista win32 */
 
#else
 
#include "os/os_time.h"
 
/** Dummy definitions */
 
typedef unsigned pipe_thread;
 
#define PIPE_THREAD_ROUTINE( name, param ) \
void * name( void *param )
 
static INLINE pipe_thread pipe_thread_create( void *(* routine)( void *), void *param )
{
return 0;
}
 
static INLINE int pipe_thread_wait( pipe_thread thread )
{
return -1;
}
 
static INLINE int pipe_thread_destroy( pipe_thread thread )
{
return -1;
}
 
typedef unsigned pipe_mutex;
 
#define pipe_static_mutex(mutex) \
static pipe_mutex mutex = 0
 
#define pipe_mutex_init(mutex) \
(void) mutex
 
#define pipe_mutex_destroy(mutex) \
(void) mutex
 
#define pipe_mutex_lock(mutex) \
(void) mutex
 
#define pipe_mutex_unlock(mutex) \
(void) mutex
 
typedef int64_t pipe_condvar;
 
#define pipe_static_condvar(condvar) \
static pipe_condvar condvar = 1000
 
#define pipe_condvar_init(condvar) \
(void) (condvar = 1000)
 
#define pipe_condvar_destroy(condvar) \
(void) condvar
 
/* Poor man's pthread_cond_wait():
Just release the mutex and sleep for one millisecond.
The caller's while() loop does all the work. */
#define pipe_condvar_wait(condvar, mutex) \
do { pipe_mutex_unlock(mutex); \
os_time_sleep(condvar); \
pipe_mutex_lock(mutex); \
} while (0)
 
#define pipe_condvar_signal(condvar) \
(void) condvar
 
#define pipe_condvar_broadcast(condvar) \
(void) condvar
 
 
#endif /* PIPE_OS_? */
 
 
/*
* pipe_barrier
*/
 
#if (defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS)) && !defined(PIPE_OS_ANDROID)
 
typedef pthread_barrier_t pipe_barrier;
 
static INLINE void pipe_barrier_init(pipe_barrier *barrier, unsigned count)
{
pthread_barrier_init(barrier, NULL, count);
}
 
static INLINE void pipe_barrier_destroy(pipe_barrier *barrier)
{
pthread_barrier_destroy(barrier);
}
 
static INLINE void pipe_barrier_wait(pipe_barrier *barrier)
{
pthread_barrier_wait(barrier);
}
 
 
#else /* If the OS doesn't have its own, implement barriers using a mutex and a condvar */
 
typedef struct {
unsigned count;
unsigned waiters;
uint64_t sequence;
pipe_mutex mutex;
pipe_condvar condvar;
} pipe_barrier;
 
static INLINE void pipe_barrier_init(pipe_barrier *barrier, unsigned count)
{
barrier->count = count;
barrier->waiters = 0;
barrier->sequence = 0;
pipe_mutex_init(barrier->mutex);
pipe_condvar_init(barrier->condvar);
}
 
static INLINE void pipe_barrier_destroy(pipe_barrier *barrier)
{
assert(barrier->waiters == 0);
pipe_mutex_destroy(barrier->mutex);
pipe_condvar_destroy(barrier->condvar);
}
 
static INLINE void pipe_barrier_wait(pipe_barrier *barrier)
{
pipe_mutex_lock(barrier->mutex);
 
assert(barrier->waiters < barrier->count);
barrier->waiters++;
 
if (barrier->waiters < barrier->count) {
uint64_t sequence = barrier->sequence;
 
do {
pipe_condvar_wait(barrier->condvar, barrier->mutex);
} while (sequence == barrier->sequence);
} else {
barrier->waiters = 0;
barrier->sequence++;
pipe_condvar_broadcast(barrier->condvar);
}
 
pipe_mutex_unlock(barrier->mutex);
}
 
 
#endif
 
 
/*
* Semaphores
*/
 
typedef struct
{
pipe_mutex mutex;
pipe_condvar cond;
int counter;
} pipe_semaphore;
 
 
static INLINE void
pipe_semaphore_init(pipe_semaphore *sema, int init_val)
{
pipe_mutex_init(sema->mutex);
pipe_condvar_init(sema->cond);
sema->counter = init_val;
}
 
static INLINE void
pipe_semaphore_destroy(pipe_semaphore *sema)
{
pipe_mutex_destroy(sema->mutex);
pipe_condvar_destroy(sema->cond);
}
 
/** Signal/increment semaphore counter */
static INLINE void
pipe_semaphore_signal(pipe_semaphore *sema)
{
pipe_mutex_lock(sema->mutex);
sema->counter++;
pipe_condvar_signal(sema->cond);
pipe_mutex_unlock(sema->mutex);
}
 
/** Wait for semaphore counter to be greater than zero */
static INLINE void
pipe_semaphore_wait(pipe_semaphore *sema)
{
pipe_mutex_lock(sema->mutex);
while (sema->counter <= 0) {
pipe_condvar_wait(sema->cond, sema->mutex);
}
sema->counter--;
pipe_mutex_unlock(sema->mutex);
}
 
 
 
/*
* Thread-specific data.
*/
 
typedef struct {
#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_HAIKU) || defined(PIPE_OS_CYGWIN)
pthread_key_t key;
#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
DWORD key;
#endif
int initMagic;
} pipe_tsd;
 
 
#define PIPE_TSD_INIT_MAGIC 0xff8adc98
 
 
static INLINE void
pipe_tsd_init(pipe_tsd *tsd)
{
#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_HAIKU) || defined(PIPE_OS_CYGWIN)
if (pthread_key_create(&tsd->key, NULL/*free*/) != 0) {
perror("pthread_key_create(): failed to allocate key for thread specific data");
exit(-1);
}
#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
assert(0);
#endif
tsd->initMagic = PIPE_TSD_INIT_MAGIC;
}
 
static INLINE void *
pipe_tsd_get(pipe_tsd *tsd)
{
if (tsd->initMagic != (int) PIPE_TSD_INIT_MAGIC) {
pipe_tsd_init(tsd);
}
#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_HAIKU) || defined(PIPE_OS_CYGWIN)
return pthread_getspecific(tsd->key);
#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
assert(0);
return NULL;
#else
assert(0);
return NULL;
#endif
}
 
static INLINE void
pipe_tsd_set(pipe_tsd *tsd, void *value)
{
if (tsd->initMagic != (int) PIPE_TSD_INIT_MAGIC) {
pipe_tsd_init(tsd);
}
#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS) || defined(PIPE_OS_APPLE) || defined(PIPE_OS_HAIKU) || defined(PIPE_OS_CYGWIN)
if (pthread_setspecific(tsd->key, value) != 0) {
perror("pthread_set_specific() failed");
exit(-1);
}
#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
assert(0);
#else
assert(0);
#endif
}
 
 
 
#endif /* OS_THREAD_H_ */
/drivers/video/Gallium/auxiliary/os/os_time.c
0,0 → 1,94
/**************************************************************************
*
* Copyright 2008-2010 VMware, Inc.
* 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 VMWARE 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
* OS independent time-manipulation functions.
*
* @author Jose Fonseca <jfonseca@vmware.com>
*/
 
 
#include "pipe/p_config.h"
 
#if defined(PIPE_OS_UNIX)
# include <time.h> /* timeval */
# include <sys/time.h> /* timeval */
#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
# include <windows.h>
#else
# error Unsupported OS
#endif
 
#include "os_time.h"
 
 
int64_t
os_time_get_nano(void)
{
#if defined(PIPE_OS_LINUX)
 
struct timespec tv;
clock_gettime(CLOCK_MONOTONIC, &tv);
return tv.tv_nsec + tv.tv_sec*INT64_C(1000000000);
 
#elif defined(PIPE_OS_UNIX)
 
struct timeval tv;
gettimeofday(&tv, NULL);
return tv.tv_usec*INT64_C(1000) + tv.tv_sec*INT64_C(1000000000);
 
#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
 
static LARGE_INTEGER frequency;
LARGE_INTEGER counter;
if(!frequency.QuadPart)
QueryPerformanceFrequency(&frequency);
QueryPerformanceCounter(&counter);
return counter.QuadPart*INT64_C(1000000000)/frequency.QuadPart;
 
#else
 
#error Unsupported OS
 
#endif
}
 
 
#if defined(PIPE_SUBSYSTEM_WINDOWS_USER)
 
void
os_time_sleep(int64_t usecs)
{
DWORD dwMilliseconds = (DWORD) ((usecs + 999) / 1000);
/* Avoid Sleep(O) as that would cause to sleep for an undetermined duration */
if (dwMilliseconds) {
Sleep(dwMilliseconds);
}
}
 
#endif
/drivers/video/Gallium/auxiliary/os/os_time.h
0,0 → 1,101
/**************************************************************************
*
* Copyright 2008-2010 VMware, Inc.
* 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 VMWARE 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
* OS independent time-manipulation functions.
*
* @author Jose Fonseca <jfonseca@vmware.com>
*/
 
#ifndef _OS_TIME_H_
#define _OS_TIME_H_
 
 
#include "pipe/p_config.h"
 
#if defined(PIPE_OS_UNIX)
# include <unistd.h> /* usleep */
#endif
 
#include "pipe/p_compiler.h"
 
 
#ifdef __cplusplus
extern "C" {
#endif
 
 
/*
* Get the current time in nanoseconds from an unknown base.
*/
int64_t
os_time_get_nano(void);
 
 
/*
* Get the current time in microseconds from an unknown base.
*/
static INLINE int64_t
os_time_get(void) {
return os_time_get_nano() / 1000;
}
 
 
/*
* Sleep.
*/
#if defined(PIPE_OS_UNIX)
#define os_time_sleep(_usecs) usleep(_usecs)
#else
void
os_time_sleep(int64_t usecs);
#endif
 
 
/*
* Helper function for detecting time outs, taking in account overflow.
*
* Returns true if the current time has elapsed beyond the specified interval.
*/
static INLINE boolean
os_time_timeout(int64_t start,
int64_t end,
int64_t curr)
{
if(start <= end)
return !(start <= curr && curr < end);
else
return !((start <= curr) || (curr < end));
}
 
 
#ifdef __cplusplus
}
#endif
 
#endif /* _OS_TIME_H_ */
/drivers/video/Gallium/auxiliary/target-helpers/inline_debug_helper.h
0,0 → 1,51
 
#ifndef INLINE_DEBUG_HELPER_H
#define INLINE_DEBUG_HELPER_H
 
#include "pipe/p_compiler.h"
#include "util/u_debug.h"
 
 
/* Helper function to wrap a screen with
* one or more debug driver: rbug, trace.
*/
 
#ifdef GALLIUM_TRACE
#include "trace/tr_public.h"
#endif
 
#ifdef GALLIUM_RBUG
#include "rbug/rbug_public.h"
#endif
 
#ifdef GALLIUM_GALAHAD
#include "galahad/glhd_public.h"
#endif
 
#ifdef GALLIUM_NOOP
#include "noop/noop_public.h"
#endif
 
static INLINE struct pipe_screen *
debug_screen_wrap(struct pipe_screen *screen)
{
#if defined(GALLIUM_RBUG)
screen = rbug_screen_create(screen);
#endif
 
#if defined(GALLIUM_TRACE)
screen = trace_screen_create(screen);
#endif
 
#if defined(GALLIUM_GALAHAD)
screen = galahad_screen_create(screen);
#endif
 
#if defined(GALLIUM_NOOP)
screen = noop_screen_create(screen);
#endif
 
return screen;
}
 
#endif
/drivers/video/Gallium/auxiliary/target-helpers/inline_sw_helper.h
0,0 → 1,61
 
#ifndef INLINE_SW_HELPER_H
#define INLINE_SW_HELPER_H
 
#include "pipe/p_compiler.h"
#include "util/u_debug.h"
#include "state_tracker/sw_winsys.h"
 
 
/* Helper function to choose and instantiate one of the software rasterizers:
* llvmpipe, softpipe.
*/
 
#ifdef GALLIUM_SOFTPIPE
#include "softpipe/sp_public.h"
#endif
 
#ifdef GALLIUM_LLVMPIPE
#include "llvmpipe/lp_public.h"
#endif
 
 
static INLINE struct pipe_screen *
sw_screen_create_named(struct sw_winsys *winsys, const char *driver)
{
struct pipe_screen *screen = NULL;
 
#if defined(GALLIUM_LLVMPIPE)
if (screen == NULL && strcmp(driver, "llvmpipe") == 0)
screen = llvmpipe_create_screen(winsys);
#endif
 
#if defined(GALLIUM_SOFTPIPE)
if (screen == NULL)
screen = softpipe_create_screen(winsys);
#endif
 
return screen;
}
 
 
static INLINE struct pipe_screen *
sw_screen_create(struct sw_winsys *winsys)
{
const char *default_driver;
const char *driver;
 
#if defined(GALLIUM_LLVMPIPE)
default_driver = "llvmpipe";
#elif defined(GALLIUM_SOFTPIPE)
default_driver = "softpipe";
#else
default_driver = "";
#endif
 
driver = "softpipe"; // debug_get_option("GALLIUM_DRIVER", default_driver);
return sw_screen_create_named(winsys, driver);
}
 
 
#endif
/drivers/video/Gallium/auxiliary/target-helpers/inline_wrapper_sw_helper.h
0,0 → 1,42
 
#ifndef INLINE_WRAPPER_SW_HELPER_H
#define INLINE_WRAPPER_SW_HELPER_H
 
#include "target-helpers/inline_sw_helper.h"
#include "sw/wrapper/wrapper_sw_winsys.h"
 
/**
* Try to wrap a hw screen with a software screen.
* On failure will return given screen.
*/
static INLINE struct pipe_screen *
sw_screen_wrap(struct pipe_screen *screen)
{
#if defined(GALLIUM_SOFTPIPE) || defined(GALLIUM_LLVMPIPE)
struct sw_winsys *sws;
struct pipe_screen *sw_screen = NULL;
const char *driver;
 
driver = debug_get_option("GALLIUM_DRIVER", "native");
if (strcmp(driver, "native") == 0)
return screen;
 
sws = wrapper_sw_winsys_wrap_pipe_screen(screen);
if (!sws)
goto err;
 
sw_screen = sw_screen_create_named(sws, driver);
 
if (!sw_screen)
goto err_winsys;
 
return sw_screen;
 
err_winsys:
return wrapper_sw_winsys_dewrap_pipe_screen(sws);
err:
#endif
return screen;
}
 
#endif
/drivers/video/Gallium/auxiliary/tgsi/tgsi_build.c
0,0 → 1,1343
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
#include "util/u_debug.h"
#include "pipe/p_format.h"
#include "pipe/p_shader_tokens.h"
#include "tgsi_build.h"
#include "tgsi_parse.h"
 
 
/*
* header
*/
 
struct tgsi_header
tgsi_build_header( void )
{
struct tgsi_header header;
 
header.HeaderSize = 1;
header.BodySize = 0;
 
return header;
}
 
static void
header_headersize_grow( struct tgsi_header *header )
{
assert( header->HeaderSize < 0xFF );
assert( header->BodySize == 0 );
 
header->HeaderSize++;
}
 
static void
header_bodysize_grow( struct tgsi_header *header )
{
assert( header->BodySize < 0xFFFFFF );
 
header->BodySize++;
}
 
struct tgsi_processor
tgsi_build_processor(
unsigned type,
struct tgsi_header *header )
{
struct tgsi_processor processor;
 
processor.Processor = type;
processor.Padding = 0;
 
header_headersize_grow( header );
 
return processor;
}
 
/*
* declaration
*/
 
static void
declaration_grow(
struct tgsi_declaration *declaration,
struct tgsi_header *header )
{
assert( declaration->NrTokens < 0xFF );
 
declaration->NrTokens++;
 
header_bodysize_grow( header );
}
 
static struct tgsi_declaration
tgsi_default_declaration( void )
{
struct tgsi_declaration declaration;
 
declaration.Type = TGSI_TOKEN_TYPE_DECLARATION;
declaration.NrTokens = 1;
declaration.File = TGSI_FILE_NULL;
declaration.UsageMask = TGSI_WRITEMASK_XYZW;
declaration.Interpolate = 0;
declaration.Dimension = 0;
declaration.Semantic = 0;
declaration.Invariant = 0;
declaration.Local = 0;
declaration.Array = 0;
declaration.Padding = 0;
 
return declaration;
}
 
static struct tgsi_declaration
tgsi_build_declaration(
unsigned file,
unsigned usage_mask,
unsigned interpolate,
unsigned dimension,
unsigned semantic,
unsigned invariant,
unsigned local,
struct tgsi_header *header )
{
struct tgsi_declaration declaration;
 
assert( file < TGSI_FILE_COUNT );
assert( interpolate < TGSI_INTERPOLATE_COUNT );
 
declaration = tgsi_default_declaration();
declaration.File = file;
declaration.UsageMask = usage_mask;
declaration.Interpolate = interpolate;
declaration.Dimension = dimension;
declaration.Semantic = semantic;
declaration.Invariant = invariant;
declaration.Local = local;
 
header_bodysize_grow( header );
 
return declaration;
}
 
static struct tgsi_declaration_range
tgsi_default_declaration_range( void )
{
struct tgsi_declaration_range dr;
 
dr.First = 0;
dr.Last = 0;
 
return dr;
}
 
static struct tgsi_declaration_range
tgsi_build_declaration_range(
unsigned first,
unsigned last,
struct tgsi_declaration *declaration,
struct tgsi_header *header )
{
struct tgsi_declaration_range declaration_range;
 
assert( last >= first );
assert( last <= 0xFFFF );
 
declaration_range.First = first;
declaration_range.Last = last;
 
declaration_grow( declaration, header );
 
return declaration_range;
}
 
static struct tgsi_declaration_dimension
tgsi_build_declaration_dimension(unsigned index_2d,
struct tgsi_declaration *declaration,
struct tgsi_header *header)
{
struct tgsi_declaration_dimension dd;
 
assert(index_2d <= 0xFFFF);
 
dd.Index2D = index_2d;
dd.Padding = 0;
 
declaration_grow(declaration, header);
 
return dd;
}
 
static struct tgsi_declaration_interp
tgsi_default_declaration_interp( void )
{
struct tgsi_declaration_interp di;
 
di.Interpolate = TGSI_INTERPOLATE_CONSTANT;
di.Centroid = 0;
di.CylindricalWrap = 0;
di.Padding = 0;
 
return di;
}
 
static struct tgsi_declaration_interp
tgsi_build_declaration_interp(unsigned interpolate,
unsigned centroid,
unsigned cylindrical_wrap,
struct tgsi_declaration *declaration,
struct tgsi_header *header)
{
struct tgsi_declaration_interp di;
 
di.Interpolate = interpolate;
di.Centroid = centroid;
di.CylindricalWrap = cylindrical_wrap;
di.Padding = 0;
 
declaration_grow(declaration, header);
 
return di;
}
 
static struct tgsi_declaration_semantic
tgsi_default_declaration_semantic( void )
{
struct tgsi_declaration_semantic ds;
 
ds.Name = TGSI_SEMANTIC_POSITION;
ds.Index = 0;
ds.Padding = 0;
 
return ds;
}
 
static struct tgsi_declaration_semantic
tgsi_build_declaration_semantic(
unsigned semantic_name,
unsigned semantic_index,
struct tgsi_declaration *declaration,
struct tgsi_header *header )
{
struct tgsi_declaration_semantic ds;
 
assert( semantic_name <= TGSI_SEMANTIC_COUNT );
assert( semantic_index <= 0xFFFF );
 
ds.Name = semantic_name;
ds.Index = semantic_index;
ds.Padding = 0;
 
declaration_grow( declaration, header );
 
return ds;
}
 
static struct tgsi_declaration_resource
tgsi_default_declaration_resource(void)
{
struct tgsi_declaration_resource dr;
 
dr.Resource = TGSI_TEXTURE_BUFFER;
dr.Raw = 0;
dr.Writable = 0;
dr.Padding = 0;
 
return dr;
}
 
static struct tgsi_declaration_resource
tgsi_build_declaration_resource(unsigned texture,
unsigned raw,
unsigned writable,
struct tgsi_declaration *declaration,
struct tgsi_header *header)
{
struct tgsi_declaration_resource dr;
 
dr = tgsi_default_declaration_resource();
dr.Resource = texture;
dr.Raw = raw;
dr.Writable = writable;
 
declaration_grow(declaration, header);
 
return dr;
}
 
static struct tgsi_declaration_sampler_view
tgsi_default_declaration_sampler_view(void)
{
struct tgsi_declaration_sampler_view dsv;
 
dsv.Resource = TGSI_TEXTURE_BUFFER;
dsv.ReturnTypeX = PIPE_TYPE_UNORM;
dsv.ReturnTypeY = PIPE_TYPE_UNORM;
dsv.ReturnTypeZ = PIPE_TYPE_UNORM;
dsv.ReturnTypeW = PIPE_TYPE_UNORM;
 
return dsv;
}
 
static struct tgsi_declaration_sampler_view
tgsi_build_declaration_sampler_view(unsigned texture,
unsigned return_type_x,
unsigned return_type_y,
unsigned return_type_z,
unsigned return_type_w,
struct tgsi_declaration *declaration,
struct tgsi_header *header)
{
struct tgsi_declaration_sampler_view dsv;
 
dsv = tgsi_default_declaration_sampler_view();
dsv.Resource = texture;
dsv.ReturnTypeX = return_type_x;
dsv.ReturnTypeY = return_type_y;
dsv.ReturnTypeZ = return_type_z;
dsv.ReturnTypeW = return_type_w;
 
declaration_grow(declaration, header);
 
return dsv;
}
 
 
static struct tgsi_declaration_array
tgsi_default_declaration_array( void )
{
struct tgsi_declaration_array a;
 
a.ArrayID = 0;
a.Padding = 0;
 
return a;
}
 
struct tgsi_full_declaration
tgsi_default_full_declaration( void )
{
struct tgsi_full_declaration full_declaration;
 
full_declaration.Declaration = tgsi_default_declaration();
full_declaration.Range = tgsi_default_declaration_range();
full_declaration.Semantic = tgsi_default_declaration_semantic();
full_declaration.Interp = tgsi_default_declaration_interp();
full_declaration.Resource = tgsi_default_declaration_resource();
full_declaration.SamplerView = tgsi_default_declaration_sampler_view();
full_declaration.Array = tgsi_default_declaration_array();
 
return full_declaration;
}
 
unsigned
tgsi_build_full_declaration(
const struct tgsi_full_declaration *full_decl,
struct tgsi_token *tokens,
struct tgsi_header *header,
unsigned maxsize )
{
unsigned size = 0;
struct tgsi_declaration *declaration;
struct tgsi_declaration_range *dr;
 
if( maxsize <= size )
return 0;
declaration = (struct tgsi_declaration *) &tokens[size];
size++;
 
*declaration = tgsi_build_declaration(
full_decl->Declaration.File,
full_decl->Declaration.UsageMask,
full_decl->Declaration.Interpolate,
full_decl->Declaration.Dimension,
full_decl->Declaration.Semantic,
full_decl->Declaration.Invariant,
full_decl->Declaration.Local,
header );
 
if (maxsize <= size)
return 0;
dr = (struct tgsi_declaration_range *) &tokens[size];
size++;
 
*dr = tgsi_build_declaration_range(
full_decl->Range.First,
full_decl->Range.Last,
declaration,
header );
 
if (full_decl->Declaration.Dimension) {
struct tgsi_declaration_dimension *dd;
 
if (maxsize <= size) {
return 0;
}
dd = (struct tgsi_declaration_dimension *)&tokens[size];
size++;
 
*dd = tgsi_build_declaration_dimension(full_decl->Dim.Index2D,
declaration,
header);
}
 
if (full_decl->Declaration.Interpolate) {
struct tgsi_declaration_interp *di;
 
if (maxsize <= size) {
return 0;
}
di = (struct tgsi_declaration_interp *)&tokens[size];
size++;
 
*di = tgsi_build_declaration_interp(full_decl->Interp.Interpolate,
full_decl->Interp.Centroid,
full_decl->Interp.CylindricalWrap,
declaration,
header);
}
 
if( full_decl->Declaration.Semantic ) {
struct tgsi_declaration_semantic *ds;
 
if( maxsize <= size )
return 0;
ds = (struct tgsi_declaration_semantic *) &tokens[size];
size++;
 
*ds = tgsi_build_declaration_semantic(
full_decl->Semantic.Name,
full_decl->Semantic.Index,
declaration,
header );
}
 
if (full_decl->Declaration.File == TGSI_FILE_RESOURCE) {
struct tgsi_declaration_resource *dr;
 
if (maxsize <= size) {
return 0;
}
dr = (struct tgsi_declaration_resource *)&tokens[size];
size++;
 
*dr = tgsi_build_declaration_resource(full_decl->Resource.Resource,
full_decl->Resource.Raw,
full_decl->Resource.Writable,
declaration,
header);
}
 
if (full_decl->Declaration.File == TGSI_FILE_SAMPLER_VIEW) {
struct tgsi_declaration_sampler_view *dsv;
 
if (maxsize <= size) {
return 0;
}
dsv = (struct tgsi_declaration_sampler_view *)&tokens[size];
size++;
 
*dsv = tgsi_build_declaration_sampler_view(
full_decl->SamplerView.Resource,
full_decl->SamplerView.ReturnTypeX,
full_decl->SamplerView.ReturnTypeY,
full_decl->SamplerView.ReturnTypeZ,
full_decl->SamplerView.ReturnTypeW,
declaration,
header);
}
 
return size;
}
 
/*
* immediate
*/
 
static struct tgsi_immediate
tgsi_default_immediate( void )
{
struct tgsi_immediate immediate;
 
immediate.Type = TGSI_TOKEN_TYPE_IMMEDIATE;
immediate.NrTokens = 1;
immediate.DataType = TGSI_IMM_FLOAT32;
immediate.Padding = 0;
 
return immediate;
}
 
static struct tgsi_immediate
tgsi_build_immediate(
struct tgsi_header *header,
unsigned type )
{
struct tgsi_immediate immediate;
 
immediate = tgsi_default_immediate();
immediate.DataType = type;
 
header_bodysize_grow( header );
 
return immediate;
}
 
struct tgsi_full_immediate
tgsi_default_full_immediate( void )
{
struct tgsi_full_immediate fullimm;
 
fullimm.Immediate = tgsi_default_immediate();
fullimm.u[0].Float = 0.0f;
fullimm.u[1].Float = 0.0f;
fullimm.u[2].Float = 0.0f;
fullimm.u[3].Float = 0.0f;
 
return fullimm;
}
 
static void
immediate_grow(
struct tgsi_immediate *immediate,
struct tgsi_header *header )
{
assert( immediate->NrTokens < 0xFF );
 
immediate->NrTokens++;
 
header_bodysize_grow( header );
}
 
unsigned
tgsi_build_full_immediate(
const struct tgsi_full_immediate *full_imm,
struct tgsi_token *tokens,
struct tgsi_header *header,
unsigned maxsize )
{
unsigned size = 0, i;
struct tgsi_immediate *immediate;
 
if( maxsize <= size )
return 0;
immediate = (struct tgsi_immediate *) &tokens[size];
size++;
 
*immediate = tgsi_build_immediate( header, full_imm->Immediate.DataType );
 
assert( full_imm->Immediate.NrTokens <= 4 + 1 );
 
for( i = 0; i < full_imm->Immediate.NrTokens - 1; i++ ) {
union tgsi_immediate_data *data;
 
if( maxsize <= size )
return 0;
 
data = (union tgsi_immediate_data *) &tokens[size];
*data = full_imm->u[i];
 
immediate_grow( immediate, header );
size++;
}
 
return size;
}
 
/*
* instruction
*/
 
struct tgsi_instruction
tgsi_default_instruction( void )
{
struct tgsi_instruction instruction;
 
instruction.Type = TGSI_TOKEN_TYPE_INSTRUCTION;
instruction.NrTokens = 0;
instruction.Opcode = TGSI_OPCODE_MOV;
instruction.Saturate = TGSI_SAT_NONE;
instruction.Predicate = 0;
instruction.NumDstRegs = 1;
instruction.NumSrcRegs = 1;
instruction.Label = 0;
instruction.Texture = 0;
instruction.Padding = 0;
 
return instruction;
}
 
static struct tgsi_instruction
tgsi_build_instruction(unsigned opcode,
unsigned saturate,
unsigned predicate,
unsigned num_dst_regs,
unsigned num_src_regs,
struct tgsi_header *header)
{
struct tgsi_instruction instruction;
 
assert (opcode <= TGSI_OPCODE_LAST);
assert (saturate <= TGSI_SAT_MINUS_PLUS_ONE);
assert (num_dst_regs <= 3);
assert (num_src_regs <= 15);
 
instruction = tgsi_default_instruction();
instruction.Opcode = opcode;
instruction.Saturate = saturate;
instruction.Predicate = predicate;
instruction.NumDstRegs = num_dst_regs;
instruction.NumSrcRegs = num_src_regs;
 
header_bodysize_grow( header );
 
return instruction;
}
 
static void
instruction_grow(
struct tgsi_instruction *instruction,
struct tgsi_header *header )
{
assert (instruction->NrTokens < 0xFF);
 
instruction->NrTokens++;
 
header_bodysize_grow( header );
}
 
struct tgsi_instruction_predicate
tgsi_default_instruction_predicate(void)
{
struct tgsi_instruction_predicate instruction_predicate;
 
instruction_predicate.SwizzleX = TGSI_SWIZZLE_X;
instruction_predicate.SwizzleY = TGSI_SWIZZLE_Y;
instruction_predicate.SwizzleZ = TGSI_SWIZZLE_Z;
instruction_predicate.SwizzleW = TGSI_SWIZZLE_W;
instruction_predicate.Negate = 0;
instruction_predicate.Index = 0;
instruction_predicate.Padding = 0;
 
return instruction_predicate;
}
 
static struct tgsi_instruction_predicate
tgsi_build_instruction_predicate(int index,
unsigned negate,
unsigned swizzleX,
unsigned swizzleY,
unsigned swizzleZ,
unsigned swizzleW,
struct tgsi_instruction *instruction,
struct tgsi_header *header)
{
struct tgsi_instruction_predicate instruction_predicate;
 
instruction_predicate = tgsi_default_instruction_predicate();
instruction_predicate.SwizzleX = swizzleX;
instruction_predicate.SwizzleY = swizzleY;
instruction_predicate.SwizzleZ = swizzleZ;
instruction_predicate.SwizzleW = swizzleW;
instruction_predicate.Negate = negate;
instruction_predicate.Index = index;
 
instruction_grow(instruction, header);
 
return instruction_predicate;
}
 
static struct tgsi_instruction_label
tgsi_default_instruction_label( void )
{
struct tgsi_instruction_label instruction_label;
 
instruction_label.Label = 0;
instruction_label.Padding = 0;
 
return instruction_label;
}
 
static struct tgsi_instruction_label
tgsi_build_instruction_label(
unsigned label,
struct tgsi_token *prev_token,
struct tgsi_instruction *instruction,
struct tgsi_header *header )
{
struct tgsi_instruction_label instruction_label;
 
instruction_label.Label = label;
instruction_label.Padding = 0;
instruction->Label = 1;
 
instruction_grow( instruction, header );
 
return instruction_label;
}
 
static struct tgsi_instruction_texture
tgsi_default_instruction_texture( void )
{
struct tgsi_instruction_texture instruction_texture;
 
instruction_texture.Texture = TGSI_TEXTURE_UNKNOWN;
instruction_texture.NumOffsets = 0;
instruction_texture.Padding = 0;
 
return instruction_texture;
}
 
static struct tgsi_instruction_texture
tgsi_build_instruction_texture(
unsigned texture,
unsigned num_offsets,
struct tgsi_token *prev_token,
struct tgsi_instruction *instruction,
struct tgsi_header *header )
{
struct tgsi_instruction_texture instruction_texture;
 
instruction_texture.Texture = texture;
instruction_texture.NumOffsets = num_offsets;
instruction_texture.Padding = 0;
instruction->Texture = 1;
 
instruction_grow( instruction, header );
 
return instruction_texture;
}
 
 
static struct tgsi_texture_offset
tgsi_default_texture_offset( void )
{
struct tgsi_texture_offset texture_offset;
 
texture_offset.Index = 0;
texture_offset.File = 0;
texture_offset.SwizzleX = 0;
texture_offset.SwizzleY = 0;
texture_offset.SwizzleZ = 0;
texture_offset.Padding = 0;
 
return texture_offset;
}
 
static struct tgsi_texture_offset
tgsi_build_texture_offset(
int index, int file, int swizzle_x, int swizzle_y, int swizzle_z,
struct tgsi_token *prev_token,
struct tgsi_instruction *instruction,
struct tgsi_header *header )
{
struct tgsi_texture_offset texture_offset;
 
texture_offset.Index = index;
texture_offset.File = file;
texture_offset.SwizzleX = swizzle_x;
texture_offset.SwizzleY = swizzle_y;
texture_offset.SwizzleZ = swizzle_z;
texture_offset.Padding = 0;
 
instruction_grow( instruction, header );
 
return texture_offset;
}
 
static struct tgsi_src_register
tgsi_default_src_register( void )
{
struct tgsi_src_register src_register;
 
src_register.File = TGSI_FILE_NULL;
src_register.SwizzleX = TGSI_SWIZZLE_X;
src_register.SwizzleY = TGSI_SWIZZLE_Y;
src_register.SwizzleZ = TGSI_SWIZZLE_Z;
src_register.SwizzleW = TGSI_SWIZZLE_W;
src_register.Negate = 0;
src_register.Absolute = 0;
src_register.Indirect = 0;
src_register.Dimension = 0;
src_register.Index = 0;
 
return src_register;
}
 
static struct tgsi_src_register
tgsi_build_src_register(
unsigned file,
unsigned swizzle_x,
unsigned swizzle_y,
unsigned swizzle_z,
unsigned swizzle_w,
unsigned negate,
unsigned absolute,
unsigned indirect,
unsigned dimension,
int index,
struct tgsi_instruction *instruction,
struct tgsi_header *header )
{
struct tgsi_src_register src_register;
 
assert( file < TGSI_FILE_COUNT );
assert( swizzle_x <= TGSI_SWIZZLE_W );
assert( swizzle_y <= TGSI_SWIZZLE_W );
assert( swizzle_z <= TGSI_SWIZZLE_W );
assert( swizzle_w <= TGSI_SWIZZLE_W );
assert( negate <= 1 );
assert( index >= -0x8000 && index <= 0x7FFF );
 
src_register.File = file;
src_register.SwizzleX = swizzle_x;
src_register.SwizzleY = swizzle_y;
src_register.SwizzleZ = swizzle_z;
src_register.SwizzleW = swizzle_w;
src_register.Negate = negate;
src_register.Absolute = absolute;
src_register.Indirect = indirect;
src_register.Dimension = dimension;
src_register.Index = index;
 
instruction_grow( instruction, header );
 
return src_register;
}
 
static struct tgsi_ind_register
tgsi_default_ind_register( void )
{
struct tgsi_ind_register ind_register;
 
ind_register.File = TGSI_FILE_NULL;
ind_register.Index = 0;
ind_register.Swizzle = TGSI_SWIZZLE_X;
ind_register.ArrayID = 0;
 
return ind_register;
}
 
static struct tgsi_ind_register
tgsi_build_ind_register(
unsigned file,
unsigned swizzle,
unsigned arrayid,
int index,
struct tgsi_instruction *instruction,
struct tgsi_header *header )
{
struct tgsi_ind_register ind_register;
 
assert( file < TGSI_FILE_COUNT );
assert( swizzle <= TGSI_SWIZZLE_W );
assert( index >= -0x8000 && index <= 0x7FFF );
 
ind_register.File = file;
ind_register.Swizzle = swizzle;
ind_register.Index = index;
ind_register.ArrayID = arrayid;
 
instruction_grow( instruction, header );
 
return ind_register;
}
 
static struct tgsi_dimension
tgsi_default_dimension( void )
{
struct tgsi_dimension dimension;
 
dimension.Indirect = 0;
dimension.Dimension = 0;
dimension.Padding = 0;
dimension.Index = 0;
 
return dimension;
}
 
static struct tgsi_full_src_register
tgsi_default_full_src_register( void )
{
struct tgsi_full_src_register full_src_register;
 
full_src_register.Register = tgsi_default_src_register();
full_src_register.Indirect = tgsi_default_ind_register();
full_src_register.Dimension = tgsi_default_dimension();
full_src_register.DimIndirect = tgsi_default_ind_register();
 
return full_src_register;
}
 
static struct tgsi_dimension
tgsi_build_dimension(
unsigned indirect,
unsigned index,
struct tgsi_instruction *instruction,
struct tgsi_header *header )
{
struct tgsi_dimension dimension;
 
dimension.Indirect = indirect;
dimension.Dimension = 0;
dimension.Padding = 0;
dimension.Index = index;
 
instruction_grow( instruction, header );
 
return dimension;
}
 
static struct tgsi_dst_register
tgsi_default_dst_register( void )
{
struct tgsi_dst_register dst_register;
 
dst_register.File = TGSI_FILE_NULL;
dst_register.WriteMask = TGSI_WRITEMASK_XYZW;
dst_register.Indirect = 0;
dst_register.Dimension = 0;
dst_register.Index = 0;
dst_register.Padding = 0;
 
return dst_register;
}
 
static struct tgsi_dst_register
tgsi_build_dst_register(
unsigned file,
unsigned mask,
unsigned indirect,
unsigned dimension,
int index,
struct tgsi_instruction *instruction,
struct tgsi_header *header )
{
struct tgsi_dst_register dst_register;
 
assert( file < TGSI_FILE_COUNT );
assert( mask <= TGSI_WRITEMASK_XYZW );
assert( index >= -32768 && index <= 32767 );
 
dst_register.File = file;
dst_register.WriteMask = mask;
dst_register.Indirect = indirect;
dst_register.Dimension = dimension;
dst_register.Index = index;
dst_register.Padding = 0;
 
instruction_grow( instruction, header );
 
return dst_register;
}
 
static struct tgsi_full_dst_register
tgsi_default_full_dst_register( void )
{
struct tgsi_full_dst_register full_dst_register;
 
full_dst_register.Register = tgsi_default_dst_register();
full_dst_register.Indirect = tgsi_default_ind_register();
full_dst_register.Dimension = tgsi_default_dimension();
full_dst_register.DimIndirect = tgsi_default_ind_register();
 
return full_dst_register;
}
 
struct tgsi_full_instruction
tgsi_default_full_instruction( void )
{
struct tgsi_full_instruction full_instruction;
unsigned i;
 
full_instruction.Instruction = tgsi_default_instruction();
full_instruction.Predicate = tgsi_default_instruction_predicate();
full_instruction.Label = tgsi_default_instruction_label();
full_instruction.Texture = tgsi_default_instruction_texture();
for( i = 0; i < TGSI_FULL_MAX_TEX_OFFSETS; i++ ) {
full_instruction.TexOffsets[i] = tgsi_default_texture_offset();
}
for( i = 0; i < TGSI_FULL_MAX_DST_REGISTERS; i++ ) {
full_instruction.Dst[i] = tgsi_default_full_dst_register();
}
for( i = 0; i < TGSI_FULL_MAX_SRC_REGISTERS; i++ ) {
full_instruction.Src[i] = tgsi_default_full_src_register();
}
 
return full_instruction;
}
 
unsigned
tgsi_build_full_instruction(
const struct tgsi_full_instruction *full_inst,
struct tgsi_token *tokens,
struct tgsi_header *header,
unsigned maxsize )
{
unsigned size = 0;
unsigned i;
struct tgsi_instruction *instruction;
struct tgsi_token *prev_token;
 
if( maxsize <= size )
return 0;
instruction = (struct tgsi_instruction *) &tokens[size];
size++;
 
*instruction = tgsi_build_instruction(full_inst->Instruction.Opcode,
full_inst->Instruction.Saturate,
full_inst->Instruction.Predicate,
full_inst->Instruction.NumDstRegs,
full_inst->Instruction.NumSrcRegs,
header);
prev_token = (struct tgsi_token *) instruction;
 
if (full_inst->Instruction.Predicate) {
struct tgsi_instruction_predicate *instruction_predicate;
 
if (maxsize <= size) {
return 0;
}
instruction_predicate = (struct tgsi_instruction_predicate *)&tokens[size];
size++;
 
*instruction_predicate =
tgsi_build_instruction_predicate(full_inst->Predicate.Index,
full_inst->Predicate.Negate,
full_inst->Predicate.SwizzleX,
full_inst->Predicate.SwizzleY,
full_inst->Predicate.SwizzleZ,
full_inst->Predicate.SwizzleW,
instruction,
header);
}
 
if (full_inst->Instruction.Label) {
struct tgsi_instruction_label *instruction_label;
 
if( maxsize <= size )
return 0;
instruction_label =
(struct tgsi_instruction_label *) &tokens[size];
size++;
 
*instruction_label = tgsi_build_instruction_label(
full_inst->Label.Label,
prev_token,
instruction,
header );
prev_token = (struct tgsi_token *) instruction_label;
}
 
if (full_inst->Instruction.Texture) {
struct tgsi_instruction_texture *instruction_texture;
 
if( maxsize <= size )
return 0;
instruction_texture =
(struct tgsi_instruction_texture *) &tokens[size];
size++;
 
*instruction_texture = tgsi_build_instruction_texture(
full_inst->Texture.Texture,
full_inst->Texture.NumOffsets,
prev_token,
instruction,
header );
prev_token = (struct tgsi_token *) instruction_texture;
 
for (i = 0; i < full_inst->Texture.NumOffsets; i++) {
struct tgsi_texture_offset *texture_offset;
if ( maxsize <= size )
return 0;
texture_offset = (struct tgsi_texture_offset *)&tokens[size];
size++;
*texture_offset = tgsi_build_texture_offset(
full_inst->TexOffsets[i].Index,
full_inst->TexOffsets[i].File,
full_inst->TexOffsets[i].SwizzleX,
full_inst->TexOffsets[i].SwizzleY,
full_inst->TexOffsets[i].SwizzleZ,
prev_token,
instruction,
header);
prev_token = (struct tgsi_token *) texture_offset;
}
}
for( i = 0; i < full_inst->Instruction.NumDstRegs; i++ ) {
const struct tgsi_full_dst_register *reg = &full_inst->Dst[i];
struct tgsi_dst_register *dst_register;
 
if( maxsize <= size )
return 0;
dst_register = (struct tgsi_dst_register *) &tokens[size];
size++;
 
*dst_register = tgsi_build_dst_register(
reg->Register.File,
reg->Register.WriteMask,
reg->Register.Indirect,
reg->Register.Dimension,
reg->Register.Index,
instruction,
header );
 
if( reg->Register.Indirect ) {
struct tgsi_ind_register *ind;
 
if( maxsize <= size )
return 0;
ind = (struct tgsi_ind_register *) &tokens[size];
size++;
 
*ind = tgsi_build_ind_register(
reg->Indirect.File,
reg->Indirect.Swizzle,
reg->Indirect.Index,
reg->Indirect.ArrayID,
instruction,
header );
}
 
if( reg->Register.Dimension ) {
struct tgsi_dimension *dim;
 
assert( !reg->Dimension.Dimension );
 
if( maxsize <= size )
return 0;
dim = (struct tgsi_dimension *) &tokens[size];
size++;
 
*dim = tgsi_build_dimension(
reg->Dimension.Indirect,
reg->Dimension.Index,
instruction,
header );
 
if( reg->Dimension.Indirect ) {
struct tgsi_ind_register *ind;
 
if( maxsize <= size )
return 0;
ind = (struct tgsi_ind_register *) &tokens[size];
size++;
 
*ind = tgsi_build_ind_register(
reg->DimIndirect.File,
reg->DimIndirect.Swizzle,
reg->DimIndirect.Index,
reg->DimIndirect.ArrayID,
instruction,
header );
}
}
}
 
for( i = 0; i < full_inst->Instruction.NumSrcRegs; i++ ) {
const struct tgsi_full_src_register *reg = &full_inst->Src[i];
struct tgsi_src_register *src_register;
 
if( maxsize <= size )
return 0;
src_register = (struct tgsi_src_register *) &tokens[size];
size++;
 
*src_register = tgsi_build_src_register(
reg->Register.File,
reg->Register.SwizzleX,
reg->Register.SwizzleY,
reg->Register.SwizzleZ,
reg->Register.SwizzleW,
reg->Register.Negate,
reg->Register.Absolute,
reg->Register.Indirect,
reg->Register.Dimension,
reg->Register.Index,
instruction,
header );
 
if( reg->Register.Indirect ) {
struct tgsi_ind_register *ind;
 
if( maxsize <= size )
return 0;
ind = (struct tgsi_ind_register *) &tokens[size];
size++;
 
*ind = tgsi_build_ind_register(
reg->Indirect.File,
reg->Indirect.Swizzle,
reg->Indirect.Index,
reg->Indirect.ArrayID,
instruction,
header );
}
 
if( reg->Register.Dimension ) {
struct tgsi_dimension *dim;
 
assert( !reg->Dimension.Dimension );
 
if( maxsize <= size )
return 0;
dim = (struct tgsi_dimension *) &tokens[size];
size++;
 
*dim = tgsi_build_dimension(
reg->Dimension.Indirect,
reg->Dimension.Index,
instruction,
header );
 
if( reg->Dimension.Indirect ) {
struct tgsi_ind_register *ind;
 
if( maxsize <= size )
return 0;
ind = (struct tgsi_ind_register *) &tokens[size];
size++;
 
*ind = tgsi_build_ind_register(
reg->DimIndirect.File,
reg->DimIndirect.Swizzle,
reg->DimIndirect.Index,
reg->DimIndirect.ArrayID,
instruction,
header );
}
}
}
 
return size;
}
 
static struct tgsi_property
tgsi_default_property( void )
{
struct tgsi_property property;
 
property.Type = TGSI_TOKEN_TYPE_PROPERTY;
property.NrTokens = 1;
property.PropertyName = TGSI_PROPERTY_GS_INPUT_PRIM;
property.Padding = 0;
 
return property;
}
 
static struct tgsi_property
tgsi_build_property(unsigned property_name,
struct tgsi_header *header)
{
struct tgsi_property property;
 
property = tgsi_default_property();
property.PropertyName = property_name;
 
header_bodysize_grow( header );
 
return property;
}
 
 
struct tgsi_full_property
tgsi_default_full_property( void )
{
struct tgsi_full_property full_property;
 
full_property.Property = tgsi_default_property();
memset(full_property.u, 0,
sizeof(struct tgsi_property_data) * 8);
 
return full_property;
}
 
static void
property_grow(
struct tgsi_property *property,
struct tgsi_header *header )
{
assert( property->NrTokens < 0xFF );
 
property->NrTokens++;
 
header_bodysize_grow( header );
}
 
static struct tgsi_property_data
tgsi_build_property_data(
unsigned value,
struct tgsi_property *property,
struct tgsi_header *header )
{
struct tgsi_property_data property_data;
 
property_data.Data = value;
 
property_grow( property, header );
 
return property_data;
}
 
unsigned
tgsi_build_full_property(
const struct tgsi_full_property *full_prop,
struct tgsi_token *tokens,
struct tgsi_header *header,
unsigned maxsize )
{
unsigned size = 0, i;
struct tgsi_property *property;
 
if( maxsize <= size )
return 0;
property = (struct tgsi_property *) &tokens[size];
size++;
 
*property = tgsi_build_property(
full_prop->Property.PropertyName,
header );
 
assert( full_prop->Property.NrTokens <= 8 + 1 );
 
for( i = 0; i < full_prop->Property.NrTokens - 1; i++ ) {
struct tgsi_property_data *data;
 
if( maxsize <= size )
return 0;
data = (struct tgsi_property_data *) &tokens[size];
size++;
 
*data = tgsi_build_property_data(
full_prop->u[i].Data,
property,
header );
}
 
return size;
}
/drivers/video/Gallium/auxiliary/tgsi/tgsi_build.h
0,0 → 1,118
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
#ifndef TGSI_BUILD_H
#define TGSI_BUILD_H
 
 
struct tgsi_token;
 
 
#if defined __cplusplus
extern "C" {
#endif
 
 
/*
* header
*/
 
struct tgsi_header
tgsi_build_header( void );
 
struct tgsi_processor
tgsi_build_processor(
unsigned processor,
struct tgsi_header *header );
 
/*
* declaration
*/
 
struct tgsi_full_declaration
tgsi_default_full_declaration( void );
 
unsigned
tgsi_build_full_declaration(
const struct tgsi_full_declaration *full_decl,
struct tgsi_token *tokens,
struct tgsi_header *header,
unsigned maxsize );
 
/*
* immediate
*/
 
struct tgsi_full_immediate
tgsi_default_full_immediate( void );
 
unsigned
tgsi_build_full_immediate(
const struct tgsi_full_immediate *full_imm,
struct tgsi_token *tokens,
struct tgsi_header *header,
unsigned maxsize );
 
/*
* properties
*/
 
struct tgsi_full_property
tgsi_default_full_property( void );
 
unsigned
tgsi_build_full_property(
const struct tgsi_full_property *full_prop,
struct tgsi_token *tokens,
struct tgsi_header *header,
unsigned maxsize );
 
/*
* instruction
*/
 
struct tgsi_instruction
tgsi_default_instruction( void );
 
struct tgsi_full_instruction
tgsi_default_full_instruction( void );
 
unsigned
tgsi_build_full_instruction(
const struct tgsi_full_instruction *full_inst,
struct tgsi_token *tokens,
struct tgsi_header *header,
unsigned maxsize );
 
struct tgsi_instruction_predicate
tgsi_default_instruction_predicate(void);
 
#if defined __cplusplus
}
#endif
 
#endif /* TGSI_BUILD_H */
/drivers/video/Gallium/auxiliary/tgsi/tgsi_dump.c
0,0 → 1,723
/**************************************************************************
*
* Copyright 2007-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.
*
**************************************************************************/
 
#include "util/u_debug.h"
#include "util/u_string.h"
#include "util/u_math.h"
#include "util/u_memory.h"
#include "tgsi_dump.h"
#include "tgsi_info.h"
#include "tgsi_iterate.h"
#include "tgsi_strings.h"
 
 
/** Number of spaces to indent for IF/LOOP/etc */
static const int indent_spaces = 3;
 
 
struct dump_ctx
{
struct tgsi_iterate_context iter;
 
uint instno;
uint immno;
int indent;
uint indentation;
 
void (*dump_printf)(struct dump_ctx *ctx, const char *format, ...);
};
 
static void
dump_ctx_printf(struct dump_ctx *ctx, const char *format, ...)
{
va_list ap;
(void)ctx;
va_start(ap, format);
_debug_vprintf(format, ap);
va_end(ap);
}
 
static void
dump_enum(
struct dump_ctx *ctx,
uint e,
const char **enums,
uint enum_count )
{
if (e >= enum_count)
ctx->dump_printf( ctx, "%u", e );
else
ctx->dump_printf( ctx, "%s", enums[e] );
}
 
#define EOL() ctx->dump_printf( ctx, "\n" )
#define TXT(S) ctx->dump_printf( ctx, "%s", S )
#define CHR(C) ctx->dump_printf( ctx, "%c", C )
#define UIX(I) ctx->dump_printf( ctx, "0x%x", I )
#define UID(I) ctx->dump_printf( ctx, "%u", I )
#define INSTID(I) ctx->dump_printf( ctx, "% 3u", I )
#define SID(I) ctx->dump_printf( ctx, "%d", I )
#define FLT(F) ctx->dump_printf( ctx, "%10.4f", F )
#define ENM(E,ENUMS) dump_enum( ctx, E, ENUMS, sizeof( ENUMS ) / sizeof( *ENUMS ) )
 
const char *
tgsi_swizzle_names[4] =
{
"x",
"y",
"z",
"w"
};
 
static void
_dump_register_src(
struct dump_ctx *ctx,
const struct tgsi_full_src_register *src )
{
TXT(tgsi_file_name(src->Register.File));
if (src->Register.Dimension) {
if (src->Dimension.Indirect) {
CHR( '[' );
TXT(tgsi_file_name(src->DimIndirect.File));
CHR( '[' );
SID( src->DimIndirect.Index );
TXT( "]." );
ENM( src->DimIndirect.Swizzle, tgsi_swizzle_names );
if (src->Dimension.Index != 0) {
if (src->Dimension.Index > 0)
CHR( '+' );
SID( src->Dimension.Index );
}
CHR( ']' );
if (src->DimIndirect.ArrayID) {
CHR( '(' );
SID( src->DimIndirect.ArrayID );
CHR( ')' );
}
} else {
CHR('[');
SID(src->Dimension.Index);
CHR(']');
}
}
if (src->Register.Indirect) {
CHR( '[' );
TXT(tgsi_file_name(src->Indirect.File));
CHR( '[' );
SID( src->Indirect.Index );
TXT( "]." );
ENM( src->Indirect.Swizzle, tgsi_swizzle_names );
if (src->Register.Index != 0) {
if (src->Register.Index > 0)
CHR( '+' );
SID( src->Register.Index );
}
CHR( ']' );
if (src->Indirect.ArrayID) {
CHR( '(' );
SID( src->Indirect.ArrayID );
CHR( ')' );
}
} else {
CHR( '[' );
SID( src->Register.Index );
CHR( ']' );
}
}
 
 
static void
_dump_register_dst(
struct dump_ctx *ctx,
const struct tgsi_full_dst_register *dst )
{
TXT(tgsi_file_name(dst->Register.File));
if (dst->Register.Dimension) {
if (dst->Dimension.Indirect) {
CHR( '[' );
TXT(tgsi_file_name(dst->DimIndirect.File));
CHR( '[' );
SID( dst->DimIndirect.Index );
TXT( "]." );
ENM( dst->DimIndirect.Swizzle, tgsi_swizzle_names );
if (dst->Dimension.Index != 0) {
if (dst->Dimension.Index > 0)
CHR( '+' );
SID( dst->Dimension.Index );
}
CHR( ']' );
if (dst->DimIndirect.ArrayID) {
CHR( '(' );
SID( dst->DimIndirect.ArrayID );
CHR( ')' );
}
} else {
CHR('[');
SID(dst->Dimension.Index);
CHR(']');
}
}
if (dst->Register.Indirect) {
CHR( '[' );
TXT(tgsi_file_name(dst->Indirect.File));
CHR( '[' );
SID( dst->Indirect.Index );
TXT( "]." );
ENM( dst->Indirect.Swizzle, tgsi_swizzle_names );
if (dst->Register.Index != 0) {
if (dst->Register.Index > 0)
CHR( '+' );
SID( dst->Register.Index );
}
CHR( ']' );
if (dst->Indirect.ArrayID) {
CHR( '(' );
SID( dst->Indirect.ArrayID );
CHR( ')' );
}
} else {
CHR( '[' );
SID( dst->Register.Index );
CHR( ']' );
}
}
static void
_dump_writemask(
struct dump_ctx *ctx,
uint writemask )
{
if (writemask != TGSI_WRITEMASK_XYZW) {
CHR( '.' );
if (writemask & TGSI_WRITEMASK_X)
CHR( 'x' );
if (writemask & TGSI_WRITEMASK_Y)
CHR( 'y' );
if (writemask & TGSI_WRITEMASK_Z)
CHR( 'z' );
if (writemask & TGSI_WRITEMASK_W)
CHR( 'w' );
}
}
 
static void
dump_imm_data(struct tgsi_iterate_context *iter,
union tgsi_immediate_data *data,
unsigned num_tokens,
unsigned data_type)
{
struct dump_ctx *ctx = (struct dump_ctx *)iter;
unsigned i ;
 
TXT( " {" );
 
assert( num_tokens <= 4 );
for (i = 0; i < num_tokens; i++) {
switch (data_type) {
case TGSI_IMM_FLOAT32:
FLT( data[i].Float );
break;
case TGSI_IMM_UINT32:
UID(data[i].Uint);
break;
case TGSI_IMM_INT32:
SID(data[i].Int);
break;
default:
assert( 0 );
}
 
if (i < num_tokens - 1)
TXT( ", " );
}
TXT( "}" );
}
 
static boolean
iter_declaration(
struct tgsi_iterate_context *iter,
struct tgsi_full_declaration *decl )
{
struct dump_ctx *ctx = (struct dump_ctx *)iter;
 
TXT( "DCL " );
 
TXT(tgsi_file_name(decl->Declaration.File));
 
/* all geometry shader inputs are two dimensional */
if (decl->Declaration.File == TGSI_FILE_INPUT &&
iter->processor.Processor == TGSI_PROCESSOR_GEOMETRY) {
TXT("[]");
}
 
if (decl->Declaration.Dimension) {
CHR('[');
SID(decl->Dim.Index2D);
CHR(']');
}
 
CHR('[');
SID(decl->Range.First);
if (decl->Range.First != decl->Range.Last) {
TXT("..");
SID(decl->Range.Last);
}
CHR(']');
 
_dump_writemask(
ctx,
decl->Declaration.UsageMask );
 
if (decl->Declaration.Array) {
TXT( ", ARRAY(" );
SID(decl->Array.ArrayID);
CHR(')');
}
 
if (decl->Declaration.Local)
TXT( ", LOCAL" );
 
if (decl->Declaration.Semantic) {
TXT( ", " );
ENM( decl->Semantic.Name, tgsi_semantic_names );
if (decl->Semantic.Index != 0 ||
decl->Semantic.Name == TGSI_SEMANTIC_TEXCOORD ||
decl->Semantic.Name == TGSI_SEMANTIC_GENERIC) {
CHR( '[' );
UID( decl->Semantic.Index );
CHR( ']' );
}
}
 
if (decl->Declaration.File == TGSI_FILE_RESOURCE) {
TXT(", ");
ENM(decl->Resource.Resource, tgsi_texture_names);
if (decl->Resource.Writable)
TXT(", WR");
if (decl->Resource.Raw)
TXT(", RAW");
}
 
if (decl->Declaration.File == TGSI_FILE_SAMPLER_VIEW) {
TXT(", ");
ENM(decl->SamplerView.Resource, tgsi_texture_names);
TXT(", ");
if ((decl->SamplerView.ReturnTypeX == decl->SamplerView.ReturnTypeY) &&
(decl->SamplerView.ReturnTypeX == decl->SamplerView.ReturnTypeZ) &&
(decl->SamplerView.ReturnTypeX == decl->SamplerView.ReturnTypeW)) {
ENM(decl->SamplerView.ReturnTypeX, tgsi_type_names);
} else {
ENM(decl->SamplerView.ReturnTypeX, tgsi_type_names);
TXT(", ");
ENM(decl->SamplerView.ReturnTypeY, tgsi_type_names);
TXT(", ");
ENM(decl->SamplerView.ReturnTypeZ, tgsi_type_names);
TXT(", ");
ENM(decl->SamplerView.ReturnTypeW, tgsi_type_names);
}
}
 
if (decl->Declaration.Interpolate) {
if (iter->processor.Processor == TGSI_PROCESSOR_FRAGMENT &&
decl->Declaration.File == TGSI_FILE_INPUT)
{
TXT( ", " );
ENM( decl->Interp.Interpolate, tgsi_interpolate_names );
}
 
if (decl->Interp.Centroid) {
TXT( ", CENTROID" );
}
 
if (decl->Interp.CylindricalWrap) {
TXT(", CYLWRAP_");
if (decl->Interp.CylindricalWrap & TGSI_CYLINDRICAL_WRAP_X) {
CHR('X');
}
if (decl->Interp.CylindricalWrap & TGSI_CYLINDRICAL_WRAP_Y) {
CHR('Y');
}
if (decl->Interp.CylindricalWrap & TGSI_CYLINDRICAL_WRAP_Z) {
CHR('Z');
}
if (decl->Interp.CylindricalWrap & TGSI_CYLINDRICAL_WRAP_W) {
CHR('W');
}
}
}
 
if (decl->Declaration.Invariant) {
TXT( ", INVARIANT" );
}
 
EOL();
 
return TRUE;
}
 
void
tgsi_dump_declaration(
const struct tgsi_full_declaration *decl )
{
struct dump_ctx ctx;
 
ctx.dump_printf = dump_ctx_printf;
 
iter_declaration( &ctx.iter, (struct tgsi_full_declaration *)decl );
}
 
static boolean
iter_property(
struct tgsi_iterate_context *iter,
struct tgsi_full_property *prop )
{
unsigned i;
struct dump_ctx *ctx = (struct dump_ctx *)iter;
 
TXT( "PROPERTY " );
ENM(prop->Property.PropertyName, tgsi_property_names);
 
if (prop->Property.NrTokens > 1)
TXT(" ");
 
for (i = 0; i < prop->Property.NrTokens - 1; ++i) {
switch (prop->Property.PropertyName) {
case TGSI_PROPERTY_GS_INPUT_PRIM:
case TGSI_PROPERTY_GS_OUTPUT_PRIM:
ENM(prop->u[i].Data, tgsi_primitive_names);
break;
case TGSI_PROPERTY_FS_COORD_ORIGIN:
ENM(prop->u[i].Data, tgsi_fs_coord_origin_names);
break;
case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER:
ENM(prop->u[i].Data, tgsi_fs_coord_pixel_center_names);
break;
default:
SID( prop->u[i].Data );
break;
}
if (i < prop->Property.NrTokens - 2)
TXT( ", " );
}
EOL();
 
return TRUE;
}
 
void tgsi_dump_property(
const struct tgsi_full_property *prop )
{
struct dump_ctx ctx;
 
ctx.dump_printf = dump_ctx_printf;
 
iter_property( &ctx.iter, (struct tgsi_full_property *)prop );
}
 
static boolean
iter_immediate(
struct tgsi_iterate_context *iter,
struct tgsi_full_immediate *imm )
{
struct dump_ctx *ctx = (struct dump_ctx *) iter;
 
TXT( "IMM[" );
SID( ctx->immno++ );
TXT( "] " );
ENM( imm->Immediate.DataType, tgsi_immediate_type_names );
 
dump_imm_data(iter, imm->u, imm->Immediate.NrTokens - 1,
imm->Immediate.DataType);
 
EOL();
 
return TRUE;
}
 
void
tgsi_dump_immediate(
const struct tgsi_full_immediate *imm )
{
struct dump_ctx ctx;
 
ctx.dump_printf = dump_ctx_printf;
 
iter_immediate( &ctx.iter, (struct tgsi_full_immediate *)imm );
}
 
static boolean
iter_instruction(
struct tgsi_iterate_context *iter,
struct tgsi_full_instruction *inst )
{
struct dump_ctx *ctx = (struct dump_ctx *) iter;
uint instno = ctx->instno++;
const struct tgsi_opcode_info *info = tgsi_get_opcode_info( inst->Instruction.Opcode );
uint i;
boolean first_reg = TRUE;
 
INSTID( instno );
TXT( ": " );
 
ctx->indent -= info->pre_dedent;
for(i = 0; (int)i < ctx->indent; ++i)
TXT( " " );
ctx->indent += info->post_indent;
 
if (inst->Instruction.Predicate) {
CHR( '(' );
 
if (inst->Predicate.Negate)
CHR( '!' );
 
TXT( "PRED[" );
SID( inst->Predicate.Index );
CHR( ']' );
 
if (inst->Predicate.SwizzleX != TGSI_SWIZZLE_X ||
inst->Predicate.SwizzleY != TGSI_SWIZZLE_Y ||
inst->Predicate.SwizzleZ != TGSI_SWIZZLE_Z ||
inst->Predicate.SwizzleW != TGSI_SWIZZLE_W) {
CHR( '.' );
ENM( inst->Predicate.SwizzleX, tgsi_swizzle_names );
ENM( inst->Predicate.SwizzleY, tgsi_swizzle_names );
ENM( inst->Predicate.SwizzleZ, tgsi_swizzle_names );
ENM( inst->Predicate.SwizzleW, tgsi_swizzle_names );
}
 
TXT( ") " );
}
 
TXT( info->mnemonic );
 
switch (inst->Instruction.Saturate) {
case TGSI_SAT_NONE:
break;
case TGSI_SAT_ZERO_ONE:
TXT( "_SAT" );
break;
case TGSI_SAT_MINUS_PLUS_ONE:
TXT( "_SATNV" );
break;
default:
assert( 0 );
}
 
for (i = 0; i < inst->Instruction.NumDstRegs; i++) {
const struct tgsi_full_dst_register *dst = &inst->Dst[i];
 
if (!first_reg)
CHR( ',' );
CHR( ' ' );
 
_dump_register_dst( ctx, dst );
_dump_writemask( ctx, dst->Register.WriteMask );
 
first_reg = FALSE;
}
 
for (i = 0; i < inst->Instruction.NumSrcRegs; i++) {
const struct tgsi_full_src_register *src = &inst->Src[i];
 
if (!first_reg)
CHR( ',' );
CHR( ' ' );
 
if (src->Register.Negate)
CHR( '-' );
if (src->Register.Absolute)
CHR( '|' );
 
_dump_register_src(ctx, src);
 
if (src->Register.SwizzleX != TGSI_SWIZZLE_X ||
src->Register.SwizzleY != TGSI_SWIZZLE_Y ||
src->Register.SwizzleZ != TGSI_SWIZZLE_Z ||
src->Register.SwizzleW != TGSI_SWIZZLE_W) {
CHR( '.' );
ENM( src->Register.SwizzleX, tgsi_swizzle_names );
ENM( src->Register.SwizzleY, tgsi_swizzle_names );
ENM( src->Register.SwizzleZ, tgsi_swizzle_names );
ENM( src->Register.SwizzleW, tgsi_swizzle_names );
}
 
if (src->Register.Absolute)
CHR( '|' );
 
first_reg = FALSE;
}
 
if (inst->Instruction.Texture) {
TXT( ", " );
ENM( inst->Texture.Texture, tgsi_texture_names );
for (i = 0; i < inst->Texture.NumOffsets; i++) {
TXT( ", " );
TXT(tgsi_file_name(inst->TexOffsets[i].File));
CHR( '[' );
SID( inst->TexOffsets[i].Index );
CHR( ']' );
CHR( '.' );
ENM( inst->TexOffsets[i].SwizzleX, tgsi_swizzle_names);
ENM( inst->TexOffsets[i].SwizzleY, tgsi_swizzle_names);
ENM( inst->TexOffsets[i].SwizzleZ, tgsi_swizzle_names);
}
}
 
switch (inst->Instruction.Opcode) {
case TGSI_OPCODE_IF:
case TGSI_OPCODE_UIF:
case TGSI_OPCODE_ELSE:
case TGSI_OPCODE_BGNLOOP:
case TGSI_OPCODE_ENDLOOP:
case TGSI_OPCODE_CAL:
TXT( " :" );
UID( inst->Label.Label );
break;
}
 
/* update indentation */
if (inst->Instruction.Opcode == TGSI_OPCODE_IF ||
inst->Instruction.Opcode == TGSI_OPCODE_UIF ||
inst->Instruction.Opcode == TGSI_OPCODE_ELSE ||
inst->Instruction.Opcode == TGSI_OPCODE_BGNLOOP) {
ctx->indentation += indent_spaces;
}
 
EOL();
 
return TRUE;
}
 
void
tgsi_dump_instruction(
const struct tgsi_full_instruction *inst,
uint instno )
{
struct dump_ctx ctx;
 
ctx.instno = instno;
ctx.immno = instno;
ctx.indent = 0;
ctx.dump_printf = dump_ctx_printf;
ctx.indentation = 0;
 
iter_instruction( &ctx.iter, (struct tgsi_full_instruction *)inst );
}
 
static boolean
prolog(
struct tgsi_iterate_context *iter )
{
struct dump_ctx *ctx = (struct dump_ctx *) iter;
ENM( iter->processor.Processor, tgsi_processor_type_names );
EOL();
return TRUE;
}
 
void
tgsi_dump(
const struct tgsi_token *tokens,
uint flags )
{
struct dump_ctx ctx;
 
ctx.iter.prolog = prolog;
ctx.iter.iterate_instruction = iter_instruction;
ctx.iter.iterate_declaration = iter_declaration;
ctx.iter.iterate_immediate = iter_immediate;
ctx.iter.iterate_property = iter_property;
ctx.iter.epilog = NULL;
 
ctx.instno = 0;
ctx.immno = 0;
ctx.indent = 0;
ctx.dump_printf = dump_ctx_printf;
ctx.indentation = 0;
 
tgsi_iterate_shader( tokens, &ctx.iter );
}
 
struct str_dump_ctx
{
struct dump_ctx base;
char *str;
char *ptr;
int left;
};
 
static void
str_dump_ctx_printf(struct dump_ctx *ctx, const char *format, ...)
{
struct str_dump_ctx *sctx = (struct str_dump_ctx *)ctx;
if(sctx->left > 1) {
int written;
va_list ap;
va_start(ap, format);
written = util_vsnprintf(sctx->ptr, sctx->left, format, ap);
va_end(ap);
 
/* Some complicated logic needed to handle the return value of
* vsnprintf:
*/
if (written > 0) {
written = MIN2(sctx->left, written);
sctx->ptr += written;
sctx->left -= written;
}
}
}
 
void
tgsi_dump_str(
const struct tgsi_token *tokens,
uint flags,
char *str,
size_t size)
{
struct str_dump_ctx ctx;
 
ctx.base.iter.prolog = prolog;
ctx.base.iter.iterate_instruction = iter_instruction;
ctx.base.iter.iterate_declaration = iter_declaration;
ctx.base.iter.iterate_immediate = iter_immediate;
ctx.base.iter.iterate_property = iter_property;
ctx.base.iter.epilog = NULL;
 
ctx.base.instno = 0;
ctx.base.immno = 0;
ctx.base.indent = 0;
ctx.base.dump_printf = &str_dump_ctx_printf;
ctx.base.indentation = 0;
 
ctx.str = str;
ctx.str[0] = 0;
ctx.ptr = str;
ctx.left = (int)size;
 
tgsi_iterate_shader( tokens, &ctx.base.iter );
}
/drivers/video/Gallium/auxiliary/tgsi/tgsi_dump.h
0,0 → 1,77
/**************************************************************************
*
* Copyright 2007-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.
*
**************************************************************************/
 
#ifndef TGSI_DUMP_H
#define TGSI_DUMP_H
 
#include "pipe/p_compiler.h"
#include "pipe/p_defines.h"
#include "pipe/p_shader_tokens.h"
 
#if defined __cplusplus
extern "C" {
#endif
 
void
tgsi_dump_str(
const struct tgsi_token *tokens,
uint flags,
char *str,
size_t size);
 
void
tgsi_dump(
const struct tgsi_token *tokens,
uint flags );
 
struct tgsi_full_immediate;
struct tgsi_full_instruction;
struct tgsi_full_declaration;
struct tgsi_full_property;
 
void
tgsi_dump_immediate(
const struct tgsi_full_immediate *imm );
 
void
tgsi_dump_instruction(
const struct tgsi_full_instruction *inst,
uint instno );
 
void
tgsi_dump_declaration(
const struct tgsi_full_declaration *decl );
 
void
tgsi_dump_property(
const struct tgsi_full_property *prop );
 
#if defined __cplusplus
}
#endif
 
#endif /* TGSI_DUMP_H */
/drivers/video/Gallium/auxiliary/tgsi/tgsi_exec.c
0,0 → 1,4431
/**************************************************************************
*
* Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
* Copyright 2009-2010 VMware, Inc. 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.
*
**************************************************************************/
 
/**
* TGSI interpreter/executor.
*
* Flow control information:
*
* Since we operate on 'quads' (4 pixels or 4 vertices in parallel)
* flow control statements (IF/ELSE/ENDIF, LOOP/ENDLOOP) require special
* care since a condition may be true for some quad components but false
* for other components.
*
* We basically execute all statements (even if they're in the part of
* an IF/ELSE clause that's "not taken") and use a special mask to
* control writing to destination registers. This is the ExecMask.
* See store_dest().
*
* The ExecMask is computed from three other masks (CondMask, LoopMask and
* ContMask) which are controlled by the flow control instructions (namely:
* (IF/ELSE/ENDIF, LOOP/ENDLOOP and CONT).
*
*
* Authors:
* Michal Krol
* Brian Paul
*/
 
#include "pipe/p_compiler.h"
#include "pipe/p_state.h"
#include "pipe/p_shader_tokens.h"
#include "tgsi/tgsi_dump.h"
#include "tgsi/tgsi_parse.h"
#include "tgsi/tgsi_util.h"
#include "tgsi_exec.h"
#include "util/u_memory.h"
#include "util/u_math.h"
 
 
#define DEBUG_EXECUTION 0
 
 
#define FAST_MATH 0
 
#define TILE_TOP_LEFT 0
#define TILE_TOP_RIGHT 1
#define TILE_BOTTOM_LEFT 2
#define TILE_BOTTOM_RIGHT 3
 
static void
micro_abs(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->f[0] = fabsf(src->f[0]);
dst->f[1] = fabsf(src->f[1]);
dst->f[2] = fabsf(src->f[2]);
dst->f[3] = fabsf(src->f[3]);
}
 
static void
micro_arl(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->i[0] = (int)floorf(src->f[0]);
dst->i[1] = (int)floorf(src->f[1]);
dst->i[2] = (int)floorf(src->f[2]);
dst->i[3] = (int)floorf(src->f[3]);
}
 
static void
micro_arr(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->i[0] = (int)floorf(src->f[0] + 0.5f);
dst->i[1] = (int)floorf(src->f[1] + 0.5f);
dst->i[2] = (int)floorf(src->f[2] + 0.5f);
dst->i[3] = (int)floorf(src->f[3] + 0.5f);
}
 
static void
micro_ceil(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->f[0] = ceilf(src->f[0]);
dst->f[1] = ceilf(src->f[1]);
dst->f[2] = ceilf(src->f[2]);
dst->f[3] = ceilf(src->f[3]);
}
 
static void
micro_clamp(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1,
const union tgsi_exec_channel *src2)
{
dst->f[0] = src0->f[0] < src1->f[0] ? src1->f[0] : src0->f[0] > src2->f[0] ? src2->f[0] : src0->f[0];
dst->f[1] = src0->f[1] < src1->f[1] ? src1->f[1] : src0->f[1] > src2->f[1] ? src2->f[1] : src0->f[1];
dst->f[2] = src0->f[2] < src1->f[2] ? src1->f[2] : src0->f[2] > src2->f[2] ? src2->f[2] : src0->f[2];
dst->f[3] = src0->f[3] < src1->f[3] ? src1->f[3] : src0->f[3] > src2->f[3] ? src2->f[3] : src0->f[3];
}
 
static void
micro_cmp(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1,
const union tgsi_exec_channel *src2)
{
dst->f[0] = src0->f[0] < 0.0f ? src1->f[0] : src2->f[0];
dst->f[1] = src0->f[1] < 0.0f ? src1->f[1] : src2->f[1];
dst->f[2] = src0->f[2] < 0.0f ? src1->f[2] : src2->f[2];
dst->f[3] = src0->f[3] < 0.0f ? src1->f[3] : src2->f[3];
}
 
static void
micro_cnd(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1,
const union tgsi_exec_channel *src2)
{
dst->f[0] = src2->f[0] > 0.5f ? src0->f[0] : src1->f[0];
dst->f[1] = src2->f[1] > 0.5f ? src0->f[1] : src1->f[1];
dst->f[2] = src2->f[2] > 0.5f ? src0->f[2] : src1->f[2];
dst->f[3] = src2->f[3] > 0.5f ? src0->f[3] : src1->f[3];
}
 
static void
micro_cos(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->f[0] = cosf(src->f[0]);
dst->f[1] = cosf(src->f[1]);
dst->f[2] = cosf(src->f[2]);
dst->f[3] = cosf(src->f[3]);
}
 
static void
micro_ddx(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->f[0] =
dst->f[1] =
dst->f[2] =
dst->f[3] = src->f[TILE_BOTTOM_RIGHT] - src->f[TILE_BOTTOM_LEFT];
}
 
static void
micro_ddy(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->f[0] =
dst->f[1] =
dst->f[2] =
dst->f[3] = src->f[TILE_BOTTOM_LEFT] - src->f[TILE_TOP_LEFT];
}
 
static void
micro_exp2(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
#if FAST_MATH
dst->f[0] = util_fast_exp2(src->f[0]);
dst->f[1] = util_fast_exp2(src->f[1]);
dst->f[2] = util_fast_exp2(src->f[2]);
dst->f[3] = util_fast_exp2(src->f[3]);
#else
#if DEBUG
/* Inf is okay for this instruction, so clamp it to silence assertions. */
uint i;
union tgsi_exec_channel clamped;
 
for (i = 0; i < 4; i++) {
if (src->f[i] > 127.99999f) {
clamped.f[i] = 127.99999f;
} else if (src->f[i] < -126.99999f) {
clamped.f[i] = -126.99999f;
} else {
clamped.f[i] = src->f[i];
}
}
src = &clamped;
#endif /* DEBUG */
 
dst->f[0] = powf(2.0f, src->f[0]);
dst->f[1] = powf(2.0f, src->f[1]);
dst->f[2] = powf(2.0f, src->f[2]);
dst->f[3] = powf(2.0f, src->f[3]);
#endif /* FAST_MATH */
}
 
static void
micro_flr(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->f[0] = floorf(src->f[0]);
dst->f[1] = floorf(src->f[1]);
dst->f[2] = floorf(src->f[2]);
dst->f[3] = floorf(src->f[3]);
}
 
static void
micro_frc(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->f[0] = src->f[0] - floorf(src->f[0]);
dst->f[1] = src->f[1] - floorf(src->f[1]);
dst->f[2] = src->f[2] - floorf(src->f[2]);
dst->f[3] = src->f[3] - floorf(src->f[3]);
}
 
static void
micro_iabs(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->i[0] = src->i[0] >= 0 ? src->i[0] : -src->i[0];
dst->i[1] = src->i[1] >= 0 ? src->i[1] : -src->i[1];
dst->i[2] = src->i[2] >= 0 ? src->i[2] : -src->i[2];
dst->i[3] = src->i[3] >= 0 ? src->i[3] : -src->i[3];
}
 
static void
micro_ineg(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->i[0] = -src->i[0];
dst->i[1] = -src->i[1];
dst->i[2] = -src->i[2];
dst->i[3] = -src->i[3];
}
 
static void
micro_lg2(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
#if FAST_MATH
dst->f[0] = util_fast_log2(src->f[0]);
dst->f[1] = util_fast_log2(src->f[1]);
dst->f[2] = util_fast_log2(src->f[2]);
dst->f[3] = util_fast_log2(src->f[3]);
#else
dst->f[0] = logf(src->f[0]) * 1.442695f;
dst->f[1] = logf(src->f[1]) * 1.442695f;
dst->f[2] = logf(src->f[2]) * 1.442695f;
dst->f[3] = logf(src->f[3]) * 1.442695f;
#endif
}
 
static void
micro_lrp(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1,
const union tgsi_exec_channel *src2)
{
dst->f[0] = src0->f[0] * (src1->f[0] - src2->f[0]) + src2->f[0];
dst->f[1] = src0->f[1] * (src1->f[1] - src2->f[1]) + src2->f[1];
dst->f[2] = src0->f[2] * (src1->f[2] - src2->f[2]) + src2->f[2];
dst->f[3] = src0->f[3] * (src1->f[3] - src2->f[3]) + src2->f[3];
}
 
static void
micro_mad(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1,
const union tgsi_exec_channel *src2)
{
dst->f[0] = src0->f[0] * src1->f[0] + src2->f[0];
dst->f[1] = src0->f[1] * src1->f[1] + src2->f[1];
dst->f[2] = src0->f[2] * src1->f[2] + src2->f[2];
dst->f[3] = src0->f[3] * src1->f[3] + src2->f[3];
}
 
static void
micro_mov(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->u[0] = src->u[0];
dst->u[1] = src->u[1];
dst->u[2] = src->u[2];
dst->u[3] = src->u[3];
}
 
static void
micro_rcp(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
#if 0 /* for debugging */
assert(src->f[0] != 0.0f);
assert(src->f[1] != 0.0f);
assert(src->f[2] != 0.0f);
assert(src->f[3] != 0.0f);
#endif
dst->f[0] = 1.0f / src->f[0];
dst->f[1] = 1.0f / src->f[1];
dst->f[2] = 1.0f / src->f[2];
dst->f[3] = 1.0f / src->f[3];
}
 
static void
micro_rnd(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->f[0] = floorf(src->f[0] + 0.5f);
dst->f[1] = floorf(src->f[1] + 0.5f);
dst->f[2] = floorf(src->f[2] + 0.5f);
dst->f[3] = floorf(src->f[3] + 0.5f);
}
 
static void
micro_rsq(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
#if 0 /* for debugging */
assert(src->f[0] != 0.0f);
assert(src->f[1] != 0.0f);
assert(src->f[2] != 0.0f);
assert(src->f[3] != 0.0f);
#endif
dst->f[0] = 1.0f / sqrtf(fabsf(src->f[0]));
dst->f[1] = 1.0f / sqrtf(fabsf(src->f[1]));
dst->f[2] = 1.0f / sqrtf(fabsf(src->f[2]));
dst->f[3] = 1.0f / sqrtf(fabsf(src->f[3]));
}
 
static void
micro_sqrt(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->f[0] = sqrtf(fabsf(src->f[0]));
dst->f[1] = sqrtf(fabsf(src->f[1]));
dst->f[2] = sqrtf(fabsf(src->f[2]));
dst->f[3] = sqrtf(fabsf(src->f[3]));
}
 
static void
micro_seq(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->f[0] = src0->f[0] == src1->f[0] ? 1.0f : 0.0f;
dst->f[1] = src0->f[1] == src1->f[1] ? 1.0f : 0.0f;
dst->f[2] = src0->f[2] == src1->f[2] ? 1.0f : 0.0f;
dst->f[3] = src0->f[3] == src1->f[3] ? 1.0f : 0.0f;
}
 
static void
micro_sge(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->f[0] = src0->f[0] >= src1->f[0] ? 1.0f : 0.0f;
dst->f[1] = src0->f[1] >= src1->f[1] ? 1.0f : 0.0f;
dst->f[2] = src0->f[2] >= src1->f[2] ? 1.0f : 0.0f;
dst->f[3] = src0->f[3] >= src1->f[3] ? 1.0f : 0.0f;
}
 
static void
micro_sgn(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->f[0] = src->f[0] < 0.0f ? -1.0f : src->f[0] > 0.0f ? 1.0f : 0.0f;
dst->f[1] = src->f[1] < 0.0f ? -1.0f : src->f[1] > 0.0f ? 1.0f : 0.0f;
dst->f[2] = src->f[2] < 0.0f ? -1.0f : src->f[2] > 0.0f ? 1.0f : 0.0f;
dst->f[3] = src->f[3] < 0.0f ? -1.0f : src->f[3] > 0.0f ? 1.0f : 0.0f;
}
 
static void
micro_isgn(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->i[0] = src->i[0] < 0 ? -1 : src->i[0] > 0 ? 1 : 0;
dst->i[1] = src->i[1] < 0 ? -1 : src->i[1] > 0 ? 1 : 0;
dst->i[2] = src->i[2] < 0 ? -1 : src->i[2] > 0 ? 1 : 0;
dst->i[3] = src->i[3] < 0 ? -1 : src->i[3] > 0 ? 1 : 0;
}
 
static void
micro_sgt(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->f[0] = src0->f[0] > src1->f[0] ? 1.0f : 0.0f;
dst->f[1] = src0->f[1] > src1->f[1] ? 1.0f : 0.0f;
dst->f[2] = src0->f[2] > src1->f[2] ? 1.0f : 0.0f;
dst->f[3] = src0->f[3] > src1->f[3] ? 1.0f : 0.0f;
}
 
static void
micro_sin(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->f[0] = sinf(src->f[0]);
dst->f[1] = sinf(src->f[1]);
dst->f[2] = sinf(src->f[2]);
dst->f[3] = sinf(src->f[3]);
}
 
static void
micro_sle(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->f[0] = src0->f[0] <= src1->f[0] ? 1.0f : 0.0f;
dst->f[1] = src0->f[1] <= src1->f[1] ? 1.0f : 0.0f;
dst->f[2] = src0->f[2] <= src1->f[2] ? 1.0f : 0.0f;
dst->f[3] = src0->f[3] <= src1->f[3] ? 1.0f : 0.0f;
}
 
static void
micro_slt(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->f[0] = src0->f[0] < src1->f[0] ? 1.0f : 0.0f;
dst->f[1] = src0->f[1] < src1->f[1] ? 1.0f : 0.0f;
dst->f[2] = src0->f[2] < src1->f[2] ? 1.0f : 0.0f;
dst->f[3] = src0->f[3] < src1->f[3] ? 1.0f : 0.0f;
}
 
static void
micro_sne(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->f[0] = src0->f[0] != src1->f[0] ? 1.0f : 0.0f;
dst->f[1] = src0->f[1] != src1->f[1] ? 1.0f : 0.0f;
dst->f[2] = src0->f[2] != src1->f[2] ? 1.0f : 0.0f;
dst->f[3] = src0->f[3] != src1->f[3] ? 1.0f : 0.0f;
}
 
static void
micro_sfl(union tgsi_exec_channel *dst)
{
dst->f[0] = 0.0f;
dst->f[1] = 0.0f;
dst->f[2] = 0.0f;
dst->f[3] = 0.0f;
}
 
static void
micro_str(union tgsi_exec_channel *dst)
{
dst->f[0] = 1.0f;
dst->f[1] = 1.0f;
dst->f[2] = 1.0f;
dst->f[3] = 1.0f;
}
 
static void
micro_trunc(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->f[0] = (float)(int)src->f[0];
dst->f[1] = (float)(int)src->f[1];
dst->f[2] = (float)(int)src->f[2];
dst->f[3] = (float)(int)src->f[3];
}
 
 
enum tgsi_exec_datatype {
TGSI_EXEC_DATA_FLOAT,
TGSI_EXEC_DATA_INT,
TGSI_EXEC_DATA_UINT
};
 
/*
* Shorthand locations of various utility registers (_I = Index, _C = Channel)
*/
#define TEMP_KILMASK_I TGSI_EXEC_TEMP_KILMASK_I
#define TEMP_KILMASK_C TGSI_EXEC_TEMP_KILMASK_C
#define TEMP_OUTPUT_I TGSI_EXEC_TEMP_OUTPUT_I
#define TEMP_OUTPUT_C TGSI_EXEC_TEMP_OUTPUT_C
#define TEMP_PRIMITIVE_I TGSI_EXEC_TEMP_PRIMITIVE_I
#define TEMP_PRIMITIVE_C TGSI_EXEC_TEMP_PRIMITIVE_C
 
 
/** The execution mask depends on the conditional mask and the loop mask */
#define UPDATE_EXEC_MASK(MACH) \
MACH->ExecMask = MACH->CondMask & MACH->LoopMask & MACH->ContMask & MACH->Switch.mask & MACH->FuncMask
 
 
static const union tgsi_exec_channel ZeroVec =
{ { 0.0, 0.0, 0.0, 0.0 } };
 
static const union tgsi_exec_channel OneVec = {
{1.0f, 1.0f, 1.0f, 1.0f}
};
 
static const union tgsi_exec_channel P128Vec = {
{128.0f, 128.0f, 128.0f, 128.0f}
};
 
static const union tgsi_exec_channel M128Vec = {
{-128.0f, -128.0f, -128.0f, -128.0f}
};
 
 
/**
* Assert that none of the float values in 'chan' are infinite or NaN.
* NaN and Inf may occur normally during program execution and should
* not lead to crashes, etc. But when debugging, it's helpful to catch
* them.
*/
static INLINE void
check_inf_or_nan(const union tgsi_exec_channel *chan)
{
assert(!util_is_inf_or_nan((chan)->f[0]));
assert(!util_is_inf_or_nan((chan)->f[1]));
assert(!util_is_inf_or_nan((chan)->f[2]));
assert(!util_is_inf_or_nan((chan)->f[3]));
}
 
 
#ifdef DEBUG
static void
print_chan(const char *msg, const union tgsi_exec_channel *chan)
{
debug_printf("%s = {%f, %f, %f, %f}\n",
msg, chan->f[0], chan->f[1], chan->f[2], chan->f[3]);
}
#endif
 
 
#ifdef DEBUG
static void
print_temp(const struct tgsi_exec_machine *mach, uint index)
{
const struct tgsi_exec_vector *tmp = &mach->Temps[index];
int i;
debug_printf("Temp[%u] =\n", index);
for (i = 0; i < 4; i++) {
debug_printf(" %c: { %f, %f, %f, %f }\n",
"XYZW"[i],
tmp->xyzw[i].f[0],
tmp->xyzw[i].f[1],
tmp->xyzw[i].f[2],
tmp->xyzw[i].f[3]);
}
}
#endif
 
 
void
tgsi_exec_set_constant_buffers(struct tgsi_exec_machine *mach,
unsigned num_bufs,
const void **bufs,
const unsigned *buf_sizes)
{
unsigned i;
 
for (i = 0; i < num_bufs; i++) {
mach->Consts[i] = bufs[i];
mach->ConstsSize[i] = buf_sizes[i];
}
}
 
 
/**
* Check if there's a potential src/dst register data dependency when
* using SOA execution.
* Example:
* MOV T, T.yxwz;
* This would expand into:
* MOV t0, t1;
* MOV t1, t0;
* MOV t2, t3;
* MOV t3, t2;
* The second instruction will have the wrong value for t0 if executed as-is.
*/
boolean
tgsi_check_soa_dependencies(const struct tgsi_full_instruction *inst)
{
uint i, chan;
 
uint writemask = inst->Dst[0].Register.WriteMask;
if (writemask == TGSI_WRITEMASK_X ||
writemask == TGSI_WRITEMASK_Y ||
writemask == TGSI_WRITEMASK_Z ||
writemask == TGSI_WRITEMASK_W ||
writemask == TGSI_WRITEMASK_NONE) {
/* no chance of data dependency */
return FALSE;
}
 
/* loop over src regs */
for (i = 0; i < inst->Instruction.NumSrcRegs; i++) {
if ((inst->Src[i].Register.File ==
inst->Dst[0].Register.File) &&
((inst->Src[i].Register.Index ==
inst->Dst[0].Register.Index) ||
inst->Src[i].Register.Indirect ||
inst->Dst[0].Register.Indirect)) {
/* loop over dest channels */
uint channelsWritten = 0x0;
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
/* check if we're reading a channel that's been written */
uint swizzle = tgsi_util_get_full_src_register_swizzle(&inst->Src[i], chan);
if (channelsWritten & (1 << swizzle)) {
return TRUE;
}
 
channelsWritten |= (1 << chan);
}
}
}
}
return FALSE;
}
 
 
/**
* Initialize machine state by expanding tokens to full instructions,
* allocating temporary storage, setting up constants, etc.
* After this, we can call tgsi_exec_machine_run() many times.
*/
void
tgsi_exec_machine_bind_shader(
struct tgsi_exec_machine *mach,
const struct tgsi_token *tokens,
struct tgsi_sampler *sampler)
{
uint k;
struct tgsi_parse_context parse;
struct tgsi_full_instruction *instructions;
struct tgsi_full_declaration *declarations;
uint maxInstructions = 10, numInstructions = 0;
uint maxDeclarations = 10, numDeclarations = 0;
 
#if 0
tgsi_dump(tokens, 0);
#endif
 
util_init_math();
 
 
mach->Tokens = tokens;
mach->Sampler = sampler;
 
if (!tokens) {
/* unbind and free all */
FREE(mach->Declarations);
mach->Declarations = NULL;
mach->NumDeclarations = 0;
 
FREE(mach->Instructions);
mach->Instructions = NULL;
mach->NumInstructions = 0;
 
return;
}
 
k = tgsi_parse_init (&parse, mach->Tokens);
if (k != TGSI_PARSE_OK) {
debug_printf( "Problem parsing!\n" );
return;
}
 
mach->Processor = parse.FullHeader.Processor.Processor;
mach->ImmLimit = 0;
mach->NumOutputs = 0;
 
if (mach->Processor == TGSI_PROCESSOR_GEOMETRY &&
!mach->UsedGeometryShader) {
struct tgsi_exec_vector *inputs;
struct tgsi_exec_vector *outputs;
 
inputs = align_malloc(sizeof(struct tgsi_exec_vector) *
TGSI_MAX_PRIM_VERTICES * PIPE_MAX_ATTRIBS,
16);
 
if (!inputs)
return;
 
outputs = align_malloc(sizeof(struct tgsi_exec_vector) *
TGSI_MAX_TOTAL_VERTICES, 16);
 
if (!outputs) {
align_free(inputs);
return;
}
 
align_free(mach->Inputs);
align_free(mach->Outputs);
 
mach->Inputs = inputs;
mach->Outputs = outputs;
mach->UsedGeometryShader = TRUE;
}
 
declarations = (struct tgsi_full_declaration *)
MALLOC( maxDeclarations * sizeof(struct tgsi_full_declaration) );
 
if (!declarations) {
return;
}
 
instructions = (struct tgsi_full_instruction *)
MALLOC( maxInstructions * sizeof(struct tgsi_full_instruction) );
 
if (!instructions) {
FREE( declarations );
return;
}
 
while( !tgsi_parse_end_of_tokens( &parse ) ) {
uint i;
 
tgsi_parse_token( &parse );
switch( parse.FullToken.Token.Type ) {
case TGSI_TOKEN_TYPE_DECLARATION:
/* save expanded declaration */
if (numDeclarations == maxDeclarations) {
declarations = REALLOC(declarations,
maxDeclarations
* sizeof(struct tgsi_full_declaration),
(maxDeclarations + 10)
* sizeof(struct tgsi_full_declaration));
maxDeclarations += 10;
}
if (parse.FullToken.FullDeclaration.Declaration.File == TGSI_FILE_OUTPUT) {
unsigned reg;
for (reg = parse.FullToken.FullDeclaration.Range.First;
reg <= parse.FullToken.FullDeclaration.Range.Last;
++reg) {
++mach->NumOutputs;
}
}
memcpy(declarations + numDeclarations,
&parse.FullToken.FullDeclaration,
sizeof(declarations[0]));
numDeclarations++;
break;
 
case TGSI_TOKEN_TYPE_IMMEDIATE:
{
uint size = parse.FullToken.FullImmediate.Immediate.NrTokens - 1;
assert( size <= 4 );
assert( mach->ImmLimit + 1 <= TGSI_EXEC_NUM_IMMEDIATES );
 
for( i = 0; i < size; i++ ) {
mach->Imms[mach->ImmLimit][i] =
parse.FullToken.FullImmediate.u[i].Float;
}
mach->ImmLimit += 1;
}
break;
 
case TGSI_TOKEN_TYPE_INSTRUCTION:
 
/* save expanded instruction */
if (numInstructions == maxInstructions) {
instructions = REALLOC(instructions,
maxInstructions
* sizeof(struct tgsi_full_instruction),
(maxInstructions + 10)
* sizeof(struct tgsi_full_instruction));
maxInstructions += 10;
}
 
memcpy(instructions + numInstructions,
&parse.FullToken.FullInstruction,
sizeof(instructions[0]));
 
numInstructions++;
break;
 
case TGSI_TOKEN_TYPE_PROPERTY:
break;
 
default:
assert( 0 );
}
}
tgsi_parse_free (&parse);
 
FREE(mach->Declarations);
mach->Declarations = declarations;
mach->NumDeclarations = numDeclarations;
 
FREE(mach->Instructions);
mach->Instructions = instructions;
mach->NumInstructions = numInstructions;
}
 
 
struct tgsi_exec_machine *
tgsi_exec_machine_create( void )
{
struct tgsi_exec_machine *mach;
uint i;
 
mach = align_malloc( sizeof *mach, 16 );
if (!mach)
goto fail;
 
memset(mach, 0, sizeof(*mach));
 
mach->Addrs = &mach->Temps[TGSI_EXEC_TEMP_ADDR];
mach->MaxGeometryShaderOutputs = TGSI_MAX_TOTAL_VERTICES;
mach->Predicates = &mach->Temps[TGSI_EXEC_TEMP_P0];
 
mach->Inputs = align_malloc(sizeof(struct tgsi_exec_vector) * PIPE_MAX_ATTRIBS, 16);
mach->Outputs = align_malloc(sizeof(struct tgsi_exec_vector) * PIPE_MAX_ATTRIBS, 16);
if (!mach->Inputs || !mach->Outputs)
goto fail;
 
/* Setup constants needed by the SSE2 executor. */
for( i = 0; i < 4; i++ ) {
mach->Temps[TGSI_EXEC_TEMP_00000000_I].xyzw[TGSI_EXEC_TEMP_00000000_C].u[i] = 0x00000000;
mach->Temps[TGSI_EXEC_TEMP_7FFFFFFF_I].xyzw[TGSI_EXEC_TEMP_7FFFFFFF_C].u[i] = 0x7FFFFFFF;
mach->Temps[TGSI_EXEC_TEMP_80000000_I].xyzw[TGSI_EXEC_TEMP_80000000_C].u[i] = 0x80000000;
mach->Temps[TGSI_EXEC_TEMP_FFFFFFFF_I].xyzw[TGSI_EXEC_TEMP_FFFFFFFF_C].u[i] = 0xFFFFFFFF; /* not used */
mach->Temps[TGSI_EXEC_TEMP_ONE_I].xyzw[TGSI_EXEC_TEMP_ONE_C].f[i] = 1.0f;
mach->Temps[TGSI_EXEC_TEMP_TWO_I].xyzw[TGSI_EXEC_TEMP_TWO_C].f[i] = 2.0f; /* not used */
mach->Temps[TGSI_EXEC_TEMP_128_I].xyzw[TGSI_EXEC_TEMP_128_C].f[i] = 128.0f;
mach->Temps[TGSI_EXEC_TEMP_MINUS_128_I].xyzw[TGSI_EXEC_TEMP_MINUS_128_C].f[i] = -128.0f;
mach->Temps[TGSI_EXEC_TEMP_THREE_I].xyzw[TGSI_EXEC_TEMP_THREE_C].f[i] = 3.0f;
mach->Temps[TGSI_EXEC_TEMP_HALF_I].xyzw[TGSI_EXEC_TEMP_HALF_C].f[i] = 0.5f;
}
 
#ifdef DEBUG
/* silence warnings */
(void) print_chan;
(void) print_temp;
#endif
 
return mach;
 
fail:
if (mach) {
align_free(mach->Inputs);
align_free(mach->Outputs);
align_free(mach);
}
return NULL;
}
 
 
void
tgsi_exec_machine_destroy(struct tgsi_exec_machine *mach)
{
if (mach) {
FREE(mach->Instructions);
FREE(mach->Declarations);
 
align_free(mach->Inputs);
align_free(mach->Outputs);
 
align_free(mach);
}
}
 
static void
micro_add(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->f[0] = src0->f[0] + src1->f[0];
dst->f[1] = src0->f[1] + src1->f[1];
dst->f[2] = src0->f[2] + src1->f[2];
dst->f[3] = src0->f[3] + src1->f[3];
}
 
static void
micro_div(
union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1 )
{
if (src1->f[0] != 0) {
dst->f[0] = src0->f[0] / src1->f[0];
}
if (src1->f[1] != 0) {
dst->f[1] = src0->f[1] / src1->f[1];
}
if (src1->f[2] != 0) {
dst->f[2] = src0->f[2] / src1->f[2];
}
if (src1->f[3] != 0) {
dst->f[3] = src0->f[3] / src1->f[3];
}
}
 
static void
micro_rcc(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
uint i;
 
for (i = 0; i < 4; i++) {
float recip = 1.0f / src->f[i];
 
if (recip > 0.0f) {
if (recip > 1.884467e+019f) {
dst->f[i] = 1.884467e+019f;
}
else if (recip < 5.42101e-020f) {
dst->f[i] = 5.42101e-020f;
}
else {
dst->f[i] = recip;
}
}
else {
if (recip < -1.884467e+019f) {
dst->f[i] = -1.884467e+019f;
}
else if (recip > -5.42101e-020f) {
dst->f[i] = -5.42101e-020f;
}
else {
dst->f[i] = recip;
}
}
}
}
 
static void
micro_lt(
union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1,
const union tgsi_exec_channel *src2,
const union tgsi_exec_channel *src3 )
{
dst->f[0] = src0->f[0] < src1->f[0] ? src2->f[0] : src3->f[0];
dst->f[1] = src0->f[1] < src1->f[1] ? src2->f[1] : src3->f[1];
dst->f[2] = src0->f[2] < src1->f[2] ? src2->f[2] : src3->f[2];
dst->f[3] = src0->f[3] < src1->f[3] ? src2->f[3] : src3->f[3];
}
 
static void
micro_max(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->f[0] = src0->f[0] > src1->f[0] ? src0->f[0] : src1->f[0];
dst->f[1] = src0->f[1] > src1->f[1] ? src0->f[1] : src1->f[1];
dst->f[2] = src0->f[2] > src1->f[2] ? src0->f[2] : src1->f[2];
dst->f[3] = src0->f[3] > src1->f[3] ? src0->f[3] : src1->f[3];
}
 
static void
micro_min(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->f[0] = src0->f[0] < src1->f[0] ? src0->f[0] : src1->f[0];
dst->f[1] = src0->f[1] < src1->f[1] ? src0->f[1] : src1->f[1];
dst->f[2] = src0->f[2] < src1->f[2] ? src0->f[2] : src1->f[2];
dst->f[3] = src0->f[3] < src1->f[3] ? src0->f[3] : src1->f[3];
}
 
static void
micro_mul(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->f[0] = src0->f[0] * src1->f[0];
dst->f[1] = src0->f[1] * src1->f[1];
dst->f[2] = src0->f[2] * src1->f[2];
dst->f[3] = src0->f[3] * src1->f[3];
}
 
static void
micro_neg(
union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src )
{
dst->f[0] = -src->f[0];
dst->f[1] = -src->f[1];
dst->f[2] = -src->f[2];
dst->f[3] = -src->f[3];
}
 
static void
micro_pow(
union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1 )
{
#if FAST_MATH
dst->f[0] = util_fast_pow( src0->f[0], src1->f[0] );
dst->f[1] = util_fast_pow( src0->f[1], src1->f[1] );
dst->f[2] = util_fast_pow( src0->f[2], src1->f[2] );
dst->f[3] = util_fast_pow( src0->f[3], src1->f[3] );
#else
dst->f[0] = powf( src0->f[0], src1->f[0] );
dst->f[1] = powf( src0->f[1], src1->f[1] );
dst->f[2] = powf( src0->f[2], src1->f[2] );
dst->f[3] = powf( src0->f[3], src1->f[3] );
#endif
}
 
static void
micro_sub(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->f[0] = src0->f[0] - src1->f[0];
dst->f[1] = src0->f[1] - src1->f[1];
dst->f[2] = src0->f[2] - src1->f[2];
dst->f[3] = src0->f[3] - src1->f[3];
}
 
static void
fetch_src_file_channel(const struct tgsi_exec_machine *mach,
const uint chan_index,
const uint file,
const uint swizzle,
const union tgsi_exec_channel *index,
const union tgsi_exec_channel *index2D,
union tgsi_exec_channel *chan)
{
uint i;
 
assert(swizzle < 4);
 
switch (file) {
case TGSI_FILE_CONSTANT:
for (i = 0; i < TGSI_QUAD_SIZE; i++) {
assert(index2D->i[i] >= 0 && index2D->i[i] < PIPE_MAX_CONSTANT_BUFFERS);
assert(mach->Consts[index2D->i[i]]);
 
if (index->i[i] < 0) {
chan->u[i] = 0;
} else {
/* NOTE: copying the const value as a uint instead of float */
const uint constbuf = index2D->i[i];
const uint *buf = (const uint *)mach->Consts[constbuf];
const int pos = index->i[i] * 4 + swizzle;
/* const buffer bounds check */
if (pos < 0 || pos >= (int) mach->ConstsSize[constbuf]) {
if (0) {
/* Debug: print warning */
static int count = 0;
if (count++ < 100)
debug_printf("TGSI Exec: const buffer index %d"
" out of bounds\n", pos);
}
chan->u[i] = 0;
}
else
chan->u[i] = buf[pos];
}
}
break;
 
case TGSI_FILE_INPUT:
for (i = 0; i < TGSI_QUAD_SIZE; i++) {
/*
if (TGSI_PROCESSOR_GEOMETRY == mach->Processor) {
debug_printf("Fetching Input[%d] (2d=%d, 1d=%d)\n",
index2D->i[i] * TGSI_EXEC_MAX_INPUT_ATTRIBS + index->i[i],
index2D->i[i], index->i[i]);
}*/
int pos = index2D->i[i] * TGSI_EXEC_MAX_INPUT_ATTRIBS + index->i[i];
assert(pos >= 0);
assert(pos < TGSI_MAX_PRIM_VERTICES * PIPE_MAX_ATTRIBS);
chan->u[i] = mach->Inputs[pos].xyzw[swizzle].u[i];
}
break;
 
case TGSI_FILE_SYSTEM_VALUE:
/* XXX no swizzling at this point. Will be needed if we put
* gl_FragCoord, for example, in a sys value register.
*/
for (i = 0; i < TGSI_QUAD_SIZE; i++) {
chan->u[i] = mach->SystemValue[index->i[i]].u[i];
}
break;
 
case TGSI_FILE_TEMPORARY:
for (i = 0; i < TGSI_QUAD_SIZE; i++) {
assert(index->i[i] < TGSI_EXEC_NUM_TEMPS);
assert(index2D->i[i] == 0);
 
chan->u[i] = mach->Temps[index->i[i]].xyzw[swizzle].u[i];
}
break;
 
case TGSI_FILE_IMMEDIATE:
for (i = 0; i < TGSI_QUAD_SIZE; i++) {
assert(index->i[i] >= 0 && index->i[i] < (int)mach->ImmLimit);
assert(index2D->i[i] == 0);
 
chan->f[i] = mach->Imms[index->i[i]][swizzle];
}
break;
 
case TGSI_FILE_ADDRESS:
for (i = 0; i < TGSI_QUAD_SIZE; i++) {
assert(index->i[i] >= 0);
assert(index2D->i[i] == 0);
 
chan->u[i] = mach->Addrs[index->i[i]].xyzw[swizzle].u[i];
}
break;
 
case TGSI_FILE_PREDICATE:
for (i = 0; i < TGSI_QUAD_SIZE; i++) {
assert(index->i[i] >= 0 && index->i[i] < TGSI_EXEC_NUM_PREDS);
assert(index2D->i[i] == 0);
 
chan->u[i] = mach->Predicates[0].xyzw[swizzle].u[i];
}
break;
 
case TGSI_FILE_OUTPUT:
/* vertex/fragment output vars can be read too */
for (i = 0; i < TGSI_QUAD_SIZE; i++) {
assert(index->i[i] >= 0);
assert(index2D->i[i] == 0);
 
chan->u[i] = mach->Outputs[index->i[i]].xyzw[swizzle].u[i];
}
break;
 
default:
assert(0);
for (i = 0; i < TGSI_QUAD_SIZE; i++) {
chan->u[i] = 0;
}
}
}
 
static void
fetch_source(const struct tgsi_exec_machine *mach,
union tgsi_exec_channel *chan,
const struct tgsi_full_src_register *reg,
const uint chan_index,
enum tgsi_exec_datatype src_datatype)
{
union tgsi_exec_channel index;
union tgsi_exec_channel index2D;
uint swizzle;
 
/* We start with a direct index into a register file.
*
* file[1],
* where:
* file = Register.File
* [1] = Register.Index
*/
index.i[0] =
index.i[1] =
index.i[2] =
index.i[3] = reg->Register.Index;
 
/* There is an extra source register that indirectly subscripts
* a register file. The direct index now becomes an offset
* that is being added to the indirect register.
*
* file[ind[2].x+1],
* where:
* ind = Indirect.File
* [2] = Indirect.Index
* .x = Indirect.SwizzleX
*/
if (reg->Register.Indirect) {
union tgsi_exec_channel index2;
union tgsi_exec_channel indir_index;
const uint execmask = mach->ExecMask;
uint i;
 
/* which address register (always zero now) */
index2.i[0] =
index2.i[1] =
index2.i[2] =
index2.i[3] = reg->Indirect.Index;
/* get current value of address register[swizzle] */
swizzle = reg->Indirect.Swizzle;
fetch_src_file_channel(mach,
chan_index,
reg->Indirect.File,
swizzle,
&index2,
&ZeroVec,
&indir_index);
 
/* add value of address register to the offset */
index.i[0] += indir_index.i[0];
index.i[1] += indir_index.i[1];
index.i[2] += indir_index.i[2];
index.i[3] += indir_index.i[3];
 
/* for disabled execution channels, zero-out the index to
* avoid using a potential garbage value.
*/
for (i = 0; i < TGSI_QUAD_SIZE; i++) {
if ((execmask & (1 << i)) == 0)
index.i[i] = 0;
}
}
 
/* There is an extra source register that is a second
* subscript to a register file. Effectively it means that
* the register file is actually a 2D array of registers.
*
* file[3][1],
* where:
* [3] = Dimension.Index
*/
if (reg->Register.Dimension) {
index2D.i[0] =
index2D.i[1] =
index2D.i[2] =
index2D.i[3] = reg->Dimension.Index;
 
/* Again, the second subscript index can be addressed indirectly
* identically to the first one.
* Nothing stops us from indirectly addressing the indirect register,
* but there is no need for that, so we won't exercise it.
*
* file[ind[4].y+3][1],
* where:
* ind = DimIndirect.File
* [4] = DimIndirect.Index
* .y = DimIndirect.SwizzleX
*/
if (reg->Dimension.Indirect) {
union tgsi_exec_channel index2;
union tgsi_exec_channel indir_index;
const uint execmask = mach->ExecMask;
uint i;
 
index2.i[0] =
index2.i[1] =
index2.i[2] =
index2.i[3] = reg->DimIndirect.Index;
 
swizzle = reg->DimIndirect.Swizzle;
fetch_src_file_channel(mach,
chan_index,
reg->DimIndirect.File,
swizzle,
&index2,
&ZeroVec,
&indir_index);
 
index2D.i[0] += indir_index.i[0];
index2D.i[1] += indir_index.i[1];
index2D.i[2] += indir_index.i[2];
index2D.i[3] += indir_index.i[3];
 
/* for disabled execution channels, zero-out the index to
* avoid using a potential garbage value.
*/
for (i = 0; i < TGSI_QUAD_SIZE; i++) {
if ((execmask & (1 << i)) == 0) {
index2D.i[i] = 0;
}
}
}
 
/* If by any chance there was a need for a 3D array of register
* files, we would have to check whether Dimension is followed
* by a dimension register and continue the saga.
*/
} else {
index2D.i[0] =
index2D.i[1] =
index2D.i[2] =
index2D.i[3] = 0;
}
 
swizzle = tgsi_util_get_full_src_register_swizzle( reg, chan_index );
fetch_src_file_channel(mach,
chan_index,
reg->Register.File,
swizzle,
&index,
&index2D,
chan);
 
if (reg->Register.Absolute) {
if (src_datatype == TGSI_EXEC_DATA_FLOAT) {
micro_abs(chan, chan);
} else {
micro_iabs(chan, chan);
}
}
 
if (reg->Register.Negate) {
if (src_datatype == TGSI_EXEC_DATA_FLOAT) {
micro_neg(chan, chan);
} else {
micro_ineg(chan, chan);
}
}
}
 
static void
store_dest(struct tgsi_exec_machine *mach,
const union tgsi_exec_channel *chan,
const struct tgsi_full_dst_register *reg,
const struct tgsi_full_instruction *inst,
uint chan_index,
enum tgsi_exec_datatype dst_datatype)
{
uint i;
union tgsi_exec_channel null;
union tgsi_exec_channel *dst;
union tgsi_exec_channel index2D;
uint execmask = mach->ExecMask;
int offset = 0; /* indirection offset */
int index;
 
/* for debugging */
if (0 && dst_datatype == TGSI_EXEC_DATA_FLOAT) {
check_inf_or_nan(chan);
}
 
/* There is an extra source register that indirectly subscripts
* a register file. The direct index now becomes an offset
* that is being added to the indirect register.
*
* file[ind[2].x+1],
* where:
* ind = Indirect.File
* [2] = Indirect.Index
* .x = Indirect.SwizzleX
*/
if (reg->Register.Indirect) {
union tgsi_exec_channel index;
union tgsi_exec_channel indir_index;
uint swizzle;
 
/* which address register (always zero for now) */
index.i[0] =
index.i[1] =
index.i[2] =
index.i[3] = reg->Indirect.Index;
 
/* get current value of address register[swizzle] */
swizzle = reg->Indirect.Swizzle;
 
/* fetch values from the address/indirection register */
fetch_src_file_channel(mach,
chan_index,
reg->Indirect.File,
swizzle,
&index,
&ZeroVec,
&indir_index);
 
/* save indirection offset */
offset = indir_index.i[0];
}
 
/* There is an extra source register that is a second
* subscript to a register file. Effectively it means that
* the register file is actually a 2D array of registers.
*
* file[3][1],
* where:
* [3] = Dimension.Index
*/
if (reg->Register.Dimension) {
index2D.i[0] =
index2D.i[1] =
index2D.i[2] =
index2D.i[3] = reg->Dimension.Index;
 
/* Again, the second subscript index can be addressed indirectly
* identically to the first one.
* Nothing stops us from indirectly addressing the indirect register,
* but there is no need for that, so we won't exercise it.
*
* file[ind[4].y+3][1],
* where:
* ind = DimIndirect.File
* [4] = DimIndirect.Index
* .y = DimIndirect.SwizzleX
*/
if (reg->Dimension.Indirect) {
union tgsi_exec_channel index2;
union tgsi_exec_channel indir_index;
const uint execmask = mach->ExecMask;
unsigned swizzle;
uint i;
 
index2.i[0] =
index2.i[1] =
index2.i[2] =
index2.i[3] = reg->DimIndirect.Index;
 
swizzle = reg->DimIndirect.Swizzle;
fetch_src_file_channel(mach,
chan_index,
reg->DimIndirect.File,
swizzle,
&index2,
&ZeroVec,
&indir_index);
 
index2D.i[0] += indir_index.i[0];
index2D.i[1] += indir_index.i[1];
index2D.i[2] += indir_index.i[2];
index2D.i[3] += indir_index.i[3];
 
/* for disabled execution channels, zero-out the index to
* avoid using a potential garbage value.
*/
for (i = 0; i < TGSI_QUAD_SIZE; i++) {
if ((execmask & (1 << i)) == 0) {
index2D.i[i] = 0;
}
}
}
 
/* If by any chance there was a need for a 3D array of register
* files, we would have to check whether Dimension is followed
* by a dimension register and continue the saga.
*/
} else {
index2D.i[0] =
index2D.i[1] =
index2D.i[2] =
index2D.i[3] = 0;
}
 
switch (reg->Register.File) {
case TGSI_FILE_NULL:
dst = &null;
break;
 
case TGSI_FILE_OUTPUT:
index = mach->Temps[TEMP_OUTPUT_I].xyzw[TEMP_OUTPUT_C].u[0]
+ reg->Register.Index;
dst = &mach->Outputs[offset + index].xyzw[chan_index];
#if 0
debug_printf("NumOutputs = %d, TEMP_O_C/I = %d, redindex = %d\n",
mach->NumOutputs, mach->Temps[TEMP_OUTPUT_I].xyzw[TEMP_OUTPUT_C].u[0],
reg->Register.Index);
if (TGSI_PROCESSOR_GEOMETRY == mach->Processor) {
debug_printf("STORING OUT[%d] mask(%d), = (", offset + index, execmask);
for (i = 0; i < TGSI_QUAD_SIZE; i++)
if (execmask & (1 << i))
debug_printf("%f, ", chan->f[i]);
debug_printf(")\n");
}
#endif
break;
 
case TGSI_FILE_TEMPORARY:
index = reg->Register.Index;
assert( index < TGSI_EXEC_NUM_TEMPS );
dst = &mach->Temps[offset + index].xyzw[chan_index];
break;
 
case TGSI_FILE_ADDRESS:
index = reg->Register.Index;
dst = &mach->Addrs[index].xyzw[chan_index];
break;
 
case TGSI_FILE_PREDICATE:
index = reg->Register.Index;
assert(index < TGSI_EXEC_NUM_PREDS);
dst = &mach->Predicates[index].xyzw[chan_index];
break;
 
default:
assert( 0 );
return;
}
 
if (inst->Instruction.Predicate) {
uint swizzle;
union tgsi_exec_channel *pred;
 
switch (chan_index) {
case TGSI_CHAN_X:
swizzle = inst->Predicate.SwizzleX;
break;
case TGSI_CHAN_Y:
swizzle = inst->Predicate.SwizzleY;
break;
case TGSI_CHAN_Z:
swizzle = inst->Predicate.SwizzleZ;
break;
case TGSI_CHAN_W:
swizzle = inst->Predicate.SwizzleW;
break;
default:
assert(0);
return;
}
 
assert(inst->Predicate.Index == 0);
 
pred = &mach->Predicates[inst->Predicate.Index].xyzw[swizzle];
 
if (inst->Predicate.Negate) {
for (i = 0; i < TGSI_QUAD_SIZE; i++) {
if (pred->u[i]) {
execmask &= ~(1 << i);
}
}
} else {
for (i = 0; i < TGSI_QUAD_SIZE; i++) {
if (!pred->u[i]) {
execmask &= ~(1 << i);
}
}
}
}
 
switch (inst->Instruction.Saturate) {
case TGSI_SAT_NONE:
for (i = 0; i < TGSI_QUAD_SIZE; i++)
if (execmask & (1 << i))
dst->i[i] = chan->i[i];
break;
 
case TGSI_SAT_ZERO_ONE:
for (i = 0; i < TGSI_QUAD_SIZE; i++)
if (execmask & (1 << i)) {
if (chan->f[i] < 0.0f)
dst->f[i] = 0.0f;
else if (chan->f[i] > 1.0f)
dst->f[i] = 1.0f;
else
dst->i[i] = chan->i[i];
}
break;
 
case TGSI_SAT_MINUS_PLUS_ONE:
for (i = 0; i < TGSI_QUAD_SIZE; i++)
if (execmask & (1 << i)) {
if (chan->f[i] < -1.0f)
dst->f[i] = -1.0f;
else if (chan->f[i] > 1.0f)
dst->f[i] = 1.0f;
else
dst->i[i] = chan->i[i];
}
break;
 
default:
assert( 0 );
}
}
 
#define FETCH(VAL,INDEX,CHAN)\
fetch_source(mach, VAL, &inst->Src[INDEX], CHAN, TGSI_EXEC_DATA_FLOAT)
 
#define IFETCH(VAL,INDEX,CHAN)\
fetch_source(mach, VAL, &inst->Src[INDEX], CHAN, TGSI_EXEC_DATA_INT)
 
 
/**
* Execute ARB-style KIL which is predicated by a src register.
* Kill fragment if any of the four values is less than zero.
*/
static void
exec_kil(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
uint uniquemask;
uint chan_index;
uint kilmask = 0; /* bit 0 = pixel 0, bit 1 = pixel 1, etc */
union tgsi_exec_channel r[1];
 
/* This mask stores component bits that were already tested. */
uniquemask = 0;
 
for (chan_index = 0; chan_index < 4; chan_index++)
{
uint swizzle;
uint i;
 
/* unswizzle channel */
swizzle = tgsi_util_get_full_src_register_swizzle (
&inst->Src[0],
chan_index);
 
/* check if the component has not been already tested */
if (uniquemask & (1 << swizzle))
continue;
uniquemask |= 1 << swizzle;
 
FETCH(&r[0], 0, chan_index);
for (i = 0; i < 4; i++)
if (r[0].f[i] < 0.0f)
kilmask |= 1 << i;
}
 
mach->Temps[TEMP_KILMASK_I].xyzw[TEMP_KILMASK_C].u[0] |= kilmask;
}
 
/**
* Execute NVIDIA-style KIL which is predicated by a condition code.
* Kill fragment if the condition code is TRUE.
*/
static void
exec_kilp(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
uint kilmask; /* bit 0 = pixel 0, bit 1 = pixel 1, etc */
 
/* "unconditional" kil */
kilmask = mach->ExecMask;
mach->Temps[TEMP_KILMASK_I].xyzw[TEMP_KILMASK_C].u[0] |= kilmask;
}
 
static void
emit_vertex(struct tgsi_exec_machine *mach)
{
/* FIXME: check for exec mask correctly
unsigned i;
for (i = 0; i < TGSI_QUAD_SIZE; ++i) {
if ((mach->ExecMask & (1 << i)))
*/
if (mach->ExecMask) {
mach->Temps[TEMP_OUTPUT_I].xyzw[TEMP_OUTPUT_C].u[0] += mach->NumOutputs;
mach->Primitives[mach->Temps[TEMP_PRIMITIVE_I].xyzw[TEMP_PRIMITIVE_C].u[0]]++;
}
}
 
static void
emit_primitive(struct tgsi_exec_machine *mach)
{
unsigned *prim_count = &mach->Temps[TEMP_PRIMITIVE_I].xyzw[TEMP_PRIMITIVE_C].u[0];
/* FIXME: check for exec mask correctly
unsigned i;
for (i = 0; i < TGSI_QUAD_SIZE; ++i) {
if ((mach->ExecMask & (1 << i)))
*/
if (mach->ExecMask) {
++(*prim_count);
debug_assert((*prim_count * mach->NumOutputs) < mach->MaxGeometryShaderOutputs);
mach->Primitives[*prim_count] = 0;
}
}
 
static void
conditional_emit_primitive(struct tgsi_exec_machine *mach)
{
if (TGSI_PROCESSOR_GEOMETRY == mach->Processor) {
int emitted_verts =
mach->Primitives[mach->Temps[TEMP_PRIMITIVE_I].xyzw[TEMP_PRIMITIVE_C].u[0]];
if (emitted_verts) {
emit_primitive(mach);
}
}
}
 
 
/*
* Fetch four texture samples using STR texture coordinates.
*/
static void
fetch_texel( struct tgsi_sampler *sampler,
const unsigned sview_idx,
const unsigned sampler_idx,
const union tgsi_exec_channel *s,
const union tgsi_exec_channel *t,
const union tgsi_exec_channel *p,
const union tgsi_exec_channel *c0,
const union tgsi_exec_channel *c1,
float derivs[3][2][TGSI_QUAD_SIZE],
const int8_t offset[3],
enum tgsi_sampler_control control,
union tgsi_exec_channel *r,
union tgsi_exec_channel *g,
union tgsi_exec_channel *b,
union tgsi_exec_channel *a )
{
uint j;
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
 
/* FIXME: handle explicit derivs, offsets */
sampler->get_samples(sampler, sview_idx, sampler_idx,
s->f, t->f, p->f, c0->f, c1->f, derivs, offset, control, rgba);
 
for (j = 0; j < 4; j++) {
r->f[j] = rgba[0][j];
g->f[j] = rgba[1][j];
b->f[j] = rgba[2][j];
a->f[j] = rgba[3][j];
}
}
 
 
#define TEX_MODIFIER_NONE 0
#define TEX_MODIFIER_PROJECTED 1
#define TEX_MODIFIER_LOD_BIAS 2
#define TEX_MODIFIER_EXPLICIT_LOD 3
#define TEX_MODIFIER_LEVEL_ZERO 4
 
 
/*
* Fetch all 3 (for s,t,r coords) texel offsets, put them into int array.
*/
static void
fetch_texel_offsets(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst,
int8_t offsets[3])
{
if (inst->Texture.NumOffsets == 1) {
union tgsi_exec_channel index;
union tgsi_exec_channel offset[3];
index.i[0] = index.i[1] = index.i[2] = index.i[3] = inst->TexOffsets[0].Index;
fetch_src_file_channel(mach, 0, inst->TexOffsets[0].File,
inst->TexOffsets[0].SwizzleX, &index, &ZeroVec, &offset[0]);
fetch_src_file_channel(mach, 0, inst->TexOffsets[0].File,
inst->TexOffsets[0].SwizzleY, &index, &ZeroVec, &offset[1]);
fetch_src_file_channel(mach, 0, inst->TexOffsets[0].File,
inst->TexOffsets[0].SwizzleZ, &index, &ZeroVec, &offset[2]);
offsets[0] = offset[0].i[0];
offsets[1] = offset[1].i[0];
offsets[2] = offset[2].i[0];
} else {
assert(inst->Texture.NumOffsets == 0);
offsets[0] = offsets[1] = offsets[2] = 0;
}
}
 
 
/*
* Fetch dx and dy values for one channel (s, t or r).
* Put dx values into one float array, dy values into another.
*/
static void
fetch_assign_deriv_channel(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst,
unsigned regdsrcx,
unsigned chan,
float derivs[2][TGSI_QUAD_SIZE])
{
union tgsi_exec_channel d;
FETCH(&d, regdsrcx, chan);
derivs[0][0] = d.f[0];
derivs[0][1] = d.f[1];
derivs[0][2] = d.f[2];
derivs[0][3] = d.f[3];
FETCH(&d, regdsrcx + 1, chan);
derivs[1][0] = d.f[0];
derivs[1][1] = d.f[1];
derivs[1][2] = d.f[2];
derivs[1][3] = d.f[3];
}
 
 
/*
* execute a texture instruction.
*
* modifier is used to control the channel routing for the\
* instruction variants like proj, lod, and texture with lod bias.
* sampler indicates which src register the sampler is contained in.
*/
static void
exec_tex(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst,
uint modifier, uint sampler)
{
const uint unit = inst->Src[sampler].Register.Index;
const union tgsi_exec_channel *args[5], *proj = NULL;
union tgsi_exec_channel r[5];
enum tgsi_sampler_control control = tgsi_sampler_lod_none;
uint chan;
int8_t offsets[3];
int dim, shadow_ref, i;
 
/* always fetch all 3 offsets, overkill but keeps code simple */
fetch_texel_offsets(mach, inst, offsets);
 
assert(modifier != TEX_MODIFIER_LEVEL_ZERO);
assert(inst->Texture.Texture != TGSI_TEXTURE_BUFFER);
 
dim = tgsi_util_get_texture_coord_dim(inst->Texture.Texture, &shadow_ref);
 
assert(dim <= 4);
if (shadow_ref >= 0)
assert(shadow_ref >= dim && shadow_ref < Elements(args));
 
/* fetch modifier to the last argument */
if (modifier != TEX_MODIFIER_NONE) {
const int last = Elements(args) - 1;
 
/* fetch modifier from src0.w or src1.x */
if (sampler == 1) {
assert(dim <= TGSI_CHAN_W && shadow_ref != TGSI_CHAN_W);
FETCH(&r[last], 0, TGSI_CHAN_W);
}
else {
assert(shadow_ref != 4);
FETCH(&r[last], 1, TGSI_CHAN_X);
}
 
if (modifier != TEX_MODIFIER_PROJECTED) {
args[last] = &r[last];
}
else {
proj = &r[last];
args[last] = &ZeroVec;
}
 
/* point unused arguments to zero vector */
for (i = dim; i < last; i++)
args[i] = &ZeroVec;
 
if (modifier == TEX_MODIFIER_EXPLICIT_LOD)
control = tgsi_sampler_lod_explicit;
else if (modifier == TEX_MODIFIER_LOD_BIAS)
control = tgsi_sampler_lod_bias;
}
else {
for (i = dim; i < Elements(args); i++)
args[i] = &ZeroVec;
}
 
/* fetch coordinates */
for (i = 0; i < dim; i++) {
FETCH(&r[i], 0, TGSI_CHAN_X + i);
 
if (proj)
micro_div(&r[i], &r[i], proj);
 
args[i] = &r[i];
}
 
/* fetch reference value */
if (shadow_ref >= 0) {
FETCH(&r[shadow_ref], shadow_ref / 4, TGSI_CHAN_X + (shadow_ref % 4));
 
if (proj)
micro_div(&r[shadow_ref], &r[shadow_ref], proj);
 
args[shadow_ref] = &r[shadow_ref];
}
 
fetch_texel(mach->Sampler, unit, unit,
args[0], args[1], args[2], args[3], args[4],
NULL, offsets, control,
&r[0], &r[1], &r[2], &r[3]); /* R, G, B, A */
 
#if 0
debug_printf("fetch r: %g %g %g %g\n",
r[0].f[0], r[0].f[1], r[0].f[2], r[0].f[3]);
debug_printf("fetch g: %g %g %g %g\n",
r[1].f[0], r[1].f[1], r[1].f[2], r[1].f[3]);
debug_printf("fetch b: %g %g %g %g\n",
r[2].f[0], r[2].f[1], r[2].f[2], r[2].f[3]);
debug_printf("fetch a: %g %g %g %g\n",
r[3].f[0], r[3].f[1], r[3].f[2], r[3].f[3]);
#endif
 
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
store_dest(mach, &r[chan], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
}
}
}
 
 
static void
exec_txd(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
const uint unit = inst->Src[3].Register.Index;
union tgsi_exec_channel r[4];
float derivs[3][2][TGSI_QUAD_SIZE];
uint chan;
int8_t offsets[3];
 
/* always fetch all 3 offsets, overkill but keeps code simple */
fetch_texel_offsets(mach, inst, offsets);
 
switch (inst->Texture.Texture) {
case TGSI_TEXTURE_1D:
FETCH(&r[0], 0, TGSI_CHAN_X);
 
fetch_assign_deriv_channel(mach, inst, 1, TGSI_CHAN_X, derivs[0]);
 
fetch_texel(mach->Sampler, unit, unit,
&r[0], &ZeroVec, &ZeroVec, &ZeroVec, &ZeroVec, /* S, T, P, C, LOD */
derivs, offsets, tgsi_sampler_derivs_explicit,
&r[0], &r[1], &r[2], &r[3]); /* R, G, B, A */
break;
 
case TGSI_TEXTURE_SHADOW1D:
case TGSI_TEXTURE_1D_ARRAY:
case TGSI_TEXTURE_SHADOW1D_ARRAY:
/* SHADOW1D/1D_ARRAY would not need Y/Z respectively, but don't bother */
FETCH(&r[0], 0, TGSI_CHAN_X);
FETCH(&r[1], 0, TGSI_CHAN_Y);
FETCH(&r[2], 0, TGSI_CHAN_Z);
 
fetch_assign_deriv_channel(mach, inst, 1, TGSI_CHAN_X, derivs[0]);
 
fetch_texel(mach->Sampler, unit, unit,
&r[0], &r[1], &r[2], &ZeroVec, &ZeroVec, /* S, T, P, C, LOD */
derivs, offsets, tgsi_sampler_derivs_explicit,
&r[0], &r[1], &r[2], &r[3]); /* R, G, B, A */
break;
 
case TGSI_TEXTURE_2D:
case TGSI_TEXTURE_RECT:
FETCH(&r[0], 0, TGSI_CHAN_X);
FETCH(&r[1], 0, TGSI_CHAN_Y);
 
fetch_assign_deriv_channel(mach, inst, 1, TGSI_CHAN_X, derivs[0]);
fetch_assign_deriv_channel(mach, inst, 1, TGSI_CHAN_Y, derivs[1]);
 
fetch_texel(mach->Sampler, unit, unit,
&r[0], &r[1], &ZeroVec, &ZeroVec, &ZeroVec, /* S, T, P, C, LOD */
derivs, offsets, tgsi_sampler_derivs_explicit,
&r[0], &r[1], &r[2], &r[3]); /* R, G, B, A */
break;
 
 
case TGSI_TEXTURE_SHADOW2D:
case TGSI_TEXTURE_SHADOWRECT:
case TGSI_TEXTURE_2D_ARRAY:
case TGSI_TEXTURE_SHADOW2D_ARRAY:
/* only SHADOW2D_ARRAY actually needs W */
FETCH(&r[0], 0, TGSI_CHAN_X);
FETCH(&r[1], 0, TGSI_CHAN_Y);
FETCH(&r[2], 0, TGSI_CHAN_Z);
FETCH(&r[3], 0, TGSI_CHAN_W);
 
fetch_assign_deriv_channel(mach, inst, 1, TGSI_CHAN_X, derivs[0]);
fetch_assign_deriv_channel(mach, inst, 1, TGSI_CHAN_Y, derivs[1]);
 
fetch_texel(mach->Sampler, unit, unit,
&r[0], &r[1], &r[2], &r[3], &ZeroVec, /* inputs */
derivs, offsets, tgsi_sampler_derivs_explicit,
&r[0], &r[1], &r[2], &r[3]); /* outputs */
break;
 
case TGSI_TEXTURE_3D:
case TGSI_TEXTURE_CUBE:
case TGSI_TEXTURE_CUBE_ARRAY:
/* only TEXTURE_CUBE_ARRAY actually needs W */
FETCH(&r[0], 0, TGSI_CHAN_X);
FETCH(&r[1], 0, TGSI_CHAN_Y);
FETCH(&r[2], 0, TGSI_CHAN_Z);
FETCH(&r[3], 0, TGSI_CHAN_W);
 
fetch_assign_deriv_channel(mach, inst, 1, TGSI_CHAN_X, derivs[0]);
fetch_assign_deriv_channel(mach, inst, 1, TGSI_CHAN_Y, derivs[1]);
fetch_assign_deriv_channel(mach, inst, 1, TGSI_CHAN_Z, derivs[2]);
 
fetch_texel(mach->Sampler, unit, unit,
&r[0], &r[1], &r[2], &r[3], &ZeroVec, /* inputs */
derivs, offsets, tgsi_sampler_derivs_explicit,
&r[0], &r[1], &r[2], &r[3]); /* outputs */
break;
 
default:
assert(0);
}
 
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
store_dest(mach, &r[chan], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
}
}
}
 
 
static void
exec_txf(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
const uint unit = inst->Src[1].Register.Index;
union tgsi_exec_channel r[4];
uint chan;
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
int j;
int8_t offsets[3];
unsigned target;
 
/* always fetch all 3 offsets, overkill but keeps code simple */
fetch_texel_offsets(mach, inst, offsets);
 
IFETCH(&r[3], 0, TGSI_CHAN_W);
 
if (inst->Instruction.Opcode == TGSI_OPCODE_SAMPLE_I) {
target = mach->SamplerViews[unit].Resource;
}
else {
target = inst->Texture.Texture;
}
switch(target) {
case TGSI_TEXTURE_3D:
case TGSI_TEXTURE_2D_ARRAY:
case TGSI_TEXTURE_SHADOW2D_ARRAY:
IFETCH(&r[2], 0, TGSI_CHAN_Z);
/* fallthrough */
case TGSI_TEXTURE_2D:
case TGSI_TEXTURE_RECT:
case TGSI_TEXTURE_SHADOW1D_ARRAY:
case TGSI_TEXTURE_SHADOW2D:
case TGSI_TEXTURE_SHADOWRECT:
case TGSI_TEXTURE_1D_ARRAY:
IFETCH(&r[1], 0, TGSI_CHAN_Y);
/* fallthrough */
case TGSI_TEXTURE_BUFFER:
case TGSI_TEXTURE_1D:
case TGSI_TEXTURE_SHADOW1D:
IFETCH(&r[0], 0, TGSI_CHAN_X);
break;
default:
assert(0);
break;
}
 
mach->Sampler->get_texel(mach->Sampler, unit, r[0].i, r[1].i, r[2].i, r[3].i,
offsets, rgba);
 
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
r[0].f[j] = rgba[0][j];
r[1].f[j] = rgba[1][j];
r[2].f[j] = rgba[2][j];
r[3].f[j] = rgba[3][j];
}
 
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
store_dest(mach, &r[chan], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
}
}
}
 
static void
exec_txq(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
const uint unit = inst->Src[1].Register.Index;
int result[4];
union tgsi_exec_channel r[4], src;
uint chan;
int i,j;
 
fetch_source(mach, &src, &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_INT);
 
mach->Sampler->get_dims(mach->Sampler, unit, src.i[0], result);
 
for (i = 0; i < TGSI_QUAD_SIZE; i++) {
for (j = 0; j < 4; j++) {
r[j].i[i] = result[j];
}
}
 
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
store_dest(mach, &r[chan], &inst->Dst[0], inst, chan,
TGSI_EXEC_DATA_INT);
}
}
}
 
static void
exec_sample(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst,
uint modifier, boolean compare)
{
const uint resource_unit = inst->Src[1].Register.Index;
const uint sampler_unit = inst->Src[2].Register.Index;
union tgsi_exec_channel r[4], c1;
const union tgsi_exec_channel *lod = &ZeroVec;
enum tgsi_sampler_control control = tgsi_sampler_lod_none;
uint chan;
int8_t offsets[3];
 
/* always fetch all 3 offsets, overkill but keeps code simple */
fetch_texel_offsets(mach, inst, offsets);
 
assert(modifier != TEX_MODIFIER_PROJECTED);
 
if (modifier != TEX_MODIFIER_NONE) {
if (modifier == TEX_MODIFIER_LOD_BIAS) {
FETCH(&c1, 3, TGSI_CHAN_X);
lod = &c1;
control = tgsi_sampler_lod_bias;
}
else if (modifier == TEX_MODIFIER_EXPLICIT_LOD) {
FETCH(&c1, 3, TGSI_CHAN_X);
lod = &c1;
control = tgsi_sampler_lod_explicit;
}
else {
assert(modifier == TEX_MODIFIER_LEVEL_ZERO);
control = tgsi_sampler_lod_zero;
}
}
 
FETCH(&r[0], 0, TGSI_CHAN_X);
 
switch (mach->SamplerViews[resource_unit].Resource) {
case TGSI_TEXTURE_1D:
if (compare) {
FETCH(&r[2], 3, TGSI_CHAN_X);
fetch_texel(mach->Sampler, resource_unit, sampler_unit,
&r[0], &ZeroVec, &r[2], &ZeroVec, lod, /* S, T, P, C, LOD */
NULL, offsets, control,
&r[0], &r[1], &r[2], &r[3]); /* R, G, B, A */
}
else {
fetch_texel(mach->Sampler, resource_unit, sampler_unit,
&r[0], &ZeroVec, &ZeroVec, &ZeroVec, lod, /* S, T, P, C, LOD */
NULL, offsets, control,
&r[0], &r[1], &r[2], &r[3]); /* R, G, B, A */
}
break;
 
case TGSI_TEXTURE_1D_ARRAY:
case TGSI_TEXTURE_2D:
case TGSI_TEXTURE_RECT:
FETCH(&r[1], 0, TGSI_CHAN_Y);
if (compare) {
FETCH(&r[2], 3, TGSI_CHAN_X);
fetch_texel(mach->Sampler, resource_unit, sampler_unit,
&r[0], &r[1], &r[2], &ZeroVec, lod, /* S, T, P, C, LOD */
NULL, offsets, control,
&r[0], &r[1], &r[2], &r[3]); /* outputs */
}
else {
fetch_texel(mach->Sampler, resource_unit, sampler_unit,
&r[0], &r[1], &ZeroVec, &ZeroVec, lod, /* S, T, P, C, LOD */
NULL, offsets, control,
&r[0], &r[1], &r[2], &r[3]); /* outputs */
}
break;
 
case TGSI_TEXTURE_2D_ARRAY:
case TGSI_TEXTURE_3D:
case TGSI_TEXTURE_CUBE:
FETCH(&r[1], 0, TGSI_CHAN_Y);
FETCH(&r[2], 0, TGSI_CHAN_Z);
if(compare) {
FETCH(&r[3], 3, TGSI_CHAN_X);
fetch_texel(mach->Sampler, resource_unit, sampler_unit,
&r[0], &r[1], &r[2], &r[3], lod,
NULL, offsets, control,
&r[0], &r[1], &r[2], &r[3]);
}
else {
fetch_texel(mach->Sampler, resource_unit, sampler_unit,
&r[0], &r[1], &r[2], &ZeroVec, lod,
NULL, offsets, control,
&r[0], &r[1], &r[2], &r[3]);
}
break;
 
case TGSI_TEXTURE_CUBE_ARRAY:
FETCH(&r[1], 0, TGSI_CHAN_Y);
FETCH(&r[2], 0, TGSI_CHAN_Z);
FETCH(&r[3], 0, TGSI_CHAN_W);
if(compare) {
FETCH(&r[4], 3, TGSI_CHAN_X);
fetch_texel(mach->Sampler, resource_unit, sampler_unit,
&r[0], &r[1], &r[2], &r[3], &r[4],
NULL, offsets, control,
&r[0], &r[1], &r[2], &r[3]);
}
else {
fetch_texel(mach->Sampler, resource_unit, sampler_unit,
&r[0], &r[1], &r[2], &r[3], lod,
NULL, offsets, control,
&r[0], &r[1], &r[2], &r[3]);
}
break;
 
 
default:
assert(0);
}
 
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
store_dest(mach, &r[chan], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
}
}
}
 
static void
exec_sample_d(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
const uint resource_unit = inst->Src[1].Register.Index;
const uint sampler_unit = inst->Src[2].Register.Index;
union tgsi_exec_channel r[4];
float derivs[3][2][TGSI_QUAD_SIZE];
uint chan;
int8_t offsets[3];
 
/* always fetch all 3 offsets, overkill but keeps code simple */
fetch_texel_offsets(mach, inst, offsets);
 
FETCH(&r[0], 0, TGSI_CHAN_X);
 
switch (mach->SamplerViews[resource_unit].Resource) {
case TGSI_TEXTURE_1D:
case TGSI_TEXTURE_1D_ARRAY:
/* only 1D array actually needs Y */
FETCH(&r[1], 0, TGSI_CHAN_Y);
 
fetch_assign_deriv_channel(mach, inst, 3, TGSI_CHAN_X, derivs[0]);
 
fetch_texel(mach->Sampler, resource_unit, sampler_unit,
&r[0], &r[1], &ZeroVec, &ZeroVec, &ZeroVec, /* S, T, P, C, LOD */
derivs, offsets, tgsi_sampler_derivs_explicit,
&r[0], &r[1], &r[2], &r[3]); /* R, G, B, A */
break;
 
case TGSI_TEXTURE_2D:
case TGSI_TEXTURE_RECT:
case TGSI_TEXTURE_2D_ARRAY:
/* only 2D array actually needs Z */
FETCH(&r[1], 0, TGSI_CHAN_Y);
FETCH(&r[2], 0, TGSI_CHAN_Z);
 
fetch_assign_deriv_channel(mach, inst, 3, TGSI_CHAN_X, derivs[0]);
fetch_assign_deriv_channel(mach, inst, 3, TGSI_CHAN_Y, derivs[1]);
 
fetch_texel(mach->Sampler, resource_unit, sampler_unit,
&r[0], &r[1], &r[2], &ZeroVec, &ZeroVec, /* inputs */
derivs, offsets, tgsi_sampler_derivs_explicit,
&r[0], &r[1], &r[2], &r[3]); /* outputs */
break;
 
case TGSI_TEXTURE_3D:
case TGSI_TEXTURE_CUBE:
case TGSI_TEXTURE_CUBE_ARRAY:
/* only cube array actually needs W */
FETCH(&r[1], 0, TGSI_CHAN_Y);
FETCH(&r[2], 0, TGSI_CHAN_Z);
FETCH(&r[3], 0, TGSI_CHAN_W);
 
fetch_assign_deriv_channel(mach, inst, 3, TGSI_CHAN_X, derivs[0]);
fetch_assign_deriv_channel(mach, inst, 3, TGSI_CHAN_Y, derivs[1]);
fetch_assign_deriv_channel(mach, inst, 3, TGSI_CHAN_Z, derivs[2]);
 
fetch_texel(mach->Sampler, resource_unit, sampler_unit,
&r[0], &r[1], &r[2], &r[3], &ZeroVec,
derivs, offsets, tgsi_sampler_derivs_explicit,
&r[0], &r[1], &r[2], &r[3]);
break;
 
default:
assert(0);
}
 
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
store_dest(mach, &r[chan], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
}
}
}
 
 
/**
* Evaluate a constant-valued coefficient at the position of the
* current quad.
*/
static void
eval_constant_coef(
struct tgsi_exec_machine *mach,
unsigned attrib,
unsigned chan )
{
unsigned i;
 
for( i = 0; i < TGSI_QUAD_SIZE; i++ ) {
mach->Inputs[attrib].xyzw[chan].f[i] = mach->InterpCoefs[attrib].a0[chan];
}
}
 
/**
* Evaluate a linear-valued coefficient at the position of the
* current quad.
*/
static void
eval_linear_coef(
struct tgsi_exec_machine *mach,
unsigned attrib,
unsigned chan )
{
const float x = mach->QuadPos.xyzw[0].f[0];
const float y = mach->QuadPos.xyzw[1].f[0];
const float dadx = mach->InterpCoefs[attrib].dadx[chan];
const float dady = mach->InterpCoefs[attrib].dady[chan];
const float a0 = mach->InterpCoefs[attrib].a0[chan] + dadx * x + dady * y;
mach->Inputs[attrib].xyzw[chan].f[0] = a0;
mach->Inputs[attrib].xyzw[chan].f[1] = a0 + dadx;
mach->Inputs[attrib].xyzw[chan].f[2] = a0 + dady;
mach->Inputs[attrib].xyzw[chan].f[3] = a0 + dadx + dady;
}
 
/**
* Evaluate a perspective-valued coefficient at the position of the
* current quad.
*/
static void
eval_perspective_coef(
struct tgsi_exec_machine *mach,
unsigned attrib,
unsigned chan )
{
const float x = mach->QuadPos.xyzw[0].f[0];
const float y = mach->QuadPos.xyzw[1].f[0];
const float dadx = mach->InterpCoefs[attrib].dadx[chan];
const float dady = mach->InterpCoefs[attrib].dady[chan];
const float a0 = mach->InterpCoefs[attrib].a0[chan] + dadx * x + dady * y;
const float *w = mach->QuadPos.xyzw[3].f;
/* divide by W here */
mach->Inputs[attrib].xyzw[chan].f[0] = a0 / w[0];
mach->Inputs[attrib].xyzw[chan].f[1] = (a0 + dadx) / w[1];
mach->Inputs[attrib].xyzw[chan].f[2] = (a0 + dady) / w[2];
mach->Inputs[attrib].xyzw[chan].f[3] = (a0 + dadx + dady) / w[3];
}
 
 
typedef void (* eval_coef_func)(
struct tgsi_exec_machine *mach,
unsigned attrib,
unsigned chan );
 
static void
exec_declaration(struct tgsi_exec_machine *mach,
const struct tgsi_full_declaration *decl)
{
if (decl->Declaration.File == TGSI_FILE_SAMPLER_VIEW) {
mach->SamplerViews[decl->Range.First] = decl->SamplerView;
return;
}
 
if (mach->Processor == TGSI_PROCESSOR_FRAGMENT) {
if (decl->Declaration.File == TGSI_FILE_INPUT) {
uint first, last, mask;
 
first = decl->Range.First;
last = decl->Range.Last;
mask = decl->Declaration.UsageMask;
 
/* XXX we could remove this special-case code since
* mach->InterpCoefs[first].a0 should already have the
* front/back-face value. But we should first update the
* ureg code to emit the right UsageMask value (WRITEMASK_X).
* Then, we could remove the tgsi_exec_machine::Face field.
*/
/* XXX make FACE a system value */
if (decl->Semantic.Name == TGSI_SEMANTIC_FACE) {
uint i;
 
assert(decl->Semantic.Index == 0);
assert(first == last);
 
for (i = 0; i < TGSI_QUAD_SIZE; i++) {
mach->Inputs[first].xyzw[0].f[i] = mach->Face;
}
} else {
eval_coef_func eval;
uint i, j;
 
switch (decl->Interp.Interpolate) {
case TGSI_INTERPOLATE_CONSTANT:
eval = eval_constant_coef;
break;
 
case TGSI_INTERPOLATE_LINEAR:
eval = eval_linear_coef;
break;
 
case TGSI_INTERPOLATE_PERSPECTIVE:
eval = eval_perspective_coef;
break;
 
case TGSI_INTERPOLATE_COLOR:
eval = mach->flatshade_color ? eval_constant_coef : eval_perspective_coef;
break;
 
default:
assert(0);
return;
}
 
for (j = 0; j < TGSI_NUM_CHANNELS; j++) {
if (mask & (1 << j)) {
for (i = first; i <= last; i++) {
eval(mach, i, j);
}
}
}
}
 
if (DEBUG_EXECUTION) {
uint i, j;
for (i = first; i <= last; ++i) {
debug_printf("IN[%2u] = ", i);
for (j = 0; j < TGSI_NUM_CHANNELS; j++) {
if (j > 0) {
debug_printf(" ");
}
debug_printf("(%6f %u, %6f %u, %6f %u, %6f %u)\n",
mach->Inputs[i].xyzw[0].f[j], mach->Inputs[i].xyzw[0].u[j],
mach->Inputs[i].xyzw[1].f[j], mach->Inputs[i].xyzw[1].u[j],
mach->Inputs[i].xyzw[2].f[j], mach->Inputs[i].xyzw[2].u[j],
mach->Inputs[i].xyzw[3].f[j], mach->Inputs[i].xyzw[3].u[j]);
}
}
}
}
}
 
if (decl->Declaration.File == TGSI_FILE_SYSTEM_VALUE) {
mach->SysSemanticToIndex[decl->Declaration.Semantic] = decl->Range.First;
}
}
 
 
typedef void (* micro_op)(union tgsi_exec_channel *dst);
 
static void
exec_vector(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst,
micro_op op,
enum tgsi_exec_datatype dst_datatype)
{
unsigned int chan;
 
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
union tgsi_exec_channel dst;
 
op(&dst);
store_dest(mach, &dst, &inst->Dst[0], inst, chan, dst_datatype);
}
}
}
 
typedef void (* micro_unary_op)(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src);
 
static void
exec_scalar_unary(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst,
micro_unary_op op,
enum tgsi_exec_datatype dst_datatype,
enum tgsi_exec_datatype src_datatype)
{
unsigned int chan;
union tgsi_exec_channel src;
union tgsi_exec_channel dst;
 
fetch_source(mach, &src, &inst->Src[0], TGSI_CHAN_X, src_datatype);
op(&dst, &src);
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
store_dest(mach, &dst, &inst->Dst[0], inst, chan, dst_datatype);
}
}
}
 
static void
exec_vector_unary(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst,
micro_unary_op op,
enum tgsi_exec_datatype dst_datatype,
enum tgsi_exec_datatype src_datatype)
{
unsigned int chan;
struct tgsi_exec_vector dst;
 
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
union tgsi_exec_channel src;
 
fetch_source(mach, &src, &inst->Src[0], chan, src_datatype);
op(&dst.xyzw[chan], &src);
}
}
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
store_dest(mach, &dst.xyzw[chan], &inst->Dst[0], inst, chan, dst_datatype);
}
}
}
 
typedef void (* micro_binary_op)(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1);
 
static void
exec_scalar_binary(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst,
micro_binary_op op,
enum tgsi_exec_datatype dst_datatype,
enum tgsi_exec_datatype src_datatype)
{
unsigned int chan;
union tgsi_exec_channel src[2];
union tgsi_exec_channel dst;
 
fetch_source(mach, &src[0], &inst->Src[0], TGSI_CHAN_X, src_datatype);
fetch_source(mach, &src[1], &inst->Src[1], TGSI_CHAN_Y, src_datatype);
op(&dst, &src[0], &src[1]);
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
store_dest(mach, &dst, &inst->Dst[0], inst, chan, dst_datatype);
}
}
}
 
static void
exec_vector_binary(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst,
micro_binary_op op,
enum tgsi_exec_datatype dst_datatype,
enum tgsi_exec_datatype src_datatype)
{
unsigned int chan;
struct tgsi_exec_vector dst;
 
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
union tgsi_exec_channel src[2];
 
fetch_source(mach, &src[0], &inst->Src[0], chan, src_datatype);
fetch_source(mach, &src[1], &inst->Src[1], chan, src_datatype);
op(&dst.xyzw[chan], &src[0], &src[1]);
}
}
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
store_dest(mach, &dst.xyzw[chan], &inst->Dst[0], inst, chan, dst_datatype);
}
}
}
 
typedef void (* micro_trinary_op)(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1,
const union tgsi_exec_channel *src2);
 
static void
exec_vector_trinary(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst,
micro_trinary_op op,
enum tgsi_exec_datatype dst_datatype,
enum tgsi_exec_datatype src_datatype)
{
unsigned int chan;
struct tgsi_exec_vector dst;
 
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
union tgsi_exec_channel src[3];
 
fetch_source(mach, &src[0], &inst->Src[0], chan, src_datatype);
fetch_source(mach, &src[1], &inst->Src[1], chan, src_datatype);
fetch_source(mach, &src[2], &inst->Src[2], chan, src_datatype);
op(&dst.xyzw[chan], &src[0], &src[1], &src[2]);
}
}
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
store_dest(mach, &dst.xyzw[chan], &inst->Dst[0], inst, chan, dst_datatype);
}
}
}
 
static void
exec_dp3(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
unsigned int chan;
union tgsi_exec_channel arg[3];
 
fetch_source(mach, &arg[0], &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
fetch_source(mach, &arg[1], &inst->Src[1], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
micro_mul(&arg[2], &arg[0], &arg[1]);
 
for (chan = TGSI_CHAN_Y; chan <= TGSI_CHAN_Z; chan++) {
fetch_source(mach, &arg[0], &inst->Src[0], chan, TGSI_EXEC_DATA_FLOAT);
fetch_source(mach, &arg[1], &inst->Src[1], chan, TGSI_EXEC_DATA_FLOAT);
micro_mad(&arg[2], &arg[0], &arg[1], &arg[2]);
}
 
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
store_dest(mach, &arg[2], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
}
}
}
 
static void
exec_dp4(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
unsigned int chan;
union tgsi_exec_channel arg[3];
 
fetch_source(mach, &arg[0], &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
fetch_source(mach, &arg[1], &inst->Src[1], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
micro_mul(&arg[2], &arg[0], &arg[1]);
 
for (chan = TGSI_CHAN_Y; chan <= TGSI_CHAN_W; chan++) {
fetch_source(mach, &arg[0], &inst->Src[0], chan, TGSI_EXEC_DATA_FLOAT);
fetch_source(mach, &arg[1], &inst->Src[1], chan, TGSI_EXEC_DATA_FLOAT);
micro_mad(&arg[2], &arg[0], &arg[1], &arg[2]);
}
 
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
store_dest(mach, &arg[2], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
}
}
}
 
static void
exec_dp2a(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
unsigned int chan;
union tgsi_exec_channel arg[3];
 
fetch_source(mach, &arg[0], &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
fetch_source(mach, &arg[1], &inst->Src[1], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
micro_mul(&arg[2], &arg[0], &arg[1]);
 
fetch_source(mach, &arg[0], &inst->Src[0], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
fetch_source(mach, &arg[1], &inst->Src[1], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
micro_mad(&arg[0], &arg[0], &arg[1], &arg[2]);
 
fetch_source(mach, &arg[1], &inst->Src[2], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
micro_add(&arg[0], &arg[0], &arg[1]);
 
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
store_dest(mach, &arg[0], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
}
}
}
 
static void
exec_dph(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
unsigned int chan;
union tgsi_exec_channel arg[3];
 
fetch_source(mach, &arg[0], &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
fetch_source(mach, &arg[1], &inst->Src[1], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
micro_mul(&arg[2], &arg[0], &arg[1]);
 
fetch_source(mach, &arg[0], &inst->Src[0], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
fetch_source(mach, &arg[1], &inst->Src[1], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
micro_mad(&arg[2], &arg[0], &arg[1], &arg[2]);
 
fetch_source(mach, &arg[0], &inst->Src[0], TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT);
fetch_source(mach, &arg[1], &inst->Src[1], TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT);
micro_mad(&arg[0], &arg[0], &arg[1], &arg[2]);
 
fetch_source(mach, &arg[1], &inst->Src[1], TGSI_CHAN_W, TGSI_EXEC_DATA_FLOAT);
micro_add(&arg[0], &arg[0], &arg[1]);
 
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
store_dest(mach, &arg[0], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
}
}
}
 
static void
exec_dp2(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
unsigned int chan;
union tgsi_exec_channel arg[3];
 
fetch_source(mach, &arg[0], &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
fetch_source(mach, &arg[1], &inst->Src[1], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
micro_mul(&arg[2], &arg[0], &arg[1]);
 
fetch_source(mach, &arg[0], &inst->Src[0], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
fetch_source(mach, &arg[1], &inst->Src[1], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
micro_mad(&arg[2], &arg[0], &arg[1], &arg[2]);
 
for (chan = 0; chan < TGSI_NUM_CHANNELS; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
store_dest(mach, &arg[2], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
}
}
}
 
static void
exec_nrm4(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
unsigned int chan;
union tgsi_exec_channel arg[4];
union tgsi_exec_channel scale;
 
fetch_source(mach, &arg[0], &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
micro_mul(&scale, &arg[0], &arg[0]);
 
for (chan = TGSI_CHAN_Y; chan <= TGSI_CHAN_W; chan++) {
union tgsi_exec_channel product;
 
fetch_source(mach, &arg[chan], &inst->Src[0], chan, TGSI_EXEC_DATA_FLOAT);
micro_mul(&product, &arg[chan], &arg[chan]);
micro_add(&scale, &scale, &product);
}
 
micro_rsq(&scale, &scale);
 
for (chan = TGSI_CHAN_X; chan <= TGSI_CHAN_W; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
micro_mul(&arg[chan], &arg[chan], &scale);
store_dest(mach, &arg[chan], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
}
}
}
 
static void
exec_nrm3(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_XYZ) {
unsigned int chan;
union tgsi_exec_channel arg[3];
union tgsi_exec_channel scale;
 
fetch_source(mach, &arg[0], &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
micro_mul(&scale, &arg[0], &arg[0]);
 
for (chan = TGSI_CHAN_Y; chan <= TGSI_CHAN_Z; chan++) {
union tgsi_exec_channel product;
 
fetch_source(mach, &arg[chan], &inst->Src[0], chan, TGSI_EXEC_DATA_FLOAT);
micro_mul(&product, &arg[chan], &arg[chan]);
micro_add(&scale, &scale, &product);
}
 
micro_rsq(&scale, &scale);
 
for (chan = TGSI_CHAN_X; chan <= TGSI_CHAN_Z; chan++) {
if (inst->Dst[0].Register.WriteMask & (1 << chan)) {
micro_mul(&arg[chan], &arg[chan], &scale);
store_dest(mach, &arg[chan], &inst->Dst[0], inst, chan, TGSI_EXEC_DATA_FLOAT);
}
}
}
 
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_W) {
store_dest(mach, &OneVec, &inst->Dst[0], inst, TGSI_CHAN_W, TGSI_EXEC_DATA_FLOAT);
}
}
 
static void
exec_scs(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_XY) {
union tgsi_exec_channel arg;
union tgsi_exec_channel result;
 
fetch_source(mach, &arg, &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
 
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_X) {
micro_cos(&result, &arg);
store_dest(mach, &result, &inst->Dst[0], inst, TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Y) {
micro_sin(&result, &arg);
store_dest(mach, &result, &inst->Dst[0], inst, TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
}
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Z) {
store_dest(mach, &ZeroVec, &inst->Dst[0], inst, TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_W) {
store_dest(mach, &OneVec, &inst->Dst[0], inst, TGSI_CHAN_W, TGSI_EXEC_DATA_FLOAT);
}
}
 
static void
exec_x2d(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
union tgsi_exec_channel r[4];
union tgsi_exec_channel d[2];
 
fetch_source(mach, &r[0], &inst->Src[1], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
fetch_source(mach, &r[1], &inst->Src[1], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_XZ) {
fetch_source(mach, &r[2], &inst->Src[2], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
micro_mul(&r[2], &r[2], &r[0]);
fetch_source(mach, &r[3], &inst->Src[2], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
micro_mul(&r[3], &r[3], &r[1]);
micro_add(&r[2], &r[2], &r[3]);
fetch_source(mach, &r[3], &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
micro_add(&d[0], &r[2], &r[3]);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_YW) {
fetch_source(mach, &r[2], &inst->Src[2], TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT);
micro_mul(&r[2], &r[2], &r[0]);
fetch_source(mach, &r[3], &inst->Src[2], TGSI_CHAN_W, TGSI_EXEC_DATA_FLOAT);
micro_mul(&r[3], &r[3], &r[1]);
micro_add(&r[2], &r[2], &r[3]);
fetch_source(mach, &r[3], &inst->Src[0], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
micro_add(&d[1], &r[2], &r[3]);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_X) {
store_dest(mach, &d[0], &inst->Dst[0], inst, TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Y) {
store_dest(mach, &d[1], &inst->Dst[0], inst, TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Z) {
store_dest(mach, &d[0], &inst->Dst[0], inst, TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_W) {
store_dest(mach, &d[1], &inst->Dst[0], inst, TGSI_CHAN_W, TGSI_EXEC_DATA_FLOAT);
}
}
 
static void
exec_rfl(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
union tgsi_exec_channel r[9];
 
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_XYZ) {
/* r0 = dp3(src0, src0) */
fetch_source(mach, &r[2], &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
micro_mul(&r[0], &r[2], &r[2]);
fetch_source(mach, &r[4], &inst->Src[0], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
micro_mul(&r[8], &r[4], &r[4]);
micro_add(&r[0], &r[0], &r[8]);
fetch_source(mach, &r[6], &inst->Src[0], TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT);
micro_mul(&r[8], &r[6], &r[6]);
micro_add(&r[0], &r[0], &r[8]);
 
/* r1 = dp3(src0, src1) */
fetch_source(mach, &r[3], &inst->Src[1], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
micro_mul(&r[1], &r[2], &r[3]);
fetch_source(mach, &r[5], &inst->Src[1], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
micro_mul(&r[8], &r[4], &r[5]);
micro_add(&r[1], &r[1], &r[8]);
fetch_source(mach, &r[7], &inst->Src[1], TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT);
micro_mul(&r[8], &r[6], &r[7]);
micro_add(&r[1], &r[1], &r[8]);
 
/* r1 = 2 * r1 / r0 */
micro_add(&r[1], &r[1], &r[1]);
micro_div(&r[1], &r[1], &r[0]);
 
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_X) {
micro_mul(&r[2], &r[2], &r[1]);
micro_sub(&r[2], &r[2], &r[3]);
store_dest(mach, &r[2], &inst->Dst[0], inst, TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Y) {
micro_mul(&r[4], &r[4], &r[1]);
micro_sub(&r[4], &r[4], &r[5]);
store_dest(mach, &r[4], &inst->Dst[0], inst, TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Z) {
micro_mul(&r[6], &r[6], &r[1]);
micro_sub(&r[6], &r[6], &r[7]);
store_dest(mach, &r[6], &inst->Dst[0], inst, TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT);
}
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_W) {
store_dest(mach, &OneVec, &inst->Dst[0], inst, TGSI_CHAN_W, TGSI_EXEC_DATA_FLOAT);
}
}
 
static void
exec_xpd(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
union tgsi_exec_channel r[6];
union tgsi_exec_channel d[3];
 
fetch_source(mach, &r[0], &inst->Src[0], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
fetch_source(mach, &r[1], &inst->Src[1], TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT);
 
micro_mul(&r[2], &r[0], &r[1]);
 
fetch_source(mach, &r[3], &inst->Src[0], TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT);
fetch_source(mach, &r[4], &inst->Src[1], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
 
micro_mul(&r[5], &r[3], &r[4] );
micro_sub(&d[TGSI_CHAN_X], &r[2], &r[5]);
 
fetch_source(mach, &r[2], &inst->Src[1], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
 
micro_mul(&r[3], &r[3], &r[2]);
 
fetch_source(mach, &r[5], &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
 
micro_mul(&r[1], &r[1], &r[5]);
micro_sub(&d[TGSI_CHAN_Y], &r[3], &r[1]);
 
micro_mul(&r[5], &r[5], &r[4]);
micro_mul(&r[0], &r[0], &r[2]);
micro_sub(&d[TGSI_CHAN_Z], &r[5], &r[0]);
 
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_X) {
store_dest(mach, &d[TGSI_CHAN_X], &inst->Dst[0], inst, TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Y) {
store_dest(mach, &d[TGSI_CHAN_Y], &inst->Dst[0], inst, TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Z) {
store_dest(mach, &d[TGSI_CHAN_Z], &inst->Dst[0], inst, TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_W) {
store_dest(mach, &OneVec, &inst->Dst[0], inst, TGSI_CHAN_W, TGSI_EXEC_DATA_FLOAT);
}
}
 
static void
exec_dst(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
union tgsi_exec_channel r[2];
union tgsi_exec_channel d[4];
 
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Y) {
fetch_source(mach, &r[0], &inst->Src[0], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
fetch_source(mach, &r[1], &inst->Src[1], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
micro_mul(&d[TGSI_CHAN_Y], &r[0], &r[1]);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Z) {
fetch_source(mach, &d[TGSI_CHAN_Z], &inst->Src[0], TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_W) {
fetch_source(mach, &d[TGSI_CHAN_W], &inst->Src[1], TGSI_CHAN_W, TGSI_EXEC_DATA_FLOAT);
}
 
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_X) {
store_dest(mach, &OneVec, &inst->Dst[0], inst, TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Y) {
store_dest(mach, &d[TGSI_CHAN_Y], &inst->Dst[0], inst, TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Z) {
store_dest(mach, &d[TGSI_CHAN_Z], &inst->Dst[0], inst, TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_W) {
store_dest(mach, &d[TGSI_CHAN_W], &inst->Dst[0], inst, TGSI_CHAN_W, TGSI_EXEC_DATA_FLOAT);
}
}
 
static void
exec_log(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
union tgsi_exec_channel r[3];
 
fetch_source(mach, &r[0], &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
micro_abs(&r[2], &r[0]); /* r2 = abs(r0) */
micro_lg2(&r[1], &r[2]); /* r1 = lg2(r2) */
micro_flr(&r[0], &r[1]); /* r0 = floor(r1) */
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_X) {
store_dest(mach, &r[0], &inst->Dst[0], inst, TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Y) {
micro_exp2(&r[0], &r[0]); /* r0 = 2 ^ r0 */
micro_div(&r[0], &r[2], &r[0]); /* r0 = r2 / r0 */
store_dest(mach, &r[0], &inst->Dst[0], inst, TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Z) {
store_dest(mach, &r[1], &inst->Dst[0], inst, TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_W) {
store_dest(mach, &OneVec, &inst->Dst[0], inst, TGSI_CHAN_W, TGSI_EXEC_DATA_FLOAT);
}
}
 
static void
exec_exp(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
union tgsi_exec_channel r[3];
 
fetch_source(mach, &r[0], &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
micro_flr(&r[1], &r[0]); /* r1 = floor(r0) */
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_X) {
micro_exp2(&r[2], &r[1]); /* r2 = 2 ^ r1 */
store_dest(mach, &r[2], &inst->Dst[0], inst, TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Y) {
micro_sub(&r[2], &r[0], &r[1]); /* r2 = r0 - r1 */
store_dest(mach, &r[2], &inst->Dst[0], inst, TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Z) {
micro_exp2(&r[2], &r[0]); /* r2 = 2 ^ r0 */
store_dest(mach, &r[2], &inst->Dst[0], inst, TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_W) {
store_dest(mach, &OneVec, &inst->Dst[0], inst, TGSI_CHAN_W, TGSI_EXEC_DATA_FLOAT);
}
}
 
static void
exec_lit(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
union tgsi_exec_channel r[3];
union tgsi_exec_channel d[3];
 
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_YZ) {
fetch_source(mach, &r[0], &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Z) {
fetch_source(mach, &r[1], &inst->Src[0], TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
micro_max(&r[1], &r[1], &ZeroVec);
 
fetch_source(mach, &r[2], &inst->Src[0], TGSI_CHAN_W, TGSI_EXEC_DATA_FLOAT);
micro_min(&r[2], &r[2], &P128Vec);
micro_max(&r[2], &r[2], &M128Vec);
micro_pow(&r[1], &r[1], &r[2]);
micro_lt(&d[TGSI_CHAN_Z], &ZeroVec, &r[0], &r[1], &ZeroVec);
store_dest(mach, &d[TGSI_CHAN_Z], &inst->Dst[0], inst, TGSI_CHAN_Z, TGSI_EXEC_DATA_FLOAT);
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_Y) {
micro_max(&d[TGSI_CHAN_Y], &r[0], &ZeroVec);
store_dest(mach, &d[TGSI_CHAN_Y], &inst->Dst[0], inst, TGSI_CHAN_Y, TGSI_EXEC_DATA_FLOAT);
}
}
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_X) {
store_dest(mach, &OneVec, &inst->Dst[0], inst, TGSI_CHAN_X, TGSI_EXEC_DATA_FLOAT);
}
 
if (inst->Dst[0].Register.WriteMask & TGSI_WRITEMASK_W) {
store_dest(mach, &OneVec, &inst->Dst[0], inst, TGSI_CHAN_W, TGSI_EXEC_DATA_FLOAT);
}
}
 
static void
exec_break(struct tgsi_exec_machine *mach)
{
if (mach->BreakType == TGSI_EXEC_BREAK_INSIDE_LOOP) {
/* turn off loop channels for each enabled exec channel */
mach->LoopMask &= ~mach->ExecMask;
/* Todo: if mach->LoopMask == 0, jump to end of loop */
UPDATE_EXEC_MASK(mach);
} else {
assert(mach->BreakType == TGSI_EXEC_BREAK_INSIDE_SWITCH);
 
mach->Switch.mask = 0x0;
 
UPDATE_EXEC_MASK(mach);
}
}
 
static void
exec_switch(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
assert(mach->SwitchStackTop < TGSI_EXEC_MAX_SWITCH_NESTING);
assert(mach->BreakStackTop < TGSI_EXEC_MAX_BREAK_STACK);
 
mach->SwitchStack[mach->SwitchStackTop++] = mach->Switch;
fetch_source(mach, &mach->Switch.selector, &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_UINT);
mach->Switch.mask = 0x0;
mach->Switch.defaultMask = 0x0;
 
mach->BreakStack[mach->BreakStackTop++] = mach->BreakType;
mach->BreakType = TGSI_EXEC_BREAK_INSIDE_SWITCH;
 
UPDATE_EXEC_MASK(mach);
}
 
static void
exec_case(struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst)
{
uint prevMask = mach->SwitchStack[mach->SwitchStackTop - 1].mask;
union tgsi_exec_channel src;
uint mask = 0;
 
fetch_source(mach, &src, &inst->Src[0], TGSI_CHAN_X, TGSI_EXEC_DATA_UINT);
 
if (mach->Switch.selector.u[0] == src.u[0]) {
mask |= 0x1;
}
if (mach->Switch.selector.u[1] == src.u[1]) {
mask |= 0x2;
}
if (mach->Switch.selector.u[2] == src.u[2]) {
mask |= 0x4;
}
if (mach->Switch.selector.u[3] == src.u[3]) {
mask |= 0x8;
}
 
mach->Switch.defaultMask |= mask;
 
mach->Switch.mask |= mask & prevMask;
 
UPDATE_EXEC_MASK(mach);
}
 
/* FIXME: this will only work if default is last */
static void
exec_default(struct tgsi_exec_machine *mach)
{
uint prevMask = mach->SwitchStack[mach->SwitchStackTop - 1].mask;
 
mach->Switch.mask |= ~mach->Switch.defaultMask & prevMask;
 
UPDATE_EXEC_MASK(mach);
}
 
static void
exec_endswitch(struct tgsi_exec_machine *mach)
{
mach->Switch = mach->SwitchStack[--mach->SwitchStackTop];
mach->BreakType = mach->BreakStack[--mach->BreakStackTop];
 
UPDATE_EXEC_MASK(mach);
}
 
static void
micro_i2f(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->f[0] = (float)src->i[0];
dst->f[1] = (float)src->i[1];
dst->f[2] = (float)src->i[2];
dst->f[3] = (float)src->i[3];
}
 
static void
micro_not(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->u[0] = ~src->u[0];
dst->u[1] = ~src->u[1];
dst->u[2] = ~src->u[2];
dst->u[3] = ~src->u[3];
}
 
static void
micro_shl(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->u[0] = src0->u[0] << src1->u[0];
dst->u[1] = src0->u[1] << src1->u[1];
dst->u[2] = src0->u[2] << src1->u[2];
dst->u[3] = src0->u[3] << src1->u[3];
}
 
static void
micro_and(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->u[0] = src0->u[0] & src1->u[0];
dst->u[1] = src0->u[1] & src1->u[1];
dst->u[2] = src0->u[2] & src1->u[2];
dst->u[3] = src0->u[3] & src1->u[3];
}
 
static void
micro_or(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->u[0] = src0->u[0] | src1->u[0];
dst->u[1] = src0->u[1] | src1->u[1];
dst->u[2] = src0->u[2] | src1->u[2];
dst->u[3] = src0->u[3] | src1->u[3];
}
 
static void
micro_xor(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->u[0] = src0->u[0] ^ src1->u[0];
dst->u[1] = src0->u[1] ^ src1->u[1];
dst->u[2] = src0->u[2] ^ src1->u[2];
dst->u[3] = src0->u[3] ^ src1->u[3];
}
 
static void
micro_mod(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->i[0] = src0->i[0] % src1->i[0];
dst->i[1] = src0->i[1] % src1->i[1];
dst->i[2] = src0->i[2] % src1->i[2];
dst->i[3] = src0->i[3] % src1->i[3];
}
 
static void
micro_f2i(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->i[0] = (int)src->f[0];
dst->i[1] = (int)src->f[1];
dst->i[2] = (int)src->f[2];
dst->i[3] = (int)src->f[3];
}
 
static void
micro_idiv(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->i[0] = src0->i[0] / src1->i[0];
dst->i[1] = src0->i[1] / src1->i[1];
dst->i[2] = src0->i[2] / src1->i[2];
dst->i[3] = src0->i[3] / src1->i[3];
}
 
static void
micro_imax(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->i[0] = src0->i[0] > src1->i[0] ? src0->i[0] : src1->i[0];
dst->i[1] = src0->i[1] > src1->i[1] ? src0->i[1] : src1->i[1];
dst->i[2] = src0->i[2] > src1->i[2] ? src0->i[2] : src1->i[2];
dst->i[3] = src0->i[3] > src1->i[3] ? src0->i[3] : src1->i[3];
}
 
static void
micro_imin(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->i[0] = src0->i[0] < src1->i[0] ? src0->i[0] : src1->i[0];
dst->i[1] = src0->i[1] < src1->i[1] ? src0->i[1] : src1->i[1];
dst->i[2] = src0->i[2] < src1->i[2] ? src0->i[2] : src1->i[2];
dst->i[3] = src0->i[3] < src1->i[3] ? src0->i[3] : src1->i[3];
}
 
static void
micro_isge(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->i[0] = src0->i[0] >= src1->i[0] ? -1 : 0;
dst->i[1] = src0->i[1] >= src1->i[1] ? -1 : 0;
dst->i[2] = src0->i[2] >= src1->i[2] ? -1 : 0;
dst->i[3] = src0->i[3] >= src1->i[3] ? -1 : 0;
}
 
static void
micro_ishr(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->i[0] = src0->i[0] >> src1->i[0];
dst->i[1] = src0->i[1] >> src1->i[1];
dst->i[2] = src0->i[2] >> src1->i[2];
dst->i[3] = src0->i[3] >> src1->i[3];
}
 
static void
micro_islt(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->i[0] = src0->i[0] < src1->i[0] ? -1 : 0;
dst->i[1] = src0->i[1] < src1->i[1] ? -1 : 0;
dst->i[2] = src0->i[2] < src1->i[2] ? -1 : 0;
dst->i[3] = src0->i[3] < src1->i[3] ? -1 : 0;
}
 
static void
micro_f2u(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->u[0] = (uint)src->f[0];
dst->u[1] = (uint)src->f[1];
dst->u[2] = (uint)src->f[2];
dst->u[3] = (uint)src->f[3];
}
 
static void
micro_u2f(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->f[0] = (float)src->u[0];
dst->f[1] = (float)src->u[1];
dst->f[2] = (float)src->u[2];
dst->f[3] = (float)src->u[3];
}
 
static void
micro_uadd(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->u[0] = src0->u[0] + src1->u[0];
dst->u[1] = src0->u[1] + src1->u[1];
dst->u[2] = src0->u[2] + src1->u[2];
dst->u[3] = src0->u[3] + src1->u[3];
}
 
static void
micro_udiv(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->u[0] = src1->u[0] ? src0->u[0] / src1->u[0] : ~0u;
dst->u[1] = src1->u[1] ? src0->u[1] / src1->u[1] : ~0u;
dst->u[2] = src1->u[2] ? src0->u[2] / src1->u[2] : ~0u;
dst->u[3] = src1->u[3] ? src0->u[3] / src1->u[3] : ~0u;
}
 
static void
micro_umad(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1,
const union tgsi_exec_channel *src2)
{
dst->u[0] = src0->u[0] * src1->u[0] + src2->u[0];
dst->u[1] = src0->u[1] * src1->u[1] + src2->u[1];
dst->u[2] = src0->u[2] * src1->u[2] + src2->u[2];
dst->u[3] = src0->u[3] * src1->u[3] + src2->u[3];
}
 
static void
micro_umax(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->u[0] = src0->u[0] > src1->u[0] ? src0->u[0] : src1->u[0];
dst->u[1] = src0->u[1] > src1->u[1] ? src0->u[1] : src1->u[1];
dst->u[2] = src0->u[2] > src1->u[2] ? src0->u[2] : src1->u[2];
dst->u[3] = src0->u[3] > src1->u[3] ? src0->u[3] : src1->u[3];
}
 
static void
micro_umin(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->u[0] = src0->u[0] < src1->u[0] ? src0->u[0] : src1->u[0];
dst->u[1] = src0->u[1] < src1->u[1] ? src0->u[1] : src1->u[1];
dst->u[2] = src0->u[2] < src1->u[2] ? src0->u[2] : src1->u[2];
dst->u[3] = src0->u[3] < src1->u[3] ? src0->u[3] : src1->u[3];
}
 
static void
micro_umod(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->u[0] = src1->u[0] ? src0->u[0] % src1->u[0] : ~0u;
dst->u[1] = src1->u[1] ? src0->u[1] % src1->u[1] : ~0u;
dst->u[2] = src1->u[2] ? src0->u[2] % src1->u[2] : ~0u;
dst->u[3] = src1->u[3] ? src0->u[3] % src1->u[3] : ~0u;
}
 
static void
micro_umul(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->u[0] = src0->u[0] * src1->u[0];
dst->u[1] = src0->u[1] * src1->u[1];
dst->u[2] = src0->u[2] * src1->u[2];
dst->u[3] = src0->u[3] * src1->u[3];
}
 
static void
micro_useq(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->u[0] = src0->u[0] == src1->u[0] ? ~0 : 0;
dst->u[1] = src0->u[1] == src1->u[1] ? ~0 : 0;
dst->u[2] = src0->u[2] == src1->u[2] ? ~0 : 0;
dst->u[3] = src0->u[3] == src1->u[3] ? ~0 : 0;
}
 
static void
micro_usge(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->u[0] = src0->u[0] >= src1->u[0] ? ~0 : 0;
dst->u[1] = src0->u[1] >= src1->u[1] ? ~0 : 0;
dst->u[2] = src0->u[2] >= src1->u[2] ? ~0 : 0;
dst->u[3] = src0->u[3] >= src1->u[3] ? ~0 : 0;
}
 
static void
micro_ushr(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->u[0] = src0->u[0] >> src1->u[0];
dst->u[1] = src0->u[1] >> src1->u[1];
dst->u[2] = src0->u[2] >> src1->u[2];
dst->u[3] = src0->u[3] >> src1->u[3];
}
 
static void
micro_uslt(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->u[0] = src0->u[0] < src1->u[0] ? ~0 : 0;
dst->u[1] = src0->u[1] < src1->u[1] ? ~0 : 0;
dst->u[2] = src0->u[2] < src1->u[2] ? ~0 : 0;
dst->u[3] = src0->u[3] < src1->u[3] ? ~0 : 0;
}
 
static void
micro_usne(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1)
{
dst->u[0] = src0->u[0] != src1->u[0] ? ~0 : 0;
dst->u[1] = src0->u[1] != src1->u[1] ? ~0 : 0;
dst->u[2] = src0->u[2] != src1->u[2] ? ~0 : 0;
dst->u[3] = src0->u[3] != src1->u[3] ? ~0 : 0;
}
 
static void
micro_uarl(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src)
{
dst->i[0] = src->u[0];
dst->i[1] = src->u[1];
dst->i[2] = src->u[2];
dst->i[3] = src->u[3];
}
 
static void
micro_ucmp(union tgsi_exec_channel *dst,
const union tgsi_exec_channel *src0,
const union tgsi_exec_channel *src1,
const union tgsi_exec_channel *src2)
{
dst->u[0] = src0->u[0] ? src1->u[0] : src2->u[0];
dst->u[1] = src0->u[1] ? src1->u[1] : src2->u[1];
dst->u[2] = src0->u[2] ? src1->u[2] : src2->u[2];
dst->u[3] = src0->u[3] ? src1->u[3] : src2->u[3];
}
 
static void
exec_instruction(
struct tgsi_exec_machine *mach,
const struct tgsi_full_instruction *inst,
int *pc )
{
union tgsi_exec_channel r[10];
 
(*pc)++;
 
switch (inst->Instruction.Opcode) {
case TGSI_OPCODE_ARL:
exec_vector_unary(mach, inst, micro_arl, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_MOV:
exec_vector_unary(mach, inst, micro_mov, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_LIT:
exec_lit(mach, inst);
break;
 
case TGSI_OPCODE_RCP:
exec_scalar_unary(mach, inst, micro_rcp, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_RSQ:
exec_scalar_unary(mach, inst, micro_rsq, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_EXP:
exec_exp(mach, inst);
break;
 
case TGSI_OPCODE_LOG:
exec_log(mach, inst);
break;
 
case TGSI_OPCODE_MUL:
exec_vector_binary(mach, inst, micro_mul, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_ADD:
exec_vector_binary(mach, inst, micro_add, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_DP3:
exec_dp3(mach, inst);
break;
 
case TGSI_OPCODE_DP4:
exec_dp4(mach, inst);
break;
 
case TGSI_OPCODE_DST:
exec_dst(mach, inst);
break;
 
case TGSI_OPCODE_MIN:
exec_vector_binary(mach, inst, micro_min, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_MAX:
exec_vector_binary(mach, inst, micro_max, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_SLT:
exec_vector_binary(mach, inst, micro_slt, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_SGE:
exec_vector_binary(mach, inst, micro_sge, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_MAD:
exec_vector_trinary(mach, inst, micro_mad, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_SUB:
exec_vector_binary(mach, inst, micro_sub, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_LRP:
exec_vector_trinary(mach, inst, micro_lrp, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_CND:
exec_vector_trinary(mach, inst, micro_cnd, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_SQRT:
exec_vector_unary(mach, inst, micro_sqrt, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_DP2A:
exec_dp2a(mach, inst);
break;
 
case TGSI_OPCODE_FRC:
exec_vector_unary(mach, inst, micro_frc, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_CLAMP:
exec_vector_trinary(mach, inst, micro_clamp, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_FLR:
exec_vector_unary(mach, inst, micro_flr, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_ROUND:
exec_vector_unary(mach, inst, micro_rnd, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_EX2:
exec_scalar_unary(mach, inst, micro_exp2, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_LG2:
exec_scalar_unary(mach, inst, micro_lg2, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_POW:
exec_scalar_binary(mach, inst, micro_pow, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_XPD:
exec_xpd(mach, inst);
break;
 
case TGSI_OPCODE_ABS:
exec_vector_unary(mach, inst, micro_abs, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_RCC:
exec_scalar_unary(mach, inst, micro_rcc, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_DPH:
exec_dph(mach, inst);
break;
 
case TGSI_OPCODE_COS:
exec_scalar_unary(mach, inst, micro_cos, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_DDX:
exec_vector_unary(mach, inst, micro_ddx, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_DDY:
exec_vector_unary(mach, inst, micro_ddy, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_KILP:
exec_kilp (mach, inst);
break;
 
case TGSI_OPCODE_KIL:
exec_kil (mach, inst);
break;
 
case TGSI_OPCODE_PK2H:
assert (0);
break;
 
case TGSI_OPCODE_PK2US:
assert (0);
break;
 
case TGSI_OPCODE_PK4B:
assert (0);
break;
 
case TGSI_OPCODE_PK4UB:
assert (0);
break;
 
case TGSI_OPCODE_RFL:
exec_rfl(mach, inst);
break;
 
case TGSI_OPCODE_SEQ:
exec_vector_binary(mach, inst, micro_seq, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_SFL:
exec_vector(mach, inst, micro_sfl, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_SGT:
exec_vector_binary(mach, inst, micro_sgt, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_SIN:
exec_scalar_unary(mach, inst, micro_sin, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_SLE:
exec_vector_binary(mach, inst, micro_sle, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_SNE:
exec_vector_binary(mach, inst, micro_sne, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_STR:
exec_vector(mach, inst, micro_str, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_TEX:
/* simple texture lookup */
/* src[0] = texcoord */
/* src[1] = sampler unit */
exec_tex(mach, inst, TEX_MODIFIER_NONE, 1);
break;
 
case TGSI_OPCODE_TXB:
/* Texture lookup with lod bias */
/* src[0] = texcoord (src[0].w = LOD bias) */
/* src[1] = sampler unit */
exec_tex(mach, inst, TEX_MODIFIER_LOD_BIAS, 1);
break;
 
case TGSI_OPCODE_TXD:
/* Texture lookup with explict partial derivatives */
/* src[0] = texcoord */
/* src[1] = d[strq]/dx */
/* src[2] = d[strq]/dy */
/* src[3] = sampler unit */
exec_txd(mach, inst);
break;
 
case TGSI_OPCODE_TXL:
/* Texture lookup with explit LOD */
/* src[0] = texcoord (src[0].w = LOD) */
/* src[1] = sampler unit */
exec_tex(mach, inst, TEX_MODIFIER_EXPLICIT_LOD, 1);
break;
 
case TGSI_OPCODE_TXP:
/* Texture lookup with projection */
/* src[0] = texcoord (src[0].w = projection) */
/* src[1] = sampler unit */
exec_tex(mach, inst, TEX_MODIFIER_PROJECTED, 1);
break;
 
case TGSI_OPCODE_UP2H:
assert (0);
break;
 
case TGSI_OPCODE_UP2US:
assert (0);
break;
 
case TGSI_OPCODE_UP4B:
assert (0);
break;
 
case TGSI_OPCODE_UP4UB:
assert (0);
break;
 
case TGSI_OPCODE_X2D:
exec_x2d(mach, inst);
break;
 
case TGSI_OPCODE_ARA:
assert (0);
break;
 
case TGSI_OPCODE_ARR:
exec_vector_unary(mach, inst, micro_arr, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_BRA:
assert (0);
break;
 
case TGSI_OPCODE_CAL:
/* skip the call if no execution channels are enabled */
if (mach->ExecMask) {
/* do the call */
 
/* First, record the depths of the execution stacks.
* This is important for deeply nested/looped return statements.
* We have to unwind the stacks by the correct amount. For a
* real code generator, we could determine the number of entries
* to pop off each stack with simple static analysis and avoid
* implementing this data structure at run time.
*/
mach->CallStack[mach->CallStackTop].CondStackTop = mach->CondStackTop;
mach->CallStack[mach->CallStackTop].LoopStackTop = mach->LoopStackTop;
mach->CallStack[mach->CallStackTop].ContStackTop = mach->ContStackTop;
mach->CallStack[mach->CallStackTop].SwitchStackTop = mach->SwitchStackTop;
mach->CallStack[mach->CallStackTop].BreakStackTop = mach->BreakStackTop;
/* note that PC was already incremented above */
mach->CallStack[mach->CallStackTop].ReturnAddr = *pc;
 
mach->CallStackTop++;
 
/* Second, push the Cond, Loop, Cont, Func stacks */
assert(mach->CondStackTop < TGSI_EXEC_MAX_COND_NESTING);
assert(mach->LoopStackTop < TGSI_EXEC_MAX_LOOP_NESTING);
assert(mach->ContStackTop < TGSI_EXEC_MAX_LOOP_NESTING);
assert(mach->SwitchStackTop < TGSI_EXEC_MAX_SWITCH_NESTING);
assert(mach->BreakStackTop < TGSI_EXEC_MAX_BREAK_STACK);
assert(mach->FuncStackTop < TGSI_EXEC_MAX_CALL_NESTING);
 
mach->CondStack[mach->CondStackTop++] = mach->CondMask;
mach->LoopStack[mach->LoopStackTop++] = mach->LoopMask;
mach->ContStack[mach->ContStackTop++] = mach->ContMask;
mach->SwitchStack[mach->SwitchStackTop++] = mach->Switch;
mach->BreakStack[mach->BreakStackTop++] = mach->BreakType;
mach->FuncStack[mach->FuncStackTop++] = mach->FuncMask;
 
/* Finally, jump to the subroutine */
*pc = inst->Label.Label;
}
break;
 
case TGSI_OPCODE_RET:
mach->FuncMask &= ~mach->ExecMask;
UPDATE_EXEC_MASK(mach);
 
if (mach->FuncMask == 0x0) {
/* really return now (otherwise, keep executing */
 
if (mach->CallStackTop == 0) {
/* returning from main() */
mach->CondStackTop = 0;
mach->LoopStackTop = 0;
*pc = -1;
return;
}
 
assert(mach->CallStackTop > 0);
mach->CallStackTop--;
 
mach->CondStackTop = mach->CallStack[mach->CallStackTop].CondStackTop;
mach->CondMask = mach->CondStack[mach->CondStackTop];
 
mach->LoopStackTop = mach->CallStack[mach->CallStackTop].LoopStackTop;
mach->LoopMask = mach->LoopStack[mach->LoopStackTop];
 
mach->ContStackTop = mach->CallStack[mach->CallStackTop].ContStackTop;
mach->ContMask = mach->ContStack[mach->ContStackTop];
 
mach->SwitchStackTop = mach->CallStack[mach->CallStackTop].SwitchStackTop;
mach->Switch = mach->SwitchStack[mach->SwitchStackTop];
 
mach->BreakStackTop = mach->CallStack[mach->CallStackTop].BreakStackTop;
mach->BreakType = mach->BreakStack[mach->BreakStackTop];
 
assert(mach->FuncStackTop > 0);
mach->FuncMask = mach->FuncStack[--mach->FuncStackTop];
 
*pc = mach->CallStack[mach->CallStackTop].ReturnAddr;
 
UPDATE_EXEC_MASK(mach);
}
break;
 
case TGSI_OPCODE_SSG:
exec_vector_unary(mach, inst, micro_sgn, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_CMP:
exec_vector_trinary(mach, inst, micro_cmp, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_SCS:
exec_scs(mach, inst);
break;
 
case TGSI_OPCODE_NRM:
exec_nrm3(mach, inst);
break;
 
case TGSI_OPCODE_NRM4:
exec_nrm4(mach, inst);
break;
 
case TGSI_OPCODE_DIV:
exec_vector_binary(mach, inst, micro_div, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_DP2:
exec_dp2(mach, inst);
break;
 
case TGSI_OPCODE_IF:
/* push CondMask */
assert(mach->CondStackTop < TGSI_EXEC_MAX_COND_NESTING);
mach->CondStack[mach->CondStackTop++] = mach->CondMask;
FETCH( &r[0], 0, TGSI_CHAN_X );
/* update CondMask */
if( ! r[0].f[0] ) {
mach->CondMask &= ~0x1;
}
if( ! r[0].f[1] ) {
mach->CondMask &= ~0x2;
}
if( ! r[0].f[2] ) {
mach->CondMask &= ~0x4;
}
if( ! r[0].f[3] ) {
mach->CondMask &= ~0x8;
}
UPDATE_EXEC_MASK(mach);
/* Todo: If CondMask==0, jump to ELSE */
break;
 
case TGSI_OPCODE_UIF:
/* push CondMask */
assert(mach->CondStackTop < TGSI_EXEC_MAX_COND_NESTING);
mach->CondStack[mach->CondStackTop++] = mach->CondMask;
IFETCH( &r[0], 0, TGSI_CHAN_X );
/* update CondMask */
if( ! r[0].u[0] ) {
mach->CondMask &= ~0x1;
}
if( ! r[0].u[1] ) {
mach->CondMask &= ~0x2;
}
if( ! r[0].u[2] ) {
mach->CondMask &= ~0x4;
}
if( ! r[0].u[3] ) {
mach->CondMask &= ~0x8;
}
UPDATE_EXEC_MASK(mach);
/* Todo: If CondMask==0, jump to ELSE */
break;
 
case TGSI_OPCODE_ELSE:
/* invert CondMask wrt previous mask */
{
uint prevMask;
assert(mach->CondStackTop > 0);
prevMask = mach->CondStack[mach->CondStackTop - 1];
mach->CondMask = ~mach->CondMask & prevMask;
UPDATE_EXEC_MASK(mach);
/* Todo: If CondMask==0, jump to ENDIF */
}
break;
 
case TGSI_OPCODE_ENDIF:
/* pop CondMask */
assert(mach->CondStackTop > 0);
mach->CondMask = mach->CondStack[--mach->CondStackTop];
UPDATE_EXEC_MASK(mach);
break;
 
case TGSI_OPCODE_END:
/* make sure we end primitives which haven't
* been explicitly emitted */
conditional_emit_primitive(mach);
/* halt execution */
*pc = -1;
break;
 
case TGSI_OPCODE_PUSHA:
assert (0);
break;
 
case TGSI_OPCODE_POPA:
assert (0);
break;
 
case TGSI_OPCODE_CEIL:
exec_vector_unary(mach, inst, micro_ceil, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_I2F:
exec_vector_unary(mach, inst, micro_i2f, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_INT);
break;
 
case TGSI_OPCODE_NOT:
exec_vector_unary(mach, inst, micro_not, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT);
break;
 
case TGSI_OPCODE_TRUNC:
exec_vector_unary(mach, inst, micro_trunc, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_SHL:
exec_vector_binary(mach, inst, micro_shl, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT);
break;
 
case TGSI_OPCODE_AND:
exec_vector_binary(mach, inst, micro_and, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT);
break;
 
case TGSI_OPCODE_OR:
exec_vector_binary(mach, inst, micro_or, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT);
break;
 
case TGSI_OPCODE_MOD:
exec_vector_binary(mach, inst, micro_mod, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_INT);
break;
 
case TGSI_OPCODE_XOR:
exec_vector_binary(mach, inst, micro_xor, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT);
break;
 
case TGSI_OPCODE_SAD:
assert (0);
break;
 
case TGSI_OPCODE_TXF:
exec_txf(mach, inst);
break;
 
case TGSI_OPCODE_TXQ:
exec_txq(mach, inst);
break;
 
case TGSI_OPCODE_EMIT:
emit_vertex(mach);
break;
 
case TGSI_OPCODE_ENDPRIM:
emit_primitive(mach);
break;
 
case TGSI_OPCODE_BGNLOOP:
/* push LoopMask and ContMasks */
assert(mach->LoopStackTop < TGSI_EXEC_MAX_LOOP_NESTING);
assert(mach->ContStackTop < TGSI_EXEC_MAX_LOOP_NESTING);
assert(mach->LoopLabelStackTop < TGSI_EXEC_MAX_LOOP_NESTING);
assert(mach->BreakStackTop < TGSI_EXEC_MAX_BREAK_STACK);
 
mach->LoopStack[mach->LoopStackTop++] = mach->LoopMask;
mach->ContStack[mach->ContStackTop++] = mach->ContMask;
mach->LoopLabelStack[mach->LoopLabelStackTop++] = *pc - 1;
mach->BreakStack[mach->BreakStackTop++] = mach->BreakType;
mach->BreakType = TGSI_EXEC_BREAK_INSIDE_LOOP;
break;
 
case TGSI_OPCODE_ENDLOOP:
/* Restore ContMask, but don't pop */
assert(mach->ContStackTop > 0);
mach->ContMask = mach->ContStack[mach->ContStackTop - 1];
UPDATE_EXEC_MASK(mach);
if (mach->ExecMask) {
/* repeat loop: jump to instruction just past BGNLOOP */
assert(mach->LoopLabelStackTop > 0);
*pc = mach->LoopLabelStack[mach->LoopLabelStackTop - 1] + 1;
}
else {
/* exit loop: pop LoopMask */
assert(mach->LoopStackTop > 0);
mach->LoopMask = mach->LoopStack[--mach->LoopStackTop];
/* pop ContMask */
assert(mach->ContStackTop > 0);
mach->ContMask = mach->ContStack[--mach->ContStackTop];
assert(mach->LoopLabelStackTop > 0);
--mach->LoopLabelStackTop;
 
mach->BreakType = mach->BreakStack[--mach->BreakStackTop];
}
UPDATE_EXEC_MASK(mach);
break;
 
case TGSI_OPCODE_BRK:
exec_break(mach);
break;
 
case TGSI_OPCODE_CONT:
/* turn off cont channels for each enabled exec channel */
mach->ContMask &= ~mach->ExecMask;
/* Todo: if mach->LoopMask == 0, jump to end of loop */
UPDATE_EXEC_MASK(mach);
break;
 
case TGSI_OPCODE_BGNSUB:
/* no-op */
break;
 
case TGSI_OPCODE_ENDSUB:
/*
* XXX: This really should be a no-op. We should never reach this opcode.
*/
 
assert(mach->CallStackTop > 0);
mach->CallStackTop--;
 
mach->CondStackTop = mach->CallStack[mach->CallStackTop].CondStackTop;
mach->CondMask = mach->CondStack[mach->CondStackTop];
 
mach->LoopStackTop = mach->CallStack[mach->CallStackTop].LoopStackTop;
mach->LoopMask = mach->LoopStack[mach->LoopStackTop];
 
mach->ContStackTop = mach->CallStack[mach->CallStackTop].ContStackTop;
mach->ContMask = mach->ContStack[mach->ContStackTop];
 
mach->SwitchStackTop = mach->CallStack[mach->CallStackTop].SwitchStackTop;
mach->Switch = mach->SwitchStack[mach->SwitchStackTop];
 
mach->BreakStackTop = mach->CallStack[mach->CallStackTop].BreakStackTop;
mach->BreakType = mach->BreakStack[mach->BreakStackTop];
 
assert(mach->FuncStackTop > 0);
mach->FuncMask = mach->FuncStack[--mach->FuncStackTop];
 
*pc = mach->CallStack[mach->CallStackTop].ReturnAddr;
 
UPDATE_EXEC_MASK(mach);
break;
 
case TGSI_OPCODE_NOP:
break;
 
case TGSI_OPCODE_BREAKC:
IFETCH(&r[0], 0, TGSI_CHAN_X);
/* update CondMask */
if (r[0].u[0] && (mach->ExecMask & 0x1)) {
mach->LoopMask &= ~0x1;
}
if (r[0].u[1] && (mach->ExecMask & 0x2)) {
mach->LoopMask &= ~0x2;
}
if (r[0].u[2] && (mach->ExecMask & 0x4)) {
mach->LoopMask &= ~0x4;
}
if (r[0].u[3] && (mach->ExecMask & 0x8)) {
mach->LoopMask &= ~0x8;
}
/* Todo: if mach->LoopMask == 0, jump to end of loop */
UPDATE_EXEC_MASK(mach);
break;
 
case TGSI_OPCODE_F2I:
exec_vector_unary(mach, inst, micro_f2i, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_IDIV:
exec_vector_binary(mach, inst, micro_idiv, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_INT);
break;
 
case TGSI_OPCODE_IMAX:
exec_vector_binary(mach, inst, micro_imax, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_INT);
break;
 
case TGSI_OPCODE_IMIN:
exec_vector_binary(mach, inst, micro_imin, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_INT);
break;
 
case TGSI_OPCODE_INEG:
exec_vector_unary(mach, inst, micro_ineg, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_INT);
break;
 
case TGSI_OPCODE_ISGE:
exec_vector_binary(mach, inst, micro_isge, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_INT);
break;
 
case TGSI_OPCODE_ISHR:
exec_vector_binary(mach, inst, micro_ishr, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_INT);
break;
 
case TGSI_OPCODE_ISLT:
exec_vector_binary(mach, inst, micro_islt, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_INT);
break;
 
case TGSI_OPCODE_F2U:
exec_vector_unary(mach, inst, micro_f2u, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_FLOAT);
break;
 
case TGSI_OPCODE_U2F:
exec_vector_unary(mach, inst, micro_u2f, TGSI_EXEC_DATA_FLOAT, TGSI_EXEC_DATA_UINT);
break;
 
case TGSI_OPCODE_UADD:
exec_vector_binary(mach, inst, micro_uadd, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_INT);
break;
 
case TGSI_OPCODE_UDIV:
exec_vector_binary(mach, inst, micro_udiv, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT);
break;
 
case TGSI_OPCODE_UMAD:
exec_vector_trinary(mach, inst, micro_umad, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT);
break;
 
case TGSI_OPCODE_UMAX:
exec_vector_binary(mach, inst, micro_umax, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT);
break;
 
case TGSI_OPCODE_UMIN:
exec_vector_binary(mach, inst, micro_umin, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT);
break;
 
case TGSI_OPCODE_UMOD:
exec_vector_binary(mach, inst, micro_umod, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT);
break;
 
case TGSI_OPCODE_UMUL:
exec_vector_binary(mach, inst, micro_umul, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT);
break;
 
case TGSI_OPCODE_USEQ:
exec_vector_binary(mach, inst, micro_useq, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT);
break;
 
case TGSI_OPCODE_USGE:
exec_vector_binary(mach, inst, micro_usge, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT);
break;
 
case TGSI_OPCODE_USHR:
exec_vector_binary(mach, inst, micro_ushr, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT);
break;
 
case TGSI_OPCODE_USLT:
exec_vector_binary(mach, inst, micro_uslt, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT);
break;
 
case TGSI_OPCODE_USNE:
exec_vector_binary(mach, inst, micro_usne, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT);
break;
 
case TGSI_OPCODE_SWITCH:
exec_switch(mach, inst);
break;
 
case TGSI_OPCODE_CASE:
exec_case(mach, inst);
break;
 
case TGSI_OPCODE_DEFAULT:
exec_default(mach);
break;
 
case TGSI_OPCODE_ENDSWITCH:
exec_endswitch(mach);
break;
 
case TGSI_OPCODE_SAMPLE_I:
exec_txf(mach, inst);
break;
 
case TGSI_OPCODE_SAMPLE_I_MS:
assert(0);
break;
 
case TGSI_OPCODE_SAMPLE:
exec_sample(mach, inst, TEX_MODIFIER_NONE, FALSE);
break;
 
case TGSI_OPCODE_SAMPLE_B:
exec_sample(mach, inst, TEX_MODIFIER_LOD_BIAS, FALSE);
break;
 
case TGSI_OPCODE_SAMPLE_C:
exec_sample(mach, inst, TEX_MODIFIER_NONE, TRUE);
break;
 
case TGSI_OPCODE_SAMPLE_C_LZ:
exec_sample(mach, inst, TEX_MODIFIER_LEVEL_ZERO, TRUE);
break;
 
case TGSI_OPCODE_SAMPLE_D:
exec_sample_d(mach, inst);
break;
 
case TGSI_OPCODE_SAMPLE_L:
exec_sample(mach, inst, TEX_MODIFIER_EXPLICIT_LOD, FALSE);
break;
 
case TGSI_OPCODE_GATHER4:
assert(0);
break;
 
case TGSI_OPCODE_SVIEWINFO:
exec_txq(mach, inst);
break;
 
case TGSI_OPCODE_SAMPLE_POS:
assert(0);
break;
 
case TGSI_OPCODE_SAMPLE_INFO:
assert(0);
break;
 
case TGSI_OPCODE_UARL:
exec_vector_unary(mach, inst, micro_uarl, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_UINT);
break;
 
case TGSI_OPCODE_UCMP:
exec_vector_trinary(mach, inst, micro_ucmp, TGSI_EXEC_DATA_UINT, TGSI_EXEC_DATA_UINT);
break;
 
case TGSI_OPCODE_IABS:
exec_vector_unary(mach, inst, micro_iabs, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_INT);
break;
 
case TGSI_OPCODE_ISSG:
exec_vector_unary(mach, inst, micro_isgn, TGSI_EXEC_DATA_INT, TGSI_EXEC_DATA_INT);
break;
 
case TGSI_OPCODE_TEX2:
/* simple texture lookup */
/* src[0] = texcoord */
/* src[1] = compare */
/* src[2] = sampler unit */
exec_tex(mach, inst, TEX_MODIFIER_NONE, 2);
break;
case TGSI_OPCODE_TXB2:
/* simple texture lookup */
/* src[0] = texcoord */
/* src[1] = bias */
/* src[2] = sampler unit */
exec_tex(mach, inst, TEX_MODIFIER_LOD_BIAS, 2);
break;
case TGSI_OPCODE_TXL2:
/* simple texture lookup */
/* src[0] = texcoord */
/* src[1] = lod */
/* src[2] = sampler unit */
exec_tex(mach, inst, TEX_MODIFIER_EXPLICIT_LOD, 2);
break;
default:
assert( 0 );
}
}
 
 
/**
* Run TGSI interpreter.
* \return bitmask of "alive" quad components
*/
uint
tgsi_exec_machine_run( struct tgsi_exec_machine *mach )
{
uint i;
int pc = 0;
uint default_mask = 0xf;
 
mach->Temps[TEMP_KILMASK_I].xyzw[TEMP_KILMASK_C].u[0] = 0;
mach->Temps[TEMP_OUTPUT_I].xyzw[TEMP_OUTPUT_C].u[0] = 0;
 
if( mach->Processor == TGSI_PROCESSOR_GEOMETRY ) {
mach->Temps[TEMP_PRIMITIVE_I].xyzw[TEMP_PRIMITIVE_C].u[0] = 0;
mach->Primitives[0] = 0;
/* GS runs on a single primitive for now */
default_mask = 0x1;
}
 
mach->CondMask = default_mask;
mach->LoopMask = default_mask;
mach->ContMask = default_mask;
mach->FuncMask = default_mask;
mach->ExecMask = default_mask;
 
mach->Switch.mask = default_mask;
 
assert(mach->CondStackTop == 0);
assert(mach->LoopStackTop == 0);
assert(mach->ContStackTop == 0);
assert(mach->SwitchStackTop == 0);
assert(mach->BreakStackTop == 0);
assert(mach->CallStackTop == 0);
 
 
/* execute declarations (interpolants) */
for (i = 0; i < mach->NumDeclarations; i++) {
exec_declaration( mach, mach->Declarations+i );
}
 
{
#if DEBUG_EXECUTION
struct tgsi_exec_vector temps[TGSI_EXEC_NUM_TEMPS + TGSI_EXEC_NUM_TEMP_EXTRAS];
struct tgsi_exec_vector outputs[PIPE_MAX_ATTRIBS];
uint inst = 1;
 
memset(mach->Temps, 0, sizeof(temps));
memset(mach->Outputs, 0, sizeof(outputs));
memset(temps, 0, sizeof(temps));
memset(outputs, 0, sizeof(outputs));
#endif
 
/* execute instructions, until pc is set to -1 */
while (pc != -1) {
 
#if DEBUG_EXECUTION
uint i;
 
tgsi_dump_instruction(&mach->Instructions[pc], inst++);
#endif
 
assert(pc < (int) mach->NumInstructions);
exec_instruction(mach, mach->Instructions + pc, &pc);
 
#if DEBUG_EXECUTION
for (i = 0; i < TGSI_EXEC_NUM_TEMPS + TGSI_EXEC_NUM_TEMP_EXTRAS; i++) {
if (memcmp(&temps[i], &mach->Temps[i], sizeof(temps[i]))) {
uint j;
 
memcpy(&temps[i], &mach->Temps[i], sizeof(temps[i]));
debug_printf("TEMP[%2u] = ", i);
for (j = 0; j < 4; j++) {
if (j > 0) {
debug_printf(" ");
}
debug_printf("(%6f %u, %6f %u, %6f %u, %6f %u)\n",
temps[i].xyzw[0].f[j], temps[i].xyzw[0].u[j],
temps[i].xyzw[1].f[j], temps[i].xyzw[1].u[j],
temps[i].xyzw[2].f[j], temps[i].xyzw[2].u[j],
temps[i].xyzw[3].f[j], temps[i].xyzw[3].u[j]);
}
}
}
for (i = 0; i < PIPE_MAX_ATTRIBS; i++) {
if (memcmp(&outputs[i], &mach->Outputs[i], sizeof(outputs[i]))) {
uint j;
 
memcpy(&outputs[i], &mach->Outputs[i], sizeof(outputs[i]));
debug_printf("OUT[%2u] = ", i);
for (j = 0; j < 4; j++) {
if (j > 0) {
debug_printf(" ");
}
debug_printf("(%6f %u, %6f %u, %6f %u, %6f %u)\n",
outputs[i].xyzw[0].f[j], outputs[i].xyzw[0].u[j],
outputs[i].xyzw[1].f[j], outputs[i].xyzw[1].u[j],
outputs[i].xyzw[2].f[j], outputs[i].xyzw[2].u[j],
outputs[i].xyzw[3].f[j], outputs[i].xyzw[3].u[j]);
}
}
}
#endif
}
}
 
#if 0
/* we scale from floats in [0,1] to Zbuffer ints in sp_quad_depth_test.c */
if (mach->Processor == TGSI_PROCESSOR_FRAGMENT) {
/*
* Scale back depth component.
*/
for (i = 0; i < 4; i++)
mach->Outputs[0].xyzw[2].f[i] *= ctx->DrawBuffer->_DepthMaxF;
}
#endif
 
/* Strictly speaking, these assertions aren't really needed but they
* can potentially catch some bugs in the control flow code.
*/
assert(mach->CondStackTop == 0);
assert(mach->LoopStackTop == 0);
assert(mach->ContStackTop == 0);
assert(mach->SwitchStackTop == 0);
assert(mach->BreakStackTop == 0);
assert(mach->CallStackTop == 0);
 
return ~mach->Temps[TEMP_KILMASK_I].xyzw[TEMP_KILMASK_C].u[0];
}
/drivers/video/Gallium/auxiliary/tgsi/tgsi_exec.h
0,0 → 1,463
/**************************************************************************
*
* Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
* Copyright 2009-2010 VMware, Inc. 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.
*
**************************************************************************/
 
#ifndef TGSI_EXEC_H
#define TGSI_EXEC_H
 
#include "pipe/p_compiler.h"
#include "pipe/p_state.h"
#include "pipe/p_shader_tokens.h"
 
#if defined __cplusplus
extern "C" {
#endif
 
#define TGSI_CHAN_X 0
#define TGSI_CHAN_Y 1
#define TGSI_CHAN_Z 2
#define TGSI_CHAN_W 3
 
#define TGSI_NUM_CHANNELS 4 /* R,G,B,A */
#define TGSI_QUAD_SIZE 4 /* 4 pixel/quad */
 
#define TGSI_FOR_EACH_CHANNEL( CHAN )\
for (CHAN = 0; CHAN < TGSI_NUM_CHANNELS; CHAN++)
 
#define TGSI_IS_DST0_CHANNEL_ENABLED( INST, CHAN )\
((INST)->Dst[0].Register.WriteMask & (1 << (CHAN)))
 
#define TGSI_IF_IS_DST0_CHANNEL_ENABLED( INST, CHAN )\
if (TGSI_IS_DST0_CHANNEL_ENABLED( INST, CHAN ))
 
#define TGSI_FOR_EACH_DST0_ENABLED_CHANNEL( INST, CHAN )\
TGSI_FOR_EACH_CHANNEL( CHAN )\
TGSI_IF_IS_DST0_CHANNEL_ENABLED( INST, CHAN )
 
 
/**
* Registers may be treated as float, signed int or unsigned int.
*/
union tgsi_exec_channel
{
float f[TGSI_QUAD_SIZE];
int i[TGSI_QUAD_SIZE];
unsigned u[TGSI_QUAD_SIZE];
};
 
/**
* A vector[RGBA] of channels[4 pixels]
*/
struct tgsi_exec_vector
{
union tgsi_exec_channel xyzw[TGSI_NUM_CHANNELS];
};
 
/**
* For fragment programs, information for computing fragment input
* values from plane equation of the triangle/line.
*/
struct tgsi_interp_coef
{
float a0[TGSI_NUM_CHANNELS]; /* in an xyzw layout */
float dadx[TGSI_NUM_CHANNELS];
float dady[TGSI_NUM_CHANNELS];
};
 
enum tgsi_sampler_control {
tgsi_sampler_lod_none,
tgsi_sampler_lod_bias,
tgsi_sampler_lod_explicit,
tgsi_sampler_lod_zero,
tgsi_sampler_derivs_explicit
};
 
/**
* Information for sampling textures, which must be implemented
* by code outside the TGSI executor.
*/
struct tgsi_sampler
{
/** Get samples for four fragments in a quad */
/* this interface contains 5 sets of channels that vary
* depending on the sampler.
* s - the first texture coordinate for sampling.
* t - the second texture coordinate for sampling - unused for 1D,
layer for 1D arrays.
* r - the third coordinate for sampling for 3D, cube, cube arrays,
* layer for 2D arrays. Compare value for 1D/2D shadows.
* c0 - Compare value for shadow cube and shadow 2d arrays,
* layer for cube arrays.
* derivs - explicit derivatives.
* offset - texel offsets
* lod - lod value, except for shadow cube arrays (compare value there).
*/
void (*get_samples)(struct tgsi_sampler *sampler,
const unsigned sview_index,
const unsigned sampler_index,
const float s[TGSI_QUAD_SIZE],
const float t[TGSI_QUAD_SIZE],
const float r[TGSI_QUAD_SIZE],
const float c0[TGSI_QUAD_SIZE],
const float c1[TGSI_QUAD_SIZE],
float derivs[3][2][TGSI_QUAD_SIZE],
const int8_t offset[3],
enum tgsi_sampler_control control,
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]);
void (*get_dims)(struct tgsi_sampler *sampler,
const unsigned sview_index,
int level, int dims[4]);
void (*get_texel)(struct tgsi_sampler *sampler,
const unsigned sview_index,
const int i[TGSI_QUAD_SIZE],
const int j[TGSI_QUAD_SIZE], const int k[TGSI_QUAD_SIZE],
const int lod[TGSI_QUAD_SIZE], const int8_t offset[3],
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]);
};
 
#define TGSI_EXEC_NUM_TEMPS 4096
#define TGSI_EXEC_NUM_IMMEDIATES 256
 
/*
* Locations of various utility registers (_I = Index, _C = Channel)
*/
#define TGSI_EXEC_TEMP_00000000_I (TGSI_EXEC_NUM_TEMPS + 0)
#define TGSI_EXEC_TEMP_00000000_C 0
 
#define TGSI_EXEC_TEMP_7FFFFFFF_I (TGSI_EXEC_NUM_TEMPS + 0)
#define TGSI_EXEC_TEMP_7FFFFFFF_C 1
 
#define TGSI_EXEC_TEMP_80000000_I (TGSI_EXEC_NUM_TEMPS + 0)
#define TGSI_EXEC_TEMP_80000000_C 2
 
#define TGSI_EXEC_TEMP_FFFFFFFF_I (TGSI_EXEC_NUM_TEMPS + 0)
#define TGSI_EXEC_TEMP_FFFFFFFF_C 3
 
#define TGSI_EXEC_TEMP_ONE_I (TGSI_EXEC_NUM_TEMPS + 1)
#define TGSI_EXEC_TEMP_ONE_C 0
 
#define TGSI_EXEC_TEMP_TWO_I (TGSI_EXEC_NUM_TEMPS + 1)
#define TGSI_EXEC_TEMP_TWO_C 1
 
#define TGSI_EXEC_TEMP_128_I (TGSI_EXEC_NUM_TEMPS + 1)
#define TGSI_EXEC_TEMP_128_C 2
 
#define TGSI_EXEC_TEMP_MINUS_128_I (TGSI_EXEC_NUM_TEMPS + 1)
#define TGSI_EXEC_TEMP_MINUS_128_C 3
 
#define TGSI_EXEC_TEMP_KILMASK_I (TGSI_EXEC_NUM_TEMPS + 2)
#define TGSI_EXEC_TEMP_KILMASK_C 0
 
#define TGSI_EXEC_TEMP_OUTPUT_I (TGSI_EXEC_NUM_TEMPS + 2)
#define TGSI_EXEC_TEMP_OUTPUT_C 1
 
#define TGSI_EXEC_TEMP_PRIMITIVE_I (TGSI_EXEC_NUM_TEMPS + 2)
#define TGSI_EXEC_TEMP_PRIMITIVE_C 2
 
#define TGSI_EXEC_TEMP_THREE_I (TGSI_EXEC_NUM_TEMPS + 2)
#define TGSI_EXEC_TEMP_THREE_C 3
 
#define TGSI_EXEC_TEMP_HALF_I (TGSI_EXEC_NUM_TEMPS + 3)
#define TGSI_EXEC_TEMP_HALF_C 0
 
/* execution mask, each value is either 0 or ~0 */
#define TGSI_EXEC_MASK_I (TGSI_EXEC_NUM_TEMPS + 3)
#define TGSI_EXEC_MASK_C 1
 
/* 4 register buffer for various purposes */
#define TGSI_EXEC_TEMP_R0 (TGSI_EXEC_NUM_TEMPS + 4)
#define TGSI_EXEC_NUM_TEMP_R 4
 
#define TGSI_EXEC_TEMP_ADDR (TGSI_EXEC_NUM_TEMPS + 8)
#define TGSI_EXEC_NUM_ADDRS 1
 
/* predicate register */
#define TGSI_EXEC_TEMP_P0 (TGSI_EXEC_NUM_TEMPS + 9)
#define TGSI_EXEC_NUM_PREDS 1
 
#define TGSI_EXEC_NUM_TEMP_EXTRAS 10
 
 
 
#define TGSI_EXEC_MAX_NESTING 32
#define TGSI_EXEC_MAX_COND_NESTING TGSI_EXEC_MAX_NESTING
#define TGSI_EXEC_MAX_LOOP_NESTING TGSI_EXEC_MAX_NESTING
#define TGSI_EXEC_MAX_SWITCH_NESTING TGSI_EXEC_MAX_NESTING
#define TGSI_EXEC_MAX_CALL_NESTING TGSI_EXEC_MAX_NESTING
 
/* The maximum number of input attributes per vertex. For 2D
* input register files, this is the stride between two 1D
* arrays.
*/
#define TGSI_EXEC_MAX_INPUT_ATTRIBS 17
 
/* The maximum number of constant vectors per constant buffer.
*/
#define TGSI_EXEC_MAX_CONST_BUFFER 4096
 
/* The maximum number of vertices per primitive */
#define TGSI_MAX_PRIM_VERTICES 6
 
/* The maximum number of primitives to be generated */
#define TGSI_MAX_PRIMITIVES 64
 
/* The maximum total number of vertices */
#define TGSI_MAX_TOTAL_VERTICES (TGSI_MAX_PRIM_VERTICES * TGSI_MAX_PRIMITIVES * PIPE_MAX_ATTRIBS)
 
#define TGSI_MAX_MISC_INPUTS 8
 
/** function call/activation record */
struct tgsi_call_record
{
uint CondStackTop;
uint LoopStackTop;
uint ContStackTop;
int SwitchStackTop;
int BreakStackTop;
uint ReturnAddr;
};
 
 
/* Switch-case block state. */
struct tgsi_switch_record {
uint mask; /**< execution mask */
union tgsi_exec_channel selector; /**< a value case statements are compared to */
uint defaultMask; /**< non-execute mask for default case */
};
 
 
enum tgsi_break_type {
TGSI_EXEC_BREAK_INSIDE_LOOP,
TGSI_EXEC_BREAK_INSIDE_SWITCH
};
 
 
#define TGSI_EXEC_MAX_BREAK_STACK (TGSI_EXEC_MAX_LOOP_NESTING + TGSI_EXEC_MAX_SWITCH_NESTING)
 
 
/**
* Run-time virtual machine state for executing TGSI shader.
*/
struct tgsi_exec_machine
{
/* Total = program temporaries + internal temporaries
*/
struct tgsi_exec_vector Temps[TGSI_EXEC_NUM_TEMPS +
TGSI_EXEC_NUM_TEMP_EXTRAS];
 
float Imms[TGSI_EXEC_NUM_IMMEDIATES][4];
 
float ImmArray[TGSI_EXEC_NUM_IMMEDIATES][4];
 
struct tgsi_exec_vector *Inputs;
struct tgsi_exec_vector *Outputs;
 
/* System values */
unsigned SysSemanticToIndex[TGSI_SEMANTIC_COUNT];
union tgsi_exec_channel SystemValue[TGSI_MAX_MISC_INPUTS];
 
struct tgsi_exec_vector *Addrs;
struct tgsi_exec_vector *Predicates;
 
struct tgsi_sampler *Sampler;
 
unsigned ImmLimit;
 
const void *Consts[PIPE_MAX_CONSTANT_BUFFERS];
unsigned ConstsSize[PIPE_MAX_CONSTANT_BUFFERS];
 
const struct tgsi_token *Tokens; /**< Declarations, instructions */
unsigned Processor; /**< TGSI_PROCESSOR_x */
 
/* GEOMETRY processor only. */
unsigned *Primitives;
unsigned NumOutputs;
unsigned MaxGeometryShaderOutputs;
 
/* FRAGMENT processor only. */
const struct tgsi_interp_coef *InterpCoefs;
struct tgsi_exec_vector QuadPos;
float Face; /**< +1 if front facing, -1 if back facing */
bool flatshade_color;
/* Conditional execution masks */
uint CondMask; /**< For IF/ELSE/ENDIF */
uint LoopMask; /**< For BGNLOOP/ENDLOOP */
uint ContMask; /**< For loop CONT statements */
uint FuncMask; /**< For function calls */
uint ExecMask; /**< = CondMask & LoopMask */
 
/* Current switch-case state. */
struct tgsi_switch_record Switch;
 
/* Current break type. */
enum tgsi_break_type BreakType;
 
/** Condition mask stack (for nested conditionals) */
uint CondStack[TGSI_EXEC_MAX_COND_NESTING];
int CondStackTop;
 
/** Loop mask stack (for nested loops) */
uint LoopStack[TGSI_EXEC_MAX_LOOP_NESTING];
int LoopStackTop;
 
/** Loop label stack */
uint LoopLabelStack[TGSI_EXEC_MAX_LOOP_NESTING];
int LoopLabelStackTop;
 
/** Loop continue mask stack (see comments in tgsi_exec.c) */
uint ContStack[TGSI_EXEC_MAX_LOOP_NESTING];
int ContStackTop;
 
/** Switch case stack */
struct tgsi_switch_record SwitchStack[TGSI_EXEC_MAX_SWITCH_NESTING];
int SwitchStackTop;
 
enum tgsi_break_type BreakStack[TGSI_EXEC_MAX_BREAK_STACK];
int BreakStackTop;
 
/** Function execution mask stack (for executing subroutine code) */
uint FuncStack[TGSI_EXEC_MAX_CALL_NESTING];
int FuncStackTop;
 
/** Function call stack for saving/restoring the program counter */
struct tgsi_call_record CallStack[TGSI_EXEC_MAX_CALL_NESTING];
int CallStackTop;
 
struct tgsi_full_instruction *Instructions;
uint NumInstructions;
 
struct tgsi_full_declaration *Declarations;
uint NumDeclarations;
 
struct tgsi_declaration_sampler_view
SamplerViews[PIPE_MAX_SHADER_SAMPLER_VIEWS];
 
boolean UsedGeometryShader;
};
 
struct tgsi_exec_machine *
tgsi_exec_machine_create( void );
 
void
tgsi_exec_machine_destroy(struct tgsi_exec_machine *mach);
 
 
void
tgsi_exec_machine_bind_shader(
struct tgsi_exec_machine *mach,
const struct tgsi_token *tokens,
struct tgsi_sampler *sampler);
 
uint
tgsi_exec_machine_run(
struct tgsi_exec_machine *mach );
 
 
void
tgsi_exec_machine_free_data(struct tgsi_exec_machine *mach);
 
 
boolean
tgsi_check_soa_dependencies(const struct tgsi_full_instruction *inst);
 
 
static INLINE void
tgsi_set_kill_mask(struct tgsi_exec_machine *mach, unsigned mask)
{
mach->Temps[TGSI_EXEC_TEMP_KILMASK_I].xyzw[TGSI_EXEC_TEMP_KILMASK_C].u[0] =
mask;
}
 
 
/** Set execution mask values prior to executing the shader */
static INLINE void
tgsi_set_exec_mask(struct tgsi_exec_machine *mach,
boolean ch0, boolean ch1, boolean ch2, boolean ch3)
{
int *mask = mach->Temps[TGSI_EXEC_MASK_I].xyzw[TGSI_EXEC_MASK_C].i;
mask[0] = ch0 ? ~0 : 0;
mask[1] = ch1 ? ~0 : 0;
mask[2] = ch2 ? ~0 : 0;
mask[3] = ch3 ? ~0 : 0;
}
 
 
extern void
tgsi_exec_set_constant_buffers(struct tgsi_exec_machine *mach,
unsigned num_bufs,
const void **bufs,
const unsigned *buf_sizes);
 
 
static INLINE int
tgsi_exec_get_shader_param(enum pipe_shader_cap param)
{
switch(param) {
case PIPE_SHADER_CAP_MAX_INSTRUCTIONS:
case PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS:
case PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS:
case PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS:
return INT_MAX;
case PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH:
return TGSI_EXEC_MAX_NESTING;
case PIPE_SHADER_CAP_MAX_INPUTS:
return TGSI_EXEC_MAX_INPUT_ATTRIBS;
case PIPE_SHADER_CAP_MAX_CONSTS:
return TGSI_EXEC_MAX_CONST_BUFFER;
case PIPE_SHADER_CAP_MAX_CONST_BUFFERS:
return PIPE_MAX_CONSTANT_BUFFERS;
case PIPE_SHADER_CAP_MAX_TEMPS:
return TGSI_EXEC_NUM_TEMPS;
case PIPE_SHADER_CAP_MAX_ADDRS:
return TGSI_EXEC_NUM_ADDRS;
case PIPE_SHADER_CAP_MAX_PREDS:
return TGSI_EXEC_NUM_PREDS;
case PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED:
return 1;
case PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR:
case PIPE_SHADER_CAP_INDIRECT_OUTPUT_ADDR:
case PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR:
case PIPE_SHADER_CAP_INDIRECT_CONST_ADDR:
return 1;
case PIPE_SHADER_CAP_SUBROUTINES:
return 1;
case PIPE_SHADER_CAP_INTEGERS:
return 1;
case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS:
return PIPE_MAX_SAMPLERS;
case PIPE_SHADER_CAP_TGSI_SQRT_SUPPORTED:
return 1;
default:
return 0;
}
}
 
#if defined __cplusplus
} /* extern "C" */
#endif
 
#endif /* TGSI_EXEC_H */
/drivers/video/Gallium/auxiliary/tgsi/tgsi_info.c
0,0 → 1,360
/**************************************************************************
*
* 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.
*
**************************************************************************/
 
#include "util/u_debug.h"
#include "util/u_memory.h"
#include "tgsi_info.h"
 
#define NONE TGSI_OUTPUT_NONE
#define COMP TGSI_OUTPUT_COMPONENTWISE
#define REPL TGSI_OUTPUT_REPLICATE
#define CHAN TGSI_OUTPUT_CHAN_DEPENDENT
#define OTHR TGSI_OUTPUT_OTHER
 
static const struct tgsi_opcode_info opcode_info[TGSI_OPCODE_LAST] =
{
{ 1, 1, 0, 0, 0, 0, COMP, "ARL", TGSI_OPCODE_ARL },
{ 1, 1, 0, 0, 0, 0, COMP, "MOV", TGSI_OPCODE_MOV },
{ 1, 1, 0, 0, 0, 0, CHAN, "LIT", TGSI_OPCODE_LIT },
{ 1, 1, 0, 0, 0, 0, REPL, "RCP", TGSI_OPCODE_RCP },
{ 1, 1, 0, 0, 0, 0, REPL, "RSQ", TGSI_OPCODE_RSQ },
{ 1, 1, 0, 0, 0, 0, CHAN, "EXP", TGSI_OPCODE_EXP },
{ 1, 1, 0, 0, 0, 0, CHAN, "LOG", TGSI_OPCODE_LOG },
{ 1, 2, 0, 0, 0, 0, COMP, "MUL", TGSI_OPCODE_MUL },
{ 1, 2, 0, 0, 0, 0, COMP, "ADD", TGSI_OPCODE_ADD },
{ 1, 2, 0, 0, 0, 0, REPL, "DP3", TGSI_OPCODE_DP3 },
{ 1, 2, 0, 0, 0, 0, REPL, "DP4", TGSI_OPCODE_DP4 },
{ 1, 2, 0, 0, 0, 0, CHAN, "DST", TGSI_OPCODE_DST },
{ 1, 2, 0, 0, 0, 0, COMP, "MIN", TGSI_OPCODE_MIN },
{ 1, 2, 0, 0, 0, 0, COMP, "MAX", TGSI_OPCODE_MAX },
{ 1, 2, 0, 0, 0, 0, COMP, "SLT", TGSI_OPCODE_SLT },
{ 1, 2, 0, 0, 0, 0, COMP, "SGE", TGSI_OPCODE_SGE },
{ 1, 3, 0, 0, 0, 0, COMP, "MAD", TGSI_OPCODE_MAD },
{ 1, 2, 0, 0, 0, 0, COMP, "SUB", TGSI_OPCODE_SUB },
{ 1, 3, 0, 0, 0, 0, COMP, "LRP", TGSI_OPCODE_LRP },
{ 1, 3, 0, 0, 0, 0, COMP, "CND", TGSI_OPCODE_CND },
{ 1, 1, 0, 0, 0, 0, REPL, "SQRT", TGSI_OPCODE_SQRT },
{ 1, 3, 0, 0, 0, 0, REPL, "DP2A", TGSI_OPCODE_DP2A },
{ 0, 0, 0, 0, 0, 0, NONE, "", 22 }, /* removed */
{ 0, 0, 0, 0, 0, 0, NONE, "", 23 }, /* removed */
{ 1, 1, 0, 0, 0, 0, COMP, "FRC", TGSI_OPCODE_FRC },
{ 1, 3, 0, 0, 0, 0, COMP, "CLAMP", TGSI_OPCODE_CLAMP },
{ 1, 1, 0, 0, 0, 0, COMP, "FLR", TGSI_OPCODE_FLR },
{ 1, 1, 0, 0, 0, 0, COMP, "ROUND", TGSI_OPCODE_ROUND },
{ 1, 1, 0, 0, 0, 0, REPL, "EX2", TGSI_OPCODE_EX2 },
{ 1, 1, 0, 0, 0, 0, REPL, "LG2", TGSI_OPCODE_LG2 },
{ 1, 2, 0, 0, 0, 0, REPL, "POW", TGSI_OPCODE_POW },
{ 1, 2, 0, 0, 0, 0, COMP, "XPD", TGSI_OPCODE_XPD },
{ 0, 0, 0, 0, 0, 0, NONE, "", 32 }, /* removed */
{ 1, 1, 0, 0, 0, 0, COMP, "ABS", TGSI_OPCODE_ABS },
{ 1, 1, 0, 0, 0, 0, REPL, "RCC", TGSI_OPCODE_RCC },
{ 1, 2, 0, 0, 0, 0, REPL, "DPH", TGSI_OPCODE_DPH },
{ 1, 1, 0, 0, 0, 0, REPL, "COS", TGSI_OPCODE_COS },
{ 1, 1, 0, 0, 0, 0, COMP, "DDX", TGSI_OPCODE_DDX },
{ 1, 1, 0, 0, 0, 0, COMP, "DDY", TGSI_OPCODE_DDY },
{ 0, 0, 0, 0, 0, 0, NONE, "KILP", TGSI_OPCODE_KILP },
{ 1, 1, 0, 0, 0, 0, COMP, "PK2H", TGSI_OPCODE_PK2H },
{ 1, 1, 0, 0, 0, 0, COMP, "PK2US", TGSI_OPCODE_PK2US },
{ 1, 1, 0, 0, 0, 0, COMP, "PK4B", TGSI_OPCODE_PK4B },
{ 1, 1, 0, 0, 0, 0, COMP, "PK4UB", TGSI_OPCODE_PK4UB },
{ 1, 2, 0, 0, 0, 0, COMP, "RFL", TGSI_OPCODE_RFL },
{ 1, 2, 0, 0, 0, 0, COMP, "SEQ", TGSI_OPCODE_SEQ },
{ 1, 2, 0, 0, 0, 0, REPL, "SFL", TGSI_OPCODE_SFL },
{ 1, 2, 0, 0, 0, 0, COMP, "SGT", TGSI_OPCODE_SGT },
{ 1, 1, 0, 0, 0, 0, REPL, "SIN", TGSI_OPCODE_SIN },
{ 1, 2, 0, 0, 0, 0, COMP, "SLE", TGSI_OPCODE_SLE },
{ 1, 2, 0, 0, 0, 0, COMP, "SNE", TGSI_OPCODE_SNE },
{ 1, 2, 0, 0, 0, 0, REPL, "STR", TGSI_OPCODE_STR },
{ 1, 2, 1, 0, 0, 0, OTHR, "TEX", TGSI_OPCODE_TEX },
{ 1, 4, 1, 0, 0, 0, OTHR, "TXD", TGSI_OPCODE_TXD },
{ 1, 2, 1, 0, 0, 0, OTHR, "TXP", TGSI_OPCODE_TXP },
{ 1, 1, 0, 0, 0, 0, COMP, "UP2H", TGSI_OPCODE_UP2H },
{ 1, 1, 0, 0, 0, 0, COMP, "UP2US", TGSI_OPCODE_UP2US },
{ 1, 1, 0, 0, 0, 0, COMP, "UP4B", TGSI_OPCODE_UP4B },
{ 1, 1, 0, 0, 0, 0, COMP, "UP4UB", TGSI_OPCODE_UP4UB },
{ 1, 3, 0, 0, 0, 0, COMP, "X2D", TGSI_OPCODE_X2D },
{ 1, 1, 0, 0, 0, 0, COMP, "ARA", TGSI_OPCODE_ARA },
{ 1, 1, 0, 0, 0, 0, COMP, "ARR", TGSI_OPCODE_ARR },
{ 0, 1, 0, 0, 0, 0, NONE, "BRA", TGSI_OPCODE_BRA },
{ 0, 0, 0, 1, 0, 0, NONE, "CAL", TGSI_OPCODE_CAL },
{ 0, 0, 0, 0, 0, 0, NONE, "RET", TGSI_OPCODE_RET },
{ 1, 1, 0, 0, 0, 0, COMP, "SSG", TGSI_OPCODE_SSG },
{ 1, 3, 0, 0, 0, 0, COMP, "CMP", TGSI_OPCODE_CMP },
{ 1, 1, 0, 0, 0, 0, CHAN, "SCS", TGSI_OPCODE_SCS },
{ 1, 2, 1, 0, 0, 0, OTHR, "TXB", TGSI_OPCODE_TXB },
{ 1, 1, 0, 0, 0, 0, COMP, "NRM", TGSI_OPCODE_NRM },
{ 1, 2, 0, 0, 0, 0, COMP, "DIV", TGSI_OPCODE_DIV },
{ 1, 2, 0, 0, 0, 0, REPL, "DP2", TGSI_OPCODE_DP2 },
{ 1, 2, 1, 0, 0, 0, OTHR, "TXL", TGSI_OPCODE_TXL },
{ 0, 0, 0, 0, 0, 0, NONE, "BRK", TGSI_OPCODE_BRK },
{ 0, 1, 0, 1, 0, 1, NONE, "IF", TGSI_OPCODE_IF },
{ 0, 1, 0, 1, 0, 1, NONE, "UIF", TGSI_OPCODE_UIF },
{ 0, 1, 0, 0, 0, 1, NONE, "", 76 }, /* removed */
{ 0, 0, 0, 1, 1, 1, NONE, "ELSE", TGSI_OPCODE_ELSE },
{ 0, 0, 0, 0, 1, 0, NONE, "ENDIF", TGSI_OPCODE_ENDIF },
{ 1, 0, 0, 0, 1, 0, NONE, "", 79 }, /* removed */
{ 0, 0, 0, 0, 1, 0, NONE, "", 80 }, /* removed */
{ 0, 1, 0, 0, 0, 0, NONE, "PUSHA", TGSI_OPCODE_PUSHA },
{ 1, 0, 0, 0, 0, 0, NONE, "POPA", TGSI_OPCODE_POPA },
{ 1, 1, 0, 0, 0, 0, COMP, "CEIL", TGSI_OPCODE_CEIL },
{ 1, 1, 0, 0, 0, 0, COMP, "I2F", TGSI_OPCODE_I2F },
{ 1, 1, 0, 0, 0, 0, COMP, "NOT", TGSI_OPCODE_NOT },
{ 1, 1, 0, 0, 0, 0, COMP, "TRUNC", TGSI_OPCODE_TRUNC },
{ 1, 2, 0, 0, 0, 0, COMP, "SHL", TGSI_OPCODE_SHL },
{ 0, 0, 0, 0, 0, 0, NONE, "", 88 }, /* removed */
{ 1, 2, 0, 0, 0, 0, COMP, "AND", TGSI_OPCODE_AND },
{ 1, 2, 0, 0, 0, 0, COMP, "OR", TGSI_OPCODE_OR },
{ 1, 2, 0, 0, 0, 0, COMP, "MOD", TGSI_OPCODE_MOD },
{ 1, 2, 0, 0, 0, 0, COMP, "XOR", TGSI_OPCODE_XOR },
{ 1, 3, 0, 0, 0, 0, COMP, "SAD", TGSI_OPCODE_SAD },
{ 1, 2, 1, 0, 0, 0, OTHR, "TXF", TGSI_OPCODE_TXF },
{ 1, 2, 1, 0, 0, 0, OTHR, "TXQ", TGSI_OPCODE_TXQ },
{ 0, 0, 0, 0, 0, 0, NONE, "CONT", TGSI_OPCODE_CONT },
{ 0, 0, 0, 0, 0, 0, NONE, "EMIT", TGSI_OPCODE_EMIT },
{ 0, 0, 0, 0, 0, 0, NONE, "ENDPRIM", TGSI_OPCODE_ENDPRIM },
{ 0, 0, 0, 1, 0, 1, NONE, "BGNLOOP", TGSI_OPCODE_BGNLOOP },
{ 0, 0, 0, 0, 0, 1, NONE, "BGNSUB", TGSI_OPCODE_BGNSUB },
{ 0, 0, 0, 1, 1, 0, NONE, "ENDLOOP", TGSI_OPCODE_ENDLOOP },
{ 0, 0, 0, 0, 1, 0, NONE, "ENDSUB", TGSI_OPCODE_ENDSUB },
{ 1, 1, 1, 0, 0, 0, OTHR, "TXQ_LZ", TGSI_OPCODE_TXQ_LZ },
{ 0, 0, 0, 0, 0, 0, NONE, "", 104 }, /* removed */
{ 0, 0, 0, 0, 0, 0, NONE, "", 105 }, /* removed */
{ 0, 0, 0, 0, 0, 0, NONE, "", 106 }, /* removed */
{ 0, 0, 0, 0, 0, 0, NONE, "NOP", TGSI_OPCODE_NOP },
{ 0, 0, 0, 0, 0, 0, NONE, "", 108 }, /* removed */
{ 0, 0, 0, 0, 0, 0, NONE, "", 109 }, /* removed */
{ 0, 0, 0, 0, 0, 0, NONE, "", 110 }, /* removed */
{ 0, 0, 0, 0, 0, 0, NONE, "", 111 }, /* removed */
{ 1, 1, 0, 0, 0, 0, REPL, "NRM4", TGSI_OPCODE_NRM4 },
{ 0, 1, 0, 0, 0, 0, NONE, "CALLNZ", TGSI_OPCODE_CALLNZ },
{ 0, 1, 0, 0, 0, 0, NONE, "", 114 }, /* removed */
{ 0, 1, 0, 0, 0, 0, NONE, "BREAKC", TGSI_OPCODE_BREAKC },
{ 0, 1, 0, 0, 0, 0, NONE, "KIL", TGSI_OPCODE_KIL },
{ 0, 0, 0, 0, 0, 0, NONE, "END", TGSI_OPCODE_END },
{ 0, 0, 0, 0, 0, 0, NONE, "", 118 }, /* removed */
{ 1, 1, 0, 0, 0, 0, COMP, "F2I", TGSI_OPCODE_F2I },
{ 1, 2, 0, 0, 0, 0, COMP, "IDIV", TGSI_OPCODE_IDIV },
{ 1, 2, 0, 0, 0, 0, COMP, "IMAX", TGSI_OPCODE_IMAX },
{ 1, 2, 0, 0, 0, 0, COMP, "IMIN", TGSI_OPCODE_IMIN },
{ 1, 1, 0, 0, 0, 0, COMP, "INEG", TGSI_OPCODE_INEG },
{ 1, 2, 0, 0, 0, 0, COMP, "ISGE", TGSI_OPCODE_ISGE },
{ 1, 2, 0, 0, 0, 0, COMP, "ISHR", TGSI_OPCODE_ISHR },
{ 1, 2, 0, 0, 0, 0, COMP, "ISLT", TGSI_OPCODE_ISLT },
{ 1, 1, 0, 0, 0, 0, COMP, "F2U", TGSI_OPCODE_F2U },
{ 1, 1, 0, 0, 0, 0, COMP, "U2F", TGSI_OPCODE_U2F },
{ 1, 2, 0, 0, 0, 0, COMP, "UADD", TGSI_OPCODE_UADD },
{ 1, 2, 0, 0, 0, 0, COMP, "UDIV", TGSI_OPCODE_UDIV },
{ 1, 3, 0, 0, 0, 0, COMP, "UMAD", TGSI_OPCODE_UMAD },
{ 1, 2, 0, 0, 0, 0, COMP, "UMAX", TGSI_OPCODE_UMAX },
{ 1, 2, 0, 0, 0, 0, COMP, "UMIN", TGSI_OPCODE_UMIN },
{ 1, 2, 0, 0, 0, 0, COMP, "UMOD", TGSI_OPCODE_UMOD },
{ 1, 2, 0, 0, 0, 0, COMP, "UMUL", TGSI_OPCODE_UMUL },
{ 1, 2, 0, 0, 0, 0, COMP, "USEQ", TGSI_OPCODE_USEQ },
{ 1, 2, 0, 0, 0, 0, COMP, "USGE", TGSI_OPCODE_USGE },
{ 1, 2, 0, 0, 0, 0, COMP, "USHR", TGSI_OPCODE_USHR },
{ 1, 2, 0, 0, 0, 0, COMP, "USLT", TGSI_OPCODE_USLT },
{ 1, 2, 0, 0, 0, 0, COMP, "USNE", TGSI_OPCODE_USNE },
{ 0, 1, 0, 0, 0, 0, NONE, "SWITCH", TGSI_OPCODE_SWITCH },
{ 0, 1, 0, 0, 0, 0, NONE, "CASE", TGSI_OPCODE_CASE },
{ 0, 0, 0, 0, 0, 0, NONE, "DEFAULT", TGSI_OPCODE_DEFAULT },
{ 0, 0, 0, 0, 0, 0, NONE, "ENDSWITCH", TGSI_OPCODE_ENDSWITCH },
 
{ 1, 3, 0, 0, 0, 0, OTHR, "SAMPLE", TGSI_OPCODE_SAMPLE },
{ 1, 2, 0, 0, 0, 0, OTHR, "SAMPLE_I", TGSI_OPCODE_SAMPLE_I },
{ 1, 3, 0, 0, 0, 0, OTHR, "SAMPLE_I_MS", TGSI_OPCODE_SAMPLE_I_MS },
{ 1, 4, 0, 0, 0, 0, OTHR, "SAMPLE_B", TGSI_OPCODE_SAMPLE_B },
{ 1, 4, 0, 0, 0, 0, OTHR, "SAMPLE_C", TGSI_OPCODE_SAMPLE_C },
{ 1, 4, 0, 0, 0, 0, OTHR, "SAMPLE_C_LZ", TGSI_OPCODE_SAMPLE_C_LZ },
{ 1, 5, 0, 0, 0, 0, OTHR, "SAMPLE_D", TGSI_OPCODE_SAMPLE_D },
{ 1, 4, 0, 0, 0, 0, OTHR, "SAMPLE_L", TGSI_OPCODE_SAMPLE_L },
{ 1, 3, 0, 0, 0, 0, OTHR, "GATHER4", TGSI_OPCODE_GATHER4 },
{ 1, 2, 0, 0, 0, 0, OTHR, "SVIEWINFO", TGSI_OPCODE_SVIEWINFO },
{ 1, 2, 0, 0, 0, 0, OTHR, "SAMPLE_POS", TGSI_OPCODE_SAMPLE_POS },
{ 1, 2, 0, 0, 0, 0, OTHR, "SAMPLE_INFO", TGSI_OPCODE_SAMPLE_INFO },
{ 1, 1, 0, 0, 0, 0, COMP, "UARL", TGSI_OPCODE_UARL },
{ 1, 3, 0, 0, 0, 0, COMP, "UCMP", TGSI_OPCODE_UCMP },
{ 1, 1, 0, 0, 0, 0, COMP, "IABS", TGSI_OPCODE_IABS },
{ 1, 1, 0, 0, 0, 0, COMP, "ISSG", TGSI_OPCODE_ISSG },
{ 1, 2, 0, 0, 0, 0, OTHR, "LOAD", TGSI_OPCODE_LOAD },
{ 1, 2, 0, 0, 0, 0, OTHR, "STORE", TGSI_OPCODE_STORE },
{ 1, 0, 0, 0, 0, 0, OTHR, "MFENCE", TGSI_OPCODE_MFENCE },
{ 1, 0, 0, 0, 0, 0, OTHR, "LFENCE", TGSI_OPCODE_LFENCE },
{ 1, 0, 0, 0, 0, 0, OTHR, "SFENCE", TGSI_OPCODE_SFENCE },
{ 0, 0, 0, 0, 0, 0, OTHR, "BARRIER", TGSI_OPCODE_BARRIER },
 
{ 1, 3, 0, 0, 0, 0, OTHR, "ATOMUADD", TGSI_OPCODE_ATOMUADD },
{ 1, 3, 0, 0, 0, 0, OTHR, "ATOMXCHG", TGSI_OPCODE_ATOMXCHG },
{ 1, 4, 0, 0, 0, 0, OTHR, "ATOMCAS", TGSI_OPCODE_ATOMCAS },
{ 1, 3, 0, 0, 0, 0, OTHR, "ATOMAND", TGSI_OPCODE_ATOMAND },
{ 1, 3, 0, 0, 0, 0, OTHR, "ATOMOR", TGSI_OPCODE_ATOMOR },
{ 1, 3, 0, 0, 0, 0, OTHR, "ATOMXOR", TGSI_OPCODE_ATOMXOR },
{ 1, 3, 0, 0, 0, 0, OTHR, "ATOMUMIN", TGSI_OPCODE_ATOMUMIN },
{ 1, 3, 0, 0, 0, 0, OTHR, "ATOMUMAX", TGSI_OPCODE_ATOMUMAX },
{ 1, 3, 0, 0, 0, 0, OTHR, "ATOMIMIN", TGSI_OPCODE_ATOMIMIN },
{ 1, 3, 0, 0, 0, 0, OTHR, "ATOMIMAX", TGSI_OPCODE_ATOMIMAX },
{ 1, 3, 1, 0, 0, 0, OTHR, "TEX2", TGSI_OPCODE_TEX2 },
{ 1, 3, 1, 0, 0, 0, OTHR, "TXB2", TGSI_OPCODE_TXB2 },
{ 1, 3, 1, 0, 0, 0, OTHR, "TXL2", TGSI_OPCODE_TXL2 },
};
 
const struct tgsi_opcode_info *
tgsi_get_opcode_info( uint opcode )
{
static boolean firsttime = 1;
 
if (firsttime) {
unsigned i;
firsttime = 0;
for (i = 0; i < Elements(opcode_info); i++)
assert(opcode_info[i].opcode == i);
}
if (opcode < TGSI_OPCODE_LAST)
return &opcode_info[opcode];
 
assert( 0 );
return NULL;
}
 
 
const char *
tgsi_get_opcode_name( uint opcode )
{
const struct tgsi_opcode_info *info = tgsi_get_opcode_info(opcode);
return info->mnemonic;
}
 
 
const char *
tgsi_get_processor_name( uint processor )
{
switch (processor) {
case TGSI_PROCESSOR_VERTEX:
return "vertex shader";
case TGSI_PROCESSOR_FRAGMENT:
return "fragment shader";
case TGSI_PROCESSOR_GEOMETRY:
return "geometry shader";
default:
return "unknown shader type!";
}
}
 
/**
* Infer the type (of the dst) of the opcode.
*
* MOV and UCMP is special so return VOID
*/
static INLINE enum tgsi_opcode_type
tgsi_opcode_infer_type( uint opcode )
{
switch (opcode) {
case TGSI_OPCODE_MOV:
case TGSI_OPCODE_UCMP:
return TGSI_TYPE_UNTYPED;
case TGSI_OPCODE_NOT:
case TGSI_OPCODE_SHL:
case TGSI_OPCODE_AND:
case TGSI_OPCODE_OR:
case TGSI_OPCODE_XOR:
case TGSI_OPCODE_SAD: /* XXX some src args may be signed for SAD ? */
case TGSI_OPCODE_TXQ:
case TGSI_OPCODE_TXQ_LZ:
case TGSI_OPCODE_F2U:
case TGSI_OPCODE_UDIV:
case TGSI_OPCODE_UMAD:
case TGSI_OPCODE_UMAX:
case TGSI_OPCODE_UMIN:
case TGSI_OPCODE_UMOD:
case TGSI_OPCODE_UMUL:
case TGSI_OPCODE_USEQ:
case TGSI_OPCODE_USGE:
case TGSI_OPCODE_USHR:
case TGSI_OPCODE_USLT:
case TGSI_OPCODE_USNE:
case TGSI_OPCODE_SVIEWINFO:
return TGSI_TYPE_UNSIGNED;
case TGSI_OPCODE_ARL:
case TGSI_OPCODE_ARR:
case TGSI_OPCODE_MOD:
case TGSI_OPCODE_F2I:
case TGSI_OPCODE_IDIV:
case TGSI_OPCODE_IMAX:
case TGSI_OPCODE_IMIN:
case TGSI_OPCODE_INEG:
case TGSI_OPCODE_ISGE:
case TGSI_OPCODE_ISHR:
case TGSI_OPCODE_ISLT:
case TGSI_OPCODE_UADD:
case TGSI_OPCODE_UARL:
case TGSI_OPCODE_IABS:
case TGSI_OPCODE_ISSG:
return TGSI_TYPE_SIGNED;
default:
return TGSI_TYPE_FLOAT;
}
}
 
/*
* infer the source type of a TGSI opcode.
*/
enum tgsi_opcode_type
tgsi_opcode_infer_src_type( uint opcode )
{
switch (opcode) {
case TGSI_OPCODE_UIF:
case TGSI_OPCODE_TXF:
case TGSI_OPCODE_BREAKC:
case TGSI_OPCODE_U2F:
case TGSI_OPCODE_UADD:
case TGSI_OPCODE_SWITCH:
case TGSI_OPCODE_CASE:
case TGSI_OPCODE_SAMPLE_I:
case TGSI_OPCODE_SAMPLE_I_MS:
return TGSI_TYPE_UNSIGNED;
case TGSI_OPCODE_I2F:
return TGSI_TYPE_SIGNED;
case TGSI_OPCODE_ARL:
case TGSI_OPCODE_ARR:
case TGSI_OPCODE_TXQ_LZ:
case TGSI_OPCODE_F2I:
case TGSI_OPCODE_F2U:
case TGSI_OPCODE_UCMP:
return TGSI_TYPE_FLOAT;
default:
return tgsi_opcode_infer_type(opcode);
}
}
 
/*
* infer the destination type of a TGSI opcode.
*/
enum tgsi_opcode_type
tgsi_opcode_infer_dst_type( uint opcode )
{
return tgsi_opcode_infer_type(opcode);
}
/drivers/video/Gallium/auxiliary/tgsi/tgsi_info.h
0,0 → 1,113
/**************************************************************************
*
* 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.
*
**************************************************************************/
 
#ifndef TGSI_INFO_H
#define TGSI_INFO_H
 
#include "pipe/p_compiler.h"
#include "pipe/p_shader_tokens.h"
#include "util/u_format.h"
 
#if defined __cplusplus
extern "C" {
#endif
 
/* This enum describes how an opcode calculates its result. */
enum tgsi_output_mode {
/** The opcode produces no result. */
TGSI_OUTPUT_NONE = 0,
 
/** When this opcode writes to a channel of the destination register,
* it takes as arguments values from the same channel of the source
* register(s).
*
* Example: TGSI_OPCODE_ADD
*/
TGSI_OUTPUT_COMPONENTWISE = 1,
 
/** This opcode writes the same value to all enabled channels of the
* destination register.
*
* Example: TGSI_OPCODE_RSQ
*/
TGSI_OUTPUT_REPLICATE = 2,
 
/** The operation performed by this opcode is dependent on which channel
* of the destination register is being written.
*
* Example: TGSI_OPCODE_LOG
*/
TGSI_OUTPUT_CHAN_DEPENDENT = 3,
 
/**
* Example: TGSI_OPCODE_TEX
*/
TGSI_OUTPUT_OTHER = 4
};
 
struct tgsi_opcode_info
{
unsigned num_dst:3;
unsigned num_src:3;
unsigned is_tex:1;
unsigned is_branch:1;
int pre_dedent:2;
int post_indent:2;
enum tgsi_output_mode output_mode:3;
const char *mnemonic;
uint opcode;
};
 
const struct tgsi_opcode_info *
tgsi_get_opcode_info( uint opcode );
 
const char *
tgsi_get_opcode_name( uint opcode );
 
const char *
tgsi_get_processor_name( uint processor );
 
enum tgsi_opcode_type {
TGSI_TYPE_UNTYPED, /* for MOV */
TGSI_TYPE_VOID,
TGSI_TYPE_UNSIGNED,
TGSI_TYPE_SIGNED,
TGSI_TYPE_FLOAT,
TGSI_TYPE_DOUBLE
};
 
enum tgsi_opcode_type
tgsi_opcode_infer_src_type( uint opcode );
 
enum tgsi_opcode_type
tgsi_opcode_infer_dst_type( uint opcode );
 
#if defined __cplusplus
}
#endif
 
#endif /* TGSI_INFO_H */
/drivers/video/Gallium/auxiliary/tgsi/tgsi_iterate.c
0,0 → 1,90
/**************************************************************************
*
* 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.
*
**************************************************************************/
 
#include "util/u_debug.h"
#include "tgsi_iterate.h"
 
boolean
tgsi_iterate_shader(
const struct tgsi_token *tokens,
struct tgsi_iterate_context *ctx )
{
struct tgsi_parse_context parse;
 
if (tgsi_parse_init( &parse, tokens ) != TGSI_PARSE_OK)
return FALSE;
 
ctx->processor = parse.FullHeader.Processor;
 
if (ctx->prolog)
if (!ctx->prolog( ctx ))
goto fail;
 
while (!tgsi_parse_end_of_tokens( &parse )) {
tgsi_parse_token( &parse );
 
switch (parse.FullToken.Token.Type) {
case TGSI_TOKEN_TYPE_INSTRUCTION:
if (ctx->iterate_instruction)
if (!ctx->iterate_instruction( ctx, &parse.FullToken.FullInstruction ))
goto fail;
break;
 
case TGSI_TOKEN_TYPE_DECLARATION:
if (ctx->iterate_declaration)
if (!ctx->iterate_declaration( ctx, &parse.FullToken.FullDeclaration ))
goto fail;
break;
 
case TGSI_TOKEN_TYPE_IMMEDIATE:
if (ctx->iterate_immediate)
if (!ctx->iterate_immediate( ctx, &parse.FullToken.FullImmediate ))
goto fail;
break;
 
case TGSI_TOKEN_TYPE_PROPERTY:
if (ctx->iterate_property)
if (!ctx->iterate_property( ctx, &parse.FullToken.FullProperty ))
goto fail;
break;
 
default:
assert( 0 );
}
}
 
if (ctx->epilog)
if (!ctx->epilog( ctx ))
goto fail;
 
tgsi_parse_free( &parse );
return TRUE;
 
fail:
tgsi_parse_free( &parse );
return FALSE;
}
/drivers/video/Gallium/auxiliary/tgsi/tgsi_iterate.h
0,0 → 1,80
/**************************************************************************
*
* 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.
*
**************************************************************************/
 
#ifndef TGSI_ITERATE_H
#define TGSI_ITERATE_H
 
#include "pipe/p_shader_tokens.h"
#include "tgsi/tgsi_parse.h"
 
#if defined __cplusplus
extern "C" {
#endif
 
struct tgsi_iterate_context
{
boolean
(* prolog)(
struct tgsi_iterate_context *ctx );
 
boolean
(* iterate_instruction)(
struct tgsi_iterate_context *ctx,
struct tgsi_full_instruction *inst );
 
boolean
(* iterate_declaration)(
struct tgsi_iterate_context *ctx,
struct tgsi_full_declaration *decl );
 
boolean
(* iterate_immediate)(
struct tgsi_iterate_context *ctx,
struct tgsi_full_immediate *imm );
 
boolean
(* iterate_property)(
struct tgsi_iterate_context *ctx,
struct tgsi_full_property *prop );
 
boolean
(* epilog)(
struct tgsi_iterate_context *ctx );
 
struct tgsi_processor processor;
};
 
boolean
tgsi_iterate_shader(
const struct tgsi_token *tokens,
struct tgsi_iterate_context *ctx );
 
#if defined __cplusplus
}
#endif
 
#endif /* TGSI_ITERATE_H */
/drivers/video/Gallium/auxiliary/tgsi/tgsi_opcode_tmp.h
0,0 → 1,226
/**************************************************************************
*
* 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.
*
**************************************************************************/
#ifndef OP12_TEX
#define OP12_TEX(a) OP12(a)
#endif
 
#ifndef OP14_TEX
#define OP14_TEX(a) OP14(a)
#endif
 
#ifndef OP12_SAMPLE
#define OP12_SAMPLE(a) OP12(a)
#endif
 
#ifndef OP13_SAMPLE
#define OP13_SAMPLE(a) OP13(a)
#endif
 
#ifndef OP14_SAMPLE
#define OP14_SAMPLE(a) OP14(a)
#endif
 
#ifndef OP15_SAMPLE
#define OP15_SAMPLE(a) OP15(a)
#endif
 
#ifndef OP00_LBL
#define OP00_LBL(a) OP00(a)
#endif
 
#ifndef OP01_LBL
#define OP01_LBL(a) OP01(a)
#endif
 
OP11(ARL)
OP11(MOV)
OP11(LIT)
OP11(RCP)
OP11(RSQ)
OP11(EXP)
OP11(LOG)
OP12(MUL)
OP12(ADD)
OP12(DP3)
OP12(DP4)
OP12(DST)
OP12(MIN)
OP12(MAX)
OP12(SLT)
OP12(SGE)
OP13(MAD)
OP12(SUB)
OP13(LRP)
OP13(CND)
OP11(SQRT)
OP13(DP2A)
OP11(FRC)
OP13(CLAMP)
OP11(FLR)
OP11(ROUND)
OP11(EX2)
OP11(LG2)
OP12(POW)
OP12(XPD)
OP11(ABS)
OP11(RCC)
OP12(DPH)
OP11(COS)
OP11(DDX)
OP11(DDY)
OP00(KILP)
OP11(PK2H)
OP11(PK2US)
OP11(PK4B)
OP11(PK4UB)
OP12(RFL)
OP12(SEQ)
OP12(SFL)
OP12(SGT)
OP11(SIN)
OP12(SLE)
OP12(SNE)
OP12(STR)
OP12_TEX(TEX)
OP14_TEX(TXD)
OP12_TEX(TXP)
OP11(UP2H)
OP11(UP2US)
OP11(UP4B)
OP11(UP4UB)
OP13(X2D)
OP11(ARA)
OP11(ARR)
OP01(BRA)
OP00_LBL(CAL)
OP00(RET)
OP11(SSG)
OP13(CMP)
OP11(SCS)
OP12_TEX(TXB)
OP11(NRM)
OP12(DIV)
OP12(DP2)
OP12_TEX(TXL)
OP00(BRK)
OP01_LBL(IF)
OP01_LBL(UIF)
OP00_LBL(ELSE)
OP00(ENDIF)
OP01(PUSHA)
OP10(POPA)
OP11(CEIL)
OP11(I2F)
OP11(NOT)
OP11(TRUNC)
OP12(SHL)
OP12(AND)
OP12(OR)
OP12(MOD)
OP12(XOR)
OP13(SAD)
OP12_TEX(TXF)
OP12_TEX(TXQ)
OP00(CONT)
OP00(EMIT)
OP00(ENDPRIM)
OP00_LBL(BGNLOOP)
OP00(BGNSUB)
OP00_LBL(ENDLOOP)
OP00(ENDSUB)
OP00(NOP)
OP11(NRM4)
OP01(CALLNZ)
OP01(BREAKC)
OP01(KIL)
OP00(END)
OP11(F2I)
OP12(IDIV)
OP12(IMAX)
OP12(IMIN)
OP11(INEG)
OP12(ISGE)
OP12(ISHR)
OP12(ISLT)
OP11(F2U)
OP11(U2F)
OP12(UADD)
OP12(UDIV)
OP13(UMAD)
OP12(UMAX)
OP12(UMIN)
OP12(UMOD)
OP12(UMUL)
OP12(USEQ)
OP12(USGE)
OP12(USHR)
OP12(USLT)
OP12(USNE)
OP01(SWITCH)
OP01(CASE)
OP00(DEFAULT)
OP00(ENDSWITCH)
 
OP13_SAMPLE(SAMPLE)
OP12_SAMPLE(SAMPLE_I)
OP13_SAMPLE(SAMPLE_I_MS)
OP14_SAMPLE(SAMPLE_B)
OP14_SAMPLE(SAMPLE_C)
OP14_SAMPLE(SAMPLE_C_LZ)
OP15_SAMPLE(SAMPLE_D)
OP14_SAMPLE(SAMPLE_L)
OP13_SAMPLE(GATHER4)
OP12(SVIEWINFO)
OP13(SAMPLE_POS)
OP12(SAMPLE_INFO)
 
 
#undef OP00
#undef OP01
#undef OP10
#undef OP11
#undef OP12
#undef OP13
 
#ifdef OP14
#undef OP14
#endif
 
#ifdef OP15
#undef OP15
#endif
 
#undef OP00_LBL
#undef OP01_LBL
 
#undef OP12_TEX
#undef OP14_TEX
 
#undef OP12_SAMPLE
#undef OP13_SAMPLE
#undef OP14_SAMPLE
#undef OP15_SAMPLE
/drivers/video/Gallium/auxiliary/tgsi/tgsi_parse.c
0,0 → 1,307
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
#include "util/u_debug.h"
#include "pipe/p_shader_tokens.h"
#include "tgsi_parse.h"
#include "util/u_memory.h"
 
unsigned
tgsi_parse_init(
struct tgsi_parse_context *ctx,
const struct tgsi_token *tokens )
{
ctx->FullHeader.Header = *(struct tgsi_header *) &tokens[0];
if( ctx->FullHeader.Header.HeaderSize >= 2 ) {
ctx->FullHeader.Processor = *(struct tgsi_processor *) &tokens[1];
}
else {
return TGSI_PARSE_ERROR;
}
 
ctx->Tokens = tokens;
ctx->Position = ctx->FullHeader.Header.HeaderSize;
 
return TGSI_PARSE_OK;
}
 
void
tgsi_parse_free(
struct tgsi_parse_context *ctx )
{
}
 
boolean
tgsi_parse_end_of_tokens(
struct tgsi_parse_context *ctx )
{
return ctx->Position >=
ctx->FullHeader.Header.HeaderSize + ctx->FullHeader.Header.BodySize;
}
 
 
/**
* This function is used to avoid and work-around type punning/aliasing
* warnings. The warnings seem harmless on x86 but on PPC they cause
* real failures.
*/
static INLINE void
copy_token(void *dst, const void *src)
{
memcpy(dst, src, 4);
}
 
 
/**
* Get next 4-byte token, return it at address specified by 'token'
*/
static void
next_token(
struct tgsi_parse_context *ctx,
void *token )
{
assert( !tgsi_parse_end_of_tokens( ctx ) );
copy_token(token, &ctx->Tokens[ctx->Position]);
ctx->Position++;
}
 
 
void
tgsi_parse_token(
struct tgsi_parse_context *ctx )
{
struct tgsi_token token;
unsigned i;
 
next_token( ctx, &token );
 
switch( token.Type ) {
case TGSI_TOKEN_TYPE_DECLARATION:
{
struct tgsi_full_declaration *decl = &ctx->FullToken.FullDeclaration;
 
memset(decl, 0, sizeof *decl);
copy_token(&decl->Declaration, &token);
 
next_token( ctx, &decl->Range );
 
if (decl->Declaration.Dimension) {
next_token(ctx, &decl->Dim);
}
 
if( decl->Declaration.Interpolate ) {
next_token( ctx, &decl->Interp );
}
 
if( decl->Declaration.Semantic ) {
next_token( ctx, &decl->Semantic );
}
 
if (decl->Declaration.File == TGSI_FILE_RESOURCE) {
next_token(ctx, &decl->Resource);
}
 
if (decl->Declaration.File == TGSI_FILE_SAMPLER_VIEW) {
next_token(ctx, &decl->SamplerView);
}
 
if( decl->Declaration.Array ) {
next_token(ctx, &decl->Array);
}
 
break;
}
 
case TGSI_TOKEN_TYPE_IMMEDIATE:
{
struct tgsi_full_immediate *imm = &ctx->FullToken.FullImmediate;
uint imm_count;
 
memset(imm, 0, sizeof *imm);
copy_token(&imm->Immediate, &token);
 
imm_count = imm->Immediate.NrTokens - 1;
 
switch (imm->Immediate.DataType) {
case TGSI_IMM_FLOAT32:
for (i = 0; i < imm_count; i++) {
next_token(ctx, &imm->u[i].Float);
}
break;
 
case TGSI_IMM_UINT32:
for (i = 0; i < imm_count; i++) {
next_token(ctx, &imm->u[i].Uint);
}
break;
 
case TGSI_IMM_INT32:
for (i = 0; i < imm_count; i++) {
next_token(ctx, &imm->u[i].Int);
}
break;
 
default:
assert( 0 );
}
 
break;
}
 
case TGSI_TOKEN_TYPE_INSTRUCTION:
{
struct tgsi_full_instruction *inst = &ctx->FullToken.FullInstruction;
 
memset(inst, 0, sizeof *inst);
copy_token(&inst->Instruction, &token);
 
if (inst->Instruction.Predicate) {
next_token(ctx, &inst->Predicate);
}
 
if (inst->Instruction.Label) {
next_token( ctx, &inst->Label);
}
 
if (inst->Instruction.Texture) {
next_token( ctx, &inst->Texture);
for( i = 0; i < inst->Texture.NumOffsets; i++ ) {
next_token( ctx, &inst->TexOffsets[i] );
}
}
 
assert( inst->Instruction.NumDstRegs <= TGSI_FULL_MAX_DST_REGISTERS );
 
for( i = 0; i < inst->Instruction.NumDstRegs; i++ ) {
 
next_token( ctx, &inst->Dst[i].Register );
 
if( inst->Dst[i].Register.Indirect )
next_token( ctx, &inst->Dst[i].Indirect );
 
if( inst->Dst[i].Register.Dimension ) {
next_token( ctx, &inst->Dst[i].Dimension );
 
/*
* No support for multi-dimensional addressing.
*/
assert( !inst->Dst[i].Dimension.Dimension );
 
if( inst->Dst[i].Dimension.Indirect )
next_token( ctx, &inst->Dst[i].DimIndirect );
}
}
 
assert( inst->Instruction.NumSrcRegs <= TGSI_FULL_MAX_SRC_REGISTERS );
 
for( i = 0; i < inst->Instruction.NumSrcRegs; i++ ) {
 
next_token( ctx, &inst->Src[i].Register );
 
if( inst->Src[i].Register.Indirect )
next_token( ctx, &inst->Src[i].Indirect );
 
if( inst->Src[i].Register.Dimension ) {
next_token( ctx, &inst->Src[i].Dimension );
 
/*
* No support for multi-dimensional addressing.
*/
assert( !inst->Src[i].Dimension.Dimension );
 
if( inst->Src[i].Dimension.Indirect )
next_token( ctx, &inst->Src[i].DimIndirect );
}
}
 
break;
}
 
case TGSI_TOKEN_TYPE_PROPERTY:
{
struct tgsi_full_property *prop = &ctx->FullToken.FullProperty;
uint prop_count;
 
memset(prop, 0, sizeof *prop);
copy_token(&prop->Property, &token);
 
prop_count = prop->Property.NrTokens - 1;
for (i = 0; i < prop_count; i++) {
next_token(ctx, &prop->u[i]);
}
 
break;
}
 
default:
assert( 0 );
}
}
 
 
 
 
/**
* Make a new copy of a token array.
*/
struct tgsi_token *
tgsi_dup_tokens(const struct tgsi_token *tokens)
{
unsigned n = tgsi_num_tokens(tokens);
unsigned bytes = n * sizeof(struct tgsi_token);
struct tgsi_token *new_tokens = (struct tgsi_token *) MALLOC(bytes);
if (new_tokens)
memcpy(new_tokens, tokens, bytes);
return new_tokens;
}
 
 
/**
* Allocate memory for num_tokens tokens.
*/
struct tgsi_token *
tgsi_alloc_tokens(unsigned num_tokens)
{
unsigned bytes = num_tokens * sizeof(struct tgsi_token);
return (struct tgsi_token *) MALLOC(bytes);
}
 
 
void
tgsi_dump_tokens(const struct tgsi_token *tokens)
{
const unsigned *dwords = (const unsigned *)tokens;
int nr = tgsi_num_tokens(tokens);
int i;
assert(sizeof(*tokens) == sizeof(unsigned));
 
debug_printf("const unsigned tokens[%d] = {\n", nr);
for (i = 0; i < nr; i++)
debug_printf("0x%08x,\n", dwords[i]);
debug_printf("};\n");
}
/drivers/video/Gallium/auxiliary/tgsi/tgsi_parse.h
0,0 → 1,159
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
#ifndef TGSI_PARSE_H
#define TGSI_PARSE_H
 
#include "pipe/p_compiler.h"
#include "pipe/p_shader_tokens.h"
 
#if defined __cplusplus
extern "C" {
#endif
 
struct tgsi_full_header
{
struct tgsi_header Header;
struct tgsi_processor Processor;
};
 
struct tgsi_full_dst_register
{
struct tgsi_dst_register Register;
struct tgsi_ind_register Indirect;
struct tgsi_dimension Dimension;
struct tgsi_ind_register DimIndirect;
};
 
struct tgsi_full_src_register
{
struct tgsi_src_register Register;
struct tgsi_ind_register Indirect;
struct tgsi_dimension Dimension;
struct tgsi_ind_register DimIndirect;
};
 
struct tgsi_full_declaration
{
struct tgsi_declaration Declaration;
struct tgsi_declaration_range Range;
struct tgsi_declaration_dimension Dim;
struct tgsi_declaration_interp Interp;
struct tgsi_declaration_semantic Semantic;
struct tgsi_declaration_resource Resource;
struct tgsi_declaration_sampler_view SamplerView;
struct tgsi_declaration_array Array;
};
 
struct tgsi_full_immediate
{
struct tgsi_immediate Immediate;
union tgsi_immediate_data u[4];
};
 
struct tgsi_full_property
{
struct tgsi_property Property;
struct tgsi_property_data u[8];
};
 
#define TGSI_FULL_MAX_DST_REGISTERS 2
#define TGSI_FULL_MAX_SRC_REGISTERS 5 /* SAMPLE_D has 5 */
#define TGSI_FULL_MAX_TEX_OFFSETS 4
 
struct tgsi_full_instruction
{
struct tgsi_instruction Instruction;
struct tgsi_instruction_predicate Predicate;
struct tgsi_instruction_label Label;
struct tgsi_instruction_texture Texture;
struct tgsi_full_dst_register Dst[TGSI_FULL_MAX_DST_REGISTERS];
struct tgsi_full_src_register Src[TGSI_FULL_MAX_SRC_REGISTERS];
struct tgsi_texture_offset TexOffsets[TGSI_FULL_MAX_TEX_OFFSETS];
};
 
union tgsi_full_token
{
struct tgsi_token Token;
struct tgsi_full_declaration FullDeclaration;
struct tgsi_full_immediate FullImmediate;
struct tgsi_full_instruction FullInstruction;
struct tgsi_full_property FullProperty;
};
 
struct tgsi_parse_context
{
const struct tgsi_token *Tokens;
unsigned Position;
struct tgsi_full_header FullHeader;
union tgsi_full_token FullToken;
};
 
#define TGSI_PARSE_OK 0
#define TGSI_PARSE_ERROR 1
 
unsigned
tgsi_parse_init(
struct tgsi_parse_context *ctx,
const struct tgsi_token *tokens );
 
void
tgsi_parse_free(
struct tgsi_parse_context *ctx );
 
boolean
tgsi_parse_end_of_tokens(
struct tgsi_parse_context *ctx );
 
void
tgsi_parse_token(
struct tgsi_parse_context *ctx );
 
static INLINE unsigned
tgsi_num_tokens(const struct tgsi_token *tokens)
{
struct tgsi_header header;
memcpy(&header, tokens, sizeof(header));
return header.HeaderSize + header.BodySize;
}
 
void
tgsi_dump_tokens(const struct tgsi_token *tokens);
 
struct tgsi_token *
tgsi_dup_tokens(const struct tgsi_token *tokens);
 
struct tgsi_token *
tgsi_alloc_tokens(unsigned num_tokens);
 
 
#if defined __cplusplus
}
#endif
 
#endif /* TGSI_PARSE_H */
 
/drivers/video/Gallium/auxiliary/tgsi/tgsi_sanity.c
0,0 → 1,562
/**************************************************************************
*
* 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.
*
**************************************************************************/
 
#include "util/u_debug.h"
#include "util/u_memory.h"
#include "util/u_prim.h"
#include "cso_cache/cso_hash.h"
#include "tgsi_sanity.h"
#include "tgsi_info.h"
#include "tgsi_iterate.h"
 
 
DEBUG_GET_ONCE_BOOL_OPTION(print_sanity, "TGSI_PRINT_SANITY", FALSE)
 
 
typedef struct {
uint file : 28;
/* max 2 dimensions */
uint dimensions : 4;
uint indices[2];
} scan_register;
 
struct sanity_check_ctx
{
struct tgsi_iterate_context iter;
struct cso_hash *regs_decl;
struct cso_hash *regs_used;
struct cso_hash *regs_ind_used;
 
uint num_imms;
uint num_instructions;
uint index_of_END;
 
uint errors;
uint warnings;
uint implied_array_size;
 
boolean print;
};
 
static INLINE unsigned
scan_register_key(const scan_register *reg)
{
unsigned key = reg->file;
key |= (reg->indices[0] << 4);
key |= (reg->indices[1] << 18);
 
return key;
}
 
static void
fill_scan_register1d(scan_register *reg,
uint file, uint index)
{
reg->file = file;
reg->dimensions = 1;
reg->indices[0] = index;
reg->indices[1] = 0;
}
 
static void
fill_scan_register2d(scan_register *reg,
uint file, uint index1, uint index2)
{
reg->file = file;
reg->dimensions = 2;
reg->indices[0] = index1;
reg->indices[1] = index2;
}
 
static void
scan_register_dst(scan_register *reg,
struct tgsi_full_dst_register *dst)
{
if (dst->Register.Dimension) {
/*FIXME: right now we don't support indirect
* multidimensional addressing */
fill_scan_register2d(reg,
dst->Register.File,
dst->Register.Index,
dst->Dimension.Index);
} else {
fill_scan_register1d(reg,
dst->Register.File,
dst->Register.Index);
}
}
 
static void
scan_register_src(scan_register *reg,
struct tgsi_full_src_register *src)
{
if (src->Register.Dimension) {
/*FIXME: right now we don't support indirect
* multidimensional addressing */
fill_scan_register2d(reg,
src->Register.File,
src->Register.Index,
src->Dimension.Index);
} else {
fill_scan_register1d(reg,
src->Register.File,
src->Register.Index);
}
}
 
static scan_register *
create_scan_register_src(struct tgsi_full_src_register *src)
{
scan_register *reg = MALLOC(sizeof(scan_register));
scan_register_src(reg, src);
 
return reg;
}
 
static scan_register *
create_scan_register_dst(struct tgsi_full_dst_register *dst)
{
scan_register *reg = MALLOC(sizeof(scan_register));
scan_register_dst(reg, dst);
 
return reg;
}
 
static void
report_error(
struct sanity_check_ctx *ctx,
const char *format,
... )
{
va_list args;
 
if (!ctx->print)
return;
 
debug_printf( "Error : " );
va_start( args, format );
_debug_vprintf( format, args );
va_end( args );
debug_printf( "\n" );
ctx->errors++;
}
 
static void
report_warning(
struct sanity_check_ctx *ctx,
const char *format,
... )
{
va_list args;
 
if (!ctx->print)
return;
 
debug_printf( "Warning: " );
va_start( args, format );
_debug_vprintf( format, args );
va_end( args );
debug_printf( "\n" );
ctx->warnings++;
}
 
static boolean
check_file_name(
struct sanity_check_ctx *ctx,
uint file )
{
if (file <= TGSI_FILE_NULL || file >= TGSI_FILE_COUNT) {
report_error( ctx, "(%u): Invalid register file name", file );
return FALSE;
}
return TRUE;
}
 
static boolean
is_register_declared(
struct sanity_check_ctx *ctx,
const scan_register *reg)
{
void *data = cso_hash_find_data_from_template(
ctx->regs_decl, scan_register_key(reg),
(void*)reg, sizeof(scan_register));
return data ? TRUE : FALSE;
}
 
static boolean
is_any_register_declared(
struct sanity_check_ctx *ctx,
uint file )
{
struct cso_hash_iter iter =
cso_hash_first_node(ctx->regs_decl);
 
while (!cso_hash_iter_is_null(iter)) {
scan_register *reg = (scan_register *)cso_hash_iter_data(iter);
if (reg->file == file)
return TRUE;
iter = cso_hash_iter_next(iter);
}
 
return FALSE;
}
 
static boolean
is_register_used(
struct sanity_check_ctx *ctx,
scan_register *reg)
{
void *data = cso_hash_find_data_from_template(
ctx->regs_used, scan_register_key(reg),
reg, sizeof(scan_register));
return data ? TRUE : FALSE;
}
 
 
static boolean
is_ind_register_used(
struct sanity_check_ctx *ctx,
scan_register *reg)
{
return cso_hash_contains(ctx->regs_ind_used, reg->file);
}
 
static const char *file_names[TGSI_FILE_COUNT] =
{
"NULL",
"CONST",
"IN",
"OUT",
"TEMP",
"SAMP",
"ADDR",
"IMM",
"PRED",
"SV",
"RES"
};
 
static boolean
check_register_usage(
struct sanity_check_ctx *ctx,
scan_register *reg,
const char *name,
boolean indirect_access )
{
if (!check_file_name( ctx, reg->file )) {
FREE(reg);
return FALSE;
}
 
if (indirect_access) {
/* Note that 'index' is an offset relative to the value of the
* address register. No range checking done here.*/
reg->indices[0] = 0;
reg->indices[1] = 0;
if (!is_any_register_declared( ctx, reg->file ))
report_error( ctx, "%s: Undeclared %s register", file_names[reg->file], name );
if (!is_ind_register_used(ctx, reg))
cso_hash_insert(ctx->regs_ind_used, reg->file, reg);
else
FREE(reg);
}
else {
if (!is_register_declared( ctx, reg )) {
if (reg->dimensions == 2) {
report_error( ctx, "%s[%d][%d]: Undeclared %s register", file_names[reg->file],
reg->indices[0], reg->indices[1], name );
}
else {
report_error( ctx, "%s[%d]: Undeclared %s register", file_names[reg->file],
reg->indices[0], name );
}
}
if (!is_register_used( ctx, reg ))
cso_hash_insert(ctx->regs_used, scan_register_key(reg), reg);
else
FREE(reg);
}
return TRUE;
}
 
static boolean
iter_instruction(
struct tgsi_iterate_context *iter,
struct tgsi_full_instruction *inst )
{
struct sanity_check_ctx *ctx = (struct sanity_check_ctx *) iter;
const struct tgsi_opcode_info *info;
uint i;
 
if (inst->Instruction.Opcode == TGSI_OPCODE_END) {
if (ctx->index_of_END != ~0) {
report_error( ctx, "Too many END instructions" );
}
ctx->index_of_END = ctx->num_instructions;
}
 
info = tgsi_get_opcode_info( inst->Instruction.Opcode );
if (info == NULL) {
report_error( ctx, "(%u): Invalid instruction opcode", inst->Instruction.Opcode );
return TRUE;
}
 
if (info->num_dst != inst->Instruction.NumDstRegs) {
report_error( ctx, "%s: Invalid number of destination operands, should be %u", info->mnemonic, info->num_dst );
}
if (info->num_src != inst->Instruction.NumSrcRegs) {
report_error( ctx, "%s: Invalid number of source operands, should be %u", info->mnemonic, info->num_src );
}
 
/* Check destination and source registers' validity.
* Mark the registers as used.
*/
for (i = 0; i < inst->Instruction.NumDstRegs; i++) {
scan_register *reg = create_scan_register_dst(&inst->Dst[i]);
check_register_usage(
ctx,
reg,
"destination",
FALSE );
if (!inst->Dst[i].Register.WriteMask) {
report_error(ctx, "Destination register has empty writemask");
}
}
for (i = 0; i < inst->Instruction.NumSrcRegs; i++) {
scan_register *reg = create_scan_register_src(&inst->Src[i]);
check_register_usage(
ctx,
reg,
"source",
(boolean)inst->Src[i].Register.Indirect );
if (inst->Src[i].Register.Indirect) {
scan_register *ind_reg = MALLOC(sizeof(scan_register));
 
fill_scan_register1d(ind_reg,
inst->Src[i].Indirect.File,
inst->Src[i].Indirect.Index);
check_register_usage(
ctx,
ind_reg,
"indirect",
FALSE );
}
}
 
ctx->num_instructions++;
 
return TRUE;
}
 
static void
check_and_declare(struct sanity_check_ctx *ctx,
scan_register *reg)
{
if (is_register_declared( ctx, reg))
report_error( ctx, "%s[%u]: The same register declared more than once",
file_names[reg->file], reg->indices[0] );
cso_hash_insert(ctx->regs_decl,
scan_register_key(reg),
reg);
}
 
 
static boolean
iter_declaration(
struct tgsi_iterate_context *iter,
struct tgsi_full_declaration *decl )
{
struct sanity_check_ctx *ctx = (struct sanity_check_ctx *) iter;
uint file;
uint i;
 
/* No declarations allowed after the first instruction.
*/
if (ctx->num_instructions > 0)
report_error( ctx, "Instruction expected but declaration found" );
 
/* Check registers' validity.
* Mark the registers as declared.
*/
file = decl->Declaration.File;
if (!check_file_name( ctx, file ))
return TRUE;
for (i = decl->Range.First; i <= decl->Range.Last; i++) {
/* declared TGSI_FILE_INPUT's for geometry processor
* have an implied second dimension */
if (file == TGSI_FILE_INPUT &&
ctx->iter.processor.Processor == TGSI_PROCESSOR_GEOMETRY) {
uint vert;
for (vert = 0; vert < ctx->implied_array_size; ++vert) {
scan_register *reg = MALLOC(sizeof(scan_register));
fill_scan_register2d(reg, file, i, vert);
check_and_declare(ctx, reg);
}
} else {
scan_register *reg = MALLOC(sizeof(scan_register));
if (decl->Declaration.Dimension) {
fill_scan_register2d(reg, file, i, decl->Dim.Index2D);
} else {
fill_scan_register1d(reg, file, i);
}
check_and_declare(ctx, reg);
}
}
 
return TRUE;
}
 
static boolean
iter_immediate(
struct tgsi_iterate_context *iter,
struct tgsi_full_immediate *imm )
{
struct sanity_check_ctx *ctx = (struct sanity_check_ctx *) iter;
scan_register *reg;
 
/* No immediates allowed after the first instruction.
*/
if (ctx->num_instructions > 0)
report_error( ctx, "Instruction expected but immediate found" );
 
/* Mark the register as declared.
*/
reg = MALLOC(sizeof(scan_register));
fill_scan_register1d(reg, TGSI_FILE_IMMEDIATE, ctx->num_imms);
cso_hash_insert(ctx->regs_decl, scan_register_key(reg), reg);
ctx->num_imms++;
 
/* Check data type validity.
*/
if (imm->Immediate.DataType != TGSI_IMM_FLOAT32 &&
imm->Immediate.DataType != TGSI_IMM_UINT32 &&
imm->Immediate.DataType != TGSI_IMM_INT32) {
report_error( ctx, "(%u): Invalid immediate data type", imm->Immediate.DataType );
return TRUE;
}
 
return TRUE;
}
 
 
static boolean
iter_property(
struct tgsi_iterate_context *iter,
struct tgsi_full_property *prop )
{
struct sanity_check_ctx *ctx = (struct sanity_check_ctx *) iter;
 
if (iter->processor.Processor == TGSI_PROCESSOR_GEOMETRY &&
prop->Property.PropertyName == TGSI_PROPERTY_GS_INPUT_PRIM) {
ctx->implied_array_size = u_vertices_per_prim(prop->u[0].Data);
}
return TRUE;
}
 
static boolean
epilog(
struct tgsi_iterate_context *iter )
{
struct sanity_check_ctx *ctx = (struct sanity_check_ctx *) iter;
 
/* There must be an END instruction somewhere.
*/
if (ctx->index_of_END == ~0) {
report_error( ctx, "Missing END instruction" );
}
 
/* Check if all declared registers were used.
*/
{
struct cso_hash_iter iter =
cso_hash_first_node(ctx->regs_decl);
 
while (!cso_hash_iter_is_null(iter)) {
scan_register *reg = (scan_register *)cso_hash_iter_data(iter);
if (!is_register_used(ctx, reg) && !is_ind_register_used(ctx, reg)) {
report_warning( ctx, "%s[%u]: Register never used",
file_names[reg->file], reg->indices[0] );
}
iter = cso_hash_iter_next(iter);
}
}
 
/* Print totals, if any.
*/
if (ctx->errors || ctx->warnings)
debug_printf( "%u errors, %u warnings\n", ctx->errors, ctx->warnings );
 
return TRUE;
}
 
static void
regs_hash_destroy(struct cso_hash *hash)
{
struct cso_hash_iter iter = cso_hash_first_node(hash);
while (!cso_hash_iter_is_null(iter)) {
scan_register *reg = (scan_register *)cso_hash_iter_data(iter);
iter = cso_hash_erase(hash, iter);
assert(reg->file < TGSI_FILE_COUNT);
FREE(reg);
}
cso_hash_delete(hash);
}
 
boolean
tgsi_sanity_check(
const struct tgsi_token *tokens )
{
struct sanity_check_ctx ctx;
 
ctx.iter.prolog = NULL;
ctx.iter.iterate_instruction = iter_instruction;
ctx.iter.iterate_declaration = iter_declaration;
ctx.iter.iterate_immediate = iter_immediate;
ctx.iter.iterate_property = iter_property;
ctx.iter.epilog = epilog;
 
ctx.regs_decl = cso_hash_create();
ctx.regs_used = cso_hash_create();
ctx.regs_ind_used = cso_hash_create();
 
ctx.num_imms = 0;
ctx.num_instructions = 0;
ctx.index_of_END = ~0;
 
ctx.errors = 0;
ctx.warnings = 0;
ctx.implied_array_size = 0;
ctx.print = debug_get_option_print_sanity();
 
if (!tgsi_iterate_shader( tokens, &ctx.iter ))
return FALSE;
 
regs_hash_destroy(ctx.regs_decl);
regs_hash_destroy(ctx.regs_used);
regs_hash_destroy(ctx.regs_ind_used);
return ctx.errors == 0;
}
/drivers/video/Gallium/auxiliary/tgsi/tgsi_sanity.h
0,0 → 1,52
/**************************************************************************
*
* 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.
*
**************************************************************************/
 
#ifndef TGSI_SANITY_H
#define TGSI_SANITY_H
 
#if defined __cplusplus
extern "C" {
#endif
 
#include "pipe/p_compiler.h"
 
struct tgsi_token;
 
/* Check the given token stream for errors and common mistakes.
* Diagnostic messages are printed out to the debug output, and is
* controlled by the debug option TGSI_PRINT_SANITY (default false).
* Returns TRUE if there are no errors, even though there could be some warnings.
*/
boolean
tgsi_sanity_check(
const struct tgsi_token *tokens );
 
#if defined __cplusplus
}
#endif
 
#endif /* TGSI_SANITY_H */
/drivers/video/Gallium/auxiliary/tgsi/tgsi_scan.c
0,0 → 1,380
/**************************************************************************
*
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
* Copyright 2008 VMware, Inc. 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.
*
**************************************************************************/
 
/**
* TGSI program scan utility.
* Used to determine which registers and instructions are used by a shader.
*
* Authors: Brian Paul
*/
 
 
#include "util/u_debug.h"
#include "util/u_math.h"
#include "util/u_prim.h"
#include "tgsi/tgsi_parse.h"
#include "tgsi/tgsi_util.h"
#include "tgsi/tgsi_scan.h"
 
 
 
 
/**
* Scan the given TGSI shader to collect information such as number of
* registers used, special instructions used, etc.
* \return info the result of the scan
*/
void
tgsi_scan_shader(const struct tgsi_token *tokens,
struct tgsi_shader_info *info)
{
uint procType, i;
struct tgsi_parse_context parse;
 
memset(info, 0, sizeof(*info));
for (i = 0; i < TGSI_FILE_COUNT; i++)
info->file_max[i] = -1;
 
/**
** Setup to begin parsing input shader
**/
if (tgsi_parse_init( &parse, tokens ) != TGSI_PARSE_OK) {
debug_printf("tgsi_parse_init() failed in tgsi_scan_shader()!\n");
return;
}
procType = parse.FullHeader.Processor.Processor;
assert(procType == TGSI_PROCESSOR_FRAGMENT ||
procType == TGSI_PROCESSOR_VERTEX ||
procType == TGSI_PROCESSOR_GEOMETRY ||
procType == TGSI_PROCESSOR_COMPUTE);
info->processor = procType;
 
 
/**
** Loop over incoming program tokens/instructions
*/
while( !tgsi_parse_end_of_tokens( &parse ) ) {
 
info->num_tokens++;
 
tgsi_parse_token( &parse );
 
switch( parse.FullToken.Token.Type ) {
case TGSI_TOKEN_TYPE_INSTRUCTION:
{
const struct tgsi_full_instruction *fullinst
= &parse.FullToken.FullInstruction;
uint i;
 
assert(fullinst->Instruction.Opcode < TGSI_OPCODE_LAST);
info->opcode_count[fullinst->Instruction.Opcode]++;
 
for (i = 0; i < fullinst->Instruction.NumSrcRegs; i++) {
const struct tgsi_full_src_register *src =
&fullinst->Src[i];
int ind = src->Register.Index;
 
/* Mark which inputs are effectively used */
if (src->Register.File == TGSI_FILE_INPUT) {
unsigned usage_mask;
usage_mask = tgsi_util_get_inst_usage_mask(fullinst, i);
if (src->Register.Indirect) {
for (ind = 0; ind < info->num_inputs; ++ind) {
info->input_usage_mask[ind] |= usage_mask;
}
} else {
assert(ind >= 0);
assert(ind < PIPE_MAX_SHADER_INPUTS);
info->input_usage_mask[ind] |= usage_mask;
}
 
if (procType == TGSI_PROCESSOR_FRAGMENT &&
src->Register.File == TGSI_FILE_INPUT &&
info->reads_position &&
src->Register.Index == 0 &&
(src->Register.SwizzleX == TGSI_SWIZZLE_Z ||
src->Register.SwizzleY == TGSI_SWIZZLE_Z ||
src->Register.SwizzleZ == TGSI_SWIZZLE_Z ||
src->Register.SwizzleW == TGSI_SWIZZLE_Z)) {
info->reads_z = TRUE;
}
}
 
/* check for indirect register reads */
if (src->Register.Indirect) {
info->indirect_files |= (1 << src->Register.File);
}
}
 
/* check for indirect register writes */
for (i = 0; i < fullinst->Instruction.NumDstRegs; i++) {
const struct tgsi_full_dst_register *dst = &fullinst->Dst[i];
if (dst->Register.Indirect) {
info->indirect_files |= (1 << dst->Register.File);
}
}
 
info->num_instructions++;
}
break;
 
case TGSI_TOKEN_TYPE_DECLARATION:
{
const struct tgsi_full_declaration *fulldecl
= &parse.FullToken.FullDeclaration;
const uint file = fulldecl->Declaration.File;
uint reg;
for (reg = fulldecl->Range.First;
reg <= fulldecl->Range.Last;
reg++) {
 
/* only first 32 regs will appear in this bitfield */
info->file_mask[file] |= (1 << reg);
info->file_count[file]++;
info->file_max[file] = MAX2(info->file_max[file], (int)reg);
 
if (file == TGSI_FILE_INPUT) {
info->input_semantic_name[reg] = (ubyte)fulldecl->Semantic.Name;
info->input_semantic_index[reg] = (ubyte)fulldecl->Semantic.Index;
info->input_interpolate[reg] = (ubyte)fulldecl->Interp.Interpolate;
info->input_centroid[reg] = (ubyte)fulldecl->Interp.Centroid;
info->input_cylindrical_wrap[reg] = (ubyte)fulldecl->Interp.CylindricalWrap;
info->num_inputs++;
 
if (procType == TGSI_PROCESSOR_FRAGMENT &&
fulldecl->Semantic.Name == TGSI_SEMANTIC_POSITION)
info->reads_position = TRUE;
}
else if (file == TGSI_FILE_SYSTEM_VALUE) {
unsigned index = fulldecl->Range.First;
unsigned semName = fulldecl->Semantic.Name;
 
info->system_value_semantic_name[index] = semName;
info->num_system_values = MAX2(info->num_system_values,
index + 1);
 
/*
info->system_value_semantic_name[info->num_system_values++] =
fulldecl->Semantic.Name;
*/
 
if (fulldecl->Semantic.Name == TGSI_SEMANTIC_INSTANCEID) {
info->uses_instanceid = TRUE;
}
else if (fulldecl->Semantic.Name == TGSI_SEMANTIC_VERTEXID) {
info->uses_vertexid = TRUE;
} else if (fulldecl->Semantic.Name == TGSI_SEMANTIC_PRIMID) {
info->uses_primid = TRUE;
}
}
else if (file == TGSI_FILE_OUTPUT) {
info->output_semantic_name[reg] = (ubyte)fulldecl->Semantic.Name;
info->output_semantic_index[reg] = (ubyte)fulldecl->Semantic.Index;
info->num_outputs++;
 
if ((procType == TGSI_PROCESSOR_VERTEX || procType == TGSI_PROCESSOR_GEOMETRY) &&
fulldecl->Semantic.Name == TGSI_SEMANTIC_CLIPDIST) {
info->num_written_clipdistance += util_bitcount(fulldecl->Declaration.UsageMask);
}
if ((procType == TGSI_PROCESSOR_VERTEX || procType == TGSI_PROCESSOR_GEOMETRY) &&
fulldecl->Semantic.Name == TGSI_SEMANTIC_CULLDIST) {
info->num_written_culldistance += util_bitcount(fulldecl->Declaration.UsageMask);
}
/* extra info for special outputs */
if (procType == TGSI_PROCESSOR_FRAGMENT &&
fulldecl->Semantic.Name == TGSI_SEMANTIC_POSITION)
info->writes_z = TRUE;
if (procType == TGSI_PROCESSOR_FRAGMENT &&
fulldecl->Semantic.Name == TGSI_SEMANTIC_STENCIL)
info->writes_stencil = TRUE;
if (procType == TGSI_PROCESSOR_VERTEX &&
fulldecl->Semantic.Name == TGSI_SEMANTIC_EDGEFLAG) {
info->writes_edgeflag = TRUE;
}
 
if (procType == TGSI_PROCESSOR_GEOMETRY &&
fulldecl->Semantic.Name ==
TGSI_SEMANTIC_VIEWPORT_INDEX) {
info->writes_viewport_index = TRUE;
}
if (procType == TGSI_PROCESSOR_GEOMETRY &&
fulldecl->Semantic.Name ==
TGSI_SEMANTIC_LAYER) {
info->writes_layer = TRUE;
}
}
 
}
}
break;
 
case TGSI_TOKEN_TYPE_IMMEDIATE:
{
uint reg = info->immediate_count++;
uint file = TGSI_FILE_IMMEDIATE;
 
info->file_mask[file] |= (1 << reg);
info->file_count[file]++;
info->file_max[file] = MAX2(info->file_max[file], (int)reg);
}
break;
 
case TGSI_TOKEN_TYPE_PROPERTY:
{
const struct tgsi_full_property *fullprop
= &parse.FullToken.FullProperty;
 
info->properties[info->num_properties].name =
fullprop->Property.PropertyName;
memcpy(info->properties[info->num_properties].data,
fullprop->u, 8 * sizeof(unsigned));;
 
++info->num_properties;
}
break;
 
default:
assert( 0 );
}
}
 
info->uses_kill = (info->opcode_count[TGSI_OPCODE_KIL] ||
info->opcode_count[TGSI_OPCODE_KILP]);
 
/* extract simple properties */
for (i = 0; i < info->num_properties; ++i) {
switch (info->properties[i].name) {
case TGSI_PROPERTY_FS_COORD_ORIGIN:
info->origin_lower_left = info->properties[i].data[0];
break;
case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER:
info->pixel_center_integer = info->properties[i].data[0];
break;
case TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS:
info->color0_writes_all_cbufs = info->properties[i].data[0];
break;
case TGSI_PROPERTY_GS_INPUT_PRIM:
/* The dimensions of the IN decleration in geometry shader have
* to be deduced from the type of the input primitive.
*/
if (procType == TGSI_PROCESSOR_GEOMETRY) {
unsigned input_primitive = info->properties[i].data[0];
int num_verts = u_vertices_per_prim(input_primitive);
unsigned j;
info->file_count[TGSI_FILE_INPUT] = num_verts;
info->file_max[TGSI_FILE_INPUT] =
MAX2(info->file_max[TGSI_FILE_INPUT], num_verts - 1);
for (j = 0; j < num_verts; ++j) {
info->file_mask[TGSI_FILE_INPUT] |= (1 << j);
}
}
break;
default:
;
}
}
 
tgsi_parse_free (&parse);
}
 
 
 
/**
* Check if the given shader is a "passthrough" shader consisting of only
* MOV instructions of the form: MOV OUT[n], IN[n]
*
*/
boolean
tgsi_is_passthrough_shader(const struct tgsi_token *tokens)
{
struct tgsi_parse_context parse;
 
/**
** Setup to begin parsing input shader
**/
if (tgsi_parse_init(&parse, tokens) != TGSI_PARSE_OK) {
debug_printf("tgsi_parse_init() failed in tgsi_is_passthrough_shader()!\n");
return FALSE;
}
 
/**
** Loop over incoming program tokens/instructions
*/
while (!tgsi_parse_end_of_tokens(&parse)) {
 
tgsi_parse_token(&parse);
 
switch (parse.FullToken.Token.Type) {
case TGSI_TOKEN_TYPE_INSTRUCTION:
{
struct tgsi_full_instruction *fullinst =
&parse.FullToken.FullInstruction;
const struct tgsi_full_src_register *src =
&fullinst->Src[0];
const struct tgsi_full_dst_register *dst =
&fullinst->Dst[0];
 
/* Do a whole bunch of checks for a simple move */
if (fullinst->Instruction.Opcode != TGSI_OPCODE_MOV ||
(src->Register.File != TGSI_FILE_INPUT &&
src->Register.File != TGSI_FILE_SYSTEM_VALUE) ||
dst->Register.File != TGSI_FILE_OUTPUT ||
src->Register.Index != dst->Register.Index ||
 
src->Register.Negate ||
src->Register.Absolute ||
 
src->Register.SwizzleX != TGSI_SWIZZLE_X ||
src->Register.SwizzleY != TGSI_SWIZZLE_Y ||
src->Register.SwizzleZ != TGSI_SWIZZLE_Z ||
src->Register.SwizzleW != TGSI_SWIZZLE_W ||
 
dst->Register.WriteMask != TGSI_WRITEMASK_XYZW)
{
tgsi_parse_free(&parse);
return FALSE;
}
}
break;
 
case TGSI_TOKEN_TYPE_DECLARATION:
/* fall-through */
case TGSI_TOKEN_TYPE_IMMEDIATE:
/* fall-through */
case TGSI_TOKEN_TYPE_PROPERTY:
/* fall-through */
default:
; /* no-op */
}
}
 
tgsi_parse_free(&parse);
 
/* if we get here, it's a pass-through shader */
return TRUE;
}
/drivers/video/Gallium/auxiliary/tgsi/tgsi_scan.h
0,0 → 1,107
/**************************************************************************
*
* 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.
*
**************************************************************************/
 
#ifndef TGSI_SCAN_H
#define TGSI_SCAN_H
 
 
#include "pipe/p_compiler.h"
#include "pipe/p_state.h"
#include "pipe/p_shader_tokens.h"
 
/**
* Shader summary info
*/
struct tgsi_shader_info
{
uint num_tokens;
 
ubyte num_inputs;
ubyte num_outputs;
ubyte input_semantic_name[PIPE_MAX_SHADER_INPUTS]; /**< TGSI_SEMANTIC_x */
ubyte input_semantic_index[PIPE_MAX_SHADER_INPUTS];
ubyte input_interpolate[PIPE_MAX_SHADER_INPUTS];
ubyte input_centroid[PIPE_MAX_SHADER_INPUTS];
ubyte input_usage_mask[PIPE_MAX_SHADER_INPUTS];
ubyte input_cylindrical_wrap[PIPE_MAX_SHADER_INPUTS];
ubyte output_semantic_name[PIPE_MAX_SHADER_OUTPUTS]; /**< TGSI_SEMANTIC_x */
ubyte output_semantic_index[PIPE_MAX_SHADER_OUTPUTS];
 
ubyte num_system_values;
ubyte system_value_semantic_name[PIPE_MAX_SHADER_INPUTS];
 
ubyte processor;
 
uint file_mask[TGSI_FILE_COUNT]; /**< bitmask of declared registers */
uint file_count[TGSI_FILE_COUNT]; /**< number of declared registers */
int file_max[TGSI_FILE_COUNT]; /**< highest index of declared registers */
 
uint immediate_count; /**< number of immediates declared */
uint num_instructions;
 
uint opcode_count[TGSI_OPCODE_LAST]; /**< opcode histogram */
 
boolean reads_position; /**< does fragment shader read position? */
boolean reads_z; /**< does fragment shader read depth? */
boolean writes_z; /**< does fragment shader write Z value? */
boolean writes_stencil; /**< does fragment shader write stencil value? */
boolean writes_edgeflag; /**< vertex shader outputs edgeflag */
boolean uses_kill; /**< KIL or KILP instruction used? */
boolean uses_instanceid;
boolean uses_vertexid;
boolean uses_primid;
boolean origin_lower_left;
boolean pixel_center_integer;
boolean color0_writes_all_cbufs;
boolean writes_viewport_index;
boolean writes_layer;
 
unsigned num_written_culldistance;
unsigned num_written_clipdistance;
/**
* Bitmask indicating which register files are accessed with
* indirect addressing. The bits are (1 << TGSI_FILE_x), etc.
*/
unsigned indirect_files;
 
struct {
unsigned name;
unsigned data[8];
} properties[TGSI_PROPERTY_COUNT];
uint num_properties;
};
 
extern void
tgsi_scan_shader(const struct tgsi_token *tokens,
struct tgsi_shader_info *info);
 
 
extern boolean
tgsi_is_passthrough_shader(const struct tgsi_token *tokens);
 
 
#endif /* TGSI_SCAN_H */
/drivers/video/Gallium/auxiliary/tgsi/tgsi_strings.c
0,0 → 1,201
/**************************************************************************
*
* Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* Copyright 2012 VMware, Inc.
* 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 THE AUTHORS 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.
*
**************************************************************************/
 
 
#include "pipe/p_compiler.h"
#include "util/u_memory.h"
#include "tgsi_strings.h"
 
 
const char *tgsi_processor_type_names[4] =
{
"FRAG",
"VERT",
"GEOM",
"COMP"
};
 
static const char *tgsi_file_names[] =
{
"NULL",
"CONST",
"IN",
"OUT",
"TEMP",
"SAMP",
"ADDR",
"IMM",
"PRED",
"SV",
"RES",
"SVIEW"
};
 
const char *tgsi_semantic_names[TGSI_SEMANTIC_COUNT] =
{
"POSITION",
"COLOR",
"BCOLOR",
"FOG",
"PSIZE",
"GENERIC",
"NORMAL",
"FACE",
"EDGEFLAG",
"PRIM_ID",
"INSTANCEID",
"VERTEXID",
"STENCIL",
"CLIPDIST",
"CLIPVERTEX",
"GRID_SIZE",
"BLOCK_ID",
"BLOCK_SIZE",
"THREAD_ID",
"TEXCOORD",
"PCOORD",
"VIEWPORT_INDEX",
"LAYER",
"CULLDIST"
};
 
const char *tgsi_texture_names[TGSI_TEXTURE_COUNT] =
{
"BUFFER",
"1D",
"2D",
"3D",
"CUBE",
"RECT",
"SHADOW1D",
"SHADOW2D",
"SHADOWRECT",
"1D_ARRAY",
"2D_ARRAY",
"SHADOW1D_ARRAY",
"SHADOW2D_ARRAY",
"SHADOWCUBE",
"2D_MSAA",
"2D_ARRAY_MSAA",
"CUBEARRAY",
"SHADOWCUBEARRAY",
"UNKNOWN",
};
 
const char *tgsi_property_names[TGSI_PROPERTY_COUNT] =
{
"GS_INPUT_PRIMITIVE",
"GS_OUTPUT_PRIMITIVE",
"GS_MAX_OUTPUT_VERTICES",
"FS_COORD_ORIGIN",
"FS_COORD_PIXEL_CENTER",
"FS_COLOR0_WRITES_ALL_CBUFS",
"FS_DEPTH_LAYOUT",
"VS_PROHIBIT_UCPS"
};
 
const char *tgsi_type_names[5] =
{
"UNORM",
"SNORM",
"SINT",
"UINT",
"FLOAT"
};
 
const char *tgsi_interpolate_names[TGSI_INTERPOLATE_COUNT] =
{
"CONSTANT",
"LINEAR",
"PERSPECTIVE",
"COLOR"
};
 
const char *tgsi_primitive_names[PIPE_PRIM_MAX] =
{
"POINTS",
"LINES",
"LINE_LOOP",
"LINE_STRIP",
"TRIANGLES",
"TRIANGLE_STRIP",
"TRIANGLE_FAN",
"QUADS",
"QUAD_STRIP",
"POLYGON",
"LINES_ADJACENCY",
"LINE_STRIP_ADJACENCY",
"TRIANGLES_ADJACENCY",
"TRIANGLE_STRIP_ADJACENCY"
};
 
const char *tgsi_fs_coord_origin_names[2] =
{
"UPPER_LEFT",
"LOWER_LEFT"
};
 
const char *tgsi_fs_coord_pixel_center_names[2] =
{
"HALF_INTEGER",
"INTEGER"
};
 
const char *tgsi_immediate_type_names[3] =
{
"FLT32",
"UINT32",
"INT32"
};
 
 
static INLINE void
tgsi_strings_check(void)
{
STATIC_ASSERT(Elements(tgsi_semantic_names) == TGSI_SEMANTIC_COUNT);
STATIC_ASSERT(Elements(tgsi_texture_names) == TGSI_TEXTURE_COUNT);
STATIC_ASSERT(Elements(tgsi_property_names) == TGSI_PROPERTY_COUNT);
STATIC_ASSERT(Elements(tgsi_primitive_names) == PIPE_PRIM_MAX);
STATIC_ASSERT(Elements(tgsi_interpolate_names) == TGSI_INTERPOLATE_COUNT);
(void) tgsi_processor_type_names;
(void) tgsi_type_names;
(void) tgsi_immediate_type_names;
(void) tgsi_fs_coord_origin_names;
(void) tgsi_fs_coord_pixel_center_names;
}
 
 
const char *
tgsi_file_name(unsigned file)
{
STATIC_ASSERT(Elements(tgsi_file_names) == TGSI_FILE_COUNT);
if (file < Elements(tgsi_file_names))
return tgsi_file_names[file];
else
return "invalid file";
}
/drivers/video/Gallium/auxiliary/tgsi/tgsi_strings.h
0,0 → 1,71
/**************************************************************************
*
* Copyright 2007-2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* Copyright 2012 VMware, Inc.
* 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 THE AUTHORS 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.
*
**************************************************************************/
 
#ifndef TGSI_STRINGS_H
#define TGSI_STRINGS_H
 
#include "pipe/p_shader_tokens.h"
#include "pipe/p_state.h"
 
 
#if defined __cplusplus
extern "C" {
#endif
 
 
extern const char *tgsi_processor_type_names[4];
 
extern const char *tgsi_semantic_names[TGSI_SEMANTIC_COUNT];
 
extern const char *tgsi_texture_names[TGSI_TEXTURE_COUNT];
 
extern const char *tgsi_property_names[TGSI_PROPERTY_COUNT];
 
extern const char *tgsi_type_names[5];
 
extern const char *tgsi_interpolate_names[TGSI_INTERPOLATE_COUNT];
 
extern const char *tgsi_primitive_names[PIPE_PRIM_MAX];
 
extern const char *tgsi_fs_coord_origin_names[2];
 
extern const char *tgsi_fs_coord_pixel_center_names[2];
 
extern const char *tgsi_immediate_type_names[3];
 
 
const char *
tgsi_file_name(unsigned file);
 
 
#if defined __cplusplus
}
#endif
 
 
#endif /* TGSI_STRINGS_H */
/drivers/video/Gallium/auxiliary/tgsi/tgsi_text.c
0,0 → 1,1591
/**************************************************************************
*
* 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.
*
**************************************************************************/
 
#include "util/u_debug.h"
#include "util/u_memory.h"
#include "util/u_prim.h"
#include "pipe/p_defines.h"
#include "util/u_inlines.h"
#include "tgsi_text.h"
#include "tgsi_build.h"
#include "tgsi_info.h"
#include "tgsi_parse.h"
#include "tgsi_sanity.h"
#include "tgsi_strings.h"
#include "tgsi_util.h"
#include "tgsi_dump.h"
 
static boolean is_alpha_underscore( const char *cur )
{
return
(*cur >= 'a' && *cur <= 'z') ||
(*cur >= 'A' && *cur <= 'Z') ||
*cur == '_';
}
 
static boolean is_digit( const char *cur )
{
return *cur >= '0' && *cur <= '9';
}
 
static boolean is_digit_alpha_underscore( const char *cur )
{
return is_digit( cur ) || is_alpha_underscore( cur );
}
 
static char uprcase( char c )
{
if (c >= 'a' && c <= 'z')
return c + 'A' - 'a';
return c;
}
 
/*
* Ignore case of str1 and assume str1 is already uppercase.
* Return TRUE iff str1 and str2 are equal.
*/
static int
streq_nocase_uprcase(const char *str1,
const char *str2)
{
while (*str1 && *str2) {
if (*str1 != uprcase(*str2))
return FALSE;
str1++;
str2++;
}
return *str1 == 0 && *str2 == 0;
}
 
/* Return TRUE if both strings match.
* The second string is terminated by zero.
* The pointer to the first string is moved at end of the read word
* on success.
*/
static boolean str_match_no_case( const char **pcur, const char *str )
{
const char *cur = *pcur;
 
while (*str != '\0' && *str == uprcase( *cur )) {
str++;
cur++;
}
if (*str == '\0') {
*pcur = cur;
return TRUE;
}
return FALSE;
}
 
/* Return TRUE if both strings match.
* The first string is be terminated by a non-digit non-letter non-underscore
* character, the second string is terminated by zero.
* The pointer to the first string is moved at end of the read word
* on success.
*/
static boolean str_match_nocase_whole( const char **pcur, const char *str )
{
const char *cur = *pcur;
 
if (str_match_no_case(&cur, str) &&
!is_digit_alpha_underscore(cur)) {
*pcur = cur;
return TRUE;
}
return FALSE;
}
 
/* Eat zero or more whitespaces.
*/
static void eat_opt_white( const char **pcur )
{
while (**pcur == ' ' || **pcur == '\t' || **pcur == '\n')
(*pcur)++;
}
 
/* Eat one or more whitespaces.
* Return TRUE if at least one whitespace eaten.
*/
static boolean eat_white( const char **pcur )
{
const char *cur = *pcur;
 
eat_opt_white( pcur );
return *pcur > cur;
}
 
/* Parse unsigned integer.
* No checks for overflow.
*/
static boolean parse_uint( const char **pcur, uint *val )
{
const char *cur = *pcur;
 
if (is_digit( cur )) {
*val = *cur++ - '0';
while (is_digit( cur ))
*val = *val * 10 + *cur++ - '0';
*pcur = cur;
return TRUE;
}
return FALSE;
}
 
static boolean parse_int( const char **pcur, int *val )
{
const char *cur = *pcur;
int sign = (*cur == '-' ? -1 : 1);
 
if (*cur == '+' || *cur == '-')
cur++;
 
if (parse_uint(&cur, (uint *)val)) {
*val *= sign;
*pcur = cur;
return TRUE;
}
 
return FALSE;
}
 
static boolean parse_identifier( const char **pcur, char *ret )
{
const char *cur = *pcur;
int i = 0;
if (is_alpha_underscore( cur )) {
ret[i++] = *cur++;
while (is_alpha_underscore( cur ) || is_digit( cur ))
ret[i++] = *cur++;
ret[i++] = '\0';
*pcur = cur;
return TRUE;
}
return FALSE;
}
 
/* Parse floating point.
*/
static boolean parse_float( const char **pcur, float *val )
{
const char *cur = *pcur;
boolean integral_part = FALSE;
boolean fractional_part = FALSE;
 
*val = (float) atof( cur );
 
if (*cur == '-' || *cur == '+')
cur++;
if (is_digit( cur )) {
cur++;
integral_part = TRUE;
while (is_digit( cur ))
cur++;
}
if (*cur == '.') {
cur++;
if (is_digit( cur )) {
cur++;
fractional_part = TRUE;
while (is_digit( cur ))
cur++;
}
}
if (!integral_part && !fractional_part)
return FALSE;
if (uprcase( *cur ) == 'E') {
cur++;
if (*cur == '-' || *cur == '+')
cur++;
if (is_digit( cur )) {
cur++;
while (is_digit( cur ))
cur++;
}
else
return FALSE;
}
*pcur = cur;
return TRUE;
}
 
struct translate_ctx
{
const char *text;
const char *cur;
struct tgsi_token *tokens;
struct tgsi_token *tokens_cur;
struct tgsi_token *tokens_end;
struct tgsi_header *header;
unsigned processor : 4;
int implied_array_size : 5;
unsigned num_immediates;
};
 
static void report_error( struct translate_ctx *ctx, const char *msg )
{
int line = 1;
int column = 1;
const char *itr = ctx->text;
 
while (itr != ctx->cur) {
if (*itr == '\n') {
column = 1;
++line;
}
++column;
++itr;
}
 
debug_printf( "\nTGSI asm error: %s [%d : %d] \n", msg, line, column );
}
 
/* Parse shader header.
* Return TRUE for one of the following headers.
* FRAG
* GEOM
* VERT
*/
static boolean parse_header( struct translate_ctx *ctx )
{
uint processor;
 
if (str_match_nocase_whole( &ctx->cur, "FRAG" ))
processor = TGSI_PROCESSOR_FRAGMENT;
else if (str_match_nocase_whole( &ctx->cur, "VERT" ))
processor = TGSI_PROCESSOR_VERTEX;
else if (str_match_nocase_whole( &ctx->cur, "GEOM" ))
processor = TGSI_PROCESSOR_GEOMETRY;
else if (str_match_nocase_whole( &ctx->cur, "COMP" ))
processor = TGSI_PROCESSOR_COMPUTE;
else {
report_error( ctx, "Unknown header" );
return FALSE;
}
 
if (ctx->tokens_cur >= ctx->tokens_end)
return FALSE;
ctx->header = (struct tgsi_header *) ctx->tokens_cur++;
*ctx->header = tgsi_build_header();
 
if (ctx->tokens_cur >= ctx->tokens_end)
return FALSE;
*(struct tgsi_processor *) ctx->tokens_cur++ = tgsi_build_processor( processor, ctx->header );
ctx->processor = processor;
 
return TRUE;
}
 
static boolean parse_label( struct translate_ctx *ctx, uint *val )
{
const char *cur = ctx->cur;
 
if (parse_uint( &cur, val )) {
eat_opt_white( &cur );
if (*cur == ':') {
cur++;
ctx->cur = cur;
return TRUE;
}
}
return FALSE;
}
 
static boolean
parse_file( const char **pcur, uint *file )
{
uint i;
 
for (i = 0; i < TGSI_FILE_COUNT; i++) {
const char *cur = *pcur;
 
if (str_match_nocase_whole( &cur, tgsi_file_name(i) )) {
*pcur = cur;
*file = i;
return TRUE;
}
}
return FALSE;
}
 
static boolean
parse_opt_writemask(
struct translate_ctx *ctx,
uint *writemask )
{
const char *cur;
 
cur = ctx->cur;
eat_opt_white( &cur );
if (*cur == '.') {
cur++;
*writemask = TGSI_WRITEMASK_NONE;
eat_opt_white( &cur );
if (uprcase( *cur ) == 'X') {
cur++;
*writemask |= TGSI_WRITEMASK_X;
}
if (uprcase( *cur ) == 'Y') {
cur++;
*writemask |= TGSI_WRITEMASK_Y;
}
if (uprcase( *cur ) == 'Z') {
cur++;
*writemask |= TGSI_WRITEMASK_Z;
}
if (uprcase( *cur ) == 'W') {
cur++;
*writemask |= TGSI_WRITEMASK_W;
}
 
if (*writemask == TGSI_WRITEMASK_NONE) {
report_error( ctx, "Writemask expected" );
return FALSE;
}
 
ctx->cur = cur;
}
else {
*writemask = TGSI_WRITEMASK_XYZW;
}
return TRUE;
}
 
 
/* <register_file_bracket> ::= <file> `['
*/
static boolean
parse_register_file_bracket(
struct translate_ctx *ctx,
uint *file )
{
if (!parse_file( &ctx->cur, file )) {
report_error( ctx, "Unknown register file" );
return FALSE;
}
eat_opt_white( &ctx->cur );
if (*ctx->cur != '[') {
report_error( ctx, "Expected `['" );
return FALSE;
}
ctx->cur++;
return TRUE;
}
 
/* <register_file_bracket_index> ::= <register_file_bracket> <uint>
*/
static boolean
parse_register_file_bracket_index(
struct translate_ctx *ctx,
uint *file,
int *index )
{
uint uindex;
 
if (!parse_register_file_bracket( ctx, file ))
return FALSE;
eat_opt_white( &ctx->cur );
if (!parse_uint( &ctx->cur, &uindex )) {
report_error( ctx, "Expected literal unsigned integer" );
return FALSE;
}
*index = (int) uindex;
return TRUE;
}
 
/* Parse simple 1d register operand.
* <register_dst> ::= <register_file_bracket_index> `]'
*/
static boolean
parse_register_1d(struct translate_ctx *ctx,
uint *file,
int *index )
{
if (!parse_register_file_bracket_index( ctx, file, index ))
return FALSE;
eat_opt_white( &ctx->cur );
if (*ctx->cur != ']') {
report_error( ctx, "Expected `]'" );
return FALSE;
}
ctx->cur++;
return TRUE;
}
 
struct parsed_bracket {
int index;
 
uint ind_file;
int ind_index;
uint ind_comp;
uint ind_array;
};
 
 
static boolean
parse_register_bracket(
struct translate_ctx *ctx,
struct parsed_bracket *brackets)
{
const char *cur;
uint uindex;
 
memset(brackets, 0, sizeof(struct parsed_bracket));
 
eat_opt_white( &ctx->cur );
 
cur = ctx->cur;
if (parse_file( &cur, &brackets->ind_file )) {
if (!parse_register_1d( ctx, &brackets->ind_file,
&brackets->ind_index ))
return FALSE;
eat_opt_white( &ctx->cur );
 
if (*ctx->cur == '.') {
ctx->cur++;
eat_opt_white(&ctx->cur);
 
switch (uprcase(*ctx->cur)) {
case 'X':
brackets->ind_comp = TGSI_SWIZZLE_X;
break;
case 'Y':
brackets->ind_comp = TGSI_SWIZZLE_Y;
break;
case 'Z':
brackets->ind_comp = TGSI_SWIZZLE_Z;
break;
case 'W':
brackets->ind_comp = TGSI_SWIZZLE_W;
break;
default:
report_error(ctx, "Expected indirect register swizzle component `x', `y', `z' or `w'");
return FALSE;
}
ctx->cur++;
eat_opt_white(&ctx->cur);
}
 
if (*ctx->cur == '+' || *ctx->cur == '-')
parse_int( &ctx->cur, &brackets->index );
else
brackets->index = 0;
}
else {
if (!parse_uint( &ctx->cur, &uindex )) {
report_error( ctx, "Expected literal unsigned integer" );
return FALSE;
}
brackets->index = (int) uindex;
brackets->ind_file = TGSI_FILE_NULL;
brackets->ind_index = 0;
}
eat_opt_white( &ctx->cur );
if (*ctx->cur != ']') {
report_error( ctx, "Expected `]'" );
return FALSE;
}
ctx->cur++;
if (*ctx->cur == '(') {
ctx->cur++;
eat_opt_white( &ctx->cur );
if (!parse_uint( &ctx->cur, &brackets->ind_array )) {
report_error( ctx, "Expected literal unsigned integer" );
return FALSE;
}
eat_opt_white( &ctx->cur );
if (*ctx->cur != ')') {
report_error( ctx, "Expected `)'" );
return FALSE;
}
ctx->cur++;
}
return TRUE;
}
 
static boolean
parse_opt_register_src_bracket(
struct translate_ctx *ctx,
struct parsed_bracket *brackets,
int *parsed_brackets)
{
const char *cur = ctx->cur;
 
*parsed_brackets = 0;
 
eat_opt_white( &cur );
if (cur[0] == '[') {
++cur;
ctx->cur = cur;
 
if (!parse_register_bracket(ctx, brackets))
return FALSE;
 
*parsed_brackets = 1;
}
 
return TRUE;
}
 
 
/* Parse source register operand.
* <register_src> ::= <register_file_bracket_index> `]' |
* <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `]' |
* <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `+' <uint> `]' |
* <register_file_bracket> <register_dst> [`.' (`x' | `y' | `z' | `w')] `-' <uint> `]'
*/
static boolean
parse_register_src(
struct translate_ctx *ctx,
uint *file,
struct parsed_bracket *brackets)
{
brackets->ind_comp = TGSI_SWIZZLE_X;
if (!parse_register_file_bracket( ctx, file ))
return FALSE;
if (!parse_register_bracket( ctx, brackets ))
return FALSE;
 
return TRUE;
}
 
struct parsed_dcl_bracket {
uint first;
uint last;
};
 
static boolean
parse_register_dcl_bracket(
struct translate_ctx *ctx,
struct parsed_dcl_bracket *bracket)
{
uint uindex;
memset(bracket, 0, sizeof(struct parsed_dcl_bracket));
 
eat_opt_white( &ctx->cur );
 
if (!parse_uint( &ctx->cur, &uindex )) {
/* it can be an empty bracket [] which means its range
* is from 0 to some implied size */
if (ctx->cur[0] == ']' && ctx->implied_array_size != 0) {
bracket->first = 0;
bracket->last = ctx->implied_array_size - 1;
goto cleanup;
}
report_error( ctx, "Expected literal unsigned integer" );
return FALSE;
}
bracket->first = uindex;
 
eat_opt_white( &ctx->cur );
 
if (ctx->cur[0] == '.' && ctx->cur[1] == '.') {
uint uindex;
 
ctx->cur += 2;
eat_opt_white( &ctx->cur );
if (!parse_uint( &ctx->cur, &uindex )) {
report_error( ctx, "Expected literal integer" );
return FALSE;
}
bracket->last = (int) uindex;
eat_opt_white( &ctx->cur );
}
else {
bracket->last = bracket->first;
}
 
cleanup:
if (*ctx->cur != ']') {
report_error( ctx, "Expected `]' or `..'" );
return FALSE;
}
ctx->cur++;
return TRUE;
}
 
/* Parse register declaration.
* <register_dcl> ::= <register_file_bracket_index> `]' |
* <register_file_bracket_index> `..' <index> `]'
*/
static boolean
parse_register_dcl(
struct translate_ctx *ctx,
uint *file,
struct parsed_dcl_bracket *brackets,
int *num_brackets)
{
const char *cur;
 
*num_brackets = 0;
 
if (!parse_register_file_bracket( ctx, file ))
return FALSE;
if (!parse_register_dcl_bracket( ctx, &brackets[0] ))
return FALSE;
 
*num_brackets = 1;
 
cur = ctx->cur;
eat_opt_white( &cur );
 
if (cur[0] == '[') {
++cur;
ctx->cur = cur;
if (!parse_register_dcl_bracket( ctx, &brackets[1] ))
return FALSE;
/* for geometry shader we don't really care about
* the first brackets it's always the size of the
* input primitive. so we want to declare just
* the index relevant to the semantics which is in
* the second bracket */
if (ctx->processor == TGSI_PROCESSOR_GEOMETRY && *file == TGSI_FILE_INPUT) {
brackets[0] = brackets[1];
*num_brackets = 1;
} else {
*num_brackets = 2;
}
}
 
return TRUE;
}
 
 
/* Parse destination register operand.*/
static boolean
parse_register_dst(
struct translate_ctx *ctx,
uint *file,
struct parsed_bracket *brackets)
{
brackets->ind_comp = TGSI_SWIZZLE_X;
if (!parse_register_file_bracket( ctx, file ))
return FALSE;
if (!parse_register_bracket( ctx, brackets ))
return FALSE;
 
return TRUE;
}
 
static boolean
parse_dst_operand(
struct translate_ctx *ctx,
struct tgsi_full_dst_register *dst )
{
uint file;
uint writemask;
const char *cur;
struct parsed_bracket bracket[2];
int parsed_opt_brackets;
 
if (!parse_register_dst( ctx, &file, &bracket[0] ))
return FALSE;
if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets))
return FALSE;
 
cur = ctx->cur;
eat_opt_white( &cur );
 
if (!parse_opt_writemask( ctx, &writemask ))
return FALSE;
 
dst->Register.File = file;
if (parsed_opt_brackets) {
dst->Register.Dimension = 1;
dst->Dimension.Indirect = 0;
dst->Dimension.Dimension = 0;
dst->Dimension.Index = bracket[0].index;
bracket[0] = bracket[1];
}
dst->Register.Index = bracket[0].index;
dst->Register.WriteMask = writemask;
if (bracket[0].ind_file != TGSI_FILE_NULL) {
dst->Register.Indirect = 1;
dst->Indirect.File = bracket[0].ind_file;
dst->Indirect.Index = bracket[0].ind_index;
dst->Indirect.Swizzle = bracket[0].ind_comp;
dst->Indirect.ArrayID = bracket[0].ind_array;
}
return TRUE;
}
 
static boolean
parse_optional_swizzle(
struct translate_ctx *ctx,
uint swizzle[4],
boolean *parsed_swizzle )
{
const char *cur = ctx->cur;
 
*parsed_swizzle = FALSE;
 
eat_opt_white( &cur );
if (*cur == '.') {
uint i;
 
cur++;
eat_opt_white( &cur );
for (i = 0; i < 4; i++) {
if (uprcase( *cur ) == 'X')
swizzle[i] = TGSI_SWIZZLE_X;
else if (uprcase( *cur ) == 'Y')
swizzle[i] = TGSI_SWIZZLE_Y;
else if (uprcase( *cur ) == 'Z')
swizzle[i] = TGSI_SWIZZLE_Z;
else if (uprcase( *cur ) == 'W')
swizzle[i] = TGSI_SWIZZLE_W;
else {
report_error( ctx, "Expected register swizzle component `x', `y', `z' or `w'" );
return FALSE;
}
cur++;
}
*parsed_swizzle = TRUE;
ctx->cur = cur;
}
return TRUE;
}
 
static boolean
parse_src_operand(
struct translate_ctx *ctx,
struct tgsi_full_src_register *src )
{
uint file;
uint swizzle[4];
boolean parsed_swizzle;
struct parsed_bracket bracket[2];
int parsed_opt_brackets;
 
if (*ctx->cur == '-') {
ctx->cur++;
eat_opt_white( &ctx->cur );
src->Register.Negate = 1;
}
 
if (*ctx->cur == '|') {
ctx->cur++;
eat_opt_white( &ctx->cur );
src->Register.Absolute = 1;
}
 
if (!parse_register_src(ctx, &file, &bracket[0]))
return FALSE;
if (!parse_opt_register_src_bracket(ctx, &bracket[1], &parsed_opt_brackets))
return FALSE;
 
src->Register.File = file;
if (parsed_opt_brackets) {
src->Register.Dimension = 1;
src->Dimension.Indirect = 0;
src->Dimension.Dimension = 0;
src->Dimension.Index = bracket[0].index;
bracket[0] = bracket[1];
}
src->Register.Index = bracket[0].index;
if (bracket[0].ind_file != TGSI_FILE_NULL) {
src->Register.Indirect = 1;
src->Indirect.File = bracket[0].ind_file;
src->Indirect.Index = bracket[0].ind_index;
src->Indirect.Swizzle = bracket[0].ind_comp;
src->Indirect.ArrayID = bracket[0].ind_array;
}
 
/* Parse optional swizzle.
*/
if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle )) {
if (parsed_swizzle) {
src->Register.SwizzleX = swizzle[0];
src->Register.SwizzleY = swizzle[1];
src->Register.SwizzleZ = swizzle[2];
src->Register.SwizzleW = swizzle[3];
}
}
 
if (src->Register.Absolute) {
eat_opt_white( &ctx->cur );
if (*ctx->cur != '|') {
report_error( ctx, "Expected `|'" );
return FALSE;
}
ctx->cur++;
}
 
 
return TRUE;
}
 
static boolean
match_inst(const char **pcur,
unsigned *saturate,
const struct tgsi_opcode_info *info)
{
const char *cur = *pcur;
 
/* simple case: the whole string matches the instruction name */
if (str_match_nocase_whole(&cur, info->mnemonic)) {
*pcur = cur;
*saturate = TGSI_SAT_NONE;
return TRUE;
}
 
if (str_match_no_case(&cur, info->mnemonic)) {
/* the instruction has a suffix, figure it out */
if (str_match_nocase_whole(&cur, "_SAT")) {
*pcur = cur;
*saturate = TGSI_SAT_ZERO_ONE;
return TRUE;
}
 
if (str_match_nocase_whole(&cur, "_SATNV")) {
*pcur = cur;
*saturate = TGSI_SAT_MINUS_PLUS_ONE;
return TRUE;
}
}
 
return FALSE;
}
 
static boolean
parse_instruction(
struct translate_ctx *ctx,
boolean has_label )
{
uint i;
uint saturate = TGSI_SAT_NONE;
const struct tgsi_opcode_info *info;
struct tgsi_full_instruction inst;
const char *cur;
uint advance;
 
inst = tgsi_default_full_instruction();
 
/* Parse predicate.
*/
eat_opt_white( &ctx->cur );
if (*ctx->cur == '(') {
uint file;
int index;
uint swizzle[4];
boolean parsed_swizzle;
 
inst.Instruction.Predicate = 1;
 
ctx->cur++;
if (*ctx->cur == '!') {
ctx->cur++;
inst.Predicate.Negate = 1;
}
 
if (!parse_register_1d( ctx, &file, &index ))
return FALSE;
 
if (parse_optional_swizzle( ctx, swizzle, &parsed_swizzle )) {
if (parsed_swizzle) {
inst.Predicate.SwizzleX = swizzle[0];
inst.Predicate.SwizzleY = swizzle[1];
inst.Predicate.SwizzleZ = swizzle[2];
inst.Predicate.SwizzleW = swizzle[3];
}
}
 
if (*ctx->cur != ')') {
report_error( ctx, "Expected `)'" );
return FALSE;
}
 
ctx->cur++;
}
 
/* Parse instruction name.
*/
eat_opt_white( &ctx->cur );
for (i = 0; i < TGSI_OPCODE_LAST; i++) {
cur = ctx->cur;
 
info = tgsi_get_opcode_info( i );
if (match_inst(&cur, &saturate, info)) {
if (info->num_dst + info->num_src + info->is_tex == 0) {
ctx->cur = cur;
break;
}
else if (*cur == '\0' || eat_white( &cur )) {
ctx->cur = cur;
break;
}
}
}
if (i == TGSI_OPCODE_LAST) {
if (has_label)
report_error( ctx, "Unknown opcode" );
else
report_error( ctx, "Expected `DCL', `IMM' or a label" );
return FALSE;
}
 
inst.Instruction.Opcode = i;
inst.Instruction.Saturate = saturate;
inst.Instruction.NumDstRegs = info->num_dst;
inst.Instruction.NumSrcRegs = info->num_src;
 
if (i >= TGSI_OPCODE_SAMPLE && i <= TGSI_OPCODE_GATHER4) {
/*
* These are not considered tex opcodes here (no additional
* target argument) however we're required to set the Texture
* bit so we can set the number of tex offsets (offsets aren't
* actually handled here yet in any case).
*/
inst.Instruction.Texture = 1;
inst.Texture.Texture = TGSI_TEXTURE_UNKNOWN;
}
 
/* Parse instruction operands.
*/
for (i = 0; i < info->num_dst + info->num_src + info->is_tex; i++) {
if (i > 0) {
eat_opt_white( &ctx->cur );
if (*ctx->cur != ',') {
report_error( ctx, "Expected `,'" );
return FALSE;
}
ctx->cur++;
eat_opt_white( &ctx->cur );
}
 
if (i < info->num_dst) {
if (!parse_dst_operand( ctx, &inst.Dst[i] ))
return FALSE;
}
else if (i < info->num_dst + info->num_src) {
if (!parse_src_operand( ctx, &inst.Src[i - info->num_dst] ))
return FALSE;
}
else {
uint j;
 
for (j = 0; j < TGSI_TEXTURE_COUNT; j++) {
if (str_match_nocase_whole( &ctx->cur, tgsi_texture_names[j] )) {
inst.Instruction.Texture = 1;
inst.Texture.Texture = j;
break;
}
}
if (j == TGSI_TEXTURE_COUNT) {
report_error( ctx, "Expected texture target" );
return FALSE;
}
}
}
 
cur = ctx->cur;
eat_opt_white( &cur );
if (info->is_branch && *cur == ':') {
uint target;
 
cur++;
eat_opt_white( &cur );
if (!parse_uint( &cur, &target )) {
report_error( ctx, "Expected a label" );
return FALSE;
}
inst.Instruction.Label = 1;
inst.Label.Label = target;
ctx->cur = cur;
}
 
advance = tgsi_build_full_instruction(
&inst,
ctx->tokens_cur,
ctx->header,
(uint) (ctx->tokens_end - ctx->tokens_cur) );
if (advance == 0)
return FALSE;
ctx->tokens_cur += advance;
 
return TRUE;
}
 
/* parses a 4-touple of the form {x, y, z, w}
* where x, y, z, w are numbers */
static boolean parse_immediate_data(struct translate_ctx *ctx, unsigned type,
union tgsi_immediate_data *values)
{
unsigned i;
int ret;
 
eat_opt_white( &ctx->cur );
if (*ctx->cur != '{') {
report_error( ctx, "Expected `{'" );
return FALSE;
}
ctx->cur++;
for (i = 0; i < 4; i++) {
eat_opt_white( &ctx->cur );
if (i > 0) {
if (*ctx->cur != ',') {
report_error( ctx, "Expected `,'" );
return FALSE;
}
ctx->cur++;
eat_opt_white( &ctx->cur );
}
 
switch (type) {
case TGSI_IMM_FLOAT32:
ret = parse_float(&ctx->cur, &values[i].Float);
break;
case TGSI_IMM_UINT32:
ret = parse_uint(&ctx->cur, &values[i].Uint);
break;
case TGSI_IMM_INT32:
ret = parse_int(&ctx->cur, &values[i].Int);
break;
default:
assert(0);
ret = FALSE;
break;
}
 
if (!ret) {
report_error( ctx, "Expected immediate constant" );
return FALSE;
}
}
eat_opt_white( &ctx->cur );
if (*ctx->cur != '}') {
report_error( ctx, "Expected `}'" );
return FALSE;
}
ctx->cur++;
 
return TRUE;
}
 
static boolean parse_declaration( struct translate_ctx *ctx )
{
struct tgsi_full_declaration decl;
uint file;
struct parsed_dcl_bracket brackets[2];
int num_brackets;
uint writemask;
const char *cur, *cur2;
uint advance;
boolean is_vs_input;
 
if (!eat_white( &ctx->cur )) {
report_error( ctx, "Syntax error" );
return FALSE;
}
if (!parse_register_dcl( ctx, &file, brackets, &num_brackets))
return FALSE;
if (!parse_opt_writemask( ctx, &writemask ))
return FALSE;
 
decl = tgsi_default_full_declaration();
decl.Declaration.File = file;
decl.Declaration.UsageMask = writemask;
 
if (num_brackets == 1) {
decl.Range.First = brackets[0].first;
decl.Range.Last = brackets[0].last;
} else {
decl.Range.First = brackets[1].first;
decl.Range.Last = brackets[1].last;
 
decl.Declaration.Dimension = 1;
decl.Dim.Index2D = brackets[0].first;
}
 
is_vs_input = (file == TGSI_FILE_INPUT &&
ctx->processor == TGSI_PROCESSOR_VERTEX);
 
cur = ctx->cur;
eat_opt_white( &cur );
if (*cur == ',') {
cur2 = cur;
cur2++;
eat_opt_white( &cur2 );
if (str_match_nocase_whole( &cur2, "ARRAY" )) {
int arrayid;
if (*cur2 != '(') {
report_error( ctx, "Expected `('" );
return FALSE;
}
cur2++;
eat_opt_white( &cur2 );
if (!parse_int( &cur2, &arrayid )) {
report_error( ctx, "Expected `,'" );
return FALSE;
}
eat_opt_white( &cur2 );
if (*cur2 != ')') {
report_error( ctx, "Expected `)'" );
return FALSE;
}
cur2++;
decl.Declaration.Array = 1;
decl.Array.ArrayID = arrayid;
ctx->cur = cur = cur2;
}
}
 
if (*cur == ',' && !is_vs_input) {
uint i, j;
 
cur++;
eat_opt_white( &cur );
if (file == TGSI_FILE_RESOURCE) {
for (i = 0; i < TGSI_TEXTURE_COUNT; i++) {
if (str_match_nocase_whole(&cur, tgsi_texture_names[i])) {
decl.Resource.Resource = i;
break;
}
}
if (i == TGSI_TEXTURE_COUNT) {
report_error(ctx, "Expected texture target");
return FALSE;
}
 
cur2 = cur;
eat_opt_white(&cur2);
while (*cur2 == ',') {
cur2++;
eat_opt_white(&cur2);
if (str_match_nocase_whole(&cur2, "RAW")) {
decl.Resource.Raw = 1;
 
} else if (str_match_nocase_whole(&cur2, "WR")) {
decl.Resource.Writable = 1;
 
} else {
break;
}
cur = cur2;
eat_opt_white(&cur2);
}
 
ctx->cur = cur;
 
} else if (file == TGSI_FILE_SAMPLER_VIEW) {
for (i = 0; i < TGSI_TEXTURE_COUNT; i++) {
if (str_match_nocase_whole(&cur, tgsi_texture_names[i])) {
decl.SamplerView.Resource = i;
break;
}
}
if (i == TGSI_TEXTURE_COUNT) {
report_error(ctx, "Expected texture target");
return FALSE;
}
eat_opt_white( &cur );
if (*cur != ',') {
report_error( ctx, "Expected `,'" );
return FALSE;
}
++cur;
eat_opt_white( &cur );
for (j = 0; j < 4; ++j) {
for (i = 0; i < PIPE_TYPE_COUNT; ++i) {
if (str_match_nocase_whole(&cur, tgsi_type_names[i])) {
switch (j) {
case 0:
decl.SamplerView.ReturnTypeX = i;
break;
case 1:
decl.SamplerView.ReturnTypeY = i;
break;
case 2:
decl.SamplerView.ReturnTypeZ = i;
break;
case 3:
decl.SamplerView.ReturnTypeW = i;
break;
default:
assert(0);
}
break;
}
}
if (i == PIPE_TYPE_COUNT) {
if (j == 0 || j > 2) {
report_error(ctx, "Expected type name");
return FALSE;
}
break;
} else {
cur2 = cur;
eat_opt_white( &cur2 );
if (*cur2 == ',') {
cur2++;
eat_opt_white( &cur2 );
cur = cur2;
continue;
} else
break;
}
}
if (j < 4) {
decl.SamplerView.ReturnTypeY =
decl.SamplerView.ReturnTypeZ =
decl.SamplerView.ReturnTypeW =
decl.SamplerView.ReturnTypeX;
}
ctx->cur = cur;
} else {
if (str_match_nocase_whole(&cur, "LOCAL")) {
decl.Declaration.Local = 1;
ctx->cur = cur;
}
 
cur = ctx->cur;
eat_opt_white( &cur );
if (*cur == ',') {
cur++;
eat_opt_white( &cur );
 
for (i = 0; i < TGSI_SEMANTIC_COUNT; i++) {
if (str_match_nocase_whole(&cur, tgsi_semantic_names[i])) {
uint index;
 
cur2 = cur;
eat_opt_white( &cur2 );
if (*cur2 == '[') {
cur2++;
eat_opt_white( &cur2 );
if (!parse_uint( &cur2, &index )) {
report_error( ctx, "Expected literal integer" );
return FALSE;
}
eat_opt_white( &cur2 );
if (*cur2 != ']') {
report_error( ctx, "Expected `]'" );
return FALSE;
}
cur2++;
 
decl.Semantic.Index = index;
 
cur = cur2;
}
 
decl.Declaration.Semantic = 1;
decl.Semantic.Name = i;
 
ctx->cur = cur;
break;
}
}
}
}
}
 
cur = ctx->cur;
eat_opt_white( &cur );
if (*cur == ',' && !is_vs_input) {
uint i;
 
cur++;
eat_opt_white( &cur );
for (i = 0; i < TGSI_INTERPOLATE_COUNT; i++) {
if (str_match_nocase_whole( &cur, tgsi_interpolate_names[i] )) {
decl.Declaration.Interpolate = 1;
decl.Interp.Interpolate = i;
 
ctx->cur = cur;
break;
}
}
if (i == TGSI_INTERPOLATE_COUNT) {
report_error( ctx, "Expected semantic or interpolate attribute" );
return FALSE;
}
}
 
advance = tgsi_build_full_declaration(
&decl,
ctx->tokens_cur,
ctx->header,
(uint) (ctx->tokens_end - ctx->tokens_cur) );
 
if (advance == 0)
return FALSE;
ctx->tokens_cur += advance;
 
return TRUE;
}
 
static boolean parse_immediate( struct translate_ctx *ctx )
{
struct tgsi_full_immediate imm;
uint advance;
int type;
 
if (*ctx->cur == '[') {
uint uindex;
 
++ctx->cur;
 
eat_opt_white( &ctx->cur );
if (!parse_uint( &ctx->cur, &uindex )) {
report_error( ctx, "Expected literal unsigned integer" );
return FALSE;
}
 
if (uindex != ctx->num_immediates) {
report_error( ctx, "Immediates must be sorted" );
return FALSE;
}
 
eat_opt_white( &ctx->cur );
if (*ctx->cur != ']') {
report_error( ctx, "Expected `]'" );
return FALSE;
}
 
ctx->cur++;
}
 
if (!eat_white( &ctx->cur )) {
report_error( ctx, "Syntax error" );
return FALSE;
}
for (type = 0; type < Elements(tgsi_immediate_type_names); ++type) {
if (str_match_nocase_whole(&ctx->cur, tgsi_immediate_type_names[type]))
break;
}
if (type == Elements(tgsi_immediate_type_names)) {
report_error( ctx, "Expected immediate type" );
return FALSE;
}
 
imm = tgsi_default_full_immediate();
imm.Immediate.NrTokens += 4;
imm.Immediate.DataType = type;
parse_immediate_data(ctx, type, imm.u);
 
advance = tgsi_build_full_immediate(
&imm,
ctx->tokens_cur,
ctx->header,
(uint) (ctx->tokens_end - ctx->tokens_cur) );
if (advance == 0)
return FALSE;
ctx->tokens_cur += advance;
 
ctx->num_immediates++;
 
return TRUE;
}
 
static boolean
parse_primitive( const char **pcur, uint *primitive )
{
uint i;
 
for (i = 0; i < PIPE_PRIM_MAX; i++) {
const char *cur = *pcur;
 
if (str_match_nocase_whole( &cur, tgsi_primitive_names[i])) {
*primitive = i;
*pcur = cur;
return TRUE;
}
}
return FALSE;
}
 
static boolean
parse_fs_coord_origin( const char **pcur, uint *fs_coord_origin )
{
uint i;
 
for (i = 0; i < Elements(tgsi_fs_coord_origin_names); i++) {
const char *cur = *pcur;
 
if (str_match_nocase_whole( &cur, tgsi_fs_coord_origin_names[i])) {
*fs_coord_origin = i;
*pcur = cur;
return TRUE;
}
}
return FALSE;
}
 
static boolean
parse_fs_coord_pixel_center( const char **pcur, uint *fs_coord_pixel_center )
{
uint i;
 
for (i = 0; i < Elements(tgsi_fs_coord_pixel_center_names); i++) {
const char *cur = *pcur;
 
if (str_match_nocase_whole( &cur, tgsi_fs_coord_pixel_center_names[i])) {
*fs_coord_pixel_center = i;
*pcur = cur;
return TRUE;
}
}
return FALSE;
}
 
 
static boolean parse_property( struct translate_ctx *ctx )
{
struct tgsi_full_property prop;
uint property_name;
uint values[8];
uint advance;
char id[64];
 
if (!eat_white( &ctx->cur )) {
report_error( ctx, "Syntax error" );
return FALSE;
}
if (!parse_identifier( &ctx->cur, id )) {
report_error( ctx, "Syntax error" );
return FALSE;
}
for (property_name = 0; property_name < TGSI_PROPERTY_COUNT;
++property_name) {
if (streq_nocase_uprcase(tgsi_property_names[property_name], id)) {
break;
}
}
if (property_name >= TGSI_PROPERTY_COUNT) {
debug_printf( "\nError: Unknown property : '%s'", id );
return FALSE;
}
 
eat_opt_white( &ctx->cur );
switch(property_name) {
case TGSI_PROPERTY_GS_INPUT_PRIM:
case TGSI_PROPERTY_GS_OUTPUT_PRIM:
if (!parse_primitive(&ctx->cur, &values[0] )) {
report_error( ctx, "Unknown primitive name as property!" );
return FALSE;
}
if (property_name == TGSI_PROPERTY_GS_INPUT_PRIM &&
ctx->processor == TGSI_PROCESSOR_GEOMETRY) {
ctx->implied_array_size = u_vertices_per_prim(values[0]);
}
break;
case TGSI_PROPERTY_FS_COORD_ORIGIN:
if (!parse_fs_coord_origin(&ctx->cur, &values[0] )) {
report_error( ctx, "Unknown coord origin as property: must be UPPER_LEFT or LOWER_LEFT!" );
return FALSE;
}
break;
case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER:
if (!parse_fs_coord_pixel_center(&ctx->cur, &values[0] )) {
report_error( ctx, "Unknown coord pixel center as property: must be HALF_INTEGER or INTEGER!" );
return FALSE;
}
break;
case TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS:
default:
if (!parse_uint(&ctx->cur, &values[0] )) {
report_error( ctx, "Expected unsigned integer as property!" );
return FALSE;
}
}
 
prop = tgsi_default_full_property();
prop.Property.PropertyName = property_name;
prop.Property.NrTokens += 1;
prop.u[0].Data = values[0];
 
advance = tgsi_build_full_property(
&prop,
ctx->tokens_cur,
ctx->header,
(uint) (ctx->tokens_end - ctx->tokens_cur) );
if (advance == 0)
return FALSE;
ctx->tokens_cur += advance;
 
return TRUE;
}
 
 
static boolean translate( struct translate_ctx *ctx )
{
eat_opt_white( &ctx->cur );
if (!parse_header( ctx ))
return FALSE;
 
while (*ctx->cur != '\0') {
uint label_val = 0;
if (!eat_white( &ctx->cur )) {
report_error( ctx, "Syntax error" );
return FALSE;
}
 
if (*ctx->cur == '\0')
break;
if (parse_label( ctx, &label_val )) {
if (!parse_instruction( ctx, TRUE ))
return FALSE;
}
else if (str_match_nocase_whole( &ctx->cur, "DCL" )) {
if (!parse_declaration( ctx ))
return FALSE;
}
else if (str_match_nocase_whole( &ctx->cur, "IMM" )) {
if (!parse_immediate( ctx ))
return FALSE;
}
else if (str_match_nocase_whole( &ctx->cur, "PROPERTY" )) {
if (!parse_property( ctx ))
return FALSE;
}
else if (!parse_instruction( ctx, FALSE )) {
return FALSE;
}
}
 
return TRUE;
}
 
boolean
tgsi_text_translate(
const char *text,
struct tgsi_token *tokens,
uint num_tokens )
{
struct translate_ctx ctx = {0};
 
ctx.text = text;
ctx.cur = text;
ctx.tokens = tokens;
ctx.tokens_cur = tokens;
ctx.tokens_end = tokens + num_tokens;
 
if (!translate( &ctx ))
return FALSE;
 
return tgsi_sanity_check( tokens );
}
/drivers/video/Gallium/auxiliary/tgsi/tgsi_text.h
0,0 → 1,49
/**************************************************************************
*
* 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.
*
**************************************************************************/
 
#ifndef TGSI_TEXT_H
#define TGSI_TEXT_H
 
#if defined __cplusplus
extern "C" {
#endif
 
#include "pipe/p_compiler.h"
 
struct tgsi_token;
 
boolean
tgsi_text_translate(
const char *text,
struct tgsi_token *tokens,
uint num_tokens );
 
#if defined __cplusplus
}
#endif
 
#endif /* TGSI_TEXT_H */
/drivers/video/Gallium/auxiliary/tgsi/tgsi_transform.c
0,0 → 1,250
/**************************************************************************
*
* 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.
*
**************************************************************************/
 
/**
* TGSI program transformation utility.
*
* Authors: Brian Paul
*/
 
#include "util/u_debug.h"
 
#include "tgsi_transform.h"
 
 
 
static void
emit_instruction(struct tgsi_transform_context *ctx,
const struct tgsi_full_instruction *inst)
{
uint ti = ctx->ti;
 
ti += tgsi_build_full_instruction(inst,
ctx->tokens_out + ti,
ctx->header,
ctx->max_tokens_out - ti);
ctx->ti = ti;
}
 
 
static void
emit_declaration(struct tgsi_transform_context *ctx,
const struct tgsi_full_declaration *decl)
{
uint ti = ctx->ti;
 
ti += tgsi_build_full_declaration(decl,
ctx->tokens_out + ti,
ctx->header,
ctx->max_tokens_out - ti);
ctx->ti = ti;
}
 
 
static void
emit_immediate(struct tgsi_transform_context *ctx,
const struct tgsi_full_immediate *imm)
{
uint ti = ctx->ti;
 
ti += tgsi_build_full_immediate(imm,
ctx->tokens_out + ti,
ctx->header,
ctx->max_tokens_out - ti);
ctx->ti = ti;
}
 
 
static void
emit_property(struct tgsi_transform_context *ctx,
const struct tgsi_full_property *prop)
{
uint ti = ctx->ti;
 
ti += tgsi_build_full_property(prop,
ctx->tokens_out + ti,
ctx->header,
ctx->max_tokens_out - ti);
ctx->ti = ti;
}
 
 
/**
* Apply user-defined transformations to the input shader to produce
* the output shader.
* For example, a register search-and-replace operation could be applied
* by defining a transform_instruction() callback that examined and changed
* the instruction src/dest regs.
*
* \return number of tokens emitted
*/
int
tgsi_transform_shader(const struct tgsi_token *tokens_in,
struct tgsi_token *tokens_out,
uint max_tokens_out,
struct tgsi_transform_context *ctx)
{
uint procType;
 
/* input shader */
struct tgsi_parse_context parse;
 
/* output shader */
struct tgsi_processor *processor;
 
 
/**
** callback context init
**/
ctx->emit_instruction = emit_instruction;
ctx->emit_declaration = emit_declaration;
ctx->emit_immediate = emit_immediate;
ctx->emit_property = emit_property;
ctx->tokens_out = tokens_out;
ctx->max_tokens_out = max_tokens_out;
 
 
/**
** Setup to begin parsing input shader
**/
if (tgsi_parse_init( &parse, tokens_in ) != TGSI_PARSE_OK) {
debug_printf("tgsi_parse_init() failed in tgsi_transform_shader()!\n");
return -1;
}
procType = parse.FullHeader.Processor.Processor;
assert(procType == TGSI_PROCESSOR_FRAGMENT ||
procType == TGSI_PROCESSOR_VERTEX ||
procType == TGSI_PROCESSOR_GEOMETRY);
 
 
/**
** Setup output shader
**/
ctx->header = (struct tgsi_header *)tokens_out;
*ctx->header = tgsi_build_header();
 
processor = (struct tgsi_processor *) (tokens_out + 1);
*processor = tgsi_build_processor( procType, ctx->header );
 
ctx->ti = 2;
 
 
/**
** Loop over incoming program tokens/instructions
*/
while( !tgsi_parse_end_of_tokens( &parse ) ) {
 
tgsi_parse_token( &parse );
 
switch( parse.FullToken.Token.Type ) {
case TGSI_TOKEN_TYPE_INSTRUCTION:
{
struct tgsi_full_instruction *fullinst
= &parse.FullToken.FullInstruction;
 
if (ctx->transform_instruction)
ctx->transform_instruction(ctx, fullinst);
else
ctx->emit_instruction(ctx, fullinst);
}
break;
 
case TGSI_TOKEN_TYPE_DECLARATION:
{
struct tgsi_full_declaration *fulldecl
= &parse.FullToken.FullDeclaration;
 
if (ctx->transform_declaration)
ctx->transform_declaration(ctx, fulldecl);
else
ctx->emit_declaration(ctx, fulldecl);
}
break;
 
case TGSI_TOKEN_TYPE_IMMEDIATE:
{
struct tgsi_full_immediate *fullimm
= &parse.FullToken.FullImmediate;
 
if (ctx->transform_immediate)
ctx->transform_immediate(ctx, fullimm);
else
ctx->emit_immediate(ctx, fullimm);
}
break;
case TGSI_TOKEN_TYPE_PROPERTY:
{
struct tgsi_full_property *fullprop
= &parse.FullToken.FullProperty;
 
if (ctx->transform_property)
ctx->transform_property(ctx, fullprop);
else
ctx->emit_property(ctx, fullprop);
}
break;
 
default:
assert( 0 );
}
}
 
if (ctx->epilog) {
ctx->epilog(ctx);
}
 
tgsi_parse_free (&parse);
 
return ctx->ti;
}
 
 
#include "tgsi_text.h"
 
extern int tgsi_transform_foo( struct tgsi_token *tokens_out,
uint max_tokens_out );
 
/* This function exists only so that tgsi_text_translate() doesn't get
* magic-ed out of the libtgsi.a archive by the build system. Don't
* remove unless you know this has been fixed - check on mingw/scons
* builds as well.
*/
int
tgsi_transform_foo( struct tgsi_token *tokens_out,
uint max_tokens_out )
{
const char *text =
"FRAG\n"
"DCL IN[0], COLOR, CONSTANT\n"
"DCL OUT[0], COLOR\n"
" 0: MOV OUT[0], IN[0]\n"
" 1: END";
return tgsi_text_translate( text,
tokens_out,
max_tokens_out );
}
/drivers/video/Gallium/auxiliary/tgsi/tgsi_transform.h
0,0 → 1,96
/**************************************************************************
*
* 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.
*
**************************************************************************/
 
#ifndef TGSI_TRANSFORM_H
#define TGSI_TRANSFORM_H
 
 
#include "pipe/p_shader_tokens.h"
#include "tgsi/tgsi_parse.h"
#include "tgsi/tgsi_build.h"
 
 
 
/**
* Subclass this to add caller-specific data
*/
struct tgsi_transform_context
{
/**** PUBLIC ***/
 
/**
* User-defined callbacks invoked per instruction.
*/
void (*transform_instruction)(struct tgsi_transform_context *ctx,
struct tgsi_full_instruction *inst);
 
void (*transform_declaration)(struct tgsi_transform_context *ctx,
struct tgsi_full_declaration *decl);
 
void (*transform_immediate)(struct tgsi_transform_context *ctx,
struct tgsi_full_immediate *imm);
void (*transform_property)(struct tgsi_transform_context *ctx,
struct tgsi_full_property *prop);
 
/**
* Called at end of input program to allow caller to append extra
* instructions. Return number of tokens emitted.
*/
void (*epilog)(struct tgsi_transform_context *ctx);
 
 
/*** PRIVATE ***/
 
/**
* These are setup by tgsi_transform_shader() and cannot be overridden.
* Meant to be called from in the above user callback functions.
*/
void (*emit_instruction)(struct tgsi_transform_context *ctx,
const struct tgsi_full_instruction *inst);
void (*emit_declaration)(struct tgsi_transform_context *ctx,
const struct tgsi_full_declaration *decl);
void (*emit_immediate)(struct tgsi_transform_context *ctx,
const struct tgsi_full_immediate *imm);
void (*emit_property)(struct tgsi_transform_context *ctx,
const struct tgsi_full_property *prop);
 
struct tgsi_header *header;
uint max_tokens_out;
struct tgsi_token *tokens_out;
uint ti;
};
 
 
 
extern int
tgsi_transform_shader(const struct tgsi_token *tokens_in,
struct tgsi_token *tokens_out,
uint max_tokens_out,
struct tgsi_transform_context *ctx);
 
 
#endif /* TGSI_TRANSFORM_H */
/drivers/video/Gallium/auxiliary/tgsi/tgsi_ureg.c
0,0 → 1,1795
/**************************************************************************
*
* Copyright 2009-2010 VMware, Inc.
* 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 VMWARE, INC 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.
*
**************************************************************************/
 
 
#include "pipe/p_context.h"
#include "pipe/p_state.h"
#include "tgsi/tgsi_ureg.h"
#include "tgsi/tgsi_build.h"
#include "tgsi/tgsi_info.h"
#include "tgsi/tgsi_dump.h"
#include "tgsi/tgsi_sanity.h"
#include "util/u_debug.h"
#include "util/u_memory.h"
#include "util/u_math.h"
#include "util/u_bitmask.h"
 
union tgsi_any_token {
struct tgsi_header header;
struct tgsi_processor processor;
struct tgsi_token token;
struct tgsi_property prop;
struct tgsi_property_data prop_data;
struct tgsi_declaration decl;
struct tgsi_declaration_range decl_range;
struct tgsi_declaration_dimension decl_dim;
struct tgsi_declaration_interp decl_interp;
struct tgsi_declaration_semantic decl_semantic;
struct tgsi_declaration_sampler_view decl_sampler_view;
struct tgsi_declaration_array array;
struct tgsi_immediate imm;
union tgsi_immediate_data imm_data;
struct tgsi_instruction insn;
struct tgsi_instruction_predicate insn_predicate;
struct tgsi_instruction_label insn_label;
struct tgsi_instruction_texture insn_texture;
struct tgsi_texture_offset insn_texture_offset;
struct tgsi_src_register src;
struct tgsi_ind_register ind;
struct tgsi_dimension dim;
struct tgsi_dst_register dst;
unsigned value;
};
 
 
struct ureg_tokens {
union tgsi_any_token *tokens;
unsigned size;
unsigned order;
unsigned count;
};
 
#define UREG_MAX_INPUT PIPE_MAX_ATTRIBS
#define UREG_MAX_SYSTEM_VALUE PIPE_MAX_ATTRIBS
#define UREG_MAX_OUTPUT PIPE_MAX_SHADER_OUTPUTS
#define UREG_MAX_CONSTANT_RANGE 32
#define UREG_MAX_IMMEDIATE 256
#define UREG_MAX_ADDR 2
#define UREG_MAX_PRED 1
#define UREG_MAX_ARRAY_TEMPS 256
 
struct const_decl {
struct {
unsigned first;
unsigned last;
} constant_range[UREG_MAX_CONSTANT_RANGE];
unsigned nr_constant_ranges;
};
 
#define DOMAIN_DECL 0
#define DOMAIN_INSN 1
 
struct ureg_program
{
unsigned processor;
struct pipe_context *pipe;
 
struct {
unsigned semantic_name;
unsigned semantic_index;
unsigned interp;
unsigned char cylindrical_wrap;
unsigned char centroid;
} fs_input[UREG_MAX_INPUT];
unsigned nr_fs_inputs;
 
unsigned vs_inputs[UREG_MAX_INPUT/32];
 
struct {
unsigned index;
unsigned semantic_name;
unsigned semantic_index;
} gs_input[UREG_MAX_INPUT];
unsigned nr_gs_inputs;
 
struct {
unsigned index;
unsigned semantic_name;
unsigned semantic_index;
} system_value[UREG_MAX_SYSTEM_VALUE];
unsigned nr_system_values;
 
struct {
unsigned semantic_name;
unsigned semantic_index;
unsigned usage_mask; /* = TGSI_WRITEMASK_* */
} output[UREG_MAX_OUTPUT];
unsigned nr_outputs;
 
struct {
union {
float f[4];
unsigned u[4];
int i[4];
} value;
unsigned nr;
unsigned type;
} immediate[UREG_MAX_IMMEDIATE];
unsigned nr_immediates;
 
struct ureg_src sampler[PIPE_MAX_SAMPLERS];
unsigned nr_samplers;
 
struct {
unsigned index;
unsigned target;
unsigned return_type_x;
unsigned return_type_y;
unsigned return_type_z;
unsigned return_type_w;
} sampler_view[PIPE_MAX_SHADER_SAMPLER_VIEWS];
unsigned nr_sampler_views;
 
struct util_bitmask *free_temps;
struct util_bitmask *local_temps;
struct util_bitmask *decl_temps;
unsigned nr_temps;
 
unsigned array_temps[UREG_MAX_ARRAY_TEMPS];
unsigned nr_array_temps;
 
struct const_decl const_decls;
struct const_decl const_decls2D[PIPE_MAX_CONSTANT_BUFFERS];
 
unsigned property_gs_input_prim;
unsigned property_gs_output_prim;
unsigned property_gs_max_vertices;
unsigned char property_fs_coord_origin; /* = TGSI_FS_COORD_ORIGIN_* */
unsigned char property_fs_coord_pixel_center; /* = TGSI_FS_COORD_PIXEL_CENTER_* */
unsigned char property_fs_color0_writes_all_cbufs; /* = TGSI_FS_COLOR0_WRITES_ALL_CBUFS * */
unsigned char property_fs_depth_layout; /* TGSI_FS_DEPTH_LAYOUT */
 
unsigned nr_addrs;
unsigned nr_preds;
unsigned nr_instructions;
 
struct ureg_tokens domain[2];
};
 
static union tgsi_any_token error_tokens[32];
 
static void tokens_error( struct ureg_tokens *tokens )
{
if (tokens->tokens && tokens->tokens != error_tokens)
FREE(tokens->tokens);
 
tokens->tokens = error_tokens;
tokens->size = Elements(error_tokens);
tokens->count = 0;
}
 
 
static void tokens_expand( struct ureg_tokens *tokens,
unsigned count )
{
unsigned old_size = tokens->size * sizeof(unsigned);
 
if (tokens->tokens == error_tokens) {
return;
}
 
while (tokens->count + count > tokens->size) {
tokens->size = (1 << ++tokens->order);
}
 
tokens->tokens = REALLOC(tokens->tokens,
old_size,
tokens->size * sizeof(unsigned));
if (tokens->tokens == NULL) {
tokens_error(tokens);
}
}
 
static void set_bad( struct ureg_program *ureg )
{
tokens_error(&ureg->domain[0]);
}
 
 
 
static union tgsi_any_token *get_tokens( struct ureg_program *ureg,
unsigned domain,
unsigned count )
{
struct ureg_tokens *tokens = &ureg->domain[domain];
union tgsi_any_token *result;
 
if (tokens->count + count > tokens->size)
tokens_expand(tokens, count);
 
result = &tokens->tokens[tokens->count];
tokens->count += count;
return result;
}
 
 
static union tgsi_any_token *retrieve_token( struct ureg_program *ureg,
unsigned domain,
unsigned nr )
{
if (ureg->domain[domain].tokens == error_tokens)
return &error_tokens[0];
 
return &ureg->domain[domain].tokens[nr];
}
 
 
 
static INLINE struct ureg_dst
ureg_dst_register( unsigned file,
unsigned index )
{
struct ureg_dst dst;
 
dst.File = file;
dst.WriteMask = TGSI_WRITEMASK_XYZW;
dst.Indirect = 0;
dst.IndirectFile = TGSI_FILE_NULL;
dst.IndirectIndex = 0;
dst.IndirectSwizzle = 0;
dst.Saturate = 0;
dst.Predicate = 0;
dst.PredNegate = 0;
dst.PredSwizzleX = TGSI_SWIZZLE_X;
dst.PredSwizzleY = TGSI_SWIZZLE_Y;
dst.PredSwizzleZ = TGSI_SWIZZLE_Z;
dst.PredSwizzleW = TGSI_SWIZZLE_W;
dst.Index = index;
dst.ArrayID = 0;
 
return dst;
}
 
 
void
ureg_property_gs_input_prim(struct ureg_program *ureg,
unsigned input_prim)
{
ureg->property_gs_input_prim = input_prim;
}
 
void
ureg_property_gs_output_prim(struct ureg_program *ureg,
unsigned output_prim)
{
ureg->property_gs_output_prim = output_prim;
}
 
void
ureg_property_gs_max_vertices(struct ureg_program *ureg,
unsigned max_vertices)
{
ureg->property_gs_max_vertices = max_vertices;
}
 
void
ureg_property_fs_coord_origin(struct ureg_program *ureg,
unsigned fs_coord_origin)
{
ureg->property_fs_coord_origin = fs_coord_origin;
}
 
void
ureg_property_fs_coord_pixel_center(struct ureg_program *ureg,
unsigned fs_coord_pixel_center)
{
ureg->property_fs_coord_pixel_center = fs_coord_pixel_center;
}
 
void
ureg_property_fs_color0_writes_all_cbufs(struct ureg_program *ureg,
unsigned fs_color0_writes_all_cbufs)
{
ureg->property_fs_color0_writes_all_cbufs = fs_color0_writes_all_cbufs;
}
 
void
ureg_property_fs_depth_layout(struct ureg_program *ureg,
unsigned fs_depth_layout)
{
ureg->property_fs_depth_layout = fs_depth_layout;
}
 
struct ureg_src
ureg_DECL_fs_input_cyl_centroid(struct ureg_program *ureg,
unsigned semantic_name,
unsigned semantic_index,
unsigned interp_mode,
unsigned cylindrical_wrap,
unsigned centroid)
{
unsigned i;
 
for (i = 0; i < ureg->nr_fs_inputs; i++) {
if (ureg->fs_input[i].semantic_name == semantic_name &&
ureg->fs_input[i].semantic_index == semantic_index) {
goto out;
}
}
 
if (ureg->nr_fs_inputs < UREG_MAX_INPUT) {
ureg->fs_input[i].semantic_name = semantic_name;
ureg->fs_input[i].semantic_index = semantic_index;
ureg->fs_input[i].interp = interp_mode;
ureg->fs_input[i].cylindrical_wrap = cylindrical_wrap;
ureg->fs_input[i].centroid = centroid;
ureg->nr_fs_inputs++;
} else {
set_bad(ureg);
}
 
out:
return ureg_src_register(TGSI_FILE_INPUT, i);
}
 
 
struct ureg_src
ureg_DECL_vs_input( struct ureg_program *ureg,
unsigned index )
{
assert(ureg->processor == TGSI_PROCESSOR_VERTEX);
ureg->vs_inputs[index/32] |= 1 << (index % 32);
return ureg_src_register( TGSI_FILE_INPUT, index );
}
 
 
struct ureg_src
ureg_DECL_gs_input(struct ureg_program *ureg,
unsigned index,
unsigned semantic_name,
unsigned semantic_index)
{
if (ureg->nr_gs_inputs < UREG_MAX_INPUT) {
ureg->gs_input[ureg->nr_gs_inputs].index = index;
ureg->gs_input[ureg->nr_gs_inputs].semantic_name = semantic_name;
ureg->gs_input[ureg->nr_gs_inputs].semantic_index = semantic_index;
ureg->nr_gs_inputs++;
} else {
set_bad(ureg);
}
 
/* XXX: Add suport for true 2D input registers. */
return ureg_src_register(TGSI_FILE_INPUT, index);
}
 
 
struct ureg_src
ureg_DECL_system_value(struct ureg_program *ureg,
unsigned index,
unsigned semantic_name,
unsigned semantic_index)
{
if (ureg->nr_system_values < UREG_MAX_SYSTEM_VALUE) {
ureg->system_value[ureg->nr_system_values].index = index;
ureg->system_value[ureg->nr_system_values].semantic_name = semantic_name;
ureg->system_value[ureg->nr_system_values].semantic_index = semantic_index;
ureg->nr_system_values++;
} else {
set_bad(ureg);
}
 
return ureg_src_register(TGSI_FILE_SYSTEM_VALUE, index);
}
 
 
struct ureg_dst
ureg_DECL_output_masked( struct ureg_program *ureg,
unsigned name,
unsigned index,
unsigned usage_mask )
{
unsigned i;
 
assert(usage_mask != 0);
 
for (i = 0; i < ureg->nr_outputs; i++) {
if (ureg->output[i].semantic_name == name &&
ureg->output[i].semantic_index == index) {
ureg->output[i].usage_mask |= usage_mask;
goto out;
}
}
 
if (ureg->nr_outputs < UREG_MAX_OUTPUT) {
ureg->output[i].semantic_name = name;
ureg->output[i].semantic_index = index;
ureg->output[i].usage_mask = usage_mask;
ureg->nr_outputs++;
}
else {
set_bad( ureg );
}
 
out:
return ureg_dst_register( TGSI_FILE_OUTPUT, i );
}
 
 
struct ureg_dst
ureg_DECL_output( struct ureg_program *ureg,
unsigned name,
unsigned index )
{
return ureg_DECL_output_masked(ureg, name, index, TGSI_WRITEMASK_XYZW);
}
 
 
/* Returns a new constant register. Keep track of which have been
* referred to so that we can emit decls later.
*
* Constant operands declared with this function must be addressed
* with a two-dimensional index.
*
* There is nothing in this code to bind this constant to any tracked
* value or manage any constant_buffer contents -- that's the
* resposibility of the calling code.
*/
void
ureg_DECL_constant2D(struct ureg_program *ureg,
unsigned first,
unsigned last,
unsigned index2D)
{
struct const_decl *decl = &ureg->const_decls2D[index2D];
 
assert(index2D < PIPE_MAX_CONSTANT_BUFFERS);
 
if (decl->nr_constant_ranges < UREG_MAX_CONSTANT_RANGE) {
uint i = decl->nr_constant_ranges++;
 
decl->constant_range[i].first = first;
decl->constant_range[i].last = last;
}
}
 
 
/* A one-dimensional, depricated version of ureg_DECL_constant2D().
*
* Constant operands declared with this function must be addressed
* with a one-dimensional index.
*/
struct ureg_src
ureg_DECL_constant(struct ureg_program *ureg,
unsigned index)
{
struct const_decl *decl = &ureg->const_decls;
unsigned minconst = index, maxconst = index;
unsigned i;
 
/* Inside existing range?
*/
for (i = 0; i < decl->nr_constant_ranges; i++) {
if (decl->constant_range[i].first <= index &&
decl->constant_range[i].last >= index) {
goto out;
}
}
 
/* Extend existing range?
*/
for (i = 0; i < decl->nr_constant_ranges; i++) {
if (decl->constant_range[i].last == index - 1) {
decl->constant_range[i].last = index;
goto out;
}
 
if (decl->constant_range[i].first == index + 1) {
decl->constant_range[i].first = index;
goto out;
}
 
minconst = MIN2(minconst, decl->constant_range[i].first);
maxconst = MAX2(maxconst, decl->constant_range[i].last);
}
 
/* Create new range?
*/
if (decl->nr_constant_ranges < UREG_MAX_CONSTANT_RANGE) {
i = decl->nr_constant_ranges++;
decl->constant_range[i].first = index;
decl->constant_range[i].last = index;
goto out;
}
 
/* Collapse all ranges down to one:
*/
i = 0;
decl->constant_range[0].first = minconst;
decl->constant_range[0].last = maxconst;
decl->nr_constant_ranges = 1;
 
out:
assert(i < decl->nr_constant_ranges);
assert(decl->constant_range[i].first <= index);
assert(decl->constant_range[i].last >= index);
return ureg_src_register(TGSI_FILE_CONSTANT, index);
}
 
static struct ureg_dst alloc_temporary( struct ureg_program *ureg,
boolean local )
{
unsigned i;
 
/* Look for a released temporary.
*/
for (i = util_bitmask_get_first_index(ureg->free_temps);
i != UTIL_BITMASK_INVALID_INDEX;
i = util_bitmask_get_next_index(ureg->free_temps, i + 1)) {
if (util_bitmask_get(ureg->local_temps, i) == local)
break;
}
 
/* Or allocate a new one.
*/
if (i == UTIL_BITMASK_INVALID_INDEX) {
i = ureg->nr_temps++;
 
if (local)
util_bitmask_set(ureg->local_temps, i);
 
/* Start a new declaration when the local flag changes */
if (!i || util_bitmask_get(ureg->local_temps, i - 1) != local)
util_bitmask_set(ureg->decl_temps, i);
}
 
util_bitmask_clear(ureg->free_temps, i);
 
return ureg_dst_register( TGSI_FILE_TEMPORARY, i );
}
 
struct ureg_dst ureg_DECL_temporary( struct ureg_program *ureg )
{
return alloc_temporary(ureg, FALSE);
}
 
struct ureg_dst ureg_DECL_local_temporary( struct ureg_program *ureg )
{
return alloc_temporary(ureg, TRUE);
}
 
struct ureg_dst ureg_DECL_array_temporary( struct ureg_program *ureg,
unsigned size,
boolean local )
{
unsigned i = ureg->nr_temps;
struct ureg_dst dst = ureg_dst_register( TGSI_FILE_TEMPORARY, i );
 
if (local)
util_bitmask_set(ureg->local_temps, i);
 
/* Always start a new declaration at the start */
util_bitmask_set(ureg->decl_temps, i);
 
ureg->nr_temps += size;
 
/* and also at the end of the array */
util_bitmask_set(ureg->decl_temps, ureg->nr_temps);
 
if (ureg->nr_array_temps < UREG_MAX_ARRAY_TEMPS) {
ureg->array_temps[ureg->nr_array_temps++] = i;
dst.ArrayID = ureg->nr_array_temps;
}
 
return dst;
}
 
void ureg_release_temporary( struct ureg_program *ureg,
struct ureg_dst tmp )
{
if(tmp.File == TGSI_FILE_TEMPORARY)
util_bitmask_set(ureg->free_temps, tmp.Index);
}
 
 
/* Allocate a new address register.
*/
struct ureg_dst ureg_DECL_address( struct ureg_program *ureg )
{
if (ureg->nr_addrs < UREG_MAX_ADDR)
return ureg_dst_register( TGSI_FILE_ADDRESS, ureg->nr_addrs++ );
 
assert( 0 );
return ureg_dst_register( TGSI_FILE_ADDRESS, 0 );
}
 
/* Allocate a new predicate register.
*/
struct ureg_dst
ureg_DECL_predicate(struct ureg_program *ureg)
{
if (ureg->nr_preds < UREG_MAX_PRED) {
return ureg_dst_register(TGSI_FILE_PREDICATE, ureg->nr_preds++);
}
 
assert(0);
return ureg_dst_register(TGSI_FILE_PREDICATE, 0);
}
 
/* Allocate a new sampler.
*/
struct ureg_src ureg_DECL_sampler( struct ureg_program *ureg,
unsigned nr )
{
unsigned i;
 
for (i = 0; i < ureg->nr_samplers; i++)
if (ureg->sampler[i].Index == nr)
return ureg->sampler[i];
if (i < PIPE_MAX_SAMPLERS) {
ureg->sampler[i] = ureg_src_register( TGSI_FILE_SAMPLER, nr );
ureg->nr_samplers++;
return ureg->sampler[i];
}
 
assert( 0 );
return ureg->sampler[0];
}
 
/*
* Allocate a new shader sampler view.
*/
struct ureg_src
ureg_DECL_sampler_view(struct ureg_program *ureg,
unsigned index,
unsigned target,
unsigned return_type_x,
unsigned return_type_y,
unsigned return_type_z,
unsigned return_type_w)
{
struct ureg_src reg = ureg_src_register(TGSI_FILE_SAMPLER_VIEW, index);
uint i;
 
for (i = 0; i < ureg->nr_sampler_views; i++) {
if (ureg->sampler_view[i].index == index) {
return reg;
}
}
 
if (i < PIPE_MAX_SHADER_SAMPLER_VIEWS) {
ureg->sampler_view[i].index = index;
ureg->sampler_view[i].target = target;
ureg->sampler_view[i].return_type_x = return_type_x;
ureg->sampler_view[i].return_type_y = return_type_y;
ureg->sampler_view[i].return_type_z = return_type_z;
ureg->sampler_view[i].return_type_w = return_type_w;
ureg->nr_sampler_views++;
return reg;
}
 
assert(0);
return reg;
}
 
static int
match_or_expand_immediate( const unsigned *v,
unsigned nr,
unsigned *v2,
unsigned *pnr2,
unsigned *swizzle )
{
unsigned nr2 = *pnr2;
unsigned i, j;
 
*swizzle = 0;
 
for (i = 0; i < nr; i++) {
boolean found = FALSE;
 
for (j = 0; j < nr2 && !found; j++) {
if (v[i] == v2[j]) {
*swizzle |= j << (i * 2);
found = TRUE;
}
}
 
if (!found) {
if (nr2 >= 4) {
return FALSE;
}
 
v2[nr2] = v[i];
*swizzle |= nr2 << (i * 2);
nr2++;
}
}
 
/* Actually expand immediate only when fully succeeded.
*/
*pnr2 = nr2;
return TRUE;
}
 
 
static struct ureg_src
decl_immediate( struct ureg_program *ureg,
const unsigned *v,
unsigned nr,
unsigned type )
{
unsigned i, j;
unsigned swizzle = 0;
 
/* Could do a first pass where we examine all existing immediates
* without expanding.
*/
 
for (i = 0; i < ureg->nr_immediates; i++) {
if (ureg->immediate[i].type != type) {
continue;
}
if (match_or_expand_immediate(v,
nr,
ureg->immediate[i].value.u,
&ureg->immediate[i].nr,
&swizzle)) {
goto out;
}
}
 
if (ureg->nr_immediates < UREG_MAX_IMMEDIATE) {
i = ureg->nr_immediates++;
ureg->immediate[i].type = type;
if (match_or_expand_immediate(v,
nr,
ureg->immediate[i].value.u,
&ureg->immediate[i].nr,
&swizzle)) {
goto out;
}
}
 
set_bad(ureg);
 
out:
/* Make sure that all referenced elements are from this immediate.
* Has the effect of making size-one immediates into scalars.
*/
for (j = nr; j < 4; j++) {
swizzle |= (swizzle & 0x3) << (j * 2);
}
 
return ureg_swizzle(ureg_src_register(TGSI_FILE_IMMEDIATE, i),
(swizzle >> 0) & 0x3,
(swizzle >> 2) & 0x3,
(swizzle >> 4) & 0x3,
(swizzle >> 6) & 0x3);
}
 
 
struct ureg_src
ureg_DECL_immediate( struct ureg_program *ureg,
const float *v,
unsigned nr )
{
union {
float f[4];
unsigned u[4];
} fu;
unsigned int i;
 
for (i = 0; i < nr; i++) {
fu.f[i] = v[i];
}
 
return decl_immediate(ureg, fu.u, nr, TGSI_IMM_FLOAT32);
}
 
 
struct ureg_src
ureg_DECL_immediate_uint( struct ureg_program *ureg,
const unsigned *v,
unsigned nr )
{
return decl_immediate(ureg, v, nr, TGSI_IMM_UINT32);
}
 
 
struct ureg_src
ureg_DECL_immediate_block_uint( struct ureg_program *ureg,
const unsigned *v,
unsigned nr )
{
uint index;
uint i;
 
if (ureg->nr_immediates + (nr + 3) / 4 > UREG_MAX_IMMEDIATE) {
set_bad(ureg);
return ureg_src_register(TGSI_FILE_IMMEDIATE, 0);
}
 
index = ureg->nr_immediates;
ureg->nr_immediates += (nr + 3) / 4;
 
for (i = index; i < ureg->nr_immediates; i++) {
ureg->immediate[i].type = TGSI_IMM_UINT32;
ureg->immediate[i].nr = nr > 4 ? 4 : nr;
memcpy(ureg->immediate[i].value.u,
&v[(i - index) * 4],
ureg->immediate[i].nr * sizeof(uint));
nr -= 4;
}
 
return ureg_src_register(TGSI_FILE_IMMEDIATE, index);
}
 
 
struct ureg_src
ureg_DECL_immediate_int( struct ureg_program *ureg,
const int *v,
unsigned nr )
{
return decl_immediate(ureg, (const unsigned *)v, nr, TGSI_IMM_INT32);
}
 
 
void
ureg_emit_src( struct ureg_program *ureg,
struct ureg_src src )
{
unsigned size = 1 + (src.Indirect ? 1 : 0) +
(src.Dimension ? (src.DimIndirect ? 2 : 1) : 0);
 
union tgsi_any_token *out = get_tokens( ureg, DOMAIN_INSN, size );
unsigned n = 0;
 
assert(src.File != TGSI_FILE_NULL);
assert(src.File < TGSI_FILE_COUNT);
out[n].value = 0;
out[n].src.File = src.File;
out[n].src.SwizzleX = src.SwizzleX;
out[n].src.SwizzleY = src.SwizzleY;
out[n].src.SwizzleZ = src.SwizzleZ;
out[n].src.SwizzleW = src.SwizzleW;
out[n].src.Index = src.Index;
out[n].src.Negate = src.Negate;
out[0].src.Absolute = src.Absolute;
n++;
 
if (src.Indirect) {
out[0].src.Indirect = 1;
out[n].value = 0;
out[n].ind.File = src.IndirectFile;
out[n].ind.Swizzle = src.IndirectSwizzle;
out[n].ind.Index = src.IndirectIndex;
out[n].ind.ArrayID = src.ArrayID;
n++;
}
 
if (src.Dimension) {
out[0].src.Dimension = 1;
out[n].dim.Dimension = 0;
out[n].dim.Padding = 0;
if (src.DimIndirect) {
out[n].dim.Indirect = 1;
out[n].dim.Index = src.DimensionIndex;
n++;
out[n].value = 0;
out[n].ind.File = src.DimIndFile;
out[n].ind.Swizzle = src.DimIndSwizzle;
out[n].ind.Index = src.DimIndIndex;
out[n].ind.ArrayID = src.ArrayID;
} else {
out[n].dim.Indirect = 0;
out[n].dim.Index = src.DimensionIndex;
}
n++;
}
 
assert(n == size);
}
 
 
void
ureg_emit_dst( struct ureg_program *ureg,
struct ureg_dst dst )
{
unsigned size = (1 +
(dst.Indirect ? 1 : 0));
 
union tgsi_any_token *out = get_tokens( ureg, DOMAIN_INSN, size );
unsigned n = 0;
 
assert(dst.File != TGSI_FILE_NULL);
assert(dst.File != TGSI_FILE_CONSTANT);
assert(dst.File != TGSI_FILE_INPUT);
assert(dst.File != TGSI_FILE_SAMPLER);
assert(dst.File != TGSI_FILE_SAMPLER_VIEW);
assert(dst.File != TGSI_FILE_IMMEDIATE);
assert(dst.File < TGSI_FILE_COUNT);
 
out[n].value = 0;
out[n].dst.File = dst.File;
out[n].dst.WriteMask = dst.WriteMask;
out[n].dst.Indirect = dst.Indirect;
out[n].dst.Index = dst.Index;
n++;
if (dst.Indirect) {
out[n].value = 0;
out[n].ind.File = dst.IndirectFile;
out[n].ind.Swizzle = dst.IndirectSwizzle;
out[n].ind.Index = dst.IndirectIndex;
out[n].ind.ArrayID = dst.ArrayID;
n++;
}
 
assert(n == size);
}
 
 
static void validate( unsigned opcode,
unsigned nr_dst,
unsigned nr_src )
{
#ifdef DEBUG
const struct tgsi_opcode_info *info = tgsi_get_opcode_info( opcode );
assert(info);
if(info) {
assert(nr_dst == info->num_dst);
assert(nr_src == info->num_src);
}
#endif
}
 
struct ureg_emit_insn_result
ureg_emit_insn(struct ureg_program *ureg,
unsigned opcode,
boolean saturate,
boolean predicate,
boolean pred_negate,
unsigned pred_swizzle_x,
unsigned pred_swizzle_y,
unsigned pred_swizzle_z,
unsigned pred_swizzle_w,
unsigned num_dst,
unsigned num_src )
{
union tgsi_any_token *out;
uint count = predicate ? 2 : 1;
struct ureg_emit_insn_result result;
 
validate( opcode, num_dst, num_src );
out = get_tokens( ureg, DOMAIN_INSN, count );
out[0].insn = tgsi_default_instruction();
out[0].insn.Opcode = opcode;
out[0].insn.Saturate = saturate;
out[0].insn.NumDstRegs = num_dst;
out[0].insn.NumSrcRegs = num_src;
 
result.insn_token = ureg->domain[DOMAIN_INSN].count - count;
result.extended_token = result.insn_token;
 
if (predicate) {
out[0].insn.Predicate = 1;
out[1].insn_predicate = tgsi_default_instruction_predicate();
out[1].insn_predicate.Negate = pred_negate;
out[1].insn_predicate.SwizzleX = pred_swizzle_x;
out[1].insn_predicate.SwizzleY = pred_swizzle_y;
out[1].insn_predicate.SwizzleZ = pred_swizzle_z;
out[1].insn_predicate.SwizzleW = pred_swizzle_w;
}
 
ureg->nr_instructions++;
 
return result;
}
 
 
void
ureg_emit_label(struct ureg_program *ureg,
unsigned extended_token,
unsigned *label_token )
{
union tgsi_any_token *out, *insn;
 
if(!label_token)
return;
 
out = get_tokens( ureg, DOMAIN_INSN, 1 );
out[0].value = 0;
 
insn = retrieve_token( ureg, DOMAIN_INSN, extended_token );
insn->insn.Label = 1;
 
*label_token = ureg->domain[DOMAIN_INSN].count - 1;
}
 
/* Will return a number which can be used in a label to point to the
* next instruction to be emitted.
*/
unsigned
ureg_get_instruction_number( struct ureg_program *ureg )
{
return ureg->nr_instructions;
}
 
/* Patch a given label (expressed as a token number) to point to a
* given instruction (expressed as an instruction number).
*/
void
ureg_fixup_label(struct ureg_program *ureg,
unsigned label_token,
unsigned instruction_number )
{
union tgsi_any_token *out = retrieve_token( ureg, DOMAIN_INSN, label_token );
 
out->insn_label.Label = instruction_number;
}
 
 
void
ureg_emit_texture(struct ureg_program *ureg,
unsigned extended_token,
unsigned target, unsigned num_offsets)
{
union tgsi_any_token *out, *insn;
 
out = get_tokens( ureg, DOMAIN_INSN, 1 );
insn = retrieve_token( ureg, DOMAIN_INSN, extended_token );
 
insn->insn.Texture = 1;
 
out[0].value = 0;
out[0].insn_texture.Texture = target;
out[0].insn_texture.NumOffsets = num_offsets;
}
 
void
ureg_emit_texture_offset(struct ureg_program *ureg,
const struct tgsi_texture_offset *offset)
{
union tgsi_any_token *out;
 
out = get_tokens( ureg, DOMAIN_INSN, 1);
 
out[0].value = 0;
out[0].insn_texture_offset = *offset;
}
 
 
void
ureg_fixup_insn_size(struct ureg_program *ureg,
unsigned insn )
{
union tgsi_any_token *out = retrieve_token( ureg, DOMAIN_INSN, insn );
 
assert(out->insn.Type == TGSI_TOKEN_TYPE_INSTRUCTION);
out->insn.NrTokens = ureg->domain[DOMAIN_INSN].count - insn - 1;
}
 
 
void
ureg_insn(struct ureg_program *ureg,
unsigned opcode,
const struct ureg_dst *dst,
unsigned nr_dst,
const struct ureg_src *src,
unsigned nr_src )
{
struct ureg_emit_insn_result insn;
unsigned i;
boolean saturate;
boolean predicate;
boolean negate = FALSE;
unsigned swizzle[4] = { 0 };
 
saturate = nr_dst ? dst[0].Saturate : FALSE;
predicate = nr_dst ? dst[0].Predicate : FALSE;
if (predicate) {
negate = dst[0].PredNegate;
swizzle[0] = dst[0].PredSwizzleX;
swizzle[1] = dst[0].PredSwizzleY;
swizzle[2] = dst[0].PredSwizzleZ;
swizzle[3] = dst[0].PredSwizzleW;
}
 
insn = ureg_emit_insn(ureg,
opcode,
saturate,
predicate,
negate,
swizzle[0],
swizzle[1],
swizzle[2],
swizzle[3],
nr_dst,
nr_src);
 
for (i = 0; i < nr_dst; i++)
ureg_emit_dst( ureg, dst[i] );
 
for (i = 0; i < nr_src; i++)
ureg_emit_src( ureg, src[i] );
 
ureg_fixup_insn_size( ureg, insn.insn_token );
}
 
void
ureg_tex_insn(struct ureg_program *ureg,
unsigned opcode,
const struct ureg_dst *dst,
unsigned nr_dst,
unsigned target,
const struct tgsi_texture_offset *texoffsets,
unsigned nr_offset,
const struct ureg_src *src,
unsigned nr_src )
{
struct ureg_emit_insn_result insn;
unsigned i;
boolean saturate;
boolean predicate;
boolean negate = FALSE;
unsigned swizzle[4] = { 0 };
 
saturate = nr_dst ? dst[0].Saturate : FALSE;
predicate = nr_dst ? dst[0].Predicate : FALSE;
if (predicate) {
negate = dst[0].PredNegate;
swizzle[0] = dst[0].PredSwizzleX;
swizzle[1] = dst[0].PredSwizzleY;
swizzle[2] = dst[0].PredSwizzleZ;
swizzle[3] = dst[0].PredSwizzleW;
}
 
insn = ureg_emit_insn(ureg,
opcode,
saturate,
predicate,
negate,
swizzle[0],
swizzle[1],
swizzle[2],
swizzle[3],
nr_dst,
nr_src);
 
ureg_emit_texture( ureg, insn.extended_token, target, nr_offset );
 
for (i = 0; i < nr_offset; i++)
ureg_emit_texture_offset( ureg, &texoffsets[i]);
 
for (i = 0; i < nr_dst; i++)
ureg_emit_dst( ureg, dst[i] );
 
for (i = 0; i < nr_src; i++)
ureg_emit_src( ureg, src[i] );
 
ureg_fixup_insn_size( ureg, insn.insn_token );
}
 
 
void
ureg_label_insn(struct ureg_program *ureg,
unsigned opcode,
const struct ureg_src *src,
unsigned nr_src,
unsigned *label_token )
{
struct ureg_emit_insn_result insn;
unsigned i;
 
insn = ureg_emit_insn(ureg,
opcode,
FALSE,
FALSE,
FALSE,
TGSI_SWIZZLE_X,
TGSI_SWIZZLE_Y,
TGSI_SWIZZLE_Z,
TGSI_SWIZZLE_W,
0,
nr_src);
 
ureg_emit_label( ureg, insn.extended_token, label_token );
 
for (i = 0; i < nr_src; i++)
ureg_emit_src( ureg, src[i] );
 
ureg_fixup_insn_size( ureg, insn.insn_token );
}
 
 
static void
emit_decl_semantic(struct ureg_program *ureg,
unsigned file,
unsigned index,
unsigned semantic_name,
unsigned semantic_index,
unsigned usage_mask)
{
union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 3);
 
out[0].value = 0;
out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION;
out[0].decl.NrTokens = 3;
out[0].decl.File = file;
out[0].decl.UsageMask = usage_mask;
out[0].decl.Semantic = 1;
 
out[1].value = 0;
out[1].decl_range.First = index;
out[1].decl_range.Last = index;
 
out[2].value = 0;
out[2].decl_semantic.Name = semantic_name;
out[2].decl_semantic.Index = semantic_index;
}
 
 
static void
emit_decl_fs(struct ureg_program *ureg,
unsigned file,
unsigned index,
unsigned semantic_name,
unsigned semantic_index,
unsigned interpolate,
unsigned cylindrical_wrap,
unsigned centroid)
{
union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 4);
 
out[0].value = 0;
out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION;
out[0].decl.NrTokens = 4;
out[0].decl.File = file;
out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW; /* FIXME! */
out[0].decl.Interpolate = 1;
out[0].decl.Semantic = 1;
 
out[1].value = 0;
out[1].decl_range.First = index;
out[1].decl_range.Last = index;
 
out[2].value = 0;
out[2].decl_interp.Interpolate = interpolate;
out[2].decl_interp.CylindricalWrap = cylindrical_wrap;
out[2].decl_interp.Centroid = centroid;
 
out[3].value = 0;
out[3].decl_semantic.Name = semantic_name;
out[3].decl_semantic.Index = semantic_index;
}
 
static void
emit_decl_temps( struct ureg_program *ureg,
unsigned first, unsigned last,
boolean local,
unsigned arrayid )
{
union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL,
arrayid ? 3 : 2 );
 
out[0].value = 0;
out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION;
out[0].decl.NrTokens = 2;
out[0].decl.File = TGSI_FILE_TEMPORARY;
out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW;
out[0].decl.Local = local;
 
out[1].value = 0;
out[1].decl_range.First = first;
out[1].decl_range.Last = last;
 
if (arrayid) {
out[0].decl.Array = 1;
out[2].value = 0;
out[2].array.ArrayID = arrayid;
}
}
 
static void emit_decl_range( struct ureg_program *ureg,
unsigned file,
unsigned first,
unsigned count )
{
union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 2 );
 
out[0].value = 0;
out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION;
out[0].decl.NrTokens = 2;
out[0].decl.File = file;
out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW;
out[0].decl.Semantic = 0;
 
out[1].value = 0;
out[1].decl_range.First = first;
out[1].decl_range.Last = first + count - 1;
}
 
static void
emit_decl_range2D(struct ureg_program *ureg,
unsigned file,
unsigned first,
unsigned last,
unsigned index2D)
{
union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 3);
 
out[0].value = 0;
out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION;
out[0].decl.NrTokens = 3;
out[0].decl.File = file;
out[0].decl.UsageMask = TGSI_WRITEMASK_XYZW;
out[0].decl.Dimension = 1;
 
out[1].value = 0;
out[1].decl_range.First = first;
out[1].decl_range.Last = last;
 
out[2].value = 0;
out[2].decl_dim.Index2D = index2D;
}
 
static void
emit_decl_sampler_view(struct ureg_program *ureg,
unsigned index,
unsigned target,
unsigned return_type_x,
unsigned return_type_y,
unsigned return_type_z,
unsigned return_type_w )
{
union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 3);
 
out[0].value = 0;
out[0].decl.Type = TGSI_TOKEN_TYPE_DECLARATION;
out[0].decl.NrTokens = 3;
out[0].decl.File = TGSI_FILE_SAMPLER_VIEW;
out[0].decl.UsageMask = 0xf;
 
out[1].value = 0;
out[1].decl_range.First = index;
out[1].decl_range.Last = index;
 
out[2].value = 0;
out[2].decl_sampler_view.Resource = target;
out[2].decl_sampler_view.ReturnTypeX = return_type_x;
out[2].decl_sampler_view.ReturnTypeY = return_type_y;
out[2].decl_sampler_view.ReturnTypeZ = return_type_z;
out[2].decl_sampler_view.ReturnTypeW = return_type_w;
}
 
static void
emit_immediate( struct ureg_program *ureg,
const unsigned *v,
unsigned type )
{
union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 5 );
 
out[0].value = 0;
out[0].imm.Type = TGSI_TOKEN_TYPE_IMMEDIATE;
out[0].imm.NrTokens = 5;
out[0].imm.DataType = type;
out[0].imm.Padding = 0;
 
out[1].imm_data.Uint = v[0];
out[2].imm_data.Uint = v[1];
out[3].imm_data.Uint = v[2];
out[4].imm_data.Uint = v[3];
}
 
static void
emit_property(struct ureg_program *ureg,
unsigned name,
unsigned data)
{
union tgsi_any_token *out = get_tokens(ureg, DOMAIN_DECL, 2);
 
out[0].value = 0;
out[0].prop.Type = TGSI_TOKEN_TYPE_PROPERTY;
out[0].prop.NrTokens = 2;
out[0].prop.PropertyName = name;
 
out[1].prop_data.Data = data;
}
 
 
static void emit_decls( struct ureg_program *ureg )
{
unsigned i;
 
if (ureg->property_gs_input_prim != ~0) {
assert(ureg->processor == TGSI_PROCESSOR_GEOMETRY);
 
emit_property(ureg,
TGSI_PROPERTY_GS_INPUT_PRIM,
ureg->property_gs_input_prim);
}
 
if (ureg->property_gs_output_prim != ~0) {
assert(ureg->processor == TGSI_PROCESSOR_GEOMETRY);
 
emit_property(ureg,
TGSI_PROPERTY_GS_OUTPUT_PRIM,
ureg->property_gs_output_prim);
}
 
if (ureg->property_gs_max_vertices != ~0) {
assert(ureg->processor == TGSI_PROCESSOR_GEOMETRY);
 
emit_property(ureg,
TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES,
ureg->property_gs_max_vertices);
}
 
if (ureg->property_fs_coord_origin) {
assert(ureg->processor == TGSI_PROCESSOR_FRAGMENT);
 
emit_property(ureg,
TGSI_PROPERTY_FS_COORD_ORIGIN,
ureg->property_fs_coord_origin);
}
 
if (ureg->property_fs_coord_pixel_center) {
assert(ureg->processor == TGSI_PROCESSOR_FRAGMENT);
 
emit_property(ureg,
TGSI_PROPERTY_FS_COORD_PIXEL_CENTER,
ureg->property_fs_coord_pixel_center);
}
 
if (ureg->property_fs_color0_writes_all_cbufs) {
assert(ureg->processor == TGSI_PROCESSOR_FRAGMENT);
 
emit_property(ureg,
TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS,
ureg->property_fs_color0_writes_all_cbufs);
}
 
if (ureg->property_fs_depth_layout) {
assert(ureg->processor == TGSI_PROCESSOR_FRAGMENT);
 
emit_property(ureg,
TGSI_PROPERTY_FS_DEPTH_LAYOUT,
ureg->property_fs_depth_layout);
}
 
if (ureg->processor == TGSI_PROCESSOR_VERTEX) {
for (i = 0; i < UREG_MAX_INPUT; i++) {
if (ureg->vs_inputs[i/32] & (1 << (i%32))) {
emit_decl_range( ureg, TGSI_FILE_INPUT, i, 1 );
}
}
} else if (ureg->processor == TGSI_PROCESSOR_FRAGMENT) {
for (i = 0; i < ureg->nr_fs_inputs; i++) {
emit_decl_fs(ureg,
TGSI_FILE_INPUT,
i,
ureg->fs_input[i].semantic_name,
ureg->fs_input[i].semantic_index,
ureg->fs_input[i].interp,
ureg->fs_input[i].cylindrical_wrap,
ureg->fs_input[i].centroid);
}
} else {
for (i = 0; i < ureg->nr_gs_inputs; i++) {
emit_decl_semantic(ureg,
TGSI_FILE_INPUT,
ureg->gs_input[i].index,
ureg->gs_input[i].semantic_name,
ureg->gs_input[i].semantic_index,
TGSI_WRITEMASK_XYZW);
}
}
 
for (i = 0; i < ureg->nr_system_values; i++) {
emit_decl_semantic(ureg,
TGSI_FILE_SYSTEM_VALUE,
ureg->system_value[i].index,
ureg->system_value[i].semantic_name,
ureg->system_value[i].semantic_index,
TGSI_WRITEMASK_XYZW);
}
 
for (i = 0; i < ureg->nr_outputs; i++) {
emit_decl_semantic(ureg,
TGSI_FILE_OUTPUT,
i,
ureg->output[i].semantic_name,
ureg->output[i].semantic_index,
ureg->output[i].usage_mask);
}
 
for (i = 0; i < ureg->nr_samplers; i++) {
emit_decl_range( ureg,
TGSI_FILE_SAMPLER,
ureg->sampler[i].Index, 1 );
}
 
for (i = 0; i < ureg->nr_sampler_views; i++) {
emit_decl_sampler_view(ureg,
ureg->sampler_view[i].index,
ureg->sampler_view[i].target,
ureg->sampler_view[i].return_type_x,
ureg->sampler_view[i].return_type_y,
ureg->sampler_view[i].return_type_z,
ureg->sampler_view[i].return_type_w);
}
 
if (ureg->const_decls.nr_constant_ranges) {
for (i = 0; i < ureg->const_decls.nr_constant_ranges; i++) {
emit_decl_range(ureg,
TGSI_FILE_CONSTANT,
ureg->const_decls.constant_range[i].first,
ureg->const_decls.constant_range[i].last - ureg->const_decls.constant_range[i].first + 1);
}
}
 
for (i = 0; i < PIPE_MAX_CONSTANT_BUFFERS; i++) {
struct const_decl *decl = &ureg->const_decls2D[i];
 
if (decl->nr_constant_ranges) {
uint j;
 
for (j = 0; j < decl->nr_constant_ranges; j++) {
emit_decl_range2D(ureg,
TGSI_FILE_CONSTANT,
decl->constant_range[j].first,
decl->constant_range[j].last,
i);
}
}
}
 
if (ureg->nr_temps) {
unsigned array = 0;
for (i = 0; i < ureg->nr_temps;) {
boolean local = util_bitmask_get(ureg->local_temps, i);
unsigned first = i;
i = util_bitmask_get_next_index(ureg->decl_temps, i + 1);
if (i == UTIL_BITMASK_INVALID_INDEX)
i = ureg->nr_temps;
 
if (array < ureg->nr_array_temps && ureg->array_temps[array] == first)
emit_decl_temps( ureg, first, i - 1, local, ++array );
else
emit_decl_temps( ureg, first, i - 1, local, 0 );
}
}
 
if (ureg->nr_addrs) {
emit_decl_range( ureg,
TGSI_FILE_ADDRESS,
0, ureg->nr_addrs );
}
 
if (ureg->nr_preds) {
emit_decl_range(ureg,
TGSI_FILE_PREDICATE,
0,
ureg->nr_preds);
}
 
for (i = 0; i < ureg->nr_immediates; i++) {
emit_immediate( ureg,
ureg->immediate[i].value.u,
ureg->immediate[i].type );
}
}
 
/* Append the instruction tokens onto the declarations to build a
* contiguous stream suitable to send to the driver.
*/
static void copy_instructions( struct ureg_program *ureg )
{
unsigned nr_tokens = ureg->domain[DOMAIN_INSN].count;
union tgsi_any_token *out = get_tokens( ureg,
DOMAIN_DECL,
nr_tokens );
 
memcpy(out,
ureg->domain[DOMAIN_INSN].tokens,
nr_tokens * sizeof out[0] );
}
 
 
static void
fixup_header_size(struct ureg_program *ureg)
{
union tgsi_any_token *out = retrieve_token( ureg, DOMAIN_DECL, 0 );
 
out->header.BodySize = ureg->domain[DOMAIN_DECL].count - 2;
}
 
 
static void
emit_header( struct ureg_program *ureg )
{
union tgsi_any_token *out = get_tokens( ureg, DOMAIN_DECL, 2 );
 
out[0].header.HeaderSize = 2;
out[0].header.BodySize = 0;
 
out[1].processor.Processor = ureg->processor;
out[1].processor.Padding = 0;
}
 
 
const struct tgsi_token *ureg_finalize( struct ureg_program *ureg )
{
const struct tgsi_token *tokens;
 
emit_header( ureg );
emit_decls( ureg );
copy_instructions( ureg );
fixup_header_size( ureg );
if (ureg->domain[0].tokens == error_tokens ||
ureg->domain[1].tokens == error_tokens) {
debug_printf("%s: error in generated shader\n", __FUNCTION__);
assert(0);
return NULL;
}
 
tokens = &ureg->domain[DOMAIN_DECL].tokens[0].token;
 
if (0) {
debug_printf("%s: emitted shader %d tokens:\n", __FUNCTION__,
ureg->domain[DOMAIN_DECL].count);
tgsi_dump( tokens, 0 );
}
 
#if DEBUG
if (tokens && !tgsi_sanity_check(tokens)) {
debug_printf("tgsi_ureg.c, sanity check failed on generated tokens:\n");
tgsi_dump(tokens, 0);
assert(0);
}
#endif
 
return tokens;
}
 
 
void *ureg_create_shader( struct ureg_program *ureg,
struct pipe_context *pipe,
const struct pipe_stream_output_info *so )
{
struct pipe_shader_state state;
 
state.tokens = ureg_finalize(ureg);
if(!state.tokens)
return NULL;
 
if (so)
state.stream_output = *so;
else
memset(&state.stream_output, 0, sizeof(state.stream_output));
 
if (ureg->processor == TGSI_PROCESSOR_VERTEX)
return pipe->create_vs_state( pipe, &state );
else
return pipe->create_fs_state( pipe, &state );
}
 
 
const struct tgsi_token *ureg_get_tokens( struct ureg_program *ureg,
unsigned *nr_tokens )
{
const struct tgsi_token *tokens;
 
ureg_finalize(ureg);
 
tokens = &ureg->domain[DOMAIN_DECL].tokens[0].token;
 
if (nr_tokens)
*nr_tokens = ureg->domain[DOMAIN_DECL].size;
 
ureg->domain[DOMAIN_DECL].tokens = 0;
ureg->domain[DOMAIN_DECL].size = 0;
ureg->domain[DOMAIN_DECL].order = 0;
ureg->domain[DOMAIN_DECL].count = 0;
 
return tokens;
}
 
 
void ureg_free_tokens( const struct tgsi_token *tokens )
{
FREE((struct tgsi_token *)tokens);
}
 
 
struct ureg_program *ureg_create( unsigned processor )
{
struct ureg_program *ureg = CALLOC_STRUCT( ureg_program );
if (ureg == NULL)
goto no_ureg;
 
ureg->processor = processor;
ureg->property_gs_input_prim = ~0;
ureg->property_gs_output_prim = ~0;
ureg->property_gs_max_vertices = ~0;
 
ureg->free_temps = util_bitmask_create();
if (ureg->free_temps == NULL)
goto no_free_temps;
 
ureg->local_temps = util_bitmask_create();
if (ureg->local_temps == NULL)
goto no_local_temps;
 
ureg->decl_temps = util_bitmask_create();
if (ureg->decl_temps == NULL)
goto no_decl_temps;
 
return ureg;
 
no_decl_temps:
util_bitmask_destroy(ureg->local_temps);
no_local_temps:
util_bitmask_destroy(ureg->free_temps);
no_free_temps:
FREE(ureg);
no_ureg:
return NULL;
}
 
 
const unsigned
ureg_get_nr_outputs( const struct ureg_program *ureg )
{
if (!ureg)
return 0;
return ureg->nr_outputs;
}
 
 
void ureg_destroy( struct ureg_program *ureg )
{
unsigned i;
 
for (i = 0; i < Elements(ureg->domain); i++) {
if (ureg->domain[i].tokens &&
ureg->domain[i].tokens != error_tokens)
FREE(ureg->domain[i].tokens);
}
 
util_bitmask_destroy(ureg->free_temps);
util_bitmask_destroy(ureg->local_temps);
util_bitmask_destroy(ureg->decl_temps);
 
FREE(ureg);
}
/drivers/video/Gallium/auxiliary/tgsi/tgsi_ureg.h
0,0 → 1,1278
/**************************************************************************
*
* Copyright 2009 VMware, Inc.
* 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 VMWARE, INC 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.
*
**************************************************************************/
 
#ifndef TGSI_UREG_H
#define TGSI_UREG_H
 
#include "pipe/p_compiler.h"
#include "pipe/p_shader_tokens.h"
#include "util/u_debug.h"
 
#ifdef __cplusplus
extern "C" {
#endif
struct ureg_program;
struct pipe_stream_output_info;
 
/* Almost a tgsi_src_register, but we need to pull in the Absolute
* flag from the _ext token. Indirect flag always implies ADDR[0].
*/
struct ureg_src
{
unsigned File : 4; /* TGSI_FILE_ */
unsigned SwizzleX : 2; /* TGSI_SWIZZLE_ */
unsigned SwizzleY : 2; /* TGSI_SWIZZLE_ */
unsigned SwizzleZ : 2; /* TGSI_SWIZZLE_ */
unsigned SwizzleW : 2; /* TGSI_SWIZZLE_ */
unsigned Indirect : 1; /* BOOL */
unsigned DimIndirect : 1; /* BOOL */
unsigned Dimension : 1; /* BOOL */
unsigned Absolute : 1; /* BOOL */
unsigned Negate : 1; /* BOOL */
unsigned IndirectFile : 4; /* TGSI_FILE_ */
unsigned IndirectSwizzle : 2; /* TGSI_SWIZZLE_ */
unsigned DimIndFile : 4; /* TGSI_FILE_ */
unsigned DimIndSwizzle : 2; /* TGSI_SWIZZLE_ */
int Index : 16; /* SINT */
int IndirectIndex : 16; /* SINT */
int DimensionIndex : 16; /* SINT */
int DimIndIndex : 16; /* SINT */
unsigned ArrayID : 10; /* UINT */
};
 
/* Very similar to a tgsi_dst_register, removing unsupported fields
* and adding a Saturate flag. It's easier to push saturate into the
* destination register than to try and create a _SAT variant of each
* instruction function.
*/
struct ureg_dst
{
unsigned File : 4; /* TGSI_FILE_ */
unsigned WriteMask : 4; /* TGSI_WRITEMASK_ */
unsigned Indirect : 1; /* BOOL */
unsigned Saturate : 1; /* BOOL */
unsigned Predicate : 1;
unsigned PredNegate : 1; /* BOOL */
unsigned PredSwizzleX : 2; /* TGSI_SWIZZLE_ */
unsigned PredSwizzleY : 2; /* TGSI_SWIZZLE_ */
unsigned PredSwizzleZ : 2; /* TGSI_SWIZZLE_ */
unsigned PredSwizzleW : 2; /* TGSI_SWIZZLE_ */
int Index : 16; /* SINT */
int IndirectIndex : 16; /* SINT */
unsigned IndirectFile : 4; /* TGSI_FILE_ */
int IndirectSwizzle : 2; /* TGSI_SWIZZLE_ */
unsigned ArrayID : 10; /* UINT */
};
 
struct pipe_context;
 
struct ureg_program *
ureg_create( unsigned processor );
 
const struct tgsi_token *
ureg_finalize( struct ureg_program * );
 
/* Create and return a shader:
*/
void *
ureg_create_shader( struct ureg_program *,
struct pipe_context *pipe,
const struct pipe_stream_output_info *so );
 
 
/* Alternately, return the built token stream and hand ownership of
* that memory to the caller:
*/
const struct tgsi_token *
ureg_get_tokens( struct ureg_program *ureg,
unsigned *nr_tokens );
 
/*
* Returns the number of currently declared outputs.
*/
const unsigned
ureg_get_nr_outputs( const struct ureg_program *ureg );
 
 
/* Free the tokens created by ureg_get_tokens() */
void ureg_free_tokens( const struct tgsi_token *tokens );
 
 
void
ureg_destroy( struct ureg_program * );
 
 
/***********************************************************************
* Convenience routine:
*/
static INLINE void *
ureg_create_shader_with_so_and_destroy( struct ureg_program *p,
struct pipe_context *pipe,
const struct pipe_stream_output_info *so )
{
void *result = ureg_create_shader( p, pipe, so );
ureg_destroy( p );
return result;
}
 
static INLINE void *
ureg_create_shader_and_destroy( struct ureg_program *p,
struct pipe_context *pipe )
{
return ureg_create_shader_with_so_and_destroy(p, pipe, NULL);
}
 
 
/***********************************************************************
* Build shader properties:
*/
 
void
ureg_property_gs_input_prim(struct ureg_program *ureg,
unsigned input_prim);
 
void
ureg_property_gs_output_prim(struct ureg_program *ureg,
unsigned output_prim);
 
void
ureg_property_gs_max_vertices(struct ureg_program *ureg,
unsigned max_vertices);
 
void
ureg_property_fs_coord_origin(struct ureg_program *ureg,
unsigned fs_coord_origin);
 
void
ureg_property_fs_coord_pixel_center(struct ureg_program *ureg,
unsigned fs_coord_pixel_center);
 
void
ureg_property_fs_color0_writes_all_cbufs(struct ureg_program *ureg,
unsigned fs_color0_writes_all_cbufs);
 
void
ureg_property_fs_depth_layout(struct ureg_program *ureg,
unsigned fs_depth_layout);
 
 
/***********************************************************************
* Build shader declarations:
*/
 
struct ureg_src
ureg_DECL_fs_input_cyl_centroid(struct ureg_program *,
unsigned semantic_name,
unsigned semantic_index,
unsigned interp_mode,
unsigned cylindrical_wrap,
unsigned centroid);
 
static INLINE struct ureg_src
ureg_DECL_fs_input_cyl(struct ureg_program *ureg,
unsigned semantic_name,
unsigned semantic_index,
unsigned interp_mode,
unsigned cylindrical_wrap)
{
return ureg_DECL_fs_input_cyl_centroid(ureg,
semantic_name,
semantic_index,
interp_mode,
cylindrical_wrap,
0);
}
 
static INLINE struct ureg_src
ureg_DECL_fs_input(struct ureg_program *ureg,
unsigned semantic_name,
unsigned semantic_index,
unsigned interp_mode)
{
return ureg_DECL_fs_input_cyl_centroid(ureg,
semantic_name,
semantic_index,
interp_mode,
0, 0);
}
 
struct ureg_src
ureg_DECL_vs_input( struct ureg_program *,
unsigned index );
 
struct ureg_src
ureg_DECL_gs_input(struct ureg_program *,
unsigned index,
unsigned semantic_name,
unsigned semantic_index);
 
struct ureg_src
ureg_DECL_system_value(struct ureg_program *,
unsigned index,
unsigned semantic_name,
unsigned semantic_index);
 
struct ureg_dst
ureg_DECL_output_masked( struct ureg_program *,
unsigned semantic_name,
unsigned semantic_index,
unsigned usage_mask );
 
struct ureg_dst
ureg_DECL_output( struct ureg_program *,
unsigned semantic_name,
unsigned semantic_index );
 
struct ureg_src
ureg_DECL_immediate( struct ureg_program *,
const float *v,
unsigned nr );
 
struct ureg_src
ureg_DECL_immediate_uint( struct ureg_program *,
const unsigned *v,
unsigned nr );
 
struct ureg_src
ureg_DECL_immediate_block_uint( struct ureg_program *,
const unsigned *v,
unsigned nr );
 
struct ureg_src
ureg_DECL_immediate_int( struct ureg_program *,
const int *v,
unsigned nr );
 
void
ureg_DECL_constant2D(struct ureg_program *ureg,
unsigned first,
unsigned last,
unsigned index2D);
 
struct ureg_src
ureg_DECL_constant( struct ureg_program *,
unsigned index );
 
struct ureg_dst
ureg_DECL_temporary( struct ureg_program * );
 
/**
* Emit a temporary with the LOCAL declaration flag set. For use when
* the register value is not required to be preserved across
* subroutine boundaries.
*/
struct ureg_dst
ureg_DECL_local_temporary( struct ureg_program * );
 
/**
* Declare "size" continuous temporary registers.
*/
struct ureg_dst
ureg_DECL_array_temporary( struct ureg_program *,
unsigned size,
boolean local );
 
void
ureg_release_temporary( struct ureg_program *ureg,
struct ureg_dst tmp );
 
struct ureg_dst
ureg_DECL_address( struct ureg_program * );
 
struct ureg_dst
ureg_DECL_predicate(struct ureg_program *);
 
/* Supply an index to the sampler declaration as this is the hook to
* the external pipe_sampler state. Users of this function probably
* don't want just any sampler, but a specific one which they've set
* up state for in the context.
*/
struct ureg_src
ureg_DECL_sampler( struct ureg_program *,
unsigned index );
 
struct ureg_src
ureg_DECL_sampler_view(struct ureg_program *,
unsigned index,
unsigned target,
unsigned return_type_x,
unsigned return_type_y,
unsigned return_type_z,
unsigned return_type_w );
 
 
static INLINE struct ureg_src
ureg_imm4f( struct ureg_program *ureg,
float a, float b,
float c, float d)
{
float v[4];
v[0] = a;
v[1] = b;
v[2] = c;
v[3] = d;
return ureg_DECL_immediate( ureg, v, 4 );
}
 
static INLINE struct ureg_src
ureg_imm3f( struct ureg_program *ureg,
float a, float b,
float c)
{
float v[3];
v[0] = a;
v[1] = b;
v[2] = c;
return ureg_DECL_immediate( ureg, v, 3 );
}
 
static INLINE struct ureg_src
ureg_imm2f( struct ureg_program *ureg,
float a, float b)
{
float v[2];
v[0] = a;
v[1] = b;
return ureg_DECL_immediate( ureg, v, 2 );
}
 
static INLINE struct ureg_src
ureg_imm1f( struct ureg_program *ureg,
float a)
{
float v[1];
v[0] = a;
return ureg_DECL_immediate( ureg, v, 1 );
}
 
static INLINE struct ureg_src
ureg_imm4u( struct ureg_program *ureg,
unsigned a, unsigned b,
unsigned c, unsigned d)
{
unsigned v[4];
v[0] = a;
v[1] = b;
v[2] = c;
v[3] = d;
return ureg_DECL_immediate_uint( ureg, v, 4 );
}
 
static INLINE struct ureg_src
ureg_imm3u( struct ureg_program *ureg,
unsigned a, unsigned b,
unsigned c)
{
unsigned v[3];
v[0] = a;
v[1] = b;
v[2] = c;
return ureg_DECL_immediate_uint( ureg, v, 3 );
}
 
static INLINE struct ureg_src
ureg_imm2u( struct ureg_program *ureg,
unsigned a, unsigned b)
{
unsigned v[2];
v[0] = a;
v[1] = b;
return ureg_DECL_immediate_uint( ureg, v, 2 );
}
 
static INLINE struct ureg_src
ureg_imm1u( struct ureg_program *ureg,
unsigned a)
{
return ureg_DECL_immediate_uint( ureg, &a, 1 );
}
 
static INLINE struct ureg_src
ureg_imm4i( struct ureg_program *ureg,
int a, int b,
int c, int d)
{
int v[4];
v[0] = a;
v[1] = b;
v[2] = c;
v[3] = d;
return ureg_DECL_immediate_int( ureg, v, 4 );
}
 
static INLINE struct ureg_src
ureg_imm3i( struct ureg_program *ureg,
int a, int b,
int c)
{
int v[3];
v[0] = a;
v[1] = b;
v[2] = c;
return ureg_DECL_immediate_int( ureg, v, 3 );
}
 
static INLINE struct ureg_src
ureg_imm2i( struct ureg_program *ureg,
int a, int b)
{
int v[2];
v[0] = a;
v[1] = b;
return ureg_DECL_immediate_int( ureg, v, 2 );
}
 
static INLINE struct ureg_src
ureg_imm1i( struct ureg_program *ureg,
int a)
{
return ureg_DECL_immediate_int( ureg, &a, 1 );
}
 
/***********************************************************************
* Functions for patching up labels
*/
 
 
/* Will return a number which can be used in a label to point to the
* next instruction to be emitted.
*/
unsigned
ureg_get_instruction_number( struct ureg_program *ureg );
 
 
/* Patch a given label (expressed as a token number) to point to a
* given instruction (expressed as an instruction number).
*
* Labels are obtained from instruction emitters, eg ureg_CAL().
* Instruction numbers are obtained from ureg_get_instruction_number(),
* above.
*/
void
ureg_fixup_label(struct ureg_program *ureg,
unsigned label_token,
unsigned instruction_number );
 
 
/* Generic instruction emitter. Use if you need to pass the opcode as
* a parameter, rather than using the emit_OP() variants below.
*/
void
ureg_insn(struct ureg_program *ureg,
unsigned opcode,
const struct ureg_dst *dst,
unsigned nr_dst,
const struct ureg_src *src,
unsigned nr_src );
 
 
void
ureg_tex_insn(struct ureg_program *ureg,
unsigned opcode,
const struct ureg_dst *dst,
unsigned nr_dst,
unsigned target,
const struct tgsi_texture_offset *texoffsets,
unsigned nr_offset,
const struct ureg_src *src,
unsigned nr_src );
 
 
void
ureg_label_insn(struct ureg_program *ureg,
unsigned opcode,
const struct ureg_src *src,
unsigned nr_src,
unsigned *label);
 
 
/***********************************************************************
* Internal instruction helpers, don't call these directly:
*/
 
struct ureg_emit_insn_result {
unsigned insn_token; /*< Used to fixup insn size. */
unsigned extended_token; /*< Used to set the Extended bit, usually the same as insn_token. */
};
 
struct ureg_emit_insn_result
ureg_emit_insn(struct ureg_program *ureg,
unsigned opcode,
boolean saturate,
boolean predicate,
boolean pred_negate,
unsigned pred_swizzle_x,
unsigned pred_swizzle_y,
unsigned pred_swizzle_z,
unsigned pred_swizzle_w,
unsigned num_dst,
unsigned num_src );
 
void
ureg_emit_label(struct ureg_program *ureg,
unsigned insn_token,
unsigned *label_token );
 
void
ureg_emit_texture(struct ureg_program *ureg,
unsigned insn_token,
unsigned target, unsigned num_offsets);
 
void
ureg_emit_texture_offset(struct ureg_program *ureg,
const struct tgsi_texture_offset *offset);
 
void
ureg_emit_dst( struct ureg_program *ureg,
struct ureg_dst dst );
 
void
ureg_emit_src( struct ureg_program *ureg,
struct ureg_src src );
 
void
ureg_fixup_insn_size(struct ureg_program *ureg,
unsigned insn );
 
 
#define OP00( op ) \
static INLINE void ureg_##op( struct ureg_program *ureg ) \
{ \
unsigned opcode = TGSI_OPCODE_##op; \
unsigned insn = ureg_emit_insn(ureg, \
opcode, \
FALSE, \
FALSE, \
FALSE, \
TGSI_SWIZZLE_X, \
TGSI_SWIZZLE_Y, \
TGSI_SWIZZLE_Z, \
TGSI_SWIZZLE_W, \
0, \
0).insn_token; \
ureg_fixup_insn_size( ureg, insn ); \
}
 
#define OP01( op ) \
static INLINE void ureg_##op( struct ureg_program *ureg, \
struct ureg_src src ) \
{ \
unsigned opcode = TGSI_OPCODE_##op; \
unsigned insn = ureg_emit_insn(ureg, \
opcode, \
FALSE, \
FALSE, \
FALSE, \
TGSI_SWIZZLE_X, \
TGSI_SWIZZLE_Y, \
TGSI_SWIZZLE_Z, \
TGSI_SWIZZLE_W, \
0, \
1).insn_token; \
ureg_emit_src( ureg, src ); \
ureg_fixup_insn_size( ureg, insn ); \
}
 
#define OP00_LBL( op ) \
static INLINE void ureg_##op( struct ureg_program *ureg, \
unsigned *label_token ) \
{ \
unsigned opcode = TGSI_OPCODE_##op; \
struct ureg_emit_insn_result insn; \
insn = ureg_emit_insn(ureg, \
opcode, \
FALSE, \
FALSE, \
FALSE, \
TGSI_SWIZZLE_X, \
TGSI_SWIZZLE_Y, \
TGSI_SWIZZLE_Z, \
TGSI_SWIZZLE_W, \
0, \
0); \
ureg_emit_label( ureg, insn.extended_token, label_token ); \
ureg_fixup_insn_size( ureg, insn.insn_token ); \
}
 
#define OP01_LBL( op ) \
static INLINE void ureg_##op( struct ureg_program *ureg, \
struct ureg_src src, \
unsigned *label_token ) \
{ \
unsigned opcode = TGSI_OPCODE_##op; \
struct ureg_emit_insn_result insn; \
insn = ureg_emit_insn(ureg, \
opcode, \
FALSE, \
FALSE, \
FALSE, \
TGSI_SWIZZLE_X, \
TGSI_SWIZZLE_Y, \
TGSI_SWIZZLE_Z, \
TGSI_SWIZZLE_W, \
0, \
1); \
ureg_emit_label( ureg, insn.extended_token, label_token ); \
ureg_emit_src( ureg, src ); \
ureg_fixup_insn_size( ureg, insn.insn_token ); \
}
 
#define OP10( op ) \
static INLINE void ureg_##op( struct ureg_program *ureg, \
struct ureg_dst dst ) \
{ \
unsigned opcode = TGSI_OPCODE_##op; \
unsigned insn = ureg_emit_insn(ureg, \
opcode, \
dst.Saturate, \
dst.Predicate, \
dst.PredNegate, \
dst.PredSwizzleX, \
dst.PredSwizzleY, \
dst.PredSwizzleZ, \
dst.PredSwizzleW, \
1, \
0).insn_token; \
ureg_emit_dst( ureg, dst ); \
ureg_fixup_insn_size( ureg, insn ); \
}
 
 
#define OP11( op ) \
static INLINE void ureg_##op( struct ureg_program *ureg, \
struct ureg_dst dst, \
struct ureg_src src ) \
{ \
unsigned opcode = TGSI_OPCODE_##op; \
unsigned insn = ureg_emit_insn(ureg, \
opcode, \
dst.Saturate, \
dst.Predicate, \
dst.PredNegate, \
dst.PredSwizzleX, \
dst.PredSwizzleY, \
dst.PredSwizzleZ, \
dst.PredSwizzleW, \
1, \
1).insn_token; \
ureg_emit_dst( ureg, dst ); \
ureg_emit_src( ureg, src ); \
ureg_fixup_insn_size( ureg, insn ); \
}
 
#define OP12( op ) \
static INLINE void ureg_##op( struct ureg_program *ureg, \
struct ureg_dst dst, \
struct ureg_src src0, \
struct ureg_src src1 ) \
{ \
unsigned opcode = TGSI_OPCODE_##op; \
unsigned insn = ureg_emit_insn(ureg, \
opcode, \
dst.Saturate, \
dst.Predicate, \
dst.PredNegate, \
dst.PredSwizzleX, \
dst.PredSwizzleY, \
dst.PredSwizzleZ, \
dst.PredSwizzleW, \
1, \
2).insn_token; \
ureg_emit_dst( ureg, dst ); \
ureg_emit_src( ureg, src0 ); \
ureg_emit_src( ureg, src1 ); \
ureg_fixup_insn_size( ureg, insn ); \
}
 
#define OP12_TEX( op ) \
static INLINE void ureg_##op( struct ureg_program *ureg, \
struct ureg_dst dst, \
unsigned target, \
struct ureg_src src0, \
struct ureg_src src1 ) \
{ \
unsigned opcode = TGSI_OPCODE_##op; \
struct ureg_emit_insn_result insn; \
insn = ureg_emit_insn(ureg, \
opcode, \
dst.Saturate, \
dst.Predicate, \
dst.PredNegate, \
dst.PredSwizzleX, \
dst.PredSwizzleY, \
dst.PredSwizzleZ, \
dst.PredSwizzleW, \
1, \
2); \
ureg_emit_texture( ureg, insn.extended_token, target, 0 ); \
ureg_emit_dst( ureg, dst ); \
ureg_emit_src( ureg, src0 ); \
ureg_emit_src( ureg, src1 ); \
ureg_fixup_insn_size( ureg, insn.insn_token ); \
}
 
#define OP12_SAMPLE( op ) \
static INLINE void ureg_##op( struct ureg_program *ureg, \
struct ureg_dst dst, \
struct ureg_src src0, \
struct ureg_src src1 ) \
{ \
unsigned opcode = TGSI_OPCODE_##op; \
unsigned target = TGSI_TEXTURE_UNKNOWN; \
struct ureg_emit_insn_result insn; \
insn = ureg_emit_insn(ureg, \
opcode, \
dst.Saturate, \
dst.Predicate, \
dst.PredNegate, \
dst.PredSwizzleX, \
dst.PredSwizzleY, \
dst.PredSwizzleZ, \
dst.PredSwizzleW, \
1, \
2); \
ureg_emit_texture( ureg, insn.extended_token, target, 0 ); \
ureg_emit_dst( ureg, dst ); \
ureg_emit_src( ureg, src0 ); \
ureg_emit_src( ureg, src1 ); \
ureg_fixup_insn_size( ureg, insn.insn_token ); \
}
 
#define OP13( op ) \
static INLINE void ureg_##op( struct ureg_program *ureg, \
struct ureg_dst dst, \
struct ureg_src src0, \
struct ureg_src src1, \
struct ureg_src src2 ) \
{ \
unsigned opcode = TGSI_OPCODE_##op; \
unsigned insn = ureg_emit_insn(ureg, \
opcode, \
dst.Saturate, \
dst.Predicate, \
dst.PredNegate, \
dst.PredSwizzleX, \
dst.PredSwizzleY, \
dst.PredSwizzleZ, \
dst.PredSwizzleW, \
1, \
3).insn_token; \
ureg_emit_dst( ureg, dst ); \
ureg_emit_src( ureg, src0 ); \
ureg_emit_src( ureg, src1 ); \
ureg_emit_src( ureg, src2 ); \
ureg_fixup_insn_size( ureg, insn ); \
}
 
#define OP13_SAMPLE( op ) \
static INLINE void ureg_##op( struct ureg_program *ureg, \
struct ureg_dst dst, \
struct ureg_src src0, \
struct ureg_src src1, \
struct ureg_src src2 ) \
{ \
unsigned opcode = TGSI_OPCODE_##op; \
unsigned target = TGSI_TEXTURE_UNKNOWN; \
struct ureg_emit_insn_result insn; \
insn = ureg_emit_insn(ureg, \
opcode, \
dst.Saturate, \
dst.Predicate, \
dst.PredNegate, \
dst.PredSwizzleX, \
dst.PredSwizzleY, \
dst.PredSwizzleZ, \
dst.PredSwizzleW, \
1, \
3); \
ureg_emit_texture( ureg, insn.extended_token, target, 0 ); \
ureg_emit_dst( ureg, dst ); \
ureg_emit_src( ureg, src0 ); \
ureg_emit_src( ureg, src1 ); \
ureg_emit_src( ureg, src2 ); \
ureg_fixup_insn_size( ureg, insn.insn_token ); \
}
 
#define OP14_TEX( op ) \
static INLINE void ureg_##op( struct ureg_program *ureg, \
struct ureg_dst dst, \
unsigned target, \
struct ureg_src src0, \
struct ureg_src src1, \
struct ureg_src src2, \
struct ureg_src src3 ) \
{ \
unsigned opcode = TGSI_OPCODE_##op; \
struct ureg_emit_insn_result insn; \
insn = ureg_emit_insn(ureg, \
opcode, \
dst.Saturate, \
dst.Predicate, \
dst.PredNegate, \
dst.PredSwizzleX, \
dst.PredSwizzleY, \
dst.PredSwizzleZ, \
dst.PredSwizzleW, \
1, \
4); \
ureg_emit_texture( ureg, insn.extended_token, target, 0 ); \
ureg_emit_dst( ureg, dst ); \
ureg_emit_src( ureg, src0 ); \
ureg_emit_src( ureg, src1 ); \
ureg_emit_src( ureg, src2 ); \
ureg_emit_src( ureg, src3 ); \
ureg_fixup_insn_size( ureg, insn.insn_token ); \
}
 
#define OP14_SAMPLE( op ) \
static INLINE void ureg_##op( struct ureg_program *ureg, \
struct ureg_dst dst, \
struct ureg_src src0, \
struct ureg_src src1, \
struct ureg_src src2, \
struct ureg_src src3 ) \
{ \
unsigned opcode = TGSI_OPCODE_##op; \
unsigned target = TGSI_TEXTURE_UNKNOWN; \
struct ureg_emit_insn_result insn; \
insn = ureg_emit_insn(ureg, \
opcode, \
dst.Saturate, \
dst.Predicate, \
dst.PredNegate, \
dst.PredSwizzleX, \
dst.PredSwizzleY, \
dst.PredSwizzleZ, \
dst.PredSwizzleW, \
1, \
4); \
ureg_emit_texture( ureg, insn.extended_token, target, 0 ); \
ureg_emit_dst( ureg, dst ); \
ureg_emit_src( ureg, src0 ); \
ureg_emit_src( ureg, src1 ); \
ureg_emit_src( ureg, src2 ); \
ureg_emit_src( ureg, src3 ); \
ureg_fixup_insn_size( ureg, insn.insn_token ); \
}
 
 
#define OP14( op ) \
static INLINE void ureg_##op( struct ureg_program *ureg, \
struct ureg_dst dst, \
struct ureg_src src0, \
struct ureg_src src1, \
struct ureg_src src2, \
struct ureg_src src3 ) \
{ \
unsigned opcode = TGSI_OPCODE_##op; \
unsigned insn = ureg_emit_insn(ureg, \
opcode, \
dst.Saturate, \
dst.Predicate, \
dst.PredNegate, \
dst.PredSwizzleX, \
dst.PredSwizzleY, \
dst.PredSwizzleZ, \
dst.PredSwizzleW, \
1, \
4).insn_token; \
ureg_emit_dst( ureg, dst ); \
ureg_emit_src( ureg, src0 ); \
ureg_emit_src( ureg, src1 ); \
ureg_emit_src( ureg, src2 ); \
ureg_emit_src( ureg, src3 ); \
ureg_fixup_insn_size( ureg, insn ); \
}
 
 
#define OP15( op ) \
static INLINE void ureg_##op( struct ureg_program *ureg, \
struct ureg_dst dst, \
struct ureg_src src0, \
struct ureg_src src1, \
struct ureg_src src2, \
struct ureg_src src3, \
struct ureg_src src4 ) \
{ \
unsigned opcode = TGSI_OPCODE_##op; \
unsigned insn = ureg_emit_insn(ureg, \
opcode, \
dst.Saturate, \
dst.Predicate, \
dst.PredNegate, \
dst.PredSwizzleX, \
dst.PredSwizzleY, \
dst.PredSwizzleZ, \
dst.PredSwizzleW, \
1, \
5).insn_token; \
ureg_emit_dst( ureg, dst ); \
ureg_emit_src( ureg, src0 ); \
ureg_emit_src( ureg, src1 ); \
ureg_emit_src( ureg, src2 ); \
ureg_emit_src( ureg, src3 ); \
ureg_emit_src( ureg, src4 ); \
ureg_fixup_insn_size( ureg, insn ); \
}
 
#define OP15_SAMPLE( op ) \
static INLINE void ureg_##op( struct ureg_program *ureg, \
struct ureg_dst dst, \
struct ureg_src src0, \
struct ureg_src src1, \
struct ureg_src src2, \
struct ureg_src src3, \
struct ureg_src src4 ) \
{ \
unsigned opcode = TGSI_OPCODE_##op; \
unsigned target = TGSI_TEXTURE_UNKNOWN; \
struct ureg_emit_insn_result insn; \
insn = ureg_emit_insn(ureg, \
opcode, \
dst.Saturate, \
dst.Predicate, \
dst.PredNegate, \
dst.PredSwizzleX, \
dst.PredSwizzleY, \
dst.PredSwizzleZ, \
dst.PredSwizzleW, \
1, \
5); \
ureg_emit_texture( ureg, insn.extended_token, target, 0 ); \
ureg_emit_dst( ureg, dst ); \
ureg_emit_src( ureg, src0 ); \
ureg_emit_src( ureg, src1 ); \
ureg_emit_src( ureg, src2 ); \
ureg_emit_src( ureg, src3 ); \
ureg_emit_src( ureg, src4 ); \
ureg_fixup_insn_size( ureg, insn.insn_token ); \
}
 
/* Use a template include to generate a correctly-typed ureg_OP()
* function for each TGSI opcode:
*/
#include "tgsi_opcode_tmp.h"
 
 
/***********************************************************************
* Inline helpers for manipulating register structs:
*/
static INLINE struct ureg_src
ureg_negate( struct ureg_src reg )
{
assert(reg.File != TGSI_FILE_NULL);
reg.Negate ^= 1;
return reg;
}
 
static INLINE struct ureg_src
ureg_abs( struct ureg_src reg )
{
assert(reg.File != TGSI_FILE_NULL);
reg.Absolute = 1;
reg.Negate = 0;
return reg;
}
 
static INLINE struct ureg_src
ureg_swizzle( struct ureg_src reg,
int x, int y, int z, int w )
{
unsigned swz = ( (reg.SwizzleX << 0) |
(reg.SwizzleY << 2) |
(reg.SwizzleZ << 4) |
(reg.SwizzleW << 6));
 
assert(reg.File != TGSI_FILE_NULL);
assert(x < 4);
assert(y < 4);
assert(z < 4);
assert(w < 4);
 
reg.SwizzleX = (swz >> (x*2)) & 0x3;
reg.SwizzleY = (swz >> (y*2)) & 0x3;
reg.SwizzleZ = (swz >> (z*2)) & 0x3;
reg.SwizzleW = (swz >> (w*2)) & 0x3;
return reg;
}
 
static INLINE struct ureg_src
ureg_scalar( struct ureg_src reg, int x )
{
return ureg_swizzle(reg, x, x, x, x);
}
 
static INLINE struct ureg_dst
ureg_writemask( struct ureg_dst reg,
unsigned writemask )
{
assert(reg.File != TGSI_FILE_NULL);
reg.WriteMask &= writemask;
return reg;
}
 
static INLINE struct ureg_dst
ureg_saturate( struct ureg_dst reg )
{
assert(reg.File != TGSI_FILE_NULL);
reg.Saturate = 1;
return reg;
}
 
static INLINE struct ureg_dst
ureg_predicate(struct ureg_dst reg,
boolean negate,
unsigned swizzle_x,
unsigned swizzle_y,
unsigned swizzle_z,
unsigned swizzle_w)
{
assert(reg.File != TGSI_FILE_NULL);
reg.Predicate = 1;
reg.PredNegate = negate;
reg.PredSwizzleX = swizzle_x;
reg.PredSwizzleY = swizzle_y;
reg.PredSwizzleZ = swizzle_z;
reg.PredSwizzleW = swizzle_w;
return reg;
}
 
static INLINE struct ureg_dst
ureg_dst_indirect( struct ureg_dst reg, struct ureg_src addr )
{
assert(reg.File != TGSI_FILE_NULL);
assert(addr.File == TGSI_FILE_ADDRESS || addr.File == TGSI_FILE_TEMPORARY);
reg.Indirect = 1;
reg.IndirectFile = addr.File;
reg.IndirectIndex = addr.Index;
reg.IndirectSwizzle = addr.SwizzleX;
return reg;
}
 
static INLINE struct ureg_src
ureg_src_indirect( struct ureg_src reg, struct ureg_src addr )
{
assert(reg.File != TGSI_FILE_NULL);
assert(addr.File == TGSI_FILE_ADDRESS || addr.File == TGSI_FILE_TEMPORARY);
reg.Indirect = 1;
reg.IndirectFile = addr.File;
reg.IndirectIndex = addr.Index;
reg.IndirectSwizzle = addr.SwizzleX;
return reg;
}
 
static INLINE struct ureg_src
ureg_src_dimension( struct ureg_src reg, int index )
{
assert(reg.File != TGSI_FILE_NULL);
reg.Dimension = 1;
reg.DimIndirect = 0;
reg.DimensionIndex = index;
return reg;
}
 
 
static INLINE struct ureg_src
ureg_src_dimension_indirect( struct ureg_src reg, struct ureg_src addr,
int index )
{
assert(reg.File != TGSI_FILE_NULL);
reg.Dimension = 1;
reg.DimIndirect = 1;
reg.DimensionIndex = index;
reg.DimIndFile = addr.File;
reg.DimIndIndex = addr.Index;
reg.DimIndSwizzle = addr.SwizzleX;
return reg;
}
 
static INLINE struct ureg_dst
ureg_dst_array_offset( struct ureg_dst reg, int offset )
{
assert(reg.File == TGSI_FILE_TEMPORARY);
reg.Index += offset;
return reg;
}
 
static INLINE struct ureg_dst
ureg_dst( struct ureg_src src )
{
struct ureg_dst dst;
 
assert(!src.Indirect ||
(src.IndirectFile == TGSI_FILE_ADDRESS ||
src.IndirectFile == TGSI_FILE_TEMPORARY));
 
dst.File = src.File;
dst.WriteMask = TGSI_WRITEMASK_XYZW;
dst.IndirectFile = src.IndirectFile;
dst.Indirect = src.Indirect;
dst.IndirectIndex = src.IndirectIndex;
dst.IndirectSwizzle = src.IndirectSwizzle;
dst.Saturate = 0;
dst.Predicate = 0;
dst.PredNegate = 0;
dst.PredSwizzleX = TGSI_SWIZZLE_X;
dst.PredSwizzleY = TGSI_SWIZZLE_Y;
dst.PredSwizzleZ = TGSI_SWIZZLE_Z;
dst.PredSwizzleW = TGSI_SWIZZLE_W;
dst.Index = src.Index;
dst.ArrayID = src.ArrayID;
 
return dst;
}
 
static INLINE struct ureg_src
ureg_src_register(unsigned file,
unsigned index)
{
struct ureg_src src;
 
src.File = file;
src.SwizzleX = TGSI_SWIZZLE_X;
src.SwizzleY = TGSI_SWIZZLE_Y;
src.SwizzleZ = TGSI_SWIZZLE_Z;
src.SwizzleW = TGSI_SWIZZLE_W;
src.Indirect = 0;
src.IndirectFile = TGSI_FILE_NULL;
src.IndirectIndex = 0;
src.IndirectSwizzle = 0;
src.Absolute = 0;
src.Index = index;
src.Negate = 0;
src.Dimension = 0;
src.DimensionIndex = 0;
src.DimIndirect = 0;
src.DimIndFile = TGSI_FILE_NULL;
src.DimIndIndex = 0;
src.DimIndSwizzle = 0;
src.ArrayID = 0;
 
return src;
}
 
static INLINE struct ureg_src
ureg_src( struct ureg_dst dst )
{
struct ureg_src src;
 
src.File = dst.File;
src.SwizzleX = TGSI_SWIZZLE_X;
src.SwizzleY = TGSI_SWIZZLE_Y;
src.SwizzleZ = TGSI_SWIZZLE_Z;
src.SwizzleW = TGSI_SWIZZLE_W;
src.Indirect = dst.Indirect;
src.IndirectFile = dst.IndirectFile;
src.IndirectIndex = dst.IndirectIndex;
src.IndirectSwizzle = dst.IndirectSwizzle;
src.Absolute = 0;
src.Index = dst.Index;
src.Negate = 0;
src.Dimension = 0;
src.DimensionIndex = 0;
src.DimIndirect = 0;
src.DimIndFile = TGSI_FILE_NULL;
src.DimIndIndex = 0;
src.DimIndSwizzle = 0;
src.ArrayID = dst.ArrayID;
 
return src;
}
 
 
 
static INLINE struct ureg_dst
ureg_dst_undef( void )
{
struct ureg_dst dst;
 
dst.File = TGSI_FILE_NULL;
dst.WriteMask = 0;
dst.Indirect = 0;
dst.IndirectFile = TGSI_FILE_NULL;
dst.IndirectIndex = 0;
dst.IndirectSwizzle = 0;
dst.Saturate = 0;
dst.Predicate = 0;
dst.PredNegate = 0;
dst.PredSwizzleX = TGSI_SWIZZLE_X;
dst.PredSwizzleY = TGSI_SWIZZLE_Y;
dst.PredSwizzleZ = TGSI_SWIZZLE_Z;
dst.PredSwizzleW = TGSI_SWIZZLE_W;
dst.Index = 0;
dst.ArrayID = 0;
 
return dst;
}
 
static INLINE struct ureg_src
ureg_src_undef( void )
{
struct ureg_src src;
 
src.File = TGSI_FILE_NULL;
src.SwizzleX = 0;
src.SwizzleY = 0;
src.SwizzleZ = 0;
src.SwizzleW = 0;
src.Indirect = 0;
src.IndirectFile = TGSI_FILE_NULL;
src.IndirectIndex = 0;
src.IndirectSwizzle = 0;
src.Absolute = 0;
src.Index = 0;
src.Negate = 0;
src.Dimension = 0;
src.DimensionIndex = 0;
src.DimIndirect = 0;
src.DimIndFile = TGSI_FILE_NULL;
src.DimIndIndex = 0;
src.DimIndSwizzle = 0;
src.ArrayID = 0;
 
return src;
}
 
static INLINE boolean
ureg_src_is_undef( struct ureg_src src )
{
return src.File == TGSI_FILE_NULL;
}
 
static INLINE boolean
ureg_dst_is_undef( struct ureg_dst dst )
{
return dst.File == TGSI_FILE_NULL;
}
 
 
#ifdef __cplusplus
}
#endif
 
#endif
/drivers/video/Gallium/auxiliary/tgsi/tgsi_util.c
0,0 → 1,433
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
#include "util/u_debug.h"
#include "pipe/p_shader_tokens.h"
#include "tgsi_parse.h"
#include "tgsi_util.h"
 
union pointer_hack
{
void *pointer;
uint64_t uint64;
};
 
void *
tgsi_align_128bit(
void *unaligned )
{
union pointer_hack ph;
 
ph.uint64 = 0;
ph.pointer = unaligned;
ph.uint64 = (ph.uint64 + 15) & ~15;
return ph.pointer;
}
 
unsigned
tgsi_util_get_src_register_swizzle(
const struct tgsi_src_register *reg,
unsigned component )
{
switch( component ) {
case 0:
return reg->SwizzleX;
case 1:
return reg->SwizzleY;
case 2:
return reg->SwizzleZ;
case 3:
return reg->SwizzleW;
default:
assert( 0 );
}
return 0;
}
 
 
unsigned
tgsi_util_get_full_src_register_swizzle(
const struct tgsi_full_src_register *reg,
unsigned component )
{
return tgsi_util_get_src_register_swizzle(
&reg->Register,
component );
}
 
void
tgsi_util_set_src_register_swizzle(
struct tgsi_src_register *reg,
unsigned swizzle,
unsigned component )
{
switch( component ) {
case 0:
reg->SwizzleX = swizzle;
break;
case 1:
reg->SwizzleY = swizzle;
break;
case 2:
reg->SwizzleZ = swizzle;
break;
case 3:
reg->SwizzleW = swizzle;
break;
default:
assert( 0 );
}
}
 
unsigned
tgsi_util_get_full_src_register_sign_mode(
const struct tgsi_full_src_register *reg,
unsigned component )
{
unsigned sign_mode;
 
if( reg->Register.Absolute ) {
/* Consider only the post-abs negation. */
 
if( reg->Register.Negate ) {
sign_mode = TGSI_UTIL_SIGN_SET;
}
else {
sign_mode = TGSI_UTIL_SIGN_CLEAR;
}
}
else {
if( reg->Register.Negate ) {
sign_mode = TGSI_UTIL_SIGN_TOGGLE;
}
else {
sign_mode = TGSI_UTIL_SIGN_KEEP;
}
}
 
return sign_mode;
}
 
void
tgsi_util_set_full_src_register_sign_mode(
struct tgsi_full_src_register *reg,
unsigned sign_mode )
{
switch (sign_mode)
{
case TGSI_UTIL_SIGN_CLEAR:
reg->Register.Negate = 0;
reg->Register.Absolute = 1;
break;
 
case TGSI_UTIL_SIGN_SET:
reg->Register.Absolute = 1;
reg->Register.Negate = 1;
break;
 
case TGSI_UTIL_SIGN_TOGGLE:
reg->Register.Negate = 1;
reg->Register.Absolute = 0;
break;
 
case TGSI_UTIL_SIGN_KEEP:
reg->Register.Negate = 0;
reg->Register.Absolute = 0;
break;
 
default:
assert( 0 );
}
}
 
/**
* Determine which channels of the specificed src register are effectively
* used by this instruction.
*/
unsigned
tgsi_util_get_inst_usage_mask(const struct tgsi_full_instruction *inst,
unsigned src_idx)
{
const struct tgsi_full_src_register *src = &inst->Src[src_idx];
unsigned write_mask = inst->Dst[0].Register.WriteMask;
unsigned read_mask;
unsigned usage_mask;
unsigned chan;
 
switch (inst->Instruction.Opcode) {
case TGSI_OPCODE_MOV:
case TGSI_OPCODE_ARL:
case TGSI_OPCODE_ARR:
case TGSI_OPCODE_RCP:
case TGSI_OPCODE_MUL:
case TGSI_OPCODE_DIV:
case TGSI_OPCODE_ADD:
case TGSI_OPCODE_MIN:
case TGSI_OPCODE_MAX:
case TGSI_OPCODE_SLT:
case TGSI_OPCODE_SGE:
case TGSI_OPCODE_MAD:
case TGSI_OPCODE_SUB:
case TGSI_OPCODE_LRP:
case TGSI_OPCODE_CND:
case TGSI_OPCODE_FRC:
case TGSI_OPCODE_CEIL:
case TGSI_OPCODE_CLAMP:
case TGSI_OPCODE_FLR:
case TGSI_OPCODE_ROUND:
case TGSI_OPCODE_POW:
case TGSI_OPCODE_ABS:
case TGSI_OPCODE_COS:
case TGSI_OPCODE_SIN:
case TGSI_OPCODE_DDX:
case TGSI_OPCODE_DDY:
case TGSI_OPCODE_SEQ:
case TGSI_OPCODE_SGT:
case TGSI_OPCODE_SLE:
case TGSI_OPCODE_SNE:
case TGSI_OPCODE_SSG:
case TGSI_OPCODE_CMP:
case TGSI_OPCODE_TRUNC:
case TGSI_OPCODE_NOT:
case TGSI_OPCODE_AND:
case TGSI_OPCODE_OR:
case TGSI_OPCODE_XOR:
case TGSI_OPCODE_SAD:
/* Channel-wise operations */
read_mask = write_mask;
break;
 
case TGSI_OPCODE_EX2:
case TGSI_OPCODE_LG2:
case TGSI_OPCODE_RCC:
read_mask = TGSI_WRITEMASK_X;
break;
 
case TGSI_OPCODE_SCS:
read_mask = write_mask & TGSI_WRITEMASK_XY ? TGSI_WRITEMASK_X : 0;
break;
 
case TGSI_OPCODE_EXP:
case TGSI_OPCODE_LOG:
read_mask = write_mask & TGSI_WRITEMASK_XYZ ? TGSI_WRITEMASK_X : 0;
break;
 
case TGSI_OPCODE_DP2A:
read_mask = src_idx == 2 ? TGSI_WRITEMASK_X : TGSI_WRITEMASK_XY;
break;
 
case TGSI_OPCODE_DP2:
read_mask = TGSI_WRITEMASK_XY;
break;
 
case TGSI_OPCODE_DP3:
read_mask = TGSI_WRITEMASK_XYZ;
break;
 
case TGSI_OPCODE_DP4:
read_mask = TGSI_WRITEMASK_XYZW;
break;
 
case TGSI_OPCODE_DPH:
read_mask = src_idx == 0 ? TGSI_WRITEMASK_XYZ : TGSI_WRITEMASK_XYZW;
break;
 
case TGSI_OPCODE_TEX:
case TGSI_OPCODE_TXD:
case TGSI_OPCODE_TXB:
case TGSI_OPCODE_TXL:
case TGSI_OPCODE_TXP:
if (src_idx == 0) {
/* Note that the SHADOW variants use the Z component too */
switch (inst->Texture.Texture) {
case TGSI_TEXTURE_1D:
read_mask = TGSI_WRITEMASK_X;
break;
case TGSI_TEXTURE_SHADOW1D:
read_mask = TGSI_WRITEMASK_XZ;
break;
case TGSI_TEXTURE_1D_ARRAY:
case TGSI_TEXTURE_2D:
case TGSI_TEXTURE_RECT:
read_mask = TGSI_WRITEMASK_XY;
break;
case TGSI_TEXTURE_SHADOW1D_ARRAY:
case TGSI_TEXTURE_SHADOW2D:
case TGSI_TEXTURE_SHADOWRECT:
case TGSI_TEXTURE_2D_ARRAY:
case TGSI_TEXTURE_3D:
case TGSI_TEXTURE_CUBE:
case TGSI_TEXTURE_2D_MSAA:
read_mask = TGSI_WRITEMASK_XYZ;
break;
case TGSI_TEXTURE_SHADOW2D_ARRAY:
case TGSI_TEXTURE_CUBE_ARRAY:
case TGSI_TEXTURE_SHADOWCUBE:
case TGSI_TEXTURE_2D_ARRAY_MSAA:
case TGSI_TEXTURE_SHADOWCUBE_ARRAY:
read_mask = TGSI_WRITEMASK_XYZW;
break;
default:
assert(0);
read_mask = 0;
}
 
if (inst->Instruction.Opcode != TGSI_OPCODE_TEX) {
read_mask |= TGSI_WRITEMASK_W;
}
} else {
/* A safe approximation */
read_mask = TGSI_WRITEMASK_XYZW;
}
break;
 
default:
/* Assume all channels are read */
read_mask = TGSI_WRITEMASK_XYZW;
break;
}
 
usage_mask = 0;
for (chan = 0; chan < 4; ++chan) {
if (read_mask & (1 << chan)) {
usage_mask |= 1 << tgsi_util_get_full_src_register_swizzle(src, chan);
}
}
 
return usage_mask;
}
 
/**
* Convert a tgsi_ind_register into a tgsi_src_register
*/
struct tgsi_src_register
tgsi_util_get_src_from_ind(const struct tgsi_ind_register *reg)
{
struct tgsi_src_register src = { 0 };
 
src.File = reg->File;
src.Index = reg->Index;
src.SwizzleX = reg->Swizzle;
src.SwizzleY = reg->Swizzle;
src.SwizzleZ = reg->Swizzle;
src.SwizzleW = reg->Swizzle;
 
return src;
}
 
/**
* Return the dimension of the texture coordinates (layer included for array
* textures), as well as the location of the shadow reference value or the
* sample index.
*/
int
tgsi_util_get_texture_coord_dim(int tgsi_tex, int *shadow_or_sample)
{
int dim;
 
/*
* Depending on the texture target, (src0.xyzw, src1.x) is interpreted
* differently:
*
* (s, X, X, X, X), for BUFFER
* (s, X, X, X, X), for 1D
* (s, t, X, X, X), for 2D, RECT
* (s, t, r, X, X), for 3D, CUBE
*
* (s, layer, X, X, X), for 1D_ARRAY
* (s, t, layer, X, X), for 2D_ARRAY
* (s, t, r, layer, X), for CUBE_ARRAY
*
* (s, X, shadow, X, X), for SHADOW1D
* (s, t, shadow, X, X), for SHADOW2D, SHADOWRECT
* (s, t, r, shadow, X), for SHADOWCUBE
*
* (s, layer, shadow, X, X), for SHADOW1D_ARRAY
* (s, t, layer, shadow, X), for SHADOW2D_ARRAY
* (s, t, r, layer, shadow), for SHADOWCUBE_ARRAY
*
* (s, t, sample, X, X), for 2D_MSAA
* (s, t, layer, sample, X), for 2D_ARRAY_MSAA
*/
switch (tgsi_tex) {
case TGSI_TEXTURE_BUFFER:
case TGSI_TEXTURE_1D:
case TGSI_TEXTURE_SHADOW1D:
dim = 1;
break;
case TGSI_TEXTURE_2D:
case TGSI_TEXTURE_RECT:
case TGSI_TEXTURE_1D_ARRAY:
case TGSI_TEXTURE_SHADOW2D:
case TGSI_TEXTURE_SHADOWRECT:
case TGSI_TEXTURE_SHADOW1D_ARRAY:
case TGSI_TEXTURE_2D_MSAA:
dim = 2;
break;
case TGSI_TEXTURE_3D:
case TGSI_TEXTURE_CUBE:
case TGSI_TEXTURE_2D_ARRAY:
case TGSI_TEXTURE_SHADOWCUBE:
case TGSI_TEXTURE_SHADOW2D_ARRAY:
case TGSI_TEXTURE_2D_ARRAY_MSAA:
dim = 3;
break;
case TGSI_TEXTURE_CUBE_ARRAY:
case TGSI_TEXTURE_SHADOWCUBE_ARRAY:
dim = 4;
break;
default:
assert(!"unknown texture target");
dim = 0;
break;
}
 
if (shadow_or_sample) {
switch (tgsi_tex) {
case TGSI_TEXTURE_SHADOW1D:
/* there is a gap */
*shadow_or_sample = 2;
break;
case TGSI_TEXTURE_SHADOW2D:
case TGSI_TEXTURE_SHADOWRECT:
case TGSI_TEXTURE_SHADOWCUBE:
case TGSI_TEXTURE_SHADOW1D_ARRAY:
case TGSI_TEXTURE_SHADOW2D_ARRAY:
case TGSI_TEXTURE_SHADOWCUBE_ARRAY:
case TGSI_TEXTURE_2D_MSAA:
case TGSI_TEXTURE_2D_ARRAY_MSAA:
*shadow_or_sample = dim;
break;
default:
/* no shadow nor sample */
*shadow_or_sample = -1;
break;
}
}
 
return dim;
}
/drivers/video/Gallium/auxiliary/tgsi/tgsi_util.h
0,0 → 1,89
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
#ifndef TGSI_UTIL_H
#define TGSI_UTIL_H
 
#if defined __cplusplus
extern "C" {
#endif
 
struct tgsi_src_register;
struct tgsi_full_src_register;
struct tgsi_full_instruction;
 
void *
tgsi_align_128bit(
void *unaligned );
 
unsigned
tgsi_util_get_src_register_swizzle(
const struct tgsi_src_register *reg,
unsigned component );
 
 
unsigned
tgsi_util_get_full_src_register_swizzle(
const struct tgsi_full_src_register *reg,
unsigned component );
 
void
tgsi_util_set_src_register_swizzle(
struct tgsi_src_register *reg,
unsigned swizzle,
unsigned component );
 
#define TGSI_UTIL_SIGN_CLEAR 0 /* Force positive */
#define TGSI_UTIL_SIGN_SET 1 /* Force negative */
#define TGSI_UTIL_SIGN_TOGGLE 2 /* Negate */
#define TGSI_UTIL_SIGN_KEEP 3 /* No change */
 
unsigned
tgsi_util_get_full_src_register_sign_mode(
const struct tgsi_full_src_register *reg,
unsigned component );
 
void
tgsi_util_set_full_src_register_sign_mode(
struct tgsi_full_src_register *reg,
unsigned sign_mode );
 
unsigned
tgsi_util_get_inst_usage_mask(const struct tgsi_full_instruction *inst,
unsigned src_idx);
 
struct tgsi_src_register
tgsi_util_get_src_from_ind(const struct tgsi_ind_register *reg);
 
int
tgsi_util_get_texture_coord_dim(int tgsi_tex, int *shadow_or_sample);
 
#if defined __cplusplus
}
#endif
 
#endif /* TGSI_UTIL_H */
/drivers/video/Gallium/auxiliary/util/dbghelp.h
0,0 → 1,1265
/**
* This file has no copyright assigned and is placed in the Public Domain.
* This file is part of the w64 mingw-runtime package.
* No warranty is given; refer to the file DISCLAIMER.PD within this package.
*/
#ifndef _DBGHELP_
#define _DBGHELP_
 
#ifdef _WIN64
#ifndef _IMAGEHLP64
#define _IMAGEHLP64
#endif
#endif
 
#ifdef __cplusplus
extern "C" {
#endif
 
#define IMAGEAPI DECLSPEC_IMPORT WINAPI
#define DBHLP_DEPRECIATED __declspec(deprecated)
 
#define DBHLPAPI IMAGEAPI
 
#define IMAGE_SEPARATION (64*1024)
 
typedef struct _LOADED_IMAGE {
PSTR ModuleName;
HANDLE hFile;
PUCHAR MappedAddress;
#ifdef _IMAGEHLP64
PIMAGE_NT_HEADERS64 FileHeader;
#else
PIMAGE_NT_HEADERS32 FileHeader;
#endif
PIMAGE_SECTION_HEADER LastRvaSection;
ULONG NumberOfSections;
PIMAGE_SECTION_HEADER Sections;
ULONG Characteristics;
BOOLEAN fSystemImage;
BOOLEAN fDOSImage;
LIST_ENTRY Links;
ULONG SizeOfImage;
} LOADED_IMAGE,*PLOADED_IMAGE;
 
#define MAX_SYM_NAME 2000
 
typedef BOOL (CALLBACK *PFIND_DEBUG_FILE_CALLBACK)(HANDLE FileHandle,PSTR FileName,PVOID CallerData);
typedef BOOL (CALLBACK *PFINDFILEINPATHCALLBACK)(PSTR filename,PVOID context);
typedef BOOL (CALLBACK *PFIND_EXE_FILE_CALLBACK)(HANDLE FileHandle,PSTR FileName,PVOID CallerData);
 
typedef BOOL (WINAPI *PSYMBOLSERVERPROC)(LPCSTR,LPCSTR,PVOID,DWORD,DWORD,LPSTR);
typedef BOOL (WINAPI *PSYMBOLSERVEROPENPROC)(VOID);
typedef BOOL (WINAPI *PSYMBOLSERVERCLOSEPROC)(VOID);
typedef BOOL (WINAPI *PSYMBOLSERVERSETOPTIONSPROC)(UINT_PTR,ULONG64);
typedef BOOL (CALLBACK WINAPI *PSYMBOLSERVERCALLBACKPROC)(UINT_PTR action,ULONG64 data,ULONG64 context);
typedef UINT_PTR (WINAPI *PSYMBOLSERVERGETOPTIONSPROC)();
typedef BOOL (WINAPI *PSYMBOLSERVERPINGPROC)(LPCSTR);
 
HANDLE IMAGEAPI FindDebugInfoFile(PSTR FileName,PSTR SymbolPath,PSTR DebugFilePath);
HANDLE IMAGEAPI FindDebugInfoFileEx(PSTR FileName,PSTR SymbolPath,PSTR DebugFilePath,PFIND_DEBUG_FILE_CALLBACK Callback,PVOID CallerData);
BOOL IMAGEAPI SymFindFileInPath(HANDLE hprocess,LPSTR SearchPath,LPSTR FileName,PVOID id,DWORD two,DWORD three,DWORD flags,LPSTR FoundFile,PFINDFILEINPATHCALLBACK callback,PVOID context);
HANDLE IMAGEAPI FindExecutableImage(PSTR FileName,PSTR SymbolPath,PSTR ImageFilePath);
HANDLE IMAGEAPI FindExecutableImageEx(PSTR FileName,PSTR SymbolPath,PSTR ImageFilePath,PFIND_EXE_FILE_CALLBACK Callback,PVOID CallerData);
PIMAGE_NT_HEADERS IMAGEAPI ImageNtHeader(PVOID Base);
PVOID IMAGEAPI ImageDirectoryEntryToDataEx(PVOID Base,BOOLEAN MappedAsImage,USHORT DirectoryEntry,PULONG Size,PIMAGE_SECTION_HEADER *FoundHeader);
PVOID IMAGEAPI ImageDirectoryEntryToData(PVOID Base,BOOLEAN MappedAsImage,USHORT DirectoryEntry,PULONG Size);
PIMAGE_SECTION_HEADER IMAGEAPI ImageRvaToSection(PIMAGE_NT_HEADERS NtHeaders,PVOID Base,ULONG Rva);
PVOID IMAGEAPI ImageRvaToVa(PIMAGE_NT_HEADERS NtHeaders,PVOID Base,ULONG Rva,PIMAGE_SECTION_HEADER *LastRvaSection);
 
#define SSRVOPT_CALLBACK 0x0001
#define SSRVOPT_DWORD 0x0002
#define SSRVOPT_DWORDPTR 0x0004
#define SSRVOPT_GUIDPTR 0x0008
#define SSRVOPT_OLDGUIDPTR 0x0010
#define SSRVOPT_UNATTENDED 0x0020
#define SSRVOPT_NOCOPY 0x0040
#define SSRVOPT_PARENTWIN 0x0080
#define SSRVOPT_PARAMTYPE 0x0100
#define SSRVOPT_SECURE 0x0200
#define SSRVOPT_TRACE 0x0400
#define SSRVOPT_SETCONTEXT 0x0800
#define SSRVOPT_PROXY 0x1000
#define SSRVOPT_DOWNSTREAM_STORE 0x2000
#define SSRVOPT_RESET ((ULONG_PTR)-1)
 
#define SSRVACTION_TRACE 1
#define SSRVACTION_QUERYCANCEL 2
#define SSRVACTION_EVENT 3
 
#ifndef _WIN64
 
typedef struct _IMAGE_DEBUG_INFORMATION {
LIST_ENTRY List;
DWORD ReservedSize;
PVOID ReservedMappedBase;
USHORT ReservedMachine;
USHORT ReservedCharacteristics;
DWORD ReservedCheckSum;
DWORD ImageBase;
DWORD SizeOfImage;
DWORD ReservedNumberOfSections;
PIMAGE_SECTION_HEADER ReservedSections;
DWORD ReservedExportedNamesSize;
PSTR ReservedExportedNames;
DWORD ReservedNumberOfFunctionTableEntries;
PIMAGE_FUNCTION_ENTRY ReservedFunctionTableEntries;
DWORD ReservedLowestFunctionStartingAddress;
DWORD ReservedHighestFunctionEndingAddress;
DWORD ReservedNumberOfFpoTableEntries;
PFPO_DATA ReservedFpoTableEntries;
DWORD SizeOfCoffSymbols;
PIMAGE_COFF_SYMBOLS_HEADER CoffSymbols;
DWORD ReservedSizeOfCodeViewSymbols;
PVOID ReservedCodeViewSymbols;
PSTR ImageFilePath;
PSTR ImageFileName;
PSTR ReservedDebugFilePath;
DWORD ReservedTimeDateStamp;
BOOL ReservedRomImage;
PIMAGE_DEBUG_DIRECTORY ReservedDebugDirectory;
DWORD ReservedNumberOfDebugDirectories;
DWORD ReservedOriginalFunctionTableBaseAddress;
DWORD Reserved[2 ];
} IMAGE_DEBUG_INFORMATION,*PIMAGE_DEBUG_INFORMATION;
 
PIMAGE_DEBUG_INFORMATION IMAGEAPI MapDebugInformation(HANDLE FileHandle,PSTR FileName,PSTR SymbolPath,DWORD ImageBase);
BOOL IMAGEAPI UnmapDebugInformation(PIMAGE_DEBUG_INFORMATION DebugInfo);
#endif
 
typedef BOOL (CALLBACK *PENUMDIRTREE_CALLBACK)(LPCSTR FilePath,PVOID CallerData);
 
BOOL IMAGEAPI SearchTreeForFile(PSTR RootPath,PSTR InputPathName,PSTR OutputPathBuffer);
BOOL IMAGEAPI EnumDirTree(HANDLE hProcess,PSTR RootPath,PSTR InputPathName,PSTR OutputPathBuffer,PENUMDIRTREE_CALLBACK Callback,PVOID CallbackData);
BOOL IMAGEAPI MakeSureDirectoryPathExists(PCSTR DirPath);
 
#define UNDNAME_COMPLETE (0x0000)
#define UNDNAME_NO_LEADING_UNDERSCORES (0x0001)
#define UNDNAME_NO_MS_KEYWORDS (0x0002)
#define UNDNAME_NO_FUNCTION_RETURNS (0x0004)
#define UNDNAME_NO_ALLOCATION_MODEL (0x0008)
#define UNDNAME_NO_ALLOCATION_LANGUAGE (0x0010)
#define UNDNAME_NO_MS_THISTYPE (0x0020)
#define UNDNAME_NO_CV_THISTYPE (0x0040)
#define UNDNAME_NO_THISTYPE (0x0060)
#define UNDNAME_NO_ACCESS_SPECIFIERS (0x0080)
#define UNDNAME_NO_THROW_SIGNATURES (0x0100)
#define UNDNAME_NO_MEMBER_TYPE (0x0200)
#define UNDNAME_NO_RETURN_UDT_MODEL (0x0400)
#define UNDNAME_32_BIT_DECODE (0x0800)
#define UNDNAME_NAME_ONLY (0x1000)
#define UNDNAME_NO_ARGUMENTS (0x2000)
#define UNDNAME_NO_SPECIAL_SYMS (0x4000)
 
DWORD IMAGEAPI WINAPI UnDecorateSymbolName(PCSTR DecoratedName,PSTR UnDecoratedName,DWORD UndecoratedLength,DWORD Flags);
 
#define DBHHEADER_DEBUGDIRS 0x1
 
typedef struct _MODLOAD_DATA {
DWORD ssize;
DWORD ssig;
PVOID data;
DWORD size;
DWORD flags;
} MODLOAD_DATA,*PMODLOAD_DATA;
 
typedef enum {
AddrMode1616,AddrMode1632,AddrModeReal,AddrModeFlat
} ADDRESS_MODE;
 
typedef struct _tagADDRESS64 {
DWORD64 Offset;
WORD Segment;
ADDRESS_MODE Mode;
} ADDRESS64,*LPADDRESS64;
 
#ifdef _IMAGEHLP64
#define ADDRESS ADDRESS64
#define LPADDRESS LPADDRESS64
#else
typedef struct _tagADDRESS {
DWORD Offset;
WORD Segment;
ADDRESS_MODE Mode;
} ADDRESS,*LPADDRESS;
 
static __inline void Address32To64(LPADDRESS a32,LPADDRESS64 a64) {
a64->Offset = (ULONG64)(LONG64)(LONG)a32->Offset;
a64->Segment = a32->Segment;
a64->Mode = a32->Mode;
}
 
static __inline void Address64To32(LPADDRESS64 a64,LPADDRESS a32) {
a32->Offset = (ULONG)a64->Offset;
a32->Segment = a64->Segment;
a32->Mode = a64->Mode;
}
#endif
 
typedef struct _KDHELP64 {
DWORD64 Thread;
DWORD ThCallbackStack;
DWORD ThCallbackBStore;
DWORD NextCallback;
DWORD FramePointer;
DWORD64 KiCallUserMode;
DWORD64 KeUserCallbackDispatcher;
DWORD64 SystemRangeStart;
DWORD64 Reserved[8];
} KDHELP64,*PKDHELP64;
 
#ifdef _IMAGEHLP64
#define KDHELP KDHELP64
#define PKDHELP PKDHELP64
#else
typedef struct _KDHELP {
DWORD Thread;
DWORD ThCallbackStack;
DWORD NextCallback;
DWORD FramePointer;
DWORD KiCallUserMode;
DWORD KeUserCallbackDispatcher;
DWORD SystemRangeStart;
DWORD ThCallbackBStore;
DWORD Reserved[8];
} KDHELP,*PKDHELP;
 
static __inline void KdHelp32To64(PKDHELP p32,PKDHELP64 p64) {
p64->Thread = p32->Thread;
p64->ThCallbackStack = p32->ThCallbackStack;
p64->NextCallback = p32->NextCallback;
p64->FramePointer = p32->FramePointer;
p64->KiCallUserMode = p32->KiCallUserMode;
p64->KeUserCallbackDispatcher = p32->KeUserCallbackDispatcher;
p64->SystemRangeStart = p32->SystemRangeStart;
}
#endif
 
typedef struct _tagSTACKFRAME64 {
ADDRESS64 AddrPC;
ADDRESS64 AddrReturn;
ADDRESS64 AddrFrame;
ADDRESS64 AddrStack;
ADDRESS64 AddrBStore;
PVOID FuncTableEntry;
DWORD64 Params[4];
BOOL Far;
BOOL Virtual;
DWORD64 Reserved[3];
KDHELP64 KdHelp;
} STACKFRAME64,*LPSTACKFRAME64;
 
#ifdef _IMAGEHLP64
#define STACKFRAME STACKFRAME64
#define LPSTACKFRAME LPSTACKFRAME64
#else
typedef struct _tagSTACKFRAME {
ADDRESS AddrPC;
ADDRESS AddrReturn;
ADDRESS AddrFrame;
ADDRESS AddrStack;
PVOID FuncTableEntry;
DWORD Params[4];
BOOL Far;
BOOL Virtual;
DWORD Reserved[3];
KDHELP KdHelp;
ADDRESS AddrBStore;
} STACKFRAME,*LPSTACKFRAME;
#endif
 
typedef BOOL (WINAPI *PREAD_PROCESS_MEMORY_ROUTINE64)(HANDLE hProcess,DWORD64 qwBaseAddress,PVOID lpBuffer,DWORD nSize,LPDWORD lpNumberOfBytesRead);
typedef PVOID (WINAPI *PFUNCTION_TABLE_ACCESS_ROUTINE64)(HANDLE hProcess,DWORD64 AddrBase);
typedef DWORD64 (WINAPI *PGET_MODULE_BASE_ROUTINE64)(HANDLE hProcess,DWORD64 Address);
typedef DWORD64 (WINAPI *PTRANSLATE_ADDRESS_ROUTINE64)(HANDLE hProcess,HANDLE hThread,LPADDRESS64 lpaddr);
 
BOOL IMAGEAPI StackWalk64(DWORD MachineType,HANDLE hProcess,HANDLE hThread,LPSTACKFRAME64 StackFrame,PVOID ContextRecord,PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine,PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress);
 
#ifdef _IMAGEHLP64
#define PREAD_PROCESS_MEMORY_ROUTINE PREAD_PROCESS_MEMORY_ROUTINE64
#define PFUNCTION_TABLE_ACCESS_ROUTINE PFUNCTION_TABLE_ACCESS_ROUTINE64
#define PGET_MODULE_BASE_ROUTINE PGET_MODULE_BASE_ROUTINE64
#define PTRANSLATE_ADDRESS_ROUTINE PTRANSLATE_ADDRESS_ROUTINE64
#define StackWalk StackWalk64
#else
typedef BOOL (WINAPI *PREAD_PROCESS_MEMORY_ROUTINE)(HANDLE hProcess,DWORD lpBaseAddress,PVOID lpBuffer,DWORD nSize,PDWORD lpNumberOfBytesRead);
typedef PVOID (WINAPI *PFUNCTION_TABLE_ACCESS_ROUTINE)(HANDLE hProcess,DWORD AddrBase);
typedef DWORD (WINAPI *PGET_MODULE_BASE_ROUTINE)(HANDLE hProcess,DWORD Address);
typedef DWORD (WINAPI *PTRANSLATE_ADDRESS_ROUTINE)(HANDLE hProcess,HANDLE hThread,LPADDRESS lpaddr);
 
BOOL IMAGEAPI StackWalk(DWORD MachineType,HANDLE hProcess,HANDLE hThread,LPSTACKFRAME StackFrame,PVOID ContextRecord,PREAD_PROCESS_MEMORY_ROUTINE ReadMemoryRoutine,PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine,PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine,PTRANSLATE_ADDRESS_ROUTINE TranslateAddress);
#endif
 
#define API_VERSION_NUMBER 9
 
typedef struct API_VERSION {
USHORT MajorVersion;
USHORT MinorVersion;
USHORT Revision;
USHORT Reserved;
} API_VERSION,*LPAPI_VERSION;
 
LPAPI_VERSION IMAGEAPI ImagehlpApiVersion(VOID);
LPAPI_VERSION IMAGEAPI ImagehlpApiVersionEx(LPAPI_VERSION AppVersion);
DWORD IMAGEAPI GetTimestampForLoadedLibrary(HMODULE Module);
 
typedef BOOL (CALLBACK *PSYM_ENUMMODULES_CALLBACK64)(PSTR ModuleName,DWORD64 BaseOfDll,PVOID UserContext);
typedef BOOL (CALLBACK *PSYM_ENUMSYMBOLS_CALLBACK64)(PSTR SymbolName,DWORD64 SymbolAddress,ULONG SymbolSize,PVOID UserContext);
typedef BOOL (CALLBACK *PSYM_ENUMSYMBOLS_CALLBACK64W)(PWSTR SymbolName,DWORD64 SymbolAddress,ULONG SymbolSize,PVOID UserContext);
typedef BOOL (CALLBACK *PENUMLOADED_MODULES_CALLBACK64)(PSTR ModuleName,DWORD64 ModuleBase,ULONG ModuleSize,PVOID UserContext);
typedef BOOL (CALLBACK *PSYMBOL_REGISTERED_CALLBACK64)(HANDLE hProcess,ULONG ActionCode,ULONG64 CallbackData,ULONG64 UserContext);
typedef PVOID (CALLBACK *PSYMBOL_FUNCENTRY_CALLBACK)(HANDLE hProcess,DWORD AddrBase,PVOID UserContext);
typedef PVOID (CALLBACK *PSYMBOL_FUNCENTRY_CALLBACK64)(HANDLE hProcess,ULONG64 AddrBase,ULONG64 UserContext);
 
#ifdef _IMAGEHLP64
#define PSYM_ENUMMODULES_CALLBACK PSYM_ENUMMODULES_CALLBACK64
#define PSYM_ENUMSYMBOLS_CALLBACK PSYM_ENUMSYMBOLS_CALLBACK64
#define PSYM_ENUMSYMBOLS_CALLBACKW PSYM_ENUMSYMBOLS_CALLBACK64W
#define PENUMLOADED_MODULES_CALLBACK PENUMLOADED_MODULES_CALLBACK64
#define PSYMBOL_REGISTERED_CALLBACK PSYMBOL_REGISTERED_CALLBACK64
#define PSYMBOL_FUNCENTRY_CALLBACK PSYMBOL_FUNCENTRY_CALLBACK64
#else
typedef BOOL (CALLBACK *PSYM_ENUMMODULES_CALLBACK)(PSTR ModuleName,ULONG BaseOfDll,PVOID UserContext);
typedef BOOL (CALLBACK *PSYM_ENUMSYMBOLS_CALLBACK)(PSTR SymbolName,ULONG SymbolAddress,ULONG SymbolSize,PVOID UserContext);
typedef BOOL (CALLBACK *PSYM_ENUMSYMBOLS_CALLBACKW)(PWSTR SymbolName,ULONG SymbolAddress,ULONG SymbolSize,PVOID UserContext);
typedef BOOL (CALLBACK *PENUMLOADED_MODULES_CALLBACK)(PSTR ModuleName,ULONG ModuleBase,ULONG ModuleSize,PVOID UserContext);
typedef BOOL (CALLBACK *PSYMBOL_REGISTERED_CALLBACK)(HANDLE hProcess,ULONG ActionCode,PVOID CallbackData,PVOID UserContext);
#endif
 
#define SYMFLAG_VALUEPRESENT 0x00000001
#define SYMFLAG_REGISTER 0x00000008
#define SYMFLAG_REGREL 0x00000010
#define SYMFLAG_FRAMEREL 0x00000020
#define SYMFLAG_PARAMETER 0x00000040
#define SYMFLAG_LOCAL 0x00000080
#define SYMFLAG_CONSTANT 0x00000100
#define SYMFLAG_EXPORT 0x00000200
#define SYMFLAG_FORWARDER 0x00000400
#define SYMFLAG_FUNCTION 0x00000800
#define SYMFLAG_VIRTUAL 0x00001000
#define SYMFLAG_THUNK 0x00002000
#define SYMFLAG_TLSREL 0x00004000
 
typedef enum {
SymNone = 0,SymCoff,SymCv,SymPdb,SymExport,SymDeferred,SymSym,SymDia,SymVirtual,NumSymTypes
} SYM_TYPE;
 
typedef struct _IMAGEHLP_SYMBOL64 {
DWORD SizeOfStruct;
DWORD64 Address;
DWORD Size;
DWORD Flags;
DWORD MaxNameLength;
CHAR Name[1];
} IMAGEHLP_SYMBOL64,*PIMAGEHLP_SYMBOL64;
 
typedef struct _IMAGEHLP_SYMBOL64_PACKAGE {
IMAGEHLP_SYMBOL64 sym;
CHAR name[MAX_SYM_NAME + 1];
} IMAGEHLP_SYMBOL64_PACKAGE,*PIMAGEHLP_SYMBOL64_PACKAGE;
 
#ifdef _IMAGEHLP64
 
#define IMAGEHLP_SYMBOL IMAGEHLP_SYMBOL64
#define PIMAGEHLP_SYMBOL PIMAGEHLP_SYMBOL64
#define IMAGEHLP_SYMBOL_PACKAGE IMAGEHLP_SYMBOL64_PACKAGE
#define PIMAGEHLP_SYMBOL_PACKAGE PIMAGEHLP_SYMBOL64_PACKAGE
#else
 
typedef struct _IMAGEHLP_SYMBOL {
DWORD SizeOfStruct;
DWORD Address;
DWORD Size;
DWORD Flags;
DWORD MaxNameLength;
CHAR Name[1];
} IMAGEHLP_SYMBOL,*PIMAGEHLP_SYMBOL;
 
typedef struct _IMAGEHLP_SYMBOL_PACKAGE {
IMAGEHLP_SYMBOL sym;
CHAR name[MAX_SYM_NAME + 1];
} IMAGEHLP_SYMBOL_PACKAGE,*PIMAGEHLP_SYMBOL_PACKAGE;
#endif
 
typedef struct _IMAGEHLP_MODULE64 {
DWORD SizeOfStruct;
DWORD64 BaseOfImage;
DWORD ImageSize;
DWORD TimeDateStamp;
DWORD CheckSum;
DWORD NumSyms;
SYM_TYPE SymType;
CHAR ModuleName[32];
CHAR ImageName[256];
CHAR LoadedImageName[256];
CHAR LoadedPdbName[256];
DWORD CVSig;
CHAR CVData[MAX_PATH*3];
DWORD PdbSig;
GUID PdbSig70;
DWORD PdbAge;
BOOL PdbUnmatched;
BOOL DbgUnmatched;
BOOL LineNumbers;
BOOL GlobalSymbols;
BOOL TypeInfo;
} IMAGEHLP_MODULE64,*PIMAGEHLP_MODULE64;
 
typedef struct _IMAGEHLP_MODULE64W {
DWORD SizeOfStruct;
DWORD64 BaseOfImage;
DWORD ImageSize;
DWORD TimeDateStamp;
DWORD CheckSum;
DWORD NumSyms;
SYM_TYPE SymType;
WCHAR ModuleName[32];
WCHAR ImageName[256];
WCHAR LoadedImageName[256];
WCHAR LoadedPdbName[256];
DWORD CVSig;
WCHAR CVData[MAX_PATH*3];
DWORD PdbSig;
GUID PdbSig70;
DWORD PdbAge;
BOOL PdbUnmatched;
BOOL DbgUnmatched;
BOOL LineNumbers;
BOOL GlobalSymbols;
BOOL TypeInfo;
} IMAGEHLP_MODULEW64,*PIMAGEHLP_MODULEW64;
 
#ifdef _IMAGEHLP64
#define IMAGEHLP_MODULE IMAGEHLP_MODULE64
#define PIMAGEHLP_MODULE PIMAGEHLP_MODULE64
#define IMAGEHLP_MODULEW IMAGEHLP_MODULEW64
#define PIMAGEHLP_MODULEW PIMAGEHLP_MODULEW64
#else
typedef struct _IMAGEHLP_MODULE {
DWORD SizeOfStruct;
DWORD BaseOfImage;
DWORD ImageSize;
DWORD TimeDateStamp;
DWORD CheckSum;
DWORD NumSyms;
SYM_TYPE SymType;
CHAR ModuleName[32];
CHAR ImageName[256];
CHAR LoadedImageName[256];
} IMAGEHLP_MODULE,*PIMAGEHLP_MODULE;
 
typedef struct _IMAGEHLP_MODULEW {
DWORD SizeOfStruct;
DWORD BaseOfImage;
DWORD ImageSize;
DWORD TimeDateStamp;
DWORD CheckSum;
DWORD NumSyms;
SYM_TYPE SymType;
WCHAR ModuleName[32];
WCHAR ImageName[256];
WCHAR LoadedImageName[256];
} IMAGEHLP_MODULEW,*PIMAGEHLP_MODULEW;
#endif
 
typedef struct _IMAGEHLP_LINE64 {
DWORD SizeOfStruct;
PVOID Key;
DWORD LineNumber;
PCHAR FileName;
DWORD64 Address;
} IMAGEHLP_LINE64,*PIMAGEHLP_LINE64;
 
#ifdef _IMAGEHLP64
#define IMAGEHLP_LINE IMAGEHLP_LINE64
#define PIMAGEHLP_LINE PIMAGEHLP_LINE64
#else
typedef struct _IMAGEHLP_LINE {
DWORD SizeOfStruct;
PVOID Key;
DWORD LineNumber;
PCHAR FileName;
DWORD Address;
} IMAGEHLP_LINE,*PIMAGEHLP_LINE;
#endif
 
typedef struct _SOURCEFILE {
DWORD64 ModBase;
PCHAR FileName;
} SOURCEFILE,*PSOURCEFILE;
 
#define CBA_DEFERRED_SYMBOL_LOAD_START 0x00000001
#define CBA_DEFERRED_SYMBOL_LOAD_COMPLETE 0x00000002
#define CBA_DEFERRED_SYMBOL_LOAD_FAILURE 0x00000003
#define CBA_SYMBOLS_UNLOADED 0x00000004
#define CBA_DUPLICATE_SYMBOL 0x00000005
#define CBA_READ_MEMORY 0x00000006
#define CBA_DEFERRED_SYMBOL_LOAD_CANCEL 0x00000007
#define CBA_SET_OPTIONS 0x00000008
#define CBA_EVENT 0x00000010
#define CBA_DEFERRED_SYMBOL_LOAD_PARTIAL 0x00000020
#define CBA_DEBUG_INFO 0x10000000
 
typedef struct _IMAGEHLP_CBA_READ_MEMORY {
DWORD64 addr;
PVOID buf;
DWORD bytes;
DWORD *bytesread;
} IMAGEHLP_CBA_READ_MEMORY,*PIMAGEHLP_CBA_READ_MEMORY;
 
enum {
sevInfo = 0,sevProblem,sevAttn,sevFatal,sevMax
};
 
typedef struct _IMAGEHLP_CBA_EVENT {
DWORD severity;
DWORD code;
PCHAR desc;
PVOID object;
} IMAGEHLP_CBA_EVENT,*PIMAGEHLP_CBA_EVENT;
 
typedef struct _IMAGEHLP_DEFERRED_SYMBOL_LOAD64 {
DWORD SizeOfStruct;
DWORD64 BaseOfImage;
DWORD CheckSum;
DWORD TimeDateStamp;
CHAR FileName[MAX_PATH];
BOOLEAN Reparse;
HANDLE hFile;
DWORD Flags;
} IMAGEHLP_DEFERRED_SYMBOL_LOAD64,*PIMAGEHLP_DEFERRED_SYMBOL_LOAD64;
 
#define DSLFLAG_MISMATCHED_PDB 0x1
#define DSLFLAG_MISMATCHED_DBG 0x2
 
#ifdef _IMAGEHLP64
#define IMAGEHLP_DEFERRED_SYMBOL_LOAD IMAGEHLP_DEFERRED_SYMBOL_LOAD64
#define PIMAGEHLP_DEFERRED_SYMBOL_LOAD PIMAGEHLP_DEFERRED_SYMBOL_LOAD64
#else
typedef struct _IMAGEHLP_DEFERRED_SYMBOL_LOAD {
DWORD SizeOfStruct;
DWORD BaseOfImage;
DWORD CheckSum;
DWORD TimeDateStamp;
CHAR FileName[MAX_PATH];
BOOLEAN Reparse;
HANDLE hFile;
} IMAGEHLP_DEFERRED_SYMBOL_LOAD,*PIMAGEHLP_DEFERRED_SYMBOL_LOAD;
#endif
 
typedef struct _IMAGEHLP_DUPLICATE_SYMBOL64 {
DWORD SizeOfStruct;
DWORD NumberOfDups;
PIMAGEHLP_SYMBOL64 Symbol;
DWORD SelectedSymbol;
} IMAGEHLP_DUPLICATE_SYMBOL64,*PIMAGEHLP_DUPLICATE_SYMBOL64;
 
#ifdef _IMAGEHLP64
#define IMAGEHLP_DUPLICATE_SYMBOL IMAGEHLP_DUPLICATE_SYMBOL64
#define PIMAGEHLP_DUPLICATE_SYMBOL PIMAGEHLP_DUPLICATE_SYMBOL64
#else
typedef struct _IMAGEHLP_DUPLICATE_SYMBOL {
DWORD SizeOfStruct;
DWORD NumberOfDups;
PIMAGEHLP_SYMBOL Symbol;
DWORD SelectedSymbol;
} IMAGEHLP_DUPLICATE_SYMBOL,*PIMAGEHLP_DUPLICATE_SYMBOL;
#endif
 
BOOL IMAGEAPI SymSetParentWindow(HWND hwnd);
PCHAR IMAGEAPI SymSetHomeDirectory(PCSTR dir);
PCHAR IMAGEAPI SymGetHomeDirectory(DWORD type,PSTR dir,size_t size);
 
enum {
hdBase = 0,hdSym,hdSrc,hdMax
};
 
#define SYMOPT_CASE_INSENSITIVE 0x00000001
#define SYMOPT_UNDNAME 0x00000002
#define SYMOPT_DEFERRED_LOADS 0x00000004
#define SYMOPT_NO_CPP 0x00000008
#define SYMOPT_LOAD_LINES 0x00000010
#define SYMOPT_OMAP_FIND_NEAREST 0x00000020
#define SYMOPT_LOAD_ANYTHING 0x00000040
#define SYMOPT_IGNORE_CVREC 0x00000080
#define SYMOPT_NO_UNQUALIFIED_LOADS 0x00000100
#define SYMOPT_FAIL_CRITICAL_ERRORS 0x00000200
#define SYMOPT_EXACT_SYMBOLS 0x00000400
#define SYMOPT_ALLOW_ABSOLUTE_SYMBOLS 0x00000800
#define SYMOPT_IGNORE_NT_SYMPATH 0x00001000
#define SYMOPT_INCLUDE_32BIT_MODULES 0x00002000
#define SYMOPT_PUBLICS_ONLY 0x00004000
#define SYMOPT_NO_PUBLICS 0x00008000
#define SYMOPT_AUTO_PUBLICS 0x00010000
#define SYMOPT_NO_IMAGE_SEARCH 0x00020000
#define SYMOPT_SECURE 0x00040000
#define SYMOPT_NO_PROMPTS 0x00080000
 
#define SYMOPT_DEBUG 0x80000000
 
DWORD IMAGEAPI SymSetOptions(DWORD SymOptions);
DWORD IMAGEAPI SymGetOptions(VOID);
BOOL IMAGEAPI SymCleanup(HANDLE hProcess);
BOOL IMAGEAPI SymMatchString(LPSTR string,LPSTR expression,BOOL fCase);
 
typedef BOOL (CALLBACK *PSYM_ENUMSOURCFILES_CALLBACK)(PSOURCEFILE pSourceFile,PVOID UserContext);
 
BOOL IMAGEAPI SymEnumSourceFiles(HANDLE hProcess,ULONG64 ModBase,LPSTR Mask,PSYM_ENUMSOURCFILES_CALLBACK cbSrcFiles,PVOID UserContext);
BOOL IMAGEAPI SymEnumerateModules64(HANDLE hProcess,PSYM_ENUMMODULES_CALLBACK64 EnumModulesCallback,PVOID UserContext);
 
#ifdef _IMAGEHLP64
#define SymEnumerateModules SymEnumerateModules64
#else
BOOL IMAGEAPI SymEnumerateModules(HANDLE hProcess,PSYM_ENUMMODULES_CALLBACK EnumModulesCallback,PVOID UserContext);
#endif
 
BOOL IMAGEAPI SymEnumerateSymbols64(HANDLE hProcess,DWORD64 BaseOfDll,PSYM_ENUMSYMBOLS_CALLBACK64 EnumSymbolsCallback,PVOID UserContext);
BOOL IMAGEAPI SymEnumerateSymbolsW64(HANDLE hProcess,DWORD64 BaseOfDll,PSYM_ENUMSYMBOLS_CALLBACK64W EnumSymbolsCallback,PVOID UserContext);
 
#ifdef _IMAGEHLP64
#define SymEnumerateSymbols SymEnumerateSymbols64
#define SymEnumerateSymbolsW SymEnumerateSymbolsW64
#else
BOOL IMAGEAPI SymEnumerateSymbols(HANDLE hProcess,DWORD BaseOfDll,PSYM_ENUMSYMBOLS_CALLBACK EnumSymbolsCallback,PVOID UserContext);
BOOL IMAGEAPI SymEnumerateSymbolsW(HANDLE hProcess,DWORD BaseOfDll,PSYM_ENUMSYMBOLS_CALLBACKW EnumSymbolsCallback,PVOID UserContext);
#endif
 
BOOL IMAGEAPI EnumerateLoadedModules64(HANDLE hProcess,PENUMLOADED_MODULES_CALLBACK64 EnumLoadedModulesCallback,PVOID UserContext);
#ifdef _IMAGEHLP64
#define EnumerateLoadedModules EnumerateLoadedModules64
#else
BOOL IMAGEAPI EnumerateLoadedModules(HANDLE hProcess,PENUMLOADED_MODULES_CALLBACK EnumLoadedModulesCallback,PVOID UserContext);
#endif
 
PVOID IMAGEAPI SymFunctionTableAccess64(HANDLE hProcess,DWORD64 AddrBase);
 
#ifdef _IMAGEHLP64
#define SymFunctionTableAccess SymFunctionTableAccess64
#else
PVOID IMAGEAPI SymFunctionTableAccess(HANDLE hProcess,DWORD AddrBase);
#endif
 
BOOL IMAGEAPI SymGetModuleInfo64(HANDLE hProcess,DWORD64 qwAddr,PIMAGEHLP_MODULE64 ModuleInfo);
BOOL IMAGEAPI SymGetModuleInfoW64(HANDLE hProcess,DWORD64 qwAddr,PIMAGEHLP_MODULEW64 ModuleInfo);
 
#ifdef _IMAGEHLP64
#define SymGetModuleInfo SymGetModuleInfo64
#define SymGetModuleInfoW SymGetModuleInfoW64
#else
BOOL IMAGEAPI SymGetModuleInfo(HANDLE hProcess,DWORD dwAddr,PIMAGEHLP_MODULE ModuleInfo);
BOOL IMAGEAPI SymGetModuleInfoW(HANDLE hProcess,DWORD dwAddr,PIMAGEHLP_MODULEW ModuleInfo);
#endif
 
DWORD64 IMAGEAPI SymGetModuleBase64(HANDLE hProcess,DWORD64 qwAddr);
 
#ifdef _IMAGEHLP64
#define SymGetModuleBase SymGetModuleBase64
#else
DWORD IMAGEAPI SymGetModuleBase(HANDLE hProcess,DWORD dwAddr);
#endif
 
BOOL IMAGEAPI SymGetSymNext64(HANDLE hProcess,PIMAGEHLP_SYMBOL64 Symbol);
 
#ifdef _IMAGEHLP64
#define SymGetSymNext SymGetSymNext64
#else
BOOL IMAGEAPI SymGetSymNext(HANDLE hProcess,PIMAGEHLP_SYMBOL Symbol);
#endif
 
BOOL IMAGEAPI SymGetSymPrev64(HANDLE hProcess,PIMAGEHLP_SYMBOL64 Symbol);
 
#ifdef _IMAGEHLP64
#define SymGetSymPrev SymGetSymPrev64
#else
BOOL IMAGEAPI SymGetSymPrev(HANDLE hProcess,PIMAGEHLP_SYMBOL Symbol);
#endif
 
typedef struct _SRCCODEINFO {
DWORD SizeOfStruct;
PVOID Key;
DWORD64 ModBase;
CHAR Obj[MAX_PATH + 1];
CHAR FileName[MAX_PATH + 1];
DWORD LineNumber;
DWORD64 Address;
} SRCCODEINFO,*PSRCCODEINFO;
 
typedef BOOL (CALLBACK *PSYM_ENUMLINES_CALLBACK)(PSRCCODEINFO LineInfo,PVOID UserContext);
 
BOOL IMAGEAPI SymEnumLines(HANDLE hProcess,ULONG64 Base,PCSTR Obj,PCSTR File,PSYM_ENUMLINES_CALLBACK EnumLinesCallback,PVOID UserContext);
BOOL IMAGEAPI SymGetLineFromAddr64(HANDLE hProcess,DWORD64 qwAddr,PDWORD pdwDisplacement,PIMAGEHLP_LINE64 Line64);
 
#ifdef _IMAGEHLP64
#define SymGetLineFromAddr SymGetLineFromAddr64
#else
BOOL IMAGEAPI SymGetLineFromAddr(HANDLE hProcess,DWORD dwAddr,PDWORD pdwDisplacement,PIMAGEHLP_LINE Line);
#endif
 
BOOL IMAGEAPI SymGetLineFromName64(HANDLE hProcess,PSTR ModuleName,PSTR FileName,DWORD dwLineNumber,PLONG plDisplacement,PIMAGEHLP_LINE64 Line);
 
#ifdef _IMAGEHLP64
#define SymGetLineFromName SymGetLineFromName64
#else
BOOL IMAGEAPI SymGetLineFromName(HANDLE hProcess,PSTR ModuleName,PSTR FileName,DWORD dwLineNumber,PLONG plDisplacement,PIMAGEHLP_LINE Line);
#endif
 
BOOL IMAGEAPI SymGetLineNext64(HANDLE hProcess,PIMAGEHLP_LINE64 Line);
 
#ifdef _IMAGEHLP64
#define SymGetLineNext SymGetLineNext64
#else
BOOL IMAGEAPI SymGetLineNext(HANDLE hProcess,PIMAGEHLP_LINE Line);
#endif
 
BOOL IMAGEAPI SymGetLinePrev64(HANDLE hProcess,PIMAGEHLP_LINE64 Line);
 
#ifdef _IMAGEHLP64
#define SymGetLinePrev SymGetLinePrev64
#else
BOOL IMAGEAPI SymGetLinePrev(HANDLE hProcess,PIMAGEHLP_LINE Line);
#endif
 
BOOL IMAGEAPI SymMatchFileName(PSTR FileName,PSTR Match,PSTR *FileNameStop,PSTR *MatchStop);
BOOL IMAGEAPI SymInitialize(HANDLE hProcess,PSTR UserSearchPath,BOOL fInvadeProcess);
BOOL IMAGEAPI SymGetSearchPath(HANDLE hProcess,PSTR SearchPath,DWORD SearchPathLength);
BOOL IMAGEAPI SymSetSearchPath(HANDLE hProcess,PSTR SearchPath);
DWORD64 IMAGEAPI SymLoadModule64(HANDLE hProcess,HANDLE hFile,PSTR ImageName,PSTR ModuleName,DWORD64 BaseOfDll,DWORD SizeOfDll);
 
#define SLMFLAG_VIRTUAL 0x1
 
DWORD64 IMAGEAPI SymLoadModuleEx(HANDLE hProcess,HANDLE hFile,PSTR ImageName,PSTR ModuleName,DWORD64 BaseOfDll,DWORD DllSize,PMODLOAD_DATA Data,DWORD Flags);
 
#ifdef _IMAGEHLP64
#define SymLoadModule SymLoadModule64
#else
DWORD IMAGEAPI SymLoadModule(HANDLE hProcess,HANDLE hFile,PSTR ImageName,PSTR ModuleName,DWORD BaseOfDll,DWORD SizeOfDll);
#endif
 
BOOL IMAGEAPI SymUnloadModule64(HANDLE hProcess,DWORD64 BaseOfDll);
 
#ifdef _IMAGEHLP64
#define SymUnloadModule SymUnloadModule64
#else
BOOL IMAGEAPI SymUnloadModule(HANDLE hProcess,DWORD BaseOfDll);
#endif
 
BOOL IMAGEAPI SymUnDName64(PIMAGEHLP_SYMBOL64 sym,PSTR UnDecName,DWORD UnDecNameLength);
 
#ifdef _IMAGEHLP64
#define SymUnDName SymUnDName64
#else
BOOL IMAGEAPI SymUnDName(PIMAGEHLP_SYMBOL sym,PSTR UnDecName,DWORD UnDecNameLength);
#endif
 
BOOL IMAGEAPI SymRegisterCallback64(HANDLE hProcess,PSYMBOL_REGISTERED_CALLBACK64 CallbackFunction,ULONG64 UserContext);
 
BOOL IMAGEAPI SymRegisterFunctionEntryCallback64(HANDLE hProcess,PSYMBOL_FUNCENTRY_CALLBACK64 CallbackFunction,ULONG64 UserContext);
 
#ifdef _IMAGEHLP64
#define SymRegisterCallback SymRegisterCallback64
#define SymRegisterFunctionEntryCallback SymRegisterFunctionEntryCallback64
#else
BOOL IMAGEAPI SymRegisterCallback(HANDLE hProcess,PSYMBOL_REGISTERED_CALLBACK CallbackFunction,PVOID UserContext);
BOOL IMAGEAPI SymRegisterFunctionEntryCallback(HANDLE hProcess,PSYMBOL_FUNCENTRY_CALLBACK CallbackFunction,PVOID UserContext);
#endif
 
typedef struct _IMAGEHLP_SYMBOL_SRC {
DWORD sizeofstruct;
DWORD type;
char file[MAX_PATH];
} IMAGEHLP_SYMBOL_SRC,*PIMAGEHLP_SYMBOL_SRC;
 
typedef struct _MODULE_TYPE_INFO {
USHORT dataLength;
USHORT leaf;
BYTE data[1];
} MODULE_TYPE_INFO,*PMODULE_TYPE_INFO;
 
typedef struct _SYMBOL_INFO {
ULONG SizeOfStruct;
ULONG TypeIndex;
ULONG64 Reserved[2];
ULONG info;
ULONG Size;
ULONG64 ModBase;
ULONG Flags;
ULONG64 Value;
ULONG64 Address;
ULONG Register;
ULONG Scope;
ULONG Tag;
ULONG NameLen;
ULONG MaxNameLen;
CHAR Name[1];
} SYMBOL_INFO,*PSYMBOL_INFO;
 
typedef struct _SYMBOL_INFO_PACKAGE {
SYMBOL_INFO si;
CHAR name[MAX_SYM_NAME + 1];
} SYMBOL_INFO_PACKAGE,*PSYMBOL_INFO_PACKAGE;
 
typedef struct _IMAGEHLP_STACK_FRAME
{
ULONG64 InstructionOffset;
ULONG64 ReturnOffset;
ULONG64 FrameOffset;
ULONG64 StackOffset;
ULONG64 BackingStoreOffset;
ULONG64 FuncTableEntry;
ULONG64 Params[4];
ULONG64 Reserved[5];
BOOL Virtual;
ULONG Reserved2;
} IMAGEHLP_STACK_FRAME,*PIMAGEHLP_STACK_FRAME;
 
typedef VOID IMAGEHLP_CONTEXT,*PIMAGEHLP_CONTEXT;
 
BOOL IMAGEAPI SymSetContext(HANDLE hProcess,PIMAGEHLP_STACK_FRAME StackFrame,PIMAGEHLP_CONTEXT Context);
BOOL IMAGEAPI SymFromAddr(HANDLE hProcess,DWORD64 Address,PDWORD64 Displacement,PSYMBOL_INFO Symbol);
BOOL IMAGEAPI SymFromToken(HANDLE hProcess,DWORD64 Base,DWORD Token,PSYMBOL_INFO Symbol);
BOOL IMAGEAPI SymFromName(HANDLE hProcess,LPSTR Name,PSYMBOL_INFO Symbol);
 
typedef BOOL (CALLBACK *PSYM_ENUMERATESYMBOLS_CALLBACK)(PSYMBOL_INFO pSymInfo,ULONG SymbolSize,PVOID UserContext);
 
BOOL IMAGEAPI SymEnumSymbols(HANDLE hProcess,ULONG64 BaseOfDll,PCSTR Mask,PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,PVOID UserContext);
BOOL IMAGEAPI SymEnumSymbolsForAddr(HANDLE hProcess,DWORD64 Address,PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,PVOID UserContext);
 
#define SYMENUMFLAG_FULLSRCH 1
#define SYMENUMFLAG_SPEEDSRCH 2
 
typedef enum _IMAGEHLP_SYMBOL_TYPE_INFO {
TI_GET_SYMTAG,TI_GET_SYMNAME,TI_GET_LENGTH,TI_GET_TYPE,TI_GET_TYPEID,TI_GET_BASETYPE,TI_GET_ARRAYINDEXTYPEID,TI_FINDCHILDREN,
TI_GET_DATAKIND,TI_GET_ADDRESSOFFSET,TI_GET_OFFSET,TI_GET_VALUE,TI_GET_COUNT,TI_GET_CHILDRENCOUNT,TI_GET_BITPOSITION,TI_GET_VIRTUALBASECLASS,
TI_GET_VIRTUALTABLESHAPEID,TI_GET_VIRTUALBASEPOINTEROFFSET,TI_GET_CLASSPARENTID,TI_GET_NESTED,TI_GET_SYMINDEX,TI_GET_LEXICALPARENT,
TI_GET_ADDRESS,TI_GET_THISADJUST,TI_GET_UDTKIND,TI_IS_EQUIV_TO,TI_GET_CALLING_CONVENTION
} IMAGEHLP_SYMBOL_TYPE_INFO;
 
typedef struct _TI_FINDCHILDREN_PARAMS {
ULONG Count;
ULONG Start;
ULONG ChildId[1];
} TI_FINDCHILDREN_PARAMS;
 
BOOL IMAGEAPI SymGetTypeInfo(HANDLE hProcess,DWORD64 ModBase,ULONG TypeId,IMAGEHLP_SYMBOL_TYPE_INFO GetType,PVOID pInfo);
BOOL IMAGEAPI SymEnumTypes(HANDLE hProcess,ULONG64 BaseOfDll,PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,PVOID UserContext);
BOOL IMAGEAPI SymGetTypeFromName(HANDLE hProcess,ULONG64 BaseOfDll,LPSTR Name,PSYMBOL_INFO Symbol);
BOOL IMAGEAPI SymAddSymbol(HANDLE hProcess,ULONG64 BaseOfDll,PCSTR Name,DWORD64 Address,DWORD Size,DWORD Flags);
BOOL IMAGEAPI SymDeleteSymbol(HANDLE hProcess,ULONG64 BaseOfDll,PCSTR Name,DWORD64 Address,DWORD Flags);
 
typedef BOOL (WINAPI *PDBGHELP_CREATE_USER_DUMP_CALLBACK)(DWORD DataType,PVOID *Data,LPDWORD DataLength,PVOID UserData);
 
BOOL WINAPI DbgHelpCreateUserDump(LPSTR FileName,PDBGHELP_CREATE_USER_DUMP_CALLBACK Callback,PVOID UserData);
BOOL WINAPI DbgHelpCreateUserDumpW(LPWSTR FileName,PDBGHELP_CREATE_USER_DUMP_CALLBACK Callback,PVOID UserData);
BOOL IMAGEAPI SymGetSymFromAddr64(HANDLE hProcess,DWORD64 qwAddr,PDWORD64 pdwDisplacement,PIMAGEHLP_SYMBOL64 Symbol);
 
#ifdef _IMAGEHLP64
#define SymGetSymFromAddr SymGetSymFromAddr64
#else
BOOL IMAGEAPI SymGetSymFromAddr(HANDLE hProcess,DWORD dwAddr,PDWORD pdwDisplacement,PIMAGEHLP_SYMBOL Symbol);
#endif
 
BOOL IMAGEAPI SymGetSymFromName64(HANDLE hProcess,PSTR Name,PIMAGEHLP_SYMBOL64 Symbol);
 
#ifdef _IMAGEHLP64
#define SymGetSymFromName SymGetSymFromName64
#else
BOOL IMAGEAPI SymGetSymFromName(HANDLE hProcess,PSTR Name,PIMAGEHLP_SYMBOL Symbol);
#endif
 
DBHLP_DEPRECIATED BOOL IMAGEAPI FindFileInPath(HANDLE hprocess,LPSTR SearchPath,LPSTR FileName,PVOID id,DWORD two,DWORD three,DWORD flags,LPSTR FilePath);
DBHLP_DEPRECIATED BOOL IMAGEAPI FindFileInSearchPath(HANDLE hprocess,LPSTR SearchPath,LPSTR FileName,DWORD one,DWORD two,DWORD three,LPSTR FilePath);
DBHLP_DEPRECIATED BOOL IMAGEAPI SymEnumSym(HANDLE hProcess,ULONG64 BaseOfDll,PSYM_ENUMERATESYMBOLS_CALLBACK EnumSymbolsCallback,PVOID UserContext);
 
#define SYMF_OMAP_GENERATED 0x00000001
#define SYMF_OMAP_MODIFIED 0x00000002
#define SYMF_REGISTER 0x00000008
#define SYMF_REGREL 0x00000010
#define SYMF_FRAMEREL 0x00000020
#define SYMF_PARAMETER 0x00000040
#define SYMF_LOCAL 0x00000080
#define SYMF_CONSTANT 0x00000100
#define SYMF_EXPORT 0x00000200
#define SYMF_FORWARDER 0x00000400
#define SYMF_FUNCTION 0x00000800
#define SYMF_VIRTUAL 0x00001000
#define SYMF_THUNK 0x00002000
#define SYMF_TLSREL 0x00004000
 
#define IMAGEHLP_SYMBOL_INFO_VALUEPRESENT 1
#define IMAGEHLP_SYMBOL_INFO_REGISTER SYMF_REGISTER
#define IMAGEHLP_SYMBOL_INFO_REGRELATIVE SYMF_REGREL
#define IMAGEHLP_SYMBOL_INFO_FRAMERELATIVE SYMF_FRAMEREL
#define IMAGEHLP_SYMBOL_INFO_PARAMETER SYMF_PARAMETER
#define IMAGEHLP_SYMBOL_INFO_LOCAL SYMF_LOCAL
#define IMAGEHLP_SYMBOL_INFO_CONSTANT SYMF_CONSTANT
#define IMAGEHLP_SYMBOL_FUNCTION SYMF_FUNCTION
#define IMAGEHLP_SYMBOL_VIRTUAL SYMF_VIRTUAL
#define IMAGEHLP_SYMBOL_THUNK SYMF_THUNK
#define IMAGEHLP_SYMBOL_INFO_TLSRELATIVE SYMF_TLSREL
 
#include <pshpack4.h>
 
#define MINIDUMP_SIGNATURE ('PMDM')
#define MINIDUMP_VERSION (42899)
typedef DWORD RVA;
typedef ULONG64 RVA64;
 
typedef struct _MINIDUMP_LOCATION_DESCRIPTOR {
ULONG32 DataSize;
RVA Rva;
} MINIDUMP_LOCATION_DESCRIPTOR;
 
typedef struct _MINIDUMP_LOCATION_DESCRIPTOR64 {
ULONG64 DataSize;
RVA64 Rva;
} MINIDUMP_LOCATION_DESCRIPTOR64;
 
typedef struct _MINIDUMP_MEMORY_DESCRIPTOR {
ULONG64 StartOfMemoryRange;
MINIDUMP_LOCATION_DESCRIPTOR Memory;
} MINIDUMP_MEMORY_DESCRIPTOR,*PMINIDUMP_MEMORY_DESCRIPTOR;
 
typedef struct _MINIDUMP_MEMORY_DESCRIPTOR64 {
ULONG64 StartOfMemoryRange;
ULONG64 DataSize;
} MINIDUMP_MEMORY_DESCRIPTOR64,*PMINIDUMP_MEMORY_DESCRIPTOR64;
 
typedef struct _MINIDUMP_HEADER {
ULONG32 Signature;
ULONG32 Version;
ULONG32 NumberOfStreams;
RVA StreamDirectoryRva;
ULONG32 CheckSum;
union {
ULONG32 Reserved;
ULONG32 TimeDateStamp;
} DUMMYUNIONNAME;
ULONG64 Flags;
} MINIDUMP_HEADER,*PMINIDUMP_HEADER;
 
typedef struct _MINIDUMP_DIRECTORY {
ULONG32 StreamType;
MINIDUMP_LOCATION_DESCRIPTOR Location;
} MINIDUMP_DIRECTORY,*PMINIDUMP_DIRECTORY;
 
typedef struct _MINIDUMP_STRING {
ULONG32 Length;
WCHAR Buffer [0];
} MINIDUMP_STRING,*PMINIDUMP_STRING;
 
typedef enum _MINIDUMP_STREAM_TYPE {
UnusedStream = 0,ReservedStream0 = 1,ReservedStream1 = 2,ThreadListStream = 3,ModuleListStream = 4,MemoryListStream = 5,
ExceptionStream = 6,SystemInfoStream = 7,ThreadExListStream = 8,Memory64ListStream = 9,CommentStreamA = 10,CommentStreamW = 11,
HandleDataStream = 12,FunctionTableStream = 13,UnloadedModuleListStream = 14,MiscInfoStream = 15,LastReservedStream = 0xffff
} MINIDUMP_STREAM_TYPE;
 
typedef union _CPU_INFORMATION {
struct {
ULONG32 VendorId [3 ];
ULONG32 VersionInformation;
ULONG32 FeatureInformation;
ULONG32 AMDExtendedCpuFeatures;
} X86CpuInfo;
struct {
ULONG64 ProcessorFeatures [2 ];
} OtherCpuInfo;
} CPU_INFORMATION,*PCPU_INFORMATION;
 
typedef struct _MINIDUMP_SYSTEM_INFO {
USHORT ProcessorArchitecture;
USHORT ProcessorLevel;
USHORT ProcessorRevision;
union {
USHORT Reserved0;
struct {
UCHAR NumberOfProcessors;
UCHAR ProductType;
} DUMMYSTRUCTNAME;
} DUMMYUNIONNAME;
ULONG32 MajorVersion;
ULONG32 MinorVersion;
ULONG32 BuildNumber;
ULONG32 PlatformId;
RVA CSDVersionRva;
union {
ULONG32 Reserved1;
struct {
USHORT SuiteMask;
USHORT Reserved2;
} DUMMYSTRUCTNAME;
} DUMMYUNIONNAME1;
CPU_INFORMATION Cpu;
} MINIDUMP_SYSTEM_INFO,*PMINIDUMP_SYSTEM_INFO;
 
C_ASSERT (sizeof (((PPROCESS_INFORMATION)0)->dwThreadId)==4);
 
typedef struct _MINIDUMP_THREAD {
ULONG32 ThreadId;
ULONG32 SuspendCount;
ULONG32 PriorityClass;
ULONG32 Priority;
ULONG64 Teb;
MINIDUMP_MEMORY_DESCRIPTOR Stack;
MINIDUMP_LOCATION_DESCRIPTOR ThreadContext;
} MINIDUMP_THREAD,*PMINIDUMP_THREAD;
 
typedef struct _MINIDUMP_THREAD_LIST {
ULONG32 NumberOfThreads;
MINIDUMP_THREAD Threads [0];
} MINIDUMP_THREAD_LIST,*PMINIDUMP_THREAD_LIST;
 
typedef struct _MINIDUMP_THREAD_EX {
ULONG32 ThreadId;
ULONG32 SuspendCount;
ULONG32 PriorityClass;
ULONG32 Priority;
ULONG64 Teb;
MINIDUMP_MEMORY_DESCRIPTOR Stack;
MINIDUMP_LOCATION_DESCRIPTOR ThreadContext;
MINIDUMP_MEMORY_DESCRIPTOR BackingStore;
} MINIDUMP_THREAD_EX,*PMINIDUMP_THREAD_EX;
 
typedef struct _MINIDUMP_THREAD_EX_LIST {
ULONG32 NumberOfThreads;
MINIDUMP_THREAD_EX Threads [0];
} MINIDUMP_THREAD_EX_LIST,*PMINIDUMP_THREAD_EX_LIST;
 
typedef struct _MINIDUMP_EXCEPTION {
ULONG32 ExceptionCode;
ULONG32 ExceptionFlags;
ULONG64 ExceptionRecord;
ULONG64 ExceptionAddress;
ULONG32 NumberParameters;
ULONG32 __unusedAlignment;
ULONG64 ExceptionInformation [EXCEPTION_MAXIMUM_PARAMETERS ];
} MINIDUMP_EXCEPTION,*PMINIDUMP_EXCEPTION;
 
typedef struct MINIDUMP_EXCEPTION_STREAM {
ULONG32 ThreadId;
ULONG32 __alignment;
MINIDUMP_EXCEPTION ExceptionRecord;
MINIDUMP_LOCATION_DESCRIPTOR ThreadContext;
} MINIDUMP_EXCEPTION_STREAM,*PMINIDUMP_EXCEPTION_STREAM;
 
typedef struct _MINIDUMP_MODULE {
ULONG64 BaseOfImage;
ULONG32 SizeOfImage;
ULONG32 CheckSum;
ULONG32 TimeDateStamp;
RVA ModuleNameRva;
VS_FIXEDFILEINFO VersionInfo;
MINIDUMP_LOCATION_DESCRIPTOR CvRecord;
MINIDUMP_LOCATION_DESCRIPTOR MiscRecord;
ULONG64 Reserved0;
ULONG64 Reserved1;
} MINIDUMP_MODULE,*PMINIDUMP_MODULE;
 
typedef struct _MINIDUMP_MODULE_LIST {
ULONG32 NumberOfModules;
MINIDUMP_MODULE Modules [0 ];
} MINIDUMP_MODULE_LIST,*PMINIDUMP_MODULE_LIST;
 
typedef struct _MINIDUMP_MEMORY_LIST {
ULONG32 NumberOfMemoryRanges;
MINIDUMP_MEMORY_DESCRIPTOR MemoryRanges [0];
} MINIDUMP_MEMORY_LIST,*PMINIDUMP_MEMORY_LIST;
 
typedef struct _MINIDUMP_MEMORY64_LIST {
ULONG64 NumberOfMemoryRanges;
RVA64 BaseRva;
MINIDUMP_MEMORY_DESCRIPTOR64 MemoryRanges [0];
} MINIDUMP_MEMORY64_LIST,*PMINIDUMP_MEMORY64_LIST;
 
typedef struct _MINIDUMP_EXCEPTION_INFORMATION {
DWORD ThreadId;
PEXCEPTION_POINTERS ExceptionPointers;
BOOL ClientPointers;
} MINIDUMP_EXCEPTION_INFORMATION,*PMINIDUMP_EXCEPTION_INFORMATION;
 
typedef struct _MINIDUMP_EXCEPTION_INFORMATION64 {
DWORD ThreadId;
ULONG64 ExceptionRecord;
ULONG64 ContextRecord;
BOOL ClientPointers;
} MINIDUMP_EXCEPTION_INFORMATION64,*PMINIDUMP_EXCEPTION_INFORMATION64;
 
typedef struct _MINIDUMP_HANDLE_DESCRIPTOR {
ULONG64 Handle;
RVA TypeNameRva;
RVA ObjectNameRva;
ULONG32 Attributes;
ULONG32 GrantedAccess;
ULONG32 HandleCount;
ULONG32 PointerCount;
} MINIDUMP_HANDLE_DESCRIPTOR,*PMINIDUMP_HANDLE_DESCRIPTOR;
 
typedef struct _MINIDUMP_HANDLE_DATA_STREAM {
ULONG32 SizeOfHeader;
ULONG32 SizeOfDescriptor;
ULONG32 NumberOfDescriptors;
ULONG32 Reserved;
} MINIDUMP_HANDLE_DATA_STREAM,*PMINIDUMP_HANDLE_DATA_STREAM;
 
typedef struct _MINIDUMP_FUNCTION_TABLE_DESCRIPTOR {
ULONG64 MinimumAddress;
ULONG64 MaximumAddress;
ULONG64 BaseAddress;
ULONG32 EntryCount;
ULONG32 SizeOfAlignPad;
} MINIDUMP_FUNCTION_TABLE_DESCRIPTOR,*PMINIDUMP_FUNCTION_TABLE_DESCRIPTOR;
 
typedef struct _MINIDUMP_FUNCTION_TABLE_STREAM {
ULONG32 SizeOfHeader;
ULONG32 SizeOfDescriptor;
ULONG32 SizeOfNativeDescriptor;
ULONG32 SizeOfFunctionEntry;
ULONG32 NumberOfDescriptors;
ULONG32 SizeOfAlignPad;
} MINIDUMP_FUNCTION_TABLE_STREAM,*PMINIDUMP_FUNCTION_TABLE_STREAM;
 
typedef struct _MINIDUMP_UNLOADED_MODULE {
ULONG64 BaseOfImage;
ULONG32 SizeOfImage;
ULONG32 CheckSum;
ULONG32 TimeDateStamp;
RVA ModuleNameRva;
} MINIDUMP_UNLOADED_MODULE,*PMINIDUMP_UNLOADED_MODULE;
 
typedef struct _MINIDUMP_UNLOADED_MODULE_LIST {
ULONG32 SizeOfHeader;
ULONG32 SizeOfEntry;
ULONG32 NumberOfEntries;
} MINIDUMP_UNLOADED_MODULE_LIST,*PMINIDUMP_UNLOADED_MODULE_LIST;
 
#define MINIDUMP_MISC1_PROCESS_ID 0x00000001
#define MINIDUMP_MISC1_PROCESS_TIMES 0x00000002
 
typedef struct _MINIDUMP_MISC_INFO {
ULONG32 SizeOfInfo;
ULONG32 Flags1;
ULONG32 ProcessId;
ULONG32 ProcessCreateTime;
ULONG32 ProcessUserTime;
ULONG32 ProcessKernelTime;
} MINIDUMP_MISC_INFO,*PMINIDUMP_MISC_INFO;
 
typedef struct _MINIDUMP_USER_RECORD {
ULONG32 Type;
MINIDUMP_LOCATION_DESCRIPTOR Memory;
} MINIDUMP_USER_RECORD,*PMINIDUMP_USER_RECORD;
 
typedef struct _MINIDUMP_USER_STREAM {
ULONG32 Type;
ULONG BufferSize;
PVOID Buffer;
} MINIDUMP_USER_STREAM,*PMINIDUMP_USER_STREAM;
 
typedef struct _MINIDUMP_USER_STREAM_INFORMATION {
ULONG UserStreamCount;
PMINIDUMP_USER_STREAM UserStreamArray;
} MINIDUMP_USER_STREAM_INFORMATION,*PMINIDUMP_USER_STREAM_INFORMATION;
 
typedef enum _MINIDUMP_CALLBACK_TYPE {
ModuleCallback,ThreadCallback,ThreadExCallback,IncludeThreadCallback,IncludeModuleCallback,MemoryCallback
} MINIDUMP_CALLBACK_TYPE;
 
typedef struct _MINIDUMP_THREAD_CALLBACK {
ULONG ThreadId;
HANDLE ThreadHandle;
CONTEXT Context;
ULONG SizeOfContext;
ULONG64 StackBase;
ULONG64 StackEnd;
} MINIDUMP_THREAD_CALLBACK,*PMINIDUMP_THREAD_CALLBACK;
 
typedef struct _MINIDUMP_THREAD_EX_CALLBACK {
ULONG ThreadId;
HANDLE ThreadHandle;
CONTEXT Context;
ULONG SizeOfContext;
ULONG64 StackBase;
ULONG64 StackEnd;
ULONG64 BackingStoreBase;
ULONG64 BackingStoreEnd;
} MINIDUMP_THREAD_EX_CALLBACK,*PMINIDUMP_THREAD_EX_CALLBACK;
 
typedef struct _MINIDUMP_INCLUDE_THREAD_CALLBACK {
ULONG ThreadId;
} MINIDUMP_INCLUDE_THREAD_CALLBACK,*PMINIDUMP_INCLUDE_THREAD_CALLBACK;
 
typedef enum _THREAD_WRITE_FLAGS {
ThreadWriteThread = 0x0001,ThreadWriteStack = 0x0002,ThreadWriteContext = 0x0004,ThreadWriteBackingStore = 0x0008,
ThreadWriteInstructionWindow = 0x0010,ThreadWriteThreadData = 0x0020
} THREAD_WRITE_FLAGS;
 
typedef struct _MINIDUMP_MODULE_CALLBACK {
PWCHAR FullPath;
ULONG64 BaseOfImage;
ULONG SizeOfImage;
ULONG CheckSum;
ULONG TimeDateStamp;
VS_FIXEDFILEINFO VersionInfo;
PVOID CvRecord;
ULONG SizeOfCvRecord;
PVOID MiscRecord;
ULONG SizeOfMiscRecord;
} MINIDUMP_MODULE_CALLBACK,*PMINIDUMP_MODULE_CALLBACK;
 
typedef struct _MINIDUMP_INCLUDE_MODULE_CALLBACK {
ULONG64 BaseOfImage;
} MINIDUMP_INCLUDE_MODULE_CALLBACK,*PMINIDUMP_INCLUDE_MODULE_CALLBACK;
 
typedef enum _MODULE_WRITE_FLAGS {
ModuleWriteModule = 0x0001,ModuleWriteDataSeg = 0x0002,ModuleWriteMiscRecord = 0x0004,ModuleWriteCvRecord = 0x0008,
ModuleReferencedByMemory = 0x0010
} MODULE_WRITE_FLAGS;
 
typedef struct _MINIDUMP_CALLBACK_INPUT {
ULONG ProcessId;
HANDLE ProcessHandle;
ULONG CallbackType;
union {
MINIDUMP_THREAD_CALLBACK Thread;
MINIDUMP_THREAD_EX_CALLBACK ThreadEx;
MINIDUMP_MODULE_CALLBACK Module;
MINIDUMP_INCLUDE_THREAD_CALLBACK IncludeThread;
MINIDUMP_INCLUDE_MODULE_CALLBACK IncludeModule;
} DUMMYUNIONNAME;
} MINIDUMP_CALLBACK_INPUT,*PMINIDUMP_CALLBACK_INPUT;
 
typedef struct _MINIDUMP_CALLBACK_OUTPUT {
union {
ULONG ModuleWriteFlags;
ULONG ThreadWriteFlags;
struct {
ULONG64 MemoryBase;
ULONG MemorySize;
} DUMMYSTRUCTNAME;
} DUMMYUNIONNAME;
} MINIDUMP_CALLBACK_OUTPUT,*PMINIDUMP_CALLBACK_OUTPUT;
 
typedef enum _MINIDUMP_TYPE {
MiniDumpNormal = 0x0000,MiniDumpWithDataSegs = 0x0001,MiniDumpWithFullMemory = 0x0002,MiniDumpWithHandleData = 0x0004,
MiniDumpFilterMemory = 0x0008,MiniDumpScanMemory = 0x0010,MiniDumpWithUnloadedModules = 0x0020,MiniDumpWithIndirectlyReferencedMemory = 0x0040,
MiniDumpFilterModulePaths = 0x0080,MiniDumpWithProcessThreadData = 0x0100,MiniDumpWithPrivateReadWriteMemory = 0x0200,
MiniDumpWithoutOptionalData = 0x0400
} MINIDUMP_TYPE;
 
typedef BOOL (WINAPI *MINIDUMP_CALLBACK_ROUTINE)(PVOID CallbackParam,CONST PMINIDUMP_CALLBACK_INPUT CallbackInput,PMINIDUMP_CALLBACK_OUTPUT CallbackOutput);
 
typedef struct _MINIDUMP_CALLBACK_INFORMATION {
MINIDUMP_CALLBACK_ROUTINE CallbackRoutine;
PVOID CallbackParam;
} MINIDUMP_CALLBACK_INFORMATION,*PMINIDUMP_CALLBACK_INFORMATION;
 
#define RVA_TO_ADDR(Mapping,Rva) ((PVOID)(((ULONG_PTR) (Mapping)) + (Rva)))
 
BOOL WINAPI MiniDumpWriteDump(HANDLE hProcess,DWORD ProcessId,HANDLE hFile,MINIDUMP_TYPE DumpType,CONST PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,CONST PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,CONST PMINIDUMP_CALLBACK_INFORMATION CallbackParam);
BOOL WINAPI MiniDumpReadDumpStream(PVOID BaseOfDump,ULONG StreamNumber,PMINIDUMP_DIRECTORY *Dir,PVOID *StreamPointer,ULONG *StreamSize);
 
#include <poppack.h>
 
#ifdef __cplusplus
}
#endif
#endif
/drivers/video/Gallium/auxiliary/util/texcompress_etc_tmp.h
0,0 → 1,170
/*
* Copyright (C) 2011 LunarG, Inc.
*
* 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, sublicense,
* 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 NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
*/
 
/*
* Included by texcompress_etc1 and gallium to define ETC1 decoding routines.
*/
 
struct TAG(etc1_block) {
uint32_t pixel_indices;
int flipped;
const int *modifier_tables[2];
UINT8_TYPE base_colors[2][3];
};
 
static UINT8_TYPE
TAG(etc1_base_color_diff_hi)(UINT8_TYPE in)
{
return (in & 0xf8) | (in >> 5);
}
 
static UINT8_TYPE
TAG(etc1_base_color_diff_lo)(UINT8_TYPE in)
{
static const int lookup[8] = { 0, 1, 2, 3, -4, -3, -2, -1 };
 
in = (in >> 3) + lookup[in & 0x7];
 
return (in << 3) | (in >> 2);
}
 
static UINT8_TYPE
TAG(etc1_base_color_ind_hi)(UINT8_TYPE in)
{
return (in & 0xf0) | ((in & 0xf0) >> 4);
}
 
static UINT8_TYPE
TAG(etc1_base_color_ind_lo)(UINT8_TYPE in)
{
return ((in & 0xf) << 4) | (in & 0xf);
}
 
static UINT8_TYPE
TAG(etc1_clamp)(UINT8_TYPE base, int modifier)
{
int tmp = (int) base + modifier;
 
/* CLAMP(tmp, 0, 255) */
return (UINT8_TYPE) ((tmp < 0) ? 0 : ((tmp > 255) ? 255 : tmp));
}
 
static const int TAG(etc1_modifier_tables)[8][4] = {
{ 2, 8, -2, -8},
{ 5, 17, -5, -17},
{ 9, 29, -9, -29},
{ 13, 42, -13, -42},
{ 18, 60, -18, -60},
{ 24, 80, -24, -80},
{ 33, 106, -33, -106},
{ 47, 183, -47, -183}
};
 
static void
TAG(etc1_parse_block)(struct TAG(etc1_block) *block, const UINT8_TYPE *src)
{
if (src[3] & 0x2) {
/* differential mode */
block->base_colors[0][0] = (int) TAG(etc1_base_color_diff_hi)(src[0]);
block->base_colors[1][0] = (int) TAG(etc1_base_color_diff_lo)(src[0]);
block->base_colors[0][1] = (int) TAG(etc1_base_color_diff_hi)(src[1]);
block->base_colors[1][1] = (int) TAG(etc1_base_color_diff_lo)(src[1]);
block->base_colors[0][2] = (int) TAG(etc1_base_color_diff_hi)(src[2]);
block->base_colors[1][2] = (int) TAG(etc1_base_color_diff_lo)(src[2]);
}
else {
/* individual mode */
block->base_colors[0][0] = (int) TAG(etc1_base_color_ind_hi)(src[0]);
block->base_colors[1][0] = (int) TAG(etc1_base_color_ind_lo)(src[0]);
block->base_colors[0][1] = (int) TAG(etc1_base_color_ind_hi)(src[1]);
block->base_colors[1][1] = (int) TAG(etc1_base_color_ind_lo)(src[1]);
block->base_colors[0][2] = (int) TAG(etc1_base_color_ind_hi)(src[2]);
block->base_colors[1][2] = (int) TAG(etc1_base_color_ind_lo)(src[2]);
}
 
/* pick modifier tables */
block->modifier_tables[0] = TAG(etc1_modifier_tables)[(src[3] >> 5) & 0x7];
block->modifier_tables[1] = TAG(etc1_modifier_tables)[(src[3] >> 2) & 0x7];
 
block->flipped = (src[3] & 0x1);
 
block->pixel_indices =
(src[4] << 24) | (src[5] << 16) | (src[6] << 8) | src[7];
}
 
static void
TAG(etc1_fetch_texel)(const struct TAG(etc1_block) *block,
int x, int y, UINT8_TYPE *dst)
{
const UINT8_TYPE *base_color;
int modifier, bit, idx, blk;
 
/* get pixel index */
bit = y + x * 4;
idx = ((block->pixel_indices >> (15 + bit)) & 0x2) |
((block->pixel_indices >> (bit)) & 0x1);
 
/* get subblock */
blk = (block->flipped) ? (y >= 2) : (x >= 2);
 
base_color = block->base_colors[blk];
modifier = block->modifier_tables[blk][idx];
 
dst[0] = TAG(etc1_clamp)(base_color[0], modifier);
dst[1] = TAG(etc1_clamp)(base_color[1], modifier);
dst[2] = TAG(etc1_clamp)(base_color[2], modifier);
}
 
static void
etc1_unpack_rgba8888(uint8_t *dst_row,
unsigned dst_stride,
const uint8_t *src_row,
unsigned src_stride,
unsigned width,
unsigned height)
{
const unsigned bw = 4, bh = 4, bs = 8, comps = 4;
struct etc1_block block;
unsigned x, y, i, j;
 
for (y = 0; y < height; y += bh) {
const uint8_t *src = src_row;
 
for (x = 0; x < width; x+= bw) {
etc1_parse_block(&block, src);
 
for (j = 0; j < MIN2(bh, height - y); j++) {
uint8_t *dst = dst_row + (y + j) * dst_stride + x * comps;
for (i = 0; i < MIN2(bw, width - x); i++) {
etc1_fetch_texel(&block, i, j, dst);
dst[3] = 255;
dst += comps;
}
}
 
src += bs;
}
 
src_row += src_stride;
}
}
/drivers/video/Gallium/auxiliary/util/texcompress_rgtc_tmp.h
0,0 → 1,418
/*
* Copyright (C) 2011 Red Hat Inc.
*
* block compression parts are:
* Copyright (C) 2004 Roland Scheidegger 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, sublicense,
* 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 NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
*
* Author:
* Dave Airlie
*/
 
/* included by texcompress_rgtc to define byte/ubyte compressors */
 
static void TAG(fetch_texel_rgtc)(unsigned srcRowStride, const TYPE *pixdata,
unsigned i, unsigned j, TYPE *value, unsigned comps)
{
TYPE decode;
const TYPE *blksrc = (pixdata + ((srcRowStride + 3) / 4 * (j / 4) + (i / 4)) * 8 * comps);
const TYPE alpha0 = blksrc[0];
const TYPE alpha1 = blksrc[1];
const char bit_pos = ((j&3) * 4 + (i&3)) * 3;
const TYPE acodelow = blksrc[2 + bit_pos / 8];
const TYPE acodehigh = (3 + bit_pos / 8) < 8 ? blksrc[3 + bit_pos / 8] : 0;
const TYPE code = (acodelow >> (bit_pos & 0x7) |
(acodehigh << (8 - (bit_pos & 0x7)))) & 0x7;
 
if (code == 0)
decode = alpha0;
else if (code == 1)
decode = alpha1;
else if (alpha0 > alpha1)
decode = ((alpha0 * (8 - code) + (alpha1 * (code - 1))) / 7);
else if (code < 6)
decode = ((alpha0 * (6 - code) + (alpha1 * (code - 1))) / 5);
else if (code == 6)
decode = T_MIN;
else
decode = T_MAX;
 
*value = decode;
}
 
static void TAG(write_rgtc_encoded_channel)(TYPE *blkaddr,
TYPE alphabase1,
TYPE alphabase2,
TYPE alphaenc[16])
{
*blkaddr++ = alphabase1;
*blkaddr++ = alphabase2;
*blkaddr++ = alphaenc[0] | (alphaenc[1] << 3) | ((alphaenc[2] & 3) << 6);
*blkaddr++ = (alphaenc[2] >> 2) | (alphaenc[3] << 1) | (alphaenc[4] << 4) | ((alphaenc[5] & 1) << 7);
*blkaddr++ = (alphaenc[5] >> 1) | (alphaenc[6] << 2) | (alphaenc[7] << 5);
*blkaddr++ = alphaenc[8] | (alphaenc[9] << 3) | ((alphaenc[10] & 3) << 6);
*blkaddr++ = (alphaenc[10] >> 2) | (alphaenc[11] << 1) | (alphaenc[12] << 4) | ((alphaenc[13] & 1) << 7);
*blkaddr++ = (alphaenc[13] >> 1) | (alphaenc[14] << 2) | (alphaenc[15] << 5);
}
 
static void TAG(encode_rgtc_ubyte)(TYPE *blkaddr, TYPE srccolors[4][4],
int numxpixels, int numypixels)
{
TYPE alphabase[2], alphause[2];
short alphatest[2] = { 0 };
unsigned int alphablockerror1, alphablockerror2, alphablockerror3;
TYPE i, j, aindex, acutValues[7];
TYPE alphaenc1[16], alphaenc2[16], alphaenc3[16];
int alphaabsmin = 0, alphaabsmax = 0;
short alphadist;
 
/* find lowest and highest alpha value in block, alphabase[0] lowest, alphabase[1] highest */
alphabase[0] = T_MAX; alphabase[1] = T_MIN;
for (j = 0; j < numypixels; j++) {
for (i = 0; i < numxpixels; i++) {
if (srccolors[j][i] == T_MIN)
alphaabsmin = 1;
else if (srccolors[j][i] == T_MAX)
alphaabsmax = 1;
else {
if (srccolors[j][i] > alphabase[1])
alphabase[1] = srccolors[j][i];
if (srccolors[j][i] < alphabase[0])
alphabase[0] = srccolors[j][i];
}
}
}
 
 
if (((alphabase[0] > alphabase[1]) && !(alphaabsmin && alphaabsmax))
|| (alphabase[0] == alphabase[1] && !alphaabsmin && !alphaabsmax)) { /* one color, either max or min */
/* shortcut here since it is a very common case (and also avoids later problems) */
/* could also thest for alpha0 == alpha1 (and not min/max), but probably not common, so don't bother */
 
*blkaddr++ = srccolors[0][0];
blkaddr++;
*blkaddr++ = 0;
*blkaddr++ = 0;
*blkaddr++ = 0;
*blkaddr++ = 0;
*blkaddr++ = 0;
*blkaddr++ = 0;
#if RGTC_DEBUG
fprintf(stderr, "enc0 used\n");
#endif
return;
}
 
/* find best encoding for alpha0 > alpha1 */
/* it's possible this encoding is better even if both alphaabsmin and alphaabsmax are true */
alphablockerror1 = 0x0;
alphablockerror2 = 0xffffffff;
alphablockerror3 = 0xffffffff;
if (alphaabsmin) alphause[0] = T_MIN;
else alphause[0] = alphabase[0];
if (alphaabsmax) alphause[1] = T_MAX;
else alphause[1] = alphabase[1];
/* calculate the 7 cut values, just the middle between 2 of the computed alpha values */
for (aindex = 0; aindex < 7; aindex++) {
/* don't forget here is always rounded down */
acutValues[aindex] = (alphause[0] * (2*aindex + 1) + alphause[1] * (14 - (2*aindex + 1))) / 14;
}
 
for (j = 0; j < numypixels; j++) {
for (i = 0; i < numxpixels; i++) {
/* maybe it's overkill to have the most complicated calculation just for the error
calculation which we only need to figure out if encoding1 or encoding2 is better... */
if (srccolors[j][i] > acutValues[0]) {
alphaenc1[4*j + i] = 0;
alphadist = srccolors[j][i] - alphause[1];
}
else if (srccolors[j][i] > acutValues[1]) {
alphaenc1[4*j + i] = 2;
alphadist = srccolors[j][i] - (alphause[1] * 6 + alphause[0] * 1) / 7;
}
else if (srccolors[j][i] > acutValues[2]) {
alphaenc1[4*j + i] = 3;
alphadist = srccolors[j][i] - (alphause[1] * 5 + alphause[0] * 2) / 7;
}
else if (srccolors[j][i] > acutValues[3]) {
alphaenc1[4*j + i] = 4;
alphadist = srccolors[j][i] - (alphause[1] * 4 + alphause[0] * 3) / 7;
}
else if (srccolors[j][i] > acutValues[4]) {
alphaenc1[4*j + i] = 5;
alphadist = srccolors[j][i] - (alphause[1] * 3 + alphause[0] * 4) / 7;
}
else if (srccolors[j][i] > acutValues[5]) {
alphaenc1[4*j + i] = 6;
alphadist = srccolors[j][i] - (alphause[1] * 2 + alphause[0] * 5) / 7;
}
else if (srccolors[j][i] > acutValues[6]) {
alphaenc1[4*j + i] = 7;
alphadist = srccolors[j][i] - (alphause[1] * 1 + alphause[0] * 6) / 7;
}
else {
alphaenc1[4*j + i] = 1;
alphadist = srccolors[j][i] - alphause[0];
}
alphablockerror1 += alphadist * alphadist;
}
}
 
#if RGTC_DEBUG
for (i = 0; i < 16; i++) {
fprintf(stderr, "%d ", alphaenc1[i]);
}
fprintf(stderr, "cutVals ");
for (i = 0; i < 7; i++) {
fprintf(stderr, "%d ", acutValues[i]);
}
fprintf(stderr, "srcVals ");
for (j = 0; j < numypixels; j++) {
for (i = 0; i < numxpixels; i++) {
fprintf(stderr, "%d ", srccolors[j][i]);
}
}
fprintf(stderr, "\n");
#endif
 
/* it's not very likely this encoding is better if both alphaabsmin and alphaabsmax
are false but try it anyway */
if (alphablockerror1 >= 32) {
 
/* don't bother if encoding is already very good, this condition should also imply
we have valid alphabase colors which we absolutely need (alphabase[0] <= alphabase[1]) */
alphablockerror2 = 0;
for (aindex = 0; aindex < 5; aindex++) {
/* don't forget here is always rounded down */
acutValues[aindex] = (alphabase[0] * (10 - (2*aindex + 1)) + alphabase[1] * (2*aindex + 1)) / 10;
}
for (j = 0; j < numypixels; j++) {
for (i = 0; i < numxpixels; i++) {
/* maybe it's overkill to have the most complicated calculation just for the error
calculation which we only need to figure out if encoding1 or encoding2 is better... */
if (srccolors[j][i] == T_MIN) {
alphaenc2[4*j + i] = 6;
alphadist = 0;
}
else if (srccolors[j][i] == T_MAX) {
alphaenc2[4*j + i] = 7;
alphadist = 0;
}
else if (srccolors[j][i] <= acutValues[0]) {
alphaenc2[4*j + i] = 0;
alphadist = srccolors[j][i] - alphabase[0];
}
else if (srccolors[j][i] <= acutValues[1]) {
alphaenc2[4*j + i] = 2;
alphadist = srccolors[j][i] - (alphabase[0] * 4 + alphabase[1] * 1) / 5;
}
else if (srccolors[j][i] <= acutValues[2]) {
alphaenc2[4*j + i] = 3;
alphadist = srccolors[j][i] - (alphabase[0] * 3 + alphabase[1] * 2) / 5;
}
else if (srccolors[j][i] <= acutValues[3]) {
alphaenc2[4*j + i] = 4;
alphadist = srccolors[j][i] - (alphabase[0] * 2 + alphabase[1] * 3) / 5;
}
else if (srccolors[j][i] <= acutValues[4]) {
alphaenc2[4*j + i] = 5;
alphadist = srccolors[j][i] - (alphabase[0] * 1 + alphabase[1] * 4) / 5;
}
else {
alphaenc2[4*j + i] = 1;
alphadist = srccolors[j][i] - alphabase[1];
}
alphablockerror2 += alphadist * alphadist;
}
}
 
 
/* skip this if the error is already very small
this encoding is MUCH better on average than #2 though, but expensive! */
if ((alphablockerror2 > 96) && (alphablockerror1 > 96)) {
short blockerrlin1 = 0;
short blockerrlin2 = 0;
TYPE nralphainrangelow = 0;
TYPE nralphainrangehigh = 0;
alphatest[0] = T_MAX;
alphatest[1] = T_MIN;
/* if we have large range it's likely there are values close to 0/255, try to map them to 0/255 */
for (j = 0; j < numypixels; j++) {
for (i = 0; i < numxpixels; i++) {
if ((srccolors[j][i] > alphatest[1]) && (srccolors[j][i] < (T_MAX -(alphabase[1] - alphabase[0]) / 28)))
alphatest[1] = srccolors[j][i];
if ((srccolors[j][i] < alphatest[0]) && (srccolors[j][i] > (alphabase[1] - alphabase[0]) / 28))
alphatest[0] = srccolors[j][i];
}
}
/* shouldn't happen too often, don't really care about those degenerated cases */
if (alphatest[1] <= alphatest[0]) {
alphatest[0] = T_MIN+1;
alphatest[1] = T_MAX-1;
}
for (aindex = 0; aindex < 5; aindex++) {
/* don't forget here is always rounded down */
acutValues[aindex] = (alphatest[0] * (10 - (2*aindex + 1)) + alphatest[1] * (2*aindex + 1)) / 10;
}
 
/* find the "average" difference between the alpha values and the next encoded value.
This is then used to calculate new base values.
Should there be some weighting, i.e. those values closer to alphatest[x] have more weight,
since they will see more improvement, and also because the values in the middle are somewhat
likely to get no improvement at all (because the base values might move in different directions)?
OTOH it would mean the values in the middle are even less likely to get an improvement
*/
for (j = 0; j < numypixels; j++) {
for (i = 0; i < numxpixels; i++) {
if (srccolors[j][i] <= alphatest[0] / 2) {
}
else if (srccolors[j][i] > ((T_MAX + alphatest[1]) / 2)) {
}
else if (srccolors[j][i] <= acutValues[0]) {
blockerrlin1 += (srccolors[j][i] - alphatest[0]);
nralphainrangelow += 1;
}
else if (srccolors[j][i] <= acutValues[1]) {
blockerrlin1 += (srccolors[j][i] - (alphatest[0] * 4 + alphatest[1] * 1) / 5);
blockerrlin2 += (srccolors[j][i] - (alphatest[0] * 4 + alphatest[1] * 1) / 5);
nralphainrangelow += 1;
nralphainrangehigh += 1;
}
else if (srccolors[j][i] <= acutValues[2]) {
blockerrlin1 += (srccolors[j][i] - (alphatest[0] * 3 + alphatest[1] * 2) / 5);
blockerrlin2 += (srccolors[j][i] - (alphatest[0] * 3 + alphatest[1] * 2) / 5);
nralphainrangelow += 1;
nralphainrangehigh += 1;
}
else if (srccolors[j][i] <= acutValues[3]) {
blockerrlin1 += (srccolors[j][i] - (alphatest[0] * 2 + alphatest[1] * 3) / 5);
blockerrlin2 += (srccolors[j][i] - (alphatest[0] * 2 + alphatest[1] * 3) / 5);
nralphainrangelow += 1;
nralphainrangehigh += 1;
}
else if (srccolors[j][i] <= acutValues[4]) {
blockerrlin1 += (srccolors[j][i] - (alphatest[0] * 1 + alphatest[1] * 4) / 5);
blockerrlin2 += (srccolors[j][i] - (alphatest[0] * 1 + alphatest[1] * 4) / 5);
nralphainrangelow += 1;
nralphainrangehigh += 1;
}
else {
blockerrlin2 += (srccolors[j][i] - alphatest[1]);
nralphainrangehigh += 1;
}
}
}
/* shouldn't happen often, needed to avoid div by zero */
if (nralphainrangelow == 0) nralphainrangelow = 1;
if (nralphainrangehigh == 0) nralphainrangehigh = 1;
alphatest[0] = alphatest[0] + (blockerrlin1 / nralphainrangelow);
#if RGTC_DEBUG
fprintf(stderr, "block err lin low %d, nr %d\n", blockerrlin1, nralphainrangelow);
fprintf(stderr, "block err lin high %d, nr %d\n", blockerrlin2, nralphainrangehigh);
#endif
/* again shouldn't really happen often... */
if (alphatest[0] < T_MIN) {
alphatest[0] = T_MIN;
}
alphatest[1] = alphatest[1] + (blockerrlin2 / nralphainrangehigh);
if (alphatest[1] > T_MAX) {
alphatest[1] = T_MAX;
}
 
alphablockerror3 = 0;
for (aindex = 0; aindex < 5; aindex++) {
/* don't forget here is always rounded down */
acutValues[aindex] = (alphatest[0] * (10 - (2*aindex + 1)) + alphatest[1] * (2*aindex + 1)) / 10;
}
for (j = 0; j < numypixels; j++) {
for (i = 0; i < numxpixels; i++) {
/* maybe it's overkill to have the most complicated calculation just for the error
calculation which we only need to figure out if encoding1 or encoding2 is better... */
if (srccolors[j][i] <= alphatest[0] / 2) {
alphaenc3[4*j + i] = 6;
alphadist = srccolors[j][i];
}
else if (srccolors[j][i] > ((T_MAX + alphatest[1]) / 2)) {
alphaenc3[4*j + i] = 7;
alphadist = T_MAX - srccolors[j][i];
}
else if (srccolors[j][i] <= acutValues[0]) {
alphaenc3[4*j + i] = 0;
alphadist = srccolors[j][i] - alphatest[0];
}
else if (srccolors[j][i] <= acutValues[1]) {
alphaenc3[4*j + i] = 2;
alphadist = srccolors[j][i] - (alphatest[0] * 4 + alphatest[1] * 1) / 5;
}
else if (srccolors[j][i] <= acutValues[2]) {
alphaenc3[4*j + i] = 3;
alphadist = srccolors[j][i] - (alphatest[0] * 3 + alphatest[1] * 2) / 5;
}
else if (srccolors[j][i] <= acutValues[3]) {
alphaenc3[4*j + i] = 4;
alphadist = srccolors[j][i] - (alphatest[0] * 2 + alphatest[1] * 3) / 5;
}
else if (srccolors[j][i] <= acutValues[4]) {
alphaenc3[4*j + i] = 5;
alphadist = srccolors[j][i] - (alphatest[0] * 1 + alphatest[1] * 4) / 5;
}
else {
alphaenc3[4*j + i] = 1;
alphadist = srccolors[j][i] - alphatest[1];
}
alphablockerror3 += alphadist * alphadist;
}
}
}
}
 
/* write the alpha values and encoding back. */
if ((alphablockerror1 <= alphablockerror2) && (alphablockerror1 <= alphablockerror3)) {
#if RGTC_DEBUG
if (alphablockerror1 > 96) fprintf(stderr, "enc1 used, error %d\n", alphablockerror1);
fprintf(stderr,"w1: min %d max %d au0 %d au1 %d\n",
T_MIN, T_MAX,
alphause[1], alphause[0]);
#endif
 
TAG(write_rgtc_encoded_channel)( blkaddr, alphause[1], alphause[0], alphaenc1 );
}
else if (alphablockerror2 <= alphablockerror3) {
#if RGTC_DEBUG
if (alphablockerror2 > 96) fprintf(stderr, "enc2 used, error %d\n", alphablockerror2);
fprintf(stderr,"w2: min %d max %d au0 %d au1 %d\n",
T_MIN, T_MAX,
alphabase[0], alphabase[1]);
#endif
 
TAG(write_rgtc_encoded_channel)( blkaddr, alphabase[0], alphabase[1], alphaenc2 );
}
else {
#if RGTC_DEBUG
fprintf(stderr, "enc3 used, error %d\n", alphablockerror3);
fprintf(stderr,"w3: min %d max %d au0 %d au1 %d\n",
T_MIN, T_MAX,
alphatest[0], alphatest[1]);
#endif
 
TAG(write_rgtc_encoded_channel)( blkaddr, (TYPE)alphatest[0], (TYPE)alphatest[1], alphaenc3 );
}
}
/drivers/video/Gallium/auxiliary/util/u_atomic.h
0,0 → 1,349
/**
* Many similar implementations exist. See for example libwsbm
* or the linux kernel include/atomic.h
*
* No copyright claimed on this file.
*
*/
 
#ifndef U_ATOMIC_H
#define U_ATOMIC_H
 
#include "pipe/p_compiler.h"
#include "pipe/p_defines.h"
 
/* Favor OS-provided implementations.
*
* Where no OS-provided implementation is available, fall back to
* locally coded assembly, compiler intrinsic or ultimately a
* mutex-based implementation.
*/
#if defined(PIPE_OS_SOLARIS)
#define PIPE_ATOMIC_OS_SOLARIS
#elif defined(PIPE_CC_MSVC)
#define PIPE_ATOMIC_MSVC_INTRINSIC
#elif (defined(PIPE_CC_MSVC) && defined(PIPE_ARCH_X86))
#define PIPE_ATOMIC_ASM_MSVC_X86
#elif (defined(PIPE_CC_GCC) && defined(PIPE_ARCH_X86))
#define PIPE_ATOMIC_ASM_GCC_X86
#elif (defined(PIPE_CC_GCC) && defined(PIPE_ARCH_X86_64))
#define PIPE_ATOMIC_ASM_GCC_X86_64
#elif defined(PIPE_CC_GCC) && (PIPE_CC_GCC_VERSION >= 401)
#define PIPE_ATOMIC_GCC_INTRINSIC
#else
#error "Unsupported platform"
#endif
 
 
#if defined(PIPE_ATOMIC_ASM_GCC_X86_64)
#define PIPE_ATOMIC "GCC x86_64 assembly"
 
#ifdef __cplusplus
extern "C" {
#endif
 
#define p_atomic_set(_v, _i) (*(_v) = (_i))
#define p_atomic_read(_v) (*(_v))
 
static INLINE boolean
p_atomic_dec_zero(int32_t *v)
{
unsigned char c;
 
__asm__ __volatile__("lock; decl %0; sete %1":"+m"(*v), "=qm"(c)
::"memory");
 
return c != 0;
}
 
static INLINE void
p_atomic_inc(int32_t *v)
{
__asm__ __volatile__("lock; incl %0":"+m"(*v));
}
 
static INLINE void
p_atomic_dec(int32_t *v)
{
__asm__ __volatile__("lock; decl %0":"+m"(*v));
}
 
static INLINE int32_t
p_atomic_cmpxchg(int32_t *v, int32_t old, int32_t _new)
{
return __sync_val_compare_and_swap(v, old, _new);
}
 
#ifdef __cplusplus
}
#endif
 
#endif /* PIPE_ATOMIC_ASM_GCC_X86_64 */
 
 
#if defined(PIPE_ATOMIC_ASM_GCC_X86)
 
#define PIPE_ATOMIC "GCC x86 assembly"
 
#ifdef __cplusplus
extern "C" {
#endif
 
#define p_atomic_set(_v, _i) (*(_v) = (_i))
#define p_atomic_read(_v) (*(_v))
 
static INLINE boolean
p_atomic_dec_zero(int32_t *v)
{
unsigned char c;
 
__asm__ __volatile__("lock; decl %0; sete %1":"+m"(*v), "=qm"(c)
::"memory");
 
return c != 0;
}
 
static INLINE void
p_atomic_inc(int32_t *v)
{
__asm__ __volatile__("lock; incl %0":"+m"(*v));
}
 
static INLINE void
p_atomic_dec(int32_t *v)
{
__asm__ __volatile__("lock; decl %0":"+m"(*v));
}
 
static INLINE int32_t
p_atomic_cmpxchg(int32_t *v, int32_t old, int32_t _new)
{
return __sync_val_compare_and_swap(v, old, _new);
}
 
#ifdef __cplusplus
}
#endif
 
#endif
 
 
 
/* Implementation using GCC-provided synchronization intrinsics
*/
#if defined(PIPE_ATOMIC_GCC_INTRINSIC)
 
#define PIPE_ATOMIC "GCC Sync Intrinsics"
 
#ifdef __cplusplus
extern "C" {
#endif
 
#define p_atomic_set(_v, _i) (*(_v) = (_i))
#define p_atomic_read(_v) (*(_v))
 
static INLINE boolean
p_atomic_dec_zero(int32_t *v)
{
return (__sync_sub_and_fetch(v, 1) == 0);
}
 
static INLINE void
p_atomic_inc(int32_t *v)
{
(void) __sync_add_and_fetch(v, 1);
}
 
static INLINE void
p_atomic_dec(int32_t *v)
{
(void) __sync_sub_and_fetch(v, 1);
}
 
static INLINE int32_t
p_atomic_cmpxchg(int32_t *v, int32_t old, int32_t _new)
{
return __sync_val_compare_and_swap(v, old, _new);
}
 
#ifdef __cplusplus
}
#endif
 
#endif
 
 
 
/* Unlocked version for single threaded environments, such as some
* windows kernel modules.
*/
#if defined(PIPE_ATOMIC_OS_UNLOCKED)
 
#define PIPE_ATOMIC "Unlocked"
 
#define p_atomic_set(_v, _i) (*(_v) = (_i))
#define p_atomic_read(_v) (*(_v))
#define p_atomic_dec_zero(_v) ((boolean) --(*(_v)))
#define p_atomic_inc(_v) ((void) (*(_v))++)
#define p_atomic_dec(_v) ((void) (*(_v))--)
#define p_atomic_cmpxchg(_v, old, _new) (*(_v) == old ? *(_v) = (_new) : *(_v))
 
#endif
 
 
/* Locally coded assembly for MSVC on x86:
*/
#if defined(PIPE_ATOMIC_ASM_MSVC_X86)
 
#define PIPE_ATOMIC "MSVC x86 assembly"
 
#ifdef __cplusplus
extern "C" {
#endif
 
#define p_atomic_set(_v, _i) (*(_v) = (_i))
#define p_atomic_read(_v) (*(_v))
 
static INLINE boolean
p_atomic_dec_zero(int32_t *v)
{
unsigned char c;
 
__asm {
mov eax, [v]
lock dec dword ptr [eax]
sete byte ptr [c]
}
 
return c != 0;
}
 
static INLINE void
p_atomic_inc(int32_t *v)
{
__asm {
mov eax, [v]
lock inc dword ptr [eax]
}
}
 
static INLINE void
p_atomic_dec(int32_t *v)
{
__asm {
mov eax, [v]
lock dec dword ptr [eax]
}
}
 
static INLINE int32_t
p_atomic_cmpxchg(int32_t *v, int32_t old, int32_t _new)
{
int32_t orig;
 
__asm {
mov ecx, [v]
mov eax, [old]
mov edx, [_new]
lock cmpxchg [ecx], edx
mov [orig], eax
}
 
return orig;
}
 
#ifdef __cplusplus
}
#endif
 
#endif
 
 
#if defined(PIPE_ATOMIC_MSVC_INTRINSIC)
 
#define PIPE_ATOMIC "MSVC Intrinsics"
 
#include <intrin.h>
 
#pragma intrinsic(_InterlockedIncrement)
#pragma intrinsic(_InterlockedDecrement)
#pragma intrinsic(_InterlockedCompareExchange)
 
#ifdef __cplusplus
extern "C" {
#endif
 
#define p_atomic_set(_v, _i) (*(_v) = (_i))
#define p_atomic_read(_v) (*(_v))
 
static INLINE boolean
p_atomic_dec_zero(int32_t *v)
{
return _InterlockedDecrement((long *)v) == 0;
}
 
static INLINE void
p_atomic_inc(int32_t *v)
{
_InterlockedIncrement((long *)v);
}
 
static INLINE void
p_atomic_dec(int32_t *v)
{
_InterlockedDecrement((long *)v);
}
 
static INLINE int32_t
p_atomic_cmpxchg(int32_t *v, int32_t old, int32_t _new)
{
return _InterlockedCompareExchange((long *)v, _new, old);
}
 
#ifdef __cplusplus
}
#endif
 
#endif
 
#if defined(PIPE_ATOMIC_OS_SOLARIS)
 
#define PIPE_ATOMIC "Solaris OS atomic functions"
 
#include <atomic.h>
 
#ifdef __cplusplus
extern "C" {
#endif
 
#define p_atomic_set(_v, _i) (*(_v) = (_i))
#define p_atomic_read(_v) (*(_v))
 
static INLINE boolean
p_atomic_dec_zero(int32_t *v)
{
uint32_t n = atomic_dec_32_nv((uint32_t *) v);
 
return n != 0;
}
 
#define p_atomic_inc(_v) atomic_inc_32((uint32_t *) _v)
#define p_atomic_dec(_v) atomic_dec_32((uint32_t *) _v)
 
#define p_atomic_cmpxchg(_v, _old, _new) \
atomic_cas_32( (uint32_t *) _v, (uint32_t) _old, (uint32_t) _new)
 
#ifdef __cplusplus
}
#endif
 
#endif
 
 
#ifndef PIPE_ATOMIC
#error "No pipe_atomic implementation selected"
#endif
 
 
 
#endif /* U_ATOMIC_H */
/drivers/video/Gallium/auxiliary/util/u_bitmask.c
0,0 → 1,328
/**************************************************************************
*
* Copyright 2009 VMware, Inc.
* 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 VMWARE 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
* Generic bitmask implementation.
*
* @author Jose Fonseca <jfonseca@vmware.com>
*/
 
 
#include "pipe/p_compiler.h"
#include "util/u_debug.h"
 
#include "util/u_memory.h"
#include "util/u_bitmask.h"
 
 
typedef uint32_t util_bitmask_word;
 
 
#define UTIL_BITMASK_INITIAL_WORDS 16
#define UTIL_BITMASK_BITS_PER_BYTE 8
#define UTIL_BITMASK_BITS_PER_WORD (sizeof(util_bitmask_word) * UTIL_BITMASK_BITS_PER_BYTE)
 
 
struct util_bitmask
{
util_bitmask_word *words;
/** Number of bits we can currently hold */
unsigned size;
/** Number of consecutive bits set at the start of the bitmask */
unsigned filled;
};
 
 
struct util_bitmask *
util_bitmask_create(void)
{
struct util_bitmask *bm;
bm = MALLOC_STRUCT(util_bitmask);
if(!bm)
return NULL;
bm->words = (util_bitmask_word *)CALLOC(UTIL_BITMASK_INITIAL_WORDS, sizeof(util_bitmask_word));
if(!bm->words) {
FREE(bm);
return NULL;
}
bm->size = UTIL_BITMASK_INITIAL_WORDS * UTIL_BITMASK_BITS_PER_WORD;
bm->filled = 0;
return bm;
}
 
 
/**
* Resize the bitmask if necessary
*/
static INLINE boolean
util_bitmask_resize(struct util_bitmask *bm,
unsigned minimum_index)
{
unsigned minimum_size = minimum_index + 1;
unsigned new_size;
util_bitmask_word *new_words;
 
/* Check integer overflow */
if(!minimum_size)
return FALSE;
if(bm->size >= minimum_size)
return TRUE;
 
assert(bm->size % UTIL_BITMASK_BITS_PER_WORD == 0);
new_size = bm->size;
while(new_size < minimum_size) {
new_size *= 2;
/* Check integer overflow */
if(new_size < bm->size)
return FALSE;
}
assert(new_size);
assert(new_size % UTIL_BITMASK_BITS_PER_WORD == 0);
new_words = (util_bitmask_word *)REALLOC((void *)bm->words,
bm->size / UTIL_BITMASK_BITS_PER_BYTE,
new_size / UTIL_BITMASK_BITS_PER_BYTE);
if(!new_words)
return FALSE;
memset(new_words + bm->size/UTIL_BITMASK_BITS_PER_WORD,
0,
(new_size - bm->size)/UTIL_BITMASK_BITS_PER_BYTE);
bm->size = new_size;
bm->words = new_words;
return TRUE;
}
 
 
/**
* Lazily update the filled.
*/
static INLINE void
util_bitmask_filled_set(struct util_bitmask *bm,
unsigned index)
{
assert(bm->filled <= bm->size);
assert(index < bm->size);
if(index == bm->filled) {
++bm->filled;
assert(bm->filled <= bm->size);
}
}
 
static INLINE void
util_bitmask_filled_unset(struct util_bitmask *bm,
unsigned index)
{
assert(bm->filled <= bm->size);
assert(index < bm->size);
if(index < bm->filled)
bm->filled = index;
}
 
 
unsigned
util_bitmask_add(struct util_bitmask *bm)
{
unsigned word;
unsigned bit;
util_bitmask_word mask;
assert(bm);
 
/* linear search for an empty index */
word = bm->filled / UTIL_BITMASK_BITS_PER_WORD;
bit = bm->filled % UTIL_BITMASK_BITS_PER_WORD;
mask = 1 << bit;
while(word < bm->size / UTIL_BITMASK_BITS_PER_WORD) {
while(bit < UTIL_BITMASK_BITS_PER_WORD) {
if(!(bm->words[word] & mask))
goto found;
++bm->filled;
++bit;
mask <<= 1;
}
++word;
bit = 0;
mask = 1;
}
found:
 
/* grow the bitmask if necessary */
if(!util_bitmask_resize(bm, bm->filled))
return UTIL_BITMASK_INVALID_INDEX;
 
assert(!(bm->words[word] & mask));
bm->words[word] |= mask;
 
return bm->filled++;
}
 
 
unsigned
util_bitmask_set(struct util_bitmask *bm,
unsigned index)
{
unsigned word;
unsigned bit;
util_bitmask_word mask;
assert(bm);
/* grow the bitmask if necessary */
if(!util_bitmask_resize(bm, index))
return UTIL_BITMASK_INVALID_INDEX;
 
word = index / UTIL_BITMASK_BITS_PER_WORD;
bit = index % UTIL_BITMASK_BITS_PER_WORD;
mask = 1 << bit;
 
bm->words[word] |= mask;
 
util_bitmask_filled_set(bm, index);
return index;
}
 
 
void
util_bitmask_clear(struct util_bitmask *bm,
unsigned index)
{
unsigned word;
unsigned bit;
util_bitmask_word mask;
assert(bm);
if(index >= bm->size)
return;
 
word = index / UTIL_BITMASK_BITS_PER_WORD;
bit = index % UTIL_BITMASK_BITS_PER_WORD;
mask = 1 << bit;
 
bm->words[word] &= ~mask;
util_bitmask_filled_unset(bm, index);
}
 
 
boolean
util_bitmask_get(struct util_bitmask *bm,
unsigned index)
{
unsigned word = index / UTIL_BITMASK_BITS_PER_WORD;
unsigned bit = index % UTIL_BITMASK_BITS_PER_WORD;
util_bitmask_word mask = 1 << bit;
assert(bm);
if(index < bm->filled) {
assert(bm->words[word] & mask);
return TRUE;
}
 
if(index >= bm->size)
return FALSE;
 
if(bm->words[word] & mask) {
util_bitmask_filled_set(bm, index);
return TRUE;
}
else
return FALSE;
}
 
 
unsigned
util_bitmask_get_next_index(struct util_bitmask *bm,
unsigned index)
{
unsigned word = index / UTIL_BITMASK_BITS_PER_WORD;
unsigned bit = index % UTIL_BITMASK_BITS_PER_WORD;
util_bitmask_word mask = 1 << bit;
 
if(index < bm->filled) {
assert(bm->words[word] & mask);
return index;
}
 
if(index >= bm->size) {
return UTIL_BITMASK_INVALID_INDEX;
}
 
/* Do a linear search */
while(word < bm->size / UTIL_BITMASK_BITS_PER_WORD) {
while(bit < UTIL_BITMASK_BITS_PER_WORD) {
if(bm->words[word] & mask) {
if(index == bm->filled) {
++bm->filled;
assert(bm->filled <= bm->size);
}
return index;
}
++index;
++bit;
mask <<= 1;
}
++word;
bit = 0;
mask = 1;
}
return UTIL_BITMASK_INVALID_INDEX;
}
 
 
unsigned
util_bitmask_get_first_index(struct util_bitmask *bm)
{
return util_bitmask_get_next_index(bm, 0);
}
 
 
void
util_bitmask_destroy(struct util_bitmask *bm)
{
assert(bm);
 
FREE(bm->words);
FREE(bm);
}
 
/drivers/video/Gallium/auxiliary/util/u_bitmask.h
0,0 → 1,117
/**************************************************************************
*
* Copyright 2009 VMware, Inc.
* 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 VMWARE 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
* Generic bitmask.
*
* @author Jose Fonseca <jfonseca@vmware.com>
*/
 
#ifndef U_HANDLE_BITMASK_H_
#define U_HANDLE_BITMASK_H_
 
 
#include "pipe/p_compiler.h"
 
 
#ifdef __cplusplus
extern "C" {
#endif
 
 
#define UTIL_BITMASK_INVALID_INDEX (~0U)
/**
* Abstract data type to represent arbitrary set of bits.
*/
struct util_bitmask;
 
 
struct util_bitmask *
util_bitmask_create(void);
 
 
/**
* Search a cleared bit and set it.
*
* It searches for the first cleared bit.
*
* Returns the bit index on success, or UTIL_BITMASK_INVALID_INDEX on out of
* memory growing the bitmask.
*/
unsigned
util_bitmask_add(struct util_bitmask *bm);
 
/**
* Set a bit.
*
* Returns the input index on success, or UTIL_BITMASK_INVALID_INDEX on out of
* memory growing the bitmask.
*/
unsigned
util_bitmask_set(struct util_bitmask *bm,
unsigned index);
 
void
util_bitmask_clear(struct util_bitmask *bm,
unsigned index);
 
boolean
util_bitmask_get(struct util_bitmask *bm,
unsigned index);
 
 
void
util_bitmask_destroy(struct util_bitmask *bm);
 
 
/**
* Search for the first set bit.
*
* Returns UTIL_BITMASK_INVALID_INDEX if a set bit cannot be found.
*/
unsigned
util_bitmask_get_first_index(struct util_bitmask *bm);
 
 
/**
* Search for the first set bit, starting from the giving index.
*
* Returns UTIL_BITMASK_INVALID_INDEX if a set bit cannot be found.
*/
unsigned
util_bitmask_get_next_index(struct util_bitmask *bm,
unsigned index);
 
 
#ifdef __cplusplus
}
#endif
 
#endif /* U_HANDLE_BITMASK_H_ */
/drivers/video/Gallium/auxiliary/util/u_blit.c
0,0 → 1,954
/**************************************************************************
*
* 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
* Copy/blit pixel rect between surfaces
*
* @author Brian Paul
*/
 
 
#include "pipe/p_context.h"
#include "util/u_debug.h"
#include "pipe/p_defines.h"
#include "util/u_inlines.h"
#include "pipe/p_shader_tokens.h"
#include "pipe/p_state.h"
 
#include "util/u_blit.h"
#include "util/u_draw_quad.h"
#include "util/u_format.h"
#include "util/u_math.h"
#include "util/u_memory.h"
#include "util/u_sampler.h"
#include "util/u_simple_shaders.h"
 
#include "cso_cache/cso_context.h"
 
 
struct blit_state
{
struct pipe_context *pipe;
struct cso_context *cso;
 
struct pipe_blend_state blend_write_color, blend_keep_color;
struct pipe_depth_stencil_alpha_state dsa_keep_depthstencil;
struct pipe_depth_stencil_alpha_state dsa_write_depthstencil;
struct pipe_depth_stencil_alpha_state dsa_write_depth;
struct pipe_depth_stencil_alpha_state dsa_write_stencil;
struct pipe_rasterizer_state rasterizer;
struct pipe_sampler_state sampler;
struct pipe_viewport_state viewport;
struct pipe_vertex_element velem[2];
enum pipe_texture_target internal_target;
 
void *vs;
void *fs[PIPE_MAX_TEXTURE_TYPES][TGSI_WRITEMASK_XYZW + 1];
void *fs_depthstencil[PIPE_MAX_TEXTURE_TYPES];
void *fs_depth[PIPE_MAX_TEXTURE_TYPES];
void *fs_stencil[PIPE_MAX_TEXTURE_TYPES];
 
struct pipe_resource *vbuf; /**< quad vertices */
unsigned vbuf_slot;
 
float vertices[4][2][4]; /**< vertex/texcoords for quad */
 
boolean has_stencil_export;
};
 
 
/**
* Create state object for blit.
* Intended to be created once and re-used for many blit() calls.
*/
struct blit_state *
util_create_blit(struct pipe_context *pipe, struct cso_context *cso)
{
struct blit_state *ctx;
uint i;
 
ctx = CALLOC_STRUCT(blit_state);
if (!ctx)
return NULL;
 
ctx->pipe = pipe;
ctx->cso = cso;
 
/* disabled blending/masking */
ctx->blend_write_color.rt[0].colormask = PIPE_MASK_RGBA;
 
/* depth stencil states */
ctx->dsa_write_depth.depth.enabled = 1;
ctx->dsa_write_depth.depth.writemask = 1;
ctx->dsa_write_depth.depth.func = PIPE_FUNC_ALWAYS;
ctx->dsa_write_stencil.stencil[0].enabled = 1;
ctx->dsa_write_stencil.stencil[0].func = PIPE_FUNC_ALWAYS;
ctx->dsa_write_stencil.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
ctx->dsa_write_stencil.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
ctx->dsa_write_stencil.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
ctx->dsa_write_stencil.stencil[0].valuemask = 0xff;
ctx->dsa_write_stencil.stencil[0].writemask = 0xff;
ctx->dsa_write_depthstencil.depth = ctx->dsa_write_depth.depth;
ctx->dsa_write_depthstencil.stencil[0] = ctx->dsa_write_stencil.stencil[0];
 
/* rasterizer */
ctx->rasterizer.cull_face = PIPE_FACE_NONE;
ctx->rasterizer.half_pixel_center = 1;
ctx->rasterizer.bottom_edge_rule = 1;
ctx->rasterizer.depth_clip = 1;
 
/* samplers */
ctx->sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
ctx->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
ctx->sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
ctx->sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
ctx->sampler.min_img_filter = 0; /* set later */
ctx->sampler.mag_img_filter = 0; /* set later */
 
/* vertex elements state */
for (i = 0; i < 2; i++) {
ctx->velem[i].src_offset = i * 4 * sizeof(float);
ctx->velem[i].instance_divisor = 0;
ctx->velem[i].vertex_buffer_index = cso_get_aux_vertex_buffer_slot(cso);
ctx->velem[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
}
 
ctx->vbuf = NULL;
 
/* init vertex data that doesn't change */
for (i = 0; i < 4; i++) {
ctx->vertices[i][0][3] = 1.0f; /* w */
ctx->vertices[i][1][2] = 0.0f; /* r */
ctx->vertices[i][1][3] = 1.0f; /* q */
}
 
if(pipe->screen->get_param(pipe->screen, PIPE_CAP_NPOT_TEXTURES))
ctx->internal_target = PIPE_TEXTURE_2D;
else
ctx->internal_target = PIPE_TEXTURE_RECT;
 
ctx->has_stencil_export =
pipe->screen->get_param(pipe->screen, PIPE_CAP_SHADER_STENCIL_EXPORT);
 
return ctx;
}
 
 
/**
* Destroy a blit context
*/
void
util_destroy_blit(struct blit_state *ctx)
{
struct pipe_context *pipe = ctx->pipe;
unsigned i, j;
 
if (ctx->vs)
pipe->delete_vs_state(pipe, ctx->vs);
 
for (i = 0; i < Elements(ctx->fs); i++) {
for (j = 0; j < Elements(ctx->fs[i]); j++) {
if (ctx->fs[i][j])
pipe->delete_fs_state(pipe, ctx->fs[i][j]);
}
}
 
for (i = 0; i < PIPE_MAX_TEXTURE_TYPES; i++) {
if (ctx->fs_depthstencil[i]) {
pipe->delete_fs_state(pipe, ctx->fs_depthstencil[i]);
}
if (ctx->fs_depth[i]) {
pipe->delete_fs_state(pipe, ctx->fs_depth[i]);
}
if (ctx->fs_stencil[i]) {
pipe->delete_fs_state(pipe, ctx->fs_stencil[i]);
}
}
 
pipe_resource_reference(&ctx->vbuf, NULL);
 
FREE(ctx);
}
 
 
/**
* Helper function to set the fragment shaders.
*/
static INLINE void
set_fragment_shader(struct blit_state *ctx, uint writemask,
enum pipe_texture_target pipe_tex)
{
if (!ctx->fs[pipe_tex][writemask]) {
unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(pipe_tex, 0);
 
ctx->fs[pipe_tex][writemask] =
util_make_fragment_tex_shader_writemask(ctx->pipe, tgsi_tex,
TGSI_INTERPOLATE_LINEAR,
writemask);
}
 
cso_set_fragment_shader_handle(ctx->cso, ctx->fs[pipe_tex][writemask]);
}
 
 
/**
* Helper function to set the shader which writes depth and stencil.
*/
static INLINE void
set_depthstencil_fragment_shader(struct blit_state *ctx,
enum pipe_texture_target pipe_tex)
{
if (!ctx->fs_depthstencil[pipe_tex]) {
unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(pipe_tex, 0);
 
ctx->fs_depthstencil[pipe_tex] =
util_make_fragment_tex_shader_writedepthstencil(ctx->pipe, tgsi_tex,
TGSI_INTERPOLATE_LINEAR);
}
 
cso_set_fragment_shader_handle(ctx->cso, ctx->fs_depthstencil[pipe_tex]);
}
 
 
/**
* Helper function to set the shader which writes depth.
*/
static INLINE void
set_depth_fragment_shader(struct blit_state *ctx,
enum pipe_texture_target pipe_tex)
{
if (!ctx->fs_depth[pipe_tex]) {
unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(pipe_tex, 0);
 
ctx->fs_depth[pipe_tex] =
util_make_fragment_tex_shader_writedepth(ctx->pipe, tgsi_tex,
TGSI_INTERPOLATE_LINEAR);
}
 
cso_set_fragment_shader_handle(ctx->cso, ctx->fs_depth[pipe_tex]);
}
 
 
/**
* Helper function to set the shader which writes stencil.
*/
static INLINE void
set_stencil_fragment_shader(struct blit_state *ctx,
enum pipe_texture_target pipe_tex)
{
if (!ctx->fs_stencil[pipe_tex]) {
unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(pipe_tex, 0);
 
ctx->fs_stencil[pipe_tex] =
util_make_fragment_tex_shader_writestencil(ctx->pipe, tgsi_tex,
TGSI_INTERPOLATE_LINEAR);
}
 
cso_set_fragment_shader_handle(ctx->cso, ctx->fs_stencil[pipe_tex]);
}
 
 
/**
* Helper function to set the vertex shader.
*/
static INLINE void
set_vertex_shader(struct blit_state *ctx)
{
/* vertex shader - still required to provide the linkage between
* fragment shader input semantics and vertex_element/buffers.
*/
if (!ctx->vs) {
const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
TGSI_SEMANTIC_GENERIC };
const uint semantic_indexes[] = { 0, 0 };
ctx->vs = util_make_vertex_passthrough_shader(ctx->pipe, 2,
semantic_names,
semantic_indexes);
}
 
cso_set_vertex_shader_handle(ctx->cso, ctx->vs);
}
 
 
/**
* Get offset of next free slot in vertex buffer for quad vertices.
*/
static unsigned
get_next_slot( struct blit_state *ctx )
{
const unsigned max_slots = 4096 / sizeof ctx->vertices;
 
if (ctx->vbuf_slot >= max_slots) {
pipe_resource_reference(&ctx->vbuf, NULL);
ctx->vbuf_slot = 0;
}
 
if (!ctx->vbuf) {
ctx->vbuf = pipe_buffer_create(ctx->pipe->screen,
PIPE_BIND_VERTEX_BUFFER,
PIPE_USAGE_STREAM,
max_slots * sizeof ctx->vertices);
}
return ctx->vbuf_slot++ * sizeof ctx->vertices;
}
 
 
 
 
/**
* Setup vertex data for the textured quad we'll draw.
* Note: y=0=top
*/
static unsigned
setup_vertex_data_tex(struct blit_state *ctx,
float x0, float y0, float x1, float y1,
float s0, float t0, float s1, float t1,
float z)
{
unsigned offset;
 
ctx->vertices[0][0][0] = x0;
ctx->vertices[0][0][1] = y0;
ctx->vertices[0][0][2] = z;
ctx->vertices[0][1][0] = s0; /*s*/
ctx->vertices[0][1][1] = t0; /*t*/
 
ctx->vertices[1][0][0] = x1;
ctx->vertices[1][0][1] = y0;
ctx->vertices[1][0][2] = z;
ctx->vertices[1][1][0] = s1; /*s*/
ctx->vertices[1][1][1] = t0; /*t*/
 
ctx->vertices[2][0][0] = x1;
ctx->vertices[2][0][1] = y1;
ctx->vertices[2][0][2] = z;
ctx->vertices[2][1][0] = s1;
ctx->vertices[2][1][1] = t1;
 
ctx->vertices[3][0][0] = x0;
ctx->vertices[3][0][1] = y1;
ctx->vertices[3][0][2] = z;
ctx->vertices[3][1][0] = s0;
ctx->vertices[3][1][1] = t1;
 
offset = get_next_slot( ctx );
 
if (ctx->vbuf) {
pipe_buffer_write_nooverlap(ctx->pipe, ctx->vbuf,
offset, sizeof(ctx->vertices), ctx->vertices);
}
 
return offset;
}
 
 
/**
* \return TRUE if two regions overlap, FALSE otherwise
*/
static boolean
regions_overlap(int srcX0, int srcY0,
int srcX1, int srcY1,
int dstX0, int dstY0,
int dstX1, int dstY1)
{
if (MAX2(srcX0, srcX1) < MIN2(dstX0, dstX1))
return FALSE; /* src completely left of dst */
 
if (MAX2(dstX0, dstX1) < MIN2(srcX0, srcX1))
return FALSE; /* dst completely left of src */
 
if (MAX2(srcY0, srcY1) < MIN2(dstY0, dstY1))
return FALSE; /* src completely above dst */
 
if (MAX2(dstY0, dstY1) < MIN2(srcY0, srcY1))
return FALSE; /* dst completely above src */
 
return TRUE; /* some overlap */
}
 
 
/**
* Can we blit from src format to dest format with a simple copy?
*/
static boolean
formats_compatible(enum pipe_format src_format,
enum pipe_format dst_format)
{
if (src_format == dst_format) {
return TRUE;
}
else {
const struct util_format_description *src_desc =
util_format_description(src_format);
const struct util_format_description *dst_desc =
util_format_description(dst_format);
return util_is_format_compatible(src_desc, dst_desc);
}
}
 
 
/**
* Copy pixel block from src surface to dst surface.
* Overlapping regions are acceptable.
* Flipping and stretching are supported.
* \param filter one of PIPE_TEX_MIPFILTER_NEAREST/LINEAR
* \param writemask controls which channels in the dest surface are sourced
* from the src surface. Disabled channels are sourced
* from (0,0,0,1).
*/
void
util_blit_pixels(struct blit_state *ctx,
struct pipe_resource *src_tex,
unsigned src_level,
int srcX0, int srcY0,
int srcX1, int srcY1,
int srcZ0,
struct pipe_surface *dst,
int dstX0, int dstY0,
int dstX1, int dstY1,
float z, uint filter,
uint writemask, uint zs_writemask)
{
struct pipe_context *pipe = ctx->pipe;
struct pipe_screen *screen = pipe->screen;
enum pipe_format src_format, dst_format;
struct pipe_sampler_view *sampler_view = NULL;
struct pipe_sampler_view sv_templ;
struct pipe_surface *dst_surface;
struct pipe_framebuffer_state fb;
const int srcW = abs(srcX1 - srcX0);
const int srcH = abs(srcY1 - srcY0);
unsigned offset;
boolean overlap;
float s0, t0, s1, t1;
boolean normalized;
boolean is_stencil, is_depth, blit_depth, blit_stencil;
const struct util_format_description *src_desc =
util_format_description(src_tex->format);
 
assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
filter == PIPE_TEX_MIPFILTER_LINEAR);
 
assert(src_level <= src_tex->last_level);
 
/* do the regions overlap? */
overlap = src_tex == dst->texture &&
dst->u.tex.level == src_level &&
dst->u.tex.first_layer == srcZ0 &&
regions_overlap(srcX0, srcY0, srcX1, srcY1,
dstX0, dstY0, dstX1, dstY1);
 
src_format = util_format_linear(src_tex->format);
dst_format = util_format_linear(dst->texture->format);
 
/* See whether we will blit depth or stencil. */
is_depth = util_format_has_depth(src_desc);
is_stencil = util_format_has_stencil(src_desc);
 
blit_depth = is_depth && (zs_writemask & BLIT_WRITEMASK_Z);
blit_stencil = is_stencil && (zs_writemask & BLIT_WRITEMASK_STENCIL);
 
assert((writemask && !zs_writemask && !is_depth && !is_stencil) ||
(!writemask && (blit_depth || blit_stencil)));
 
/*
* Check for simple case: no format conversion, no flipping, no stretching,
* no overlapping, same number of samples.
* Filter mode should not matter since there's no stretching.
*/
if (formats_compatible(src_format, dst_format) &&
src_tex->nr_samples == dst->texture->nr_samples &&
is_stencil == blit_stencil &&
is_depth == blit_depth &&
srcX0 < srcX1 &&
dstX0 < dstX1 &&
srcY0 < srcY1 &&
dstY0 < dstY1 &&
(dstX1 - dstX0) == (srcX1 - srcX0) &&
(dstY1 - dstY0) == (srcY1 - srcY0) &&
!overlap) {
struct pipe_box src_box;
src_box.x = srcX0;
src_box.y = srcY0;
src_box.z = srcZ0;
src_box.width = srcW;
src_box.height = srcH;
src_box.depth = 1;
pipe->resource_copy_region(pipe,
dst->texture, dst->u.tex.level,
dstX0, dstY0, dst->u.tex.first_layer,/* dest */
src_tex, src_level,
&src_box);
return;
}
 
/* XXX Reading multisample textures is unimplemented. */
assert(src_tex->nr_samples <= 1);
if (src_tex->nr_samples > 1) {
return;
}
 
/* It's a mistake to call this function with a stencil format and
* without shader stencil export. We don't do software fallbacks here.
* Ignore stencil and only copy depth.
*/
if (blit_stencil && !ctx->has_stencil_export) {
blit_stencil = FALSE;
 
if (!blit_depth)
return;
}
 
if (dst_format == dst->format) {
dst_surface = dst;
} else {
struct pipe_surface templ = *dst;
templ.format = dst_format;
dst_surface = pipe->create_surface(pipe, dst->texture, &templ);
}
 
/* Create a temporary texture when src and dest alias.
*/
if (src_tex == dst_surface->texture &&
dst_surface->u.tex.level == src_level &&
dst_surface->u.tex.first_layer == srcZ0) {
/* Make a temporary texture which contains a copy of the source pixels.
* Then we'll sample from the temporary texture.
*/
struct pipe_resource texTemp;
struct pipe_resource *tex;
struct pipe_sampler_view sv_templ;
struct pipe_box src_box;
const int srcLeft = MIN2(srcX0, srcX1);
const int srcTop = MIN2(srcY0, srcY1);
 
if (srcLeft != srcX0) {
/* left-right flip */
int tmp = dstX0;
dstX0 = dstX1;
dstX1 = tmp;
}
 
if (srcTop != srcY0) {
/* up-down flip */
int tmp = dstY0;
dstY0 = dstY1;
dstY1 = tmp;
}
 
/* create temp texture */
memset(&texTemp, 0, sizeof(texTemp));
texTemp.target = ctx->internal_target;
texTemp.format = src_format;
texTemp.last_level = 0;
texTemp.width0 = srcW;
texTemp.height0 = srcH;
texTemp.depth0 = 1;
texTemp.array_size = 1;
texTemp.bind = PIPE_BIND_SAMPLER_VIEW;
 
tex = screen->resource_create(screen, &texTemp);
if (!tex)
return;
 
src_box.x = srcLeft;
src_box.y = srcTop;
src_box.z = srcZ0;
src_box.width = srcW;
src_box.height = srcH;
src_box.depth = 1;
/* load temp texture */
pipe->resource_copy_region(pipe,
tex, 0, 0, 0, 0, /* dest */
src_tex, src_level, &src_box);
 
normalized = tex->target != PIPE_TEXTURE_RECT;
if(normalized) {
s0 = 0.0f;
s1 = 1.0f;
t0 = 0.0f;
t1 = 1.0f;
}
else {
s0 = 0;
s1 = srcW;
t0 = 0;
t1 = srcH;
}
 
u_sampler_view_default_template(&sv_templ, tex, tex->format);
if (!blit_depth && blit_stencil) {
/* set a stencil-only format, e.g. Z24S8 --> X24S8 */
sv_templ.format = util_format_stencil_only(tex->format);
assert(sv_templ.format != PIPE_FORMAT_NONE);
}
sampler_view = pipe->create_sampler_view(pipe, tex, &sv_templ);
 
if (!sampler_view) {
pipe_resource_reference(&tex, NULL);
return;
}
pipe_resource_reference(&tex, NULL);
}
else {
/* Directly sample from the source resource/texture */
u_sampler_view_default_template(&sv_templ, src_tex, src_format);
if (!blit_depth && blit_stencil) {
/* set a stencil-only format, e.g. Z24S8 --> X24S8 */
sv_templ.format = util_format_stencil_only(src_format);
assert(sv_templ.format != PIPE_FORMAT_NONE);
}
sampler_view = pipe->create_sampler_view(pipe, src_tex, &sv_templ);
 
if (!sampler_view) {
return;
}
 
s0 = srcX0;
s1 = srcX1;
t0 = srcY0;
t1 = srcY1;
normalized = sampler_view->texture->target != PIPE_TEXTURE_RECT;
if(normalized)
{
s0 /= (float)(u_minify(sampler_view->texture->width0, src_level));
s1 /= (float)(u_minify(sampler_view->texture->width0, src_level));
t0 /= (float)(u_minify(sampler_view->texture->height0, src_level));
t1 /= (float)(u_minify(sampler_view->texture->height0, src_level));
}
}
 
assert(screen->is_format_supported(screen, sampler_view->format,
ctx->internal_target, sampler_view->texture->nr_samples,
PIPE_BIND_SAMPLER_VIEW));
assert(screen->is_format_supported(screen, dst_format, ctx->internal_target,
dst_surface->texture->nr_samples,
is_depth || is_stencil ? PIPE_BIND_DEPTH_STENCIL :
PIPE_BIND_RENDER_TARGET));
 
/* save state (restored below) */
cso_save_blend(ctx->cso);
cso_save_depth_stencil_alpha(ctx->cso);
cso_save_rasterizer(ctx->cso);
cso_save_sample_mask(ctx->cso);
cso_save_samplers(ctx->cso, PIPE_SHADER_FRAGMENT);
cso_save_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT);
cso_save_stream_outputs(ctx->cso);
cso_save_viewport(ctx->cso);
cso_save_framebuffer(ctx->cso);
cso_save_fragment_shader(ctx->cso);
cso_save_vertex_shader(ctx->cso);
cso_save_geometry_shader(ctx->cso);
cso_save_vertex_elements(ctx->cso);
cso_save_aux_vertex_buffer_slot(ctx->cso);
cso_save_render_condition(ctx->cso);
 
/* set misc state we care about */
if (writemask)
cso_set_blend(ctx->cso, &ctx->blend_write_color);
else
cso_set_blend(ctx->cso, &ctx->blend_keep_color);
 
cso_set_sample_mask(ctx->cso, ~0);
cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
cso_set_vertex_elements(ctx->cso, 2, ctx->velem);
cso_set_stream_outputs(ctx->cso, 0, NULL, 0);
cso_set_render_condition(ctx->cso, NULL, FALSE, 0);
 
/* default sampler state */
ctx->sampler.normalized_coords = normalized;
ctx->sampler.min_img_filter = filter;
ctx->sampler.mag_img_filter = filter;
ctx->sampler.min_lod = src_level;
ctx->sampler.max_lod = src_level;
 
/* Depth stencil state, fragment shader and sampler setup depending on what
* we blit.
*/
if (blit_depth && blit_stencil) {
cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler);
/* don't filter stencil */
ctx->sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
ctx->sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 1, &ctx->sampler);
 
cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_write_depthstencil);
set_depthstencil_fragment_shader(ctx, sampler_view->texture->target);
}
else if (blit_depth) {
cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler);
cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_write_depth);
set_depth_fragment_shader(ctx, sampler_view->texture->target);
}
else if (blit_stencil) {
/* don't filter stencil */
ctx->sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
ctx->sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler);
 
cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_write_stencil);
set_stencil_fragment_shader(ctx, sampler_view->texture->target);
}
else { /* color */
cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler);
cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_keep_depthstencil);
set_fragment_shader(ctx, writemask, sampler_view->texture->target);
}
cso_single_sampler_done(ctx->cso, PIPE_SHADER_FRAGMENT);
 
/* textures */
if (blit_depth && blit_stencil) {
/* Setup two samplers, one for depth and the other one for stencil. */
struct pipe_sampler_view templ;
struct pipe_sampler_view *views[2];
 
templ = *sampler_view;
templ.format = util_format_stencil_only(templ.format);
assert(templ.format != PIPE_FORMAT_NONE);
 
views[0] = sampler_view;
views[1] = pipe->create_sampler_view(pipe, views[0]->texture, &templ);
cso_set_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT, 2, views);
 
pipe_sampler_view_reference(&views[1], NULL);
}
else {
cso_set_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT, 1, &sampler_view);
}
 
/* viewport */
ctx->viewport.scale[0] = 0.5f * dst_surface->width;
ctx->viewport.scale[1] = 0.5f * dst_surface->height;
ctx->viewport.scale[2] = 0.5f;
ctx->viewport.scale[3] = 1.0f;
ctx->viewport.translate[0] = 0.5f * dst_surface->width;
ctx->viewport.translate[1] = 0.5f * dst_surface->height;
ctx->viewport.translate[2] = 0.5f;
ctx->viewport.translate[3] = 0.0f;
cso_set_viewport(ctx->cso, &ctx->viewport);
 
set_vertex_shader(ctx);
cso_set_geometry_shader_handle(ctx->cso, NULL);
 
/* drawing dest */
memset(&fb, 0, sizeof(fb));
fb.width = dst_surface->width;
fb.height = dst_surface->height;
if (blit_depth || blit_stencil) {
fb.zsbuf = dst_surface;
} else {
fb.nr_cbufs = 1;
fb.cbufs[0] = dst_surface;
}
cso_set_framebuffer(ctx->cso, &fb);
 
/* draw quad */
offset = setup_vertex_data_tex(ctx,
(float) dstX0 / dst_surface->width * 2.0f - 1.0f,
(float) dstY0 / dst_surface->height * 2.0f - 1.0f,
(float) dstX1 / dst_surface->width * 2.0f - 1.0f,
(float) dstY1 / dst_surface->height * 2.0f - 1.0f,
s0, t0,
s1, t1,
z);
 
if (ctx->vbuf) {
util_draw_vertex_buffer(ctx->pipe, ctx->cso, ctx->vbuf,
cso_get_aux_vertex_buffer_slot(ctx->cso),
offset,
PIPE_PRIM_TRIANGLE_FAN,
4, /* verts */
2); /* attribs/vert */
}
 
/* restore state we changed */
cso_restore_blend(ctx->cso);
cso_restore_depth_stencil_alpha(ctx->cso);
cso_restore_rasterizer(ctx->cso);
cso_restore_sample_mask(ctx->cso);
cso_restore_samplers(ctx->cso, PIPE_SHADER_FRAGMENT);
cso_restore_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT);
cso_restore_viewport(ctx->cso);
cso_restore_framebuffer(ctx->cso);
cso_restore_fragment_shader(ctx->cso);
cso_restore_vertex_shader(ctx->cso);
cso_restore_geometry_shader(ctx->cso);
cso_restore_vertex_elements(ctx->cso);
cso_restore_aux_vertex_buffer_slot(ctx->cso);
cso_restore_stream_outputs(ctx->cso);
cso_restore_render_condition(ctx->cso);
 
pipe_sampler_view_reference(&sampler_view, NULL);
if (dst_surface != dst)
pipe_surface_reference(&dst_surface, NULL);
}
 
 
/**
* Copy pixel block from src texture to dst surface.
* The sampler view's first_level field indicates the source
* mipmap level to use.
* XXX need some control over blitting Z and/or stencil.
*/
void
util_blit_pixels_tex(struct blit_state *ctx,
struct pipe_sampler_view *src_sampler_view,
int srcX0, int srcY0,
int srcX1, int srcY1,
struct pipe_surface *dst,
int dstX0, int dstY0,
int dstX1, int dstY1,
float z, uint filter)
{
boolean normalized = src_sampler_view->texture->target != PIPE_TEXTURE_RECT;
struct pipe_framebuffer_state fb;
float s0, t0, s1, t1;
unsigned offset;
struct pipe_resource *tex = src_sampler_view->texture;
 
assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
filter == PIPE_TEX_MIPFILTER_LINEAR);
 
assert(tex);
assert(tex->width0 != 0);
assert(tex->height0 != 0);
 
s0 = srcX0;
s1 = srcX1;
t0 = srcY0;
t1 = srcY1;
 
if(normalized)
{
/* normalize according to the mipmap level's size */
int level = src_sampler_view->u.tex.first_level;
float w = (float) u_minify(tex->width0, level);
float h = (float) u_minify(tex->height0, level);
s0 /= w;
s1 /= w;
t0 /= h;
t1 /= h;
}
 
assert(ctx->pipe->screen->is_format_supported(ctx->pipe->screen, dst->format,
PIPE_TEXTURE_2D,
dst->texture->nr_samples,
PIPE_BIND_RENDER_TARGET));
 
/* save state (restored below) */
cso_save_blend(ctx->cso);
cso_save_depth_stencil_alpha(ctx->cso);
cso_save_rasterizer(ctx->cso);
cso_save_sample_mask(ctx->cso);
cso_save_samplers(ctx->cso, PIPE_SHADER_FRAGMENT);
cso_save_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT);
cso_save_stream_outputs(ctx->cso);
cso_save_viewport(ctx->cso);
cso_save_framebuffer(ctx->cso);
cso_save_fragment_shader(ctx->cso);
cso_save_vertex_shader(ctx->cso);
cso_save_geometry_shader(ctx->cso);
cso_save_vertex_elements(ctx->cso);
cso_save_aux_vertex_buffer_slot(ctx->cso);
 
/* set misc state we care about */
cso_set_blend(ctx->cso, &ctx->blend_write_color);
cso_set_depth_stencil_alpha(ctx->cso, &ctx->dsa_keep_depthstencil);
cso_set_sample_mask(ctx->cso, ~0);
cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
cso_set_vertex_elements(ctx->cso, 2, ctx->velem);
cso_set_stream_outputs(ctx->cso, 0, NULL, 0);
 
/* sampler */
ctx->sampler.normalized_coords = normalized;
ctx->sampler.min_img_filter = filter;
ctx->sampler.mag_img_filter = filter;
cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler);
cso_single_sampler_done(ctx->cso, PIPE_SHADER_FRAGMENT);
 
/* viewport */
ctx->viewport.scale[0] = 0.5f * dst->width;
ctx->viewport.scale[1] = 0.5f * dst->height;
ctx->viewport.scale[2] = 0.5f;
ctx->viewport.scale[3] = 1.0f;
ctx->viewport.translate[0] = 0.5f * dst->width;
ctx->viewport.translate[1] = 0.5f * dst->height;
ctx->viewport.translate[2] = 0.5f;
ctx->viewport.translate[3] = 0.0f;
cso_set_viewport(ctx->cso, &ctx->viewport);
 
/* texture */
cso_set_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT, 1, &src_sampler_view);
 
/* shaders */
set_fragment_shader(ctx, TGSI_WRITEMASK_XYZW,
src_sampler_view->texture->target);
set_vertex_shader(ctx);
cso_set_geometry_shader_handle(ctx->cso, NULL);
 
/* drawing dest */
memset(&fb, 0, sizeof(fb));
fb.width = dst->width;
fb.height = dst->height;
fb.nr_cbufs = 1;
fb.cbufs[0] = dst;
cso_set_framebuffer(ctx->cso, &fb);
 
/* draw quad */
offset = setup_vertex_data_tex(ctx,
(float) dstX0 / dst->width * 2.0f - 1.0f,
(float) dstY0 / dst->height * 2.0f - 1.0f,
(float) dstX1 / dst->width * 2.0f - 1.0f,
(float) dstY1 / dst->height * 2.0f - 1.0f,
s0, t0, s1, t1,
z);
 
util_draw_vertex_buffer(ctx->pipe, ctx->cso, ctx->vbuf,
cso_get_aux_vertex_buffer_slot(ctx->cso),
offset,
PIPE_PRIM_TRIANGLE_FAN,
4, /* verts */
2); /* attribs/vert */
 
/* restore state we changed */
cso_restore_blend(ctx->cso);
cso_restore_depth_stencil_alpha(ctx->cso);
cso_restore_rasterizer(ctx->cso);
cso_restore_sample_mask(ctx->cso);
cso_restore_samplers(ctx->cso, PIPE_SHADER_FRAGMENT);
cso_restore_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT);
cso_restore_viewport(ctx->cso);
cso_restore_framebuffer(ctx->cso);
cso_restore_fragment_shader(ctx->cso);
cso_restore_vertex_shader(ctx->cso);
cso_restore_geometry_shader(ctx->cso);
cso_restore_vertex_elements(ctx->cso);
cso_restore_aux_vertex_buffer_slot(ctx->cso);
cso_restore_stream_outputs(ctx->cso);
}
/drivers/video/Gallium/auxiliary/util/u_blit.h
0,0 → 1,85
/**************************************************************************
*
* 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.
*
**************************************************************************/
 
 
#ifndef U_BLIT_H
#define U_BLIT_H
 
 
#include "pipe/p_compiler.h"
/* for TGSI_WRITEMASK_* specification in util_blit_pixels */
#include "pipe/p_shader_tokens.h"
 
 
#ifdef __cplusplus
extern "C" {
#endif
 
struct cso_context;
struct pipe_context;
struct pipe_resource;
struct pipe_sampler_view;
struct pipe_surface;
 
#define BLIT_WRITEMASK_Z 1
#define BLIT_WRITEMASK_STENCIL 2
 
extern struct blit_state *
util_create_blit(struct pipe_context *pipe, struct cso_context *cso);
 
extern void
util_destroy_blit(struct blit_state *ctx);
 
extern void
util_blit_pixels(struct blit_state *ctx,
struct pipe_resource *src_tex,
unsigned src_level,
int srcX0, int srcY0,
int srcX1, int srcY1,
int srcZ0,
struct pipe_surface *dst,
int dstX0, int dstY0,
int dstX1, int dstY1,
float z, uint filter,
uint writemask, uint zs_writemask);
 
extern void
util_blit_pixels_tex(struct blit_state *ctx,
struct pipe_sampler_view *src_sampler_view,
int srcX0, int srcY0,
int srcX1, int srcY1,
struct pipe_surface *dst,
int dstX0, int dstY0,
int dstX1, int dstY1,
float z, uint filter);
 
#ifdef __cplusplus
}
#endif
 
#endif
/drivers/video/Gallium/auxiliary/util/u_blitter.c
0,0 → 1,1877
/**************************************************************************
*
* Copyright 2009 Marek Olšák <maraeo@gmail.com>
*
* 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
* Blitter utility to facilitate acceleration of the clear, clear_render_target,
* clear_depth_stencil, resource_copy_region, and blit functions.
*
* @author Marek Olšák
*/
 
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "util/u_inlines.h"
#include "pipe/p_shader_tokens.h"
#include "pipe/p_state.h"
 
#include "util/u_format.h"
#include "util/u_memory.h"
#include "util/u_math.h"
#include "util/u_blitter.h"
#include "util/u_draw_quad.h"
#include "util/u_sampler.h"
#include "util/u_simple_shaders.h"
#include "util/u_surface.h"
#include "util/u_texture.h"
#include "util/u_upload_mgr.h"
 
#define INVALID_PTR ((void*)~0)
 
struct blitter_context_priv
{
struct blitter_context base;
 
struct u_upload_mgr *upload;
 
float vertices[4][2][4]; /**< {pos, color} or {pos, texcoord} */
 
/* Templates for various state objects. */
 
/* Constant state objects. */
/* Vertex shaders. */
void *vs; /**< Vertex shader which passes {pos, generic} to the output.*/
void *vs_pos_only; /**< Vertex shader which passes pos to the output.*/
 
/* Fragment shaders. */
void *fs_empty;
void *fs_write_one_cbuf;
void *fs_write_all_cbufs;
 
/* FS which outputs a color from a texture,
where the index is PIPE_TEXTURE_* to be sampled. */
void *fs_texfetch_col[PIPE_MAX_TEXTURE_TYPES];
 
/* FS which outputs a depth from a texture,
where the index is PIPE_TEXTURE_* to be sampled. */
void *fs_texfetch_depth[PIPE_MAX_TEXTURE_TYPES];
void *fs_texfetch_depthstencil[PIPE_MAX_TEXTURE_TYPES];
void *fs_texfetch_stencil[PIPE_MAX_TEXTURE_TYPES];
 
/* FS which outputs one sample from a multisample texture. */
void *fs_texfetch_col_msaa[PIPE_MAX_TEXTURE_TYPES];
void *fs_texfetch_depth_msaa[PIPE_MAX_TEXTURE_TYPES];
void *fs_texfetch_depthstencil_msaa[PIPE_MAX_TEXTURE_TYPES];
void *fs_texfetch_stencil_msaa[PIPE_MAX_TEXTURE_TYPES];
 
/* Blend state. */
void *blend[PIPE_MASK_RGBA+1]; /**< blend state with writemask */
 
/* Depth stencil alpha state. */
void *dsa_write_depth_stencil;
void *dsa_write_depth_keep_stencil;
void *dsa_keep_depth_stencil;
void *dsa_keep_depth_write_stencil;
 
/* Vertex elements states. */
void *velem_state;
void *velem_state_readbuf[4]; /**< X, XY, XYZ, XYZW */
 
/* Sampler state. */
void *sampler_state;
void *sampler_state_linear;
void *sampler_state_rect;
void *sampler_state_rect_linear;
 
/* Rasterizer state. */
void *rs_state, *rs_state_scissor, *rs_discard_state;
 
/* Viewport state. */
struct pipe_viewport_state viewport;
 
/* Destination surface dimensions. */
unsigned dst_width;
unsigned dst_height;
 
boolean has_geometry_shader;
boolean has_stream_out;
boolean has_stencil_export;
boolean has_texture_multisample;
 
/* The Draw module overrides these functions.
* Always create the blitter before Draw. */
void (*bind_fs_state)(struct pipe_context *, void *);
void (*delete_fs_state)(struct pipe_context *, void *);
};
 
static struct pipe_surface *
util_blitter_get_next_surface_layer(struct pipe_context *pipe,
struct pipe_surface *surf);
 
struct blitter_context *util_blitter_create(struct pipe_context *pipe)
{
struct blitter_context_priv *ctx;
struct pipe_blend_state blend;
struct pipe_depth_stencil_alpha_state dsa;
struct pipe_rasterizer_state rs_state;
struct pipe_sampler_state sampler_state;
struct pipe_vertex_element velem[2];
unsigned i;
 
ctx = CALLOC_STRUCT(blitter_context_priv);
if (!ctx)
return NULL;
 
ctx->base.pipe = pipe;
ctx->base.draw_rectangle = util_blitter_draw_rectangle;
ctx->base.get_next_surface_layer = util_blitter_get_next_surface_layer;
 
ctx->bind_fs_state = pipe->bind_fs_state;
ctx->delete_fs_state = pipe->delete_fs_state;
 
/* init state objects for them to be considered invalid */
ctx->base.saved_blend_state = INVALID_PTR;
ctx->base.saved_dsa_state = INVALID_PTR;
ctx->base.saved_rs_state = INVALID_PTR;
ctx->base.saved_fs = INVALID_PTR;
ctx->base.saved_vs = INVALID_PTR;
ctx->base.saved_gs = INVALID_PTR;
ctx->base.saved_velem_state = INVALID_PTR;
ctx->base.saved_fb_state.nr_cbufs = ~0;
ctx->base.saved_num_sampler_views = ~0;
ctx->base.saved_num_sampler_states = ~0;
ctx->base.saved_num_so_targets = ~0;
 
ctx->has_geometry_shader =
pipe->screen->get_shader_param(pipe->screen, PIPE_SHADER_GEOMETRY,
PIPE_SHADER_CAP_MAX_INSTRUCTIONS) > 0;
ctx->has_stream_out =
pipe->screen->get_param(pipe->screen,
PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS) != 0;
 
ctx->has_stencil_export =
pipe->screen->get_param(pipe->screen,
PIPE_CAP_SHADER_STENCIL_EXPORT);
 
ctx->has_texture_multisample =
pipe->screen->get_param(pipe->screen, PIPE_CAP_TEXTURE_MULTISAMPLE);
 
/* blend state objects */
memset(&blend, 0, sizeof(blend));
 
for (i = 0; i <= PIPE_MASK_RGBA; i++) {
blend.rt[0].colormask = i;
ctx->blend[i] = pipe->create_blend_state(pipe, &blend);
}
 
/* depth stencil alpha state objects */
memset(&dsa, 0, sizeof(dsa));
ctx->dsa_keep_depth_stencil =
pipe->create_depth_stencil_alpha_state(pipe, &dsa);
 
dsa.depth.enabled = 1;
dsa.depth.writemask = 1;
dsa.depth.func = PIPE_FUNC_ALWAYS;
ctx->dsa_write_depth_keep_stencil =
pipe->create_depth_stencil_alpha_state(pipe, &dsa);
 
dsa.stencil[0].enabled = 1;
dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
dsa.stencil[0].valuemask = 0xff;
dsa.stencil[0].writemask = 0xff;
ctx->dsa_write_depth_stencil =
pipe->create_depth_stencil_alpha_state(pipe, &dsa);
 
dsa.depth.enabled = 0;
dsa.depth.writemask = 0;
ctx->dsa_keep_depth_write_stencil =
pipe->create_depth_stencil_alpha_state(pipe, &dsa);
 
/* sampler state */
memset(&sampler_state, 0, sizeof(sampler_state));
sampler_state.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
sampler_state.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
sampler_state.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
sampler_state.normalized_coords = 1;
ctx->sampler_state = pipe->create_sampler_state(pipe, &sampler_state);
sampler_state.normalized_coords = 0;
ctx->sampler_state_rect = pipe->create_sampler_state(pipe, &sampler_state);
 
sampler_state.min_img_filter = PIPE_TEX_FILTER_LINEAR;
sampler_state.mag_img_filter = PIPE_TEX_FILTER_LINEAR;
sampler_state.normalized_coords = 1;
ctx->sampler_state_linear = pipe->create_sampler_state(pipe, &sampler_state);
sampler_state.normalized_coords = 0;
ctx->sampler_state_rect_linear = pipe->create_sampler_state(pipe, &sampler_state);
 
/* rasterizer state */
memset(&rs_state, 0, sizeof(rs_state));
rs_state.cull_face = PIPE_FACE_NONE;
rs_state.half_pixel_center = 1;
rs_state.bottom_edge_rule = 1;
rs_state.flatshade = 1;
rs_state.depth_clip = 1;
ctx->rs_state = pipe->create_rasterizer_state(pipe, &rs_state);
 
rs_state.scissor = 1;
ctx->rs_state_scissor = pipe->create_rasterizer_state(pipe, &rs_state);
 
if (ctx->has_stream_out) {
rs_state.scissor = 0;
rs_state.rasterizer_discard = 1;
ctx->rs_discard_state = pipe->create_rasterizer_state(pipe, &rs_state);
}
 
ctx->base.vb_slot = 0; /* 0 for now */
 
/* vertex elements states */
memset(&velem[0], 0, sizeof(velem[0]) * 2);
for (i = 0; i < 2; i++) {
velem[i].src_offset = i * 4 * sizeof(float);
velem[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
velem[i].vertex_buffer_index = ctx->base.vb_slot;
}
ctx->velem_state = pipe->create_vertex_elements_state(pipe, 2, &velem[0]);
 
if (ctx->has_stream_out) {
static enum pipe_format formats[4] = {
PIPE_FORMAT_R32_UINT,
PIPE_FORMAT_R32G32_UINT,
PIPE_FORMAT_R32G32B32_UINT,
PIPE_FORMAT_R32G32B32A32_UINT
};
 
for (i = 0; i < 4; i++) {
velem[0].src_format = formats[i];
velem[0].vertex_buffer_index = ctx->base.vb_slot;
ctx->velem_state_readbuf[i] =
pipe->create_vertex_elements_state(pipe, 1, &velem[0]);
}
}
 
/* Fragment shaders are created on-demand, except these.
* The interpolation must be constant for integer texture clearing to work.
*/
ctx->fs_empty = util_make_empty_fragment_shader(pipe);
ctx->fs_write_one_cbuf =
util_make_fragment_passthrough_shader(pipe, TGSI_SEMANTIC_GENERIC,
TGSI_INTERPOLATE_CONSTANT, FALSE);
ctx->fs_write_all_cbufs =
util_make_fragment_passthrough_shader(pipe, TGSI_SEMANTIC_GENERIC,
TGSI_INTERPOLATE_CONSTANT, TRUE);
 
/* vertex shaders */
{
const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
TGSI_SEMANTIC_GENERIC };
const uint semantic_indices[] = { 0, 0 };
ctx->vs =
util_make_vertex_passthrough_shader(pipe, 2, semantic_names,
semantic_indices);
}
if (ctx->has_stream_out) {
struct pipe_stream_output_info so;
const uint semantic_names[] = { TGSI_SEMANTIC_POSITION };
const uint semantic_indices[] = { 0 };
 
memset(&so, 0, sizeof(so));
so.num_outputs = 1;
so.output[0].num_components = 1;
so.stride[0] = 1;
 
ctx->vs_pos_only =
util_make_vertex_passthrough_shader_with_so(pipe, 1, semantic_names,
semantic_indices, &so);
}
 
/* set invariant vertex coordinates */
for (i = 0; i < 4; i++)
ctx->vertices[i][0][3] = 1; /*v.w*/
 
ctx->upload = u_upload_create(pipe, 65536, 4, PIPE_BIND_VERTEX_BUFFER);
 
return &ctx->base;
}
 
void util_blitter_destroy(struct blitter_context *blitter)
{
struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
struct pipe_context *pipe = blitter->pipe;
int i;
 
for (i = 0; i <= PIPE_MASK_RGBA; i++) {
pipe->delete_blend_state(pipe, ctx->blend[i]);
}
pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
pipe->delete_depth_stencil_alpha_state(pipe,
ctx->dsa_write_depth_keep_stencil);
pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil);
pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil);
 
pipe->delete_rasterizer_state(pipe, ctx->rs_state);
pipe->delete_rasterizer_state(pipe, ctx->rs_state_scissor);
if (ctx->rs_discard_state)
pipe->delete_rasterizer_state(pipe, ctx->rs_discard_state);
pipe->delete_vs_state(pipe, ctx->vs);
if (ctx->vs_pos_only)
pipe->delete_vs_state(pipe, ctx->vs_pos_only);
pipe->delete_vertex_elements_state(pipe, ctx->velem_state);
for (i = 0; i < 4; i++) {
if (ctx->velem_state_readbuf[i]) {
pipe->delete_vertex_elements_state(pipe, ctx->velem_state_readbuf[i]);
}
}
 
for (i = 0; i < PIPE_MAX_TEXTURE_TYPES; i++) {
if (ctx->fs_texfetch_col[i])
ctx->delete_fs_state(pipe, ctx->fs_texfetch_col[i]);
if (ctx->fs_texfetch_depth[i])
ctx->delete_fs_state(pipe, ctx->fs_texfetch_depth[i]);
if (ctx->fs_texfetch_depthstencil[i])
ctx->delete_fs_state(pipe, ctx->fs_texfetch_depthstencil[i]);
if (ctx->fs_texfetch_stencil[i])
ctx->delete_fs_state(pipe, ctx->fs_texfetch_stencil[i]);
}
ctx->delete_fs_state(pipe, ctx->fs_empty);
ctx->delete_fs_state(pipe, ctx->fs_write_one_cbuf);
ctx->delete_fs_state(pipe, ctx->fs_write_all_cbufs);
 
pipe->delete_sampler_state(pipe, ctx->sampler_state_rect_linear);
pipe->delete_sampler_state(pipe, ctx->sampler_state_rect);
pipe->delete_sampler_state(pipe, ctx->sampler_state_linear);
pipe->delete_sampler_state(pipe, ctx->sampler_state);
u_upload_destroy(ctx->upload);
FREE(ctx);
}
 
void util_blitter_set_texture_multisample(struct blitter_context *blitter,
boolean supported)
{
struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
 
ctx->has_texture_multisample = supported;
}
 
static void blitter_set_running_flag(struct blitter_context_priv *ctx)
{
if (ctx->base.running) {
_debug_printf("u_blitter:%i: Caught recursion. This is a driver bug.\n",
__LINE__);
}
ctx->base.running = TRUE;
}
 
static void blitter_unset_running_flag(struct blitter_context_priv *ctx)
{
if (!ctx->base.running) {
_debug_printf("u_blitter:%i: Caught recursion. This is a driver bug.\n",
__LINE__);
}
ctx->base.running = FALSE;
}
 
static void blitter_check_saved_vertex_states(struct blitter_context_priv *ctx)
{
assert(ctx->base.saved_velem_state != INVALID_PTR);
assert(ctx->base.saved_vs != INVALID_PTR);
assert(!ctx->has_geometry_shader || ctx->base.saved_gs != INVALID_PTR);
assert(!ctx->has_stream_out || ctx->base.saved_num_so_targets != ~0);
assert(ctx->base.saved_rs_state != INVALID_PTR);
}
 
static void blitter_restore_vertex_states(struct blitter_context_priv *ctx)
{
struct pipe_context *pipe = ctx->base.pipe;
unsigned i;
 
/* Vertex buffer. */
pipe->set_vertex_buffers(pipe, ctx->base.vb_slot, 1,
&ctx->base.saved_vertex_buffer);
pipe_resource_reference(&ctx->base.saved_vertex_buffer.buffer, NULL);
 
/* Vertex elements. */
pipe->bind_vertex_elements_state(pipe, ctx->base.saved_velem_state);
ctx->base.saved_velem_state = INVALID_PTR;
 
/* Vertex shader. */
pipe->bind_vs_state(pipe, ctx->base.saved_vs);
ctx->base.saved_vs = INVALID_PTR;
 
/* Geometry shader. */
if (ctx->has_geometry_shader) {
pipe->bind_gs_state(pipe, ctx->base.saved_gs);
ctx->base.saved_gs = INVALID_PTR;
}
 
/* Stream outputs. */
if (ctx->has_stream_out) {
pipe->set_stream_output_targets(pipe,
ctx->base.saved_num_so_targets,
ctx->base.saved_so_targets, ~0);
 
for (i = 0; i < ctx->base.saved_num_so_targets; i++)
pipe_so_target_reference(&ctx->base.saved_so_targets[i], NULL);
 
ctx->base.saved_num_so_targets = ~0;
}
 
/* Rasterizer. */
pipe->bind_rasterizer_state(pipe, ctx->base.saved_rs_state);
ctx->base.saved_rs_state = INVALID_PTR;
}
 
static void blitter_check_saved_fragment_states(struct blitter_context_priv *ctx)
{
assert(ctx->base.saved_fs != INVALID_PTR);
assert(ctx->base.saved_dsa_state != INVALID_PTR);
assert(ctx->base.saved_blend_state != INVALID_PTR);
}
 
static void blitter_restore_fragment_states(struct blitter_context_priv *ctx)
{
struct pipe_context *pipe = ctx->base.pipe;
 
/* Fragment shader. */
ctx->bind_fs_state(pipe, ctx->base.saved_fs);
ctx->base.saved_fs = INVALID_PTR;
 
/* Depth, stencil, alpha. */
pipe->bind_depth_stencil_alpha_state(pipe, ctx->base.saved_dsa_state);
ctx->base.saved_dsa_state = INVALID_PTR;
 
/* Blend state. */
pipe->bind_blend_state(pipe, ctx->base.saved_blend_state);
ctx->base.saved_blend_state = INVALID_PTR;
 
/* Sample mask. */
if (ctx->base.is_sample_mask_saved) {
pipe->set_sample_mask(pipe, ctx->base.saved_sample_mask);
ctx->base.is_sample_mask_saved = FALSE;
}
 
/* Miscellaneous states. */
/* XXX check whether these are saved and whether they need to be restored
* (depending on the operation) */
pipe->set_stencil_ref(pipe, &ctx->base.saved_stencil_ref);
pipe->set_viewport_states(pipe, 0, 1, &ctx->base.saved_viewport);
}
 
static void blitter_check_saved_fb_state(struct blitter_context_priv *ctx)
{
assert(ctx->base.saved_fb_state.nr_cbufs != ~0);
}
 
static void blitter_disable_render_cond(struct blitter_context_priv *ctx)
{
struct pipe_context *pipe = ctx->base.pipe;
 
if (ctx->base.saved_render_cond_query) {
pipe->render_condition(pipe, NULL, FALSE, 0);
}
}
 
static void blitter_restore_render_cond(struct blitter_context_priv *ctx)
{
struct pipe_context *pipe = ctx->base.pipe;
 
if (ctx->base.saved_render_cond_query) {
pipe->render_condition(pipe, ctx->base.saved_render_cond_query,
ctx->base.saved_render_cond_cond,
ctx->base.saved_render_cond_mode);
ctx->base.saved_render_cond_query = NULL;
}
}
 
static void blitter_restore_fb_state(struct blitter_context_priv *ctx)
{
struct pipe_context *pipe = ctx->base.pipe;
 
pipe->set_framebuffer_state(pipe, &ctx->base.saved_fb_state);
util_unreference_framebuffer_state(&ctx->base.saved_fb_state);
}
 
static void blitter_check_saved_textures(struct blitter_context_priv *ctx)
{
assert(ctx->base.saved_num_sampler_states != ~0);
assert(ctx->base.saved_num_sampler_views != ~0);
}
 
static void blitter_restore_textures(struct blitter_context_priv *ctx)
{
struct pipe_context *pipe = ctx->base.pipe;
unsigned i;
 
/* Fragment sampler states. */
pipe->bind_fragment_sampler_states(pipe,
ctx->base.saved_num_sampler_states,
ctx->base.saved_sampler_states);
ctx->base.saved_num_sampler_states = ~0;
 
/* Fragment sampler views. */
pipe->set_fragment_sampler_views(pipe,
ctx->base.saved_num_sampler_views,
ctx->base.saved_sampler_views);
 
for (i = 0; i < ctx->base.saved_num_sampler_views; i++)
pipe_sampler_view_reference(&ctx->base.saved_sampler_views[i], NULL);
 
ctx->base.saved_num_sampler_views = ~0;
}
 
static void blitter_set_rectangle(struct blitter_context_priv *ctx,
int x1, int y1, int x2, int y2,
float depth)
{
int i;
 
/* set vertex positions */
ctx->vertices[0][0][0] = (float)x1 / ctx->dst_width * 2.0f - 1.0f; /*v0.x*/
ctx->vertices[0][0][1] = (float)y1 / ctx->dst_height * 2.0f - 1.0f; /*v0.y*/
 
ctx->vertices[1][0][0] = (float)x2 / ctx->dst_width * 2.0f - 1.0f; /*v1.x*/
ctx->vertices[1][0][1] = (float)y1 / ctx->dst_height * 2.0f - 1.0f; /*v1.y*/
 
ctx->vertices[2][0][0] = (float)x2 / ctx->dst_width * 2.0f - 1.0f; /*v2.x*/
ctx->vertices[2][0][1] = (float)y2 / ctx->dst_height * 2.0f - 1.0f; /*v2.y*/
 
ctx->vertices[3][0][0] = (float)x1 / ctx->dst_width * 2.0f - 1.0f; /*v3.x*/
ctx->vertices[3][0][1] = (float)y2 / ctx->dst_height * 2.0f - 1.0f; /*v3.y*/
 
for (i = 0; i < 4; i++)
ctx->vertices[i][0][2] = depth; /*z*/
 
/* viewport */
ctx->viewport.scale[0] = 0.5f * ctx->dst_width;
ctx->viewport.scale[1] = 0.5f * ctx->dst_height;
ctx->viewport.scale[2] = 1.0f;
ctx->viewport.scale[3] = 1.0f;
ctx->viewport.translate[0] = 0.5f * ctx->dst_width;
ctx->viewport.translate[1] = 0.5f * ctx->dst_height;
ctx->viewport.translate[2] = 0.0f;
ctx->viewport.translate[3] = 0.0f;
ctx->base.pipe->set_viewport_states(ctx->base.pipe, 0, 1, &ctx->viewport);
}
 
static void blitter_set_clear_color(struct blitter_context_priv *ctx,
const union pipe_color_union *color)
{
int i;
 
if (color) {
for (i = 0; i < 4; i++) {
uint32_t *uiverts = (uint32_t *)ctx->vertices[i][1];
uiverts[0] = color->ui[0];
uiverts[1] = color->ui[1];
uiverts[2] = color->ui[2];
uiverts[3] = color->ui[3];
}
} else {
for (i = 0; i < 4; i++) {
ctx->vertices[i][1][0] = 0;
ctx->vertices[i][1][1] = 0;
ctx->vertices[i][1][2] = 0;
ctx->vertices[i][1][3] = 0;
}
}
}
 
static void get_texcoords(struct pipe_sampler_view *src,
unsigned src_width0, unsigned src_height0,
int x1, int y1, int x2, int y2,
float out[4])
{
struct pipe_resource *tex = src->texture;
unsigned level = src->u.tex.first_level;
boolean normalized = tex->target != PIPE_TEXTURE_RECT &&
tex->nr_samples <= 1;
 
if (normalized) {
out[0] = x1 / (float)u_minify(src_width0, level);
out[1] = y1 / (float)u_minify(src_height0, level);
out[2] = x2 / (float)u_minify(src_width0, level);
out[3] = y2 / (float)u_minify(src_height0, level);
} else {
out[0] = (float) x1;
out[1] = (float) y1;
out[2] = (float) x2;
out[3] = (float) y2;
}
}
 
static void set_texcoords_in_vertices(const float coord[4],
float *out, unsigned stride)
{
out[0] = coord[0]; /*t0.s*/
out[1] = coord[1]; /*t0.t*/
out += stride;
out[0] = coord[2]; /*t1.s*/
out[1] = coord[1]; /*t1.t*/
out += stride;
out[0] = coord[2]; /*t2.s*/
out[1] = coord[3]; /*t2.t*/
out += stride;
out[0] = coord[0]; /*t3.s*/
out[1] = coord[3]; /*t3.t*/
}
 
static void blitter_set_texcoords(struct blitter_context_priv *ctx,
struct pipe_sampler_view *src,
unsigned src_width0, unsigned src_height0,
unsigned layer, unsigned sample,
int x1, int y1, int x2, int y2)
{
unsigned i;
float coord[4];
float face_coord[4][2];
 
get_texcoords(src, src_width0, src_height0, x1, y1, x2, y2, coord);
 
if (src->texture->target == PIPE_TEXTURE_CUBE ||
src->texture->target == PIPE_TEXTURE_CUBE_ARRAY) {
set_texcoords_in_vertices(coord, &face_coord[0][0], 2);
util_map_texcoords2d_onto_cubemap(layer % 6,
/* pointer, stride in floats */
&face_coord[0][0], 2,
&ctx->vertices[0][1][0], 8);
} else {
set_texcoords_in_vertices(coord, &ctx->vertices[0][1][0], 8);
}
 
/* Set the layer. */
switch (src->texture->target) {
case PIPE_TEXTURE_3D:
{
float r = layer / (float)u_minify(src->texture->depth0,
src->u.tex.first_level);
for (i = 0; i < 4; i++)
ctx->vertices[i][1][2] = r; /*r*/
}
break;
 
case PIPE_TEXTURE_1D_ARRAY:
for (i = 0; i < 4; i++)
ctx->vertices[i][1][1] = (float) layer; /*t*/
break;
 
case PIPE_TEXTURE_2D_ARRAY:
for (i = 0; i < 4; i++) {
ctx->vertices[i][1][2] = (float) layer; /*r*/
ctx->vertices[i][1][3] = (float) sample; /*q*/
}
break;
 
case PIPE_TEXTURE_CUBE_ARRAY:
for (i = 0; i < 4; i++)
ctx->vertices[i][1][3] = (float) (layer / 6); /*w*/
break;
 
case PIPE_TEXTURE_2D:
for (i = 0; i < 4; i++) {
ctx->vertices[i][1][3] = (float) sample; /*r*/
}
break;
 
default:;
}
}
 
static void blitter_set_dst_dimensions(struct blitter_context_priv *ctx,
unsigned width, unsigned height)
{
ctx->dst_width = width;
ctx->dst_height = height;
}
 
static void *blitter_get_fs_texfetch_col(struct blitter_context_priv *ctx,
enum pipe_texture_target target,
unsigned nr_samples)
{
struct pipe_context *pipe = ctx->base.pipe;
 
assert(target < PIPE_MAX_TEXTURE_TYPES);
 
if (nr_samples > 1) {
void **shader = &ctx->fs_texfetch_col_msaa[target];
 
/* Create the fragment shader on-demand. */
if (!*shader) {
unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target,
nr_samples);
 
*shader = util_make_fs_blit_msaa_color(pipe, tgsi_tex);
}
 
return *shader;
} else {
void **shader = &ctx->fs_texfetch_col[target];
 
/* Create the fragment shader on-demand. */
if (!*shader) {
unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target, 0);
 
*shader =
util_make_fragment_tex_shader(pipe, tgsi_tex,
TGSI_INTERPOLATE_LINEAR);
}
 
return *shader;
}
}
 
static INLINE
void *blitter_get_fs_texfetch_depth(struct blitter_context_priv *ctx,
enum pipe_texture_target target,
unsigned nr_samples)
{
struct pipe_context *pipe = ctx->base.pipe;
 
assert(target < PIPE_MAX_TEXTURE_TYPES);
 
if (nr_samples > 1) {
void **shader = &ctx->fs_texfetch_depth_msaa[target];
 
/* Create the fragment shader on-demand. */
if (!*shader) {
unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target,
nr_samples);
 
*shader =
util_make_fs_blit_msaa_depth(pipe, tgsi_tex);
}
 
return *shader;
} else {
void **shader = &ctx->fs_texfetch_depth[target];
 
/* Create the fragment shader on-demand. */
if (!*shader) {
unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target, 0);
 
*shader =
util_make_fragment_tex_shader_writedepth(pipe, tgsi_tex,
TGSI_INTERPOLATE_LINEAR);
}
 
return *shader;
}
}
 
static INLINE
void *blitter_get_fs_texfetch_depthstencil(struct blitter_context_priv *ctx,
enum pipe_texture_target target,
unsigned nr_samples)
{
struct pipe_context *pipe = ctx->base.pipe;
 
assert(target < PIPE_MAX_TEXTURE_TYPES);
 
if (nr_samples > 1) {
void **shader = &ctx->fs_texfetch_depthstencil_msaa[target];
 
/* Create the fragment shader on-demand. */
if (!*shader) {
unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target,
nr_samples);
 
*shader =
util_make_fs_blit_msaa_depthstencil(pipe, tgsi_tex);
}
 
return *shader;
} else {
void **shader = &ctx->fs_texfetch_depthstencil[target];
 
/* Create the fragment shader on-demand. */
if (!*shader) {
unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target, 0);
 
*shader =
util_make_fragment_tex_shader_writedepthstencil(pipe, tgsi_tex,
TGSI_INTERPOLATE_LINEAR);
}
 
return *shader;
}
}
 
static INLINE
void *blitter_get_fs_texfetch_stencil(struct blitter_context_priv *ctx,
enum pipe_texture_target target,
unsigned nr_samples)
{
struct pipe_context *pipe = ctx->base.pipe;
 
assert(target < PIPE_MAX_TEXTURE_TYPES);
 
if (nr_samples > 1) {
void **shader = &ctx->fs_texfetch_stencil_msaa[target];
 
/* Create the fragment shader on-demand. */
if (!*shader) {
unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target,
nr_samples);
 
*shader =
util_make_fs_blit_msaa_stencil(pipe, tgsi_tex);
}
 
return *shader;
} else {
void **shader = &ctx->fs_texfetch_stencil[target];
 
/* Create the fragment shader on-demand. */
if (!*shader) {
unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(target, 0);
 
*shader =
util_make_fragment_tex_shader_writestencil(pipe, tgsi_tex,
TGSI_INTERPOLATE_LINEAR);
}
 
return *shader;
}
}
 
void util_blitter_cache_all_shaders(struct blitter_context *blitter)
{
struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
struct pipe_screen *screen = blitter->pipe->screen;
unsigned i, target, max_samples;
boolean has_arraytex, has_cubearraytex;
 
max_samples = ctx->has_texture_multisample ? 2 : 1;
has_arraytex = screen->get_param(screen,
PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS) != 0;
has_cubearraytex = screen->get_param(screen,
PIPE_CAP_CUBE_MAP_ARRAY) != 0;
 
/* It only matters if i <= 1 or > 1. */
for (i = 1; i <= max_samples; i++) {
for (target = PIPE_TEXTURE_1D; target < PIPE_MAX_TEXTURE_TYPES; target++) {
if (!has_arraytex &&
(target == PIPE_TEXTURE_1D_ARRAY ||
target == PIPE_TEXTURE_2D_ARRAY)) {
continue;
}
if (!has_cubearraytex &&
(target == PIPE_TEXTURE_CUBE_ARRAY))
continue;
 
if (i > 1 &&
(target != PIPE_TEXTURE_2D &&
target != PIPE_TEXTURE_2D_ARRAY))
continue;
 
blitter_get_fs_texfetch_col(ctx, target, i);
blitter_get_fs_texfetch_depth(ctx, target, i);
if (ctx->has_stencil_export) {
blitter_get_fs_texfetch_depthstencil(ctx, target, i);
blitter_get_fs_texfetch_stencil(ctx, target, i);
}
}
}
}
 
static void blitter_set_common_draw_rect_state(struct blitter_context_priv *ctx,
boolean scissor)
{
struct pipe_context *pipe = ctx->base.pipe;
 
pipe->bind_rasterizer_state(pipe, scissor ? ctx->rs_state_scissor
: ctx->rs_state);
pipe->bind_vs_state(pipe, ctx->vs);
if (ctx->has_geometry_shader)
pipe->bind_gs_state(pipe, NULL);
if (ctx->has_stream_out)
pipe->set_stream_output_targets(pipe, 0, NULL, 0);
}
 
static void blitter_draw(struct blitter_context_priv *ctx,
int x1, int y1, int x2, int y2, float depth)
{
struct pipe_resource *buf = NULL;
unsigned offset = 0;
 
blitter_set_rectangle(ctx, x1, y1, x2, y2, depth);
 
u_upload_data(ctx->upload, 0, sizeof(ctx->vertices), ctx->vertices,
&offset, &buf);
u_upload_unmap(ctx->upload);
util_draw_vertex_buffer(ctx->base.pipe, NULL, buf, ctx->base.vb_slot,
offset, PIPE_PRIM_TRIANGLE_FAN, 4, 2);
pipe_resource_reference(&buf, NULL);
}
 
void util_blitter_draw_rectangle(struct blitter_context *blitter,
int x1, int y1, int x2, int y2, float depth,
enum blitter_attrib_type type,
const union pipe_color_union *attrib)
{
struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
 
switch (type) {
case UTIL_BLITTER_ATTRIB_COLOR:
blitter_set_clear_color(ctx, attrib);
break;
 
case UTIL_BLITTER_ATTRIB_TEXCOORD:
set_texcoords_in_vertices(attrib->f, &ctx->vertices[0][1][0], 8);
break;
 
default:;
}
 
blitter_draw(ctx, x1, y1, x2, y2, depth);
}
 
static void util_blitter_clear_custom(struct blitter_context *blitter,
unsigned width, unsigned height,
unsigned clear_buffers,
const union pipe_color_union *color,
double depth, unsigned stencil,
void *custom_blend, void *custom_dsa)
{
struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
struct pipe_context *pipe = ctx->base.pipe;
struct pipe_stencil_ref sr = { { 0 } };
 
blitter_set_running_flag(ctx);
blitter_check_saved_vertex_states(ctx);
blitter_check_saved_fragment_states(ctx);
blitter_disable_render_cond(ctx);
 
/* bind states */
if (custom_blend) {
pipe->bind_blend_state(pipe, custom_blend);
} else if (clear_buffers & PIPE_CLEAR_COLOR) {
pipe->bind_blend_state(pipe, ctx->blend[PIPE_MASK_RGBA]);
} else {
pipe->bind_blend_state(pipe, ctx->blend[0]);
}
 
if (custom_dsa) {
pipe->bind_depth_stencil_alpha_state(pipe, custom_dsa);
} else if ((clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) == PIPE_CLEAR_DEPTHSTENCIL) {
pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil);
} else if (clear_buffers & PIPE_CLEAR_DEPTH) {
pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_keep_stencil);
} else if (clear_buffers & PIPE_CLEAR_STENCIL) {
pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil);
} else {
pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
}
 
sr.ref_value[0] = stencil & 0xff;
pipe->set_stencil_ref(pipe, &sr);
 
pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
ctx->bind_fs_state(pipe, ctx->fs_write_all_cbufs);
pipe->set_sample_mask(pipe, ~0);
 
blitter_set_common_draw_rect_state(ctx, FALSE);
blitter_set_dst_dimensions(ctx, width, height);
blitter->draw_rectangle(blitter, 0, 0, width, height, (float) depth,
UTIL_BLITTER_ATTRIB_COLOR, color);
 
blitter_restore_vertex_states(ctx);
blitter_restore_fragment_states(ctx);
blitter_restore_render_cond(ctx);
blitter_unset_running_flag(ctx);
}
 
void util_blitter_clear(struct blitter_context *blitter,
unsigned width, unsigned height,
unsigned clear_buffers,
const union pipe_color_union *color,
double depth, unsigned stencil)
{
util_blitter_clear_custom(blitter, width, height,
clear_buffers, color, depth, stencil,
NULL, NULL);
}
 
void util_blitter_custom_clear_depth(struct blitter_context *blitter,
unsigned width, unsigned height,
double depth, void *custom_dsa)
{
static const union pipe_color_union color;
util_blitter_clear_custom(blitter, width, height, 0, &color, depth, 0,
NULL, custom_dsa);
}
 
void util_blitter_default_dst_texture(struct pipe_surface *dst_templ,
struct pipe_resource *dst,
unsigned dstlevel,
unsigned dstz)
{
memset(dst_templ, 0, sizeof(*dst_templ));
dst_templ->format = util_format_linear(dst->format);
dst_templ->u.tex.level = dstlevel;
dst_templ->u.tex.first_layer = dstz;
dst_templ->u.tex.last_layer = dstz;
}
 
static struct pipe_surface *
util_blitter_get_next_surface_layer(struct pipe_context *pipe,
struct pipe_surface *surf)
{
struct pipe_surface dst_templ;
 
memset(&dst_templ, 0, sizeof(dst_templ));
dst_templ.format = surf->format;
dst_templ.u.tex.level = surf->u.tex.level;
dst_templ.u.tex.first_layer = surf->u.tex.first_layer + 1;
dst_templ.u.tex.last_layer = surf->u.tex.last_layer + 1;
 
return pipe->create_surface(pipe, surf->texture, &dst_templ);
}
 
void util_blitter_default_src_texture(struct pipe_sampler_view *src_templ,
struct pipe_resource *src,
unsigned srclevel)
{
memset(src_templ, 0, sizeof(*src_templ));
src_templ->format = util_format_linear(src->format);
src_templ->u.tex.first_level = srclevel;
src_templ->u.tex.last_level = srclevel;
src_templ->u.tex.first_layer = 0;
src_templ->u.tex.last_layer =
src->target == PIPE_TEXTURE_3D ? u_minify(src->depth0, srclevel) - 1
: src->array_size - 1;
src_templ->swizzle_r = PIPE_SWIZZLE_RED;
src_templ->swizzle_g = PIPE_SWIZZLE_GREEN;
src_templ->swizzle_b = PIPE_SWIZZLE_BLUE;
src_templ->swizzle_a = PIPE_SWIZZLE_ALPHA;
}
 
static boolean is_blit_generic_supported(struct blitter_context *blitter,
const struct pipe_resource *dst,
enum pipe_format dst_format,
const struct pipe_resource *src,
enum pipe_format src_format,
unsigned mask)
{
struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
struct pipe_screen *screen = ctx->base.pipe->screen;
 
if (dst) {
unsigned bind;
const struct util_format_description *desc =
util_format_description(dst_format);
boolean dst_has_stencil = util_format_has_stencil(desc);
 
/* Stencil export must be supported for stencil copy. */
if ((mask & PIPE_MASK_S) && dst_has_stencil &&
!ctx->has_stencil_export) {
return FALSE;
}
 
if (dst_has_stencil || util_format_has_depth(desc))
bind = PIPE_BIND_DEPTH_STENCIL;
else
bind = PIPE_BIND_RENDER_TARGET;
 
if (!screen->is_format_supported(screen, dst_format, dst->target,
dst->nr_samples, bind)) {
return FALSE;
}
}
 
if (src) {
if (src->nr_samples > 1 && !ctx->has_texture_multisample) {
return FALSE;
}
 
if (!screen->is_format_supported(screen, src_format, src->target,
src->nr_samples, PIPE_BIND_SAMPLER_VIEW)) {
return FALSE;
}
 
/* Check stencil sampler support for stencil copy. */
if (mask & PIPE_MASK_S) {
if (util_format_has_stencil(util_format_description(src_format))) {
enum pipe_format stencil_format =
util_format_stencil_only(src_format);
assert(stencil_format != PIPE_FORMAT_NONE);
 
if (stencil_format != src_format &&
!screen->is_format_supported(screen, stencil_format,
src->target, src->nr_samples,
PIPE_BIND_SAMPLER_VIEW)) {
return FALSE;
}
}
}
}
 
return TRUE;
}
 
boolean util_blitter_is_copy_supported(struct blitter_context *blitter,
const struct pipe_resource *dst,
const struct pipe_resource *src,
unsigned mask)
{
return is_blit_generic_supported(blitter, dst, dst->format,
src, src->format, mask);
}
 
boolean util_blitter_is_blit_supported(struct blitter_context *blitter,
const struct pipe_blit_info *info)
{
return is_blit_generic_supported(blitter,
info->dst.resource, info->dst.format,
info->src.resource, info->src.format,
info->mask);
}
 
void util_blitter_copy_texture(struct blitter_context *blitter,
struct pipe_resource *dst,
unsigned dst_level,
unsigned dstx, unsigned dsty, unsigned dstz,
struct pipe_resource *src,
unsigned src_level,
const struct pipe_box *srcbox, unsigned mask,
boolean copy_all_samples)
{
struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
struct pipe_context *pipe = ctx->base.pipe;
struct pipe_surface *dst_view, dst_templ;
struct pipe_sampler_view src_templ, *src_view;
struct pipe_box dstbox;
 
assert(dst && src);
assert(src->target < PIPE_MAX_TEXTURE_TYPES);
 
u_box_3d(dstx, dsty, dstz, abs(srcbox->width), abs(srcbox->height),
abs(srcbox->depth), &dstbox);
 
/* Initialize the surface. */
util_blitter_default_dst_texture(&dst_templ, dst, dst_level, dstz);
dst_view = pipe->create_surface(pipe, dst, &dst_templ);
 
/* Initialize the sampler view. */
util_blitter_default_src_texture(&src_templ, src, src_level);
src_view = pipe->create_sampler_view(pipe, src, &src_templ);
 
/* Copy. */
util_blitter_blit_generic(blitter, dst_view, &dstbox,
src_view, srcbox, src->width0, src->height0,
mask, PIPE_TEX_FILTER_NEAREST, NULL,
copy_all_samples);
 
pipe_surface_reference(&dst_view, NULL);
pipe_sampler_view_reference(&src_view, NULL);
}
 
void util_blitter_blit_generic(struct blitter_context *blitter,
struct pipe_surface *dst,
const struct pipe_box *dstbox,
struct pipe_sampler_view *src,
const struct pipe_box *srcbox,
unsigned src_width0, unsigned src_height0,
unsigned mask, unsigned filter,
const struct pipe_scissor_state *scissor,
boolean copy_all_samples)
{
struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
struct pipe_context *pipe = ctx->base.pipe;
struct pipe_framebuffer_state fb_state;
enum pipe_texture_target src_target = src->texture->target;
unsigned src_samples = src->texture->nr_samples;
boolean has_depth, has_stencil, has_color;
boolean blit_stencil, blit_depth, blit_color;
void *sampler_state;
const struct util_format_description *src_desc =
util_format_description(src->format);
const struct util_format_description *dst_desc =
util_format_description(dst->format);
 
has_color = src_desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS &&
dst_desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS;
has_depth = util_format_has_depth(src_desc) &&
util_format_has_depth(dst_desc);
has_stencil = util_format_has_stencil(src_desc) &&
util_format_has_stencil(dst_desc);
 
blit_color = has_color && (mask & PIPE_MASK_RGBA);
blit_depth = has_depth && (mask & PIPE_MASK_Z);
blit_stencil = has_stencil && (mask & PIPE_MASK_S) &&
ctx->has_stencil_export;
 
if (!blit_stencil && !blit_depth && !blit_color) {
return;
}
 
/* Check whether the states are properly saved. */
blitter_set_running_flag(ctx);
blitter_check_saved_vertex_states(ctx);
blitter_check_saved_fragment_states(ctx);
blitter_check_saved_textures(ctx);
blitter_check_saved_fb_state(ctx);
blitter_disable_render_cond(ctx);
 
/* Initialize framebuffer state. */
fb_state.width = dst->width;
fb_state.height = dst->height;
fb_state.nr_cbufs = blit_depth || blit_stencil ? 0 : 1;
fb_state.cbufs[0] = NULL;
fb_state.zsbuf = NULL;
 
if (blit_depth || blit_stencil) {
pipe->bind_blend_state(pipe, ctx->blend[0]);
 
if (blit_depth && blit_stencil) {
pipe->bind_depth_stencil_alpha_state(pipe,
ctx->dsa_write_depth_stencil);
ctx->bind_fs_state(pipe,
blitter_get_fs_texfetch_depthstencil(ctx, src_target,
src_samples));
} else if (blit_depth) {
pipe->bind_depth_stencil_alpha_state(pipe,
ctx->dsa_write_depth_keep_stencil);
ctx->bind_fs_state(pipe,
blitter_get_fs_texfetch_depth(ctx, src_target,
src_samples));
} else { /* is_stencil */
pipe->bind_depth_stencil_alpha_state(pipe,
ctx->dsa_keep_depth_write_stencil);
ctx->bind_fs_state(pipe,
blitter_get_fs_texfetch_stencil(ctx, src_target,
src_samples));
}
 
} else {
pipe->bind_blend_state(pipe, ctx->blend[mask & PIPE_MASK_RGBA]);
pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
ctx->bind_fs_state(pipe,
blitter_get_fs_texfetch_col(ctx, src_target,
src_samples));
}
 
/* Set the linear filter only for scaled color non-MSAA blits. */
if (filter == PIPE_TEX_FILTER_LINEAR &&
!blit_depth && !blit_stencil &&
src_samples <= 1 &&
(dstbox->width != abs(srcbox->width) ||
dstbox->height != abs(srcbox->height))) {
if (src_target == PIPE_TEXTURE_RECT) {
sampler_state = ctx->sampler_state_rect_linear;
} else {
sampler_state = ctx->sampler_state_linear;
}
} else {
if (src_target == PIPE_TEXTURE_RECT) {
sampler_state = ctx->sampler_state_rect;
} else {
sampler_state = ctx->sampler_state;
}
}
 
/* Set samplers. */
if (blit_depth && blit_stencil) {
/* Setup two samplers, one for depth and the other one for stencil. */
struct pipe_sampler_view templ;
struct pipe_sampler_view *views[2];
void *samplers[2] = {sampler_state, sampler_state};
 
templ = *src;
templ.format = util_format_stencil_only(templ.format);
assert(templ.format != PIPE_FORMAT_NONE);
 
views[0] = src;
views[1] = pipe->create_sampler_view(pipe, src->texture, &templ);
 
pipe->set_fragment_sampler_views(pipe, 2, views);
pipe->bind_fragment_sampler_states(pipe, 2, samplers);
 
pipe_sampler_view_reference(&views[1], NULL);
} else if (blit_stencil) {
/* Set a stencil-only sampler view for it not to sample depth instead. */
struct pipe_sampler_view templ;
struct pipe_sampler_view *view;
 
templ = *src;
templ.format = util_format_stencil_only(templ.format);
assert(templ.format != PIPE_FORMAT_NONE);
 
view = pipe->create_sampler_view(pipe, src->texture, &templ);
 
pipe->set_fragment_sampler_views(pipe, 1, &view);
pipe->bind_fragment_sampler_states(pipe, 1, &sampler_state);
 
pipe_sampler_view_reference(&view, NULL);
} else {
pipe->set_fragment_sampler_views(pipe, 1, &src);
pipe->bind_fragment_sampler_states(pipe, 1, &sampler_state);
}
 
pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
if (scissor) {
pipe->set_scissor_states(pipe, 0, 1, scissor);
}
 
blitter_set_common_draw_rect_state(ctx, scissor != NULL);
blitter_set_dst_dimensions(ctx, dst->width, dst->height);
 
if ((src_target == PIPE_TEXTURE_1D ||
src_target == PIPE_TEXTURE_2D ||
src_target == PIPE_TEXTURE_RECT) &&
src_samples <= 1) {
/* Draw the quad with the draw_rectangle callback. */
 
/* Set texture coordinates. - use a pipe color union
* for interface purposes.
* XXX pipe_color_union is a wrong name since we use that to set
* texture coordinates too.
*/
union pipe_color_union coord;
get_texcoords(src, src_width0, src_height0, srcbox->x, srcbox->y,
srcbox->x+srcbox->width, srcbox->y+srcbox->height, coord.f);
 
/* Set framebuffer state. */
if (blit_depth || blit_stencil) {
fb_state.zsbuf = dst;
} else {
fb_state.cbufs[0] = dst;
}
pipe->set_framebuffer_state(pipe, &fb_state);
 
/* Draw. */
pipe->set_sample_mask(pipe, ~0);
blitter->draw_rectangle(blitter, dstbox->x, dstbox->y,
dstbox->x + dstbox->width,
dstbox->y + dstbox->height, 0,
UTIL_BLITTER_ATTRIB_TEXCOORD, &coord);
} else {
/* Draw the quad with the generic codepath. */
int z;
for (z = 0; z < dstbox->depth; z++) {
struct pipe_surface *old;
 
/* Set framebuffer state. */
if (blit_depth || blit_stencil) {
fb_state.zsbuf = dst;
} else {
fb_state.cbufs[0] = dst;
}
pipe->set_framebuffer_state(pipe, &fb_state);
 
/* See if we need to blit a multisample or singlesample buffer. */
if (copy_all_samples &&
src_samples == dst->texture->nr_samples &&
dst->texture->nr_samples > 1) {
unsigned i, max_sample = MAX2(dst->texture->nr_samples, 1) - 1;
 
for (i = 0; i <= max_sample; i++) {
pipe->set_sample_mask(pipe, 1 << i);
blitter_set_texcoords(ctx, src, src_width0, src_height0,
srcbox->z + z,
i, srcbox->x, srcbox->y,
srcbox->x + srcbox->width,
srcbox->y + srcbox->height);
blitter_draw(ctx, dstbox->x, dstbox->y,
dstbox->x + dstbox->width,
dstbox->y + dstbox->height, 0);
}
} else {
pipe->set_sample_mask(pipe, ~0);
blitter_set_texcoords(ctx, src, src_width0, src_height0,
srcbox->z + z, 0,
srcbox->x, srcbox->y,
srcbox->x + srcbox->width,
srcbox->y + srcbox->height);
blitter_draw(ctx, dstbox->x, dstbox->y,
dstbox->x + dstbox->width,
dstbox->y + dstbox->height, 0);
}
 
/* Get the next surface or (if this is the last iteration)
* just unreference the last one. */
old = dst;
if (z < dstbox->depth-1) {
dst = ctx->base.get_next_surface_layer(ctx->base.pipe, dst);
}
if (z) {
pipe_surface_reference(&old, NULL);
}
}
}
 
blitter_restore_vertex_states(ctx);
blitter_restore_fragment_states(ctx);
blitter_restore_textures(ctx);
blitter_restore_fb_state(ctx);
if (scissor) {
pipe->set_scissor_states(pipe, 0, 1, &ctx->base.saved_scissor);
}
blitter_restore_render_cond(ctx);
blitter_unset_running_flag(ctx);
}
 
void
util_blitter_blit(struct blitter_context *blitter,
const struct pipe_blit_info *info)
{
struct pipe_resource *dst = info->dst.resource;
struct pipe_resource *src = info->src.resource;
struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
struct pipe_context *pipe = ctx->base.pipe;
struct pipe_surface *dst_view, dst_templ;
struct pipe_sampler_view src_templ, *src_view;
 
/* Initialize the surface. */
util_blitter_default_dst_texture(&dst_templ, dst, info->dst.level,
info->dst.box.z);
dst_templ.format = info->dst.format;
dst_view = pipe->create_surface(pipe, dst, &dst_templ);
 
/* Initialize the sampler view. */
util_blitter_default_src_texture(&src_templ, src, info->src.level);
src_templ.format = info->src.format;
src_view = pipe->create_sampler_view(pipe, src, &src_templ);
 
/* Copy. */
util_blitter_blit_generic(blitter, dst_view, &info->dst.box,
src_view, &info->src.box, src->width0, src->height0,
info->mask, info->filter,
info->scissor_enable ? &info->scissor : NULL, TRUE);
 
pipe_surface_reference(&dst_view, NULL);
pipe_sampler_view_reference(&src_view, NULL);
}
 
/* Clear a region of a color surface to a constant value. */
void util_blitter_clear_render_target(struct blitter_context *blitter,
struct pipe_surface *dstsurf,
const union pipe_color_union *color,
unsigned dstx, unsigned dsty,
unsigned width, unsigned height)
{
struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
struct pipe_context *pipe = ctx->base.pipe;
struct pipe_framebuffer_state fb_state;
 
assert(dstsurf->texture);
if (!dstsurf->texture)
return;
 
/* check the saved state */
blitter_set_running_flag(ctx);
blitter_check_saved_vertex_states(ctx);
blitter_check_saved_fragment_states(ctx);
blitter_check_saved_fb_state(ctx);
blitter_disable_render_cond(ctx);
 
/* bind states */
pipe->bind_blend_state(pipe, ctx->blend[PIPE_MASK_RGBA]);
pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
ctx->bind_fs_state(pipe, ctx->fs_write_one_cbuf);
pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
 
/* set a framebuffer state */
fb_state.width = dstsurf->width;
fb_state.height = dstsurf->height;
fb_state.nr_cbufs = 1;
fb_state.cbufs[0] = dstsurf;
fb_state.zsbuf = 0;
pipe->set_framebuffer_state(pipe, &fb_state);
pipe->set_sample_mask(pipe, ~0);
 
blitter_set_common_draw_rect_state(ctx, FALSE);
blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height);
blitter->draw_rectangle(blitter, dstx, dsty, dstx+width, dsty+height, 0,
UTIL_BLITTER_ATTRIB_COLOR, color);
 
blitter_restore_vertex_states(ctx);
blitter_restore_fragment_states(ctx);
blitter_restore_fb_state(ctx);
blitter_restore_render_cond(ctx);
blitter_unset_running_flag(ctx);
}
 
/* Clear a region of a depth stencil surface. */
void util_blitter_clear_depth_stencil(struct blitter_context *blitter,
struct pipe_surface *dstsurf,
unsigned clear_flags,
double depth,
unsigned stencil,
unsigned dstx, unsigned dsty,
unsigned width, unsigned height)
{
struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
struct pipe_context *pipe = ctx->base.pipe;
struct pipe_framebuffer_state fb_state;
struct pipe_stencil_ref sr = { { 0 } };
 
assert(dstsurf->texture);
if (!dstsurf->texture)
return;
 
/* check the saved state */
blitter_set_running_flag(ctx);
blitter_check_saved_vertex_states(ctx);
blitter_check_saved_fragment_states(ctx);
blitter_check_saved_fb_state(ctx);
blitter_disable_render_cond(ctx);
 
/* bind states */
pipe->bind_blend_state(pipe, ctx->blend[0]);
if ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) == PIPE_CLEAR_DEPTHSTENCIL) {
sr.ref_value[0] = stencil & 0xff;
pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_stencil);
pipe->set_stencil_ref(pipe, &sr);
}
else if (clear_flags & PIPE_CLEAR_DEPTH) {
pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_write_depth_keep_stencil);
}
else if (clear_flags & PIPE_CLEAR_STENCIL) {
sr.ref_value[0] = stencil & 0xff;
pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_write_stencil);
pipe->set_stencil_ref(pipe, &sr);
}
else
/* hmm that should be illegal probably, or make it a no-op somewhere */
pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
 
ctx->bind_fs_state(pipe, ctx->fs_empty);
pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
 
/* set a framebuffer state */
fb_state.width = dstsurf->width;
fb_state.height = dstsurf->height;
fb_state.nr_cbufs = 0;
fb_state.cbufs[0] = 0;
fb_state.zsbuf = dstsurf;
pipe->set_framebuffer_state(pipe, &fb_state);
pipe->set_sample_mask(pipe, ~0);
 
blitter_set_common_draw_rect_state(ctx, FALSE);
blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height);
blitter->draw_rectangle(blitter, dstx, dsty, dstx+width, dsty+height,
(float) depth,
UTIL_BLITTER_ATTRIB_NONE, NULL);
 
blitter_restore_vertex_states(ctx);
blitter_restore_fragment_states(ctx);
blitter_restore_fb_state(ctx);
blitter_restore_render_cond(ctx);
blitter_unset_running_flag(ctx);
}
 
/* draw a rectangle across a region using a custom dsa stage - for r600g */
void util_blitter_custom_depth_stencil(struct blitter_context *blitter,
struct pipe_surface *zsurf,
struct pipe_surface *cbsurf,
unsigned sample_mask,
void *dsa_stage, float depth)
{
struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
struct pipe_context *pipe = ctx->base.pipe;
struct pipe_framebuffer_state fb_state;
 
assert(zsurf->texture);
if (!zsurf->texture)
return;
 
/* check the saved state */
blitter_set_running_flag(ctx);
blitter_check_saved_vertex_states(ctx);
blitter_check_saved_fragment_states(ctx);
blitter_check_saved_fb_state(ctx);
blitter_disable_render_cond(ctx);
 
/* bind states */
pipe->bind_blend_state(pipe, cbsurf ? ctx->blend[PIPE_MASK_RGBA] :
ctx->blend[0]);
pipe->bind_depth_stencil_alpha_state(pipe, dsa_stage);
ctx->bind_fs_state(pipe, ctx->fs_empty);
pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
 
/* set a framebuffer state */
fb_state.width = zsurf->width;
fb_state.height = zsurf->height;
fb_state.nr_cbufs = 1;
if (cbsurf) {
fb_state.cbufs[0] = cbsurf;
fb_state.nr_cbufs = 1;
} else {
fb_state.cbufs[0] = NULL;
fb_state.nr_cbufs = 0;
}
fb_state.zsbuf = zsurf;
pipe->set_framebuffer_state(pipe, &fb_state);
pipe->set_sample_mask(pipe, sample_mask);
 
blitter_set_common_draw_rect_state(ctx, FALSE);
blitter_set_dst_dimensions(ctx, zsurf->width, zsurf->height);
blitter->draw_rectangle(blitter, 0, 0, zsurf->width, zsurf->height, depth,
UTIL_BLITTER_ATTRIB_NONE, NULL);
 
blitter_restore_vertex_states(ctx);
blitter_restore_fragment_states(ctx);
blitter_restore_fb_state(ctx);
blitter_restore_render_cond(ctx);
blitter_unset_running_flag(ctx);
}
 
void util_blitter_copy_buffer(struct blitter_context *blitter,
struct pipe_resource *dst,
unsigned dstx,
struct pipe_resource *src,
unsigned srcx,
unsigned size)
{
struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
struct pipe_context *pipe = ctx->base.pipe;
struct pipe_vertex_buffer vb;
struct pipe_stream_output_target *so_target;
 
if (srcx >= src->width0 ||
dstx >= dst->width0) {
return;
}
if (srcx + size > src->width0) {
size = src->width0 - srcx;
}
if (dstx + size > dst->width0) {
size = dst->width0 - dstx;
}
 
/* Drivers not capable of Stream Out should not call this function
* in the first place. */
assert(ctx->has_stream_out);
 
/* Some alignment is required. */
if (srcx % 4 != 0 || dstx % 4 != 0 || size % 4 != 0 ||
!ctx->has_stream_out) {
struct pipe_box box;
u_box_1d(srcx, size, &box);
util_resource_copy_region(pipe, dst, 0, dstx, 0, 0, src, 0, &box);
return;
}
 
blitter_set_running_flag(ctx);
blitter_check_saved_vertex_states(ctx);
blitter_disable_render_cond(ctx);
 
vb.buffer = src;
vb.buffer_offset = srcx;
vb.stride = 4;
 
pipe->set_vertex_buffers(pipe, ctx->base.vb_slot, 1, &vb);
pipe->bind_vertex_elements_state(pipe, ctx->velem_state_readbuf[0]);
pipe->bind_vs_state(pipe, ctx->vs_pos_only);
if (ctx->has_geometry_shader)
pipe->bind_gs_state(pipe, NULL);
pipe->bind_rasterizer_state(pipe, ctx->rs_discard_state);
 
so_target = pipe->create_stream_output_target(pipe, dst, dstx, size);
pipe->set_stream_output_targets(pipe, 1, &so_target, 0);
 
util_draw_arrays(pipe, PIPE_PRIM_POINTS, 0, size / 4);
 
blitter_restore_vertex_states(ctx);
blitter_restore_render_cond(ctx);
blitter_unset_running_flag(ctx);
pipe_so_target_reference(&so_target, NULL);
}
 
void util_blitter_clear_buffer(struct blitter_context *blitter,
struct pipe_resource *dst,
unsigned offset, unsigned size,
unsigned num_channels,
const union pipe_color_union *clear_value)
{
struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
struct pipe_context *pipe = ctx->base.pipe;
struct pipe_vertex_buffer vb = {0};
struct pipe_stream_output_target *so_target;
 
assert(num_channels >= 1);
assert(num_channels <= 4);
 
/* IMPORTANT: DON'T DO ANY BOUNDS CHECKING HERE!
*
* R600 uses this to initialize texture resources, so width0 might not be
* what you think it is.
*/
 
/* Streamout is required. */
if (!ctx->has_stream_out) {
assert(!"Streamout unsupported in util_blitter_clear_buffer()");
return;
}
 
/* Some alignment is required. */
if (offset % 4 != 0 || size % 4 != 0) {
assert(!"Bad alignment in util_blitter_clear_buffer()");
return;
}
 
u_upload_data(ctx->upload, 0, num_channels*4, clear_value,
&vb.buffer_offset, &vb.buffer);
vb.stride = 0;
 
blitter_set_running_flag(ctx);
blitter_check_saved_vertex_states(ctx);
blitter_disable_render_cond(ctx);
 
pipe->set_vertex_buffers(pipe, ctx->base.vb_slot, 1, &vb);
pipe->bind_vertex_elements_state(pipe,
ctx->velem_state_readbuf[num_channels-1]);
pipe->bind_vs_state(pipe, ctx->vs_pos_only);
if (ctx->has_geometry_shader)
pipe->bind_gs_state(pipe, NULL);
pipe->bind_rasterizer_state(pipe, ctx->rs_discard_state);
 
so_target = pipe->create_stream_output_target(pipe, dst, offset, size);
pipe->set_stream_output_targets(pipe, 1, &so_target, 0);
 
util_draw_arrays(pipe, PIPE_PRIM_POINTS, 0, size / 4);
 
blitter_restore_vertex_states(ctx);
blitter_restore_render_cond(ctx);
blitter_unset_running_flag(ctx);
pipe_so_target_reference(&so_target, NULL);
pipe_resource_reference(&vb.buffer, NULL);
}
 
/* probably radeon specific */
void util_blitter_custom_resolve_color(struct blitter_context *blitter,
struct pipe_resource *dst,
unsigned dst_level,
unsigned dst_layer,
struct pipe_resource *src,
unsigned src_layer,
unsigned sample_mask,
void *custom_blend,
enum pipe_format format)
{
struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
struct pipe_context *pipe = ctx->base.pipe;
struct pipe_framebuffer_state fb_state;
struct pipe_surface *srcsurf, *dstsurf, surf_tmpl;
 
blitter_set_running_flag(ctx);
blitter_check_saved_vertex_states(ctx);
blitter_check_saved_fragment_states(ctx);
blitter_disable_render_cond(ctx);
 
/* bind states */
pipe->bind_blend_state(pipe, custom_blend);
pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
ctx->bind_fs_state(pipe, ctx->fs_write_one_cbuf);
pipe->set_sample_mask(pipe, sample_mask);
 
memset(&surf_tmpl, 0, sizeof(surf_tmpl));
surf_tmpl.format = format;
surf_tmpl.u.tex.level = dst_level;
surf_tmpl.u.tex.first_layer = dst_layer;
surf_tmpl.u.tex.last_layer = dst_layer;
 
dstsurf = pipe->create_surface(pipe, dst, &surf_tmpl);
 
surf_tmpl.u.tex.level = 0;
surf_tmpl.u.tex.first_layer = src_layer;
surf_tmpl.u.tex.last_layer = src_layer;
 
srcsurf = pipe->create_surface(pipe, src, &surf_tmpl);
 
/* set a framebuffer state */
fb_state.width = src->width0;
fb_state.height = src->height0;
fb_state.nr_cbufs = 2;
fb_state.cbufs[0] = srcsurf;
fb_state.cbufs[1] = dstsurf;
fb_state.zsbuf = NULL;
pipe->set_framebuffer_state(pipe, &fb_state);
 
blitter_set_common_draw_rect_state(ctx, FALSE);
blitter_set_dst_dimensions(ctx, src->width0, src->height0);
blitter->draw_rectangle(blitter, 0, 0, src->width0, src->height0,
0, 0, NULL);
blitter_restore_fb_state(ctx);
blitter_restore_vertex_states(ctx);
blitter_restore_fragment_states(ctx);
blitter_restore_render_cond(ctx);
blitter_unset_running_flag(ctx);
 
pipe_surface_reference(&srcsurf, NULL);
pipe_surface_reference(&dstsurf, NULL);
}
 
void util_blitter_custom_color(struct blitter_context *blitter,
struct pipe_surface *dstsurf,
void *custom_blend)
{
struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter;
struct pipe_context *pipe = ctx->base.pipe;
struct pipe_framebuffer_state fb_state;
 
assert(dstsurf->texture);
if (!dstsurf->texture)
return;
 
/* check the saved state */
blitter_set_running_flag(ctx);
blitter_check_saved_vertex_states(ctx);
blitter_check_saved_fragment_states(ctx);
blitter_check_saved_fb_state(ctx);
blitter_disable_render_cond(ctx);
 
/* bind states */
pipe->bind_blend_state(pipe, custom_blend ? custom_blend
: ctx->blend[PIPE_MASK_RGBA]);
pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_depth_stencil);
ctx->bind_fs_state(pipe, ctx->fs_write_one_cbuf);
pipe->bind_vertex_elements_state(pipe, ctx->velem_state);
pipe->set_sample_mask(pipe, (1ull << MAX2(1, dstsurf->texture->nr_samples)) - 1);
 
/* set a framebuffer state */
fb_state.width = dstsurf->width;
fb_state.height = dstsurf->height;
fb_state.nr_cbufs = 1;
fb_state.cbufs[0] = dstsurf;
fb_state.zsbuf = 0;
pipe->set_framebuffer_state(pipe, &fb_state);
pipe->set_sample_mask(pipe, ~0);
 
blitter_set_common_draw_rect_state(ctx, FALSE);
blitter_set_dst_dimensions(ctx, dstsurf->width, dstsurf->height);
blitter->draw_rectangle(blitter, 0, 0, dstsurf->width, dstsurf->height,
0, 0, NULL);
 
blitter_restore_vertex_states(ctx);
blitter_restore_fragment_states(ctx);
blitter_restore_fb_state(ctx);
blitter_restore_render_cond(ctx);
blitter_unset_running_flag(ctx);
}
/drivers/video/Gallium/auxiliary/util/u_blitter.h
0,0 → 1,531
/**************************************************************************
*
* Copyright 2009 Marek Olšák <maraeo@gmail.com>
*
* 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.
*
**************************************************************************/
 
#ifndef U_BLITTER_H
#define U_BLITTER_H
 
#include "util/u_framebuffer.h"
#include "util/u_inlines.h"
 
#include "pipe/p_state.h"
 
/* u_memory.h conflicts with st/mesa */
#ifndef Elements
#define Elements(x) (sizeof(x)/sizeof((x)[0]))
#endif
 
 
#ifdef __cplusplus
extern "C" {
#endif
 
struct pipe_context;
 
enum blitter_attrib_type {
UTIL_BLITTER_ATTRIB_NONE,
UTIL_BLITTER_ATTRIB_COLOR,
UTIL_BLITTER_ATTRIB_TEXCOORD
};
 
struct blitter_context
{
/**
* Draw a rectangle.
*
* \param x1 An X coordinate of the top-left corner.
* \param y1 A Y coordinate of the top-left corner.
* \param x2 An X coordinate of the bottom-right corner.
* \param y2 A Y coordinate of the bottom-right corner.
* \param depth A depth which the rectangle is rendered at.
*
* \param type Semantics of the attributes "attrib".
* If type is UTIL_BLITTER_ATTRIB_NONE, ignore them.
* If type is UTIL_BLITTER_ATTRIB_COLOR, the attributes
* make up a constant RGBA color, and should go
* to the GENERIC0 varying slot of a fragment shader.
* If type is UTIL_BLITTER_ATTRIB_TEXCOORD, {a1, a2} and
* {a3, a4} specify top-left and bottom-right texture
* coordinates of the rectangle, respectively, and should go
* to the GENERIC0 varying slot of a fragment shader.
*
* \param attrib See type.
*
* \note A driver may optionally override this callback to implement
* a specialized hardware path for drawing a rectangle, e.g. using
* a rectangular point sprite.
*/
void (*draw_rectangle)(struct blitter_context *blitter,
int x1, int y1, int x2, int y2,
float depth,
enum blitter_attrib_type type,
const union pipe_color_union *color);
 
/**
* Get the next surface layer for the pipe surface, i.e. make a copy
* of the surface and increment the first and last layer by 1.
*
* This callback is exposed, so that drivers can override it if needed.
*/
struct pipe_surface *(*get_next_surface_layer)(struct pipe_context *pipe,
struct pipe_surface *surf);
 
/* Whether the blitter is running. */
boolean running;
 
/* Private members, really. */
struct pipe_context *pipe; /**< pipe context */
 
void *saved_blend_state; /**< blend state */
void *saved_dsa_state; /**< depth stencil alpha state */
void *saved_velem_state; /**< vertex elements state */
void *saved_rs_state; /**< rasterizer state */
void *saved_fs, *saved_vs, *saved_gs; /**< shaders */
 
struct pipe_framebuffer_state saved_fb_state; /**< framebuffer state */
struct pipe_stencil_ref saved_stencil_ref; /**< stencil ref */
struct pipe_viewport_state saved_viewport;
struct pipe_scissor_state saved_scissor;
boolean is_sample_mask_saved;
unsigned saved_sample_mask;
 
unsigned saved_num_sampler_states;
void *saved_sampler_states[PIPE_MAX_SAMPLERS];
 
unsigned saved_num_sampler_views;
struct pipe_sampler_view *saved_sampler_views[PIPE_MAX_SAMPLERS];
 
unsigned vb_slot;
struct pipe_vertex_buffer saved_vertex_buffer;
 
unsigned saved_num_so_targets;
struct pipe_stream_output_target *saved_so_targets[PIPE_MAX_SO_BUFFERS];
 
struct pipe_query *saved_render_cond_query;
uint saved_render_cond_mode;
boolean saved_render_cond_cond;
};
 
/**
* Create a blitter context.
*/
struct blitter_context *util_blitter_create(struct pipe_context *pipe);
 
/**
* Destroy a blitter context.
*/
void util_blitter_destroy(struct blitter_context *blitter);
 
void util_blitter_cache_all_shaders(struct blitter_context *blitter);
 
/**
* Return the pipe context associated with a blitter context.
*/
static INLINE
struct pipe_context *util_blitter_get_pipe(struct blitter_context *blitter)
{
return blitter->pipe;
}
 
/**
* Override PIPE_CAP_TEXTURE_MULTISAMPLE as reported by the driver.
*/
void util_blitter_set_texture_multisample(struct blitter_context *blitter,
boolean supported);
 
/* The default function to draw a rectangle. This can only be used
* inside of the draw_rectangle callback if the driver overrides it. */
void util_blitter_draw_rectangle(struct blitter_context *blitter,
int x1, int y1, int x2, int y2, float depth,
enum blitter_attrib_type type,
const union pipe_color_union *attrib);
 
 
/*
* These states must be saved before any of the following functions are called:
* - vertex buffers
* - vertex elements
* - vertex shader
* - geometry shader (if supported)
* - stream output targets (if supported)
* - rasterizer state
*/
 
/**
* Clear a specified set of currently bound buffers to specified values.
*
* These states must be saved in the blitter in addition to the state objects
* already required to be saved:
* - fragment shader
* - depth stencil alpha state
* - blend state
*/
void util_blitter_clear(struct blitter_context *blitter,
unsigned width, unsigned height,
unsigned clear_buffers,
const union pipe_color_union *color,
double depth, unsigned stencil);
 
/**
* Check if the blitter (with the help of the driver) can blit between
* the two resources.
* The mask is a combination of the PIPE_MASK_* flags.
* Set to PIPE_MASK_RGBAZS if unsure.
*/
boolean util_blitter_is_copy_supported(struct blitter_context *blitter,
const struct pipe_resource *dst,
const struct pipe_resource *src,
unsigned mask);
 
boolean util_blitter_is_blit_supported(struct blitter_context *blitter,
const struct pipe_blit_info *info);
 
/**
* Copy a block of pixels from one surface to another.
*
* These states must be saved in the blitter in addition to the state objects
* already required to be saved:
* - fragment shader
* - depth stencil alpha state
* - blend state
* - fragment sampler states
* - fragment sampler textures
* - framebuffer state
* - sample mask
*/
void util_blitter_copy_texture(struct blitter_context *blitter,
struct pipe_resource *dst,
unsigned dst_level,
unsigned dstx, unsigned dsty, unsigned dstz,
struct pipe_resource *src,
unsigned src_level,
const struct pipe_box *srcbox, unsigned mask,
boolean copy_all_samples);
 
/**
* This is a generic implementation of pipe->blit, which accepts
* sampler/surface views instead of resources.
*
* The layer and mipmap level are specified by the views.
*
* Drivers can use this to change resource properties (like format, width,
* height) by changing how the views interpret them, instead of changing
* pipe_resource directly. This is used to blit resources of formats which
* are not renderable.
*
* src_width0 and src_height0 are sampler_view-private properties that
* override pipe_resource. The blitter uses them for computation of texture
* coordinates. The dst dimensions are supplied through pipe_surface::width
* and height.
*
* The mask is a combination of the PIPE_MASK_* flags.
* Set to PIPE_MASK_RGBAZS if unsure.
*/
void util_blitter_blit_generic(struct blitter_context *blitter,
struct pipe_surface *dst,
const struct pipe_box *dstbox,
struct pipe_sampler_view *src,
const struct pipe_box *srcbox,
unsigned src_width0, unsigned src_height0,
unsigned mask, unsigned filter,
const struct pipe_scissor_state *scissor,
boolean copy_all_samples);
 
void util_blitter_blit(struct blitter_context *blitter,
const struct pipe_blit_info *info);
 
/**
* Helper function to initialize a view for copy_texture_view.
* The parameters must match copy_texture_view.
*/
void util_blitter_default_dst_texture(struct pipe_surface *dst_templ,
struct pipe_resource *dst,
unsigned dstlevel,
unsigned dstz);
 
/**
* Helper function to initialize a view for copy_texture_view.
* The parameters must match copy_texture_view.
*/
void util_blitter_default_src_texture(struct pipe_sampler_view *src_templ,
struct pipe_resource *src,
unsigned srclevel);
 
/**
* Copy data from one buffer to another using the Stream Output functionality.
* 4-byte alignment is required, otherwise software fallback is used.
*/
void util_blitter_copy_buffer(struct blitter_context *blitter,
struct pipe_resource *dst,
unsigned dstx,
struct pipe_resource *src,
unsigned srcx,
unsigned size);
 
/**
* Clear the contents of a buffer using the Stream Output functionality.
* 4-byte alignment is required.
*
* "num_channels" can be 1, 2, 3, or 4, and specifies if the clear value is
* R, RG, RGB, or RGBA.
*
* For each element, only "num_channels" components of "clear_value" are
* copied to the buffer, then the offset is incremented by num_channels*4.
*/
void util_blitter_clear_buffer(struct blitter_context *blitter,
struct pipe_resource *dst,
unsigned offset, unsigned size,
unsigned num_channels,
const union pipe_color_union *clear_value);
 
/**
* Clear a region of a (color) surface to a constant value.
*
* These states must be saved in the blitter in addition to the state objects
* already required to be saved:
* - fragment shader
* - depth stencil alpha state
* - blend state
* - framebuffer state
*/
void util_blitter_clear_render_target(struct blitter_context *blitter,
struct pipe_surface *dst,
const union pipe_color_union *color,
unsigned dstx, unsigned dsty,
unsigned width, unsigned height);
 
/**
* Clear a region of a depth-stencil surface, both stencil and depth
* or only one of them if this is a combined depth-stencil surface.
*
* These states must be saved in the blitter in addition to the state objects
* already required to be saved:
* - fragment shader
* - depth stencil alpha state
* - blend state
* - framebuffer state
*/
void util_blitter_clear_depth_stencil(struct blitter_context *blitter,
struct pipe_surface *dst,
unsigned clear_flags,
double depth,
unsigned stencil,
unsigned dstx, unsigned dsty,
unsigned width, unsigned height);
 
/* The following functions are customized variants of the clear functions.
* Some drivers use them internally to do things like MSAA resolve
* and resource decompression. It usually consists of rendering a full-screen
* quad with a special blend or DSA state.
*/
 
/* Used by r300g for depth decompression. */
void util_blitter_custom_clear_depth(struct blitter_context *blitter,
unsigned width, unsigned height,
double depth, void *custom_dsa);
 
/* Used by r600g for depth decompression. */
void util_blitter_custom_depth_stencil(struct blitter_context *blitter,
struct pipe_surface *zsurf,
struct pipe_surface *cbsurf,
unsigned sample_mask,
void *dsa_stage, float depth);
 
/* Used by r600g for color decompression. */
void util_blitter_custom_color(struct blitter_context *blitter,
struct pipe_surface *dstsurf,
void *custom_blend);
 
/* Used by r600g for MSAA color resolve. */
void util_blitter_custom_resolve_color(struct blitter_context *blitter,
struct pipe_resource *dst,
unsigned dst_level,
unsigned dst_layer,
struct pipe_resource *src,
unsigned src_layer,
unsigned sampled_mask,
void *custom_blend,
enum pipe_format format);
 
/* The functions below should be used to save currently bound constant state
* objects inside a driver. The objects are automatically restored at the end
* of the util_blitter_{clear, copy_region, fill_region} functions and then
* forgotten.
*
* States not listed here are not affected by util_blitter. */
 
static INLINE
void util_blitter_save_blend(struct blitter_context *blitter,
void *state)
{
blitter->saved_blend_state = state;
}
 
static INLINE
void util_blitter_save_depth_stencil_alpha(struct blitter_context *blitter,
void *state)
{
blitter->saved_dsa_state = state;
}
 
static INLINE
void util_blitter_save_vertex_elements(struct blitter_context *blitter,
void *state)
{
blitter->saved_velem_state = state;
}
 
static INLINE
void util_blitter_save_stencil_ref(struct blitter_context *blitter,
const struct pipe_stencil_ref *state)
{
blitter->saved_stencil_ref = *state;
}
 
static INLINE
void util_blitter_save_rasterizer(struct blitter_context *blitter,
void *state)
{
blitter->saved_rs_state = state;
}
 
static INLINE
void util_blitter_save_fragment_shader(struct blitter_context *blitter,
void *fs)
{
blitter->saved_fs = fs;
}
 
static INLINE
void util_blitter_save_vertex_shader(struct blitter_context *blitter,
void *vs)
{
blitter->saved_vs = vs;
}
 
static INLINE
void util_blitter_save_geometry_shader(struct blitter_context *blitter,
void *gs)
{
blitter->saved_gs = gs;
}
 
static INLINE
void util_blitter_save_framebuffer(struct blitter_context *blitter,
const struct pipe_framebuffer_state *state)
{
blitter->saved_fb_state.nr_cbufs = 0; /* It's ~0 now, meaning it's unsaved. */
util_copy_framebuffer_state(&blitter->saved_fb_state, state);
}
 
static INLINE
void util_blitter_save_viewport(struct blitter_context *blitter,
struct pipe_viewport_state *state)
{
blitter->saved_viewport = *state;
}
 
static INLINE
void util_blitter_save_scissor(struct blitter_context *blitter,
struct pipe_scissor_state *state)
{
blitter->saved_scissor = *state;
}
 
static INLINE
void util_blitter_save_fragment_sampler_states(
struct blitter_context *blitter,
unsigned num_sampler_states,
void **sampler_states)
{
assert(num_sampler_states <= Elements(blitter->saved_sampler_states));
 
blitter->saved_num_sampler_states = num_sampler_states;
memcpy(blitter->saved_sampler_states, sampler_states,
num_sampler_states * sizeof(void *));
}
 
static INLINE void
util_blitter_save_fragment_sampler_views(struct blitter_context *blitter,
unsigned num_views,
struct pipe_sampler_view **views)
{
unsigned i;
assert(num_views <= Elements(blitter->saved_sampler_views));
 
blitter->saved_num_sampler_views = num_views;
for (i = 0; i < num_views; i++)
pipe_sampler_view_reference(&blitter->saved_sampler_views[i],
views[i]);
}
 
static INLINE void
util_blitter_save_vertex_buffer_slot(struct blitter_context *blitter,
struct pipe_vertex_buffer *vertex_buffers)
{
pipe_resource_reference(&blitter->saved_vertex_buffer.buffer,
vertex_buffers[blitter->vb_slot].buffer);
memcpy(&blitter->saved_vertex_buffer, &vertex_buffers[blitter->vb_slot],
sizeof(struct pipe_vertex_buffer));
}
 
static INLINE void
util_blitter_save_so_targets(struct blitter_context *blitter,
unsigned num_targets,
struct pipe_stream_output_target **targets)
{
unsigned i;
assert(num_targets <= Elements(blitter->saved_so_targets));
 
blitter->saved_num_so_targets = num_targets;
for (i = 0; i < num_targets; i++)
pipe_so_target_reference(&blitter->saved_so_targets[i],
targets[i]);
}
 
static INLINE void
util_blitter_save_sample_mask(struct blitter_context *blitter,
unsigned sample_mask)
{
blitter->is_sample_mask_saved = TRUE;
blitter->saved_sample_mask = sample_mask;
}
 
static INLINE void
util_blitter_save_render_condition(struct blitter_context *blitter,
struct pipe_query *query,
boolean condition,
uint mode)
{
blitter->saved_render_cond_query = query;
blitter->saved_render_cond_mode = mode;
blitter->saved_render_cond_cond = condition;
}
 
#ifdef __cplusplus
}
#endif
 
#endif
/drivers/video/Gallium/auxiliary/util/u_box.h
0,0 → 1,80
#ifndef UTIL_BOX_INLINES_H
#define UTIL_BOX_INLINES_H
 
#include "pipe/p_state.h"
 
static INLINE
void u_box_1d( unsigned x,
unsigned w,
struct pipe_box *box )
{
box->x = x;
box->y = 0;
box->z = 0;
box->width = w;
box->height = 1;
box->depth = 1;
}
 
static INLINE
void u_box_2d( unsigned x,
unsigned y,
unsigned w,
unsigned h,
struct pipe_box *box )
{
box->x = x;
box->y = y;
box->z = 0;
box->width = w;
box->height = h;
box->depth = 1;
}
 
static INLINE
void u_box_origin_2d( unsigned w,
unsigned h,
struct pipe_box *box )
{
box->x = 0;
box->y = 0;
box->z = 0;
box->width = w;
box->height = h;
box->depth = 1;
}
 
static INLINE
void u_box_2d_zslice( unsigned x,
unsigned y,
unsigned z,
unsigned w,
unsigned h,
struct pipe_box *box )
{
box->x = x;
box->y = y;
box->z = z;
box->width = w;
box->height = h;
box->depth = 1;
}
 
static INLINE
void u_box_3d( unsigned x,
unsigned y,
unsigned z,
unsigned w,
unsigned h,
unsigned d,
struct pipe_box *box )
{
box->x = x;
box->y = y;
box->z = z;
box->width = w;
box->height = h;
box->depth = d;
}
 
#endif
/drivers/video/Gallium/auxiliary/util/u_cache.c
0,0 → 1,351
/**************************************************************************
*
* Copyright 2008 VMware, Inc.
* 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 VMWARE 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
* Improved cache implementation.
*
* Fixed size array with linear probing on collision and LRU eviction
* on full.
*
* @author Jose Fonseca <jfonseca@vmware.com>
*/
 
 
#include "pipe/p_compiler.h"
#include "util/u_debug.h"
 
#include "util/u_math.h"
#include "util/u_memory.h"
#include "util/u_cache.h"
#include "util/u_simple_list.h"
 
 
struct util_cache_entry
{
enum { EMPTY = 0, FILLED, DELETED } state;
uint32_t hash;
 
struct util_cache_entry *next;
struct util_cache_entry *prev;
 
void *key;
void *value;
#ifdef DEBUG
unsigned count;
#endif
};
 
 
struct util_cache
{
/** Hash function */
uint32_t (*hash)(const void *key);
/** Compare two keys */
int (*compare)(const void *key1, const void *key2);
 
/** Destroy a (key, value) pair */
void (*destroy)(void *key, void *value);
 
uint32_t size;
struct util_cache_entry *entries;
unsigned count;
struct util_cache_entry lru;
};
 
static void
ensure_sanity(const struct util_cache *cache);
 
#define CACHE_DEFAULT_ALPHA 2
 
struct util_cache *
util_cache_create(uint32_t (*hash)(const void *key),
int (*compare)(const void *key1, const void *key2),
void (*destroy)(void *key, void *value),
uint32_t size)
{
struct util_cache *cache;
cache = CALLOC_STRUCT(util_cache);
if(!cache)
return NULL;
cache->hash = hash;
cache->compare = compare;
cache->destroy = destroy;
 
make_empty_list(&cache->lru);
 
size *= CACHE_DEFAULT_ALPHA;
cache->size = size;
cache->entries = CALLOC(size, sizeof(struct util_cache_entry));
if(!cache->entries) {
FREE(cache);
return NULL;
}
ensure_sanity(cache);
return cache;
}
 
 
static struct util_cache_entry *
util_cache_entry_get(struct util_cache *cache,
uint32_t hash,
const void *key)
{
struct util_cache_entry *first_unfilled = NULL;
uint32_t index = hash % cache->size;
uint32_t probe;
 
/* Probe until we find either a matching FILLED entry or an EMPTY
* slot (which has never been occupied).
*
* Deleted or non-matching slots are not indicative of completion
* as a previous linear probe for the same key could have continued
* past this point.
*/
for (probe = 0; probe < cache->size; probe++) {
uint32_t i = (index + probe) % cache->size;
struct util_cache_entry *current = &cache->entries[i];
 
if (current->state == FILLED) {
if (current->hash == hash &&
cache->compare(key, current->key) == 0)
return current;
}
else {
if (!first_unfilled)
first_unfilled = current;
 
if (current->state == EMPTY)
return first_unfilled;
}
}
 
return NULL;
}
 
static INLINE void
util_cache_entry_destroy(struct util_cache *cache,
struct util_cache_entry *entry)
{
void *key = entry->key;
void *value = entry->value;
entry->key = NULL;
entry->value = NULL;
if (entry->state == FILLED) {
remove_from_list(entry);
cache->count--;
 
if(cache->destroy)
cache->destroy(key, value);
 
entry->state = DELETED;
}
}
 
 
void
util_cache_set(struct util_cache *cache,
void *key,
void *value)
{
struct util_cache_entry *entry;
uint32_t hash;
 
assert(cache);
if (!cache)
return;
hash = cache->hash(key);
entry = util_cache_entry_get(cache, hash, key);
if (!entry)
entry = cache->lru.prev;
 
if (cache->count >= cache->size / CACHE_DEFAULT_ALPHA)
util_cache_entry_destroy(cache, cache->lru.prev);
 
util_cache_entry_destroy(cache, entry);
#ifdef DEBUG
++entry->count;
#endif
entry->key = key;
entry->hash = hash;
entry->value = value;
entry->state = FILLED;
insert_at_head(&cache->lru, entry);
cache->count++;
 
ensure_sanity(cache);
}
 
 
void *
util_cache_get(struct util_cache *cache,
const void *key)
{
struct util_cache_entry *entry;
uint32_t hash;
 
assert(cache);
if (!cache)
return NULL;
hash = cache->hash(key);
entry = util_cache_entry_get(cache, hash, key);
if (!entry)
return NULL;
 
if (entry->state == FILLED)
move_to_head(&cache->lru, entry);
return entry->value;
}
 
 
void
util_cache_clear(struct util_cache *cache)
{
uint32_t i;
 
assert(cache);
if (!cache)
return;
 
for(i = 0; i < cache->size; ++i) {
util_cache_entry_destroy(cache, &cache->entries[i]);
cache->entries[i].state = EMPTY;
}
 
assert(cache->count == 0);
assert(is_empty_list(&cache->lru));
ensure_sanity(cache);
}
 
 
void
util_cache_destroy(struct util_cache *cache)
{
assert(cache);
if (!cache)
return;
 
#ifdef DEBUG
if(cache->count >= 20*cache->size) {
/* Normal approximation of the Poisson distribution */
double mean = (double)cache->count/(double)cache->size;
double stddev = sqrt(mean);
unsigned i;
for(i = 0; i < cache->size; ++i) {
double z = fabs(cache->entries[i].count - mean)/stddev;
/* This assert should not fail 99.9999998027% of the times, unless
* the hash function is a poor one */
assert(z <= 6.0);
}
}
#endif
util_cache_clear(cache);
FREE(cache->entries);
FREE(cache);
}
 
 
void
util_cache_remove(struct util_cache *cache,
const void *key)
{
struct util_cache_entry *entry;
uint32_t hash;
 
assert(cache);
if (!cache)
return;
 
hash = cache->hash(key);
 
entry = util_cache_entry_get(cache, hash, key);
if (!entry)
return;
 
if (entry->state == FILLED)
util_cache_entry_destroy(cache, entry);
 
ensure_sanity(cache);
}
 
 
static void
ensure_sanity(const struct util_cache *cache)
{
#ifdef DEBUG
unsigned i, cnt = 0;
 
assert(cache);
for (i = 0; i < cache->size; i++) {
struct util_cache_entry *header = &cache->entries[i];
 
assert(header);
assert(header->state == FILLED ||
header->state == EMPTY ||
header->state == DELETED);
if (header->state == FILLED) {
cnt++;
assert(header->hash == cache->hash(header->key));
}
}
 
assert(cnt == cache->count);
assert(cache->size >= cnt);
 
if (cache->count == 0) {
assert (is_empty_list(&cache->lru));
}
else {
struct util_cache_entry *header = cache->lru.next;
 
assert (header);
assert (!is_empty_list(&cache->lru));
 
for (i = 0; i < cache->count; i++)
header = header->next;
 
assert(header == &cache->lru);
}
#endif
 
(void)cache;
}
/drivers/video/Gallium/auxiliary/util/u_cache.h
0,0 → 1,91
/**************************************************************************
*
* Copyright 2008 VMware, Inc.
* 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 VMWARE 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
* Simple cache.
*
* @author Jose Fonseca <jfonseca@vmware.com>
*/
 
#ifndef U_CACHE_H_
#define U_CACHE_H_
 
 
#include "pipe/p_compiler.h"
 
 
#ifdef __cplusplus
extern "C" {
#endif
 
/**
* Least Recently Used (LRU) cache.
*/
struct util_cache;
 
 
/**
* Create a cache.
*
* @param hash hash function
* @param compare should return 0 for two equal keys
* @param destroy destruction callback (optional)
* @param size maximum number of entries
*/
struct util_cache *
util_cache_create(uint32_t (*hash)(const void *key),
int (*compare)(const void *key1, const void *key2),
void (*destroy)(void *key, void *value),
uint32_t size);
 
void
util_cache_set(struct util_cache *cache,
void *key,
void *value);
 
void *
util_cache_get(struct util_cache *cache,
const void *key);
 
void
util_cache_clear(struct util_cache *cache);
 
void
util_cache_destroy(struct util_cache *cache);
 
void
util_cache_remove(struct util_cache *cache,
const void *key);
 
 
#ifdef __cplusplus
}
#endif
 
#endif /* U_CACHE_H_ */
/drivers/video/Gallium/auxiliary/util/u_caps.c
0,0 → 1,269
/**************************************************************************
*
* Copyright 2010 Vmware, Inc.
* 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 VMWARE 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.
*
**************************************************************************/
 
#include "pipe/p_screen.h"
#include "util/u_format.h"
#include "util/u_debug.h"
#include "u_caps.h"
 
/**
* Iterates over a list of caps checks as defined in u_caps.h. Should
* all checks pass returns TRUE and out is set to the last element of
* the list (TERMINATE). Should any check fail returns FALSE and set
* out to the index of the start of the first failing check.
*/
boolean
util_check_caps_out(struct pipe_screen *screen, const unsigned *list, int *out)
{
int i, tmpi;
float tmpf;
 
for (i = 0; list[i];) {
switch(list[i++]) {
case UTIL_CAPS_CHECK_CAP:
if (!screen->get_param(screen, list[i++])) {
*out = i - 2;
return FALSE;
}
break;
case UTIL_CAPS_CHECK_INT:
tmpi = screen->get_param(screen, list[i++]);
if (tmpi < (int)list[i++]) {
*out = i - 3;
return FALSE;
}
break;
case UTIL_CAPS_CHECK_FLOAT:
tmpf = screen->get_paramf(screen, list[i++]);
if (tmpf < (float)list[i++]) {
*out = i - 3;
return FALSE;
}
break;
case UTIL_CAPS_CHECK_FORMAT:
if (!screen->is_format_supported(screen,
list[i++],
PIPE_TEXTURE_2D,
0,
PIPE_BIND_SAMPLER_VIEW)) {
*out = i - 2;
return FALSE;
}
break;
case UTIL_CAPS_CHECK_SHADER:
tmpi = screen->get_shader_param(screen, list[i] >> 24, list[i] & ((1 << 24) - 1));
++i;
if (tmpi < (int)list[i++]) {
*out = i - 3;
return FALSE;
}
break;
case UTIL_CAPS_CHECK_UNIMPLEMENTED:
*out = i - 1;
return FALSE;
default:
assert(!"Unsupported check");
return FALSE;
}
}
 
*out = i;
return TRUE;
}
 
/**
* Iterates over a list of caps checks as defined in u_caps.h.
* Returns TRUE if all caps checks pass returns FALSE otherwise.
*/
boolean
util_check_caps(struct pipe_screen *screen, const unsigned *list)
{
int out;
return util_check_caps_out(screen, list, &out);
}
 
 
/*
* Below follows some demo lists.
*
* None of these lists are exhausting lists of what is
* actually needed to support said API and more here for
* as example on how to uses the above functions. Especially
* for DX10 and DX11 where Gallium is missing features.
*/
 
/* DX 9_1 */
static unsigned caps_dx_9_1[] = {
UTIL_CHECK_INT(MAX_RENDER_TARGETS, 1),
UTIL_CHECK_INT(MAX_TEXTURE_2D_LEVELS, 12), /* 2048 */
UTIL_CHECK_INT(MAX_TEXTURE_3D_LEVELS, 9), /* 256 */
UTIL_CHECK_INT(MAX_TEXTURE_CUBE_LEVELS, 10), /* 512 */
UTIL_CHECK_FLOAT(MAX_TEXTURE_ANISOTROPY, 2),
UTIL_CHECK_TERMINATE
};
 
/* DX 9_2 */
static unsigned caps_dx_9_2[] = {
UTIL_CHECK_CAP(OCCLUSION_QUERY),
UTIL_CHECK_CAP(BLEND_EQUATION_SEPARATE),
UTIL_CHECK_INT(MAX_RENDER_TARGETS, 1),
UTIL_CHECK_INT(MAX_TEXTURE_2D_LEVELS, 12), /* 2048 */
UTIL_CHECK_INT(MAX_TEXTURE_3D_LEVELS, 9), /* 256 */
UTIL_CHECK_INT(MAX_TEXTURE_CUBE_LEVELS, 10), /* 512 */
UTIL_CHECK_FLOAT(MAX_TEXTURE_ANISOTROPY, 16),
UTIL_CHECK_TERMINATE
};
 
/* DX 9_3 */
static unsigned caps_dx_9_3[] = {
UTIL_CHECK_CAP(SM3),
//UTIL_CHECK_CAP(INSTANCING),
UTIL_CHECK_CAP(OCCLUSION_QUERY),
UTIL_CHECK_INT(MAX_RENDER_TARGETS, 4),
UTIL_CHECK_INT(MAX_TEXTURE_2D_LEVELS, 13), /* 4096 */
UTIL_CHECK_INT(MAX_TEXTURE_3D_LEVELS, 9), /* 256 */
UTIL_CHECK_INT(MAX_TEXTURE_CUBE_LEVELS, 10), /* 512 */
UTIL_CHECK_FLOAT(MAX_TEXTURE_ANISOTROPY, 16),
UTIL_CHECK_TERMINATE
};
 
/* DX 10 */
static unsigned caps_dx_10[] = {
UTIL_CHECK_CAP(SM3),
//UTIL_CHECK_CAP(INSTANCING),
UTIL_CHECK_CAP(OCCLUSION_QUERY),
UTIL_CHECK_INT(MAX_RENDER_TARGETS, 8),
UTIL_CHECK_INT(MAX_TEXTURE_2D_LEVELS, 14), /* 8192 */
UTIL_CHECK_INT(MAX_TEXTURE_3D_LEVELS, 12), /* 2048 */
UTIL_CHECK_INT(MAX_TEXTURE_CUBE_LEVELS, 14), /* 8192 */
UTIL_CHECK_FLOAT(MAX_TEXTURE_ANISOTROPY, 16),
UTIL_CHECK_UNIMPLEMENTED, /* XXX Unimplemented features in Gallium */
UTIL_CHECK_TERMINATE
};
 
/* DX11 */
static unsigned caps_dx_11[] = {
UTIL_CHECK_CAP(SM3),
//UTIL_CHECK_CAP(INSTANCING),
UTIL_CHECK_CAP(OCCLUSION_QUERY),
UTIL_CHECK_INT(MAX_RENDER_TARGETS, 8),
UTIL_CHECK_INT(MAX_TEXTURE_2D_LEVELS, 14), /* 16384 */
UTIL_CHECK_INT(MAX_TEXTURE_3D_LEVELS, 12), /* 2048 */
UTIL_CHECK_INT(MAX_TEXTURE_CUBE_LEVELS, 14), /* 16384 */
UTIL_CHECK_FLOAT(MAX_TEXTURE_ANISOTROPY, 16),
UTIL_CHECK_FORMAT(B8G8R8A8_UNORM),
UTIL_CHECK_UNIMPLEMENTED, /* XXX Unimplemented features in Gallium */
UTIL_CHECK_TERMINATE
};
 
/* OpenGL 2.1 */
static unsigned caps_opengl_2_1[] = {
UTIL_CHECK_CAP(OCCLUSION_QUERY),
UTIL_CHECK_CAP(TWO_SIDED_STENCIL),
UTIL_CHECK_CAP(BLEND_EQUATION_SEPARATE),
UTIL_CHECK_INT(MAX_RENDER_TARGETS, 2),
UTIL_CHECK_TERMINATE
};
 
/* OpenGL 3.0 */
/* UTIL_CHECK_INT(MAX_RENDER_TARGETS, 8), */
 
/* Shader Model 3 */
static unsigned caps_sm3[] = {
UTIL_CHECK_SHADER(FRAGMENT, MAX_INSTRUCTIONS, 512),
UTIL_CHECK_SHADER(FRAGMENT, MAX_INPUTS, 10),
UTIL_CHECK_SHADER(FRAGMENT, MAX_TEMPS, 32),
UTIL_CHECK_SHADER(FRAGMENT, MAX_ADDRS, 1),
UTIL_CHECK_SHADER(FRAGMENT, MAX_CONSTS, 224),
 
UTIL_CHECK_SHADER(VERTEX, MAX_INSTRUCTIONS, 512),
UTIL_CHECK_SHADER(VERTEX, MAX_INPUTS, 16),
UTIL_CHECK_SHADER(VERTEX, MAX_TEMPS, 32),
UTIL_CHECK_SHADER(VERTEX, MAX_ADDRS, 2),
UTIL_CHECK_SHADER(VERTEX, MAX_CONSTS, 256),
 
UTIL_CHECK_TERMINATE
};
 
/**
* Demo function which checks against theoretical caps needed for different APIs.
*/
void util_caps_demo_print(struct pipe_screen *screen)
{
struct {
char* name;
unsigned *list;
} list[] = {
{"DX 9.1", caps_dx_9_1},
{"DX 9.2", caps_dx_9_2},
{"DX 9.3", caps_dx_9_3},
{"DX 10", caps_dx_10},
{"DX 11", caps_dx_11},
{"OpenGL 2.1", caps_opengl_2_1},
/* {"OpenGL 3.0", caps_opengl_3_0},*/
{"SM3", caps_sm3},
{NULL, NULL}
};
int i, out = 0;
 
for (i = 0; list[i].name; i++) {
if (util_check_caps_out(screen, list[i].list, &out)) {
debug_printf("%s: %s yes\n", __FUNCTION__, list[i].name);
continue;
}
switch (list[i].list[out]) {
case UTIL_CAPS_CHECK_CAP:
debug_printf("%s: %s no (cap %u not supported)\n", __FUNCTION__,
list[i].name,
list[i].list[out + 1]);
break;
case UTIL_CAPS_CHECK_INT:
debug_printf("%s: %s no (cap %u less then %u)\n", __FUNCTION__,
list[i].name,
list[i].list[out + 1],
list[i].list[out + 2]);
break;
case UTIL_CAPS_CHECK_FLOAT:
debug_printf("%s: %s no (cap %u less then %f)\n", __FUNCTION__,
list[i].name,
list[i].list[out + 1],
(double)(int)list[i].list[out + 2]);
break;
case UTIL_CAPS_CHECK_FORMAT:
debug_printf("%s: %s no (format %s not supported)\n", __FUNCTION__,
list[i].name,
util_format_name(list[i].list[out + 1]) + 12);
break;
case UTIL_CAPS_CHECK_UNIMPLEMENTED:
debug_printf("%s: %s no (not implemented in gallium or state tracker)\n",
__FUNCTION__, list[i].name);
break;
default:
assert(!"Unsupported check");
}
}
}
/drivers/video/Gallium/auxiliary/util/u_caps.h
0,0 → 1,71
/**************************************************************************
*
* Copyright 2010 Vmware, Inc.
* 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 VMWARE 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.
*
**************************************************************************/
 
#ifndef U_CAPS_H
#define U_CAPS_H
 
#include "pipe/p_compiler.h"
 
struct pipe_screen;
 
enum u_caps_check_enum {
UTIL_CAPS_CHECK_TERMINATE = 0,
UTIL_CAPS_CHECK_CAP,
UTIL_CAPS_CHECK_INT,
UTIL_CAPS_CHECK_FLOAT,
UTIL_CAPS_CHECK_FORMAT,
UTIL_CAPS_CHECK_SHADER,
UTIL_CAPS_CHECK_UNIMPLEMENTED,
};
 
#define UTIL_CHECK_CAP(cap) \
UTIL_CAPS_CHECK_CAP, PIPE_CAP_##cap
 
#define UTIL_CHECK_INT(cap, higher) \
UTIL_CAPS_CHECK_INT, PIPE_CAP_##cap, (unsigned)(higher)
 
/* Floats currently lose precision */
#define UTIL_CHECK_FLOAT(cap, higher) \
UTIL_CAPS_CHECK_FLOAT, PIPE_CAPF_##cap, (unsigned)(int)(higher)
 
#define UTIL_CHECK_FORMAT(format) \
UTIL_CAPS_CHECK_FORMAT, PIPE_FORMAT_##format
 
#define UTIL_CHECK_SHADER(shader, cap, higher) \
UTIL_CAPS_CHECK_SHADER, (PIPE_SHADER_##shader << 24) | PIPE_SHADER_CAP_##cap, (unsigned)(higher)
 
#define UTIL_CHECK_UNIMPLEMENTED \
UTIL_CAPS_CHECK_UNIMPLEMENTED
 
#define UTIL_CHECK_TERMINATE \
UTIL_CAPS_CHECK_TERMINATE
 
boolean util_check_caps(struct pipe_screen *screen, const unsigned *list);
boolean util_check_caps_out(struct pipe_screen *screen, const unsigned *list, int *out);
void util_caps_demo_print(struct pipe_screen *screen);
 
#endif
/drivers/video/Gallium/auxiliary/util/u_clear.h
0,0 → 1,59
/**************************************************************************
*
* Copyright 2009 VMware, Inc. 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.
*
**************************************************************************/
 
/* Authors:
* Michel Dänzer
*/
 
 
#include "pipe/p_context.h"
#include "pipe/p_state.h"
 
 
/**
* Clear the given buffers to the specified values.
* No masking, no scissor (clear entire buffer).
*/
static INLINE void
util_clear(struct pipe_context *pipe,
struct pipe_framebuffer_state *framebuffer, unsigned buffers,
const union pipe_color_union *color, double depth, unsigned stencil)
{
if (buffers & PIPE_CLEAR_COLOR) {
unsigned i;
for (i = 0; i < framebuffer->nr_cbufs; i++) {
struct pipe_surface *ps = framebuffer->cbufs[i];
pipe->clear_render_target(pipe, ps, color, 0, 0, ps->width, ps->height);
}
}
 
if (buffers & PIPE_CLEAR_DEPTHSTENCIL) {
struct pipe_surface *ps = framebuffer->zsbuf;
pipe->clear_depth_stencil(pipe, ps, buffers & PIPE_CLEAR_DEPTHSTENCIL,
depth, stencil,
0, 0, ps->width, ps->height);
}
}
/drivers/video/Gallium/auxiliary/util/u_cpu_detect.c
0,0 → 1,355
/**************************************************************************
*
* Copyright 2008 Dennis Smit
* 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
* on 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
* AUTHORS, COPYRIGHT HOLDERS, AND/OR THEIR 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
* CPU feature detection.
*
* @author Dennis Smit
* @author Based on the work of Eric Anholt <anholt@FreeBSD.org>
*/
 
#include "pipe/p_config.h"
 
#include "u_debug.h"
#include "u_cpu_detect.h"
 
#if defined(PIPE_ARCH_PPC)
#if defined(PIPE_OS_APPLE)
#include <sys/sysctl.h>
#else
#include <signal.h>
#include <setjmp.h>
#endif
#endif
 
#if defined(PIPE_OS_NETBSD) || defined(PIPE_OS_OPENBSD)
#include <sys/param.h>
#include <sys/sysctl.h>
#include <machine/cpu.h>
#endif
 
#if defined(PIPE_OS_FREEBSD)
#include <sys/types.h>
#include <sys/sysctl.h>
#endif
 
#if defined(PIPE_OS_LINUX)
#include <signal.h>
#endif
 
#ifdef PIPE_OS_UNIX
#include <unistd.h>
#endif
 
#if defined(PIPE_OS_WINDOWS)
#include <windows.h>
#if defined(MSVC)
#include <intrin.h>
#endif
#endif
 
 
#ifdef DEBUG
DEBUG_GET_ONCE_BOOL_OPTION(dump_cpu, "GALLIUM_DUMP_CPU", FALSE)
#endif
 
 
struct util_cpu_caps util_cpu_caps;
 
#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
static int has_cpuid(void);
#endif
 
 
#if defined(PIPE_ARCH_PPC) && !defined(PIPE_OS_APPLE)
static jmp_buf __lv_powerpc_jmpbuf;
static volatile sig_atomic_t __lv_powerpc_canjump = 0;
 
static void
sigill_handler(int sig)
{
if (!__lv_powerpc_canjump) {
signal (sig, SIG_DFL);
raise (sig);
}
 
__lv_powerpc_canjump = 0;
longjmp(__lv_powerpc_jmpbuf, 1);
}
#endif
 
#if defined(PIPE_ARCH_PPC)
static void
check_os_altivec_support(void)
{
#if defined(PIPE_OS_APPLE)
int sels[2] = {CTL_HW, HW_VECTORUNIT};
int has_vu = 0;
int len = sizeof (has_vu);
int err;
 
err = sysctl(sels, 2, &has_vu, &len, NULL, 0);
 
if (err == 0) {
if (has_vu != 0) {
util_cpu_caps.has_altivec = 1;
}
}
#else /* !PIPE_OS_APPLE */
/* not on Apple/Darwin, do it the brute-force way */
/* this is borrowed from the libmpeg2 library */
signal(SIGILL, sigill_handler);
if (setjmp(__lv_powerpc_jmpbuf)) {
signal(SIGILL, SIG_DFL);
} else {
__lv_powerpc_canjump = 1;
 
__asm __volatile
("mtspr 256, %0\n\t"
"vand %%v0, %%v0, %%v0"
:
: "r" (-1));
 
signal(SIGILL, SIG_DFL);
util_cpu_caps.has_altivec = 1;
}
#endif /* !PIPE_OS_APPLE */
}
#endif /* PIPE_ARCH_PPC */
 
 
#if defined(PIPE_ARCH_X86) || defined (PIPE_ARCH_X86_64)
static int has_cpuid(void)
{
#if defined(PIPE_ARCH_X86)
#if defined(PIPE_OS_GCC)
int a, c;
 
__asm __volatile
("pushf\n"
"popl %0\n"
"movl %0, %1\n"
"xorl $0x200000, %0\n"
"push %0\n"
"popf\n"
"pushf\n"
"popl %0\n"
: "=a" (a), "=c" (c)
:
: "cc");
 
return a != c;
#else
/* FIXME */
return 1;
#endif
#elif defined(PIPE_ARCH_X86_64)
return 1;
#else
return 0;
#endif
}
 
 
/**
* @sa cpuid.h included in gcc-4.3 onwards.
* @sa http://msdn.microsoft.com/en-us/library/hskdteyh.aspx
*/
static INLINE void
cpuid(uint32_t ax, uint32_t *p)
{
#if (defined(PIPE_CC_GCC) || defined(PIPE_CC_SUNPRO)) && defined(PIPE_ARCH_X86)
__asm __volatile (
"xchgl %%ebx, %1\n\t"
"cpuid\n\t"
"xchgl %%ebx, %1"
: "=a" (p[0]),
"=S" (p[1]),
"=c" (p[2]),
"=d" (p[3])
: "0" (ax)
);
#elif (defined(PIPE_CC_GCC) || defined(PIPE_CC_SUNPRO)) && defined(PIPE_ARCH_X86_64)
__asm __volatile (
"cpuid\n\t"
: "=a" (p[0]),
"=b" (p[1]),
"=c" (p[2]),
"=d" (p[3])
: "0" (ax)
);
#elif defined(PIPE_CC_MSVC)
__cpuid(p, ax);
#else
p[0] = 0;
p[1] = 0;
p[2] = 0;
p[3] = 0;
#endif
}
#endif /* X86 or X86_64 */
 
void
util_cpu_detect(void)
{
static boolean util_cpu_detect_initialized = FALSE;
 
if(util_cpu_detect_initialized)
return;
 
memset(&util_cpu_caps, 0, sizeof util_cpu_caps);
 
/* Count the number of CPUs in system */
#if defined(PIPE_OS_WINDOWS)
{
SYSTEM_INFO system_info;
GetSystemInfo(&system_info);
util_cpu_caps.nr_cpus = system_info.dwNumberOfProcessors;
}
#elif defined(PIPE_OS_UNIX) && defined(_SC_NPROCESSORS_ONLN)
util_cpu_caps.nr_cpus = sysconf(_SC_NPROCESSORS_ONLN);
if (util_cpu_caps.nr_cpus == -1)
util_cpu_caps.nr_cpus = 1;
#elif defined(PIPE_OS_BSD)
{
int mib[2], ncpu;
int len;
 
mib[0] = CTL_HW;
mib[1] = HW_NCPU;
 
len = sizeof (ncpu);
sysctl(mib, 2, &ncpu, &len, NULL, 0);
util_cpu_caps.nr_cpus = ncpu;
}
#else
util_cpu_caps.nr_cpus = 1;
#endif
 
/* Make the fallback cacheline size nonzero so that it can be
* safely passed to align().
*/
util_cpu_caps.cacheline = sizeof(void *);
 
#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
if (has_cpuid()) {
uint32_t regs[4];
uint32_t regs2[4];
 
util_cpu_caps.cacheline = 32;
 
/* Get max cpuid level */
cpuid(0x00000000, regs);
 
if (regs[0] >= 0x00000001) {
unsigned int cacheline;
 
cpuid (0x00000001, regs2);
 
util_cpu_caps.x86_cpu_type = (regs2[0] >> 8) & 0xf;
if (util_cpu_caps.x86_cpu_type == 0xf)
util_cpu_caps.x86_cpu_type = 8 + ((regs2[0] >> 20) & 255); /* use extended family (P4, IA64) */
 
/* general feature flags */
util_cpu_caps.has_tsc = (regs2[3] >> 4) & 1; /* 0x0000010 */
util_cpu_caps.has_mmx = (regs2[3] >> 23) & 1; /* 0x0800000 */
util_cpu_caps.has_sse = (regs2[3] >> 25) & 1; /* 0x2000000 */
util_cpu_caps.has_sse2 = (regs2[3] >> 26) & 1; /* 0x4000000 */
util_cpu_caps.has_sse3 = (regs2[2] >> 0) & 1; /* 0x0000001 */
util_cpu_caps.has_ssse3 = (regs2[2] >> 9) & 1; /* 0x0000020 */
util_cpu_caps.has_sse4_1 = (regs2[2] >> 19) & 1;
util_cpu_caps.has_sse4_2 = (regs2[2] >> 20) & 1;
util_cpu_caps.has_popcnt = (regs2[2] >> 23) & 1;
util_cpu_caps.has_avx = (regs2[2] >> 28) & 1;
util_cpu_caps.has_f16c = (regs2[2] >> 29) & 1;
util_cpu_caps.has_mmx2 = util_cpu_caps.has_sse; /* SSE cpus supports mmxext too */
 
cacheline = ((regs2[1] >> 8) & 0xFF) * 8;
if (cacheline > 0)
util_cpu_caps.cacheline = cacheline;
}
 
if (regs[1] == 0x756e6547 && regs[2] == 0x6c65746e && regs[3] == 0x49656e69) {
/* GenuineIntel */
util_cpu_caps.has_intel = 1;
}
 
cpuid(0x80000000, regs);
 
if (regs[0] >= 0x80000001) {
 
cpuid(0x80000001, regs2);
 
util_cpu_caps.has_mmx |= (regs2[3] >> 23) & 1;
util_cpu_caps.has_mmx2 |= (regs2[3] >> 22) & 1;
util_cpu_caps.has_3dnow = (regs2[3] >> 31) & 1;
util_cpu_caps.has_3dnow_ext = (regs2[3] >> 30) & 1;
}
 
if (regs[0] >= 0x80000006) {
cpuid(0x80000006, regs2);
util_cpu_caps.cacheline = regs2[2] & 0xFF;
}
 
if (!util_cpu_caps.has_sse) {
util_cpu_caps.has_sse2 = 0;
util_cpu_caps.has_sse3 = 0;
util_cpu_caps.has_ssse3 = 0;
util_cpu_caps.has_sse4_1 = 0;
}
}
#endif /* PIPE_ARCH_X86 || PIPE_ARCH_X86_64 */
 
#if defined(PIPE_ARCH_PPC)
check_os_altivec_support();
#endif /* PIPE_ARCH_PPC */
 
#ifdef DEBUG
if (debug_get_option_dump_cpu()) {
debug_printf("util_cpu_caps.nr_cpus = %u\n", util_cpu_caps.nr_cpus);
 
debug_printf("util_cpu_caps.x86_cpu_type = %u\n", util_cpu_caps.x86_cpu_type);
debug_printf("util_cpu_caps.cacheline = %u\n", util_cpu_caps.cacheline);
 
debug_printf("util_cpu_caps.has_tsc = %u\n", util_cpu_caps.has_tsc);
debug_printf("util_cpu_caps.has_mmx = %u\n", util_cpu_caps.has_mmx);
debug_printf("util_cpu_caps.has_mmx2 = %u\n", util_cpu_caps.has_mmx2);
debug_printf("util_cpu_caps.has_sse = %u\n", util_cpu_caps.has_sse);
debug_printf("util_cpu_caps.has_sse2 = %u\n", util_cpu_caps.has_sse2);
debug_printf("util_cpu_caps.has_sse3 = %u\n", util_cpu_caps.has_sse3);
debug_printf("util_cpu_caps.has_ssse3 = %u\n", util_cpu_caps.has_ssse3);
debug_printf("util_cpu_caps.has_sse4_1 = %u\n", util_cpu_caps.has_sse4_1);
debug_printf("util_cpu_caps.has_sse4_2 = %u\n", util_cpu_caps.has_sse4_2);
debug_printf("util_cpu_caps.has_avx = %u\n", util_cpu_caps.has_avx);
debug_printf("util_cpu_caps.has_3dnow = %u\n", util_cpu_caps.has_3dnow);
debug_printf("util_cpu_caps.has_3dnow_ext = %u\n", util_cpu_caps.has_3dnow_ext);
debug_printf("util_cpu_caps.has_altivec = %u\n", util_cpu_caps.has_altivec);
}
#endif
 
util_cpu_detect_initialized = TRUE;
}
/drivers/video/Gallium/auxiliary/util/u_cpu_detect.h
0,0 → 1,84
/**************************************************************************
*
* Copyright 2008 Dennis Smit
* 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
* on 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
* AUTHORS, COPYRIGHT HOLDERS, AND/OR THEIR 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
* CPU feature detection.
*
* @author Dennis Smit
* @author Based on the work of Eric Anholt <anholt@FreeBSD.org>
*/
 
#ifndef _UTIL_CPU_DETECT_H
#define _UTIL_CPU_DETECT_H
 
 
#include "pipe/p_compiler.h"
#include "pipe/p_config.h"
 
 
#ifdef __cplusplus
extern "C" {
#endif
 
 
struct util_cpu_caps {
unsigned nr_cpus;
 
/* Feature flags */
int x86_cpu_type;
unsigned cacheline;
 
unsigned has_intel:1;
unsigned has_tsc:1;
unsigned has_mmx:1;
unsigned has_mmx2:1;
unsigned has_sse:1;
unsigned has_sse2:1;
unsigned has_sse3:1;
unsigned has_ssse3:1;
unsigned has_sse4_1:1;
unsigned has_sse4_2:1;
unsigned has_popcnt:1;
unsigned has_avx:1;
unsigned has_f16c:1;
unsigned has_3dnow:1;
unsigned has_3dnow_ext:1;
unsigned has_altivec:1;
};
 
extern struct util_cpu_caps
util_cpu_caps;
 
void util_cpu_detect(void);
 
 
#ifdef __cplusplus
}
#endif
 
 
#endif /* _UTIL_CPU_DETECT_H */
/drivers/video/Gallium/auxiliary/util/u_debug.c
0,0 → 1,730
/**************************************************************************
*
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* Copyright (c) 2008 VMware, Inc.
* 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.
*
**************************************************************************/
 
 
#include "pipe/p_config.h"
 
#include "pipe/p_compiler.h"
#include "util/u_debug.h"
#include "pipe/p_format.h"
#include "pipe/p_state.h"
#include "util/u_inlines.h"
#include "util/u_format.h"
#include "util/u_memory.h"
#include "util/u_string.h"
#include "util/u_math.h"
#include "util/u_tile.h"
#include "util/u_prim.h"
#include "util/u_surface.h"
 
#include <stdio.h>
#include <limits.h> /* CHAR_BIT */
#include <ctype.h> /* isalnum */
 
void _debug_vprintf(const char *format, va_list ap)
{
static char buf[4096] = {'\0'};
#if defined(PIPE_OS_WINDOWS) || defined(PIPE_SUBSYSTEM_EMBEDDED)
/* We buffer until we find a newline. */
size_t len = strlen(buf);
int ret = util_vsnprintf(buf + len, sizeof(buf) - len, format, ap);
if(ret > (int)(sizeof(buf) - len - 1) || util_strchr(buf + len, '\n')) {
os_log_message(buf);
buf[0] = '\0';
}
#else
util_vsnprintf(buf, sizeof(buf), format, ap);
os_log_message(buf);
#endif
}
 
 
#ifdef DEBUG
void debug_print_blob( const char *name,
const void *blob,
unsigned size )
{
const unsigned *ublob = (const unsigned *)blob;
unsigned i;
 
debug_printf("%s (%d dwords%s)\n", name, size/4,
size%4 ? "... plus a few bytes" : "");
 
for (i = 0; i < size/4; i++) {
debug_printf("%d:\t%08x\n", i, ublob[i]);
}
}
#endif
 
 
static boolean
debug_get_option_should_print(void)
{
static boolean first = TRUE;
static boolean value = FALSE;
 
if (!first)
return value;
 
/* Oh hey this will call into this function,
* but its cool since we set first to false
*/
first = FALSE;
value = debug_get_bool_option("GALLIUM_PRINT_OPTIONS", FALSE);
/* XXX should we print this option? Currently it wont */
return value;
}
 
const char *
debug_get_option(const char *name, const char *dfault)
{
const char *result;
 
result = os_get_option(name);
if(!result)
result = dfault;
 
if (debug_get_option_should_print())
debug_printf("%s: %s = %s\n", __FUNCTION__, name, result ? result : "(null)");
return result;
}
 
boolean
debug_get_bool_option(const char *name, boolean dfault)
{
const char *str = os_get_option(name);
boolean result;
if(str == NULL)
result = dfault;
else if(!util_strcmp(str, "n"))
result = FALSE;
else if(!util_strcmp(str, "no"))
result = FALSE;
else if(!util_strcmp(str, "0"))
result = FALSE;
else if(!util_strcmp(str, "f"))
result = FALSE;
else if(!util_strcmp(str, "F"))
result = FALSE;
else if(!util_strcmp(str, "false"))
result = FALSE;
else if(!util_strcmp(str, "FALSE"))
result = FALSE;
else
result = TRUE;
 
if (debug_get_option_should_print())
debug_printf("%s: %s = %s\n", __FUNCTION__, name, result ? "TRUE" : "FALSE");
return result;
}
 
 
long
debug_get_num_option(const char *name, long dfault)
{
long result;
const char *str;
str = os_get_option(name);
if(!str)
result = dfault;
else {
long sign;
char c;
c = *str++;
if(c == '-') {
sign = -1;
c = *str++;
}
else {
sign = 1;
}
result = 0;
while('0' <= c && c <= '9') {
result = result*10 + (c - '0');
c = *str++;
}
result *= sign;
}
 
if (debug_get_option_should_print())
debug_printf("%s: %s = %li\n", __FUNCTION__, name, result);
 
return result;
}
 
static boolean str_has_option(const char *str, const char *name)
{
/* Empty string. */
if (!*str) {
return FALSE;
}
 
/* OPTION=all */
if (!util_strcmp(str, "all")) {
return TRUE;
}
 
/* Find 'name' in 'str' surrounded by non-alphanumeric characters. */
{
const char *start = str;
unsigned name_len = strlen(name);
 
/* 'start' is the beginning of the currently-parsed word,
* we increment 'str' each iteration.
* if we find either the end of string or a non-alphanumeric character,
* we compare 'start' up to 'str-1' with 'name'. */
 
while (1) {
if (!*str || !(isalnum(*str) || *str == '_')) {
if (str-start == name_len &&
!memcmp(start, name, name_len)) {
return TRUE;
}
 
if (!*str) {
return FALSE;
}
 
start = str+1;
}
 
str++;
}
}
 
return FALSE;
}
 
unsigned long
debug_get_flags_option(const char *name,
const struct debug_named_value *flags,
unsigned long dfault)
{
unsigned long result;
const char *str;
const struct debug_named_value *orig = flags;
unsigned namealign = 0;
str = os_get_option(name);
if(!str)
result = dfault;
else if (!util_strcmp(str, "help")) {
result = dfault;
_debug_printf("%s: help for %s:\n", __FUNCTION__, name);
for (; flags->name; ++flags)
namealign = MAX2(namealign, strlen(flags->name));
for (flags = orig; flags->name; ++flags)
_debug_printf("| %*s [0x%0*lx]%s%s\n", namealign, flags->name,
(int)sizeof(unsigned long)*CHAR_BIT/4, flags->value,
flags->desc ? " " : "", flags->desc ? flags->desc : "");
}
else {
result = 0;
while( flags->name ) {
if (str_has_option(str, flags->name))
result |= flags->value;
++flags;
}
}
 
if (debug_get_option_should_print()) {
if (str) {
debug_printf("%s: %s = 0x%lx (%s)\n", __FUNCTION__, name, result, str);
} else {
debug_printf("%s: %s = 0x%lx\n", __FUNCTION__, name, result);
}
}
 
return result;
}
 
 
void _debug_assert_fail(const char *expr,
const char *file,
unsigned line,
const char *function)
{
_debug_printf("%s:%u:%s: Assertion `%s' failed.\n", file, line, function, expr);
if (debug_get_bool_option("GALLIUM_ABORT_ON_ASSERT", TRUE))
os_abort();
else
_debug_printf("continuing...\n");
}
 
 
const char *
debug_dump_enum(const struct debug_named_value *names,
unsigned long value)
{
static char rest[64];
while(names->name) {
if(names->value == value)
return names->name;
++names;
}
 
util_snprintf(rest, sizeof(rest), "0x%08lx", value);
return rest;
}
 
 
const char *
debug_dump_enum_noprefix(const struct debug_named_value *names,
const char *prefix,
unsigned long value)
{
static char rest[64];
while(names->name) {
if(names->value == value) {
const char *name = names->name;
while (*name == *prefix) {
name++;
prefix++;
}
return name;
}
++names;
}
 
 
util_snprintf(rest, sizeof(rest), "0x%08lx", value);
return rest;
}
 
 
const char *
debug_dump_flags(const struct debug_named_value *names,
unsigned long value)
{
static char output[4096];
static char rest[256];
int first = 1;
 
output[0] = '\0';
 
while(names->name) {
if((names->value & value) == names->value) {
if (!first)
util_strncat(output, "|", sizeof(output));
else
first = 0;
util_strncat(output, names->name, sizeof(output) - 1);
output[sizeof(output) - 1] = '\0';
value &= ~names->value;
}
++names;
}
if (value) {
if (!first)
util_strncat(output, "|", sizeof(output));
else
first = 0;
util_snprintf(rest, sizeof(rest), "0x%08lx", value);
util_strncat(output, rest, sizeof(output) - 1);
output[sizeof(output) - 1] = '\0';
}
if(first)
return "0";
return output;
}
 
 
#ifdef DEBUG
void debug_print_format(const char *msg, unsigned fmt )
{
debug_printf("%s: %s\n", msg, util_format_name(fmt));
}
#endif
 
 
 
static const struct debug_named_value pipe_prim_names[] = {
#ifdef DEBUG
DEBUG_NAMED_VALUE(PIPE_PRIM_POINTS),
DEBUG_NAMED_VALUE(PIPE_PRIM_LINES),
DEBUG_NAMED_VALUE(PIPE_PRIM_LINE_LOOP),
DEBUG_NAMED_VALUE(PIPE_PRIM_LINE_STRIP),
DEBUG_NAMED_VALUE(PIPE_PRIM_TRIANGLES),
DEBUG_NAMED_VALUE(PIPE_PRIM_TRIANGLE_STRIP),
DEBUG_NAMED_VALUE(PIPE_PRIM_TRIANGLE_FAN),
DEBUG_NAMED_VALUE(PIPE_PRIM_QUADS),
DEBUG_NAMED_VALUE(PIPE_PRIM_QUAD_STRIP),
DEBUG_NAMED_VALUE(PIPE_PRIM_POLYGON),
DEBUG_NAMED_VALUE(PIPE_PRIM_LINES_ADJACENCY),
DEBUG_NAMED_VALUE(PIPE_PRIM_LINE_STRIP_ADJACENCY),
DEBUG_NAMED_VALUE(PIPE_PRIM_TRIANGLES_ADJACENCY),
DEBUG_NAMED_VALUE(PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY),
#endif
DEBUG_NAMED_VALUE_END
};
 
 
const char *u_prim_name( unsigned prim )
{
return debug_dump_enum(pipe_prim_names, prim);
}
 
 
 
#ifdef DEBUG
int fl_indent = 0;
const char* fl_function[1024];
 
int debug_funclog_enter(const char* f, const int line, const char* file)
{
int i;
 
for (i = 0; i < fl_indent; i++)
debug_printf(" ");
debug_printf("%s\n", f);
 
assert(fl_indent < 1023);
fl_function[fl_indent++] = f;
 
return 0;
}
 
void debug_funclog_exit(const char* f, const int line, const char* file)
{
--fl_indent;
assert(fl_indent >= 0);
assert(fl_function[fl_indent] == f);
}
 
void debug_funclog_enter_exit(const char* f, const int line, const char* file)
{
int i;
for (i = 0; i < fl_indent; i++)
debug_printf(" ");
debug_printf("%s\n", f);
}
#endif
 
 
 
#ifdef DEBUG
/**
* Dump an image to .ppm file.
* \param format PIPE_FORMAT_x
* \param cpp bytes per pixel
* \param width width in pixels
* \param height height in pixels
* \param stride row stride in bytes
*/
void debug_dump_image(const char *prefix,
enum pipe_format format, unsigned cpp,
unsigned width, unsigned height,
unsigned stride,
const void *data)
{
/* write a ppm file */
char filename[256];
unsigned char *rgb8;
FILE *f;
 
util_snprintf(filename, sizeof(filename), "%s.ppm", prefix);
 
rgb8 = MALLOC(height * width * 3);
if (!rgb8) {
return;
}
 
util_format_translate(
PIPE_FORMAT_R8G8B8_UNORM,
rgb8, width * 3,
0, 0,
format,
data, stride,
0, 0, width, height);
 
/* Must be opened in binary mode or DOS line ending causes data
* to be read with one byte offset.
*/
f = fopen(filename, "wb");
if (f) {
fprintf(f, "P6\n");
fprintf(f, "# ppm-file created by gallium\n");
fprintf(f, "%i %i\n", width, height);
fprintf(f, "255\n");
fwrite(rgb8, 1, height * width * 3, f);
fclose(f);
}
else {
fprintf(stderr, "Can't open %s for writing\n", filename);
}
 
FREE(rgb8);
}
 
/* FIXME: dump resources, not surfaces... */
void debug_dump_surface(struct pipe_context *pipe,
const char *prefix,
struct pipe_surface *surface)
{
struct pipe_resource *texture;
struct pipe_transfer *transfer;
void *data;
 
if (!surface)
return;
 
/* XXX: this doesn't necessarily work, as the driver may be using
* temporary storage for the surface which hasn't been propagated
* back into the texture. Need to nail down the semantics of views
* and transfers a bit better before we can say if extra work needs
* to be done here:
*/
texture = surface->texture;
 
data = pipe_transfer_map(pipe, texture, surface->u.tex.level,
surface->u.tex.first_layer,
PIPE_TRANSFER_READ,
0, 0, surface->width, surface->height, &transfer);
if(!data)
return;
 
debug_dump_image(prefix,
texture->format,
util_format_get_blocksize(texture->format),
util_format_get_nblocksx(texture->format, surface->width),
util_format_get_nblocksy(texture->format, surface->height),
transfer->stride,
data);
 
pipe->transfer_unmap(pipe, transfer);
}
 
 
void debug_dump_texture(struct pipe_context *pipe,
const char *prefix,
struct pipe_resource *texture)
{
struct pipe_surface *surface, surf_tmpl;
 
if (!texture)
return;
 
/* XXX for now, just dump image for layer=0, level=0 */
u_surface_default_template(&surf_tmpl, texture);
surface = pipe->create_surface(pipe, texture, &surf_tmpl);
if (surface) {
debug_dump_surface(pipe, prefix, surface);
pipe->surface_destroy(pipe, surface);
}
}
 
 
#pragma pack(push,2)
struct bmp_file_header {
uint16_t bfType;
uint32_t bfSize;
uint16_t bfReserved1;
uint16_t bfReserved2;
uint32_t bfOffBits;
};
#pragma pack(pop)
 
struct bmp_info_header {
uint32_t biSize;
int32_t biWidth;
int32_t biHeight;
uint16_t biPlanes;
uint16_t biBitCount;
uint32_t biCompression;
uint32_t biSizeImage;
int32_t biXPelsPerMeter;
int32_t biYPelsPerMeter;
uint32_t biClrUsed;
uint32_t biClrImportant;
};
 
struct bmp_rgb_quad {
uint8_t rgbBlue;
uint8_t rgbGreen;
uint8_t rgbRed;
uint8_t rgbAlpha;
};
 
void
debug_dump_surface_bmp(struct pipe_context *pipe,
const char *filename,
struct pipe_surface *surface)
{
struct pipe_transfer *transfer;
struct pipe_resource *texture = surface->texture;
void *ptr;
 
ptr = pipe_transfer_map(pipe, texture, surface->u.tex.level,
surface->u.tex.first_layer, PIPE_TRANSFER_READ,
0, 0, surface->width, surface->height, &transfer);
 
debug_dump_transfer_bmp(pipe, filename, transfer, ptr);
 
pipe->transfer_unmap(pipe, transfer);
}
 
void
debug_dump_transfer_bmp(struct pipe_context *pipe,
const char *filename,
struct pipe_transfer *transfer, void *ptr)
{
float *rgba;
 
if (!transfer)
goto error1;
 
rgba = MALLOC(transfer->box.width *
transfer->box.height *
transfer->box.depth *
4*sizeof(float));
if(!rgba)
goto error1;
 
pipe_get_tile_rgba(transfer, ptr, 0, 0,
transfer->box.width, transfer->box.height,
rgba);
 
debug_dump_float_rgba_bmp(filename,
transfer->box.width, transfer->box.height,
rgba, transfer->box.width);
 
FREE(rgba);
error1:
;
}
 
void
debug_dump_float_rgba_bmp(const char *filename,
unsigned width, unsigned height,
float *rgba, unsigned stride)
{
FILE *stream;
struct bmp_file_header bmfh;
struct bmp_info_header bmih;
unsigned x, y;
 
if(!rgba)
goto error1;
 
bmfh.bfType = 0x4d42;
bmfh.bfSize = 14 + 40 + height*width*4;
bmfh.bfReserved1 = 0;
bmfh.bfReserved2 = 0;
bmfh.bfOffBits = 14 + 40;
 
bmih.biSize = 40;
bmih.biWidth = width;
bmih.biHeight = height;
bmih.biPlanes = 1;
bmih.biBitCount = 32;
bmih.biCompression = 0;
bmih.biSizeImage = height*width*4;
bmih.biXPelsPerMeter = 0;
bmih.biYPelsPerMeter = 0;
bmih.biClrUsed = 0;
bmih.biClrImportant = 0;
 
stream = fopen(filename, "wb");
if(!stream)
goto error1;
 
fwrite(&bmfh, 14, 1, stream);
fwrite(&bmih, 40, 1, stream);
 
y = height;
while(y--) {
float *ptr = rgba + (stride * y * 4);
for(x = 0; x < width; ++x)
{
struct bmp_rgb_quad pixel;
pixel.rgbRed = float_to_ubyte(ptr[x*4 + 0]);
pixel.rgbGreen = float_to_ubyte(ptr[x*4 + 1]);
pixel.rgbBlue = float_to_ubyte(ptr[x*4 + 2]);
pixel.rgbAlpha = float_to_ubyte(ptr[x*4 + 3]);
fwrite(&pixel, 1, 4, stream);
}
}
 
fclose(stream);
error1:
;
}
 
 
/**
* Print PIPE_TRANSFER_x flags with a message.
*/
void
debug_print_transfer_flags(const char *msg, unsigned usage)
{
#define FLAG(x) { x, #x }
static const struct {
unsigned bit;
const char *name;
} flags[] = {
FLAG(PIPE_TRANSFER_READ),
FLAG(PIPE_TRANSFER_WRITE),
FLAG(PIPE_TRANSFER_MAP_DIRECTLY),
FLAG(PIPE_TRANSFER_DISCARD_RANGE),
FLAG(PIPE_TRANSFER_DONTBLOCK),
FLAG(PIPE_TRANSFER_UNSYNCHRONIZED),
FLAG(PIPE_TRANSFER_FLUSH_EXPLICIT),
FLAG(PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE)
};
unsigned i;
 
debug_printf("%s ", msg);
 
for (i = 0; i < Elements(flags); i++) {
if (usage & flags[i].bit) {
debug_printf("%s", flags[i].name);
usage &= ~flags[i].bit;
if (usage) {
debug_printf(" | ");
}
}
}
 
debug_printf("\n");
#undef FLAG
}
 
 
 
#endif
/drivers/video/Gallium/auxiliary/util/u_debug.h
0,0 → 1,459
/**************************************************************************
*
* 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
* Cross-platform debugging helpers.
*
* For now it just has assert and printf replacements, but it might be extended
* with stack trace reports and more advanced logging in the near future.
*
* @author Jose Fonseca <jrfonseca@tungstengraphics.com>
*/
 
#ifndef U_DEBUG_H_
#define U_DEBUG_H_
 
 
#include "os/os_misc.h"
 
#include "pipe/p_format.h"
 
 
#ifdef __cplusplus
extern "C" {
#endif
 
 
#if defined(__GNUC__)
#define _util_printf_format(fmt, list) __attribute__ ((format (printf, fmt, list)))
#else
#define _util_printf_format(fmt, list)
#endif
 
void _debug_vprintf(const char *format, va_list ap);
 
static INLINE void
_debug_printf(const char *format, ...)
{
va_list ap;
va_start(ap, format);
_debug_vprintf(format, ap);
va_end(ap);
}
 
 
/**
* Print debug messages.
*
* The actual channel used to output debug message is platform specific. To
* avoid misformating or truncation, follow these rules of thumb:
* - output whole lines
* - avoid outputing large strings (512 bytes is the current maximum length
* that is guaranteed to be printed in all platforms)
*/
#if !defined(PIPE_OS_HAIKU)
static INLINE void
debug_printf(const char *format, ...) _util_printf_format(1,2);
 
static INLINE void
debug_printf(const char *format, ...)
{
#ifdef DEBUG
va_list ap;
va_start(ap, format);
_debug_vprintf(format, ap);
va_end(ap);
#else
(void) format; /* silence warning */
#endif
}
#else /* is Haiku */
/* Haiku provides debug_printf in libroot with OS.h */
#include <OS.h>
#endif
 
 
/*
* ... isn't portable so we need to pass arguments in parentheses.
*
* usage:
* debug_printf_once(("answer: %i\n", 42));
*/
#define debug_printf_once(args) \
do { \
static boolean once = TRUE; \
if (once) { \
once = FALSE; \
debug_printf args; \
} \
} while (0)
 
 
#ifdef DEBUG
#define debug_vprintf(_format, _ap) _debug_vprintf(_format, _ap)
#else
#define debug_vprintf(_format, _ap) ((void)0)
#endif
 
 
#ifdef DEBUG
/**
* Dump a blob in hex to the same place that debug_printf sends its
* messages.
*/
void debug_print_blob( const char *name, const void *blob, unsigned size );
 
/* Print a message along with a prettified format string
*/
void debug_print_format(const char *msg, unsigned fmt );
#else
#define debug_print_blob(_name, _blob, _size) ((void)0)
#define debug_print_format(_msg, _fmt) ((void)0)
#endif
 
 
/**
* Hard-coded breakpoint.
*/
#ifdef DEBUG
#define debug_break() os_break()
#else /* !DEBUG */
#define debug_break() ((void)0)
#endif /* !DEBUG */
 
 
long
debug_get_num_option(const char *name, long dfault);
 
void _debug_assert_fail(const char *expr,
const char *file,
unsigned line,
const char *function);
 
 
/**
* Assert macro
*
* Do not expect that the assert call terminates -- errors must be handled
* regardless of assert behavior.
*
* For non debug builds the assert macro will expand to a no-op, so do not
* call functions with side effects in the assert expression.
*/
#ifdef DEBUG
#define debug_assert(expr) ((expr) ? (void)0 : _debug_assert_fail(#expr, __FILE__, __LINE__, __FUNCTION__))
#else
#define debug_assert(expr) do { } while (0 && (expr))
#endif
 
 
/** Override standard assert macro */
#ifdef assert
#undef assert
#endif
#define assert(expr) debug_assert(expr)
 
 
/**
* Output the current function name.
*/
#ifdef DEBUG
#define debug_checkpoint() \
_debug_printf("%s\n", __FUNCTION__)
#else
#define debug_checkpoint() \
((void)0)
#endif
 
 
/**
* Output the full source code position.
*/
#ifdef DEBUG
#define debug_checkpoint_full() \
_debug_printf("%s:%u:%s\n", __FILE__, __LINE__, __FUNCTION__)
#else
#define debug_checkpoint_full() \
((void)0)
#endif
 
 
/**
* Output a warning message. Muted on release version.
*/
#ifdef DEBUG
#define debug_warning(__msg) \
_debug_printf("%s:%u:%s: warning: %s\n", __FILE__, __LINE__, __FUNCTION__, __msg)
#else
#define debug_warning(__msg) \
((void)0)
#endif
 
 
/**
* Emit a warning message, but only once.
*/
#ifdef DEBUG
#define debug_warn_once(__msg) \
do { \
static bool warned = FALSE; \
if (!warned) { \
_debug_printf("%s:%u:%s: one time warning: %s\n", \
__FILE__, __LINE__, __FUNCTION__, __msg); \
warned = TRUE; \
} \
} while (0)
#else
#define debug_warn_once(__msg) \
((void)0)
#endif
 
 
/**
* Output an error message. Not muted on release version.
*/
#ifdef DEBUG
#define debug_error(__msg) \
_debug_printf("%s:%u:%s: error: %s\n", __FILE__, __LINE__, __FUNCTION__, __msg)
#else
#define debug_error(__msg) \
_debug_printf("error: %s\n", __msg)
#endif
 
 
/**
* Used by debug_dump_enum and debug_dump_flags to describe symbols.
*/
struct debug_named_value
{
const char *name;
unsigned long value;
const char *desc;
};
 
 
/**
* Some C pre-processor magic to simplify creating named values.
*
* Example:
* @code
* static const debug_named_value my_names[] = {
* DEBUG_NAMED_VALUE(MY_ENUM_VALUE_X),
* DEBUG_NAMED_VALUE(MY_ENUM_VALUE_Y),
* DEBUG_NAMED_VALUE(MY_ENUM_VALUE_Z),
* DEBUG_NAMED_VALUE_END
* };
*
* ...
* debug_printf("%s = %s\n",
* name,
* debug_dump_enum(my_names, my_value));
* ...
* @endcode
*/
#define DEBUG_NAMED_VALUE(__symbol) {#__symbol, (unsigned long)__symbol, NULL}
#define DEBUG_NAMED_VALUE_WITH_DESCRIPTION(__symbol, __desc) {#__symbol, (unsigned long)__symbol, __desc}
#define DEBUG_NAMED_VALUE_END {NULL, 0, NULL}
 
 
/**
* Convert a enum value to a string.
*/
const char *
debug_dump_enum(const struct debug_named_value *names,
unsigned long value);
 
const char *
debug_dump_enum_noprefix(const struct debug_named_value *names,
const char *prefix,
unsigned long value);
 
 
/**
* Convert binary flags value to a string.
*/
const char *
debug_dump_flags(const struct debug_named_value *names,
unsigned long value);
 
 
/**
* Function enter exit loggers
*/
#ifdef DEBUG
int debug_funclog_enter(const char* f, const int line, const char* file);
void debug_funclog_exit(const char* f, const int line, const char* file);
void debug_funclog_enter_exit(const char* f, const int line, const char* file);
 
#define DEBUG_FUNCLOG_ENTER() \
int __debug_decleration_work_around = \
debug_funclog_enter(__FUNCTION__, __LINE__, __FILE__)
#define DEBUG_FUNCLOG_EXIT() \
do { \
(void)__debug_decleration_work_around; \
debug_funclog_exit(__FUNCTION__, __LINE__, __FILE__); \
return; \
} while(0)
#define DEBUG_FUNCLOG_EXIT_RET(ret) \
do { \
(void)__debug_decleration_work_around; \
debug_funclog_exit(__FUNCTION__, __LINE__, __FILE__); \
return ret; \
} while(0)
#define DEBUG_FUNCLOG_ENTER_EXIT() \
debug_funclog_enter_exit(__FUNCTION__, __LINE__, __FILE__)
 
#else
#define DEBUG_FUNCLOG_ENTER() \
int __debug_decleration_work_around
#define DEBUG_FUNCLOG_EXIT() \
do { (void)__debug_decleration_work_around; return; } while(0)
#define DEBUG_FUNCLOG_EXIT_RET(ret) \
do { (void)__debug_decleration_work_around; return ret; } while(0)
#define DEBUG_FUNCLOG_ENTER_EXIT()
#endif
 
 
/**
* Get option.
*
* It is an alias for getenv on Linux.
*
* On Windows it reads C:\gallium.cfg, which is a text file with CR+LF line
* endings with one option per line as
*
* NAME=value
*
* This file must be terminated with an extra empty line.
*/
const char *
debug_get_option(const char *name, const char *dfault);
 
boolean
debug_get_bool_option(const char *name, boolean dfault);
 
long
debug_get_num_option(const char *name, long dfault);
 
unsigned long
debug_get_flags_option(const char *name,
const struct debug_named_value *flags,
unsigned long dfault);
 
#define DEBUG_GET_ONCE_BOOL_OPTION(sufix, name, dfault) \
static boolean \
debug_get_option_ ## sufix (void) \
{ \
static boolean first = TRUE; \
static boolean value; \
if (first) { \
first = FALSE; \
value = debug_get_bool_option(name, dfault); \
} \
return value; \
}
 
#define DEBUG_GET_ONCE_NUM_OPTION(sufix, name, dfault) \
static long \
debug_get_option_ ## sufix (void) \
{ \
static boolean first = TRUE; \
static long value; \
if (first) { \
first = FALSE; \
value = debug_get_num_option(name, dfault); \
} \
return value; \
}
 
#define DEBUG_GET_ONCE_FLAGS_OPTION(sufix, name, flags, dfault) \
static unsigned long \
debug_get_option_ ## sufix (void) \
{ \
static boolean first = TRUE; \
static unsigned long value; \
if (first) { \
first = FALSE; \
value = debug_get_flags_option(name, flags, dfault); \
} \
return value; \
}
 
 
unsigned long
debug_memory_begin(void);
 
void
debug_memory_end(unsigned long beginning);
 
 
#ifdef DEBUG
struct pipe_context;
struct pipe_surface;
struct pipe_transfer;
struct pipe_resource;
 
void debug_dump_image(const char *prefix,
enum pipe_format format, unsigned cpp,
unsigned width, unsigned height,
unsigned stride,
const void *data);
void debug_dump_surface(struct pipe_context *pipe,
const char *prefix,
struct pipe_surface *surface);
void debug_dump_texture(struct pipe_context *pipe,
const char *prefix,
struct pipe_resource *texture);
void debug_dump_surface_bmp(struct pipe_context *pipe,
const char *filename,
struct pipe_surface *surface);
void debug_dump_transfer_bmp(struct pipe_context *pipe,
const char *filename,
struct pipe_transfer *transfer, void *ptr);
void debug_dump_float_rgba_bmp(const char *filename,
unsigned width, unsigned height,
float *rgba, unsigned stride);
#else
#define debug_dump_image(prefix, format, cpp, width, height, stride, data) ((void)0)
#define debug_dump_surface(pipe, prefix, surface) ((void)0)
#define debug_dump_surface_bmp(pipe, filename, surface) ((void)0)
#define debug_dump_transfer_bmp(filename, transfer, ptr) ((void)0)
#define debug_dump_float_rgba_bmp(filename, width, height, rgba, stride) ((void)0)
#endif
 
 
void
debug_print_transfer_flags(const char *msg, unsigned usage);
 
 
#ifdef __cplusplus
}
#endif
 
#endif /* U_DEBUG_H_ */
/drivers/video/Gallium/auxiliary/util/u_debug_describe.c
0,0 → 1,91
/**************************************************************************
*
* Copyright 2010 Luca Barbieri
*
* 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, sublicense, 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 NONINFRINGEMENT.
* IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
*
**************************************************************************/
 
#include "pipe/p_state.h"
#include "util/u_format.h"
#include "util/u_debug_describe.h"
#include "util/u_string.h"
 
void
debug_describe_reference(char* buf, const struct pipe_reference*ptr)
{
strcpy(buf, "pipe_object");
}
 
void
debug_describe_resource(char* buf, const struct pipe_resource *ptr)
{
switch(ptr->target)
{
case PIPE_BUFFER:
util_sprintf(buf, "pipe_buffer<%u>", (unsigned)util_format_get_stride(ptr->format, ptr->width0));
break;
case PIPE_TEXTURE_1D:
util_sprintf(buf, "pipe_texture1d<%u,%s,%u>", ptr->width0, util_format_short_name(ptr->format), ptr->last_level);
break;
case PIPE_TEXTURE_2D:
util_sprintf(buf, "pipe_texture2d<%u,%u,%s,%u>", ptr->width0, ptr->height0, util_format_short_name(ptr->format), ptr->last_level);
break;
case PIPE_TEXTURE_RECT:
util_sprintf(buf, "pipe_texture_rect<%u,%u,%s>", ptr->width0, ptr->height0, util_format_short_name(ptr->format));
break;
case PIPE_TEXTURE_CUBE:
util_sprintf(buf, "pipe_texture_cube<%u,%u,%s,%u>", ptr->width0, ptr->height0, util_format_short_name(ptr->format), ptr->last_level);
break;
case PIPE_TEXTURE_3D:
util_sprintf(buf, "pipe_texture3d<%u,%u,%u,%s,%u>", ptr->width0, ptr->height0, ptr->depth0, util_format_short_name(ptr->format), ptr->last_level);
break;
default:
util_sprintf(buf, "pipe_martian_resource<%u>", ptr->target);
break;
}
}
 
void
debug_describe_surface(char* buf, const struct pipe_surface *ptr)
{
char res[128];
debug_describe_resource(res, ptr->texture);
util_sprintf(buf, "pipe_surface<%s,%u,%u,%u>", res, ptr->u.tex.level, ptr->u.tex.first_layer, ptr->u.tex.last_layer);
}
 
void
debug_describe_sampler_view(char* buf, const struct pipe_sampler_view *ptr)
{
char res[128];
debug_describe_resource(res, ptr->texture);
util_sprintf(buf, "pipe_sampler_view<%s,%s>", res, util_format_short_name(ptr->format));
}
 
void
debug_describe_so_target(char* buf,
const struct pipe_stream_output_target *ptr)
{
char res[128];
debug_describe_resource(res, ptr->buffer);
util_sprintf(buf, "pipe_stream_output_target<%s,%u,%u>", res,
ptr->buffer_offset, ptr->buffer_size);
}
/drivers/video/Gallium/auxiliary/util/u_debug_describe.h
0,0 → 1,51
/**************************************************************************
*
* Copyright 2010 Luca Barbieri
*
* 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, sublicense, 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 NONINFRINGEMENT.
* IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
*
**************************************************************************/
 
#ifndef U_DEBUG_DESCRIBE_H_
#define U_DEBUG_DESCRIBE_H_
 
#ifdef __cplusplus
extern "C" {
#endif
 
struct pipe_reference;
struct pipe_resource;
struct pipe_surface;
struct pipe_sampler_view;
 
/* a 256-byte buffer is necessary and sufficient */
void debug_describe_reference(char* buf, const struct pipe_reference*ptr);
void debug_describe_resource(char* buf, const struct pipe_resource *ptr);
void debug_describe_surface(char* buf, const struct pipe_surface *ptr);
void debug_describe_sampler_view(char* buf, const struct pipe_sampler_view *ptr);
void debug_describe_so_target(char* buf,
const struct pipe_stream_output_target *ptr);
 
#ifdef __cplusplus
}
#endif
 
#endif /* U_DEBUG_DESCRIBE_H_ */
/drivers/video/Gallium/auxiliary/util/u_debug_memory.c
0,0 → 1,451
/**************************************************************************
*
* 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
* Memory debugging.
*
* @author José Fonseca <jrfonseca@tungstengraphics.com>
*/
 
#include "pipe/p_config.h"
 
#define DEBUG_MEMORY_IMPLEMENTATION
 
#include "os/os_memory.h"
#include "os/os_memory_debug.h"
#include "os/os_thread.h"
 
#include "util/u_debug.h"
#include "util/u_debug_stack.h"
#include "util/u_double_list.h"
 
 
#define DEBUG_MEMORY_MAGIC 0x6e34090aU
#define DEBUG_MEMORY_STACK 0 /* XXX: disabled until we have symbol lookup */
 
/**
* Set to 1 to enable checking of freed blocks of memory.
* Basically, don't really deallocate freed memory; keep it in the list
* but mark it as freed and do extra checking in debug_memory_check().
* This can detect some cases of use-after-free. But note that since we
* never really free anything this will use a lot of memory.
*/
#define DEBUG_FREED_MEMORY 0
#define DEBUG_FREED_BYTE 0x33
 
 
struct debug_memory_header
{
struct list_head head;
unsigned long no;
const char *file;
unsigned line;
const char *function;
#if DEBUG_MEMORY_STACK
struct debug_stack_frame backtrace[DEBUG_MEMORY_STACK];
#endif
size_t size;
#if DEBUG_FREED_MEMORY
boolean freed; /**< Is this a freed block? */
#endif
 
unsigned magic;
unsigned tag;
};
 
struct debug_memory_footer
{
unsigned magic;
};
 
 
static struct list_head list = { &list, &list };
 
pipe_static_mutex(list_mutex);
 
static unsigned long last_no = 0;
 
 
static INLINE struct debug_memory_header *
header_from_data(void *data)
{
if(data)
return (struct debug_memory_header *)((char *)data - sizeof(struct debug_memory_header));
else
return NULL;
}
 
static INLINE void *
data_from_header(struct debug_memory_header *hdr)
{
if(hdr)
return (void *)((char *)hdr + sizeof(struct debug_memory_header));
else
return NULL;
}
 
static INLINE struct debug_memory_footer *
footer_from_header(struct debug_memory_header *hdr)
{
if(hdr)
return (struct debug_memory_footer *)((char *)hdr + sizeof(struct debug_memory_header) + hdr->size);
else
return NULL;
}
 
 
void *
debug_malloc(const char *file, unsigned line, const char *function,
size_t size)
{
struct debug_memory_header *hdr;
struct debug_memory_footer *ftr;
hdr = os_malloc(sizeof(*hdr) + size + sizeof(*ftr));
if(!hdr) {
debug_printf("%s:%u:%s: out of memory when trying to allocate %lu bytes\n",
file, line, function,
(long unsigned)size);
return NULL;
}
hdr->no = last_no++;
hdr->file = file;
hdr->line = line;
hdr->function = function;
hdr->size = size;
hdr->magic = DEBUG_MEMORY_MAGIC;
hdr->tag = 0;
#if DEBUG_FREED_MEMORY
hdr->freed = FALSE;
#endif
 
#if DEBUG_MEMORY_STACK
debug_backtrace_capture(hdr->backtrace, 0, DEBUG_MEMORY_STACK);
#endif
 
ftr = footer_from_header(hdr);
ftr->magic = DEBUG_MEMORY_MAGIC;
pipe_mutex_lock(list_mutex);
LIST_ADDTAIL(&hdr->head, &list);
pipe_mutex_unlock(list_mutex);
return data_from_header(hdr);
}
 
void
debug_free(const char *file, unsigned line, const char *function,
void *ptr)
{
struct debug_memory_header *hdr;
struct debug_memory_footer *ftr;
if(!ptr)
return;
hdr = header_from_data(ptr);
if(hdr->magic != DEBUG_MEMORY_MAGIC) {
debug_printf("%s:%u:%s: freeing bad or corrupted memory %p\n",
file, line, function,
ptr);
debug_assert(0);
return;
}
 
ftr = footer_from_header(hdr);
if(ftr->magic != DEBUG_MEMORY_MAGIC) {
debug_printf("%s:%u:%s: buffer overflow %p\n",
hdr->file, hdr->line, hdr->function,
ptr);
debug_assert(0);
}
 
#if DEBUG_FREED_MEMORY
/* Check for double-free */
assert(!hdr->freed);
/* Mark the block as freed but don't really free it */
hdr->freed = TRUE;
/* Save file/line where freed */
hdr->file = file;
hdr->line = line;
/* set freed memory to special value */
memset(ptr, DEBUG_FREED_BYTE, hdr->size);
#else
pipe_mutex_lock(list_mutex);
LIST_DEL(&hdr->head);
pipe_mutex_unlock(list_mutex);
hdr->magic = 0;
ftr->magic = 0;
os_free(hdr);
#endif
}
 
void *
debug_calloc(const char *file, unsigned line, const char *function,
size_t count, size_t size )
{
void *ptr = debug_malloc( file, line, function, count * size );
if( ptr )
memset( ptr, 0, count * size );
return ptr;
}
 
void *
debug_realloc(const char *file, unsigned line, const char *function,
void *old_ptr, size_t old_size, size_t new_size )
{
struct debug_memory_header *old_hdr, *new_hdr;
struct debug_memory_footer *old_ftr, *new_ftr;
void *new_ptr;
if(!old_ptr)
return debug_malloc( file, line, function, new_size );
if(!new_size) {
debug_free( file, line, function, old_ptr );
return NULL;
}
old_hdr = header_from_data(old_ptr);
if(old_hdr->magic != DEBUG_MEMORY_MAGIC) {
debug_printf("%s:%u:%s: reallocating bad or corrupted memory %p\n",
file, line, function,
old_ptr);
debug_assert(0);
return NULL;
}
old_ftr = footer_from_header(old_hdr);
if(old_ftr->magic != DEBUG_MEMORY_MAGIC) {
debug_printf("%s:%u:%s: buffer overflow %p\n",
old_hdr->file, old_hdr->line, old_hdr->function,
old_ptr);
debug_assert(0);
}
 
/* alloc new */
new_hdr = os_malloc(sizeof(*new_hdr) + new_size + sizeof(*new_ftr));
if(!new_hdr) {
debug_printf("%s:%u:%s: out of memory when trying to allocate %lu bytes\n",
file, line, function,
(long unsigned)new_size);
return NULL;
}
new_hdr->no = old_hdr->no;
new_hdr->file = old_hdr->file;
new_hdr->line = old_hdr->line;
new_hdr->function = old_hdr->function;
new_hdr->size = new_size;
new_hdr->magic = DEBUG_MEMORY_MAGIC;
new_hdr->tag = 0;
#if DEBUG_FREED_MEMORY
new_hdr->freed = FALSE;
#endif
new_ftr = footer_from_header(new_hdr);
new_ftr->magic = DEBUG_MEMORY_MAGIC;
pipe_mutex_lock(list_mutex);
LIST_REPLACE(&old_hdr->head, &new_hdr->head);
pipe_mutex_unlock(list_mutex);
 
/* copy data */
new_ptr = data_from_header(new_hdr);
memcpy( new_ptr, old_ptr, old_size < new_size ? old_size : new_size );
 
/* free old */
old_hdr->magic = 0;
old_ftr->magic = 0;
os_free(old_hdr);
 
return new_ptr;
}
 
unsigned long
debug_memory_begin(void)
{
return last_no;
}
 
void
debug_memory_end(unsigned long start_no)
{
size_t total_size = 0;
struct list_head *entry;
 
if(start_no == last_no)
return;
 
entry = list.prev;
for (; entry != &list; entry = entry->prev) {
struct debug_memory_header *hdr;
void *ptr;
struct debug_memory_footer *ftr;
 
hdr = LIST_ENTRY(struct debug_memory_header, entry, head);
ptr = data_from_header(hdr);
ftr = footer_from_header(hdr);
 
if(hdr->magic != DEBUG_MEMORY_MAGIC) {
debug_printf("%s:%u:%s: bad or corrupted memory %p\n",
hdr->file, hdr->line, hdr->function,
ptr);
debug_assert(0);
}
 
if((start_no <= hdr->no && hdr->no < last_no) ||
(last_no < start_no && (hdr->no < last_no || start_no <= hdr->no))) {
debug_printf("%s:%u:%s: %lu bytes at %p not freed\n",
hdr->file, hdr->line, hdr->function,
(unsigned long) hdr->size, ptr);
#if DEBUG_MEMORY_STACK
debug_backtrace_dump(hdr->backtrace, DEBUG_MEMORY_STACK);
#endif
total_size += hdr->size;
}
 
if(ftr->magic != DEBUG_MEMORY_MAGIC) {
debug_printf("%s:%u:%s: buffer overflow %p\n",
hdr->file, hdr->line, hdr->function,
ptr);
debug_assert(0);
}
}
 
if(total_size) {
debug_printf("Total of %lu KB of system memory apparently leaked\n",
(unsigned long) (total_size + 1023)/1024);
}
else {
debug_printf("No memory leaks detected.\n");
}
}
 
 
/**
* Put a tag (arbitrary integer) on a memory block.
* Can be useful for debugging.
*/
void
debug_memory_tag(void *ptr, unsigned tag)
{
struct debug_memory_header *hdr;
if (!ptr)
return;
hdr = header_from_data(ptr);
if (hdr->magic != DEBUG_MEMORY_MAGIC) {
debug_printf("%s corrupted memory at %p\n", __FUNCTION__, ptr);
debug_assert(0);
}
 
hdr->tag = tag;
}
 
 
/**
* Check the given block of memory for validity/corruption.
*/
void
debug_memory_check_block(void *ptr)
{
struct debug_memory_header *hdr;
struct debug_memory_footer *ftr;
if (!ptr)
return;
hdr = header_from_data(ptr);
ftr = footer_from_header(hdr);
 
if (hdr->magic != DEBUG_MEMORY_MAGIC) {
debug_printf("%s:%u:%s: bad or corrupted memory %p\n",
hdr->file, hdr->line, hdr->function, ptr);
debug_assert(0);
}
 
if (ftr->magic != DEBUG_MEMORY_MAGIC) {
debug_printf("%s:%u:%s: buffer overflow %p\n",
hdr->file, hdr->line, hdr->function, ptr);
debug_assert(0);
}
}
 
 
 
/**
* We can periodically call this from elsewhere to do a basic sanity
* check of the heap memory we've allocated.
*/
void
debug_memory_check(void)
{
struct list_head *entry;
 
entry = list.prev;
for (; entry != &list; entry = entry->prev) {
struct debug_memory_header *hdr;
struct debug_memory_footer *ftr;
const char *ptr;
 
hdr = LIST_ENTRY(struct debug_memory_header, entry, head);
ftr = footer_from_header(hdr);
ptr = (const char *) data_from_header(hdr);
 
if (hdr->magic != DEBUG_MEMORY_MAGIC) {
debug_printf("%s:%u:%s: bad or corrupted memory %p\n",
hdr->file, hdr->line, hdr->function, ptr);
debug_assert(0);
}
 
if (ftr->magic != DEBUG_MEMORY_MAGIC) {
debug_printf("%s:%u:%s: buffer overflow %p\n",
hdr->file, hdr->line, hdr->function, ptr);
debug_assert(0);
}
 
#if DEBUG_FREED_MEMORY
/* If this block is marked as freed, check that it hasn't been touched */
if (hdr->freed) {
int i;
for (i = 0; i < hdr->size; i++) {
if (ptr[i] != DEBUG_FREED_BYTE) {
debug_printf("Memory error: byte %d of block at %p of size %d is 0x%x\n",
i, ptr, hdr->size, ptr[i]);
debug_printf("Block was freed at %s:%d\n", hdr->file, hdr->line);
}
assert(ptr[i] == DEBUG_FREED_BYTE);
}
}
#endif
}
}
/drivers/video/Gallium/auxiliary/util/u_debug_refcnt.c
0,0 → 1,195
/**************************************************************************
*
* Copyright 2010 Luca Barbieri
*
* 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, sublicense, 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 NONINFRINGEMENT.
* IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
*
**************************************************************************/
 
#if defined(DEBUG)
 
/* see http://www.mozilla.org/performance/refcnt-balancer.html for what do with the output
* on Linux, use tools/addr2line.sh to postprocess it before anything else
**/
 
#include <stdio.h>
 
#include "util/u_debug.h"
#include "util/u_debug_refcnt.h"
#include "util/u_debug_stack.h"
#include "util/u_debug_symbol.h"
#include "util/u_string.h"
#include "util/u_hash_table.h"
#include "os/os_thread.h"
 
int debug_refcnt_state;
 
FILE* stream;
 
/* TODO: maybe move this serial machinery to a stand-alone module and expose it? */
pipe_static_mutex(serials_mutex);
 
static struct util_hash_table* serials_hash;
static unsigned serials_last;
 
static unsigned hash_ptr(void* p)
{
return (unsigned)(uintptr_t)p;
}
 
static int compare_ptr(void* a, void* b)
{
if(a == b)
return 0;
else if(a < b)
return -1;
else
return 1;
}
 
static boolean debug_serial(void* p, unsigned* pserial)
{
unsigned serial;
boolean found = TRUE;
#ifdef PIPE_SUBSYSTEM_WINDOWS_USER
static boolean first = TRUE;
 
if (first) {
pipe_mutex_init(serials_mutex);
first = FALSE;
}
#endif
 
pipe_mutex_lock(serials_mutex);
if(!serials_hash)
serials_hash = util_hash_table_create(hash_ptr, compare_ptr);
serial = (unsigned)(uintptr_t)util_hash_table_get(serials_hash, p);
if(!serial)
{
/* time to stop logging... (you'll have a 100 GB logfile at least at this point)
* TODO: avoid this
*/
serial = ++serials_last;
if(!serial)
{
debug_error("More than 2^32 objects detected, aborting.\n");
os_abort();
}
 
util_hash_table_set(serials_hash, p, (void*)(uintptr_t)serial);
found = FALSE;
}
pipe_mutex_unlock(serials_mutex);
*pserial = serial;
return found;
}
 
static void debug_serial_delete(void* p)
{
pipe_mutex_lock(serials_mutex);
util_hash_table_remove(serials_hash, p);
pipe_mutex_unlock(serials_mutex);
}
 
#define STACK_LEN 64
 
static void dump_stack(const char* symbols[STACK_LEN])
{
unsigned i;
for(i = 0; i < STACK_LEN; ++i)
{
if(symbols[i])
fprintf(stream, "%s\n", symbols[i]);
}
fprintf(stream, "\n");
}
 
void debug_reference_slowpath(const struct pipe_reference* p, debug_reference_descriptor get_desc, int change)
{
if(debug_refcnt_state < 0)
return;
 
if(!debug_refcnt_state)
{
const char* filename = debug_get_option("GALLIUM_REFCNT_LOG", NULL);
if(filename && filename[0])
stream = fopen(filename, "wt");
 
if(stream)
debug_refcnt_state = 1;
else
debug_refcnt_state = -1;
}
 
if(debug_refcnt_state > 0)
{
struct debug_stack_frame frames[STACK_LEN];
const char* symbols[STACK_LEN];
char buf[1024];
 
unsigned i;
unsigned refcnt = p->count;
unsigned serial;
boolean existing = debug_serial((void*)p, &serial);
 
debug_backtrace_capture(frames, 1, STACK_LEN);
for(i = 0; i < STACK_LEN; ++i)
{
if(frames[i].function)
symbols[i] = debug_symbol_name_cached(frames[i].function);
else
symbols[i] = 0;
}
 
get_desc(buf, p);
 
if(!existing)
{
fprintf(stream, "<%s> %p %u Create\n", buf, (void *) p, serial);
dump_stack(symbols);
 
/* this is there to provide a gradual change even if we don't see the initialization */
for(i = 1; i <= refcnt - change; ++i)
{
fprintf(stream, "<%s> %p %u AddRef %u\n", buf, (void *) p,
serial, i);
dump_stack(symbols);
}
}
 
if(change)
{
fprintf(stream, "<%s> %p %u %s %u\n", buf, (void *) p, serial,
change > 0 ? "AddRef" : "Release", refcnt);
dump_stack(symbols);
}
 
if(!refcnt)
{
debug_serial_delete((void*)p);
fprintf(stream, "<%s> %p %u Destroy\n", buf, (void *) p, serial);
dump_stack(symbols);
}
 
fflush(stream);
}
}
#endif
/drivers/video/Gallium/auxiliary/util/u_debug_refcnt.h
0,0 → 1,63
/**************************************************************************
*
* Copyright 2010 Luca Barbieri
*
* 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, sublicense, 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 NONINFRINGEMENT.
* IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
*
**************************************************************************/
 
#ifndef U_DEBUG_REFCNT_H_
#define U_DEBUG_REFCNT_H_
 
#include "pipe/p_config.h"
#include "pipe/p_state.h"
 
#ifdef __cplusplus
extern "C" {
#endif
 
typedef void (*debug_reference_descriptor)(char*, const struct pipe_reference*);
 
#if defined(DEBUG) && (!defined(PIPE_OS_WINDOWS) || defined(PIPE_SUBSYSTEM_WINDOWS_USER))
 
extern int debug_refcnt_state;
 
void debug_reference_slowpath(const struct pipe_reference* p, debug_reference_descriptor get_desc, int change);
 
static INLINE void debug_reference(const struct pipe_reference* p, debug_reference_descriptor get_desc, int change)
{
if (debug_refcnt_state >= 0)
debug_reference_slowpath(p, get_desc, change);
}
 
#else
 
static INLINE void debug_reference(const struct pipe_reference* p, debug_reference_descriptor get_desc, int change)
{
}
 
#endif
 
#ifdef __cplusplus
}
#endif
 
#endif /* U_DEBUG_REFCNT_H_ */
/drivers/video/Gallium/auxiliary/util/u_debug_stack.c
0,0 → 1,161
/**************************************************************************
*
* Copyright 2009 VMware, Inc.
* 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 VMWARE 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
* Stack backtracing.
*
* @author Jose Fonseca <jfonseca@vmware.com>
*/
 
#include "u_debug.h"
#include "u_debug_symbol.h"
#include "u_debug_stack.h"
 
#if defined(PIPE_OS_WINDOWS)
#include <windows.h>
#endif
 
 
/**
* Capture stack backtrace.
*
* NOTE: The implementation of this function is quite big, but it is important not to
* break it down in smaller functions to avoid adding new frames to the calling stack.
*/
void
debug_backtrace_capture(struct debug_stack_frame *backtrace,
unsigned start_frame,
unsigned nr_frames)
{
const void **frame_pointer = NULL;
unsigned i = 0;
 
if (!nr_frames) {
return;
}
 
/*
* On Windows try obtaining the stack backtrace via CaptureStackBackTrace.
*
* It works reliably both for x86 for x86_64.
*/
#if defined(PIPE_OS_WINDOWS)
{
typedef USHORT (WINAPI *PFNCAPTURESTACKBACKTRACE)(ULONG, ULONG, PVOID *, PULONG);
static PFNCAPTURESTACKBACKTRACE pfnCaptureStackBackTrace = NULL;
 
if (!pfnCaptureStackBackTrace) {
static HMODULE hModule = NULL;
if (!hModule) {
hModule = LoadLibraryA("kernel32");
assert(hModule);
}
if (hModule) {
pfnCaptureStackBackTrace = (PFNCAPTURESTACKBACKTRACE)GetProcAddress(hModule,
"RtlCaptureStackBackTrace");
}
}
if (pfnCaptureStackBackTrace) {
/*
* Skip this (debug_backtrace_capture) function's frame.
*/
 
start_frame += 1;
 
assert(start_frame + nr_frames < 63);
i = pfnCaptureStackBackTrace(start_frame, nr_frames, (PVOID *) &backtrace->function, NULL);
 
/* Pad remaing requested frames with NULL */
while (i < nr_frames) {
backtrace[i++].function = NULL;
}
 
return;
}
}
#endif
 
#if defined(PIPE_CC_GCC)
frame_pointer = ((const void **)__builtin_frame_address(1));
#elif defined(PIPE_CC_MSVC) && defined(PIPE_ARCH_X86)
__asm {
mov frame_pointer, ebp
}
frame_pointer = (const void **)frame_pointer[0];
#else
frame_pointer = NULL;
#endif
#ifdef PIPE_ARCH_X86
while(nr_frames) {
const void **next_frame_pointer;
 
if(!frame_pointer)
break;
if(start_frame)
--start_frame;
else {
backtrace[i++].function = frame_pointer[1];
--nr_frames;
}
next_frame_pointer = (const void **)frame_pointer[0];
/* Limit the stack walk to avoid referencing undefined memory */
if((uintptr_t)next_frame_pointer <= (uintptr_t)frame_pointer ||
(uintptr_t)next_frame_pointer > (uintptr_t)frame_pointer + 64*1024)
break;
frame_pointer = next_frame_pointer;
}
#else
(void) frame_pointer;
#endif
 
while(nr_frames) {
backtrace[i++].function = NULL;
--nr_frames;
}
}
 
void
debug_backtrace_dump(const struct debug_stack_frame *backtrace,
unsigned nr_frames)
{
unsigned i;
for(i = 0; i < nr_frames; ++i) {
if(!backtrace[i].function)
break;
debug_symbol_print(backtrace[i].function);
}
}
 
/drivers/video/Gallium/auxiliary/util/u_debug_stack.h
0,0 → 1,72
/**************************************************************************
*
* Copyright 2009 VMware, Inc.
* 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 VMWARE 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.
*
**************************************************************************/
 
#ifndef U_DEBUG_STACK_H_
#define U_DEBUG_STACK_H_
 
 
/**
* @file
* Stack backtracing.
*
* @author Jose Fonseca <jfonseca@vmware.com>
*/
 
 
#ifdef __cplusplus
extern "C" {
#endif
 
 
/**
* Represent a frame from a stack backtrace.
*
* XXX: Do not change this.
*
* TODO: This should be refactored as a void * typedef.
*/
struct debug_stack_frame
{
const void *function;
};
 
void
debug_backtrace_capture(struct debug_stack_frame *backtrace,
unsigned start_frame,
unsigned nr_frames);
 
void
debug_backtrace_dump(const struct debug_stack_frame *backtrace,
unsigned nr_frames);
 
 
#ifdef __cplusplus
}
#endif
 
#endif /* U_DEBUG_STACK_H_ */
/drivers/video/Gallium/auxiliary/util/u_debug_symbol.c
0,0 → 1,326
/**************************************************************************
*
* Copyright 2009 VMware, Inc.
* 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 VMWARE 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
* Symbol lookup.
*
* @author Jose Fonseca <jfonseca@vmware.com>
*/
 
#include "pipe/p_compiler.h"
#include "os/os_thread.h"
#include "u_string.h"
 
#include "u_debug.h"
#include "u_debug_symbol.h"
#include "u_hash_table.h"
 
 
#if defined(PIPE_OS_WINDOWS)
#include <windows.h>
#include <stddef.h>
 
#include "dbghelp.h"
 
 
/**
* SymInitialize() must be called once for each process (in this case, the
* current process), before any of the other functions can be called.
*/
static BOOL g_bSymInitialized = FALSE;
 
 
/**
* Lookup the address of a DbgHelp function.
*/
static FARPROC WINAPI
getDbgHelpProcAddress(LPCSTR lpProcName)
{
static HMODULE hModule = NULL;
 
if (!hModule) {
static boolean bail = FALSE;
 
if (bail) {
return NULL;
}
 
#ifdef PIPE_CC_GCC
/*
* DbgHelp does not understand the debug information generated by MinGW toolchain.
*
* mgwhelp.dll is a dbghelp.dll look-alike replacement, which is able to
* understand MinGW symbols, including on 64-bit builds.
*/
if (!hModule) {
hModule = LoadLibraryA("mgwhelp.dll");
if (!hModule) {
_debug_printf("warning: mgwhelp.dll not found: symbol names will not be resolved\n"
"warning: download it from http://code.google.com/p/jrfonseca/wiki/DrMingw#MgwHelp\n");
}
}
 
/*
* bfdhelp.dll was the predecessor of mgwhelp.dll. It is available from
* http://people.freedesktop.org/~jrfonseca/bfdhelp/ for now.
*/
if (!hModule) {
hModule = LoadLibraryA("bfdhelp.dll");
}
#endif
 
/*
* Fallback to the real DbgHelp.
*/
if (!hModule) {
hModule = LoadLibraryA("dbghelp.dll");
}
 
if (!hModule) {
bail = TRUE;
return NULL;
}
}
 
return GetProcAddress(hModule, lpProcName);
}
 
 
/**
* Generic macro to dispatch a DbgHelp functions.
*/
#define DBGHELP_DISPATCH(_name, _ret_type, _ret_default, _arg_types, _arg_names) \
static _ret_type WINAPI \
j_##_name _arg_types \
{ \
typedef BOOL (WINAPI *PFN) _arg_types; \
static PFN pfn = NULL; \
if (!pfn) { \
pfn = (PFN) getDbgHelpProcAddress(#_name); \
if (!pfn) { \
return _ret_default; \
} \
} \
return pfn _arg_names; \
}
 
DBGHELP_DISPATCH(SymInitialize,
BOOL, 0,
(HANDLE hProcess, PSTR UserSearchPath, BOOL fInvadeProcess),
(hProcess, UserSearchPath, fInvadeProcess))
 
DBGHELP_DISPATCH(SymSetOptions,
DWORD, FALSE,
(DWORD SymOptions),
(SymOptions))
 
DBGHELP_DISPATCH(SymFromAddr,
BOOL, FALSE,
(HANDLE hProcess, DWORD64 Address, PDWORD64 Displacement, PSYMBOL_INFO Symbol),
(hProcess, Address, Displacement, Symbol))
 
DBGHELP_DISPATCH(SymGetLineFromAddr64,
BOOL, FALSE,
(HANDLE hProcess, DWORD64 dwAddr, PDWORD pdwDisplacement, PIMAGEHLP_LINE64 Line),
(hProcess, dwAddr, pdwDisplacement, Line))
 
 
#undef DBGHELP_DISPATCH
 
 
static INLINE boolean
debug_symbol_name_dbghelp(const void *addr, char* buf, unsigned size)
{
DWORD64 dwAddr = (DWORD64)(uintptr_t)addr;
HANDLE hProcess = GetCurrentProcess();
 
/* General purpose buffer, to back pSymbol and other temporary stuff.
* Must not be too memory hungry here to avoid stack overflows.
*/
CHAR buffer[512];
 
PSYMBOL_INFO pSymbol = (PSYMBOL_INFO) buffer;
DWORD64 dwDisplacement = 0; /* Displacement of the input address, relative to the start of the symbol */
DWORD dwLineDisplacement = 0;
IMAGEHLP_LINE64 Line;
 
memset(pSymbol, 0, sizeof *pSymbol);
pSymbol->SizeOfStruct = sizeof buffer;
pSymbol->MaxNameLen = sizeof buffer - offsetof(SYMBOL_INFO, Name);
 
if (!g_bSymInitialized) {
j_SymSetOptions(/* SYMOPT_UNDNAME | */ SYMOPT_LOAD_LINES);
if (j_SymInitialize(hProcess, NULL, TRUE)) {
g_bSymInitialized = TRUE;
}
}
 
/* Lookup symbol name */
if (!g_bSymInitialized ||
!j_SymFromAddr(hProcess, dwAddr, &dwDisplacement, pSymbol)) {
/*
* We couldn't obtain symbol information. At least tell which module the address belongs.
*/
 
HMODULE hModule = NULL;
 
if (!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
(LPCTSTR)addr,
&hModule)) {
return FALSE;
}
 
if (GetModuleFileNameA(hModule, buffer, sizeof buffer) == sizeof buffer) {
return FALSE;
}
util_snprintf(buf, size, "%p at %s+0x%lx",
addr, buffer,
(unsigned long)((uintptr_t)addr - (uintptr_t)hModule));
 
return TRUE;
}
 
/*
* Try to get filename and line number.
*/
memset(&Line, 0, sizeof Line);
Line.SizeOfStruct = sizeof Line;
if (!j_SymGetLineFromAddr64(hProcess, dwAddr, &dwLineDisplacement, &Line)) {
Line.FileName = NULL;
}
 
if (Line.FileName) {
util_snprintf(buf, size, "%s at %s:%lu", pSymbol->Name, Line.FileName, Line.LineNumber);
} else {
util_snprintf(buf, size, "%s", pSymbol->Name);
}
 
return TRUE;
}
 
#endif /* PIPE_OS_WINDOWS */
 
 
#if defined(__GLIBC__) && !defined(__UCLIBC__)
 
#include <execinfo.h>
 
/* This can only provide dynamic symbols, or binary offsets into a file.
*
* To fix this, post-process the output with tools/addr2line.sh
*/
static INLINE boolean
debug_symbol_name_glibc(const void *addr, char* buf, unsigned size)
{
char** syms = backtrace_symbols((void**)&addr, 1);
if (!syms) {
return FALSE;
}
strncpy(buf, syms[0], size);
buf[size - 1] = 0;
free(syms);
return TRUE;
}
 
#endif /* defined(__GLIBC__) && !defined(__UCLIBC__) */
 
 
void
debug_symbol_name(const void *addr, char* buf, unsigned size)
{
#if defined(PIPE_OS_WINDOWS)
if (debug_symbol_name_dbghelp(addr, buf, size)) {
return;
}
#endif
 
#if defined(__GLIBC__) && !defined(__UCLIBC__)
if (debug_symbol_name_glibc(addr, buf, size)) {
return;
}
#endif
 
util_snprintf(buf, size, "%p", addr);
buf[size - 1] = 0;
}
 
void
debug_symbol_print(const void *addr)
{
char buf[1024];
debug_symbol_name(addr, buf, sizeof(buf));
debug_printf("\t%s\n", buf);
}
 
struct util_hash_table* symbols_hash;
pipe_static_mutex(symbols_mutex);
 
static unsigned hash_ptr(void* p)
{
return (unsigned)(uintptr_t)p;
}
 
static int compare_ptr(void* a, void* b)
{
if(a == b)
return 0;
else if(a < b)
return -1;
else
return 1;
}
 
const char*
debug_symbol_name_cached(const void *addr)
{
const char* name;
#ifdef PIPE_SUBSYSTEM_WINDOWS_USER
static boolean first = TRUE;
 
if (first) {
pipe_mutex_init(symbols_mutex);
first = FALSE;
}
#endif
 
pipe_mutex_lock(symbols_mutex);
if(!symbols_hash)
symbols_hash = util_hash_table_create(hash_ptr, compare_ptr);
name = util_hash_table_get(symbols_hash, (void*)addr);
if(!name)
{
char buf[1024];
debug_symbol_name(addr, buf, sizeof(buf));
name = strdup(buf);
 
util_hash_table_set(symbols_hash, (void*)addr, (void*)name);
}
pipe_mutex_unlock(symbols_mutex);
return name;
}
/drivers/video/Gallium/auxiliary/util/u_debug_symbol.h
0,0 → 1,58
/**************************************************************************
*
* Copyright 2009 VMware, Inc.
* 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 VMWARE 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.
*
**************************************************************************/
 
#ifndef U_DEBUG_SYMBOL_H_
#define U_DEBUG_SYMBOL_H_
 
 
/**
* @file
* Symbol lookup.
*
* @author Jose Fonseca <jfonseca@vmware.com>
*/
 
 
#ifdef __cplusplus
extern "C" {
#endif
 
 
void
debug_symbol_name(const void *addr, char* buf, unsigned size);
 
const char*
debug_symbol_name_cached(const void *addr);
 
void
debug_symbol_print(const void *addr);
 
#ifdef __cplusplus
}
#endif
 
#endif /* U_DEBUG_SYMBOL_H_ */
/drivers/video/Gallium/auxiliary/util/u_dirty_flags.h
0,0 → 1,32
#ifndef U_DIRTY_FLAGS_H
#define U_DIRTY_FLAGS_H
 
/* Here's a convenient list of dirty flags to use in a driver. Either
* include it directly or use it as a starting point for your own
* list.
*/
#define U_NEW_VIEWPORT 0x1
#define U_NEW_RASTERIZER 0x2
#define U_NEW_FS 0x4
#define U_NEW_FS_CONSTANTS 0x8
#define U_NEW_FS_SAMPLER_VIEW 0x10
#define U_NEW_FS_SAMPLER_STATES 0x20
#define U_NEW_VS 0x40
#define U_NEW_VS_CONSTANTS 0x80
#define U_NEW_VS_SAMPLER_VIEW 0x100
#define U_NEW_VS_SAMPLER_STATES 0x200
#define U_NEW_BLEND 0x400
#define U_NEW_CLIP 0x800
#define U_NEW_SCISSOR 0x1000
#define U_NEW_POLYGON_STIPPLE 0x2000
#define U_NEW_FRAMEBUFFER 0x4000
#define U_NEW_VERTEX_ELEMENTS 0x8000
#define U_NEW_VERTEX_BUFFER 0x10000
#define U_NEW_QUERY 0x20000
#define U_NEW_DEPTH_STENCIL 0x40000
#define U_NEW_GS 0x80000
#define U_NEW_GS_CONSTANTS 0x100000
#define U_NEW_GS_SAMPLER_VIEW 0x200000
#define U_NEW_GS_SAMPLER_STATES 0x400000
 
#endif
/drivers/video/Gallium/auxiliary/util/u_dirty_surfaces.h
0,0 → 1,119
/**************************************************************************
*
* Copyright 2010 Luca Barbieri
*
* 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, sublicense, 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 NONINFRINGEMENT.
* IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
*
**************************************************************************/
 
#ifndef U_DIRTY_SURFACES_H_
#define U_DIRTY_SURFACES_H_
 
#include "pipe/p_state.h"
 
#include "util/u_double_list.h"
#include "util/u_math.h"
 
struct pipe_context;
 
typedef void (*util_dirty_surface_flush_t) (struct pipe_context *, struct pipe_surface *);
 
struct util_dirty_surfaces
{
struct list_head dirty_list;
};
 
struct util_dirty_surface
{
struct pipe_surface base;
struct list_head dirty_list;
};
 
static INLINE void
util_dirty_surfaces_init(struct util_dirty_surfaces *ds)
{
LIST_INITHEAD(&ds->dirty_list);
}
 
static INLINE void
util_dirty_surfaces_use_for_sampling(struct pipe_context *pipe, struct util_dirty_surfaces *dss, util_dirty_surface_flush_t flush)
{
struct list_head *p, *next;
for(p = dss->dirty_list.next; p != &dss->dirty_list; p = next)
{
struct util_dirty_surface *ds = LIST_ENTRY(struct util_dirty_surface, p, dirty_list);
next = p->next;
 
flush(pipe, &ds->base);
}
}
 
static INLINE void
util_dirty_surfaces_use_levels_for_sampling(struct pipe_context *pipe, struct util_dirty_surfaces *dss, unsigned first, unsigned last, util_dirty_surface_flush_t flush)
{
struct list_head *p, *next;
if(first > last)
return;
for(p = dss->dirty_list.next; p != &dss->dirty_list; p = next)
{
struct util_dirty_surface *ds = LIST_ENTRY(struct util_dirty_surface, p, dirty_list);
next = p->next;
 
if(ds->base.u.tex.level >= first && ds->base.u.tex.level <= last)
flush(pipe, &ds->base);
}
}
 
static INLINE void
util_dirty_surfaces_use_for_sampling_with(struct pipe_context *pipe, struct util_dirty_surfaces *dss, struct pipe_sampler_view *psv, struct pipe_sampler_state *pss, util_dirty_surface_flush_t flush)
{
if(!LIST_IS_EMPTY(&dss->dirty_list))
util_dirty_surfaces_use_levels_for_sampling(pipe, dss, (unsigned)pss->min_lod + psv->u.tex.first_level,
MIN2((unsigned)ceilf(pss->max_lod) + psv->u.tex.first_level, psv->u.tex.last_level), flush);
}
 
static INLINE void
util_dirty_surface_init(struct util_dirty_surface *ds)
{
LIST_INITHEAD(&ds->dirty_list);
}
 
static INLINE boolean
util_dirty_surface_is_dirty(struct util_dirty_surface *ds)
{
return !LIST_IS_EMPTY(&ds->dirty_list);
}
 
static INLINE void
util_dirty_surface_set_dirty(struct util_dirty_surfaces *dss, struct util_dirty_surface *ds)
{
if(LIST_IS_EMPTY(&ds->dirty_list))
LIST_ADDTAIL(&ds->dirty_list, &dss->dirty_list);
}
 
static INLINE void
util_dirty_surface_set_clean(struct util_dirty_surfaces *dss, struct util_dirty_surface *ds)
{
if(!LIST_IS_EMPTY(&ds->dirty_list))
LIST_DELINIT(&ds->dirty_list);
}
 
#endif
/drivers/video/Gallium/auxiliary/util/u_dl.c
0,0 → 1,94
/**************************************************************************
*
* Copyright 2009 VMware, Inc.
* Copyright 1999-2008 Brian Paul
* 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 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
* THE COPYRIGHT HOLDERS, AUTHORS 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.
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
**************************************************************************/
 
 
#include "pipe/p_config.h"
#include "pipe/p_compiler.h"
 
#if defined(PIPE_OS_UNIX)
#include <dlfcn.h>
#endif
#if defined(PIPE_OS_WINDOWS)
#include <windows.h>
#endif
 
#include "u_dl.h"
#include "u_pointer.h"
 
 
struct util_dl_library *
util_dl_open(const char *filename)
{
#if defined(PIPE_OS_UNIX)
return (struct util_dl_library *)dlopen(filename, RTLD_LAZY | RTLD_GLOBAL);
#elif defined(PIPE_OS_WINDOWS)
return (struct util_dl_library *)LoadLibraryA(filename);
#else
return NULL;
#endif
}
 
 
util_dl_proc
util_dl_get_proc_address(struct util_dl_library *library,
const char *procname)
{
#if defined(PIPE_OS_UNIX)
return (util_dl_proc) pointer_to_func(dlsym((void *)library, procname));
#elif defined(PIPE_OS_WINDOWS)
return (util_dl_proc)GetProcAddress((HMODULE)library, procname);
#else
return (util_dl_proc)NULL;
#endif
}
 
 
void
util_dl_close(struct util_dl_library *library)
{
#if defined(PIPE_OS_UNIX)
dlclose((void *)library);
#elif defined(PIPE_OS_WINDOWS)
FreeLibrary((HMODULE)library);
#else
(void)library;
#endif
}
 
 
const char *
util_dl_error(void)
{
#if defined(PIPE_OS_UNIX)
return dlerror();
#elif defined(PIPE_OS_WINDOWS)
return "unknown error";
#else
return "unknown error";
#endif
}
/drivers/video/Gallium/auxiliary/util/u_dl.h
0,0 → 1,83
/**************************************************************************
*
* Copyright 2009 VMware, Inc.
* 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 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
* THE COPYRIGHT HOLDERS, AUTHORS 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.
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
**************************************************************************/
 
 
#ifndef U_DL_H_
#define U_DL_H_
 
 
#include "pipe/p_config.h"
 
 
#if defined(PIPE_OS_WINDOWS)
# define UTIL_DL_EXT ".dll"
# define UTIL_DL_PREFIX ""
#elif defined(PIPE_OS_APPLE)
# define UTIL_DL_EXT ".dylib"
# define UTIL_DL_PREFIX "lib"
#else
# define UTIL_DL_EXT ".so"
# define UTIL_DL_PREFIX "lib"
#endif
 
 
struct util_dl_library;
 
 
typedef void (*util_dl_proc)(void);
 
 
/**
* Open a library dynamically.
*/
struct util_dl_library *
util_dl_open(const char *filename);
 
 
/**
* Lookup a function in a library.
*/
util_dl_proc
util_dl_get_proc_address(struct util_dl_library *library,
const char *procname);
 
 
/**
* Close a library.
*/
void
util_dl_close(struct util_dl_library *library);
 
 
/**
* Return most recent error message.
*/
const char *
util_dl_error(void);
 
 
#endif /* U_DL_H_ */
/drivers/video/Gallium/auxiliary/util/u_double_list.h
0,0 → 1,147
/**************************************************************************
*
* Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND. USA.
* 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 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
* THE COPYRIGHT HOLDERS, AUTHORS 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.
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
**************************************************************************/
 
/**
* \file
* List macros heavily inspired by the Linux kernel
* list handling. No list looping yet.
*
* Is not threadsafe, so common operations need to
* be protected using an external mutex.
*/
 
#ifndef _U_DOUBLE_LIST_H_
#define _U_DOUBLE_LIST_H_
 
 
#include <stddef.h>
#include "pipe/p_compiler.h"
 
 
struct list_head
{
struct list_head *prev;
struct list_head *next;
};
 
static INLINE void list_inithead(struct list_head *item)
{
item->prev = item;
item->next = item;
}
 
static INLINE void list_add(struct list_head *item, struct list_head *list)
{
item->prev = list;
item->next = list->next;
list->next->prev = item;
list->next = item;
}
 
static INLINE void list_addtail(struct list_head *item, struct list_head *list)
{
item->next = list;
item->prev = list->prev;
list->prev->next = item;
list->prev = item;
}
 
static INLINE void list_replace(struct list_head *from, struct list_head *to)
{
to->prev = from->prev;
to->next = from->next;
from->next->prev = to;
from->prev->next = to;
}
 
static INLINE void list_del(struct list_head *item)
{
item->prev->next = item->next;
item->next->prev = item->prev;
item->prev = item->next = NULL;
}
 
static INLINE void list_delinit(struct list_head *item)
{
item->prev->next = item->next;
item->next->prev = item->prev;
item->next = item;
item->prev = item;
}
 
#define LIST_INITHEAD(__item) list_inithead(__item)
#define LIST_ADD(__item, __list) list_add(__item, __list)
#define LIST_ADDTAIL(__item, __list) list_addtail(__item, __list)
#define LIST_REPLACE(__from, __to) list_replace(__from, __to)
#define LIST_DEL(__item) list_del(__item)
#define LIST_DELINIT(__item) list_delinit(__item)
 
#define LIST_ENTRY(__type, __item, __field) \
((__type *)(((char *)(__item)) - offsetof(__type, __field)))
 
#define LIST_IS_EMPTY(__list) \
((__list)->next == (__list))
 
/**
* Cast from a pointer to a member of a struct back to the containing struct.
*
* 'sample' MUST be initialized, or else the result is undefined!
*/
#ifndef container_of
#define container_of(ptr, sample, member) \
(void *)((char *)(ptr) \
- ((char *)&(sample)->member - (char *)(sample)))
#endif
 
#define LIST_FOR_EACH_ENTRY(pos, head, member) \
for (pos = NULL, pos = container_of((head)->next, pos, member); \
&pos->member != (head); \
pos = container_of(pos->member.next, pos, member))
 
#define LIST_FOR_EACH_ENTRY_SAFE(pos, storage, head, member) \
for (pos = NULL, pos = container_of((head)->next, pos, member), \
storage = container_of(pos->member.next, pos, member); \
&pos->member != (head); \
pos = storage, storage = container_of(storage->member.next, storage, member))
 
#define LIST_FOR_EACH_ENTRY_SAFE_REV(pos, storage, head, member) \
for (pos = NULL, pos = container_of((head)->prev, pos, member), \
storage = container_of(pos->member.prev, pos, member); \
&pos->member != (head); \
pos = storage, storage = container_of(storage->member.prev, storage, member))
 
#define LIST_FOR_EACH_ENTRY_FROM(pos, start, head, member) \
for (pos = NULL, pos = container_of((start), pos, member); \
&pos->member != (head); \
pos = container_of(pos->member.next, pos, member))
 
#define LIST_FOR_EACH_ENTRY_FROM_REV(pos, start, head, member) \
for (pos = NULL, pos = container_of((start), pos, member); \
&pos->member != (head); \
pos = container_of(pos->member.prev, pos, member))
 
#endif /*_U_DOUBLE_LIST_H_*/
/drivers/video/Gallium/auxiliary/util/u_draw.c
0,0 → 1,125
/**************************************************************************
*
* Copyright 2011 VMware, Inc.
* 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 VMWARE 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.
*
**************************************************************************/
 
 
#include "util/u_debug.h"
#include "util/u_math.h"
#include "util/u_format.h"
#include "util/u_draw.h"
 
 
/**
* Returns the largest legal index value plus one for the current set
* of bound vertex buffers. Regardless of any other consideration,
* all vertex lookups need to be clamped to 0..max_index-1 to prevent
* an out-of-bound access.
*
* Note that if zero is returned it means that one or more buffers is
* too small to contain any valid vertex data.
*/
unsigned
util_draw_max_index(
const struct pipe_vertex_buffer *vertex_buffers,
const struct pipe_vertex_element *vertex_elements,
unsigned nr_vertex_elements,
const struct pipe_draw_info *info)
{
unsigned max_index;
unsigned i;
 
max_index = ~0U - 1;
for (i = 0; i < nr_vertex_elements; i++) {
const struct pipe_vertex_element *element =
&vertex_elements[i];
const struct pipe_vertex_buffer *buffer =
&vertex_buffers[element->vertex_buffer_index];
unsigned buffer_size;
const struct util_format_description *format_desc;
unsigned format_size;
 
if (!buffer->buffer) {
continue;
}
 
assert(buffer->buffer->height0 == 1);
assert(buffer->buffer->depth0 == 1);
buffer_size = buffer->buffer->width0;
 
format_desc = util_format_description(element->src_format);
assert(format_desc->block.width == 1);
assert(format_desc->block.height == 1);
assert(format_desc->block.bits % 8 == 0);
format_size = format_desc->block.bits/8;
 
if (buffer->buffer_offset >= buffer_size) {
/* buffer is too small */
return 0;
}
 
buffer_size -= buffer->buffer_offset;
 
if (element->src_offset >= buffer_size) {
/* buffer is too small */
return 0;
}
 
buffer_size -= element->src_offset;
 
if (format_size > buffer_size) {
/* buffer is too small */
return 0;
}
 
buffer_size -= format_size;
 
if (buffer->stride != 0) {
unsigned buffer_max_index;
 
buffer_max_index = buffer_size / buffer->stride;
 
if (element->instance_divisor == 0) {
/* Per-vertex data */
max_index = MIN2(max_index, buffer_max_index);
}
else {
/* Per-instance data. Simply make sure the state tracker didn't
* request more instances than those that fit in the buffer */
if ((info->start_instance + info->instance_count)/element->instance_divisor
> (buffer_max_index + 1)) {
/* FIXME: We really should stop thinking in terms of maximum
* indices/instances and simply start clamping against buffer
* size. */
debug_printf("%s: too many instances for vertex buffer\n",
__FUNCTION__);
return 0;
}
}
}
}
 
return max_index + 1;
}
/drivers/video/Gallium/auxiliary/util/u_draw.h
0,0 → 1,157
/**************************************************************************
*
* 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.
*
**************************************************************************/
 
#ifndef U_DRAW_H
#define U_DRAW_H
 
 
#include "pipe/p_compiler.h"
#include "pipe/p_context.h"
#include "pipe/p_state.h"
 
 
#ifdef __cplusplus
extern "C" {
#endif
 
 
static INLINE void
util_draw_init_info(struct pipe_draw_info *info)
{
memset(info, 0, sizeof(*info));
info->instance_count = 1;
info->max_index = 0xffffffff;
}
 
 
static INLINE void
util_draw_arrays(struct pipe_context *pipe, uint mode, uint start, uint count)
{
struct pipe_draw_info info;
 
util_draw_init_info(&info);
info.mode = mode;
info.start = start;
info.count = count;
info.min_index = start;
info.max_index = start + count - 1;
 
pipe->draw_vbo(pipe, &info);
}
 
static INLINE void
util_draw_elements(struct pipe_context *pipe, int index_bias,
uint mode, uint start, uint count)
{
struct pipe_draw_info info;
 
util_draw_init_info(&info);
info.indexed = TRUE;
info.mode = mode;
info.start = start;
info.count = count;
info.index_bias = index_bias;
 
pipe->draw_vbo(pipe, &info);
}
 
static INLINE void
util_draw_arrays_instanced(struct pipe_context *pipe,
uint mode, uint start, uint count,
uint start_instance,
uint instance_count)
{
struct pipe_draw_info info;
 
util_draw_init_info(&info);
info.mode = mode;
info.start = start;
info.count = count;
info.start_instance = start_instance;
info.instance_count = instance_count;
info.min_index = start;
info.max_index = start + count - 1;
 
pipe->draw_vbo(pipe, &info);
}
 
static INLINE void
util_draw_elements_instanced(struct pipe_context *pipe,
int index_bias,
uint mode, uint start, uint count,
uint start_instance,
uint instance_count)
{
struct pipe_draw_info info;
 
util_draw_init_info(&info);
info.indexed = TRUE;
info.mode = mode;
info.start = start;
info.count = count;
info.index_bias = index_bias;
info.start_instance = start_instance;
info.instance_count = instance_count;
 
pipe->draw_vbo(pipe, &info);
}
 
static INLINE void
util_draw_range_elements(struct pipe_context *pipe,
int index_bias,
uint min_index,
uint max_index,
uint mode, uint start, uint count)
{
struct pipe_draw_info info;
 
util_draw_init_info(&info);
info.indexed = TRUE;
info.mode = mode;
info.start = start;
info.count = count;
info.index_bias = index_bias;
info.min_index = min_index;
info.max_index = max_index;
 
pipe->draw_vbo(pipe, &info);
}
 
 
unsigned
util_draw_max_index(
const struct pipe_vertex_buffer *vertex_buffers,
const struct pipe_vertex_element *vertex_elements,
unsigned nr_vertex_elements,
const struct pipe_draw_info *info);
 
 
#ifdef __cplusplus
}
#endif
 
#endif /* !U_DRAW_H */
/drivers/video/Gallium/auxiliary/util/u_draw_quad.c
0,0 → 1,158
/**************************************************************************
*
* 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.
*
**************************************************************************/
 
 
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "util/u_inlines.h"
#include "util/u_draw_quad.h"
#include "util/u_memory.h"
#include "cso_cache/cso_context.h"
 
 
/**
* Draw a simple vertex buffer / primitive.
* Limited to float[4] vertex attribs, tightly packed.
*/
void
util_draw_vertex_buffer(struct pipe_context *pipe,
struct cso_context *cso,
struct pipe_resource *vbuf,
uint vbuf_slot,
uint offset,
uint prim_type,
uint num_verts,
uint num_attribs)
{
struct pipe_vertex_buffer vbuffer;
 
assert(num_attribs <= PIPE_MAX_ATTRIBS);
 
/* tell pipe about the vertex buffer */
memset(&vbuffer, 0, sizeof(vbuffer));
vbuffer.buffer = vbuf;
vbuffer.stride = num_attribs * 4 * sizeof(float); /* vertex size */
vbuffer.buffer_offset = offset;
 
/* note: vertex elements already set by caller */
 
if (cso) {
cso_set_vertex_buffers(cso, vbuf_slot, 1, &vbuffer);
cso_draw_arrays(cso, prim_type, 0, num_verts);
} else {
pipe->set_vertex_buffers(pipe, vbuf_slot, 1, &vbuffer);
util_draw_arrays(pipe, prim_type, 0, num_verts);
}
}
 
 
/**
* Draw a simple vertex buffer / primitive.
* Limited to float[4] vertex attribs, tightly packed.
*/
void
util_draw_user_vertex_buffer(struct cso_context *cso, void *buffer,
uint prim_type, uint num_verts, uint num_attribs)
{
struct pipe_vertex_buffer vbuffer = {0};
 
assert(num_attribs <= PIPE_MAX_ATTRIBS);
 
vbuffer.user_buffer = buffer;
vbuffer.stride = num_attribs * 4 * sizeof(float); /* vertex size */
 
/* note: vertex elements already set by caller */
 
cso_set_vertex_buffers(cso, 0, 1, &vbuffer);
cso_draw_arrays(cso, prim_type, 0, num_verts);
}
 
 
/**
* Draw screen-aligned textured quad.
* Note: this isn't especially efficient.
*/
void
util_draw_texquad(struct pipe_context *pipe, struct cso_context *cso,
uint vbuf_slot,
float x0, float y0, float x1, float y1, float z)
{
uint numAttribs = 2, i, j;
uint vertexBytes = 4 * (4 * numAttribs * sizeof(float));
struct pipe_resource *vbuf = NULL;
float *v = NULL;
 
v = MALLOC(vertexBytes);
if (v == NULL)
goto out;
 
/*
* Load vertex buffer
*/
for (i = j = 0; i < 4; i++) {
v[j + 2] = z; /* z */
v[j + 3] = 1.0; /* w */
v[j + 6] = 0.0; /* r */
v[j + 7] = 1.0; /* q */
j += 8;
}
 
v[0] = x0;
v[1] = y0;
v[4] = 0.0; /*s*/
v[5] = 0.0; /*t*/
 
v[8] = x1;
v[9] = y0;
v[12] = 1.0;
v[13] = 0.0;
 
v[16] = x1;
v[17] = y1;
v[20] = 1.0;
v[21] = 1.0;
 
v[24] = x0;
v[25] = y1;
v[28] = 0.0;
v[29] = 1.0;
vbuf = pipe_buffer_create(pipe->screen, PIPE_BIND_VERTEX_BUFFER,
PIPE_USAGE_STAGING, vertexBytes);
if (!vbuf)
goto out;
pipe_buffer_write(pipe, vbuf, 0, vertexBytes, v);
 
util_draw_vertex_buffer(pipe, cso, vbuf, vbuf_slot, 0,
PIPE_PRIM_TRIANGLE_FAN, 4, 2);
 
out:
if (vbuf)
pipe_resource_reference(&vbuf, NULL);
FREE(v);
}
/drivers/video/Gallium/auxiliary/util/u_draw_quad.h
0,0 → 1,66
/**************************************************************************
*
* 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.
*
**************************************************************************/
 
#ifndef U_DRAWQUAD_H
#define U_DRAWQUAD_H
 
 
#include "pipe/p_compiler.h"
#include "pipe/p_context.h"
 
 
#ifdef __cplusplus
extern "C" {
#endif
 
struct pipe_resource;
struct cso_context;
 
#include "util/u_draw.h"
 
extern void
util_draw_vertex_buffer(struct pipe_context *pipe, struct cso_context *cso,
struct pipe_resource *vbuf, uint vbuf_slot,
uint offset, uint prim_type, uint num_attribs,
uint num_verts);
 
void
util_draw_user_vertex_buffer(struct cso_context *cso, void *buffer,
uint prim_type, uint num_verts, uint num_attribs);
 
extern void
util_draw_texquad(struct pipe_context *pipe, struct cso_context *cso,
uint vbuf_slot,
float x0, float y0, float x1, float y1, float z);
 
 
#ifdef __cplusplus
}
#endif
 
 
#endif
/drivers/video/Gallium/auxiliary/util/u_dual_blend.h
0,0 → 1,26
#ifndef U_DUAL_BLEND_H
#define U_DUAL_BLEND_H
 
#include "pipe/p_state.h"
 
static INLINE boolean util_blend_factor_is_dual_src(int factor)
{
return (factor == PIPE_BLENDFACTOR_SRC1_COLOR) ||
(factor == PIPE_BLENDFACTOR_SRC1_ALPHA) ||
(factor == PIPE_BLENDFACTOR_INV_SRC1_COLOR) ||
(factor == PIPE_BLENDFACTOR_INV_SRC1_ALPHA);
}
 
static INLINE boolean util_blend_state_is_dual(const struct pipe_blend_state *blend,
int index)
{
if (util_blend_factor_is_dual_src(blend->rt[index].rgb_src_factor) ||
util_blend_factor_is_dual_src(blend->rt[index].alpha_src_factor) ||
util_blend_factor_is_dual_src(blend->rt[index].rgb_dst_factor) ||
util_blend_factor_is_dual_src(blend->rt[index].alpha_dst_factor))
return true;
return false;
}
 
 
#endif
/drivers/video/Gallium/auxiliary/util/u_dump.h
0,0 → 1,181
/**************************************************************************
*
* Copyright 2009 VMware, Inc.
* 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 VMWARE 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
* Dump data in human/machine readable format.
*
* @author Jose Fonseca <jfonseca@vmware.com>
*/
 
#ifndef U_DEBUG_DUMP_H_
#define U_DEBUG_DUMP_H_
 
 
#include "pipe/p_compiler.h"
#include "pipe/p_state.h"
 
#include <stdio.h>
 
 
#ifdef __cplusplus
extern "C" {
#endif
 
 
#define UTIL_DUMP_INVALID_NAME "<invalid>"
 
 
/*
* p_defines.h
*
* XXX: These functions don't really dump anything -- just translate into
* strings so a verb better than "dump" should be used instead, in order to
* free up the namespace to the true dumper functions.
*/
 
const char *
util_dump_blend_factor(unsigned value, boolean shortened);
 
const char *
util_dump_blend_func(unsigned value, boolean shortened);
 
const char *
util_dump_logicop(unsigned value, boolean shortened);
 
const char *
util_dump_func(unsigned value, boolean shortened);
 
const char *
util_dump_stencil_op(unsigned value, boolean shortened);
 
const char *
util_dump_tex_target(unsigned value, boolean shortened);
 
const char *
util_dump_tex_wrap(unsigned value, boolean shortened);
 
const char *
util_dump_tex_mipfilter(unsigned value, boolean shortened);
 
const char *
util_dump_tex_filter(unsigned value, boolean shortened);
 
 
/*
* p_state.h, through a FILE
*/
 
void
util_dump_template(FILE *stream,
const struct pipe_resource *templat);
 
void
util_dump_rasterizer_state(FILE *stream,
const struct pipe_rasterizer_state *state);
 
void
util_dump_poly_stipple(FILE *stream,
const struct pipe_poly_stipple *state);
 
void
util_dump_viewport_state(FILE *stream,
const struct pipe_viewport_state *state);
 
void
util_dump_scissor_state(FILE *stream,
const struct pipe_scissor_state *state);
 
void
util_dump_clip_state(FILE *stream,
const struct pipe_clip_state *state);
 
void
util_dump_shader_state(FILE *stream,
const struct pipe_shader_state *state);
 
void
util_dump_depth_stencil_alpha_state(FILE *stream,
const struct pipe_depth_stencil_alpha_state *state);
 
void
util_dump_rt_blend_state(FILE *stream,
const struct pipe_rt_blend_state *state);
 
void
util_dump_blend_state(FILE *stream,
const struct pipe_blend_state *state);
 
void
util_dump_blend_color(FILE *stream,
const struct pipe_blend_color *state);
 
void
util_dump_stencil_ref(FILE *stream,
const struct pipe_stencil_ref *state);
 
void
util_dump_framebuffer_state(FILE *stream,
const struct pipe_framebuffer_state *state);
 
void
util_dump_sampler_state(FILE *stream,
const struct pipe_sampler_state *state);
 
void
util_dump_surface(FILE *stream,
const struct pipe_surface *state);
 
void
util_dump_transfer(FILE *stream,
const struct pipe_transfer *state);
 
void
util_dump_vertex_buffer(FILE *stream,
const struct pipe_vertex_buffer *state);
 
void
util_dump_vertex_element(FILE *stream,
const struct pipe_vertex_element *state);
 
void
util_dump_draw_info(FILE *stream, const struct pipe_draw_info *state);
 
void
util_dump_box(FILE *stream, const struct pipe_box *box);
 
void
util_dump_blit_info(FILE *stream, const struct pipe_blit_info *info);
 
/* FIXME: Move the other debug_dump_xxx functions out of u_debug.h into here. */
 
 
#ifdef __cplusplus
}
#endif
 
#endif /* U_DEBUG_H_ */
/drivers/video/Gallium/auxiliary/util/u_dump_defines.c
0,0 → 1,361
/**************************************************************************
*
* Copyright 2009 VMware, Inc.
* 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 VMWARE 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.
*
**************************************************************************/
 
 
#include "util/u_memory.h"
#include "util/u_debug.h"
#include "util/u_dump.h"
 
 
#if 0
static const char *
util_dump_strip_prefix(const char *name,
const char *prefix)
{
const char *stripped;
assert(name);
assert(prefix);
stripped = name;
while(*prefix) {
if(*stripped != *prefix)
return name;
 
++stripped;
++prefix;
}
return stripped;
}
#endif
 
static const char *
util_dump_enum_continuous(unsigned value,
unsigned num_names,
const char **names)
{
if (value >= num_names)
return UTIL_DUMP_INVALID_NAME;
return names[value];
}
 
 
#define DEFINE_UTIL_DUMP_CONTINUOUS(_name) \
const char * \
util_dump_##_name(unsigned value, boolean shortened) \
{ \
if(shortened) \
return util_dump_enum_continuous(value, Elements(util_dump_##_name##_short_names), util_dump_##_name##_short_names); \
else \
return util_dump_enum_continuous(value, Elements(util_dump_##_name##_names), util_dump_##_name##_names); \
}
 
 
/**
* Same as DEFINE_UTIL_DUMP_CONTINUOUS but with static assertions to detect
* failures to update lists.
*/
#define DEFINE_UTIL_DUMP_CONTINUOUS_COUNT(_name, _count) \
const char * \
util_dump_##_name(unsigned value, boolean shortened) \
{ \
STATIC_ASSERT(Elements(util_dump_##_name##_names) == _count); \
STATIC_ASSERT(Elements(util_dump_##_name##_short_names) == _count); \
if(shortened) \
return util_dump_enum_continuous(value, Elements(util_dump_##_name##_short_names), util_dump_##_name##_short_names); \
else \
return util_dump_enum_continuous(value, Elements(util_dump_##_name##_names), util_dump_##_name##_names); \
}
 
 
static const char *
util_dump_blend_factor_names[] = {
UTIL_DUMP_INVALID_NAME, /* 0x0 */
"PIPE_BLENDFACTOR_ONE",
"PIPE_BLENDFACTOR_SRC_COLOR",
"PIPE_BLENDFACTOR_SRC_ALPHA",
"PIPE_BLENDFACTOR_DST_ALPHA",
"PIPE_BLENDFACTOR_DST_COLOR",
"PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE",
"PIPE_BLENDFACTOR_CONST_COLOR",
"PIPE_BLENDFACTOR_CONST_ALPHA",
"PIPE_BLENDFACTOR_SRC1_COLOR",
"PIPE_BLENDFACTOR_SRC1_ALPHA",
UTIL_DUMP_INVALID_NAME, /* 0x0b */
UTIL_DUMP_INVALID_NAME, /* 0x0c */
UTIL_DUMP_INVALID_NAME, /* 0x0d */
UTIL_DUMP_INVALID_NAME, /* 0x0e */
UTIL_DUMP_INVALID_NAME, /* 0x0f */
UTIL_DUMP_INVALID_NAME, /* 0x10 */
"PIPE_BLENDFACTOR_ZERO",
"PIPE_BLENDFACTOR_INV_SRC_COLOR",
"PIPE_BLENDFACTOR_INV_SRC_ALPHA",
"PIPE_BLENDFACTOR_INV_DST_ALPHA",
"PIPE_BLENDFACTOR_INV_DST_COLOR",
UTIL_DUMP_INVALID_NAME, /* 0x16 */
"PIPE_BLENDFACTOR_INV_CONST_COLOR",
"PIPE_BLENDFACTOR_INV_CONST_ALPHA",
"PIPE_BLENDFACTOR_INV_SRC1_COLOR",
"PIPE_BLENDFACTOR_INV_SRC1_ALPHA"
};
 
static const char *
util_dump_blend_factor_short_names[] = {
UTIL_DUMP_INVALID_NAME, /* 0x0 */
"one",
"src_color",
"src_alpha",
"dst_alpha",
"dst_color",
"src_alpha_saturate",
"const_color",
"const_alpha",
"src1_color",
"src1_alpha",
UTIL_DUMP_INVALID_NAME, /* 0x0b */
UTIL_DUMP_INVALID_NAME, /* 0x0c */
UTIL_DUMP_INVALID_NAME, /* 0x0d */
UTIL_DUMP_INVALID_NAME, /* 0x0e */
UTIL_DUMP_INVALID_NAME, /* 0x0f */
UTIL_DUMP_INVALID_NAME, /* 0x10 */
"zero",
"inv_src_color",
"inv_src_alpha",
"inv_dst_alpha",
"inv_dst_color",
UTIL_DUMP_INVALID_NAME, /* 0x16 */
"inv_const_color",
"inv_const_alpha",
"inv_src1_color",
"inv_src1_alpha"
};
 
DEFINE_UTIL_DUMP_CONTINUOUS(blend_factor)
 
 
static const char *
util_dump_blend_func_names[] = {
"PIPE_BLEND_ADD",
"PIPE_BLEND_SUBTRACT",
"PIPE_BLEND_REVERSE_SUBTRACT",
"PIPE_BLEND_MIN",
"PIPE_BLEND_MAX"
};
 
static const char *
util_dump_blend_func_short_names[] = {
"add",
"sub",
"rev_sub",
"min",
"max"
};
 
DEFINE_UTIL_DUMP_CONTINUOUS(blend_func)
 
 
static const char *
util_dump_logicop_names[] = {
"PIPE_LOGICOP_CLEAR",
"PIPE_LOGICOP_NOR",
"PIPE_LOGICOP_AND_INVERTED",
"PIPE_LOGICOP_COPY_INVERTED",
"PIPE_LOGICOP_AND_REVERSE",
"PIPE_LOGICOP_INVERT",
"PIPE_LOGICOP_XOR",
"PIPE_LOGICOP_NAND",
"PIPE_LOGICOP_AND",
"PIPE_LOGICOP_EQUIV",
"PIPE_LOGICOP_NOOP",
"PIPE_LOGICOP_OR_INVERTED",
"PIPE_LOGICOP_COPY",
"PIPE_LOGICOP_OR_REVERSE",
"PIPE_LOGICOP_OR",
"PIPE_LOGICOP_SET"
};
 
static const char *
util_dump_logicop_short_names[] = {
"clear",
"nor",
"and_inverted",
"copy_inverted",
"and_reverse",
"invert",
"xor",
"nand",
"and",
"equiv",
"noop",
"or_inverted",
"copy",
"or_reverse",
"or",
"set"
};
 
DEFINE_UTIL_DUMP_CONTINUOUS(logicop)
 
 
static const char *
util_dump_func_names[] = {
"PIPE_FUNC_NEVER",
"PIPE_FUNC_LESS",
"PIPE_FUNC_EQUAL",
"PIPE_FUNC_LEQUAL",
"PIPE_FUNC_GREATER",
"PIPE_FUNC_NOTEQUAL",
"PIPE_FUNC_GEQUAL",
"PIPE_FUNC_ALWAYS"
};
 
static const char *
util_dump_func_short_names[] = {
"never",
"less",
"equal",
"less_equal",
"greater",
"not_equal",
"greater_equal",
"always"
};
 
DEFINE_UTIL_DUMP_CONTINUOUS(func)
 
 
static const char *
util_dump_stencil_op_names[] = {
"PIPE_STENCIL_OP_KEEP",
"PIPE_STENCIL_OP_ZERO",
"PIPE_STENCIL_OP_REPLACE",
"PIPE_STENCIL_OP_INCR",
"PIPE_STENCIL_OP_DECR",
"PIPE_STENCIL_OP_INCR_WRAP",
"PIPE_STENCIL_OP_DECR_WRAP",
"PIPE_STENCIL_OP_INVERT"
};
 
static const char *
util_dump_stencil_op_short_names[] = {
"keep",
"zero",
"replace",
"incr",
"decr",
"incr_wrap",
"decr_wrap",
"invert"
};
 
DEFINE_UTIL_DUMP_CONTINUOUS(stencil_op)
 
 
static const char *
util_dump_tex_target_names[] = {
"PIPE_BUFFER",
"PIPE_TEXTURE_1D",
"PIPE_TEXTURE_2D",
"PIPE_TEXTURE_3D",
"PIPE_TEXTURE_CUBE",
"PIPE_TEXTURE_RECT",
"PIPE_TEXTURE_1D_ARRAY",
"PIPE_TEXTURE_2D_ARRAY",
"PIPE_TEXTURE_CUBE_ARRAY",
};
 
static const char *
util_dump_tex_target_short_names[] = {
"buffer",
"1d",
"2d",
"3d",
"cube",
"rect",
"1d_array",
"2d_array",
"cube_array",
};
 
DEFINE_UTIL_DUMP_CONTINUOUS_COUNT(tex_target, PIPE_MAX_TEXTURE_TYPES)
 
 
static const char *
util_dump_tex_wrap_names[] = {
"PIPE_TEX_WRAP_REPEAT",
"PIPE_TEX_WRAP_CLAMP",
"PIPE_TEX_WRAP_CLAMP_TO_EDGE",
"PIPE_TEX_WRAP_CLAMP_TO_BORDER",
"PIPE_TEX_WRAP_MIRROR_REPEAT",
"PIPE_TEX_WRAP_MIRROR_CLAMP",
"PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE",
"PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER"
};
 
static const char *
util_dump_tex_wrap_short_names[] = {
"repeat",
"clamp",
"clamp_to_edge",
"clamp_to_border",
"mirror_repeat",
"mirror_clamp",
"mirror_clamp_to_edge",
"mirror_clamp_to_border"
};
 
DEFINE_UTIL_DUMP_CONTINUOUS(tex_wrap)
 
 
static const char *
util_dump_tex_mipfilter_names[] = {
"PIPE_TEX_MIPFILTER_NEAREST",
"PIPE_TEX_MIPFILTER_LINEAR",
"PIPE_TEX_MIPFILTER_NONE"
};
 
static const char *
util_dump_tex_mipfilter_short_names[] = {
"nearest",
"linear",
"none"
};
 
DEFINE_UTIL_DUMP_CONTINUOUS(tex_mipfilter)
 
 
static const char *
util_dump_tex_filter_names[] = {
"PIPE_TEX_FILTER_NEAREST",
"PIPE_TEX_FILTER_LINEAR"
};
 
static const char *
util_dump_tex_filter_short_names[] = {
"nearest",
"linear"
};
 
DEFINE_UTIL_DUMP_CONTINUOUS(tex_filter)
/drivers/video/Gallium/auxiliary/util/u_dump_state.c
0,0 → 1,836
/**************************************************************************
*
* Copyright 2008-2010 VMware, Inc.
* 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 VMWARE 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.
*
**************************************************************************/
 
 
#include "pipe/p_compiler.h"
#include "util/u_memory.h"
#include "util/u_string.h"
#include "util/u_format.h"
#include "tgsi/tgsi_dump.h"
 
#include "u_dump.h"
 
 
/*
* Dump primitives
*/
 
static INLINE void
util_stream_writef(FILE *stream, const char *format, ...)
{
static char buf[1024];
unsigned len;
va_list ap;
va_start(ap, format);
len = util_vsnprintf(buf, sizeof(buf), format, ap);
va_end(ap);
fwrite(buf, len, 1, stream);
}
 
static void
util_dump_bool(FILE *stream, int value)
{
util_stream_writef(stream, "%c", value ? '1' : '0');
}
 
static void
util_dump_int(FILE *stream, long long int value)
{
util_stream_writef(stream, "%lli", value);
}
 
static void
util_dump_uint(FILE *stream, long long unsigned value)
{
util_stream_writef(stream, "%llu", value);
}
 
static void
util_dump_float(FILE *stream, double value)
{
util_stream_writef(stream, "%g", value);
}
 
static void
util_dump_string(FILE *stream, const char *str)
{
fputs("\"", stream);
fputs(str, stream);
fputs("\"", stream);
}
 
static void
util_dump_enum(FILE *stream, const char *value)
{
fputs(value, stream);
}
 
static void
util_dump_array_begin(FILE *stream)
{
fputs("{", stream);
}
 
static void
util_dump_array_end(FILE *stream)
{
fputs("}", stream);
}
 
static void
util_dump_elem_begin(FILE *stream)
{
}
 
static void
util_dump_elem_end(FILE *stream)
{
fputs(", ", stream);
}
 
static void
util_dump_struct_begin(FILE *stream, const char *name)
{
fputs("{", stream);
}
 
static void
util_dump_struct_end(FILE *stream)
{
fputs("}", stream);
}
 
static void
util_dump_member_begin(FILE *stream, const char *name)
{
util_stream_writef(stream, "%s = ", name);
}
 
static void
util_dump_member_end(FILE *stream)
{
fputs(", ", stream);
}
 
static void
util_dump_null(FILE *stream)
{
fputs("NULL", stream);
}
 
static void
util_dump_ptr(FILE *stream, const void *value)
{
if(value)
util_stream_writef(stream, "0x%08lx", (unsigned long)(uintptr_t)value);
else
util_dump_null(stream);
}
 
 
/*
* Code saving macros.
*/
 
#define util_dump_arg(_stream, _type, _arg) \
do { \
util_dump_arg_begin(_stream, #_arg); \
util_dump_##_type(_stream, _arg); \
util_dump_arg_end(_stream); \
} while(0)
 
#define util_dump_ret(_stream, _type, _arg) \
do { \
util_dump_ret_begin(_stream); \
util_dump_##_type(_stream, _arg); \
util_dump_ret_end(_stream); \
} while(0)
 
#define util_dump_array(_stream, _type, _obj, _size) \
do { \
size_t idx; \
util_dump_array_begin(_stream); \
for(idx = 0; idx < (_size); ++idx) { \
util_dump_elem_begin(_stream); \
util_dump_##_type(_stream, (_obj)[idx]); \
util_dump_elem_end(_stream); \
} \
util_dump_array_end(_stream); \
} while(0)
 
#define util_dump_struct_array(_stream, _type, _obj, _size) \
do { \
size_t idx; \
util_dump_array_begin(_stream); \
for(idx = 0; idx < (_size); ++idx) { \
util_dump_elem_begin(_stream); \
util_dump_##_type(_stream, &(_obj)[idx]); \
util_dump_elem_end(_stream); \
} \
util_dump_array_end(_stream); \
} while(0)
 
#define util_dump_member(_stream, _type, _obj, _member) \
do { \
util_dump_member_begin(_stream, #_member); \
util_dump_##_type(_stream, (_obj)->_member); \
util_dump_member_end(_stream); \
} while(0)
 
#define util_dump_arg_array(_stream, _type, _arg, _size) \
do { \
util_dump_arg_begin(_stream, #_arg); \
util_dump_array(_stream, _type, _arg, _size); \
util_dump_arg_end(_stream); \
} while(0)
 
#define util_dump_member_array(_stream, _type, _obj, _member) \
do { \
util_dump_member_begin(_stream, #_member); \
util_dump_array(_stream, _type, (_obj)->_member, sizeof((_obj)->_member)/sizeof((_obj)->_member[0])); \
util_dump_member_end(_stream); \
} while(0)
 
 
 
/*
* Wrappers for enum -> string dumpers.
*/
 
 
static void
util_dump_format(FILE *stream, enum pipe_format format)
{
util_dump_enum(stream, util_format_name(format));
}
 
 
static void
util_dump_enum_blend_factor(FILE *stream, unsigned value)
{
util_dump_enum(stream, util_dump_blend_factor(value, TRUE));
}
 
static void
util_dump_enum_blend_func(FILE *stream, unsigned value)
{
util_dump_enum(stream, util_dump_blend_func(value, TRUE));
}
 
static void
util_dump_enum_func(FILE *stream, unsigned value)
{
util_dump_enum(stream, util_dump_func(value, TRUE));
}
 
 
/*
* Public functions
*/
 
 
void
util_dump_template(FILE *stream, const struct pipe_resource *templat)
{
if(!templat) {
util_dump_null(stream);
return;
}
 
util_dump_struct_begin(stream, "pipe_resource");
 
util_dump_member(stream, int, templat, target);
util_dump_member(stream, format, templat, format);
 
util_dump_member_begin(stream, "width");
util_dump_uint(stream, templat->width0);
util_dump_member_end(stream);
 
util_dump_member_begin(stream, "height");
util_dump_uint(stream, templat->height0);
util_dump_member_end(stream);
 
util_dump_member_begin(stream, "depth");
util_dump_uint(stream, templat->depth0);
util_dump_member_end(stream);
 
util_dump_member_begin(stream, "array_size");
util_dump_uint(stream, templat->array_size);
util_dump_member_end(stream);
 
util_dump_member(stream, uint, templat, last_level);
util_dump_member(stream, uint, templat, usage);
util_dump_member(stream, uint, templat, bind);
util_dump_member(stream, uint, templat, flags);
 
util_dump_struct_end(stream);
}
 
 
void
util_dump_rasterizer_state(FILE *stream, const struct pipe_rasterizer_state *state)
{
if(!state) {
util_dump_null(stream);
return;
}
 
util_dump_struct_begin(stream, "pipe_rasterizer_state");
 
util_dump_member(stream, bool, state, flatshade);
util_dump_member(stream, bool, state, light_twoside);
util_dump_member(stream, bool, state, clamp_vertex_color);
util_dump_member(stream, bool, state, clamp_fragment_color);
util_dump_member(stream, uint, state, front_ccw);
util_dump_member(stream, uint, state, cull_face);
util_dump_member(stream, uint, state, fill_front);
util_dump_member(stream, uint, state, fill_back);
util_dump_member(stream, bool, state, offset_point);
util_dump_member(stream, bool, state, offset_line);
util_dump_member(stream, bool, state, offset_tri);
util_dump_member(stream, bool, state, scissor);
util_dump_member(stream, bool, state, poly_smooth);
util_dump_member(stream, bool, state, poly_stipple_enable);
util_dump_member(stream, bool, state, point_smooth);
util_dump_member(stream, uint, state, sprite_coord_enable);
util_dump_member(stream, bool, state, sprite_coord_mode);
util_dump_member(stream, bool, state, point_quad_rasterization);
util_dump_member(stream, bool, state, point_size_per_vertex);
util_dump_member(stream, bool, state, multisample);
util_dump_member(stream, bool, state, line_smooth);
util_dump_member(stream, bool, state, line_stipple_enable);
util_dump_member(stream, uint, state, line_stipple_factor);
util_dump_member(stream, uint, state, line_stipple_pattern);
util_dump_member(stream, bool, state, line_last_pixel);
util_dump_member(stream, bool, state, flatshade_first);
util_dump_member(stream, bool, state, half_pixel_center);
util_dump_member(stream, bool, state, bottom_edge_rule);
util_dump_member(stream, bool, state, rasterizer_discard);
util_dump_member(stream, bool, state, depth_clip);
util_dump_member(stream, uint, state, clip_plane_enable);
 
util_dump_member(stream, float, state, line_width);
util_dump_member(stream, float, state, point_size);
util_dump_member(stream, float, state, offset_units);
util_dump_member(stream, float, state, offset_scale);
util_dump_member(stream, float, state, offset_clamp);
 
util_dump_struct_end(stream);
}
 
 
void
util_dump_poly_stipple(FILE *stream, const struct pipe_poly_stipple *state)
{
if(!state) {
util_dump_null(stream);
return;
}
 
util_dump_struct_begin(stream, "pipe_poly_stipple");
 
util_dump_member_begin(stream, "stipple");
util_dump_member_array(stream, uint, state, stipple);
util_dump_member_end(stream);
 
util_dump_struct_end(stream);
}
 
 
void
util_dump_viewport_state(FILE *stream, const struct pipe_viewport_state *state)
{
if(!state) {
util_dump_null(stream);
return;
}
 
util_dump_struct_begin(stream, "pipe_viewport_state");
 
util_dump_member_array(stream, float, state, scale);
util_dump_member_array(stream, float, state, translate);
 
util_dump_struct_end(stream);
}
 
 
void
util_dump_scissor_state(FILE *stream, const struct pipe_scissor_state *state)
{
if(!state) {
util_dump_null(stream);
return;
}
 
util_dump_struct_begin(stream, "pipe_scissor_state");
 
util_dump_member(stream, uint, state, minx);
util_dump_member(stream, uint, state, miny);
util_dump_member(stream, uint, state, maxx);
util_dump_member(stream, uint, state, maxy);
 
util_dump_struct_end(stream);
}
 
 
void
util_dump_clip_state(FILE *stream, const struct pipe_clip_state *state)
{
unsigned i;
 
if(!state) {
util_dump_null(stream);
return;
}
 
util_dump_struct_begin(stream, "pipe_clip_state");
 
util_dump_member_begin(stream, "ucp");
util_dump_array_begin(stream);
for(i = 0; i < PIPE_MAX_CLIP_PLANES; ++i) {
util_dump_elem_begin(stream);
util_dump_array(stream, float, state->ucp[i], 4);
util_dump_elem_end(stream);
}
util_dump_array_end(stream);
util_dump_member_end(stream);
 
util_dump_struct_end(stream);
}
 
 
void
util_dump_shader_state(FILE *stream, const struct pipe_shader_state *state)
{
char str[8192];
unsigned i;
 
if(!state) {
util_dump_null(stream);
return;
}
 
tgsi_dump_str(state->tokens, 0, str, sizeof(str));
 
util_dump_struct_begin(stream, "pipe_shader_state");
 
util_dump_member_begin(stream, "tokens");
util_dump_string(stream, str);
util_dump_member_end(stream);
 
util_dump_member_begin(stream, "stream_output");
util_dump_struct_begin(stream, "pipe_stream_output_info");
util_dump_member(stream, uint, &state->stream_output, num_outputs);
util_dump_array(stream, uint, state->stream_output.stride,
Elements(state->stream_output.stride));
util_dump_array_begin(stream);
for(i = 0; i < state->stream_output.num_outputs; ++i) {
util_dump_elem_begin(stream);
util_dump_struct_begin(stream, ""); /* anonymous */
util_dump_member(stream, uint, &state->stream_output.output[i], register_index);
util_dump_member(stream, uint, &state->stream_output.output[i], start_component);
util_dump_member(stream, uint, &state->stream_output.output[i], num_components);
util_dump_member(stream, uint, &state->stream_output.output[i], output_buffer);
util_dump_struct_end(stream);
util_dump_elem_end(stream);
}
util_dump_array_end(stream);
util_dump_struct_end(stream);
util_dump_member_end(stream);
 
util_dump_struct_end(stream);
}
 
 
void
util_dump_depth_stencil_alpha_state(FILE *stream, const struct pipe_depth_stencil_alpha_state *state)
{
unsigned i;
 
if(!state) {
util_dump_null(stream);
return;
}
 
util_dump_struct_begin(stream, "pipe_depth_stencil_alpha_state");
 
util_dump_member_begin(stream, "depth");
util_dump_struct_begin(stream, "pipe_depth_state");
util_dump_member(stream, bool, &state->depth, enabled);
if (state->depth.enabled) {
util_dump_member(stream, bool, &state->depth, writemask);
util_dump_member(stream, enum_func, &state->depth, func);
}
util_dump_struct_end(stream);
util_dump_member_end(stream);
 
util_dump_member_begin(stream, "stencil");
util_dump_array_begin(stream);
for(i = 0; i < Elements(state->stencil); ++i) {
util_dump_elem_begin(stream);
util_dump_struct_begin(stream, "pipe_stencil_state");
util_dump_member(stream, bool, &state->stencil[i], enabled);
if (state->stencil[i].enabled) {
util_dump_member(stream, enum_func, &state->stencil[i], func);
util_dump_member(stream, uint, &state->stencil[i], fail_op);
util_dump_member(stream, uint, &state->stencil[i], zpass_op);
util_dump_member(stream, uint, &state->stencil[i], zfail_op);
util_dump_member(stream, uint, &state->stencil[i], valuemask);
util_dump_member(stream, uint, &state->stencil[i], writemask);
}
util_dump_struct_end(stream);
util_dump_elem_end(stream);
}
util_dump_array_end(stream);
util_dump_member_end(stream);
 
util_dump_member_begin(stream, "alpha");
util_dump_struct_begin(stream, "pipe_alpha_state");
util_dump_member(stream, bool, &state->alpha, enabled);
if (state->alpha.enabled) {
util_dump_member(stream, enum_func, &state->alpha, func);
util_dump_member(stream, float, &state->alpha, ref_value);
}
util_dump_struct_end(stream);
util_dump_member_end(stream);
 
util_dump_struct_end(stream);
}
 
void
util_dump_rt_blend_state(FILE *stream, const struct pipe_rt_blend_state *state)
{
util_dump_struct_begin(stream, "pipe_rt_blend_state");
 
util_dump_member(stream, uint, state, blend_enable);
if (state->blend_enable) {
util_dump_member(stream, enum_blend_func, state, rgb_func);
util_dump_member(stream, enum_blend_factor, state, rgb_src_factor);
util_dump_member(stream, enum_blend_factor, state, rgb_dst_factor);
 
util_dump_member(stream, enum_blend_func, state, alpha_func);
util_dump_member(stream, enum_blend_factor, state, alpha_src_factor);
util_dump_member(stream, enum_blend_factor, state, alpha_dst_factor);
}
 
util_dump_member(stream, uint, state, colormask);
 
util_dump_struct_end(stream);
}
 
void
util_dump_blend_state(FILE *stream, const struct pipe_blend_state *state)
{
unsigned valid_entries = 1;
 
if(!state) {
util_dump_null(stream);
return;
}
 
util_dump_struct_begin(stream, "pipe_blend_state");
 
util_dump_member(stream, bool, state, dither);
 
util_dump_member(stream, bool, state, logicop_enable);
if (state->logicop_enable) {
util_dump_member(stream, enum_func, state, logicop_func);
}
else {
util_dump_member(stream, bool, state, independent_blend_enable);
 
util_dump_member_begin(stream, "rt");
if (state->independent_blend_enable)
valid_entries = PIPE_MAX_COLOR_BUFS;
util_dump_struct_array(stream, rt_blend_state, state->rt, valid_entries);
util_dump_member_end(stream);
}
 
util_dump_struct_end(stream);
}
 
 
void
util_dump_blend_color(FILE *stream, const struct pipe_blend_color *state)
{
if(!state) {
util_dump_null(stream);
return;
}
 
util_dump_struct_begin(stream, "pipe_blend_color");
 
util_dump_member_array(stream, float, state, color);
 
util_dump_struct_end(stream);
}
 
void
util_dump_stencil_ref(FILE *stream, const struct pipe_stencil_ref *state)
{
if(!state) {
util_dump_null(stream);
return;
}
 
util_dump_struct_begin(stream, "pipe_stencil_ref");
 
util_dump_member_array(stream, uint, state, ref_value);
 
util_dump_struct_end(stream);
}
 
void
util_dump_framebuffer_state(FILE *stream, const struct pipe_framebuffer_state *state)
{
util_dump_struct_begin(stream, "pipe_framebuffer_state");
 
util_dump_member(stream, uint, state, width);
util_dump_member(stream, uint, state, height);
util_dump_member(stream, uint, state, nr_cbufs);
util_dump_member_array(stream, ptr, state, cbufs);
util_dump_member(stream, ptr, state, zsbuf);
 
util_dump_struct_end(stream);
}
 
 
void
util_dump_sampler_state(FILE *stream, const struct pipe_sampler_state *state)
{
if(!state) {
util_dump_null(stream);
return;
}
 
util_dump_struct_begin(stream, "pipe_sampler_state");
 
util_dump_member(stream, uint, state, wrap_s);
util_dump_member(stream, uint, state, wrap_t);
util_dump_member(stream, uint, state, wrap_r);
util_dump_member(stream, uint, state, min_img_filter);
util_dump_member(stream, uint, state, min_mip_filter);
util_dump_member(stream, uint, state, mag_img_filter);
util_dump_member(stream, uint, state, compare_mode);
util_dump_member(stream, enum_func, state, compare_func);
util_dump_member(stream, bool, state, normalized_coords);
util_dump_member(stream, uint, state, max_anisotropy);
util_dump_member(stream, float, state, lod_bias);
util_dump_member(stream, float, state, min_lod);
util_dump_member(stream, float, state, max_lod);
util_dump_member_array(stream, float, state, border_color.f);
 
util_dump_struct_end(stream);
}
 
 
void
util_dump_surface(FILE *stream, const struct pipe_surface *state)
{
if(!state) {
util_dump_null(stream);
return;
}
 
util_dump_struct_begin(stream, "pipe_surface");
 
util_dump_member(stream, format, state, format);
util_dump_member(stream, uint, state, width);
util_dump_member(stream, uint, state, height);
 
util_dump_member(stream, ptr, state, texture);
util_dump_member(stream, uint, state, u.tex.level);
util_dump_member(stream, uint, state, u.tex.first_layer);
util_dump_member(stream, uint, state, u.tex.last_layer);
 
util_dump_struct_end(stream);
}
 
 
void
util_dump_transfer(FILE *stream, const struct pipe_transfer *state)
{
if(!state) {
util_dump_null(stream);
return;
}
 
util_dump_struct_begin(stream, "pipe_transfer");
 
util_dump_member(stream, ptr, state, resource);
util_dump_member(stream, uint, state, level);
util_dump_member(stream, uint, state, usage);
util_dump_member_begin(stream, "box");
util_dump_box(stream, &state->box);
util_dump_member_end(stream);
util_dump_member(stream, uint, state, stride);
util_dump_member(stream, uint, state, layer_stride);
 
util_dump_struct_end(stream);
}
 
 
void
util_dump_vertex_buffer(FILE *stream, const struct pipe_vertex_buffer *state)
{
if(!state) {
util_dump_null(stream);
return;
}
 
util_dump_struct_begin(stream, "pipe_vertex_buffer");
 
util_dump_member(stream, uint, state, stride);
util_dump_member(stream, uint, state, buffer_offset);
util_dump_member(stream, ptr, state, buffer);
 
util_dump_struct_end(stream);
}
 
 
void
util_dump_vertex_element(FILE *stream, const struct pipe_vertex_element *state)
{
if(!state) {
util_dump_null(stream);
return;
}
 
util_dump_struct_begin(stream, "pipe_vertex_element");
 
util_dump_member(stream, uint, state, src_offset);
util_dump_member(stream, uint, state, instance_divisor);
util_dump_member(stream, uint, state, vertex_buffer_index);
util_dump_member(stream, format, state, src_format);
 
util_dump_struct_end(stream);
}
 
 
void
util_dump_draw_info(FILE *stream, const struct pipe_draw_info *state)
{
if(!state) {
util_dump_null(stream);
return;
}
 
util_dump_struct_begin(stream, "pipe_draw_info");
 
util_dump_member(stream, bool, state, indexed);
 
util_dump_member(stream, uint, state, mode);
util_dump_member(stream, uint, state, start);
util_dump_member(stream, uint, state, count);
 
util_dump_member(stream, uint, state, start_instance);
util_dump_member(stream, uint, state, instance_count);
 
util_dump_member(stream, int, state, index_bias);
util_dump_member(stream, uint, state, min_index);
util_dump_member(stream, uint, state, max_index);
 
util_dump_member(stream, bool, state, primitive_restart);
util_dump_member(stream, uint, state, restart_index);
 
util_dump_member(stream, ptr, state, count_from_stream_output);
 
util_dump_struct_end(stream);
}
 
void util_dump_box(FILE *stream, const struct pipe_box *box)
{
if(!box) {
util_dump_null(stream);
return;
}
 
util_dump_struct_begin(stream, "pipe_box");
 
util_dump_member(stream, int, box, x);
util_dump_member(stream, int, box, y);
util_dump_member(stream, int, box, z);
util_dump_member(stream, int, box, width);
util_dump_member(stream, int, box, height);
util_dump_member(stream, int, box, depth);
 
util_dump_struct_end(stream);
}
 
void util_dump_blit_info(FILE *stream, const struct pipe_blit_info *info)
{
char mask[7];
 
if (!info) {
util_dump_null(stream);
return;
}
 
util_dump_struct_begin(stream, "pipe_blit_info");
 
util_dump_member_begin(stream, "dst");
util_dump_struct_begin(stream, "dst");
util_dump_member(stream, ptr, &info->dst, resource);
util_dump_member(stream, uint, &info->dst, level);
util_dump_member(stream, format, &info->dst, format);
util_dump_member_begin(stream, "box");
util_dump_box(stream, &info->dst.box);
util_dump_member_end(stream);
util_dump_struct_end(stream);
util_dump_member_end(stream);
 
util_dump_member_begin(stream, "src");
util_dump_struct_begin(stream, "src");
util_dump_member(stream, ptr, &info->src, resource);
util_dump_member(stream, uint, &info->src, level);
util_dump_member(stream, format, &info->src, format);
util_dump_member_begin(stream, "box");
util_dump_box(stream, &info->src.box);
util_dump_member_end(stream);
util_dump_struct_end(stream);
util_dump_member_end(stream);
 
mask[0] = (info->mask & PIPE_MASK_R) ? 'R' : '-';
mask[1] = (info->mask & PIPE_MASK_G) ? 'G' : '-';
mask[2] = (info->mask & PIPE_MASK_B) ? 'B' : '-';
mask[3] = (info->mask & PIPE_MASK_A) ? 'A' : '-';
mask[4] = (info->mask & PIPE_MASK_Z) ? 'Z' : '-';
mask[5] = (info->mask & PIPE_MASK_S) ? 'S' : '-';
mask[6] = 0;
 
util_dump_member_begin(stream, "mask");
util_dump_string(stream, mask);
util_dump_member_end(stream);
util_dump_member(stream, uint, info, filter);
 
util_dump_member(stream, bool, info, scissor_enable);
util_dump_member_begin(stream, "scissor");
util_dump_scissor_state(stream, &info->scissor);
util_dump_member_end(stream);
 
util_dump_struct_end(stream);
}
/drivers/video/Gallium/auxiliary/util/u_dynarray.h
0,0 → 1,114
/**************************************************************************
*
* Copyright 2010 Luca Barbieri
*
* 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, sublicense, 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 NONINFRINGEMENT.
* IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
*
**************************************************************************/
 
#ifndef U_DYNARRAY_H
#define U_DYNARRAY_H
 
#include "pipe/p_compiler.h"
#include "util/u_memory.h"
 
/* A zero-initialized version of this is guaranteed to represent an
* empty array.
*
* Also, size <= capacity and data != 0 if and only if capacity != 0
* capacity will always be the allocation size of data
*/
struct util_dynarray
{
void *data;
unsigned size;
unsigned capacity;
};
 
static INLINE void
util_dynarray_init(struct util_dynarray *buf)
{
memset(buf, 0, sizeof(*buf));
}
 
static INLINE void
util_dynarray_fini(struct util_dynarray *buf)
{
if(buf->data)
{
FREE(buf->data);
util_dynarray_init(buf);
}
}
 
/* use util_dynarray_trim to reduce the allocated storage */
static INLINE void *
util_dynarray_resize(struct util_dynarray *buf, unsigned newsize)
{
char *p;
if(newsize > buf->capacity)
{
unsigned newcap = buf->capacity << 1;
if(newsize > newcap)
newcap = newsize;
buf->data = REALLOC(buf->data, buf->capacity, newcap);
buf->capacity = newcap;
}
 
p = (char *)buf->data + buf->size;
buf->size = newsize;
return p;
}
 
static INLINE void *
util_dynarray_grow(struct util_dynarray *buf, int diff)
{
return util_dynarray_resize(buf, buf->size + diff);
}
 
static INLINE void
util_dynarray_trim(struct util_dynarray *buf)
{
if (buf->size != buf->capacity) {
if (buf->size) {
buf->data = REALLOC(buf->data, buf->capacity, buf->size);
buf->capacity = buf->size;
}
else {
FREE(buf->data);
buf->data = 0;
buf->capacity = 0;
}
}
}
 
#define util_dynarray_append(buf, type, v) do {type __v = (v); memcpy(util_dynarray_grow((buf), sizeof(type)), &__v, sizeof(type));} while(0)
#define util_dynarray_top_ptr(buf, type) (type*)((char*)(buf)->data + (buf)->size - sizeof(type))
#define util_dynarray_top(buf, type) *util_dynarray_top_ptr(buf, type)
#define util_dynarray_pop_ptr(buf, type) (type*)((char*)(buf)->data + ((buf)->size -= sizeof(type)))
#define util_dynarray_pop(buf, type) *util_dynarray_pop_ptr(buf, type)
#define util_dynarray_contains(buf, type) ((buf)->size >= sizeof(type))
#define util_dynarray_element(buf, type, idx) ((type*)(buf)->data + (idx))
#define util_dynarray_begin(buf) ((buf)->data)
#define util_dynarray_end(buf) ((void*)util_dynarray_element((buf), char, (buf)->size))
 
#endif /* U_DYNARRAY_H */
 
/drivers/video/Gallium/auxiliary/util/u_fifo.h
0,0 → 1,94
/**************************************************************************
*
* Copyright © 2009 Jakob Bornecrantz
*
* 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, sublicense,
* 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 NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
*
**************************************************************************/
 
#ifndef U_FIFO_H
#define U_FIFO_H
 
#include "util/u_memory.h"
 
struct util_fifo
{
size_t head;
size_t tail;
size_t num;
size_t size;
};
 
static INLINE struct util_fifo *
u_fifo_create(size_t size)
{
struct util_fifo *fifo;
fifo = MALLOC(sizeof(*fifo) + size * sizeof(void*));
 
fifo->head = 0;
fifo->tail = 0;
fifo->num = 0;
fifo->size = size;
 
return fifo;
}
 
static INLINE boolean
u_fifo_add(struct util_fifo *fifo, void *ptr)
{
void **array = (void**)&fifo[1];
if (fifo->num >= fifo->size)
return FALSE;
 
if (++fifo->head >= fifo->size)
fifo->head = 0;
 
array[fifo->head] = ptr;
 
++fifo->num;
 
return TRUE;
}
 
static INLINE boolean
u_fifo_pop(struct util_fifo *fifo, void **ptr)
{
void **array = (void**)&fifo[1];
 
if (!fifo->num)
return FALSE;
 
if (++fifo->tail >= fifo->size)
fifo->tail = 0;
 
*ptr = array[fifo->tail];
 
++fifo->num;
 
return TRUE;
}
 
static INLINE void
u_fifo_destroy(struct util_fifo *fifo)
{
FREE(fifo);
}
 
#endif
/drivers/video/Gallium/auxiliary/util/u_format.c
0,0 → 1,725
/**************************************************************************
*
* Copyright 2010 VMware, Inc.
* 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 VMWARE 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
* Pixel format accessor functions.
*
* @author Jose Fonseca <jfonseca@vmware.com>
*/
 
#include "u_math.h"
#include "u_memory.h"
#include "u_rect.h"
#include "u_format.h"
#include "u_format_s3tc.h"
 
#include "pipe/p_defines.h"
 
 
boolean
util_format_is_float(enum pipe_format format)
{
const struct util_format_description *desc = util_format_description(format);
unsigned i;
 
assert(desc);
if (!desc) {
return FALSE;
}
 
i = util_format_get_first_non_void_channel(format);
if (i == -1) {
return FALSE;
}
 
return desc->channel[i].type == UTIL_FORMAT_TYPE_FLOAT ? TRUE : FALSE;
}
 
 
/** Test if the format contains RGB, but not alpha */
boolean
util_format_has_alpha(enum pipe_format format)
{
const struct util_format_description *desc =
util_format_description(format);
 
return (desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) &&
desc->swizzle[3] != UTIL_FORMAT_SWIZZLE_1;
}
 
 
boolean
util_format_is_luminance(enum pipe_format format)
{
const struct util_format_description *desc =
util_format_description(format);
 
if ((desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) &&
desc->swizzle[0] == UTIL_FORMAT_SWIZZLE_X &&
desc->swizzle[1] == UTIL_FORMAT_SWIZZLE_X &&
desc->swizzle[2] == UTIL_FORMAT_SWIZZLE_X &&
desc->swizzle[3] == UTIL_FORMAT_SWIZZLE_1) {
return TRUE;
}
return FALSE;
}
 
boolean
util_format_is_pure_integer(enum pipe_format format)
{
const struct util_format_description *desc = util_format_description(format);
int i;
 
/* Find the first non-void channel. */
i = util_format_get_first_non_void_channel(format);
if (i == -1)
return FALSE;
 
return desc->channel[i].pure_integer ? TRUE : FALSE;
}
 
boolean
util_format_is_pure_sint(enum pipe_format format)
{
const struct util_format_description *desc = util_format_description(format);
int i;
 
i = util_format_get_first_non_void_channel(format);
if (i == -1)
return FALSE;
 
return (desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED && desc->channel[i].pure_integer) ? TRUE : FALSE;
}
 
boolean
util_format_is_pure_uint(enum pipe_format format)
{
const struct util_format_description *desc = util_format_description(format);
int i;
 
i = util_format_get_first_non_void_channel(format);
if (i == -1)
return FALSE;
 
return (desc->channel[i].type == UTIL_FORMAT_TYPE_UNSIGNED && desc->channel[i].pure_integer) ? TRUE : FALSE;
}
 
/**
* Returns true if all non-void channels are normalized signed.
*/
boolean
util_format_is_snorm(enum pipe_format format)
{
const struct util_format_description *desc = util_format_description(format);
int i;
 
if (desc->is_mixed)
return FALSE;
 
i = util_format_get_first_non_void_channel(format);
if (i == -1)
return FALSE;
 
return desc->channel[i].type == UTIL_FORMAT_TYPE_SIGNED &&
!desc->channel[i].pure_integer &&
desc->channel[i].normalized;
}
 
boolean
util_format_is_luminance_alpha(enum pipe_format format)
{
const struct util_format_description *desc =
util_format_description(format);
 
if ((desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) &&
desc->swizzle[0] == UTIL_FORMAT_SWIZZLE_X &&
desc->swizzle[1] == UTIL_FORMAT_SWIZZLE_X &&
desc->swizzle[2] == UTIL_FORMAT_SWIZZLE_X &&
desc->swizzle[3] == UTIL_FORMAT_SWIZZLE_Y) {
return TRUE;
}
return FALSE;
}
 
 
boolean
util_format_is_intensity(enum pipe_format format)
{
const struct util_format_description *desc =
util_format_description(format);
 
if ((desc->colorspace == UTIL_FORMAT_COLORSPACE_RGB ||
desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) &&
desc->swizzle[0] == UTIL_FORMAT_SWIZZLE_X &&
desc->swizzle[1] == UTIL_FORMAT_SWIZZLE_X &&
desc->swizzle[2] == UTIL_FORMAT_SWIZZLE_X &&
desc->swizzle[3] == UTIL_FORMAT_SWIZZLE_X) {
return TRUE;
}
return FALSE;
}
 
 
boolean
util_format_is_supported(enum pipe_format format, unsigned bind)
{
if (util_format_is_s3tc(format) && !util_format_s3tc_enabled) {
return FALSE;
}
 
#ifndef TEXTURE_FLOAT_ENABLED
if ((bind & PIPE_BIND_RENDER_TARGET) &&
format != PIPE_FORMAT_R9G9B9E5_FLOAT &&
format != PIPE_FORMAT_R11G11B10_FLOAT &&
util_format_is_float(format)) {
return FALSE;
}
#endif
 
return TRUE;
}
 
 
void
util_format_read_4f(enum pipe_format format,
float *dst, unsigned dst_stride,
const void *src, unsigned src_stride,
unsigned x, unsigned y, unsigned w, unsigned h)
{
const struct util_format_description *format_desc;
const uint8_t *src_row;
float *dst_row;
 
format_desc = util_format_description(format);
 
assert(x % format_desc->block.width == 0);
assert(y % format_desc->block.height == 0);
 
src_row = (const uint8_t *)src + y*src_stride + x*(format_desc->block.bits/8);
dst_row = dst;
 
format_desc->unpack_rgba_float(dst_row, dst_stride, src_row, src_stride, w, h);
}
 
 
void
util_format_write_4f(enum pipe_format format,
const float *src, unsigned src_stride,
void *dst, unsigned dst_stride,
unsigned x, unsigned y, unsigned w, unsigned h)
{
const struct util_format_description *format_desc;
uint8_t *dst_row;
const float *src_row;
 
format_desc = util_format_description(format);
 
assert(x % format_desc->block.width == 0);
assert(y % format_desc->block.height == 0);
 
dst_row = (uint8_t *)dst + y*dst_stride + x*(format_desc->block.bits/8);
src_row = src;
 
format_desc->pack_rgba_float(dst_row, dst_stride, src_row, src_stride, w, h);
}
 
 
void
util_format_read_4ub(enum pipe_format format, uint8_t *dst, unsigned dst_stride, const void *src, unsigned src_stride, unsigned x, unsigned y, unsigned w, unsigned h)
{
const struct util_format_description *format_desc;
const uint8_t *src_row;
uint8_t *dst_row;
 
format_desc = util_format_description(format);
 
assert(x % format_desc->block.width == 0);
assert(y % format_desc->block.height == 0);
 
src_row = (const uint8_t *)src + y*src_stride + x*(format_desc->block.bits/8);
dst_row = dst;
 
format_desc->unpack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, w, h);
}
 
 
void
util_format_write_4ub(enum pipe_format format, const uint8_t *src, unsigned src_stride, void *dst, unsigned dst_stride, unsigned x, unsigned y, unsigned w, unsigned h)
{
const struct util_format_description *format_desc;
uint8_t *dst_row;
const uint8_t *src_row;
 
format_desc = util_format_description(format);
 
assert(x % format_desc->block.width == 0);
assert(y % format_desc->block.height == 0);
 
dst_row = (uint8_t *)dst + y*dst_stride + x*(format_desc->block.bits/8);
src_row = src;
 
format_desc->pack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, w, h);
}
 
void
util_format_read_4ui(enum pipe_format format,
unsigned *dst, unsigned dst_stride,
const void *src, unsigned src_stride,
unsigned x, unsigned y, unsigned w, unsigned h)
{
const struct util_format_description *format_desc;
const uint8_t *src_row;
unsigned *dst_row;
 
format_desc = util_format_description(format);
 
assert(x % format_desc->block.width == 0);
assert(y % format_desc->block.height == 0);
 
src_row = (const uint8_t *)src + y*src_stride + x*(format_desc->block.bits/8);
dst_row = dst;
 
format_desc->unpack_rgba_uint(dst_row, dst_stride, src_row, src_stride, w, h);
}
 
void
util_format_write_4ui(enum pipe_format format,
const unsigned int *src, unsigned src_stride,
void *dst, unsigned dst_stride,
unsigned x, unsigned y, unsigned w, unsigned h)
{
const struct util_format_description *format_desc;
uint8_t *dst_row;
const unsigned *src_row;
 
format_desc = util_format_description(format);
 
assert(x % format_desc->block.width == 0);
assert(y % format_desc->block.height == 0);
 
dst_row = (uint8_t *)dst + y*dst_stride + x*(format_desc->block.bits/8);
src_row = src;
 
format_desc->pack_rgba_uint(dst_row, dst_stride, src_row, src_stride, w, h);
}
 
void
util_format_read_4i(enum pipe_format format,
int *dst, unsigned dst_stride,
const void *src, unsigned src_stride,
unsigned x, unsigned y, unsigned w, unsigned h)
{
const struct util_format_description *format_desc;
const uint8_t *src_row;
int *dst_row;
 
format_desc = util_format_description(format);
 
assert(x % format_desc->block.width == 0);
assert(y % format_desc->block.height == 0);
 
src_row = (const uint8_t *)src + y*src_stride + x*(format_desc->block.bits/8);
dst_row = dst;
 
format_desc->unpack_rgba_sint(dst_row, dst_stride, src_row, src_stride, w, h);
}
 
void
util_format_write_4i(enum pipe_format format,
const int *src, unsigned src_stride,
void *dst, unsigned dst_stride,
unsigned x, unsigned y, unsigned w, unsigned h)
{
const struct util_format_description *format_desc;
uint8_t *dst_row;
const int *src_row;
 
format_desc = util_format_description(format);
 
assert(x % format_desc->block.width == 0);
assert(y % format_desc->block.height == 0);
 
dst_row = (uint8_t *)dst + y*dst_stride + x*(format_desc->block.bits/8);
src_row = src;
 
format_desc->pack_rgba_sint(dst_row, dst_stride, src_row, src_stride, w, h);
}
 
boolean
util_is_format_compatible(const struct util_format_description *src_desc,
const struct util_format_description *dst_desc)
{
unsigned chan;
 
if (src_desc->format == dst_desc->format) {
return TRUE;
}
 
if (src_desc->layout != UTIL_FORMAT_LAYOUT_PLAIN ||
dst_desc->layout != UTIL_FORMAT_LAYOUT_PLAIN) {
return FALSE;
}
 
if (src_desc->block.bits != dst_desc->block.bits ||
src_desc->nr_channels != dst_desc->nr_channels ||
src_desc->colorspace != dst_desc->colorspace) {
return FALSE;
}
 
for (chan = 0; chan < 4; ++chan) {
if (src_desc->channel[chan].size !=
dst_desc->channel[chan].size) {
return FALSE;
}
}
 
for (chan = 0; chan < 4; ++chan) {
enum util_format_swizzle swizzle = dst_desc->swizzle[chan];
 
if (swizzle < 4) {
if (src_desc->swizzle[chan] != swizzle) {
return FALSE;
}
if ((src_desc->channel[swizzle].type !=
dst_desc->channel[swizzle].type) ||
(src_desc->channel[swizzle].normalized !=
dst_desc->channel[swizzle].normalized)) {
return FALSE;
}
}
}
 
return TRUE;
}
 
 
boolean
util_format_fits_8unorm(const struct util_format_description *format_desc)
{
unsigned chan;
 
/*
* After linearized sRGB values require more than 8bits.
*/
 
if (format_desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) {
return FALSE;
}
 
switch (format_desc->layout) {
 
case UTIL_FORMAT_LAYOUT_S3TC:
/*
* These are straight forward.
*/
return TRUE;
case UTIL_FORMAT_LAYOUT_RGTC:
if (format_desc->format == PIPE_FORMAT_RGTC1_SNORM ||
format_desc->format == PIPE_FORMAT_RGTC2_SNORM ||
format_desc->format == PIPE_FORMAT_LATC1_SNORM ||
format_desc->format == PIPE_FORMAT_LATC2_SNORM)
return FALSE;
return TRUE;
 
case UTIL_FORMAT_LAYOUT_PLAIN:
/*
* For these we can find a generic rule.
*/
 
for (chan = 0; chan < format_desc->nr_channels; ++chan) {
switch (format_desc->channel[chan].type) {
case UTIL_FORMAT_TYPE_VOID:
break;
case UTIL_FORMAT_TYPE_UNSIGNED:
if (!format_desc->channel[chan].normalized ||
format_desc->channel[chan].size > 8) {
return FALSE;
}
break;
default:
return FALSE;
}
}
return TRUE;
 
default:
/*
* Handle all others on a case by case basis.
*/
 
switch (format_desc->format) {
case PIPE_FORMAT_R1_UNORM:
case PIPE_FORMAT_UYVY:
case PIPE_FORMAT_YUYV:
case PIPE_FORMAT_R8G8_B8G8_UNORM:
case PIPE_FORMAT_G8R8_G8B8_UNORM:
return TRUE;
 
default:
return FALSE;
}
}
}
 
 
void
util_format_translate(enum pipe_format dst_format,
void *dst, unsigned dst_stride,
unsigned dst_x, unsigned dst_y,
enum pipe_format src_format,
const void *src, unsigned src_stride,
unsigned src_x, unsigned src_y,
unsigned width, unsigned height)
{
const struct util_format_description *dst_format_desc;
const struct util_format_description *src_format_desc;
uint8_t *dst_row;
const uint8_t *src_row;
unsigned x_step, y_step;
unsigned dst_step;
unsigned src_step;
 
dst_format_desc = util_format_description(dst_format);
src_format_desc = util_format_description(src_format);
 
if (util_is_format_compatible(src_format_desc, dst_format_desc)) {
/*
* Trivial case.
*/
 
util_copy_rect(dst, dst_format, dst_stride, dst_x, dst_y,
width, height, src, (int)src_stride,
src_x, src_y);
return;
}
 
assert(dst_x % dst_format_desc->block.width == 0);
assert(dst_y % dst_format_desc->block.height == 0);
assert(src_x % src_format_desc->block.width == 0);
assert(src_y % src_format_desc->block.height == 0);
 
dst_row = (uint8_t *)dst + dst_y*dst_stride + dst_x*(dst_format_desc->block.bits/8);
src_row = (const uint8_t *)src + src_y*src_stride + src_x*(src_format_desc->block.bits/8);
 
/*
* This works because all pixel formats have pixel blocks with power of two
* sizes.
*/
 
y_step = MAX2(dst_format_desc->block.height, src_format_desc->block.height);
x_step = MAX2(dst_format_desc->block.width, src_format_desc->block.width);
assert(y_step % dst_format_desc->block.height == 0);
assert(y_step % src_format_desc->block.height == 0);
 
dst_step = y_step / dst_format_desc->block.height * dst_stride;
src_step = y_step / src_format_desc->block.height * src_stride;
 
/*
* TODO: double formats will loose precision
* TODO: Add a special case for formats that are mere swizzles of each other
*/
 
if (src_format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS ||
dst_format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) {
float *tmp_z = NULL;
uint8_t *tmp_s = NULL;
 
assert(x_step == 1);
assert(y_step == 1);
 
if (src_format_desc->unpack_z_float &&
dst_format_desc->pack_z_float) {
tmp_z = MALLOC(width * sizeof *tmp_z);
}
 
if (src_format_desc->unpack_s_8uint &&
dst_format_desc->pack_s_8uint) {
tmp_s = MALLOC(width * sizeof *tmp_s);
}
 
while (height--) {
if (tmp_z) {
src_format_desc->unpack_z_float(tmp_z, 0, src_row, src_stride, width, 1);
dst_format_desc->pack_z_float(dst_row, dst_stride, tmp_z, 0, width, 1);
}
 
if (tmp_s) {
src_format_desc->unpack_s_8uint(tmp_s, 0, src_row, src_stride, width, 1);
dst_format_desc->pack_s_8uint(dst_row, dst_stride, tmp_s, 0, width, 1);
}
 
dst_row += dst_step;
src_row += src_step;
}
 
FREE(tmp_s);
 
FREE(tmp_z);
 
return;
}
 
if (util_format_fits_8unorm(src_format_desc) ||
util_format_fits_8unorm(dst_format_desc)) {
unsigned tmp_stride;
uint8_t *tmp_row;
 
tmp_stride = MAX2(width, x_step) * 4 * sizeof *tmp_row;
tmp_row = MALLOC(y_step * tmp_stride);
if (!tmp_row)
return;
 
while (height >= y_step) {
src_format_desc->unpack_rgba_8unorm(tmp_row, tmp_stride, src_row, src_stride, width, y_step);
dst_format_desc->pack_rgba_8unorm(dst_row, dst_stride, tmp_row, tmp_stride, width, y_step);
 
dst_row += dst_step;
src_row += src_step;
height -= y_step;
}
 
if (height) {
src_format_desc->unpack_rgba_8unorm(tmp_row, tmp_stride, src_row, src_stride, width, height);
dst_format_desc->pack_rgba_8unorm(dst_row, dst_stride, tmp_row, tmp_stride, width, height);
}
 
FREE(tmp_row);
}
else {
unsigned tmp_stride;
float *tmp_row;
 
tmp_stride = MAX2(width, x_step) * 4 * sizeof *tmp_row;
tmp_row = MALLOC(y_step * tmp_stride);
if (!tmp_row)
return;
 
while (height >= y_step) {
src_format_desc->unpack_rgba_float(tmp_row, tmp_stride, src_row, src_stride, width, y_step);
dst_format_desc->pack_rgba_float(dst_row, dst_stride, tmp_row, tmp_stride, width, y_step);
 
dst_row += dst_step;
src_row += src_step;
height -= y_step;
}
 
if (height) {
src_format_desc->unpack_rgba_float(tmp_row, tmp_stride, src_row, src_stride, width, height);
dst_format_desc->pack_rgba_float(dst_row, dst_stride, tmp_row, tmp_stride, width, height);
}
 
FREE(tmp_row);
}
}
 
void util_format_compose_swizzles(const unsigned char swz1[4],
const unsigned char swz2[4],
unsigned char dst[4])
{
unsigned i;
 
for (i = 0; i < 4; i++) {
dst[i] = swz2[i] <= UTIL_FORMAT_SWIZZLE_W ?
swz1[swz2[i]] : swz2[i];
}
}
 
void util_format_apply_color_swizzle(union pipe_color_union *dst,
const union pipe_color_union *src,
const unsigned char swz[4],
const boolean is_integer)
{
unsigned c;
 
if (is_integer) {
for (c = 0; c < 4; ++c) {
switch (swz[c]) {
case PIPE_SWIZZLE_RED: dst->ui[c] = src->ui[0]; break;
case PIPE_SWIZZLE_GREEN: dst->ui[c] = src->ui[1]; break;
case PIPE_SWIZZLE_BLUE: dst->ui[c] = src->ui[2]; break;
case PIPE_SWIZZLE_ALPHA: dst->ui[c] = src->ui[3]; break;
default:
dst->ui[c] = (swz[c] == PIPE_SWIZZLE_ONE) ? 1 : 0;
break;
}
}
} else {
for (c = 0; c < 4; ++c) {
switch (swz[c]) {
case PIPE_SWIZZLE_RED: dst->f[c] = src->f[0]; break;
case PIPE_SWIZZLE_GREEN: dst->f[c] = src->f[1]; break;
case PIPE_SWIZZLE_BLUE: dst->f[c] = src->f[2]; break;
case PIPE_SWIZZLE_ALPHA: dst->f[c] = src->f[3]; break;
default:
dst->f[c] = (swz[c] == PIPE_SWIZZLE_ONE) ? 1.0f : 0.0f;
break;
}
}
}
}
 
void util_format_swizzle_4f(float *dst, const float *src,
const unsigned char swz[4])
{
unsigned i;
 
for (i = 0; i < 4; i++) {
if (swz[i] <= UTIL_FORMAT_SWIZZLE_W)
dst[i] = src[swz[i]];
else if (swz[i] == UTIL_FORMAT_SWIZZLE_0)
dst[i] = 0;
else if (swz[i] == UTIL_FORMAT_SWIZZLE_1)
dst[i] = 1;
}
}
 
void util_format_unswizzle_4f(float *dst, const float *src,
const unsigned char swz[4])
{
unsigned i;
 
for (i = 0; i < 4; i++) {
switch (swz[i]) {
case UTIL_FORMAT_SWIZZLE_X:
dst[0] = src[i];
break;
case UTIL_FORMAT_SWIZZLE_Y:
dst[1] = src[i];
break;
case UTIL_FORMAT_SWIZZLE_Z:
dst[2] = src[i];
break;
case UTIL_FORMAT_SWIZZLE_W:
dst[3] = src[i];
break;
}
}
}
/drivers/video/Gallium/auxiliary/util/u_format.csv
0,0 → 1,374
###########################################################################
#
# Copyright 2009-2010 VMware, Inc.
# 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 THE AUTHORS 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.
#
###########################################################################
 
# This CSV file has the input data for u_format.h's struct
# util_format_description.
#
# Each format entry contains:
# - name, per enum pipe_format
# - layout, per enum util_format_layout, in shortened lower caps
# - pixel block's width
# - pixel block's height
# - channel encoding (only meaningful for plain layout), containing for each
# channel the following information:
# - type, one of
# - 'x': void
# - 'u': unsigned
# - 's': signed
# - 'h': fixed
# - 'f': FLOAT
# - optionally followed by 'n' if it is normalized
# - optionally followed by 'p' if it is pure
# - number of bits
# - channel swizzle
# - color space: rgb, yub, sz
#
# See also:
# - http://msdn.microsoft.com/en-us/library/bb172558.aspx (D3D9)
# - http://msdn.microsoft.com/en-us/library/bb205073.aspx#mapping_texture_formats (D3D9 -> D3D10)
# - http://msdn.microsoft.com/en-us/library/bb173059.aspx (D3D10)
#
# Note that GL doesn't really specify the layout of internal formats. See
# OpenGL 2.1 specification, Table 3.16, on the "Correspondence of sized
# internal formats to base in- ternal formats, and desired component
# resolutions for each sized internal format."
 
# None
# Described as regular uint_8 bytes, i.e. PIPE_FORMAT_R8_USCALED
PIPE_FORMAT_NONE , plain, 1, 1, u8 , , , , x001, rgb
 
# Typical rendertarget formats
PIPE_FORMAT_B8G8R8A8_UNORM , plain, 1, 1, un8 , un8 , un8 , un8 , zyxw, rgb
PIPE_FORMAT_B8G8R8X8_UNORM , plain, 1, 1, un8 , un8 , un8 , x8 , zyx1, rgb
PIPE_FORMAT_A8R8G8B8_UNORM , plain, 1, 1, un8 , un8 , un8 , un8 , yzwx, rgb
PIPE_FORMAT_X8R8G8B8_UNORM , plain, 1, 1, x8 , un8 , un8 , un8 , yzw1, rgb
PIPE_FORMAT_A8B8G8R8_UNORM , plain, 1, 1, un8 , un8 , un8 , un8 , wzyx, rgb
PIPE_FORMAT_X8B8G8R8_UNORM , plain, 1, 1, x8 , un8 , un8 , un8 , wzy1, rgb
# PIPE_FORMAT_R8G8B8A8_UNORM is below
PIPE_FORMAT_R8G8B8X8_UNORM , plain, 1, 1, un8 , un8 , un8 , x8 , xyz1, rgb
#PIPE_FORMAT_B5G5R5X1_UNORM , plain, 1, 1, un5 , un5 , un5 , x1 , zyx1, rgb
#PIPE_FORMAT_B5G5R5A1_UNORM , plain, 1, 1, un5 , un5 , un5 , un1 , zyxw, rgb
#PIPE_FORMAT_B4G4R4A4_UNORM , plain, 1, 1, un4 , un4 , un4 , un4 , zyxw, rgb
#PIPE_FORMAT_B4G4R4X4_UNORM , plain, 1, 1, un4 , un4 , un4 , x4 , zyx1, rgb
#PIPE_FORMAT_B5G6R5_UNORM , plain, 1, 1, un5 , un6 , un5 , , zyx1, rgb
#PIPE_FORMAT_R10G10B10A2_UNORM , plain, 1, 1, un10, un10, un10, un2 , xyzw, rgb
#PIPE_FORMAT_B10G10R10A2_UNORM , plain, 1, 1, un10, un10, un10, un2 , zyxw, rgb
#PIPE_FORMAT_B2G3R3_UNORM , plain, 1, 1, un2 , un3 , un3 , , zyx1, rgb
 
# Luminance/Intensity/Alpha formats
PIPE_FORMAT_L8_UNORM , plain, 1, 1, un8 , , , , xxx1, rgb
PIPE_FORMAT_A8_UNORM , plain, 1, 1, un8 , , , , 000x, rgb
PIPE_FORMAT_I8_UNORM , plain, 1, 1, un8 , , , , xxxx, rgb
PIPE_FORMAT_L4A4_UNORM , plain, 1, 1, un4 , un4 , , , xxxy, rgb
PIPE_FORMAT_L8A8_UNORM , plain, 1, 1, un8 , un8 , , , xxxy, rgb
PIPE_FORMAT_L16_UNORM , plain, 1, 1, un16, , , , xxx1, rgb
PIPE_FORMAT_A16_UNORM , plain, 1, 1, un16, , , , 000x, rgb
PIPE_FORMAT_I16_UNORM , plain, 1, 1, un16, , , , xxxx, rgb
PIPE_FORMAT_L16A16_UNORM , plain, 1, 1, un16, un16, , , xxxy, rgb
PIPE_FORMAT_A8_SNORM , plain, 1, 1, sn8 , , , , 000x, rgb
PIPE_FORMAT_L8_SNORM , plain, 1, 1, sn8 , , , , xxx1, rgb
PIPE_FORMAT_L8A8_SNORM , plain, 1, 1, sn8 , sn8 , , , xxxy, rgb
PIPE_FORMAT_I8_SNORM , plain, 1, 1, sn8 , , , , xxxx, rgb
PIPE_FORMAT_A16_SNORM , plain, 1, 1, sn16, , , , 000x, rgb
PIPE_FORMAT_L16_SNORM , plain, 1, 1, sn16, , , , xxx1, rgb
PIPE_FORMAT_L16A16_SNORM , plain, 1, 1, sn16, sn16, , , xxxy, rgb
PIPE_FORMAT_I16_SNORM , plain, 1, 1, sn16, , , , xxxx, rgb
PIPE_FORMAT_A16_FLOAT , plain, 1, 1, f16 , , , , 000x, rgb
PIPE_FORMAT_L16_FLOAT , plain, 1, 1, f16 , , , , xxx1, rgb
PIPE_FORMAT_L16A16_FLOAT , plain, 1, 1, f16 , f16 , , , xxxy, rgb
PIPE_FORMAT_I16_FLOAT , plain, 1, 1, f16 , , , , xxxx, rgb
PIPE_FORMAT_A32_FLOAT , plain, 1, 1, f32 , , , , 000x, rgb
PIPE_FORMAT_L32_FLOAT , plain, 1, 1, f32 , , , , xxx1, rgb
PIPE_FORMAT_L32A32_FLOAT , plain, 1, 1, f32 , f32 , , , xxxy, rgb
PIPE_FORMAT_I32_FLOAT , plain, 1, 1, f32 , , , , xxxx, rgb
 
# SRGB formats
#PIPE_FORMAT_L8_SRGB , plain, 1, 1, un8 , , , , xxx1, srgb
#PIPE_FORMAT_L8A8_SRGB , plain, 1, 1, un8 , un8 , , , xxxy, srgb
#PIPE_FORMAT_R8G8B8_SRGB , plain, 1, 1, un8 , un8 , un8 , , xyz1, srgb
#PIPE_FORMAT_R8G8B8A8_SRGB , plain, 1, 1, un8 , un8 , un8 , un8 , xyzw, srgb
#PIPE_FORMAT_A8B8G8R8_SRGB , plain, 1, 1, un8 , un8 , un8 , un8 , wzyx, srgb
#PIPE_FORMAT_X8B8G8R8_SRGB , plain, 1, 1, x8 , un8 , un8 , un8 , wzy1, srgb
#PIPE_FORMAT_B8G8R8A8_SRGB , plain, 1, 1, un8 , un8 , un8 , un8 , zyxw, srgb
#PIPE_FORMAT_B8G8R8X8_SRGB , plain, 1, 1, un8 , un8 , un8 , x8 , zyx1, srgb
#PIPE_FORMAT_A8R8G8B8_SRGB , plain, 1, 1, un8 , un8 , un8 , un8 , yzwx, srgb
#PIPE_FORMAT_X8R8G8B8_SRGB , plain, 1, 1, x8 , un8 , un8 , un8 , yzw1, srgb
 
# Mixed-sign formats (typically used for bump map textures)
PIPE_FORMAT_R8SG8SB8UX8U_NORM , plain, 1, 1, sn8 , sn8 , un8 , x8 , xyz1, rgb
#PIPE_FORMAT_R10SG10SB10SA2U_NORM , plain, 1, 1, sn10, sn10, sn10, un2 , xyzw, rgb
PIPE_FORMAT_R5SG5SB6U_NORM , plain, 1, 1, sn5 , sn5 , un6 , , xyz1, rgb
 
# Depth-stencil formats
PIPE_FORMAT_S8_UINT , plain, 1, 1, up8 , , , , _x__, zs
PIPE_FORMAT_Z16_UNORM , plain, 1, 1, un16, , , , x___, zs
PIPE_FORMAT_Z32_UNORM , plain, 1, 1, un32, , , , x___, zs
PIPE_FORMAT_Z32_FLOAT , plain, 1, 1, f32 , , , , x___, zs
PIPE_FORMAT_Z24_UNORM_S8_UINT , plain, 1, 1, un24, up8 , , , xy__, zs
PIPE_FORMAT_S8_UINT_Z24_UNORM , plain, 1, 1, up8 , un24, , , yx__, zs
PIPE_FORMAT_X24S8_UINT , plain, 1, 1, x24 , up8 , , , _y__, zs
PIPE_FORMAT_S8X24_UINT , plain, 1, 1, up8 , x24 , , , _x__, zs
PIPE_FORMAT_Z24X8_UNORM , plain, 1, 1, un24, x8 , , , x___, zs
PIPE_FORMAT_X8Z24_UNORM , plain, 1, 1, x8 , un24, , , y___, zs
PIPE_FORMAT_Z32_FLOAT_S8X24_UINT , plain, 1, 1, f32 , up8 , x24, , xy__, zs
PIPE_FORMAT_X32_S8X24_UINT , plain, 1, 1, x32 , up8 , x24, , _y__, zs
 
# YUV formats
# http://www.fourcc.org/yuv.php#UYVY
PIPE_FORMAT_UYVY , subsampled, 2, 1, x32 , , , , xyz1, yuv
# http://www.fourcc.org/yuv.php#YUYV (a.k.a http://www.fourcc.org/yuv.php#YUY2)
PIPE_FORMAT_YUYV , subsampled, 2, 1, x32 , , , , xyz1, yuv
# same subsampling but with rgb channels
PIPE_FORMAT_R8G8_B8G8_UNORM , subsampled, 2, 1, x32 , , , , xyz1, rgb
PIPE_FORMAT_G8R8_G8B8_UNORM , subsampled, 2, 1, x32 , , , , xyz1, rgb
PIPE_FORMAT_G8R8_B8R8_UNORM , subsampled, 2, 1, x32 , , , , yxz1, rgb
PIPE_FORMAT_R8G8_R8B8_UNORM , subsampled, 2, 1, x32 , , , , yxz1, rgb
 
# some special formats not fitting anywhere else
PIPE_FORMAT_R11G11B10_FLOAT , other, 1, 1, x32 , , , , xyz1, rgb
PIPE_FORMAT_R9G9B9E5_FLOAT , other, 1, 1, x32 , , , , xyz1, rgb
PIPE_FORMAT_R1_UNORM , other, 8, 1, x8 , , , , x001, rgb
# A.k.a. D3DFMT_CxV8U8
PIPE_FORMAT_R8G8Bx_SNORM , other, 1, 1, sn8 , sn8 , , , xyz1, rgb
 
# Compressed formats
# - http://en.wikipedia.org/wiki/S3_Texture_Compression
# - http://www.opengl.org/registry/specs/EXT/texture_compression_s3tc.txt
# - http://www.opengl.org/registry/specs/ARB/texture_compression_rgtc.txt
# - http://www.opengl.org/registry/specs/EXT/texture_compression_latc.txt
# - http://www.khronos.org/registry/gles/extensions/OES/OES_compressed_ETC1_RGB8_texture.txt
# - http://msdn.microsoft.com/en-us/library/bb694531.aspx
#PIPE_FORMAT_DXT1_RGB , s3tc, 4, 4, x64 , , , , xyz1, rgb
#PIPE_FORMAT_DXT1_RGBA , s3tc, 4, 4, x64 , , , , xyzw, rgb
#PIPE_FORMAT_DXT3_RGBA , s3tc, 4, 4, x128, , , , xyzw, rgb
#PIPE_FORMAT_DXT5_RGBA , s3tc, 4, 4, x128, , , , xyzw, rgb
#PIPE_FORMAT_DXT1_SRGB , s3tc, 4, 4, x64 , , , , xyz1, srgb
#PIPE_FORMAT_DXT1_SRGBA , s3tc, 4, 4, x64 , , , , xyzw, srgb
#PIPE_FORMAT_DXT3_SRGBA , s3tc, 4, 4, x128, , , , xyzw, srgb
#PIPE_FORMAT_DXT5_SRGBA , s3tc, 4, 4, x128, , , , xyzw, srgb
 
#PIPE_FORMAT_RGTC1_UNORM , rgtc, 4, 4, x64, , , , x001, rgb
#PIPE_FORMAT_RGTC1_SNORM , rgtc, 4, 4, x64, , , , x001, rgb
#PIPE_FORMAT_RGTC2_UNORM , rgtc, 4, 4, x128, , , , xy01, rgb
#PIPE_FORMAT_RGTC2_SNORM , rgtc, 4, 4, x128, , , , xy01, rgb
 
#PIPE_FORMAT_LATC1_UNORM , rgtc, 4, 4, x64, , , , xxx1, rgb
#PIPE_FORMAT_LATC1_SNORM , rgtc, 4, 4, x64, , , , xxx1, rgb
#PIPE_FORMAT_LATC2_UNORM , rgtc, 4, 4, x128, , , , xxxy, rgb
#PIPE_FORMAT_LATC2_SNORM , rgtc, 4, 4, x128, , , , xxxy, rgb
 
#PIPE_FORMAT_ETC1_RGB8 , etc, 4, 4, x64, , , , xyz1, rgb
 
# Straightforward D3D10-like formats (also used for
# vertex buffer element description)
#
# See also:
# - src/gallium/auxiliary/translate/translate_generic.c
# - src/mesa/state_tracker/st_draw.c
PIPE_FORMAT_R64_FLOAT , plain, 1, 1, f64 , , , , x001, rgb
PIPE_FORMAT_R64G64_FLOAT , plain, 1, 1, f64 , f64 , , , xy01, rgb
PIPE_FORMAT_R64G64B64_FLOAT , plain, 1, 1, f64 , f64 , f64 , , xyz1, rgb
PIPE_FORMAT_R64G64B64A64_FLOAT , plain, 1, 1, f64 , f64 , f64 , f64 , xyzw, rgb
PIPE_FORMAT_R32_FLOAT , plain, 1, 1, f32 , , , , x001, rgb
PIPE_FORMAT_R32G32_FLOAT , plain, 1, 1, f32 , f32 , , , xy01, rgb
PIPE_FORMAT_R32G32B32_FLOAT , plain, 1, 1, f32 , f32 , f32 , , xyz1, rgb
PIPE_FORMAT_R32G32B32A32_FLOAT , plain, 1, 1, f32 , f32 , f32 , f32 , xyzw, rgb
PIPE_FORMAT_R32_UNORM , plain, 1, 1, un32, , , , x001, rgb
PIPE_FORMAT_R32G32_UNORM , plain, 1, 1, un32, un32, , , xy01, rgb
PIPE_FORMAT_R32G32B32_UNORM , plain, 1, 1, un32, un32, un32, , xyz1, rgb
PIPE_FORMAT_R32G32B32A32_UNORM , plain, 1, 1, un32, un32, un32, un32, xyzw, rgb
PIPE_FORMAT_R32_USCALED , plain, 1, 1, u32 , , , , x001, rgb
PIPE_FORMAT_R32G32_USCALED , plain, 1, 1, u32 , u32 , , , xy01, rgb
PIPE_FORMAT_R32G32B32_USCALED , plain, 1, 1, u32 , u32 , u32 , , xyz1, rgb
PIPE_FORMAT_R32G32B32A32_USCALED , plain, 1, 1, u32 , u32 , u32 , u32 , xyzw, rgb
PIPE_FORMAT_R32_SNORM , plain, 1, 1, sn32, , , , x001, rgb
PIPE_FORMAT_R32G32_SNORM , plain, 1, 1, sn32, sn32, , , xy01, rgb
PIPE_FORMAT_R32G32B32_SNORM , plain, 1, 1, sn32, sn32, sn32, , xyz1, rgb
PIPE_FORMAT_R32G32B32A32_SNORM , plain, 1, 1, sn32, sn32, sn32, sn32, xyzw, rgb
PIPE_FORMAT_R32_SSCALED , plain, 1, 1, s32 , , , , x001, rgb
PIPE_FORMAT_R32G32_SSCALED , plain, 1, 1, s32 , s32 , , , xy01, rgb
PIPE_FORMAT_R32G32B32_SSCALED , plain, 1, 1, s32 , s32 , s32 , , xyz1, rgb
PIPE_FORMAT_R32G32B32A32_SSCALED , plain, 1, 1, s32 , s32 , s32 , s32 , xyzw, rgb
PIPE_FORMAT_R16_FLOAT , plain, 1, 1, f16 , , , , x001, rgb
PIPE_FORMAT_R16G16_FLOAT , plain, 1, 1, f16 , f16 , , , xy01, rgb
PIPE_FORMAT_R16G16B16_FLOAT , plain, 1, 1, f16 , f16 , f16 , , xyz1, rgb
PIPE_FORMAT_R16G16B16A16_FLOAT , plain, 1, 1, f16 , f16 , f16 , f16 , xyzw, rgb
PIPE_FORMAT_R16_UNORM , plain, 1, 1, un16, , , , x001, rgb
PIPE_FORMAT_R16G16_UNORM , plain, 1, 1, un16, un16, , , xy01, rgb
PIPE_FORMAT_R16G16B16_UNORM , plain, 1, 1, un16, un16, un16, , xyz1, rgb
PIPE_FORMAT_R16G16B16A16_UNORM , plain, 1, 1, un16, un16, un16, un16, xyzw, rgb
PIPE_FORMAT_R16_USCALED , plain, 1, 1, u16 , , , , x001, rgb
PIPE_FORMAT_R16G16_USCALED , plain, 1, 1, u16 , u16 , , , xy01, rgb
PIPE_FORMAT_R16G16B16_USCALED , plain, 1, 1, u16 , u16 , u16 , , xyz1, rgb
PIPE_FORMAT_R16G16B16A16_USCALED , plain, 1, 1, u16 , u16 , u16 , u16 , xyzw, rgb
PIPE_FORMAT_R16_SNORM , plain, 1, 1, sn16, , , , x001, rgb
PIPE_FORMAT_R16G16_SNORM , plain, 1, 1, sn16, sn16, , , xy01, rgb
PIPE_FORMAT_R16G16B16_SNORM , plain, 1, 1, sn16, sn16, sn16, , xyz1, rgb
PIPE_FORMAT_R16G16B16A16_SNORM , plain, 1, 1, sn16, sn16, sn16, sn16, xyzw, rgb
PIPE_FORMAT_R16_SSCALED , plain, 1, 1, s16 , , , , x001, rgb
PIPE_FORMAT_R16G16_SSCALED , plain, 1, 1, s16 , s16 , , , xy01, rgb
PIPE_FORMAT_R16G16B16_SSCALED , plain, 1, 1, s16 , s16 , s16 , , xyz1, rgb
PIPE_FORMAT_R16G16B16A16_SSCALED , plain, 1, 1, s16 , s16 , s16 , s16 , xyzw, rgb
PIPE_FORMAT_R8_UNORM , plain, 1, 1, un8 , , , , x001, rgb
PIPE_FORMAT_R8G8_UNORM , plain, 1, 1, un8 , un8 , , , xy01, rgb
PIPE_FORMAT_R8G8B8_UNORM , plain, 1, 1, un8 , un8 , un8 , , xyz1, rgb
PIPE_FORMAT_R8G8B8A8_UNORM , plain, 1, 1, un8 , un8 , un8 , un8 , xyzw, rgb
PIPE_FORMAT_R8_USCALED , plain, 1, 1, u8 , , , , x001, rgb
PIPE_FORMAT_R8G8_USCALED , plain, 1, 1, u8 , u8 , , , xy01, rgb
PIPE_FORMAT_R8G8B8_USCALED , plain, 1, 1, u8 , u8 , u8 , , xyz1, rgb
PIPE_FORMAT_R8G8B8A8_USCALED , plain, 1, 1, u8 , u8 , u8 , u8 , xyzw, rgb
PIPE_FORMAT_R8_SNORM , plain, 1, 1, sn8 , , , , x001, rgb
PIPE_FORMAT_R8G8_SNORM , plain, 1, 1, sn8 , sn8 , , , xy01, rgb
PIPE_FORMAT_R8G8B8_SNORM , plain, 1, 1, sn8 , sn8 , sn8 , , xyz1, rgb
PIPE_FORMAT_R8G8B8A8_SNORM , plain, 1, 1, sn8 , sn8 , sn8 , sn8 , xyzw, rgb
PIPE_FORMAT_R8_SSCALED , plain, 1, 1, s8 , , , , x001, rgb
PIPE_FORMAT_R8G8_SSCALED , plain, 1, 1, s8 , s8 , , , xy01, rgb
PIPE_FORMAT_R8G8B8_SSCALED , plain, 1, 1, s8 , s8 , s8 , , xyz1, rgb
PIPE_FORMAT_R8G8B8A8_SSCALED , plain, 1, 1, s8 , s8 , s8 , s8 , xyzw, rgb
 
# GL-specific vertex buffer element formats
# A.k.a. GL_FIXED
PIPE_FORMAT_R32_FIXED , plain, 1, 1, h32 , , , , x001, rgb
PIPE_FORMAT_R32G32_FIXED , plain, 1, 1, h32 , h32 , , , xy01, rgb
PIPE_FORMAT_R32G32B32_FIXED , plain, 1, 1, h32 , h32 , h32 , , xyz1, rgb
PIPE_FORMAT_R32G32B32A32_FIXED , plain, 1, 1, h32 , h32 , h32 , h32 , xyzw, rgb
 
# D3D9-specific vertex buffer element formats
# See also:
# - http://msdn.microsoft.com/en-us/library/bb172533.aspx
# A.k.a. D3DDECLTYPE_UDEC3
PIPE_FORMAT_R10G10B10X2_USCALED , plain, 1, 1, u10 , u10 , u10 , x2 , xyz1, rgb
# A.k.a. D3DDECLTYPE_DEC3N
PIPE_FORMAT_R10G10B10X2_SNORM , plain, 1, 1, sn10, sn10, sn10 , x2 , xyz1, rgb
 
PIPE_FORMAT_YV12 , other, 1, 1, x8 , x8 , x8 , x8 , xyzw, yuv
PIPE_FORMAT_YV16 , other, 1, 1, x8 , x8 , x8 , x8 , xyzw, yuv
PIPE_FORMAT_IYUV , other, 1, 1, x8 , x8 , x8 , x8 , xyzw, yuv
PIPE_FORMAT_NV12 , other, 1, 1, x8 , x8 , x8 , x8 , xyzw, yuv
PIPE_FORMAT_NV21 , other, 1, 1, x8 , x8 , x8 , x8 , xyzw, yuv
 
# Usually used to implement IA44 and AI44 formats in video decoding
PIPE_FORMAT_R4A4_UNORM , plain, 1, 1, un4 , un4 , , , y00x, rgb
PIPE_FORMAT_A4R4_UNORM , plain, 1, 1, un4 , un4 , , , x00y, rgb
PIPE_FORMAT_R8A8_UNORM , plain, 1, 1, un8 , un8 , , , x00y, rgb
PIPE_FORMAT_A8R8_UNORM , plain, 1, 1, un8 , un8 , , , y00x, rgb
 
# ARB_vertex_type_10_10_10_2_REV
#PIPE_FORMAT_R10G10B10A2_USCALED , plain, 1, 1, u10, u10, u10, u2, xyzw, rgb
#PIPE_FORMAT_R10G10B10A2_SSCALED , plain, 1, 1, s10, s10, s10, s2, xyzw, rgb
#PIPE_FORMAT_R10G10B10A2_SNORM , plain, 1, 1, sn10, sn10, sn10, sn2, xyzw, rgb
#PIPE_FORMAT_B10G10R10A2_USCALED , plain, 1, 1, u10, u10, u10, u2, zyxw, rgb
#PIPE_FORMAT_B10G10R10A2_SSCALED , plain, 1, 1, s10, s10, s10, s2, zyxw, rgb
#PIPE_FORMAT_B10G10R10A2_SNORM , plain, 1, 1, sn10, sn10, sn10, sn2, zyxw, rgb
 
PIPE_FORMAT_R8_UINT , plain, 1, 1, up8, , , , x001, rgb
PIPE_FORMAT_R8G8_UINT , plain, 1, 1, up8, up8, , , xy01, rgb
PIPE_FORMAT_R8G8B8_UINT , plain, 1, 1, up8, up8, up8, , xyz1, rgb
PIPE_FORMAT_R8G8B8A8_UINT , plain, 1, 1, up8, up8, up8, up8, xyzw, rgb
 
PIPE_FORMAT_R8_SINT , plain, 1, 1, sp8, , , , x001, rgb
PIPE_FORMAT_R8G8_SINT , plain, 1, 1, sp8, sp8, , , xy01, rgb
PIPE_FORMAT_R8G8B8_SINT , plain, 1, 1, sp8, sp8, sp8, , xyz1, rgb
PIPE_FORMAT_R8G8B8A8_SINT , plain, 1, 1, sp8, sp8, sp8, sp8, xyzw, rgb
 
PIPE_FORMAT_R16_UINT , plain, 1, 1, up16, , , , x001, rgb
PIPE_FORMAT_R16G16_UINT , plain, 1, 1, up16, up16, , , xy01, rgb
PIPE_FORMAT_R16G16B16_UINT , plain, 1, 1, up16, up16, up16, , xyz1, rgb
PIPE_FORMAT_R16G16B16A16_UINT , plain, 1, 1, up16, up16, up16, up16, xyzw, rgb
 
PIPE_FORMAT_R16_SINT , plain, 1, 1, sp16, , , , x001, rgb
PIPE_FORMAT_R16G16_SINT , plain, 1, 1, sp16, sp16, , , xy01, rgb
PIPE_FORMAT_R16G16B16_SINT , plain, 1, 1, sp16, sp16, sp16, , xyz1, rgb
PIPE_FORMAT_R16G16B16A16_SINT , plain, 1, 1, sp16, sp16, sp16, sp16, xyzw, rgb
 
PIPE_FORMAT_R32_UINT , plain, 1, 1, up32, , , , x001, rgb
PIPE_FORMAT_R32G32_UINT , plain, 1, 1, up32, up32, , , xy01, rgb
PIPE_FORMAT_R32G32B32_UINT , plain, 1, 1, up32, up32, up32, , xyz1, rgb
PIPE_FORMAT_R32G32B32A32_UINT , plain, 1, 1, up32, up32, up32, up32, xyzw, rgb
 
PIPE_FORMAT_R32_SINT , plain, 1, 1, sp32, , , , x001, rgb
PIPE_FORMAT_R32G32_SINT , plain, 1, 1, sp32, sp32, , , xy01, rgb
PIPE_FORMAT_R32G32B32_SINT , plain, 1, 1, sp32, sp32, sp32, , xyz1, rgb
PIPE_FORMAT_R32G32B32A32_SINT , plain, 1, 1, sp32, sp32, sp32, sp32, xyzw, rgb
 
PIPE_FORMAT_A8_UINT , plain, 1, 1, up8, , , , 000x, rgb
PIPE_FORMAT_I8_UINT , plain, 1, 1, up8, , , , xxxx, rgb
PIPE_FORMAT_L8_UINT , plain, 1, 1, up8, , , , xxx1, rgb
PIPE_FORMAT_L8A8_UINT , plain, 1, 1, up8, up8, , , xxxy, rgb
 
PIPE_FORMAT_A8_SINT , plain, 1, 1, sp8, , , , 000x, rgb
PIPE_FORMAT_I8_SINT , plain, 1, 1, sp8, , , , xxxx, rgb
PIPE_FORMAT_L8_SINT , plain, 1, 1, sp8, , , , xxx1, rgb
PIPE_FORMAT_L8A8_SINT , plain, 1, 1, sp8, sp8, , , xxxy, rgb
 
PIPE_FORMAT_A16_UINT , plain, 1, 1, up16, , , , 000x, rgb
PIPE_FORMAT_I16_UINT , plain, 1, 1, up16, , , , xxxx, rgb
PIPE_FORMAT_L16_UINT , plain, 1, 1, up16, , , , xxx1, rgb
PIPE_FORMAT_L16A16_UINT , plain, 1, 1, up16, up16, , , xxxy, rgb
 
PIPE_FORMAT_A16_SINT , plain, 1, 1, sp16, , , , 000x, rgb
PIPE_FORMAT_I16_SINT , plain, 1, 1, sp16, , , , xxxx, rgb
PIPE_FORMAT_L16_SINT , plain, 1, 1, sp16, , , , xxx1, rgb
PIPE_FORMAT_L16A16_SINT , plain, 1, 1, sp16, sp16, , , xxxy, rgb
 
PIPE_FORMAT_A32_UINT , plain, 1, 1, up32, , , , 000x, rgb
PIPE_FORMAT_I32_UINT , plain, 1, 1, up32, , , , xxxx, rgb
PIPE_FORMAT_L32_UINT , plain, 1, 1, up32, , , , xxx1, rgb
PIPE_FORMAT_L32A32_UINT , plain, 1, 1, up32, up32, , , xxxy, rgb
 
PIPE_FORMAT_A32_SINT , plain, 1, 1, sp32, , , , 000x, rgb
PIPE_FORMAT_I32_SINT , plain, 1, 1, sp32, , , , xxxx, rgb
PIPE_FORMAT_L32_SINT , plain, 1, 1, sp32, , , , xxx1, rgb
PIPE_FORMAT_L32A32_SINT , plain, 1, 1, sp32, sp32, , , xxxy, rgb
 
#PIPE_FORMAT_B10G10R10A2_UINT , plain, 1, 1, up10, up10, up10, up2, zyxw, rgb
 
PIPE_FORMAT_R8G8B8X8_SNORM , plain, 1, 1, sn8, sn8, sn8, x8, xyz1, rgb
PIPE_FORMAT_R8G8B8X8_SRGB , plain, 1, 1, un8, un8, un8, x8, xyz1, srgb
PIPE_FORMAT_R8G8B8X8_UINT , plain, 1, 1, up8, up8, up8, x8, xyz1, rgb
PIPE_FORMAT_R8G8B8X8_SINT , plain, 1, 1, sp8, sp8, sp8, x8, xyz1, rgb
#PIPE_FORMAT_B10G10R10X2_UNORM , plain, 1, 1, un10, un10, un10, x2, zyx1, rgb
PIPE_FORMAT_R16G16B16X16_UNORM , plain, 1, 1, un16, un16, un16, x16, xyz1, rgb
PIPE_FORMAT_R16G16B16X16_SNORM , plain, 1, 1, sn16, sn16, sn16, x16, xyz1, rgb
PIPE_FORMAT_R16G16B16X16_FLOAT , plain, 1, 1, f16, f16, f16, x16, xyz1, rgb
PIPE_FORMAT_R16G16B16X16_UINT , plain, 1, 1, up16, up16, up16, x16, xyz1, rgb
PIPE_FORMAT_R16G16B16X16_SINT , plain, 1, 1, sp16, sp16, sp16, x16, xyz1, rgb
PIPE_FORMAT_R32G32B32X32_FLOAT , plain, 1, 1, f32, f32, f32, x32, xyz1, rgb
PIPE_FORMAT_R32G32B32X32_UINT , plain, 1, 1, up32, up32, up32, x32, xyz1, rgb
PIPE_FORMAT_R32G32B32X32_SINT , plain, 1, 1, sp32, sp32, sp32, x32, xyz1, rgb
 
PIPE_FORMAT_R8A8_SNORM , plain, 1, 1, sn8 , sn8 , , , x00y, rgb
PIPE_FORMAT_R16A16_UNORM , plain, 1, 1, un16 , un16 , , , x00y, rgb
PIPE_FORMAT_R16A16_SNORM , plain, 1, 1, sn16 , sn16 , , , x00y, rgb
PIPE_FORMAT_R16A16_FLOAT , plain, 1, 1, f16 , f16 , , , x00y, rgb
PIPE_FORMAT_R32A32_FLOAT , plain, 1, 1, f32 , f32 , , , x00y, rgb
PIPE_FORMAT_R8A8_UINT , plain, 1, 1, up8 , up8 , , , x00y, rgb
PIPE_FORMAT_R8A8_SINT , plain, 1, 1, sp8 , sp8 , , , x00y, rgb
PIPE_FORMAT_R16A16_UINT , plain, 1, 1, up16 , up16 , , , x00y, rgb
PIPE_FORMAT_R16A16_SINT , plain, 1, 1, sp16 , sp16 , , , x00y, rgb
PIPE_FORMAT_R32A32_UINT , plain, 1, 1, up32 , up32 , , , x00y, rgb
PIPE_FORMAT_R32A32_SINT , plain, 1, 1, sp32 , sp32 , , , x00y, rgb
/drivers/video/Gallium/auxiliary/util/u_format.h
0,0 → 1,1196
/**************************************************************************
*
* Copyright 2009-2010 Vmware, Inc.
* 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 VMWARE 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.
*
**************************************************************************/
 
 
#ifndef U_FORMAT_H
#define U_FORMAT_H
 
 
#include "pipe/p_format.h"
#include "pipe/p_defines.h"
#include "util/u_debug.h"
 
union pipe_color_union;
 
 
#ifdef __cplusplus
extern "C" {
#endif
 
 
/**
* Describe how to pack/unpack pixels into/from the prescribed format.
*
* XXX: This could be renamed to something like util_format_pack, or broke down
* in flags inside util_format_block that said exactly what we want.
*/
enum util_format_layout {
/**
* Formats with util_format_block::width == util_format_block::height == 1
* that can be described as an ordinary data structure.
*/
UTIL_FORMAT_LAYOUT_PLAIN = 0,
 
/**
* Formats with sub-sampled channels.
*
* This is for formats like YVYU where there is less than one sample per
* pixel.
*/
UTIL_FORMAT_LAYOUT_SUBSAMPLED = 3,
 
/**
* S3 Texture Compression formats.
*/
UTIL_FORMAT_LAYOUT_S3TC = 4,
 
/**
* Red-Green Texture Compression formats.
*/
UTIL_FORMAT_LAYOUT_RGTC = 5,
 
/**
* Ericsson Texture Compression
*/
UTIL_FORMAT_LAYOUT_ETC = 6,
 
/**
* Everything else that doesn't fit in any of the above layouts.
*/
UTIL_FORMAT_LAYOUT_OTHER = 7
};
 
 
struct util_format_block
{
/** Block width in pixels */
unsigned width;
/** Block height in pixels */
unsigned height;
 
/** Block size in bits */
unsigned bits;
};
 
 
enum util_format_type {
UTIL_FORMAT_TYPE_VOID = 0,
UTIL_FORMAT_TYPE_UNSIGNED = 1,
UTIL_FORMAT_TYPE_SIGNED = 2,
UTIL_FORMAT_TYPE_FIXED = 3,
UTIL_FORMAT_TYPE_FLOAT = 4
};
 
 
enum util_format_swizzle {
UTIL_FORMAT_SWIZZLE_X = 0,
UTIL_FORMAT_SWIZZLE_Y = 1,
UTIL_FORMAT_SWIZZLE_Z = 2,
UTIL_FORMAT_SWIZZLE_W = 3,
UTIL_FORMAT_SWIZZLE_0 = 4,
UTIL_FORMAT_SWIZZLE_1 = 5,
UTIL_FORMAT_SWIZZLE_NONE = 6,
UTIL_FORMAT_SWIZZLE_MAX = 7 /**< Number of enums counter (must be last) */
};
 
 
enum util_format_colorspace {
UTIL_FORMAT_COLORSPACE_RGB = 0,
UTIL_FORMAT_COLORSPACE_SRGB = 1,
UTIL_FORMAT_COLORSPACE_YUV = 2,
UTIL_FORMAT_COLORSPACE_ZS = 3
};
 
 
struct util_format_channel_description
{
unsigned type:5; /**< UTIL_FORMAT_TYPE_x */
unsigned normalized:1;
unsigned pure_integer:1;
unsigned size:9; /**< bits per channel */
unsigned shift:16; /** number of bits from lsb */
};
 
 
struct util_format_description
{
enum pipe_format format;
 
const char *name;
 
/**
* Short name, striped of the prefix, lower case.
*/
const char *short_name;
 
/**
* Pixel block dimensions.
*/
struct util_format_block block;
 
enum util_format_layout layout;
 
/**
* The number of channels.
*/
unsigned nr_channels:3;
 
/**
* Whether all channels have the same number of (whole) bytes and type.
*/
unsigned is_array:1;
 
/**
* Whether the pixel format can be described as a bitfield structure.
*
* In particular:
* - pixel depth must be 8, 16, or 32 bits;
* - all channels must be unsigned, signed, or void
*/
unsigned is_bitmask:1;
 
/**
* Whether channels have mixed types (ignoring UTIL_FORMAT_TYPE_VOID).
*/
unsigned is_mixed:1;
 
/**
* Input channel description, in the order XYZW.
*
* Only valid for UTIL_FORMAT_LAYOUT_PLAIN formats.
*
* If each channel is accessed as an individual N-byte value, X is always
* at the lowest address in memory, Y is always next, and so on. For all
* currently-defined formats, the N-byte value has native endianness.
*
* If instead a group of channels is accessed as a single N-byte value,
* the order of the channels within that value depends on endianness.
* For big-endian targets, X is the most significant subvalue,
* otherwise it is the least significant one.
*
* For example, if X is 8 bits and Y is 24 bits, the memory order is:
*
* 0 1 2 3
* little-endian: X Yl Ym Yu (l = lower, m = middle, u = upper)
* big-endian: X Yu Ym Yl
*
* If X is 5 bits, Y is 5 bits, Z is 5 bits and W is 1 bit, the layout is:
*
* 0 1
* msb lsb msb lsb
* little-endian: YYYXXXXX WZZZZZYY
* big-endian: XXXXXYYY YYZZZZZW
*/
struct util_format_channel_description channel[4];
 
/**
* Output channel swizzle.
*
* The order is either:
* - RGBA
* - YUV(A)
* - ZS
* depending on the colorspace.
*/
unsigned char swizzle[4];
 
/**
* Colorspace transformation.
*/
enum util_format_colorspace colorspace;
 
/**
* Unpack pixel blocks to R8G8B8A8_UNORM.
* Note: strides are in bytes.
*
* Only defined for non-depth-stencil formats.
*/
void
(*unpack_rgba_8unorm)(uint8_t *dst, unsigned dst_stride,
const uint8_t *src, unsigned src_stride,
unsigned width, unsigned height);
 
/**
* Pack pixel blocks from R8G8B8A8_UNORM.
* Note: strides are in bytes.
*
* Only defined for non-depth-stencil formats.
*/
void
(*pack_rgba_8unorm)(uint8_t *dst, unsigned dst_stride,
const uint8_t *src, unsigned src_stride,
unsigned width, unsigned height);
 
/**
* Fetch a single pixel (i, j) from a block.
*
* XXX: Only defined for a very few select formats.
*/
void
(*fetch_rgba_8unorm)(uint8_t *dst,
const uint8_t *src,
unsigned i, unsigned j);
 
/**
* Unpack pixel blocks to R32G32B32A32_FLOAT.
* Note: strides are in bytes.
*
* Only defined for non-depth-stencil formats.
*/
void
(*unpack_rgba_float)(float *dst, unsigned dst_stride,
const uint8_t *src, unsigned src_stride,
unsigned width, unsigned height);
 
/**
* Pack pixel blocks from R32G32B32A32_FLOAT.
* Note: strides are in bytes.
*
* Only defined for non-depth-stencil formats.
*/
void
(*pack_rgba_float)(uint8_t *dst, unsigned dst_stride,
const float *src, unsigned src_stride,
unsigned width, unsigned height);
 
/**
* Fetch a single pixel (i, j) from a block.
*
* Only defined for non-depth-stencil and non-integer formats.
*/
void
(*fetch_rgba_float)(float *dst,
const uint8_t *src,
unsigned i, unsigned j);
 
/**
* Unpack pixels to Z32_UNORM.
* Note: strides are in bytes.
*
* Only defined for depth formats.
*/
void
(*unpack_z_32unorm)(uint32_t *dst, unsigned dst_stride,
const uint8_t *src, unsigned src_stride,
unsigned width, unsigned height);
 
/**
* Pack pixels from Z32_FLOAT.
* Note: strides are in bytes.
*
* Only defined for depth formats.
*/
void
(*pack_z_32unorm)(uint8_t *dst, unsigned dst_stride,
const uint32_t *src, unsigned src_stride,
unsigned width, unsigned height);
 
/**
* Unpack pixels to Z32_FLOAT.
* Note: strides are in bytes.
*
* Only defined for depth formats.
*/
void
(*unpack_z_float)(float *dst, unsigned dst_stride,
const uint8_t *src, unsigned src_stride,
unsigned width, unsigned height);
 
/**
* Pack pixels from Z32_FLOAT.
* Note: strides are in bytes.
*
* Only defined for depth formats.
*/
void
(*pack_z_float)(uint8_t *dst, unsigned dst_stride,
const float *src, unsigned src_stride,
unsigned width, unsigned height);
 
/**
* Unpack pixels to S8_UINT.
* Note: strides are in bytes.
*
* Only defined for stencil formats.
*/
void
(*unpack_s_8uint)(uint8_t *dst, unsigned dst_stride,
const uint8_t *src, unsigned src_stride,
unsigned width, unsigned height);
 
/**
* Pack pixels from S8_UINT.
* Note: strides are in bytes.
*
* Only defined for stencil formats.
*/
void
(*pack_s_8uint)(uint8_t *dst, unsigned dst_stride,
const uint8_t *src, unsigned src_stride,
unsigned width, unsigned height);
 
/**
* Unpack pixel blocks to R32G32B32A32_UINT.
* Note: strides are in bytes.
*
* Only defined for INT formats.
*/
void
(*unpack_rgba_uint)(unsigned *dst, unsigned dst_stride,
const uint8_t *src, unsigned src_stride,
unsigned width, unsigned height);
 
void
(*pack_rgba_uint)(uint8_t *dst, unsigned dst_stride,
const unsigned *src, unsigned src_stride,
unsigned width, unsigned height);
 
/**
* Unpack pixel blocks to R32G32B32A32_SINT.
* Note: strides are in bytes.
*
* Only defined for INT formats.
*/
void
(*unpack_rgba_sint)(signed *dst, unsigned dst_stride,
const uint8_t *src, unsigned src_stride,
unsigned width, unsigned height);
 
void
(*pack_rgba_sint)(uint8_t *dst, unsigned dst_stride,
const int *src, unsigned src_stride,
unsigned width, unsigned height);
 
/**
* Fetch a single pixel (i, j) from a block.
*
* Only defined for unsigned (pure) integer formats.
*/
void
(*fetch_rgba_uint)(uint32_t *dst,
const uint8_t *src,
unsigned i, unsigned j);
 
/**
* Fetch a single pixel (i, j) from a block.
*
* Only defined for signed (pure) integer formats.
*/
void
(*fetch_rgba_sint)(int32_t *dst,
const uint8_t *src,
unsigned i, unsigned j);
};
 
 
extern const struct util_format_description
util_format_description_table[];
 
 
const struct util_format_description *
util_format_description(enum pipe_format format);
 
 
/*
* Format query functions.
*/
 
static INLINE const char *
util_format_name(enum pipe_format format)
{
const struct util_format_description *desc = util_format_description(format);
 
assert(desc);
if (!desc) {
return "PIPE_FORMAT_???";
}
 
return desc->name;
}
 
static INLINE const char *
util_format_short_name(enum pipe_format format)
{
const struct util_format_description *desc = util_format_description(format);
 
assert(desc);
if (!desc) {
return "???";
}
 
return desc->short_name;
}
 
/**
* Whether this format is plain, see UTIL_FORMAT_LAYOUT_PLAIN for more info.
*/
static INLINE boolean
util_format_is_plain(enum pipe_format format)
{
const struct util_format_description *desc = util_format_description(format);
 
if (!format) {
return FALSE;
}
 
return desc->layout == UTIL_FORMAT_LAYOUT_PLAIN ? TRUE : FALSE;
}
 
static INLINE boolean
util_format_is_compressed(enum pipe_format format)
{
const struct util_format_description *desc = util_format_description(format);
 
assert(desc);
if (!desc) {
return FALSE;
}
 
switch (desc->layout) {
case UTIL_FORMAT_LAYOUT_S3TC:
case UTIL_FORMAT_LAYOUT_RGTC:
case UTIL_FORMAT_LAYOUT_ETC:
/* XXX add other formats in the future */
return TRUE;
default:
return FALSE;
}
}
 
static INLINE boolean
util_format_is_s3tc(enum pipe_format format)
{
const struct util_format_description *desc = util_format_description(format);
 
assert(desc);
if (!desc) {
return FALSE;
}
 
return desc->layout == UTIL_FORMAT_LAYOUT_S3TC ? TRUE : FALSE;
}
 
static INLINE boolean
util_format_is_srgb(enum pipe_format format)
{
const struct util_format_description *desc = util_format_description(format);
return desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB;
}
 
static INLINE boolean
util_format_has_depth(const struct util_format_description *desc)
{
return desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS &&
desc->swizzle[0] != UTIL_FORMAT_SWIZZLE_NONE;
}
 
static INLINE boolean
util_format_has_stencil(const struct util_format_description *desc)
{
return desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS &&
desc->swizzle[1] != UTIL_FORMAT_SWIZZLE_NONE;
}
 
static INLINE boolean
util_format_is_depth_or_stencil(enum pipe_format format)
{
const struct util_format_description *desc = util_format_description(format);
 
assert(desc);
if (!desc) {
return FALSE;
}
 
return util_format_has_depth(desc) ||
util_format_has_stencil(desc);
}
 
static INLINE boolean
util_format_is_depth_and_stencil(enum pipe_format format)
{
const struct util_format_description *desc = util_format_description(format);
 
assert(desc);
if (!desc) {
return FALSE;
}
 
return util_format_has_depth(desc) &&
util_format_has_stencil(desc);
}
 
/**
* Return whether this is an RGBA, Z, S, or combined ZS format.
* Useful for initializing pipe_blit_info::mask.
*/
static INLINE unsigned
util_format_get_mask(enum pipe_format format)
{
const struct util_format_description *desc =
util_format_description(format);
 
if (!desc)
return 0;
 
if (util_format_has_depth(desc)) {
if (util_format_has_stencil(desc)) {
return PIPE_MASK_ZS;
} else {
return PIPE_MASK_Z;
}
} else {
if (util_format_has_stencil(desc)) {
return PIPE_MASK_S;
} else {
return PIPE_MASK_RGBA;
}
}
}
 
/**
* Give the RGBA colormask of the channels that can be represented in this
* format.
*
* That is, the channels whose values are preserved.
*/
static INLINE unsigned
util_format_colormask(const struct util_format_description *desc)
{
unsigned colormask;
unsigned chan;
 
switch (desc->colorspace) {
case UTIL_FORMAT_COLORSPACE_RGB:
case UTIL_FORMAT_COLORSPACE_SRGB:
case UTIL_FORMAT_COLORSPACE_YUV:
colormask = 0;
for (chan = 0; chan < 4; ++chan) {
if (desc->swizzle[chan] < 4) {
colormask |= (1 << chan);
}
}
return colormask;
case UTIL_FORMAT_COLORSPACE_ZS:
return 0;
default:
assert(0);
return 0;
}
}
 
 
/**
* Checks if color mask covers every channel for the specified format
*
* @param desc a format description to check colormask with
* @param colormask a bit mask for channels, matches format of PIPE_MASK_RGBA
*/
static INLINE boolean
util_format_colormask_full(const struct util_format_description *desc, unsigned colormask)
{
return (~colormask & util_format_colormask(desc)) == 0;
}
 
 
boolean
util_format_is_float(enum pipe_format format);
 
 
boolean
util_format_has_alpha(enum pipe_format format);
 
 
boolean
util_format_is_luminance(enum pipe_format format);
 
 
boolean
util_format_is_luminance_alpha(enum pipe_format format);
 
 
boolean
util_format_is_intensity(enum pipe_format format);
 
boolean
util_format_is_pure_integer(enum pipe_format format);
 
boolean
util_format_is_pure_sint(enum pipe_format format);
 
boolean
util_format_is_pure_uint(enum pipe_format format);
 
boolean
util_format_is_snorm(enum pipe_format format);
 
/**
* Check if the src format can be blitted to the destination format with
* a simple memcpy. For example, blitting from RGBA to RGBx is OK, but not
* the reverse.
*/
boolean
util_is_format_compatible(const struct util_format_description *src_desc,
const struct util_format_description *dst_desc);
 
/**
* Whether the format is supported by Gallium for the given bindings.
* This covers S3TC textures and floating-point render targets.
*/
boolean
util_format_is_supported(enum pipe_format format, unsigned bind);
 
/**
* Whether this format is a rgab8 variant.
*
* That is, any format that matches the
*
* PIPE_FORMAT_?8?8?8?8_UNORM
*/
static INLINE boolean
util_format_is_rgba8_variant(const struct util_format_description *desc)
{
unsigned chan;
 
if(desc->block.width != 1 ||
desc->block.height != 1 ||
desc->block.bits != 32)
return FALSE;
 
for(chan = 0; chan < 4; ++chan) {
if(desc->channel[chan].type != UTIL_FORMAT_TYPE_UNSIGNED &&
desc->channel[chan].type != UTIL_FORMAT_TYPE_VOID)
return FALSE;
if(desc->channel[chan].size != 8)
return FALSE;
}
 
return TRUE;
}
 
 
/**
* Return total bits needed for the pixel format per block.
*/
static INLINE uint
util_format_get_blocksizebits(enum pipe_format format)
{
const struct util_format_description *desc = util_format_description(format);
 
assert(desc);
if (!desc) {
return 0;
}
 
return desc->block.bits;
}
 
/**
* Return bytes per block (not pixel) for the given format.
*/
static INLINE uint
util_format_get_blocksize(enum pipe_format format)
{
uint bits = util_format_get_blocksizebits(format);
 
assert(bits % 8 == 0);
 
return bits / 8;
}
 
static INLINE uint
util_format_get_blockwidth(enum pipe_format format)
{
const struct util_format_description *desc = util_format_description(format);
 
assert(desc);
if (!desc) {
return 1;
}
 
return desc->block.width;
}
 
static INLINE uint
util_format_get_blockheight(enum pipe_format format)
{
const struct util_format_description *desc = util_format_description(format);
 
assert(desc);
if (!desc) {
return 1;
}
 
return desc->block.height;
}
 
static INLINE unsigned
util_format_get_nblocksx(enum pipe_format format,
unsigned x)
{
unsigned blockwidth = util_format_get_blockwidth(format);
return (x + blockwidth - 1) / blockwidth;
}
 
static INLINE unsigned
util_format_get_nblocksy(enum pipe_format format,
unsigned y)
{
unsigned blockheight = util_format_get_blockheight(format);
return (y + blockheight - 1) / blockheight;
}
 
static INLINE unsigned
util_format_get_nblocks(enum pipe_format format,
unsigned width,
unsigned height)
{
return util_format_get_nblocksx(format, width) * util_format_get_nblocksy(format, height);
}
 
static INLINE size_t
util_format_get_stride(enum pipe_format format,
unsigned width)
{
return util_format_get_nblocksx(format, width) * util_format_get_blocksize(format);
}
 
static INLINE size_t
util_format_get_2d_size(enum pipe_format format,
size_t stride,
unsigned height)
{
return util_format_get_nblocksy(format, height) * stride;
}
 
static INLINE uint
util_format_get_component_bits(enum pipe_format format,
enum util_format_colorspace colorspace,
uint component)
{
const struct util_format_description *desc = util_format_description(format);
enum util_format_colorspace desc_colorspace;
 
assert(format);
if (!format) {
return 0;
}
 
assert(component < 4);
 
/* Treat RGB and SRGB as equivalent. */
if (colorspace == UTIL_FORMAT_COLORSPACE_SRGB) {
colorspace = UTIL_FORMAT_COLORSPACE_RGB;
}
if (desc->colorspace == UTIL_FORMAT_COLORSPACE_SRGB) {
desc_colorspace = UTIL_FORMAT_COLORSPACE_RGB;
} else {
desc_colorspace = desc->colorspace;
}
 
if (desc_colorspace != colorspace) {
return 0;
}
 
switch (desc->swizzle[component]) {
case UTIL_FORMAT_SWIZZLE_X:
return desc->channel[0].size;
case UTIL_FORMAT_SWIZZLE_Y:
return desc->channel[1].size;
case UTIL_FORMAT_SWIZZLE_Z:
return desc->channel[2].size;
case UTIL_FORMAT_SWIZZLE_W:
return desc->channel[3].size;
default:
return 0;
}
}
 
/**
* Given a linear RGB colorspace format, return the corresponding SRGB
* format, or PIPE_FORMAT_NONE if none.
*/
static INLINE enum pipe_format
util_format_srgb(enum pipe_format format)
{
switch (format) {
case PIPE_FORMAT_L8_UNORM:
return PIPE_FORMAT_L8_SRGB;
case PIPE_FORMAT_L8A8_UNORM:
return PIPE_FORMAT_L8A8_SRGB;
case PIPE_FORMAT_R8G8B8_UNORM:
return PIPE_FORMAT_R8G8B8_SRGB;
case PIPE_FORMAT_A8B8G8R8_UNORM:
return PIPE_FORMAT_A8B8G8R8_SRGB;
case PIPE_FORMAT_X8B8G8R8_UNORM:
return PIPE_FORMAT_X8B8G8R8_SRGB;
case PIPE_FORMAT_B8G8R8A8_UNORM:
return PIPE_FORMAT_B8G8R8A8_SRGB;
case PIPE_FORMAT_B8G8R8X8_UNORM:
return PIPE_FORMAT_B8G8R8X8_SRGB;
case PIPE_FORMAT_A8R8G8B8_UNORM:
return PIPE_FORMAT_A8R8G8B8_SRGB;
case PIPE_FORMAT_X8R8G8B8_UNORM:
return PIPE_FORMAT_X8R8G8B8_SRGB;
case PIPE_FORMAT_R8G8B8A8_UNORM:
return PIPE_FORMAT_R8G8B8A8_SRGB;
case PIPE_FORMAT_R8G8B8X8_UNORM:
return PIPE_FORMAT_R8G8B8X8_SRGB;
case PIPE_FORMAT_DXT1_RGB:
return PIPE_FORMAT_DXT1_SRGB;
case PIPE_FORMAT_DXT1_RGBA:
return PIPE_FORMAT_DXT1_SRGBA;
case PIPE_FORMAT_DXT3_RGBA:
return PIPE_FORMAT_DXT3_SRGBA;
case PIPE_FORMAT_DXT5_RGBA:
return PIPE_FORMAT_DXT5_SRGBA;
default:
return PIPE_FORMAT_NONE;
}
}
 
/**
* Given an sRGB format, return the corresponding linear colorspace format.
* For non sRGB formats, return the format unchanged.
*/
static INLINE enum pipe_format
util_format_linear(enum pipe_format format)
{
switch (format) {
case PIPE_FORMAT_L8_SRGB:
return PIPE_FORMAT_L8_UNORM;
case PIPE_FORMAT_L8A8_SRGB:
return PIPE_FORMAT_L8A8_UNORM;
case PIPE_FORMAT_R8G8B8_SRGB:
return PIPE_FORMAT_R8G8B8_UNORM;
case PIPE_FORMAT_A8B8G8R8_SRGB:
return PIPE_FORMAT_A8B8G8R8_UNORM;
case PIPE_FORMAT_X8B8G8R8_SRGB:
return PIPE_FORMAT_X8B8G8R8_UNORM;
case PIPE_FORMAT_B8G8R8A8_SRGB:
return PIPE_FORMAT_B8G8R8A8_UNORM;
case PIPE_FORMAT_B8G8R8X8_SRGB:
return PIPE_FORMAT_B8G8R8X8_UNORM;
case PIPE_FORMAT_A8R8G8B8_SRGB:
return PIPE_FORMAT_A8R8G8B8_UNORM;
case PIPE_FORMAT_X8R8G8B8_SRGB:
return PIPE_FORMAT_X8R8G8B8_UNORM;
case PIPE_FORMAT_R8G8B8A8_SRGB:
return PIPE_FORMAT_R8G8B8A8_UNORM;
case PIPE_FORMAT_R8G8B8X8_SRGB:
return PIPE_FORMAT_R8G8B8X8_UNORM;
case PIPE_FORMAT_DXT1_SRGB:
return PIPE_FORMAT_DXT1_RGB;
case PIPE_FORMAT_DXT1_SRGBA:
return PIPE_FORMAT_DXT1_RGBA;
case PIPE_FORMAT_DXT3_SRGBA:
return PIPE_FORMAT_DXT3_RGBA;
case PIPE_FORMAT_DXT5_SRGBA:
return PIPE_FORMAT_DXT5_RGBA;
default:
return format;
}
}
 
/**
* Given a depth-stencil format, return the corresponding stencil-only format.
* For stencil-only formats, return the format unchanged.
*/
static INLINE enum pipe_format
util_format_stencil_only(enum pipe_format format)
{
switch (format) {
/* mask out the depth component */
case PIPE_FORMAT_Z24_UNORM_S8_UINT:
return PIPE_FORMAT_X24S8_UINT;
case PIPE_FORMAT_S8_UINT_Z24_UNORM:
return PIPE_FORMAT_S8X24_UINT;
case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
return PIPE_FORMAT_X32_S8X24_UINT;
 
/* stencil only formats */
case PIPE_FORMAT_X24S8_UINT:
case PIPE_FORMAT_S8X24_UINT:
case PIPE_FORMAT_X32_S8X24_UINT:
case PIPE_FORMAT_S8_UINT:
return format;
 
default:
assert(0);
return PIPE_FORMAT_NONE;
}
}
 
/**
* Converts PIPE_FORMAT_*I* to PIPE_FORMAT_*R*.
* This is identity for non-intensity formats.
*/
static INLINE enum pipe_format
util_format_intensity_to_red(enum pipe_format format)
{
switch (format) {
case PIPE_FORMAT_I8_UNORM:
return PIPE_FORMAT_R8_UNORM;
case PIPE_FORMAT_I8_SNORM:
return PIPE_FORMAT_R8_SNORM;
case PIPE_FORMAT_I16_UNORM:
return PIPE_FORMAT_R16_UNORM;
case PIPE_FORMAT_I16_SNORM:
return PIPE_FORMAT_R16_SNORM;
case PIPE_FORMAT_I16_FLOAT:
return PIPE_FORMAT_R16_FLOAT;
case PIPE_FORMAT_I32_FLOAT:
return PIPE_FORMAT_R32_FLOAT;
case PIPE_FORMAT_I8_UINT:
return PIPE_FORMAT_R8_UINT;
case PIPE_FORMAT_I8_SINT:
return PIPE_FORMAT_R8_SINT;
case PIPE_FORMAT_I16_UINT:
return PIPE_FORMAT_R16_UINT;
case PIPE_FORMAT_I16_SINT:
return PIPE_FORMAT_R16_SINT;
case PIPE_FORMAT_I32_UINT:
return PIPE_FORMAT_R32_UINT;
case PIPE_FORMAT_I32_SINT:
return PIPE_FORMAT_R32_SINT;
default:
assert(!util_format_is_intensity(format));
return format;
}
}
 
/**
* Converts PIPE_FORMAT_*L* to PIPE_FORMAT_*R*.
* This is identity for non-luminance formats.
*/
static INLINE enum pipe_format
util_format_luminance_to_red(enum pipe_format format)
{
switch (format) {
case PIPE_FORMAT_L8_UNORM:
return PIPE_FORMAT_R8_UNORM;
case PIPE_FORMAT_L8_SNORM:
return PIPE_FORMAT_R8_SNORM;
case PIPE_FORMAT_L16_UNORM:
return PIPE_FORMAT_R16_UNORM;
case PIPE_FORMAT_L16_SNORM:
return PIPE_FORMAT_R16_SNORM;
case PIPE_FORMAT_L16_FLOAT:
return PIPE_FORMAT_R16_FLOAT;
case PIPE_FORMAT_L32_FLOAT:
return PIPE_FORMAT_R32_FLOAT;
case PIPE_FORMAT_L8_UINT:
return PIPE_FORMAT_R8_UINT;
case PIPE_FORMAT_L8_SINT:
return PIPE_FORMAT_R8_SINT;
case PIPE_FORMAT_L16_UINT:
return PIPE_FORMAT_R16_UINT;
case PIPE_FORMAT_L16_SINT:
return PIPE_FORMAT_R16_SINT;
case PIPE_FORMAT_L32_UINT:
return PIPE_FORMAT_R32_UINT;
case PIPE_FORMAT_L32_SINT:
return PIPE_FORMAT_R32_SINT;
 
case PIPE_FORMAT_LATC1_UNORM:
return PIPE_FORMAT_RGTC1_UNORM;
case PIPE_FORMAT_LATC1_SNORM:
return PIPE_FORMAT_RGTC1_SNORM;
 
case PIPE_FORMAT_L4A4_UNORM:
/* XXX A4R4 is defined as x00y in u_format.csv */
return PIPE_FORMAT_A4R4_UNORM;
 
case PIPE_FORMAT_L8A8_UNORM:
return PIPE_FORMAT_R8A8_UNORM;
case PIPE_FORMAT_L8A8_SNORM:
return PIPE_FORMAT_R8A8_SNORM;
case PIPE_FORMAT_L16A16_UNORM:
return PIPE_FORMAT_R16A16_UNORM;
case PIPE_FORMAT_L16A16_SNORM:
return PIPE_FORMAT_R16A16_SNORM;
case PIPE_FORMAT_L16A16_FLOAT:
return PIPE_FORMAT_R16A16_FLOAT;
case PIPE_FORMAT_L32A32_FLOAT:
return PIPE_FORMAT_R32A32_FLOAT;
case PIPE_FORMAT_L8A8_UINT:
return PIPE_FORMAT_R8A8_UINT;
case PIPE_FORMAT_L8A8_SINT:
return PIPE_FORMAT_R8A8_SINT;
case PIPE_FORMAT_L16A16_UINT:
return PIPE_FORMAT_R16A16_UINT;
case PIPE_FORMAT_L16A16_SINT:
return PIPE_FORMAT_R16A16_SINT;
case PIPE_FORMAT_L32A32_UINT:
return PIPE_FORMAT_R32A32_UINT;
case PIPE_FORMAT_L32A32_SINT:
return PIPE_FORMAT_R32A32_SINT;
 
/* We don't have compressed red-alpha variants for these. */
case PIPE_FORMAT_LATC2_UNORM:
case PIPE_FORMAT_LATC2_SNORM:
return PIPE_FORMAT_NONE;
 
default:
assert(!util_format_is_luminance(format) &&
!util_format_is_luminance_alpha(format));
return format;
}
}
 
/**
* Return the number of components stored.
* Formats with block size != 1x1 will always have 1 component (the block).
*/
static INLINE unsigned
util_format_get_nr_components(enum pipe_format format)
{
const struct util_format_description *desc = util_format_description(format);
return desc->nr_channels;
}
 
/**
* Return the index of the first non-void channel
* -1 if no non-void channels
*/
static INLINE int
util_format_get_first_non_void_channel(enum pipe_format format)
{
const struct util_format_description *desc = util_format_description(format);
int i;
 
for (i = 0; i < 4; i++)
if (desc->channel[i].type != UTIL_FORMAT_TYPE_VOID)
break;
 
if (i == 4)
return -1;
 
return i;
}
 
/*
* Format access functions.
*/
 
void
util_format_read_4f(enum pipe_format format,
float *dst, unsigned dst_stride,
const void *src, unsigned src_stride,
unsigned x, unsigned y, unsigned w, unsigned h);
 
void
util_format_write_4f(enum pipe_format format,
const float *src, unsigned src_stride,
void *dst, unsigned dst_stride,
unsigned x, unsigned y, unsigned w, unsigned h);
 
void
util_format_read_4ub(enum pipe_format format,
uint8_t *dst, unsigned dst_stride,
const void *src, unsigned src_stride,
unsigned x, unsigned y, unsigned w, unsigned h);
 
void
util_format_write_4ub(enum pipe_format format,
const uint8_t *src, unsigned src_stride,
void *dst, unsigned dst_stride,
unsigned x, unsigned y, unsigned w, unsigned h);
 
void
util_format_read_4ui(enum pipe_format format,
unsigned *dst, unsigned dst_stride,
const void *src, unsigned src_stride,
unsigned x, unsigned y, unsigned w, unsigned h);
 
void
util_format_write_4ui(enum pipe_format format,
const unsigned int *src, unsigned src_stride,
void *dst, unsigned dst_stride,
unsigned x, unsigned y, unsigned w, unsigned h);
 
void
util_format_read_4i(enum pipe_format format,
int *dst, unsigned dst_stride,
const void *src, unsigned src_stride,
unsigned x, unsigned y, unsigned w, unsigned h);
 
void
util_format_write_4i(enum pipe_format format,
const int *src, unsigned src_stride,
void *dst, unsigned dst_stride,
unsigned x, unsigned y, unsigned w, unsigned h);
 
/*
* Generic format conversion;
*/
 
boolean
util_format_fits_8unorm(const struct util_format_description *format_desc);
 
void
util_format_translate(enum pipe_format dst_format,
void *dst, unsigned dst_stride,
unsigned dst_x, unsigned dst_y,
enum pipe_format src_format,
const void *src, unsigned src_stride,
unsigned src_x, unsigned src_y,
unsigned width, unsigned height);
 
/*
* Swizzle operations.
*/
 
/* Compose two sets of swizzles.
* If V is a 4D vector and the function parameters represent functions that
* swizzle vector components, this holds:
* swz2(swz1(V)) = dst(V)
*/
void util_format_compose_swizzles(const unsigned char swz1[4],
const unsigned char swz2[4],
unsigned char dst[4]);
 
/* Apply the swizzle provided in \param swz (which is one of PIPE_SWIZZLE_x)
* to \param src and store the result in \param dst.
* \param is_integer determines the value written for PIPE_SWIZZLE_ONE.
*/
void util_format_apply_color_swizzle(union pipe_color_union *dst,
const union pipe_color_union *src,
const unsigned char swz[4],
const boolean is_integer);
 
void util_format_swizzle_4f(float *dst, const float *src,
const unsigned char swz[4]);
 
void util_format_unswizzle_4f(float *dst, const float *src,
const unsigned char swz[4]);
 
#ifdef __cplusplus
} // extern "C" {
#endif
 
#endif /* ! U_FORMAT_H */
/drivers/video/Gallium/auxiliary/util/u_format_etc.c
0,0 → 1,81
#include "pipe/p_compiler.h"
#include "util/u_debug.h"
#include "util/u_math.h"
#include "u_format_etc.h"
 
/* define etc1_parse_block and etc. */
#define UINT8_TYPE uint8_t
#define TAG(x) x
#include "texcompress_etc_tmp.h"
#undef TAG
#undef UINT8_TYPE
 
void
util_format_etc1_rgb8_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
etc1_unpack_rgba8888(dst_row, dst_stride, src_row, src_stride, width, height);
}
 
void
util_format_etc1_rgb8_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
assert(0);
}
 
void
util_format_etc1_rgb8_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
const unsigned bw = 4, bh = 4, bs = 8, comps = 4;
struct etc1_block block;
unsigned x, y, i, j;
 
for (y = 0; y < height; y += bh) {
const uint8_t *src = src_row;
 
for (x = 0; x < width; x+= bw) {
etc1_parse_block(&block, src);
 
for (j = 0; j < bh; j++) {
float *dst = dst_row + (y + j) * dst_stride / sizeof(*dst_row) + x * comps;
uint8_t tmp[3];
 
for (i = 0; i < bw; i++) {
etc1_fetch_texel(&block, i, j, tmp);
dst[0] = ubyte_to_float(tmp[0]);
dst[1] = ubyte_to_float(tmp[1]);
dst[2] = ubyte_to_float(tmp[2]);
dst[3] = 1.0f;
dst += comps;
}
}
 
src += bs;
}
 
src_row += src_stride;
}
}
 
void
util_format_etc1_rgb8_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
assert(0);
}
 
void
util_format_etc1_rgb8_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
const unsigned bw = 4, bh = 4;
struct etc1_block block;
uint8_t tmp[3];
 
assert(i < bw && j < bh);
 
etc1_parse_block(&block, src);
etc1_fetch_texel(&block, i, j, tmp);
 
dst[0] = ubyte_to_float(tmp[0]);
dst[1] = ubyte_to_float(tmp[1]);
dst[2] = ubyte_to_float(tmp[2]);
dst[3] = 1.0f;
}
/drivers/video/Gallium/auxiliary/util/u_format_etc.h
0,0 → 1,46
/**************************************************************************
*
* Copyright 2011 LunarG, Inc.
* 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 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
* THE COPYRIGHT HOLDERS, AUTHORS 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.
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
**************************************************************************/
 
#ifndef U_FORMAT_ETC1_H_
#define U_FORMAT_ETC1_H_
 
void
util_format_etc1_rgb8_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_etc1_rgb8_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_etc1_rgb8_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_etc1_rgb8_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_etc1_rgb8_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j);
 
#endif /* U_FORMAT_ETC1_H_ */
/drivers/video/Gallium/auxiliary/util/u_format_latc.c
0,0 → 1,332
/**************************************************************************
*
* Copyright (C) 2011 Red Hat Inc.
*
* 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, sublicense,
* 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
*
**************************************************************************/
 
#include <stdio.h>
#include "u_math.h"
#include "u_format.h"
#include "u_format_rgtc.h"
#include "u_format_latc.h"
 
static void u_format_unsigned_encode_rgtc_ubyte(uint8_t *blkaddr, uint8_t srccolors[4][4],
int numxpixels, int numypixels);
 
static void u_format_unsigned_fetch_texel_rgtc(unsigned srcRowStride, const uint8_t *pixdata,
unsigned i, unsigned j, uint8_t *value, unsigned comps);
 
static void u_format_signed_encode_rgtc_ubyte(int8_t *blkaddr, int8_t srccolors[4][4],
int numxpixels, int numypixels);
 
static void u_format_signed_fetch_texel_rgtc(unsigned srcRowStride, const int8_t *pixdata,
unsigned i, unsigned j, int8_t *value, unsigned comps);
 
void
util_format_latc1_unorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j)
{
/* Fix warnings here: */
(void) u_format_unsigned_encode_rgtc_ubyte;
(void) u_format_signed_encode_rgtc_ubyte;
 
u_format_unsigned_fetch_texel_rgtc(0, src, i, j, dst, 1);
dst[1] = dst[0];
dst[2] = dst[0];
dst[3] = 255;
}
 
void
util_format_latc1_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
util_format_rgtc1_unorm_unpack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, width, height);
}
 
void
util_format_latc1_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row,
unsigned src_stride, unsigned width, unsigned height)
{
util_format_rgtc1_unorm_pack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, width, height);
}
 
void
util_format_latc1_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y, i, j;
int block_size = 8;
 
for(y = 0; y < height; y += 4) {
const uint8_t *src = src_row;
for(x = 0; x < width; x += 4) {
for(j = 0; j < 4; ++j) {
for(i = 0; i < 4; ++i) {
float *dst = dst_row + (y + j)*dst_stride/sizeof(*dst_row) + (x + i)*4;
uint8_t tmp_r;
u_format_unsigned_fetch_texel_rgtc(0, src, i, j, &tmp_r, 1);
dst[0] =
dst[1] =
dst[2] = ubyte_to_float(tmp_r);
dst[3] = 1.0;
}
}
src += block_size;
}
src_row += src_stride;
}
}
 
void
util_format_latc1_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
util_format_rgtc1_unorm_pack_rgba_float(dst_row, dst_stride, src_row, src_stride, width, height);
}
 
void
util_format_latc1_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint8_t tmp_r;
 
u_format_unsigned_fetch_texel_rgtc(0, src, i, j, &tmp_r, 1);
dst[0] =
dst[1] =
dst[2] = ubyte_to_float(tmp_r);
dst[3] = 1.0;
}
 
void
util_format_latc1_snorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j)
{
fprintf(stderr,"%s\n", __func__);
}
 
void
util_format_latc1_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
fprintf(stderr,"%s\n", __func__);
}
 
void
util_format_latc1_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
fprintf(stderr,"%s\n", __func__);
}
 
void
util_format_latc1_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
util_format_rgtc1_snorm_pack_rgba_float(dst_row, dst_stride, src_row, src_stride, width, height);
}
 
void
util_format_latc1_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y, i, j;
int block_size = 8;
 
for(y = 0; y < height; y += 4) {
const int8_t *src = (int8_t *)src_row;
for(x = 0; x < width; x += 4) {
for(j = 0; j < 4; ++j) {
for(i = 0; i < 4; ++i) {
float *dst = dst_row + (y + j)*dst_stride/sizeof(*dst_row) + (x + i)*4;
int8_t tmp_r;
u_format_signed_fetch_texel_rgtc(0, src, i, j, &tmp_r, 1);
dst[0] =
dst[1] =
dst[2] = byte_to_float_tex(tmp_r);
dst[3] = 1.0;
}
}
src += block_size;
}
src_row += src_stride;
}
}
 
void
util_format_latc1_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
int8_t tmp_r;
 
u_format_signed_fetch_texel_rgtc(0, (int8_t *)src, i, j, &tmp_r, 1);
dst[0] =
dst[1] =
dst[2] = byte_to_float_tex(tmp_r);
dst[3] = 1.0;
}
 
 
void
util_format_latc2_unorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j)
{
u_format_unsigned_fetch_texel_rgtc(0, src, i, j, dst, 2);
dst[1] = dst[0];
dst[2] = dst[0];
u_format_unsigned_fetch_texel_rgtc(0, src + 8, i, j, dst + 3, 2);
}
 
void
util_format_latc2_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
util_format_rgtc2_unorm_unpack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, width, height);
}
 
void
util_format_latc2_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
util_format_rgtc2_unorm_pack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, width, height);
}
 
void
util_format_latc2_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
util_format_rxtc2_unorm_pack_rgba_float(dst_row, dst_stride, src_row, src_stride, width, height, 3);
}
 
void
util_format_latc2_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y, i, j;
int block_size = 16;
 
for(y = 0; y < height; y += 4) {
const uint8_t *src = src_row;
for(x = 0; x < width; x += 4) {
for(j = 0; j < 4; ++j) {
for(i = 0; i < 4; ++i) {
float *dst = dst_row + (y + j)*dst_stride/sizeof(*dst_row) + (x + i)*4;
uint8_t tmp_r, tmp_g;
u_format_unsigned_fetch_texel_rgtc(0, src, i, j, &tmp_r, 2);
u_format_unsigned_fetch_texel_rgtc(0, src + 8, i, j, &tmp_g, 2);
dst[0] =
dst[1] =
dst[2] = ubyte_to_float(tmp_r);
dst[3] = ubyte_to_float(tmp_g);
}
}
src += block_size;
}
src_row += src_stride;
}
}
 
void
util_format_latc2_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint8_t tmp_r, tmp_g;
 
u_format_unsigned_fetch_texel_rgtc(0, src, i, j, &tmp_r, 2);
u_format_unsigned_fetch_texel_rgtc(0, src + 8, i, j, &tmp_g, 2);
dst[0] =
dst[1] =
dst[2] = ubyte_to_float(tmp_r);
dst[3] = ubyte_to_float(tmp_g);
}
 
 
void
util_format_latc2_snorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j)
{
fprintf(stderr,"%s\n", __func__);
}
 
void
util_format_latc2_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
fprintf(stderr,"%s\n", __func__);
}
 
void
util_format_latc2_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
fprintf(stderr,"%s\n", __func__);
}
 
void
util_format_latc2_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y, i, j;
int block_size = 16;
 
for(y = 0; y < height; y += 4) {
const int8_t *src = (int8_t *)src_row;
for(x = 0; x < width; x += 4) {
for(j = 0; j < 4; ++j) {
for(i = 0; i < 4; ++i) {
float *dst = dst_row + (y + j)*dst_stride/sizeof(*dst_row) + (x + i)*4;
int8_t tmp_r, tmp_g;
u_format_signed_fetch_texel_rgtc(0, src, i, j, &tmp_r, 2);
u_format_signed_fetch_texel_rgtc(0, src + 8, i, j, &tmp_g, 2);
dst[0] =
dst[1] =
dst[2] = byte_to_float_tex(tmp_r);
dst[3] = byte_to_float_tex(tmp_g);
}
}
src += block_size;
}
src_row += src_stride;
}
}
 
void
util_format_latc2_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
util_format_rxtc2_snorm_pack_rgba_float(dst_row, dst_stride, src_row, src_stride, width, height, 3);
}
 
void
util_format_latc2_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
int8_t tmp_r, tmp_g;
 
u_format_signed_fetch_texel_rgtc(0, (int8_t *)src, i, j, &tmp_r, 2);
u_format_signed_fetch_texel_rgtc(0, (int8_t *)src + 8, i, j, &tmp_g, 2);
dst[0] =
dst[1] =
dst[2] = byte_to_float_tex(tmp_r);
dst[3] = byte_to_float_tex(tmp_g);
}
 
 
#define TAG(x) u_format_unsigned_##x
#define TYPE uint8_t
#define T_MIN 0
#define T_MAX 255
 
#include "texcompress_rgtc_tmp.h"
 
#undef TYPE
#undef TAG
#undef T_MIN
#undef T_MAX
 
 
#define TAG(x) u_format_signed_##x
#define TYPE int8_t
#define T_MIN (int8_t)-128
#define T_MAX (int8_t)127
 
#include "texcompress_rgtc_tmp.h"
 
#undef TYPE
#undef TAG
#undef T_MIN
#undef T_MAX
/drivers/video/Gallium/auxiliary/util/u_format_latc.h
0,0 → 1,108
/**************************************************************************
*
* Copyright 2011 Red Hat Inc.
* 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 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
* THE COPYRIGHT HOLDERS, AUTHORS 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.
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
**************************************************************************/
 
#ifndef U_FORMAT_LATC_H_
#define U_FORMAT_LATC_H_
 
void
util_format_latc1_unorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j);
 
void
util_format_latc1_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_latc1_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_latc1_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_latc1_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_latc1_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j);
 
 
 
void
util_format_latc1_snorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j);
 
void
util_format_latc1_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_latc1_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_latc1_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_latc1_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_latc1_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j);
 
 
void
util_format_latc2_unorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j);
 
void
util_format_latc2_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_latc2_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_latc2_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_latc2_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_latc2_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j);
 
 
void
util_format_latc2_snorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j);
 
void
util_format_latc2_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_latc2_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_latc2_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_latc2_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_latc2_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j);
 
 
#endif
/drivers/video/Gallium/auxiliary/util/u_format_other.c
0,0 → 1,472
/**************************************************************************
*
* Copyright 2010 VMware, Inc.
* 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 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
* THE COPYRIGHT HOLDERS, AUTHORS 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.
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
**************************************************************************/
 
 
#include "u_math.h"
#include "u_format_other.h"
#include "u_format_rgb9e5.h"
#include "u_format_r11g11b10f.h"
 
 
void
util_format_r9g9b9e5_float_unpack_rgba_float(float *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
rgb9e5_to_float3(value, dst);
dst[3] = 1; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
void
util_format_r9g9b9e5_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
const float *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = float3_to_rgb9e5(src);
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
void
util_format_r9g9b9e5_float_fetch_rgba_float(float *dst, const uint8_t *src,
unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
rgb9e5_to_float3(value, dst);
dst[3] = 1; /* a */
}
 
 
void
util_format_r9g9b9e5_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
float p[3];
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
rgb9e5_to_float3(value, p);
dst[0] = float_to_ubyte(p[0]); /* r */
dst[1] = float_to_ubyte(p[1]); /* g */
dst[2] = float_to_ubyte(p[2]); /* b */
dst[3] = 255; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
 
void
util_format_r9g9b9e5_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
float p[3];
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value;
p[0] = ubyte_to_float(src[0]);
p[1] = ubyte_to_float(src[1]);
p[2] = ubyte_to_float(src[2]);
value = float3_to_rgb9e5(p);
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
 
void
util_format_r11g11b10_float_unpack_rgba_float(float *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
r11g11b10f_to_float3(value, dst);
dst[3] = 1; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
void
util_format_r11g11b10_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
const float *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = float3_to_r11g11b10f(src);
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
void
util_format_r11g11b10_float_fetch_rgba_float(float *dst, const uint8_t *src,
unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
r11g11b10f_to_float3(value, dst);
dst[3] = 1; /* a */
}
 
 
void
util_format_r11g11b10_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
float p[3];
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
r11g11b10f_to_float3(value, p);
dst[0] = float_to_ubyte(p[0]); /* r */
dst[1] = float_to_ubyte(p[1]); /* g */
dst[2] = float_to_ubyte(p[2]); /* b */
dst[3] = 255; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
 
void
util_format_r11g11b10_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
float p[3];
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value;
p[0] = ubyte_to_float(src[0]);
p[1] = ubyte_to_float(src[1]);
p[2] = ubyte_to_float(src[2]);
value = float3_to_r11g11b10f(p);
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
 
void
util_format_r1_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
 
}
 
 
void
util_format_r1_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
const float *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
 
}
 
 
void
util_format_r1_unorm_fetch_rgba_float(float *dst, const uint8_t *src,
unsigned i, unsigned j)
{
 
}
 
 
void
util_format_r1_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
 
}
 
 
void
util_format_r1_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
}
 
 
/*
* PIPE_FORMAT_R8G8Bx_SNORM
*
* A.k.a. D3DFMT_CxV8U8
*/
 
static uint8_t
r8g8bx_derive(int16_t r, int16_t g)
{
/* Derive blue from red and green components.
* Apparently, we must always use integers to perform calculations,
* otherwise the results won't match D3D's CxV8U8 definition.
*/
return (uint8_t)sqrtf(0x7f * 0x7f - r * r - g * g) * 0xff / 0x7f;
}
 
void
util_format_r8g8bx_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
 
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint16_t *src = (const uint16_t *)src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *src++;
int16_t r, g;
 
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap16(value);
#endif
 
r = ((int16_t)(value << 8)) >> 8;
g = ((int16_t)(value << 0)) >> 8;
 
dst[0] = (float)(r * (1.0f/0x7f)); /* r */
dst[1] = (float)(g * (1.0f/0x7f)); /* g */
dst[2] = r8g8bx_derive(r, g) * (1.0f/0xff); /* b */
dst[3] = 1.0f; /* a */
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
 
void
util_format_r8g8bx_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint16_t *src = (const uint16_t *)src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *src++;
int16_t r, g;
 
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap16(value);
#endif
 
r = ((int16_t)(value << 8)) >> 8;
g = ((int16_t)(value << 0)) >> 8;
 
dst[0] = (uint8_t)(((uint16_t)MAX2(r, 0)) * 0xff / 0x7f); /* r */
dst[1] = (uint8_t)(((uint16_t)MAX2(g, 0)) * 0xff / 0x7f); /* g */
dst[2] = r8g8bx_derive(r, g); /* b */
dst[3] = 255; /* a */
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
 
void
util_format_r8g8bx_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
const float *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint16_t *dst = (uint16_t *)dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
 
value |= (uint16_t)(((int8_t)(CLAMP(src[0], -1, 1) * 0x7f)) & 0xff) ;
value |= (uint16_t)((((int8_t)(CLAMP(src[1], -1, 1) * 0x7f)) & 0xff) << 8) ;
 
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap16(value);
#endif
 
*dst++ = value;
 
src += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
 
void
util_format_r8g8bx_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
 
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint16_t *dst = (uint16_t *)dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
 
value |= src[0] >> 1;
value |= (src[1] >> 1) << 8;
 
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap16(value);
#endif
 
*dst++ = value;
 
src += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
 
void
util_format_r8g8bx_snorm_fetch_rgba_float(float *dst, const uint8_t *src,
unsigned i, unsigned j)
{
uint16_t value = *(const uint16_t *)src;
int16_t r, g;
 
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap16(value);
#endif
 
r = ((int16_t)(value << 8)) >> 8;
g = ((int16_t)(value << 0)) >> 8;
 
dst[0] = r * (1.0f/0x7f); /* r */
dst[1] = g * (1.0f/0x7f); /* g */
dst[2] = r8g8bx_derive(r, g) * (1.0f/0xff); /* b */
dst[3] = 1.0f; /* a */
}
/drivers/video/Gallium/auxiliary/util/u_format_other.h
0,0 → 1,134
/**************************************************************************
*
* Copyright 2010 VMware, Inc.
* 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 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
* THE COPYRIGHT HOLDERS, AUTHORS 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.
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
**************************************************************************/
 
 
#ifndef U_FORMAT_OTHER_H_
#define U_FORMAT_OTHER_H_
 
 
#include "pipe/p_compiler.h"
 
 
void
util_format_r9g9b9e5_float_unpack_rgba_float(float *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height);
 
void
util_format_r9g9b9e5_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
const float *src_row, unsigned src_stride,
unsigned width, unsigned height);
 
void
util_format_r9g9b9e5_float_fetch_rgba_float(float *dst, const uint8_t *src,
unsigned i, unsigned j);
 
void
util_format_r9g9b9e5_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height);
 
void
util_format_r9g9b9e5_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height);
 
 
void
util_format_r11g11b10_float_unpack_rgba_float(float *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height);
 
void
util_format_r11g11b10_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
const float *src_row, unsigned src_stride,
unsigned width, unsigned height);
 
void
util_format_r11g11b10_float_fetch_rgba_float(float *dst, const uint8_t *src,
unsigned i, unsigned j);
 
void
util_format_r11g11b10_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height);
 
void
util_format_r11g11b10_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height);
 
 
void
util_format_r1_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height);
 
void
util_format_r1_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
const float *src_row, unsigned src_stride,
unsigned width, unsigned height);
 
void
util_format_r1_unorm_fetch_rgba_float(float *dst, const uint8_t *src,
unsigned i, unsigned j);
 
void
util_format_r1_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height);
 
void
util_format_r1_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height);
 
void
util_format_r8g8bx_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height);
 
void
util_format_r8g8bx_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
const float *src_row, unsigned src_stride,
unsigned width, unsigned height);
 
void
util_format_r8g8bx_snorm_fetch_rgba_float(float *dst, const uint8_t *src,
unsigned i, unsigned j);
 
void
util_format_r8g8bx_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height);
 
void
util_format_r8g8bx_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height);
 
#endif /* U_FORMAT_OTHER_H_ */
/drivers/video/Gallium/auxiliary/util/u_format_pack.py
0,0 → 1,700
#!/usr/bin/env python
 
'''
/**************************************************************************
*
* Copyright 2009-2010 VMware, Inc.
* 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 VMWARE 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
* Pixel format packing and unpacking functions.
*
* @author Jose Fonseca <jfonseca@vmware.com>
*/
'''
 
 
from u_format_parse import *
 
 
def generate_format_type(format):
'''Generate a structure that describes the format.'''
 
assert format.layout == PLAIN
print 'union util_format_%s {' % format.short_name()
if format.block_size() in (8, 16, 32, 64):
print ' uint%u_t value;' % (format.block_size(),)
 
use_bitfields = False
for channel in format.channels:
if channel.size % 8 or not is_pot(channel.size):
use_bitfields = True
 
print ' struct {'
for channel in format.channels:
if use_bitfields:
if channel.type == VOID:
if channel.size:
print ' unsigned %s:%u;' % (channel.name, channel.size)
elif channel.type == UNSIGNED:
print ' unsigned %s:%u;' % (channel.name, channel.size)
elif channel.type in (SIGNED, FIXED):
print ' int %s:%u;' % (channel.name, channel.size)
elif channel.type == FLOAT:
if channel.size == 64:
print ' double %s;' % (channel.name)
elif channel.size == 32:
print ' float %s;' % (channel.name)
else:
print ' unsigned %s:%u;' % (channel.name, channel.size)
else:
assert 0
else:
assert channel.size % 8 == 0 and is_pot(channel.size)
if channel.type == VOID:
if channel.size:
print ' uint%u_t %s;' % (channel.size, channel.name)
elif channel.type == UNSIGNED:
print ' uint%u_t %s;' % (channel.size, channel.name)
elif channel.type in (SIGNED, FIXED):
print ' int%u_t %s;' % (channel.size, channel.name)
elif channel.type == FLOAT:
if channel.size == 64:
print ' double %s;' % (channel.name)
elif channel.size == 32:
print ' float %s;' % (channel.name)
elif channel.size == 16:
print ' uint16_t %s;' % (channel.name)
else:
assert 0
else:
assert 0
print ' } chan;'
print '};'
print
 
 
def is_format_supported(format):
'''Determines whether we actually have the plumbing necessary to generate the
to read/write to/from this format.'''
 
# FIXME: Ideally we would support any format combination here.
 
if format.layout != PLAIN:
return False
 
for i in range(4):
channel = format.channels[i]
if channel.type not in (VOID, UNSIGNED, SIGNED, FLOAT, FIXED):
return False
if channel.type == FLOAT and channel.size not in (16, 32, 64):
return False
 
return True
 
def is_format_pure_unsigned(format):
for i in range(4):
channel = format.channels[i]
if channel.type not in (VOID, UNSIGNED):
return False
if channel.type == UNSIGNED and channel.pure == False:
return False
 
return True
 
 
def is_format_pure_signed(format):
for i in range(4):
channel = format.channels[i]
if channel.type not in (VOID, SIGNED):
return False
if channel.type == SIGNED and channel.pure == False:
return False
 
return True
 
def native_type(format):
'''Get the native appropriate for a format.'''
 
if format.name == 'PIPE_FORMAT_R11G11B10_FLOAT':
return 'uint32_t'
if format.name == 'PIPE_FORMAT_R9G9B9E5_FLOAT':
return 'uint32_t'
 
if format.layout == PLAIN:
if not format.is_array():
# For arithmetic pixel formats return the integer type that matches the whole pixel
return 'uint%u_t' % format.block_size()
else:
# For array pixel formats return the integer type that matches the color channel
channel = format.channels[0]
if channel.type in (UNSIGNED, VOID):
return 'uint%u_t' % channel.size
elif channel.type in (SIGNED, FIXED):
return 'int%u_t' % channel.size
elif channel.type == FLOAT:
if channel.size == 16:
return 'uint16_t'
elif channel.size == 32:
return 'float'
elif channel.size == 64:
return 'double'
else:
assert False
else:
assert False
else:
assert False
 
 
def intermediate_native_type(bits, sign):
'''Find a native type adequate to hold intermediate results of the request bit size.'''
 
bytes = 4 # don't use anything smaller than 32bits
while bytes * 8 < bits:
bytes *= 2
bits = bytes*8
 
if sign:
return 'int%u_t' % bits
else:
return 'uint%u_t' % bits
 
 
def get_one_shift(type):
'''Get the number of the bit that matches unity for this type.'''
if type.type == 'FLOAT':
assert False
if not type.norm:
return 0
if type.type == UNSIGNED:
return type.size
if type.type == SIGNED:
return type.size - 1
if type.type == FIXED:
return type.size / 2
assert False
 
 
def value_to_native(type, value):
'''Get the value of unity for this type.'''
if type.type == FLOAT:
return value
if type.type == FIXED:
return int(value * (1 << (type.size/2)))
if not type.norm:
return int(value)
if type.type == UNSIGNED:
return int(value * ((1 << type.size) - 1))
if type.type == SIGNED:
return int(value * ((1 << (type.size - 1)) - 1))
assert False
 
 
def native_to_constant(type, value):
'''Get the value of unity for this type.'''
if type.type == FLOAT:
if type.size <= 32:
return "%ff" % value
else:
return "%ff" % value
else:
return str(int(value))
 
 
def get_one(type):
'''Get the value of unity for this type.'''
return value_to_native(type, 1)
 
 
def clamp_expr(src_channel, dst_channel, dst_native_type, value):
'''Generate the expression to clamp the value in the source type to the
destination type range.'''
 
if src_channel == dst_channel:
return value
 
src_min = src_channel.min()
src_max = src_channel.max()
dst_min = dst_channel.min()
dst_max = dst_channel.max()
# Translate the destination range to the src native value
dst_min_native = value_to_native(src_channel, dst_min)
dst_max_native = value_to_native(src_channel, dst_max)
 
if src_min < dst_min and src_max > dst_max:
return 'CLAMP(%s, %s, %s)' % (value, dst_min_native, dst_max_native)
 
if src_max > dst_max:
return 'MIN2(%s, %s)' % (value, dst_max_native)
if src_min < dst_min:
return 'MAX2(%s, %s)' % (value, dst_min_native)
 
return value
 
 
def conversion_expr(src_channel,
dst_channel, dst_native_type,
value,
clamp=True,
src_colorspace = RGB,
dst_colorspace = RGB):
'''Generate the expression to convert a value between two types.'''
 
if src_colorspace != dst_colorspace:
if src_colorspace == SRGB:
assert src_channel.type == UNSIGNED
assert src_channel.norm
assert src_channel.size == 8
assert dst_colorspace == RGB
if dst_channel.type == FLOAT:
return 'util_format_srgb_8unorm_to_linear_float(%s)' % value
else:
assert dst_channel.type == UNSIGNED
assert dst_channel.norm
assert dst_channel.size == 8
return 'util_format_srgb_to_linear_8unorm(%s)' % value
elif dst_colorspace == SRGB:
assert dst_channel.type == UNSIGNED
assert dst_channel.norm
assert dst_channel.size == 8
assert src_colorspace == RGB
if src_channel.type == FLOAT:
return 'util_format_linear_float_to_srgb_8unorm(%s)' % value
else:
assert src_channel.type == UNSIGNED
assert src_channel.norm
assert src_channel.size == 8
return 'util_format_linear_to_srgb_8unorm(%s)' % value
elif src_colorspace == ZS:
pass
elif dst_colorspace == ZS:
pass
else:
assert 0
 
if src_channel == dst_channel:
return value
 
src_type = src_channel.type
src_size = src_channel.size
src_norm = src_channel.norm
src_pure = src_channel.pure
 
# Promote half to float
if src_type == FLOAT and src_size == 16:
value = 'util_half_to_float(%s)' % value
src_size = 32
 
# Special case for float <-> ubytes for more accurate results
# Done before clamping since these functions already take care of that
if src_type == UNSIGNED and src_norm and src_size == 8 and dst_channel.type == FLOAT and dst_channel.size == 32:
return 'ubyte_to_float(%s)' % value
if src_type == FLOAT and src_size == 32 and dst_channel.type == UNSIGNED and dst_channel.norm and dst_channel.size == 8:
return 'float_to_ubyte(%s)' % value
 
if clamp:
if dst_channel.type != FLOAT or src_type != FLOAT:
value = clamp_expr(src_channel, dst_channel, dst_native_type, value)
 
if src_type in (SIGNED, UNSIGNED) and dst_channel.type in (SIGNED, UNSIGNED):
if not src_norm and not dst_channel.norm:
# neither is normalized -- just cast
return '(%s)%s' % (dst_native_type, value)
 
src_one = get_one(src_channel)
dst_one = get_one(dst_channel)
 
if src_one > dst_one and src_norm and dst_channel.norm:
# We can just bitshift
src_shift = get_one_shift(src_channel)
dst_shift = get_one_shift(dst_channel)
value = '(%s >> %s)' % (value, src_shift - dst_shift)
else:
# We need to rescale using an intermediate type big enough to hold the multiplication of both
tmp_native_type = intermediate_native_type(src_size + dst_channel.size, src_channel.sign and dst_channel.sign)
value = '((%s)%s)' % (tmp_native_type, value)
value = '(%s * 0x%x / 0x%x)' % (value, dst_one, src_one)
value = '(%s)%s' % (dst_native_type, value)
return value
 
# Promote to either float or double
if src_type != FLOAT:
if src_norm or src_type == FIXED:
one = get_one(src_channel)
if src_size <= 23:
value = '(%s * (1.0f/0x%x))' % (value, one)
if dst_channel.size <= 32:
value = '(float)%s' % value
src_size = 32
else:
# bigger than single precision mantissa, use double
value = '(%s * (1.0/0x%x))' % (value, one)
src_size = 64
src_norm = False
else:
if src_size <= 23 or dst_channel.size <= 32:
value = '(float)%s' % value
src_size = 32
else:
# bigger than single precision mantissa, use double
value = '(double)%s' % value
src_size = 64
src_type = FLOAT
 
# Convert double or float to non-float
if dst_channel.type != FLOAT:
if dst_channel.norm or dst_channel.type == FIXED:
dst_one = get_one(dst_channel)
if dst_channel.size <= 23:
value = 'util_iround(%s * 0x%x)' % (value, dst_one)
else:
# bigger than single precision mantissa, use double
value = '(%s * (double)0x%x)' % (value, dst_one)
value = '(%s)%s' % (dst_native_type, value)
else:
# Cast double to float when converting to either half or float
if dst_channel.size <= 32 and src_size > 32:
value = '(float)%s' % value
src_size = 32
 
if dst_channel.size == 16:
value = 'util_float_to_half(%s)' % value
elif dst_channel.size == 64 and src_size < 64:
value = '(double)%s' % value
 
return value
 
 
def generate_unpack_kernel(format, dst_channel, dst_native_type):
 
if not is_format_supported(format):
return
assert format.layout == PLAIN
 
src_native_type = native_type(format)
 
if format.is_bitmask():
depth = format.block_size()
print ' uint%u_t value = *(const uint%u_t *)src;' % (depth, depth)
 
# Declare the intermediate variables
for i in range(format.nr_channels()):
src_channel = format.channels[i]
if src_channel.type == UNSIGNED:
print ' uint%u_t %s;' % (depth, src_channel.name)
elif src_channel.type == SIGNED:
print ' int%u_t %s;' % (depth, src_channel.name)
 
# Compute the intermediate unshifted values
for i in range(format.nr_channels()):
src_channel = format.channels[i]
value = 'value'
shift = src_channel.shift
if src_channel.type == UNSIGNED:
if shift:
value = '%s >> %u' % (value, shift)
if shift + src_channel.size < depth:
value = '(%s) & 0x%x' % (value, (1 << src_channel.size) - 1)
elif src_channel.type == SIGNED:
if shift + src_channel.size < depth:
# Align the sign bit
lshift = depth - (shift + src_channel.size)
value = '%s << %u' % (value, lshift)
# Cast to signed
value = '(int%u_t)(%s) ' % (depth, value)
if src_channel.size < depth:
# Align the LSB bit
rshift = depth - src_channel.size
value = '(%s) >> %u' % (value, rshift)
else:
value = None
if value is not None:
print ' %s = %s;' % (src_channel.name, value)
# Convert, swizzle, and store final values
for i in range(4):
swizzle = format.swizzles[i]
if swizzle < 4:
src_channel = format.channels[swizzle]
src_colorspace = format.colorspace
if src_colorspace == SRGB and i == 3:
# Alpha channel is linear
src_colorspace = RGB
value = src_channel.name
value = conversion_expr(src_channel,
dst_channel, dst_native_type,
value,
src_colorspace = src_colorspace)
elif swizzle == SWIZZLE_0:
value = '0'
elif swizzle == SWIZZLE_1:
value = get_one(dst_channel)
elif swizzle == SWIZZLE_NONE:
value = '0'
else:
assert False
print ' dst[%u] = %s; /* %s */' % (i, value, 'rgba'[i])
else:
print ' union util_format_%s pixel;' % format.short_name()
print ' memcpy(&pixel, src, sizeof pixel);'
for i in range(4):
swizzle = format.swizzles[i]
if swizzle < 4:
src_channel = format.channels[swizzle]
src_colorspace = format.colorspace
if src_colorspace == SRGB and i == 3:
# Alpha channel is linear
src_colorspace = RGB
value = 'pixel.chan.%s' % src_channel.name
value = conversion_expr(src_channel,
dst_channel, dst_native_type,
value,
src_colorspace = src_colorspace)
elif swizzle == SWIZZLE_0:
value = '0'
elif swizzle == SWIZZLE_1:
value = get_one(dst_channel)
elif swizzle == SWIZZLE_NONE:
value = '0'
else:
assert False
print ' dst[%u] = %s; /* %s */' % (i, value, 'rgba'[i])
 
def generate_pack_kernel(format, src_channel, src_native_type):
 
if not is_format_supported(format):
return
dst_native_type = native_type(format)
 
assert format.layout == PLAIN
 
inv_swizzle = format.inv_swizzles()
 
if format.is_bitmask():
depth = format.block_size()
print ' uint%u_t value = 0;' % depth
 
for i in range(4):
dst_channel = format.channels[i]
shift = dst_channel.shift
if inv_swizzle[i] is not None:
value ='src[%u]' % inv_swizzle[i]
dst_colorspace = format.colorspace
if dst_colorspace == SRGB and inv_swizzle[i] == 3:
# Alpha channel is linear
dst_colorspace = RGB
value = conversion_expr(src_channel,
dst_channel, dst_native_type,
value,
dst_colorspace = dst_colorspace)
if dst_channel.type in (UNSIGNED, SIGNED):
if shift + dst_channel.size < depth:
value = '(%s) & 0x%x' % (value, (1 << dst_channel.size) - 1)
if shift:
value = '(%s) << %u' % (value, shift)
if dst_channel.type == SIGNED:
# Cast to unsigned
value = '(uint%u_t)(%s) ' % (depth, value)
else:
value = None
if value is not None:
print ' value |= %s;' % (value)
print ' *(uint%u_t *)dst = value;' % depth
 
else:
print ' union util_format_%s pixel;' % format.short_name()
for i in range(4):
dst_channel = format.channels[i]
width = dst_channel.size
if inv_swizzle[i] is None:
continue
dst_colorspace = format.colorspace
if dst_colorspace == SRGB and inv_swizzle[i] == 3:
# Alpha channel is linear
dst_colorspace = RGB
value ='src[%u]' % inv_swizzle[i]
value = conversion_expr(src_channel,
dst_channel, dst_native_type,
value,
dst_colorspace = dst_colorspace)
print ' pixel.chan.%s = %s;' % (dst_channel.name, value)
print ' memcpy(dst, &pixel, sizeof pixel);'
 
def generate_format_unpack(format, dst_channel, dst_native_type, dst_suffix):
'''Generate the function to unpack pixels from a particular format'''
 
name = format.short_name()
 
print 'static INLINE void'
print 'util_format_%s_unpack_%s(%s *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)' % (name, dst_suffix, dst_native_type)
print '{'
 
if is_format_supported(format):
print ' unsigned x, y;'
print ' for(y = 0; y < height; y += %u) {' % (format.block_height,)
print ' %s *dst = dst_row;' % (dst_native_type)
print ' const uint8_t *src = src_row;'
print ' for(x = 0; x < width; x += %u) {' % (format.block_width,)
generate_unpack_kernel(format, dst_channel, dst_native_type)
print ' src += %u;' % (format.block_size() / 8,)
print ' dst += 4;'
print ' }'
print ' src_row += src_stride;'
print ' dst_row += dst_stride/sizeof(*dst_row);'
print ' }'
 
print '}'
print
 
def generate_format_pack(format, src_channel, src_native_type, src_suffix):
'''Generate the function to pack pixels to a particular format'''
 
name = format.short_name()
 
print 'static INLINE void'
print 'util_format_%s_pack_%s(uint8_t *dst_row, unsigned dst_stride, const %s *src_row, unsigned src_stride, unsigned width, unsigned height)' % (name, src_suffix, src_native_type)
print '{'
if is_format_supported(format):
print ' unsigned x, y;'
print ' for(y = 0; y < height; y += %u) {' % (format.block_height,)
print ' const %s *src = src_row;' % (src_native_type)
print ' uint8_t *dst = dst_row;'
print ' for(x = 0; x < width; x += %u) {' % (format.block_width,)
generate_pack_kernel(format, src_channel, src_native_type)
print ' src += 4;'
print ' dst += %u;' % (format.block_size() / 8,)
print ' }'
print ' dst_row += dst_stride;'
print ' src_row += src_stride/sizeof(*src_row);'
print ' }'
print '}'
print
 
def generate_format_fetch(format, dst_channel, dst_native_type, dst_suffix):
'''Generate the function to unpack pixels from a particular format'''
 
name = format.short_name()
 
print 'static INLINE void'
print 'util_format_%s_fetch_%s(%s *dst, const uint8_t *src, unsigned i, unsigned j)' % (name, dst_suffix, dst_native_type)
print '{'
 
if is_format_supported(format):
generate_unpack_kernel(format, dst_channel, dst_native_type)
 
print '}'
print
 
 
def is_format_hand_written(format):
return format.layout in ('s3tc', 'rgtc', 'etc', 'subsampled', 'other') or format.colorspace == ZS
 
 
def generate(formats):
print
print '#include "pipe/p_compiler.h"'
print '#include "u_math.h"'
print '#include "u_half.h"'
print '#include "u_format.h"'
print '#include "u_format_other.h"'
print '#include "u_format_srgb.h"'
print '#include "u_format_yuv.h"'
print '#include "u_format_zs.h"'
print
 
for format in formats:
if not is_format_hand_written(format):
if is_format_supported(format):
generate_format_type(format)
 
if is_format_pure_unsigned(format):
native_type = 'unsigned'
suffix = 'unsigned'
channel = Channel(UNSIGNED, False, True, 32)
 
generate_format_unpack(format, channel, native_type, suffix)
generate_format_pack(format, channel, native_type, suffix)
generate_format_fetch(format, channel, native_type, suffix)
 
channel = Channel(SIGNED, False, True, 32)
native_type = 'int'
suffix = 'signed'
generate_format_unpack(format, channel, native_type, suffix)
generate_format_pack(format, channel, native_type, suffix)
elif is_format_pure_signed(format):
native_type = 'int'
suffix = 'signed'
channel = Channel(SIGNED, False, True, 32)
 
generate_format_unpack(format, channel, native_type, suffix)
generate_format_pack(format, channel, native_type, suffix)
generate_format_fetch(format, channel, native_type, suffix)
 
native_type = 'unsigned'
suffix = 'unsigned'
channel = Channel(UNSIGNED, False, True, 32)
generate_format_unpack(format, channel, native_type, suffix)
generate_format_pack(format, channel, native_type, suffix)
else:
channel = Channel(FLOAT, False, False, 32)
native_type = 'float'
suffix = 'rgba_float'
 
generate_format_unpack(format, channel, native_type, suffix)
generate_format_pack(format, channel, native_type, suffix)
generate_format_fetch(format, channel, native_type, suffix)
 
channel = Channel(UNSIGNED, True, False, 8)
native_type = 'uint8_t'
suffix = 'rgba_8unorm'
 
generate_format_unpack(format, channel, native_type, suffix)
generate_format_pack(format, channel, native_type, suffix)
 
/drivers/video/Gallium/auxiliary/util/u_format_parse.py
0,0 → 1,323
#!/usr/bin/env python
 
'''
/**************************************************************************
*
* Copyright 2009 VMware, Inc.
* 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 VMWARE 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.
*
**************************************************************************/
'''
 
 
import sys
 
VOID, UNSIGNED, SIGNED, FIXED, FLOAT = range(5)
 
SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W, SWIZZLE_0, SWIZZLE_1, SWIZZLE_NONE, = range(7)
 
PLAIN = 'plain'
 
RGB = 'rgb'
SRGB = 'srgb'
YUV = 'yuv'
ZS = 'zs'
 
 
# Not cross-compiler friendly
is_big_endian = sys.byteorder == 'big'
 
def is_pot(x):
return (x & (x - 1)) == 0
 
 
VERY_LARGE = 99999999999999999999999
 
 
class Channel:
'''Describe the channel of a color channel.'''
def __init__(self, type, norm, pure, size, name = ''):
self.type = type
self.norm = norm
self.pure = pure
self.size = size
self.sign = type in (SIGNED, FIXED, FLOAT)
self.name = name
 
def __str__(self):
s = str(self.type)
if self.norm:
s += 'n'
if self.pure:
s += 'p'
s += str(self.size)
return s
 
def __eq__(self, other):
return self.type == other.type and self.norm == other.norm and self.pure == other.pure and self.size == other.size
 
def max(self):
'''Maximum representable number.'''
if self.type == FLOAT:
return VERY_LARGE
if self.type == FIXED:
return (1 << (self.size/2)) - 1
if self.norm:
return 1
if self.type == UNSIGNED:
return (1 << self.size) - 1
if self.type == SIGNED:
return (1 << (self.size - 1)) - 1
assert False
def min(self):
'''Minimum representable number.'''
if self.type == FLOAT:
return -VERY_LARGE
if self.type == FIXED:
return -(1 << (self.size/2))
if self.type == UNSIGNED:
return 0
if self.norm:
return -1
if self.type == SIGNED:
return -(1 << (self.size - 1))
assert False
 
 
class Format:
'''Describe a pixel format.'''
 
def __init__(self, name, layout, block_width, block_height, channels, swizzles, colorspace):
self.name = name
self.layout = layout
self.block_width = block_width
self.block_height = block_height
self.channels = channels
self.swizzles = swizzles
self.name = name
self.colorspace = colorspace
 
def __str__(self):
return self.name
 
def short_name(self):
'''Make up a short norm for a format, suitable to be used as suffix in
function names.'''
 
name = self.name
if name.startswith('PIPE_FORMAT_'):
name = name[len('PIPE_FORMAT_'):]
name = name.lower()
return name
 
def block_size(self):
size = 0
for channel in self.channels:
size += channel.size
return size
 
def nr_channels(self):
nr_channels = 0
for channel in self.channels:
if channel.size:
nr_channels += 1
return nr_channels
 
def is_array(self):
if self.layout != PLAIN:
return False
ref_channel = self.channels[0]
if ref_channel.type == VOID:
ref_channel = self.channels[1]
for channel in self.channels:
if channel.size and (channel.size != ref_channel.size or channel.size % 8):
return False
if channel.type != VOID:
if channel.type != ref_channel.type:
return False
if channel.norm != ref_channel.norm:
return False
if channel.pure != ref_channel.pure:
return False
return True
 
def is_mixed(self):
if self.layout != PLAIN:
return False
ref_channel = self.channels[0]
if ref_channel.type == VOID:
ref_channel = self.channels[1]
for channel in self.channels[1:]:
if channel.type != VOID:
if channel.type != ref_channel.type:
return True
if channel.norm != ref_channel.norm:
return True
if channel.pure != ref_channel.pure:
return True
return False
 
def is_pot(self):
return is_pot(self.block_size())
 
def is_int(self):
if self.layout != PLAIN:
return False
for channel in self.channels:
if channel.type not in (VOID, UNSIGNED, SIGNED):
return False
return True
 
def is_float(self):
if self.layout != PLAIN:
return False
for channel in self.channels:
if channel.type not in (VOID, FLOAT):
return False
return True
 
def is_bitmask(self):
if self.layout != PLAIN:
return False
if self.block_size() not in (8, 16, 32):
return False
for channel in self.channels:
if channel.type not in (VOID, UNSIGNED, SIGNED):
return False
return True
 
def inv_swizzles(self):
'''Return an array[4] of inverse swizzle terms'''
'''Only pick the first matching value to avoid l8 getting blue and i8 getting alpha'''
inv_swizzle = [None]*4
for i in range(4):
swizzle = self.swizzles[i]
if swizzle < 4 and inv_swizzle[swizzle] == None:
inv_swizzle[swizzle] = i
return inv_swizzle
 
def stride(self):
return self.block_size()/8
 
 
_type_parse_map = {
'': VOID,
'x': VOID,
'u': UNSIGNED,
's': SIGNED,
'h': FIXED,
'f': FLOAT,
}
 
_swizzle_parse_map = {
'x': SWIZZLE_X,
'y': SWIZZLE_Y,
'z': SWIZZLE_Z,
'w': SWIZZLE_W,
'0': SWIZZLE_0,
'1': SWIZZLE_1,
'_': SWIZZLE_NONE,
}
 
def parse(filename):
'''Parse the format descrition in CSV format in terms of the
Channel and Format classes above.'''
 
stream = open(filename)
formats = []
for line in stream:
try:
comment = line.index('#')
except ValueError:
pass
else:
line = line[:comment]
line = line.strip()
if not line:
continue
 
fields = [field.strip() for field in line.split(',')]
name = fields[0]
layout = fields[1]
block_width, block_height = map(int, fields[2:4])
 
swizzles = [_swizzle_parse_map[swizzle] for swizzle in fields[8]]
colorspace = fields[9]
if layout == PLAIN:
names = ['']*4
if colorspace in (RGB, SRGB):
for i in range(4):
swizzle = swizzles[i]
if swizzle < 4:
names[swizzle] += 'rgba'[i]
elif colorspace == ZS:
for i in range(4):
swizzle = swizzles[i]
if swizzle < 4:
names[swizzle] += 'zs'[i]
else:
assert False
for i in range(4):
if names[i] == '':
names[i] = 'x'
else:
names = ['x', 'y', 'z', 'w']
 
channels = []
for i in range(0, 4):
field = fields[4 + i]
if field:
type = _type_parse_map[field[0]]
if field[1] == 'n':
norm = True
pure = False
size = int(field[2:])
elif field[1] == 'p':
pure = True
norm = False
size = int(field[2:])
else:
norm = False
pure = False
size = int(field[1:])
else:
type = VOID
norm = False
pure = False
size = 0
channel = Channel(type, norm, pure, size, names[i])
channels.append(channel)
 
shift = 0
for channel in channels[3::-1] if is_big_endian else channels:
channel.shift = shift
shift += channel.size
 
format = Format(name, layout, block_width, block_height, channels, swizzles, colorspace)
formats.append(format)
return formats
 
/drivers/video/Gallium/auxiliary/util/u_format_r11g11b10f.h
0,0 → 1,232
/*
* Copyright (C) 2011 Marek Olšák <maraeo@gmail.com>
*
* 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, sublicense,
* 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 NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
*/
 
/* Based on code from The OpenGL Programming Guide / 7th Edition, Appendix J.
* Available here: http://www.opengl-redbook.com/appendices/
* The algorithm in the book contains a bug though, which is fixed in the code
* below.
*/
 
#define UF11(e, m) ((e << 6) | (m))
#define UF11_EXPONENT_BIAS 15
#define UF11_EXPONENT_BITS 0x1F
#define UF11_EXPONENT_SHIFT 6
#define UF11_MANTISSA_BITS 0x3F
#define UF11_MANTISSA_SHIFT (23 - UF11_EXPONENT_SHIFT)
#define UF11_MAX_EXPONENT (UF11_EXPONENT_BITS << UF11_EXPONENT_SHIFT)
 
#define UF10(e, m) ((e << 5) | (m))
#define UF10_EXPONENT_BIAS 15
#define UF10_EXPONENT_BITS 0x1F
#define UF10_EXPONENT_SHIFT 5
#define UF10_MANTISSA_BITS 0x1F
#define UF10_MANTISSA_SHIFT (23 - UF10_EXPONENT_SHIFT)
#define UF10_MAX_EXPONENT (UF10_EXPONENT_BITS << UF10_EXPONENT_SHIFT)
 
#define F32_INFINITY 0x7f800000
 
static INLINE unsigned f32_to_uf11(float val)
{
union {
float f;
uint32_t ui;
} f32 = {val};
 
uint16_t uf11 = 0;
 
/* Decode little-endian 32-bit floating-point value */
int sign = (f32.ui >> 16) & 0x8000;
/* Map exponent to the range [-127,128] */
int exponent = ((f32.ui >> 23) & 0xff) - 127;
int mantissa = f32.ui & 0x007fffff;
 
if (exponent == 128) { /* Infinity or NaN */
/* From the GL_EXT_packed_float spec:
*
* "Additionally: negative infinity is converted to zero; positive
* infinity is converted to positive infinity; and both positive and
* negative NaN are converted to positive NaN."
*/
uf11 = UF11_MAX_EXPONENT;
if (mantissa) {
uf11 |= 1; /* NaN */
} else {
if (sign)
uf11 = 0; /* 0.0 */
}
} else if (sign) {
return 0;
} else if (val > 65024.0f) {
/* From the GL_EXT_packed_float spec:
*
* "Likewise, finite positive values greater than 65024 (the maximum
* finite representable unsigned 11-bit floating-point value) are
* converted to 65024."
*/
uf11 = UF11(30, 63);
}
else if (exponent > -15) { /* Representable value */
exponent += UF11_EXPONENT_BIAS;
mantissa >>= UF11_MANTISSA_SHIFT;
uf11 = exponent << UF11_EXPONENT_SHIFT | mantissa;
}
 
return uf11;
}
 
static INLINE float uf11_to_f32(uint16_t val)
{
union {
float f;
uint32_t ui;
} f32;
 
int exponent = (val & 0x07c0) >> UF11_EXPONENT_SHIFT;
int mantissa = (val & 0x003f);
 
f32.f = 0.0;
 
if (exponent == 0) {
if (mantissa != 0) {
const float scale = 1.0 / (1 << 20);
f32.f = scale * mantissa;
}
}
else if (exponent == 31) {
f32.ui = F32_INFINITY | mantissa;
}
else {
float scale, decimal;
exponent -= 15;
if (exponent < 0) {
scale = 1.0f / (1 << -exponent);
}
else {
scale = (float) (1 << exponent);
}
decimal = 1.0f + (float) mantissa / 64;
f32.f = scale * decimal;
}
 
return f32.f;
}
 
static INLINE unsigned f32_to_uf10(float val)
{
union {
float f;
uint32_t ui;
} f32 = {val};
 
uint16_t uf10 = 0;
 
/* Decode little-endian 32-bit floating-point value */
int sign = (f32.ui >> 16) & 0x8000;
/* Map exponent to the range [-127,128] */
int exponent = ((f32.ui >> 23) & 0xff) - 127;
int mantissa = f32.ui & 0x007fffff;
 
if (exponent == 128) {
/* From the GL_EXT_packed_float spec:
*
* "Additionally: negative infinity is converted to zero; positive
* infinity is converted to positive infinity; and both positive and
* negative NaN are converted to positive NaN."
*/
uf10 = UF10_MAX_EXPONENT;
if (mantissa) {
uf10 |= 1; /* NaN */
} else {
if (sign)
uf10 = 0; /* 0.0 */
}
} else if (sign) {
return 0;
} else if (val > 64512.0f) { /* Overflow - flush to Infinity */
/* From the GL_EXT_packed_float spec:
*
* "Likewise, finite positive values greater than 64512 (the maximum
* finite representable unsigned 10-bit floating-point value) are
* converted to 64512."
*/
uf10 = UF10(30, 31);
}
else if (exponent > -15) { /* Representable value */
exponent += UF10_EXPONENT_BIAS;
mantissa >>= UF10_MANTISSA_SHIFT;
uf10 = exponent << UF10_EXPONENT_SHIFT | mantissa;
}
 
return uf10;
}
 
static INLINE float uf10_to_f32(uint16_t val)
{
union {
float f;
uint32_t ui;
} f32;
 
int exponent = (val & 0x03e0) >> UF10_EXPONENT_SHIFT;
int mantissa = (val & 0x001f);
 
f32.f = 0.0;
 
if (exponent == 0) {
if (mantissa != 0) {
const float scale = 1.0 / (1 << 20);
f32.f = scale * mantissa;
}
}
else if (exponent == 31) {
f32.ui = F32_INFINITY | mantissa;
}
else {
float scale, decimal;
exponent -= 15;
if (exponent < 0) {
scale = 1.0f / (1 << -exponent);
}
else {
scale = (float) (1 << exponent);
}
decimal = 1.0f + (float) mantissa / 32;
f32.f = scale * decimal;
}
 
return f32.f;
}
 
static INLINE unsigned float3_to_r11g11b10f(const float rgb[3])
{
return ( f32_to_uf11(rgb[0]) & 0x7ff) |
((f32_to_uf11(rgb[1]) & 0x7ff) << 11) |
((f32_to_uf10(rgb[2]) & 0x3ff) << 22);
}
 
static INLINE void r11g11b10f_to_float3(unsigned rgb, float retval[3])
{
retval[0] = uf11_to_f32( rgb & 0x7ff);
retval[1] = uf11_to_f32((rgb >> 11) & 0x7ff);
retval[2] = uf10_to_f32((rgb >> 22) & 0x3ff);
}
/drivers/video/Gallium/auxiliary/util/u_format_rgb9e5.h
0,0 → 1,164
/*
* Copyright (C) 2011 Marek Olšák <maraeo@gmail.com>
*
* 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, sublicense,
* 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 NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
*/
 
/* Copied from EXT_texture_shared_exponent and edited. */
 
#ifndef RGB9E5_H
#define RGB9E5_H
 
#include <math.h>
#include <assert.h>
 
#define RGB9E5_EXPONENT_BITS 5
#define RGB9E5_MANTISSA_BITS 9
#define RGB9E5_EXP_BIAS 15
#define RGB9E5_MAX_VALID_BIASED_EXP 31
 
#define MAX_RGB9E5_EXP (RGB9E5_MAX_VALID_BIASED_EXP - RGB9E5_EXP_BIAS)
#define RGB9E5_MANTISSA_VALUES (1<<RGB9E5_MANTISSA_BITS)
#define MAX_RGB9E5_MANTISSA (RGB9E5_MANTISSA_VALUES-1)
#define MAX_RGB9E5 (((float)MAX_RGB9E5_MANTISSA)/RGB9E5_MANTISSA_VALUES * (1<<MAX_RGB9E5_EXP))
#define EPSILON_RGB9E5 ((1.0/RGB9E5_MANTISSA_VALUES) / (1<<RGB9E5_EXP_BIAS))
 
typedef union {
unsigned int raw;
float value;
struct {
#if defined(MESA_BIG_ENDIAN) || defined(PIPE_ARCH_BIG_ENDIAN)
unsigned int negative:1;
unsigned int biasedexponent:8;
unsigned int mantissa:23;
#else
unsigned int mantissa:23;
unsigned int biasedexponent:8;
unsigned int negative:1;
#endif
} field;
} float754;
 
typedef union {
unsigned int raw;
struct {
#if defined(MESA_BIG_ENDIAN) || defined(PIPE_ARCH_BIG_ENDIAN)
unsigned int biasedexponent:RGB9E5_EXPONENT_BITS;
unsigned int b:RGB9E5_MANTISSA_BITS;
unsigned int g:RGB9E5_MANTISSA_BITS;
unsigned int r:RGB9E5_MANTISSA_BITS;
#else
unsigned int r:RGB9E5_MANTISSA_BITS;
unsigned int g:RGB9E5_MANTISSA_BITS;
unsigned int b:RGB9E5_MANTISSA_BITS;
unsigned int biasedexponent:RGB9E5_EXPONENT_BITS;
#endif
} field;
} rgb9e5;
 
static INLINE float rgb9e5_ClampRange(float x)
{
if (x > 0.0) {
if (x >= MAX_RGB9E5) {
return MAX_RGB9E5;
} else {
return x;
}
} else {
/* NaN gets here too since comparisons with NaN always fail! */
return 0.0;
}
}
 
/* Ok, FloorLog2 is not correct for the denorm and zero values, but we
are going to do a max of this value with the minimum rgb9e5 exponent
that will hide these problem cases. */
static INLINE int rgb9e5_FloorLog2(float x)
{
float754 f;
 
f.value = x;
return (f.field.biasedexponent - 127);
}
 
static INLINE unsigned float3_to_rgb9e5(const float rgb[3])
{
rgb9e5 retval;
float maxrgb;
int rm, gm, bm;
float rc, gc, bc;
int exp_shared, maxm;
double denom;
 
rc = rgb9e5_ClampRange(rgb[0]);
gc = rgb9e5_ClampRange(rgb[1]);
bc = rgb9e5_ClampRange(rgb[2]);
 
maxrgb = MAX3(rc, gc, bc);
exp_shared = MAX2(-RGB9E5_EXP_BIAS-1, rgb9e5_FloorLog2(maxrgb)) + 1 + RGB9E5_EXP_BIAS;
assert(exp_shared <= RGB9E5_MAX_VALID_BIASED_EXP);
assert(exp_shared >= 0);
/* This pow function could be replaced by a table. */
denom = pow(2, exp_shared - RGB9E5_EXP_BIAS - RGB9E5_MANTISSA_BITS);
 
maxm = (int) floor(maxrgb / denom + 0.5);
if (maxm == MAX_RGB9E5_MANTISSA+1) {
denom *= 2;
exp_shared += 1;
assert(exp_shared <= RGB9E5_MAX_VALID_BIASED_EXP);
} else {
assert(maxm <= MAX_RGB9E5_MANTISSA);
}
 
rm = (int) floor(rc / denom + 0.5);
gm = (int) floor(gc / denom + 0.5);
bm = (int) floor(bc / denom + 0.5);
 
assert(rm <= MAX_RGB9E5_MANTISSA);
assert(gm <= MAX_RGB9E5_MANTISSA);
assert(bm <= MAX_RGB9E5_MANTISSA);
assert(rm >= 0);
assert(gm >= 0);
assert(bm >= 0);
 
retval.field.r = rm;
retval.field.g = gm;
retval.field.b = bm;
retval.field.biasedexponent = exp_shared;
 
return retval.raw;
}
 
static INLINE void rgb9e5_to_float3(unsigned rgb, float retval[3])
{
rgb9e5 v;
int exponent;
float scale;
 
v.raw = rgb;
exponent = v.field.biasedexponent - RGB9E5_EXP_BIAS - RGB9E5_MANTISSA_BITS;
scale = (float) pow(2, exponent);
 
retval[0] = v.field.r * scale;
retval[1] = v.field.g * scale;
retval[2] = v.field.b * scale;
}
 
#endif
/drivers/video/Gallium/auxiliary/util/u_format_rgtc.c
0,0 → 1,474
/**************************************************************************
*
* Copyright (C) 2011 Red Hat Inc.
*
* 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, sublicense,
* 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
*
**************************************************************************/
 
#include <stdio.h>
#include "u_math.h"
#include "u_format.h"
#include "u_format_rgtc.h"
 
static void u_format_unsigned_encode_rgtc_ubyte(uint8_t *blkaddr, uint8_t srccolors[4][4],
int numxpixels, int numypixels);
 
static void u_format_unsigned_fetch_texel_rgtc(unsigned srcRowStride, const uint8_t *pixdata,
unsigned i, unsigned j, uint8_t *value, unsigned comps);
 
static void u_format_signed_encode_rgtc_ubyte(int8_t *blkaddr, int8_t srccolors[4][4],
int numxpixels, int numypixels);
 
static void u_format_signed_fetch_texel_rgtc(unsigned srcRowStride, const int8_t *pixdata,
unsigned i, unsigned j, int8_t *value, unsigned comps);
 
void
util_format_rgtc1_unorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j)
{
u_format_unsigned_fetch_texel_rgtc(0, src, i, j, dst, 1);
dst[1] = 0;
dst[2] = 0;
dst[3] = 255;
}
 
void
util_format_rgtc1_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
const unsigned bw = 4, bh = 4, comps = 4;
unsigned x, y, i, j;
unsigned block_size = 8;
 
for(y = 0; y < height; y += bh) {
const uint8_t *src = src_row;
for(x = 0; x < width; x += bw) {
for(j = 0; j < bh; ++j) {
for(i = 0; i < bw; ++i) {
uint8_t *dst = dst_row + (y + j)*dst_stride/sizeof(*dst_row) + (x + i)*comps;
u_format_unsigned_fetch_texel_rgtc(0, src, i, j, dst, 1);
dst[1] = 0;
dst[2] = 0;
dst[3] = 255;
}
}
src += block_size;
}
src_row += src_stride;
}
}
 
void
util_format_rgtc1_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row,
unsigned src_stride, unsigned width, unsigned height)
{
const unsigned bw = 4, bh = 4, bytes_per_block = 8;
unsigned x, y, i, j;
 
for(y = 0; y < height; y += bh) {
uint8_t *dst = dst_row;
for(x = 0; x < width; x += bw) {
uint8_t tmp[4][4]; /* [bh][bw][comps] */
for(j = 0; j < bh; ++j) {
for(i = 0; i < bw; ++i) {
tmp[j][i] = src_row[(y + j)*src_stride/sizeof(*src_row) + (x + i)*4];
}
}
u_format_unsigned_encode_rgtc_ubyte(dst, tmp, 4, 4);
dst += bytes_per_block;
}
dst_row += dst_stride / sizeof(*dst_row);
}
}
 
void
util_format_rgtc1_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y, i, j;
int block_size = 8;
for(y = 0; y < height; y += 4) {
const uint8_t *src = src_row;
for(x = 0; x < width; x += 4) {
for(j = 0; j < 4; ++j) {
for(i = 0; i < 4; ++i) {
float *dst = dst_row + (y + j)*dst_stride/sizeof(*dst_row) + (x + i)*4;
uint8_t tmp_r;
u_format_unsigned_fetch_texel_rgtc(0, src, i, j, &tmp_r, 1);
dst[0] = ubyte_to_float(tmp_r);
dst[1] = 0.0;
dst[2] = 0.0;
dst[3] = 1.0;
}
}
src += block_size;
}
src_row += src_stride;
}
}
 
void
util_format_rgtc1_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
const unsigned bw = 4, bh = 4, bytes_per_block = 8;
unsigned x, y, i, j;
 
for(y = 0; y < height; y += bh) {
uint8_t *dst = dst_row;
for(x = 0; x < width; x += bw) {
uint8_t tmp[4][4]; /* [bh][bw][comps] */
for(j = 0; j < bh; ++j) {
for(i = 0; i < bw; ++i) {
tmp[j][i] = float_to_ubyte(src_row[(y + j)*src_stride/sizeof(*src_row) + (x + i)*4]);
}
}
u_format_unsigned_encode_rgtc_ubyte(dst, tmp, 4, 4);
dst += bytes_per_block;
}
dst_row += dst_stride / sizeof(*dst_row);
}
}
 
void
util_format_rgtc1_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint8_t tmp_r;
u_format_unsigned_fetch_texel_rgtc(0, src, i, j, &tmp_r, 1);
dst[0] = ubyte_to_float(tmp_r);
dst[1] = 0.0;
dst[2] = 0.0;
dst[3] = 1.0;
}
 
void
util_format_rgtc1_snorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j)
{
fprintf(stderr,"%s\n", __func__);
}
 
void
util_format_rgtc1_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
fprintf(stderr,"%s\n", __func__);
}
 
void
util_format_rgtc1_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
fprintf(stderr,"%s\n", __func__);
}
 
void
util_format_rgtc1_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
const unsigned bw = 4, bh = 4, bytes_per_block = 8;
unsigned x, y, i, j;
 
for(y = 0; y < height; y += bh) {
int8_t *dst = (int8_t *)dst_row;
for(x = 0; x < width; x += bw) {
int8_t tmp[4][4]; /* [bh][bw][comps] */
for(j = 0; j < bh; ++j) {
for(i = 0; i < bw; ++i) {
tmp[j][i] = float_to_byte_tex(src_row[(y + j)*src_stride/sizeof(*src_row) + (x + i)*4]);
}
}
u_format_signed_encode_rgtc_ubyte(dst, tmp, 4, 4);
dst += bytes_per_block;
}
dst_row += dst_stride / sizeof(*dst_row);
}
}
 
void
util_format_rgtc1_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y, i, j;
int block_size = 8;
for(y = 0; y < height; y += 4) {
const int8_t *src = (int8_t *)src_row;
for(x = 0; x < width; x += 4) {
for(j = 0; j < 4; ++j) {
for(i = 0; i < 4; ++i) {
float *dst = dst_row + (y + j)*dst_stride/sizeof(*dst_row) + (x + i)*4;
int8_t tmp_r;
u_format_signed_fetch_texel_rgtc(0, src, i, j, &tmp_r, 1);
dst[0] = byte_to_float_tex(tmp_r);
dst[1] = 0.0;
dst[2] = 0.0;
dst[3] = 1.0;
}
}
src += block_size;
}
src_row += src_stride;
}
}
 
void
util_format_rgtc1_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
int8_t tmp_r;
u_format_signed_fetch_texel_rgtc(0, (int8_t *)src, i, j, &tmp_r, 1);
dst[0] = byte_to_float_tex(tmp_r);
dst[1] = 0.0;
dst[2] = 0.0;
dst[3] = 1.0;
}
 
 
void
util_format_rgtc2_unorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j)
{
u_format_unsigned_fetch_texel_rgtc(0, src, i, j, dst, 2);
u_format_unsigned_fetch_texel_rgtc(0, src + 8, i, j, dst + 1, 2);
dst[2] = 0;
dst[3] = 255;
}
 
void
util_format_rgtc2_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
const unsigned bw = 4, bh = 4, comps = 4;
unsigned x, y, i, j;
unsigned block_size = 16;
 
for(y = 0; y < height; y += bh) {
const uint8_t *src = src_row;
for(x = 0; x < width; x += bw) {
for(j = 0; j < bh; ++j) {
for(i = 0; i < bw; ++i) {
uint8_t *dst = dst_row + (y + j)*dst_stride/sizeof(*dst_row) + (x + i)*comps;
u_format_unsigned_fetch_texel_rgtc(0, src, i, j, dst, 2);
u_format_unsigned_fetch_texel_rgtc(0, src + 8, i, j, dst + 1, 2);
dst[2] = 0;
dst[3] = 255;
}
}
src += block_size;
}
src_row += src_stride;
}
}
 
void
util_format_rgtc2_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
const unsigned bw = 4, bh = 4, bytes_per_block = 16;
unsigned x, y, i, j;
 
for(y = 0; y < height; y += bh) {
uint8_t *dst = dst_row;
for(x = 0; x < width; x += bw) {
uint8_t tmp_r[4][4]; /* [bh][bw] */
uint8_t tmp_g[4][4]; /* [bh][bw] */
for(j = 0; j < bh; ++j) {
for(i = 0; i < bw; ++i) {
tmp_r[j][i] = src_row[(y + j)*src_stride/sizeof(*src_row) + (x + i)*4];
tmp_g[j][i] = src_row[((y + j)*src_stride/sizeof(*src_row) + (x + i)*4) + 1];
}
}
u_format_unsigned_encode_rgtc_ubyte(dst, tmp_r, 4, 4);
u_format_unsigned_encode_rgtc_ubyte(dst + 8, tmp_g, 4, 4);
dst += bytes_per_block;
}
dst_row += dst_stride / sizeof(*dst_row);
}
}
 
void
util_format_rxtc2_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height, unsigned chan2off)
{
const unsigned bw = 4, bh = 4, bytes_per_block = 16;
unsigned x, y, i, j;
 
for(y = 0; y < height; y += bh) {
uint8_t *dst = dst_row;
for(x = 0; x < width; x += bw) {
uint8_t tmp_r[4][4]; /* [bh][bw][comps] */
uint8_t tmp_g[4][4]; /* [bh][bw][comps] */
for(j = 0; j < bh; ++j) {
for(i = 0; i < bw; ++i) {
tmp_r[j][i] = float_to_ubyte(src_row[(y + j)*src_stride/sizeof(*src_row) + (x + i)*4]);
tmp_g[j][i] = float_to_ubyte(src_row[(y + j)*src_stride/sizeof(*src_row) + (x + i)*4 + chan2off]);
}
}
u_format_unsigned_encode_rgtc_ubyte(dst, tmp_r, 4, 4);
u_format_unsigned_encode_rgtc_ubyte(dst + 8, tmp_g, 4, 4);
dst += bytes_per_block;
}
dst_row += dst_stride / sizeof(*dst_row);
}
}
 
void
util_format_rgtc2_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
util_format_rxtc2_unorm_pack_rgba_float(dst_row, dst_stride, src_row, src_stride, width, height, 1);
}
 
void
util_format_rgtc2_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y, i, j;
int block_size = 16;
for(y = 0; y < height; y += 4) {
const uint8_t *src = src_row;
for(x = 0; x < width; x += 4) {
for(j = 0; j < 4; ++j) {
for(i = 0; i < 4; ++i) {
float *dst = dst_row + (y + j)*dst_stride/sizeof(*dst_row) + (x + i)*4;
uint8_t tmp_r, tmp_g;
u_format_unsigned_fetch_texel_rgtc(0, src, i, j, &tmp_r, 2);
u_format_unsigned_fetch_texel_rgtc(0, src + 8, i, j, &tmp_g, 2);
dst[0] = ubyte_to_float(tmp_r);
dst[1] = ubyte_to_float(tmp_g);
dst[2] = 0.0;
dst[3] = 1.0;
}
}
src += block_size;
}
src_row += src_stride;
}
}
 
void
util_format_rgtc2_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint8_t tmp_r, tmp_g;
u_format_unsigned_fetch_texel_rgtc(0, src, i, j, &tmp_r, 2);
u_format_unsigned_fetch_texel_rgtc(0, src + 8, i, j, &tmp_g, 2);
dst[0] = ubyte_to_float(tmp_r);
dst[1] = ubyte_to_float(tmp_g);
dst[2] = 0.0;
dst[3] = 1.0;
}
 
 
void
util_format_rgtc2_snorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j)
{
fprintf(stderr,"%s\n", __func__);
}
 
void
util_format_rgtc2_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
fprintf(stderr,"%s\n", __func__);
}
 
void
util_format_rgtc2_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
fprintf(stderr,"%s\n", __func__);
}
 
void
util_format_rgtc2_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y, i, j;
int block_size = 16;
for(y = 0; y < height; y += 4) {
const int8_t *src = (int8_t *)src_row;
for(x = 0; x < width; x += 4) {
for(j = 0; j < 4; ++j) {
for(i = 0; i < 4; ++i) {
float *dst = dst_row + (y + j)*dst_stride/sizeof(*dst_row) + (x + i)*4;
int8_t tmp_r, tmp_g;
u_format_signed_fetch_texel_rgtc(0, src, i, j, &tmp_r, 2);
u_format_signed_fetch_texel_rgtc(0, src + 8, i, j, &tmp_g, 2);
dst[0] = byte_to_float_tex(tmp_r);
dst[1] = byte_to_float_tex(tmp_g);
dst[2] = 0.0;
dst[3] = 1.0;
}
}
src += block_size;
}
src_row += src_stride;
}
}
 
void
util_format_rxtc2_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height, unsigned chan2off)
{
const unsigned bw = 4, bh = 4, bytes_per_block = 16;
unsigned x, y, i, j;
 
for(y = 0; y < height; y += bh) {
int8_t *dst = (int8_t *)dst_row;
for(x = 0; x < width; x += bw) {
int8_t tmp_r[4][4]; /* [bh][bw][comps] */
int8_t tmp_g[4][4]; /* [bh][bw][comps] */
for(j = 0; j < bh; ++j) {
for(i = 0; i < bw; ++i) {
tmp_r[j][i] = float_to_byte_tex(src_row[(y + j)*src_stride/sizeof(*src_row) + (x + i)*4]);
tmp_g[j][i] = float_to_byte_tex(src_row[(y + j)*src_stride/sizeof(*src_row) + (x + i)*4 + chan2off]);
}
}
u_format_signed_encode_rgtc_ubyte(dst, tmp_r, 4, 4);
u_format_signed_encode_rgtc_ubyte(dst + 8, tmp_g, 4, 4);
dst += bytes_per_block;
}
dst_row += dst_stride / sizeof(*dst_row);
}
}
 
void
util_format_rgtc2_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
util_format_rxtc2_snorm_pack_rgba_float(dst_row, dst_stride, src_row, src_stride, width, height, 1);
}
 
void
util_format_rgtc2_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
int8_t tmp_r, tmp_g;
u_format_signed_fetch_texel_rgtc(0, (int8_t *)src, i, j, &tmp_r, 2);
u_format_signed_fetch_texel_rgtc(0, (int8_t *)src + 8, i, j, &tmp_g, 2);
dst[0] = byte_to_float_tex(tmp_r);
dst[1] = byte_to_float_tex(tmp_g);
dst[2] = 0.0;
dst[3] = 1.0;
}
 
 
#define TAG(x) u_format_unsigned_##x
#define TYPE uint8_t
#define T_MIN 0
#define T_MAX 255
 
#include "texcompress_rgtc_tmp.h"
 
#undef TYPE
#undef TAG
#undef T_MIN
#undef T_MAX
 
 
#define TAG(x) u_format_signed_##x
#define TYPE int8_t
#define T_MIN (int8_t)-128
#define T_MAX (int8_t)127
 
#include "texcompress_rgtc_tmp.h"
 
#undef TYPE
#undef TAG
#undef T_MIN
#undef T_MAX
/drivers/video/Gallium/auxiliary/util/u_format_rgtc.h
0,0 → 1,114
/**************************************************************************
*
* Copyright 2011 Red Hat Inc.
* 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 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
* THE COPYRIGHT HOLDERS, AUTHORS 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.
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
**************************************************************************/
 
#ifndef U_FORMAT_RGTC_H_
#define U_FORMAT_RGTC_H_
 
void
util_format_rgtc1_unorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j);
 
void
util_format_rgtc1_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_rgtc1_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_rgtc1_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_rgtc1_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_rgtc1_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j);
 
 
 
void
util_format_rgtc1_snorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j);
 
void
util_format_rgtc1_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_rgtc1_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_rgtc1_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_rgtc1_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_rgtc1_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j);
 
 
void
util_format_rgtc2_unorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j);
 
void
util_format_rgtc2_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_rgtc2_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_rxtc2_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height, unsigned chan2off);
 
void
util_format_rgtc2_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_rgtc2_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_rgtc2_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j);
 
 
void
util_format_rgtc2_snorm_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j);
 
void
util_format_rgtc2_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_rgtc2_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_rgtc2_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_rxtc2_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height, unsigned chan2off);
 
void
util_format_rgtc2_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_rgtc2_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j);
 
 
#endif
/drivers/video/Gallium/auxiliary/util/u_format_s3tc.c
0,0 → 1,740
/**************************************************************************
*
* Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
* Copyright (c) 2008 VMware, Inc.
*
* 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, sublicense,
* 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
*
**************************************************************************/
 
#include "u_dl.h"
#include "u_math.h"
#include "u_format.h"
#include "u_format_s3tc.h"
 
 
#if defined(_WIN32) || defined(WIN32)
#define DXTN_LIBNAME "dxtn.dll"
#elif defined(__APPLE__)
#define DXTN_LIBNAME "libtxc_dxtn.dylib"
#else
#define DXTN_LIBNAME "libtxc_dxtn.so"
#endif
 
 
static void
util_format_dxt1_rgb_fetch_stub(int src_stride,
const uint8_t *src,
int col, int row,
uint8_t *dst)
{
assert(0);
}
 
 
static void
util_format_dxt1_rgba_fetch_stub(int src_stride,
const uint8_t *src,
int col, int row,
uint8_t *dst )
{
assert(0);
}
 
 
static void
util_format_dxt3_rgba_fetch_stub(int src_stride,
const uint8_t *src,
int col, int row,
uint8_t *dst )
{
assert(0);
}
 
 
static void
util_format_dxt5_rgba_fetch_stub(int src_stride,
const uint8_t *src,
int col, int row,
uint8_t *dst )
{
assert(0);
}
 
 
static void
util_format_dxtn_pack_stub(int src_comps,
int width, int height,
const uint8_t *src,
enum util_format_dxtn dst_format,
uint8_t *dst,
int dst_stride)
{
assert(0);
}
 
 
boolean util_format_s3tc_enabled = FALSE;
 
util_format_dxtn_fetch_t util_format_dxt1_rgb_fetch = util_format_dxt1_rgb_fetch_stub;
util_format_dxtn_fetch_t util_format_dxt1_rgba_fetch = util_format_dxt1_rgba_fetch_stub;
util_format_dxtn_fetch_t util_format_dxt3_rgba_fetch = util_format_dxt3_rgba_fetch_stub;
util_format_dxtn_fetch_t util_format_dxt5_rgba_fetch = util_format_dxt5_rgba_fetch_stub;
 
util_format_dxtn_pack_t util_format_dxtn_pack = util_format_dxtn_pack_stub;
 
 
void
util_format_s3tc_init(void)
{
static boolean first_time = TRUE;
struct util_dl_library *library = NULL;
util_dl_proc fetch_2d_texel_rgb_dxt1;
util_dl_proc fetch_2d_texel_rgba_dxt1;
util_dl_proc fetch_2d_texel_rgba_dxt3;
util_dl_proc fetch_2d_texel_rgba_dxt5;
util_dl_proc tx_compress_dxtn;
char *force_s3tc_enable;
return;
#if 0
if (!first_time)
return;
first_time = FALSE;
 
if (util_format_s3tc_enabled)
return;
 
// library = util_dl_open(DXTN_LIBNAME);
if (!library) {
if ((force_s3tc_enable = getenv("force_s3tc_enable")) &&
!strcmp(force_s3tc_enable, "true")) {
debug_printf("couldn't open " DXTN_LIBNAME ", enabling DXTn due to "
"force_s3tc_enable=true environment variable\n");
util_format_s3tc_enabled = TRUE;
} else {
debug_printf("couldn't open " DXTN_LIBNAME ", software DXTn "
"compression/decompression unavailable\n");
}
return;
}
 
fetch_2d_texel_rgb_dxt1 =
util_dl_get_proc_address(library, "fetch_2d_texel_rgb_dxt1");
fetch_2d_texel_rgba_dxt1 =
util_dl_get_proc_address(library, "fetch_2d_texel_rgba_dxt1");
fetch_2d_texel_rgba_dxt3 =
util_dl_get_proc_address(library, "fetch_2d_texel_rgba_dxt3");
fetch_2d_texel_rgba_dxt5 =
util_dl_get_proc_address(library, "fetch_2d_texel_rgba_dxt5");
tx_compress_dxtn =
util_dl_get_proc_address(library, "tx_compress_dxtn");
 
if (!util_format_dxt1_rgb_fetch ||
!util_format_dxt1_rgba_fetch ||
!util_format_dxt3_rgba_fetch ||
!util_format_dxt5_rgba_fetch ||
!util_format_dxtn_pack) {
debug_printf("couldn't reference all symbols in " DXTN_LIBNAME
", software DXTn compression/decompression "
"unavailable\n");
util_dl_close(library);
return;
}
 
util_format_dxt1_rgb_fetch = (util_format_dxtn_fetch_t)fetch_2d_texel_rgb_dxt1;
util_format_dxt1_rgba_fetch = (util_format_dxtn_fetch_t)fetch_2d_texel_rgba_dxt1;
util_format_dxt3_rgba_fetch = (util_format_dxtn_fetch_t)fetch_2d_texel_rgba_dxt3;
util_format_dxt5_rgba_fetch = (util_format_dxtn_fetch_t)fetch_2d_texel_rgba_dxt5;
util_format_dxtn_pack = (util_format_dxtn_pack_t)tx_compress_dxtn;
util_format_s3tc_enabled = TRUE;
#endif
}
 
 
/*
* Pixel fetch.
*/
 
void
util_format_dxt1_rgb_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j)
{
util_format_dxt1_rgb_fetch(0, src, i, j, dst);
}
 
void
util_format_dxt1_rgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j)
{
util_format_dxt1_rgba_fetch(0, src, i, j, dst);
}
 
void
util_format_dxt3_rgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j)
{
util_format_dxt3_rgba_fetch(0, src, i, j, dst);
}
 
void
util_format_dxt5_rgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j)
{
util_format_dxt5_rgba_fetch(0, src, i, j, dst);
}
 
void
util_format_dxt1_rgb_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint8_t tmp[4];
util_format_dxt1_rgb_fetch(0, src, i, j, tmp);
dst[0] = ubyte_to_float(tmp[0]);
dst[1] = ubyte_to_float(tmp[1]);
dst[2] = ubyte_to_float(tmp[2]);
dst[3] = 1.0;
}
 
void
util_format_dxt1_rgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint8_t tmp[4];
util_format_dxt1_rgba_fetch(0, src, i, j, tmp);
dst[0] = ubyte_to_float(tmp[0]);
dst[1] = ubyte_to_float(tmp[1]);
dst[2] = ubyte_to_float(tmp[2]);
dst[3] = ubyte_to_float(tmp[3]);
}
 
void
util_format_dxt3_rgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint8_t tmp[4];
util_format_dxt3_rgba_fetch(0, src, i, j, tmp);
dst[0] = ubyte_to_float(tmp[0]);
dst[1] = ubyte_to_float(tmp[1]);
dst[2] = ubyte_to_float(tmp[2]);
dst[3] = ubyte_to_float(tmp[3]);
}
 
void
util_format_dxt5_rgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint8_t tmp[4];
util_format_dxt5_rgba_fetch(0, src, i, j, tmp);
dst[0] = ubyte_to_float(tmp[0]);
dst[1] = ubyte_to_float(tmp[1]);
dst[2] = ubyte_to_float(tmp[2]);
dst[3] = ubyte_to_float(tmp[3]);
}
 
 
/*
* Block decompression.
*/
 
static INLINE void
util_format_dxtn_rgb_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height,
util_format_dxtn_fetch_t fetch,
unsigned block_size)
{
const unsigned bw = 4, bh = 4, comps = 4;
unsigned x, y, i, j;
for(y = 0; y < height; y += bh) {
const uint8_t *src = src_row;
for(x = 0; x < width; x += bw) {
for(j = 0; j < bh; ++j) {
for(i = 0; i < bw; ++i) {
uint8_t *dst = dst_row + (y + j)*dst_stride/sizeof(*dst_row) + (x + i)*comps;
fetch(0, src, i, j, dst);
}
}
src += block_size;
}
src_row += src_stride;
}
}
 
void
util_format_dxt1_rgb_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
util_format_dxtn_rgb_unpack_rgba_8unorm(dst_row, dst_stride,
src_row, src_stride,
width, height,
util_format_dxt1_rgb_fetch, 8);
}
 
void
util_format_dxt1_rgba_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
util_format_dxtn_rgb_unpack_rgba_8unorm(dst_row, dst_stride,
src_row, src_stride,
width, height,
util_format_dxt1_rgba_fetch, 8);
}
 
void
util_format_dxt3_rgba_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
util_format_dxtn_rgb_unpack_rgba_8unorm(dst_row, dst_stride,
src_row, src_stride,
width, height,
util_format_dxt3_rgba_fetch, 16);
}
 
void
util_format_dxt5_rgba_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
util_format_dxtn_rgb_unpack_rgba_8unorm(dst_row, dst_stride,
src_row, src_stride,
width, height,
util_format_dxt5_rgba_fetch, 16);
}
 
static INLINE void
util_format_dxtn_rgb_unpack_rgba_float(float *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height,
util_format_dxtn_fetch_t fetch,
unsigned block_size)
{
unsigned x, y, i, j;
for(y = 0; y < height; y += 4) {
const uint8_t *src = src_row;
for(x = 0; x < width; x += 4) {
for(j = 0; j < 4; ++j) {
for(i = 0; i < 4; ++i) {
float *dst = dst_row + (y + j)*dst_stride/sizeof(*dst_row) + (x + i)*4;
uint8_t tmp[4];
fetch(0, src, i, j, tmp);
dst[0] = ubyte_to_float(tmp[0]);
dst[1] = ubyte_to_float(tmp[1]);
dst[2] = ubyte_to_float(tmp[2]);
dst[3] = ubyte_to_float(tmp[3]);
}
}
src += block_size;
}
src_row += src_stride;
}
}
 
void
util_format_dxt1_rgb_unpack_rgba_float(float *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
util_format_dxtn_rgb_unpack_rgba_float(dst_row, dst_stride,
src_row, src_stride,
width, height,
util_format_dxt1_rgb_fetch, 8);
}
 
void
util_format_dxt1_rgba_unpack_rgba_float(float *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
util_format_dxtn_rgb_unpack_rgba_float(dst_row, dst_stride,
src_row, src_stride,
width, height,
util_format_dxt1_rgba_fetch, 8);
}
 
void
util_format_dxt3_rgba_unpack_rgba_float(float *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
util_format_dxtn_rgb_unpack_rgba_float(dst_row, dst_stride,
src_row, src_stride,
width, height,
util_format_dxt3_rgba_fetch, 16);
}
 
void
util_format_dxt5_rgba_unpack_rgba_float(float *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
util_format_dxtn_rgb_unpack_rgba_float(dst_row, dst_stride,
src_row, src_stride,
width, height,
util_format_dxt5_rgba_fetch, 16);
}
 
 
/*
* Block compression.
*/
 
void
util_format_dxt1_rgb_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src, unsigned src_stride,
unsigned width, unsigned height)
{
const unsigned bw = 4, bh = 4, bytes_per_block = 8;
unsigned x, y, i, j, k;
for(y = 0; y < height; y += bh) {
uint8_t *dst = dst_row;
for(x = 0; x < width; x += bw) {
uint8_t tmp[4][4][3]; /* [bh][bw][comps] */
for(j = 0; j < bh; ++j) {
for(i = 0; i < bw; ++i) {
for(k = 0; k < 3; ++k) {
tmp[j][i][k] = src[(y + j)*src_stride/sizeof(*src) + (x + i)*4 + k];
}
}
}
util_format_dxtn_pack(3, 4, 4, &tmp[0][0][0], UTIL_FORMAT_DXT1_RGB, dst, 0);
dst += bytes_per_block;
}
dst_row += dst_stride / sizeof(*dst_row);
}
}
 
void
util_format_dxt1_rgba_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src, unsigned src_stride,
unsigned width, unsigned height)
{
const unsigned bw = 4, bh = 4, comps = 4, bytes_per_block = 8;
unsigned x, y, i, j, k;
for(y = 0; y < height; y += bh) {
uint8_t *dst = dst_row;
for(x = 0; x < width; x += bw) {
uint8_t tmp[4][4][4]; /* [bh][bw][comps] */
for(j = 0; j < bh; ++j) {
for(i = 0; i < bw; ++i) {
for(k = 0; k < comps; ++k) {
tmp[j][i][k] = src[(y + j)*src_stride/sizeof(*src) + (x + i)*comps + k];
}
}
}
util_format_dxtn_pack(4, 4, 4, &tmp[0][0][0], UTIL_FORMAT_DXT1_RGBA, dst, 0);
dst += bytes_per_block;
}
dst_row += dst_stride / sizeof(*dst_row);
}
}
 
void
util_format_dxt3_rgba_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src, unsigned src_stride,
unsigned width, unsigned height)
{
const unsigned bw = 4, bh = 4, comps = 4, bytes_per_block = 16;
unsigned x, y, i, j, k;
for(y = 0; y < height; y += bh) {
uint8_t *dst = dst_row;
for(x = 0; x < width; x += bw) {
uint8_t tmp[4][4][4]; /* [bh][bw][comps] */
for(j = 0; j < bh; ++j) {
for(i = 0; i < bw; ++i) {
for(k = 0; k < comps; ++k) {
tmp[j][i][k] = src[(y + j)*src_stride/sizeof(*src) + (x + i)*comps + k];
}
}
}
util_format_dxtn_pack(4, 4, 4, &tmp[0][0][0], UTIL_FORMAT_DXT3_RGBA, dst, 0);
dst += bytes_per_block;
}
dst_row += dst_stride / sizeof(*dst_row);
}
}
 
void
util_format_dxt5_rgba_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src, unsigned src_stride,
unsigned width, unsigned height)
{
const unsigned bw = 4, bh = 4, comps = 4, bytes_per_block = 16;
unsigned x, y, i, j, k;
 
for(y = 0; y < height; y += bh) {
uint8_t *dst = dst_row;
for(x = 0; x < width; x += bw) {
uint8_t tmp[4][4][4]; /* [bh][bw][comps] */
for(j = 0; j < bh; ++j) {
for(i = 0; i < bw; ++i) {
for(k = 0; k < comps; ++k) {
tmp[j][i][k] = src[(y + j)*src_stride/sizeof(*src) + (x + i)*comps + k];
}
}
}
util_format_dxtn_pack(4, 4, 4, &tmp[0][0][0], UTIL_FORMAT_DXT5_RGBA, dst, 0);
dst += bytes_per_block;
}
dst_row += dst_stride / sizeof(*dst_row);
}
}
 
void
util_format_dxt1_rgb_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
const float *src, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y, i, j, k;
for(y = 0; y < height; y += 4) {
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 4) {
uint8_t tmp[4][4][3];
for(j = 0; j < 4; ++j) {
for(i = 0; i < 4; ++i) {
for(k = 0; k < 3; ++k) {
tmp[j][i][k] = float_to_ubyte(src[(y + j)*src_stride/sizeof(*src) + (x+i)*4 + k]);
}
}
}
util_format_dxtn_pack(3, 4, 4, &tmp[0][0][0], UTIL_FORMAT_DXT1_RGB, dst, 0);
dst += 8;
}
dst_row += 4*dst_stride/sizeof(*dst_row);
}
}
 
void
util_format_dxt1_rgba_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
const float *src, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y, i, j, k;
for(y = 0; y < height; y += 4) {
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 4) {
uint8_t tmp[4][4][4];
for(j = 0; j < 4; ++j) {
for(i = 0; i < 4; ++i) {
for(k = 0; k < 4; ++k) {
tmp[j][i][k] = float_to_ubyte(src[(y + j)*src_stride/sizeof(*src) + (x+i)*4 + k]);
}
}
}
util_format_dxtn_pack(4, 4, 4, &tmp[0][0][0], UTIL_FORMAT_DXT1_RGBA, dst, 0);
dst += 8;
}
dst_row += 4*dst_stride/sizeof(*dst_row);
}
}
 
void
util_format_dxt3_rgba_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
const float *src, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y, i, j, k;
for(y = 0; y < height; y += 4) {
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 4) {
uint8_t tmp[4][4][4];
for(j = 0; j < 4; ++j) {
for(i = 0; i < 4; ++i) {
for(k = 0; k < 4; ++k) {
tmp[j][i][k] = float_to_ubyte(src[(y + j)*src_stride/sizeof(*src) + (x+i)*4 + k]);
}
}
}
util_format_dxtn_pack(4, 4, 4, &tmp[0][0][0], UTIL_FORMAT_DXT3_RGBA, dst, 0);
dst += 16;
}
dst_row += 4*dst_stride/sizeof(*dst_row);
}
}
 
void
util_format_dxt5_rgba_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
const float *src, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y, i, j, k;
for(y = 0; y < height; y += 4) {
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 4) {
uint8_t tmp[4][4][4];
for(j = 0; j < 4; ++j) {
for(i = 0; i < 4; ++i) {
for(k = 0; k < 4; ++k) {
tmp[j][i][k] = float_to_ubyte(src[(y + j)*src_stride/sizeof(*src) + (x+i)*4 + k]);
}
}
}
util_format_dxtn_pack(4, 4, 4, &tmp[0][0][0], UTIL_FORMAT_DXT5_RGBA, dst, 0);
dst += 16;
}
dst_row += 4*dst_stride/sizeof(*dst_row);
}
}
 
 
/*
* SRGB variants.
*
* FIXME: shunts to RGB for now
*/
 
void
util_format_dxt1_srgb_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
util_format_dxt1_rgb_unpack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, width, height);
}
 
void
util_format_dxt1_srgb_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
util_format_dxt1_rgb_pack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, width, height);
}
 
void
util_format_dxt1_srgb_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j)
{
util_format_dxt1_rgb_fetch_rgba_8unorm(dst, src, i, j);
}
 
void
util_format_dxt1_srgba_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
util_format_dxt1_rgba_unpack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, width, height);
}
 
void
util_format_dxt1_srgba_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
util_format_dxt1_rgba_pack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, width, height);
}
 
void
util_format_dxt1_srgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j)
{
util_format_dxt1_rgba_fetch_rgba_8unorm(dst, src, i, j);
}
 
void
util_format_dxt3_srgba_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
util_format_dxt3_rgba_unpack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, width, height);
}
 
void
util_format_dxt3_srgba_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
util_format_dxt3_rgba_pack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, width, height);
}
 
void
util_format_dxt3_srgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j)
{
util_format_dxt3_rgba_fetch_rgba_8unorm(dst, src, i, j);
}
 
void
util_format_dxt5_srgba_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
util_format_dxt5_rgba_unpack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, width, height);
}
 
void
util_format_dxt5_srgba_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
util_format_dxt5_rgba_pack_rgba_8unorm(dst_row, dst_stride, src_row, src_stride, width, height);
}
 
void
util_format_dxt5_srgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j)
{
util_format_dxt5_rgba_fetch_rgba_8unorm(dst, src, i, j);
}
 
void
util_format_dxt1_srgb_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
util_format_dxt1_rgb_unpack_rgba_float(dst_row, dst_stride, src_row, src_stride, width, height);
}
 
void
util_format_dxt1_srgb_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
util_format_dxt1_rgb_pack_rgba_float(dst_row, dst_stride, src_row, src_stride, width, height);
}
 
void
util_format_dxt1_srgb_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
util_format_dxt1_rgb_fetch_rgba_float(dst, src, i, j);
}
 
void
util_format_dxt1_srgba_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
util_format_dxt1_rgba_unpack_rgba_float(dst_row, dst_stride, src_row, src_stride, width, height);
}
 
void
util_format_dxt1_srgba_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
util_format_dxt1_rgba_pack_rgba_float(dst_row, dst_stride, src_row, src_stride, width, height);
}
 
void
util_format_dxt1_srgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
util_format_dxt1_rgba_fetch_rgba_float(dst, src, i, j);
}
 
void
util_format_dxt3_srgba_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
util_format_dxt3_rgba_unpack_rgba_float(dst_row, dst_stride, src_row, src_stride, width, height);
}
 
void
util_format_dxt3_srgba_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
util_format_dxt3_rgba_pack_rgba_float(dst_row, dst_stride, src_row, src_stride, width, height);
}
 
void
util_format_dxt3_srgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
util_format_dxt3_rgba_fetch_rgba_float(dst, src, i, j);
}
 
void
util_format_dxt5_srgba_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
util_format_dxt5_rgba_unpack_rgba_float(dst_row, dst_stride, src_row, src_stride, width, height);
}
 
void
util_format_dxt5_srgba_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
util_format_dxt5_rgba_pack_rgba_float(dst_row, dst_stride, src_row, src_stride, width, height);
}
 
void
util_format_dxt5_srgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
util_format_dxt5_rgba_fetch_rgba_float(dst, src, i, j);
}
 
/drivers/video/Gallium/auxiliary/util/u_format_s3tc.h
0,0 → 1,218
/**************************************************************************
*
* Copyright 2010 VMware, Inc.
* 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 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
* THE COPYRIGHT HOLDERS, AUTHORS 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.
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
**************************************************************************/
 
 
#ifndef U_FORMAT_S3TC_H_
#define U_FORMAT_S3TC_H_
 
 
#include "pipe/p_compiler.h"
 
 
enum util_format_dxtn {
UTIL_FORMAT_DXT1_RGB = 0x83F0,
UTIL_FORMAT_DXT1_RGBA = 0x83F1,
UTIL_FORMAT_DXT3_RGBA = 0x83F2,
UTIL_FORMAT_DXT5_RGBA = 0x83F3
};
 
 
typedef void
(*util_format_dxtn_fetch_t)( int src_stride,
const uint8_t *src,
int col, int row,
uint8_t *dst );
 
typedef void
(*util_format_dxtn_pack_t)( int src_comps,
int width, int height,
const uint8_t *src,
enum util_format_dxtn dst_format,
uint8_t *dst,
int dst_stride);
 
extern boolean util_format_s3tc_enabled;
 
extern util_format_dxtn_fetch_t util_format_dxt1_rgb_fetch;
extern util_format_dxtn_fetch_t util_format_dxt1_rgba_fetch;
extern util_format_dxtn_fetch_t util_format_dxt3_rgba_fetch;
extern util_format_dxtn_fetch_t util_format_dxt5_rgba_fetch;
 
extern util_format_dxtn_pack_t util_format_dxtn_pack;
 
 
void
util_format_s3tc_init(void);
 
 
void
util_format_dxt1_rgb_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_dxt1_rgb_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_dxt1_rgb_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j);
 
void
util_format_dxt1_rgba_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_dxt1_rgba_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_dxt1_rgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j);
 
void
util_format_dxt3_rgba_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_dxt3_rgba_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_dxt3_rgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j);
 
void
util_format_dxt5_rgba_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_dxt5_rgba_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_dxt5_rgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j);
 
void
util_format_dxt1_srgb_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_dxt1_srgb_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_dxt1_srgb_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j);
 
void
util_format_dxt1_srgba_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_dxt1_srgba_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_dxt1_srgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j);
 
void
util_format_dxt3_srgba_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_dxt3_srgba_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_dxt3_srgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j);
 
void
util_format_dxt5_srgba_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_dxt5_srgba_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_dxt5_srgba_fetch_rgba_8unorm(uint8_t *dst, const uint8_t *src, unsigned i, unsigned j);
 
 
void
util_format_dxt1_rgb_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_dxt1_rgb_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_dxt1_rgb_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j);
 
void
util_format_dxt1_rgba_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_dxt1_rgba_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_dxt1_rgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j);
 
void
util_format_dxt3_rgba_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_dxt3_rgba_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_dxt3_rgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j);
 
void
util_format_dxt5_rgba_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_dxt5_rgba_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_dxt5_rgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j);
 
void
util_format_dxt1_srgb_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_dxt1_srgb_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_dxt1_srgb_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j);
 
void
util_format_dxt1_srgba_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_dxt1_srgba_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_dxt1_srgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j);
 
void
util_format_dxt3_srgba_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_dxt3_srgba_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_dxt3_srgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j);
 
void
util_format_dxt5_srgba_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_dxt5_srgba_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_dxt5_srgba_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j);
 
 
#endif /* U_FORMAT_S3TC_H_ */
/drivers/video/Gallium/auxiliary/util/u_format_srgb.c
0,0 → 1,148
/* This file is autogenerated by u_format_srgb.py. Do not edit directly. */
 
/**************************************************************************
*
* Copyright 2010 VMware, Inc.
* 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 VMWARE 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
* SRGB translation.
*
* @author Brian Paul <brianp@vmware.com>
* @author Michal Krol <michal@vmware.com>
* @author Jose Fonseca <jfonseca@vmware.com>
*/
 
#include "u_format_srgb.h"
 
const float
util_format_srgb_8unorm_to_linear_float_table[256] = {
0.0000000e+00, 3.0352698e-04, 6.0705397e-04, 9.1058095e-04,
1.2141079e-03, 1.5176349e-03, 1.8211619e-03, 2.1246889e-03,
2.4282159e-03, 2.7317429e-03, 3.0352698e-03, 3.3465358e-03,
3.6765073e-03, 4.0247170e-03, 4.3914420e-03, 4.7769535e-03,
5.1815167e-03, 5.6053916e-03, 6.0488330e-03, 6.5120908e-03,
6.9954102e-03, 7.4990320e-03, 8.0231930e-03, 8.5681256e-03,
9.1340587e-03, 9.7212173e-03, 1.0329823e-02, 1.0960094e-02,
1.1612245e-02, 1.2286488e-02, 1.2983032e-02, 1.3702083e-02,
1.4443844e-02, 1.5208514e-02, 1.5996293e-02, 1.6807376e-02,
1.7641954e-02, 1.8500220e-02, 1.9382361e-02, 2.0288563e-02,
2.1219010e-02, 2.2173885e-02, 2.3153366e-02, 2.4157632e-02,
2.5186860e-02, 2.6241222e-02, 2.7320892e-02, 2.8426040e-02,
2.9556834e-02, 3.0713444e-02, 3.1896033e-02, 3.3104767e-02,
3.4339807e-02, 3.5601315e-02, 3.6889450e-02, 3.8204372e-02,
3.9546235e-02, 4.0915197e-02, 4.2311411e-02, 4.3735029e-02,
4.5186204e-02, 4.6665086e-02, 4.8171824e-02, 4.9706566e-02,
5.1269458e-02, 5.2860647e-02, 5.4480276e-02, 5.6128490e-02,
5.7805430e-02, 5.9511238e-02, 6.1246054e-02, 6.3010018e-02,
6.4803267e-02, 6.6625939e-02, 6.8478170e-02, 7.0360096e-02,
7.2271851e-02, 7.4213568e-02, 7.6185381e-02, 7.8187422e-02,
8.0219820e-02, 8.2282707e-02, 8.4376212e-02, 8.6500462e-02,
8.8655586e-02, 9.0841711e-02, 9.3058963e-02, 9.5307467e-02,
9.7587347e-02, 9.9898728e-02, 1.0224173e-01, 1.0461648e-01,
1.0702310e-01, 1.0946171e-01, 1.1193243e-01, 1.1443537e-01,
1.1697067e-01, 1.1953843e-01, 1.2213877e-01, 1.2477182e-01,
1.2743768e-01, 1.3013648e-01, 1.3286832e-01, 1.3563333e-01,
1.3843162e-01, 1.4126329e-01, 1.4412847e-01, 1.4702727e-01,
1.4995979e-01, 1.5292615e-01, 1.5592646e-01, 1.5896084e-01,
1.6202938e-01, 1.6513219e-01, 1.6826940e-01, 1.7144110e-01,
1.7464740e-01, 1.7788842e-01, 1.8116424e-01, 1.8447499e-01,
1.8782077e-01, 1.9120168e-01, 1.9461783e-01, 1.9806932e-01,
2.0155625e-01, 2.0507874e-01, 2.0863687e-01, 2.1223076e-01,
2.1586050e-01, 2.1952620e-01, 2.2322796e-01, 2.2696587e-01,
2.3074005e-01, 2.3455058e-01, 2.3839757e-01, 2.4228112e-01,
2.4620133e-01, 2.5015828e-01, 2.5415209e-01, 2.5818285e-01,
2.6225066e-01, 2.6635560e-01, 2.7049779e-01, 2.7467731e-01,
2.7889426e-01, 2.8314874e-01, 2.8744084e-01, 2.9177065e-01,
2.9613827e-01, 3.0054379e-01, 3.0498731e-01, 3.0946892e-01,
3.1398871e-01, 3.1854678e-01, 3.2314321e-01, 3.2777810e-01,
3.3245154e-01, 3.3716362e-01, 3.4191442e-01, 3.4670406e-01,
3.5153260e-01, 3.5640014e-01, 3.6130678e-01, 3.6625260e-01,
3.7123768e-01, 3.7626212e-01, 3.8132601e-01, 3.8642943e-01,
3.9157248e-01, 3.9675523e-01, 4.0197778e-01, 4.0724021e-01,
4.1254261e-01, 4.1788507e-01, 4.2326767e-01, 4.2869050e-01,
4.3415364e-01, 4.3965717e-01, 4.4520119e-01, 4.5078578e-01,
4.5641102e-01, 4.6207700e-01, 4.6778380e-01, 4.7353150e-01,
4.7932018e-01, 4.8514994e-01, 4.9102085e-01, 4.9693300e-01,
5.0288646e-01, 5.0888132e-01, 5.1491767e-01, 5.2099557e-01,
5.2711513e-01, 5.3327640e-01, 5.3947949e-01, 5.4572446e-01,
5.5201140e-01, 5.5834039e-01, 5.6471151e-01, 5.7112483e-01,
5.7758044e-01, 5.8407842e-01, 5.9061884e-01, 5.9720179e-01,
6.0382734e-01, 6.1049557e-01, 6.1720656e-01, 6.2396039e-01,
6.3075714e-01, 6.3759687e-01, 6.4447968e-01, 6.5140564e-01,
6.5837482e-01, 6.6538730e-01, 6.7244316e-01, 6.7954247e-01,
6.8668531e-01, 6.9387176e-01, 7.0110189e-01, 7.0837578e-01,
7.1569350e-01, 7.2305513e-01, 7.3046074e-01, 7.3791041e-01,
7.4540421e-01, 7.5294222e-01, 7.6052450e-01, 7.6815115e-01,
7.7582222e-01, 7.8353779e-01, 7.9129794e-01, 7.9910274e-01,
8.0695226e-01, 8.1484657e-01, 8.2278575e-01, 8.3076988e-01,
8.3879901e-01, 8.4687323e-01, 8.5499261e-01, 8.6315721e-01,
8.7136712e-01, 8.7962240e-01, 8.8792312e-01, 8.9626935e-01,
9.0466117e-01, 9.1309865e-01, 9.2158186e-01, 9.3011086e-01,
9.3868573e-01, 9.4730654e-01, 9.5597335e-01, 9.6468625e-01,
9.7344529e-01, 9.8225055e-01, 9.9110210e-01, 1.0000000e+00,
};
 
const uint8_t
util_format_srgb_to_linear_8unorm_table[256] = {
0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3,
4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7,
8, 8, 8, 8, 9, 9, 9, 10, 10, 10, 11, 11, 12, 12, 12, 13,
13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 17, 18, 18, 19, 19, 20,
20, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 27, 27, 28, 29, 29,
30, 30, 31, 32, 32, 33, 34, 35, 35, 36, 37, 37, 38, 39, 40, 41,
41, 42, 43, 44, 45, 45, 46, 47, 48, 49, 50, 51, 51, 52, 53, 54,
55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
71, 72, 73, 74, 76, 77, 78, 79, 80, 81, 82, 84, 85, 86, 87, 88,
90, 91, 92, 93, 95, 96, 97, 99, 100, 101, 103, 104, 105, 107, 108, 109,
111, 112, 114, 115, 116, 118, 119, 121, 122, 124, 125, 127, 128, 130, 131, 133,
134, 136, 138, 139, 141, 142, 144, 146, 147, 149, 151, 152, 154, 156, 157, 159,
161, 163, 164, 166, 168, 170, 171, 173, 175, 177, 179, 181, 183, 184, 186, 188,
190, 192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 218, 220,
222, 224, 226, 229, 231, 233, 235, 237, 239, 242, 244, 246, 248, 250, 253, 255,
};
 
const uint8_t
util_format_linear_to_srgb_8unorm_table[256] = {
0, 13, 22, 28, 34, 38, 42, 46, 50, 53, 56, 59, 61, 64, 66, 69,
71, 73, 75, 77, 79, 81, 83, 85, 86, 88, 90, 92, 93, 95, 96, 98,
99, 101, 102, 104, 105, 106, 108, 109, 110, 112, 113, 114, 115, 117, 118, 119,
120, 121, 122, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136,
137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 148, 149, 150, 151,
152, 153, 154, 155, 155, 156, 157, 158, 159, 159, 160, 161, 162, 163, 163, 164,
165, 166, 167, 167, 168, 169, 170, 170, 171, 172, 173, 173, 174, 175, 175, 176,
177, 178, 178, 179, 180, 180, 181, 182, 182, 183, 184, 185, 185, 186, 187, 187,
188, 189, 189, 190, 190, 191, 192, 192, 193, 194, 194, 195, 196, 196, 197, 197,
198, 199, 199, 200, 200, 201, 202, 202, 203, 203, 204, 205, 205, 206, 206, 207,
208, 208, 209, 209, 210, 210, 211, 212, 212, 213, 213, 214, 214, 215, 215, 216,
216, 217, 218, 218, 219, 219, 220, 220, 221, 221, 222, 222, 223, 223, 224, 224,
225, 226, 226, 227, 227, 228, 228, 229, 229, 230, 230, 231, 231, 232, 232, 233,
233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 238, 238, 239, 239, 240, 240,
241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 246, 246, 246, 247, 247, 248,
248, 249, 249, 250, 250, 251, 251, 251, 252, 252, 253, 253, 254, 254, 255, 255,
};
 
/drivers/video/Gallium/auxiliary/util/u_format_srgb.h
0,0 → 1,106
/**************************************************************************
*
* Copyright 2010 VMware, Inc.
* 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 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
* THE COPYRIGHT HOLDERS, AUTHORS 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.
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
**************************************************************************/
 
/**
* @file
* SRGB translation.
*
* @author Brian Paul <brianp@vmware.com>
* @author Michal Krol <michal@vmware.com>
* @author Jose Fonseca <jfonseca@vmware.com>
*/
 
#ifndef U_FORMAT_SRGB_H_
#define U_FORMAT_SRGB_H_
 
 
#include "pipe/p_compiler.h"
#include "u_math.h"
 
 
extern const float
util_format_srgb_8unorm_to_linear_float_table[256];
 
extern const uint8_t
util_format_srgb_to_linear_8unorm_table[256];
 
extern const uint8_t
util_format_linear_to_srgb_8unorm_table[256];
 
 
/**
* Convert a unclamped linear float to srgb value in the [0,255].
* XXX this hasn't been tested (render to srgb surface).
* XXX this needs optimization.
*/
static INLINE uint8_t
util_format_linear_float_to_srgb_8unorm(float x)
{
if (x >= 1.0f)
return 255;
else if (x >= 0.0031308f)
return float_to_ubyte(1.055f * powf(x, 0.41666f) - 0.055f);
else if (x > 0.0f)
return float_to_ubyte(12.92f * x);
else
return 0;
}
 
 
/**
* Convert an 8-bit sRGB value from non-linear space to a
* linear RGB value in [0, 1].
* Implemented with a 256-entry lookup table.
*/
static INLINE float
util_format_srgb_8unorm_to_linear_float(uint8_t x)
{
return util_format_srgb_8unorm_to_linear_float_table[x];
}
 
 
/**
* Convert a 8bit normalized value from linear to srgb.
*/
static INLINE uint8_t
util_format_linear_to_srgb_8unorm(uint8_t x)
{
return util_format_linear_to_srgb_8unorm_table[x];
}
 
 
/**
* Convert a 8bit normalized value from srgb to linear.
*/
static INLINE uint8_t
util_format_srgb_to_linear_8unorm(uint8_t x)
{
return util_format_srgb_to_linear_8unorm_table[x];
}
 
 
#endif /* U_FORMAT_SRGB_H_ */
/drivers/video/Gallium/auxiliary/util/u_format_srgb.py
0,0 → 1,100
#!/usr/bin/env python
 
CopyRight = '''
/**************************************************************************
*
* Copyright 2010 VMware, Inc.
* 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 VMWARE 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
* SRGB translation.
*
* @author Brian Paul <brianp@vmware.com>
* @author Michal Krol <michal@vmware.com>
* @author Jose Fonseca <jfonseca@vmware.com>
*/
'''
 
 
import math
 
 
def srgb_to_linear(x):
if x <= 0.04045:
return x / 12.92
else:
return math.pow((x + 0.055) / 1.055, 2.4)
 
 
def linear_to_srgb(x):
if x >= 0.0031308:
return 1.055 * math.pow(x, 0.41666) - 0.055
else:
return 12.92 * x
 
def generate_srgb_tables():
print 'const float'
print 'util_format_srgb_8unorm_to_linear_float_table[256] = {'
for j in range(0, 256, 4):
print ' ',
for i in range(j, j + 4):
print '%.7e,' % (srgb_to_linear(i / 255.0),),
print
print '};'
print
print 'const uint8_t'
print 'util_format_srgb_to_linear_8unorm_table[256] = {'
for j in range(0, 256, 16):
print ' ',
for i in range(j, j + 16):
print '%3u,' % (int(srgb_to_linear(i / 255.0) * 255.0 + 0.5),),
print
print '};'
print
print 'const uint8_t'
print 'util_format_linear_to_srgb_8unorm_table[256] = {'
for j in range(0, 256, 16):
print ' ',
for i in range(j, j + 16):
print '%3u,' % (int(linear_to_srgb(i / 255.0) * 255.0 + 0.5),),
print
print '};'
print
 
 
def main():
print '/* This file is autogenerated by u_format_srgb.py. Do not edit directly. */'
print
# This will print the copyright message on the top of this file
print CopyRight.strip()
print
print '#include "u_format_srgb.h"'
print
generate_srgb_tables()
 
 
if __name__ == '__main__':
main()
/drivers/video/Gallium/auxiliary/util/u_format_table.c
0,0 → 1,28411
/* This file is autogenerated by u_format_table.py from u_format.csv. Do not edit directly. */
 
/**************************************************************************
*
* Copyright 2010 VMware, Inc.
* 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 VMWARE 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.
*
**************************************************************************/
 
#include "u_format.h"
#include "u_format_s3tc.h"
#include "u_format_rgtc.h"
#include "u_format_latc.h"
#include "u_format_etc.h"
 
 
#include "pipe/p_compiler.h"
#include "u_math.h"
#include "u_half.h"
#include "u_format.h"
#include "u_format_other.h"
#include "u_format_srgb.h"
#include "u_format_yuv.h"
#include "u_format_zs.h"
 
union util_format_none {
uint8_t value;
struct {
uint8_t r;
} chan;
};
 
static INLINE void
util_format_none_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint8_t value = *(const uint8_t *)src;
uint8_t r;
r = value;
dst[0] = (float)r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 1;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_none_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint8_t value = 0;
value |= (uint8_t)CLAMP(src[0], 0, 255);
*(uint8_t *)dst = value;
src += 4;
dst += 1;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_none_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint8_t value = *(const uint8_t *)src;
uint8_t r;
r = value;
dst[0] = (float)r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_none_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint8_t value = *(const uint8_t *)src;
uint8_t r;
r = value;
dst[0] = (uint8_t)(((uint32_t)MIN2(r, 1)) * 0xff / 0x1); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 255; /* a */
src += 1;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_none_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint8_t value = 0;
value |= (uint8_t)(((uint32_t)src[0]) * 0x1 / 0xff);
*(uint8_t *)dst = value;
src += 4;
dst += 1;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_b8g8r8a8_unorm {
uint32_t value;
struct {
uint8_t b;
uint8_t g;
uint8_t r;
uint8_t a;
} chan;
};
 
static INLINE void
util_format_b8g8r8a8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t b;
uint32_t g;
uint32_t r;
uint32_t a;
b = (value) & 0xff;
g = (value >> 8) & 0xff;
r = (value >> 16) & 0xff;
a = value >> 24;
dst[0] = ubyte_to_float(r); /* r */
dst[1] = ubyte_to_float(g); /* g */
dst[2] = ubyte_to_float(b); /* b */
dst[3] = ubyte_to_float(a); /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_b8g8r8a8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (float_to_ubyte(src[2])) & 0xff;
value |= ((float_to_ubyte(src[1])) & 0xff) << 8;
value |= ((float_to_ubyte(src[0])) & 0xff) << 16;
value |= (float_to_ubyte(src[3])) << 24;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_b8g8r8a8_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
uint32_t b;
uint32_t g;
uint32_t r;
uint32_t a;
b = (value) & 0xff;
g = (value >> 8) & 0xff;
r = (value >> 16) & 0xff;
a = value >> 24;
dst[0] = ubyte_to_float(r); /* r */
dst[1] = ubyte_to_float(g); /* g */
dst[2] = ubyte_to_float(b); /* b */
dst[3] = ubyte_to_float(a); /* a */
}
 
static INLINE void
util_format_b8g8r8a8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t b;
uint32_t g;
uint32_t r;
uint32_t a;
b = (value) & 0xff;
g = (value >> 8) & 0xff;
r = (value >> 16) & 0xff;
a = value >> 24;
dst[0] = r; /* r */
dst[1] = g; /* g */
dst[2] = b; /* b */
dst[3] = a; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_b8g8r8a8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (src[2]) & 0xff;
value |= ((src[1]) & 0xff) << 8;
value |= ((src[0]) & 0xff) << 16;
value |= (src[3]) << 24;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_b8g8r8x8_unorm {
uint32_t value;
struct {
uint8_t b;
uint8_t g;
uint8_t r;
uint8_t x;
} chan;
};
 
static INLINE void
util_format_b8g8r8x8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t b;
uint32_t g;
uint32_t r;
b = (value) & 0xff;
g = (value >> 8) & 0xff;
r = (value >> 16) & 0xff;
dst[0] = ubyte_to_float(r); /* r */
dst[1] = ubyte_to_float(g); /* g */
dst[2] = ubyte_to_float(b); /* b */
dst[3] = 1; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_b8g8r8x8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (float_to_ubyte(src[2])) & 0xff;
value |= ((float_to_ubyte(src[1])) & 0xff) << 8;
value |= ((float_to_ubyte(src[0])) & 0xff) << 16;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_b8g8r8x8_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
uint32_t b;
uint32_t g;
uint32_t r;
b = (value) & 0xff;
g = (value >> 8) & 0xff;
r = (value >> 16) & 0xff;
dst[0] = ubyte_to_float(r); /* r */
dst[1] = ubyte_to_float(g); /* g */
dst[2] = ubyte_to_float(b); /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_b8g8r8x8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t b;
uint32_t g;
uint32_t r;
b = (value) & 0xff;
g = (value >> 8) & 0xff;
r = (value >> 16) & 0xff;
dst[0] = r; /* r */
dst[1] = g; /* g */
dst[2] = b; /* b */
dst[3] = 255; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_b8g8r8x8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (src[2]) & 0xff;
value |= ((src[1]) & 0xff) << 8;
value |= ((src[0]) & 0xff) << 16;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_a8r8g8b8_unorm {
uint32_t value;
struct {
uint8_t a;
uint8_t r;
uint8_t g;
uint8_t b;
} chan;
};
 
static INLINE void
util_format_a8r8g8b8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t a;
uint32_t r;
uint32_t g;
uint32_t b;
a = (value) & 0xff;
r = (value >> 8) & 0xff;
g = (value >> 16) & 0xff;
b = value >> 24;
dst[0] = ubyte_to_float(r); /* r */
dst[1] = ubyte_to_float(g); /* g */
dst[2] = ubyte_to_float(b); /* b */
dst[3] = ubyte_to_float(a); /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_a8r8g8b8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (float_to_ubyte(src[3])) & 0xff;
value |= ((float_to_ubyte(src[0])) & 0xff) << 8;
value |= ((float_to_ubyte(src[1])) & 0xff) << 16;
value |= (float_to_ubyte(src[2])) << 24;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_a8r8g8b8_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
uint32_t a;
uint32_t r;
uint32_t g;
uint32_t b;
a = (value) & 0xff;
r = (value >> 8) & 0xff;
g = (value >> 16) & 0xff;
b = value >> 24;
dst[0] = ubyte_to_float(r); /* r */
dst[1] = ubyte_to_float(g); /* g */
dst[2] = ubyte_to_float(b); /* b */
dst[3] = ubyte_to_float(a); /* a */
}
 
static INLINE void
util_format_a8r8g8b8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t a;
uint32_t r;
uint32_t g;
uint32_t b;
a = (value) & 0xff;
r = (value >> 8) & 0xff;
g = (value >> 16) & 0xff;
b = value >> 24;
dst[0] = r; /* r */
dst[1] = g; /* g */
dst[2] = b; /* b */
dst[3] = a; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_a8r8g8b8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (src[3]) & 0xff;
value |= ((src[0]) & 0xff) << 8;
value |= ((src[1]) & 0xff) << 16;
value |= (src[2]) << 24;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_x8r8g8b8_unorm {
uint32_t value;
struct {
uint8_t x;
uint8_t r;
uint8_t g;
uint8_t b;
} chan;
};
 
static INLINE void
util_format_x8r8g8b8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t r;
uint32_t g;
uint32_t b;
r = (value >> 8) & 0xff;
g = (value >> 16) & 0xff;
b = value >> 24;
dst[0] = ubyte_to_float(r); /* r */
dst[1] = ubyte_to_float(g); /* g */
dst[2] = ubyte_to_float(b); /* b */
dst[3] = 1; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_x8r8g8b8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= ((float_to_ubyte(src[0])) & 0xff) << 8;
value |= ((float_to_ubyte(src[1])) & 0xff) << 16;
value |= (float_to_ubyte(src[2])) << 24;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_x8r8g8b8_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
uint32_t r;
uint32_t g;
uint32_t b;
r = (value >> 8) & 0xff;
g = (value >> 16) & 0xff;
b = value >> 24;
dst[0] = ubyte_to_float(r); /* r */
dst[1] = ubyte_to_float(g); /* g */
dst[2] = ubyte_to_float(b); /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_x8r8g8b8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t r;
uint32_t g;
uint32_t b;
r = (value >> 8) & 0xff;
g = (value >> 16) & 0xff;
b = value >> 24;
dst[0] = r; /* r */
dst[1] = g; /* g */
dst[2] = b; /* b */
dst[3] = 255; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_x8r8g8b8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= ((src[0]) & 0xff) << 8;
value |= ((src[1]) & 0xff) << 16;
value |= (src[2]) << 24;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_a8b8g8r8_unorm {
uint32_t value;
struct {
uint8_t a;
uint8_t b;
uint8_t g;
uint8_t r;
} chan;
};
 
static INLINE void
util_format_a8b8g8r8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t a;
uint32_t b;
uint32_t g;
uint32_t r;
a = (value) & 0xff;
b = (value >> 8) & 0xff;
g = (value >> 16) & 0xff;
r = value >> 24;
dst[0] = ubyte_to_float(r); /* r */
dst[1] = ubyte_to_float(g); /* g */
dst[2] = ubyte_to_float(b); /* b */
dst[3] = ubyte_to_float(a); /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_a8b8g8r8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (float_to_ubyte(src[3])) & 0xff;
value |= ((float_to_ubyte(src[2])) & 0xff) << 8;
value |= ((float_to_ubyte(src[1])) & 0xff) << 16;
value |= (float_to_ubyte(src[0])) << 24;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_a8b8g8r8_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
uint32_t a;
uint32_t b;
uint32_t g;
uint32_t r;
a = (value) & 0xff;
b = (value >> 8) & 0xff;
g = (value >> 16) & 0xff;
r = value >> 24;
dst[0] = ubyte_to_float(r); /* r */
dst[1] = ubyte_to_float(g); /* g */
dst[2] = ubyte_to_float(b); /* b */
dst[3] = ubyte_to_float(a); /* a */
}
 
static INLINE void
util_format_a8b8g8r8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t a;
uint32_t b;
uint32_t g;
uint32_t r;
a = (value) & 0xff;
b = (value >> 8) & 0xff;
g = (value >> 16) & 0xff;
r = value >> 24;
dst[0] = r; /* r */
dst[1] = g; /* g */
dst[2] = b; /* b */
dst[3] = a; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_a8b8g8r8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (src[3]) & 0xff;
value |= ((src[2]) & 0xff) << 8;
value |= ((src[1]) & 0xff) << 16;
value |= (src[0]) << 24;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_x8b8g8r8_unorm {
uint32_t value;
struct {
uint8_t x;
uint8_t b;
uint8_t g;
uint8_t r;
} chan;
};
 
static INLINE void
util_format_x8b8g8r8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t b;
uint32_t g;
uint32_t r;
b = (value >> 8) & 0xff;
g = (value >> 16) & 0xff;
r = value >> 24;
dst[0] = ubyte_to_float(r); /* r */
dst[1] = ubyte_to_float(g); /* g */
dst[2] = ubyte_to_float(b); /* b */
dst[3] = 1; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_x8b8g8r8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= ((float_to_ubyte(src[2])) & 0xff) << 8;
value |= ((float_to_ubyte(src[1])) & 0xff) << 16;
value |= (float_to_ubyte(src[0])) << 24;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_x8b8g8r8_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
uint32_t b;
uint32_t g;
uint32_t r;
b = (value >> 8) & 0xff;
g = (value >> 16) & 0xff;
r = value >> 24;
dst[0] = ubyte_to_float(r); /* r */
dst[1] = ubyte_to_float(g); /* g */
dst[2] = ubyte_to_float(b); /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_x8b8g8r8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t b;
uint32_t g;
uint32_t r;
b = (value >> 8) & 0xff;
g = (value >> 16) & 0xff;
r = value >> 24;
dst[0] = r; /* r */
dst[1] = g; /* g */
dst[2] = b; /* b */
dst[3] = 255; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_x8b8g8r8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= ((src[2]) & 0xff) << 8;
value |= ((src[1]) & 0xff) << 16;
value |= (src[0]) << 24;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r8g8b8x8_unorm {
uint32_t value;
struct {
uint8_t r;
uint8_t g;
uint8_t b;
uint8_t x;
} chan;
};
 
static INLINE void
util_format_r8g8b8x8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t r;
uint32_t g;
uint32_t b;
r = (value) & 0xff;
g = (value >> 8) & 0xff;
b = (value >> 16) & 0xff;
dst[0] = ubyte_to_float(r); /* r */
dst[1] = ubyte_to_float(g); /* g */
dst[2] = ubyte_to_float(b); /* b */
dst[3] = 1; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8g8b8x8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (float_to_ubyte(src[0])) & 0xff;
value |= ((float_to_ubyte(src[1])) & 0xff) << 8;
value |= ((float_to_ubyte(src[2])) & 0xff) << 16;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r8g8b8x8_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
uint32_t r;
uint32_t g;
uint32_t b;
r = (value) & 0xff;
g = (value >> 8) & 0xff;
b = (value >> 16) & 0xff;
dst[0] = ubyte_to_float(r); /* r */
dst[1] = ubyte_to_float(g); /* g */
dst[2] = ubyte_to_float(b); /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r8g8b8x8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t r;
uint32_t g;
uint32_t b;
r = (value) & 0xff;
g = (value >> 8) & 0xff;
b = (value >> 16) & 0xff;
dst[0] = r; /* r */
dst[1] = g; /* g */
dst[2] = b; /* b */
dst[3] = 255; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8g8b8x8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (src[0]) & 0xff;
value |= ((src[1]) & 0xff) << 8;
value |= ((src[2]) & 0xff) << 16;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_l8_unorm {
uint8_t value;
struct {
uint8_t rgb;
} chan;
};
 
static INLINE void
util_format_l8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint8_t value = *(const uint8_t *)src;
uint8_t rgb;
rgb = value;
dst[0] = ubyte_to_float(rgb); /* r */
dst[1] = ubyte_to_float(rgb); /* g */
dst[2] = ubyte_to_float(rgb); /* b */
dst[3] = 1; /* a */
src += 1;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint8_t value = 0;
value |= float_to_ubyte(src[0]);
*(uint8_t *)dst = value;
src += 4;
dst += 1;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_l8_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint8_t value = *(const uint8_t *)src;
uint8_t rgb;
rgb = value;
dst[0] = ubyte_to_float(rgb); /* r */
dst[1] = ubyte_to_float(rgb); /* g */
dst[2] = ubyte_to_float(rgb); /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_l8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint8_t value = *(const uint8_t *)src;
uint8_t rgb;
rgb = value;
dst[0] = rgb; /* r */
dst[1] = rgb; /* g */
dst[2] = rgb; /* b */
dst[3] = 255; /* a */
src += 1;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint8_t value = 0;
value |= src[0];
*(uint8_t *)dst = value;
src += 4;
dst += 1;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_a8_unorm {
uint8_t value;
struct {
uint8_t a;
} chan;
};
 
static INLINE void
util_format_a8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint8_t value = *(const uint8_t *)src;
uint8_t a;
a = value;
dst[0] = 0; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = ubyte_to_float(a); /* a */
src += 1;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_a8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint8_t value = 0;
value |= float_to_ubyte(src[3]);
*(uint8_t *)dst = value;
src += 4;
dst += 1;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_a8_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint8_t value = *(const uint8_t *)src;
uint8_t a;
a = value;
dst[0] = 0; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = ubyte_to_float(a); /* a */
}
 
static INLINE void
util_format_a8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint8_t value = *(const uint8_t *)src;
uint8_t a;
a = value;
dst[0] = 0; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = a; /* a */
src += 1;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_a8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint8_t value = 0;
value |= src[3];
*(uint8_t *)dst = value;
src += 4;
dst += 1;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_i8_unorm {
uint8_t value;
struct {
uint8_t rgba;
} chan;
};
 
static INLINE void
util_format_i8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint8_t value = *(const uint8_t *)src;
uint8_t rgba;
rgba = value;
dst[0] = ubyte_to_float(rgba); /* r */
dst[1] = ubyte_to_float(rgba); /* g */
dst[2] = ubyte_to_float(rgba); /* b */
dst[3] = ubyte_to_float(rgba); /* a */
src += 1;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_i8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint8_t value = 0;
value |= float_to_ubyte(src[0]);
*(uint8_t *)dst = value;
src += 4;
dst += 1;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_i8_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint8_t value = *(const uint8_t *)src;
uint8_t rgba;
rgba = value;
dst[0] = ubyte_to_float(rgba); /* r */
dst[1] = ubyte_to_float(rgba); /* g */
dst[2] = ubyte_to_float(rgba); /* b */
dst[3] = ubyte_to_float(rgba); /* a */
}
 
static INLINE void
util_format_i8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint8_t value = *(const uint8_t *)src;
uint8_t rgba;
rgba = value;
dst[0] = rgba; /* r */
dst[1] = rgba; /* g */
dst[2] = rgba; /* b */
dst[3] = rgba; /* a */
src += 1;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_i8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint8_t value = 0;
value |= src[0];
*(uint8_t *)dst = value;
src += 4;
dst += 1;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_l4a4_unorm {
uint8_t value;
struct {
unsigned rgb:4;
unsigned a:4;
} chan;
};
 
static INLINE void
util_format_l4a4_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint8_t value = *(const uint8_t *)src;
uint8_t rgb;
uint8_t a;
rgb = (value) & 0xf;
a = value >> 4;
dst[0] = (float)(rgb * (1.0f/0xf)); /* r */
dst[1] = (float)(rgb * (1.0f/0xf)); /* g */
dst[2] = (float)(rgb * (1.0f/0xf)); /* b */
dst[3] = (float)(a * (1.0f/0xf)); /* a */
src += 1;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l4a4_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint8_t value = 0;
value |= ((uint8_t)util_iround(CLAMP(src[0], 0, 1) * 0xf)) & 0xf;
value |= ((uint8_t)util_iround(CLAMP(src[3], 0, 1) * 0xf)) << 4;
*(uint8_t *)dst = value;
src += 4;
dst += 1;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_l4a4_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint8_t value = *(const uint8_t *)src;
uint8_t rgb;
uint8_t a;
rgb = (value) & 0xf;
a = value >> 4;
dst[0] = (float)(rgb * (1.0f/0xf)); /* r */
dst[1] = (float)(rgb * (1.0f/0xf)); /* g */
dst[2] = (float)(rgb * (1.0f/0xf)); /* b */
dst[3] = (float)(a * (1.0f/0xf)); /* a */
}
 
static INLINE void
util_format_l4a4_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint8_t value = *(const uint8_t *)src;
uint8_t rgb;
uint8_t a;
rgb = (value) & 0xf;
a = value >> 4;
dst[0] = (uint8_t)(((uint32_t)rgb) * 0xff / 0xf); /* r */
dst[1] = (uint8_t)(((uint32_t)rgb) * 0xff / 0xf); /* g */
dst[2] = (uint8_t)(((uint32_t)rgb) * 0xff / 0xf); /* b */
dst[3] = (uint8_t)(((uint32_t)a) * 0xff / 0xf); /* a */
src += 1;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l4a4_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint8_t value = 0;
value |= ((uint8_t)(src[0] >> 4)) & 0xf;
value |= ((uint8_t)(src[3] >> 4)) << 4;
*(uint8_t *)dst = value;
src += 4;
dst += 1;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_l8a8_unorm {
uint16_t value;
struct {
uint8_t rgb;
uint8_t a;
} chan;
};
 
static INLINE void
util_format_l8a8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
uint16_t rgb;
uint16_t a;
rgb = (value) & 0xff;
a = value >> 8;
dst[0] = ubyte_to_float(rgb); /* r */
dst[1] = ubyte_to_float(rgb); /* g */
dst[2] = ubyte_to_float(rgb); /* b */
dst[3] = ubyte_to_float(a); /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l8a8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (float_to_ubyte(src[0])) & 0xff;
value |= (float_to_ubyte(src[3])) << 8;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_l8a8_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint16_t value = *(const uint16_t *)src;
uint16_t rgb;
uint16_t a;
rgb = (value) & 0xff;
a = value >> 8;
dst[0] = ubyte_to_float(rgb); /* r */
dst[1] = ubyte_to_float(rgb); /* g */
dst[2] = ubyte_to_float(rgb); /* b */
dst[3] = ubyte_to_float(a); /* a */
}
 
static INLINE void
util_format_l8a8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
uint16_t rgb;
uint16_t a;
rgb = (value) & 0xff;
a = value >> 8;
dst[0] = rgb; /* r */
dst[1] = rgb; /* g */
dst[2] = rgb; /* b */
dst[3] = a; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l8a8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (src[0]) & 0xff;
value |= (src[3]) << 8;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_l16_unorm {
uint16_t value;
struct {
uint16_t rgb;
} chan;
};
 
static INLINE void
util_format_l16_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
uint16_t rgb;
rgb = value;
dst[0] = (float)(rgb * (1.0f/0xffff)); /* r */
dst[1] = (float)(rgb * (1.0f/0xffff)); /* g */
dst[2] = (float)(rgb * (1.0f/0xffff)); /* b */
dst[3] = 1; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l16_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)util_iround(CLAMP(src[0], 0, 1) * 0xffff);
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_l16_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint16_t value = *(const uint16_t *)src;
uint16_t rgb;
rgb = value;
dst[0] = (float)(rgb * (1.0f/0xffff)); /* r */
dst[1] = (float)(rgb * (1.0f/0xffff)); /* g */
dst[2] = (float)(rgb * (1.0f/0xffff)); /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_l16_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
uint16_t rgb;
rgb = value;
dst[0] = (uint8_t)(rgb >> 8); /* r */
dst[1] = (uint8_t)(rgb >> 8); /* g */
dst[2] = (uint8_t)(rgb >> 8); /* b */
dst[3] = 255; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l16_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)(((uint32_t)src[0]) * 0xffff / 0xff);
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_a16_unorm {
uint16_t value;
struct {
uint16_t a;
} chan;
};
 
static INLINE void
util_format_a16_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
uint16_t a;
a = value;
dst[0] = 0; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (float)(a * (1.0f/0xffff)); /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_a16_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)util_iround(CLAMP(src[3], 0, 1) * 0xffff);
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_a16_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint16_t value = *(const uint16_t *)src;
uint16_t a;
a = value;
dst[0] = 0; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (float)(a * (1.0f/0xffff)); /* a */
}
 
static INLINE void
util_format_a16_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
uint16_t a;
a = value;
dst[0] = 0; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (uint8_t)(a >> 8); /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_a16_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)(((uint32_t)src[3]) * 0xffff / 0xff);
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_i16_unorm {
uint16_t value;
struct {
uint16_t rgba;
} chan;
};
 
static INLINE void
util_format_i16_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
uint16_t rgba;
rgba = value;
dst[0] = (float)(rgba * (1.0f/0xffff)); /* r */
dst[1] = (float)(rgba * (1.0f/0xffff)); /* g */
dst[2] = (float)(rgba * (1.0f/0xffff)); /* b */
dst[3] = (float)(rgba * (1.0f/0xffff)); /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_i16_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)util_iround(CLAMP(src[0], 0, 1) * 0xffff);
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_i16_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint16_t value = *(const uint16_t *)src;
uint16_t rgba;
rgba = value;
dst[0] = (float)(rgba * (1.0f/0xffff)); /* r */
dst[1] = (float)(rgba * (1.0f/0xffff)); /* g */
dst[2] = (float)(rgba * (1.0f/0xffff)); /* b */
dst[3] = (float)(rgba * (1.0f/0xffff)); /* a */
}
 
static INLINE void
util_format_i16_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
uint16_t rgba;
rgba = value;
dst[0] = (uint8_t)(rgba >> 8); /* r */
dst[1] = (uint8_t)(rgba >> 8); /* g */
dst[2] = (uint8_t)(rgba >> 8); /* b */
dst[3] = (uint8_t)(rgba >> 8); /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_i16_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)(((uint32_t)src[0]) * 0xffff / 0xff);
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_l16a16_unorm {
uint32_t value;
struct {
uint16_t rgb;
uint16_t a;
} chan;
};
 
static INLINE void
util_format_l16a16_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t rgb;
uint32_t a;
rgb = (value) & 0xffff;
a = value >> 16;
dst[0] = (float)(rgb * (1.0f/0xffff)); /* r */
dst[1] = (float)(rgb * (1.0f/0xffff)); /* g */
dst[2] = (float)(rgb * (1.0f/0xffff)); /* b */
dst[3] = (float)(a * (1.0f/0xffff)); /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l16a16_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= ((uint16_t)util_iround(CLAMP(src[0], 0, 1) * 0xffff)) & 0xffff;
value |= ((uint16_t)util_iround(CLAMP(src[3], 0, 1) * 0xffff)) << 16;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_l16a16_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
uint32_t rgb;
uint32_t a;
rgb = (value) & 0xffff;
a = value >> 16;
dst[0] = (float)(rgb * (1.0f/0xffff)); /* r */
dst[1] = (float)(rgb * (1.0f/0xffff)); /* g */
dst[2] = (float)(rgb * (1.0f/0xffff)); /* b */
dst[3] = (float)(a * (1.0f/0xffff)); /* a */
}
 
static INLINE void
util_format_l16a16_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t rgb;
uint32_t a;
rgb = (value) & 0xffff;
a = value >> 16;
dst[0] = (uint8_t)(rgb >> 8); /* r */
dst[1] = (uint8_t)(rgb >> 8); /* g */
dst[2] = (uint8_t)(rgb >> 8); /* b */
dst[3] = (uint8_t)(a >> 8); /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l16a16_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= ((uint16_t)(((uint32_t)src[0]) * 0xffff / 0xff)) & 0xffff;
value |= ((uint16_t)(((uint32_t)src[3]) * 0xffff / 0xff)) << 16;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_a8_snorm {
uint8_t value;
struct {
int8_t a;
} chan;
};
 
static INLINE void
util_format_a8_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint8_t value = *(const uint8_t *)src;
int8_t a;
a = (int8_t)(value) ;
dst[0] = 0; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (float)(a * (1.0f/0x7f)); /* a */
src += 1;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_a8_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint8_t value = 0;
value |= (uint8_t)((int8_t)util_iround(CLAMP(src[3], -1, 1) * 0x7f)) ;
*(uint8_t *)dst = value;
src += 4;
dst += 1;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_a8_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint8_t value = *(const uint8_t *)src;
int8_t a;
a = (int8_t)(value) ;
dst[0] = 0; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (float)(a * (1.0f/0x7f)); /* a */
}
 
static INLINE void
util_format_a8_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint8_t value = *(const uint8_t *)src;
int8_t a;
a = (int8_t)(value) ;
dst[0] = 0; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (uint8_t)(((uint32_t)MAX2(a, 0)) * 0xff / 0x7f); /* a */
src += 1;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_a8_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint8_t value = 0;
value |= (uint8_t)((int8_t)(src[3] >> 1)) ;
*(uint8_t *)dst = value;
src += 4;
dst += 1;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_l8_snorm {
uint8_t value;
struct {
int8_t rgb;
} chan;
};
 
static INLINE void
util_format_l8_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint8_t value = *(const uint8_t *)src;
int8_t rgb;
rgb = (int8_t)(value) ;
dst[0] = (float)(rgb * (1.0f/0x7f)); /* r */
dst[1] = (float)(rgb * (1.0f/0x7f)); /* g */
dst[2] = (float)(rgb * (1.0f/0x7f)); /* b */
dst[3] = 1; /* a */
src += 1;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l8_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint8_t value = 0;
value |= (uint8_t)((int8_t)util_iround(CLAMP(src[0], -1, 1) * 0x7f)) ;
*(uint8_t *)dst = value;
src += 4;
dst += 1;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_l8_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint8_t value = *(const uint8_t *)src;
int8_t rgb;
rgb = (int8_t)(value) ;
dst[0] = (float)(rgb * (1.0f/0x7f)); /* r */
dst[1] = (float)(rgb * (1.0f/0x7f)); /* g */
dst[2] = (float)(rgb * (1.0f/0x7f)); /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_l8_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint8_t value = *(const uint8_t *)src;
int8_t rgb;
rgb = (int8_t)(value) ;
dst[0] = (uint8_t)(((uint32_t)MAX2(rgb, 0)) * 0xff / 0x7f); /* r */
dst[1] = (uint8_t)(((uint32_t)MAX2(rgb, 0)) * 0xff / 0x7f); /* g */
dst[2] = (uint8_t)(((uint32_t)MAX2(rgb, 0)) * 0xff / 0x7f); /* b */
dst[3] = 255; /* a */
src += 1;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l8_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint8_t value = 0;
value |= (uint8_t)((int8_t)(src[0] >> 1)) ;
*(uint8_t *)dst = value;
src += 4;
dst += 1;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_l8a8_snorm {
uint16_t value;
struct {
int8_t rgb;
int8_t a;
} chan;
};
 
static INLINE void
util_format_l8a8_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
int16_t rgb;
int16_t a;
rgb = ((int16_t)(value << 8) ) >> 8;
a = ((int16_t)(value) ) >> 8;
dst[0] = (float)(rgb * (1.0f/0x7f)); /* r */
dst[1] = (float)(rgb * (1.0f/0x7f)); /* g */
dst[2] = (float)(rgb * (1.0f/0x7f)); /* b */
dst[3] = (float)(a * (1.0f/0x7f)); /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l8a8_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)(((int8_t)util_iround(CLAMP(src[0], -1, 1) * 0x7f)) & 0xff) ;
value |= (uint16_t)(((int8_t)util_iround(CLAMP(src[3], -1, 1) * 0x7f)) << 8) ;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_l8a8_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint16_t value = *(const uint16_t *)src;
int16_t rgb;
int16_t a;
rgb = ((int16_t)(value << 8) ) >> 8;
a = ((int16_t)(value) ) >> 8;
dst[0] = (float)(rgb * (1.0f/0x7f)); /* r */
dst[1] = (float)(rgb * (1.0f/0x7f)); /* g */
dst[2] = (float)(rgb * (1.0f/0x7f)); /* b */
dst[3] = (float)(a * (1.0f/0x7f)); /* a */
}
 
static INLINE void
util_format_l8a8_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
int16_t rgb;
int16_t a;
rgb = ((int16_t)(value << 8) ) >> 8;
a = ((int16_t)(value) ) >> 8;
dst[0] = (uint8_t)(((uint32_t)MAX2(rgb, 0)) * 0xff / 0x7f); /* r */
dst[1] = (uint8_t)(((uint32_t)MAX2(rgb, 0)) * 0xff / 0x7f); /* g */
dst[2] = (uint8_t)(((uint32_t)MAX2(rgb, 0)) * 0xff / 0x7f); /* b */
dst[3] = (uint8_t)(((uint32_t)MAX2(a, 0)) * 0xff / 0x7f); /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l8a8_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)(((int8_t)(src[0] >> 1)) & 0xff) ;
value |= (uint16_t)(((int8_t)(src[3] >> 1)) << 8) ;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_i8_snorm {
uint8_t value;
struct {
int8_t rgba;
} chan;
};
 
static INLINE void
util_format_i8_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint8_t value = *(const uint8_t *)src;
int8_t rgba;
rgba = (int8_t)(value) ;
dst[0] = (float)(rgba * (1.0f/0x7f)); /* r */
dst[1] = (float)(rgba * (1.0f/0x7f)); /* g */
dst[2] = (float)(rgba * (1.0f/0x7f)); /* b */
dst[3] = (float)(rgba * (1.0f/0x7f)); /* a */
src += 1;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_i8_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint8_t value = 0;
value |= (uint8_t)((int8_t)util_iround(CLAMP(src[0], -1, 1) * 0x7f)) ;
*(uint8_t *)dst = value;
src += 4;
dst += 1;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_i8_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint8_t value = *(const uint8_t *)src;
int8_t rgba;
rgba = (int8_t)(value) ;
dst[0] = (float)(rgba * (1.0f/0x7f)); /* r */
dst[1] = (float)(rgba * (1.0f/0x7f)); /* g */
dst[2] = (float)(rgba * (1.0f/0x7f)); /* b */
dst[3] = (float)(rgba * (1.0f/0x7f)); /* a */
}
 
static INLINE void
util_format_i8_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint8_t value = *(const uint8_t *)src;
int8_t rgba;
rgba = (int8_t)(value) ;
dst[0] = (uint8_t)(((uint32_t)MAX2(rgba, 0)) * 0xff / 0x7f); /* r */
dst[1] = (uint8_t)(((uint32_t)MAX2(rgba, 0)) * 0xff / 0x7f); /* g */
dst[2] = (uint8_t)(((uint32_t)MAX2(rgba, 0)) * 0xff / 0x7f); /* b */
dst[3] = (uint8_t)(((uint32_t)MAX2(rgba, 0)) * 0xff / 0x7f); /* a */
src += 1;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_i8_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint8_t value = 0;
value |= (uint8_t)((int8_t)(src[0] >> 1)) ;
*(uint8_t *)dst = value;
src += 4;
dst += 1;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_a16_snorm {
uint16_t value;
struct {
int16_t a;
} chan;
};
 
static INLINE void
util_format_a16_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
int16_t a;
a = (int16_t)(value) ;
dst[0] = 0; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (float)(a * (1.0f/0x7fff)); /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_a16_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)((int16_t)util_iround(CLAMP(src[3], -1, 1) * 0x7fff)) ;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_a16_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint16_t value = *(const uint16_t *)src;
int16_t a;
a = (int16_t)(value) ;
dst[0] = 0; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (float)(a * (1.0f/0x7fff)); /* a */
}
 
static INLINE void
util_format_a16_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
int16_t a;
a = (int16_t)(value) ;
dst[0] = 0; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (uint8_t)(MAX2(a, 0) >> 7); /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_a16_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)((int16_t)(((uint32_t)src[3]) * 0x7fff / 0xff)) ;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_l16_snorm {
uint16_t value;
struct {
int16_t rgb;
} chan;
};
 
static INLINE void
util_format_l16_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
int16_t rgb;
rgb = (int16_t)(value) ;
dst[0] = (float)(rgb * (1.0f/0x7fff)); /* r */
dst[1] = (float)(rgb * (1.0f/0x7fff)); /* g */
dst[2] = (float)(rgb * (1.0f/0x7fff)); /* b */
dst[3] = 1; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l16_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)((int16_t)util_iround(CLAMP(src[0], -1, 1) * 0x7fff)) ;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_l16_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint16_t value = *(const uint16_t *)src;
int16_t rgb;
rgb = (int16_t)(value) ;
dst[0] = (float)(rgb * (1.0f/0x7fff)); /* r */
dst[1] = (float)(rgb * (1.0f/0x7fff)); /* g */
dst[2] = (float)(rgb * (1.0f/0x7fff)); /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_l16_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
int16_t rgb;
rgb = (int16_t)(value) ;
dst[0] = (uint8_t)(MAX2(rgb, 0) >> 7); /* r */
dst[1] = (uint8_t)(MAX2(rgb, 0) >> 7); /* g */
dst[2] = (uint8_t)(MAX2(rgb, 0) >> 7); /* b */
dst[3] = 255; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l16_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)((int16_t)(((uint32_t)src[0]) * 0x7fff / 0xff)) ;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_l16a16_snorm {
uint32_t value;
struct {
int16_t rgb;
int16_t a;
} chan;
};
 
static INLINE void
util_format_l16a16_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
int32_t rgb;
int32_t a;
rgb = ((int32_t)(value << 16) ) >> 16;
a = ((int32_t)(value) ) >> 16;
dst[0] = (float)(rgb * (1.0f/0x7fff)); /* r */
dst[1] = (float)(rgb * (1.0f/0x7fff)); /* g */
dst[2] = (float)(rgb * (1.0f/0x7fff)); /* b */
dst[3] = (float)(a * (1.0f/0x7fff)); /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l16a16_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)(((int16_t)util_iround(CLAMP(src[0], -1, 1) * 0x7fff)) & 0xffff) ;
value |= (uint32_t)(((int16_t)util_iround(CLAMP(src[3], -1, 1) * 0x7fff)) << 16) ;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_l16a16_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
int32_t rgb;
int32_t a;
rgb = ((int32_t)(value << 16) ) >> 16;
a = ((int32_t)(value) ) >> 16;
dst[0] = (float)(rgb * (1.0f/0x7fff)); /* r */
dst[1] = (float)(rgb * (1.0f/0x7fff)); /* g */
dst[2] = (float)(rgb * (1.0f/0x7fff)); /* b */
dst[3] = (float)(a * (1.0f/0x7fff)); /* a */
}
 
static INLINE void
util_format_l16a16_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
int32_t rgb;
int32_t a;
rgb = ((int32_t)(value << 16) ) >> 16;
a = ((int32_t)(value) ) >> 16;
dst[0] = (uint8_t)(MAX2(rgb, 0) >> 7); /* r */
dst[1] = (uint8_t)(MAX2(rgb, 0) >> 7); /* g */
dst[2] = (uint8_t)(MAX2(rgb, 0) >> 7); /* b */
dst[3] = (uint8_t)(MAX2(a, 0) >> 7); /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l16a16_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)(((int16_t)(((uint32_t)src[0]) * 0x7fff / 0xff)) & 0xffff) ;
value |= (uint32_t)(((int16_t)(((uint32_t)src[3]) * 0x7fff / 0xff)) << 16) ;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_i16_snorm {
uint16_t value;
struct {
int16_t rgba;
} chan;
};
 
static INLINE void
util_format_i16_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
int16_t rgba;
rgba = (int16_t)(value) ;
dst[0] = (float)(rgba * (1.0f/0x7fff)); /* r */
dst[1] = (float)(rgba * (1.0f/0x7fff)); /* g */
dst[2] = (float)(rgba * (1.0f/0x7fff)); /* b */
dst[3] = (float)(rgba * (1.0f/0x7fff)); /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_i16_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)((int16_t)util_iround(CLAMP(src[0], -1, 1) * 0x7fff)) ;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_i16_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint16_t value = *(const uint16_t *)src;
int16_t rgba;
rgba = (int16_t)(value) ;
dst[0] = (float)(rgba * (1.0f/0x7fff)); /* r */
dst[1] = (float)(rgba * (1.0f/0x7fff)); /* g */
dst[2] = (float)(rgba * (1.0f/0x7fff)); /* b */
dst[3] = (float)(rgba * (1.0f/0x7fff)); /* a */
}
 
static INLINE void
util_format_i16_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
int16_t rgba;
rgba = (int16_t)(value) ;
dst[0] = (uint8_t)(MAX2(rgba, 0) >> 7); /* r */
dst[1] = (uint8_t)(MAX2(rgba, 0) >> 7); /* g */
dst[2] = (uint8_t)(MAX2(rgba, 0) >> 7); /* b */
dst[3] = (uint8_t)(MAX2(rgba, 0) >> 7); /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_i16_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)((int16_t)(((uint32_t)src[0]) * 0x7fff / 0xff)) ;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_a16_float {
uint16_t value;
struct {
uint16_t a;
} chan;
};
 
static INLINE void
util_format_a16_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_a16_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = 0; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = util_half_to_float(pixel.chan.a); /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_a16_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_a16_float pixel;
pixel.chan.a = util_float_to_half(src[3]);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_a16_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_a16_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = 0; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = util_half_to_float(pixel.chan.a); /* a */
}
 
static INLINE void
util_format_a16_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_a16_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = 0; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = float_to_ubyte(util_half_to_float(pixel.chan.a)); /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_a16_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_a16_float pixel;
pixel.chan.a = util_float_to_half((float)(src[3] * (1.0f/0xff)));
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_l16_float {
uint16_t value;
struct {
uint16_t rgb;
} chan;
};
 
static INLINE void
util_format_l16_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_l16_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = util_half_to_float(pixel.chan.rgb); /* r */
dst[1] = util_half_to_float(pixel.chan.rgb); /* g */
dst[2] = util_half_to_float(pixel.chan.rgb); /* b */
dst[3] = 1; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l16_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_l16_float pixel;
pixel.chan.rgb = util_float_to_half(src[0]);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_l16_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_l16_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = util_half_to_float(pixel.chan.rgb); /* r */
dst[1] = util_half_to_float(pixel.chan.rgb); /* g */
dst[2] = util_half_to_float(pixel.chan.rgb); /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_l16_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_l16_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = float_to_ubyte(util_half_to_float(pixel.chan.rgb)); /* r */
dst[1] = float_to_ubyte(util_half_to_float(pixel.chan.rgb)); /* g */
dst[2] = float_to_ubyte(util_half_to_float(pixel.chan.rgb)); /* b */
dst[3] = 255; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l16_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_l16_float pixel;
pixel.chan.rgb = util_float_to_half((float)(src[0] * (1.0f/0xff)));
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_l16a16_float {
uint32_t value;
struct {
uint16_t rgb;
uint16_t a;
} chan;
};
 
static INLINE void
util_format_l16a16_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_l16a16_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = util_half_to_float(pixel.chan.rgb); /* r */
dst[1] = util_half_to_float(pixel.chan.rgb); /* g */
dst[2] = util_half_to_float(pixel.chan.rgb); /* b */
dst[3] = util_half_to_float(pixel.chan.a); /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l16a16_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_l16a16_float pixel;
pixel.chan.rgb = util_float_to_half(src[0]);
pixel.chan.a = util_float_to_half(src[3]);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_l16a16_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_l16a16_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = util_half_to_float(pixel.chan.rgb); /* r */
dst[1] = util_half_to_float(pixel.chan.rgb); /* g */
dst[2] = util_half_to_float(pixel.chan.rgb); /* b */
dst[3] = util_half_to_float(pixel.chan.a); /* a */
}
 
static INLINE void
util_format_l16a16_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_l16a16_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = float_to_ubyte(util_half_to_float(pixel.chan.rgb)); /* r */
dst[1] = float_to_ubyte(util_half_to_float(pixel.chan.rgb)); /* g */
dst[2] = float_to_ubyte(util_half_to_float(pixel.chan.rgb)); /* b */
dst[3] = float_to_ubyte(util_half_to_float(pixel.chan.a)); /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l16a16_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_l16a16_float pixel;
pixel.chan.rgb = util_float_to_half((float)(src[0] * (1.0f/0xff)));
pixel.chan.a = util_float_to_half((float)(src[3] * (1.0f/0xff)));
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_i16_float {
uint16_t value;
struct {
uint16_t rgba;
} chan;
};
 
static INLINE void
util_format_i16_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_i16_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = util_half_to_float(pixel.chan.rgba); /* r */
dst[1] = util_half_to_float(pixel.chan.rgba); /* g */
dst[2] = util_half_to_float(pixel.chan.rgba); /* b */
dst[3] = util_half_to_float(pixel.chan.rgba); /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_i16_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_i16_float pixel;
pixel.chan.rgba = util_float_to_half(src[0]);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_i16_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_i16_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = util_half_to_float(pixel.chan.rgba); /* r */
dst[1] = util_half_to_float(pixel.chan.rgba); /* g */
dst[2] = util_half_to_float(pixel.chan.rgba); /* b */
dst[3] = util_half_to_float(pixel.chan.rgba); /* a */
}
 
static INLINE void
util_format_i16_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_i16_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = float_to_ubyte(util_half_to_float(pixel.chan.rgba)); /* r */
dst[1] = float_to_ubyte(util_half_to_float(pixel.chan.rgba)); /* g */
dst[2] = float_to_ubyte(util_half_to_float(pixel.chan.rgba)); /* b */
dst[3] = float_to_ubyte(util_half_to_float(pixel.chan.rgba)); /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_i16_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_i16_float pixel;
pixel.chan.rgba = util_float_to_half((float)(src[0] * (1.0f/0xff)));
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_a32_float {
uint32_t value;
struct {
float a;
} chan;
};
 
static INLINE void
util_format_a32_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_a32_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = 0; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = pixel.chan.a; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_a32_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_a32_float pixel;
pixel.chan.a = src[3];
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_a32_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_a32_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = 0; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = pixel.chan.a; /* a */
}
 
static INLINE void
util_format_a32_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_a32_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = 0; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = float_to_ubyte(pixel.chan.a); /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_a32_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_a32_float pixel;
pixel.chan.a = ubyte_to_float(src[3]);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_l32_float {
uint32_t value;
struct {
float rgb;
} chan;
};
 
static INLINE void
util_format_l32_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_l32_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = pixel.chan.rgb; /* r */
dst[1] = pixel.chan.rgb; /* g */
dst[2] = pixel.chan.rgb; /* b */
dst[3] = 1; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l32_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_l32_float pixel;
pixel.chan.rgb = src[0];
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_l32_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_l32_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = pixel.chan.rgb; /* r */
dst[1] = pixel.chan.rgb; /* g */
dst[2] = pixel.chan.rgb; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_l32_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_l32_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = float_to_ubyte(pixel.chan.rgb); /* r */
dst[1] = float_to_ubyte(pixel.chan.rgb); /* g */
dst[2] = float_to_ubyte(pixel.chan.rgb); /* b */
dst[3] = 255; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l32_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_l32_float pixel;
pixel.chan.rgb = ubyte_to_float(src[0]);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_l32a32_float {
uint64_t value;
struct {
float rgb;
float a;
} chan;
};
 
static INLINE void
util_format_l32a32_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_l32a32_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = pixel.chan.rgb; /* r */
dst[1] = pixel.chan.rgb; /* g */
dst[2] = pixel.chan.rgb; /* b */
dst[3] = pixel.chan.a; /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l32a32_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_l32a32_float pixel;
pixel.chan.rgb = src[0];
pixel.chan.a = src[3];
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_l32a32_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_l32a32_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = pixel.chan.rgb; /* r */
dst[1] = pixel.chan.rgb; /* g */
dst[2] = pixel.chan.rgb; /* b */
dst[3] = pixel.chan.a; /* a */
}
 
static INLINE void
util_format_l32a32_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_l32a32_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = float_to_ubyte(pixel.chan.rgb); /* r */
dst[1] = float_to_ubyte(pixel.chan.rgb); /* g */
dst[2] = float_to_ubyte(pixel.chan.rgb); /* b */
dst[3] = float_to_ubyte(pixel.chan.a); /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l32a32_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_l32a32_float pixel;
pixel.chan.rgb = ubyte_to_float(src[0]);
pixel.chan.a = ubyte_to_float(src[3]);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_i32_float {
uint32_t value;
struct {
float rgba;
} chan;
};
 
static INLINE void
util_format_i32_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_i32_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = pixel.chan.rgba; /* r */
dst[1] = pixel.chan.rgba; /* g */
dst[2] = pixel.chan.rgba; /* b */
dst[3] = pixel.chan.rgba; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_i32_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_i32_float pixel;
pixel.chan.rgba = src[0];
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_i32_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_i32_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = pixel.chan.rgba; /* r */
dst[1] = pixel.chan.rgba; /* g */
dst[2] = pixel.chan.rgba; /* b */
dst[3] = pixel.chan.rgba; /* a */
}
 
static INLINE void
util_format_i32_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_i32_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = float_to_ubyte(pixel.chan.rgba); /* r */
dst[1] = float_to_ubyte(pixel.chan.rgba); /* g */
dst[2] = float_to_ubyte(pixel.chan.rgba); /* b */
dst[3] = float_to_ubyte(pixel.chan.rgba); /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_i32_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_i32_float pixel;
pixel.chan.rgba = ubyte_to_float(src[0]);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r8sg8sb8ux8u_norm {
uint32_t value;
struct {
int8_t r;
int8_t g;
uint8_t b;
uint8_t x;
} chan;
};
 
static INLINE void
util_format_r8sg8sb8ux8u_norm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
int32_t r;
int32_t g;
uint32_t b;
r = ((int32_t)(value << 24) ) >> 24;
g = ((int32_t)(value << 16) ) >> 24;
b = (value >> 16) & 0xff;
dst[0] = (float)(r * (1.0f/0x7f)); /* r */
dst[1] = (float)(g * (1.0f/0x7f)); /* g */
dst[2] = ubyte_to_float(b); /* b */
dst[3] = 1; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8sg8sb8ux8u_norm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)(((uint32_t)util_iround(CLAMP(src[0], -1, 1) * 0x7f)) & 0xff) ;
value |= (uint32_t)((((uint32_t)util_iround(CLAMP(src[1], -1, 1) * 0x7f)) & 0xff) << 8) ;
value |= ((float_to_ubyte(src[2])) & 0xff) << 16;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r8sg8sb8ux8u_norm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
int32_t r;
int32_t g;
uint32_t b;
r = ((int32_t)(value << 24) ) >> 24;
g = ((int32_t)(value << 16) ) >> 24;
b = (value >> 16) & 0xff;
dst[0] = (float)(r * (1.0f/0x7f)); /* r */
dst[1] = (float)(g * (1.0f/0x7f)); /* g */
dst[2] = ubyte_to_float(b); /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r8sg8sb8ux8u_norm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
int32_t r;
int32_t g;
uint32_t b;
r = ((int32_t)(value << 24) ) >> 24;
g = ((int32_t)(value << 16) ) >> 24;
b = (value >> 16) & 0xff;
dst[0] = (uint8_t)(((uint32_t)MAX2(r, 0)) * 0xff / 0x7f); /* r */
dst[1] = (uint8_t)(((uint32_t)MAX2(g, 0)) * 0xff / 0x7f); /* g */
dst[2] = b; /* b */
dst[3] = 255; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8sg8sb8ux8u_norm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)(((uint32_t)(src[0] >> 1)) & 0xff) ;
value |= (uint32_t)((((uint32_t)(src[1] >> 1)) & 0xff) << 8) ;
value |= ((src[2]) & 0xff) << 16;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r5sg5sb6u_norm {
uint16_t value;
struct {
int r:5;
int g:5;
unsigned b:6;
} chan;
};
 
static INLINE void
util_format_r5sg5sb6u_norm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
int16_t r;
int16_t g;
uint16_t b;
r = ((int16_t)(value << 11) ) >> 11;
g = ((int16_t)(value << 6) ) >> 11;
b = value >> 10;
dst[0] = (float)(r * (1.0f/0xf)); /* r */
dst[1] = (float)(g * (1.0f/0xf)); /* g */
dst[2] = (float)(b * (1.0f/0x3f)); /* b */
dst[3] = 1; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r5sg5sb6u_norm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)(((uint16_t)util_iround(CLAMP(src[0], -1, 1) * 0xf)) & 0x1f) ;
value |= (uint16_t)((((uint16_t)util_iround(CLAMP(src[1], -1, 1) * 0xf)) & 0x1f) << 5) ;
value |= ((uint16_t)util_iround(CLAMP(src[2], 0, 1) * 0x3f)) << 10;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r5sg5sb6u_norm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint16_t value = *(const uint16_t *)src;
int16_t r;
int16_t g;
uint16_t b;
r = ((int16_t)(value << 11) ) >> 11;
g = ((int16_t)(value << 6) ) >> 11;
b = value >> 10;
dst[0] = (float)(r * (1.0f/0xf)); /* r */
dst[1] = (float)(g * (1.0f/0xf)); /* g */
dst[2] = (float)(b * (1.0f/0x3f)); /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r5sg5sb6u_norm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
int16_t r;
int16_t g;
uint16_t b;
r = ((int16_t)(value << 11) ) >> 11;
g = ((int16_t)(value << 6) ) >> 11;
b = value >> 10;
dst[0] = (uint8_t)(((uint32_t)MAX2(r, 0)) * 0xff / 0xf); /* r */
dst[1] = (uint8_t)(((uint32_t)MAX2(g, 0)) * 0xff / 0xf); /* g */
dst[2] = (uint8_t)(((uint32_t)b) * 0xff / 0x3f); /* b */
dst[3] = 255; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r5sg5sb6u_norm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)(((uint16_t)(src[0] >> 4)) & 0x1f) ;
value |= (uint16_t)((((uint16_t)(src[1] >> 4)) & 0x1f) << 5) ;
value |= ((uint16_t)(src[2] >> 2)) << 10;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r64_float {
uint64_t value;
struct {
double r;
} chan;
};
 
static INLINE void
util_format_r64_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r64_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)pixel.chan.r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r64_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r64_float pixel;
pixel.chan.r = (double)src[0];
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r64_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r64_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)pixel.chan.r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r64_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r64_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (uint8_t)util_iround(CLAMP(pixel.chan.r, 0, 1) * 0xff); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 255; /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r64_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r64_float pixel;
pixel.chan.r = (double)(src[0] * (1.0f/0xff));
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r64g64_float {
struct {
double r;
double g;
} chan;
};
 
static INLINE void
util_format_r64g64_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r64g64_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)pixel.chan.r; /* r */
dst[1] = (float)pixel.chan.g; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 16;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r64g64_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r64g64_float pixel;
pixel.chan.r = (double)src[0];
pixel.chan.g = (double)src[1];
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 16;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r64g64_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r64g64_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)pixel.chan.r; /* r */
dst[1] = (float)pixel.chan.g; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r64g64_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r64g64_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (uint8_t)util_iround(CLAMP(pixel.chan.r, 0, 1) * 0xff); /* r */
dst[1] = (uint8_t)util_iround(CLAMP(pixel.chan.g, 0, 1) * 0xff); /* g */
dst[2] = 0; /* b */
dst[3] = 255; /* a */
src += 16;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r64g64_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r64g64_float pixel;
pixel.chan.r = (double)(src[0] * (1.0f/0xff));
pixel.chan.g = (double)(src[1] * (1.0f/0xff));
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 16;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r64g64b64_float {
struct {
double r;
double g;
double b;
} chan;
};
 
static INLINE void
util_format_r64g64b64_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r64g64b64_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)pixel.chan.r; /* r */
dst[1] = (float)pixel.chan.g; /* g */
dst[2] = (float)pixel.chan.b; /* b */
dst[3] = 1; /* a */
src += 24;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r64g64b64_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r64g64b64_float pixel;
pixel.chan.r = (double)src[0];
pixel.chan.g = (double)src[1];
pixel.chan.b = (double)src[2];
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 24;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r64g64b64_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r64g64b64_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)pixel.chan.r; /* r */
dst[1] = (float)pixel.chan.g; /* g */
dst[2] = (float)pixel.chan.b; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r64g64b64_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r64g64b64_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (uint8_t)util_iround(CLAMP(pixel.chan.r, 0, 1) * 0xff); /* r */
dst[1] = (uint8_t)util_iround(CLAMP(pixel.chan.g, 0, 1) * 0xff); /* g */
dst[2] = (uint8_t)util_iround(CLAMP(pixel.chan.b, 0, 1) * 0xff); /* b */
dst[3] = 255; /* a */
src += 24;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r64g64b64_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r64g64b64_float pixel;
pixel.chan.r = (double)(src[0] * (1.0f/0xff));
pixel.chan.g = (double)(src[1] * (1.0f/0xff));
pixel.chan.b = (double)(src[2] * (1.0f/0xff));
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 24;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r64g64b64a64_float {
struct {
double r;
double g;
double b;
double a;
} chan;
};
 
static INLINE void
util_format_r64g64b64a64_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r64g64b64a64_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)pixel.chan.r; /* r */
dst[1] = (float)pixel.chan.g; /* g */
dst[2] = (float)pixel.chan.b; /* b */
dst[3] = (float)pixel.chan.a; /* a */
src += 32;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r64g64b64a64_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r64g64b64a64_float pixel;
pixel.chan.r = (double)src[0];
pixel.chan.g = (double)src[1];
pixel.chan.b = (double)src[2];
pixel.chan.a = (double)src[3];
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 32;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r64g64b64a64_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r64g64b64a64_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)pixel.chan.r; /* r */
dst[1] = (float)pixel.chan.g; /* g */
dst[2] = (float)pixel.chan.b; /* b */
dst[3] = (float)pixel.chan.a; /* a */
}
 
static INLINE void
util_format_r64g64b64a64_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r64g64b64a64_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (uint8_t)util_iround(CLAMP(pixel.chan.r, 0, 1) * 0xff); /* r */
dst[1] = (uint8_t)util_iround(CLAMP(pixel.chan.g, 0, 1) * 0xff); /* g */
dst[2] = (uint8_t)util_iround(CLAMP(pixel.chan.b, 0, 1) * 0xff); /* b */
dst[3] = (uint8_t)util_iround(CLAMP(pixel.chan.a, 0, 1) * 0xff); /* a */
src += 32;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r64g64b64a64_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r64g64b64a64_float pixel;
pixel.chan.r = (double)(src[0] * (1.0f/0xff));
pixel.chan.g = (double)(src[1] * (1.0f/0xff));
pixel.chan.b = (double)(src[2] * (1.0f/0xff));
pixel.chan.a = (double)(src[3] * (1.0f/0xff));
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 32;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r32_float {
uint32_t value;
struct {
float r;
} chan;
};
 
static INLINE void
util_format_r32_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = pixel.chan.r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32_float pixel;
pixel.chan.r = src[0];
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r32_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r32_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = pixel.chan.r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r32_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = float_to_ubyte(pixel.chan.r); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 255; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32_float pixel;
pixel.chan.r = ubyte_to_float(src[0]);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r32g32_float {
uint64_t value;
struct {
float r;
float g;
} chan;
};
 
static INLINE void
util_format_r32g32_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = pixel.chan.r; /* r */
dst[1] = pixel.chan.g; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32_float pixel;
pixel.chan.r = src[0];
pixel.chan.g = src[1];
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r32g32_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r32g32_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = pixel.chan.r; /* r */
dst[1] = pixel.chan.g; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r32g32_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = float_to_ubyte(pixel.chan.r); /* r */
dst[1] = float_to_ubyte(pixel.chan.g); /* g */
dst[2] = 0; /* b */
dst[3] = 255; /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32_float pixel;
pixel.chan.r = ubyte_to_float(src[0]);
pixel.chan.g = ubyte_to_float(src[1]);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r32g32b32_float {
struct {
float r;
float g;
float b;
} chan;
};
 
static INLINE void
util_format_r32g32b32_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = pixel.chan.r; /* r */
dst[1] = pixel.chan.g; /* g */
dst[2] = pixel.chan.b; /* b */
dst[3] = 1; /* a */
src += 12;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32b32_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32_float pixel;
pixel.chan.r = src[0];
pixel.chan.g = src[1];
pixel.chan.b = src[2];
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 12;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r32g32b32_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r32g32b32_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = pixel.chan.r; /* r */
dst[1] = pixel.chan.g; /* g */
dst[2] = pixel.chan.b; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r32g32b32_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = float_to_ubyte(pixel.chan.r); /* r */
dst[1] = float_to_ubyte(pixel.chan.g); /* g */
dst[2] = float_to_ubyte(pixel.chan.b); /* b */
dst[3] = 255; /* a */
src += 12;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32b32_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32_float pixel;
pixel.chan.r = ubyte_to_float(src[0]);
pixel.chan.g = ubyte_to_float(src[1]);
pixel.chan.b = ubyte_to_float(src[2]);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 12;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r32g32b32a32_float {
struct {
float r;
float g;
float b;
float a;
} chan;
};
 
static INLINE void
util_format_r32g32b32a32_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32a32_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = pixel.chan.r; /* r */
dst[1] = pixel.chan.g; /* g */
dst[2] = pixel.chan.b; /* b */
dst[3] = pixel.chan.a; /* a */
src += 16;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32b32a32_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32a32_float pixel;
pixel.chan.r = src[0];
pixel.chan.g = src[1];
pixel.chan.b = src[2];
pixel.chan.a = src[3];
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 16;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r32g32b32a32_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r32g32b32a32_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = pixel.chan.r; /* r */
dst[1] = pixel.chan.g; /* g */
dst[2] = pixel.chan.b; /* b */
dst[3] = pixel.chan.a; /* a */
}
 
static INLINE void
util_format_r32g32b32a32_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32a32_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = float_to_ubyte(pixel.chan.r); /* r */
dst[1] = float_to_ubyte(pixel.chan.g); /* g */
dst[2] = float_to_ubyte(pixel.chan.b); /* b */
dst[3] = float_to_ubyte(pixel.chan.a); /* a */
src += 16;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32b32a32_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32a32_float pixel;
pixel.chan.r = ubyte_to_float(src[0]);
pixel.chan.g = ubyte_to_float(src[1]);
pixel.chan.b = ubyte_to_float(src[2]);
pixel.chan.a = ubyte_to_float(src[3]);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 16;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r32_unorm {
uint32_t value;
struct {
uint32_t r;
} chan;
};
 
static INLINE void
util_format_r32_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t r;
r = value;
dst[0] = (float)(r * (1.0/0xffffffff)); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)(CLAMP(src[0], 0, 1) * (double)0xffffffff);
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r32_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
uint32_t r;
r = value;
dst[0] = (float)(r * (1.0/0xffffffff)); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r32_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t r;
r = value;
dst[0] = (uint8_t)(r >> 24); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 255; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)(((uint64_t)src[0]) * 0xffffffff / 0xff);
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r32g32_unorm {
uint64_t value;
struct {
uint32_t r;
uint32_t g;
} chan;
};
 
static INLINE void
util_format_r32g32_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32_unorm pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)(pixel.chan.r * (1.0/0xffffffff)); /* r */
dst[1] = (float)(pixel.chan.g * (1.0/0xffffffff)); /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32_unorm pixel;
pixel.chan.r = (uint32_t)(CLAMP(src[0], 0, 1) * (double)0xffffffff);
pixel.chan.g = (uint32_t)(CLAMP(src[1], 0, 1) * (double)0xffffffff);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r32g32_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r32g32_unorm pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)(pixel.chan.r * (1.0/0xffffffff)); /* r */
dst[1] = (float)(pixel.chan.g * (1.0/0xffffffff)); /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r32g32_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32_unorm pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (uint8_t)(pixel.chan.r >> 24); /* r */
dst[1] = (uint8_t)(pixel.chan.g >> 24); /* g */
dst[2] = 0; /* b */
dst[3] = 255; /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32_unorm pixel;
pixel.chan.r = (uint32_t)(((uint64_t)src[0]) * 0xffffffff / 0xff);
pixel.chan.g = (uint32_t)(((uint64_t)src[1]) * 0xffffffff / 0xff);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r32g32b32_unorm {
struct {
uint32_t r;
uint32_t g;
uint32_t b;
} chan;
};
 
static INLINE void
util_format_r32g32b32_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32_unorm pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)(pixel.chan.r * (1.0/0xffffffff)); /* r */
dst[1] = (float)(pixel.chan.g * (1.0/0xffffffff)); /* g */
dst[2] = (float)(pixel.chan.b * (1.0/0xffffffff)); /* b */
dst[3] = 1; /* a */
src += 12;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32b32_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32_unorm pixel;
pixel.chan.r = (uint32_t)(CLAMP(src[0], 0, 1) * (double)0xffffffff);
pixel.chan.g = (uint32_t)(CLAMP(src[1], 0, 1) * (double)0xffffffff);
pixel.chan.b = (uint32_t)(CLAMP(src[2], 0, 1) * (double)0xffffffff);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 12;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r32g32b32_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r32g32b32_unorm pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)(pixel.chan.r * (1.0/0xffffffff)); /* r */
dst[1] = (float)(pixel.chan.g * (1.0/0xffffffff)); /* g */
dst[2] = (float)(pixel.chan.b * (1.0/0xffffffff)); /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r32g32b32_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32_unorm pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (uint8_t)(pixel.chan.r >> 24); /* r */
dst[1] = (uint8_t)(pixel.chan.g >> 24); /* g */
dst[2] = (uint8_t)(pixel.chan.b >> 24); /* b */
dst[3] = 255; /* a */
src += 12;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32b32_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32_unorm pixel;
pixel.chan.r = (uint32_t)(((uint64_t)src[0]) * 0xffffffff / 0xff);
pixel.chan.g = (uint32_t)(((uint64_t)src[1]) * 0xffffffff / 0xff);
pixel.chan.b = (uint32_t)(((uint64_t)src[2]) * 0xffffffff / 0xff);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 12;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r32g32b32a32_unorm {
struct {
uint32_t r;
uint32_t g;
uint32_t b;
uint32_t a;
} chan;
};
 
static INLINE void
util_format_r32g32b32a32_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32a32_unorm pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)(pixel.chan.r * (1.0/0xffffffff)); /* r */
dst[1] = (float)(pixel.chan.g * (1.0/0xffffffff)); /* g */
dst[2] = (float)(pixel.chan.b * (1.0/0xffffffff)); /* b */
dst[3] = (float)(pixel.chan.a * (1.0/0xffffffff)); /* a */
src += 16;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32b32a32_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32a32_unorm pixel;
pixel.chan.r = (uint32_t)(CLAMP(src[0], 0, 1) * (double)0xffffffff);
pixel.chan.g = (uint32_t)(CLAMP(src[1], 0, 1) * (double)0xffffffff);
pixel.chan.b = (uint32_t)(CLAMP(src[2], 0, 1) * (double)0xffffffff);
pixel.chan.a = (uint32_t)(CLAMP(src[3], 0, 1) * (double)0xffffffff);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 16;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r32g32b32a32_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r32g32b32a32_unorm pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)(pixel.chan.r * (1.0/0xffffffff)); /* r */
dst[1] = (float)(pixel.chan.g * (1.0/0xffffffff)); /* g */
dst[2] = (float)(pixel.chan.b * (1.0/0xffffffff)); /* b */
dst[3] = (float)(pixel.chan.a * (1.0/0xffffffff)); /* a */
}
 
static INLINE void
util_format_r32g32b32a32_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32a32_unorm pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (uint8_t)(pixel.chan.r >> 24); /* r */
dst[1] = (uint8_t)(pixel.chan.g >> 24); /* g */
dst[2] = (uint8_t)(pixel.chan.b >> 24); /* b */
dst[3] = (uint8_t)(pixel.chan.a >> 24); /* a */
src += 16;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32b32a32_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32a32_unorm pixel;
pixel.chan.r = (uint32_t)(((uint64_t)src[0]) * 0xffffffff / 0xff);
pixel.chan.g = (uint32_t)(((uint64_t)src[1]) * 0xffffffff / 0xff);
pixel.chan.b = (uint32_t)(((uint64_t)src[2]) * 0xffffffff / 0xff);
pixel.chan.a = (uint32_t)(((uint64_t)src[3]) * 0xffffffff / 0xff);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 16;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r32_uscaled {
uint32_t value;
struct {
uint32_t r;
} chan;
};
 
static INLINE void
util_format_r32_uscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t r;
r = value;
dst[0] = (float)r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32_uscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)CLAMP(src[0], 0, 4294967295);
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r32_uscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
uint32_t r;
r = value;
dst[0] = (float)r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r32_uscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t r;
r = value;
dst[0] = (uint8_t)(((uint64_t)MIN2(r, 1)) * 0xff / 0x1); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 255; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32_uscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)(((uint64_t)src[0]) * 0x1 / 0xff);
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r32g32_uscaled {
uint64_t value;
struct {
uint32_t r;
uint32_t g;
} chan;
};
 
static INLINE void
util_format_r32g32_uscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32_uscaled pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)pixel.chan.r; /* r */
dst[1] = (float)pixel.chan.g; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32_uscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32_uscaled pixel;
pixel.chan.r = (uint32_t)CLAMP(src[0], 0, 4294967295);
pixel.chan.g = (uint32_t)CLAMP(src[1], 0, 4294967295);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r32g32_uscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r32g32_uscaled pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)pixel.chan.r; /* r */
dst[1] = (float)pixel.chan.g; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r32g32_uscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32_uscaled pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (uint8_t)(((uint64_t)MIN2(pixel.chan.r, 1)) * 0xff / 0x1); /* r */
dst[1] = (uint8_t)(((uint64_t)MIN2(pixel.chan.g, 1)) * 0xff / 0x1); /* g */
dst[2] = 0; /* b */
dst[3] = 255; /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32_uscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32_uscaled pixel;
pixel.chan.r = (uint32_t)(((uint64_t)src[0]) * 0x1 / 0xff);
pixel.chan.g = (uint32_t)(((uint64_t)src[1]) * 0x1 / 0xff);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r32g32b32_uscaled {
struct {
uint32_t r;
uint32_t g;
uint32_t b;
} chan;
};
 
static INLINE void
util_format_r32g32b32_uscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32_uscaled pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)pixel.chan.r; /* r */
dst[1] = (float)pixel.chan.g; /* g */
dst[2] = (float)pixel.chan.b; /* b */
dst[3] = 1; /* a */
src += 12;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32b32_uscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32_uscaled pixel;
pixel.chan.r = (uint32_t)CLAMP(src[0], 0, 4294967295);
pixel.chan.g = (uint32_t)CLAMP(src[1], 0, 4294967295);
pixel.chan.b = (uint32_t)CLAMP(src[2], 0, 4294967295);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 12;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r32g32b32_uscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r32g32b32_uscaled pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)pixel.chan.r; /* r */
dst[1] = (float)pixel.chan.g; /* g */
dst[2] = (float)pixel.chan.b; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r32g32b32_uscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32_uscaled pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (uint8_t)(((uint64_t)MIN2(pixel.chan.r, 1)) * 0xff / 0x1); /* r */
dst[1] = (uint8_t)(((uint64_t)MIN2(pixel.chan.g, 1)) * 0xff / 0x1); /* g */
dst[2] = (uint8_t)(((uint64_t)MIN2(pixel.chan.b, 1)) * 0xff / 0x1); /* b */
dst[3] = 255; /* a */
src += 12;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32b32_uscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32_uscaled pixel;
pixel.chan.r = (uint32_t)(((uint64_t)src[0]) * 0x1 / 0xff);
pixel.chan.g = (uint32_t)(((uint64_t)src[1]) * 0x1 / 0xff);
pixel.chan.b = (uint32_t)(((uint64_t)src[2]) * 0x1 / 0xff);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 12;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r32g32b32a32_uscaled {
struct {
uint32_t r;
uint32_t g;
uint32_t b;
uint32_t a;
} chan;
};
 
static INLINE void
util_format_r32g32b32a32_uscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32a32_uscaled pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)pixel.chan.r; /* r */
dst[1] = (float)pixel.chan.g; /* g */
dst[2] = (float)pixel.chan.b; /* b */
dst[3] = (float)pixel.chan.a; /* a */
src += 16;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32b32a32_uscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32a32_uscaled pixel;
pixel.chan.r = (uint32_t)CLAMP(src[0], 0, 4294967295);
pixel.chan.g = (uint32_t)CLAMP(src[1], 0, 4294967295);
pixel.chan.b = (uint32_t)CLAMP(src[2], 0, 4294967295);
pixel.chan.a = (uint32_t)CLAMP(src[3], 0, 4294967295);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 16;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r32g32b32a32_uscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r32g32b32a32_uscaled pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)pixel.chan.r; /* r */
dst[1] = (float)pixel.chan.g; /* g */
dst[2] = (float)pixel.chan.b; /* b */
dst[3] = (float)pixel.chan.a; /* a */
}
 
static INLINE void
util_format_r32g32b32a32_uscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32a32_uscaled pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (uint8_t)(((uint64_t)MIN2(pixel.chan.r, 1)) * 0xff / 0x1); /* r */
dst[1] = (uint8_t)(((uint64_t)MIN2(pixel.chan.g, 1)) * 0xff / 0x1); /* g */
dst[2] = (uint8_t)(((uint64_t)MIN2(pixel.chan.b, 1)) * 0xff / 0x1); /* b */
dst[3] = (uint8_t)(((uint64_t)MIN2(pixel.chan.a, 1)) * 0xff / 0x1); /* a */
src += 16;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32b32a32_uscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32a32_uscaled pixel;
pixel.chan.r = (uint32_t)(((uint64_t)src[0]) * 0x1 / 0xff);
pixel.chan.g = (uint32_t)(((uint64_t)src[1]) * 0x1 / 0xff);
pixel.chan.b = (uint32_t)(((uint64_t)src[2]) * 0x1 / 0xff);
pixel.chan.a = (uint32_t)(((uint64_t)src[3]) * 0x1 / 0xff);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 16;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r32_snorm {
uint32_t value;
struct {
int32_t r;
} chan;
};
 
static INLINE void
util_format_r32_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
int32_t r;
r = (int32_t)(value) ;
dst[0] = (float)(r * (1.0/0x7fffffff)); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)((int32_t)(CLAMP(src[0], -1, 1) * (double)0x7fffffff)) ;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r32_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
int32_t r;
r = (int32_t)(value) ;
dst[0] = (float)(r * (1.0/0x7fffffff)); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r32_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
int32_t r;
r = (int32_t)(value) ;
dst[0] = (uint8_t)(MAX2(r, 0) >> 23); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 255; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)((int32_t)(((uint64_t)src[0]) * 0x7fffffff / 0xff)) ;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r32g32_snorm {
uint64_t value;
struct {
int32_t r;
int32_t g;
} chan;
};
 
static INLINE void
util_format_r32g32_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32_snorm pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)(pixel.chan.r * (1.0/0x7fffffff)); /* r */
dst[1] = (float)(pixel.chan.g * (1.0/0x7fffffff)); /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32_snorm pixel;
pixel.chan.r = (int32_t)(CLAMP(src[0], -1, 1) * (double)0x7fffffff);
pixel.chan.g = (int32_t)(CLAMP(src[1], -1, 1) * (double)0x7fffffff);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r32g32_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r32g32_snorm pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)(pixel.chan.r * (1.0/0x7fffffff)); /* r */
dst[1] = (float)(pixel.chan.g * (1.0/0x7fffffff)); /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r32g32_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32_snorm pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (uint8_t)(MAX2(pixel.chan.r, 0) >> 23); /* r */
dst[1] = (uint8_t)(MAX2(pixel.chan.g, 0) >> 23); /* g */
dst[2] = 0; /* b */
dst[3] = 255; /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32_snorm pixel;
pixel.chan.r = (int32_t)(((uint64_t)src[0]) * 0x7fffffff / 0xff);
pixel.chan.g = (int32_t)(((uint64_t)src[1]) * 0x7fffffff / 0xff);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r32g32b32_snorm {
struct {
int32_t r;
int32_t g;
int32_t b;
} chan;
};
 
static INLINE void
util_format_r32g32b32_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32_snorm pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)(pixel.chan.r * (1.0/0x7fffffff)); /* r */
dst[1] = (float)(pixel.chan.g * (1.0/0x7fffffff)); /* g */
dst[2] = (float)(pixel.chan.b * (1.0/0x7fffffff)); /* b */
dst[3] = 1; /* a */
src += 12;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32b32_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32_snorm pixel;
pixel.chan.r = (int32_t)(CLAMP(src[0], -1, 1) * (double)0x7fffffff);
pixel.chan.g = (int32_t)(CLAMP(src[1], -1, 1) * (double)0x7fffffff);
pixel.chan.b = (int32_t)(CLAMP(src[2], -1, 1) * (double)0x7fffffff);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 12;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r32g32b32_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r32g32b32_snorm pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)(pixel.chan.r * (1.0/0x7fffffff)); /* r */
dst[1] = (float)(pixel.chan.g * (1.0/0x7fffffff)); /* g */
dst[2] = (float)(pixel.chan.b * (1.0/0x7fffffff)); /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r32g32b32_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32_snorm pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (uint8_t)(MAX2(pixel.chan.r, 0) >> 23); /* r */
dst[1] = (uint8_t)(MAX2(pixel.chan.g, 0) >> 23); /* g */
dst[2] = (uint8_t)(MAX2(pixel.chan.b, 0) >> 23); /* b */
dst[3] = 255; /* a */
src += 12;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32b32_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32_snorm pixel;
pixel.chan.r = (int32_t)(((uint64_t)src[0]) * 0x7fffffff / 0xff);
pixel.chan.g = (int32_t)(((uint64_t)src[1]) * 0x7fffffff / 0xff);
pixel.chan.b = (int32_t)(((uint64_t)src[2]) * 0x7fffffff / 0xff);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 12;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r32g32b32a32_snorm {
struct {
int32_t r;
int32_t g;
int32_t b;
int32_t a;
} chan;
};
 
static INLINE void
util_format_r32g32b32a32_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32a32_snorm pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)(pixel.chan.r * (1.0/0x7fffffff)); /* r */
dst[1] = (float)(pixel.chan.g * (1.0/0x7fffffff)); /* g */
dst[2] = (float)(pixel.chan.b * (1.0/0x7fffffff)); /* b */
dst[3] = (float)(pixel.chan.a * (1.0/0x7fffffff)); /* a */
src += 16;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32b32a32_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32a32_snorm pixel;
pixel.chan.r = (int32_t)(CLAMP(src[0], -1, 1) * (double)0x7fffffff);
pixel.chan.g = (int32_t)(CLAMP(src[1], -1, 1) * (double)0x7fffffff);
pixel.chan.b = (int32_t)(CLAMP(src[2], -1, 1) * (double)0x7fffffff);
pixel.chan.a = (int32_t)(CLAMP(src[3], -1, 1) * (double)0x7fffffff);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 16;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r32g32b32a32_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r32g32b32a32_snorm pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)(pixel.chan.r * (1.0/0x7fffffff)); /* r */
dst[1] = (float)(pixel.chan.g * (1.0/0x7fffffff)); /* g */
dst[2] = (float)(pixel.chan.b * (1.0/0x7fffffff)); /* b */
dst[3] = (float)(pixel.chan.a * (1.0/0x7fffffff)); /* a */
}
 
static INLINE void
util_format_r32g32b32a32_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32a32_snorm pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (uint8_t)(MAX2(pixel.chan.r, 0) >> 23); /* r */
dst[1] = (uint8_t)(MAX2(pixel.chan.g, 0) >> 23); /* g */
dst[2] = (uint8_t)(MAX2(pixel.chan.b, 0) >> 23); /* b */
dst[3] = (uint8_t)(MAX2(pixel.chan.a, 0) >> 23); /* a */
src += 16;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32b32a32_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32a32_snorm pixel;
pixel.chan.r = (int32_t)(((uint64_t)src[0]) * 0x7fffffff / 0xff);
pixel.chan.g = (int32_t)(((uint64_t)src[1]) * 0x7fffffff / 0xff);
pixel.chan.b = (int32_t)(((uint64_t)src[2]) * 0x7fffffff / 0xff);
pixel.chan.a = (int32_t)(((uint64_t)src[3]) * 0x7fffffff / 0xff);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 16;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r32_sscaled {
uint32_t value;
struct {
int32_t r;
} chan;
};
 
static INLINE void
util_format_r32_sscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
int32_t r;
r = (int32_t)(value) ;
dst[0] = (float)r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32_sscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)((int32_t)CLAMP(src[0], -2147483648, 2147483647)) ;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r32_sscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
int32_t r;
r = (int32_t)(value) ;
dst[0] = (float)r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r32_sscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
int32_t r;
r = (int32_t)(value) ;
dst[0] = (uint8_t)(((uint64_t)CLAMP(r, 0, 1)) * 0xff / 0x1); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 255; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32_sscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)((int32_t)(((uint64_t)src[0]) * 0x1 / 0xff)) ;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r32g32_sscaled {
uint64_t value;
struct {
int32_t r;
int32_t g;
} chan;
};
 
static INLINE void
util_format_r32g32_sscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32_sscaled pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)pixel.chan.r; /* r */
dst[1] = (float)pixel.chan.g; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32_sscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32_sscaled pixel;
pixel.chan.r = (int32_t)CLAMP(src[0], -2147483648, 2147483647);
pixel.chan.g = (int32_t)CLAMP(src[1], -2147483648, 2147483647);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r32g32_sscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r32g32_sscaled pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)pixel.chan.r; /* r */
dst[1] = (float)pixel.chan.g; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r32g32_sscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32_sscaled pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (uint8_t)(((uint64_t)CLAMP(pixel.chan.r, 0, 1)) * 0xff / 0x1); /* r */
dst[1] = (uint8_t)(((uint64_t)CLAMP(pixel.chan.g, 0, 1)) * 0xff / 0x1); /* g */
dst[2] = 0; /* b */
dst[3] = 255; /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32_sscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32_sscaled pixel;
pixel.chan.r = (int32_t)(((uint64_t)src[0]) * 0x1 / 0xff);
pixel.chan.g = (int32_t)(((uint64_t)src[1]) * 0x1 / 0xff);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r32g32b32_sscaled {
struct {
int32_t r;
int32_t g;
int32_t b;
} chan;
};
 
static INLINE void
util_format_r32g32b32_sscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32_sscaled pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)pixel.chan.r; /* r */
dst[1] = (float)pixel.chan.g; /* g */
dst[2] = (float)pixel.chan.b; /* b */
dst[3] = 1; /* a */
src += 12;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32b32_sscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32_sscaled pixel;
pixel.chan.r = (int32_t)CLAMP(src[0], -2147483648, 2147483647);
pixel.chan.g = (int32_t)CLAMP(src[1], -2147483648, 2147483647);
pixel.chan.b = (int32_t)CLAMP(src[2], -2147483648, 2147483647);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 12;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r32g32b32_sscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r32g32b32_sscaled pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)pixel.chan.r; /* r */
dst[1] = (float)pixel.chan.g; /* g */
dst[2] = (float)pixel.chan.b; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r32g32b32_sscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32_sscaled pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (uint8_t)(((uint64_t)CLAMP(pixel.chan.r, 0, 1)) * 0xff / 0x1); /* r */
dst[1] = (uint8_t)(((uint64_t)CLAMP(pixel.chan.g, 0, 1)) * 0xff / 0x1); /* g */
dst[2] = (uint8_t)(((uint64_t)CLAMP(pixel.chan.b, 0, 1)) * 0xff / 0x1); /* b */
dst[3] = 255; /* a */
src += 12;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32b32_sscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32_sscaled pixel;
pixel.chan.r = (int32_t)(((uint64_t)src[0]) * 0x1 / 0xff);
pixel.chan.g = (int32_t)(((uint64_t)src[1]) * 0x1 / 0xff);
pixel.chan.b = (int32_t)(((uint64_t)src[2]) * 0x1 / 0xff);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 12;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r32g32b32a32_sscaled {
struct {
int32_t r;
int32_t g;
int32_t b;
int32_t a;
} chan;
};
 
static INLINE void
util_format_r32g32b32a32_sscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32a32_sscaled pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)pixel.chan.r; /* r */
dst[1] = (float)pixel.chan.g; /* g */
dst[2] = (float)pixel.chan.b; /* b */
dst[3] = (float)pixel.chan.a; /* a */
src += 16;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32b32a32_sscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32a32_sscaled pixel;
pixel.chan.r = (int32_t)CLAMP(src[0], -2147483648, 2147483647);
pixel.chan.g = (int32_t)CLAMP(src[1], -2147483648, 2147483647);
pixel.chan.b = (int32_t)CLAMP(src[2], -2147483648, 2147483647);
pixel.chan.a = (int32_t)CLAMP(src[3], -2147483648, 2147483647);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 16;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r32g32b32a32_sscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r32g32b32a32_sscaled pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)pixel.chan.r; /* r */
dst[1] = (float)pixel.chan.g; /* g */
dst[2] = (float)pixel.chan.b; /* b */
dst[3] = (float)pixel.chan.a; /* a */
}
 
static INLINE void
util_format_r32g32b32a32_sscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32a32_sscaled pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (uint8_t)(((uint64_t)CLAMP(pixel.chan.r, 0, 1)) * 0xff / 0x1); /* r */
dst[1] = (uint8_t)(((uint64_t)CLAMP(pixel.chan.g, 0, 1)) * 0xff / 0x1); /* g */
dst[2] = (uint8_t)(((uint64_t)CLAMP(pixel.chan.b, 0, 1)) * 0xff / 0x1); /* b */
dst[3] = (uint8_t)(((uint64_t)CLAMP(pixel.chan.a, 0, 1)) * 0xff / 0x1); /* a */
src += 16;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32b32a32_sscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32a32_sscaled pixel;
pixel.chan.r = (int32_t)(((uint64_t)src[0]) * 0x1 / 0xff);
pixel.chan.g = (int32_t)(((uint64_t)src[1]) * 0x1 / 0xff);
pixel.chan.b = (int32_t)(((uint64_t)src[2]) * 0x1 / 0xff);
pixel.chan.a = (int32_t)(((uint64_t)src[3]) * 0x1 / 0xff);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 16;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r16_float {
uint16_t value;
struct {
uint16_t r;
} chan;
};
 
static INLINE void
util_format_r16_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r16_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = util_half_to_float(pixel.chan.r); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r16_float pixel;
pixel.chan.r = util_float_to_half(src[0]);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r16_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r16_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = util_half_to_float(pixel.chan.r); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r16_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r16_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = float_to_ubyte(util_half_to_float(pixel.chan.r)); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 255; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r16_float pixel;
pixel.chan.r = util_float_to_half((float)(src[0] * (1.0f/0xff)));
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r16g16_float {
uint32_t value;
struct {
uint16_t r;
uint16_t g;
} chan;
};
 
static INLINE void
util_format_r16g16_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = util_half_to_float(pixel.chan.r); /* r */
dst[1] = util_half_to_float(pixel.chan.g); /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16_float pixel;
pixel.chan.r = util_float_to_half(src[0]);
pixel.chan.g = util_float_to_half(src[1]);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r16g16_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r16g16_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = util_half_to_float(pixel.chan.r); /* r */
dst[1] = util_half_to_float(pixel.chan.g); /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r16g16_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = float_to_ubyte(util_half_to_float(pixel.chan.r)); /* r */
dst[1] = float_to_ubyte(util_half_to_float(pixel.chan.g)); /* g */
dst[2] = 0; /* b */
dst[3] = 255; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16_float pixel;
pixel.chan.r = util_float_to_half((float)(src[0] * (1.0f/0xff)));
pixel.chan.g = util_float_to_half((float)(src[1] * (1.0f/0xff)));
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r16g16b16_float {
struct {
uint16_t r;
uint16_t g;
uint16_t b;
} chan;
};
 
static INLINE void
util_format_r16g16b16_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = util_half_to_float(pixel.chan.r); /* r */
dst[1] = util_half_to_float(pixel.chan.g); /* g */
dst[2] = util_half_to_float(pixel.chan.b); /* b */
dst[3] = 1; /* a */
src += 6;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16b16_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16_float pixel;
pixel.chan.r = util_float_to_half(src[0]);
pixel.chan.g = util_float_to_half(src[1]);
pixel.chan.b = util_float_to_half(src[2]);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 6;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r16g16b16_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r16g16b16_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = util_half_to_float(pixel.chan.r); /* r */
dst[1] = util_half_to_float(pixel.chan.g); /* g */
dst[2] = util_half_to_float(pixel.chan.b); /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r16g16b16_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = float_to_ubyte(util_half_to_float(pixel.chan.r)); /* r */
dst[1] = float_to_ubyte(util_half_to_float(pixel.chan.g)); /* g */
dst[2] = float_to_ubyte(util_half_to_float(pixel.chan.b)); /* b */
dst[3] = 255; /* a */
src += 6;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16b16_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16_float pixel;
pixel.chan.r = util_float_to_half((float)(src[0] * (1.0f/0xff)));
pixel.chan.g = util_float_to_half((float)(src[1] * (1.0f/0xff)));
pixel.chan.b = util_float_to_half((float)(src[2] * (1.0f/0xff)));
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 6;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r16g16b16a16_float {
uint64_t value;
struct {
uint16_t r;
uint16_t g;
uint16_t b;
uint16_t a;
} chan;
};
 
static INLINE void
util_format_r16g16b16a16_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16a16_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = util_half_to_float(pixel.chan.r); /* r */
dst[1] = util_half_to_float(pixel.chan.g); /* g */
dst[2] = util_half_to_float(pixel.chan.b); /* b */
dst[3] = util_half_to_float(pixel.chan.a); /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16b16a16_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16a16_float pixel;
pixel.chan.r = util_float_to_half(src[0]);
pixel.chan.g = util_float_to_half(src[1]);
pixel.chan.b = util_float_to_half(src[2]);
pixel.chan.a = util_float_to_half(src[3]);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r16g16b16a16_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r16g16b16a16_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = util_half_to_float(pixel.chan.r); /* r */
dst[1] = util_half_to_float(pixel.chan.g); /* g */
dst[2] = util_half_to_float(pixel.chan.b); /* b */
dst[3] = util_half_to_float(pixel.chan.a); /* a */
}
 
static INLINE void
util_format_r16g16b16a16_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16a16_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = float_to_ubyte(util_half_to_float(pixel.chan.r)); /* r */
dst[1] = float_to_ubyte(util_half_to_float(pixel.chan.g)); /* g */
dst[2] = float_to_ubyte(util_half_to_float(pixel.chan.b)); /* b */
dst[3] = float_to_ubyte(util_half_to_float(pixel.chan.a)); /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16b16a16_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16a16_float pixel;
pixel.chan.r = util_float_to_half((float)(src[0] * (1.0f/0xff)));
pixel.chan.g = util_float_to_half((float)(src[1] * (1.0f/0xff)));
pixel.chan.b = util_float_to_half((float)(src[2] * (1.0f/0xff)));
pixel.chan.a = util_float_to_half((float)(src[3] * (1.0f/0xff)));
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r16_unorm {
uint16_t value;
struct {
uint16_t r;
} chan;
};
 
static INLINE void
util_format_r16_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
uint16_t r;
r = value;
dst[0] = (float)(r * (1.0f/0xffff)); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)util_iround(CLAMP(src[0], 0, 1) * 0xffff);
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r16_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint16_t value = *(const uint16_t *)src;
uint16_t r;
r = value;
dst[0] = (float)(r * (1.0f/0xffff)); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r16_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
uint16_t r;
r = value;
dst[0] = (uint8_t)(r >> 8); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 255; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)(((uint32_t)src[0]) * 0xffff / 0xff);
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r16g16_unorm {
uint32_t value;
struct {
uint16_t r;
uint16_t g;
} chan;
};
 
static INLINE void
util_format_r16g16_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t r;
uint32_t g;
r = (value) & 0xffff;
g = value >> 16;
dst[0] = (float)(r * (1.0f/0xffff)); /* r */
dst[1] = (float)(g * (1.0f/0xffff)); /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= ((uint16_t)util_iround(CLAMP(src[0], 0, 1) * 0xffff)) & 0xffff;
value |= ((uint16_t)util_iround(CLAMP(src[1], 0, 1) * 0xffff)) << 16;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r16g16_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
uint32_t r;
uint32_t g;
r = (value) & 0xffff;
g = value >> 16;
dst[0] = (float)(r * (1.0f/0xffff)); /* r */
dst[1] = (float)(g * (1.0f/0xffff)); /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r16g16_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t r;
uint32_t g;
r = (value) & 0xffff;
g = value >> 16;
dst[0] = (uint8_t)(r >> 8); /* r */
dst[1] = (uint8_t)(g >> 8); /* g */
dst[2] = 0; /* b */
dst[3] = 255; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= ((uint16_t)(((uint32_t)src[0]) * 0xffff / 0xff)) & 0xffff;
value |= ((uint16_t)(((uint32_t)src[1]) * 0xffff / 0xff)) << 16;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r16g16b16_unorm {
struct {
uint16_t r;
uint16_t g;
uint16_t b;
} chan;
};
 
static INLINE void
util_format_r16g16b16_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16_unorm pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)(pixel.chan.r * (1.0f/0xffff)); /* r */
dst[1] = (float)(pixel.chan.g * (1.0f/0xffff)); /* g */
dst[2] = (float)(pixel.chan.b * (1.0f/0xffff)); /* b */
dst[3] = 1; /* a */
src += 6;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16b16_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16_unorm pixel;
pixel.chan.r = (uint16_t)util_iround(CLAMP(src[0], 0, 1) * 0xffff);
pixel.chan.g = (uint16_t)util_iround(CLAMP(src[1], 0, 1) * 0xffff);
pixel.chan.b = (uint16_t)util_iround(CLAMP(src[2], 0, 1) * 0xffff);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 6;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r16g16b16_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r16g16b16_unorm pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)(pixel.chan.r * (1.0f/0xffff)); /* r */
dst[1] = (float)(pixel.chan.g * (1.0f/0xffff)); /* g */
dst[2] = (float)(pixel.chan.b * (1.0f/0xffff)); /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r16g16b16_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16_unorm pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (uint8_t)(pixel.chan.r >> 8); /* r */
dst[1] = (uint8_t)(pixel.chan.g >> 8); /* g */
dst[2] = (uint8_t)(pixel.chan.b >> 8); /* b */
dst[3] = 255; /* a */
src += 6;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16b16_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16_unorm pixel;
pixel.chan.r = (uint16_t)(((uint32_t)src[0]) * 0xffff / 0xff);
pixel.chan.g = (uint16_t)(((uint32_t)src[1]) * 0xffff / 0xff);
pixel.chan.b = (uint16_t)(((uint32_t)src[2]) * 0xffff / 0xff);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 6;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r16g16b16a16_unorm {
uint64_t value;
struct {
uint16_t r;
uint16_t g;
uint16_t b;
uint16_t a;
} chan;
};
 
static INLINE void
util_format_r16g16b16a16_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16a16_unorm pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)(pixel.chan.r * (1.0f/0xffff)); /* r */
dst[1] = (float)(pixel.chan.g * (1.0f/0xffff)); /* g */
dst[2] = (float)(pixel.chan.b * (1.0f/0xffff)); /* b */
dst[3] = (float)(pixel.chan.a * (1.0f/0xffff)); /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16b16a16_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16a16_unorm pixel;
pixel.chan.r = (uint16_t)util_iround(CLAMP(src[0], 0, 1) * 0xffff);
pixel.chan.g = (uint16_t)util_iround(CLAMP(src[1], 0, 1) * 0xffff);
pixel.chan.b = (uint16_t)util_iround(CLAMP(src[2], 0, 1) * 0xffff);
pixel.chan.a = (uint16_t)util_iround(CLAMP(src[3], 0, 1) * 0xffff);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r16g16b16a16_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r16g16b16a16_unorm pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)(pixel.chan.r * (1.0f/0xffff)); /* r */
dst[1] = (float)(pixel.chan.g * (1.0f/0xffff)); /* g */
dst[2] = (float)(pixel.chan.b * (1.0f/0xffff)); /* b */
dst[3] = (float)(pixel.chan.a * (1.0f/0xffff)); /* a */
}
 
static INLINE void
util_format_r16g16b16a16_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16a16_unorm pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (uint8_t)(pixel.chan.r >> 8); /* r */
dst[1] = (uint8_t)(pixel.chan.g >> 8); /* g */
dst[2] = (uint8_t)(pixel.chan.b >> 8); /* b */
dst[3] = (uint8_t)(pixel.chan.a >> 8); /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16b16a16_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16a16_unorm pixel;
pixel.chan.r = (uint16_t)(((uint32_t)src[0]) * 0xffff / 0xff);
pixel.chan.g = (uint16_t)(((uint32_t)src[1]) * 0xffff / 0xff);
pixel.chan.b = (uint16_t)(((uint32_t)src[2]) * 0xffff / 0xff);
pixel.chan.a = (uint16_t)(((uint32_t)src[3]) * 0xffff / 0xff);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r16_uscaled {
uint16_t value;
struct {
uint16_t r;
} chan;
};
 
static INLINE void
util_format_r16_uscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
uint16_t r;
r = value;
dst[0] = (float)r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16_uscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)CLAMP(src[0], 0, 65535);
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r16_uscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint16_t value = *(const uint16_t *)src;
uint16_t r;
r = value;
dst[0] = (float)r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r16_uscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
uint16_t r;
r = value;
dst[0] = (uint8_t)(((uint32_t)MIN2(r, 1)) * 0xff / 0x1); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 255; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16_uscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)(((uint32_t)src[0]) * 0x1 / 0xff);
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r16g16_uscaled {
uint32_t value;
struct {
uint16_t r;
uint16_t g;
} chan;
};
 
static INLINE void
util_format_r16g16_uscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t r;
uint32_t g;
r = (value) & 0xffff;
g = value >> 16;
dst[0] = (float)r; /* r */
dst[1] = (float)g; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16_uscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= ((uint16_t)CLAMP(src[0], 0, 65535)) & 0xffff;
value |= ((uint16_t)CLAMP(src[1], 0, 65535)) << 16;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r16g16_uscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
uint32_t r;
uint32_t g;
r = (value) & 0xffff;
g = value >> 16;
dst[0] = (float)r; /* r */
dst[1] = (float)g; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r16g16_uscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t r;
uint32_t g;
r = (value) & 0xffff;
g = value >> 16;
dst[0] = (uint8_t)(((uint32_t)MIN2(r, 1)) * 0xff / 0x1); /* r */
dst[1] = (uint8_t)(((uint32_t)MIN2(g, 1)) * 0xff / 0x1); /* g */
dst[2] = 0; /* b */
dst[3] = 255; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16_uscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= ((uint16_t)(((uint32_t)src[0]) * 0x1 / 0xff)) & 0xffff;
value |= ((uint16_t)(((uint32_t)src[1]) * 0x1 / 0xff)) << 16;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r16g16b16_uscaled {
struct {
uint16_t r;
uint16_t g;
uint16_t b;
} chan;
};
 
static INLINE void
util_format_r16g16b16_uscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16_uscaled pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)pixel.chan.r; /* r */
dst[1] = (float)pixel.chan.g; /* g */
dst[2] = (float)pixel.chan.b; /* b */
dst[3] = 1; /* a */
src += 6;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16b16_uscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16_uscaled pixel;
pixel.chan.r = (uint16_t)CLAMP(src[0], 0, 65535);
pixel.chan.g = (uint16_t)CLAMP(src[1], 0, 65535);
pixel.chan.b = (uint16_t)CLAMP(src[2], 0, 65535);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 6;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r16g16b16_uscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r16g16b16_uscaled pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)pixel.chan.r; /* r */
dst[1] = (float)pixel.chan.g; /* g */
dst[2] = (float)pixel.chan.b; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r16g16b16_uscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16_uscaled pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (uint8_t)(((uint32_t)MIN2(pixel.chan.r, 1)) * 0xff / 0x1); /* r */
dst[1] = (uint8_t)(((uint32_t)MIN2(pixel.chan.g, 1)) * 0xff / 0x1); /* g */
dst[2] = (uint8_t)(((uint32_t)MIN2(pixel.chan.b, 1)) * 0xff / 0x1); /* b */
dst[3] = 255; /* a */
src += 6;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16b16_uscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16_uscaled pixel;
pixel.chan.r = (uint16_t)(((uint32_t)src[0]) * 0x1 / 0xff);
pixel.chan.g = (uint16_t)(((uint32_t)src[1]) * 0x1 / 0xff);
pixel.chan.b = (uint16_t)(((uint32_t)src[2]) * 0x1 / 0xff);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 6;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r16g16b16a16_uscaled {
uint64_t value;
struct {
uint16_t r;
uint16_t g;
uint16_t b;
uint16_t a;
} chan;
};
 
static INLINE void
util_format_r16g16b16a16_uscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16a16_uscaled pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)pixel.chan.r; /* r */
dst[1] = (float)pixel.chan.g; /* g */
dst[2] = (float)pixel.chan.b; /* b */
dst[3] = (float)pixel.chan.a; /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16b16a16_uscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16a16_uscaled pixel;
pixel.chan.r = (uint16_t)CLAMP(src[0], 0, 65535);
pixel.chan.g = (uint16_t)CLAMP(src[1], 0, 65535);
pixel.chan.b = (uint16_t)CLAMP(src[2], 0, 65535);
pixel.chan.a = (uint16_t)CLAMP(src[3], 0, 65535);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r16g16b16a16_uscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r16g16b16a16_uscaled pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)pixel.chan.r; /* r */
dst[1] = (float)pixel.chan.g; /* g */
dst[2] = (float)pixel.chan.b; /* b */
dst[3] = (float)pixel.chan.a; /* a */
}
 
static INLINE void
util_format_r16g16b16a16_uscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16a16_uscaled pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (uint8_t)(((uint32_t)MIN2(pixel.chan.r, 1)) * 0xff / 0x1); /* r */
dst[1] = (uint8_t)(((uint32_t)MIN2(pixel.chan.g, 1)) * 0xff / 0x1); /* g */
dst[2] = (uint8_t)(((uint32_t)MIN2(pixel.chan.b, 1)) * 0xff / 0x1); /* b */
dst[3] = (uint8_t)(((uint32_t)MIN2(pixel.chan.a, 1)) * 0xff / 0x1); /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16b16a16_uscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16a16_uscaled pixel;
pixel.chan.r = (uint16_t)(((uint32_t)src[0]) * 0x1 / 0xff);
pixel.chan.g = (uint16_t)(((uint32_t)src[1]) * 0x1 / 0xff);
pixel.chan.b = (uint16_t)(((uint32_t)src[2]) * 0x1 / 0xff);
pixel.chan.a = (uint16_t)(((uint32_t)src[3]) * 0x1 / 0xff);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r16_snorm {
uint16_t value;
struct {
int16_t r;
} chan;
};
 
static INLINE void
util_format_r16_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
int16_t r;
r = (int16_t)(value) ;
dst[0] = (float)(r * (1.0f/0x7fff)); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)((int16_t)util_iround(CLAMP(src[0], -1, 1) * 0x7fff)) ;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r16_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint16_t value = *(const uint16_t *)src;
int16_t r;
r = (int16_t)(value) ;
dst[0] = (float)(r * (1.0f/0x7fff)); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r16_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
int16_t r;
r = (int16_t)(value) ;
dst[0] = (uint8_t)(MAX2(r, 0) >> 7); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 255; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)((int16_t)(((uint32_t)src[0]) * 0x7fff / 0xff)) ;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r16g16_snorm {
uint32_t value;
struct {
int16_t r;
int16_t g;
} chan;
};
 
static INLINE void
util_format_r16g16_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
int32_t r;
int32_t g;
r = ((int32_t)(value << 16) ) >> 16;
g = ((int32_t)(value) ) >> 16;
dst[0] = (float)(r * (1.0f/0x7fff)); /* r */
dst[1] = (float)(g * (1.0f/0x7fff)); /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)(((int16_t)util_iround(CLAMP(src[0], -1, 1) * 0x7fff)) & 0xffff) ;
value |= (uint32_t)(((int16_t)util_iround(CLAMP(src[1], -1, 1) * 0x7fff)) << 16) ;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r16g16_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
int32_t r;
int32_t g;
r = ((int32_t)(value << 16) ) >> 16;
g = ((int32_t)(value) ) >> 16;
dst[0] = (float)(r * (1.0f/0x7fff)); /* r */
dst[1] = (float)(g * (1.0f/0x7fff)); /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r16g16_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
int32_t r;
int32_t g;
r = ((int32_t)(value << 16) ) >> 16;
g = ((int32_t)(value) ) >> 16;
dst[0] = (uint8_t)(MAX2(r, 0) >> 7); /* r */
dst[1] = (uint8_t)(MAX2(g, 0) >> 7); /* g */
dst[2] = 0; /* b */
dst[3] = 255; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)(((int16_t)(((uint32_t)src[0]) * 0x7fff / 0xff)) & 0xffff) ;
value |= (uint32_t)(((int16_t)(((uint32_t)src[1]) * 0x7fff / 0xff)) << 16) ;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r16g16b16_snorm {
struct {
int16_t r;
int16_t g;
int16_t b;
} chan;
};
 
static INLINE void
util_format_r16g16b16_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16_snorm pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)(pixel.chan.r * (1.0f/0x7fff)); /* r */
dst[1] = (float)(pixel.chan.g * (1.0f/0x7fff)); /* g */
dst[2] = (float)(pixel.chan.b * (1.0f/0x7fff)); /* b */
dst[3] = 1; /* a */
src += 6;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16b16_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16_snorm pixel;
pixel.chan.r = (int16_t)util_iround(CLAMP(src[0], -1, 1) * 0x7fff);
pixel.chan.g = (int16_t)util_iround(CLAMP(src[1], -1, 1) * 0x7fff);
pixel.chan.b = (int16_t)util_iround(CLAMP(src[2], -1, 1) * 0x7fff);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 6;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r16g16b16_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r16g16b16_snorm pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)(pixel.chan.r * (1.0f/0x7fff)); /* r */
dst[1] = (float)(pixel.chan.g * (1.0f/0x7fff)); /* g */
dst[2] = (float)(pixel.chan.b * (1.0f/0x7fff)); /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r16g16b16_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16_snorm pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (uint8_t)(MAX2(pixel.chan.r, 0) >> 7); /* r */
dst[1] = (uint8_t)(MAX2(pixel.chan.g, 0) >> 7); /* g */
dst[2] = (uint8_t)(MAX2(pixel.chan.b, 0) >> 7); /* b */
dst[3] = 255; /* a */
src += 6;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16b16_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16_snorm pixel;
pixel.chan.r = (int16_t)(((uint32_t)src[0]) * 0x7fff / 0xff);
pixel.chan.g = (int16_t)(((uint32_t)src[1]) * 0x7fff / 0xff);
pixel.chan.b = (int16_t)(((uint32_t)src[2]) * 0x7fff / 0xff);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 6;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r16g16b16a16_snorm {
uint64_t value;
struct {
int16_t r;
int16_t g;
int16_t b;
int16_t a;
} chan;
};
 
static INLINE void
util_format_r16g16b16a16_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16a16_snorm pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)(pixel.chan.r * (1.0f/0x7fff)); /* r */
dst[1] = (float)(pixel.chan.g * (1.0f/0x7fff)); /* g */
dst[2] = (float)(pixel.chan.b * (1.0f/0x7fff)); /* b */
dst[3] = (float)(pixel.chan.a * (1.0f/0x7fff)); /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16b16a16_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16a16_snorm pixel;
pixel.chan.r = (int16_t)util_iround(CLAMP(src[0], -1, 1) * 0x7fff);
pixel.chan.g = (int16_t)util_iround(CLAMP(src[1], -1, 1) * 0x7fff);
pixel.chan.b = (int16_t)util_iround(CLAMP(src[2], -1, 1) * 0x7fff);
pixel.chan.a = (int16_t)util_iround(CLAMP(src[3], -1, 1) * 0x7fff);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r16g16b16a16_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r16g16b16a16_snorm pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)(pixel.chan.r * (1.0f/0x7fff)); /* r */
dst[1] = (float)(pixel.chan.g * (1.0f/0x7fff)); /* g */
dst[2] = (float)(pixel.chan.b * (1.0f/0x7fff)); /* b */
dst[3] = (float)(pixel.chan.a * (1.0f/0x7fff)); /* a */
}
 
static INLINE void
util_format_r16g16b16a16_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16a16_snorm pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (uint8_t)(MAX2(pixel.chan.r, 0) >> 7); /* r */
dst[1] = (uint8_t)(MAX2(pixel.chan.g, 0) >> 7); /* g */
dst[2] = (uint8_t)(MAX2(pixel.chan.b, 0) >> 7); /* b */
dst[3] = (uint8_t)(MAX2(pixel.chan.a, 0) >> 7); /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16b16a16_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16a16_snorm pixel;
pixel.chan.r = (int16_t)(((uint32_t)src[0]) * 0x7fff / 0xff);
pixel.chan.g = (int16_t)(((uint32_t)src[1]) * 0x7fff / 0xff);
pixel.chan.b = (int16_t)(((uint32_t)src[2]) * 0x7fff / 0xff);
pixel.chan.a = (int16_t)(((uint32_t)src[3]) * 0x7fff / 0xff);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r16_sscaled {
uint16_t value;
struct {
int16_t r;
} chan;
};
 
static INLINE void
util_format_r16_sscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
int16_t r;
r = (int16_t)(value) ;
dst[0] = (float)r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16_sscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)((int16_t)CLAMP(src[0], -32768, 32767)) ;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r16_sscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint16_t value = *(const uint16_t *)src;
int16_t r;
r = (int16_t)(value) ;
dst[0] = (float)r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r16_sscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
int16_t r;
r = (int16_t)(value) ;
dst[0] = (uint8_t)(((uint32_t)CLAMP(r, 0, 1)) * 0xff / 0x1); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 255; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16_sscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)((int16_t)(((uint32_t)src[0]) * 0x1 / 0xff)) ;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r16g16_sscaled {
uint32_t value;
struct {
int16_t r;
int16_t g;
} chan;
};
 
static INLINE void
util_format_r16g16_sscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
int32_t r;
int32_t g;
r = ((int32_t)(value << 16) ) >> 16;
g = ((int32_t)(value) ) >> 16;
dst[0] = (float)r; /* r */
dst[1] = (float)g; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16_sscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)(((int16_t)CLAMP(src[0], -32768, 32767)) & 0xffff) ;
value |= (uint32_t)(((int16_t)CLAMP(src[1], -32768, 32767)) << 16) ;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r16g16_sscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
int32_t r;
int32_t g;
r = ((int32_t)(value << 16) ) >> 16;
g = ((int32_t)(value) ) >> 16;
dst[0] = (float)r; /* r */
dst[1] = (float)g; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r16g16_sscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
int32_t r;
int32_t g;
r = ((int32_t)(value << 16) ) >> 16;
g = ((int32_t)(value) ) >> 16;
dst[0] = (uint8_t)(((uint32_t)CLAMP(r, 0, 1)) * 0xff / 0x1); /* r */
dst[1] = (uint8_t)(((uint32_t)CLAMP(g, 0, 1)) * 0xff / 0x1); /* g */
dst[2] = 0; /* b */
dst[3] = 255; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16_sscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)(((int16_t)(((uint32_t)src[0]) * 0x1 / 0xff)) & 0xffff) ;
value |= (uint32_t)(((int16_t)(((uint32_t)src[1]) * 0x1 / 0xff)) << 16) ;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r16g16b16_sscaled {
struct {
int16_t r;
int16_t g;
int16_t b;
} chan;
};
 
static INLINE void
util_format_r16g16b16_sscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16_sscaled pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)pixel.chan.r; /* r */
dst[1] = (float)pixel.chan.g; /* g */
dst[2] = (float)pixel.chan.b; /* b */
dst[3] = 1; /* a */
src += 6;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16b16_sscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16_sscaled pixel;
pixel.chan.r = (int16_t)CLAMP(src[0], -32768, 32767);
pixel.chan.g = (int16_t)CLAMP(src[1], -32768, 32767);
pixel.chan.b = (int16_t)CLAMP(src[2], -32768, 32767);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 6;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r16g16b16_sscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r16g16b16_sscaled pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)pixel.chan.r; /* r */
dst[1] = (float)pixel.chan.g; /* g */
dst[2] = (float)pixel.chan.b; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r16g16b16_sscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16_sscaled pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (uint8_t)(((uint32_t)CLAMP(pixel.chan.r, 0, 1)) * 0xff / 0x1); /* r */
dst[1] = (uint8_t)(((uint32_t)CLAMP(pixel.chan.g, 0, 1)) * 0xff / 0x1); /* g */
dst[2] = (uint8_t)(((uint32_t)CLAMP(pixel.chan.b, 0, 1)) * 0xff / 0x1); /* b */
dst[3] = 255; /* a */
src += 6;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16b16_sscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16_sscaled pixel;
pixel.chan.r = (int16_t)(((uint32_t)src[0]) * 0x1 / 0xff);
pixel.chan.g = (int16_t)(((uint32_t)src[1]) * 0x1 / 0xff);
pixel.chan.b = (int16_t)(((uint32_t)src[2]) * 0x1 / 0xff);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 6;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r16g16b16a16_sscaled {
uint64_t value;
struct {
int16_t r;
int16_t g;
int16_t b;
int16_t a;
} chan;
};
 
static INLINE void
util_format_r16g16b16a16_sscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16a16_sscaled pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)pixel.chan.r; /* r */
dst[1] = (float)pixel.chan.g; /* g */
dst[2] = (float)pixel.chan.b; /* b */
dst[3] = (float)pixel.chan.a; /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16b16a16_sscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16a16_sscaled pixel;
pixel.chan.r = (int16_t)CLAMP(src[0], -32768, 32767);
pixel.chan.g = (int16_t)CLAMP(src[1], -32768, 32767);
pixel.chan.b = (int16_t)CLAMP(src[2], -32768, 32767);
pixel.chan.a = (int16_t)CLAMP(src[3], -32768, 32767);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r16g16b16a16_sscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r16g16b16a16_sscaled pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)pixel.chan.r; /* r */
dst[1] = (float)pixel.chan.g; /* g */
dst[2] = (float)pixel.chan.b; /* b */
dst[3] = (float)pixel.chan.a; /* a */
}
 
static INLINE void
util_format_r16g16b16a16_sscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16a16_sscaled pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (uint8_t)(((uint32_t)CLAMP(pixel.chan.r, 0, 1)) * 0xff / 0x1); /* r */
dst[1] = (uint8_t)(((uint32_t)CLAMP(pixel.chan.g, 0, 1)) * 0xff / 0x1); /* g */
dst[2] = (uint8_t)(((uint32_t)CLAMP(pixel.chan.b, 0, 1)) * 0xff / 0x1); /* b */
dst[3] = (uint8_t)(((uint32_t)CLAMP(pixel.chan.a, 0, 1)) * 0xff / 0x1); /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16b16a16_sscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16a16_sscaled pixel;
pixel.chan.r = (int16_t)(((uint32_t)src[0]) * 0x1 / 0xff);
pixel.chan.g = (int16_t)(((uint32_t)src[1]) * 0x1 / 0xff);
pixel.chan.b = (int16_t)(((uint32_t)src[2]) * 0x1 / 0xff);
pixel.chan.a = (int16_t)(((uint32_t)src[3]) * 0x1 / 0xff);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r8_unorm {
uint8_t value;
struct {
uint8_t r;
} chan;
};
 
static INLINE void
util_format_r8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint8_t value = *(const uint8_t *)src;
uint8_t r;
r = value;
dst[0] = ubyte_to_float(r); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 1;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint8_t value = 0;
value |= float_to_ubyte(src[0]);
*(uint8_t *)dst = value;
src += 4;
dst += 1;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r8_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint8_t value = *(const uint8_t *)src;
uint8_t r;
r = value;
dst[0] = ubyte_to_float(r); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint8_t value = *(const uint8_t *)src;
uint8_t r;
r = value;
dst[0] = r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 255; /* a */
src += 1;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint8_t value = 0;
value |= src[0];
*(uint8_t *)dst = value;
src += 4;
dst += 1;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r8g8_unorm {
uint16_t value;
struct {
uint8_t r;
uint8_t g;
} chan;
};
 
static INLINE void
util_format_r8g8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
uint16_t r;
uint16_t g;
r = (value) & 0xff;
g = value >> 8;
dst[0] = ubyte_to_float(r); /* r */
dst[1] = ubyte_to_float(g); /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8g8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (float_to_ubyte(src[0])) & 0xff;
value |= (float_to_ubyte(src[1])) << 8;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r8g8_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint16_t value = *(const uint16_t *)src;
uint16_t r;
uint16_t g;
r = (value) & 0xff;
g = value >> 8;
dst[0] = ubyte_to_float(r); /* r */
dst[1] = ubyte_to_float(g); /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r8g8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
uint16_t r;
uint16_t g;
r = (value) & 0xff;
g = value >> 8;
dst[0] = r; /* r */
dst[1] = g; /* g */
dst[2] = 0; /* b */
dst[3] = 255; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8g8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (src[0]) & 0xff;
value |= (src[1]) << 8;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r8g8b8_unorm {
struct {
uint8_t r;
uint8_t g;
uint8_t b;
} chan;
};
 
static INLINE void
util_format_r8g8b8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r8g8b8_unorm pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = ubyte_to_float(pixel.chan.r); /* r */
dst[1] = ubyte_to_float(pixel.chan.g); /* g */
dst[2] = ubyte_to_float(pixel.chan.b); /* b */
dst[3] = 1; /* a */
src += 3;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8g8b8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r8g8b8_unorm pixel;
pixel.chan.r = float_to_ubyte(src[0]);
pixel.chan.g = float_to_ubyte(src[1]);
pixel.chan.b = float_to_ubyte(src[2]);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 3;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r8g8b8_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r8g8b8_unorm pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = ubyte_to_float(pixel.chan.r); /* r */
dst[1] = ubyte_to_float(pixel.chan.g); /* g */
dst[2] = ubyte_to_float(pixel.chan.b); /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r8g8b8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r8g8b8_unorm pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = pixel.chan.r; /* r */
dst[1] = pixel.chan.g; /* g */
dst[2] = pixel.chan.b; /* b */
dst[3] = 255; /* a */
src += 3;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8g8b8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r8g8b8_unorm pixel;
pixel.chan.r = src[0];
pixel.chan.g = src[1];
pixel.chan.b = src[2];
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 3;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r8g8b8a8_unorm {
uint32_t value;
struct {
uint8_t r;
uint8_t g;
uint8_t b;
uint8_t a;
} chan;
};
 
static INLINE void
util_format_r8g8b8a8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t r;
uint32_t g;
uint32_t b;
uint32_t a;
r = (value) & 0xff;
g = (value >> 8) & 0xff;
b = (value >> 16) & 0xff;
a = value >> 24;
dst[0] = ubyte_to_float(r); /* r */
dst[1] = ubyte_to_float(g); /* g */
dst[2] = ubyte_to_float(b); /* b */
dst[3] = ubyte_to_float(a); /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8g8b8a8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (float_to_ubyte(src[0])) & 0xff;
value |= ((float_to_ubyte(src[1])) & 0xff) << 8;
value |= ((float_to_ubyte(src[2])) & 0xff) << 16;
value |= (float_to_ubyte(src[3])) << 24;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r8g8b8a8_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
uint32_t r;
uint32_t g;
uint32_t b;
uint32_t a;
r = (value) & 0xff;
g = (value >> 8) & 0xff;
b = (value >> 16) & 0xff;
a = value >> 24;
dst[0] = ubyte_to_float(r); /* r */
dst[1] = ubyte_to_float(g); /* g */
dst[2] = ubyte_to_float(b); /* b */
dst[3] = ubyte_to_float(a); /* a */
}
 
static INLINE void
util_format_r8g8b8a8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t r;
uint32_t g;
uint32_t b;
uint32_t a;
r = (value) & 0xff;
g = (value >> 8) & 0xff;
b = (value >> 16) & 0xff;
a = value >> 24;
dst[0] = r; /* r */
dst[1] = g; /* g */
dst[2] = b; /* b */
dst[3] = a; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8g8b8a8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (src[0]) & 0xff;
value |= ((src[1]) & 0xff) << 8;
value |= ((src[2]) & 0xff) << 16;
value |= (src[3]) << 24;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r8_uscaled {
uint8_t value;
struct {
uint8_t r;
} chan;
};
 
static INLINE void
util_format_r8_uscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint8_t value = *(const uint8_t *)src;
uint8_t r;
r = value;
dst[0] = (float)r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 1;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8_uscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint8_t value = 0;
value |= (uint8_t)CLAMP(src[0], 0, 255);
*(uint8_t *)dst = value;
src += 4;
dst += 1;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r8_uscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint8_t value = *(const uint8_t *)src;
uint8_t r;
r = value;
dst[0] = (float)r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r8_uscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint8_t value = *(const uint8_t *)src;
uint8_t r;
r = value;
dst[0] = (uint8_t)(((uint32_t)MIN2(r, 1)) * 0xff / 0x1); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 255; /* a */
src += 1;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8_uscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint8_t value = 0;
value |= (uint8_t)(((uint32_t)src[0]) * 0x1 / 0xff);
*(uint8_t *)dst = value;
src += 4;
dst += 1;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r8g8_uscaled {
uint16_t value;
struct {
uint8_t r;
uint8_t g;
} chan;
};
 
static INLINE void
util_format_r8g8_uscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
uint16_t r;
uint16_t g;
r = (value) & 0xff;
g = value >> 8;
dst[0] = (float)r; /* r */
dst[1] = (float)g; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8g8_uscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= ((uint8_t)CLAMP(src[0], 0, 255)) & 0xff;
value |= ((uint8_t)CLAMP(src[1], 0, 255)) << 8;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r8g8_uscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint16_t value = *(const uint16_t *)src;
uint16_t r;
uint16_t g;
r = (value) & 0xff;
g = value >> 8;
dst[0] = (float)r; /* r */
dst[1] = (float)g; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r8g8_uscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
uint16_t r;
uint16_t g;
r = (value) & 0xff;
g = value >> 8;
dst[0] = (uint8_t)(((uint32_t)MIN2(r, 1)) * 0xff / 0x1); /* r */
dst[1] = (uint8_t)(((uint32_t)MIN2(g, 1)) * 0xff / 0x1); /* g */
dst[2] = 0; /* b */
dst[3] = 255; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8g8_uscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= ((uint8_t)(((uint32_t)src[0]) * 0x1 / 0xff)) & 0xff;
value |= ((uint8_t)(((uint32_t)src[1]) * 0x1 / 0xff)) << 8;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r8g8b8_uscaled {
struct {
uint8_t r;
uint8_t g;
uint8_t b;
} chan;
};
 
static INLINE void
util_format_r8g8b8_uscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r8g8b8_uscaled pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)pixel.chan.r; /* r */
dst[1] = (float)pixel.chan.g; /* g */
dst[2] = (float)pixel.chan.b; /* b */
dst[3] = 1; /* a */
src += 3;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8g8b8_uscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r8g8b8_uscaled pixel;
pixel.chan.r = (uint8_t)CLAMP(src[0], 0, 255);
pixel.chan.g = (uint8_t)CLAMP(src[1], 0, 255);
pixel.chan.b = (uint8_t)CLAMP(src[2], 0, 255);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 3;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r8g8b8_uscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r8g8b8_uscaled pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)pixel.chan.r; /* r */
dst[1] = (float)pixel.chan.g; /* g */
dst[2] = (float)pixel.chan.b; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r8g8b8_uscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r8g8b8_uscaled pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (uint8_t)(((uint32_t)MIN2(pixel.chan.r, 1)) * 0xff / 0x1); /* r */
dst[1] = (uint8_t)(((uint32_t)MIN2(pixel.chan.g, 1)) * 0xff / 0x1); /* g */
dst[2] = (uint8_t)(((uint32_t)MIN2(pixel.chan.b, 1)) * 0xff / 0x1); /* b */
dst[3] = 255; /* a */
src += 3;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8g8b8_uscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r8g8b8_uscaled pixel;
pixel.chan.r = (uint8_t)(((uint32_t)src[0]) * 0x1 / 0xff);
pixel.chan.g = (uint8_t)(((uint32_t)src[1]) * 0x1 / 0xff);
pixel.chan.b = (uint8_t)(((uint32_t)src[2]) * 0x1 / 0xff);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 3;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r8g8b8a8_uscaled {
uint32_t value;
struct {
uint8_t r;
uint8_t g;
uint8_t b;
uint8_t a;
} chan;
};
 
static INLINE void
util_format_r8g8b8a8_uscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t r;
uint32_t g;
uint32_t b;
uint32_t a;
r = (value) & 0xff;
g = (value >> 8) & 0xff;
b = (value >> 16) & 0xff;
a = value >> 24;
dst[0] = (float)r; /* r */
dst[1] = (float)g; /* g */
dst[2] = (float)b; /* b */
dst[3] = (float)a; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8g8b8a8_uscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= ((uint8_t)CLAMP(src[0], 0, 255)) & 0xff;
value |= (((uint8_t)CLAMP(src[1], 0, 255)) & 0xff) << 8;
value |= (((uint8_t)CLAMP(src[2], 0, 255)) & 0xff) << 16;
value |= ((uint8_t)CLAMP(src[3], 0, 255)) << 24;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r8g8b8a8_uscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
uint32_t r;
uint32_t g;
uint32_t b;
uint32_t a;
r = (value) & 0xff;
g = (value >> 8) & 0xff;
b = (value >> 16) & 0xff;
a = value >> 24;
dst[0] = (float)r; /* r */
dst[1] = (float)g; /* g */
dst[2] = (float)b; /* b */
dst[3] = (float)a; /* a */
}
 
static INLINE void
util_format_r8g8b8a8_uscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t r;
uint32_t g;
uint32_t b;
uint32_t a;
r = (value) & 0xff;
g = (value >> 8) & 0xff;
b = (value >> 16) & 0xff;
a = value >> 24;
dst[0] = (uint8_t)(((uint32_t)MIN2(r, 1)) * 0xff / 0x1); /* r */
dst[1] = (uint8_t)(((uint32_t)MIN2(g, 1)) * 0xff / 0x1); /* g */
dst[2] = (uint8_t)(((uint32_t)MIN2(b, 1)) * 0xff / 0x1); /* b */
dst[3] = (uint8_t)(((uint32_t)MIN2(a, 1)) * 0xff / 0x1); /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8g8b8a8_uscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= ((uint8_t)(((uint32_t)src[0]) * 0x1 / 0xff)) & 0xff;
value |= (((uint8_t)(((uint32_t)src[1]) * 0x1 / 0xff)) & 0xff) << 8;
value |= (((uint8_t)(((uint32_t)src[2]) * 0x1 / 0xff)) & 0xff) << 16;
value |= ((uint8_t)(((uint32_t)src[3]) * 0x1 / 0xff)) << 24;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r8_snorm {
uint8_t value;
struct {
int8_t r;
} chan;
};
 
static INLINE void
util_format_r8_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint8_t value = *(const uint8_t *)src;
int8_t r;
r = (int8_t)(value) ;
dst[0] = (float)(r * (1.0f/0x7f)); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 1;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint8_t value = 0;
value |= (uint8_t)((int8_t)util_iround(CLAMP(src[0], -1, 1) * 0x7f)) ;
*(uint8_t *)dst = value;
src += 4;
dst += 1;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r8_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint8_t value = *(const uint8_t *)src;
int8_t r;
r = (int8_t)(value) ;
dst[0] = (float)(r * (1.0f/0x7f)); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r8_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint8_t value = *(const uint8_t *)src;
int8_t r;
r = (int8_t)(value) ;
dst[0] = (uint8_t)(((uint32_t)MAX2(r, 0)) * 0xff / 0x7f); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 255; /* a */
src += 1;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint8_t value = 0;
value |= (uint8_t)((int8_t)(src[0] >> 1)) ;
*(uint8_t *)dst = value;
src += 4;
dst += 1;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r8g8_snorm {
uint16_t value;
struct {
int8_t r;
int8_t g;
} chan;
};
 
static INLINE void
util_format_r8g8_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
int16_t r;
int16_t g;
r = ((int16_t)(value << 8) ) >> 8;
g = ((int16_t)(value) ) >> 8;
dst[0] = (float)(r * (1.0f/0x7f)); /* r */
dst[1] = (float)(g * (1.0f/0x7f)); /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8g8_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)(((int8_t)util_iround(CLAMP(src[0], -1, 1) * 0x7f)) & 0xff) ;
value |= (uint16_t)(((int8_t)util_iround(CLAMP(src[1], -1, 1) * 0x7f)) << 8) ;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r8g8_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint16_t value = *(const uint16_t *)src;
int16_t r;
int16_t g;
r = ((int16_t)(value << 8) ) >> 8;
g = ((int16_t)(value) ) >> 8;
dst[0] = (float)(r * (1.0f/0x7f)); /* r */
dst[1] = (float)(g * (1.0f/0x7f)); /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r8g8_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
int16_t r;
int16_t g;
r = ((int16_t)(value << 8) ) >> 8;
g = ((int16_t)(value) ) >> 8;
dst[0] = (uint8_t)(((uint32_t)MAX2(r, 0)) * 0xff / 0x7f); /* r */
dst[1] = (uint8_t)(((uint32_t)MAX2(g, 0)) * 0xff / 0x7f); /* g */
dst[2] = 0; /* b */
dst[3] = 255; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8g8_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)(((int8_t)(src[0] >> 1)) & 0xff) ;
value |= (uint16_t)(((int8_t)(src[1] >> 1)) << 8) ;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r8g8b8_snorm {
struct {
int8_t r;
int8_t g;
int8_t b;
} chan;
};
 
static INLINE void
util_format_r8g8b8_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r8g8b8_snorm pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)(pixel.chan.r * (1.0f/0x7f)); /* r */
dst[1] = (float)(pixel.chan.g * (1.0f/0x7f)); /* g */
dst[2] = (float)(pixel.chan.b * (1.0f/0x7f)); /* b */
dst[3] = 1; /* a */
src += 3;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8g8b8_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r8g8b8_snorm pixel;
pixel.chan.r = (int8_t)util_iround(CLAMP(src[0], -1, 1) * 0x7f);
pixel.chan.g = (int8_t)util_iround(CLAMP(src[1], -1, 1) * 0x7f);
pixel.chan.b = (int8_t)util_iround(CLAMP(src[2], -1, 1) * 0x7f);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 3;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r8g8b8_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r8g8b8_snorm pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)(pixel.chan.r * (1.0f/0x7f)); /* r */
dst[1] = (float)(pixel.chan.g * (1.0f/0x7f)); /* g */
dst[2] = (float)(pixel.chan.b * (1.0f/0x7f)); /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r8g8b8_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r8g8b8_snorm pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (uint8_t)(((uint32_t)MAX2(pixel.chan.r, 0)) * 0xff / 0x7f); /* r */
dst[1] = (uint8_t)(((uint32_t)MAX2(pixel.chan.g, 0)) * 0xff / 0x7f); /* g */
dst[2] = (uint8_t)(((uint32_t)MAX2(pixel.chan.b, 0)) * 0xff / 0x7f); /* b */
dst[3] = 255; /* a */
src += 3;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8g8b8_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r8g8b8_snorm pixel;
pixel.chan.r = (int8_t)(src[0] >> 1);
pixel.chan.g = (int8_t)(src[1] >> 1);
pixel.chan.b = (int8_t)(src[2] >> 1);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 3;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r8g8b8a8_snorm {
uint32_t value;
struct {
int8_t r;
int8_t g;
int8_t b;
int8_t a;
} chan;
};
 
static INLINE void
util_format_r8g8b8a8_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
int32_t r;
int32_t g;
int32_t b;
int32_t a;
r = ((int32_t)(value << 24) ) >> 24;
g = ((int32_t)(value << 16) ) >> 24;
b = ((int32_t)(value << 8) ) >> 24;
a = ((int32_t)(value) ) >> 24;
dst[0] = (float)(r * (1.0f/0x7f)); /* r */
dst[1] = (float)(g * (1.0f/0x7f)); /* g */
dst[2] = (float)(b * (1.0f/0x7f)); /* b */
dst[3] = (float)(a * (1.0f/0x7f)); /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8g8b8a8_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)(((int8_t)util_iround(CLAMP(src[0], -1, 1) * 0x7f)) & 0xff) ;
value |= (uint32_t)((((int8_t)util_iround(CLAMP(src[1], -1, 1) * 0x7f)) & 0xff) << 8) ;
value |= (uint32_t)((((int8_t)util_iround(CLAMP(src[2], -1, 1) * 0x7f)) & 0xff) << 16) ;
value |= (uint32_t)(((int8_t)util_iround(CLAMP(src[3], -1, 1) * 0x7f)) << 24) ;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r8g8b8a8_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
int32_t r;
int32_t g;
int32_t b;
int32_t a;
r = ((int32_t)(value << 24) ) >> 24;
g = ((int32_t)(value << 16) ) >> 24;
b = ((int32_t)(value << 8) ) >> 24;
a = ((int32_t)(value) ) >> 24;
dst[0] = (float)(r * (1.0f/0x7f)); /* r */
dst[1] = (float)(g * (1.0f/0x7f)); /* g */
dst[2] = (float)(b * (1.0f/0x7f)); /* b */
dst[3] = (float)(a * (1.0f/0x7f)); /* a */
}
 
static INLINE void
util_format_r8g8b8a8_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
int32_t r;
int32_t g;
int32_t b;
int32_t a;
r = ((int32_t)(value << 24) ) >> 24;
g = ((int32_t)(value << 16) ) >> 24;
b = ((int32_t)(value << 8) ) >> 24;
a = ((int32_t)(value) ) >> 24;
dst[0] = (uint8_t)(((uint32_t)MAX2(r, 0)) * 0xff / 0x7f); /* r */
dst[1] = (uint8_t)(((uint32_t)MAX2(g, 0)) * 0xff / 0x7f); /* g */
dst[2] = (uint8_t)(((uint32_t)MAX2(b, 0)) * 0xff / 0x7f); /* b */
dst[3] = (uint8_t)(((uint32_t)MAX2(a, 0)) * 0xff / 0x7f); /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8g8b8a8_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)(((int8_t)(src[0] >> 1)) & 0xff) ;
value |= (uint32_t)((((int8_t)(src[1] >> 1)) & 0xff) << 8) ;
value |= (uint32_t)((((int8_t)(src[2] >> 1)) & 0xff) << 16) ;
value |= (uint32_t)(((int8_t)(src[3] >> 1)) << 24) ;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r8_sscaled {
uint8_t value;
struct {
int8_t r;
} chan;
};
 
static INLINE void
util_format_r8_sscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint8_t value = *(const uint8_t *)src;
int8_t r;
r = (int8_t)(value) ;
dst[0] = (float)r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 1;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8_sscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint8_t value = 0;
value |= (uint8_t)((int8_t)CLAMP(src[0], -128, 127)) ;
*(uint8_t *)dst = value;
src += 4;
dst += 1;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r8_sscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint8_t value = *(const uint8_t *)src;
int8_t r;
r = (int8_t)(value) ;
dst[0] = (float)r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r8_sscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint8_t value = *(const uint8_t *)src;
int8_t r;
r = (int8_t)(value) ;
dst[0] = (uint8_t)(((uint32_t)CLAMP(r, 0, 1)) * 0xff / 0x1); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 255; /* a */
src += 1;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8_sscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint8_t value = 0;
value |= (uint8_t)((int8_t)(((uint32_t)src[0]) * 0x1 / 0xff)) ;
*(uint8_t *)dst = value;
src += 4;
dst += 1;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r8g8_sscaled {
uint16_t value;
struct {
int8_t r;
int8_t g;
} chan;
};
 
static INLINE void
util_format_r8g8_sscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
int16_t r;
int16_t g;
r = ((int16_t)(value << 8) ) >> 8;
g = ((int16_t)(value) ) >> 8;
dst[0] = (float)r; /* r */
dst[1] = (float)g; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8g8_sscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)(((int8_t)CLAMP(src[0], -128, 127)) & 0xff) ;
value |= (uint16_t)(((int8_t)CLAMP(src[1], -128, 127)) << 8) ;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r8g8_sscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint16_t value = *(const uint16_t *)src;
int16_t r;
int16_t g;
r = ((int16_t)(value << 8) ) >> 8;
g = ((int16_t)(value) ) >> 8;
dst[0] = (float)r; /* r */
dst[1] = (float)g; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r8g8_sscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
int16_t r;
int16_t g;
r = ((int16_t)(value << 8) ) >> 8;
g = ((int16_t)(value) ) >> 8;
dst[0] = (uint8_t)(((uint32_t)CLAMP(r, 0, 1)) * 0xff / 0x1); /* r */
dst[1] = (uint8_t)(((uint32_t)CLAMP(g, 0, 1)) * 0xff / 0x1); /* g */
dst[2] = 0; /* b */
dst[3] = 255; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8g8_sscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)(((int8_t)(((uint32_t)src[0]) * 0x1 / 0xff)) & 0xff) ;
value |= (uint16_t)(((int8_t)(((uint32_t)src[1]) * 0x1 / 0xff)) << 8) ;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r8g8b8_sscaled {
struct {
int8_t r;
int8_t g;
int8_t b;
} chan;
};
 
static INLINE void
util_format_r8g8b8_sscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r8g8b8_sscaled pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)pixel.chan.r; /* r */
dst[1] = (float)pixel.chan.g; /* g */
dst[2] = (float)pixel.chan.b; /* b */
dst[3] = 1; /* a */
src += 3;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8g8b8_sscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r8g8b8_sscaled pixel;
pixel.chan.r = (int8_t)CLAMP(src[0], -128, 127);
pixel.chan.g = (int8_t)CLAMP(src[1], -128, 127);
pixel.chan.b = (int8_t)CLAMP(src[2], -128, 127);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 3;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r8g8b8_sscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r8g8b8_sscaled pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)pixel.chan.r; /* r */
dst[1] = (float)pixel.chan.g; /* g */
dst[2] = (float)pixel.chan.b; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r8g8b8_sscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r8g8b8_sscaled pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (uint8_t)(((uint32_t)CLAMP(pixel.chan.r, 0, 1)) * 0xff / 0x1); /* r */
dst[1] = (uint8_t)(((uint32_t)CLAMP(pixel.chan.g, 0, 1)) * 0xff / 0x1); /* g */
dst[2] = (uint8_t)(((uint32_t)CLAMP(pixel.chan.b, 0, 1)) * 0xff / 0x1); /* b */
dst[3] = 255; /* a */
src += 3;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8g8b8_sscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r8g8b8_sscaled pixel;
pixel.chan.r = (int8_t)(((uint32_t)src[0]) * 0x1 / 0xff);
pixel.chan.g = (int8_t)(((uint32_t)src[1]) * 0x1 / 0xff);
pixel.chan.b = (int8_t)(((uint32_t)src[2]) * 0x1 / 0xff);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 3;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r8g8b8a8_sscaled {
uint32_t value;
struct {
int8_t r;
int8_t g;
int8_t b;
int8_t a;
} chan;
};
 
static INLINE void
util_format_r8g8b8a8_sscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
int32_t r;
int32_t g;
int32_t b;
int32_t a;
r = ((int32_t)(value << 24) ) >> 24;
g = ((int32_t)(value << 16) ) >> 24;
b = ((int32_t)(value << 8) ) >> 24;
a = ((int32_t)(value) ) >> 24;
dst[0] = (float)r; /* r */
dst[1] = (float)g; /* g */
dst[2] = (float)b; /* b */
dst[3] = (float)a; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8g8b8a8_sscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)(((int8_t)CLAMP(src[0], -128, 127)) & 0xff) ;
value |= (uint32_t)((((int8_t)CLAMP(src[1], -128, 127)) & 0xff) << 8) ;
value |= (uint32_t)((((int8_t)CLAMP(src[2], -128, 127)) & 0xff) << 16) ;
value |= (uint32_t)(((int8_t)CLAMP(src[3], -128, 127)) << 24) ;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r8g8b8a8_sscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
int32_t r;
int32_t g;
int32_t b;
int32_t a;
r = ((int32_t)(value << 24) ) >> 24;
g = ((int32_t)(value << 16) ) >> 24;
b = ((int32_t)(value << 8) ) >> 24;
a = ((int32_t)(value) ) >> 24;
dst[0] = (float)r; /* r */
dst[1] = (float)g; /* g */
dst[2] = (float)b; /* b */
dst[3] = (float)a; /* a */
}
 
static INLINE void
util_format_r8g8b8a8_sscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
int32_t r;
int32_t g;
int32_t b;
int32_t a;
r = ((int32_t)(value << 24) ) >> 24;
g = ((int32_t)(value << 16) ) >> 24;
b = ((int32_t)(value << 8) ) >> 24;
a = ((int32_t)(value) ) >> 24;
dst[0] = (uint8_t)(((uint32_t)CLAMP(r, 0, 1)) * 0xff / 0x1); /* r */
dst[1] = (uint8_t)(((uint32_t)CLAMP(g, 0, 1)) * 0xff / 0x1); /* g */
dst[2] = (uint8_t)(((uint32_t)CLAMP(b, 0, 1)) * 0xff / 0x1); /* b */
dst[3] = (uint8_t)(((uint32_t)CLAMP(a, 0, 1)) * 0xff / 0x1); /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8g8b8a8_sscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)(((int8_t)(((uint32_t)src[0]) * 0x1 / 0xff)) & 0xff) ;
value |= (uint32_t)((((int8_t)(((uint32_t)src[1]) * 0x1 / 0xff)) & 0xff) << 8) ;
value |= (uint32_t)((((int8_t)(((uint32_t)src[2]) * 0x1 / 0xff)) & 0xff) << 16) ;
value |= (uint32_t)(((int8_t)(((uint32_t)src[3]) * 0x1 / 0xff)) << 24) ;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r32_fixed {
uint32_t value;
struct {
int32_t r;
} chan;
};
 
static INLINE void
util_format_r32_fixed_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32_fixed pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)(pixel.chan.r * (1.0/0x10000)); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32_fixed_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32_fixed pixel;
pixel.chan.r = (int32_t)(CLAMP(src[0], -65536, 65535) * (double)0x10000);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r32_fixed_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r32_fixed pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)(pixel.chan.r * (1.0/0x10000)); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r32_fixed_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32_fixed pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (uint8_t)util_iround((CLAMP(pixel.chan.r, 0, 65536) * (1.0/0x10000)) * 0xff); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 255; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32_fixed_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32_fixed pixel;
pixel.chan.r = (int32_t)((float)(src[0] * (1.0f/0xff)) * (double)0x10000);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r32g32_fixed {
uint64_t value;
struct {
int32_t r;
int32_t g;
} chan;
};
 
static INLINE void
util_format_r32g32_fixed_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32_fixed pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)(pixel.chan.r * (1.0/0x10000)); /* r */
dst[1] = (float)(pixel.chan.g * (1.0/0x10000)); /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32_fixed_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32_fixed pixel;
pixel.chan.r = (int32_t)(CLAMP(src[0], -65536, 65535) * (double)0x10000);
pixel.chan.g = (int32_t)(CLAMP(src[1], -65536, 65535) * (double)0x10000);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r32g32_fixed_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r32g32_fixed pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)(pixel.chan.r * (1.0/0x10000)); /* r */
dst[1] = (float)(pixel.chan.g * (1.0/0x10000)); /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r32g32_fixed_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32_fixed pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (uint8_t)util_iround((CLAMP(pixel.chan.r, 0, 65536) * (1.0/0x10000)) * 0xff); /* r */
dst[1] = (uint8_t)util_iround((CLAMP(pixel.chan.g, 0, 65536) * (1.0/0x10000)) * 0xff); /* g */
dst[2] = 0; /* b */
dst[3] = 255; /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32_fixed_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32_fixed pixel;
pixel.chan.r = (int32_t)((float)(src[0] * (1.0f/0xff)) * (double)0x10000);
pixel.chan.g = (int32_t)((float)(src[1] * (1.0f/0xff)) * (double)0x10000);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r32g32b32_fixed {
struct {
int32_t r;
int32_t g;
int32_t b;
} chan;
};
 
static INLINE void
util_format_r32g32b32_fixed_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32_fixed pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)(pixel.chan.r * (1.0/0x10000)); /* r */
dst[1] = (float)(pixel.chan.g * (1.0/0x10000)); /* g */
dst[2] = (float)(pixel.chan.b * (1.0/0x10000)); /* b */
dst[3] = 1; /* a */
src += 12;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32b32_fixed_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32_fixed pixel;
pixel.chan.r = (int32_t)(CLAMP(src[0], -65536, 65535) * (double)0x10000);
pixel.chan.g = (int32_t)(CLAMP(src[1], -65536, 65535) * (double)0x10000);
pixel.chan.b = (int32_t)(CLAMP(src[2], -65536, 65535) * (double)0x10000);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 12;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r32g32b32_fixed_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r32g32b32_fixed pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)(pixel.chan.r * (1.0/0x10000)); /* r */
dst[1] = (float)(pixel.chan.g * (1.0/0x10000)); /* g */
dst[2] = (float)(pixel.chan.b * (1.0/0x10000)); /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r32g32b32_fixed_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32_fixed pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (uint8_t)util_iround((CLAMP(pixel.chan.r, 0, 65536) * (1.0/0x10000)) * 0xff); /* r */
dst[1] = (uint8_t)util_iround((CLAMP(pixel.chan.g, 0, 65536) * (1.0/0x10000)) * 0xff); /* g */
dst[2] = (uint8_t)util_iround((CLAMP(pixel.chan.b, 0, 65536) * (1.0/0x10000)) * 0xff); /* b */
dst[3] = 255; /* a */
src += 12;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32b32_fixed_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32_fixed pixel;
pixel.chan.r = (int32_t)((float)(src[0] * (1.0f/0xff)) * (double)0x10000);
pixel.chan.g = (int32_t)((float)(src[1] * (1.0f/0xff)) * (double)0x10000);
pixel.chan.b = (int32_t)((float)(src[2] * (1.0f/0xff)) * (double)0x10000);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 12;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r32g32b32a32_fixed {
struct {
int32_t r;
int32_t g;
int32_t b;
int32_t a;
} chan;
};
 
static INLINE void
util_format_r32g32b32a32_fixed_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32a32_fixed pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)(pixel.chan.r * (1.0/0x10000)); /* r */
dst[1] = (float)(pixel.chan.g * (1.0/0x10000)); /* g */
dst[2] = (float)(pixel.chan.b * (1.0/0x10000)); /* b */
dst[3] = (float)(pixel.chan.a * (1.0/0x10000)); /* a */
src += 16;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32b32a32_fixed_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32a32_fixed pixel;
pixel.chan.r = (int32_t)(CLAMP(src[0], -65536, 65535) * (double)0x10000);
pixel.chan.g = (int32_t)(CLAMP(src[1], -65536, 65535) * (double)0x10000);
pixel.chan.b = (int32_t)(CLAMP(src[2], -65536, 65535) * (double)0x10000);
pixel.chan.a = (int32_t)(CLAMP(src[3], -65536, 65535) * (double)0x10000);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 16;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r32g32b32a32_fixed_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r32g32b32a32_fixed pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)(pixel.chan.r * (1.0/0x10000)); /* r */
dst[1] = (float)(pixel.chan.g * (1.0/0x10000)); /* g */
dst[2] = (float)(pixel.chan.b * (1.0/0x10000)); /* b */
dst[3] = (float)(pixel.chan.a * (1.0/0x10000)); /* a */
}
 
static INLINE void
util_format_r32g32b32a32_fixed_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32a32_fixed pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (uint8_t)util_iround((CLAMP(pixel.chan.r, 0, 65536) * (1.0/0x10000)) * 0xff); /* r */
dst[1] = (uint8_t)util_iround((CLAMP(pixel.chan.g, 0, 65536) * (1.0/0x10000)) * 0xff); /* g */
dst[2] = (uint8_t)util_iround((CLAMP(pixel.chan.b, 0, 65536) * (1.0/0x10000)) * 0xff); /* b */
dst[3] = (uint8_t)util_iround((CLAMP(pixel.chan.a, 0, 65536) * (1.0/0x10000)) * 0xff); /* a */
src += 16;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32b32a32_fixed_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32a32_fixed pixel;
pixel.chan.r = (int32_t)((float)(src[0] * (1.0f/0xff)) * (double)0x10000);
pixel.chan.g = (int32_t)((float)(src[1] * (1.0f/0xff)) * (double)0x10000);
pixel.chan.b = (int32_t)((float)(src[2] * (1.0f/0xff)) * (double)0x10000);
pixel.chan.a = (int32_t)((float)(src[3] * (1.0f/0xff)) * (double)0x10000);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 16;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r10g10b10x2_uscaled {
uint32_t value;
struct {
unsigned r:10;
unsigned g:10;
unsigned b:10;
unsigned x:2;
} chan;
};
 
static INLINE void
util_format_r10g10b10x2_uscaled_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t r;
uint32_t g;
uint32_t b;
r = (value) & 0x3ff;
g = (value >> 10) & 0x3ff;
b = (value >> 20) & 0x3ff;
dst[0] = (float)r; /* r */
dst[1] = (float)g; /* g */
dst[2] = (float)b; /* b */
dst[3] = 1; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r10g10b10x2_uscaled_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= ((uint32_t)CLAMP(src[0], 0, 1023)) & 0x3ff;
value |= (((uint32_t)CLAMP(src[1], 0, 1023)) & 0x3ff) << 10;
value |= (((uint32_t)CLAMP(src[2], 0, 1023)) & 0x3ff) << 20;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r10g10b10x2_uscaled_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
uint32_t r;
uint32_t g;
uint32_t b;
r = (value) & 0x3ff;
g = (value >> 10) & 0x3ff;
b = (value >> 20) & 0x3ff;
dst[0] = (float)r; /* r */
dst[1] = (float)g; /* g */
dst[2] = (float)b; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r10g10b10x2_uscaled_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t r;
uint32_t g;
uint32_t b;
r = (value) & 0x3ff;
g = (value >> 10) & 0x3ff;
b = (value >> 20) & 0x3ff;
dst[0] = (uint8_t)(((uint32_t)MIN2(r, 1)) * 0xff / 0x1); /* r */
dst[1] = (uint8_t)(((uint32_t)MIN2(g, 1)) * 0xff / 0x1); /* g */
dst[2] = (uint8_t)(((uint32_t)MIN2(b, 1)) * 0xff / 0x1); /* b */
dst[3] = 255; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r10g10b10x2_uscaled_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= ((uint32_t)(((uint32_t)src[0]) * 0x1 / 0xff)) & 0x3ff;
value |= (((uint32_t)(((uint32_t)src[1]) * 0x1 / 0xff)) & 0x3ff) << 10;
value |= (((uint32_t)(((uint32_t)src[2]) * 0x1 / 0xff)) & 0x3ff) << 20;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r10g10b10x2_snorm {
uint32_t value;
struct {
int r:10;
int g:10;
int b:10;
unsigned x:2;
} chan;
};
 
static INLINE void
util_format_r10g10b10x2_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
int32_t r;
int32_t g;
int32_t b;
r = ((int32_t)(value << 22) ) >> 22;
g = ((int32_t)(value << 12) ) >> 22;
b = ((int32_t)(value << 2) ) >> 22;
dst[0] = (float)(r * (1.0f/0x1ff)); /* r */
dst[1] = (float)(g * (1.0f/0x1ff)); /* g */
dst[2] = (float)(b * (1.0f/0x1ff)); /* b */
dst[3] = 1; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r10g10b10x2_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)(((uint32_t)util_iround(CLAMP(src[0], -1, 1) * 0x1ff)) & 0x3ff) ;
value |= (uint32_t)((((uint32_t)util_iround(CLAMP(src[1], -1, 1) * 0x1ff)) & 0x3ff) << 10) ;
value |= (uint32_t)((((uint32_t)util_iround(CLAMP(src[2], -1, 1) * 0x1ff)) & 0x3ff) << 20) ;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r10g10b10x2_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
int32_t r;
int32_t g;
int32_t b;
r = ((int32_t)(value << 22) ) >> 22;
g = ((int32_t)(value << 12) ) >> 22;
b = ((int32_t)(value << 2) ) >> 22;
dst[0] = (float)(r * (1.0f/0x1ff)); /* r */
dst[1] = (float)(g * (1.0f/0x1ff)); /* g */
dst[2] = (float)(b * (1.0f/0x1ff)); /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r10g10b10x2_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
int32_t r;
int32_t g;
int32_t b;
r = ((int32_t)(value << 22) ) >> 22;
g = ((int32_t)(value << 12) ) >> 22;
b = ((int32_t)(value << 2) ) >> 22;
dst[0] = (uint8_t)(MAX2(r, 0) >> 1); /* r */
dst[1] = (uint8_t)(MAX2(g, 0) >> 1); /* g */
dst[2] = (uint8_t)(MAX2(b, 0) >> 1); /* b */
dst[3] = 255; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r10g10b10x2_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)(((uint32_t)(((uint32_t)src[0]) * 0x1ff / 0xff)) & 0x3ff) ;
value |= (uint32_t)((((uint32_t)(((uint32_t)src[1]) * 0x1ff / 0xff)) & 0x3ff) << 10) ;
value |= (uint32_t)((((uint32_t)(((uint32_t)src[2]) * 0x1ff / 0xff)) & 0x3ff) << 20) ;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r4a4_unorm {
uint8_t value;
struct {
unsigned a:4;
unsigned r:4;
} chan;
};
 
static INLINE void
util_format_r4a4_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint8_t value = *(const uint8_t *)src;
uint8_t a;
uint8_t r;
a = (value) & 0xf;
r = value >> 4;
dst[0] = (float)(r * (1.0f/0xf)); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (float)(a * (1.0f/0xf)); /* a */
src += 1;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r4a4_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint8_t value = 0;
value |= ((uint8_t)util_iround(CLAMP(src[3], 0, 1) * 0xf)) & 0xf;
value |= ((uint8_t)util_iround(CLAMP(src[0], 0, 1) * 0xf)) << 4;
*(uint8_t *)dst = value;
src += 4;
dst += 1;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r4a4_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint8_t value = *(const uint8_t *)src;
uint8_t a;
uint8_t r;
a = (value) & 0xf;
r = value >> 4;
dst[0] = (float)(r * (1.0f/0xf)); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (float)(a * (1.0f/0xf)); /* a */
}
 
static INLINE void
util_format_r4a4_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint8_t value = *(const uint8_t *)src;
uint8_t a;
uint8_t r;
a = (value) & 0xf;
r = value >> 4;
dst[0] = (uint8_t)(((uint32_t)r) * 0xff / 0xf); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (uint8_t)(((uint32_t)a) * 0xff / 0xf); /* a */
src += 1;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r4a4_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint8_t value = 0;
value |= ((uint8_t)(src[3] >> 4)) & 0xf;
value |= ((uint8_t)(src[0] >> 4)) << 4;
*(uint8_t *)dst = value;
src += 4;
dst += 1;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_a4r4_unorm {
uint8_t value;
struct {
unsigned r:4;
unsigned a:4;
} chan;
};
 
static INLINE void
util_format_a4r4_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint8_t value = *(const uint8_t *)src;
uint8_t r;
uint8_t a;
r = (value) & 0xf;
a = value >> 4;
dst[0] = (float)(r * (1.0f/0xf)); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (float)(a * (1.0f/0xf)); /* a */
src += 1;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_a4r4_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint8_t value = 0;
value |= ((uint8_t)util_iround(CLAMP(src[0], 0, 1) * 0xf)) & 0xf;
value |= ((uint8_t)util_iround(CLAMP(src[3], 0, 1) * 0xf)) << 4;
*(uint8_t *)dst = value;
src += 4;
dst += 1;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_a4r4_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint8_t value = *(const uint8_t *)src;
uint8_t r;
uint8_t a;
r = (value) & 0xf;
a = value >> 4;
dst[0] = (float)(r * (1.0f/0xf)); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (float)(a * (1.0f/0xf)); /* a */
}
 
static INLINE void
util_format_a4r4_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint8_t value = *(const uint8_t *)src;
uint8_t r;
uint8_t a;
r = (value) & 0xf;
a = value >> 4;
dst[0] = (uint8_t)(((uint32_t)r) * 0xff / 0xf); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (uint8_t)(((uint32_t)a) * 0xff / 0xf); /* a */
src += 1;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_a4r4_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint8_t value = 0;
value |= ((uint8_t)(src[0] >> 4)) & 0xf;
value |= ((uint8_t)(src[3] >> 4)) << 4;
*(uint8_t *)dst = value;
src += 4;
dst += 1;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r8a8_unorm {
uint16_t value;
struct {
uint8_t r;
uint8_t a;
} chan;
};
 
static INLINE void
util_format_r8a8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
uint16_t r;
uint16_t a;
r = (value) & 0xff;
a = value >> 8;
dst[0] = ubyte_to_float(r); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = ubyte_to_float(a); /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8a8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (float_to_ubyte(src[0])) & 0xff;
value |= (float_to_ubyte(src[3])) << 8;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r8a8_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint16_t value = *(const uint16_t *)src;
uint16_t r;
uint16_t a;
r = (value) & 0xff;
a = value >> 8;
dst[0] = ubyte_to_float(r); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = ubyte_to_float(a); /* a */
}
 
static INLINE void
util_format_r8a8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
uint16_t r;
uint16_t a;
r = (value) & 0xff;
a = value >> 8;
dst[0] = r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = a; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8a8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (src[0]) & 0xff;
value |= (src[3]) << 8;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_a8r8_unorm {
uint16_t value;
struct {
uint8_t a;
uint8_t r;
} chan;
};
 
static INLINE void
util_format_a8r8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
uint16_t a;
uint16_t r;
a = (value) & 0xff;
r = value >> 8;
dst[0] = ubyte_to_float(r); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = ubyte_to_float(a); /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_a8r8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (float_to_ubyte(src[3])) & 0xff;
value |= (float_to_ubyte(src[0])) << 8;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_a8r8_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint16_t value = *(const uint16_t *)src;
uint16_t a;
uint16_t r;
a = (value) & 0xff;
r = value >> 8;
dst[0] = ubyte_to_float(r); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = ubyte_to_float(a); /* a */
}
 
static INLINE void
util_format_a8r8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
uint16_t a;
uint16_t r;
a = (value) & 0xff;
r = value >> 8;
dst[0] = r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = a; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_a8r8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (src[3]) & 0xff;
value |= (src[0]) << 8;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r8_uint {
uint8_t value;
struct {
uint8_t r;
} chan;
};
 
static INLINE void
util_format_r8_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint8_t value = *(const uint8_t *)src;
uint8_t r;
r = value;
dst[0] = (unsigned)r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 1;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint8_t value = 0;
value |= (uint8_t)MIN2(src[0], 255);
*(uint8_t *)dst = value;
src += 4;
dst += 1;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r8_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint8_t value = *(const uint8_t *)src;
uint8_t r;
r = value;
dst[0] = (unsigned)r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r8_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint8_t value = *(const uint8_t *)src;
uint8_t r;
r = value;
dst[0] = (int)r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 1;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint8_t value = 0;
value |= (uint8_t)CLAMP(src[0], 0, 255);
*(uint8_t *)dst = value;
src += 4;
dst += 1;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r8g8_uint {
uint16_t value;
struct {
uint8_t r;
uint8_t g;
} chan;
};
 
static INLINE void
util_format_r8g8_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
uint16_t r;
uint16_t g;
r = (value) & 0xff;
g = value >> 8;
dst[0] = (unsigned)r; /* r */
dst[1] = (unsigned)g; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8g8_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= ((uint8_t)MIN2(src[0], 255)) & 0xff;
value |= ((uint8_t)MIN2(src[1], 255)) << 8;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r8g8_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint16_t value = *(const uint16_t *)src;
uint16_t r;
uint16_t g;
r = (value) & 0xff;
g = value >> 8;
dst[0] = (unsigned)r; /* r */
dst[1] = (unsigned)g; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r8g8_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
uint16_t r;
uint16_t g;
r = (value) & 0xff;
g = value >> 8;
dst[0] = (int)r; /* r */
dst[1] = (int)g; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8g8_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= ((uint8_t)CLAMP(src[0], 0, 255)) & 0xff;
value |= ((uint8_t)CLAMP(src[1], 0, 255)) << 8;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r8g8b8_uint {
struct {
uint8_t r;
uint8_t g;
uint8_t b;
} chan;
};
 
static INLINE void
util_format_r8g8b8_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r8g8b8_uint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (unsigned)pixel.chan.r; /* r */
dst[1] = (unsigned)pixel.chan.g; /* g */
dst[2] = (unsigned)pixel.chan.b; /* b */
dst[3] = 1; /* a */
src += 3;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8g8b8_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r8g8b8_uint pixel;
pixel.chan.r = (uint8_t)MIN2(src[0], 255);
pixel.chan.g = (uint8_t)MIN2(src[1], 255);
pixel.chan.b = (uint8_t)MIN2(src[2], 255);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 3;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r8g8b8_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r8g8b8_uint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (unsigned)pixel.chan.r; /* r */
dst[1] = (unsigned)pixel.chan.g; /* g */
dst[2] = (unsigned)pixel.chan.b; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r8g8b8_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r8g8b8_uint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (int)pixel.chan.r; /* r */
dst[1] = (int)pixel.chan.g; /* g */
dst[2] = (int)pixel.chan.b; /* b */
dst[3] = 1; /* a */
src += 3;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8g8b8_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r8g8b8_uint pixel;
pixel.chan.r = (uint8_t)CLAMP(src[0], 0, 255);
pixel.chan.g = (uint8_t)CLAMP(src[1], 0, 255);
pixel.chan.b = (uint8_t)CLAMP(src[2], 0, 255);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 3;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r8g8b8a8_uint {
uint32_t value;
struct {
uint8_t r;
uint8_t g;
uint8_t b;
uint8_t a;
} chan;
};
 
static INLINE void
util_format_r8g8b8a8_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t r;
uint32_t g;
uint32_t b;
uint32_t a;
r = (value) & 0xff;
g = (value >> 8) & 0xff;
b = (value >> 16) & 0xff;
a = value >> 24;
dst[0] = (unsigned)r; /* r */
dst[1] = (unsigned)g; /* g */
dst[2] = (unsigned)b; /* b */
dst[3] = (unsigned)a; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8g8b8a8_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= ((uint8_t)MIN2(src[0], 255)) & 0xff;
value |= (((uint8_t)MIN2(src[1], 255)) & 0xff) << 8;
value |= (((uint8_t)MIN2(src[2], 255)) & 0xff) << 16;
value |= ((uint8_t)MIN2(src[3], 255)) << 24;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r8g8b8a8_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
uint32_t r;
uint32_t g;
uint32_t b;
uint32_t a;
r = (value) & 0xff;
g = (value >> 8) & 0xff;
b = (value >> 16) & 0xff;
a = value >> 24;
dst[0] = (unsigned)r; /* r */
dst[1] = (unsigned)g; /* g */
dst[2] = (unsigned)b; /* b */
dst[3] = (unsigned)a; /* a */
}
 
static INLINE void
util_format_r8g8b8a8_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t r;
uint32_t g;
uint32_t b;
uint32_t a;
r = (value) & 0xff;
g = (value >> 8) & 0xff;
b = (value >> 16) & 0xff;
a = value >> 24;
dst[0] = (int)r; /* r */
dst[1] = (int)g; /* g */
dst[2] = (int)b; /* b */
dst[3] = (int)a; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8g8b8a8_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= ((uint8_t)CLAMP(src[0], 0, 255)) & 0xff;
value |= (((uint8_t)CLAMP(src[1], 0, 255)) & 0xff) << 8;
value |= (((uint8_t)CLAMP(src[2], 0, 255)) & 0xff) << 16;
value |= ((uint8_t)CLAMP(src[3], 0, 255)) << 24;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r8_sint {
uint8_t value;
struct {
int8_t r;
} chan;
};
 
static INLINE void
util_format_r8_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint8_t value = *(const uint8_t *)src;
int8_t r;
r = (int8_t)(value) ;
dst[0] = (int)r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 1;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint8_t value = 0;
value |= (uint8_t)((int8_t)CLAMP(src[0], -128, 127)) ;
*(uint8_t *)dst = value;
src += 4;
dst += 1;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r8_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint8_t value = *(const uint8_t *)src;
int8_t r;
r = (int8_t)(value) ;
dst[0] = (int)r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r8_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint8_t value = *(const uint8_t *)src;
int8_t r;
r = (int8_t)(value) ;
dst[0] = (unsigned)MAX2(r, 0); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 1;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint8_t value = 0;
value |= (uint8_t)((int8_t)MIN2(src[0], 127)) ;
*(uint8_t *)dst = value;
src += 4;
dst += 1;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r8g8_sint {
uint16_t value;
struct {
int8_t r;
int8_t g;
} chan;
};
 
static INLINE void
util_format_r8g8_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
int16_t r;
int16_t g;
r = ((int16_t)(value << 8) ) >> 8;
g = ((int16_t)(value) ) >> 8;
dst[0] = (int)r; /* r */
dst[1] = (int)g; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8g8_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)(((int8_t)CLAMP(src[0], -128, 127)) & 0xff) ;
value |= (uint16_t)(((int8_t)CLAMP(src[1], -128, 127)) << 8) ;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r8g8_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint16_t value = *(const uint16_t *)src;
int16_t r;
int16_t g;
r = ((int16_t)(value << 8) ) >> 8;
g = ((int16_t)(value) ) >> 8;
dst[0] = (int)r; /* r */
dst[1] = (int)g; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r8g8_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
int16_t r;
int16_t g;
r = ((int16_t)(value << 8) ) >> 8;
g = ((int16_t)(value) ) >> 8;
dst[0] = (unsigned)MAX2(r, 0); /* r */
dst[1] = (unsigned)MAX2(g, 0); /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8g8_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)(((int8_t)MIN2(src[0], 127)) & 0xff) ;
value |= (uint16_t)(((int8_t)MIN2(src[1], 127)) << 8) ;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r8g8b8_sint {
struct {
int8_t r;
int8_t g;
int8_t b;
} chan;
};
 
static INLINE void
util_format_r8g8b8_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r8g8b8_sint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (int)pixel.chan.r; /* r */
dst[1] = (int)pixel.chan.g; /* g */
dst[2] = (int)pixel.chan.b; /* b */
dst[3] = 1; /* a */
src += 3;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8g8b8_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r8g8b8_sint pixel;
pixel.chan.r = (int8_t)CLAMP(src[0], -128, 127);
pixel.chan.g = (int8_t)CLAMP(src[1], -128, 127);
pixel.chan.b = (int8_t)CLAMP(src[2], -128, 127);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 3;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r8g8b8_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r8g8b8_sint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (int)pixel.chan.r; /* r */
dst[1] = (int)pixel.chan.g; /* g */
dst[2] = (int)pixel.chan.b; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r8g8b8_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r8g8b8_sint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (unsigned)MAX2(pixel.chan.r, 0); /* r */
dst[1] = (unsigned)MAX2(pixel.chan.g, 0); /* g */
dst[2] = (unsigned)MAX2(pixel.chan.b, 0); /* b */
dst[3] = 1; /* a */
src += 3;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8g8b8_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r8g8b8_sint pixel;
pixel.chan.r = (int8_t)MIN2(src[0], 127);
pixel.chan.g = (int8_t)MIN2(src[1], 127);
pixel.chan.b = (int8_t)MIN2(src[2], 127);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 3;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r8g8b8a8_sint {
uint32_t value;
struct {
int8_t r;
int8_t g;
int8_t b;
int8_t a;
} chan;
};
 
static INLINE void
util_format_r8g8b8a8_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
int32_t r;
int32_t g;
int32_t b;
int32_t a;
r = ((int32_t)(value << 24) ) >> 24;
g = ((int32_t)(value << 16) ) >> 24;
b = ((int32_t)(value << 8) ) >> 24;
a = ((int32_t)(value) ) >> 24;
dst[0] = (int)r; /* r */
dst[1] = (int)g; /* g */
dst[2] = (int)b; /* b */
dst[3] = (int)a; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8g8b8a8_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)(((int8_t)CLAMP(src[0], -128, 127)) & 0xff) ;
value |= (uint32_t)((((int8_t)CLAMP(src[1], -128, 127)) & 0xff) << 8) ;
value |= (uint32_t)((((int8_t)CLAMP(src[2], -128, 127)) & 0xff) << 16) ;
value |= (uint32_t)(((int8_t)CLAMP(src[3], -128, 127)) << 24) ;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r8g8b8a8_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
int32_t r;
int32_t g;
int32_t b;
int32_t a;
r = ((int32_t)(value << 24) ) >> 24;
g = ((int32_t)(value << 16) ) >> 24;
b = ((int32_t)(value << 8) ) >> 24;
a = ((int32_t)(value) ) >> 24;
dst[0] = (int)r; /* r */
dst[1] = (int)g; /* g */
dst[2] = (int)b; /* b */
dst[3] = (int)a; /* a */
}
 
static INLINE void
util_format_r8g8b8a8_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
int32_t r;
int32_t g;
int32_t b;
int32_t a;
r = ((int32_t)(value << 24) ) >> 24;
g = ((int32_t)(value << 16) ) >> 24;
b = ((int32_t)(value << 8) ) >> 24;
a = ((int32_t)(value) ) >> 24;
dst[0] = (unsigned)MAX2(r, 0); /* r */
dst[1] = (unsigned)MAX2(g, 0); /* g */
dst[2] = (unsigned)MAX2(b, 0); /* b */
dst[3] = (unsigned)MAX2(a, 0); /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8g8b8a8_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)(((int8_t)MIN2(src[0], 127)) & 0xff) ;
value |= (uint32_t)((((int8_t)MIN2(src[1], 127)) & 0xff) << 8) ;
value |= (uint32_t)((((int8_t)MIN2(src[2], 127)) & 0xff) << 16) ;
value |= (uint32_t)(((int8_t)MIN2(src[3], 127)) << 24) ;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r16_uint {
uint16_t value;
struct {
uint16_t r;
} chan;
};
 
static INLINE void
util_format_r16_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
uint16_t r;
r = value;
dst[0] = (unsigned)r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)MIN2(src[0], 65535);
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r16_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint16_t value = *(const uint16_t *)src;
uint16_t r;
r = value;
dst[0] = (unsigned)r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r16_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
uint16_t r;
r = value;
dst[0] = (int)r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)CLAMP(src[0], 0, 65535);
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r16g16_uint {
uint32_t value;
struct {
uint16_t r;
uint16_t g;
} chan;
};
 
static INLINE void
util_format_r16g16_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t r;
uint32_t g;
r = (value) & 0xffff;
g = value >> 16;
dst[0] = (unsigned)r; /* r */
dst[1] = (unsigned)g; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= ((uint16_t)MIN2(src[0], 65535)) & 0xffff;
value |= ((uint16_t)MIN2(src[1], 65535)) << 16;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r16g16_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
uint32_t r;
uint32_t g;
r = (value) & 0xffff;
g = value >> 16;
dst[0] = (unsigned)r; /* r */
dst[1] = (unsigned)g; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r16g16_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t r;
uint32_t g;
r = (value) & 0xffff;
g = value >> 16;
dst[0] = (int)r; /* r */
dst[1] = (int)g; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= ((uint16_t)CLAMP(src[0], 0, 65535)) & 0xffff;
value |= ((uint16_t)CLAMP(src[1], 0, 65535)) << 16;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r16g16b16_uint {
struct {
uint16_t r;
uint16_t g;
uint16_t b;
} chan;
};
 
static INLINE void
util_format_r16g16b16_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16_uint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (unsigned)pixel.chan.r; /* r */
dst[1] = (unsigned)pixel.chan.g; /* g */
dst[2] = (unsigned)pixel.chan.b; /* b */
dst[3] = 1; /* a */
src += 6;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16b16_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16_uint pixel;
pixel.chan.r = (uint16_t)MIN2(src[0], 65535);
pixel.chan.g = (uint16_t)MIN2(src[1], 65535);
pixel.chan.b = (uint16_t)MIN2(src[2], 65535);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 6;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r16g16b16_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r16g16b16_uint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (unsigned)pixel.chan.r; /* r */
dst[1] = (unsigned)pixel.chan.g; /* g */
dst[2] = (unsigned)pixel.chan.b; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r16g16b16_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16_uint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (int)pixel.chan.r; /* r */
dst[1] = (int)pixel.chan.g; /* g */
dst[2] = (int)pixel.chan.b; /* b */
dst[3] = 1; /* a */
src += 6;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16b16_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16_uint pixel;
pixel.chan.r = (uint16_t)CLAMP(src[0], 0, 65535);
pixel.chan.g = (uint16_t)CLAMP(src[1], 0, 65535);
pixel.chan.b = (uint16_t)CLAMP(src[2], 0, 65535);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 6;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r16g16b16a16_uint {
uint64_t value;
struct {
uint16_t r;
uint16_t g;
uint16_t b;
uint16_t a;
} chan;
};
 
static INLINE void
util_format_r16g16b16a16_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16a16_uint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (unsigned)pixel.chan.r; /* r */
dst[1] = (unsigned)pixel.chan.g; /* g */
dst[2] = (unsigned)pixel.chan.b; /* b */
dst[3] = (unsigned)pixel.chan.a; /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16b16a16_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16a16_uint pixel;
pixel.chan.r = (uint16_t)MIN2(src[0], 65535);
pixel.chan.g = (uint16_t)MIN2(src[1], 65535);
pixel.chan.b = (uint16_t)MIN2(src[2], 65535);
pixel.chan.a = (uint16_t)MIN2(src[3], 65535);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r16g16b16a16_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r16g16b16a16_uint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (unsigned)pixel.chan.r; /* r */
dst[1] = (unsigned)pixel.chan.g; /* g */
dst[2] = (unsigned)pixel.chan.b; /* b */
dst[3] = (unsigned)pixel.chan.a; /* a */
}
 
static INLINE void
util_format_r16g16b16a16_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16a16_uint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (int)pixel.chan.r; /* r */
dst[1] = (int)pixel.chan.g; /* g */
dst[2] = (int)pixel.chan.b; /* b */
dst[3] = (int)pixel.chan.a; /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16b16a16_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16a16_uint pixel;
pixel.chan.r = (uint16_t)CLAMP(src[0], 0, 65535);
pixel.chan.g = (uint16_t)CLAMP(src[1], 0, 65535);
pixel.chan.b = (uint16_t)CLAMP(src[2], 0, 65535);
pixel.chan.a = (uint16_t)CLAMP(src[3], 0, 65535);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r16_sint {
uint16_t value;
struct {
int16_t r;
} chan;
};
 
static INLINE void
util_format_r16_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
int16_t r;
r = (int16_t)(value) ;
dst[0] = (int)r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)((int16_t)CLAMP(src[0], -32768, 32767)) ;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r16_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint16_t value = *(const uint16_t *)src;
int16_t r;
r = (int16_t)(value) ;
dst[0] = (int)r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r16_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
int16_t r;
r = (int16_t)(value) ;
dst[0] = (unsigned)MAX2(r, 0); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)((int16_t)MIN2(src[0], 32767)) ;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r16g16_sint {
uint32_t value;
struct {
int16_t r;
int16_t g;
} chan;
};
 
static INLINE void
util_format_r16g16_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
int32_t r;
int32_t g;
r = ((int32_t)(value << 16) ) >> 16;
g = ((int32_t)(value) ) >> 16;
dst[0] = (int)r; /* r */
dst[1] = (int)g; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)(((int16_t)CLAMP(src[0], -32768, 32767)) & 0xffff) ;
value |= (uint32_t)(((int16_t)CLAMP(src[1], -32768, 32767)) << 16) ;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r16g16_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
int32_t r;
int32_t g;
r = ((int32_t)(value << 16) ) >> 16;
g = ((int32_t)(value) ) >> 16;
dst[0] = (int)r; /* r */
dst[1] = (int)g; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r16g16_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
int32_t r;
int32_t g;
r = ((int32_t)(value << 16) ) >> 16;
g = ((int32_t)(value) ) >> 16;
dst[0] = (unsigned)MAX2(r, 0); /* r */
dst[1] = (unsigned)MAX2(g, 0); /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)(((int16_t)MIN2(src[0], 32767)) & 0xffff) ;
value |= (uint32_t)(((int16_t)MIN2(src[1], 32767)) << 16) ;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r16g16b16_sint {
struct {
int16_t r;
int16_t g;
int16_t b;
} chan;
};
 
static INLINE void
util_format_r16g16b16_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16_sint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (int)pixel.chan.r; /* r */
dst[1] = (int)pixel.chan.g; /* g */
dst[2] = (int)pixel.chan.b; /* b */
dst[3] = 1; /* a */
src += 6;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16b16_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16_sint pixel;
pixel.chan.r = (int16_t)CLAMP(src[0], -32768, 32767);
pixel.chan.g = (int16_t)CLAMP(src[1], -32768, 32767);
pixel.chan.b = (int16_t)CLAMP(src[2], -32768, 32767);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 6;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r16g16b16_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r16g16b16_sint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (int)pixel.chan.r; /* r */
dst[1] = (int)pixel.chan.g; /* g */
dst[2] = (int)pixel.chan.b; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r16g16b16_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16_sint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (unsigned)MAX2(pixel.chan.r, 0); /* r */
dst[1] = (unsigned)MAX2(pixel.chan.g, 0); /* g */
dst[2] = (unsigned)MAX2(pixel.chan.b, 0); /* b */
dst[3] = 1; /* a */
src += 6;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16b16_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16_sint pixel;
pixel.chan.r = (int16_t)MIN2(src[0], 32767);
pixel.chan.g = (int16_t)MIN2(src[1], 32767);
pixel.chan.b = (int16_t)MIN2(src[2], 32767);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 6;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r16g16b16a16_sint {
uint64_t value;
struct {
int16_t r;
int16_t g;
int16_t b;
int16_t a;
} chan;
};
 
static INLINE void
util_format_r16g16b16a16_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16a16_sint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (int)pixel.chan.r; /* r */
dst[1] = (int)pixel.chan.g; /* g */
dst[2] = (int)pixel.chan.b; /* b */
dst[3] = (int)pixel.chan.a; /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16b16a16_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16a16_sint pixel;
pixel.chan.r = (int16_t)CLAMP(src[0], -32768, 32767);
pixel.chan.g = (int16_t)CLAMP(src[1], -32768, 32767);
pixel.chan.b = (int16_t)CLAMP(src[2], -32768, 32767);
pixel.chan.a = (int16_t)CLAMP(src[3], -32768, 32767);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r16g16b16a16_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r16g16b16a16_sint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (int)pixel.chan.r; /* r */
dst[1] = (int)pixel.chan.g; /* g */
dst[2] = (int)pixel.chan.b; /* b */
dst[3] = (int)pixel.chan.a; /* a */
}
 
static INLINE void
util_format_r16g16b16a16_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16a16_sint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (unsigned)MAX2(pixel.chan.r, 0); /* r */
dst[1] = (unsigned)MAX2(pixel.chan.g, 0); /* g */
dst[2] = (unsigned)MAX2(pixel.chan.b, 0); /* b */
dst[3] = (unsigned)MAX2(pixel.chan.a, 0); /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16b16a16_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16a16_sint pixel;
pixel.chan.r = (int16_t)MIN2(src[0], 32767);
pixel.chan.g = (int16_t)MIN2(src[1], 32767);
pixel.chan.b = (int16_t)MIN2(src[2], 32767);
pixel.chan.a = (int16_t)MIN2(src[3], 32767);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r32_uint {
uint32_t value;
struct {
uint32_t r;
} chan;
};
 
static INLINE void
util_format_r32_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t r;
r = value;
dst[0] = r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= src[0];
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r32_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
uint32_t r;
r = value;
dst[0] = r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r32_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t r;
r = value;
dst[0] = (int)MIN2(r, 2147483647); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)MAX2(src[0], 0);
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r32g32_uint {
uint64_t value;
struct {
uint32_t r;
uint32_t g;
} chan;
};
 
static INLINE void
util_format_r32g32_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32_uint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = pixel.chan.r; /* r */
dst[1] = pixel.chan.g; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32_uint pixel;
pixel.chan.r = src[0];
pixel.chan.g = src[1];
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r32g32_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r32g32_uint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = pixel.chan.r; /* r */
dst[1] = pixel.chan.g; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r32g32_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32_uint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (int)MIN2(pixel.chan.r, 2147483647); /* r */
dst[1] = (int)MIN2(pixel.chan.g, 2147483647); /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32_uint pixel;
pixel.chan.r = (uint32_t)MAX2(src[0], 0);
pixel.chan.g = (uint32_t)MAX2(src[1], 0);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r32g32b32_uint {
struct {
uint32_t r;
uint32_t g;
uint32_t b;
} chan;
};
 
static INLINE void
util_format_r32g32b32_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32_uint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = pixel.chan.r; /* r */
dst[1] = pixel.chan.g; /* g */
dst[2] = pixel.chan.b; /* b */
dst[3] = 1; /* a */
src += 12;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32b32_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32_uint pixel;
pixel.chan.r = src[0];
pixel.chan.g = src[1];
pixel.chan.b = src[2];
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 12;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r32g32b32_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r32g32b32_uint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = pixel.chan.r; /* r */
dst[1] = pixel.chan.g; /* g */
dst[2] = pixel.chan.b; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r32g32b32_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32_uint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (int)MIN2(pixel.chan.r, 2147483647); /* r */
dst[1] = (int)MIN2(pixel.chan.g, 2147483647); /* g */
dst[2] = (int)MIN2(pixel.chan.b, 2147483647); /* b */
dst[3] = 1; /* a */
src += 12;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32b32_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32_uint pixel;
pixel.chan.r = (uint32_t)MAX2(src[0], 0);
pixel.chan.g = (uint32_t)MAX2(src[1], 0);
pixel.chan.b = (uint32_t)MAX2(src[2], 0);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 12;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r32g32b32a32_uint {
struct {
uint32_t r;
uint32_t g;
uint32_t b;
uint32_t a;
} chan;
};
 
static INLINE void
util_format_r32g32b32a32_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32a32_uint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = pixel.chan.r; /* r */
dst[1] = pixel.chan.g; /* g */
dst[2] = pixel.chan.b; /* b */
dst[3] = pixel.chan.a; /* a */
src += 16;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32b32a32_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32a32_uint pixel;
pixel.chan.r = src[0];
pixel.chan.g = src[1];
pixel.chan.b = src[2];
pixel.chan.a = src[3];
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 16;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r32g32b32a32_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r32g32b32a32_uint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = pixel.chan.r; /* r */
dst[1] = pixel.chan.g; /* g */
dst[2] = pixel.chan.b; /* b */
dst[3] = pixel.chan.a; /* a */
}
 
static INLINE void
util_format_r32g32b32a32_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32a32_uint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (int)MIN2(pixel.chan.r, 2147483647); /* r */
dst[1] = (int)MIN2(pixel.chan.g, 2147483647); /* g */
dst[2] = (int)MIN2(pixel.chan.b, 2147483647); /* b */
dst[3] = (int)MIN2(pixel.chan.a, 2147483647); /* a */
src += 16;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32b32a32_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32a32_uint pixel;
pixel.chan.r = (uint32_t)MAX2(src[0], 0);
pixel.chan.g = (uint32_t)MAX2(src[1], 0);
pixel.chan.b = (uint32_t)MAX2(src[2], 0);
pixel.chan.a = (uint32_t)MAX2(src[3], 0);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 16;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r32_sint {
uint32_t value;
struct {
int32_t r;
} chan;
};
 
static INLINE void
util_format_r32_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
int32_t r;
r = (int32_t)(value) ;
dst[0] = r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)(src[0]) ;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r32_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
int32_t r;
r = (int32_t)(value) ;
dst[0] = r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r32_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
int32_t r;
r = (int32_t)(value) ;
dst[0] = (unsigned)MAX2(r, 0); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)((int32_t)MIN2(src[0], 2147483647)) ;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r32g32_sint {
uint64_t value;
struct {
int32_t r;
int32_t g;
} chan;
};
 
static INLINE void
util_format_r32g32_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32_sint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = pixel.chan.r; /* r */
dst[1] = pixel.chan.g; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32_sint pixel;
pixel.chan.r = src[0];
pixel.chan.g = src[1];
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r32g32_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r32g32_sint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = pixel.chan.r; /* r */
dst[1] = pixel.chan.g; /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r32g32_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32_sint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (unsigned)MAX2(pixel.chan.r, 0); /* r */
dst[1] = (unsigned)MAX2(pixel.chan.g, 0); /* g */
dst[2] = 0; /* b */
dst[3] = 1; /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32_sint pixel;
pixel.chan.r = (int32_t)MIN2(src[0], 2147483647);
pixel.chan.g = (int32_t)MIN2(src[1], 2147483647);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r32g32b32_sint {
struct {
int32_t r;
int32_t g;
int32_t b;
} chan;
};
 
static INLINE void
util_format_r32g32b32_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32_sint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = pixel.chan.r; /* r */
dst[1] = pixel.chan.g; /* g */
dst[2] = pixel.chan.b; /* b */
dst[3] = 1; /* a */
src += 12;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32b32_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32_sint pixel;
pixel.chan.r = src[0];
pixel.chan.g = src[1];
pixel.chan.b = src[2];
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 12;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r32g32b32_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r32g32b32_sint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = pixel.chan.r; /* r */
dst[1] = pixel.chan.g; /* g */
dst[2] = pixel.chan.b; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r32g32b32_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32_sint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (unsigned)MAX2(pixel.chan.r, 0); /* r */
dst[1] = (unsigned)MAX2(pixel.chan.g, 0); /* g */
dst[2] = (unsigned)MAX2(pixel.chan.b, 0); /* b */
dst[3] = 1; /* a */
src += 12;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32b32_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32_sint pixel;
pixel.chan.r = (int32_t)MIN2(src[0], 2147483647);
pixel.chan.g = (int32_t)MIN2(src[1], 2147483647);
pixel.chan.b = (int32_t)MIN2(src[2], 2147483647);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 12;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r32g32b32a32_sint {
struct {
int32_t r;
int32_t g;
int32_t b;
int32_t a;
} chan;
};
 
static INLINE void
util_format_r32g32b32a32_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32a32_sint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = pixel.chan.r; /* r */
dst[1] = pixel.chan.g; /* g */
dst[2] = pixel.chan.b; /* b */
dst[3] = pixel.chan.a; /* a */
src += 16;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32b32a32_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32a32_sint pixel;
pixel.chan.r = src[0];
pixel.chan.g = src[1];
pixel.chan.b = src[2];
pixel.chan.a = src[3];
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 16;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r32g32b32a32_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r32g32b32a32_sint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = pixel.chan.r; /* r */
dst[1] = pixel.chan.g; /* g */
dst[2] = pixel.chan.b; /* b */
dst[3] = pixel.chan.a; /* a */
}
 
static INLINE void
util_format_r32g32b32a32_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32a32_sint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (unsigned)MAX2(pixel.chan.r, 0); /* r */
dst[1] = (unsigned)MAX2(pixel.chan.g, 0); /* g */
dst[2] = (unsigned)MAX2(pixel.chan.b, 0); /* b */
dst[3] = (unsigned)MAX2(pixel.chan.a, 0); /* a */
src += 16;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32b32a32_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32a32_sint pixel;
pixel.chan.r = (int32_t)MIN2(src[0], 2147483647);
pixel.chan.g = (int32_t)MIN2(src[1], 2147483647);
pixel.chan.b = (int32_t)MIN2(src[2], 2147483647);
pixel.chan.a = (int32_t)MIN2(src[3], 2147483647);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 16;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_a8_uint {
uint8_t value;
struct {
uint8_t a;
} chan;
};
 
static INLINE void
util_format_a8_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint8_t value = *(const uint8_t *)src;
uint8_t a;
a = value;
dst[0] = 0; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (unsigned)a; /* a */
src += 1;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_a8_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint8_t value = 0;
value |= (uint8_t)MIN2(src[3], 255);
*(uint8_t *)dst = value;
src += 4;
dst += 1;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_a8_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint8_t value = *(const uint8_t *)src;
uint8_t a;
a = value;
dst[0] = 0; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (unsigned)a; /* a */
}
 
static INLINE void
util_format_a8_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint8_t value = *(const uint8_t *)src;
uint8_t a;
a = value;
dst[0] = 0; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (int)a; /* a */
src += 1;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_a8_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint8_t value = 0;
value |= (uint8_t)CLAMP(src[3], 0, 255);
*(uint8_t *)dst = value;
src += 4;
dst += 1;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_i8_uint {
uint8_t value;
struct {
uint8_t rgba;
} chan;
};
 
static INLINE void
util_format_i8_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint8_t value = *(const uint8_t *)src;
uint8_t rgba;
rgba = value;
dst[0] = (unsigned)rgba; /* r */
dst[1] = (unsigned)rgba; /* g */
dst[2] = (unsigned)rgba; /* b */
dst[3] = (unsigned)rgba; /* a */
src += 1;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_i8_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint8_t value = 0;
value |= (uint8_t)MIN2(src[0], 255);
*(uint8_t *)dst = value;
src += 4;
dst += 1;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_i8_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint8_t value = *(const uint8_t *)src;
uint8_t rgba;
rgba = value;
dst[0] = (unsigned)rgba; /* r */
dst[1] = (unsigned)rgba; /* g */
dst[2] = (unsigned)rgba; /* b */
dst[3] = (unsigned)rgba; /* a */
}
 
static INLINE void
util_format_i8_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint8_t value = *(const uint8_t *)src;
uint8_t rgba;
rgba = value;
dst[0] = (int)rgba; /* r */
dst[1] = (int)rgba; /* g */
dst[2] = (int)rgba; /* b */
dst[3] = (int)rgba; /* a */
src += 1;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_i8_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint8_t value = 0;
value |= (uint8_t)CLAMP(src[0], 0, 255);
*(uint8_t *)dst = value;
src += 4;
dst += 1;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_l8_uint {
uint8_t value;
struct {
uint8_t rgb;
} chan;
};
 
static INLINE void
util_format_l8_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint8_t value = *(const uint8_t *)src;
uint8_t rgb;
rgb = value;
dst[0] = (unsigned)rgb; /* r */
dst[1] = (unsigned)rgb; /* g */
dst[2] = (unsigned)rgb; /* b */
dst[3] = 1; /* a */
src += 1;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l8_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint8_t value = 0;
value |= (uint8_t)MIN2(src[0], 255);
*(uint8_t *)dst = value;
src += 4;
dst += 1;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_l8_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint8_t value = *(const uint8_t *)src;
uint8_t rgb;
rgb = value;
dst[0] = (unsigned)rgb; /* r */
dst[1] = (unsigned)rgb; /* g */
dst[2] = (unsigned)rgb; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_l8_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint8_t value = *(const uint8_t *)src;
uint8_t rgb;
rgb = value;
dst[0] = (int)rgb; /* r */
dst[1] = (int)rgb; /* g */
dst[2] = (int)rgb; /* b */
dst[3] = 1; /* a */
src += 1;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l8_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint8_t value = 0;
value |= (uint8_t)CLAMP(src[0], 0, 255);
*(uint8_t *)dst = value;
src += 4;
dst += 1;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_l8a8_uint {
uint16_t value;
struct {
uint8_t rgb;
uint8_t a;
} chan;
};
 
static INLINE void
util_format_l8a8_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
uint16_t rgb;
uint16_t a;
rgb = (value) & 0xff;
a = value >> 8;
dst[0] = (unsigned)rgb; /* r */
dst[1] = (unsigned)rgb; /* g */
dst[2] = (unsigned)rgb; /* b */
dst[3] = (unsigned)a; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l8a8_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= ((uint8_t)MIN2(src[0], 255)) & 0xff;
value |= ((uint8_t)MIN2(src[3], 255)) << 8;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_l8a8_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint16_t value = *(const uint16_t *)src;
uint16_t rgb;
uint16_t a;
rgb = (value) & 0xff;
a = value >> 8;
dst[0] = (unsigned)rgb; /* r */
dst[1] = (unsigned)rgb; /* g */
dst[2] = (unsigned)rgb; /* b */
dst[3] = (unsigned)a; /* a */
}
 
static INLINE void
util_format_l8a8_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
uint16_t rgb;
uint16_t a;
rgb = (value) & 0xff;
a = value >> 8;
dst[0] = (int)rgb; /* r */
dst[1] = (int)rgb; /* g */
dst[2] = (int)rgb; /* b */
dst[3] = (int)a; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l8a8_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= ((uint8_t)CLAMP(src[0], 0, 255)) & 0xff;
value |= ((uint8_t)CLAMP(src[3], 0, 255)) << 8;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_a8_sint {
uint8_t value;
struct {
int8_t a;
} chan;
};
 
static INLINE void
util_format_a8_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint8_t value = *(const uint8_t *)src;
int8_t a;
a = (int8_t)(value) ;
dst[0] = 0; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (int)a; /* a */
src += 1;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_a8_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint8_t value = 0;
value |= (uint8_t)((int8_t)CLAMP(src[3], -128, 127)) ;
*(uint8_t *)dst = value;
src += 4;
dst += 1;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_a8_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint8_t value = *(const uint8_t *)src;
int8_t a;
a = (int8_t)(value) ;
dst[0] = 0; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (int)a; /* a */
}
 
static INLINE void
util_format_a8_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint8_t value = *(const uint8_t *)src;
int8_t a;
a = (int8_t)(value) ;
dst[0] = 0; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (unsigned)MAX2(a, 0); /* a */
src += 1;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_a8_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint8_t value = 0;
value |= (uint8_t)((int8_t)MIN2(src[3], 127)) ;
*(uint8_t *)dst = value;
src += 4;
dst += 1;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_i8_sint {
uint8_t value;
struct {
int8_t rgba;
} chan;
};
 
static INLINE void
util_format_i8_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint8_t value = *(const uint8_t *)src;
int8_t rgba;
rgba = (int8_t)(value) ;
dst[0] = (int)rgba; /* r */
dst[1] = (int)rgba; /* g */
dst[2] = (int)rgba; /* b */
dst[3] = (int)rgba; /* a */
src += 1;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_i8_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint8_t value = 0;
value |= (uint8_t)((int8_t)CLAMP(src[0], -128, 127)) ;
*(uint8_t *)dst = value;
src += 4;
dst += 1;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_i8_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint8_t value = *(const uint8_t *)src;
int8_t rgba;
rgba = (int8_t)(value) ;
dst[0] = (int)rgba; /* r */
dst[1] = (int)rgba; /* g */
dst[2] = (int)rgba; /* b */
dst[3] = (int)rgba; /* a */
}
 
static INLINE void
util_format_i8_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint8_t value = *(const uint8_t *)src;
int8_t rgba;
rgba = (int8_t)(value) ;
dst[0] = (unsigned)MAX2(rgba, 0); /* r */
dst[1] = (unsigned)MAX2(rgba, 0); /* g */
dst[2] = (unsigned)MAX2(rgba, 0); /* b */
dst[3] = (unsigned)MAX2(rgba, 0); /* a */
src += 1;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_i8_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint8_t value = 0;
value |= (uint8_t)((int8_t)MIN2(src[0], 127)) ;
*(uint8_t *)dst = value;
src += 4;
dst += 1;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_l8_sint {
uint8_t value;
struct {
int8_t rgb;
} chan;
};
 
static INLINE void
util_format_l8_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint8_t value = *(const uint8_t *)src;
int8_t rgb;
rgb = (int8_t)(value) ;
dst[0] = (int)rgb; /* r */
dst[1] = (int)rgb; /* g */
dst[2] = (int)rgb; /* b */
dst[3] = 1; /* a */
src += 1;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l8_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint8_t value = 0;
value |= (uint8_t)((int8_t)CLAMP(src[0], -128, 127)) ;
*(uint8_t *)dst = value;
src += 4;
dst += 1;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_l8_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint8_t value = *(const uint8_t *)src;
int8_t rgb;
rgb = (int8_t)(value) ;
dst[0] = (int)rgb; /* r */
dst[1] = (int)rgb; /* g */
dst[2] = (int)rgb; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_l8_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint8_t value = *(const uint8_t *)src;
int8_t rgb;
rgb = (int8_t)(value) ;
dst[0] = (unsigned)MAX2(rgb, 0); /* r */
dst[1] = (unsigned)MAX2(rgb, 0); /* g */
dst[2] = (unsigned)MAX2(rgb, 0); /* b */
dst[3] = 1; /* a */
src += 1;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l8_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint8_t value = 0;
value |= (uint8_t)((int8_t)MIN2(src[0], 127)) ;
*(uint8_t *)dst = value;
src += 4;
dst += 1;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_l8a8_sint {
uint16_t value;
struct {
int8_t rgb;
int8_t a;
} chan;
};
 
static INLINE void
util_format_l8a8_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
int16_t rgb;
int16_t a;
rgb = ((int16_t)(value << 8) ) >> 8;
a = ((int16_t)(value) ) >> 8;
dst[0] = (int)rgb; /* r */
dst[1] = (int)rgb; /* g */
dst[2] = (int)rgb; /* b */
dst[3] = (int)a; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l8a8_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)(((int8_t)CLAMP(src[0], -128, 127)) & 0xff) ;
value |= (uint16_t)(((int8_t)CLAMP(src[3], -128, 127)) << 8) ;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_l8a8_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint16_t value = *(const uint16_t *)src;
int16_t rgb;
int16_t a;
rgb = ((int16_t)(value << 8) ) >> 8;
a = ((int16_t)(value) ) >> 8;
dst[0] = (int)rgb; /* r */
dst[1] = (int)rgb; /* g */
dst[2] = (int)rgb; /* b */
dst[3] = (int)a; /* a */
}
 
static INLINE void
util_format_l8a8_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
int16_t rgb;
int16_t a;
rgb = ((int16_t)(value << 8) ) >> 8;
a = ((int16_t)(value) ) >> 8;
dst[0] = (unsigned)MAX2(rgb, 0); /* r */
dst[1] = (unsigned)MAX2(rgb, 0); /* g */
dst[2] = (unsigned)MAX2(rgb, 0); /* b */
dst[3] = (unsigned)MAX2(a, 0); /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l8a8_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)(((int8_t)MIN2(src[0], 127)) & 0xff) ;
value |= (uint16_t)(((int8_t)MIN2(src[3], 127)) << 8) ;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_a16_uint {
uint16_t value;
struct {
uint16_t a;
} chan;
};
 
static INLINE void
util_format_a16_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
uint16_t a;
a = value;
dst[0] = 0; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (unsigned)a; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_a16_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)MIN2(src[3], 65535);
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_a16_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint16_t value = *(const uint16_t *)src;
uint16_t a;
a = value;
dst[0] = 0; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (unsigned)a; /* a */
}
 
static INLINE void
util_format_a16_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
uint16_t a;
a = value;
dst[0] = 0; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (int)a; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_a16_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)CLAMP(src[3], 0, 65535);
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_i16_uint {
uint16_t value;
struct {
uint16_t rgba;
} chan;
};
 
static INLINE void
util_format_i16_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
uint16_t rgba;
rgba = value;
dst[0] = (unsigned)rgba; /* r */
dst[1] = (unsigned)rgba; /* g */
dst[2] = (unsigned)rgba; /* b */
dst[3] = (unsigned)rgba; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_i16_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)MIN2(src[0], 65535);
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_i16_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint16_t value = *(const uint16_t *)src;
uint16_t rgba;
rgba = value;
dst[0] = (unsigned)rgba; /* r */
dst[1] = (unsigned)rgba; /* g */
dst[2] = (unsigned)rgba; /* b */
dst[3] = (unsigned)rgba; /* a */
}
 
static INLINE void
util_format_i16_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
uint16_t rgba;
rgba = value;
dst[0] = (int)rgba; /* r */
dst[1] = (int)rgba; /* g */
dst[2] = (int)rgba; /* b */
dst[3] = (int)rgba; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_i16_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)CLAMP(src[0], 0, 65535);
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_l16_uint {
uint16_t value;
struct {
uint16_t rgb;
} chan;
};
 
static INLINE void
util_format_l16_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
uint16_t rgb;
rgb = value;
dst[0] = (unsigned)rgb; /* r */
dst[1] = (unsigned)rgb; /* g */
dst[2] = (unsigned)rgb; /* b */
dst[3] = 1; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l16_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)MIN2(src[0], 65535);
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_l16_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint16_t value = *(const uint16_t *)src;
uint16_t rgb;
rgb = value;
dst[0] = (unsigned)rgb; /* r */
dst[1] = (unsigned)rgb; /* g */
dst[2] = (unsigned)rgb; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_l16_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
uint16_t rgb;
rgb = value;
dst[0] = (int)rgb; /* r */
dst[1] = (int)rgb; /* g */
dst[2] = (int)rgb; /* b */
dst[3] = 1; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l16_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)CLAMP(src[0], 0, 65535);
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_l16a16_uint {
uint32_t value;
struct {
uint16_t rgb;
uint16_t a;
} chan;
};
 
static INLINE void
util_format_l16a16_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t rgb;
uint32_t a;
rgb = (value) & 0xffff;
a = value >> 16;
dst[0] = (unsigned)rgb; /* r */
dst[1] = (unsigned)rgb; /* g */
dst[2] = (unsigned)rgb; /* b */
dst[3] = (unsigned)a; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l16a16_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= ((uint16_t)MIN2(src[0], 65535)) & 0xffff;
value |= ((uint16_t)MIN2(src[3], 65535)) << 16;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_l16a16_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
uint32_t rgb;
uint32_t a;
rgb = (value) & 0xffff;
a = value >> 16;
dst[0] = (unsigned)rgb; /* r */
dst[1] = (unsigned)rgb; /* g */
dst[2] = (unsigned)rgb; /* b */
dst[3] = (unsigned)a; /* a */
}
 
static INLINE void
util_format_l16a16_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t rgb;
uint32_t a;
rgb = (value) & 0xffff;
a = value >> 16;
dst[0] = (int)rgb; /* r */
dst[1] = (int)rgb; /* g */
dst[2] = (int)rgb; /* b */
dst[3] = (int)a; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l16a16_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= ((uint16_t)CLAMP(src[0], 0, 65535)) & 0xffff;
value |= ((uint16_t)CLAMP(src[3], 0, 65535)) << 16;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_a16_sint {
uint16_t value;
struct {
int16_t a;
} chan;
};
 
static INLINE void
util_format_a16_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
int16_t a;
a = (int16_t)(value) ;
dst[0] = 0; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (int)a; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_a16_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)((int16_t)CLAMP(src[3], -32768, 32767)) ;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_a16_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint16_t value = *(const uint16_t *)src;
int16_t a;
a = (int16_t)(value) ;
dst[0] = 0; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (int)a; /* a */
}
 
static INLINE void
util_format_a16_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
int16_t a;
a = (int16_t)(value) ;
dst[0] = 0; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (unsigned)MAX2(a, 0); /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_a16_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)((int16_t)MIN2(src[3], 32767)) ;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_i16_sint {
uint16_t value;
struct {
int16_t rgba;
} chan;
};
 
static INLINE void
util_format_i16_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
int16_t rgba;
rgba = (int16_t)(value) ;
dst[0] = (int)rgba; /* r */
dst[1] = (int)rgba; /* g */
dst[2] = (int)rgba; /* b */
dst[3] = (int)rgba; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_i16_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)((int16_t)CLAMP(src[0], -32768, 32767)) ;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_i16_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint16_t value = *(const uint16_t *)src;
int16_t rgba;
rgba = (int16_t)(value) ;
dst[0] = (int)rgba; /* r */
dst[1] = (int)rgba; /* g */
dst[2] = (int)rgba; /* b */
dst[3] = (int)rgba; /* a */
}
 
static INLINE void
util_format_i16_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
int16_t rgba;
rgba = (int16_t)(value) ;
dst[0] = (unsigned)MAX2(rgba, 0); /* r */
dst[1] = (unsigned)MAX2(rgba, 0); /* g */
dst[2] = (unsigned)MAX2(rgba, 0); /* b */
dst[3] = (unsigned)MAX2(rgba, 0); /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_i16_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)((int16_t)MIN2(src[0], 32767)) ;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_l16_sint {
uint16_t value;
struct {
int16_t rgb;
} chan;
};
 
static INLINE void
util_format_l16_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
int16_t rgb;
rgb = (int16_t)(value) ;
dst[0] = (int)rgb; /* r */
dst[1] = (int)rgb; /* g */
dst[2] = (int)rgb; /* b */
dst[3] = 1; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l16_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)((int16_t)CLAMP(src[0], -32768, 32767)) ;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_l16_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint16_t value = *(const uint16_t *)src;
int16_t rgb;
rgb = (int16_t)(value) ;
dst[0] = (int)rgb; /* r */
dst[1] = (int)rgb; /* g */
dst[2] = (int)rgb; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_l16_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
int16_t rgb;
rgb = (int16_t)(value) ;
dst[0] = (unsigned)MAX2(rgb, 0); /* r */
dst[1] = (unsigned)MAX2(rgb, 0); /* g */
dst[2] = (unsigned)MAX2(rgb, 0); /* b */
dst[3] = 1; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l16_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)((int16_t)MIN2(src[0], 32767)) ;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_l16a16_sint {
uint32_t value;
struct {
int16_t rgb;
int16_t a;
} chan;
};
 
static INLINE void
util_format_l16a16_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
int32_t rgb;
int32_t a;
rgb = ((int32_t)(value << 16) ) >> 16;
a = ((int32_t)(value) ) >> 16;
dst[0] = (int)rgb; /* r */
dst[1] = (int)rgb; /* g */
dst[2] = (int)rgb; /* b */
dst[3] = (int)a; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l16a16_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)(((int16_t)CLAMP(src[0], -32768, 32767)) & 0xffff) ;
value |= (uint32_t)(((int16_t)CLAMP(src[3], -32768, 32767)) << 16) ;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_l16a16_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
int32_t rgb;
int32_t a;
rgb = ((int32_t)(value << 16) ) >> 16;
a = ((int32_t)(value) ) >> 16;
dst[0] = (int)rgb; /* r */
dst[1] = (int)rgb; /* g */
dst[2] = (int)rgb; /* b */
dst[3] = (int)a; /* a */
}
 
static INLINE void
util_format_l16a16_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
int32_t rgb;
int32_t a;
rgb = ((int32_t)(value << 16) ) >> 16;
a = ((int32_t)(value) ) >> 16;
dst[0] = (unsigned)MAX2(rgb, 0); /* r */
dst[1] = (unsigned)MAX2(rgb, 0); /* g */
dst[2] = (unsigned)MAX2(rgb, 0); /* b */
dst[3] = (unsigned)MAX2(a, 0); /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l16a16_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)(((int16_t)MIN2(src[0], 32767)) & 0xffff) ;
value |= (uint32_t)(((int16_t)MIN2(src[3], 32767)) << 16) ;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_a32_uint {
uint32_t value;
struct {
uint32_t a;
} chan;
};
 
static INLINE void
util_format_a32_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t a;
a = value;
dst[0] = 0; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = a; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_a32_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= src[3];
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_a32_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
uint32_t a;
a = value;
dst[0] = 0; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = a; /* a */
}
 
static INLINE void
util_format_a32_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t a;
a = value;
dst[0] = 0; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (int)MIN2(a, 2147483647); /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_a32_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)MAX2(src[3], 0);
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_i32_uint {
uint32_t value;
struct {
uint32_t rgba;
} chan;
};
 
static INLINE void
util_format_i32_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t rgba;
rgba = value;
dst[0] = rgba; /* r */
dst[1] = rgba; /* g */
dst[2] = rgba; /* b */
dst[3] = rgba; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_i32_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= src[0];
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_i32_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
uint32_t rgba;
rgba = value;
dst[0] = rgba; /* r */
dst[1] = rgba; /* g */
dst[2] = rgba; /* b */
dst[3] = rgba; /* a */
}
 
static INLINE void
util_format_i32_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t rgba;
rgba = value;
dst[0] = (int)MIN2(rgba, 2147483647); /* r */
dst[1] = (int)MIN2(rgba, 2147483647); /* g */
dst[2] = (int)MIN2(rgba, 2147483647); /* b */
dst[3] = (int)MIN2(rgba, 2147483647); /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_i32_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)MAX2(src[0], 0);
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_l32_uint {
uint32_t value;
struct {
uint32_t rgb;
} chan;
};
 
static INLINE void
util_format_l32_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t rgb;
rgb = value;
dst[0] = rgb; /* r */
dst[1] = rgb; /* g */
dst[2] = rgb; /* b */
dst[3] = 1; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l32_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= src[0];
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_l32_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
uint32_t rgb;
rgb = value;
dst[0] = rgb; /* r */
dst[1] = rgb; /* g */
dst[2] = rgb; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_l32_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t rgb;
rgb = value;
dst[0] = (int)MIN2(rgb, 2147483647); /* r */
dst[1] = (int)MIN2(rgb, 2147483647); /* g */
dst[2] = (int)MIN2(rgb, 2147483647); /* b */
dst[3] = 1; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l32_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)MAX2(src[0], 0);
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_l32a32_uint {
uint64_t value;
struct {
uint32_t rgb;
uint32_t a;
} chan;
};
 
static INLINE void
util_format_l32a32_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_l32a32_uint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = pixel.chan.rgb; /* r */
dst[1] = pixel.chan.rgb; /* g */
dst[2] = pixel.chan.rgb; /* b */
dst[3] = pixel.chan.a; /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l32a32_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_l32a32_uint pixel;
pixel.chan.rgb = src[0];
pixel.chan.a = src[3];
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_l32a32_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_l32a32_uint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = pixel.chan.rgb; /* r */
dst[1] = pixel.chan.rgb; /* g */
dst[2] = pixel.chan.rgb; /* b */
dst[3] = pixel.chan.a; /* a */
}
 
static INLINE void
util_format_l32a32_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_l32a32_uint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (int)MIN2(pixel.chan.rgb, 2147483647); /* r */
dst[1] = (int)MIN2(pixel.chan.rgb, 2147483647); /* g */
dst[2] = (int)MIN2(pixel.chan.rgb, 2147483647); /* b */
dst[3] = (int)MIN2(pixel.chan.a, 2147483647); /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l32a32_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_l32a32_uint pixel;
pixel.chan.rgb = (uint32_t)MAX2(src[0], 0);
pixel.chan.a = (uint32_t)MAX2(src[3], 0);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_a32_sint {
uint32_t value;
struct {
int32_t a;
} chan;
};
 
static INLINE void
util_format_a32_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
int32_t a;
a = (int32_t)(value) ;
dst[0] = 0; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = a; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_a32_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)(src[3]) ;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_a32_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
int32_t a;
a = (int32_t)(value) ;
dst[0] = 0; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = a; /* a */
}
 
static INLINE void
util_format_a32_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
int32_t a;
a = (int32_t)(value) ;
dst[0] = 0; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (unsigned)MAX2(a, 0); /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_a32_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)((int32_t)MIN2(src[3], 2147483647)) ;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_i32_sint {
uint32_t value;
struct {
int32_t rgba;
} chan;
};
 
static INLINE void
util_format_i32_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
int32_t rgba;
rgba = (int32_t)(value) ;
dst[0] = rgba; /* r */
dst[1] = rgba; /* g */
dst[2] = rgba; /* b */
dst[3] = rgba; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_i32_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)(src[0]) ;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_i32_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
int32_t rgba;
rgba = (int32_t)(value) ;
dst[0] = rgba; /* r */
dst[1] = rgba; /* g */
dst[2] = rgba; /* b */
dst[3] = rgba; /* a */
}
 
static INLINE void
util_format_i32_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
int32_t rgba;
rgba = (int32_t)(value) ;
dst[0] = (unsigned)MAX2(rgba, 0); /* r */
dst[1] = (unsigned)MAX2(rgba, 0); /* g */
dst[2] = (unsigned)MAX2(rgba, 0); /* b */
dst[3] = (unsigned)MAX2(rgba, 0); /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_i32_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)((int32_t)MIN2(src[0], 2147483647)) ;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_l32_sint {
uint32_t value;
struct {
int32_t rgb;
} chan;
};
 
static INLINE void
util_format_l32_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
int32_t rgb;
rgb = (int32_t)(value) ;
dst[0] = rgb; /* r */
dst[1] = rgb; /* g */
dst[2] = rgb; /* b */
dst[3] = 1; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l32_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)(src[0]) ;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_l32_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
int32_t rgb;
rgb = (int32_t)(value) ;
dst[0] = rgb; /* r */
dst[1] = rgb; /* g */
dst[2] = rgb; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_l32_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
int32_t rgb;
rgb = (int32_t)(value) ;
dst[0] = (unsigned)MAX2(rgb, 0); /* r */
dst[1] = (unsigned)MAX2(rgb, 0); /* g */
dst[2] = (unsigned)MAX2(rgb, 0); /* b */
dst[3] = 1; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l32_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)((int32_t)MIN2(src[0], 2147483647)) ;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_l32a32_sint {
uint64_t value;
struct {
int32_t rgb;
int32_t a;
} chan;
};
 
static INLINE void
util_format_l32a32_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_l32a32_sint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = pixel.chan.rgb; /* r */
dst[1] = pixel.chan.rgb; /* g */
dst[2] = pixel.chan.rgb; /* b */
dst[3] = pixel.chan.a; /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l32a32_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_l32a32_sint pixel;
pixel.chan.rgb = src[0];
pixel.chan.a = src[3];
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_l32a32_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_l32a32_sint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = pixel.chan.rgb; /* r */
dst[1] = pixel.chan.rgb; /* g */
dst[2] = pixel.chan.rgb; /* b */
dst[3] = pixel.chan.a; /* a */
}
 
static INLINE void
util_format_l32a32_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_l32a32_sint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (unsigned)MAX2(pixel.chan.rgb, 0); /* r */
dst[1] = (unsigned)MAX2(pixel.chan.rgb, 0); /* g */
dst[2] = (unsigned)MAX2(pixel.chan.rgb, 0); /* b */
dst[3] = (unsigned)MAX2(pixel.chan.a, 0); /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_l32a32_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_l32a32_sint pixel;
pixel.chan.rgb = (int32_t)MIN2(src[0], 2147483647);
pixel.chan.a = (int32_t)MIN2(src[3], 2147483647);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r8g8b8x8_snorm {
uint32_t value;
struct {
int8_t r;
int8_t g;
int8_t b;
uint8_t x;
} chan;
};
 
static INLINE void
util_format_r8g8b8x8_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
int32_t r;
int32_t g;
int32_t b;
r = ((int32_t)(value << 24) ) >> 24;
g = ((int32_t)(value << 16) ) >> 24;
b = ((int32_t)(value << 8) ) >> 24;
dst[0] = (float)(r * (1.0f/0x7f)); /* r */
dst[1] = (float)(g * (1.0f/0x7f)); /* g */
dst[2] = (float)(b * (1.0f/0x7f)); /* b */
dst[3] = 1; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8g8b8x8_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)(((int8_t)util_iround(CLAMP(src[0], -1, 1) * 0x7f)) & 0xff) ;
value |= (uint32_t)((((int8_t)util_iround(CLAMP(src[1], -1, 1) * 0x7f)) & 0xff) << 8) ;
value |= (uint32_t)((((int8_t)util_iround(CLAMP(src[2], -1, 1) * 0x7f)) & 0xff) << 16) ;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r8g8b8x8_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
int32_t r;
int32_t g;
int32_t b;
r = ((int32_t)(value << 24) ) >> 24;
g = ((int32_t)(value << 16) ) >> 24;
b = ((int32_t)(value << 8) ) >> 24;
dst[0] = (float)(r * (1.0f/0x7f)); /* r */
dst[1] = (float)(g * (1.0f/0x7f)); /* g */
dst[2] = (float)(b * (1.0f/0x7f)); /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r8g8b8x8_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
int32_t r;
int32_t g;
int32_t b;
r = ((int32_t)(value << 24) ) >> 24;
g = ((int32_t)(value << 16) ) >> 24;
b = ((int32_t)(value << 8) ) >> 24;
dst[0] = (uint8_t)(((uint32_t)MAX2(r, 0)) * 0xff / 0x7f); /* r */
dst[1] = (uint8_t)(((uint32_t)MAX2(g, 0)) * 0xff / 0x7f); /* g */
dst[2] = (uint8_t)(((uint32_t)MAX2(b, 0)) * 0xff / 0x7f); /* b */
dst[3] = 255; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8g8b8x8_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)(((int8_t)(src[0] >> 1)) & 0xff) ;
value |= (uint32_t)((((int8_t)(src[1] >> 1)) & 0xff) << 8) ;
value |= (uint32_t)((((int8_t)(src[2] >> 1)) & 0xff) << 16) ;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r8g8b8x8_srgb {
uint32_t value;
struct {
uint8_t r;
uint8_t g;
uint8_t b;
uint8_t x;
} chan;
};
 
static INLINE void
util_format_r8g8b8x8_srgb_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t r;
uint32_t g;
uint32_t b;
r = (value) & 0xff;
g = (value >> 8) & 0xff;
b = (value >> 16) & 0xff;
dst[0] = util_format_srgb_8unorm_to_linear_float(r); /* r */
dst[1] = util_format_srgb_8unorm_to_linear_float(g); /* g */
dst[2] = util_format_srgb_8unorm_to_linear_float(b); /* b */
dst[3] = 1; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8g8b8x8_srgb_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (util_format_linear_float_to_srgb_8unorm(src[0])) & 0xff;
value |= ((util_format_linear_float_to_srgb_8unorm(src[1])) & 0xff) << 8;
value |= ((util_format_linear_float_to_srgb_8unorm(src[2])) & 0xff) << 16;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r8g8b8x8_srgb_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
uint32_t r;
uint32_t g;
uint32_t b;
r = (value) & 0xff;
g = (value >> 8) & 0xff;
b = (value >> 16) & 0xff;
dst[0] = util_format_srgb_8unorm_to_linear_float(r); /* r */
dst[1] = util_format_srgb_8unorm_to_linear_float(g); /* g */
dst[2] = util_format_srgb_8unorm_to_linear_float(b); /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r8g8b8x8_srgb_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t r;
uint32_t g;
uint32_t b;
r = (value) & 0xff;
g = (value >> 8) & 0xff;
b = (value >> 16) & 0xff;
dst[0] = util_format_srgb_to_linear_8unorm(r); /* r */
dst[1] = util_format_srgb_to_linear_8unorm(g); /* g */
dst[2] = util_format_srgb_to_linear_8unorm(b); /* b */
dst[3] = 255; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8g8b8x8_srgb_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (util_format_linear_to_srgb_8unorm(src[0])) & 0xff;
value |= ((util_format_linear_to_srgb_8unorm(src[1])) & 0xff) << 8;
value |= ((util_format_linear_to_srgb_8unorm(src[2])) & 0xff) << 16;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r8g8b8x8_uint {
uint32_t value;
struct {
uint8_t r;
uint8_t g;
uint8_t b;
uint8_t x;
} chan;
};
 
static INLINE void
util_format_r8g8b8x8_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t r;
uint32_t g;
uint32_t b;
r = (value) & 0xff;
g = (value >> 8) & 0xff;
b = (value >> 16) & 0xff;
dst[0] = (unsigned)r; /* r */
dst[1] = (unsigned)g; /* g */
dst[2] = (unsigned)b; /* b */
dst[3] = 1; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8g8b8x8_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= ((uint8_t)MIN2(src[0], 255)) & 0xff;
value |= (((uint8_t)MIN2(src[1], 255)) & 0xff) << 8;
value |= (((uint8_t)MIN2(src[2], 255)) & 0xff) << 16;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r8g8b8x8_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
uint32_t r;
uint32_t g;
uint32_t b;
r = (value) & 0xff;
g = (value >> 8) & 0xff;
b = (value >> 16) & 0xff;
dst[0] = (unsigned)r; /* r */
dst[1] = (unsigned)g; /* g */
dst[2] = (unsigned)b; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r8g8b8x8_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t r;
uint32_t g;
uint32_t b;
r = (value) & 0xff;
g = (value >> 8) & 0xff;
b = (value >> 16) & 0xff;
dst[0] = (int)r; /* r */
dst[1] = (int)g; /* g */
dst[2] = (int)b; /* b */
dst[3] = 1; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8g8b8x8_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= ((uint8_t)CLAMP(src[0], 0, 255)) & 0xff;
value |= (((uint8_t)CLAMP(src[1], 0, 255)) & 0xff) << 8;
value |= (((uint8_t)CLAMP(src[2], 0, 255)) & 0xff) << 16;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r8g8b8x8_sint {
uint32_t value;
struct {
int8_t r;
int8_t g;
int8_t b;
uint8_t x;
} chan;
};
 
static INLINE void
util_format_r8g8b8x8_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
int32_t r;
int32_t g;
int32_t b;
r = ((int32_t)(value << 24) ) >> 24;
g = ((int32_t)(value << 16) ) >> 24;
b = ((int32_t)(value << 8) ) >> 24;
dst[0] = (int)r; /* r */
dst[1] = (int)g; /* g */
dst[2] = (int)b; /* b */
dst[3] = 1; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8g8b8x8_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)(((int8_t)CLAMP(src[0], -128, 127)) & 0xff) ;
value |= (uint32_t)((((int8_t)CLAMP(src[1], -128, 127)) & 0xff) << 8) ;
value |= (uint32_t)((((int8_t)CLAMP(src[2], -128, 127)) & 0xff) << 16) ;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r8g8b8x8_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
int32_t r;
int32_t g;
int32_t b;
r = ((int32_t)(value << 24) ) >> 24;
g = ((int32_t)(value << 16) ) >> 24;
b = ((int32_t)(value << 8) ) >> 24;
dst[0] = (int)r; /* r */
dst[1] = (int)g; /* g */
dst[2] = (int)b; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r8g8b8x8_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
int32_t r;
int32_t g;
int32_t b;
r = ((int32_t)(value << 24) ) >> 24;
g = ((int32_t)(value << 16) ) >> 24;
b = ((int32_t)(value << 8) ) >> 24;
dst[0] = (unsigned)MAX2(r, 0); /* r */
dst[1] = (unsigned)MAX2(g, 0); /* g */
dst[2] = (unsigned)MAX2(b, 0); /* b */
dst[3] = 1; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8g8b8x8_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)(((int8_t)MIN2(src[0], 127)) & 0xff) ;
value |= (uint32_t)((((int8_t)MIN2(src[1], 127)) & 0xff) << 8) ;
value |= (uint32_t)((((int8_t)MIN2(src[2], 127)) & 0xff) << 16) ;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r16g16b16x16_unorm {
uint64_t value;
struct {
uint16_t r;
uint16_t g;
uint16_t b;
uint16_t x;
} chan;
};
 
static INLINE void
util_format_r16g16b16x16_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16x16_unorm pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)(pixel.chan.r * (1.0f/0xffff)); /* r */
dst[1] = (float)(pixel.chan.g * (1.0f/0xffff)); /* g */
dst[2] = (float)(pixel.chan.b * (1.0f/0xffff)); /* b */
dst[3] = 1; /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16b16x16_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16x16_unorm pixel;
pixel.chan.r = (uint16_t)util_iround(CLAMP(src[0], 0, 1) * 0xffff);
pixel.chan.g = (uint16_t)util_iround(CLAMP(src[1], 0, 1) * 0xffff);
pixel.chan.b = (uint16_t)util_iround(CLAMP(src[2], 0, 1) * 0xffff);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r16g16b16x16_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r16g16b16x16_unorm pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)(pixel.chan.r * (1.0f/0xffff)); /* r */
dst[1] = (float)(pixel.chan.g * (1.0f/0xffff)); /* g */
dst[2] = (float)(pixel.chan.b * (1.0f/0xffff)); /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r16g16b16x16_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16x16_unorm pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (uint8_t)(pixel.chan.r >> 8); /* r */
dst[1] = (uint8_t)(pixel.chan.g >> 8); /* g */
dst[2] = (uint8_t)(pixel.chan.b >> 8); /* b */
dst[3] = 255; /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16b16x16_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16x16_unorm pixel;
pixel.chan.r = (uint16_t)(((uint32_t)src[0]) * 0xffff / 0xff);
pixel.chan.g = (uint16_t)(((uint32_t)src[1]) * 0xffff / 0xff);
pixel.chan.b = (uint16_t)(((uint32_t)src[2]) * 0xffff / 0xff);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r16g16b16x16_snorm {
uint64_t value;
struct {
int16_t r;
int16_t g;
int16_t b;
uint16_t x;
} chan;
};
 
static INLINE void
util_format_r16g16b16x16_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16x16_snorm pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)(pixel.chan.r * (1.0f/0x7fff)); /* r */
dst[1] = (float)(pixel.chan.g * (1.0f/0x7fff)); /* g */
dst[2] = (float)(pixel.chan.b * (1.0f/0x7fff)); /* b */
dst[3] = 1; /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16b16x16_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16x16_snorm pixel;
pixel.chan.r = (int16_t)util_iround(CLAMP(src[0], -1, 1) * 0x7fff);
pixel.chan.g = (int16_t)util_iround(CLAMP(src[1], -1, 1) * 0x7fff);
pixel.chan.b = (int16_t)util_iround(CLAMP(src[2], -1, 1) * 0x7fff);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r16g16b16x16_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r16g16b16x16_snorm pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (float)(pixel.chan.r * (1.0f/0x7fff)); /* r */
dst[1] = (float)(pixel.chan.g * (1.0f/0x7fff)); /* g */
dst[2] = (float)(pixel.chan.b * (1.0f/0x7fff)); /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r16g16b16x16_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16x16_snorm pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (uint8_t)(MAX2(pixel.chan.r, 0) >> 7); /* r */
dst[1] = (uint8_t)(MAX2(pixel.chan.g, 0) >> 7); /* g */
dst[2] = (uint8_t)(MAX2(pixel.chan.b, 0) >> 7); /* b */
dst[3] = 255; /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16b16x16_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16x16_snorm pixel;
pixel.chan.r = (int16_t)(((uint32_t)src[0]) * 0x7fff / 0xff);
pixel.chan.g = (int16_t)(((uint32_t)src[1]) * 0x7fff / 0xff);
pixel.chan.b = (int16_t)(((uint32_t)src[2]) * 0x7fff / 0xff);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r16g16b16x16_float {
uint64_t value;
struct {
uint16_t r;
uint16_t g;
uint16_t b;
uint16_t x;
} chan;
};
 
static INLINE void
util_format_r16g16b16x16_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16x16_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = util_half_to_float(pixel.chan.r); /* r */
dst[1] = util_half_to_float(pixel.chan.g); /* g */
dst[2] = util_half_to_float(pixel.chan.b); /* b */
dst[3] = 1; /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16b16x16_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16x16_float pixel;
pixel.chan.r = util_float_to_half(src[0]);
pixel.chan.g = util_float_to_half(src[1]);
pixel.chan.b = util_float_to_half(src[2]);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r16g16b16x16_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r16g16b16x16_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = util_half_to_float(pixel.chan.r); /* r */
dst[1] = util_half_to_float(pixel.chan.g); /* g */
dst[2] = util_half_to_float(pixel.chan.b); /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r16g16b16x16_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16x16_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = float_to_ubyte(util_half_to_float(pixel.chan.r)); /* r */
dst[1] = float_to_ubyte(util_half_to_float(pixel.chan.g)); /* g */
dst[2] = float_to_ubyte(util_half_to_float(pixel.chan.b)); /* b */
dst[3] = 255; /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16b16x16_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16x16_float pixel;
pixel.chan.r = util_float_to_half((float)(src[0] * (1.0f/0xff)));
pixel.chan.g = util_float_to_half((float)(src[1] * (1.0f/0xff)));
pixel.chan.b = util_float_to_half((float)(src[2] * (1.0f/0xff)));
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r16g16b16x16_uint {
uint64_t value;
struct {
uint16_t r;
uint16_t g;
uint16_t b;
uint16_t x;
} chan;
};
 
static INLINE void
util_format_r16g16b16x16_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16x16_uint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (unsigned)pixel.chan.r; /* r */
dst[1] = (unsigned)pixel.chan.g; /* g */
dst[2] = (unsigned)pixel.chan.b; /* b */
dst[3] = 1; /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16b16x16_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16x16_uint pixel;
pixel.chan.r = (uint16_t)MIN2(src[0], 65535);
pixel.chan.g = (uint16_t)MIN2(src[1], 65535);
pixel.chan.b = (uint16_t)MIN2(src[2], 65535);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r16g16b16x16_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r16g16b16x16_uint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (unsigned)pixel.chan.r; /* r */
dst[1] = (unsigned)pixel.chan.g; /* g */
dst[2] = (unsigned)pixel.chan.b; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r16g16b16x16_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16x16_uint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (int)pixel.chan.r; /* r */
dst[1] = (int)pixel.chan.g; /* g */
dst[2] = (int)pixel.chan.b; /* b */
dst[3] = 1; /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16b16x16_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16x16_uint pixel;
pixel.chan.r = (uint16_t)CLAMP(src[0], 0, 65535);
pixel.chan.g = (uint16_t)CLAMP(src[1], 0, 65535);
pixel.chan.b = (uint16_t)CLAMP(src[2], 0, 65535);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r16g16b16x16_sint {
uint64_t value;
struct {
int16_t r;
int16_t g;
int16_t b;
uint16_t x;
} chan;
};
 
static INLINE void
util_format_r16g16b16x16_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16x16_sint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (int)pixel.chan.r; /* r */
dst[1] = (int)pixel.chan.g; /* g */
dst[2] = (int)pixel.chan.b; /* b */
dst[3] = 1; /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16b16x16_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16x16_sint pixel;
pixel.chan.r = (int16_t)CLAMP(src[0], -32768, 32767);
pixel.chan.g = (int16_t)CLAMP(src[1], -32768, 32767);
pixel.chan.b = (int16_t)CLAMP(src[2], -32768, 32767);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r16g16b16x16_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r16g16b16x16_sint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (int)pixel.chan.r; /* r */
dst[1] = (int)pixel.chan.g; /* g */
dst[2] = (int)pixel.chan.b; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r16g16b16x16_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16x16_sint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (unsigned)MAX2(pixel.chan.r, 0); /* r */
dst[1] = (unsigned)MAX2(pixel.chan.g, 0); /* g */
dst[2] = (unsigned)MAX2(pixel.chan.b, 0); /* b */
dst[3] = 1; /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16g16b16x16_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r16g16b16x16_sint pixel;
pixel.chan.r = (int16_t)MIN2(src[0], 32767);
pixel.chan.g = (int16_t)MIN2(src[1], 32767);
pixel.chan.b = (int16_t)MIN2(src[2], 32767);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r32g32b32x32_float {
struct {
float r;
float g;
float b;
uint32_t x;
} chan;
};
 
static INLINE void
util_format_r32g32b32x32_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32x32_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = pixel.chan.r; /* r */
dst[1] = pixel.chan.g; /* g */
dst[2] = pixel.chan.b; /* b */
dst[3] = 1; /* a */
src += 16;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32b32x32_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32x32_float pixel;
pixel.chan.r = src[0];
pixel.chan.g = src[1];
pixel.chan.b = src[2];
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 16;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r32g32b32x32_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r32g32b32x32_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = pixel.chan.r; /* r */
dst[1] = pixel.chan.g; /* g */
dst[2] = pixel.chan.b; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r32g32b32x32_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32x32_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = float_to_ubyte(pixel.chan.r); /* r */
dst[1] = float_to_ubyte(pixel.chan.g); /* g */
dst[2] = float_to_ubyte(pixel.chan.b); /* b */
dst[3] = 255; /* a */
src += 16;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32b32x32_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32x32_float pixel;
pixel.chan.r = ubyte_to_float(src[0]);
pixel.chan.g = ubyte_to_float(src[1]);
pixel.chan.b = ubyte_to_float(src[2]);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 16;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r32g32b32x32_uint {
struct {
uint32_t r;
uint32_t g;
uint32_t b;
uint32_t x;
} chan;
};
 
static INLINE void
util_format_r32g32b32x32_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32x32_uint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = pixel.chan.r; /* r */
dst[1] = pixel.chan.g; /* g */
dst[2] = pixel.chan.b; /* b */
dst[3] = 1; /* a */
src += 16;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32b32x32_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32x32_uint pixel;
pixel.chan.r = src[0];
pixel.chan.g = src[1];
pixel.chan.b = src[2];
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 16;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r32g32b32x32_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r32g32b32x32_uint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = pixel.chan.r; /* r */
dst[1] = pixel.chan.g; /* g */
dst[2] = pixel.chan.b; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r32g32b32x32_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32x32_uint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (int)MIN2(pixel.chan.r, 2147483647); /* r */
dst[1] = (int)MIN2(pixel.chan.g, 2147483647); /* g */
dst[2] = (int)MIN2(pixel.chan.b, 2147483647); /* b */
dst[3] = 1; /* a */
src += 16;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32b32x32_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32x32_uint pixel;
pixel.chan.r = (uint32_t)MAX2(src[0], 0);
pixel.chan.g = (uint32_t)MAX2(src[1], 0);
pixel.chan.b = (uint32_t)MAX2(src[2], 0);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 16;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r32g32b32x32_sint {
struct {
int32_t r;
int32_t g;
int32_t b;
uint32_t x;
} chan;
};
 
static INLINE void
util_format_r32g32b32x32_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32x32_sint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = pixel.chan.r; /* r */
dst[1] = pixel.chan.g; /* g */
dst[2] = pixel.chan.b; /* b */
dst[3] = 1; /* a */
src += 16;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32b32x32_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32x32_sint pixel;
pixel.chan.r = src[0];
pixel.chan.g = src[1];
pixel.chan.b = src[2];
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 16;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r32g32b32x32_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r32g32b32x32_sint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = pixel.chan.r; /* r */
dst[1] = pixel.chan.g; /* g */
dst[2] = pixel.chan.b; /* b */
dst[3] = 1; /* a */
}
 
static INLINE void
util_format_r32g32b32x32_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32x32_sint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (unsigned)MAX2(pixel.chan.r, 0); /* r */
dst[1] = (unsigned)MAX2(pixel.chan.g, 0); /* g */
dst[2] = (unsigned)MAX2(pixel.chan.b, 0); /* b */
dst[3] = 1; /* a */
src += 16;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32g32b32x32_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32g32b32x32_sint pixel;
pixel.chan.r = (int32_t)MIN2(src[0], 2147483647);
pixel.chan.g = (int32_t)MIN2(src[1], 2147483647);
pixel.chan.b = (int32_t)MIN2(src[2], 2147483647);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 16;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r8a8_snorm {
uint16_t value;
struct {
int8_t r;
int8_t a;
} chan;
};
 
static INLINE void
util_format_r8a8_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
int16_t r;
int16_t a;
r = ((int16_t)(value << 8) ) >> 8;
a = ((int16_t)(value) ) >> 8;
dst[0] = (float)(r * (1.0f/0x7f)); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (float)(a * (1.0f/0x7f)); /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8a8_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)(((int8_t)util_iround(CLAMP(src[0], -1, 1) * 0x7f)) & 0xff) ;
value |= (uint16_t)(((int8_t)util_iround(CLAMP(src[3], -1, 1) * 0x7f)) << 8) ;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r8a8_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint16_t value = *(const uint16_t *)src;
int16_t r;
int16_t a;
r = ((int16_t)(value << 8) ) >> 8;
a = ((int16_t)(value) ) >> 8;
dst[0] = (float)(r * (1.0f/0x7f)); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (float)(a * (1.0f/0x7f)); /* a */
}
 
static INLINE void
util_format_r8a8_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
int16_t r;
int16_t a;
r = ((int16_t)(value << 8) ) >> 8;
a = ((int16_t)(value) ) >> 8;
dst[0] = (uint8_t)(((uint32_t)MAX2(r, 0)) * 0xff / 0x7f); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (uint8_t)(((uint32_t)MAX2(a, 0)) * 0xff / 0x7f); /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8a8_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)(((int8_t)(src[0] >> 1)) & 0xff) ;
value |= (uint16_t)(((int8_t)(src[3] >> 1)) << 8) ;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r16a16_unorm {
uint32_t value;
struct {
uint16_t r;
uint16_t a;
} chan;
};
 
static INLINE void
util_format_r16a16_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t r;
uint32_t a;
r = (value) & 0xffff;
a = value >> 16;
dst[0] = (float)(r * (1.0f/0xffff)); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (float)(a * (1.0f/0xffff)); /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16a16_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= ((uint16_t)util_iround(CLAMP(src[0], 0, 1) * 0xffff)) & 0xffff;
value |= ((uint16_t)util_iround(CLAMP(src[3], 0, 1) * 0xffff)) << 16;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r16a16_unorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
uint32_t r;
uint32_t a;
r = (value) & 0xffff;
a = value >> 16;
dst[0] = (float)(r * (1.0f/0xffff)); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (float)(a * (1.0f/0xffff)); /* a */
}
 
static INLINE void
util_format_r16a16_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t r;
uint32_t a;
r = (value) & 0xffff;
a = value >> 16;
dst[0] = (uint8_t)(r >> 8); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (uint8_t)(a >> 8); /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16a16_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= ((uint16_t)(((uint32_t)src[0]) * 0xffff / 0xff)) & 0xffff;
value |= ((uint16_t)(((uint32_t)src[3]) * 0xffff / 0xff)) << 16;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r16a16_snorm {
uint32_t value;
struct {
int16_t r;
int16_t a;
} chan;
};
 
static INLINE void
util_format_r16a16_snorm_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
int32_t r;
int32_t a;
r = ((int32_t)(value << 16) ) >> 16;
a = ((int32_t)(value) ) >> 16;
dst[0] = (float)(r * (1.0f/0x7fff)); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (float)(a * (1.0f/0x7fff)); /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16a16_snorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)(((int16_t)util_iround(CLAMP(src[0], -1, 1) * 0x7fff)) & 0xffff) ;
value |= (uint32_t)(((int16_t)util_iround(CLAMP(src[3], -1, 1) * 0x7fff)) << 16) ;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r16a16_snorm_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
int32_t r;
int32_t a;
r = ((int32_t)(value << 16) ) >> 16;
a = ((int32_t)(value) ) >> 16;
dst[0] = (float)(r * (1.0f/0x7fff)); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (float)(a * (1.0f/0x7fff)); /* a */
}
 
static INLINE void
util_format_r16a16_snorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
int32_t r;
int32_t a;
r = ((int32_t)(value << 16) ) >> 16;
a = ((int32_t)(value) ) >> 16;
dst[0] = (uint8_t)(MAX2(r, 0) >> 7); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (uint8_t)(MAX2(a, 0) >> 7); /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16a16_snorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)(((int16_t)(((uint32_t)src[0]) * 0x7fff / 0xff)) & 0xffff) ;
value |= (uint32_t)(((int16_t)(((uint32_t)src[3]) * 0x7fff / 0xff)) << 16) ;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r16a16_float {
uint32_t value;
struct {
uint16_t r;
uint16_t a;
} chan;
};
 
static INLINE void
util_format_r16a16_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r16a16_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = util_half_to_float(pixel.chan.r); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = util_half_to_float(pixel.chan.a); /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16a16_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r16a16_float pixel;
pixel.chan.r = util_float_to_half(src[0]);
pixel.chan.a = util_float_to_half(src[3]);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r16a16_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r16a16_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = util_half_to_float(pixel.chan.r); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = util_half_to_float(pixel.chan.a); /* a */
}
 
static INLINE void
util_format_r16a16_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r16a16_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = float_to_ubyte(util_half_to_float(pixel.chan.r)); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = float_to_ubyte(util_half_to_float(pixel.chan.a)); /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16a16_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r16a16_float pixel;
pixel.chan.r = util_float_to_half((float)(src[0] * (1.0f/0xff)));
pixel.chan.a = util_float_to_half((float)(src[3] * (1.0f/0xff)));
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r32a32_float {
uint64_t value;
struct {
float r;
float a;
} chan;
};
 
static INLINE void
util_format_r32a32_float_unpack_rgba_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32a32_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = pixel.chan.r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = pixel.chan.a; /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32a32_float_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const float *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32a32_float pixel;
pixel.chan.r = src[0];
pixel.chan.a = src[3];
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r32a32_float_fetch_rgba_float(float *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r32a32_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = pixel.chan.r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = pixel.chan.a; /* a */
}
 
static INLINE void
util_format_r32a32_float_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32a32_float pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = float_to_ubyte(pixel.chan.r); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = float_to_ubyte(pixel.chan.a); /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32a32_float_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32a32_float pixel;
pixel.chan.r = ubyte_to_float(src[0]);
pixel.chan.a = ubyte_to_float(src[3]);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r8a8_uint {
uint16_t value;
struct {
uint8_t r;
uint8_t a;
} chan;
};
 
static INLINE void
util_format_r8a8_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
uint16_t r;
uint16_t a;
r = (value) & 0xff;
a = value >> 8;
dst[0] = (unsigned)r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (unsigned)a; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8a8_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= ((uint8_t)MIN2(src[0], 255)) & 0xff;
value |= ((uint8_t)MIN2(src[3], 255)) << 8;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r8a8_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint16_t value = *(const uint16_t *)src;
uint16_t r;
uint16_t a;
r = (value) & 0xff;
a = value >> 8;
dst[0] = (unsigned)r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (unsigned)a; /* a */
}
 
static INLINE void
util_format_r8a8_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
uint16_t r;
uint16_t a;
r = (value) & 0xff;
a = value >> 8;
dst[0] = (int)r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (int)a; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8a8_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= ((uint8_t)CLAMP(src[0], 0, 255)) & 0xff;
value |= ((uint8_t)CLAMP(src[3], 0, 255)) << 8;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r8a8_sint {
uint16_t value;
struct {
int8_t r;
int8_t a;
} chan;
};
 
static INLINE void
util_format_r8a8_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
int16_t r;
int16_t a;
r = ((int16_t)(value << 8) ) >> 8;
a = ((int16_t)(value) ) >> 8;
dst[0] = (int)r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (int)a; /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8a8_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)(((int8_t)CLAMP(src[0], -128, 127)) & 0xff) ;
value |= (uint16_t)(((int8_t)CLAMP(src[3], -128, 127)) << 8) ;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r8a8_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint16_t value = *(const uint16_t *)src;
int16_t r;
int16_t a;
r = ((int16_t)(value << 8) ) >> 8;
a = ((int16_t)(value) ) >> 8;
dst[0] = (int)r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (int)a; /* a */
}
 
static INLINE void
util_format_r8a8_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint16_t value = *(const uint16_t *)src;
int16_t r;
int16_t a;
r = ((int16_t)(value << 8) ) >> 8;
a = ((int16_t)(value) ) >> 8;
dst[0] = (unsigned)MAX2(r, 0); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (unsigned)MAX2(a, 0); /* a */
src += 2;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r8a8_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint16_t value = 0;
value |= (uint16_t)(((int8_t)MIN2(src[0], 127)) & 0xff) ;
value |= (uint16_t)(((int8_t)MIN2(src[3], 127)) << 8) ;
*(uint16_t *)dst = value;
src += 4;
dst += 2;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r16a16_uint {
uint32_t value;
struct {
uint16_t r;
uint16_t a;
} chan;
};
 
static INLINE void
util_format_r16a16_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t r;
uint32_t a;
r = (value) & 0xffff;
a = value >> 16;
dst[0] = (unsigned)r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (unsigned)a; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16a16_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= ((uint16_t)MIN2(src[0], 65535)) & 0xffff;
value |= ((uint16_t)MIN2(src[3], 65535)) << 16;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r16a16_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
uint32_t r;
uint32_t a;
r = (value) & 0xffff;
a = value >> 16;
dst[0] = (unsigned)r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (unsigned)a; /* a */
}
 
static INLINE void
util_format_r16a16_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
uint32_t r;
uint32_t a;
r = (value) & 0xffff;
a = value >> 16;
dst[0] = (int)r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (int)a; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16a16_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= ((uint16_t)CLAMP(src[0], 0, 65535)) & 0xffff;
value |= ((uint16_t)CLAMP(src[3], 0, 65535)) << 16;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r16a16_sint {
uint32_t value;
struct {
int16_t r;
int16_t a;
} chan;
};
 
static INLINE void
util_format_r16a16_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
int32_t r;
int32_t a;
r = ((int32_t)(value << 16) ) >> 16;
a = ((int32_t)(value) ) >> 16;
dst[0] = (int)r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (int)a; /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16a16_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)(((int16_t)CLAMP(src[0], -32768, 32767)) & 0xffff) ;
value |= (uint32_t)(((int16_t)CLAMP(src[3], -32768, 32767)) << 16) ;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r16a16_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j)
{
uint32_t value = *(const uint32_t *)src;
int32_t r;
int32_t a;
r = ((int32_t)(value << 16) ) >> 16;
a = ((int32_t)(value) ) >> 16;
dst[0] = (int)r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (int)a; /* a */
}
 
static INLINE void
util_format_r16a16_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
uint32_t value = *(const uint32_t *)src;
int32_t r;
int32_t a;
r = ((int32_t)(value << 16) ) >> 16;
a = ((int32_t)(value) ) >> 16;
dst[0] = (unsigned)MAX2(r, 0); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (unsigned)MAX2(a, 0); /* a */
src += 4;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r16a16_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
uint32_t value = 0;
value |= (uint32_t)(((int16_t)MIN2(src[0], 32767)) & 0xffff) ;
value |= (uint32_t)(((int16_t)MIN2(src[3], 32767)) << 16) ;
*(uint32_t *)dst = value;
src += 4;
dst += 4;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r32a32_uint {
uint64_t value;
struct {
uint32_t r;
uint32_t a;
} chan;
};
 
static INLINE void
util_format_r32a32_uint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32a32_uint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = pixel.chan.r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = pixel.chan.a; /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32a32_uint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32a32_uint pixel;
pixel.chan.r = src[0];
pixel.chan.a = src[3];
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r32a32_uint_fetch_unsigned(unsigned *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r32a32_uint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = pixel.chan.r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = pixel.chan.a; /* a */
}
 
static INLINE void
util_format_r32a32_uint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32a32_uint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (int)MIN2(pixel.chan.r, 2147483647); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (int)MIN2(pixel.chan.a, 2147483647); /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32a32_uint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32a32_uint pixel;
pixel.chan.r = (uint32_t)MAX2(src[0], 0);
pixel.chan.a = (uint32_t)MAX2(src[3], 0);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
union util_format_r32a32_sint {
uint64_t value;
struct {
int32_t r;
int32_t a;
} chan;
};
 
static INLINE void
util_format_r32a32_sint_unpack_signed(int *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
int *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32a32_sint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = pixel.chan.r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = pixel.chan.a; /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32a32_sint_pack_signed(uint8_t *dst_row, unsigned dst_stride, const int *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const int *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32a32_sint pixel;
pixel.chan.r = src[0];
pixel.chan.a = src[3];
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
static INLINE void
util_format_r32a32_sint_fetch_signed(int *dst, const uint8_t *src, unsigned i, unsigned j)
{
union util_format_r32a32_sint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = pixel.chan.r; /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = pixel.chan.a; /* a */
}
 
static INLINE void
util_format_r32a32_sint_unpack_unsigned(unsigned *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
unsigned *dst = dst_row;
const uint8_t *src = src_row;
for(x = 0; x < width; x += 1) {
union util_format_r32a32_sint pixel;
memcpy(&pixel, src, sizeof pixel);
dst[0] = (unsigned)MAX2(pixel.chan.r, 0); /* r */
dst[1] = 0; /* g */
dst[2] = 0; /* b */
dst[3] = (unsigned)MAX2(pixel.chan.a, 0); /* a */
src += 8;
dst += 4;
}
src_row += src_stride;
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
static INLINE void
util_format_r32a32_sint_pack_unsigned(uint8_t *dst_row, unsigned dst_stride, const unsigned *src_row, unsigned src_stride, unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; y += 1) {
const unsigned *src = src_row;
uint8_t *dst = dst_row;
for(x = 0; x < width; x += 1) {
union util_format_r32a32_sint pixel;
pixel.chan.r = (int32_t)MIN2(src[0], 2147483647);
pixel.chan.a = (int32_t)MIN2(src[3], 2147483647);
memcpy(dst, &pixel, sizeof pixel);
src += 4;
dst += 8;
}
dst_row += dst_stride;
src_row += src_stride/sizeof(*src_row);
}
}
 
const struct util_format_description
util_format_none_description = {
PIPE_FORMAT_NONE,
"PIPE_FORMAT_NONE",
"none",
{1, 1, 8}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 8, 0}, /* x = r */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_none_unpack_rgba_8unorm,
&util_format_none_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_none_unpack_rgba_float,
&util_format_none_pack_rgba_float,
&util_format_none_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_b8g8r8a8_unorm_description = {
PIPE_FORMAT_B8G8R8A8_UNORM,
"PIPE_FORMAT_B8G8R8A8_UNORM",
"b8g8r8a8_unorm",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
4, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 0}, /* x = b */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 8}, /* y = g */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 16}, /* z = r */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 24} /* w = a */
},
{
UTIL_FORMAT_SWIZZLE_Z, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_X, /* b */
UTIL_FORMAT_SWIZZLE_W /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_b8g8r8a8_unorm_unpack_rgba_8unorm,
&util_format_b8g8r8a8_unorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_b8g8r8a8_unorm_unpack_rgba_float,
&util_format_b8g8r8a8_unorm_pack_rgba_float,
&util_format_b8g8r8a8_unorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_b8g8r8x8_unorm_description = {
PIPE_FORMAT_B8G8R8X8_UNORM,
"PIPE_FORMAT_B8G8R8X8_UNORM",
"b8g8r8x8_unorm",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
4, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 0}, /* x = b */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 8}, /* y = g */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 16}, /* z = r */
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 24} /* w = x */
},
{
UTIL_FORMAT_SWIZZLE_Z, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_X, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_b8g8r8x8_unorm_unpack_rgba_8unorm,
&util_format_b8g8r8x8_unorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_b8g8r8x8_unorm_unpack_rgba_float,
&util_format_b8g8r8x8_unorm_pack_rgba_float,
&util_format_b8g8r8x8_unorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_a8r8g8b8_unorm_description = {
PIPE_FORMAT_A8R8G8B8_UNORM,
"PIPE_FORMAT_A8R8G8B8_UNORM",
"a8r8g8b8_unorm",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
4, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 0}, /* x = a */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 8}, /* y = r */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 16}, /* z = g */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 24} /* w = b */
},
{
UTIL_FORMAT_SWIZZLE_Y, /* r */
UTIL_FORMAT_SWIZZLE_Z, /* g */
UTIL_FORMAT_SWIZZLE_W, /* b */
UTIL_FORMAT_SWIZZLE_X /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_a8r8g8b8_unorm_unpack_rgba_8unorm,
&util_format_a8r8g8b8_unorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_a8r8g8b8_unorm_unpack_rgba_float,
&util_format_a8r8g8b8_unorm_pack_rgba_float,
&util_format_a8r8g8b8_unorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_x8r8g8b8_unorm_description = {
PIPE_FORMAT_X8R8G8B8_UNORM,
"PIPE_FORMAT_X8R8G8B8_UNORM",
"x8r8g8b8_unorm",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
4, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 0}, /* x = x */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 8}, /* y = r */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 16}, /* z = g */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 24} /* w = b */
},
{
UTIL_FORMAT_SWIZZLE_Y, /* r */
UTIL_FORMAT_SWIZZLE_Z, /* g */
UTIL_FORMAT_SWIZZLE_W, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_x8r8g8b8_unorm_unpack_rgba_8unorm,
&util_format_x8r8g8b8_unorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_x8r8g8b8_unorm_unpack_rgba_float,
&util_format_x8r8g8b8_unorm_pack_rgba_float,
&util_format_x8r8g8b8_unorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_a8b8g8r8_unorm_description = {
PIPE_FORMAT_A8B8G8R8_UNORM,
"PIPE_FORMAT_A8B8G8R8_UNORM",
"a8b8g8r8_unorm",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
4, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 0}, /* x = a */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 8}, /* y = b */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 16}, /* z = g */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 24} /* w = r */
},
{
UTIL_FORMAT_SWIZZLE_W, /* r */
UTIL_FORMAT_SWIZZLE_Z, /* g */
UTIL_FORMAT_SWIZZLE_Y, /* b */
UTIL_FORMAT_SWIZZLE_X /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_a8b8g8r8_unorm_unpack_rgba_8unorm,
&util_format_a8b8g8r8_unorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_a8b8g8r8_unorm_unpack_rgba_float,
&util_format_a8b8g8r8_unorm_pack_rgba_float,
&util_format_a8b8g8r8_unorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_x8b8g8r8_unorm_description = {
PIPE_FORMAT_X8B8G8R8_UNORM,
"PIPE_FORMAT_X8B8G8R8_UNORM",
"x8b8g8r8_unorm",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
4, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 0}, /* x = x */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 8}, /* y = b */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 16}, /* z = g */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 24} /* w = r */
},
{
UTIL_FORMAT_SWIZZLE_W, /* r */
UTIL_FORMAT_SWIZZLE_Z, /* g */
UTIL_FORMAT_SWIZZLE_Y, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_x8b8g8r8_unorm_unpack_rgba_8unorm,
&util_format_x8b8g8r8_unorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_x8b8g8r8_unorm_unpack_rgba_float,
&util_format_x8b8g8r8_unorm_pack_rgba_float,
&util_format_x8b8g8r8_unorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r8g8b8x8_unorm_description = {
PIPE_FORMAT_R8G8B8X8_UNORM,
"PIPE_FORMAT_R8G8B8X8_UNORM",
"r8g8b8x8_unorm",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
4, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 0}, /* x = r */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 8}, /* y = g */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 16}, /* z = b */
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 24} /* w = x */
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r8g8b8x8_unorm_unpack_rgba_8unorm,
&util_format_r8g8b8x8_unorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r8g8b8x8_unorm_unpack_rgba_float,
&util_format_r8g8b8x8_unorm_pack_rgba_float,
&util_format_r8g8b8x8_unorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_l8_unorm_description = {
PIPE_FORMAT_L8_UNORM,
"PIPE_FORMAT_L8_UNORM",
"l8_unorm",
{1, 1, 8}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 0}, /* x = rgb */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_X, /* g */
UTIL_FORMAT_SWIZZLE_X, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_l8_unorm_unpack_rgba_8unorm,
&util_format_l8_unorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_l8_unorm_unpack_rgba_float,
&util_format_l8_unorm_pack_rgba_float,
&util_format_l8_unorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_a8_unorm_description = {
PIPE_FORMAT_A8_UNORM,
"PIPE_FORMAT_A8_UNORM",
"a8_unorm",
{1, 1, 8}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 0}, /* x = a */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_0, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_X /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_a8_unorm_unpack_rgba_8unorm,
&util_format_a8_unorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_a8_unorm_unpack_rgba_float,
&util_format_a8_unorm_pack_rgba_float,
&util_format_a8_unorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_i8_unorm_description = {
PIPE_FORMAT_I8_UNORM,
"PIPE_FORMAT_I8_UNORM",
"i8_unorm",
{1, 1, 8}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 0}, /* x = rgba */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_X, /* g */
UTIL_FORMAT_SWIZZLE_X, /* b */
UTIL_FORMAT_SWIZZLE_X /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_i8_unorm_unpack_rgba_8unorm,
&util_format_i8_unorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_i8_unorm_unpack_rgba_float,
&util_format_i8_unorm_pack_rgba_float,
&util_format_i8_unorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_l4a4_unorm_description = {
PIPE_FORMAT_L4A4_UNORM,
"PIPE_FORMAT_L4A4_UNORM",
"l4a4_unorm",
{1, 1, 8}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
FALSE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 4, 0}, /* x = rgb */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 4, 4}, /* y = a */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_X, /* g */
UTIL_FORMAT_SWIZZLE_X, /* b */
UTIL_FORMAT_SWIZZLE_Y /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_l4a4_unorm_unpack_rgba_8unorm,
&util_format_l4a4_unorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_l4a4_unorm_unpack_rgba_float,
&util_format_l4a4_unorm_pack_rgba_float,
&util_format_l4a4_unorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_l8a8_unorm_description = {
PIPE_FORMAT_L8A8_UNORM,
"PIPE_FORMAT_L8A8_UNORM",
"l8a8_unorm",
{1, 1, 16}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 0}, /* x = rgb */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 8}, /* y = a */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_X, /* g */
UTIL_FORMAT_SWIZZLE_X, /* b */
UTIL_FORMAT_SWIZZLE_Y /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_l8a8_unorm_unpack_rgba_8unorm,
&util_format_l8a8_unorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_l8a8_unorm_unpack_rgba_float,
&util_format_l8a8_unorm_pack_rgba_float,
&util_format_l8a8_unorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_l16_unorm_description = {
PIPE_FORMAT_L16_UNORM,
"PIPE_FORMAT_L16_UNORM",
"l16_unorm",
{1, 1, 16}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 16, 0}, /* x = rgb */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_X, /* g */
UTIL_FORMAT_SWIZZLE_X, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_l16_unorm_unpack_rgba_8unorm,
&util_format_l16_unorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_l16_unorm_unpack_rgba_float,
&util_format_l16_unorm_pack_rgba_float,
&util_format_l16_unorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_a16_unorm_description = {
PIPE_FORMAT_A16_UNORM,
"PIPE_FORMAT_A16_UNORM",
"a16_unorm",
{1, 1, 16}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 16, 0}, /* x = a */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_0, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_X /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_a16_unorm_unpack_rgba_8unorm,
&util_format_a16_unorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_a16_unorm_unpack_rgba_float,
&util_format_a16_unorm_pack_rgba_float,
&util_format_a16_unorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_i16_unorm_description = {
PIPE_FORMAT_I16_UNORM,
"PIPE_FORMAT_I16_UNORM",
"i16_unorm",
{1, 1, 16}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 16, 0}, /* x = rgba */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_X, /* g */
UTIL_FORMAT_SWIZZLE_X, /* b */
UTIL_FORMAT_SWIZZLE_X /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_i16_unorm_unpack_rgba_8unorm,
&util_format_i16_unorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_i16_unorm_unpack_rgba_float,
&util_format_i16_unorm_pack_rgba_float,
&util_format_i16_unorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_l16a16_unorm_description = {
PIPE_FORMAT_L16A16_UNORM,
"PIPE_FORMAT_L16A16_UNORM",
"l16a16_unorm",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 16, 0}, /* x = rgb */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 16, 16}, /* y = a */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_X, /* g */
UTIL_FORMAT_SWIZZLE_X, /* b */
UTIL_FORMAT_SWIZZLE_Y /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_l16a16_unorm_unpack_rgba_8unorm,
&util_format_l16a16_unorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_l16a16_unorm_unpack_rgba_float,
&util_format_l16a16_unorm_pack_rgba_float,
&util_format_l16a16_unorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_a8_snorm_description = {
PIPE_FORMAT_A8_SNORM,
"PIPE_FORMAT_A8_SNORM",
"a8_snorm",
{1, 1, 8}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 0}, /* x = a */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_0, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_X /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_a8_snorm_unpack_rgba_8unorm,
&util_format_a8_snorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_a8_snorm_unpack_rgba_float,
&util_format_a8_snorm_pack_rgba_float,
&util_format_a8_snorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_l8_snorm_description = {
PIPE_FORMAT_L8_SNORM,
"PIPE_FORMAT_L8_SNORM",
"l8_snorm",
{1, 1, 8}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 0}, /* x = rgb */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_X, /* g */
UTIL_FORMAT_SWIZZLE_X, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_l8_snorm_unpack_rgba_8unorm,
&util_format_l8_snorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_l8_snorm_unpack_rgba_float,
&util_format_l8_snorm_pack_rgba_float,
&util_format_l8_snorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_l8a8_snorm_description = {
PIPE_FORMAT_L8A8_SNORM,
"PIPE_FORMAT_L8A8_SNORM",
"l8a8_snorm",
{1, 1, 16}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 0}, /* x = rgb */
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 8}, /* y = a */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_X, /* g */
UTIL_FORMAT_SWIZZLE_X, /* b */
UTIL_FORMAT_SWIZZLE_Y /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_l8a8_snorm_unpack_rgba_8unorm,
&util_format_l8a8_snorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_l8a8_snorm_unpack_rgba_float,
&util_format_l8a8_snorm_pack_rgba_float,
&util_format_l8a8_snorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_i8_snorm_description = {
PIPE_FORMAT_I8_SNORM,
"PIPE_FORMAT_I8_SNORM",
"i8_snorm",
{1, 1, 8}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 0}, /* x = rgba */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_X, /* g */
UTIL_FORMAT_SWIZZLE_X, /* b */
UTIL_FORMAT_SWIZZLE_X /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_i8_snorm_unpack_rgba_8unorm,
&util_format_i8_snorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_i8_snorm_unpack_rgba_float,
&util_format_i8_snorm_pack_rgba_float,
&util_format_i8_snorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_a16_snorm_description = {
PIPE_FORMAT_A16_SNORM,
"PIPE_FORMAT_A16_SNORM",
"a16_snorm",
{1, 1, 16}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 16, 0}, /* x = a */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_0, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_X /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_a16_snorm_unpack_rgba_8unorm,
&util_format_a16_snorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_a16_snorm_unpack_rgba_float,
&util_format_a16_snorm_pack_rgba_float,
&util_format_a16_snorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_l16_snorm_description = {
PIPE_FORMAT_L16_SNORM,
"PIPE_FORMAT_L16_SNORM",
"l16_snorm",
{1, 1, 16}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 16, 0}, /* x = rgb */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_X, /* g */
UTIL_FORMAT_SWIZZLE_X, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_l16_snorm_unpack_rgba_8unorm,
&util_format_l16_snorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_l16_snorm_unpack_rgba_float,
&util_format_l16_snorm_pack_rgba_float,
&util_format_l16_snorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_l16a16_snorm_description = {
PIPE_FORMAT_L16A16_SNORM,
"PIPE_FORMAT_L16A16_SNORM",
"l16a16_snorm",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 16, 0}, /* x = rgb */
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 16, 16}, /* y = a */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_X, /* g */
UTIL_FORMAT_SWIZZLE_X, /* b */
UTIL_FORMAT_SWIZZLE_Y /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_l16a16_snorm_unpack_rgba_8unorm,
&util_format_l16a16_snorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_l16a16_snorm_unpack_rgba_float,
&util_format_l16a16_snorm_pack_rgba_float,
&util_format_l16a16_snorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_i16_snorm_description = {
PIPE_FORMAT_I16_SNORM,
"PIPE_FORMAT_I16_SNORM",
"i16_snorm",
{1, 1, 16}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 16, 0}, /* x = rgba */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_X, /* g */
UTIL_FORMAT_SWIZZLE_X, /* b */
UTIL_FORMAT_SWIZZLE_X /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_i16_snorm_unpack_rgba_8unorm,
&util_format_i16_snorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_i16_snorm_unpack_rgba_float,
&util_format_i16_snorm_pack_rgba_float,
&util_format_i16_snorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_a16_float_description = {
PIPE_FORMAT_A16_FLOAT,
"PIPE_FORMAT_A16_FLOAT",
"a16_float",
{1, 1, 16}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 16, 0}, /* x = a */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_0, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_X /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_a16_float_unpack_rgba_8unorm,
&util_format_a16_float_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_a16_float_unpack_rgba_float,
&util_format_a16_float_pack_rgba_float,
&util_format_a16_float_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_l16_float_description = {
PIPE_FORMAT_L16_FLOAT,
"PIPE_FORMAT_L16_FLOAT",
"l16_float",
{1, 1, 16}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 16, 0}, /* x = rgb */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_X, /* g */
UTIL_FORMAT_SWIZZLE_X, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_l16_float_unpack_rgba_8unorm,
&util_format_l16_float_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_l16_float_unpack_rgba_float,
&util_format_l16_float_pack_rgba_float,
&util_format_l16_float_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_l16a16_float_description = {
PIPE_FORMAT_L16A16_FLOAT,
"PIPE_FORMAT_L16A16_FLOAT",
"l16a16_float",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 16, 0}, /* x = rgb */
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 16, 16}, /* y = a */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_X, /* g */
UTIL_FORMAT_SWIZZLE_X, /* b */
UTIL_FORMAT_SWIZZLE_Y /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_l16a16_float_unpack_rgba_8unorm,
&util_format_l16a16_float_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_l16a16_float_unpack_rgba_float,
&util_format_l16a16_float_pack_rgba_float,
&util_format_l16a16_float_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_i16_float_description = {
PIPE_FORMAT_I16_FLOAT,
"PIPE_FORMAT_I16_FLOAT",
"i16_float",
{1, 1, 16}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 16, 0}, /* x = rgba */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_X, /* g */
UTIL_FORMAT_SWIZZLE_X, /* b */
UTIL_FORMAT_SWIZZLE_X /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_i16_float_unpack_rgba_8unorm,
&util_format_i16_float_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_i16_float_unpack_rgba_float,
&util_format_i16_float_pack_rgba_float,
&util_format_i16_float_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_a32_float_description = {
PIPE_FORMAT_A32_FLOAT,
"PIPE_FORMAT_A32_FLOAT",
"a32_float",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 32, 0}, /* x = a */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_0, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_X /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_a32_float_unpack_rgba_8unorm,
&util_format_a32_float_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_a32_float_unpack_rgba_float,
&util_format_a32_float_pack_rgba_float,
&util_format_a32_float_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_l32_float_description = {
PIPE_FORMAT_L32_FLOAT,
"PIPE_FORMAT_L32_FLOAT",
"l32_float",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 32, 0}, /* x = rgb */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_X, /* g */
UTIL_FORMAT_SWIZZLE_X, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_l32_float_unpack_rgba_8unorm,
&util_format_l32_float_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_l32_float_unpack_rgba_float,
&util_format_l32_float_pack_rgba_float,
&util_format_l32_float_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_l32a32_float_description = {
PIPE_FORMAT_L32A32_FLOAT,
"PIPE_FORMAT_L32A32_FLOAT",
"l32a32_float",
{1, 1, 64}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 32, 0}, /* x = rgb */
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 32, 32}, /* y = a */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_X, /* g */
UTIL_FORMAT_SWIZZLE_X, /* b */
UTIL_FORMAT_SWIZZLE_Y /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_l32a32_float_unpack_rgba_8unorm,
&util_format_l32a32_float_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_l32a32_float_unpack_rgba_float,
&util_format_l32a32_float_pack_rgba_float,
&util_format_l32a32_float_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_i32_float_description = {
PIPE_FORMAT_I32_FLOAT,
"PIPE_FORMAT_I32_FLOAT",
"i32_float",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 32, 0}, /* x = rgba */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_X, /* g */
UTIL_FORMAT_SWIZZLE_X, /* b */
UTIL_FORMAT_SWIZZLE_X /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_i32_float_unpack_rgba_8unorm,
&util_format_i32_float_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_i32_float_unpack_rgba_float,
&util_format_i32_float_pack_rgba_float,
&util_format_i32_float_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r8sg8sb8ux8u_norm_description = {
PIPE_FORMAT_R8SG8SB8UX8U_NORM,
"PIPE_FORMAT_R8SG8SB8UX8U_NORM",
"r8sg8sb8ux8u_norm",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
4, /* nr_channels */
FALSE, /* is_array */
TRUE, /* is_bitmask */
TRUE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 0}, /* x = r */
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 8}, /* y = g */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 16}, /* z = b */
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 24} /* w = x */
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r8sg8sb8ux8u_norm_unpack_rgba_8unorm,
&util_format_r8sg8sb8ux8u_norm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r8sg8sb8ux8u_norm_unpack_rgba_float,
&util_format_r8sg8sb8ux8u_norm_pack_rgba_float,
&util_format_r8sg8sb8ux8u_norm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r5sg5sb6u_norm_description = {
PIPE_FORMAT_R5SG5SB6U_NORM,
"PIPE_FORMAT_R5SG5SB6U_NORM",
"r5sg5sb6u_norm",
{1, 1, 16}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
3, /* nr_channels */
FALSE, /* is_array */
TRUE, /* is_bitmask */
TRUE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 5, 0}, /* x = r */
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 5, 5}, /* y = g */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 6, 10}, /* z = b */
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r5sg5sb6u_norm_unpack_rgba_8unorm,
&util_format_r5sg5sb6u_norm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r5sg5sb6u_norm_unpack_rgba_float,
&util_format_r5sg5sb6u_norm_pack_rgba_float,
&util_format_r5sg5sb6u_norm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_s8_uint_description = {
PIPE_FORMAT_S8_UINT,
"PIPE_FORMAT_S8_UINT",
"s8_uint",
{1, 1, 8}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 0}, /* x = s */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_NONE, /* z */
UTIL_FORMAT_SWIZZLE_X, /* s */
UTIL_FORMAT_SWIZZLE_NONE, /* ignored */
UTIL_FORMAT_SWIZZLE_NONE /* ignored */
},
UTIL_FORMAT_COLORSPACE_ZS,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
&util_format_s8_uint_unpack_s_8uint,
&util_format_s8_uint_pack_s_8uint,
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_z16_unorm_description = {
PIPE_FORMAT_Z16_UNORM,
"PIPE_FORMAT_Z16_UNORM",
"z16_unorm",
{1, 1, 16}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 16, 0}, /* x = z */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* z */
UTIL_FORMAT_SWIZZLE_NONE, /* s */
UTIL_FORMAT_SWIZZLE_NONE, /* ignored */
UTIL_FORMAT_SWIZZLE_NONE /* ignored */
},
UTIL_FORMAT_COLORSPACE_ZS,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
&util_format_z16_unorm_unpack_z_32unorm,
&util_format_z16_unorm_pack_z_32unorm,
&util_format_z16_unorm_unpack_z_float,
&util_format_z16_unorm_pack_z_float,
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_z32_unorm_description = {
PIPE_FORMAT_Z32_UNORM,
"PIPE_FORMAT_Z32_UNORM",
"z32_unorm",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 32, 0}, /* x = z */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* z */
UTIL_FORMAT_SWIZZLE_NONE, /* s */
UTIL_FORMAT_SWIZZLE_NONE, /* ignored */
UTIL_FORMAT_SWIZZLE_NONE /* ignored */
},
UTIL_FORMAT_COLORSPACE_ZS,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
&util_format_z32_unorm_unpack_z_32unorm,
&util_format_z32_unorm_pack_z_32unorm,
&util_format_z32_unorm_unpack_z_float,
&util_format_z32_unorm_pack_z_float,
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_z32_float_description = {
PIPE_FORMAT_Z32_FLOAT,
"PIPE_FORMAT_Z32_FLOAT",
"z32_float",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 32, 0}, /* x = z */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* z */
UTIL_FORMAT_SWIZZLE_NONE, /* s */
UTIL_FORMAT_SWIZZLE_NONE, /* ignored */
UTIL_FORMAT_SWIZZLE_NONE /* ignored */
},
UTIL_FORMAT_COLORSPACE_ZS,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
&util_format_z32_float_unpack_z_32unorm,
&util_format_z32_float_pack_z_32unorm,
&util_format_z32_float_unpack_z_float,
&util_format_z32_float_pack_z_float,
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_z24_unorm_s8_uint_description = {
PIPE_FORMAT_Z24_UNORM_S8_UINT,
"PIPE_FORMAT_Z24_UNORM_S8_UINT",
"z24_unorm_s8_uint",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
FALSE, /* is_array */
TRUE, /* is_bitmask */
TRUE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 24, 0}, /* x = z */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 24}, /* y = s */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* z */
UTIL_FORMAT_SWIZZLE_Y, /* s */
UTIL_FORMAT_SWIZZLE_NONE, /* ignored */
UTIL_FORMAT_SWIZZLE_NONE /* ignored */
},
UTIL_FORMAT_COLORSPACE_ZS,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
&util_format_z24_unorm_s8_uint_unpack_z_32unorm,
&util_format_z24_unorm_s8_uint_pack_z_32unorm,
&util_format_z24_unorm_s8_uint_unpack_z_float,
&util_format_z24_unorm_s8_uint_pack_z_float,
&util_format_z24_unorm_s8_uint_unpack_s_8uint,
&util_format_z24_unorm_s8_uint_pack_s_8uint,
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_s8_uint_z24_unorm_description = {
PIPE_FORMAT_S8_UINT_Z24_UNORM,
"PIPE_FORMAT_S8_UINT_Z24_UNORM",
"s8_uint_z24_unorm",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
FALSE, /* is_array */
TRUE, /* is_bitmask */
TRUE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 0}, /* x = s */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 24, 8}, /* y = z */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_Y, /* z */
UTIL_FORMAT_SWIZZLE_X, /* s */
UTIL_FORMAT_SWIZZLE_NONE, /* ignored */
UTIL_FORMAT_SWIZZLE_NONE /* ignored */
},
UTIL_FORMAT_COLORSPACE_ZS,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
&util_format_s8_uint_z24_unorm_unpack_z_32unorm,
&util_format_s8_uint_z24_unorm_pack_z_32unorm,
&util_format_s8_uint_z24_unorm_unpack_z_float,
&util_format_s8_uint_z24_unorm_pack_z_float,
&util_format_s8_uint_z24_unorm_unpack_s_8uint,
&util_format_s8_uint_z24_unorm_pack_s_8uint,
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_x24s8_uint_description = {
PIPE_FORMAT_X24S8_UINT,
"PIPE_FORMAT_X24S8_UINT",
"x24s8_uint",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
FALSE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 24, 0}, /* x = x */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 24}, /* y = s */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_NONE, /* z */
UTIL_FORMAT_SWIZZLE_Y, /* s */
UTIL_FORMAT_SWIZZLE_NONE, /* ignored */
UTIL_FORMAT_SWIZZLE_NONE /* ignored */
},
UTIL_FORMAT_COLORSPACE_ZS,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
&util_format_x24s8_uint_unpack_s_8uint,
&util_format_x24s8_uint_pack_s_8uint,
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_s8x24_uint_description = {
PIPE_FORMAT_S8X24_UINT,
"PIPE_FORMAT_S8X24_UINT",
"s8x24_uint",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
FALSE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 0}, /* x = s */
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 24, 8}, /* y = x */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_NONE, /* z */
UTIL_FORMAT_SWIZZLE_X, /* s */
UTIL_FORMAT_SWIZZLE_NONE, /* ignored */
UTIL_FORMAT_SWIZZLE_NONE /* ignored */
},
UTIL_FORMAT_COLORSPACE_ZS,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
&util_format_s8x24_uint_unpack_s_8uint,
&util_format_s8x24_uint_pack_s_8uint,
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_z24x8_unorm_description = {
PIPE_FORMAT_Z24X8_UNORM,
"PIPE_FORMAT_Z24X8_UNORM",
"z24x8_unorm",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
FALSE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 24, 0}, /* x = z */
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 24}, /* y = x */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* z */
UTIL_FORMAT_SWIZZLE_NONE, /* s */
UTIL_FORMAT_SWIZZLE_NONE, /* ignored */
UTIL_FORMAT_SWIZZLE_NONE /* ignored */
},
UTIL_FORMAT_COLORSPACE_ZS,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
&util_format_z24x8_unorm_unpack_z_32unorm,
&util_format_z24x8_unorm_pack_z_32unorm,
&util_format_z24x8_unorm_unpack_z_float,
&util_format_z24x8_unorm_pack_z_float,
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_x8z24_unorm_description = {
PIPE_FORMAT_X8Z24_UNORM,
"PIPE_FORMAT_X8Z24_UNORM",
"x8z24_unorm",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
FALSE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 0}, /* x = x */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 24, 8}, /* y = z */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_Y, /* z */
UTIL_FORMAT_SWIZZLE_NONE, /* s */
UTIL_FORMAT_SWIZZLE_NONE, /* ignored */
UTIL_FORMAT_SWIZZLE_NONE /* ignored */
},
UTIL_FORMAT_COLORSPACE_ZS,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
&util_format_x8z24_unorm_unpack_z_32unorm,
&util_format_x8z24_unorm_pack_z_32unorm,
&util_format_x8z24_unorm_unpack_z_float,
&util_format_x8z24_unorm_pack_z_float,
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_z32_float_s8x24_uint_description = {
PIPE_FORMAT_Z32_FLOAT_S8X24_UINT,
"PIPE_FORMAT_Z32_FLOAT_S8X24_UINT",
"z32_float_s8x24_uint",
{1, 1, 64}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
3, /* nr_channels */
FALSE, /* is_array */
FALSE, /* is_bitmask */
TRUE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 32, 0}, /* x = z */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 32}, /* y = s */
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 24, 40}, /* z = x */
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* z */
UTIL_FORMAT_SWIZZLE_Y, /* s */
UTIL_FORMAT_SWIZZLE_NONE, /* ignored */
UTIL_FORMAT_SWIZZLE_NONE /* ignored */
},
UTIL_FORMAT_COLORSPACE_ZS,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
&util_format_z32_float_s8x24_uint_unpack_z_32unorm,
&util_format_z32_float_s8x24_uint_pack_z_32unorm,
&util_format_z32_float_s8x24_uint_unpack_z_float,
&util_format_z32_float_s8x24_uint_pack_z_float,
&util_format_z32_float_s8x24_uint_unpack_s_8uint,
&util_format_z32_float_s8x24_uint_pack_s_8uint,
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_x32_s8x24_uint_description = {
PIPE_FORMAT_X32_S8X24_UINT,
"PIPE_FORMAT_X32_S8X24_UINT",
"x32_s8x24_uint",
{1, 1, 64}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
3, /* nr_channels */
FALSE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 32, 0}, /* x = x */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 32}, /* y = s */
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 24, 40}, /* z = x */
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_NONE, /* z */
UTIL_FORMAT_SWIZZLE_Y, /* s */
UTIL_FORMAT_SWIZZLE_NONE, /* ignored */
UTIL_FORMAT_SWIZZLE_NONE /* ignored */
},
UTIL_FORMAT_COLORSPACE_ZS,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
&util_format_x32_s8x24_uint_unpack_s_8uint,
&util_format_x32_s8x24_uint_pack_s_8uint,
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_uyvy_description = {
PIPE_FORMAT_UYVY,
"PIPE_FORMAT_UYVY",
"uyvy",
{2, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_SUBSAMPLED,
1, /* nr_channels */
FALSE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 32, 0}, /* x = x */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* y */
UTIL_FORMAT_SWIZZLE_Y, /* u */
UTIL_FORMAT_SWIZZLE_Z, /* v */
UTIL_FORMAT_SWIZZLE_1 /* ignored */
},
UTIL_FORMAT_COLORSPACE_YUV,
&util_format_uyvy_unpack_rgba_8unorm,
&util_format_uyvy_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_uyvy_unpack_rgba_float,
&util_format_uyvy_pack_rgba_float,
&util_format_uyvy_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_yuyv_description = {
PIPE_FORMAT_YUYV,
"PIPE_FORMAT_YUYV",
"yuyv",
{2, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_SUBSAMPLED,
1, /* nr_channels */
FALSE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 32, 0}, /* x = x */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* y */
UTIL_FORMAT_SWIZZLE_Y, /* u */
UTIL_FORMAT_SWIZZLE_Z, /* v */
UTIL_FORMAT_SWIZZLE_1 /* ignored */
},
UTIL_FORMAT_COLORSPACE_YUV,
&util_format_yuyv_unpack_rgba_8unorm,
&util_format_yuyv_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_yuyv_unpack_rgba_float,
&util_format_yuyv_pack_rgba_float,
&util_format_yuyv_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r8g8_b8g8_unorm_description = {
PIPE_FORMAT_R8G8_B8G8_UNORM,
"PIPE_FORMAT_R8G8_B8G8_UNORM",
"r8g8_b8g8_unorm",
{2, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_SUBSAMPLED,
1, /* nr_channels */
FALSE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 32, 0}, /* x = x */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r8g8_b8g8_unorm_unpack_rgba_8unorm,
&util_format_r8g8_b8g8_unorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r8g8_b8g8_unorm_unpack_rgba_float,
&util_format_r8g8_b8g8_unorm_pack_rgba_float,
&util_format_r8g8_b8g8_unorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_g8r8_g8b8_unorm_description = {
PIPE_FORMAT_G8R8_G8B8_UNORM,
"PIPE_FORMAT_G8R8_G8B8_UNORM",
"g8r8_g8b8_unorm",
{2, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_SUBSAMPLED,
1, /* nr_channels */
FALSE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 32, 0}, /* x = x */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_g8r8_g8b8_unorm_unpack_rgba_8unorm,
&util_format_g8r8_g8b8_unorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_g8r8_g8b8_unorm_unpack_rgba_float,
&util_format_g8r8_g8b8_unorm_pack_rgba_float,
&util_format_g8r8_g8b8_unorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_g8r8_b8r8_unorm_description = {
PIPE_FORMAT_G8R8_B8R8_UNORM,
"PIPE_FORMAT_G8R8_B8R8_UNORM",
"g8r8_b8r8_unorm",
{2, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_SUBSAMPLED,
1, /* nr_channels */
FALSE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 32, 0}, /* x = x */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_Y, /* r */
UTIL_FORMAT_SWIZZLE_X, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_g8r8_b8r8_unorm_unpack_rgba_8unorm,
&util_format_g8r8_b8r8_unorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_g8r8_b8r8_unorm_unpack_rgba_float,
&util_format_g8r8_b8r8_unorm_pack_rgba_float,
&util_format_g8r8_b8r8_unorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r8g8_r8b8_unorm_description = {
PIPE_FORMAT_R8G8_R8B8_UNORM,
"PIPE_FORMAT_R8G8_R8B8_UNORM",
"r8g8_r8b8_unorm",
{2, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_SUBSAMPLED,
1, /* nr_channels */
FALSE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 32, 0}, /* x = x */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_Y, /* r */
UTIL_FORMAT_SWIZZLE_X, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r8g8_r8b8_unorm_unpack_rgba_8unorm,
&util_format_r8g8_r8b8_unorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r8g8_r8b8_unorm_unpack_rgba_float,
&util_format_r8g8_r8b8_unorm_pack_rgba_float,
&util_format_r8g8_r8b8_unorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r11g11b10_float_description = {
PIPE_FORMAT_R11G11B10_FLOAT,
"PIPE_FORMAT_R11G11B10_FLOAT",
"r11g11b10_float",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_OTHER,
1, /* nr_channels */
FALSE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 32, 0}, /* x = x */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r11g11b10_float_unpack_rgba_8unorm,
&util_format_r11g11b10_float_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r11g11b10_float_unpack_rgba_float,
&util_format_r11g11b10_float_pack_rgba_float,
&util_format_r11g11b10_float_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r9g9b9e5_float_description = {
PIPE_FORMAT_R9G9B9E5_FLOAT,
"PIPE_FORMAT_R9G9B9E5_FLOAT",
"r9g9b9e5_float",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_OTHER,
1, /* nr_channels */
FALSE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 32, 0}, /* x = x */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r9g9b9e5_float_unpack_rgba_8unorm,
&util_format_r9g9b9e5_float_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r9g9b9e5_float_unpack_rgba_float,
&util_format_r9g9b9e5_float_pack_rgba_float,
&util_format_r9g9b9e5_float_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r1_unorm_description = {
PIPE_FORMAT_R1_UNORM,
"PIPE_FORMAT_R1_UNORM",
"r1_unorm",
{8, 1, 8}, /* block */
UTIL_FORMAT_LAYOUT_OTHER,
1, /* nr_channels */
FALSE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 0}, /* x = x */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r1_unorm_unpack_rgba_8unorm,
&util_format_r1_unorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r1_unorm_unpack_rgba_float,
&util_format_r1_unorm_pack_rgba_float,
&util_format_r1_unorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r8g8bx_snorm_description = {
PIPE_FORMAT_R8G8Bx_SNORM,
"PIPE_FORMAT_R8G8Bx_SNORM",
"r8g8bx_snorm",
{1, 1, 16}, /* block */
UTIL_FORMAT_LAYOUT_OTHER,
2, /* nr_channels */
FALSE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 0}, /* x = x */
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 8}, /* y = y */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r8g8bx_snorm_unpack_rgba_8unorm,
&util_format_r8g8bx_snorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r8g8bx_snorm_unpack_rgba_float,
&util_format_r8g8bx_snorm_pack_rgba_float,
&util_format_r8g8bx_snorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r64_float_description = {
PIPE_FORMAT_R64_FLOAT,
"PIPE_FORMAT_R64_FLOAT",
"r64_float",
{1, 1, 64}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 64, 0}, /* x = r */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r64_float_unpack_rgba_8unorm,
&util_format_r64_float_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r64_float_unpack_rgba_float,
&util_format_r64_float_pack_rgba_float,
&util_format_r64_float_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r64g64_float_description = {
PIPE_FORMAT_R64G64_FLOAT,
"PIPE_FORMAT_R64G64_FLOAT",
"r64g64_float",
{1, 1, 128}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 64, 0}, /* x = r */
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 64, 64}, /* y = g */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r64g64_float_unpack_rgba_8unorm,
&util_format_r64g64_float_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r64g64_float_unpack_rgba_float,
&util_format_r64g64_float_pack_rgba_float,
&util_format_r64g64_float_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r64g64b64_float_description = {
PIPE_FORMAT_R64G64B64_FLOAT,
"PIPE_FORMAT_R64G64B64_FLOAT",
"r64g64b64_float",
{1, 1, 192}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
3, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 64, 0}, /* x = r */
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 64, 64}, /* y = g */
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 64, 128}, /* z = b */
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r64g64b64_float_unpack_rgba_8unorm,
&util_format_r64g64b64_float_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r64g64b64_float_unpack_rgba_float,
&util_format_r64g64b64_float_pack_rgba_float,
&util_format_r64g64b64_float_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r64g64b64a64_float_description = {
PIPE_FORMAT_R64G64B64A64_FLOAT,
"PIPE_FORMAT_R64G64B64A64_FLOAT",
"r64g64b64a64_float",
{1, 1, 256}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
4, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 64, 0}, /* x = r */
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 64, 64}, /* y = g */
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 64, 128}, /* z = b */
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 64, 192} /* w = a */
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_W /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r64g64b64a64_float_unpack_rgba_8unorm,
&util_format_r64g64b64a64_float_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r64g64b64a64_float_unpack_rgba_float,
&util_format_r64g64b64a64_float_pack_rgba_float,
&util_format_r64g64b64a64_float_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r32_float_description = {
PIPE_FORMAT_R32_FLOAT,
"PIPE_FORMAT_R32_FLOAT",
"r32_float",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 32, 0}, /* x = r */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r32_float_unpack_rgba_8unorm,
&util_format_r32_float_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r32_float_unpack_rgba_float,
&util_format_r32_float_pack_rgba_float,
&util_format_r32_float_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r32g32_float_description = {
PIPE_FORMAT_R32G32_FLOAT,
"PIPE_FORMAT_R32G32_FLOAT",
"r32g32_float",
{1, 1, 64}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 32, 0}, /* x = r */
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 32, 32}, /* y = g */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r32g32_float_unpack_rgba_8unorm,
&util_format_r32g32_float_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r32g32_float_unpack_rgba_float,
&util_format_r32g32_float_pack_rgba_float,
&util_format_r32g32_float_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r32g32b32_float_description = {
PIPE_FORMAT_R32G32B32_FLOAT,
"PIPE_FORMAT_R32G32B32_FLOAT",
"r32g32b32_float",
{1, 1, 96}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
3, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 32, 0}, /* x = r */
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 32, 32}, /* y = g */
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 32, 64}, /* z = b */
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r32g32b32_float_unpack_rgba_8unorm,
&util_format_r32g32b32_float_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r32g32b32_float_unpack_rgba_float,
&util_format_r32g32b32_float_pack_rgba_float,
&util_format_r32g32b32_float_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r32g32b32a32_float_description = {
PIPE_FORMAT_R32G32B32A32_FLOAT,
"PIPE_FORMAT_R32G32B32A32_FLOAT",
"r32g32b32a32_float",
{1, 1, 128}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
4, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 32, 0}, /* x = r */
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 32, 32}, /* y = g */
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 32, 64}, /* z = b */
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 32, 96} /* w = a */
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_W /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r32g32b32a32_float_unpack_rgba_8unorm,
&util_format_r32g32b32a32_float_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r32g32b32a32_float_unpack_rgba_float,
&util_format_r32g32b32a32_float_pack_rgba_float,
&util_format_r32g32b32a32_float_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r32_unorm_description = {
PIPE_FORMAT_R32_UNORM,
"PIPE_FORMAT_R32_UNORM",
"r32_unorm",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 32, 0}, /* x = r */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r32_unorm_unpack_rgba_8unorm,
&util_format_r32_unorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r32_unorm_unpack_rgba_float,
&util_format_r32_unorm_pack_rgba_float,
&util_format_r32_unorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r32g32_unorm_description = {
PIPE_FORMAT_R32G32_UNORM,
"PIPE_FORMAT_R32G32_UNORM",
"r32g32_unorm",
{1, 1, 64}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 32, 0}, /* x = r */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 32, 32}, /* y = g */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r32g32_unorm_unpack_rgba_8unorm,
&util_format_r32g32_unorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r32g32_unorm_unpack_rgba_float,
&util_format_r32g32_unorm_pack_rgba_float,
&util_format_r32g32_unorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r32g32b32_unorm_description = {
PIPE_FORMAT_R32G32B32_UNORM,
"PIPE_FORMAT_R32G32B32_UNORM",
"r32g32b32_unorm",
{1, 1, 96}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
3, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 32, 0}, /* x = r */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 32, 32}, /* y = g */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 32, 64}, /* z = b */
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r32g32b32_unorm_unpack_rgba_8unorm,
&util_format_r32g32b32_unorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r32g32b32_unorm_unpack_rgba_float,
&util_format_r32g32b32_unorm_pack_rgba_float,
&util_format_r32g32b32_unorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r32g32b32a32_unorm_description = {
PIPE_FORMAT_R32G32B32A32_UNORM,
"PIPE_FORMAT_R32G32B32A32_UNORM",
"r32g32b32a32_unorm",
{1, 1, 128}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
4, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 32, 0}, /* x = r */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 32, 32}, /* y = g */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 32, 64}, /* z = b */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 32, 96} /* w = a */
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_W /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r32g32b32a32_unorm_unpack_rgba_8unorm,
&util_format_r32g32b32a32_unorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r32g32b32a32_unorm_unpack_rgba_float,
&util_format_r32g32b32a32_unorm_pack_rgba_float,
&util_format_r32g32b32a32_unorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r32_uscaled_description = {
PIPE_FORMAT_R32_USCALED,
"PIPE_FORMAT_R32_USCALED",
"r32_uscaled",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 32, 0}, /* x = r */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r32_uscaled_unpack_rgba_8unorm,
&util_format_r32_uscaled_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r32_uscaled_unpack_rgba_float,
&util_format_r32_uscaled_pack_rgba_float,
&util_format_r32_uscaled_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r32g32_uscaled_description = {
PIPE_FORMAT_R32G32_USCALED,
"PIPE_FORMAT_R32G32_USCALED",
"r32g32_uscaled",
{1, 1, 64}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 32, 0}, /* x = r */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 32, 32}, /* y = g */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r32g32_uscaled_unpack_rgba_8unorm,
&util_format_r32g32_uscaled_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r32g32_uscaled_unpack_rgba_float,
&util_format_r32g32_uscaled_pack_rgba_float,
&util_format_r32g32_uscaled_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r32g32b32_uscaled_description = {
PIPE_FORMAT_R32G32B32_USCALED,
"PIPE_FORMAT_R32G32B32_USCALED",
"r32g32b32_uscaled",
{1, 1, 96}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
3, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 32, 0}, /* x = r */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 32, 32}, /* y = g */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 32, 64}, /* z = b */
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r32g32b32_uscaled_unpack_rgba_8unorm,
&util_format_r32g32b32_uscaled_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r32g32b32_uscaled_unpack_rgba_float,
&util_format_r32g32b32_uscaled_pack_rgba_float,
&util_format_r32g32b32_uscaled_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r32g32b32a32_uscaled_description = {
PIPE_FORMAT_R32G32B32A32_USCALED,
"PIPE_FORMAT_R32G32B32A32_USCALED",
"r32g32b32a32_uscaled",
{1, 1, 128}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
4, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 32, 0}, /* x = r */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 32, 32}, /* y = g */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 32, 64}, /* z = b */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 32, 96} /* w = a */
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_W /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r32g32b32a32_uscaled_unpack_rgba_8unorm,
&util_format_r32g32b32a32_uscaled_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r32g32b32a32_uscaled_unpack_rgba_float,
&util_format_r32g32b32a32_uscaled_pack_rgba_float,
&util_format_r32g32b32a32_uscaled_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r32_snorm_description = {
PIPE_FORMAT_R32_SNORM,
"PIPE_FORMAT_R32_SNORM",
"r32_snorm",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 32, 0}, /* x = r */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r32_snorm_unpack_rgba_8unorm,
&util_format_r32_snorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r32_snorm_unpack_rgba_float,
&util_format_r32_snorm_pack_rgba_float,
&util_format_r32_snorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r32g32_snorm_description = {
PIPE_FORMAT_R32G32_SNORM,
"PIPE_FORMAT_R32G32_SNORM",
"r32g32_snorm",
{1, 1, 64}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 32, 0}, /* x = r */
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 32, 32}, /* y = g */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r32g32_snorm_unpack_rgba_8unorm,
&util_format_r32g32_snorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r32g32_snorm_unpack_rgba_float,
&util_format_r32g32_snorm_pack_rgba_float,
&util_format_r32g32_snorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r32g32b32_snorm_description = {
PIPE_FORMAT_R32G32B32_SNORM,
"PIPE_FORMAT_R32G32B32_SNORM",
"r32g32b32_snorm",
{1, 1, 96}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
3, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 32, 0}, /* x = r */
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 32, 32}, /* y = g */
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 32, 64}, /* z = b */
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r32g32b32_snorm_unpack_rgba_8unorm,
&util_format_r32g32b32_snorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r32g32b32_snorm_unpack_rgba_float,
&util_format_r32g32b32_snorm_pack_rgba_float,
&util_format_r32g32b32_snorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r32g32b32a32_snorm_description = {
PIPE_FORMAT_R32G32B32A32_SNORM,
"PIPE_FORMAT_R32G32B32A32_SNORM",
"r32g32b32a32_snorm",
{1, 1, 128}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
4, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 32, 0}, /* x = r */
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 32, 32}, /* y = g */
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 32, 64}, /* z = b */
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 32, 96} /* w = a */
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_W /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r32g32b32a32_snorm_unpack_rgba_8unorm,
&util_format_r32g32b32a32_snorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r32g32b32a32_snorm_unpack_rgba_float,
&util_format_r32g32b32a32_snorm_pack_rgba_float,
&util_format_r32g32b32a32_snorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r32_sscaled_description = {
PIPE_FORMAT_R32_SSCALED,
"PIPE_FORMAT_R32_SSCALED",
"r32_sscaled",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 32, 0}, /* x = r */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r32_sscaled_unpack_rgba_8unorm,
&util_format_r32_sscaled_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r32_sscaled_unpack_rgba_float,
&util_format_r32_sscaled_pack_rgba_float,
&util_format_r32_sscaled_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r32g32_sscaled_description = {
PIPE_FORMAT_R32G32_SSCALED,
"PIPE_FORMAT_R32G32_SSCALED",
"r32g32_sscaled",
{1, 1, 64}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 32, 0}, /* x = r */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 32, 32}, /* y = g */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r32g32_sscaled_unpack_rgba_8unorm,
&util_format_r32g32_sscaled_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r32g32_sscaled_unpack_rgba_float,
&util_format_r32g32_sscaled_pack_rgba_float,
&util_format_r32g32_sscaled_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r32g32b32_sscaled_description = {
PIPE_FORMAT_R32G32B32_SSCALED,
"PIPE_FORMAT_R32G32B32_SSCALED",
"r32g32b32_sscaled",
{1, 1, 96}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
3, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 32, 0}, /* x = r */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 32, 32}, /* y = g */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 32, 64}, /* z = b */
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r32g32b32_sscaled_unpack_rgba_8unorm,
&util_format_r32g32b32_sscaled_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r32g32b32_sscaled_unpack_rgba_float,
&util_format_r32g32b32_sscaled_pack_rgba_float,
&util_format_r32g32b32_sscaled_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r32g32b32a32_sscaled_description = {
PIPE_FORMAT_R32G32B32A32_SSCALED,
"PIPE_FORMAT_R32G32B32A32_SSCALED",
"r32g32b32a32_sscaled",
{1, 1, 128}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
4, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 32, 0}, /* x = r */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 32, 32}, /* y = g */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 32, 64}, /* z = b */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 32, 96} /* w = a */
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_W /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r32g32b32a32_sscaled_unpack_rgba_8unorm,
&util_format_r32g32b32a32_sscaled_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r32g32b32a32_sscaled_unpack_rgba_float,
&util_format_r32g32b32a32_sscaled_pack_rgba_float,
&util_format_r32g32b32a32_sscaled_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r16_float_description = {
PIPE_FORMAT_R16_FLOAT,
"PIPE_FORMAT_R16_FLOAT",
"r16_float",
{1, 1, 16}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 16, 0}, /* x = r */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r16_float_unpack_rgba_8unorm,
&util_format_r16_float_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r16_float_unpack_rgba_float,
&util_format_r16_float_pack_rgba_float,
&util_format_r16_float_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r16g16_float_description = {
PIPE_FORMAT_R16G16_FLOAT,
"PIPE_FORMAT_R16G16_FLOAT",
"r16g16_float",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 16, 0}, /* x = r */
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 16, 16}, /* y = g */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r16g16_float_unpack_rgba_8unorm,
&util_format_r16g16_float_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r16g16_float_unpack_rgba_float,
&util_format_r16g16_float_pack_rgba_float,
&util_format_r16g16_float_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r16g16b16_float_description = {
PIPE_FORMAT_R16G16B16_FLOAT,
"PIPE_FORMAT_R16G16B16_FLOAT",
"r16g16b16_float",
{1, 1, 48}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
3, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 16, 0}, /* x = r */
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 16, 16}, /* y = g */
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 16, 32}, /* z = b */
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r16g16b16_float_unpack_rgba_8unorm,
&util_format_r16g16b16_float_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r16g16b16_float_unpack_rgba_float,
&util_format_r16g16b16_float_pack_rgba_float,
&util_format_r16g16b16_float_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r16g16b16a16_float_description = {
PIPE_FORMAT_R16G16B16A16_FLOAT,
"PIPE_FORMAT_R16G16B16A16_FLOAT",
"r16g16b16a16_float",
{1, 1, 64}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
4, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 16, 0}, /* x = r */
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 16, 16}, /* y = g */
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 16, 32}, /* z = b */
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 16, 48} /* w = a */
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_W /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r16g16b16a16_float_unpack_rgba_8unorm,
&util_format_r16g16b16a16_float_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r16g16b16a16_float_unpack_rgba_float,
&util_format_r16g16b16a16_float_pack_rgba_float,
&util_format_r16g16b16a16_float_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r16_unorm_description = {
PIPE_FORMAT_R16_UNORM,
"PIPE_FORMAT_R16_UNORM",
"r16_unorm",
{1, 1, 16}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 16, 0}, /* x = r */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r16_unorm_unpack_rgba_8unorm,
&util_format_r16_unorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r16_unorm_unpack_rgba_float,
&util_format_r16_unorm_pack_rgba_float,
&util_format_r16_unorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r16g16_unorm_description = {
PIPE_FORMAT_R16G16_UNORM,
"PIPE_FORMAT_R16G16_UNORM",
"r16g16_unorm",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 16, 0}, /* x = r */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 16, 16}, /* y = g */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r16g16_unorm_unpack_rgba_8unorm,
&util_format_r16g16_unorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r16g16_unorm_unpack_rgba_float,
&util_format_r16g16_unorm_pack_rgba_float,
&util_format_r16g16_unorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r16g16b16_unorm_description = {
PIPE_FORMAT_R16G16B16_UNORM,
"PIPE_FORMAT_R16G16B16_UNORM",
"r16g16b16_unorm",
{1, 1, 48}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
3, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 16, 0}, /* x = r */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 16, 16}, /* y = g */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 16, 32}, /* z = b */
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r16g16b16_unorm_unpack_rgba_8unorm,
&util_format_r16g16b16_unorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r16g16b16_unorm_unpack_rgba_float,
&util_format_r16g16b16_unorm_pack_rgba_float,
&util_format_r16g16b16_unorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r16g16b16a16_unorm_description = {
PIPE_FORMAT_R16G16B16A16_UNORM,
"PIPE_FORMAT_R16G16B16A16_UNORM",
"r16g16b16a16_unorm",
{1, 1, 64}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
4, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 16, 0}, /* x = r */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 16, 16}, /* y = g */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 16, 32}, /* z = b */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 16, 48} /* w = a */
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_W /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r16g16b16a16_unorm_unpack_rgba_8unorm,
&util_format_r16g16b16a16_unorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r16g16b16a16_unorm_unpack_rgba_float,
&util_format_r16g16b16a16_unorm_pack_rgba_float,
&util_format_r16g16b16a16_unorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r16_uscaled_description = {
PIPE_FORMAT_R16_USCALED,
"PIPE_FORMAT_R16_USCALED",
"r16_uscaled",
{1, 1, 16}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 16, 0}, /* x = r */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r16_uscaled_unpack_rgba_8unorm,
&util_format_r16_uscaled_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r16_uscaled_unpack_rgba_float,
&util_format_r16_uscaled_pack_rgba_float,
&util_format_r16_uscaled_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r16g16_uscaled_description = {
PIPE_FORMAT_R16G16_USCALED,
"PIPE_FORMAT_R16G16_USCALED",
"r16g16_uscaled",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 16, 0}, /* x = r */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 16, 16}, /* y = g */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r16g16_uscaled_unpack_rgba_8unorm,
&util_format_r16g16_uscaled_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r16g16_uscaled_unpack_rgba_float,
&util_format_r16g16_uscaled_pack_rgba_float,
&util_format_r16g16_uscaled_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r16g16b16_uscaled_description = {
PIPE_FORMAT_R16G16B16_USCALED,
"PIPE_FORMAT_R16G16B16_USCALED",
"r16g16b16_uscaled",
{1, 1, 48}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
3, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 16, 0}, /* x = r */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 16, 16}, /* y = g */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 16, 32}, /* z = b */
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r16g16b16_uscaled_unpack_rgba_8unorm,
&util_format_r16g16b16_uscaled_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r16g16b16_uscaled_unpack_rgba_float,
&util_format_r16g16b16_uscaled_pack_rgba_float,
&util_format_r16g16b16_uscaled_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r16g16b16a16_uscaled_description = {
PIPE_FORMAT_R16G16B16A16_USCALED,
"PIPE_FORMAT_R16G16B16A16_USCALED",
"r16g16b16a16_uscaled",
{1, 1, 64}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
4, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 16, 0}, /* x = r */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 16, 16}, /* y = g */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 16, 32}, /* z = b */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 16, 48} /* w = a */
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_W /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r16g16b16a16_uscaled_unpack_rgba_8unorm,
&util_format_r16g16b16a16_uscaled_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r16g16b16a16_uscaled_unpack_rgba_float,
&util_format_r16g16b16a16_uscaled_pack_rgba_float,
&util_format_r16g16b16a16_uscaled_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r16_snorm_description = {
PIPE_FORMAT_R16_SNORM,
"PIPE_FORMAT_R16_SNORM",
"r16_snorm",
{1, 1, 16}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 16, 0}, /* x = r */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r16_snorm_unpack_rgba_8unorm,
&util_format_r16_snorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r16_snorm_unpack_rgba_float,
&util_format_r16_snorm_pack_rgba_float,
&util_format_r16_snorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r16g16_snorm_description = {
PIPE_FORMAT_R16G16_SNORM,
"PIPE_FORMAT_R16G16_SNORM",
"r16g16_snorm",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 16, 0}, /* x = r */
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 16, 16}, /* y = g */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r16g16_snorm_unpack_rgba_8unorm,
&util_format_r16g16_snorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r16g16_snorm_unpack_rgba_float,
&util_format_r16g16_snorm_pack_rgba_float,
&util_format_r16g16_snorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r16g16b16_snorm_description = {
PIPE_FORMAT_R16G16B16_SNORM,
"PIPE_FORMAT_R16G16B16_SNORM",
"r16g16b16_snorm",
{1, 1, 48}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
3, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 16, 0}, /* x = r */
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 16, 16}, /* y = g */
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 16, 32}, /* z = b */
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r16g16b16_snorm_unpack_rgba_8unorm,
&util_format_r16g16b16_snorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r16g16b16_snorm_unpack_rgba_float,
&util_format_r16g16b16_snorm_pack_rgba_float,
&util_format_r16g16b16_snorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r16g16b16a16_snorm_description = {
PIPE_FORMAT_R16G16B16A16_SNORM,
"PIPE_FORMAT_R16G16B16A16_SNORM",
"r16g16b16a16_snorm",
{1, 1, 64}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
4, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 16, 0}, /* x = r */
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 16, 16}, /* y = g */
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 16, 32}, /* z = b */
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 16, 48} /* w = a */
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_W /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r16g16b16a16_snorm_unpack_rgba_8unorm,
&util_format_r16g16b16a16_snorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r16g16b16a16_snorm_unpack_rgba_float,
&util_format_r16g16b16a16_snorm_pack_rgba_float,
&util_format_r16g16b16a16_snorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r16_sscaled_description = {
PIPE_FORMAT_R16_SSCALED,
"PIPE_FORMAT_R16_SSCALED",
"r16_sscaled",
{1, 1, 16}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 16, 0}, /* x = r */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r16_sscaled_unpack_rgba_8unorm,
&util_format_r16_sscaled_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r16_sscaled_unpack_rgba_float,
&util_format_r16_sscaled_pack_rgba_float,
&util_format_r16_sscaled_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r16g16_sscaled_description = {
PIPE_FORMAT_R16G16_SSCALED,
"PIPE_FORMAT_R16G16_SSCALED",
"r16g16_sscaled",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 16, 0}, /* x = r */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 16, 16}, /* y = g */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r16g16_sscaled_unpack_rgba_8unorm,
&util_format_r16g16_sscaled_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r16g16_sscaled_unpack_rgba_float,
&util_format_r16g16_sscaled_pack_rgba_float,
&util_format_r16g16_sscaled_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r16g16b16_sscaled_description = {
PIPE_FORMAT_R16G16B16_SSCALED,
"PIPE_FORMAT_R16G16B16_SSCALED",
"r16g16b16_sscaled",
{1, 1, 48}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
3, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 16, 0}, /* x = r */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 16, 16}, /* y = g */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 16, 32}, /* z = b */
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r16g16b16_sscaled_unpack_rgba_8unorm,
&util_format_r16g16b16_sscaled_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r16g16b16_sscaled_unpack_rgba_float,
&util_format_r16g16b16_sscaled_pack_rgba_float,
&util_format_r16g16b16_sscaled_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r16g16b16a16_sscaled_description = {
PIPE_FORMAT_R16G16B16A16_SSCALED,
"PIPE_FORMAT_R16G16B16A16_SSCALED",
"r16g16b16a16_sscaled",
{1, 1, 64}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
4, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 16, 0}, /* x = r */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 16, 16}, /* y = g */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 16, 32}, /* z = b */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 16, 48} /* w = a */
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_W /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r16g16b16a16_sscaled_unpack_rgba_8unorm,
&util_format_r16g16b16a16_sscaled_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r16g16b16a16_sscaled_unpack_rgba_float,
&util_format_r16g16b16a16_sscaled_pack_rgba_float,
&util_format_r16g16b16a16_sscaled_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r8_unorm_description = {
PIPE_FORMAT_R8_UNORM,
"PIPE_FORMAT_R8_UNORM",
"r8_unorm",
{1, 1, 8}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 0}, /* x = r */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r8_unorm_unpack_rgba_8unorm,
&util_format_r8_unorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r8_unorm_unpack_rgba_float,
&util_format_r8_unorm_pack_rgba_float,
&util_format_r8_unorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r8g8_unorm_description = {
PIPE_FORMAT_R8G8_UNORM,
"PIPE_FORMAT_R8G8_UNORM",
"r8g8_unorm",
{1, 1, 16}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 0}, /* x = r */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 8}, /* y = g */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r8g8_unorm_unpack_rgba_8unorm,
&util_format_r8g8_unorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r8g8_unorm_unpack_rgba_float,
&util_format_r8g8_unorm_pack_rgba_float,
&util_format_r8g8_unorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r8g8b8_unorm_description = {
PIPE_FORMAT_R8G8B8_UNORM,
"PIPE_FORMAT_R8G8B8_UNORM",
"r8g8b8_unorm",
{1, 1, 24}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
3, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 0}, /* x = r */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 8}, /* y = g */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 16}, /* z = b */
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r8g8b8_unorm_unpack_rgba_8unorm,
&util_format_r8g8b8_unorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r8g8b8_unorm_unpack_rgba_float,
&util_format_r8g8b8_unorm_pack_rgba_float,
&util_format_r8g8b8_unorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r8g8b8a8_unorm_description = {
PIPE_FORMAT_R8G8B8A8_UNORM,
"PIPE_FORMAT_R8G8B8A8_UNORM",
"r8g8b8a8_unorm",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
4, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 0}, /* x = r */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 8}, /* y = g */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 16}, /* z = b */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 24} /* w = a */
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_W /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r8g8b8a8_unorm_unpack_rgba_8unorm,
&util_format_r8g8b8a8_unorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r8g8b8a8_unorm_unpack_rgba_float,
&util_format_r8g8b8a8_unorm_pack_rgba_float,
&util_format_r8g8b8a8_unorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r8_uscaled_description = {
PIPE_FORMAT_R8_USCALED,
"PIPE_FORMAT_R8_USCALED",
"r8_uscaled",
{1, 1, 8}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 8, 0}, /* x = r */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r8_uscaled_unpack_rgba_8unorm,
&util_format_r8_uscaled_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r8_uscaled_unpack_rgba_float,
&util_format_r8_uscaled_pack_rgba_float,
&util_format_r8_uscaled_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r8g8_uscaled_description = {
PIPE_FORMAT_R8G8_USCALED,
"PIPE_FORMAT_R8G8_USCALED",
"r8g8_uscaled",
{1, 1, 16}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 8, 0}, /* x = r */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 8, 8}, /* y = g */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r8g8_uscaled_unpack_rgba_8unorm,
&util_format_r8g8_uscaled_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r8g8_uscaled_unpack_rgba_float,
&util_format_r8g8_uscaled_pack_rgba_float,
&util_format_r8g8_uscaled_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r8g8b8_uscaled_description = {
PIPE_FORMAT_R8G8B8_USCALED,
"PIPE_FORMAT_R8G8B8_USCALED",
"r8g8b8_uscaled",
{1, 1, 24}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
3, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 8, 0}, /* x = r */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 8, 8}, /* y = g */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 8, 16}, /* z = b */
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r8g8b8_uscaled_unpack_rgba_8unorm,
&util_format_r8g8b8_uscaled_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r8g8b8_uscaled_unpack_rgba_float,
&util_format_r8g8b8_uscaled_pack_rgba_float,
&util_format_r8g8b8_uscaled_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r8g8b8a8_uscaled_description = {
PIPE_FORMAT_R8G8B8A8_USCALED,
"PIPE_FORMAT_R8G8B8A8_USCALED",
"r8g8b8a8_uscaled",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
4, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 8, 0}, /* x = r */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 8, 8}, /* y = g */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 8, 16}, /* z = b */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 8, 24} /* w = a */
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_W /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r8g8b8a8_uscaled_unpack_rgba_8unorm,
&util_format_r8g8b8a8_uscaled_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r8g8b8a8_uscaled_unpack_rgba_float,
&util_format_r8g8b8a8_uscaled_pack_rgba_float,
&util_format_r8g8b8a8_uscaled_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r8_snorm_description = {
PIPE_FORMAT_R8_SNORM,
"PIPE_FORMAT_R8_SNORM",
"r8_snorm",
{1, 1, 8}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 0}, /* x = r */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r8_snorm_unpack_rgba_8unorm,
&util_format_r8_snorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r8_snorm_unpack_rgba_float,
&util_format_r8_snorm_pack_rgba_float,
&util_format_r8_snorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r8g8_snorm_description = {
PIPE_FORMAT_R8G8_SNORM,
"PIPE_FORMAT_R8G8_SNORM",
"r8g8_snorm",
{1, 1, 16}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 0}, /* x = r */
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 8}, /* y = g */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r8g8_snorm_unpack_rgba_8unorm,
&util_format_r8g8_snorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r8g8_snorm_unpack_rgba_float,
&util_format_r8g8_snorm_pack_rgba_float,
&util_format_r8g8_snorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r8g8b8_snorm_description = {
PIPE_FORMAT_R8G8B8_SNORM,
"PIPE_FORMAT_R8G8B8_SNORM",
"r8g8b8_snorm",
{1, 1, 24}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
3, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 0}, /* x = r */
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 8}, /* y = g */
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 16}, /* z = b */
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r8g8b8_snorm_unpack_rgba_8unorm,
&util_format_r8g8b8_snorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r8g8b8_snorm_unpack_rgba_float,
&util_format_r8g8b8_snorm_pack_rgba_float,
&util_format_r8g8b8_snorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r8g8b8a8_snorm_description = {
PIPE_FORMAT_R8G8B8A8_SNORM,
"PIPE_FORMAT_R8G8B8A8_SNORM",
"r8g8b8a8_snorm",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
4, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 0}, /* x = r */
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 8}, /* y = g */
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 16}, /* z = b */
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 24} /* w = a */
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_W /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r8g8b8a8_snorm_unpack_rgba_8unorm,
&util_format_r8g8b8a8_snorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r8g8b8a8_snorm_unpack_rgba_float,
&util_format_r8g8b8a8_snorm_pack_rgba_float,
&util_format_r8g8b8a8_snorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r8_sscaled_description = {
PIPE_FORMAT_R8_SSCALED,
"PIPE_FORMAT_R8_SSCALED",
"r8_sscaled",
{1, 1, 8}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 8, 0}, /* x = r */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r8_sscaled_unpack_rgba_8unorm,
&util_format_r8_sscaled_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r8_sscaled_unpack_rgba_float,
&util_format_r8_sscaled_pack_rgba_float,
&util_format_r8_sscaled_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r8g8_sscaled_description = {
PIPE_FORMAT_R8G8_SSCALED,
"PIPE_FORMAT_R8G8_SSCALED",
"r8g8_sscaled",
{1, 1, 16}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 8, 0}, /* x = r */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 8, 8}, /* y = g */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r8g8_sscaled_unpack_rgba_8unorm,
&util_format_r8g8_sscaled_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r8g8_sscaled_unpack_rgba_float,
&util_format_r8g8_sscaled_pack_rgba_float,
&util_format_r8g8_sscaled_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r8g8b8_sscaled_description = {
PIPE_FORMAT_R8G8B8_SSCALED,
"PIPE_FORMAT_R8G8B8_SSCALED",
"r8g8b8_sscaled",
{1, 1, 24}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
3, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 8, 0}, /* x = r */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 8, 8}, /* y = g */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 8, 16}, /* z = b */
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r8g8b8_sscaled_unpack_rgba_8unorm,
&util_format_r8g8b8_sscaled_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r8g8b8_sscaled_unpack_rgba_float,
&util_format_r8g8b8_sscaled_pack_rgba_float,
&util_format_r8g8b8_sscaled_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r8g8b8a8_sscaled_description = {
PIPE_FORMAT_R8G8B8A8_SSCALED,
"PIPE_FORMAT_R8G8B8A8_SSCALED",
"r8g8b8a8_sscaled",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
4, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 8, 0}, /* x = r */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 8, 8}, /* y = g */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 8, 16}, /* z = b */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, FALSE, 8, 24} /* w = a */
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_W /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r8g8b8a8_sscaled_unpack_rgba_8unorm,
&util_format_r8g8b8a8_sscaled_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r8g8b8a8_sscaled_unpack_rgba_float,
&util_format_r8g8b8a8_sscaled_pack_rgba_float,
&util_format_r8g8b8a8_sscaled_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r32_fixed_description = {
PIPE_FORMAT_R32_FIXED,
"PIPE_FORMAT_R32_FIXED",
"r32_fixed",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_FIXED, FALSE, FALSE, 32, 0}, /* x = r */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r32_fixed_unpack_rgba_8unorm,
&util_format_r32_fixed_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r32_fixed_unpack_rgba_float,
&util_format_r32_fixed_pack_rgba_float,
&util_format_r32_fixed_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r32g32_fixed_description = {
PIPE_FORMAT_R32G32_FIXED,
"PIPE_FORMAT_R32G32_FIXED",
"r32g32_fixed",
{1, 1, 64}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_FIXED, FALSE, FALSE, 32, 0}, /* x = r */
{UTIL_FORMAT_TYPE_FIXED, FALSE, FALSE, 32, 32}, /* y = g */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r32g32_fixed_unpack_rgba_8unorm,
&util_format_r32g32_fixed_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r32g32_fixed_unpack_rgba_float,
&util_format_r32g32_fixed_pack_rgba_float,
&util_format_r32g32_fixed_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r32g32b32_fixed_description = {
PIPE_FORMAT_R32G32B32_FIXED,
"PIPE_FORMAT_R32G32B32_FIXED",
"r32g32b32_fixed",
{1, 1, 96}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
3, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_FIXED, FALSE, FALSE, 32, 0}, /* x = r */
{UTIL_FORMAT_TYPE_FIXED, FALSE, FALSE, 32, 32}, /* y = g */
{UTIL_FORMAT_TYPE_FIXED, FALSE, FALSE, 32, 64}, /* z = b */
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r32g32b32_fixed_unpack_rgba_8unorm,
&util_format_r32g32b32_fixed_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r32g32b32_fixed_unpack_rgba_float,
&util_format_r32g32b32_fixed_pack_rgba_float,
&util_format_r32g32b32_fixed_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r32g32b32a32_fixed_description = {
PIPE_FORMAT_R32G32B32A32_FIXED,
"PIPE_FORMAT_R32G32B32A32_FIXED",
"r32g32b32a32_fixed",
{1, 1, 128}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
4, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_FIXED, FALSE, FALSE, 32, 0}, /* x = r */
{UTIL_FORMAT_TYPE_FIXED, FALSE, FALSE, 32, 32}, /* y = g */
{UTIL_FORMAT_TYPE_FIXED, FALSE, FALSE, 32, 64}, /* z = b */
{UTIL_FORMAT_TYPE_FIXED, FALSE, FALSE, 32, 96} /* w = a */
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_W /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r32g32b32a32_fixed_unpack_rgba_8unorm,
&util_format_r32g32b32a32_fixed_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r32g32b32a32_fixed_unpack_rgba_float,
&util_format_r32g32b32a32_fixed_pack_rgba_float,
&util_format_r32g32b32a32_fixed_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r10g10b10x2_uscaled_description = {
PIPE_FORMAT_R10G10B10X2_USCALED,
"PIPE_FORMAT_R10G10B10X2_USCALED",
"r10g10b10x2_uscaled",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
4, /* nr_channels */
FALSE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 10, 0}, /* x = r */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 10, 10}, /* y = g */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, FALSE, 10, 20}, /* z = b */
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 2, 30} /* w = x */
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r10g10b10x2_uscaled_unpack_rgba_8unorm,
&util_format_r10g10b10x2_uscaled_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r10g10b10x2_uscaled_unpack_rgba_float,
&util_format_r10g10b10x2_uscaled_pack_rgba_float,
&util_format_r10g10b10x2_uscaled_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r10g10b10x2_snorm_description = {
PIPE_FORMAT_R10G10B10X2_SNORM,
"PIPE_FORMAT_R10G10B10X2_SNORM",
"r10g10b10x2_snorm",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
4, /* nr_channels */
FALSE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 10, 0}, /* x = r */
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 10, 10}, /* y = g */
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 10, 20}, /* z = b */
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 2, 30} /* w = x */
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r10g10b10x2_snorm_unpack_rgba_8unorm,
&util_format_r10g10b10x2_snorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r10g10b10x2_snorm_unpack_rgba_float,
&util_format_r10g10b10x2_snorm_pack_rgba_float,
&util_format_r10g10b10x2_snorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_yv12_description = {
PIPE_FORMAT_YV12,
"PIPE_FORMAT_YV12",
"yv12",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_OTHER,
4, /* nr_channels */
FALSE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 0}, /* x = x */
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 8}, /* y = y */
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 16}, /* z = z */
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 24} /* w = w */
},
{
UTIL_FORMAT_SWIZZLE_X, /* y */
UTIL_FORMAT_SWIZZLE_Y, /* u */
UTIL_FORMAT_SWIZZLE_Z, /* v */
UTIL_FORMAT_SWIZZLE_W /* ignored */
},
UTIL_FORMAT_COLORSPACE_YUV,
&util_format_yv12_unpack_rgba_8unorm,
&util_format_yv12_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_yv12_unpack_rgba_float,
&util_format_yv12_pack_rgba_float,
&util_format_yv12_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_yv16_description = {
PIPE_FORMAT_YV16,
"PIPE_FORMAT_YV16",
"yv16",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_OTHER,
4, /* nr_channels */
FALSE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 0}, /* x = x */
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 8}, /* y = y */
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 16}, /* z = z */
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 24} /* w = w */
},
{
UTIL_FORMAT_SWIZZLE_X, /* y */
UTIL_FORMAT_SWIZZLE_Y, /* u */
UTIL_FORMAT_SWIZZLE_Z, /* v */
UTIL_FORMAT_SWIZZLE_W /* ignored */
},
UTIL_FORMAT_COLORSPACE_YUV,
&util_format_yv16_unpack_rgba_8unorm,
&util_format_yv16_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_yv16_unpack_rgba_float,
&util_format_yv16_pack_rgba_float,
&util_format_yv16_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_iyuv_description = {
PIPE_FORMAT_IYUV,
"PIPE_FORMAT_IYUV",
"iyuv",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_OTHER,
4, /* nr_channels */
FALSE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 0}, /* x = x */
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 8}, /* y = y */
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 16}, /* z = z */
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 24} /* w = w */
},
{
UTIL_FORMAT_SWIZZLE_X, /* y */
UTIL_FORMAT_SWIZZLE_Y, /* u */
UTIL_FORMAT_SWIZZLE_Z, /* v */
UTIL_FORMAT_SWIZZLE_W /* ignored */
},
UTIL_FORMAT_COLORSPACE_YUV,
&util_format_iyuv_unpack_rgba_8unorm,
&util_format_iyuv_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_iyuv_unpack_rgba_float,
&util_format_iyuv_pack_rgba_float,
&util_format_iyuv_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_nv12_description = {
PIPE_FORMAT_NV12,
"PIPE_FORMAT_NV12",
"nv12",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_OTHER,
4, /* nr_channels */
FALSE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 0}, /* x = x */
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 8}, /* y = y */
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 16}, /* z = z */
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 24} /* w = w */
},
{
UTIL_FORMAT_SWIZZLE_X, /* y */
UTIL_FORMAT_SWIZZLE_Y, /* u */
UTIL_FORMAT_SWIZZLE_Z, /* v */
UTIL_FORMAT_SWIZZLE_W /* ignored */
},
UTIL_FORMAT_COLORSPACE_YUV,
&util_format_nv12_unpack_rgba_8unorm,
&util_format_nv12_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_nv12_unpack_rgba_float,
&util_format_nv12_pack_rgba_float,
&util_format_nv12_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_nv21_description = {
PIPE_FORMAT_NV21,
"PIPE_FORMAT_NV21",
"nv21",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_OTHER,
4, /* nr_channels */
FALSE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 0}, /* x = x */
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 8}, /* y = y */
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 16}, /* z = z */
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 24} /* w = w */
},
{
UTIL_FORMAT_SWIZZLE_X, /* y */
UTIL_FORMAT_SWIZZLE_Y, /* u */
UTIL_FORMAT_SWIZZLE_Z, /* v */
UTIL_FORMAT_SWIZZLE_W /* ignored */
},
UTIL_FORMAT_COLORSPACE_YUV,
&util_format_nv21_unpack_rgba_8unorm,
&util_format_nv21_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_nv21_unpack_rgba_float,
&util_format_nv21_pack_rgba_float,
&util_format_nv21_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r4a4_unorm_description = {
PIPE_FORMAT_R4A4_UNORM,
"PIPE_FORMAT_R4A4_UNORM",
"r4a4_unorm",
{1, 1, 8}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
FALSE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 4, 0}, /* x = a */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 4, 4}, /* y = r */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_Y, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_X /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r4a4_unorm_unpack_rgba_8unorm,
&util_format_r4a4_unorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r4a4_unorm_unpack_rgba_float,
&util_format_r4a4_unorm_pack_rgba_float,
&util_format_r4a4_unorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_a4r4_unorm_description = {
PIPE_FORMAT_A4R4_UNORM,
"PIPE_FORMAT_A4R4_UNORM",
"a4r4_unorm",
{1, 1, 8}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
FALSE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 4, 0}, /* x = r */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 4, 4}, /* y = a */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_Y /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_a4r4_unorm_unpack_rgba_8unorm,
&util_format_a4r4_unorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_a4r4_unorm_unpack_rgba_float,
&util_format_a4r4_unorm_pack_rgba_float,
&util_format_a4r4_unorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r8a8_unorm_description = {
PIPE_FORMAT_R8A8_UNORM,
"PIPE_FORMAT_R8A8_UNORM",
"r8a8_unorm",
{1, 1, 16}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 0}, /* x = r */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 8}, /* y = a */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_Y /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r8a8_unorm_unpack_rgba_8unorm,
&util_format_r8a8_unorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r8a8_unorm_unpack_rgba_float,
&util_format_r8a8_unorm_pack_rgba_float,
&util_format_r8a8_unorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_a8r8_unorm_description = {
PIPE_FORMAT_A8R8_UNORM,
"PIPE_FORMAT_A8R8_UNORM",
"a8r8_unorm",
{1, 1, 16}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 0}, /* x = a */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 8}, /* y = r */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_Y, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_X /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_a8r8_unorm_unpack_rgba_8unorm,
&util_format_a8r8_unorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_a8r8_unorm_unpack_rgba_float,
&util_format_a8r8_unorm_pack_rgba_float,
&util_format_a8r8_unorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r8_uint_description = {
PIPE_FORMAT_R8_UINT,
"PIPE_FORMAT_R8_UINT",
"r8_uint",
{1, 1, 8}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 0}, /* x = r */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_r8_uint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_r8_uint_pack_unsigned, /* pack_rgba_uint */
&util_format_r8_uint_unpack_signed, /* unpack_rgba_sint */
&util_format_r8_uint_pack_signed, /* pack_rgba_sint */
&util_format_r8_uint_fetch_unsigned, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r8g8_uint_description = {
PIPE_FORMAT_R8G8_UINT,
"PIPE_FORMAT_R8G8_UINT",
"r8g8_uint",
{1, 1, 16}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 0}, /* x = r */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 8}, /* y = g */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_r8g8_uint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_r8g8_uint_pack_unsigned, /* pack_rgba_uint */
&util_format_r8g8_uint_unpack_signed, /* unpack_rgba_sint */
&util_format_r8g8_uint_pack_signed, /* pack_rgba_sint */
&util_format_r8g8_uint_fetch_unsigned, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r8g8b8_uint_description = {
PIPE_FORMAT_R8G8B8_UINT,
"PIPE_FORMAT_R8G8B8_UINT",
"r8g8b8_uint",
{1, 1, 24}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
3, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 0}, /* x = r */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 8}, /* y = g */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 16}, /* z = b */
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_r8g8b8_uint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_r8g8b8_uint_pack_unsigned, /* pack_rgba_uint */
&util_format_r8g8b8_uint_unpack_signed, /* unpack_rgba_sint */
&util_format_r8g8b8_uint_pack_signed, /* pack_rgba_sint */
&util_format_r8g8b8_uint_fetch_unsigned, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r8g8b8a8_uint_description = {
PIPE_FORMAT_R8G8B8A8_UINT,
"PIPE_FORMAT_R8G8B8A8_UINT",
"r8g8b8a8_uint",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
4, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 0}, /* x = r */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 8}, /* y = g */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 16}, /* z = b */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 24} /* w = a */
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_W /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_r8g8b8a8_uint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_r8g8b8a8_uint_pack_unsigned, /* pack_rgba_uint */
&util_format_r8g8b8a8_uint_unpack_signed, /* unpack_rgba_sint */
&util_format_r8g8b8a8_uint_pack_signed, /* pack_rgba_sint */
&util_format_r8g8b8a8_uint_fetch_unsigned, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r8_sint_description = {
PIPE_FORMAT_R8_SINT,
"PIPE_FORMAT_R8_SINT",
"r8_sint",
{1, 1, 8}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 8, 0}, /* x = r */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_r8_sint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_r8_sint_pack_unsigned, /* pack_rgba_uint */
&util_format_r8_sint_unpack_signed, /* unpack_rgba_sint */
&util_format_r8_sint_pack_signed, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
&util_format_r8_sint_fetch_signed /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r8g8_sint_description = {
PIPE_FORMAT_R8G8_SINT,
"PIPE_FORMAT_R8G8_SINT",
"r8g8_sint",
{1, 1, 16}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 8, 0}, /* x = r */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 8, 8}, /* y = g */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_r8g8_sint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_r8g8_sint_pack_unsigned, /* pack_rgba_uint */
&util_format_r8g8_sint_unpack_signed, /* unpack_rgba_sint */
&util_format_r8g8_sint_pack_signed, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
&util_format_r8g8_sint_fetch_signed /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r8g8b8_sint_description = {
PIPE_FORMAT_R8G8B8_SINT,
"PIPE_FORMAT_R8G8B8_SINT",
"r8g8b8_sint",
{1, 1, 24}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
3, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 8, 0}, /* x = r */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 8, 8}, /* y = g */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 8, 16}, /* z = b */
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_r8g8b8_sint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_r8g8b8_sint_pack_unsigned, /* pack_rgba_uint */
&util_format_r8g8b8_sint_unpack_signed, /* unpack_rgba_sint */
&util_format_r8g8b8_sint_pack_signed, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
&util_format_r8g8b8_sint_fetch_signed /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r8g8b8a8_sint_description = {
PIPE_FORMAT_R8G8B8A8_SINT,
"PIPE_FORMAT_R8G8B8A8_SINT",
"r8g8b8a8_sint",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
4, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 8, 0}, /* x = r */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 8, 8}, /* y = g */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 8, 16}, /* z = b */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 8, 24} /* w = a */
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_W /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_r8g8b8a8_sint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_r8g8b8a8_sint_pack_unsigned, /* pack_rgba_uint */
&util_format_r8g8b8a8_sint_unpack_signed, /* unpack_rgba_sint */
&util_format_r8g8b8a8_sint_pack_signed, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
&util_format_r8g8b8a8_sint_fetch_signed /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r16_uint_description = {
PIPE_FORMAT_R16_UINT,
"PIPE_FORMAT_R16_UINT",
"r16_uint",
{1, 1, 16}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 16, 0}, /* x = r */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_r16_uint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_r16_uint_pack_unsigned, /* pack_rgba_uint */
&util_format_r16_uint_unpack_signed, /* unpack_rgba_sint */
&util_format_r16_uint_pack_signed, /* pack_rgba_sint */
&util_format_r16_uint_fetch_unsigned, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r16g16_uint_description = {
PIPE_FORMAT_R16G16_UINT,
"PIPE_FORMAT_R16G16_UINT",
"r16g16_uint",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 16, 0}, /* x = r */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 16, 16}, /* y = g */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_r16g16_uint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_r16g16_uint_pack_unsigned, /* pack_rgba_uint */
&util_format_r16g16_uint_unpack_signed, /* unpack_rgba_sint */
&util_format_r16g16_uint_pack_signed, /* pack_rgba_sint */
&util_format_r16g16_uint_fetch_unsigned, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r16g16b16_uint_description = {
PIPE_FORMAT_R16G16B16_UINT,
"PIPE_FORMAT_R16G16B16_UINT",
"r16g16b16_uint",
{1, 1, 48}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
3, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 16, 0}, /* x = r */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 16, 16}, /* y = g */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 16, 32}, /* z = b */
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_r16g16b16_uint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_r16g16b16_uint_pack_unsigned, /* pack_rgba_uint */
&util_format_r16g16b16_uint_unpack_signed, /* unpack_rgba_sint */
&util_format_r16g16b16_uint_pack_signed, /* pack_rgba_sint */
&util_format_r16g16b16_uint_fetch_unsigned, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r16g16b16a16_uint_description = {
PIPE_FORMAT_R16G16B16A16_UINT,
"PIPE_FORMAT_R16G16B16A16_UINT",
"r16g16b16a16_uint",
{1, 1, 64}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
4, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 16, 0}, /* x = r */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 16, 16}, /* y = g */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 16, 32}, /* z = b */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 16, 48} /* w = a */
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_W /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_r16g16b16a16_uint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_r16g16b16a16_uint_pack_unsigned, /* pack_rgba_uint */
&util_format_r16g16b16a16_uint_unpack_signed, /* unpack_rgba_sint */
&util_format_r16g16b16a16_uint_pack_signed, /* pack_rgba_sint */
&util_format_r16g16b16a16_uint_fetch_unsigned, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r16_sint_description = {
PIPE_FORMAT_R16_SINT,
"PIPE_FORMAT_R16_SINT",
"r16_sint",
{1, 1, 16}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 16, 0}, /* x = r */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_r16_sint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_r16_sint_pack_unsigned, /* pack_rgba_uint */
&util_format_r16_sint_unpack_signed, /* unpack_rgba_sint */
&util_format_r16_sint_pack_signed, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
&util_format_r16_sint_fetch_signed /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r16g16_sint_description = {
PIPE_FORMAT_R16G16_SINT,
"PIPE_FORMAT_R16G16_SINT",
"r16g16_sint",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 16, 0}, /* x = r */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 16, 16}, /* y = g */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_r16g16_sint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_r16g16_sint_pack_unsigned, /* pack_rgba_uint */
&util_format_r16g16_sint_unpack_signed, /* unpack_rgba_sint */
&util_format_r16g16_sint_pack_signed, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
&util_format_r16g16_sint_fetch_signed /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r16g16b16_sint_description = {
PIPE_FORMAT_R16G16B16_SINT,
"PIPE_FORMAT_R16G16B16_SINT",
"r16g16b16_sint",
{1, 1, 48}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
3, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 16, 0}, /* x = r */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 16, 16}, /* y = g */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 16, 32}, /* z = b */
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_r16g16b16_sint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_r16g16b16_sint_pack_unsigned, /* pack_rgba_uint */
&util_format_r16g16b16_sint_unpack_signed, /* unpack_rgba_sint */
&util_format_r16g16b16_sint_pack_signed, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
&util_format_r16g16b16_sint_fetch_signed /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r16g16b16a16_sint_description = {
PIPE_FORMAT_R16G16B16A16_SINT,
"PIPE_FORMAT_R16G16B16A16_SINT",
"r16g16b16a16_sint",
{1, 1, 64}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
4, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 16, 0}, /* x = r */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 16, 16}, /* y = g */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 16, 32}, /* z = b */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 16, 48} /* w = a */
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_W /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_r16g16b16a16_sint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_r16g16b16a16_sint_pack_unsigned, /* pack_rgba_uint */
&util_format_r16g16b16a16_sint_unpack_signed, /* unpack_rgba_sint */
&util_format_r16g16b16a16_sint_pack_signed, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
&util_format_r16g16b16a16_sint_fetch_signed /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r32_uint_description = {
PIPE_FORMAT_R32_UINT,
"PIPE_FORMAT_R32_UINT",
"r32_uint",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 32, 0}, /* x = r */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_r32_uint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_r32_uint_pack_unsigned, /* pack_rgba_uint */
&util_format_r32_uint_unpack_signed, /* unpack_rgba_sint */
&util_format_r32_uint_pack_signed, /* pack_rgba_sint */
&util_format_r32_uint_fetch_unsigned, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r32g32_uint_description = {
PIPE_FORMAT_R32G32_UINT,
"PIPE_FORMAT_R32G32_UINT",
"r32g32_uint",
{1, 1, 64}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 32, 0}, /* x = r */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 32, 32}, /* y = g */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_r32g32_uint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_r32g32_uint_pack_unsigned, /* pack_rgba_uint */
&util_format_r32g32_uint_unpack_signed, /* unpack_rgba_sint */
&util_format_r32g32_uint_pack_signed, /* pack_rgba_sint */
&util_format_r32g32_uint_fetch_unsigned, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r32g32b32_uint_description = {
PIPE_FORMAT_R32G32B32_UINT,
"PIPE_FORMAT_R32G32B32_UINT",
"r32g32b32_uint",
{1, 1, 96}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
3, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 32, 0}, /* x = r */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 32, 32}, /* y = g */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 32, 64}, /* z = b */
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_r32g32b32_uint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_r32g32b32_uint_pack_unsigned, /* pack_rgba_uint */
&util_format_r32g32b32_uint_unpack_signed, /* unpack_rgba_sint */
&util_format_r32g32b32_uint_pack_signed, /* pack_rgba_sint */
&util_format_r32g32b32_uint_fetch_unsigned, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r32g32b32a32_uint_description = {
PIPE_FORMAT_R32G32B32A32_UINT,
"PIPE_FORMAT_R32G32B32A32_UINT",
"r32g32b32a32_uint",
{1, 1, 128}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
4, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 32, 0}, /* x = r */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 32, 32}, /* y = g */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 32, 64}, /* z = b */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 32, 96} /* w = a */
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_W /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_r32g32b32a32_uint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_r32g32b32a32_uint_pack_unsigned, /* pack_rgba_uint */
&util_format_r32g32b32a32_uint_unpack_signed, /* unpack_rgba_sint */
&util_format_r32g32b32a32_uint_pack_signed, /* pack_rgba_sint */
&util_format_r32g32b32a32_uint_fetch_unsigned, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r32_sint_description = {
PIPE_FORMAT_R32_SINT,
"PIPE_FORMAT_R32_SINT",
"r32_sint",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 32, 0}, /* x = r */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_r32_sint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_r32_sint_pack_unsigned, /* pack_rgba_uint */
&util_format_r32_sint_unpack_signed, /* unpack_rgba_sint */
&util_format_r32_sint_pack_signed, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
&util_format_r32_sint_fetch_signed /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r32g32_sint_description = {
PIPE_FORMAT_R32G32_SINT,
"PIPE_FORMAT_R32G32_SINT",
"r32g32_sint",
{1, 1, 64}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 32, 0}, /* x = r */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 32, 32}, /* y = g */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_r32g32_sint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_r32g32_sint_pack_unsigned, /* pack_rgba_uint */
&util_format_r32g32_sint_unpack_signed, /* unpack_rgba_sint */
&util_format_r32g32_sint_pack_signed, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
&util_format_r32g32_sint_fetch_signed /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r32g32b32_sint_description = {
PIPE_FORMAT_R32G32B32_SINT,
"PIPE_FORMAT_R32G32B32_SINT",
"r32g32b32_sint",
{1, 1, 96}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
3, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 32, 0}, /* x = r */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 32, 32}, /* y = g */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 32, 64}, /* z = b */
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_r32g32b32_sint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_r32g32b32_sint_pack_unsigned, /* pack_rgba_uint */
&util_format_r32g32b32_sint_unpack_signed, /* unpack_rgba_sint */
&util_format_r32g32b32_sint_pack_signed, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
&util_format_r32g32b32_sint_fetch_signed /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r32g32b32a32_sint_description = {
PIPE_FORMAT_R32G32B32A32_SINT,
"PIPE_FORMAT_R32G32B32A32_SINT",
"r32g32b32a32_sint",
{1, 1, 128}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
4, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 32, 0}, /* x = r */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 32, 32}, /* y = g */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 32, 64}, /* z = b */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 32, 96} /* w = a */
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_W /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_r32g32b32a32_sint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_r32g32b32a32_sint_pack_unsigned, /* pack_rgba_uint */
&util_format_r32g32b32a32_sint_unpack_signed, /* unpack_rgba_sint */
&util_format_r32g32b32a32_sint_pack_signed, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
&util_format_r32g32b32a32_sint_fetch_signed /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_a8_uint_description = {
PIPE_FORMAT_A8_UINT,
"PIPE_FORMAT_A8_UINT",
"a8_uint",
{1, 1, 8}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 0}, /* x = a */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_0, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_X /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_a8_uint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_a8_uint_pack_unsigned, /* pack_rgba_uint */
&util_format_a8_uint_unpack_signed, /* unpack_rgba_sint */
&util_format_a8_uint_pack_signed, /* pack_rgba_sint */
&util_format_a8_uint_fetch_unsigned, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_i8_uint_description = {
PIPE_FORMAT_I8_UINT,
"PIPE_FORMAT_I8_UINT",
"i8_uint",
{1, 1, 8}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 0}, /* x = rgba */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_X, /* g */
UTIL_FORMAT_SWIZZLE_X, /* b */
UTIL_FORMAT_SWIZZLE_X /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_i8_uint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_i8_uint_pack_unsigned, /* pack_rgba_uint */
&util_format_i8_uint_unpack_signed, /* unpack_rgba_sint */
&util_format_i8_uint_pack_signed, /* pack_rgba_sint */
&util_format_i8_uint_fetch_unsigned, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_l8_uint_description = {
PIPE_FORMAT_L8_UINT,
"PIPE_FORMAT_L8_UINT",
"l8_uint",
{1, 1, 8}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 0}, /* x = rgb */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_X, /* g */
UTIL_FORMAT_SWIZZLE_X, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_l8_uint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_l8_uint_pack_unsigned, /* pack_rgba_uint */
&util_format_l8_uint_unpack_signed, /* unpack_rgba_sint */
&util_format_l8_uint_pack_signed, /* pack_rgba_sint */
&util_format_l8_uint_fetch_unsigned, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_l8a8_uint_description = {
PIPE_FORMAT_L8A8_UINT,
"PIPE_FORMAT_L8A8_UINT",
"l8a8_uint",
{1, 1, 16}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 0}, /* x = rgb */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 8}, /* y = a */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_X, /* g */
UTIL_FORMAT_SWIZZLE_X, /* b */
UTIL_FORMAT_SWIZZLE_Y /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_l8a8_uint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_l8a8_uint_pack_unsigned, /* pack_rgba_uint */
&util_format_l8a8_uint_unpack_signed, /* unpack_rgba_sint */
&util_format_l8a8_uint_pack_signed, /* pack_rgba_sint */
&util_format_l8a8_uint_fetch_unsigned, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_a8_sint_description = {
PIPE_FORMAT_A8_SINT,
"PIPE_FORMAT_A8_SINT",
"a8_sint",
{1, 1, 8}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 8, 0}, /* x = a */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_0, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_X /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_a8_sint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_a8_sint_pack_unsigned, /* pack_rgba_uint */
&util_format_a8_sint_unpack_signed, /* unpack_rgba_sint */
&util_format_a8_sint_pack_signed, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
&util_format_a8_sint_fetch_signed /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_i8_sint_description = {
PIPE_FORMAT_I8_SINT,
"PIPE_FORMAT_I8_SINT",
"i8_sint",
{1, 1, 8}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 8, 0}, /* x = rgba */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_X, /* g */
UTIL_FORMAT_SWIZZLE_X, /* b */
UTIL_FORMAT_SWIZZLE_X /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_i8_sint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_i8_sint_pack_unsigned, /* pack_rgba_uint */
&util_format_i8_sint_unpack_signed, /* unpack_rgba_sint */
&util_format_i8_sint_pack_signed, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
&util_format_i8_sint_fetch_signed /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_l8_sint_description = {
PIPE_FORMAT_L8_SINT,
"PIPE_FORMAT_L8_SINT",
"l8_sint",
{1, 1, 8}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 8, 0}, /* x = rgb */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_X, /* g */
UTIL_FORMAT_SWIZZLE_X, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_l8_sint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_l8_sint_pack_unsigned, /* pack_rgba_uint */
&util_format_l8_sint_unpack_signed, /* unpack_rgba_sint */
&util_format_l8_sint_pack_signed, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
&util_format_l8_sint_fetch_signed /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_l8a8_sint_description = {
PIPE_FORMAT_L8A8_SINT,
"PIPE_FORMAT_L8A8_SINT",
"l8a8_sint",
{1, 1, 16}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 8, 0}, /* x = rgb */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 8, 8}, /* y = a */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_X, /* g */
UTIL_FORMAT_SWIZZLE_X, /* b */
UTIL_FORMAT_SWIZZLE_Y /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_l8a8_sint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_l8a8_sint_pack_unsigned, /* pack_rgba_uint */
&util_format_l8a8_sint_unpack_signed, /* unpack_rgba_sint */
&util_format_l8a8_sint_pack_signed, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
&util_format_l8a8_sint_fetch_signed /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_a16_uint_description = {
PIPE_FORMAT_A16_UINT,
"PIPE_FORMAT_A16_UINT",
"a16_uint",
{1, 1, 16}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 16, 0}, /* x = a */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_0, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_X /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_a16_uint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_a16_uint_pack_unsigned, /* pack_rgba_uint */
&util_format_a16_uint_unpack_signed, /* unpack_rgba_sint */
&util_format_a16_uint_pack_signed, /* pack_rgba_sint */
&util_format_a16_uint_fetch_unsigned, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_i16_uint_description = {
PIPE_FORMAT_I16_UINT,
"PIPE_FORMAT_I16_UINT",
"i16_uint",
{1, 1, 16}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 16, 0}, /* x = rgba */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_X, /* g */
UTIL_FORMAT_SWIZZLE_X, /* b */
UTIL_FORMAT_SWIZZLE_X /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_i16_uint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_i16_uint_pack_unsigned, /* pack_rgba_uint */
&util_format_i16_uint_unpack_signed, /* unpack_rgba_sint */
&util_format_i16_uint_pack_signed, /* pack_rgba_sint */
&util_format_i16_uint_fetch_unsigned, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_l16_uint_description = {
PIPE_FORMAT_L16_UINT,
"PIPE_FORMAT_L16_UINT",
"l16_uint",
{1, 1, 16}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 16, 0}, /* x = rgb */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_X, /* g */
UTIL_FORMAT_SWIZZLE_X, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_l16_uint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_l16_uint_pack_unsigned, /* pack_rgba_uint */
&util_format_l16_uint_unpack_signed, /* unpack_rgba_sint */
&util_format_l16_uint_pack_signed, /* pack_rgba_sint */
&util_format_l16_uint_fetch_unsigned, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_l16a16_uint_description = {
PIPE_FORMAT_L16A16_UINT,
"PIPE_FORMAT_L16A16_UINT",
"l16a16_uint",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 16, 0}, /* x = rgb */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 16, 16}, /* y = a */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_X, /* g */
UTIL_FORMAT_SWIZZLE_X, /* b */
UTIL_FORMAT_SWIZZLE_Y /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_l16a16_uint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_l16a16_uint_pack_unsigned, /* pack_rgba_uint */
&util_format_l16a16_uint_unpack_signed, /* unpack_rgba_sint */
&util_format_l16a16_uint_pack_signed, /* pack_rgba_sint */
&util_format_l16a16_uint_fetch_unsigned, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_a16_sint_description = {
PIPE_FORMAT_A16_SINT,
"PIPE_FORMAT_A16_SINT",
"a16_sint",
{1, 1, 16}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 16, 0}, /* x = a */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_0, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_X /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_a16_sint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_a16_sint_pack_unsigned, /* pack_rgba_uint */
&util_format_a16_sint_unpack_signed, /* unpack_rgba_sint */
&util_format_a16_sint_pack_signed, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
&util_format_a16_sint_fetch_signed /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_i16_sint_description = {
PIPE_FORMAT_I16_SINT,
"PIPE_FORMAT_I16_SINT",
"i16_sint",
{1, 1, 16}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 16, 0}, /* x = rgba */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_X, /* g */
UTIL_FORMAT_SWIZZLE_X, /* b */
UTIL_FORMAT_SWIZZLE_X /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_i16_sint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_i16_sint_pack_unsigned, /* pack_rgba_uint */
&util_format_i16_sint_unpack_signed, /* unpack_rgba_sint */
&util_format_i16_sint_pack_signed, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
&util_format_i16_sint_fetch_signed /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_l16_sint_description = {
PIPE_FORMAT_L16_SINT,
"PIPE_FORMAT_L16_SINT",
"l16_sint",
{1, 1, 16}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 16, 0}, /* x = rgb */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_X, /* g */
UTIL_FORMAT_SWIZZLE_X, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_l16_sint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_l16_sint_pack_unsigned, /* pack_rgba_uint */
&util_format_l16_sint_unpack_signed, /* unpack_rgba_sint */
&util_format_l16_sint_pack_signed, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
&util_format_l16_sint_fetch_signed /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_l16a16_sint_description = {
PIPE_FORMAT_L16A16_SINT,
"PIPE_FORMAT_L16A16_SINT",
"l16a16_sint",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 16, 0}, /* x = rgb */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 16, 16}, /* y = a */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_X, /* g */
UTIL_FORMAT_SWIZZLE_X, /* b */
UTIL_FORMAT_SWIZZLE_Y /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_l16a16_sint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_l16a16_sint_pack_unsigned, /* pack_rgba_uint */
&util_format_l16a16_sint_unpack_signed, /* unpack_rgba_sint */
&util_format_l16a16_sint_pack_signed, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
&util_format_l16a16_sint_fetch_signed /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_a32_uint_description = {
PIPE_FORMAT_A32_UINT,
"PIPE_FORMAT_A32_UINT",
"a32_uint",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 32, 0}, /* x = a */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_0, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_X /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_a32_uint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_a32_uint_pack_unsigned, /* pack_rgba_uint */
&util_format_a32_uint_unpack_signed, /* unpack_rgba_sint */
&util_format_a32_uint_pack_signed, /* pack_rgba_sint */
&util_format_a32_uint_fetch_unsigned, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_i32_uint_description = {
PIPE_FORMAT_I32_UINT,
"PIPE_FORMAT_I32_UINT",
"i32_uint",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 32, 0}, /* x = rgba */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_X, /* g */
UTIL_FORMAT_SWIZZLE_X, /* b */
UTIL_FORMAT_SWIZZLE_X /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_i32_uint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_i32_uint_pack_unsigned, /* pack_rgba_uint */
&util_format_i32_uint_unpack_signed, /* unpack_rgba_sint */
&util_format_i32_uint_pack_signed, /* pack_rgba_sint */
&util_format_i32_uint_fetch_unsigned, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_l32_uint_description = {
PIPE_FORMAT_L32_UINT,
"PIPE_FORMAT_L32_UINT",
"l32_uint",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 32, 0}, /* x = rgb */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_X, /* g */
UTIL_FORMAT_SWIZZLE_X, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_l32_uint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_l32_uint_pack_unsigned, /* pack_rgba_uint */
&util_format_l32_uint_unpack_signed, /* unpack_rgba_sint */
&util_format_l32_uint_pack_signed, /* pack_rgba_sint */
&util_format_l32_uint_fetch_unsigned, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_l32a32_uint_description = {
PIPE_FORMAT_L32A32_UINT,
"PIPE_FORMAT_L32A32_UINT",
"l32a32_uint",
{1, 1, 64}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 32, 0}, /* x = rgb */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 32, 32}, /* y = a */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_X, /* g */
UTIL_FORMAT_SWIZZLE_X, /* b */
UTIL_FORMAT_SWIZZLE_Y /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_l32a32_uint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_l32a32_uint_pack_unsigned, /* pack_rgba_uint */
&util_format_l32a32_uint_unpack_signed, /* unpack_rgba_sint */
&util_format_l32a32_uint_pack_signed, /* pack_rgba_sint */
&util_format_l32a32_uint_fetch_unsigned, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_a32_sint_description = {
PIPE_FORMAT_A32_SINT,
"PIPE_FORMAT_A32_SINT",
"a32_sint",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 32, 0}, /* x = a */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_0, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_X /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_a32_sint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_a32_sint_pack_unsigned, /* pack_rgba_uint */
&util_format_a32_sint_unpack_signed, /* unpack_rgba_sint */
&util_format_a32_sint_pack_signed, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
&util_format_a32_sint_fetch_signed /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_i32_sint_description = {
PIPE_FORMAT_I32_SINT,
"PIPE_FORMAT_I32_SINT",
"i32_sint",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 32, 0}, /* x = rgba */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_X, /* g */
UTIL_FORMAT_SWIZZLE_X, /* b */
UTIL_FORMAT_SWIZZLE_X /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_i32_sint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_i32_sint_pack_unsigned, /* pack_rgba_uint */
&util_format_i32_sint_unpack_signed, /* unpack_rgba_sint */
&util_format_i32_sint_pack_signed, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
&util_format_i32_sint_fetch_signed /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_l32_sint_description = {
PIPE_FORMAT_L32_SINT,
"PIPE_FORMAT_L32_SINT",
"l32_sint",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
1, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 32, 0}, /* x = rgb */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_X, /* g */
UTIL_FORMAT_SWIZZLE_X, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_l32_sint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_l32_sint_pack_unsigned, /* pack_rgba_uint */
&util_format_l32_sint_unpack_signed, /* unpack_rgba_sint */
&util_format_l32_sint_pack_signed, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
&util_format_l32_sint_fetch_signed /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_l32a32_sint_description = {
PIPE_FORMAT_L32A32_SINT,
"PIPE_FORMAT_L32A32_SINT",
"l32a32_sint",
{1, 1, 64}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 32, 0}, /* x = rgb */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 32, 32}, /* y = a */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_X, /* g */
UTIL_FORMAT_SWIZZLE_X, /* b */
UTIL_FORMAT_SWIZZLE_Y /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_l32a32_sint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_l32a32_sint_pack_unsigned, /* pack_rgba_uint */
&util_format_l32a32_sint_unpack_signed, /* unpack_rgba_sint */
&util_format_l32a32_sint_pack_signed, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
&util_format_l32a32_sint_fetch_signed /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r8g8b8x8_snorm_description = {
PIPE_FORMAT_R8G8B8X8_SNORM,
"PIPE_FORMAT_R8G8B8X8_SNORM",
"r8g8b8x8_snorm",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
4, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 0}, /* x = r */
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 8}, /* y = g */
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 16}, /* z = b */
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 24} /* w = x */
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r8g8b8x8_snorm_unpack_rgba_8unorm,
&util_format_r8g8b8x8_snorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r8g8b8x8_snorm_unpack_rgba_float,
&util_format_r8g8b8x8_snorm_pack_rgba_float,
&util_format_r8g8b8x8_snorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r8g8b8x8_srgb_description = {
PIPE_FORMAT_R8G8B8X8_SRGB,
"PIPE_FORMAT_R8G8B8X8_SRGB",
"r8g8b8x8_srgb",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
4, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 0}, /* x = r */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 8}, /* y = g */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 8, 16}, /* z = b */
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 24} /* w = x */
},
{
UTIL_FORMAT_SWIZZLE_X, /* sr */
UTIL_FORMAT_SWIZZLE_Y, /* sg */
UTIL_FORMAT_SWIZZLE_Z, /* sb */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_SRGB,
&util_format_r8g8b8x8_srgb_unpack_rgba_8unorm,
&util_format_r8g8b8x8_srgb_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r8g8b8x8_srgb_unpack_rgba_float,
&util_format_r8g8b8x8_srgb_pack_rgba_float,
&util_format_r8g8b8x8_srgb_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r8g8b8x8_uint_description = {
PIPE_FORMAT_R8G8B8X8_UINT,
"PIPE_FORMAT_R8G8B8X8_UINT",
"r8g8b8x8_uint",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
4, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 0}, /* x = r */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 8}, /* y = g */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 16}, /* z = b */
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 24} /* w = x */
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_r8g8b8x8_uint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_r8g8b8x8_uint_pack_unsigned, /* pack_rgba_uint */
&util_format_r8g8b8x8_uint_unpack_signed, /* unpack_rgba_sint */
&util_format_r8g8b8x8_uint_pack_signed, /* pack_rgba_sint */
&util_format_r8g8b8x8_uint_fetch_unsigned, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r8g8b8x8_sint_description = {
PIPE_FORMAT_R8G8B8X8_SINT,
"PIPE_FORMAT_R8G8B8X8_SINT",
"r8g8b8x8_sint",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
4, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 8, 0}, /* x = r */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 8, 8}, /* y = g */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 8, 16}, /* z = b */
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 8, 24} /* w = x */
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_r8g8b8x8_sint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_r8g8b8x8_sint_pack_unsigned, /* pack_rgba_uint */
&util_format_r8g8b8x8_sint_unpack_signed, /* unpack_rgba_sint */
&util_format_r8g8b8x8_sint_pack_signed, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
&util_format_r8g8b8x8_sint_fetch_signed /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r16g16b16x16_unorm_description = {
PIPE_FORMAT_R16G16B16X16_UNORM,
"PIPE_FORMAT_R16G16B16X16_UNORM",
"r16g16b16x16_unorm",
{1, 1, 64}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
4, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 16, 0}, /* x = r */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 16, 16}, /* y = g */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 16, 32}, /* z = b */
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 16, 48} /* w = x */
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r16g16b16x16_unorm_unpack_rgba_8unorm,
&util_format_r16g16b16x16_unorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r16g16b16x16_unorm_unpack_rgba_float,
&util_format_r16g16b16x16_unorm_pack_rgba_float,
&util_format_r16g16b16x16_unorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r16g16b16x16_snorm_description = {
PIPE_FORMAT_R16G16B16X16_SNORM,
"PIPE_FORMAT_R16G16B16X16_SNORM",
"r16g16b16x16_snorm",
{1, 1, 64}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
4, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 16, 0}, /* x = r */
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 16, 16}, /* y = g */
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 16, 32}, /* z = b */
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 16, 48} /* w = x */
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r16g16b16x16_snorm_unpack_rgba_8unorm,
&util_format_r16g16b16x16_snorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r16g16b16x16_snorm_unpack_rgba_float,
&util_format_r16g16b16x16_snorm_pack_rgba_float,
&util_format_r16g16b16x16_snorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r16g16b16x16_float_description = {
PIPE_FORMAT_R16G16B16X16_FLOAT,
"PIPE_FORMAT_R16G16B16X16_FLOAT",
"r16g16b16x16_float",
{1, 1, 64}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
4, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 16, 0}, /* x = r */
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 16, 16}, /* y = g */
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 16, 32}, /* z = b */
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 16, 48} /* w = x */
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r16g16b16x16_float_unpack_rgba_8unorm,
&util_format_r16g16b16x16_float_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r16g16b16x16_float_unpack_rgba_float,
&util_format_r16g16b16x16_float_pack_rgba_float,
&util_format_r16g16b16x16_float_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r16g16b16x16_uint_description = {
PIPE_FORMAT_R16G16B16X16_UINT,
"PIPE_FORMAT_R16G16B16X16_UINT",
"r16g16b16x16_uint",
{1, 1, 64}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
4, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 16, 0}, /* x = r */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 16, 16}, /* y = g */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 16, 32}, /* z = b */
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 16, 48} /* w = x */
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_r16g16b16x16_uint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_r16g16b16x16_uint_pack_unsigned, /* pack_rgba_uint */
&util_format_r16g16b16x16_uint_unpack_signed, /* unpack_rgba_sint */
&util_format_r16g16b16x16_uint_pack_signed, /* pack_rgba_sint */
&util_format_r16g16b16x16_uint_fetch_unsigned, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r16g16b16x16_sint_description = {
PIPE_FORMAT_R16G16B16X16_SINT,
"PIPE_FORMAT_R16G16B16X16_SINT",
"r16g16b16x16_sint",
{1, 1, 64}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
4, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 16, 0}, /* x = r */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 16, 16}, /* y = g */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 16, 32}, /* z = b */
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 16, 48} /* w = x */
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_r16g16b16x16_sint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_r16g16b16x16_sint_pack_unsigned, /* pack_rgba_uint */
&util_format_r16g16b16x16_sint_unpack_signed, /* unpack_rgba_sint */
&util_format_r16g16b16x16_sint_pack_signed, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
&util_format_r16g16b16x16_sint_fetch_signed /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r32g32b32x32_float_description = {
PIPE_FORMAT_R32G32B32X32_FLOAT,
"PIPE_FORMAT_R32G32B32X32_FLOAT",
"r32g32b32x32_float",
{1, 1, 128}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
4, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 32, 0}, /* x = r */
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 32, 32}, /* y = g */
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 32, 64}, /* z = b */
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 32, 96} /* w = x */
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r32g32b32x32_float_unpack_rgba_8unorm,
&util_format_r32g32b32x32_float_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r32g32b32x32_float_unpack_rgba_float,
&util_format_r32g32b32x32_float_pack_rgba_float,
&util_format_r32g32b32x32_float_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r32g32b32x32_uint_description = {
PIPE_FORMAT_R32G32B32X32_UINT,
"PIPE_FORMAT_R32G32B32X32_UINT",
"r32g32b32x32_uint",
{1, 1, 128}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
4, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 32, 0}, /* x = r */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 32, 32}, /* y = g */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 32, 64}, /* z = b */
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 32, 96} /* w = x */
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_r32g32b32x32_uint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_r32g32b32x32_uint_pack_unsigned, /* pack_rgba_uint */
&util_format_r32g32b32x32_uint_unpack_signed, /* unpack_rgba_sint */
&util_format_r32g32b32x32_uint_pack_signed, /* pack_rgba_sint */
&util_format_r32g32b32x32_uint_fetch_unsigned, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r32g32b32x32_sint_description = {
PIPE_FORMAT_R32G32B32X32_SINT,
"PIPE_FORMAT_R32G32B32X32_SINT",
"r32g32b32x32_sint",
{1, 1, 128}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
4, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 32, 0}, /* x = r */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 32, 32}, /* y = g */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 32, 64}, /* z = b */
{UTIL_FORMAT_TYPE_VOID, FALSE, FALSE, 32, 96} /* w = x */
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_Y, /* g */
UTIL_FORMAT_SWIZZLE_Z, /* b */
UTIL_FORMAT_SWIZZLE_1 /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_r32g32b32x32_sint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_r32g32b32x32_sint_pack_unsigned, /* pack_rgba_uint */
&util_format_r32g32b32x32_sint_unpack_signed, /* unpack_rgba_sint */
&util_format_r32g32b32x32_sint_pack_signed, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
&util_format_r32g32b32x32_sint_fetch_signed /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r8a8_snorm_description = {
PIPE_FORMAT_R8A8_SNORM,
"PIPE_FORMAT_R8A8_SNORM",
"r8a8_snorm",
{1, 1, 16}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 0}, /* x = r */
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 8, 8}, /* y = a */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_Y /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r8a8_snorm_unpack_rgba_8unorm,
&util_format_r8a8_snorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r8a8_snorm_unpack_rgba_float,
&util_format_r8a8_snorm_pack_rgba_float,
&util_format_r8a8_snorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r16a16_unorm_description = {
PIPE_FORMAT_R16A16_UNORM,
"PIPE_FORMAT_R16A16_UNORM",
"r16a16_unorm",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 16, 0}, /* x = r */
{UTIL_FORMAT_TYPE_UNSIGNED, TRUE, FALSE, 16, 16}, /* y = a */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_Y /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r16a16_unorm_unpack_rgba_8unorm,
&util_format_r16a16_unorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r16a16_unorm_unpack_rgba_float,
&util_format_r16a16_unorm_pack_rgba_float,
&util_format_r16a16_unorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r16a16_snorm_description = {
PIPE_FORMAT_R16A16_SNORM,
"PIPE_FORMAT_R16A16_SNORM",
"r16a16_snorm",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 16, 0}, /* x = r */
{UTIL_FORMAT_TYPE_SIGNED, TRUE, FALSE, 16, 16}, /* y = a */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_Y /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r16a16_snorm_unpack_rgba_8unorm,
&util_format_r16a16_snorm_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r16a16_snorm_unpack_rgba_float,
&util_format_r16a16_snorm_pack_rgba_float,
&util_format_r16a16_snorm_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r16a16_float_description = {
PIPE_FORMAT_R16A16_FLOAT,
"PIPE_FORMAT_R16A16_FLOAT",
"r16a16_float",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 16, 0}, /* x = r */
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 16, 16}, /* y = a */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_Y /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r16a16_float_unpack_rgba_8unorm,
&util_format_r16a16_float_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r16a16_float_unpack_rgba_float,
&util_format_r16a16_float_pack_rgba_float,
&util_format_r16a16_float_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r32a32_float_description = {
PIPE_FORMAT_R32A32_FLOAT,
"PIPE_FORMAT_R32A32_FLOAT",
"r32a32_float",
{1, 1, 64}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 32, 0}, /* x = r */
{UTIL_FORMAT_TYPE_FLOAT, FALSE, FALSE, 32, 32}, /* y = a */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_Y /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
&util_format_r32a32_float_unpack_rgba_8unorm,
&util_format_r32a32_float_pack_rgba_8unorm,
NULL, /* fetch_rgba_8unorm */
&util_format_r32a32_float_unpack_rgba_float,
&util_format_r32a32_float_pack_rgba_float,
&util_format_r32a32_float_fetch_rgba_float,
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
NULL, /* unpack_rgba_uint */
NULL, /* pack_rgba_uint */
NULL, /* unpack_rgba_sint */
NULL, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r8a8_uint_description = {
PIPE_FORMAT_R8A8_UINT,
"PIPE_FORMAT_R8A8_UINT",
"r8a8_uint",
{1, 1, 16}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 0}, /* x = r */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 8, 8}, /* y = a */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_Y /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_r8a8_uint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_r8a8_uint_pack_unsigned, /* pack_rgba_uint */
&util_format_r8a8_uint_unpack_signed, /* unpack_rgba_sint */
&util_format_r8a8_uint_pack_signed, /* pack_rgba_sint */
&util_format_r8a8_uint_fetch_unsigned, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r8a8_sint_description = {
PIPE_FORMAT_R8A8_SINT,
"PIPE_FORMAT_R8A8_SINT",
"r8a8_sint",
{1, 1, 16}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 8, 0}, /* x = r */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 8, 8}, /* y = a */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_Y /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_r8a8_sint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_r8a8_sint_pack_unsigned, /* pack_rgba_uint */
&util_format_r8a8_sint_unpack_signed, /* unpack_rgba_sint */
&util_format_r8a8_sint_pack_signed, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
&util_format_r8a8_sint_fetch_signed /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r16a16_uint_description = {
PIPE_FORMAT_R16A16_UINT,
"PIPE_FORMAT_R16A16_UINT",
"r16a16_uint",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 16, 0}, /* x = r */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 16, 16}, /* y = a */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_Y /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_r16a16_uint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_r16a16_uint_pack_unsigned, /* pack_rgba_uint */
&util_format_r16a16_uint_unpack_signed, /* unpack_rgba_sint */
&util_format_r16a16_uint_pack_signed, /* pack_rgba_sint */
&util_format_r16a16_uint_fetch_unsigned, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r16a16_sint_description = {
PIPE_FORMAT_R16A16_SINT,
"PIPE_FORMAT_R16A16_SINT",
"r16a16_sint",
{1, 1, 32}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
TRUE, /* is_array */
TRUE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 16, 0}, /* x = r */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 16, 16}, /* y = a */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_Y /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_r16a16_sint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_r16a16_sint_pack_unsigned, /* pack_rgba_uint */
&util_format_r16a16_sint_unpack_signed, /* unpack_rgba_sint */
&util_format_r16a16_sint_pack_signed, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
&util_format_r16a16_sint_fetch_signed /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r32a32_uint_description = {
PIPE_FORMAT_R32A32_UINT,
"PIPE_FORMAT_R32A32_UINT",
"r32a32_uint",
{1, 1, 64}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 32, 0}, /* x = r */
{UTIL_FORMAT_TYPE_UNSIGNED, FALSE, TRUE, 32, 32}, /* y = a */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_Y /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_r32a32_uint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_r32a32_uint_pack_unsigned, /* pack_rgba_uint */
&util_format_r32a32_uint_unpack_signed, /* unpack_rgba_sint */
&util_format_r32a32_uint_pack_signed, /* pack_rgba_sint */
&util_format_r32a32_uint_fetch_unsigned, /* fetch_rgba_uint */
NULL /* fetch_rgba_sint */
};
 
const struct util_format_description
util_format_r32a32_sint_description = {
PIPE_FORMAT_R32A32_SINT,
"PIPE_FORMAT_R32A32_SINT",
"r32a32_sint",
{1, 1, 64}, /* block */
UTIL_FORMAT_LAYOUT_PLAIN,
2, /* nr_channels */
TRUE, /* is_array */
FALSE, /* is_bitmask */
FALSE, /* is_mixed */
{
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 32, 0}, /* x = r */
{UTIL_FORMAT_TYPE_SIGNED, FALSE, TRUE, 32, 32}, /* y = a */
{0, 0, 0, 0, 0},
{0, 0, 0, 0, 0}
},
{
UTIL_FORMAT_SWIZZLE_X, /* r */
UTIL_FORMAT_SWIZZLE_0, /* g */
UTIL_FORMAT_SWIZZLE_0, /* b */
UTIL_FORMAT_SWIZZLE_Y /* a */
},
UTIL_FORMAT_COLORSPACE_RGB,
NULL, /* unpack_rgba_8unorm */
NULL, /* pack_rgba_8unorm */
NULL, /* fetch_rgba_8unorm */
NULL, /* unpack_rgba_float */
NULL, /* pack_rgba_float */
NULL, /* fetch_rgba_float */
NULL, /* unpack_z_32unorm */
NULL, /* pack_z_32unorm */
NULL, /* unpack_z_float */
NULL, /* pack_z_float */
NULL, /* unpack_s_8uint */
NULL, /* pack_s_8uint */
&util_format_r32a32_sint_unpack_unsigned, /* unpack_rgba_uint */
&util_format_r32a32_sint_pack_unsigned, /* pack_rgba_uint */
&util_format_r32a32_sint_unpack_signed, /* unpack_rgba_sint */
&util_format_r32a32_sint_pack_signed, /* pack_rgba_sint */
NULL, /* fetch_rgba_uint */
&util_format_r32a32_sint_fetch_signed /* fetch_rgba_sint */
};
 
const struct util_format_description *
util_format_description(enum pipe_format format)
{
if (format >= PIPE_FORMAT_COUNT) {
return NULL;
}
 
switch (format) {
case PIPE_FORMAT_NONE:
return &util_format_none_description;
case PIPE_FORMAT_B8G8R8A8_UNORM:
return &util_format_b8g8r8a8_unorm_description;
case PIPE_FORMAT_B8G8R8X8_UNORM:
return &util_format_b8g8r8x8_unorm_description;
case PIPE_FORMAT_A8R8G8B8_UNORM:
return &util_format_a8r8g8b8_unorm_description;
case PIPE_FORMAT_X8R8G8B8_UNORM:
return &util_format_x8r8g8b8_unorm_description;
case PIPE_FORMAT_A8B8G8R8_UNORM:
return &util_format_a8b8g8r8_unorm_description;
case PIPE_FORMAT_X8B8G8R8_UNORM:
return &util_format_x8b8g8r8_unorm_description;
case PIPE_FORMAT_R8G8B8X8_UNORM:
return &util_format_r8g8b8x8_unorm_description;
case PIPE_FORMAT_L8_UNORM:
return &util_format_l8_unorm_description;
case PIPE_FORMAT_A8_UNORM:
return &util_format_a8_unorm_description;
case PIPE_FORMAT_I8_UNORM:
return &util_format_i8_unorm_description;
case PIPE_FORMAT_L4A4_UNORM:
return &util_format_l4a4_unorm_description;
case PIPE_FORMAT_L8A8_UNORM:
return &util_format_l8a8_unorm_description;
case PIPE_FORMAT_L16_UNORM:
return &util_format_l16_unorm_description;
case PIPE_FORMAT_A16_UNORM:
return &util_format_a16_unorm_description;
case PIPE_FORMAT_I16_UNORM:
return &util_format_i16_unorm_description;
case PIPE_FORMAT_L16A16_UNORM:
return &util_format_l16a16_unorm_description;
case PIPE_FORMAT_A8_SNORM:
return &util_format_a8_snorm_description;
case PIPE_FORMAT_L8_SNORM:
return &util_format_l8_snorm_description;
case PIPE_FORMAT_L8A8_SNORM:
return &util_format_l8a8_snorm_description;
case PIPE_FORMAT_I8_SNORM:
return &util_format_i8_snorm_description;
case PIPE_FORMAT_A16_SNORM:
return &util_format_a16_snorm_description;
case PIPE_FORMAT_L16_SNORM:
return &util_format_l16_snorm_description;
case PIPE_FORMAT_L16A16_SNORM:
return &util_format_l16a16_snorm_description;
case PIPE_FORMAT_I16_SNORM:
return &util_format_i16_snorm_description;
case PIPE_FORMAT_A16_FLOAT:
return &util_format_a16_float_description;
case PIPE_FORMAT_L16_FLOAT:
return &util_format_l16_float_description;
case PIPE_FORMAT_L16A16_FLOAT:
return &util_format_l16a16_float_description;
case PIPE_FORMAT_I16_FLOAT:
return &util_format_i16_float_description;
case PIPE_FORMAT_A32_FLOAT:
return &util_format_a32_float_description;
case PIPE_FORMAT_L32_FLOAT:
return &util_format_l32_float_description;
case PIPE_FORMAT_L32A32_FLOAT:
return &util_format_l32a32_float_description;
case PIPE_FORMAT_I32_FLOAT:
return &util_format_i32_float_description;
case PIPE_FORMAT_R8SG8SB8UX8U_NORM:
return &util_format_r8sg8sb8ux8u_norm_description;
case PIPE_FORMAT_R5SG5SB6U_NORM:
return &util_format_r5sg5sb6u_norm_description;
case PIPE_FORMAT_S8_UINT:
return &util_format_s8_uint_description;
case PIPE_FORMAT_Z16_UNORM:
return &util_format_z16_unorm_description;
case PIPE_FORMAT_Z32_UNORM:
return &util_format_z32_unorm_description;
case PIPE_FORMAT_Z32_FLOAT:
return &util_format_z32_float_description;
case PIPE_FORMAT_Z24_UNORM_S8_UINT:
return &util_format_z24_unorm_s8_uint_description;
case PIPE_FORMAT_S8_UINT_Z24_UNORM:
return &util_format_s8_uint_z24_unorm_description;
case PIPE_FORMAT_X24S8_UINT:
return &util_format_x24s8_uint_description;
case PIPE_FORMAT_S8X24_UINT:
return &util_format_s8x24_uint_description;
case PIPE_FORMAT_Z24X8_UNORM:
return &util_format_z24x8_unorm_description;
case PIPE_FORMAT_X8Z24_UNORM:
return &util_format_x8z24_unorm_description;
case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
return &util_format_z32_float_s8x24_uint_description;
case PIPE_FORMAT_X32_S8X24_UINT:
return &util_format_x32_s8x24_uint_description;
case PIPE_FORMAT_UYVY:
return &util_format_uyvy_description;
case PIPE_FORMAT_YUYV:
return &util_format_yuyv_description;
case PIPE_FORMAT_R8G8_B8G8_UNORM:
return &util_format_r8g8_b8g8_unorm_description;
case PIPE_FORMAT_G8R8_G8B8_UNORM:
return &util_format_g8r8_g8b8_unorm_description;
case PIPE_FORMAT_G8R8_B8R8_UNORM:
return &util_format_g8r8_b8r8_unorm_description;
case PIPE_FORMAT_R8G8_R8B8_UNORM:
return &util_format_r8g8_r8b8_unorm_description;
case PIPE_FORMAT_R11G11B10_FLOAT:
return &util_format_r11g11b10_float_description;
case PIPE_FORMAT_R9G9B9E5_FLOAT:
return &util_format_r9g9b9e5_float_description;
case PIPE_FORMAT_R1_UNORM:
return &util_format_r1_unorm_description;
case PIPE_FORMAT_R8G8Bx_SNORM:
return &util_format_r8g8bx_snorm_description;
case PIPE_FORMAT_R64_FLOAT:
return &util_format_r64_float_description;
case PIPE_FORMAT_R64G64_FLOAT:
return &util_format_r64g64_float_description;
case PIPE_FORMAT_R64G64B64_FLOAT:
return &util_format_r64g64b64_float_description;
case PIPE_FORMAT_R64G64B64A64_FLOAT:
return &util_format_r64g64b64a64_float_description;
case PIPE_FORMAT_R32_FLOAT:
return &util_format_r32_float_description;
case PIPE_FORMAT_R32G32_FLOAT:
return &util_format_r32g32_float_description;
case PIPE_FORMAT_R32G32B32_FLOAT:
return &util_format_r32g32b32_float_description;
case PIPE_FORMAT_R32G32B32A32_FLOAT:
return &util_format_r32g32b32a32_float_description;
case PIPE_FORMAT_R32_UNORM:
return &util_format_r32_unorm_description;
case PIPE_FORMAT_R32G32_UNORM:
return &util_format_r32g32_unorm_description;
case PIPE_FORMAT_R32G32B32_UNORM:
return &util_format_r32g32b32_unorm_description;
case PIPE_FORMAT_R32G32B32A32_UNORM:
return &util_format_r32g32b32a32_unorm_description;
case PIPE_FORMAT_R32_USCALED:
return &util_format_r32_uscaled_description;
case PIPE_FORMAT_R32G32_USCALED:
return &util_format_r32g32_uscaled_description;
case PIPE_FORMAT_R32G32B32_USCALED:
return &util_format_r32g32b32_uscaled_description;
case PIPE_FORMAT_R32G32B32A32_USCALED:
return &util_format_r32g32b32a32_uscaled_description;
case PIPE_FORMAT_R32_SNORM:
return &util_format_r32_snorm_description;
case PIPE_FORMAT_R32G32_SNORM:
return &util_format_r32g32_snorm_description;
case PIPE_FORMAT_R32G32B32_SNORM:
return &util_format_r32g32b32_snorm_description;
case PIPE_FORMAT_R32G32B32A32_SNORM:
return &util_format_r32g32b32a32_snorm_description;
case PIPE_FORMAT_R32_SSCALED:
return &util_format_r32_sscaled_description;
case PIPE_FORMAT_R32G32_SSCALED:
return &util_format_r32g32_sscaled_description;
case PIPE_FORMAT_R32G32B32_SSCALED:
return &util_format_r32g32b32_sscaled_description;
case PIPE_FORMAT_R32G32B32A32_SSCALED:
return &util_format_r32g32b32a32_sscaled_description;
case PIPE_FORMAT_R16_FLOAT:
return &util_format_r16_float_description;
case PIPE_FORMAT_R16G16_FLOAT:
return &util_format_r16g16_float_description;
case PIPE_FORMAT_R16G16B16_FLOAT:
return &util_format_r16g16b16_float_description;
case PIPE_FORMAT_R16G16B16A16_FLOAT:
return &util_format_r16g16b16a16_float_description;
case PIPE_FORMAT_R16_UNORM:
return &util_format_r16_unorm_description;
case PIPE_FORMAT_R16G16_UNORM:
return &util_format_r16g16_unorm_description;
case PIPE_FORMAT_R16G16B16_UNORM:
return &util_format_r16g16b16_unorm_description;
case PIPE_FORMAT_R16G16B16A16_UNORM:
return &util_format_r16g16b16a16_unorm_description;
case PIPE_FORMAT_R16_USCALED:
return &util_format_r16_uscaled_description;
case PIPE_FORMAT_R16G16_USCALED:
return &util_format_r16g16_uscaled_description;
case PIPE_FORMAT_R16G16B16_USCALED:
return &util_format_r16g16b16_uscaled_description;
case PIPE_FORMAT_R16G16B16A16_USCALED:
return &util_format_r16g16b16a16_uscaled_description;
case PIPE_FORMAT_R16_SNORM:
return &util_format_r16_snorm_description;
case PIPE_FORMAT_R16G16_SNORM:
return &util_format_r16g16_snorm_description;
case PIPE_FORMAT_R16G16B16_SNORM:
return &util_format_r16g16b16_snorm_description;
case PIPE_FORMAT_R16G16B16A16_SNORM:
return &util_format_r16g16b16a16_snorm_description;
case PIPE_FORMAT_R16_SSCALED:
return &util_format_r16_sscaled_description;
case PIPE_FORMAT_R16G16_SSCALED:
return &util_format_r16g16_sscaled_description;
case PIPE_FORMAT_R16G16B16_SSCALED:
return &util_format_r16g16b16_sscaled_description;
case PIPE_FORMAT_R16G16B16A16_SSCALED:
return &util_format_r16g16b16a16_sscaled_description;
case PIPE_FORMAT_R8_UNORM:
return &util_format_r8_unorm_description;
case PIPE_FORMAT_R8G8_UNORM:
return &util_format_r8g8_unorm_description;
case PIPE_FORMAT_R8G8B8_UNORM:
return &util_format_r8g8b8_unorm_description;
case PIPE_FORMAT_R8G8B8A8_UNORM:
return &util_format_r8g8b8a8_unorm_description;
case PIPE_FORMAT_R8_USCALED:
return &util_format_r8_uscaled_description;
case PIPE_FORMAT_R8G8_USCALED:
return &util_format_r8g8_uscaled_description;
case PIPE_FORMAT_R8G8B8_USCALED:
return &util_format_r8g8b8_uscaled_description;
case PIPE_FORMAT_R8G8B8A8_USCALED:
return &util_format_r8g8b8a8_uscaled_description;
case PIPE_FORMAT_R8_SNORM:
return &util_format_r8_snorm_description;
case PIPE_FORMAT_R8G8_SNORM:
return &util_format_r8g8_snorm_description;
case PIPE_FORMAT_R8G8B8_SNORM:
return &util_format_r8g8b8_snorm_description;
case PIPE_FORMAT_R8G8B8A8_SNORM:
return &util_format_r8g8b8a8_snorm_description;
case PIPE_FORMAT_R8_SSCALED:
return &util_format_r8_sscaled_description;
case PIPE_FORMAT_R8G8_SSCALED:
return &util_format_r8g8_sscaled_description;
case PIPE_FORMAT_R8G8B8_SSCALED:
return &util_format_r8g8b8_sscaled_description;
case PIPE_FORMAT_R8G8B8A8_SSCALED:
return &util_format_r8g8b8a8_sscaled_description;
case PIPE_FORMAT_R32_FIXED:
return &util_format_r32_fixed_description;
case PIPE_FORMAT_R32G32_FIXED:
return &util_format_r32g32_fixed_description;
case PIPE_FORMAT_R32G32B32_FIXED:
return &util_format_r32g32b32_fixed_description;
case PIPE_FORMAT_R32G32B32A32_FIXED:
return &util_format_r32g32b32a32_fixed_description;
case PIPE_FORMAT_R10G10B10X2_USCALED:
return &util_format_r10g10b10x2_uscaled_description;
case PIPE_FORMAT_R10G10B10X2_SNORM:
return &util_format_r10g10b10x2_snorm_description;
case PIPE_FORMAT_YV12:
return &util_format_yv12_description;
case PIPE_FORMAT_YV16:
return &util_format_yv16_description;
case PIPE_FORMAT_IYUV:
return &util_format_iyuv_description;
case PIPE_FORMAT_NV12:
return &util_format_nv12_description;
case PIPE_FORMAT_NV21:
return &util_format_nv21_description;
case PIPE_FORMAT_R4A4_UNORM:
return &util_format_r4a4_unorm_description;
case PIPE_FORMAT_A4R4_UNORM:
return &util_format_a4r4_unorm_description;
case PIPE_FORMAT_R8A8_UNORM:
return &util_format_r8a8_unorm_description;
case PIPE_FORMAT_A8R8_UNORM:
return &util_format_a8r8_unorm_description;
case PIPE_FORMAT_R8_UINT:
return &util_format_r8_uint_description;
case PIPE_FORMAT_R8G8_UINT:
return &util_format_r8g8_uint_description;
case PIPE_FORMAT_R8G8B8_UINT:
return &util_format_r8g8b8_uint_description;
case PIPE_FORMAT_R8G8B8A8_UINT:
return &util_format_r8g8b8a8_uint_description;
case PIPE_FORMAT_R8_SINT:
return &util_format_r8_sint_description;
case PIPE_FORMAT_R8G8_SINT:
return &util_format_r8g8_sint_description;
case PIPE_FORMAT_R8G8B8_SINT:
return &util_format_r8g8b8_sint_description;
case PIPE_FORMAT_R8G8B8A8_SINT:
return &util_format_r8g8b8a8_sint_description;
case PIPE_FORMAT_R16_UINT:
return &util_format_r16_uint_description;
case PIPE_FORMAT_R16G16_UINT:
return &util_format_r16g16_uint_description;
case PIPE_FORMAT_R16G16B16_UINT:
return &util_format_r16g16b16_uint_description;
case PIPE_FORMAT_R16G16B16A16_UINT:
return &util_format_r16g16b16a16_uint_description;
case PIPE_FORMAT_R16_SINT:
return &util_format_r16_sint_description;
case PIPE_FORMAT_R16G16_SINT:
return &util_format_r16g16_sint_description;
case PIPE_FORMAT_R16G16B16_SINT:
return &util_format_r16g16b16_sint_description;
case PIPE_FORMAT_R16G16B16A16_SINT:
return &util_format_r16g16b16a16_sint_description;
case PIPE_FORMAT_R32_UINT:
return &util_format_r32_uint_description;
case PIPE_FORMAT_R32G32_UINT:
return &util_format_r32g32_uint_description;
case PIPE_FORMAT_R32G32B32_UINT:
return &util_format_r32g32b32_uint_description;
case PIPE_FORMAT_R32G32B32A32_UINT:
return &util_format_r32g32b32a32_uint_description;
case PIPE_FORMAT_R32_SINT:
return &util_format_r32_sint_description;
case PIPE_FORMAT_R32G32_SINT:
return &util_format_r32g32_sint_description;
case PIPE_FORMAT_R32G32B32_SINT:
return &util_format_r32g32b32_sint_description;
case PIPE_FORMAT_R32G32B32A32_SINT:
return &util_format_r32g32b32a32_sint_description;
case PIPE_FORMAT_A8_UINT:
return &util_format_a8_uint_description;
case PIPE_FORMAT_I8_UINT:
return &util_format_i8_uint_description;
case PIPE_FORMAT_L8_UINT:
return &util_format_l8_uint_description;
case PIPE_FORMAT_L8A8_UINT:
return &util_format_l8a8_uint_description;
case PIPE_FORMAT_A8_SINT:
return &util_format_a8_sint_description;
case PIPE_FORMAT_I8_SINT:
return &util_format_i8_sint_description;
case PIPE_FORMAT_L8_SINT:
return &util_format_l8_sint_description;
case PIPE_FORMAT_L8A8_SINT:
return &util_format_l8a8_sint_description;
case PIPE_FORMAT_A16_UINT:
return &util_format_a16_uint_description;
case PIPE_FORMAT_I16_UINT:
return &util_format_i16_uint_description;
case PIPE_FORMAT_L16_UINT:
return &util_format_l16_uint_description;
case PIPE_FORMAT_L16A16_UINT:
return &util_format_l16a16_uint_description;
case PIPE_FORMAT_A16_SINT:
return &util_format_a16_sint_description;
case PIPE_FORMAT_I16_SINT:
return &util_format_i16_sint_description;
case PIPE_FORMAT_L16_SINT:
return &util_format_l16_sint_description;
case PIPE_FORMAT_L16A16_SINT:
return &util_format_l16a16_sint_description;
case PIPE_FORMAT_A32_UINT:
return &util_format_a32_uint_description;
case PIPE_FORMAT_I32_UINT:
return &util_format_i32_uint_description;
case PIPE_FORMAT_L32_UINT:
return &util_format_l32_uint_description;
case PIPE_FORMAT_L32A32_UINT:
return &util_format_l32a32_uint_description;
case PIPE_FORMAT_A32_SINT:
return &util_format_a32_sint_description;
case PIPE_FORMAT_I32_SINT:
return &util_format_i32_sint_description;
case PIPE_FORMAT_L32_SINT:
return &util_format_l32_sint_description;
case PIPE_FORMAT_L32A32_SINT:
return &util_format_l32a32_sint_description;
case PIPE_FORMAT_R8G8B8X8_SNORM:
return &util_format_r8g8b8x8_snorm_description;
case PIPE_FORMAT_R8G8B8X8_SRGB:
return &util_format_r8g8b8x8_srgb_description;
case PIPE_FORMAT_R8G8B8X8_UINT:
return &util_format_r8g8b8x8_uint_description;
case PIPE_FORMAT_R8G8B8X8_SINT:
return &util_format_r8g8b8x8_sint_description;
case PIPE_FORMAT_R16G16B16X16_UNORM:
return &util_format_r16g16b16x16_unorm_description;
case PIPE_FORMAT_R16G16B16X16_SNORM:
return &util_format_r16g16b16x16_snorm_description;
case PIPE_FORMAT_R16G16B16X16_FLOAT:
return &util_format_r16g16b16x16_float_description;
case PIPE_FORMAT_R16G16B16X16_UINT:
return &util_format_r16g16b16x16_uint_description;
case PIPE_FORMAT_R16G16B16X16_SINT:
return &util_format_r16g16b16x16_sint_description;
case PIPE_FORMAT_R32G32B32X32_FLOAT:
return &util_format_r32g32b32x32_float_description;
case PIPE_FORMAT_R32G32B32X32_UINT:
return &util_format_r32g32b32x32_uint_description;
case PIPE_FORMAT_R32G32B32X32_SINT:
return &util_format_r32g32b32x32_sint_description;
case PIPE_FORMAT_R8A8_SNORM:
return &util_format_r8a8_snorm_description;
case PIPE_FORMAT_R16A16_UNORM:
return &util_format_r16a16_unorm_description;
case PIPE_FORMAT_R16A16_SNORM:
return &util_format_r16a16_snorm_description;
case PIPE_FORMAT_R16A16_FLOAT:
return &util_format_r16a16_float_description;
case PIPE_FORMAT_R32A32_FLOAT:
return &util_format_r32a32_float_description;
case PIPE_FORMAT_R8A8_UINT:
return &util_format_r8a8_uint_description;
case PIPE_FORMAT_R8A8_SINT:
return &util_format_r8a8_sint_description;
case PIPE_FORMAT_R16A16_UINT:
return &util_format_r16a16_uint_description;
case PIPE_FORMAT_R16A16_SINT:
return &util_format_r16a16_sint_description;
case PIPE_FORMAT_R32A32_UINT:
return &util_format_r32a32_uint_description;
case PIPE_FORMAT_R32A32_SINT:
return &util_format_r32a32_sint_description;
default:
return NULL;
}
}
 
/drivers/video/Gallium/auxiliary/util/u_format_table.py
0,0 → 1,219
#!/usr/bin/env python
 
CopyRight = '''
/**************************************************************************
*
* Copyright 2010 VMware, Inc.
* 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 VMWARE 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.
*
**************************************************************************/
'''
 
 
import sys
 
from u_format_parse import *
import u_format_pack
 
 
def layout_map(layout):
return 'UTIL_FORMAT_LAYOUT_' + str(layout).upper()
 
 
def colorspace_map(colorspace):
return 'UTIL_FORMAT_COLORSPACE_' + str(colorspace).upper()
 
 
colorspace_channels_map = {
'rgb': ['r', 'g', 'b', 'a'],
'srgb': ['sr', 'sg', 'sb', 'a'],
'zs': ['z', 's'],
'yuv': ['y', 'u', 'v'],
}
 
 
type_map = {
VOID: "UTIL_FORMAT_TYPE_VOID",
UNSIGNED: "UTIL_FORMAT_TYPE_UNSIGNED",
SIGNED: "UTIL_FORMAT_TYPE_SIGNED",
FIXED: "UTIL_FORMAT_TYPE_FIXED",
FLOAT: "UTIL_FORMAT_TYPE_FLOAT",
}
 
 
def bool_map(value):
if value:
return "TRUE"
else:
return "FALSE"
 
 
swizzle_map = {
SWIZZLE_X: "UTIL_FORMAT_SWIZZLE_X",
SWIZZLE_Y: "UTIL_FORMAT_SWIZZLE_Y",
SWIZZLE_Z: "UTIL_FORMAT_SWIZZLE_Z",
SWIZZLE_W: "UTIL_FORMAT_SWIZZLE_W",
SWIZZLE_0: "UTIL_FORMAT_SWIZZLE_0",
SWIZZLE_1: "UTIL_FORMAT_SWIZZLE_1",
SWIZZLE_NONE: "UTIL_FORMAT_SWIZZLE_NONE",
}
 
 
def write_format_table(formats):
print '/* This file is autogenerated by u_format_table.py from u_format.csv. Do not edit directly. */'
print
# This will print the copyright message on the top of this file
print CopyRight.strip()
print
print '#include "u_format.h"'
print '#include "u_format_s3tc.h"'
print '#include "u_format_rgtc.h"'
print '#include "u_format_latc.h"'
print '#include "u_format_etc.h"'
print
u_format_pack.generate(formats)
for format in formats:
print 'const struct util_format_description'
print 'util_format_%s_description = {' % (format.short_name(),)
print " %s," % (format.name,)
print " \"%s\"," % (format.name,)
print " \"%s\"," % (format.short_name(),)
print " {%u, %u, %u},\t/* block */" % (format.block_width, format.block_height, format.block_size())
print " %s," % (layout_map(format.layout),)
print " %u,\t/* nr_channels */" % (format.nr_channels(),)
print " %s,\t/* is_array */" % (bool_map(format.is_array()),)
print " %s,\t/* is_bitmask */" % (bool_map(format.is_bitmask()),)
print " %s,\t/* is_mixed */" % (bool_map(format.is_mixed()),)
print " {"
for i in range(4):
channel = format.channels[i]
if i < 3:
sep = ","
else:
sep = ""
if channel.size:
print " {%s, %s, %s, %u, %u}%s\t/* %s = %s */" % (type_map[channel.type], bool_map(channel.norm), bool_map(channel.pure), channel.size, channel.shift, sep, "xyzw"[i], channel.name)
else:
print " {0, 0, 0, 0, 0}%s" % (sep,)
print " },"
print " {"
for i in range(4):
swizzle = format.swizzles[i]
if i < 3:
sep = ","
else:
sep = ""
try:
comment = colorspace_channels_map[format.colorspace][i]
except (KeyError, IndexError):
comment = 'ignored'
print " %s%s\t/* %s */" % (swizzle_map[swizzle], sep, comment)
print " },"
print " %s," % (colorspace_map(format.colorspace),)
if format.colorspace != ZS and format.channels[0].pure == False:
print " &util_format_%s_unpack_rgba_8unorm," % format.short_name()
print " &util_format_%s_pack_rgba_8unorm," % format.short_name()
if format.layout == 's3tc' or format.layout == 'rgtc':
print " &util_format_%s_fetch_rgba_8unorm," % format.short_name()
else:
print " NULL, /* fetch_rgba_8unorm */"
print " &util_format_%s_unpack_rgba_float," % format.short_name()
print " &util_format_%s_pack_rgba_float," % format.short_name()
print " &util_format_%s_fetch_rgba_float," % format.short_name()
else:
print " NULL, /* unpack_rgba_8unorm */"
print " NULL, /* pack_rgba_8unorm */"
print " NULL, /* fetch_rgba_8unorm */"
print " NULL, /* unpack_rgba_float */"
print " NULL, /* pack_rgba_float */"
print " NULL, /* fetch_rgba_float */"
if format.colorspace == ZS and format.swizzles[0] != SWIZZLE_NONE:
print " &util_format_%s_unpack_z_32unorm," % format.short_name()
print " &util_format_%s_pack_z_32unorm," % format.short_name()
print " &util_format_%s_unpack_z_float," % format.short_name()
print " &util_format_%s_pack_z_float," % format.short_name()
else:
print " NULL, /* unpack_z_32unorm */"
print " NULL, /* pack_z_32unorm */"
print " NULL, /* unpack_z_float */"
print " NULL, /* pack_z_float */"
if format.colorspace == ZS and format.swizzles[1] != SWIZZLE_NONE:
print " &util_format_%s_unpack_s_8uint," % format.short_name()
print " &util_format_%s_pack_s_8uint," % format.short_name()
else:
print " NULL, /* unpack_s_8uint */"
print " NULL, /* pack_s_8uint */"
if format.colorspace != ZS and format.channels[0].pure == True and format.channels[0].type == UNSIGNED:
print " &util_format_%s_unpack_unsigned, /* unpack_rgba_uint */" % format.short_name()
print " &util_format_%s_pack_unsigned, /* pack_rgba_uint */" % format.short_name()
print " &util_format_%s_unpack_signed, /* unpack_rgba_sint */" % format.short_name()
print " &util_format_%s_pack_signed, /* pack_rgba_sint */" % format.short_name()
print " &util_format_%s_fetch_unsigned, /* fetch_rgba_uint */" % format.short_name()
print " NULL /* fetch_rgba_sint */"
elif format.colorspace != ZS and format.channels[0].pure == True and format.channels[0].type == SIGNED:
print " &util_format_%s_unpack_unsigned, /* unpack_rgba_uint */" % format.short_name()
print " &util_format_%s_pack_unsigned, /* pack_rgba_uint */" % format.short_name()
print " &util_format_%s_unpack_signed, /* unpack_rgba_sint */" % format.short_name()
print " &util_format_%s_pack_signed, /* pack_rgba_sint */" % format.short_name()
print " NULL, /* fetch_rgba_uint */"
print " &util_format_%s_fetch_signed /* fetch_rgba_sint */" % format.short_name()
else:
print " NULL, /* unpack_rgba_uint */"
print " NULL, /* pack_rgba_uint */"
print " NULL, /* unpack_rgba_sint */"
print " NULL, /* pack_rgba_sint */"
print " NULL, /* fetch_rgba_uint */"
print " NULL /* fetch_rgba_sint */"
print "};"
print
print "const struct util_format_description *"
print "util_format_description(enum pipe_format format)"
print "{"
print " if (format >= PIPE_FORMAT_COUNT) {"
print " return NULL;"
print " }"
print
print " switch (format) {"
for format in formats:
print " case %s:" % format.name
print " return &util_format_%s_description;" % (format.short_name(),)
print " default:"
print " return NULL;"
print " }"
print "}"
print
 
 
def main():
 
formats = []
for arg in sys.argv[1:]:
formats.extend(parse(arg))
write_format_table(formats)
 
 
if __name__ == '__main__':
main()
/drivers/video/Gallium/auxiliary/util/u_format_tests.c
0,0 → 1,1006
/**************************************************************************
*
* Copyright 2009-2010 VMware, Inc.
* 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 VMWARE 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.
*
**************************************************************************/
 
 
#include <math.h>
#include <float.h>
 
#include "pipe/p_config.h"
#include "u_memory.h"
#include "u_format_tests.h"
 
 
/*
* Helper macros to create the packed bytes for longer words.
*/
 
#define PACKED_1x8(x) {x, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#define PACKED_2x8(x, y) {x, y, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#define PACKED_3x8(x, y, z) {x, y, z, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#define PACKED_4x8(x, y, z, w) {x, y, z, w, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#define PACKED_8x8(a, b, c, d, e, f, g, h) {a, b, c, d, e, f, g, h, 0, 0, 0, 0, 0, 0, 0, 0}
 
#define PACKED_1x16(x) {(x) & 0xff, (x) >> 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#define PACKED_2x16(x, y) {(x) & 0xff, (x) >> 8, (y) & 0xff, (y) >> 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#define PACKED_3x16(x, y, z) {(x) & 0xff, (x) >> 8, (y) & 0xff, (y) >> 8, (z) & 0xff, (z) >> 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#define PACKED_4x16(x, y, z, w) {(x) & 0xff, (x) >> 8, (y) & 0xff, (y) >> 8, (z) & 0xff, (z) >> 8, (w) & 0xff, (w) >> 8, 0, 0, 0, 0, 0, 0, 0, 0}
 
#define PACKED_1x32(x) {(x) & 0xff, ((x) >> 8) & 0xff, ((x) >> 16) & 0xff, (x) >> 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
#define PACKED_2x32(x, y) {(x) & 0xff, ((x) >> 8) & 0xff, ((x) >> 16) & 0xff, (x) >> 24, (y) & 0xff, ((y) >> 8) & 0xff, ((y) >> 16) & 0xff, (y) >> 24, 0, 0, 0, 0, 0, 0, 0, 0}
#define PACKED_3x32(x, y, z) {(x) & 0xff, ((x) >> 8) & 0xff, ((x) >> 16) & 0xff, (x) >> 24, (y) & 0xff, ((y) >> 8) & 0xff, ((y) >> 16) & 0xff, (y) >> 24, (z) & 0xff, ((z) >> 8) & 0xff, ((z) >> 16) & 0xff, (z) >> 24, 0, 0, 0, 0}
#define PACKED_4x32(x, y, z, w) {(x) & 0xff, ((x) >> 8) & 0xff, ((x) >> 16) & 0xff, (x) >> 24, (y) & 0xff, ((y) >> 8) & 0xff, ((y) >> 16) & 0xff, (y) >> 24, (z) & 0xff, ((z) >> 8) & 0xff, ((z) >> 16) & 0xff, (z) >> 24, (w) & 0xff, ((w) >> 8) & 0xff, ((w) >> 16) & 0xff, (w) >> 24}
 
#define UNPACKED_1x1(r, g, b, a) \
{{{r, g, b, a}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, \
{{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, \
{{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, \
{{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}}
 
#define UNPACKED_2x1(r0, g0, b0, a0, r1, g1, b1, a1) \
{{{r0, g0, b0, a0}, {r1, g1, b1, a1}, {0, 0, 0, 0}, {0, 0, 0, 0}}, \
{{ 0, 0, 0, 0}, { 0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, \
{{ 0, 0, 0, 0}, { 0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, \
{{ 0, 0, 0, 0}, { 0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}}
 
 
/**
* Test cases.
*
* These were manually entered. We could generate these
*
* To keep this to a we cover only the corner cases, which should produce
* good enough coverage since that pixel format transformations are afine for
* non SRGB formats.
*/
const struct util_format_test_case
util_format_test_cases[] =
{
 
/*
* 32-bit rendertarget formats
*/
 
{PIPE_FORMAT_B8G8R8A8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_B8G8R8A8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x000000ff), UNPACKED_1x1(0.0, 0.0, 1.0, 0.0)},
{PIPE_FORMAT_B8G8R8A8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x0000ff00), UNPACKED_1x1(0.0, 1.0, 0.0, 0.0)},
{PIPE_FORMAT_B8G8R8A8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00ff0000), UNPACKED_1x1(1.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_B8G8R8A8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xff000000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_B8G8R8A8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xffffffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)},
 
{PIPE_FORMAT_B8G8R8X8_UNORM, PACKED_1x32(0x00ffffff), PACKED_1x32(0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_B8G8R8X8_UNORM, PACKED_1x32(0x00ffffff), PACKED_1x32(0x000000ff), UNPACKED_1x1(0.0, 0.0, 1.0, 1.0)},
{PIPE_FORMAT_B8G8R8X8_UNORM, PACKED_1x32(0x00ffffff), PACKED_1x32(0x0000ff00), UNPACKED_1x1(0.0, 1.0, 0.0, 1.0)},
{PIPE_FORMAT_B8G8R8X8_UNORM, PACKED_1x32(0x00ffffff), PACKED_1x32(0x00ff0000), UNPACKED_1x1(1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_B8G8R8X8_UNORM, PACKED_1x32(0x00ffffff), PACKED_1x32(0xff000000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_B8G8R8X8_UNORM, PACKED_1x32(0x00ffffff), PACKED_1x32(0xffffffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)},
 
{PIPE_FORMAT_A8R8G8B8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_A8R8G8B8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x000000ff), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_A8R8G8B8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x0000ff00), UNPACKED_1x1(1.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_A8R8G8B8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00ff0000), UNPACKED_1x1(0.0, 1.0, 0.0, 0.0)},
{PIPE_FORMAT_A8R8G8B8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xff000000), UNPACKED_1x1(0.0, 0.0, 1.0, 0.0)},
{PIPE_FORMAT_A8R8G8B8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xffffffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)},
 
{PIPE_FORMAT_X8R8G8B8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_X8R8G8B8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0x000000ff), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_X8R8G8B8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0x0000ff00), UNPACKED_1x1(1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_X8R8G8B8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0x00ff0000), UNPACKED_1x1(0.0, 1.0, 0.0, 1.0)},
{PIPE_FORMAT_X8R8G8B8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0xff000000), UNPACKED_1x1(0.0, 0.0, 1.0, 1.0)},
{PIPE_FORMAT_X8R8G8B8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0xffffffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)},
 
{PIPE_FORMAT_A8B8G8R8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_A8B8G8R8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x000000ff), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_A8B8G8R8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x0000ff00), UNPACKED_1x1(0.0, 0.0, 1.0, 0.0)},
{PIPE_FORMAT_A8B8G8R8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00ff0000), UNPACKED_1x1(0.0, 1.0, 0.0, 0.0)},
{PIPE_FORMAT_A8B8G8R8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xff000000), UNPACKED_1x1(1.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_A8B8G8R8_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xffffffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)},
 
{PIPE_FORMAT_X8B8G8R8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_X8B8G8R8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0x000000ff), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_X8B8G8R8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0x0000ff00), UNPACKED_1x1(0.0, 0.0, 1.0, 1.0)},
{PIPE_FORMAT_X8B8G8R8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0x00ff0000), UNPACKED_1x1(0.0, 1.0, 0.0, 1.0)},
{PIPE_FORMAT_X8B8G8R8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0xff000000), UNPACKED_1x1(1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_X8B8G8R8_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0xffffffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)},
 
{PIPE_FORMAT_R8G8B8X8_UNORM, PACKED_1x32(0x00ffffff), PACKED_1x32(0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8B8X8_UNORM, PACKED_1x32(0x00ffffff), PACKED_1x32(0x000000ff), UNPACKED_1x1(1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8B8X8_UNORM, PACKED_1x32(0x00ffffff), PACKED_1x32(0x0000ff00), UNPACKED_1x1(0.0, 1.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8B8X8_UNORM, PACKED_1x32(0x00ffffff), PACKED_1x32(0x00ff0000), UNPACKED_1x1(0.0, 0.0, 1.0, 1.0)},
{PIPE_FORMAT_R8G8B8X8_UNORM, PACKED_1x32(0x00ffffff), PACKED_1x32(0xff000000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8B8X8_UNORM, PACKED_1x32(0x00ffffff), PACKED_1x32(0xffffffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)},
 
{PIPE_FORMAT_R10G10B10A2_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_R10G10B10A2_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x000003ff), UNPACKED_1x1(1.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_R10G10B10A2_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x000ffc00), UNPACKED_1x1(0.0, 1.0, 0.0, 0.0)},
{PIPE_FORMAT_R10G10B10A2_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x3ff00000), UNPACKED_1x1(0.0, 0.0, 1.0, 0.0)},
{PIPE_FORMAT_R10G10B10A2_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xc0000000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R10G10B10A2_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xffffffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)},
 
{PIPE_FORMAT_B10G10R10A2_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_B10G10R10A2_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x000003ff), UNPACKED_1x1(0.0, 0.0, 1.0, 0.0)},
{PIPE_FORMAT_B10G10R10A2_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x000ffc00), UNPACKED_1x1(0.0, 1.0, 0.0, 0.0)},
{PIPE_FORMAT_B10G10R10A2_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x3ff00000), UNPACKED_1x1(1.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_B10G10R10A2_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xc0000000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_B10G10R10A2_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xffffffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)},
 
/*
* 16-bit rendertarget formats
*/
 
{PIPE_FORMAT_B5G5R5X1_UNORM, PACKED_1x16(0x7fff), PACKED_1x16(0x0000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_B5G5R5X1_UNORM, PACKED_1x16(0x7fff), PACKED_1x16(0x001f), UNPACKED_1x1(0.0, 0.0, 1.0, 1.0)},
{PIPE_FORMAT_B5G5R5X1_UNORM, PACKED_1x16(0x7fff), PACKED_1x16(0x03e0), UNPACKED_1x1(0.0, 1.0, 0.0, 1.0)},
{PIPE_FORMAT_B5G5R5X1_UNORM, PACKED_1x16(0x7fff), PACKED_1x16(0x7c00), UNPACKED_1x1(1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_B5G5R5X1_UNORM, PACKED_1x16(0x7fff), PACKED_1x16(0x7fff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)},
 
{PIPE_FORMAT_B5G5R5A1_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x0000), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_B5G5R5A1_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x001f), UNPACKED_1x1(0.0, 0.0, 1.0, 0.0)},
{PIPE_FORMAT_B5G5R5A1_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x03e0), UNPACKED_1x1(0.0, 1.0, 0.0, 0.0)},
{PIPE_FORMAT_B5G5R5A1_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x7c00), UNPACKED_1x1(1.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_B5G5R5A1_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x8000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_B5G5R5A1_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0xffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)},
 
{PIPE_FORMAT_B4G4R4X4_UNORM, PACKED_1x16(0x0fff), PACKED_1x16(0x0000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_B4G4R4X4_UNORM, PACKED_1x16(0x0fff), PACKED_1x16(0x000f), UNPACKED_1x1(0.0, 0.0, 1.0, 1.0)},
{PIPE_FORMAT_B4G4R4X4_UNORM, PACKED_1x16(0x0fff), PACKED_1x16(0x00f0), UNPACKED_1x1(0.0, 1.0, 0.0, 1.0)},
{PIPE_FORMAT_B4G4R4X4_UNORM, PACKED_1x16(0x0fff), PACKED_1x16(0x0f00), UNPACKED_1x1(1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_B4G4R4X4_UNORM, PACKED_1x16(0x0fff), PACKED_1x16(0x0fff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)},
 
{PIPE_FORMAT_B4G4R4A4_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x0000), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_B4G4R4A4_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x000f), UNPACKED_1x1(0.0, 0.0, 1.0, 0.0)},
{PIPE_FORMAT_B4G4R4A4_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x00f0), UNPACKED_1x1(0.0, 1.0, 0.0, 0.0)},
{PIPE_FORMAT_B4G4R4A4_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x0f00), UNPACKED_1x1(1.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_B4G4R4A4_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0xf000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_B4G4R4A4_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0xffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)},
 
{PIPE_FORMAT_B5G6R5_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x0000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_B5G6R5_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x001f), UNPACKED_1x1(0.0, 0.0, 1.0, 1.0)},
{PIPE_FORMAT_B5G6R5_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x07e0), UNPACKED_1x1(0.0, 1.0, 0.0, 1.0)},
{PIPE_FORMAT_B5G6R5_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0xf800), UNPACKED_1x1(1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_B5G6R5_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0xffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)},
 
/*
* Luminance/intensity/alpha formats
*/
 
{PIPE_FORMAT_L8_UNORM, PACKED_1x8(0xff), PACKED_1x8(0x00), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_L8_UNORM, PACKED_1x8(0xff), PACKED_1x8(0xff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)},
 
{PIPE_FORMAT_A8_UNORM, PACKED_1x8(0xff), PACKED_1x8(0x00), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_A8_UNORM, PACKED_1x8(0xff), PACKED_1x8(0xff), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)},
 
{PIPE_FORMAT_I8_UNORM, PACKED_1x8(0xff), PACKED_1x8(0x00), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_I8_UNORM, PACKED_1x8(0xff), PACKED_1x8(0xff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)},
 
{PIPE_FORMAT_L4A4_UNORM, PACKED_1x8(0xff), PACKED_1x8(0x00), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_L4A4_UNORM, PACKED_1x8(0xff), PACKED_1x8(0x0f), UNPACKED_1x1(1.0, 1.0, 1.0, 0.0)},
{PIPE_FORMAT_L4A4_UNORM, PACKED_1x8(0xff), PACKED_1x8(0xf0), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_L4A4_UNORM, PACKED_1x8(0xff), PACKED_1x8(0xff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)},
 
{PIPE_FORMAT_L8A8_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x0000), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_L8A8_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x00ff), UNPACKED_1x1(1.0, 1.0, 1.0, 0.0)},
{PIPE_FORMAT_L8A8_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0xff00), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_L8A8_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0xffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)},
 
{PIPE_FORMAT_L16_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x0000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_L16_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0xffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)},
 
/*
* SRGB formats
*/
 
{PIPE_FORMAT_L8_SRGB, PACKED_1x8(0xff), PACKED_1x8(0x00), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_L8_SRGB, PACKED_1x8(0xff), PACKED_1x8(0xbc), UNPACKED_1x1(0.502886458033, 0.502886458033, 0.502886458033, 1.0)},
{PIPE_FORMAT_L8_SRGB, PACKED_1x8(0xff), PACKED_1x8(0xff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)},
 
{PIPE_FORMAT_L8A8_SRGB, PACKED_1x16(0xffff), PACKED_1x16(0x0000), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_L8A8_SRGB, PACKED_1x16(0xffff), PACKED_1x16(0x00bc), UNPACKED_1x1(0.502886458033, 0.502886458033, 0.502886458033, 0.0)},
{PIPE_FORMAT_L8A8_SRGB, PACKED_1x16(0xffff), PACKED_1x16(0x00ff), UNPACKED_1x1(1.0, 1.0, 1.0, 0.0)},
{PIPE_FORMAT_L8A8_SRGB, PACKED_1x16(0xffff), PACKED_1x16(0xcc00), UNPACKED_1x1(0.0, 0.0, 0.0, 0.8)},
{PIPE_FORMAT_L8A8_SRGB, PACKED_1x16(0xffff), PACKED_1x16(0xff00), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_L8A8_SRGB, PACKED_1x16(0xffff), PACKED_1x16(0xffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)},
 
{PIPE_FORMAT_R8G8B8_SRGB, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x00, 0x00), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8B8_SRGB, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0xbc, 0x00, 0x00), UNPACKED_1x1(0.502886458033, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8B8_SRGB, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0xff, 0x00, 0x00), UNPACKED_1x1(1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8B8_SRGB, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0xbc, 0x00), UNPACKED_1x1(0.0, 0.502886458033, 0.0, 1.0)},
{PIPE_FORMAT_R8G8B8_SRGB, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0xff, 0x00), UNPACKED_1x1(0.0, 1.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8B8_SRGB, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x00, 0xbc), UNPACKED_1x1(0.0, 0.0, 0.502886458033, 1.0)},
{PIPE_FORMAT_R8G8B8_SRGB, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x00, 0xff), UNPACKED_1x1(0.0, 0.0, 1.0, 1.0)},
{PIPE_FORMAT_R8G8B8_SRGB, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0xff, 0xff, 0xff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)},
 
{PIPE_FORMAT_R8G8B8A8_SRGB, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0x00), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_R8G8B8A8_SRGB, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0xbc, 0x00, 0x00, 0x00), UNPACKED_1x1(0.502886458033, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_R8G8B8A8_SRGB, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0xff, 0x00, 0x00, 0x00), UNPACKED_1x1(1.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_R8G8B8A8_SRGB, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0xbc, 0x00, 0x00), UNPACKED_1x1(0.0, 0.502886458033, 0.0, 0.0)},
{PIPE_FORMAT_R8G8B8A8_SRGB, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0xff, 0x00, 0x00), UNPACKED_1x1(0.0, 1.0, 0.0, 0.0)},
{PIPE_FORMAT_R8G8B8A8_SRGB, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0xbc, 0x00), UNPACKED_1x1(0.0, 0.0, 0.502886458033, 0.0)},
{PIPE_FORMAT_R8G8B8A8_SRGB, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0xff, 0x00), UNPACKED_1x1(0.0, 0.0, 1.0, 0.0)},
{PIPE_FORMAT_R8G8B8A8_SRGB, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0xcc), UNPACKED_1x1(0.0, 0.0, 0.0, 0.8)},
{PIPE_FORMAT_R8G8B8A8_SRGB, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0xff), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8B8A8_SRGB, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0xff, 0xff, 0xff, 0xff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)},
 
{PIPE_FORMAT_B8G8R8A8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_B8G8R8A8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0x000000bc), UNPACKED_1x1(0.0, 0.0, 0.502886458033, 0.0)},
{PIPE_FORMAT_B8G8R8A8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0x000000ff), UNPACKED_1x1(0.0, 0.0, 1.0, 0.0)},
{PIPE_FORMAT_B8G8R8A8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0x0000bc00), UNPACKED_1x1(0.0, 0.502886458033, 0.0, 0.0)},
{PIPE_FORMAT_B8G8R8A8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0x0000ff00), UNPACKED_1x1(0.0, 1.0, 0.0, 0.0)},
{PIPE_FORMAT_B8G8R8A8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0x00bc0000), UNPACKED_1x1(0.502886458033, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_B8G8R8A8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0x00ff0000), UNPACKED_1x1(1.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_B8G8R8A8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0xcc000000), UNPACKED_1x1(0.0, 0.0, 0.0, 0.8)},
{PIPE_FORMAT_B8G8R8A8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0xff000000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_B8G8R8A8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0xffffffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)},
 
{PIPE_FORMAT_B8G8R8X8_SRGB, PACKED_1x32(0x00ffffff), PACKED_1x32(0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_B8G8R8X8_SRGB, PACKED_1x32(0x00ffffff), PACKED_1x32(0x000000bc), UNPACKED_1x1(0.0, 0.0, 0.502886458033, 1.0)},
{PIPE_FORMAT_B8G8R8X8_SRGB, PACKED_1x32(0x00ffffff), PACKED_1x32(0x000000ff), UNPACKED_1x1(0.0, 0.0, 1.0, 1.0)},
{PIPE_FORMAT_B8G8R8X8_SRGB, PACKED_1x32(0x00ffffff), PACKED_1x32(0x0000bc00), UNPACKED_1x1(0.0, 0.502886458033, 0.0, 1.0)},
{PIPE_FORMAT_B8G8R8X8_SRGB, PACKED_1x32(0x00ffffff), PACKED_1x32(0x0000ff00), UNPACKED_1x1(0.0, 1.0, 0.0, 1.0)},
{PIPE_FORMAT_B8G8R8X8_SRGB, PACKED_1x32(0x00ffffff), PACKED_1x32(0x00bc0000), UNPACKED_1x1(0.502886458033, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_B8G8R8X8_SRGB, PACKED_1x32(0x00ffffff), PACKED_1x32(0x00ff0000), UNPACKED_1x1(1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_B8G8R8X8_SRGB, PACKED_1x32(0x00ffffff), PACKED_1x32(0xffffffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)},
 
{PIPE_FORMAT_A8R8G8B8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_A8R8G8B8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0x000000cc), UNPACKED_1x1(0.0, 0.0, 0.0, 0.8)},
{PIPE_FORMAT_A8R8G8B8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0x000000ff), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_A8R8G8B8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0x0000bc00), UNPACKED_1x1(0.502886458033, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_A8R8G8B8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0x0000ff00), UNPACKED_1x1(1.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_A8R8G8B8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0x00bc0000), UNPACKED_1x1(0.0, 0.502886458033, 0.0, 0.0)},
{PIPE_FORMAT_A8R8G8B8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0x00ff0000), UNPACKED_1x1(0.0, 1.0, 0.0, 0.0)},
{PIPE_FORMAT_A8R8G8B8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0xbc000000), UNPACKED_1x1(0.0, 0.0, 0.502886458033, 0.0)},
{PIPE_FORMAT_A8R8G8B8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0xff000000), UNPACKED_1x1(0.0, 0.0, 1.0, 0.0)},
{PIPE_FORMAT_A8R8G8B8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0xffffffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)},
 
{PIPE_FORMAT_X8R8G8B8_SRGB, PACKED_1x32(0xffffff00), PACKED_1x32(0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_X8R8G8B8_SRGB, PACKED_1x32(0xffffff00), PACKED_1x32(0x0000bc00), UNPACKED_1x1(0.502886458033, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_X8R8G8B8_SRGB, PACKED_1x32(0xffffff00), PACKED_1x32(0x0000ff00), UNPACKED_1x1(1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_X8R8G8B8_SRGB, PACKED_1x32(0xffffff00), PACKED_1x32(0x00bc0000), UNPACKED_1x1(0.0, 0.502886458033, 0.0, 1.0)},
{PIPE_FORMAT_X8R8G8B8_SRGB, PACKED_1x32(0xffffff00), PACKED_1x32(0x00ff0000), UNPACKED_1x1(0.0, 1.0, 0.0, 1.0)},
{PIPE_FORMAT_X8R8G8B8_SRGB, PACKED_1x32(0xffffff00), PACKED_1x32(0xbc000000), UNPACKED_1x1(0.0, 0.0, 0.502886458033, 1.0)},
{PIPE_FORMAT_X8R8G8B8_SRGB, PACKED_1x32(0xffffff00), PACKED_1x32(0xff000000), UNPACKED_1x1(0.0, 0.0, 1.0, 1.0)},
{PIPE_FORMAT_X8R8G8B8_SRGB, PACKED_1x32(0xffffff00), PACKED_1x32(0xffffffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)},
 
{PIPE_FORMAT_A8B8G8R8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_A8B8G8R8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0x000000cc), UNPACKED_1x1(0.0, 0.0, 0.0, 0.8)},
{PIPE_FORMAT_A8B8G8R8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0x000000ff), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_A8B8G8R8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0x0000bc00), UNPACKED_1x1(0.0, 0.0, 0.502886458033, 0.0)},
{PIPE_FORMAT_A8B8G8R8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0x0000ff00), UNPACKED_1x1(0.0, 0.0, 1.0, 0.0)},
{PIPE_FORMAT_A8B8G8R8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0x00bc0000), UNPACKED_1x1(0.0, 0.502886458033, 0.0, 0.0)},
{PIPE_FORMAT_A8B8G8R8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0x00ff0000), UNPACKED_1x1(0.0, 1.0, 0.0, 0.0)},
{PIPE_FORMAT_A8B8G8R8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0xbc000000), UNPACKED_1x1(0.502886458033, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_A8B8G8R8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0xff000000), UNPACKED_1x1(1.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_A8B8G8R8_SRGB, PACKED_1x32(0xffffffff), PACKED_1x32(0xffffffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)},
 
{PIPE_FORMAT_X8B8G8R8_SRGB, PACKED_1x32(0xffffff00), PACKED_1x32(0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_X8B8G8R8_SRGB, PACKED_1x32(0xffffff00), PACKED_1x32(0x0000bc00), UNPACKED_1x1(0.0, 0.0, 0.502886458033, 1.0)},
{PIPE_FORMAT_X8B8G8R8_SRGB, PACKED_1x32(0xffffff00), PACKED_1x32(0x0000ff00), UNPACKED_1x1(0.0, 0.0, 1.0, 1.0)},
{PIPE_FORMAT_X8B8G8R8_SRGB, PACKED_1x32(0xffffff00), PACKED_1x32(0x00bc0000), UNPACKED_1x1(0.0, 0.502886458033, 0.0, 1.0)},
{PIPE_FORMAT_X8B8G8R8_SRGB, PACKED_1x32(0xffffff00), PACKED_1x32(0x00ff0000), UNPACKED_1x1(0.0, 1.0, 0.0, 1.0)},
{PIPE_FORMAT_X8B8G8R8_SRGB, PACKED_1x32(0xffffff00), PACKED_1x32(0xbc000000), UNPACKED_1x1(0.502886458033, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_X8B8G8R8_SRGB, PACKED_1x32(0xffffff00), PACKED_1x32(0xff000000), UNPACKED_1x1(1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_X8B8G8R8_SRGB, PACKED_1x32(0xffffff00), PACKED_1x32(0xffffffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)},
 
/*
* Mixed-signed formats
*/
 
{PIPE_FORMAT_R8SG8SB8UX8U_NORM, PACKED_4x8(0xff, 0xff, 0xff, 0x00), PACKED_4x8(0x00, 0x00, 0x00, 0x00), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R8SG8SB8UX8U_NORM, PACKED_4x8(0xff, 0xff, 0xff, 0x00), PACKED_4x8(0x7f, 0x00, 0x00, 0x00), UNPACKED_1x1( 1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R8SG8SB8UX8U_NORM, PACKED_4x8(0xff, 0xff, 0xff, 0x00), PACKED_4x8(0x81, 0x00, 0x00, 0x00), UNPACKED_1x1(-1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R8SG8SB8UX8U_NORM, PACKED_4x8(0xff, 0xff, 0xff, 0x00), PACKED_4x8(0x00, 0x7f, 0x00, 0x00), UNPACKED_1x1( 0.0, 1.0, 0.0, 1.0)},
{PIPE_FORMAT_R8SG8SB8UX8U_NORM, PACKED_4x8(0xff, 0xff, 0xff, 0x00), PACKED_4x8(0x00, 0x81, 0x00, 0x00), UNPACKED_1x1( 0.0, -1.0, 0.0, 1.0)},
{PIPE_FORMAT_R8SG8SB8UX8U_NORM, PACKED_4x8(0xff, 0xff, 0xff, 0x00), PACKED_4x8(0x00, 0x00, 0xff, 0x00), UNPACKED_1x1( 0.0, 0.0, 1.0, 1.0)},
 
{PIPE_FORMAT_R10SG10SB10SA2U_NORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_R10SG10SB10SA2U_NORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x000001ff), UNPACKED_1x1( 1.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_R10SG10SB10SA2U_NORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000201), UNPACKED_1x1(-1.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_R10SG10SB10SA2U_NORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x0007fc00), UNPACKED_1x1( 0.0, 1.0, 0.0, 0.0)},
{PIPE_FORMAT_R10SG10SB10SA2U_NORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00080400), UNPACKED_1x1( 0.0, -1.0, 0.0, 0.0)},
{PIPE_FORMAT_R10SG10SB10SA2U_NORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x1ff00000), UNPACKED_1x1( 0.0, 0.0, 1.0, 0.0)},
{PIPE_FORMAT_R10SG10SB10SA2U_NORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x20100000), UNPACKED_1x1( 0.0, 0.0, -1.0, 0.0)},
{PIPE_FORMAT_R10SG10SB10SA2U_NORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xc0000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)},
 
{PIPE_FORMAT_R5SG5SB6U_NORM, PACKED_1x16(0xffff), PACKED_1x16(0x0000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R5SG5SB6U_NORM, PACKED_1x16(0xffff), PACKED_1x16(0x000f), UNPACKED_1x1( 1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R5SG5SB6U_NORM, PACKED_1x16(0xffff), PACKED_1x16(0x0011), UNPACKED_1x1(-1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R5SG5SB6U_NORM, PACKED_1x16(0xffff), PACKED_1x16(0x01e0), UNPACKED_1x1( 0.0, 1.0, 0.0, 1.0)},
{PIPE_FORMAT_R5SG5SB6U_NORM, PACKED_1x16(0xffff), PACKED_1x16(0x0220), UNPACKED_1x1( 0.0, -1.0, 0.0, 1.0)},
{PIPE_FORMAT_R5SG5SB6U_NORM, PACKED_1x16(0xffff), PACKED_1x16(0xfc00), UNPACKED_1x1( 0.0, 0.0, 1.0, 1.0)},
 
{PIPE_FORMAT_R8G8Bx_SNORM, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x00, 0x00), UNPACKED_1x1( 0.0, 0.0, 1.0, 1.0)},
{PIPE_FORMAT_R8G8Bx_SNORM, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x7f, 0x00), UNPACKED_1x1( 1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8Bx_SNORM, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x81, 0x00), UNPACKED_1x1(-1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8Bx_SNORM, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x00, 0x7f), UNPACKED_1x1( 0.0, 1.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8Bx_SNORM, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x00, 0x81), UNPACKED_1x1( 0.0, -1.0, 0.0, 1.0)},
 
/*
* Depth-stencil formats
*/
 
{PIPE_FORMAT_S8_UINT, PACKED_1x8(0xff), PACKED_1x8(0x00), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_S8_UINT, PACKED_1x8(0xff), PACKED_1x8(0xff), UNPACKED_1x1(0.0, 255.0, 0.0, 0.0)},
 
{PIPE_FORMAT_Z16_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x0000), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_Z16_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0xffff), UNPACKED_1x1(1.0, 0.0, 0.0, 0.0)},
 
{PIPE_FORMAT_Z32_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_Z32_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xffffffff), UNPACKED_1x1(1.0, 0.0, 0.0, 0.0)},
 
{PIPE_FORMAT_Z32_FLOAT, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_Z32_FLOAT, PACKED_1x32(0xffffffff), PACKED_1x32(0x3f800000), UNPACKED_1x1(1.0, 0.0, 0.0, 0.0)},
 
{PIPE_FORMAT_Z24_UNORM_S8_UINT, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_Z24_UNORM_S8_UINT, PACKED_1x32(0xffffffff), PACKED_1x32(0x00ffffff), UNPACKED_1x1(1.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_Z24_UNORM_S8_UINT, PACKED_1x32(0xffffffff), PACKED_1x32(0xff000000), UNPACKED_1x1(0.0, 255.0, 0.0, 0.0)},
{PIPE_FORMAT_Z24_UNORM_S8_UINT, PACKED_1x32(0xffffffff), PACKED_1x32(0xffffffff), UNPACKED_1x1(1.0, 255.0, 0.0, 0.0)},
 
{PIPE_FORMAT_S8_UINT_Z24_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_S8_UINT_Z24_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xffffff00), UNPACKED_1x1(1.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_S8_UINT_Z24_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x000000ff), UNPACKED_1x1(0.0, 255.0, 0.0, 0.0)},
{PIPE_FORMAT_S8_UINT_Z24_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xffffffff), UNPACKED_1x1(1.0, 255.0, 0.0, 0.0)},
 
{PIPE_FORMAT_Z24X8_UNORM, PACKED_1x32(0x00ffffff), PACKED_1x32(0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_Z24X8_UNORM, PACKED_1x32(0x00ffffff), PACKED_1x32(0x00ffffff), UNPACKED_1x1(1.0, 0.0, 0.0, 0.0)},
 
{PIPE_FORMAT_X8Z24_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_X8Z24_UNORM, PACKED_1x32(0xffffff00), PACKED_1x32(0xffffff00), UNPACKED_1x1(1.0, 0.0, 0.0, 0.0)},
 
{PIPE_FORMAT_Z32_FLOAT_S8X24_UINT, PACKED_2x32(0xffffffff, 0x000000ff), PACKED_2x32(0x00000000, 0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_Z32_FLOAT_S8X24_UINT, PACKED_2x32(0xffffffff, 0x000000ff), PACKED_2x32(0x3f800000, 0x00000000), UNPACKED_1x1( 1.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_Z32_FLOAT_S8X24_UINT, PACKED_2x32(0xffffffff, 0x000000ff), PACKED_2x32(0x00000000, 0x000000ff), UNPACKED_1x1( 0.0, 255.0, 0.0, 0.0)},
 
/*
* YUV formats
*/
 
{PIPE_FORMAT_R8G8_B8G8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0x00), UNPACKED_2x1(0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8_B8G8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0xff, 0x00, 0x00, 0x00), UNPACKED_2x1(1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8_B8G8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0xff, 0x00, 0x00), UNPACKED_2x1(0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8_B8G8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0xff, 0x00), UNPACKED_2x1(0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0)},
{PIPE_FORMAT_R8G8_B8G8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0xff), UNPACKED_2x1(0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8_B8G8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0xff, 0xff, 0xff, 0xff), UNPACKED_2x1(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0)},
 
{PIPE_FORMAT_G8R8_G8B8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0x00), UNPACKED_2x1(0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_G8R8_G8B8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0xff, 0x00, 0x00, 0x00), UNPACKED_2x1(0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_G8R8_G8B8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0xff, 0x00, 0x00), UNPACKED_2x1(1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_G8R8_G8B8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0xff, 0x00), UNPACKED_2x1(0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0)},
{PIPE_FORMAT_G8R8_G8B8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0xff), UNPACKED_2x1(0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0)},
{PIPE_FORMAT_G8R8_G8B8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0xff, 0xff, 0xff, 0xff), UNPACKED_2x1(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0)},
 
/*
* TODO: Exercise the UV channels as well.
*/
{PIPE_FORMAT_UYVY, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x80, 0x10, 0x80, 0x10), UNPACKED_2x1(0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_UYVY, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x80, 0xeb, 0x80, 0x10), UNPACKED_2x1(1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_UYVY, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x80, 0x10, 0x80, 0xeb), UNPACKED_2x1(0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0)},
 
{PIPE_FORMAT_YUYV, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x10, 0x80, 0x10, 0x80), UNPACKED_2x1(0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_YUYV, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0xeb, 0x80, 0x10, 0x80), UNPACKED_2x1(1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_YUYV, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x10, 0x80, 0xeb, 0x80), UNPACKED_2x1(0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0)},
 
/*
* Compressed formats
*/
 
{
PIPE_FORMAT_DXT1_RGB,
PACKED_8x8(0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff),
PACKED_8x8(0xf2, 0xd7, 0xb0, 0x20, 0xae, 0x2c, 0x6f, 0x97),
{
{
{0x99/255.0, 0xb0/255.0, 0x8e/255.0, 0xff/255.0},
{0x5d/255.0, 0x62/255.0, 0x89/255.0, 0xff/255.0},
{0x99/255.0, 0xb0/255.0, 0x8e/255.0, 0xff/255.0},
{0x99/255.0, 0xb0/255.0, 0x8e/255.0, 0xff/255.0}
},
{
{0xd6/255.0, 0xff/255.0, 0x94/255.0, 0xff/255.0},
{0x5d/255.0, 0x62/255.0, 0x89/255.0, 0xff/255.0},
{0x99/255.0, 0xb0/255.0, 0x8e/255.0, 0xff/255.0},
{0xd6/255.0, 0xff/255.0, 0x94/255.0, 0xff/255.0}
},
{
{0x5d/255.0, 0x62/255.0, 0x89/255.0, 0xff/255.0},
{0x5d/255.0, 0x62/255.0, 0x89/255.0, 0xff/255.0},
{0x99/255.0, 0xb0/255.0, 0x8e/255.0, 0xff/255.0},
{0x21/255.0, 0x14/255.0, 0x84/255.0, 0xff/255.0}
},
{
{0x5d/255.0, 0x62/255.0, 0x89/255.0, 0xff/255.0},
{0x21/255.0, 0x14/255.0, 0x84/255.0, 0xff/255.0},
{0x21/255.0, 0x14/255.0, 0x84/255.0, 0xff/255.0},
{0x99/255.0, 0xb0/255.0, 0x8e/255.0, 0xff/255.0}
}
}
},
{
PIPE_FORMAT_DXT1_RGBA,
PACKED_8x8(0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff),
PACKED_8x8(0xff, 0x2f, 0xa4, 0x72, 0xeb, 0xb2, 0xbd, 0xbe),
{
{
{0x00/255.0, 0x00/255.0, 0x00/255.0, 0x00/255.0},
{0x4e/255.0, 0xaa/255.0, 0x90/255.0, 0xff/255.0},
{0x4e/255.0, 0xaa/255.0, 0x90/255.0, 0xff/255.0},
{0x00/255.0, 0x00/255.0, 0x00/255.0, 0x00/255.0}
},
{
{0x4e/255.0, 0xaa/255.0, 0x90/255.0, 0xff/255.0},
{0x29/255.0, 0xff/255.0, 0xff/255.0, 0xff/255.0},
{0x00/255.0, 0x00/255.0, 0x00/255.0, 0x00/255.0},
{0x4e/255.0, 0xaa/255.0, 0x90/255.0, 0xff/255.0}
},
{
{0x73/255.0, 0x55/255.0, 0x21/255.0, 0xff/255.0},
{0x00/255.0, 0x00/255.0, 0x00/255.0, 0x00/255.0},
{0x00/255.0, 0x00/255.0, 0x00/255.0, 0x00/255.0},
{0x4e/255.0, 0xaa/255.0, 0x90/255.0, 0xff/255.0}
},
{
{0x4e/255.0, 0xaa/255.0, 0x90/255.0, 0xff/255.0},
{0x00/255.0, 0x00/255.0, 0x00/255.0, 0x00/255.0},
{0x00/255.0, 0x00/255.0, 0x00/255.0, 0x00/255.0},
{0x4e/255.0, 0xaa/255.0, 0x90/255.0, 0xff/255.0}
}
}
},
{
PIPE_FORMAT_DXT3_RGBA,
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
{0xe7, 0x4a, 0x8f, 0x96, 0x5b, 0xc1, 0x1c, 0x84, 0xf6, 0x8f, 0xab, 0x32, 0x2a, 0x9a, 0x95, 0x5a},
{
{
{0x6d/255.0, 0xc6/255.0, 0x96/255.0, 0x77/255.0},
{0x6d/255.0, 0xc6/255.0, 0x96/255.0, 0xee/255.0},
{0x6d/255.0, 0xc6/255.0, 0x96/255.0, 0xaa/255.0},
{0x8c/255.0, 0xff/255.0, 0xb5/255.0, 0x44/255.0}
},
{
{0x6d/255.0, 0xc6/255.0, 0x96/255.0, 0xff/255.0},
{0x6d/255.0, 0xc6/255.0, 0x96/255.0, 0x88/255.0},
{0x31/255.0, 0x55/255.0, 0x5a/255.0, 0x66/255.0},
{0x6d/255.0, 0xc6/255.0, 0x96/255.0, 0x99/255.0}
},
{
{0x31/255.0, 0x55/255.0, 0x5a/255.0, 0xbb/255.0},
{0x31/255.0, 0x55/255.0, 0x5a/255.0, 0x55/255.0},
{0x31/255.0, 0x55/255.0, 0x5a/255.0, 0x11/255.0},
{0x6d/255.0, 0xc6/255.0, 0x96/255.0, 0xcc/255.0}
},
{
{0x6d/255.0, 0xc6/255.0, 0x96/255.0, 0xcc/255.0},
{0x6d/255.0, 0xc6/255.0, 0x96/255.0, 0x11/255.0},
{0x31/255.0, 0x55/255.0, 0x5a/255.0, 0x44/255.0},
{0x31/255.0, 0x55/255.0, 0x5a/255.0, 0x88/255.0}
}
}
},
{
PIPE_FORMAT_DXT5_RGBA,
{0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
{0xf8, 0x11, 0xc5, 0x0c, 0x9a, 0x73, 0xb4, 0x9c, 0xf6, 0x8f, 0xab, 0x32, 0x2a, 0x9a, 0x95, 0x5a},
{
{
{0x6d/255.0, 0xc6/255.0, 0x96/255.0, 0x74/255.0},
{0x6d/255.0, 0xc6/255.0, 0x96/255.0, 0xf8/255.0},
{0x6d/255.0, 0xc6/255.0, 0x96/255.0, 0xb6/255.0},
{0x8c/255.0, 0xff/255.0, 0xb5/255.0, 0x53/255.0}
},
{
{0x6d/255.0, 0xc6/255.0, 0x96/255.0, 0xf8/255.0},
{0x6d/255.0, 0xc6/255.0, 0x96/255.0, 0x95/255.0},
{0x31/255.0, 0x55/255.0, 0x5a/255.0, 0x53/255.0},
{0x6d/255.0, 0xc6/255.0, 0x96/255.0, 0x95/255.0}
},
{
{0x31/255.0, 0x55/255.0, 0x5a/255.0, 0xb6/255.0},
{0x31/255.0, 0x55/255.0, 0x5a/255.0, 0x53/255.0},
{0x31/255.0, 0x55/255.0, 0x5a/255.0, 0x11/255.0},
{0x6d/255.0, 0xc6/255.0, 0x96/255.0, 0xd7/255.0}
},
{
{0x6d/255.0, 0xc6/255.0, 0x96/255.0, 0xb6/255.0},
{0x6d/255.0, 0xc6/255.0, 0x96/255.0, 0x11/255.0},
{0x31/255.0, 0x55/255.0, 0x5a/255.0, 0x32/255.0},
{0x31/255.0, 0x55/255.0, 0x5a/255.0, 0x95/255.0}
}
}
},
 
 
/*
* Standard 8-bit integer formats
*/
 
{PIPE_FORMAT_R8_UNORM, PACKED_1x8(0xff), PACKED_1x8(0x00), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R8_UNORM, PACKED_1x8(0xff), PACKED_1x8(0xff), UNPACKED_1x1(1.0, 0.0, 0.0, 1.0)},
 
{PIPE_FORMAT_R8G8_UNORM, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x00, 0x00), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8_UNORM, PACKED_2x8(0xff, 0xff), PACKED_2x8(0xff, 0x00), UNPACKED_1x1(1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8_UNORM, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x00, 0xff), UNPACKED_1x1(0.0, 1.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8_UNORM, PACKED_2x8(0xff, 0xff), PACKED_2x8(0xff, 0xff), UNPACKED_1x1(1.0, 1.0, 0.0, 1.0)},
 
{PIPE_FORMAT_R8G8B8_UNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x00, 0x00), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8B8_UNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0xff, 0x00, 0x00), UNPACKED_1x1(1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8B8_UNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0xff, 0x00), UNPACKED_1x1(0.0, 1.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8B8_UNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x00, 0xff), UNPACKED_1x1(0.0, 0.0, 1.0, 1.0)},
{PIPE_FORMAT_R8G8B8_UNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0xff, 0xff, 0xff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)},
 
{PIPE_FORMAT_R8G8B8A8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0x00), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_R8G8B8A8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0xff, 0x00, 0x00, 0x00), UNPACKED_1x1(1.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_R8G8B8A8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0xff, 0x00, 0x00), UNPACKED_1x1(0.0, 1.0, 0.0, 0.0)},
{PIPE_FORMAT_R8G8B8A8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0xff, 0x00), UNPACKED_1x1(0.0, 0.0, 1.0, 0.0)},
{PIPE_FORMAT_R8G8B8A8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0xff), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8B8A8_UNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0xff, 0xff, 0xff, 0xff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)},
 
{PIPE_FORMAT_R8_USCALED, PACKED_1x8(0xff), PACKED_1x8(0x00), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R8_USCALED, PACKED_1x8(0xff), PACKED_1x8(0xff), UNPACKED_1x1(255.0, 0.0, 0.0, 1.0)},
 
{PIPE_FORMAT_R8G8_USCALED, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x00, 0x00), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8_USCALED, PACKED_2x8(0xff, 0xff), PACKED_2x8(0xff, 0x00), UNPACKED_1x1(255.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8_USCALED, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x00, 0xff), UNPACKED_1x1( 0.0, 255.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8_USCALED, PACKED_2x8(0xff, 0xff), PACKED_2x8(0xff, 0xff), UNPACKED_1x1(255.0, 255.0, 0.0, 1.0)},
 
{PIPE_FORMAT_R8G8B8_USCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x00, 0x00), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8B8_USCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0xff, 0x00, 0x00), UNPACKED_1x1(255.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8B8_USCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0xff, 0x00), UNPACKED_1x1( 0.0, 255.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8B8_USCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x00, 0xff), UNPACKED_1x1( 0.0, 0.0, 255.0, 1.0)},
{PIPE_FORMAT_R8G8B8_USCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0xff, 0xff, 0xff), UNPACKED_1x1(255.0, 255.0, 255.0, 1.0)},
 
{PIPE_FORMAT_R8G8B8A8_USCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0x00), UNPACKED_1x1( 0.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_R8G8B8A8_USCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0xff, 0x00, 0x00, 0x00), UNPACKED_1x1(255.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_R8G8B8A8_USCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0xff, 0x00, 0x00), UNPACKED_1x1( 0.0, 255.0, 0.0, 0.0)},
{PIPE_FORMAT_R8G8B8A8_USCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0xff, 0x00), UNPACKED_1x1( 0.0, 0.0, 255.0, 0.0)},
{PIPE_FORMAT_R8G8B8A8_USCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0xff), UNPACKED_1x1( 0.0, 0.0, 0.0, 255.0)},
{PIPE_FORMAT_R8G8B8A8_USCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0xff, 0xff, 0xff, 0xff), UNPACKED_1x1(255.0, 255.0, 255.0, 255.0)},
 
{PIPE_FORMAT_R8_SNORM, PACKED_1x8(0xff), PACKED_1x8(0x00), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R8_SNORM, PACKED_1x8(0xff), PACKED_1x8(0x7f), UNPACKED_1x1( 1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R8_SNORM, PACKED_1x8(0xff), PACKED_1x8(0x81), UNPACKED_1x1(-1.0, 0.0, 0.0, 1.0)},
 
{PIPE_FORMAT_R8G8_SNORM, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x00, 0x00), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8_SNORM, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x7f, 0x00), UNPACKED_1x1( 1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8_SNORM, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x81, 0x00), UNPACKED_1x1(-1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8_SNORM, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x00, 0x7f), UNPACKED_1x1( 0.0, 1.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8_SNORM, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x00, 0x81), UNPACKED_1x1( 0.0, -1.0, 0.0, 1.0)},
 
{PIPE_FORMAT_R8G8B8_SNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x00, 0x00), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8B8_SNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x7f, 0x00, 0x00), UNPACKED_1x1( 1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8B8_SNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x81, 0x00, 0x00), UNPACKED_1x1(-1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8B8_SNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x7f, 0x00), UNPACKED_1x1( 0.0, 1.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8B8_SNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x81, 0x00), UNPACKED_1x1( 0.0, -1.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8B8_SNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x00, 0x7f), UNPACKED_1x1( 0.0, 0.0, 1.0, 1.0)},
{PIPE_FORMAT_R8G8B8_SNORM, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x00, 0x81), UNPACKED_1x1( 0.0, 0.0, -1.0, 1.0)},
 
{PIPE_FORMAT_R8G8B8A8_SNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0x00), UNPACKED_1x1( 0.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_R8G8B8A8_SNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x7f, 0x00, 0x00, 0x00), UNPACKED_1x1( 1.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_R8G8B8A8_SNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x81, 0x00, 0x00, 0x00), UNPACKED_1x1(-1.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_R8G8B8A8_SNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x7f, 0x00, 0x00), UNPACKED_1x1( 0.0, 1.0, 0.0, 0.0)},
{PIPE_FORMAT_R8G8B8A8_SNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x81, 0x00, 0x00), UNPACKED_1x1( 0.0, -1.0, 0.0, 0.0)},
{PIPE_FORMAT_R8G8B8A8_SNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x7f, 0x00), UNPACKED_1x1( 0.0, 0.0, 1.0, 0.0)},
{PIPE_FORMAT_R8G8B8A8_SNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x81, 0x00), UNPACKED_1x1( 0.0, 0.0, -1.0, 0.0)},
{PIPE_FORMAT_R8G8B8A8_SNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0x7f), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8B8A8_SNORM, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0x81), UNPACKED_1x1( 0.0, 0.0, 0.0, -1.0)},
 
{PIPE_FORMAT_R8_SSCALED, PACKED_1x8(0xff), PACKED_1x8(0x00), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R8_SSCALED, PACKED_1x8(0xff), PACKED_1x8(0x7f), UNPACKED_1x1( 127.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R8_SSCALED, PACKED_1x8(0xff), PACKED_1x8(0x80), UNPACKED_1x1(-128.0, 0.0, 0.0, 1.0)},
 
{PIPE_FORMAT_R8G8_SSCALED, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x00, 0x00), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8_SSCALED, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x7f, 0x00), UNPACKED_1x1( 127.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8_SSCALED, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x80, 0x00), UNPACKED_1x1(-128.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8_SSCALED, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x00, 0x7f), UNPACKED_1x1( 0.0, 127.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8_SSCALED, PACKED_2x8(0xff, 0xff), PACKED_2x8(0x00, 0x80), UNPACKED_1x1( 0.0, -128.0, 0.0, 1.0)},
 
{PIPE_FORMAT_R8G8B8_SSCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x00, 0x00), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8B8_SSCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x7f, 0x00, 0x00), UNPACKED_1x1( 127.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8B8_SSCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x80, 0x00, 0x00), UNPACKED_1x1(-128.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8B8_SSCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x7f, 0x00), UNPACKED_1x1( 0.0, 127.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8B8_SSCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x80, 0x00), UNPACKED_1x1( 0.0, -128.0, 0.0, 1.0)},
{PIPE_FORMAT_R8G8B8_SSCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x00, 0x7f), UNPACKED_1x1( 0.0, 0.0, 127.0, 1.0)},
{PIPE_FORMAT_R8G8B8_SSCALED, PACKED_3x8(0xff, 0xff, 0xff), PACKED_3x8(0x00, 0x00, 0x80), UNPACKED_1x1( 0.0, 0.0, -128.0, 1.0)},
 
{PIPE_FORMAT_R8G8B8A8_SSCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0x00), UNPACKED_1x1( 0.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_R8G8B8A8_SSCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x7f, 0x00, 0x00, 0x00), UNPACKED_1x1( 127.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_R8G8B8A8_SSCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x80, 0x00, 0x00, 0x00), UNPACKED_1x1(-128.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_R8G8B8A8_SSCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x7f, 0x00, 0x00), UNPACKED_1x1( 0.0, 127.0, 0.0, 0.0)},
{PIPE_FORMAT_R8G8B8A8_SSCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x80, 0x00, 0x00), UNPACKED_1x1( 0.0, -128.0, 0.0, 0.0)},
{PIPE_FORMAT_R8G8B8A8_SSCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x7f, 0x00), UNPACKED_1x1( 0.0, 0.0, 127.0, 0.0)},
{PIPE_FORMAT_R8G8B8A8_SSCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x80, 0x00), UNPACKED_1x1( 0.0, 0.0, -128.0, 0.0)},
{PIPE_FORMAT_R8G8B8A8_SSCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0x7f), UNPACKED_1x1( 0.0, 0.0, 0.0, 127.0)},
{PIPE_FORMAT_R8G8B8A8_SSCALED, PACKED_4x8(0xff, 0xff, 0xff, 0xff), PACKED_4x8(0x00, 0x00, 0x00, 0x80), UNPACKED_1x1( 0.0, 0.0, 0.0, -128.0)},
 
/*
* Standard 16-bit integer formats
*/
 
{PIPE_FORMAT_R16_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0x0000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R16_UNORM, PACKED_1x16(0xffff), PACKED_1x16(0xffff), UNPACKED_1x1(1.0, 0.0, 0.0, 1.0)},
 
{PIPE_FORMAT_R16G16_UNORM, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x0000, 0x0000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R16G16_UNORM, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0xffff, 0x0000), UNPACKED_1x1(1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R16G16_UNORM, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x0000, 0xffff), UNPACKED_1x1(0.0, 1.0, 0.0, 1.0)},
{PIPE_FORMAT_R16G16_UNORM, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0xffff, 0xffff), UNPACKED_1x1(1.0, 1.0, 0.0, 1.0)},
 
{PIPE_FORMAT_R16G16B16_UNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x0000, 0x0000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R16G16B16_UNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0xffff, 0x0000, 0x0000), UNPACKED_1x1(1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R16G16B16_UNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0xffff, 0x0000), UNPACKED_1x1(0.0, 1.0, 0.0, 1.0)},
{PIPE_FORMAT_R16G16B16_UNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x0000, 0xffff), UNPACKED_1x1(0.0, 0.0, 1.0, 1.0)},
{PIPE_FORMAT_R16G16B16_UNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0xffff, 0xffff, 0xffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)},
 
{PIPE_FORMAT_R16G16B16A16_UNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x0000, 0x0000), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_R16G16B16A16_UNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0xffff, 0x0000, 0x0000, 0x0000), UNPACKED_1x1(1.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_R16G16B16A16_UNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0xffff, 0x0000, 0x0000), UNPACKED_1x1(0.0, 1.0, 0.0, 0.0)},
{PIPE_FORMAT_R16G16B16A16_UNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0xffff, 0x0000), UNPACKED_1x1(0.0, 0.0, 1.0, 0.0)},
{PIPE_FORMAT_R16G16B16A16_UNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x0000, 0xffff), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R16G16B16A16_UNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)},
 
{PIPE_FORMAT_R16_USCALED, PACKED_1x16(0xffff), PACKED_1x16(0x0000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R16_USCALED, PACKED_1x16(0xffff), PACKED_1x16(0xffff), UNPACKED_1x1(65535.0, 0.0, 0.0, 1.0)},
 
{PIPE_FORMAT_R16G16_USCALED, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x0000, 0x0000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R16G16_USCALED, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0xffff, 0x0000), UNPACKED_1x1(65535.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R16G16_USCALED, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x0000, 0xffff), UNPACKED_1x1( 0.0, 65535.0, 0.0, 1.0)},
{PIPE_FORMAT_R16G16_USCALED, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0xffff, 0xffff), UNPACKED_1x1(65535.0, 65535.0, 0.0, 1.0)},
 
{PIPE_FORMAT_R16G16B16_USCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x0000, 0x0000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R16G16B16_USCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0xffff, 0x0000, 0x0000), UNPACKED_1x1(65535.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R16G16B16_USCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0xffff, 0x0000), UNPACKED_1x1( 0.0, 65535.0, 0.0, 1.0)},
{PIPE_FORMAT_R16G16B16_USCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x0000, 0xffff), UNPACKED_1x1( 0.0, 0.0, 65535.0, 1.0)},
{PIPE_FORMAT_R16G16B16_USCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0xffff, 0xffff, 0xffff), UNPACKED_1x1(65535.0, 65535.0, 65535.0, 1.0)},
 
{PIPE_FORMAT_R16G16B16A16_USCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x0000, 0x0000), UNPACKED_1x1( 0.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_R16G16B16A16_USCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0xffff, 0x0000, 0x0000, 0x0000), UNPACKED_1x1(65535.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_R16G16B16A16_USCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0xffff, 0x0000, 0x0000), UNPACKED_1x1( 0.0, 65535.0, 0.0, 0.0)},
{PIPE_FORMAT_R16G16B16A16_USCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0xffff, 0x0000), UNPACKED_1x1( 0.0, 0.0, 65535.0, 0.0)},
{PIPE_FORMAT_R16G16B16A16_USCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x0000, 0xffff), UNPACKED_1x1( 0.0, 0.0, 0.0, 65535.0)},
{PIPE_FORMAT_R16G16B16A16_USCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), UNPACKED_1x1(65535.0, 65535.0, 65535.0, 65535.0)},
 
{PIPE_FORMAT_R16_SNORM, PACKED_1x16(0xffff), PACKED_1x16(0x0000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R16_SNORM, PACKED_1x16(0xffff), PACKED_1x16(0x7fff), UNPACKED_1x1( 1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R16_SNORM, PACKED_1x16(0xffff), PACKED_1x16(0x8001), UNPACKED_1x1( -1.0, 0.0, 0.0, 1.0)},
 
{PIPE_FORMAT_R16G16_SNORM, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x0000, 0x0000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R16G16_SNORM, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x7fff, 0x0000), UNPACKED_1x1( 1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R16G16_SNORM, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x8001, 0x0000), UNPACKED_1x1( -1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R16G16_SNORM, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x0000, 0x7fff), UNPACKED_1x1( 0.0, 1.0, 0.0, 1.0)},
{PIPE_FORMAT_R16G16_SNORM, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x0000, 0x8001), UNPACKED_1x1( 0.0, -1.0, 0.0, 1.0)},
 
{PIPE_FORMAT_R16G16B16_SNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x0000, 0x0000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R16G16B16_SNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x7fff, 0x0000, 0x0000), UNPACKED_1x1( 1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R16G16B16_SNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x8001, 0x0000, 0x0000), UNPACKED_1x1( -1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R16G16B16_SNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x7fff, 0x0000), UNPACKED_1x1( 0.0, 1.0, 0.0, 1.0)},
{PIPE_FORMAT_R16G16B16_SNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x8001, 0x0000), UNPACKED_1x1( 0.0, -1.0, 0.0, 1.0)},
{PIPE_FORMAT_R16G16B16_SNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x0000, 0x7fff), UNPACKED_1x1( 0.0, 0.0, 1.0, 1.0)},
{PIPE_FORMAT_R16G16B16_SNORM, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x0000, 0x8001), UNPACKED_1x1( 0.0, 0.0, -1.0, 1.0)},
 
{PIPE_FORMAT_R16G16B16A16_SNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x0000, 0x0000), UNPACKED_1x1( 0.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_R16G16B16A16_SNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x7fff, 0x0000, 0x0000, 0x0000), UNPACKED_1x1( 1.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_R16G16B16A16_SNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x8001, 0x0000, 0x0000, 0x0000), UNPACKED_1x1( -1.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_R16G16B16A16_SNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x7fff, 0x0000, 0x0000), UNPACKED_1x1( 0.0, 1.0, 0.0, 0.0)},
{PIPE_FORMAT_R16G16B16A16_SNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x8001, 0x0000, 0x0000), UNPACKED_1x1( 0.0, -1.0, 0.0, 0.0)},
{PIPE_FORMAT_R16G16B16A16_SNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x7fff, 0x0000), UNPACKED_1x1( 0.0, 0.0, 1.0, 0.0)},
{PIPE_FORMAT_R16G16B16A16_SNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x8001, 0x0000), UNPACKED_1x1( 0.0, 0.0, -1.0, 0.0)},
{PIPE_FORMAT_R16G16B16A16_SNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x0000, 0x7fff), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R16G16B16A16_SNORM, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x0000, 0x8001), UNPACKED_1x1( 0.0, 0.0, 0.0, -1.0)},
 
{PIPE_FORMAT_R16_SSCALED, PACKED_1x16(0xffff), PACKED_1x16(0x0000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R16_SSCALED, PACKED_1x16(0xffff), PACKED_1x16(0x7fff), UNPACKED_1x1( 32767.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R16_SSCALED, PACKED_1x16(0xffff), PACKED_1x16(0x8000), UNPACKED_1x1(-32768.0, 0.0, 0.0, 1.0)},
 
{PIPE_FORMAT_R16G16_SSCALED, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x0000, 0x0000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R16G16_SSCALED, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x7fff, 0x0000), UNPACKED_1x1( 32767.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R16G16_SSCALED, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x8000, 0x0000), UNPACKED_1x1(-32768.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R16G16_SSCALED, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x0000, 0x7fff), UNPACKED_1x1( 0.0, 32767.0, 0.0, 1.0)},
{PIPE_FORMAT_R16G16_SSCALED, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x0000, 0x8000), UNPACKED_1x1( 0.0, -32768.0, 0.0, 1.0)},
 
{PIPE_FORMAT_R16G16B16_SSCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x0000, 0x0000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R16G16B16_SSCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x7fff, 0x0000, 0x0000), UNPACKED_1x1( 32767.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R16G16B16_SSCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x8000, 0x0000, 0x0000), UNPACKED_1x1(-32768.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R16G16B16_SSCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x7fff, 0x0000), UNPACKED_1x1( 0.0, 32767.0, 0.0, 1.0)},
{PIPE_FORMAT_R16G16B16_SSCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x8000, 0x0000), UNPACKED_1x1( 0.0, -32768.0, 0.0, 1.0)},
{PIPE_FORMAT_R16G16B16_SSCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x0000, 0x7fff), UNPACKED_1x1( 0.0, 0.0, 32767.0, 1.0)},
{PIPE_FORMAT_R16G16B16_SSCALED, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x0000, 0x8000), UNPACKED_1x1( 0.0, 0.0, -32768.0, 1.0)},
 
{PIPE_FORMAT_R16G16B16A16_SSCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x0000, 0x0000), UNPACKED_1x1( 0.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_R16G16B16A16_SSCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x7fff, 0x0000, 0x0000, 0x0000), UNPACKED_1x1( 32767.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_R16G16B16A16_SSCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x8000, 0x0000, 0x0000, 0x0000), UNPACKED_1x1(-32768.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_R16G16B16A16_SSCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x7fff, 0x0000, 0x0000), UNPACKED_1x1( 0.0, 32767.0, 0.0, 0.0)},
{PIPE_FORMAT_R16G16B16A16_SSCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x8000, 0x0000, 0x0000), UNPACKED_1x1( 0.0, -32768.0, 0.0, 0.0)},
{PIPE_FORMAT_R16G16B16A16_SSCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x7fff, 0x0000), UNPACKED_1x1( 0.0, 0.0, 32767.0, 0.0)},
{PIPE_FORMAT_R16G16B16A16_SSCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x8000, 0x0000), UNPACKED_1x1( 0.0, 0.0, -32768.0, 0.0)},
{PIPE_FORMAT_R16G16B16A16_SSCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x0000, 0x7fff), UNPACKED_1x1( 0.0, 0.0, 0.0, 32767.0)},
{PIPE_FORMAT_R16G16B16A16_SSCALED, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x0000, 0x8000), UNPACKED_1x1( 0.0, 0.0, 0.0, -32768.0)},
 
/*
* Standard 32-bit integer formats
*
* NOTE: We can't accurately represent integers larger than +/-0x1000000
* with single precision floats, so that's as far as we test.
*/
 
{PIPE_FORMAT_R32_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R32_UNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0xffffffff), UNPACKED_1x1(1.0, 0.0, 0.0, 1.0)},
 
{PIPE_FORMAT_R32G32_UNORM, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32_UNORM, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0xffffffff, 0x00000000), UNPACKED_1x1(1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32_UNORM, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0xffffffff), UNPACKED_1x1(0.0, 1.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32_UNORM, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0xffffffff, 0xffffffff), UNPACKED_1x1(1.0, 1.0, 0.0, 1.0)},
 
{PIPE_FORMAT_R32G32B32_UNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32B32_UNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0xffffffff, 0x00000000, 0x00000000), UNPACKED_1x1(1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32B32_UNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0xffffffff, 0x00000000), UNPACKED_1x1(0.0, 1.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32B32_UNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0xffffffff), UNPACKED_1x1(0.0, 0.0, 1.0, 1.0)},
{PIPE_FORMAT_R32G32B32_UNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)},
 
{PIPE_FORMAT_R32G32B32A32_UNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0x00000000), UNPACKED_1x1(0.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_R32G32B32A32_UNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0xffffffff, 0x00000000, 0x00000000, 0x00000000), UNPACKED_1x1(1.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_R32G32B32A32_UNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0xffffffff, 0x00000000, 0x00000000), UNPACKED_1x1(0.0, 1.0, 0.0, 0.0)},
{PIPE_FORMAT_R32G32B32A32_UNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0xffffffff, 0x00000000), UNPACKED_1x1(0.0, 0.0, 1.0, 0.0)},
{PIPE_FORMAT_R32G32B32A32_UNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0xffffffff), UNPACKED_1x1(0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32B32A32_UNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), UNPACKED_1x1(1.0, 1.0, 1.0, 1.0)},
 
{PIPE_FORMAT_R32_USCALED, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R32_USCALED, PACKED_1x32(0xffffffff), PACKED_1x32(0x01000000), UNPACKED_1x1(16777216.0, 0.0, 0.0, 1.0)},
 
{PIPE_FORMAT_R32G32_USCALED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32_USCALED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x01000000, 0x00000000), UNPACKED_1x1(16777216.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32_USCALED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0x01000000), UNPACKED_1x1( 0.0, 16777216.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32_USCALED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x01000000, 0x01000000), UNPACKED_1x1(16777216.0, 16777216.0, 0.0, 1.0)},
 
{PIPE_FORMAT_R32G32B32_USCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32B32_USCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x01000000, 0x00000000, 0x00000000), UNPACKED_1x1(16777216.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32B32_USCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x01000000, 0x00000000), UNPACKED_1x1( 0.0, 16777216.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32B32_USCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0x01000000), UNPACKED_1x1( 0.0, 0.0, 16777216.0, 1.0)},
{PIPE_FORMAT_R32G32B32_USCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x01000000, 0x01000000, 0x01000000), UNPACKED_1x1(16777216.0, 16777216.0, 16777216.0, 1.0)},
 
{PIPE_FORMAT_R32G32B32A32_USCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_R32G32B32A32_USCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x01000000, 0x00000000, 0x00000000, 0x00000000), UNPACKED_1x1(16777216.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_R32G32B32A32_USCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x01000000, 0x00000000, 0x00000000), UNPACKED_1x1( 0.0, 16777216.0, 0.0, 0.0)},
{PIPE_FORMAT_R32G32B32A32_USCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x01000000, 0x00000000), UNPACKED_1x1( 0.0, 0.0, 16777216.0, 0.0)},
{PIPE_FORMAT_R32G32B32A32_USCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0x01000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 16777216.0)},
{PIPE_FORMAT_R32G32B32A32_USCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x01000000, 0x01000000, 0x01000000, 0x01000000), UNPACKED_1x1(16777216.0, 16777216.0, 16777216.0, 16777216.0)},
 
{PIPE_FORMAT_R32_SNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R32_SNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x7fffffff), UNPACKED_1x1( 1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R32_SNORM, PACKED_1x32(0xffffffff), PACKED_1x32(0x80000001), UNPACKED_1x1( -1.0, 0.0, 0.0, 1.0)},
 
{PIPE_FORMAT_R32G32_SNORM, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32_SNORM, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x7fffffff, 0x00000000), UNPACKED_1x1( 1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32_SNORM, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x80000001, 0x00000000), UNPACKED_1x1( -1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32_SNORM, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0x7fffffff), UNPACKED_1x1( 0.0, 1.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32_SNORM, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0x80000001), UNPACKED_1x1( 0.0, -1.0, 0.0, 1.0)},
 
{PIPE_FORMAT_R32G32B32_SNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32B32_SNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x7fffffff, 0x00000000, 0x00000000), UNPACKED_1x1( 1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32B32_SNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x80000001, 0x00000000, 0x00000000), UNPACKED_1x1( -1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32B32_SNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x7fffffff, 0x00000000), UNPACKED_1x1( 0.0, 1.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32B32_SNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x80000001, 0x00000000), UNPACKED_1x1( 0.0, -1.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32B32_SNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0x7fffffff), UNPACKED_1x1( 0.0, 0.0, 1.0, 1.0)},
{PIPE_FORMAT_R32G32B32_SNORM, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0x80000001), UNPACKED_1x1( 0.0, 0.0, -1.0, 1.0)},
 
{PIPE_FORMAT_R32G32B32A32_SNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_R32G32B32A32_SNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x7fffffff, 0x00000000, 0x00000000, 0x00000000), UNPACKED_1x1( 1.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_R32G32B32A32_SNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x80000001, 0x00000000, 0x00000000, 0x00000000), UNPACKED_1x1( -1.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_R32G32B32A32_SNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x7fffffff, 0x00000000, 0x00000000), UNPACKED_1x1( 0.0, 1.0, 0.0, 0.0)},
{PIPE_FORMAT_R32G32B32A32_SNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x80000001, 0x00000000, 0x00000000), UNPACKED_1x1( 0.0, -1.0, 0.0, 0.0)},
{PIPE_FORMAT_R32G32B32A32_SNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x7fffffff, 0x00000000), UNPACKED_1x1( 0.0, 0.0, 1.0, 0.0)},
{PIPE_FORMAT_R32G32B32A32_SNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x80000001, 0x00000000), UNPACKED_1x1( 0.0, 0.0, -1.0, 0.0)},
{PIPE_FORMAT_R32G32B32A32_SNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0x7fffffff), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32B32A32_SNORM, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0x80000001), UNPACKED_1x1( 0.0, 0.0, 0.0, -1.0)},
 
{PIPE_FORMAT_R32_SSCALED, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R32_SSCALED, PACKED_1x32(0xffffffff), PACKED_1x32(0x01000000), UNPACKED_1x1( 16777216.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R32_SSCALED, PACKED_1x32(0xffffffff), PACKED_1x32(0xff000000), UNPACKED_1x1(-16777216.0, 0.0, 0.0, 1.0)},
 
{PIPE_FORMAT_R32G32_SSCALED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32_SSCALED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x01000000, 0x00000000), UNPACKED_1x1( 16777216.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32_SSCALED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0xff000000, 0x00000000), UNPACKED_1x1(-16777216.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32_SSCALED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0x01000000), UNPACKED_1x1( 0.0, 16777216.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32_SSCALED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0xff000000), UNPACKED_1x1( 0.0, -16777216.0, 0.0, 1.0)},
 
{PIPE_FORMAT_R32G32B32_SSCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32B32_SSCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x01000000, 0x00000000, 0x00000000), UNPACKED_1x1( 16777216.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32B32_SSCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0xff000000, 0x00000000, 0x00000000), UNPACKED_1x1(-16777216.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32B32_SSCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x01000000, 0x00000000), UNPACKED_1x1( 0.0, 16777216.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32B32_SSCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0xff000000, 0x00000000), UNPACKED_1x1( 0.0, -16777216.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32B32_SSCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0x01000000), UNPACKED_1x1( 0.0, 0.0, 16777216.0, 1.0)},
{PIPE_FORMAT_R32G32B32_SSCALED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0xff000000), UNPACKED_1x1( 0.0, 0.0, -16777216.0, 1.0)},
 
{PIPE_FORMAT_R32G32B32A32_SSCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_R32G32B32A32_SSCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x01000000, 0x00000000, 0x00000000, 0x00000000), UNPACKED_1x1( 16777216.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_R32G32B32A32_SSCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0xff000000, 0x00000000, 0x00000000, 0x00000000), UNPACKED_1x1(-16777216.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_R32G32B32A32_SSCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x01000000, 0x00000000, 0x00000000), UNPACKED_1x1( 0.0, 16777216.0, 0.0, 0.0)},
{PIPE_FORMAT_R32G32B32A32_SSCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0xff000000, 0x00000000, 0x00000000), UNPACKED_1x1( 0.0, -16777216.0, 0.0, 0.0)},
{PIPE_FORMAT_R32G32B32A32_SSCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x01000000, 0x00000000), UNPACKED_1x1( 0.0, 0.0, 16777216.0, 0.0)},
{PIPE_FORMAT_R32G32B32A32_SSCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0xff000000, 0x00000000), UNPACKED_1x1( 0.0, 0.0, -16777216.0, 0.0)},
{PIPE_FORMAT_R32G32B32A32_SSCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0x01000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 16777216.0)},
{PIPE_FORMAT_R32G32B32A32_SSCALED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0xff000000), UNPACKED_1x1( 0.0, 0.0, 0.0, -16777216.0)},
 
/*
* Standard 32-bit float formats
*/
 
{PIPE_FORMAT_R32_FLOAT, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R32_FLOAT, PACKED_1x32(0xffffffff), PACKED_1x32(0x3f800000), UNPACKED_1x1( 1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R32_FLOAT, PACKED_1x32(0xffffffff), PACKED_1x32(0xbf800000), UNPACKED_1x1( -1.0, 0.0, 0.0, 1.0)},
 
{PIPE_FORMAT_R32G32_FLOAT, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32_FLOAT, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x3f800000, 0x00000000), UNPACKED_1x1( 1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32_FLOAT, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0xbf800000, 0x00000000), UNPACKED_1x1(-1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32_FLOAT, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0x3f800000), UNPACKED_1x1( 0.0, 1.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32_FLOAT, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0xbf800000), UNPACKED_1x1( 0.0, -1.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32_FLOAT, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x3f800000, 0x3f800000), UNPACKED_1x1( 1.0, 1.0, 0.0, 1.0)},
 
{PIPE_FORMAT_R32G32B32_FLOAT, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32B32_FLOAT, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x3f800000, 0x00000000, 0x00000000), UNPACKED_1x1( 1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32B32_FLOAT, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0xbf800000, 0x00000000, 0x00000000), UNPACKED_1x1(-1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32B32_FLOAT, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x3f800000, 0x00000000), UNPACKED_1x1( 0.0, 1.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32B32_FLOAT, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0xbf800000, 0x00000000), UNPACKED_1x1( 0.0, -1.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32B32_FLOAT, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0x3f800000), UNPACKED_1x1( 0.0, 0.0, 1.0, 1.0)},
{PIPE_FORMAT_R32G32B32_FLOAT, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0xbf800000), UNPACKED_1x1( 0.0, 0.0, -1.0, 1.0)},
{PIPE_FORMAT_R32G32B32_FLOAT, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x3f800000, 0x3f800000, 0x3f800000), UNPACKED_1x1( 1.0, 1.0, 1.0, 1.0)},
 
{PIPE_FORMAT_R32G32B32A32_FLOAT, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_R32G32B32A32_FLOAT, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x3f800000, 0x00000000, 0x00000000, 0x00000000), UNPACKED_1x1( 1.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_R32G32B32A32_FLOAT, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0xbf800000, 0x00000000, 0x00000000, 0x00000000), UNPACKED_1x1(-1.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_R32G32B32A32_FLOAT, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x3f800000, 0x00000000, 0x00000000), UNPACKED_1x1( 0.0, 1.0, 0.0, 0.0)},
{PIPE_FORMAT_R32G32B32A32_FLOAT, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0xbf800000, 0x00000000, 0x00000000), UNPACKED_1x1( 0.0, -1.0, 0.0, 0.0)},
{PIPE_FORMAT_R32G32B32A32_FLOAT, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x3f800000, 0x00000000), UNPACKED_1x1( 0.0, 0.0, 1.0, 0.0)},
{PIPE_FORMAT_R32G32B32A32_FLOAT, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0xbf800000, 0x00000000), UNPACKED_1x1( 0.0, 0.0, -1.0, 0.0)},
{PIPE_FORMAT_R32G32B32A32_FLOAT, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0x3f800000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32B32A32_FLOAT, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0xbf800000), UNPACKED_1x1( 0.0, 0.0, 0.0, -1.0)},
{PIPE_FORMAT_R32G32B32A32_FLOAT, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x3f800000, 0x3f800000, 0x3f800000, 0x3f800000), UNPACKED_1x1( 1.0, 1.0, 1.0, 1.0)},
 
/*
* Half float formats
*/
 
/* Minimum positive normal */
{PIPE_FORMAT_R16_FLOAT, PACKED_1x16(0xffff), PACKED_1x16(0x0400), UNPACKED_1x1( 6.10352E-5, 0.0, 0.0, 1.0)},
 
/* Max denormal */
{PIPE_FORMAT_R16_FLOAT, PACKED_1x16(0xffff), PACKED_1x16(0x03FF), UNPACKED_1x1( 6.09756E-5, 0.0, 0.0, 1.0)},
 
/* Minimum positive denormal */
{PIPE_FORMAT_R16_FLOAT, PACKED_1x16(0xffff), PACKED_1x16(0x0001), UNPACKED_1x1( 5.96046E-8, 0.0, 0.0, 1.0)},
 
/* Min representable value */
{PIPE_FORMAT_R16_FLOAT, PACKED_1x16(0xffff), PACKED_1x16(0xfbff), UNPACKED_1x1( -65504.0, 0.0, 0.0, 1.0)},
 
/* Max representable value */
{PIPE_FORMAT_R16_FLOAT, PACKED_1x16(0xffff), PACKED_1x16(0x7bff), UNPACKED_1x1( 65504.0, 0.0, 0.0, 1.0)},
 
#if !defined(PIPE_CC_MSVC)
 
/* NaNs */
{PIPE_FORMAT_R16_FLOAT, PACKED_1x16(0xffff), PACKED_1x16(0x7c01), UNPACKED_1x1( NAN, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R16_FLOAT, PACKED_1x16(0xffff), PACKED_1x16(0xfc01), UNPACKED_1x1( -NAN, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R16_FLOAT, PACKED_1x16(0xffff), PACKED_1x16(0x7fff), UNPACKED_1x1( NAN, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R16_FLOAT, PACKED_1x16(0xffff), PACKED_1x16(0xffff), UNPACKED_1x1( -NAN, 0.0, 0.0, 1.0)},
 
/* Inf */
{PIPE_FORMAT_R16_FLOAT, PACKED_1x16(0xffff), PACKED_1x16(0x7c00), UNPACKED_1x1( INFINITY, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R16_FLOAT, PACKED_1x16(0xffff), PACKED_1x16(0xfc00), UNPACKED_1x1( -INFINITY, 0.0, 0.0, 1.0)},
 
#endif
 
/* Zero, ignore sign */
{PIPE_FORMAT_R16_FLOAT, PACKED_1x16(0x7fff), PACKED_1x16(0x8000), UNPACKED_1x1( -0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R16_FLOAT, PACKED_1x16(0x7fff), PACKED_1x16(0x0000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)},
 
{PIPE_FORMAT_R16_FLOAT, PACKED_1x16(0xffff), PACKED_1x16(0x3c00), UNPACKED_1x1( 1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R16_FLOAT, PACKED_1x16(0xffff), PACKED_1x16(0xbc00), UNPACKED_1x1( -1.0, 0.0, 0.0, 1.0)},
 
{PIPE_FORMAT_R16G16_FLOAT, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x0000, 0x0000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R16G16_FLOAT, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x3c00, 0x0000), UNPACKED_1x1( 1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R16G16_FLOAT, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0xbc00, 0x0000), UNPACKED_1x1(-1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R16G16_FLOAT, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x0000, 0x3c00), UNPACKED_1x1( 0.0, 1.0, 0.0, 1.0)},
{PIPE_FORMAT_R16G16_FLOAT, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x0000, 0xbc00), UNPACKED_1x1( 0.0, -1.0, 0.0, 1.0)},
{PIPE_FORMAT_R16G16_FLOAT, PACKED_2x16(0xffff, 0xffff), PACKED_2x16(0x3c00, 0x3c00), UNPACKED_1x1( 1.0, 1.0, 0.0, 1.0)},
 
{PIPE_FORMAT_R16G16B16_FLOAT, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x0000, 0x0000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R16G16B16_FLOAT, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x3c00, 0x0000, 0x0000), UNPACKED_1x1( 1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R16G16B16_FLOAT, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0xbc00, 0x0000, 0x0000), UNPACKED_1x1(-1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R16G16B16_FLOAT, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x3c00, 0x0000), UNPACKED_1x1( 0.0, 1.0, 0.0, 1.0)},
{PIPE_FORMAT_R16G16B16_FLOAT, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0xbc00, 0x0000), UNPACKED_1x1( 0.0, -1.0, 0.0, 1.0)},
{PIPE_FORMAT_R16G16B16_FLOAT, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x0000, 0x3c00), UNPACKED_1x1( 0.0, 0.0, 1.0, 1.0)},
{PIPE_FORMAT_R16G16B16_FLOAT, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x0000, 0x0000, 0xbc00), UNPACKED_1x1( 0.0, 0.0, -1.0, 1.0)},
{PIPE_FORMAT_R16G16B16_FLOAT, PACKED_3x16(0xffff, 0xffff, 0xffff), PACKED_3x16(0x3c00, 0x3c00, 0x3c00), UNPACKED_1x1( 1.0, 1.0, 1.0, 1.0)},
 
{PIPE_FORMAT_R16G16B16A16_FLOAT, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x0000, 0x0000), UNPACKED_1x1( 0.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_R16G16B16A16_FLOAT, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x3c00, 0x0000, 0x0000, 0x0000), UNPACKED_1x1( 1.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_R16G16B16A16_FLOAT, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0xbc00, 0x0000, 0x0000, 0x0000), UNPACKED_1x1(-1.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_R16G16B16A16_FLOAT, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x3c00, 0x0000, 0x0000), UNPACKED_1x1( 0.0, 1.0, 0.0, 0.0)},
{PIPE_FORMAT_R16G16B16A16_FLOAT, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0xbc00, 0x0000, 0x0000), UNPACKED_1x1( 0.0, -1.0, 0.0, 0.0)},
{PIPE_FORMAT_R16G16B16A16_FLOAT, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x3c00, 0x0000), UNPACKED_1x1( 0.0, 0.0, 1.0, 0.0)},
{PIPE_FORMAT_R16G16B16A16_FLOAT, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0xbc00, 0x0000), UNPACKED_1x1( 0.0, 0.0, -1.0, 0.0)},
{PIPE_FORMAT_R16G16B16A16_FLOAT, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x0000, 0x3c00), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R16G16B16A16_FLOAT, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x0000, 0x0000, 0x0000, 0xbc00), UNPACKED_1x1( 0.0, 0.0, 0.0, -1.0)},
{PIPE_FORMAT_R16G16B16A16_FLOAT, PACKED_4x16(0xffff, 0xffff, 0xffff, 0xffff), PACKED_4x16(0x3c00, 0x3c00, 0x3c00, 0x3c00), UNPACKED_1x1( 1.0, 1.0, 1.0, 1.0)},
 
/*
* 32-bit fixed point formats
*/
 
{PIPE_FORMAT_R32_FIXED, PACKED_1x32(0xffffffff), PACKED_1x32(0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R32_FIXED, PACKED_1x32(0xffffffff), PACKED_1x32(0x00010000), UNPACKED_1x1( 1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R32_FIXED, PACKED_1x32(0xffffffff), PACKED_1x32(0xffff0000), UNPACKED_1x1( -1.0, 0.0, 0.0, 1.0)},
 
{PIPE_FORMAT_R32G32_FIXED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32_FIXED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00010000, 0x00000000), UNPACKED_1x1( 1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32_FIXED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0xffff0000, 0x00000000), UNPACKED_1x1(-1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32_FIXED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0x00010000), UNPACKED_1x1( 0.0, 1.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32_FIXED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00000000, 0xffff0000), UNPACKED_1x1( 0.0, -1.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32_FIXED, PACKED_2x32(0xffffffff, 0xffffffff), PACKED_2x32(0x00010000, 0x00010000), UNPACKED_1x1( 1.0, 1.0, 0.0, 1.0)},
 
{PIPE_FORMAT_R32G32B32_FIXED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32B32_FIXED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00010000, 0x00000000, 0x00000000), UNPACKED_1x1( 1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32B32_FIXED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0xffff0000, 0x00000000, 0x00000000), UNPACKED_1x1(-1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32B32_FIXED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00010000, 0x00000000), UNPACKED_1x1( 0.0, 1.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32B32_FIXED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0xffff0000, 0x00000000), UNPACKED_1x1( 0.0, -1.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32B32_FIXED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0x00010000), UNPACKED_1x1( 0.0, 0.0, 1.0, 1.0)},
{PIPE_FORMAT_R32G32B32_FIXED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00000000, 0x00000000, 0xffff0000), UNPACKED_1x1( 0.0, 0.0, -1.0, 1.0)},
{PIPE_FORMAT_R32G32B32_FIXED, PACKED_3x32(0xffffffff, 0xffffffff, 0xffffffff), PACKED_3x32(0x00010000, 0x00010000, 0x00010000), UNPACKED_1x1( 1.0, 1.0, 1.0, 1.0)},
 
{PIPE_FORMAT_R32G32B32A32_FIXED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_R32G32B32A32_FIXED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00010000, 0x00000000, 0x00000000, 0x00000000), UNPACKED_1x1( 1.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_R32G32B32A32_FIXED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0xffff0000, 0x00000000, 0x00000000, 0x00000000), UNPACKED_1x1(-1.0, 0.0, 0.0, 0.0)},
{PIPE_FORMAT_R32G32B32A32_FIXED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00010000, 0x00000000, 0x00000000), UNPACKED_1x1( 0.0, 1.0, 0.0, 0.0)},
{PIPE_FORMAT_R32G32B32A32_FIXED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0xffff0000, 0x00000000, 0x00000000), UNPACKED_1x1( 0.0, -1.0, 0.0, 0.0)},
{PIPE_FORMAT_R32G32B32A32_FIXED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00010000, 0x00000000), UNPACKED_1x1( 0.0, 0.0, 1.0, 0.0)},
{PIPE_FORMAT_R32G32B32A32_FIXED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0xffff0000, 0x00000000), UNPACKED_1x1( 0.0, 0.0, -1.0, 0.0)},
{PIPE_FORMAT_R32G32B32A32_FIXED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0x00010000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R32G32B32A32_FIXED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00000000, 0x00000000, 0x00000000, 0xffff0000), UNPACKED_1x1( 0.0, 0.0, 0.0, -1.0)},
{PIPE_FORMAT_R32G32B32A32_FIXED, PACKED_4x32(0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff), PACKED_4x32(0x00010000, 0x00010000, 0x00010000, 0x00010000), UNPACKED_1x1( 1.0, 1.0, 1.0, 1.0)},
 
/*
* D3D9 specific vertex formats
*/
 
{PIPE_FORMAT_R10G10B10X2_USCALED, PACKED_1x32(0x3fffffff), PACKED_1x32(0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R10G10B10X2_USCALED, PACKED_1x32(0x3fffffff), PACKED_1x32(0x000003ff), UNPACKED_1x1(1023.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R10G10B10X2_USCALED, PACKED_1x32(0x3fffffff), PACKED_1x32(0x000ffc00), UNPACKED_1x1( 0.0, 1023.0, 0.0, 1.0)},
{PIPE_FORMAT_R10G10B10X2_USCALED, PACKED_1x32(0x3fffffff), PACKED_1x32(0x3ff00000), UNPACKED_1x1( 0.0, 0.0, 1023.0, 1.0)},
{PIPE_FORMAT_R10G10B10X2_USCALED, PACKED_1x32(0x3fffffff), PACKED_1x32(0x3fffffff), UNPACKED_1x1(1023.0, 1023.0, 1023.0, 1.0)},
 
{PIPE_FORMAT_R10G10B10X2_SNORM, PACKED_1x32(0x3fffffff), PACKED_1x32(0x00000000), UNPACKED_1x1( 0.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R10G10B10X2_SNORM, PACKED_1x32(0x3fffffff), PACKED_1x32(0x000001ff), UNPACKED_1x1( 1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R10G10B10X2_SNORM, PACKED_1x32(0x3fffffff), PACKED_1x32(0x00000201), UNPACKED_1x1(-1.0, 0.0, 0.0, 1.0)},
{PIPE_FORMAT_R10G10B10X2_SNORM, PACKED_1x32(0x3fffffff), PACKED_1x32(0x0007fc00), UNPACKED_1x1( 0.0, 1.0, 0.0, 1.0)},
{PIPE_FORMAT_R10G10B10X2_SNORM, PACKED_1x32(0x3fffffff), PACKED_1x32(0x00080400), UNPACKED_1x1( 0.0, -1.0, 0.0, 1.0)},
{PIPE_FORMAT_R10G10B10X2_SNORM, PACKED_1x32(0x3fffffff), PACKED_1x32(0x1ff00000), UNPACKED_1x1( 0.0, 0.0, 1.0, 1.0)},
{PIPE_FORMAT_R10G10B10X2_SNORM, PACKED_1x32(0x3fffffff), PACKED_1x32(0x20100000), UNPACKED_1x1( 0.0, 0.0, -1.0, 1.0)},
 
/*
* Special formats that not fit anywhere else
*/
 
};
 
 
const unsigned util_format_nr_test_cases = Elements(util_format_test_cases);
/drivers/video/Gallium/auxiliary/util/u_format_tests.h
0,0 → 1,71
/**************************************************************************
*
* Copyright 2010 VMware, Inc.
* 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 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
* THE COPYRIGHT HOLDERS, AUTHORS 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.
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
**************************************************************************/
 
 
#ifndef U_FORMAT_TESTS_H_
#define U_FORMAT_TESTS_H_
 
 
#include "pipe/p_compiler.h"
#include "pipe/p_format.h"
 
 
#define UTIL_FORMAT_MAX_PACKED_BYTES 16
#define UTIL_FORMAT_MAX_UNPACKED_WIDTH 4
#define UTIL_FORMAT_MAX_UNPACKED_HEIGHT 4
 
 
/**
* A (packed, unpacked) color pair.
*/
struct util_format_test_case
{
enum pipe_format format;
 
/**
* Mask of the bits that actually meaningful data. Used to mask out the
* "X" channels.
*/
uint8_t mask[UTIL_FORMAT_MAX_PACKED_BYTES];
 
uint8_t packed[UTIL_FORMAT_MAX_PACKED_BYTES];
 
/**
* RGBA.
*/
double unpacked[UTIL_FORMAT_MAX_UNPACKED_HEIGHT][UTIL_FORMAT_MAX_UNPACKED_WIDTH][4];
};
 
 
extern const struct util_format_test_case
util_format_test_cases[];
 
 
extern const unsigned util_format_nr_test_cases;
 
 
#endif /* U_FORMAT_TESTS_H_ */
/drivers/video/Gallium/auxiliary/util/u_format_yuv.c
0,0 → 1,1193
/**************************************************************************
*
* Copyright 2010 VMware, Inc.
* 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 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
* THE COPYRIGHT HOLDERS, AUTHORS 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.
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
**************************************************************************/
 
 
/**
* @file
* YUV and RGB subsampled formats conversion.
*
* @author Jose Fonseca <jfonseca@vmware.com>
*/
 
 
#include "util/u_debug.h"
#include "util/u_format_yuv.h"
 
 
void
util_format_r8g8_b8g8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
 
for (y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint32_t *src = (const uint32_t *)src_row;
uint32_t value;
float r, g0, g1, b;
 
for (x = 0; x + 1 < width; x += 2) {
value = *src++;
 
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
 
r = ubyte_to_float((value >> 0) & 0xff);
g0 = ubyte_to_float((value >> 8) & 0xff);
b = ubyte_to_float((value >> 16) & 0xff);
g1 = ubyte_to_float((value >> 24) & 0xff);
 
dst[0] = r; /* r */
dst[1] = g0; /* g */
dst[2] = b; /* b */
dst[3] = 1.0f; /* a */
dst += 4;
 
dst[0] = r; /* r */
dst[1] = g1; /* g */
dst[2] = b; /* b */
dst[3] = 1.0f; /* a */
dst += 4;
}
 
if (x < width) {
value = *src;
 
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
 
r = ubyte_to_float((value >> 0) & 0xff);
g0 = ubyte_to_float((value >> 8) & 0xff);
b = ubyte_to_float((value >> 16) & 0xff);
g1 = ubyte_to_float((value >> 24) & 0xff);
 
dst[0] = r; /* r */
dst[1] = g0; /* g */
dst[2] = b; /* b */
dst[3] = 1.0f; /* a */
}
 
src_row += src_stride/sizeof(*src_row);
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
 
void
util_format_r8g8_b8g8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
 
for (y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint32_t *src = (const uint32_t *)src_row;
uint32_t value;
uint8_t r, g0, g1, b;
 
for (x = 0; x + 1 < width; x += 2) {
value = *src++;
 
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
 
r = (value >> 0) & 0xff;
g0 = (value >> 8) & 0xff;
b = (value >> 16) & 0xff;
g1 = (value >> 24) & 0xff;
 
dst[0] = r; /* r */
dst[1] = g0; /* g */
dst[2] = b; /* b */
dst[3] = 0xff; /* a */
dst += 4;
 
dst[0] = r; /* r */
dst[1] = g1; /* g */
dst[2] = b; /* b */
dst[3] = 0xff; /* a */
dst += 4;
}
 
if (x < width) {
value = *src;
 
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
 
r = (value >> 0) & 0xff;
g0 = (value >> 8) & 0xff;
b = (value >> 16) & 0xff;
g1 = (value >> 24) & 0xff;
 
dst[0] = r; /* r */
dst[1] = g0; /* g */
dst[2] = b; /* b */
dst[3] = 0xff; /* a */
}
 
src_row += src_stride/sizeof(*src_row);
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
 
void
util_format_r8g8_b8g8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
const float *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
 
for (y = 0; y < height; y += 1) {
const float *src = src_row;
uint32_t *dst = (uint32_t *)dst_row;
float r, g0, g1, b;
uint32_t value;
 
for (x = 0; x + 1 < width; x += 2) {
r = 0.5f*(src[0] + src[4]);
g0 = src[1];
g1 = src[5];
b = 0.5f*(src[2] + src[6]);
 
value = float_to_ubyte(r);
value |= float_to_ubyte(g0) << 8;
value |= float_to_ubyte(b) << 16;
value |= float_to_ubyte(g1) << 24;
 
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
 
*dst++ = value;
 
src += 8;
}
 
if (x < width) {
r = src[0];
g0 = src[1];
g1 = 0;
b = src[2];
 
value = float_to_ubyte(r);
value |= float_to_ubyte(g0) << 8;
value |= float_to_ubyte(b) << 16;
value |= float_to_ubyte(g1) << 24;
 
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
 
*dst = value;
}
 
dst_row += dst_stride/sizeof(*dst_row);
src_row += src_stride/sizeof(*src_row);
}
}
 
 
void
util_format_r8g8_b8g8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
 
for (y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint32_t *dst = (uint32_t *)dst_row;
uint32_t r, g0, g1, b;
uint32_t value;
 
for (x = 0; x + 1 < width; x += 2) {
r = (src[0] + src[4] + 1) >> 1;
g0 = src[1];
g1 = src[5];
b = (src[2] + src[6] + 1) >> 1;
 
value = r;
value |= g0 << 8;
value |= b << 16;
value |= g1 << 24;
 
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
 
*dst++ = value;
 
src += 8;
}
 
if (x < width) {
r = src[0];
g0 = src[1];
g1 = 0;
b = src[2];
 
value = r;
value |= g0 << 8;
value |= b << 16;
value |= g1 << 24;
 
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
 
*dst = value;
}
 
dst_row += dst_stride/sizeof(*dst_row);
src_row += src_stride/sizeof(*src_row);
}
}
 
 
void
util_format_r8g8_b8g8_unorm_fetch_rgba_float(float *dst, const uint8_t *src,
unsigned i, unsigned j)
{
assert(i < 2);
assert(j < 1);
 
dst[0] = ubyte_to_float(src[0]); /* r */
dst[1] = ubyte_to_float(src[1 + 2*i]); /* g */
dst[2] = ubyte_to_float(src[2]); /* b */
dst[3] = 1.0f; /* a */
}
 
 
void
util_format_g8r8_g8b8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
 
for (y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint32_t *src = (const uint32_t *)src_row;
uint32_t value;
float r, g0, g1, b;
 
for (x = 0; x + 1 < width; x += 2) {
value = *src++;
 
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
 
g0 = ubyte_to_float((value >> 0) & 0xff);
r = ubyte_to_float((value >> 8) & 0xff);
g1 = ubyte_to_float((value >> 16) & 0xff);
b = ubyte_to_float((value >> 24) & 0xff);
 
dst[0] = r; /* r */
dst[1] = g0; /* g */
dst[2] = b; /* b */
dst[3] = 1.0f; /* a */
dst += 4;
 
dst[0] = r; /* r */
dst[1] = g1; /* g */
dst[2] = b; /* b */
dst[3] = 1.0f; /* a */
dst += 4;
}
 
if (x < width) {
value = *src;
 
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
 
g0 = ubyte_to_float((value >> 0) & 0xff);
r = ubyte_to_float((value >> 8) & 0xff);
g1 = ubyte_to_float((value >> 16) & 0xff);
b = ubyte_to_float((value >> 24) & 0xff);
 
dst[0] = r; /* r */
dst[1] = g0; /* g */
dst[2] = b; /* b */
dst[3] = 1.0f; /* a */
}
 
src_row += src_stride/sizeof(*src_row);
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
 
void
util_format_g8r8_g8b8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
 
for (y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint32_t *src = (const uint32_t *)src_row;
uint32_t value;
uint8_t r, g0, g1, b;
 
for (x = 0; x + 1 < width; x += 2) {
value = *src++;
 
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
 
g0 = (value >> 0) & 0xff;
r = (value >> 8) & 0xff;
g1 = (value >> 16) & 0xff;
b = (value >> 24) & 0xff;
 
dst[0] = r; /* r */
dst[1] = g0; /* g */
dst[2] = b; /* b */
dst[3] = 0xff; /* a */
dst += 4;
 
dst[0] = r; /* r */
dst[1] = g1; /* g */
dst[2] = b; /* b */
dst[3] = 0xff; /* a */
dst += 4;
}
 
if (x < width) {
value = *src;
 
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
 
g0 = (value >> 0) & 0xff;
r = (value >> 8) & 0xff;
g1 = (value >> 16) & 0xff;
b = (value >> 24) & 0xff;
 
dst[0] = r; /* r */
dst[1] = g0; /* g */
dst[2] = b; /* b */
dst[3] = 0xff; /* a */
}
 
src_row += src_stride/sizeof(*src_row);
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
 
void
util_format_g8r8_g8b8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
const float *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
 
for (y = 0; y < height; y += 1) {
const float *src = src_row;
uint32_t *dst = (uint32_t *)dst_row;
float r, g0, g1, b;
uint32_t value;
 
for (x = 0; x + 1 < width; x += 2) {
r = 0.5f*(src[0] + src[4]);
g0 = src[1];
g1 = src[5];
b = 0.5f*(src[2] + src[6]);
 
value = float_to_ubyte(g0);
value |= float_to_ubyte(r) << 8;
value |= float_to_ubyte(g1) << 16;
value |= float_to_ubyte(b) << 24;
 
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
 
*dst++ = value;
 
src += 8;
}
 
if (x < width) {
r = src[0];
g0 = src[1];
g1 = 0;
b = src[2];
 
value = float_to_ubyte(g0);
value |= float_to_ubyte(r) << 8;
value |= float_to_ubyte(g1) << 16;
value |= float_to_ubyte(b) << 24;
 
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
 
*dst = value;
}
 
dst_row += dst_stride/sizeof(*dst_row);
src_row += src_stride/sizeof(*src_row);
}
}
 
 
void
util_format_g8r8_g8b8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
 
for (y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint32_t *dst = (uint32_t *)dst_row;
uint32_t r, g0, g1, b;
uint32_t value;
 
for (x = 0; x + 1 < width; x += 2) {
r = (src[0] + src[4] + 1) >> 1;
g0 = src[1];
g1 = src[5];
b = (src[2] + src[6] + 1) >> 1;
 
value = g0;
value |= r << 8;
value |= g1 << 16;
value |= b << 24;
 
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
 
*dst++ = value;
 
src += 8;
}
 
if (x < width) {
r = src[0];
g0 = src[1];
g1 = 0;
b = src[2];
 
value = g0;
value |= r << 8;
value |= g1 << 16;
value |= b << 24;
 
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
 
*dst = value;
}
 
dst_row += dst_stride/sizeof(*dst_row);
src_row += src_stride/sizeof(*src_row);
}
}
 
 
void
util_format_g8r8_g8b8_unorm_fetch_rgba_float(float *dst, const uint8_t *src,
unsigned i, unsigned j)
{
assert(i < 2);
assert(j < 1);
 
dst[0] = ubyte_to_float(src[1]); /* r */
dst[1] = ubyte_to_float(src[0 + 2*i]); /* g */
dst[2] = ubyte_to_float(src[3]); /* b */
dst[3] = 1.0f; /* a */
}
 
 
void
util_format_uyvy_unpack_rgba_float(float *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
 
for (y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint32_t *src = (const uint32_t *)src_row;
uint32_t value;
uint8_t y0, y1, u, v;
 
for (x = 0; x + 1 < width; x += 2) {
value = *src++;
 
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
 
u = (value >> 0) & 0xff;
y0 = (value >> 8) & 0xff;
v = (value >> 16) & 0xff;
y1 = (value >> 24) & 0xff;
 
util_format_yuv_to_rgb_float(y0, u, v, &dst[0], &dst[1], &dst[2]);
dst[3] = 1.0f; /* a */
dst += 4;
 
util_format_yuv_to_rgb_float(y1, u, v, &dst[0], &dst[1], &dst[2]);
dst[3] = 1.0f; /* a */
dst += 4;
}
 
if (x < width) {
value = *src;
 
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
 
u = (value >> 0) & 0xff;
y0 = (value >> 8) & 0xff;
v = (value >> 16) & 0xff;
y1 = (value >> 24) & 0xff;
 
util_format_yuv_to_rgb_float(y0, u, v, &dst[0], &dst[1], &dst[2]);
dst[3] = 1.0f; /* a */
}
 
src_row += src_stride/sizeof(*src_row);
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
 
void
util_format_uyvy_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
 
for (y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint32_t *src = (const uint32_t *)src_row;
uint32_t value;
uint8_t y0, y1, u, v;
 
for (x = 0; x + 1 < width; x += 2) {
value = *src++;
 
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
 
u = (value >> 0) & 0xff;
y0 = (value >> 8) & 0xff;
v = (value >> 16) & 0xff;
y1 = (value >> 24) & 0xff;
 
util_format_yuv_to_rgb_8unorm(y0, u, v, &dst[0], &dst[1], &dst[2]);
dst[3] = 0xff; /* a */
dst += 4;
 
util_format_yuv_to_rgb_8unorm(y1, u, v, &dst[0], &dst[1], &dst[2]);
dst[3] = 0xff; /* a */
dst += 4;
}
 
if (x < width) {
value = *src;
 
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
 
u = (value >> 0) & 0xff;
y0 = (value >> 8) & 0xff;
v = (value >> 16) & 0xff;
y1 = (value >> 24) & 0xff;
 
util_format_yuv_to_rgb_8unorm(y0, u, v, &dst[0], &dst[1], &dst[2]);
dst[3] = 0xff; /* a */
}
 
src_row += src_stride/sizeof(*src_row);
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
 
void
util_format_uyvy_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
const float *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
 
for (y = 0; y < height; y += 1) {
const float *src = src_row;
uint32_t *dst = (uint32_t *)dst_row;
uint8_t y0, y1, u, v;
uint32_t value;
 
for (x = 0; x + 1 < width; x += 2) {
uint8_t y0, y1, u0, u1, v0, v1, u, v;
 
util_format_rgb_float_to_yuv(src[0], src[1], src[2],
&y0, &u0, &v0);
util_format_rgb_float_to_yuv(src[4], src[5], src[6],
&y1, &u1, &v1);
 
u = (u0 + u1 + 1) >> 1;
v = (v0 + v1 + 1) >> 1;
 
value = u;
value |= y0 << 8;
value |= v << 16;
value |= y1 << 24;
 
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
 
*dst++ = value;
 
src += 8;
}
 
if (x < width) {
util_format_rgb_float_to_yuv(src[0], src[1], src[2],
&y0, &u, &v);
y1 = 0;
 
value = u;
value |= y0 << 8;
value |= v << 16;
value |= y1 << 24;
 
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
 
*dst = value;
}
 
dst_row += dst_stride/sizeof(*dst_row);
src_row += src_stride/sizeof(*src_row);
}
}
 
 
void
util_format_uyvy_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
 
for (y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint32_t *dst = (uint32_t *)dst_row;
uint8_t y0, y1, u, v;
uint32_t value;
 
for (x = 0; x + 1 < width; x += 2) {
uint8_t y0, y1, u0, u1, v0, v1, u, v;
 
util_format_rgb_8unorm_to_yuv(src[0], src[1], src[2],
&y0, &u0, &v0);
util_format_rgb_8unorm_to_yuv(src[4], src[5], src[6],
&y1, &u1, &v1);
 
u = (u0 + u1 + 1) >> 1;
v = (v0 + v1 + 1) >> 1;
 
value = u;
value |= y0 << 8;
value |= v << 16;
value |= y1 << 24;
 
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
 
*dst++ = value;
 
src += 8;
}
 
if (x < width) {
util_format_rgb_8unorm_to_yuv(src[0], src[1], src[2],
&y0, &u, &v);
y1 = 0;
 
value = u;
value |= y0 << 8;
value |= v << 16;
value |= y1 << 24;
 
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
 
*dst = value;
}
 
dst_row += dst_stride/sizeof(*dst_row);
src_row += src_stride/sizeof(*src_row);
}
}
 
 
void
util_format_uyvy_fetch_rgba_float(float *dst, const uint8_t *src,
unsigned i, unsigned j)
{
uint8_t y, u, v;
 
assert(i < 2);
assert(j < 1);
 
y = src[1 + i*2];
u = src[0];
v = src[2];
 
util_format_yuv_to_rgb_float(y, u, v, &dst[0], &dst[1], &dst[2]);
 
dst[3] = 1.0f;
}
 
 
void
util_format_yuyv_unpack_rgba_float(float *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
 
for (y = 0; y < height; y += 1) {
float *dst = dst_row;
const uint32_t *src = (const uint32_t *)src_row;
uint32_t value;
uint8_t y0, y1, u, v;
 
for (x = 0; x + 1 < width; x += 2) {
value = *src++;
 
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
 
y0 = (value >> 0) & 0xff;
u = (value >> 8) & 0xff;
y1 = (value >> 16) & 0xff;
v = (value >> 24) & 0xff;
 
util_format_yuv_to_rgb_float(y0, u, v, &dst[0], &dst[1], &dst[2]);
dst[3] = 1.0f; /* a */
dst += 4;
 
util_format_yuv_to_rgb_float(y1, u, v, &dst[0], &dst[1], &dst[2]);
dst[3] = 1.0f; /* a */
dst += 4;
}
 
if (x < width) {
value = *src;
 
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
 
y0 = (value >> 0) & 0xff;
u = (value >> 8) & 0xff;
y1 = (value >> 16) & 0xff;
v = (value >> 24) & 0xff;
 
util_format_yuv_to_rgb_float(y0, u, v, &dst[0], &dst[1], &dst[2]);
dst[3] = 1.0f; /* a */
}
 
src_row += src_stride/sizeof(*src_row);
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
 
void
util_format_yuyv_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
 
for (y = 0; y < height; y += 1) {
uint8_t *dst = dst_row;
const uint32_t *src = (const uint32_t *)src_row;
uint32_t value;
uint8_t y0, y1, u, v;
 
for (x = 0; x + 1 < width; x += 2) {
value = *src++;
 
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
 
y0 = (value >> 0) & 0xff;
u = (value >> 8) & 0xff;
y1 = (value >> 16) & 0xff;
v = (value >> 24) & 0xff;
 
util_format_yuv_to_rgb_8unorm(y0, u, v, &dst[0], &dst[1], &dst[2]);
dst[3] = 0xff; /* a */
dst += 4;
 
util_format_yuv_to_rgb_8unorm(y1, u, v, &dst[0], &dst[1], &dst[2]);
dst[3] = 0xff; /* a */
dst += 4;
}
 
if (x < width) {
value = *src;
 
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
 
y0 = (value >> 0) & 0xff;
u = (value >> 8) & 0xff;
y1 = (value >> 16) & 0xff;
v = (value >> 24) & 0xff;
 
util_format_yuv_to_rgb_8unorm(y0, u, v, &dst[0], &dst[1], &dst[2]);
dst[3] = 0xff; /* a */
}
 
src_row += src_stride/sizeof(*src_row);
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
 
void
util_format_yuyv_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
const float *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
 
for (y = 0; y < height; y += 1) {
const float *src = src_row;
uint32_t *dst = (uint32_t *)dst_row;
uint8_t y0, y1, u, v;
uint32_t value;
 
for (x = 0; x + 1 < width; x += 2) {
uint8_t y0, y1, u0, u1, v0, v1, u, v;
 
util_format_rgb_float_to_yuv(src[0], src[1], src[2],
&y0, &u0, &v0);
util_format_rgb_float_to_yuv(src[4], src[5], src[6],
&y1, &u1, &v1);
 
u = (u0 + u1 + 1) >> 1;
v = (v0 + v1 + 1) >> 1;
 
value = y0;
value |= u << 8;
value |= y1 << 16;
value |= v << 24;
 
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
 
*dst++ = value;
 
src += 8;
}
 
if (x < width) {
util_format_rgb_float_to_yuv(src[0], src[1], src[2],
&y0, &u, &v);
y1 = 0;
 
value = y0;
value |= u << 8;
value |= y1 << 16;
value |= v << 24;
 
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
 
*dst = value;
}
 
dst_row += dst_stride/sizeof(*dst_row);
src_row += src_stride/sizeof(*src_row);
}
}
 
 
void
util_format_yuyv_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
 
for (y = 0; y < height; y += 1) {
const uint8_t *src = src_row;
uint32_t *dst = (uint32_t *)dst_row;
uint8_t y0, y1, u, v;
uint32_t value;
 
for (x = 0; x + 1 < width; x += 2) {
uint8_t y0, y1, u0, u1, v0, v1, u, v;
 
util_format_rgb_8unorm_to_yuv(src[0], src[1], src[2],
&y0, &u0, &v0);
util_format_rgb_8unorm_to_yuv(src[4], src[5], src[6],
&y1, &u1, &v1);
 
u = (u0 + u1 + 1) >> 1;
v = (v0 + v1 + 1) >> 1;
 
value = y0;
value |= u << 8;
value |= y1 << 16;
value |= v << 24;
 
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
 
*dst++ = value;
 
src += 8;
}
 
if (x < width) {
util_format_rgb_8unorm_to_yuv(src[0], src[1], src[2],
&y0, &u, &v);
y1 = 0;
 
value = y0;
value |= u << 8;
value |= y1 << 16;
value |= v << 24;
 
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
 
*dst = value;
}
 
dst_row += dst_stride/sizeof(*dst_row);
src_row += src_stride/sizeof(*src_row);
}
}
 
 
void
util_format_yuyv_fetch_rgba_float(float *dst, const uint8_t *src,
unsigned i, unsigned j)
{
uint8_t y, u, v;
 
assert(i < 2);
assert(j < 1);
 
y = src[0 + i*2];
u = src[1];
v = src[3];
 
util_format_yuv_to_rgb_float(y, u, v, &dst[0], &dst[1], &dst[2]);
 
dst[3] = 1.0f;
}
 
/* XXX: Stubbed for now */
void
util_format_yv12_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height) {}
void
util_format_yv12_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height) {}
void
util_format_yv12_unpack_rgba_float(float *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height) {}
void
util_format_yv12_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
const float *src_row, unsigned src_stride,
unsigned width, unsigned height) {}
void
util_format_yv12_fetch_rgba_float(float *dst, const uint8_t *src,
unsigned i, unsigned j) {}
void
util_format_yv16_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height) {}
void
util_format_yv16_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height) {}
void
util_format_yv16_unpack_rgba_float(float *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height) {}
void
util_format_yv16_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
const float *src_row, unsigned src_stride,
unsigned width, unsigned height) {}
void
util_format_yv16_fetch_rgba_float(float *dst, const uint8_t *src,
unsigned i, unsigned j) {}
void
util_format_iyuv_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height) {}
void
util_format_iyuv_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height) {}
void
util_format_iyuv_unpack_rgba_float(float *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height) {}
void
util_format_iyuv_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
const float *src_row, unsigned src_stride,
unsigned width, unsigned height) {}
void
util_format_iyuv_fetch_rgba_float(float *dst, const uint8_t *src,
unsigned i, unsigned j) {}
void
util_format_nv12_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height) {}
void
util_format_nv12_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height) {}
void
util_format_nv12_unpack_rgba_float(float *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height) {}
void
util_format_nv12_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
const float *src_row, unsigned src_stride,
unsigned width, unsigned height) {}
void
util_format_nv12_fetch_rgba_float(float *dst, const uint8_t *src,
unsigned i, unsigned j) {}
void
util_format_nv21_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height) {}
void
util_format_nv21_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height) {}
void
util_format_nv21_unpack_rgba_float(float *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height) {}
void
util_format_nv21_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
const float *src_row, unsigned src_stride,
unsigned width, unsigned height) {}
void
util_format_nv21_fetch_rgba_float(float *dst, const uint8_t *src,
unsigned i, unsigned j) {}
 
void
util_format_r8g8_r8b8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height) {}
 
void
util_format_r8g8_r8b8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height) {}
 
void
util_format_r8g8_r8b8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
const float *src_row, unsigned src_stride,
unsigned width, unsigned height) {}
 
void
util_format_r8g8_r8b8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height) {}
 
void
util_format_r8g8_r8b8_unorm_fetch_rgba_float(float *dst, const uint8_t *src,
unsigned i, unsigned j) {}
 
void
util_format_g8r8_b8r8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height) {}
 
void
util_format_g8r8_b8r8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height) {}
 
void
util_format_g8r8_b8r8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
const float *src_row, unsigned src_stride,
unsigned width, unsigned height) {}
 
void
util_format_g8r8_b8r8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height) {}
 
void
util_format_g8r8_b8r8_unorm_fetch_rgba_float(float *dst, const uint8_t *src,
unsigned i, unsigned j) {}
/drivers/video/Gallium/auxiliary/util/u_format_yuv.h
0,0 → 1,364
/**************************************************************************
*
* Copyright 2010 VMware, Inc.
* 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 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
* THE COPYRIGHT HOLDERS, AUTHORS 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.
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
**************************************************************************/
 
 
/**
* @file
* YUV colorspace conversion.
*
* @author Brian Paul <brianp@vmware.com>
* @author Michal Krol <michal@vmware.com>
* @author Jose Fonseca <jfonseca@vmware.com>
*
* See also:
* - http://www.fourcc.org/fccyvrgb.php
* - http://msdn.microsoft.com/en-us/library/ms893078
* - http://en.wikipedia.org/wiki/YUV
*/
 
 
#ifndef U_FORMAT_YUV_H_
#define U_FORMAT_YUV_H_
 
 
#include "pipe/p_compiler.h"
#include "u_math.h"
 
 
/*
* TODO: Ensure we use consistent and right floating formulas, with enough
* precision in the coefficients.
*/
 
static INLINE void
util_format_rgb_float_to_yuv(float r, float g, float b,
uint8_t *y, uint8_t *u, uint8_t *v)
{
const float _r = CLAMP(r, 0.0f, 1.0f);
const float _g = CLAMP(g, 0.0f, 1.0f);
const float _b = CLAMP(b, 0.0f, 1.0f);
 
const float scale = 255.0f;
 
const int _y = scale * ( (0.257f * _r) + (0.504f * _g) + (0.098f * _b));
const int _u = scale * (-(0.148f * _r) - (0.291f * _g) + (0.439f * _b));
const int _v = scale * ( (0.439f * _r) - (0.368f * _g) - (0.071f * _b));
 
*y = _y + 16;
*u = _u + 128;
*v = _v + 128;
}
 
 
static INLINE void
util_format_yuv_to_rgb_float(uint8_t y, uint8_t u, uint8_t v,
float *r, float *g, float *b)
{
const int _y = y - 16;
const int _u = u - 128;
const int _v = v - 128;
 
const float y_factor = 255.0f / 219.0f;
 
const float scale = 1.0f / 255.0f;
 
*r = scale * (y_factor * _y + 1.596f * _v);
*g = scale * (y_factor * _y - 0.391f * _u - 0.813f * _v);
*b = scale * (y_factor * _y + 2.018f * _u );
}
 
 
static INLINE void
util_format_rgb_8unorm_to_yuv(uint8_t r, uint8_t g, uint8_t b,
uint8_t *y, uint8_t *u, uint8_t *v)
{
*y = (( 66 * r + 129 * g + 25 * b + 128) >> 8) + 16;
*u = (( -38 * r - 74 * g + 112 * b + 128) >> 8) + 128;
*v = (( 112 * r - 94 * g - 18 * b + 128) >> 8) + 128;
}
 
 
static INLINE void
util_format_yuv_to_rgb_8unorm(uint8_t y, uint8_t u, uint8_t v,
uint8_t *r, uint8_t *g, uint8_t *b)
{
const int _y = y - 16;
const int _u = u - 128;
const int _v = v - 128;
 
const int _r = (298 * _y + 409 * _v + 128) >> 8;
const int _g = (298 * _y - 100 * _u - 208 * _v + 128) >> 8;
const int _b = (298 * _y + 516 * _u + 128) >> 8;
 
*r = CLAMP(_r, 0, 255);
*g = CLAMP(_g, 0, 255);
*b = CLAMP(_b, 0, 255);
}
 
 
 
void
util_format_uyvy_unpack_rgba_float(float *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height);
 
void
util_format_uyvy_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height);
 
void
util_format_uyvy_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
const float *src_row, unsigned src_stride,
unsigned width, unsigned height);
 
void
util_format_uyvy_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height);
 
void
util_format_uyvy_fetch_rgba_float(float *dst, const uint8_t *src,
unsigned i, unsigned j);
 
void
util_format_yuyv_unpack_rgba_float(float *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height);
 
void
util_format_yuyv_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height);
 
void
util_format_yuyv_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
const float *src_row, unsigned src_stride,
unsigned width, unsigned height);
 
void
util_format_yuyv_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height);
 
void
util_format_yuyv_fetch_rgba_float(float *dst, const uint8_t *src,
unsigned i, unsigned j);
 
/* XXX: Stubbed for now */
void
util_format_yv12_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height);
void
util_format_yv12_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height);
void
util_format_yv12_unpack_rgba_float(float *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height);
void
util_format_yv12_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
const float *src_row, unsigned src_stride,
unsigned width, unsigned height);
void
util_format_yv12_fetch_rgba_float(float *dst, const uint8_t *src,
unsigned i, unsigned j);
void
util_format_yv16_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height);
void
util_format_yv16_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height);
void
util_format_yv16_unpack_rgba_float(float *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height);
void
util_format_yv16_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
const float *src_row, unsigned src_stride,
unsigned width, unsigned height);
void
util_format_yv16_fetch_rgba_float(float *dst, const uint8_t *src,
unsigned i, unsigned j);
void
util_format_iyuv_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height);
void
util_format_iyuv_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height);
void
util_format_iyuv_unpack_rgba_float(float *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height);
void
util_format_iyuv_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
const float *src_row, unsigned src_stride,
unsigned width, unsigned height);
void
util_format_iyuv_fetch_rgba_float(float *dst, const uint8_t *src,
unsigned i, unsigned j);
void
util_format_nv12_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height);
void
util_format_nv12_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height);
void
util_format_nv12_unpack_rgba_float(float *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height);
void
util_format_nv12_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
const float *src_row, unsigned src_stride,
unsigned width, unsigned height);
void
util_format_nv12_fetch_rgba_float(float *dst, const uint8_t *src,
unsigned i, unsigned j);
void
util_format_nv21_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height);
void
util_format_nv21_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height);
void
util_format_nv21_unpack_rgba_float(float *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height);
void
util_format_nv21_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
const float *src_row, unsigned src_stride,
unsigned width, unsigned height);
void
util_format_nv21_fetch_rgba_float(float *dst, const uint8_t *src,
unsigned i, unsigned j);
void
util_format_r8g8_b8g8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height);
 
void
util_format_r8g8_b8g8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height);
 
void
util_format_r8g8_b8g8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
const float *src_row, unsigned src_stride,
unsigned width, unsigned height);
 
void
util_format_r8g8_b8g8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height);
 
void
util_format_r8g8_b8g8_unorm_fetch_rgba_float(float *dst, const uint8_t *src,
unsigned i, unsigned j);
 
void
util_format_g8r8_g8b8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height);
 
void
util_format_g8r8_g8b8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height);
 
void
util_format_g8r8_g8b8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
const float *src_row, unsigned src_stride,
unsigned width, unsigned height);
 
void
util_format_g8r8_g8b8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height);
 
void
util_format_g8r8_g8b8_unorm_fetch_rgba_float(float *dst, const uint8_t *src,
unsigned i, unsigned j);
 
void
util_format_r8g8_r8b8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height);
 
void
util_format_r8g8_r8b8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height);
 
void
util_format_r8g8_r8b8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
const float *src_row, unsigned src_stride,
unsigned width, unsigned height);
 
void
util_format_r8g8_r8b8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height);
 
void
util_format_r8g8_r8b8_unorm_fetch_rgba_float(float *dst, const uint8_t *src,
unsigned i, unsigned j);
 
void
util_format_g8r8_b8r8_unorm_unpack_rgba_float(float *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height);
 
void
util_format_g8r8_b8r8_unorm_unpack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height);
 
void
util_format_g8r8_b8r8_unorm_pack_rgba_float(uint8_t *dst_row, unsigned dst_stride,
const float *src_row, unsigned src_stride,
unsigned width, unsigned height);
 
void
util_format_g8r8_b8r8_unorm_pack_rgba_8unorm(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height);
 
void
util_format_g8r8_b8r8_unorm_fetch_rgba_float(float *dst, const uint8_t *src,
unsigned i, unsigned j);
 
#endif /* U_FORMAT_YUV_H_ */
/drivers/video/Gallium/auxiliary/util/u_format_zs.c
0,0 → 1,973
/**************************************************************************
*
* Copyright 2010 VMware, Inc.
* 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 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
* THE COPYRIGHT HOLDERS, AUTHORS 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.
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
**************************************************************************/
 
 
#include "u_debug.h"
#include "u_math.h"
#include "u_format_zs.h"
 
 
/*
* z32_unorm conversion functions
*/
 
static INLINE uint16_t
z32_unorm_to_z16_unorm(uint32_t z)
{
/* z * 0xffff / 0xffffffff */
return z >> 16;
}
 
static INLINE uint32_t
z16_unorm_to_z32_unorm(uint16_t z)
{
/* z * 0xffffffff / 0xffff */
return (z << 16) | z;
}
 
static INLINE uint32_t
z32_unorm_to_z24_unorm(uint32_t z)
{
/* z * 0xffffff / 0xffffffff */
return z >> 8;
}
 
static INLINE uint32_t
z24_unorm_to_z32_unorm(uint32_t z)
{
/* z * 0xffffffff / 0xffffff */
return (z << 8) | (z >> 16);
}
 
 
/*
* z32_float conversion functions
*/
 
static INLINE uint16_t
z32_float_to_z16_unorm(float z)
{
const float scale = 0xffff;
return (uint16_t)(z * scale + 0.5f);
}
 
static INLINE float
z16_unorm_to_z32_float(uint16_t z)
{
const float scale = 1.0 / 0xffff;
return (float)(z * scale);
}
 
static INLINE uint32_t
z32_float_to_z24_unorm(float z)
{
const double scale = 0xffffff;
return (uint32_t)(z * scale) & 0xffffff;
}
 
static INLINE float
z24_unorm_to_z32_float(uint32_t z)
{
const double scale = 1.0 / 0xffffff;
return (float)(z * scale);
}
 
static INLINE uint32_t
z32_float_to_z32_unorm(float z)
{
const double scale = 0xffffffff;
return (uint32_t)(z * scale);
}
 
static INLINE float
z32_unorm_to_z32_float(uint32_t z)
{
const double scale = 1.0 / 0xffffffff;
return (float)(z * scale);
}
 
 
void
util_format_s8_uint_unpack_s_8uint(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned y;
for(y = 0; y < height; ++y) {
memcpy(dst_row, src_row, width);
src_row += src_stride/sizeof(*src_row);
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
void
util_format_s8_uint_pack_s_8uint(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned y;
for(y = 0; y < height; ++y) {
memcpy(dst_row, src_row, width);
src_row += src_stride/sizeof(*src_row);
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
void
util_format_z16_unorm_unpack_z_float(float *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; ++y) {
float *dst = dst_row;
const uint16_t *src = (const uint16_t *)src_row;
for(x = 0; x < width; ++x) {
uint16_t value = *src++;
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap16(value);
#endif
*dst++ = z16_unorm_to_z32_float(value);
}
src_row += src_stride/sizeof(*src_row);
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
void
util_format_z16_unorm_pack_z_float(uint8_t *dst_row, unsigned dst_stride,
const float *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; ++y) {
const float *src = src_row;
uint16_t *dst = (uint16_t *)dst_row;
for(x = 0; x < width; ++x) {
uint16_t value;
value = z32_float_to_z16_unorm(*src++);
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap16(value);
#endif
*dst++ = value;
}
dst_row += dst_stride/sizeof(*dst_row);
src_row += src_stride/sizeof(*src_row);
}
}
 
void
util_format_z16_unorm_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; ++y) {
uint32_t *dst = dst_row;
const uint16_t *src = (const uint16_t *)src_row;
for(x = 0; x < width; ++x) {
uint16_t value = *src++;
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap16(value);
#endif
*dst++ = z16_unorm_to_z32_unorm(value);
}
src_row += src_stride/sizeof(*src_row);
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
void
util_format_z16_unorm_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride,
const uint32_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; ++y) {
const uint32_t *src = src_row;
uint16_t *dst = (uint16_t *)dst_row;
for(x = 0; x < width; ++x) {
uint16_t value;
value = z32_unorm_to_z16_unorm(*src++);
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap16(value);
#endif
*dst++ = value;
}
dst_row += dst_stride/sizeof(*dst_row);
src_row += src_stride/sizeof(*src_row);
}
}
 
void
util_format_z32_unorm_unpack_z_float(float *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; ++y) {
float *dst = dst_row;
const uint32_t *src = (const uint32_t *)src_row;
for(x = 0; x < width; ++x) {
uint32_t value = *src++;
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
*dst++ = z32_unorm_to_z32_float(value);
}
src_row += src_stride/sizeof(*src_row);
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
void
util_format_z32_unorm_pack_z_float(uint8_t *dst_row, unsigned dst_stride,
const float *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; ++y) {
const float *src = src_row;
uint32_t *dst = (uint32_t *)dst_row;
for(x = 0; x < width; ++x) {
uint32_t value;
value = z32_float_to_z32_unorm(*src++);
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
*dst++ = value;
}
dst_row += dst_stride/sizeof(*dst_row);
src_row += src_stride/sizeof(*src_row);
}
}
 
void
util_format_z32_unorm_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned y;
for(y = 0; y < height; ++y) {
memcpy(dst_row, src_row, width * 4);
src_row += src_stride/sizeof(*src_row);
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
void
util_format_z32_unorm_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride,
const uint32_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned y;
for(y = 0; y < height; ++y) {
memcpy(dst_row, src_row, width * 4);
src_row += src_stride/sizeof(*src_row);
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
void
util_format_z32_float_unpack_z_float(float *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned y;
for(y = 0; y < height; ++y) {
memcpy(dst_row, src_row, width * 4);
src_row += src_stride/sizeof(*src_row);
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
void
util_format_z32_float_pack_z_float(uint8_t *dst_row, unsigned dst_stride,
const float *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned y;
for(y = 0; y < height; ++y) {
memcpy(dst_row, src_row, width * 4);
src_row += src_stride/sizeof(*src_row);
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
void
util_format_z32_float_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; ++y) {
uint32_t *dst = dst_row;
const float *src = (const float *)src_row;
for(x = 0; x < width; ++x) {
*dst++ = z32_float_to_z32_unorm(*src++);
}
src_row += src_stride/sizeof(*src_row);
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
void
util_format_z32_float_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride,
const uint32_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; ++y) {
const uint32_t *src = src_row;
float *dst = (float *)dst_row;
for(x = 0; x < width; ++x) {
*dst++ = z32_unorm_to_z32_float(*src++);
}
dst_row += dst_stride/sizeof(*dst_row);
src_row += src_stride/sizeof(*src_row);
}
}
 
void
util_format_z24_unorm_s8_uint_unpack_z_float(float *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; ++y) {
float *dst = dst_row;
const uint32_t *src = (const uint32_t *)src_row;
for(x = 0; x < width; ++x) {
uint32_t value = *src++;
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
*dst++ = z24_unorm_to_z32_float(value & 0xffffff);
}
src_row += src_stride/sizeof(*src_row);
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
void
util_format_z24_unorm_s8_uint_pack_z_float(uint8_t *dst_row, unsigned dst_stride,
const float *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; ++y) {
const float *src = src_row;
uint32_t *dst = (uint32_t *)dst_row;
for(x = 0; x < width; ++x) {
uint32_t value = *dst;
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
value &= 0xff000000;
value |= z32_float_to_z24_unorm(*src++);
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
*dst++ = value;
}
dst_row += dst_stride/sizeof(*dst_row);
src_row += src_stride/sizeof(*src_row);
}
}
 
void
util_format_z24_unorm_s8_uint_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; ++y) {
uint32_t *dst = dst_row;
const uint32_t *src = (const uint32_t *)src_row;
for(x = 0; x < width; ++x) {
uint32_t value = *src++;
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
*dst++ = z24_unorm_to_z32_unorm(value & 0xffffff);
}
src_row += src_stride/sizeof(*src_row);
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
void
util_format_z24_unorm_s8_uint_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride,
const uint32_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; ++y) {
const uint32_t *src = src_row;
uint32_t *dst = (uint32_t *)dst_row;
for(x = 0; x < width; ++x) {
uint32_t value= *dst;
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
value &= 0xff000000;
value |= z32_unorm_to_z24_unorm(*src++);
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
*dst++ = value;
}
dst_row += dst_stride/sizeof(*dst_row);
src_row += src_stride/sizeof(*src_row);
}
}
 
void
util_format_z24_unorm_s8_uint_unpack_s_8uint(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; ++y) {
uint8_t *dst = dst_row;
const uint32_t *src = (const uint32_t *)src_row;
for(x = 0; x < width; ++x) {
uint32_t value = *src++;
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
*dst++ = value >> 24;
}
src_row += src_stride/sizeof(*src_row);
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
void
util_format_z24_unorm_s8_uint_pack_s_8uint(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; ++y) {
const uint8_t *src = src_row;
uint32_t *dst = (uint32_t *)dst_row;
for(x = 0; x < width; ++x) {
uint32_t value = *dst;
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
value &= 0x00ffffff;
value |= *src++ << 24;
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
*dst++ = value;
}
dst_row += dst_stride/sizeof(*dst_row);
src_row += src_stride/sizeof(*src_row);
}
}
 
void
util_format_s8_uint_z24_unorm_unpack_z_float(float *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; ++y) {
float *dst = dst_row;
const uint32_t *src = (const uint32_t *)src_row;
for(x = 0; x < width; ++x) {
uint32_t value = *src++;
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
*dst++ = z24_unorm_to_z32_float(value >> 8);
}
src_row += src_stride/sizeof(*src_row);
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
void
util_format_s8_uint_z24_unorm_pack_z_float(uint8_t *dst_row, unsigned dst_stride,
const float *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; ++y) {
const float *src = src_row;
uint32_t *dst = (uint32_t *)dst_row;
for(x = 0; x < width; ++x) {
uint32_t value = *dst;
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
value &= 0x000000ff;
value |= z32_float_to_z24_unorm(*src++) << 8;
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
*dst++ = value;
}
dst_row += dst_stride/sizeof(*dst_row);
src_row += src_stride/sizeof(*src_row);
}
}
 
void
util_format_s8_uint_z24_unorm_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; ++y) {
uint32_t *dst = dst_row;
const uint32_t *src = (const uint32_t *)src_row;
for(x = 0; x < width; ++x) {
uint32_t value = *src++;
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
*dst++ = z24_unorm_to_z32_unorm(value >> 8);
}
src_row += src_stride/sizeof(*src_row);
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
void
util_format_s8_uint_z24_unorm_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride,
const uint32_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; ++y) {
const uint32_t *src = src_row;
uint32_t *dst = (uint32_t *)dst_row;
for(x = 0; x < width; ++x) {
uint32_t value = *dst;
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
value &= 0x000000ff;
value |= *src++ & 0xffffff00;
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
*dst++ = value;
}
dst_row += dst_stride/sizeof(*dst_row);
src_row += src_stride/sizeof(*src_row);
}
}
 
void
util_format_s8_uint_z24_unorm_unpack_s_8uint(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; ++y) {
uint8_t *dst = dst_row;
const uint32_t *src = (const uint32_t *)src_row;
for(x = 0; x < width; ++x) {
uint32_t value = *src++;
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
*dst++ = value & 0xff;
}
src_row += src_stride/sizeof(*src_row);
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
void
util_format_s8_uint_z24_unorm_pack_s_8uint(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; ++y) {
const uint8_t *src = src_row;
uint32_t *dst = (uint32_t *)dst_row;
for(x = 0; x < width; ++x) {
uint32_t value = *dst;
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
value &= 0xffffff00;
value |= *src++;
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
*dst++ = value;
}
dst_row += dst_stride/sizeof(*dst_row);
src_row += src_stride/sizeof(*src_row);
}
}
 
void
util_format_z24x8_unorm_unpack_z_float(float *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; ++y) {
float *dst = dst_row;
const uint32_t *src = (const uint32_t *)src_row;
for(x = 0; x < width; ++x) {
uint32_t value = *src++;
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
*dst++ = z24_unorm_to_z32_float(value & 0xffffff);
}
src_row += src_stride/sizeof(*src_row);
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
void
util_format_z24x8_unorm_pack_z_float(uint8_t *dst_row, unsigned dst_stride,
const float *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; ++y) {
const float *src = src_row;
uint32_t *dst = (uint32_t *)dst_row;
for(x = 0; x < width; ++x) {
uint32_t value;
value = z32_float_to_z24_unorm(*src++);
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
*dst++ = value;
}
dst_row += dst_stride/sizeof(*dst_row);
src_row += src_stride/sizeof(*src_row);
}
}
 
void
util_format_z24x8_unorm_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; ++y) {
uint32_t *dst = dst_row;
const uint32_t *src = (const uint32_t *)src_row;
for(x = 0; x < width; ++x) {
uint32_t value = *src++;
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
*dst++ = z24_unorm_to_z32_unorm(value & 0xffffff);
}
src_row += src_stride/sizeof(*src_row);
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
void
util_format_z24x8_unorm_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride,
const uint32_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; ++y) {
const uint32_t *src = src_row;
uint32_t *dst = (uint32_t *)dst_row;
for(x = 0; x < width; ++x) {
uint32_t value;
value = z32_unorm_to_z24_unorm(*src++);
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
*dst++ = value;
}
dst_row += dst_stride/sizeof(*dst_row);
src_row += src_stride/sizeof(*src_row);
}
}
 
void
util_format_x8z24_unorm_unpack_z_float(float *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; ++y) {
float *dst = dst_row;
const uint32_t *src = (uint32_t *)src_row;
for(x = 0; x < width; ++x) {
uint32_t value = *src++;
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
*dst++ = z24_unorm_to_z32_float(value >> 8);
}
src_row += src_stride/sizeof(*src_row);
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
void
util_format_x8z24_unorm_pack_z_float(uint8_t *dst_row, unsigned dst_stride,
const float *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; ++y) {
const float *src = src_row;
uint32_t *dst = (uint32_t *)dst_row;
for(x = 0; x < width; ++x) {
uint32_t value;
value = z32_float_to_z24_unorm(*src++) << 8;
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
*dst++ = value;
}
dst_row += dst_stride/sizeof(*dst_row);
src_row += src_stride/sizeof(*src_row);
}
}
 
void
util_format_x8z24_unorm_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; ++y) {
uint32_t *dst = dst_row;
const uint32_t *src = (const uint32_t *)src_row;
for(x = 0; x < width; ++x) {
uint32_t value = *src++;
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
*dst++ = z24_unorm_to_z32_unorm(value >> 8);
}
src_row += src_stride/sizeof(*src_row);
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
void
util_format_x8z24_unorm_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride,
const uint32_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; ++y) {
const uint32_t *src = src_row;
uint32_t *dst = (uint32_t *)dst_row;
for(x = 0; x < width; ++x) {
uint32_t value;
value = z32_unorm_to_z24_unorm(*src++) << 8;
#ifdef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
*dst++ = value;
}
dst_row += dst_stride/sizeof(*dst_row);
src_row += src_stride/sizeof(*src_row);
}
}
 
void
util_format_z32_float_s8x24_uint_unpack_z_float(float *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; ++y) {
float *dst = dst_row;
const float *src = (const float *)src_row;
for(x = 0; x < width; ++x) {
*dst = *src;
src += 2;
dst += 1;
}
src_row += src_stride/sizeof(*src_row);
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
void
util_format_z32_float_s8x24_uint_pack_z_float(uint8_t *dst_row, unsigned dst_stride,
const float *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; ++y) {
const float *src = src_row;
float *dst = (float *)dst_row;
for(x = 0; x < width; ++x) {
*dst = *src;
src += 1;
dst += 2;
}
dst_row += dst_stride/sizeof(*dst_row);
src_row += src_stride/sizeof(*src_row);
}
}
 
void
util_format_z32_float_s8x24_uint_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; ++y) {
uint32_t *dst = dst_row;
const float *src = (const float *)src_row;
for(x = 0; x < width; ++x) {
*dst = z32_float_to_z32_unorm(*src);
src += 2;
dst += 1;
}
src_row += src_stride/sizeof(*src_row);
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
void
util_format_z32_float_s8x24_uint_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride,
const uint32_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; ++y) {
const uint32_t *src = src_row;
float *dst = (float *)dst_row;
for(x = 0; x < width; ++x) {
*dst++ = z32_unorm_to_z32_float(*src++);
}
dst_row += dst_stride/sizeof(*dst_row);
src_row += src_stride/sizeof(*src_row);
}
}
 
void
util_format_z32_float_s8x24_uint_unpack_s_8uint(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; ++y) {
uint8_t *dst = dst_row;
const uint8_t *src = src_row + 4;
for(x = 0; x < width; ++x) {
*dst = *src;
src += 8;
dst += 1;
}
src_row += src_stride/sizeof(*src_row);
dst_row += dst_stride/sizeof(*dst_row);
}
}
 
void
util_format_z32_float_s8x24_uint_pack_s_8uint(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
unsigned x, y;
for(y = 0; y < height; ++y) {
const uint8_t *src = src_row;
uint8_t *dst = dst_row + 4;
for(x = 0; x < width; ++x) {
*dst = *src;
src += 1;
dst += 8;
}
dst_row += dst_stride/sizeof(*dst_row);
src_row += src_stride/sizeof(*src_row);
}
}
 
 
void
util_format_x24s8_uint_unpack_s_8uint(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
util_format_z24_unorm_s8_uint_unpack_s_8uint(dst_row, dst_stride,
src_row, src_stride,
width, height);
}
 
void
util_format_x24s8_uint_pack_s_8uint(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
util_format_z24_unorm_s8_uint_pack_s_8uint(dst_row, dst_stride,
src_row, src_stride,
width, height);
}
 
void
util_format_s8x24_uint_unpack_s_8uint(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
util_format_s8_uint_z24_unorm_unpack_s_8uint(dst_row, dst_stride,
src_row, src_stride,
width, height);
}
 
void
util_format_s8x24_uint_pack_s_8uint(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height)
{
util_format_s8_uint_z24_unorm_pack_s_8uint(dst_row, dst_stride,
src_row, src_stride,
width, height);
}
 
void
util_format_x32_s8x24_uint_unpack_s_8uint(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
util_format_z32_float_s8x24_uint_unpack_s_8uint(dst_row, dst_stride,
src_row, src_stride,
width, height);
 
}
 
void
util_format_x32_s8x24_uint_pack_s_8uint(uint8_t *dst_row, unsigned dst_stride,
const uint8_t *src_row, unsigned src_stride,
unsigned width, unsigned height)
{
util_format_z32_float_s8x24_uint_pack_s_8uint(dst_row, dst_stride,
src_row, src_stride,
width, height);
}
/drivers/video/Gallium/auxiliary/util/u_format_zs.h
0,0 → 1,212
/**************************************************************************
*
* Copyright 2010 VMware, Inc.
* 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 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
* THE COPYRIGHT HOLDERS, AUTHORS 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.
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
**************************************************************************/
 
 
#ifndef U_FORMAT_ZS_H_
#define U_FORMAT_ZS_H_
 
 
#include "pipe/p_compiler.h"
 
 
void
util_format_s8_uint_unpack_s_8uint(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
 
void
util_format_s8_uint_pack_s_8uint(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
 
void
util_format_z16_unorm_unpack_z_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
 
void
util_format_z16_unorm_pack_z_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height);
 
 
void
util_format_z16_unorm_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
 
void
util_format_z16_unorm_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride, const uint32_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
 
void
util_format_z32_unorm_unpack_z_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
 
void
util_format_z32_unorm_pack_z_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height);
 
 
void
util_format_z32_unorm_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
 
void
util_format_z32_unorm_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride, const uint32_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
 
void
util_format_z32_float_unpack_z_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
 
void
util_format_z32_float_pack_z_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height);
 
 
void
util_format_z32_float_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
 
void
util_format_z32_float_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride, const uint32_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
 
void
util_format_z24_unorm_s8_uint_unpack_z_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
 
void
util_format_z24_unorm_s8_uint_pack_z_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height);
 
 
void
util_format_z24_unorm_s8_uint_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
 
void
util_format_z24_unorm_s8_uint_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride, const uint32_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
 
void
util_format_z24_unorm_s8_uint_unpack_s_8uint(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
 
void
util_format_z24_unorm_s8_uint_pack_s_8uint(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
 
void
util_format_s8_uint_z24_unorm_unpack_z_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
 
void
util_format_s8_uint_z24_unorm_pack_z_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height);
 
 
void
util_format_s8_uint_z24_unorm_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
 
void
util_format_s8_uint_z24_unorm_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride, const uint32_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
 
void
util_format_s8_uint_z24_unorm_unpack_s_8uint(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
 
void
util_format_s8_uint_z24_unorm_pack_s_8uint(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
 
void
util_format_z24x8_unorm_unpack_z_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
 
void
util_format_z24x8_unorm_pack_z_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height);
 
 
void
util_format_z24x8_unorm_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
 
void
util_format_z24x8_unorm_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride, const uint32_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
 
void
util_format_x8z24_unorm_unpack_z_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
 
void
util_format_x8z24_unorm_pack_z_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height);
 
 
void
util_format_x8z24_unorm_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
 
void
util_format_x8z24_unorm_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride, const uint32_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
 
void
util_format_z32_float_s8x24_uint_unpack_z_float(float *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
 
void
util_format_z32_float_s8x24_uint_pack_z_float(uint8_t *dst_row, unsigned dst_stride, const float *src_row, unsigned src_stride, unsigned width, unsigned height);
 
 
void
util_format_z32_float_s8x24_uint_unpack_z_32unorm(uint32_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
 
void
util_format_z32_float_s8x24_uint_pack_z_32unorm(uint8_t *dst_row, unsigned dst_stride, const uint32_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
 
void
util_format_z32_float_s8x24_uint_unpack_s_8uint(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
 
void
util_format_z32_float_s8x24_uint_pack_s_8uint(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_x24s8_uint_unpack_s_8uint(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_x24s8_uint_pack_s_8uint(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_s8x24_uint_unpack_s_8uint(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_s8x24_uint_pack_s_8uint(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_x32_s8x24_uint_unpack_s_8uint(uint8_t *dst_row, unsigned dst_stride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
 
void
util_format_x32_s8x24_uint_pack_s_8uint(uint8_t *dst_row, unsigned dst_sride, const uint8_t *src_row, unsigned src_stride, unsigned width, unsigned height);
#endif /* U_FORMAT_ZS_H_ */
/drivers/video/Gallium/auxiliary/util/u_framebuffer.c
0,0 → 1,148
/**************************************************************************
*
* Copyright 2009-2010 VMware, Inc. 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 VMWARE 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
* Framebuffer utility functions.
*
* @author Brian Paul
*/
 
 
#include "pipe/p_screen.h"
#include "pipe/p_state.h"
#include "pipe/p_defines.h"
#include "util/u_inlines.h"
 
#include "util/u_memory.h"
#include "util/u_framebuffer.h"
 
 
/**
* Compare pipe_framebuffer_state objects.
* \return TRUE if same, FALSE if different
*/
boolean
util_framebuffer_state_equal(const struct pipe_framebuffer_state *dst,
const struct pipe_framebuffer_state *src)
{
unsigned i;
 
if (dst->width != src->width ||
dst->height != src->height)
return FALSE;
 
for (i = 0; i < Elements(src->cbufs); i++) {
if (dst->cbufs[i] != src->cbufs[i]) {
return FALSE;
}
}
 
if (dst->nr_cbufs != src->nr_cbufs) {
return FALSE;
}
 
if (dst->zsbuf != src->zsbuf) {
return FALSE;
}
 
return TRUE;
}
 
 
/**
* Copy framebuffer state from src to dst, updating refcounts.
*/
void
util_copy_framebuffer_state(struct pipe_framebuffer_state *dst,
const struct pipe_framebuffer_state *src)
{
unsigned i;
 
dst->width = src->width;
dst->height = src->height;
 
for (i = 0; i < src->nr_cbufs; i++)
pipe_surface_reference(&dst->cbufs[i], src->cbufs[i]);
 
for (i = src->nr_cbufs; i < dst->nr_cbufs; i++)
pipe_surface_reference(&dst->cbufs[i], NULL);
 
dst->nr_cbufs = src->nr_cbufs;
 
pipe_surface_reference(&dst->zsbuf, src->zsbuf);
}
 
 
void
util_unreference_framebuffer_state(struct pipe_framebuffer_state *fb)
{
unsigned i;
 
for (i = 0; i < fb->nr_cbufs; i++) {
pipe_surface_reference(&fb->cbufs[i], NULL);
}
 
pipe_surface_reference(&fb->zsbuf, NULL);
 
fb->width = fb->height = 0;
fb->nr_cbufs = 0;
}
 
 
/* Where multiple sizes are allowed for framebuffer surfaces, find the
* minimum width and height of all bound surfaces.
*/
boolean
util_framebuffer_min_size(const struct pipe_framebuffer_state *fb,
unsigned *width,
unsigned *height)
{
unsigned w = ~0;
unsigned h = ~0;
unsigned i;
 
for (i = 0; i < fb->nr_cbufs; i++) {
w = MIN2(w, fb->cbufs[i]->width);
h = MIN2(h, fb->cbufs[i]->height);
}
 
if (fb->zsbuf) {
w = MIN2(w, fb->zsbuf->width);
h = MIN2(h, fb->zsbuf->height);
}
 
if (w == ~0) {
*width = 0;
*height = 0;
return FALSE;
}
else {
*width = w;
*height = h;
return TRUE;
}
}
/drivers/video/Gallium/auxiliary/util/u_framebuffer.h
0,0 → 1,62
/**************************************************************************
*
* Copyright 2009-2010 VMware, Inc. 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 VMWARE 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.
*
**************************************************************************/
 
 
#ifndef U_FRAMEBUFFER_H
#define U_FRAMEBUFFER_H
 
 
#include "pipe/p_compiler.h"
#include "pipe/p_state.h"
 
 
#ifdef __cplusplus
extern "C" {
#endif
 
extern boolean
util_framebuffer_state_equal(const struct pipe_framebuffer_state *dst,
const struct pipe_framebuffer_state *src);
 
extern void
util_copy_framebuffer_state(struct pipe_framebuffer_state *dst,
const struct pipe_framebuffer_state *src);
 
 
extern void
util_unreference_framebuffer_state(struct pipe_framebuffer_state *fb);
 
 
extern boolean
util_framebuffer_min_size(const struct pipe_framebuffer_state *fb,
unsigned *width,
unsigned *height);
 
#ifdef __cplusplus
}
#endif
 
#endif /* U_FRAMEBUFFER_H */
/drivers/video/Gallium/auxiliary/util/u_gen_mipmap.c
0,0 → 1,1703
/**************************************************************************
*
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
* Copyright 2008 VMware, Inc. 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
* Mipmap generation utility
*
* @author Brian Paul
*/
 
 
#include "pipe/p_context.h"
#include "util/u_debug.h"
#include "pipe/p_defines.h"
#include "util/u_inlines.h"
#include "pipe/p_shader_tokens.h"
#include "pipe/p_state.h"
 
#include "util/u_format.h"
#include "util/u_memory.h"
#include "util/u_draw_quad.h"
#include "util/u_gen_mipmap.h"
#include "util/u_simple_shaders.h"
#include "util/u_math.h"
#include "util/u_texture.h"
#include "util/u_half.h"
#include "util/u_surface.h"
 
#include "cso_cache/cso_context.h"
 
 
struct gen_mipmap_state
{
struct pipe_context *pipe;
struct cso_context *cso;
 
struct pipe_blend_state blend_keep_color, blend_write_color;
struct pipe_depth_stencil_alpha_state dsa_keep_depth, dsa_write_depth;
struct pipe_rasterizer_state rasterizer;
struct pipe_sampler_state sampler;
struct pipe_vertex_element velem[2];
 
void *vs;
 
/** Not all are used, but simplifies code */
void *fs_color[TGSI_TEXTURE_COUNT];
void *fs_depth[TGSI_TEXTURE_COUNT];
 
struct pipe_resource *vbuf; /**< quad vertices */
unsigned vbuf_slot;
 
float vertices[4][2][4]; /**< vertex/texcoords for quad */
};
 
 
 
enum dtype
{
DTYPE_UBYTE,
DTYPE_UBYTE_3_3_2,
DTYPE_USHORT,
DTYPE_USHORT_4_4_4_4,
DTYPE_USHORT_5_6_5,
DTYPE_USHORT_1_5_5_5_REV,
DTYPE_UINT,
DTYPE_FLOAT,
DTYPE_HALF_FLOAT
};
 
 
typedef uint16_t half_float;
 
 
/**
* \name Support macros for do_row and do_row_3d
*
* The macro madness is here for two reasons. First, it compacts the code
* slightly. Second, it makes it much easier to adjust the specifics of the
* filter to tune the rounding characteristics.
*/
/*@{*/
#define DECLARE_ROW_POINTERS(t, e) \
const t(*rowA)[e] = (const t(*)[e]) srcRowA; \
const t(*rowB)[e] = (const t(*)[e]) srcRowB; \
const t(*rowC)[e] = (const t(*)[e]) srcRowC; \
const t(*rowD)[e] = (const t(*)[e]) srcRowD; \
t(*dst)[e] = (t(*)[e]) dstRow
 
#define DECLARE_ROW_POINTERS0(t) \
const t *rowA = (const t *) srcRowA; \
const t *rowB = (const t *) srcRowB; \
const t *rowC = (const t *) srcRowC; \
const t *rowD = (const t *) srcRowD; \
t *dst = (t *) dstRow
 
#define FILTER_SUM_3D(Aj, Ak, Bj, Bk, Cj, Ck, Dj, Dk) \
((unsigned) Aj + (unsigned) Ak \
+ (unsigned) Bj + (unsigned) Bk \
+ (unsigned) Cj + (unsigned) Ck \
+ (unsigned) Dj + (unsigned) Dk \
+ 4) >> 3
 
#define FILTER_3D(e) \
do { \
dst[i][e] = FILTER_SUM_3D(rowA[j][e], rowA[k][e], \
rowB[j][e], rowB[k][e], \
rowC[j][e], rowC[k][e], \
rowD[j][e], rowD[k][e]); \
} while(0)
 
#define FILTER_F_3D(e) \
do { \
dst[i][e] = (rowA[j][e] + rowA[k][e] \
+ rowB[j][e] + rowB[k][e] \
+ rowC[j][e] + rowC[k][e] \
+ rowD[j][e] + rowD[k][e]) * 0.125F; \
} while(0)
 
#define FILTER_HF_3D(e) \
do { \
const float aj = util_half_to_float(rowA[j][e]); \
const float ak = util_half_to_float(rowA[k][e]); \
const float bj = util_half_to_float(rowB[j][e]); \
const float bk = util_half_to_float(rowB[k][e]); \
const float cj = util_half_to_float(rowC[j][e]); \
const float ck = util_half_to_float(rowC[k][e]); \
const float dj = util_half_to_float(rowD[j][e]); \
const float dk = util_half_to_float(rowD[k][e]); \
dst[i][e] = util_float_to_half((aj + ak + bj + bk + cj + ck + dj + dk) \
* 0.125F); \
} while(0)
/*@}*/
 
 
/**
* Average together two rows of a source image to produce a single new
* row in the dest image. It's legal for the two source rows to point
* to the same data. The source width must be equal to either the
* dest width or two times the dest width.
* \param datatype GL_UNSIGNED_BYTE, GL_UNSIGNED_SHORT, GL_FLOAT, etc.
* \param comps number of components per pixel (1..4)
*/
static void
do_row(enum dtype datatype, uint comps, int srcWidth,
const void *srcRowA, const void *srcRowB,
int dstWidth, void *dstRow)
{
const uint k0 = (srcWidth == dstWidth) ? 0 : 1;
const uint colStride = (srcWidth == dstWidth) ? 1 : 2;
 
assert(comps >= 1);
assert(comps <= 4);
 
/* This assertion is no longer valid with non-power-of-2 textures
assert(srcWidth == dstWidth || srcWidth == 2 * dstWidth);
*/
 
if (datatype == DTYPE_UBYTE && comps == 4) {
uint i, j, k;
const ubyte(*rowA)[4] = (const ubyte(*)[4]) srcRowA;
const ubyte(*rowB)[4] = (const ubyte(*)[4]) srcRowB;
ubyte(*dst)[4] = (ubyte(*)[4]) dstRow;
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4;
}
}
else if (datatype == DTYPE_UBYTE && comps == 3) {
uint i, j, k;
const ubyte(*rowA)[3] = (const ubyte(*)[3]) srcRowA;
const ubyte(*rowB)[3] = (const ubyte(*)[3]) srcRowB;
ubyte(*dst)[3] = (ubyte(*)[3]) dstRow;
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
}
}
else if (datatype == DTYPE_UBYTE && comps == 2) {
uint i, j, k;
const ubyte(*rowA)[2] = (const ubyte(*)[2]) srcRowA;
const ubyte(*rowB)[2] = (const ubyte(*)[2]) srcRowB;
ubyte(*dst)[2] = (ubyte(*)[2]) dstRow;
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) >> 2;
dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) >> 2;
}
}
else if (datatype == DTYPE_UBYTE && comps == 1) {
uint i, j, k;
const ubyte *rowA = (const ubyte *) srcRowA;
const ubyte *rowB = (const ubyte *) srcRowB;
ubyte *dst = (ubyte *) dstRow;
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) >> 2;
}
}
 
else if (datatype == DTYPE_USHORT && comps == 4) {
uint i, j, k;
const ushort(*rowA)[4] = (const ushort(*)[4]) srcRowA;
const ushort(*rowB)[4] = (const ushort(*)[4]) srcRowB;
ushort(*dst)[4] = (ushort(*)[4]) dstRow;
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
dst[i][3] = (rowA[j][3] + rowA[k][3] + rowB[j][3] + rowB[k][3]) / 4;
}
}
else if (datatype == DTYPE_USHORT && comps == 3) {
uint i, j, k;
const ushort(*rowA)[3] = (const ushort(*)[3]) srcRowA;
const ushort(*rowB)[3] = (const ushort(*)[3]) srcRowB;
ushort(*dst)[3] = (ushort(*)[3]) dstRow;
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
dst[i][2] = (rowA[j][2] + rowA[k][2] + rowB[j][2] + rowB[k][2]) / 4;
}
}
else if (datatype == DTYPE_USHORT && comps == 2) {
uint i, j, k;
const ushort(*rowA)[2] = (const ushort(*)[2]) srcRowA;
const ushort(*rowB)[2] = (const ushort(*)[2]) srcRowB;
ushort(*dst)[2] = (ushort(*)[2]) dstRow;
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
dst[i][0] = (rowA[j][0] + rowA[k][0] + rowB[j][0] + rowB[k][0]) / 4;
dst[i][1] = (rowA[j][1] + rowA[k][1] + rowB[j][1] + rowB[k][1]) / 4;
}
}
else if (datatype == DTYPE_USHORT && comps == 1) {
uint i, j, k;
const ushort *rowA = (const ushort *) srcRowA;
const ushort *rowB = (const ushort *) srcRowB;
ushort *dst = (ushort *) dstRow;
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) / 4;
}
}
 
else if (datatype == DTYPE_FLOAT && comps == 4) {
uint i, j, k;
const float(*rowA)[4] = (const float(*)[4]) srcRowA;
const float(*rowB)[4] = (const float(*)[4]) srcRowB;
float(*dst)[4] = (float(*)[4]) dstRow;
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
dst[i][0] = (rowA[j][0] + rowA[k][0] +
rowB[j][0] + rowB[k][0]) * 0.25F;
dst[i][1] = (rowA[j][1] + rowA[k][1] +
rowB[j][1] + rowB[k][1]) * 0.25F;
dst[i][2] = (rowA[j][2] + rowA[k][2] +
rowB[j][2] + rowB[k][2]) * 0.25F;
dst[i][3] = (rowA[j][3] + rowA[k][3] +
rowB[j][3] + rowB[k][3]) * 0.25F;
}
}
else if (datatype == DTYPE_FLOAT && comps == 3) {
uint i, j, k;
const float(*rowA)[3] = (const float(*)[3]) srcRowA;
const float(*rowB)[3] = (const float(*)[3]) srcRowB;
float(*dst)[3] = (float(*)[3]) dstRow;
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
dst[i][0] = (rowA[j][0] + rowA[k][0] +
rowB[j][0] + rowB[k][0]) * 0.25F;
dst[i][1] = (rowA[j][1] + rowA[k][1] +
rowB[j][1] + rowB[k][1]) * 0.25F;
dst[i][2] = (rowA[j][2] + rowA[k][2] +
rowB[j][2] + rowB[k][2]) * 0.25F;
}
}
else if (datatype == DTYPE_FLOAT && comps == 2) {
uint i, j, k;
const float(*rowA)[2] = (const float(*)[2]) srcRowA;
const float(*rowB)[2] = (const float(*)[2]) srcRowB;
float(*dst)[2] = (float(*)[2]) dstRow;
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
dst[i][0] = (rowA[j][0] + rowA[k][0] +
rowB[j][0] + rowB[k][0]) * 0.25F;
dst[i][1] = (rowA[j][1] + rowA[k][1] +
rowB[j][1] + rowB[k][1]) * 0.25F;
}
}
else if (datatype == DTYPE_FLOAT && comps == 1) {
uint i, j, k;
const float *rowA = (const float *) srcRowA;
const float *rowB = (const float *) srcRowB;
float *dst = (float *) dstRow;
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
dst[i] = (rowA[j] + rowA[k] + rowB[j] + rowB[k]) * 0.25F;
}
}
 
else if (datatype == DTYPE_HALF_FLOAT && comps == 4) {
uint i, j, k, comp;
const half_float(*rowA)[4] = (const half_float(*)[4]) srcRowA;
const half_float(*rowB)[4] = (const half_float(*)[4]) srcRowB;
half_float(*dst)[4] = (half_float(*)[4]) dstRow;
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
for (comp = 0; comp < 4; comp++) {
float aj, ak, bj, bk;
aj = util_half_to_float(rowA[j][comp]);
ak = util_half_to_float(rowA[k][comp]);
bj = util_half_to_float(rowB[j][comp]);
bk = util_half_to_float(rowB[k][comp]);
dst[i][comp] = util_float_to_half((aj + ak + bj + bk) * 0.25F);
}
}
}
else if (datatype == DTYPE_HALF_FLOAT && comps == 3) {
uint i, j, k, comp;
const half_float(*rowA)[3] = (const half_float(*)[3]) srcRowA;
const half_float(*rowB)[3] = (const half_float(*)[3]) srcRowB;
half_float(*dst)[3] = (half_float(*)[3]) dstRow;
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
for (comp = 0; comp < 3; comp++) {
float aj, ak, bj, bk;
aj = util_half_to_float(rowA[j][comp]);
ak = util_half_to_float(rowA[k][comp]);
bj = util_half_to_float(rowB[j][comp]);
bk = util_half_to_float(rowB[k][comp]);
dst[i][comp] = util_float_to_half((aj + ak + bj + bk) * 0.25F);
}
}
}
else if (datatype == DTYPE_HALF_FLOAT && comps == 2) {
uint i, j, k, comp;
const half_float(*rowA)[2] = (const half_float(*)[2]) srcRowA;
const half_float(*rowB)[2] = (const half_float(*)[2]) srcRowB;
half_float(*dst)[2] = (half_float(*)[2]) dstRow;
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
for (comp = 0; comp < 2; comp++) {
float aj, ak, bj, bk;
aj = util_half_to_float(rowA[j][comp]);
ak = util_half_to_float(rowA[k][comp]);
bj = util_half_to_float(rowB[j][comp]);
bk = util_half_to_float(rowB[k][comp]);
dst[i][comp] = util_float_to_half((aj + ak + bj + bk) * 0.25F);
}
}
}
else if (datatype == DTYPE_HALF_FLOAT && comps == 1) {
uint i, j, k;
const half_float *rowA = (const half_float *) srcRowA;
const half_float *rowB = (const half_float *) srcRowB;
half_float *dst = (half_float *) dstRow;
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
float aj, ak, bj, bk;
aj = util_half_to_float(rowA[j]);
ak = util_half_to_float(rowA[k]);
bj = util_half_to_float(rowB[j]);
bk = util_half_to_float(rowB[k]);
dst[i] = util_float_to_half((aj + ak + bj + bk) * 0.25F);
}
}
 
else if (datatype == DTYPE_UINT && comps == 1) {
uint i, j, k;
const uint *rowA = (const uint *) srcRowA;
const uint *rowB = (const uint *) srcRowB;
uint *dst = (uint *) dstRow;
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
dst[i] = rowA[j] / 4 + rowA[k] / 4 + rowB[j] / 4 + rowB[k] / 4;
}
}
 
else if (datatype == DTYPE_USHORT_5_6_5 && comps == 3) {
uint i, j, k;
const ushort *rowA = (const ushort *) srcRowA;
const ushort *rowB = (const ushort *) srcRowB;
ushort *dst = (ushort *) dstRow;
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
const int rowAr0 = rowA[j] & 0x1f;
const int rowAr1 = rowA[k] & 0x1f;
const int rowBr0 = rowB[j] & 0x1f;
const int rowBr1 = rowB[k] & 0x1f;
const int rowAg0 = (rowA[j] >> 5) & 0x3f;
const int rowAg1 = (rowA[k] >> 5) & 0x3f;
const int rowBg0 = (rowB[j] >> 5) & 0x3f;
const int rowBg1 = (rowB[k] >> 5) & 0x3f;
const int rowAb0 = (rowA[j] >> 11) & 0x1f;
const int rowAb1 = (rowA[k] >> 11) & 0x1f;
const int rowBb0 = (rowB[j] >> 11) & 0x1f;
const int rowBb1 = (rowB[k] >> 11) & 0x1f;
const int red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
const int green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
const int blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
dst[i] = (blue << 11) | (green << 5) | red;
}
}
else if (datatype == DTYPE_USHORT_4_4_4_4 && comps == 4) {
uint i, j, k;
const ushort *rowA = (const ushort *) srcRowA;
const ushort *rowB = (const ushort *) srcRowB;
ushort *dst = (ushort *) dstRow;
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
const int rowAr0 = rowA[j] & 0xf;
const int rowAr1 = rowA[k] & 0xf;
const int rowBr0 = rowB[j] & 0xf;
const int rowBr1 = rowB[k] & 0xf;
const int rowAg0 = (rowA[j] >> 4) & 0xf;
const int rowAg1 = (rowA[k] >> 4) & 0xf;
const int rowBg0 = (rowB[j] >> 4) & 0xf;
const int rowBg1 = (rowB[k] >> 4) & 0xf;
const int rowAb0 = (rowA[j] >> 8) & 0xf;
const int rowAb1 = (rowA[k] >> 8) & 0xf;
const int rowBb0 = (rowB[j] >> 8) & 0xf;
const int rowBb1 = (rowB[k] >> 8) & 0xf;
const int rowAa0 = (rowA[j] >> 12) & 0xf;
const int rowAa1 = (rowA[k] >> 12) & 0xf;
const int rowBa0 = (rowB[j] >> 12) & 0xf;
const int rowBa1 = (rowB[k] >> 12) & 0xf;
const int red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
const int green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
const int blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
const int alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2;
dst[i] = (alpha << 12) | (blue << 8) | (green << 4) | red;
}
}
else if (datatype == DTYPE_USHORT_1_5_5_5_REV && comps == 4) {
uint i, j, k;
const ushort *rowA = (const ushort *) srcRowA;
const ushort *rowB = (const ushort *) srcRowB;
ushort *dst = (ushort *) dstRow;
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
const int rowAr0 = rowA[j] & 0x1f;
const int rowAr1 = rowA[k] & 0x1f;
const int rowBr0 = rowB[j] & 0x1f;
const int rowBr1 = rowB[k] & 0x1f;
const int rowAg0 = (rowA[j] >> 5) & 0x1f;
const int rowAg1 = (rowA[k] >> 5) & 0x1f;
const int rowBg0 = (rowB[j] >> 5) & 0x1f;
const int rowBg1 = (rowB[k] >> 5) & 0x1f;
const int rowAb0 = (rowA[j] >> 10) & 0x1f;
const int rowAb1 = (rowA[k] >> 10) & 0x1f;
const int rowBb0 = (rowB[j] >> 10) & 0x1f;
const int rowBb1 = (rowB[k] >> 10) & 0x1f;
const int rowAa0 = (rowA[j] >> 15) & 0x1;
const int rowAa1 = (rowA[k] >> 15) & 0x1;
const int rowBa0 = (rowB[j] >> 15) & 0x1;
const int rowBa1 = (rowB[k] >> 15) & 0x1;
const int red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
const int green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
const int blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
const int alpha = (rowAa0 + rowAa1 + rowBa0 + rowBa1) >> 2;
dst[i] = (alpha << 15) | (blue << 10) | (green << 5) | red;
}
}
else if (datatype == DTYPE_UBYTE_3_3_2 && comps == 3) {
uint i, j, k;
const ubyte *rowA = (const ubyte *) srcRowA;
const ubyte *rowB = (const ubyte *) srcRowB;
ubyte *dst = (ubyte *) dstRow;
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
const int rowAr0 = rowA[j] & 0x3;
const int rowAr1 = rowA[k] & 0x3;
const int rowBr0 = rowB[j] & 0x3;
const int rowBr1 = rowB[k] & 0x3;
const int rowAg0 = (rowA[j] >> 2) & 0x7;
const int rowAg1 = (rowA[k] >> 2) & 0x7;
const int rowBg0 = (rowB[j] >> 2) & 0x7;
const int rowBg1 = (rowB[k] >> 2) & 0x7;
const int rowAb0 = (rowA[j] >> 5) & 0x7;
const int rowAb1 = (rowA[k] >> 5) & 0x7;
const int rowBb0 = (rowB[j] >> 5) & 0x7;
const int rowBb1 = (rowB[k] >> 5) & 0x7;
const int red = (rowAr0 + rowAr1 + rowBr0 + rowBr1) >> 2;
const int green = (rowAg0 + rowAg1 + rowBg0 + rowBg1) >> 2;
const int blue = (rowAb0 + rowAb1 + rowBb0 + rowBb1) >> 2;
dst[i] = (blue << 5) | (green << 2) | red;
}
}
else {
debug_printf("bad format in do_row()");
}
}
 
 
/**
* Average together four rows of a source image to produce a single new
* row in the dest image. It's legal for the two source rows to point
* to the same data. The source width must be equal to either the
* dest width or two times the dest width.
*
* \param datatype GL pixel type \c GL_UNSIGNED_BYTE, \c GL_UNSIGNED_SHORT,
* \c GL_FLOAT, etc.
* \param comps number of components per pixel (1..4)
* \param srcWidth Width of a row in the source data
* \param srcRowA Pointer to one of the rows of source data
* \param srcRowB Pointer to one of the rows of source data
* \param srcRowC Pointer to one of the rows of source data
* \param srcRowD Pointer to one of the rows of source data
* \param dstWidth Width of a row in the destination data
* \param srcRowA Pointer to the row of destination data
*/
static void
do_row_3D(enum dtype datatype, uint comps, int srcWidth,
const void *srcRowA, const void *srcRowB,
const void *srcRowC, const void *srcRowD,
int dstWidth, void *dstRow)
{
const uint k0 = (srcWidth == dstWidth) ? 0 : 1;
const uint colStride = (srcWidth == dstWidth) ? 1 : 2;
uint i, j, k;
 
assert(comps >= 1);
assert(comps <= 4);
 
if ((datatype == DTYPE_UBYTE) && (comps == 4)) {
DECLARE_ROW_POINTERS(ubyte, 4);
 
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
FILTER_3D(0);
FILTER_3D(1);
FILTER_3D(2);
FILTER_3D(3);
}
}
else if ((datatype == DTYPE_UBYTE) && (comps == 3)) {
DECLARE_ROW_POINTERS(ubyte, 3);
 
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
FILTER_3D(0);
FILTER_3D(1);
FILTER_3D(2);
}
}
else if ((datatype == DTYPE_UBYTE) && (comps == 2)) {
DECLARE_ROW_POINTERS(ubyte, 2);
 
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
FILTER_3D(0);
FILTER_3D(1);
}
}
else if ((datatype == DTYPE_UBYTE) && (comps == 1)) {
DECLARE_ROW_POINTERS(ubyte, 1);
 
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
FILTER_3D(0);
}
}
else if ((datatype == DTYPE_USHORT) && (comps == 4)) {
DECLARE_ROW_POINTERS(ushort, 4);
 
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
FILTER_3D(0);
FILTER_3D(1);
FILTER_3D(2);
FILTER_3D(3);
}
}
else if ((datatype == DTYPE_USHORT) && (comps == 3)) {
DECLARE_ROW_POINTERS(ushort, 3);
 
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
FILTER_3D(0);
FILTER_3D(1);
FILTER_3D(2);
}
}
else if ((datatype == DTYPE_USHORT) && (comps == 2)) {
DECLARE_ROW_POINTERS(ushort, 2);
 
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
FILTER_3D(0);
FILTER_3D(1);
}
}
else if ((datatype == DTYPE_USHORT) && (comps == 1)) {
DECLARE_ROW_POINTERS(ushort, 1);
 
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
FILTER_3D(0);
}
}
else if ((datatype == DTYPE_FLOAT) && (comps == 4)) {
DECLARE_ROW_POINTERS(float, 4);
 
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
FILTER_F_3D(0);
FILTER_F_3D(1);
FILTER_F_3D(2);
FILTER_F_3D(3);
}
}
else if ((datatype == DTYPE_FLOAT) && (comps == 3)) {
DECLARE_ROW_POINTERS(float, 3);
 
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
FILTER_F_3D(0);
FILTER_F_3D(1);
FILTER_F_3D(2);
}
}
else if ((datatype == DTYPE_FLOAT) && (comps == 2)) {
DECLARE_ROW_POINTERS(float, 2);
 
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
FILTER_F_3D(0);
FILTER_F_3D(1);
}
}
else if ((datatype == DTYPE_FLOAT) && (comps == 1)) {
DECLARE_ROW_POINTERS(float, 1);
 
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
FILTER_F_3D(0);
}
}
else if ((datatype == DTYPE_HALF_FLOAT) && (comps == 4)) {
DECLARE_ROW_POINTERS(half_float, 4);
 
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
FILTER_HF_3D(0);
FILTER_HF_3D(1);
FILTER_HF_3D(2);
FILTER_HF_3D(3);
}
}
else if ((datatype == DTYPE_HALF_FLOAT) && (comps == 3)) {
DECLARE_ROW_POINTERS(half_float, 4);
 
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
FILTER_HF_3D(0);
FILTER_HF_3D(1);
FILTER_HF_3D(2);
}
}
else if ((datatype == DTYPE_HALF_FLOAT) && (comps == 2)) {
DECLARE_ROW_POINTERS(half_float, 4);
 
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
FILTER_HF_3D(0);
FILTER_HF_3D(1);
}
}
else if ((datatype == DTYPE_HALF_FLOAT) && (comps == 1)) {
DECLARE_ROW_POINTERS(half_float, 4);
 
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
FILTER_HF_3D(0);
}
}
else if ((datatype == DTYPE_UINT) && (comps == 1)) {
const uint *rowA = (const uint *) srcRowA;
const uint *rowB = (const uint *) srcRowB;
const uint *rowC = (const uint *) srcRowC;
const uint *rowD = (const uint *) srcRowD;
float *dst = (float *) dstRow;
 
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
const uint64_t tmp = (((uint64_t) rowA[j] + (uint64_t) rowA[k])
+ ((uint64_t) rowB[j] + (uint64_t) rowB[k])
+ ((uint64_t) rowC[j] + (uint64_t) rowC[k])
+ ((uint64_t) rowD[j] + (uint64_t) rowD[k]));
dst[i] = (float)((double) tmp * 0.125);
}
}
else if ((datatype == DTYPE_USHORT_5_6_5) && (comps == 3)) {
DECLARE_ROW_POINTERS0(ushort);
 
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
const int rowAr0 = rowA[j] & 0x1f;
const int rowAr1 = rowA[k] & 0x1f;
const int rowBr0 = rowB[j] & 0x1f;
const int rowBr1 = rowB[k] & 0x1f;
const int rowCr0 = rowC[j] & 0x1f;
const int rowCr1 = rowC[k] & 0x1f;
const int rowDr0 = rowD[j] & 0x1f;
const int rowDr1 = rowD[k] & 0x1f;
const int rowAg0 = (rowA[j] >> 5) & 0x3f;
const int rowAg1 = (rowA[k] >> 5) & 0x3f;
const int rowBg0 = (rowB[j] >> 5) & 0x3f;
const int rowBg1 = (rowB[k] >> 5) & 0x3f;
const int rowCg0 = (rowC[j] >> 5) & 0x3f;
const int rowCg1 = (rowC[k] >> 5) & 0x3f;
const int rowDg0 = (rowD[j] >> 5) & 0x3f;
const int rowDg1 = (rowD[k] >> 5) & 0x3f;
const int rowAb0 = (rowA[j] >> 11) & 0x1f;
const int rowAb1 = (rowA[k] >> 11) & 0x1f;
const int rowBb0 = (rowB[j] >> 11) & 0x1f;
const int rowBb1 = (rowB[k] >> 11) & 0x1f;
const int rowCb0 = (rowC[j] >> 11) & 0x1f;
const int rowCb1 = (rowC[k] >> 11) & 0x1f;
const int rowDb0 = (rowD[j] >> 11) & 0x1f;
const int rowDb1 = (rowD[k] >> 11) & 0x1f;
const int r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1,
rowCr0, rowCr1, rowDr0, rowDr1);
const int g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1,
rowCg0, rowCg1, rowDg0, rowDg1);
const int b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1,
rowCb0, rowCb1, rowDb0, rowDb1);
dst[i] = (b << 11) | (g << 5) | r;
}
}
else if ((datatype == DTYPE_USHORT_4_4_4_4) && (comps == 4)) {
DECLARE_ROW_POINTERS0(ushort);
 
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
const int rowAr0 = rowA[j] & 0xf;
const int rowAr1 = rowA[k] & 0xf;
const int rowBr0 = rowB[j] & 0xf;
const int rowBr1 = rowB[k] & 0xf;
const int rowCr0 = rowC[j] & 0xf;
const int rowCr1 = rowC[k] & 0xf;
const int rowDr0 = rowD[j] & 0xf;
const int rowDr1 = rowD[k] & 0xf;
const int rowAg0 = (rowA[j] >> 4) & 0xf;
const int rowAg1 = (rowA[k] >> 4) & 0xf;
const int rowBg0 = (rowB[j] >> 4) & 0xf;
const int rowBg1 = (rowB[k] >> 4) & 0xf;
const int rowCg0 = (rowC[j] >> 4) & 0xf;
const int rowCg1 = (rowC[k] >> 4) & 0xf;
const int rowDg0 = (rowD[j] >> 4) & 0xf;
const int rowDg1 = (rowD[k] >> 4) & 0xf;
const int rowAb0 = (rowA[j] >> 8) & 0xf;
const int rowAb1 = (rowA[k] >> 8) & 0xf;
const int rowBb0 = (rowB[j] >> 8) & 0xf;
const int rowBb1 = (rowB[k] >> 8) & 0xf;
const int rowCb0 = (rowC[j] >> 8) & 0xf;
const int rowCb1 = (rowC[k] >> 8) & 0xf;
const int rowDb0 = (rowD[j] >> 8) & 0xf;
const int rowDb1 = (rowD[k] >> 8) & 0xf;
const int rowAa0 = (rowA[j] >> 12) & 0xf;
const int rowAa1 = (rowA[k] >> 12) & 0xf;
const int rowBa0 = (rowB[j] >> 12) & 0xf;
const int rowBa1 = (rowB[k] >> 12) & 0xf;
const int rowCa0 = (rowC[j] >> 12) & 0xf;
const int rowCa1 = (rowC[k] >> 12) & 0xf;
const int rowDa0 = (rowD[j] >> 12) & 0xf;
const int rowDa1 = (rowD[k] >> 12) & 0xf;
const int r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1,
rowCr0, rowCr1, rowDr0, rowDr1);
const int g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1,
rowCg0, rowCg1, rowDg0, rowDg1);
const int b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1,
rowCb0, rowCb1, rowDb0, rowDb1);
const int a = FILTER_SUM_3D(rowAa0, rowAa1, rowBa0, rowBa1,
rowCa0, rowCa1, rowDa0, rowDa1);
 
dst[i] = (a << 12) | (b << 8) | (g << 4) | r;
}
}
else if ((datatype == DTYPE_USHORT_1_5_5_5_REV) && (comps == 4)) {
DECLARE_ROW_POINTERS0(ushort);
 
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
const int rowAr0 = rowA[j] & 0x1f;
const int rowAr1 = rowA[k] & 0x1f;
const int rowBr0 = rowB[j] & 0x1f;
const int rowBr1 = rowB[k] & 0x1f;
const int rowCr0 = rowC[j] & 0x1f;
const int rowCr1 = rowC[k] & 0x1f;
const int rowDr0 = rowD[j] & 0x1f;
const int rowDr1 = rowD[k] & 0x1f;
const int rowAg0 = (rowA[j] >> 5) & 0x1f;
const int rowAg1 = (rowA[k] >> 5) & 0x1f;
const int rowBg0 = (rowB[j] >> 5) & 0x1f;
const int rowBg1 = (rowB[k] >> 5) & 0x1f;
const int rowCg0 = (rowC[j] >> 5) & 0x1f;
const int rowCg1 = (rowC[k] >> 5) & 0x1f;
const int rowDg0 = (rowD[j] >> 5) & 0x1f;
const int rowDg1 = (rowD[k] >> 5) & 0x1f;
const int rowAb0 = (rowA[j] >> 10) & 0x1f;
const int rowAb1 = (rowA[k] >> 10) & 0x1f;
const int rowBb0 = (rowB[j] >> 10) & 0x1f;
const int rowBb1 = (rowB[k] >> 10) & 0x1f;
const int rowCb0 = (rowC[j] >> 10) & 0x1f;
const int rowCb1 = (rowC[k] >> 10) & 0x1f;
const int rowDb0 = (rowD[j] >> 10) & 0x1f;
const int rowDb1 = (rowD[k] >> 10) & 0x1f;
const int rowAa0 = (rowA[j] >> 15) & 0x1;
const int rowAa1 = (rowA[k] >> 15) & 0x1;
const int rowBa0 = (rowB[j] >> 15) & 0x1;
const int rowBa1 = (rowB[k] >> 15) & 0x1;
const int rowCa0 = (rowC[j] >> 15) & 0x1;
const int rowCa1 = (rowC[k] >> 15) & 0x1;
const int rowDa0 = (rowD[j] >> 15) & 0x1;
const int rowDa1 = (rowD[k] >> 15) & 0x1;
const int r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1,
rowCr0, rowCr1, rowDr0, rowDr1);
const int g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1,
rowCg0, rowCg1, rowDg0, rowDg1);
const int b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1,
rowCb0, rowCb1, rowDb0, rowDb1);
const int a = FILTER_SUM_3D(rowAa0, rowAa1, rowBa0, rowBa1,
rowCa0, rowCa1, rowDa0, rowDa1);
 
dst[i] = (a << 15) | (b << 10) | (g << 5) | r;
}
}
else if ((datatype == DTYPE_UBYTE_3_3_2) && (comps == 3)) {
DECLARE_ROW_POINTERS0(ushort);
 
for (i = j = 0, k = k0; i < (uint) dstWidth;
i++, j += colStride, k += colStride) {
const int rowAr0 = rowA[j] & 0x3;
const int rowAr1 = rowA[k] & 0x3;
const int rowBr0 = rowB[j] & 0x3;
const int rowBr1 = rowB[k] & 0x3;
const int rowCr0 = rowC[j] & 0x3;
const int rowCr1 = rowC[k] & 0x3;
const int rowDr0 = rowD[j] & 0x3;
const int rowDr1 = rowD[k] & 0x3;
const int rowAg0 = (rowA[j] >> 2) & 0x7;
const int rowAg1 = (rowA[k] >> 2) & 0x7;
const int rowBg0 = (rowB[j] >> 2) & 0x7;
const int rowBg1 = (rowB[k] >> 2) & 0x7;
const int rowCg0 = (rowC[j] >> 2) & 0x7;
const int rowCg1 = (rowC[k] >> 2) & 0x7;
const int rowDg0 = (rowD[j] >> 2) & 0x7;
const int rowDg1 = (rowD[k] >> 2) & 0x7;
const int rowAb0 = (rowA[j] >> 5) & 0x7;
const int rowAb1 = (rowA[k] >> 5) & 0x7;
const int rowBb0 = (rowB[j] >> 5) & 0x7;
const int rowBb1 = (rowB[k] >> 5) & 0x7;
const int rowCb0 = (rowC[j] >> 5) & 0x7;
const int rowCb1 = (rowC[k] >> 5) & 0x7;
const int rowDb0 = (rowD[j] >> 5) & 0x7;
const int rowDb1 = (rowD[k] >> 5) & 0x7;
const int r = FILTER_SUM_3D(rowAr0, rowAr1, rowBr0, rowBr1,
rowCr0, rowCr1, rowDr0, rowDr1);
const int g = FILTER_SUM_3D(rowAg0, rowAg1, rowBg0, rowBg1,
rowCg0, rowCg1, rowDg0, rowDg1);
const int b = FILTER_SUM_3D(rowAb0, rowAb1, rowBb0, rowBb1,
rowCb0, rowCb1, rowDb0, rowDb1);
dst[i] = (b << 5) | (g << 2) | r;
}
}
else {
debug_printf("bad format in do_row_3D()");
}
}
 
 
 
static void
format_to_type_comps(enum pipe_format pformat,
enum dtype *datatype, uint *comps)
{
/* XXX I think this could be implemented in terms of the pf_*() functions */
switch (pformat) {
case PIPE_FORMAT_B8G8R8A8_UNORM:
case PIPE_FORMAT_B8G8R8X8_UNORM:
case PIPE_FORMAT_A8R8G8B8_UNORM:
case PIPE_FORMAT_X8R8G8B8_UNORM:
case PIPE_FORMAT_A8B8G8R8_SRGB:
case PIPE_FORMAT_X8B8G8R8_SRGB:
case PIPE_FORMAT_B8G8R8A8_SRGB:
case PIPE_FORMAT_B8G8R8X8_SRGB:
case PIPE_FORMAT_A8R8G8B8_SRGB:
case PIPE_FORMAT_X8R8G8B8_SRGB:
case PIPE_FORMAT_R8G8B8_SRGB:
*datatype = DTYPE_UBYTE;
*comps = 4;
return;
case PIPE_FORMAT_B5G5R5X1_UNORM:
case PIPE_FORMAT_B5G5R5A1_UNORM:
*datatype = DTYPE_USHORT_1_5_5_5_REV;
*comps = 4;
return;
case PIPE_FORMAT_B4G4R4A4_UNORM:
*datatype = DTYPE_USHORT_4_4_4_4;
*comps = 4;
return;
case PIPE_FORMAT_B5G6R5_UNORM:
*datatype = DTYPE_USHORT_5_6_5;
*comps = 3;
return;
case PIPE_FORMAT_L8_UNORM:
case PIPE_FORMAT_L8_SRGB:
case PIPE_FORMAT_A8_UNORM:
case PIPE_FORMAT_I8_UNORM:
*datatype = DTYPE_UBYTE;
*comps = 1;
return;
case PIPE_FORMAT_L8A8_UNORM:
case PIPE_FORMAT_L8A8_SRGB:
*datatype = DTYPE_UBYTE;
*comps = 2;
return;
default:
assert(0);
*datatype = DTYPE_UBYTE;
*comps = 0;
break;
}
}
 
 
static void
reduce_1d(enum pipe_format pformat,
int srcWidth, const ubyte *srcPtr,
int dstWidth, ubyte *dstPtr)
{
enum dtype datatype;
uint comps;
 
format_to_type_comps(pformat, &datatype, &comps);
 
/* we just duplicate the input row, kind of hack, saves code */
do_row(datatype, comps,
srcWidth, srcPtr, srcPtr,
dstWidth, dstPtr);
}
 
 
/**
* Strides are in bytes. If zero, it'll be computed as width * bpp.
*/
static void
reduce_2d(enum pipe_format pformat,
int srcWidth, int srcHeight,
int srcRowStride, const ubyte *srcPtr,
int dstWidth, int dstHeight,
int dstRowStride, ubyte *dstPtr)
{
enum dtype datatype;
uint comps;
const int bpt = util_format_get_blocksize(pformat);
const ubyte *srcA, *srcB;
ubyte *dst;
int row;
 
format_to_type_comps(pformat, &datatype, &comps);
 
if (!srcRowStride)
srcRowStride = bpt * srcWidth;
 
if (!dstRowStride)
dstRowStride = bpt * dstWidth;
 
/* Compute src and dst pointers */
srcA = srcPtr;
if (srcHeight > 1)
srcB = srcA + srcRowStride;
else
srcB = srcA;
dst = dstPtr;
 
for (row = 0; row < dstHeight; row++) {
do_row(datatype, comps,
srcWidth, srcA, srcB,
dstWidth, dst);
srcA += 2 * srcRowStride;
srcB += 2 * srcRowStride;
dst += dstRowStride;
}
}
 
 
static void
reduce_3d(enum pipe_format pformat,
int srcWidth, int srcHeight, int srcDepth,
int srcRowStride, int srcImageStride, const ubyte *srcPtr,
int dstWidth, int dstHeight, int dstDepth,
int dstRowStride, int dstImageStride, ubyte *dstPtr)
{
const int bpt = util_format_get_blocksize(pformat);
int img, row;
int srcImageOffset, srcRowOffset;
enum dtype datatype;
uint comps;
 
format_to_type_comps(pformat, &datatype, &comps);
 
/* XXX I think we should rather assert those strides */
if (!srcImageStride)
srcImageStride = srcWidth * srcHeight * bpt;
if (!dstImageStride)
dstImageStride = dstWidth * dstHeight * bpt;
 
if (!srcRowStride)
srcRowStride = srcWidth * bpt;
if (!dstRowStride)
dstRowStride = dstWidth * bpt;
 
/* Offset between adjacent src images to be averaged together */
srcImageOffset = (srcDepth == dstDepth) ? 0 : srcImageStride;
 
/* Offset between adjacent src rows to be averaged together */
srcRowOffset = (srcHeight == dstHeight) ? 0 : srcRowStride;
 
/*
* Need to average together up to 8 src pixels for each dest pixel.
* Break that down into 3 operations:
* 1. take two rows from source image and average them together.
* 2. take two rows from next source image and average them together.
* 3. take the two averaged rows and average them for the final dst row.
*/
 
/*
printf("mip3d %d x %d x %d -> %d x %d x %d\n",
srcWidth, srcHeight, srcDepth, dstWidth, dstHeight, dstDepth);
*/
 
for (img = 0; img < dstDepth; img++) {
/* first source image pointer */
const ubyte *imgSrcA = srcPtr
+ img * (srcImageStride + srcImageOffset);
/* second source image pointer */
const ubyte *imgSrcB = imgSrcA + srcImageOffset;
/* address of the dest image */
ubyte *imgDst = dstPtr + img * dstImageStride;
 
/* setup the four source row pointers and the dest row pointer */
const ubyte *srcImgARowA = imgSrcA;
const ubyte *srcImgARowB = imgSrcA + srcRowOffset;
const ubyte *srcImgBRowA = imgSrcB;
const ubyte *srcImgBRowB = imgSrcB + srcRowOffset;
ubyte *dstImgRow = imgDst;
 
for (row = 0; row < dstHeight; row++) {
do_row_3D(datatype, comps, srcWidth,
srcImgARowA, srcImgARowB,
srcImgBRowA, srcImgBRowB,
dstWidth, dstImgRow);
 
/* advance to next rows */
srcImgARowA += srcRowStride + srcRowOffset;
srcImgARowB += srcRowStride + srcRowOffset;
srcImgBRowA += srcRowStride + srcRowOffset;
srcImgBRowB += srcRowStride + srcRowOffset;
dstImgRow += dstImageStride;
}
}
}
 
 
 
 
static void
make_1d_mipmap(struct gen_mipmap_state *ctx,
struct pipe_resource *pt,
uint layer, uint baseLevel, uint lastLevel)
{
struct pipe_context *pipe = ctx->pipe;
uint dstLevel;
 
for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
const uint srcLevel = dstLevel - 1;
struct pipe_transfer *srcTrans, *dstTrans;
void *srcMap, *dstMap;
 
srcMap = pipe_transfer_map(pipe, pt, srcLevel, layer,
PIPE_TRANSFER_READ, 0, 0,
u_minify(pt->width0, srcLevel),
u_minify(pt->height0, srcLevel), &srcTrans);
dstMap = pipe_transfer_map(pipe, pt, dstLevel, layer,
PIPE_TRANSFER_WRITE, 0, 0,
u_minify(pt->width0, dstLevel),
u_minify(pt->height0, dstLevel), &dstTrans);
 
reduce_1d(pt->format,
srcTrans->box.width, srcMap,
dstTrans->box.width, dstMap);
 
pipe->transfer_unmap(pipe, srcTrans);
pipe->transfer_unmap(pipe, dstTrans);
}
}
 
 
static void
make_2d_mipmap(struct gen_mipmap_state *ctx,
struct pipe_resource *pt,
uint layer, uint baseLevel, uint lastLevel)
{
struct pipe_context *pipe = ctx->pipe;
uint dstLevel;
 
assert(util_format_get_blockwidth(pt->format) == 1);
assert(util_format_get_blockheight(pt->format) == 1);
 
for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
const uint srcLevel = dstLevel - 1;
struct pipe_transfer *srcTrans, *dstTrans;
ubyte *srcMap, *dstMap;
 
srcMap = pipe_transfer_map(pipe, pt, srcLevel, layer,
PIPE_TRANSFER_READ, 0, 0,
u_minify(pt->width0, srcLevel),
u_minify(pt->height0, srcLevel), &srcTrans);
dstMap = pipe_transfer_map(pipe, pt, dstLevel, layer,
PIPE_TRANSFER_WRITE, 0, 0,
u_minify(pt->width0, dstLevel),
u_minify(pt->height0, dstLevel), &dstTrans);
 
reduce_2d(pt->format,
srcTrans->box.width, srcTrans->box.height,
srcTrans->stride, srcMap,
dstTrans->box.width, dstTrans->box.height,
dstTrans->stride, dstMap);
 
pipe->transfer_unmap(pipe, srcTrans);
pipe->transfer_unmap(pipe, dstTrans);
}
}
 
 
/* XXX looks a bit more like it could work now but need to test */
static void
make_3d_mipmap(struct gen_mipmap_state *ctx,
struct pipe_resource *pt,
uint face, uint baseLevel, uint lastLevel)
{
struct pipe_context *pipe = ctx->pipe;
uint dstLevel;
struct pipe_box src_box, dst_box;
 
assert(util_format_get_blockwidth(pt->format) == 1);
assert(util_format_get_blockheight(pt->format) == 1);
 
src_box.x = src_box.y = src_box.z = 0;
dst_box.x = dst_box.y = dst_box.z = 0;
 
for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
const uint srcLevel = dstLevel - 1;
struct pipe_transfer *srcTrans, *dstTrans;
ubyte *srcMap, *dstMap;
struct pipe_box src_box, dst_box;
src_box.width = u_minify(pt->width0, srcLevel);
src_box.height = u_minify(pt->height0, srcLevel);
src_box.depth = u_minify(pt->depth0, srcLevel);
dst_box.width = u_minify(pt->width0, dstLevel);
dst_box.height = u_minify(pt->height0, dstLevel);
dst_box.depth = u_minify(pt->depth0, dstLevel);
 
srcMap = pipe->transfer_map(pipe, pt, srcLevel,
PIPE_TRANSFER_READ,
&src_box, &srcTrans);
dstMap = pipe->transfer_map(pipe, pt, dstLevel,
PIPE_TRANSFER_WRITE,
&dst_box, &dstTrans);
 
reduce_3d(pt->format,
srcTrans->box.width, srcTrans->box.height, srcTrans->box.depth,
srcTrans->stride, srcTrans->layer_stride, srcMap,
dstTrans->box.width, dstTrans->box.height, dstTrans->box.depth,
dstTrans->stride, dstTrans->layer_stride, dstMap);
 
pipe->transfer_unmap(pipe, srcTrans);
pipe->transfer_unmap(pipe, dstTrans);
}
}
 
 
static void
fallback_gen_mipmap(struct gen_mipmap_state *ctx,
struct pipe_resource *pt,
uint layer, uint baseLevel, uint lastLevel)
{
switch (pt->target) {
case PIPE_TEXTURE_1D:
make_1d_mipmap(ctx, pt, layer, baseLevel, lastLevel);
break;
case PIPE_TEXTURE_2D:
case PIPE_TEXTURE_RECT:
case PIPE_TEXTURE_CUBE:
make_2d_mipmap(ctx, pt, layer, baseLevel, lastLevel);
break;
case PIPE_TEXTURE_3D:
make_3d_mipmap(ctx, pt, layer, baseLevel, lastLevel);
break;
default:
assert(0);
}
}
 
 
/**
* Create a mipmap generation context.
* The idea is to create one of these and re-use it each time we need to
* generate a mipmap.
*/
struct gen_mipmap_state *
util_create_gen_mipmap(struct pipe_context *pipe,
struct cso_context *cso)
{
struct gen_mipmap_state *ctx;
uint i;
 
ctx = CALLOC_STRUCT(gen_mipmap_state);
if (!ctx)
return NULL;
 
ctx->pipe = pipe;
ctx->cso = cso;
 
/* disabled blending/masking */
memset(&ctx->blend_keep_color, 0, sizeof(ctx->blend_keep_color));
memset(&ctx->blend_write_color, 0, sizeof(ctx->blend_write_color));
ctx->blend_write_color.rt[0].colormask = PIPE_MASK_RGBA;
 
/* no-op depth/stencil/alpha */
memset(&ctx->dsa_keep_depth, 0, sizeof(ctx->dsa_keep_depth));
memset(&ctx->dsa_write_depth, 0, sizeof(ctx->dsa_write_depth));
ctx->dsa_write_depth.depth.enabled = 1;
ctx->dsa_write_depth.depth.func = PIPE_FUNC_ALWAYS;
ctx->dsa_write_depth.depth.writemask = 1;
 
/* rasterizer */
memset(&ctx->rasterizer, 0, sizeof(ctx->rasterizer));
ctx->rasterizer.cull_face = PIPE_FACE_NONE;
ctx->rasterizer.half_pixel_center = 1;
ctx->rasterizer.bottom_edge_rule = 1;
ctx->rasterizer.depth_clip = 1;
 
/* sampler state */
memset(&ctx->sampler, 0, sizeof(ctx->sampler));
ctx->sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
ctx->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
ctx->sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
ctx->sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST;
ctx->sampler.normalized_coords = 1;
 
/* vertex elements state */
memset(&ctx->velem[0], 0, sizeof(ctx->velem[0]) * 2);
for (i = 0; i < 2; i++) {
ctx->velem[i].src_offset = i * 4 * sizeof(float);
ctx->velem[i].instance_divisor = 0;
ctx->velem[i].vertex_buffer_index = cso_get_aux_vertex_buffer_slot(cso);
ctx->velem[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
}
 
/* vertex data that doesn't change */
for (i = 0; i < 4; i++) {
ctx->vertices[i][0][2] = 0.0f; /* z */
ctx->vertices[i][0][3] = 1.0f; /* w */
ctx->vertices[i][1][3] = 1.0f; /* q */
}
 
/* Note: the actual vertex buffer is allocated as needed below */
 
return ctx;
}
 
 
/**
* Helper function to set the fragment shaders.
*/
static INLINE void
set_fragment_shader(struct gen_mipmap_state *ctx, uint type,
boolean output_depth)
{
if (output_depth) {
if (!ctx->fs_depth[type])
ctx->fs_depth[type] =
util_make_fragment_tex_shader_writedepth(ctx->pipe, type,
TGSI_INTERPOLATE_LINEAR);
 
cso_set_fragment_shader_handle(ctx->cso, ctx->fs_depth[type]);
}
else {
if (!ctx->fs_color[type])
ctx->fs_color[type] =
util_make_fragment_tex_shader(ctx->pipe, type,
TGSI_INTERPOLATE_LINEAR);
 
cso_set_fragment_shader_handle(ctx->cso, ctx->fs_color[type]);
}
}
 
 
/**
* Helper function to set the vertex shader.
*/
static INLINE void
set_vertex_shader(struct gen_mipmap_state *ctx)
{
/* vertex shader - still required to provide the linkage between
* fragment shader input semantics and vertex_element/buffers.
*/
if (!ctx->vs)
{
const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
TGSI_SEMANTIC_GENERIC };
const uint semantic_indexes[] = { 0, 0 };
ctx->vs = util_make_vertex_passthrough_shader(ctx->pipe, 2,
semantic_names,
semantic_indexes);
}
 
cso_set_vertex_shader_handle(ctx->cso, ctx->vs);
}
 
 
/**
* Get next "slot" of vertex space in the vertex buffer.
* We're allocating one large vertex buffer and using it piece by piece.
*/
static unsigned
get_next_slot(struct gen_mipmap_state *ctx)
{
const unsigned max_slots = 4096 / sizeof ctx->vertices;
 
if (ctx->vbuf_slot >= max_slots) {
pipe_resource_reference(&ctx->vbuf, NULL);
ctx->vbuf_slot = 0;
}
 
if (!ctx->vbuf) {
ctx->vbuf = pipe_buffer_create(ctx->pipe->screen,
PIPE_BIND_VERTEX_BUFFER,
PIPE_USAGE_STREAM,
max_slots * sizeof ctx->vertices);
}
return ctx->vbuf_slot++ * sizeof ctx->vertices;
}
 
 
static unsigned
set_vertex_data(struct gen_mipmap_state *ctx,
enum pipe_texture_target tex_target,
uint layer, float r)
{
unsigned offset;
 
/* vert[0].position */
ctx->vertices[0][0][0] = -1.0f; /*x*/
ctx->vertices[0][0][1] = -1.0f; /*y*/
 
/* vert[1].position */
ctx->vertices[1][0][0] = 1.0f;
ctx->vertices[1][0][1] = -1.0f;
 
/* vert[2].position */
ctx->vertices[2][0][0] = 1.0f;
ctx->vertices[2][0][1] = 1.0f;
 
/* vert[3].position */
ctx->vertices[3][0][0] = -1.0f;
ctx->vertices[3][0][1] = 1.0f;
 
/* Setup vertex texcoords. This is a little tricky for cube maps. */
if (tex_target == PIPE_TEXTURE_CUBE) {
static const float st[4][2] = {
{0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f}
};
 
util_map_texcoords2d_onto_cubemap(layer, &st[0][0], 2,
&ctx->vertices[0][1][0], 8);
}
else if (tex_target == PIPE_TEXTURE_1D_ARRAY) {
/* 1D texture array */
ctx->vertices[0][1][0] = 0.0f; /*s*/
ctx->vertices[0][1][1] = r; /*t*/
ctx->vertices[0][1][2] = 0.0f; /*r*/
 
ctx->vertices[1][1][0] = 1.0f;
ctx->vertices[1][1][1] = r;
ctx->vertices[1][1][2] = 0.0f;
 
ctx->vertices[2][1][0] = 1.0f;
ctx->vertices[2][1][1] = r;
ctx->vertices[2][1][2] = 0.0f;
 
ctx->vertices[3][1][0] = 0.0f;
ctx->vertices[3][1][1] = r;
ctx->vertices[3][1][2] = 0.0f;
} else {
/* 1D/2D/3D/2D array */
ctx->vertices[0][1][0] = 0.0f; /*s*/
ctx->vertices[0][1][1] = 0.0f; /*t*/
ctx->vertices[0][1][2] = r; /*r*/
 
ctx->vertices[1][1][0] = 1.0f;
ctx->vertices[1][1][1] = 0.0f;
ctx->vertices[1][1][2] = r;
 
ctx->vertices[2][1][0] = 1.0f;
ctx->vertices[2][1][1] = 1.0f;
ctx->vertices[2][1][2] = r;
 
ctx->vertices[3][1][0] = 0.0f;
ctx->vertices[3][1][1] = 1.0f;
ctx->vertices[3][1][2] = r;
}
 
offset = get_next_slot( ctx );
 
pipe_buffer_write_nooverlap(ctx->pipe, ctx->vbuf,
offset, sizeof(ctx->vertices), ctx->vertices);
 
return offset;
}
 
 
 
/**
* Destroy a mipmap generation context
*/
void
util_destroy_gen_mipmap(struct gen_mipmap_state *ctx)
{
struct pipe_context *pipe = ctx->pipe;
unsigned i;
 
for (i = 0; i < Elements(ctx->fs_color); i++)
if (ctx->fs_color[i])
pipe->delete_fs_state(pipe, ctx->fs_color[i]);
 
for (i = 0; i < Elements(ctx->fs_depth); i++)
if (ctx->fs_depth[i])
pipe->delete_fs_state(pipe, ctx->fs_depth[i]);
 
if (ctx->vs)
pipe->delete_vs_state(pipe, ctx->vs);
 
pipe_resource_reference(&ctx->vbuf, NULL);
 
FREE(ctx);
}
 
 
/**
* Generate mipmap images. It's assumed all needed texture memory is
* already allocated.
*
* \param psv the sampler view to the texture to generate mipmap levels for
* \param face which cube face to generate mipmaps for (0 for non-cube maps)
* \param baseLevel the first mipmap level to use as a src
* \param lastLevel the last mipmap level to generate
* \param filter the minification filter used to generate mipmap levels with
* \param filter one of PIPE_TEX_FILTER_LINEAR, PIPE_TEX_FILTER_NEAREST
*/
void
util_gen_mipmap(struct gen_mipmap_state *ctx,
struct pipe_sampler_view *psv,
uint face, uint baseLevel, uint lastLevel, uint filter)
{
struct pipe_context *pipe = ctx->pipe;
struct pipe_screen *screen = pipe->screen;
struct pipe_framebuffer_state fb;
struct pipe_resource *pt = psv->texture;
uint dstLevel;
uint offset;
uint type;
boolean is_depth = util_format_is_depth_or_stencil(psv->format);
 
/* The texture object should have room for the levels which we're
* about to generate.
*/
assert(lastLevel <= pt->last_level);
 
/* If this fails, why are we here? */
assert(lastLevel > baseLevel);
 
assert(filter == PIPE_TEX_FILTER_LINEAR ||
filter == PIPE_TEX_FILTER_NEAREST);
 
switch (pt->target) {
case PIPE_TEXTURE_1D:
type = TGSI_TEXTURE_1D;
break;
case PIPE_TEXTURE_2D:
type = TGSI_TEXTURE_2D;
break;
case PIPE_TEXTURE_3D:
type = TGSI_TEXTURE_3D;
break;
case PIPE_TEXTURE_CUBE:
type = TGSI_TEXTURE_CUBE;
break;
case PIPE_TEXTURE_1D_ARRAY:
type = TGSI_TEXTURE_1D_ARRAY;
break;
case PIPE_TEXTURE_2D_ARRAY:
type = TGSI_TEXTURE_2D_ARRAY;
break;
default:
assert(0);
type = TGSI_TEXTURE_2D;
}
 
/* check if we can render in the texture's format */
if (!screen->is_format_supported(screen, psv->format, pt->target,
pt->nr_samples,
is_depth ? PIPE_BIND_DEPTH_STENCIL :
PIPE_BIND_RENDER_TARGET)) {
fallback_gen_mipmap(ctx, pt, face, baseLevel, lastLevel);
return;
}
 
/* save state (restored below) */
cso_save_blend(ctx->cso);
cso_save_depth_stencil_alpha(ctx->cso);
cso_save_rasterizer(ctx->cso);
cso_save_sample_mask(ctx->cso);
cso_save_samplers(ctx->cso, PIPE_SHADER_FRAGMENT);
cso_save_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT);
cso_save_stream_outputs(ctx->cso);
cso_save_framebuffer(ctx->cso);
cso_save_fragment_shader(ctx->cso);
cso_save_vertex_shader(ctx->cso);
cso_save_geometry_shader(ctx->cso);
cso_save_viewport(ctx->cso);
cso_save_vertex_elements(ctx->cso);
cso_save_aux_vertex_buffer_slot(ctx->cso);
cso_save_render_condition(ctx->cso);
 
/* bind our state */
cso_set_blend(ctx->cso, is_depth ? &ctx->blend_keep_color :
&ctx->blend_write_color);
cso_set_depth_stencil_alpha(ctx->cso, is_depth ? &ctx->dsa_write_depth :
&ctx->dsa_keep_depth);
cso_set_rasterizer(ctx->cso, &ctx->rasterizer);
cso_set_sample_mask(ctx->cso, ~0);
cso_set_vertex_elements(ctx->cso, 2, ctx->velem);
cso_set_stream_outputs(ctx->cso, 0, NULL, 0);
cso_set_render_condition(ctx->cso, NULL, FALSE, 0);
 
set_fragment_shader(ctx, type, is_depth);
set_vertex_shader(ctx);
cso_set_geometry_shader_handle(ctx->cso, NULL);
 
/* init framebuffer state */
memset(&fb, 0, sizeof(fb));
 
/* set min/mag to same filter for faster sw speed */
ctx->sampler.mag_img_filter = filter;
ctx->sampler.min_img_filter = filter;
 
for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
const uint srcLevel = dstLevel - 1;
struct pipe_viewport_state vp;
unsigned nr_layers, layer, i;
float rcoord = 0.0f;
 
if (pt->target == PIPE_TEXTURE_3D)
nr_layers = u_minify(pt->depth0, dstLevel);
else if (pt->target == PIPE_TEXTURE_2D_ARRAY || pt->target == PIPE_TEXTURE_1D_ARRAY)
nr_layers = pt->array_size;
else
nr_layers = 1;
 
for (i = 0; i < nr_layers; i++) {
struct pipe_surface *surf, surf_templ;
if (pt->target == PIPE_TEXTURE_3D) {
/* in theory with geom shaders and driver with full layer support
could do that in one go. */
layer = i;
/* XXX hmm really? */
rcoord = (float)layer / (float)nr_layers + 1.0f / (float)(nr_layers * 2);
} else if (pt->target == PIPE_TEXTURE_2D_ARRAY || pt->target == PIPE_TEXTURE_1D_ARRAY) {
layer = i;
rcoord = (float)layer;
} else
layer = face;
 
u_surface_default_template(&surf_templ, pt);
surf_templ.u.tex.level = dstLevel;
surf_templ.u.tex.first_layer = layer;
surf_templ.u.tex.last_layer = layer;
surf = pipe->create_surface(pipe, pt, &surf_templ);
 
/*
* Setup framebuffer / dest surface
*/
if (is_depth) {
fb.nr_cbufs = 0;
fb.zsbuf = surf;
}
else {
fb.nr_cbufs = 1;
fb.cbufs[0] = surf;
}
fb.width = u_minify(pt->width0, dstLevel);
fb.height = u_minify(pt->height0, dstLevel);
cso_set_framebuffer(ctx->cso, &fb);
 
/* viewport */
vp.scale[0] = 0.5f * fb.width;
vp.scale[1] = 0.5f * fb.height;
vp.scale[2] = 1.0f;
vp.scale[3] = 1.0f;
vp.translate[0] = 0.5f * fb.width;
vp.translate[1] = 0.5f * fb.height;
vp.translate[2] = 0.0f;
vp.translate[3] = 0.0f;
cso_set_viewport(ctx->cso, &vp);
 
/*
* Setup sampler state
* Note: we should only have to set the min/max LOD clamps to ensure
* we grab texels from the right mipmap level. But some hardware
* has trouble with min clamping so we also set the lod_bias to
* try to work around that.
*/
ctx->sampler.min_lod = ctx->sampler.max_lod = (float) srcLevel;
ctx->sampler.lod_bias = (float) srcLevel;
cso_single_sampler(ctx->cso, PIPE_SHADER_FRAGMENT, 0, &ctx->sampler);
cso_single_sampler_done(ctx->cso, PIPE_SHADER_FRAGMENT);
 
cso_set_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT, 1, &psv);
 
/* quad coords in clip coords */
offset = set_vertex_data(ctx,
pt->target,
face,
rcoord);
 
util_draw_vertex_buffer(ctx->pipe,
ctx->cso,
ctx->vbuf,
cso_get_aux_vertex_buffer_slot(ctx->cso),
offset,
PIPE_PRIM_TRIANGLE_FAN,
4, /* verts */
2); /* attribs/vert */
 
/* need to signal that the texture has changed _after_ rendering to it */
pipe_surface_reference( &surf, NULL );
}
}
 
/* restore state we changed */
cso_restore_blend(ctx->cso);
cso_restore_depth_stencil_alpha(ctx->cso);
cso_restore_rasterizer(ctx->cso);
cso_restore_sample_mask(ctx->cso);
cso_restore_samplers(ctx->cso, PIPE_SHADER_FRAGMENT);
cso_restore_sampler_views(ctx->cso, PIPE_SHADER_FRAGMENT);
cso_restore_framebuffer(ctx->cso);
cso_restore_fragment_shader(ctx->cso);
cso_restore_vertex_shader(ctx->cso);
cso_restore_geometry_shader(ctx->cso);
cso_restore_viewport(ctx->cso);
cso_restore_vertex_elements(ctx->cso);
cso_restore_stream_outputs(ctx->cso);
cso_restore_aux_vertex_buffer_slot(ctx->cso);
cso_restore_render_condition(ctx->cso);
}
/drivers/video/Gallium/auxiliary/util/u_gen_mipmap.h
0,0 → 1,64
/**************************************************************************
*
* 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.
*
**************************************************************************/
 
#ifndef U_GENMIPMAP_H
#define U_GENMIPMAP_H
 
#include "pipe/p_state.h"
 
 
#ifdef __cplusplus
extern "C" {
#endif
 
struct pipe_context;
struct pipe_resource;
struct cso_context;
 
struct gen_mipmap_state;
 
 
extern struct gen_mipmap_state *
util_create_gen_mipmap(struct pipe_context *pipe, struct cso_context *cso);
 
 
extern void
util_destroy_gen_mipmap(struct gen_mipmap_state *ctx);
 
 
extern void
util_gen_mipmap(struct gen_mipmap_state *ctx,
struct pipe_sampler_view *psv,
uint layer, uint baseLevel, uint lastLevel, uint filter);
 
 
#ifdef __cplusplus
}
#endif
 
#endif
/drivers/video/Gallium/auxiliary/util/u_half.h
0,0 → 1,123
/**************************************************************************
*
* Copyright 2010 Luca Barbieri
*
* 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, sublicense, 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 NONINFRINGEMENT.
* IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
*
**************************************************************************/
 
 
#ifndef U_HALF_H
#define U_HALF_H
 
#include "pipe/p_compiler.h"
#include "util/u_math.h"
 
#ifdef __cplusplus
extern "C" {
#endif
 
/*
* References for float <-> half conversions
*
* http://fgiesen.wordpress.com/2012/03/28/half-to-float-done-quic/
* https://gist.github.com/2156668
* https://gist.github.com/2144712
*/
 
static INLINE uint16_t
util_float_to_half(float f)
{
uint32_t sign_mask = 0x80000000;
uint32_t round_mask = ~0xfff;
uint32_t f32inf = 0xff << 23;
uint32_t f16inf = 0x1f << 23;
uint32_t sign;
union fi magic;
union fi f32;
uint16_t f16;
 
magic.ui = 0xf << 23;
 
f32.f = f;
 
/* Sign */
sign = f32.ui & sign_mask;
f32.ui ^= sign;
 
if (f32.ui == f32inf) {
/* Inf */
f16 = 0x7c00;
} else if (f32.ui > f32inf) {
/* NaN */
f16 = 0x7e00;
} else {
/* Number */
f32.ui &= round_mask;
f32.f *= magic.f;
f32.ui -= round_mask;
 
/* Clamp to infinity if overflowed */
if (f32.ui > f16inf)
f32.ui = f16inf;
 
f16 = f32.ui >> 13;
}
 
/* Sign */
f16 |= sign >> 16;
 
return f16;
}
 
static INLINE float
util_half_to_float(uint16_t f16)
{
union fi infnan;
union fi magic;
union fi f32;
 
infnan.ui = 0x8f << 23;
infnan.f = 65536.0f;
magic.ui = 0xef << 23;
 
/* Exponent / Mantissa */
f32.ui = (f16 & 0x7fff) << 13;
 
/* Adjust */
f32.f *= magic.f;
 
/* Inf / NaN */
if (f32.f >= infnan.f)
f32.ui |= 0xff << 23;
 
/* Sign */
f32.ui |= (f16 & 0x8000) << 16;
 
return f32.f;
}
 
#ifdef __cplusplus
}
#endif
 
#endif /* U_HALF_H */
 
/drivers/video/Gallium/auxiliary/util/u_handle_table.c
0,0 → 1,298
/**************************************************************************
*
* 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
* Generic handle table implementation.
*
* @author José Fonseca <jrfonseca@tungstengraphics.com>
*/
 
 
#include "pipe/p_compiler.h"
#include "util/u_debug.h"
 
#include "util/u_memory.h"
#include "util/u_handle_table.h"
 
 
#define HANDLE_TABLE_INITIAL_SIZE 16
 
 
struct handle_table
{
/** Object array. Empty handles have a null object */
void **objects;
/** Number of objects the handle can currently hold */
unsigned size;
/** Number of consecutive objects allocated at the start of the table */
unsigned filled;
/** Optional object destructor */
void (*destroy)(void *object);
};
 
 
struct handle_table *
handle_table_create(void)
{
struct handle_table *ht;
ht = MALLOC_STRUCT(handle_table);
if(!ht)
return NULL;
ht->objects = (void **)CALLOC(HANDLE_TABLE_INITIAL_SIZE, sizeof(void *));
if(!ht->objects) {
FREE(ht);
return NULL;
}
ht->size = HANDLE_TABLE_INITIAL_SIZE;
ht->filled = 0;
ht->destroy = NULL;
return ht;
}
 
 
void
handle_table_set_destroy(struct handle_table *ht,
void (*destroy)(void *object))
{
assert(ht);
if (!ht)
return;
ht->destroy = destroy;
}
 
 
/**
* Resize the table if necessary
*/
static INLINE int
handle_table_resize(struct handle_table *ht,
unsigned minimum_size)
{
unsigned new_size;
void **new_objects;
 
if(ht->size > minimum_size)
return ht->size;
 
new_size = ht->size;
while(!(new_size > minimum_size))
new_size *= 2;
assert(new_size);
new_objects = (void **)REALLOC((void *)ht->objects,
ht->size*sizeof(void *),
new_size*sizeof(void *));
if(!new_objects)
return 0;
memset(new_objects + ht->size, 0, (new_size - ht->size)*sizeof(void *));
ht->size = new_size;
ht->objects = new_objects;
return ht->size;
}
 
 
static INLINE void
handle_table_clear(struct handle_table *ht,
unsigned index)
{
void *object;
/* The order here is important so that the object being destroyed is not
* present in the table when seen by the destroy callback, because the
* destroy callback may directly or indirectly call the other functions in
* this module.
*/
 
object = ht->objects[index];
if(object) {
ht->objects[index] = NULL;
if(ht->destroy)
ht->destroy(object);
}
}
 
 
unsigned
handle_table_add(struct handle_table *ht,
void *object)
{
unsigned index;
unsigned handle;
assert(ht);
assert(object);
if(!object || !ht)
return 0;
 
/* linear search for an empty handle */
while(ht->filled < ht->size) {
if(!ht->objects[ht->filled])
break;
++ht->filled;
}
index = ht->filled;
handle = index + 1;
/* check integer overflow */
if(!handle)
return 0;
/* grow the table if necessary */
if(!handle_table_resize(ht, index))
return 0;
 
assert(!ht->objects[index]);
ht->objects[index] = object;
++ht->filled;
return handle;
}
 
 
unsigned
handle_table_set(struct handle_table *ht,
unsigned handle,
void *object)
{
unsigned index;
assert(ht);
assert(handle);
if(!handle || !ht)
return 0;
 
assert(object);
if(!object)
return 0;
index = handle - 1;
 
/* grow the table if necessary */
if(!handle_table_resize(ht, index))
return 0;
 
handle_table_clear(ht, index);
 
ht->objects[index] = object;
return handle;
}
 
 
void *
handle_table_get(struct handle_table *ht,
unsigned handle)
{
void *object;
assert(ht);
assert(handle);
if(!handle || !ht || handle > ht->size)
return NULL;
 
object = ht->objects[handle - 1];
return object;
}
 
 
void
handle_table_remove(struct handle_table *ht,
unsigned handle)
{
void *object;
unsigned index;
assert(ht);
assert(handle);
if(!handle || !ht || handle > ht->size)
return;
 
index = handle - 1;
object = ht->objects[index];
if(!object)
return;
handle_table_clear(ht, index);
 
if(index < ht->filled)
ht->filled = index;
}
 
 
unsigned
handle_table_get_next_handle(struct handle_table *ht,
unsigned handle)
{
unsigned index;
for(index = handle; index < ht->size; ++index) {
if(ht->objects[index])
return index + 1;
}
 
return 0;
}
 
 
unsigned
handle_table_get_first_handle(struct handle_table *ht)
{
return handle_table_get_next_handle(ht, 0);
}
 
 
void
handle_table_destroy(struct handle_table *ht)
{
unsigned index;
assert(ht);
 
if (!ht)
return;
 
if(ht->destroy)
for(index = 0; index < ht->size; ++index)
handle_table_clear(ht, index);
FREE(ht->objects);
FREE(ht);
}
 
/drivers/video/Gallium/auxiliary/util/u_handle_table.h
0,0 → 1,116
/**************************************************************************
*
* 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
* Generic handle table.
*
* @author José Fonseca <jrfonseca@tungstengraphics.com>
*/
 
#ifndef U_HANDLE_TABLE_H_
#define U_HANDLE_TABLE_H_
 
 
#ifdef __cplusplus
extern "C" {
#endif
 
/**
* Abstract data type to map integer handles to objects.
*
* Also referred as "pointer array".
*/
struct handle_table;
 
 
struct handle_table *
handle_table_create(void);
 
 
/**
* Set an optional destructor callback.
*
* If set, it will be called during handle_table_remove and
* handle_table_destroy calls.
*/
void
handle_table_set_destroy(struct handle_table *ht,
void (*destroy)(void *object));
 
 
/**
* Add a new object.
*
* Returns a zero handle on failure (out of memory).
*/
unsigned
handle_table_add(struct handle_table *ht,
void *object);
 
/**
* Returns zero on failure (out of memory).
*/
unsigned
handle_table_set(struct handle_table *ht,
unsigned handle,
void *object);
 
/**
* Fetch an existing object.
*
* Returns NULL for an invalid handle.
*/
void *
handle_table_get(struct handle_table *ht,
unsigned handle);
 
 
void
handle_table_remove(struct handle_table *ht,
unsigned handle);
 
 
void
handle_table_destroy(struct handle_table *ht);
 
 
unsigned
handle_table_get_first_handle(struct handle_table *ht);
 
 
unsigned
handle_table_get_next_handle(struct handle_table *ht,
unsigned handle);
 
 
#ifdef __cplusplus
}
#endif
 
#endif /* U_HANDLE_TABLE_H_ */
/drivers/video/Gallium/auxiliary/util/u_hash.c
0,0 → 1,121
/**************************************************************************
*
* Copyright 2008 VMware, Inc.
* 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 VMWARE 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
* Hash functions implementation.
*
* @author Jose Fonseca
*/
 
 
#include "u_hash.h"
 
 
static const uint32_t
util_crc32_table[256] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
 
 
/**
* @sa http://www.w3.org/TR/PNG/#D-CRCAppendix
*/
uint32_t
util_hash_crc32(const void *data, size_t size)
{
uint8_t *p = (uint8_t *)data;
uint32_t crc = 0xffffffff;
while (size--)
crc = util_crc32_table[(crc ^ *p++) & 0xff] ^ (crc >> 8);
return crc;
}
/drivers/video/Gallium/auxiliary/util/u_hash.h
0,0 → 1,55
/**************************************************************************
*
* Copyright 2008 VMware, Inc.
* 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 VMWARE 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
* Hash functions.
*
* @author Jose Fonseca <jfonseca@vmware.com>
*/
 
#ifndef U_HASH_H_
#define U_HASH_H_
 
 
#include "pipe/p_compiler.h"
 
 
#ifdef __cplusplus
extern "C" {
#endif
 
uint32_t
util_hash_crc32(const void *data, size_t size);
 
 
#ifdef __cplusplus
}
#endif
 
#endif /* U_HASH_H_ */
/drivers/video/Gallium/auxiliary/util/u_hash_table.c
0,0 → 1,293
/**************************************************************************
*
* 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
* General purpose hash table implementation.
*
* Just uses the cso_hash for now, but it might be better switch to a linear
* probing hash table implementation at some point -- as it is said they have
* better lookup and cache performance and it appears to be possible to write
* a lock-free implementation of such hash tables .
*
* @author José Fonseca <jrfonseca@tungstengraphics.com>
*/
 
 
#include "pipe/p_compiler.h"
#include "util/u_debug.h"
 
#include "cso_cache/cso_hash.h"
 
#include "util/u_memory.h"
#include "util/u_hash_table.h"
 
 
struct util_hash_table
{
struct cso_hash *cso;
/** Hash function */
unsigned (*hash)(void *key);
/** Compare two keys */
int (*compare)(void *key1, void *key2);
/* TODO: key, value destructors? */
};
 
 
struct util_hash_table_item
{
void *key;
void *value;
};
 
 
static INLINE struct util_hash_table_item *
util_hash_table_item(struct cso_hash_iter iter)
{
return (struct util_hash_table_item *)cso_hash_iter_data(iter);
}
 
 
struct util_hash_table *
util_hash_table_create(unsigned (*hash)(void *key),
int (*compare)(void *key1, void *key2))
{
struct util_hash_table *ht;
ht = MALLOC_STRUCT(util_hash_table);
if(!ht)
return NULL;
ht->cso = cso_hash_create();
if(!ht->cso) {
FREE(ht);
return NULL;
}
ht->hash = hash;
ht->compare = compare;
return ht;
}
 
 
static INLINE struct cso_hash_iter
util_hash_table_find_iter(struct util_hash_table *ht,
void *key,
unsigned key_hash)
{
struct cso_hash_iter iter;
struct util_hash_table_item *item;
iter = cso_hash_find(ht->cso, key_hash);
while (!cso_hash_iter_is_null(iter)) {
item = (struct util_hash_table_item *)cso_hash_iter_data(iter);
if (!ht->compare(item->key, key))
break;
iter = cso_hash_iter_next(iter);
}
return iter;
}
 
 
static INLINE struct util_hash_table_item *
util_hash_table_find_item(struct util_hash_table *ht,
void *key,
unsigned key_hash)
{
struct cso_hash_iter iter;
struct util_hash_table_item *item;
iter = cso_hash_find(ht->cso, key_hash);
while (!cso_hash_iter_is_null(iter)) {
item = (struct util_hash_table_item *)cso_hash_iter_data(iter);
if (!ht->compare(item->key, key))
return item;
iter = cso_hash_iter_next(iter);
}
return NULL;
}
 
 
enum pipe_error
util_hash_table_set(struct util_hash_table *ht,
void *key,
void *value)
{
unsigned key_hash;
struct util_hash_table_item *item;
struct cso_hash_iter iter;
 
assert(ht);
if (!ht)
return PIPE_ERROR_BAD_INPUT;
 
key_hash = ht->hash(key);
 
item = util_hash_table_find_item(ht, key, key_hash);
if(item) {
/* TODO: key/value destruction? */
item->value = value;
return PIPE_OK;
}
item = MALLOC_STRUCT(util_hash_table_item);
if(!item)
return PIPE_ERROR_OUT_OF_MEMORY;
item->key = key;
item->value = value;
iter = cso_hash_insert(ht->cso, key_hash, item);
if(cso_hash_iter_is_null(iter)) {
FREE(item);
return PIPE_ERROR_OUT_OF_MEMORY;
}
 
return PIPE_OK;
}
 
 
void *
util_hash_table_get(struct util_hash_table *ht,
void *key)
{
unsigned key_hash;
struct util_hash_table_item *item;
 
assert(ht);
if (!ht)
return NULL;
 
key_hash = ht->hash(key);
 
item = util_hash_table_find_item(ht, key, key_hash);
if(!item)
return NULL;
return item->value;
}
 
 
void
util_hash_table_remove(struct util_hash_table *ht,
void *key)
{
unsigned key_hash;
struct cso_hash_iter iter;
struct util_hash_table_item *item;
 
assert(ht);
if (!ht)
return;
 
key_hash = ht->hash(key);
 
iter = util_hash_table_find_iter(ht, key, key_hash);
if(cso_hash_iter_is_null(iter))
return;
item = util_hash_table_item(iter);
assert(item);
FREE(item);
cso_hash_erase(ht->cso, iter);
}
 
 
void
util_hash_table_clear(struct util_hash_table *ht)
{
struct cso_hash_iter iter;
struct util_hash_table_item *item;
 
assert(ht);
if (!ht)
return;
 
iter = cso_hash_first_node(ht->cso);
while (!cso_hash_iter_is_null(iter)) {
item = (struct util_hash_table_item *)cso_hash_take(ht->cso, cso_hash_iter_key(iter));
FREE(item);
iter = cso_hash_first_node(ht->cso);
}
}
 
 
enum pipe_error
util_hash_table_foreach(struct util_hash_table *ht,
enum pipe_error (*callback)
(void *key, void *value, void *data),
void *data)
{
struct cso_hash_iter iter;
struct util_hash_table_item *item;
enum pipe_error result;
 
assert(ht);
if (!ht)
return PIPE_ERROR_BAD_INPUT;
 
iter = cso_hash_first_node(ht->cso);
while (!cso_hash_iter_is_null(iter)) {
item = (struct util_hash_table_item *)cso_hash_iter_data(iter);
result = callback(item->key, item->value, data);
if(result != PIPE_OK)
return result;
iter = cso_hash_iter_next(iter);
}
 
return PIPE_OK;
}
 
 
void
util_hash_table_destroy(struct util_hash_table *ht)
{
struct cso_hash_iter iter;
struct util_hash_table_item *item;
 
assert(ht);
if (!ht)
return;
 
iter = cso_hash_first_node(ht->cso);
while (!cso_hash_iter_is_null(iter)) {
item = (struct util_hash_table_item *)cso_hash_iter_data(iter);
FREE(item);
iter = cso_hash_iter_next(iter);
}
 
cso_hash_delete(ht->cso);
FREE(ht);
}
/drivers/video/Gallium/auxiliary/util/u_hash_table.h
0,0 → 1,96
/**************************************************************************
*
* 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.
*
**************************************************************************/
 
/**
* General purpose hash table.
*
* @author José Fonseca <jrfonseca@tungstengraphics.com>
*/
 
#ifndef U_HASH_TABLE_H_
#define U_HASH_TABLE_H_
 
 
#include "pipe/p_defines.h"
 
 
#ifdef __cplusplus
extern "C" {
#endif
 
/**
* Generic purpose hash table.
*/
struct util_hash_table;
 
 
/**
* Create an hash table.
*
* @param hash hash function
* @param compare should return 0 for two equal keys.
*/
struct util_hash_table *
util_hash_table_create(unsigned (*hash)(void *key),
int (*compare)(void *key1, void *key2));
 
 
enum pipe_error
util_hash_table_set(struct util_hash_table *ht,
void *key,
void *value);
 
void *
util_hash_table_get(struct util_hash_table *ht,
void *key);
 
 
void
util_hash_table_remove(struct util_hash_table *ht,
void *key);
 
 
void
util_hash_table_clear(struct util_hash_table *ht);
 
 
enum pipe_error
util_hash_table_foreach(struct util_hash_table *ht,
enum pipe_error (*callback)
(void *key, void *value, void *data),
void *data);
 
void
util_hash_table_destroy(struct util_hash_table *ht);
 
 
#ifdef __cplusplus
}
#endif
 
#endif /* U_HASH_TABLE_H_ */
/drivers/video/Gallium/auxiliary/util/u_helpers.c
0,0 → 1,90
/**************************************************************************
*
* Copyright 2012 Marek Olšák <maraeo@gmail.com>
* 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 THE AUTHORS AND/OR THEIR 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.
*
**************************************************************************/
 
#include "util/u_helpers.h"
#include "util/u_inlines.h"
 
/**
* This function is used to copy an array of pipe_vertex_buffer structures,
* while properly referencing the pipe_vertex_buffer::buffer member.
*
* enabled_buffers is updated such that the bits corresponding to the indices
* of disabled buffers are set to 0 and the enabled ones are set to 1.
*
* \sa util_copy_framebuffer_state
*/
void util_set_vertex_buffers_mask(struct pipe_vertex_buffer *dst,
uint32_t *enabled_buffers,
const struct pipe_vertex_buffer *src,
unsigned start_slot, unsigned count)
{
unsigned i;
uint32_t bitmask = 0;
 
dst += start_slot;
 
if (src) {
for (i = 0; i < count; i++) {
if (src[i].buffer || src[i].user_buffer) {
bitmask |= 1 << i;
}
pipe_resource_reference(&dst[i].buffer, src[i].buffer);
}
 
/* Copy over the other members of pipe_vertex_buffer. */
memcpy(dst, src, count * sizeof(struct pipe_vertex_buffer));
 
*enabled_buffers &= ~(((1ull << count) - 1) << start_slot);
*enabled_buffers |= bitmask << start_slot;
}
else {
/* Unreference the buffers. */
for (i = 0; i < count; i++) {
pipe_resource_reference(&dst[i].buffer, NULL);
dst[i].user_buffer = NULL;
}
 
*enabled_buffers &= ~(((1ull << count) - 1) << start_slot);
}
}
 
/**
* Same as util_set_vertex_buffers_mask, but it only returns the number
* of bound buffers.
*/
void util_set_vertex_buffers_count(struct pipe_vertex_buffer *dst,
unsigned *dst_count,
const struct pipe_vertex_buffer *src,
unsigned start_slot, unsigned count)
{
uint32_t enabled_buffers = (1ull << *dst_count) - 1;
 
util_set_vertex_buffers_mask(dst, &enabled_buffers, src, start_slot,
count);
 
*dst_count = util_last_bit(enabled_buffers);
}
/drivers/video/Gallium/auxiliary/util/u_helpers.h
0,0 → 1,51
/**************************************************************************
*
* Copyright 2012 Marek Olšák <maraeo@gmail.com>
* 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 THE AUTHORS AND/OR THEIR 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.
*
**************************************************************************/
 
#ifndef U_HELPERS_H
#define U_HELPERS_H
 
#ifdef __cplusplus
extern "C" {
#endif
 
#include "pipe/p_state.h"
 
void util_set_vertex_buffers_mask(struct pipe_vertex_buffer *dst,
uint32_t *enabled_buffers,
const struct pipe_vertex_buffer *src,
unsigned start_slot, unsigned count);
 
void util_set_vertex_buffers_count(struct pipe_vertex_buffer *dst,
unsigned *dst_count,
const struct pipe_vertex_buffer *src,
unsigned start_slot, unsigned count);
 
#ifdef __cplusplus
}
#endif
 
#endif
/drivers/video/Gallium/auxiliary/util/u_index_modify.c
0,0 → 1,203
/*
* Copyright 2010 Marek Olšák <maraeo@gmail.com>
*
* 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
* on 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
* THE AUTHOR(S) AND/OR THEIR 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. */
 
#include "pipe/p_context.h"
#include "util/u_index_modify.h"
#include "util/u_inlines.h"
 
/* Ubyte indices. */
 
void util_shorten_ubyte_elts_to_userptr(struct pipe_context *context,
struct pipe_index_buffer *ib,
int index_bias,
unsigned start,
unsigned count,
void *out)
{
struct pipe_transfer *src_transfer = NULL;
const unsigned char *in_map;
unsigned short *out_map = out;
unsigned i;
 
if (ib->user_buffer) {
in_map = ib->user_buffer;
} else {
in_map = pipe_buffer_map(context, ib->buffer,
PIPE_TRANSFER_READ |
PIPE_TRANSFER_UNSYNCHRONIZED,
&src_transfer);
}
in_map += start;
 
for (i = 0; i < count; i++) {
*out_map = (unsigned short)(*in_map + index_bias);
in_map++;
out_map++;
}
 
if (src_transfer)
pipe_buffer_unmap(context, src_transfer);
}
 
void util_shorten_ubyte_elts(struct pipe_context *context,
struct pipe_index_buffer *ib,
struct pipe_resource **out_buf,
int index_bias,
unsigned start,
unsigned count)
{
struct pipe_resource* new_elts;
unsigned short *out_map;
struct pipe_transfer *dst_transfer;
 
new_elts = pipe_buffer_create(context->screen,
PIPE_BIND_INDEX_BUFFER,
PIPE_USAGE_STATIC,
2 * count);
 
out_map = pipe_buffer_map(context, new_elts, PIPE_TRANSFER_WRITE,
&dst_transfer);
util_shorten_ubyte_elts_to_userptr(context, ib, index_bias,
start, count, out_map);
pipe_buffer_unmap(context, dst_transfer);
 
pipe_resource_reference(out_buf, NULL);
*out_buf = new_elts;
}
 
 
/* Ushort indices. */
 
void util_rebuild_ushort_elts_to_userptr(struct pipe_context *context,
struct pipe_index_buffer *ib,
int index_bias,
unsigned start, unsigned count,
void *out)
{
struct pipe_transfer *in_transfer = NULL;
const unsigned short *in_map;
unsigned short *out_map = out;
unsigned i;
 
if (ib->user_buffer) {
in_map = ib->user_buffer;
} else {
in_map = pipe_buffer_map(context, ib->buffer,
PIPE_TRANSFER_READ |
PIPE_TRANSFER_UNSYNCHRONIZED,
&in_transfer);
}
in_map += start;
 
for (i = 0; i < count; i++) {
*out_map = (unsigned short)(*in_map + index_bias);
in_map++;
out_map++;
}
 
if (in_transfer)
pipe_buffer_unmap(context, in_transfer);
}
 
void util_rebuild_ushort_elts(struct pipe_context *context,
struct pipe_index_buffer *ib,
struct pipe_resource **out_buf,
int index_bias,
unsigned start, unsigned count)
{
struct pipe_transfer *out_transfer = NULL;
struct pipe_resource *new_elts;
unsigned short *out_map;
 
new_elts = pipe_buffer_create(context->screen,
PIPE_BIND_INDEX_BUFFER,
PIPE_USAGE_STATIC,
2 * count);
 
out_map = pipe_buffer_map(context, new_elts,
PIPE_TRANSFER_WRITE, &out_transfer);
util_rebuild_ushort_elts_to_userptr(context, ib, index_bias,
start, count, out_map);
pipe_buffer_unmap(context, out_transfer);
 
pipe_resource_reference(out_buf, NULL);
*out_buf = new_elts;
}
 
 
/* Uint indices. */
 
void util_rebuild_uint_elts_to_userptr(struct pipe_context *context,
struct pipe_index_buffer *ib,
int index_bias,
unsigned start, unsigned count,
void *out)
{
struct pipe_transfer *in_transfer = NULL;
const unsigned int *in_map;
unsigned int *out_map = out;
unsigned i;
 
if (ib->user_buffer) {
in_map = ib->user_buffer;
} else {
in_map = pipe_buffer_map(context, ib->buffer,
PIPE_TRANSFER_READ |
PIPE_TRANSFER_UNSYNCHRONIZED,
&in_transfer);
}
in_map += start;
 
for (i = 0; i < count; i++) {
*out_map = (unsigned int)(*in_map + index_bias);
in_map++;
out_map++;
}
 
if (in_transfer)
pipe_buffer_unmap(context, in_transfer);
}
 
void util_rebuild_uint_elts(struct pipe_context *context,
struct pipe_index_buffer *ib,
struct pipe_resource **out_buf,
int index_bias,
unsigned start, unsigned count)
{
struct pipe_transfer *out_transfer = NULL;
struct pipe_resource *new_elts;
unsigned int *out_map;
 
new_elts = pipe_buffer_create(context->screen,
PIPE_BIND_INDEX_BUFFER,
PIPE_USAGE_STATIC,
2 * count);
 
out_map = pipe_buffer_map(context, new_elts,
PIPE_TRANSFER_WRITE, &out_transfer);
util_rebuild_uint_elts_to_userptr(context, ib, index_bias,
start, count, out_map);
pipe_buffer_unmap(context, out_transfer);
 
pipe_resource_reference(out_buf, NULL);
*out_buf = new_elts;
}
/drivers/video/Gallium/auxiliary/util/u_index_modify.h
0,0 → 1,72
/*
* Copyright 2010 Marek Olšák <maraeo@gmail.com>
*
* 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
* on 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
* THE AUTHOR(S) AND/OR THEIR 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. */
 
#ifndef UTIL_INDEX_MODIFY_H
#define UTIL_INDEX_MODIFY_H
 
struct pipe_context;
struct pipe_resource;
struct pipe_index_buffer;
 
void util_shorten_ubyte_elts_to_userptr(struct pipe_context *context,
struct pipe_index_buffer *ib,
int index_bias,
unsigned start,
unsigned count,
void *out);
 
void util_shorten_ubyte_elts(struct pipe_context *context,
struct pipe_index_buffer *ib,
struct pipe_resource **out_buf,
int index_bias,
unsigned start,
unsigned count);
 
 
 
void util_rebuild_ushort_elts_to_userptr(struct pipe_context *context,
struct pipe_index_buffer *ib,
int index_bias,
unsigned start, unsigned count,
void *out);
 
void util_rebuild_ushort_elts(struct pipe_context *context,
struct pipe_index_buffer *ib,
struct pipe_resource **out_buf,
int index_bias,
unsigned start, unsigned count);
 
 
 
void util_rebuild_uint_elts_to_userptr(struct pipe_context *context,
struct pipe_index_buffer *ib,
int index_bias,
unsigned start, unsigned count,
void *out);
 
void util_rebuild_uint_elts(struct pipe_context *context,
struct pipe_index_buffer *ib,
struct pipe_resource **out_buf,
int index_bias,
unsigned start, unsigned count);
 
#endif
/drivers/video/Gallium/auxiliary/util/u_init.h
0,0 → 1,52
/*
* Copyright 2010 Luca Barbieri
*
* 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, sublicense, 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 NONINFRINGEMENT.
* IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
*
**************************************************************************/
 
#ifndef U_INIT_H
#define U_INIT_H
 
/* Use UTIL_INIT(f) to have f called at program initialization.
Note that it is only guaranteed to be called if any symbol in the
.c file it is in sis referenced by the program.
 
UTIL_INIT functions are called in arbitrary order.
*/
 
#ifdef __cplusplus
/* use a C++ global constructor */
#define UTIL_INIT(f) struct f##__gctor_t {f##__gctor_t() {x();}} f##__gctor;
#elif defined(_MSC_VER)
/* add a pointer to the section where MSVC stores global constructor pointers */
/* see http://blogs.msdn.com/vcblog/archive/2006/10/20/crt-initialization.aspx and
http://stackoverflow.com/questions/1113409/attribute-constructor-equivalent-in-vc */
#pragma section(".CRT$XCU",read)
#define UTIL_INIT(f) static void __cdecl f##__init(void) {f();}; __declspec(allocate(".CRT$XCU")) void (__cdecl* f##__xcu)(void) = f##__init;
#elif defined(__GNUC__)
#define UTIL_INIT(f) static void f##__init(void) __attribute__((constructor)); static void f##__init(void) {f();}
#else
#error Unsupported compiler: please find out how to implement global initializers in C on it
#endif
 
#endif
 
/drivers/video/Gallium/auxiliary/util/u_inlines.h
0,0 → 1,605
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
#ifndef U_INLINES_H
#define U_INLINES_H
 
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "pipe/p_shader_tokens.h"
#include "pipe/p_state.h"
#include "pipe/p_screen.h"
#include "util/u_debug.h"
#include "util/u_debug_describe.h"
#include "util/u_debug_refcnt.h"
#include "util/u_atomic.h"
#include "util/u_box.h"
#include "util/u_math.h"
 
 
#ifdef __cplusplus
extern "C" {
#endif
 
 
/*
* Reference counting helper functions.
*/
 
 
static INLINE void
pipe_reference_init(struct pipe_reference *reference, unsigned count)
{
p_atomic_set(&reference->count, count);
}
 
static INLINE boolean
pipe_is_referenced(struct pipe_reference *reference)
{
return p_atomic_read(&reference->count) != 0;
}
 
/**
* Update reference counting.
* The old thing pointed to, if any, will be unreferenced.
* Both 'ptr' and 'reference' may be NULL.
* \return TRUE if the object's refcount hits zero and should be destroyed.
*/
static INLINE boolean
pipe_reference_described(struct pipe_reference *ptr,
struct pipe_reference *reference,
debug_reference_descriptor get_desc)
{
boolean destroy = FALSE;
 
if(ptr != reference) {
/* bump the reference.count first */
if (reference) {
assert(pipe_is_referenced(reference));
p_atomic_inc(&reference->count);
debug_reference(reference, get_desc, 1);
}
 
if (ptr) {
assert(pipe_is_referenced(ptr));
if (p_atomic_dec_zero(&ptr->count)) {
destroy = TRUE;
}
debug_reference(ptr, get_desc, -1);
}
}
 
return destroy;
}
 
static INLINE boolean
pipe_reference(struct pipe_reference *ptr, struct pipe_reference *reference)
{
return pipe_reference_described(ptr, reference,
(debug_reference_descriptor)debug_describe_reference);
}
 
static INLINE void
pipe_surface_reference(struct pipe_surface **ptr, struct pipe_surface *surf)
{
struct pipe_surface *old_surf = *ptr;
 
if (pipe_reference_described(&(*ptr)->reference, &surf->reference,
(debug_reference_descriptor)debug_describe_surface))
old_surf->context->surface_destroy(old_surf->context, old_surf);
*ptr = surf;
}
 
/**
* Similar to pipe_surface_reference() but always set the pointer to NULL
* and pass in an explicit context. The explicit context avoids the problem
* of using a deleted context's surface_destroy() method when freeing a surface
* that's shared by multiple contexts.
*/
static INLINE void
pipe_surface_release(struct pipe_context *pipe, struct pipe_surface **ptr)
{
if (pipe_reference_described(&(*ptr)->reference, NULL,
(debug_reference_descriptor)debug_describe_surface))
pipe->surface_destroy(pipe, *ptr);
*ptr = NULL;
}
 
 
static INLINE void
pipe_resource_reference(struct pipe_resource **ptr, struct pipe_resource *tex)
{
struct pipe_resource *old_tex = *ptr;
 
if (pipe_reference_described(&(*ptr)->reference, &tex->reference,
(debug_reference_descriptor)debug_describe_resource))
old_tex->screen->resource_destroy(old_tex->screen, old_tex);
*ptr = tex;
}
 
static INLINE void
pipe_sampler_view_reference(struct pipe_sampler_view **ptr, struct pipe_sampler_view *view)
{
struct pipe_sampler_view *old_view = *ptr;
 
if (pipe_reference_described(&(*ptr)->reference, &view->reference,
(debug_reference_descriptor)debug_describe_sampler_view))
old_view->context->sampler_view_destroy(old_view->context, old_view);
*ptr = view;
}
 
/**
* Similar to pipe_sampler_view_reference() but always set the pointer to
* NULL and pass in an explicit context. Passing an explicit context is a
* work-around for fixing a dangling context pointer problem when textures
* are shared by multiple contexts. XXX fix this someday.
*/
static INLINE void
pipe_sampler_view_release(struct pipe_context *ctx,
struct pipe_sampler_view **ptr)
{
struct pipe_sampler_view *old_view = *ptr;
if (*ptr && (*ptr)->context != ctx) {
debug_printf_once(("context mis-match in pipe_sampler_view_release()\n"));
}
if (pipe_reference_described(&(*ptr)->reference, NULL,
(debug_reference_descriptor)debug_describe_sampler_view)) {
ctx->sampler_view_destroy(ctx, old_view);
}
*ptr = NULL;
}
 
 
static INLINE void
pipe_so_target_reference(struct pipe_stream_output_target **ptr,
struct pipe_stream_output_target *target)
{
struct pipe_stream_output_target *old = *ptr;
 
if (pipe_reference_described(&(*ptr)->reference, &target->reference,
(debug_reference_descriptor)debug_describe_so_target))
old->context->stream_output_target_destroy(old->context, old);
*ptr = target;
}
 
static INLINE void
pipe_surface_reset(struct pipe_context *ctx, struct pipe_surface* ps,
struct pipe_resource *pt, unsigned level, unsigned layer)
{
pipe_resource_reference(&ps->texture, pt);
ps->format = pt->format;
ps->width = u_minify(pt->width0, level);
ps->height = u_minify(pt->height0, level);
ps->u.tex.level = level;
ps->u.tex.first_layer = ps->u.tex.last_layer = layer;
ps->context = ctx;
}
 
static INLINE void
pipe_surface_init(struct pipe_context *ctx, struct pipe_surface* ps,
struct pipe_resource *pt, unsigned level, unsigned layer)
{
ps->texture = 0;
pipe_reference_init(&ps->reference, 1);
pipe_surface_reset(ctx, ps, pt, level, layer);
}
 
/* Return true if the surfaces are equal. */
static INLINE boolean
pipe_surface_equal(struct pipe_surface *s1, struct pipe_surface *s2)
{
return s1->texture == s2->texture &&
s1->format == s2->format &&
(s1->texture->target != PIPE_BUFFER ||
(s1->u.buf.first_element == s2->u.buf.first_element &&
s1->u.buf.last_element == s2->u.buf.last_element)) &&
(s1->texture->target == PIPE_BUFFER ||
(s1->u.tex.level == s2->u.tex.level &&
s1->u.tex.first_layer == s2->u.tex.first_layer &&
s1->u.tex.last_layer == s2->u.tex.last_layer));
}
 
/*
* Convenience wrappers for screen buffer functions.
*/
 
static INLINE struct pipe_resource *
pipe_buffer_create( struct pipe_screen *screen,
unsigned bind,
unsigned usage,
unsigned size )
{
struct pipe_resource buffer;
memset(&buffer, 0, sizeof buffer);
buffer.target = PIPE_BUFFER;
buffer.format = PIPE_FORMAT_R8_UNORM; /* want TYPELESS or similar */
buffer.bind = bind;
buffer.usage = usage;
buffer.flags = 0;
buffer.width0 = size;
buffer.height0 = 1;
buffer.depth0 = 1;
buffer.array_size = 1;
return screen->resource_create(screen, &buffer);
}
 
static INLINE void *
pipe_buffer_map_range(struct pipe_context *pipe,
struct pipe_resource *buffer,
unsigned offset,
unsigned length,
unsigned usage,
struct pipe_transfer **transfer)
{
struct pipe_box box;
void *map;
 
assert(offset < buffer->width0);
assert(offset + length <= buffer->width0);
assert(length);
 
u_box_1d(offset, length, &box);
 
map = pipe->transfer_map(pipe, buffer, 0, usage, &box, transfer);
if (map == NULL) {
return NULL;
}
 
return map;
}
 
 
static INLINE void *
pipe_buffer_map(struct pipe_context *pipe,
struct pipe_resource *buffer,
unsigned usage,
struct pipe_transfer **transfer)
{
return pipe_buffer_map_range(pipe, buffer, 0, buffer->width0, usage, transfer);
}
 
 
static INLINE void
pipe_buffer_unmap(struct pipe_context *pipe,
struct pipe_transfer *transfer)
{
pipe->transfer_unmap(pipe, transfer);
}
 
static INLINE void
pipe_buffer_flush_mapped_range(struct pipe_context *pipe,
struct pipe_transfer *transfer,
unsigned offset,
unsigned length)
{
struct pipe_box box;
int transfer_offset;
 
assert(length);
assert(transfer->box.x <= (int) offset);
assert((int) (offset + length) <= transfer->box.x + transfer->box.width);
 
/* Match old screen->buffer_flush_mapped_range() behaviour, where
* offset parameter is relative to the start of the buffer, not the
* mapped range.
*/
transfer_offset = offset - transfer->box.x;
 
u_box_1d(transfer_offset, length, &box);
 
pipe->transfer_flush_region(pipe, transfer, &box);
}
 
static INLINE void
pipe_buffer_write(struct pipe_context *pipe,
struct pipe_resource *buf,
unsigned offset,
unsigned size,
const void *data)
{
struct pipe_box box;
unsigned usage = PIPE_TRANSFER_WRITE;
 
if (offset == 0 && size == buf->width0) {
usage |= PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE;
} else {
usage |= PIPE_TRANSFER_DISCARD_RANGE;
}
 
u_box_1d(offset, size, &box);
 
pipe->transfer_inline_write( pipe,
buf,
0,
usage,
&box,
data,
size,
0);
}
 
/**
* Special case for writing non-overlapping ranges.
*
* We can avoid GPU/CPU synchronization when writing range that has never
* been written before.
*/
static INLINE void
pipe_buffer_write_nooverlap(struct pipe_context *pipe,
struct pipe_resource *buf,
unsigned offset, unsigned size,
const void *data)
{
struct pipe_box box;
 
u_box_1d(offset, size, &box);
 
pipe->transfer_inline_write(pipe,
buf,
0,
(PIPE_TRANSFER_WRITE |
PIPE_TRANSFER_UNSYNCHRONIZED),
&box,
data,
0, 0);
}
 
static INLINE struct pipe_resource *
pipe_buffer_create_with_data(struct pipe_context *pipe,
unsigned bind,
unsigned usage,
unsigned size,
void *ptr)
{
struct pipe_resource *res = pipe_buffer_create(pipe->screen,
bind, usage, size);
pipe_buffer_write_nooverlap(pipe, res, 0, size, ptr);
return res;
}
 
static INLINE void
pipe_buffer_read(struct pipe_context *pipe,
struct pipe_resource *buf,
unsigned offset,
unsigned size,
void *data)
{
struct pipe_transfer *src_transfer;
ubyte *map;
 
map = (ubyte *) pipe_buffer_map_range(pipe,
buf,
offset, size,
PIPE_TRANSFER_READ,
&src_transfer);
if (!map)
return;
 
memcpy(data, map, size);
pipe_buffer_unmap(pipe, src_transfer);
}
 
static INLINE void *
pipe_transfer_map(struct pipe_context *context,
struct pipe_resource *resource,
unsigned level, unsigned layer,
enum pipe_transfer_usage usage,
unsigned x, unsigned y,
unsigned w, unsigned h,
struct pipe_transfer **transfer)
{
struct pipe_box box;
u_box_2d_zslice(x, y, layer, w, h, &box);
return context->transfer_map(context,
resource,
level,
usage,
&box, transfer);
}
 
static INLINE void *
pipe_transfer_map_3d(struct pipe_context *context,
struct pipe_resource *resource,
unsigned level,
enum pipe_transfer_usage usage,
unsigned x, unsigned y, unsigned z,
unsigned w, unsigned h, unsigned d,
struct pipe_transfer **transfer)
{
struct pipe_box box;
u_box_3d(x, y, z, w, h, d, &box);
return context->transfer_map(context,
resource,
level,
usage,
&box, transfer);
}
 
static INLINE void
pipe_transfer_unmap( struct pipe_context *context,
struct pipe_transfer *transfer )
{
context->transfer_unmap( context, transfer );
}
 
static INLINE void
pipe_set_constant_buffer(struct pipe_context *pipe, uint shader, uint index,
struct pipe_resource *buf)
{
if (buf) {
struct pipe_constant_buffer cb;
cb.buffer = buf;
cb.buffer_offset = 0;
cb.buffer_size = buf->width0;
cb.user_buffer = NULL;
pipe->set_constant_buffer(pipe, shader, index, &cb);
} else {
pipe->set_constant_buffer(pipe, shader, index, NULL);
}
}
 
 
static INLINE boolean util_get_offset(
const struct pipe_rasterizer_state *templ,
unsigned fill_mode)
{
switch(fill_mode) {
case PIPE_POLYGON_MODE_POINT:
return templ->offset_point;
case PIPE_POLYGON_MODE_LINE:
return templ->offset_line;
case PIPE_POLYGON_MODE_FILL:
return templ->offset_tri;
default:
assert(0);
return FALSE;
}
}
 
static INLINE float
util_get_min_point_size(const struct pipe_rasterizer_state *state)
{
/* The point size should be clamped to this value at the rasterizer stage.
*/
return !state->point_quad_rasterization &&
!state->point_smooth &&
!state->multisample ? 1.0f : 0.0f;
}
 
static INLINE void
util_query_clear_result(union pipe_query_result *result, unsigned type)
{
switch (type) {
case PIPE_QUERY_OCCLUSION_PREDICATE:
case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
case PIPE_QUERY_GPU_FINISHED:
result->b = FALSE;
break;
case PIPE_QUERY_OCCLUSION_COUNTER:
case PIPE_QUERY_TIMESTAMP:
case PIPE_QUERY_TIME_ELAPSED:
case PIPE_QUERY_PRIMITIVES_GENERATED:
case PIPE_QUERY_PRIMITIVES_EMITTED:
result->u64 = 0;
break;
case PIPE_QUERY_SO_STATISTICS:
memset(&result->so_statistics, 0, sizeof(result->so_statistics));
break;
case PIPE_QUERY_TIMESTAMP_DISJOINT:
memset(&result->timestamp_disjoint, 0, sizeof(result->timestamp_disjoint));
break;
case PIPE_QUERY_PIPELINE_STATISTICS:
memset(&result->pipeline_statistics, 0, sizeof(result->pipeline_statistics));
break;
default:
memset(result, 0, sizeof(*result));
}
}
 
/** Convert PIPE_TEXTURE_x to TGSI_TEXTURE_x */
static INLINE unsigned
util_pipe_tex_to_tgsi_tex(enum pipe_texture_target pipe_tex_target,
unsigned nr_samples)
{
switch (pipe_tex_target) {
case PIPE_TEXTURE_1D:
assert(nr_samples <= 1);
return TGSI_TEXTURE_1D;
 
case PIPE_TEXTURE_2D:
return nr_samples > 1 ? TGSI_TEXTURE_2D_MSAA : TGSI_TEXTURE_2D;
 
case PIPE_TEXTURE_RECT:
assert(nr_samples <= 1);
return TGSI_TEXTURE_RECT;
 
case PIPE_TEXTURE_3D:
assert(nr_samples <= 1);
return TGSI_TEXTURE_3D;
 
case PIPE_TEXTURE_CUBE:
assert(nr_samples <= 1);
return TGSI_TEXTURE_CUBE;
 
case PIPE_TEXTURE_1D_ARRAY:
assert(nr_samples <= 1);
return TGSI_TEXTURE_1D_ARRAY;
 
case PIPE_TEXTURE_2D_ARRAY:
return nr_samples > 1 ? TGSI_TEXTURE_2D_ARRAY_MSAA :
TGSI_TEXTURE_2D_ARRAY;
 
case PIPE_TEXTURE_CUBE_ARRAY:
return TGSI_TEXTURE_CUBE_ARRAY;
 
default:
assert(0 && "unexpected texture target");
return TGSI_TEXTURE_UNKNOWN;
}
}
 
 
static INLINE void
util_copy_constant_buffer(struct pipe_constant_buffer *dst,
const struct pipe_constant_buffer *src)
{
if (src) {
pipe_resource_reference(&dst->buffer, src->buffer);
dst->buffer_offset = src->buffer_offset;
dst->buffer_size = src->buffer_size;
dst->user_buffer = src->user_buffer;
}
else {
pipe_resource_reference(&dst->buffer, NULL);
dst->buffer_offset = 0;
dst->buffer_size = 0;
dst->user_buffer = NULL;
}
}
 
static INLINE unsigned
util_max_layer(const struct pipe_resource *r, unsigned level)
{
switch (r->target) {
case PIPE_TEXTURE_CUBE:
return 6 - 1;
case PIPE_TEXTURE_3D:
return u_minify(r->depth0, level) - 1;
case PIPE_TEXTURE_1D_ARRAY:
case PIPE_TEXTURE_2D_ARRAY:
case PIPE_TEXTURE_CUBE_ARRAY:
return r->array_size - 1;
default:
return 0;
}
}
 
#ifdef __cplusplus
}
#endif
 
#endif /* U_INLINES_H */
/drivers/video/Gallium/auxiliary/util/u_keymap.c
0,0 → 1,318
/**************************************************************************
*
* 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.
*
**************************************************************************/
 
/**
* Key lookup/associative container.
*
* Like Jose's util_hash_table, based on CSO cache code for now.
*
* Author: Brian Paul
*/
 
 
#include "pipe/p_compiler.h"
#include "util/u_debug.h"
 
#include "cso_cache/cso_hash.h"
 
#include "util/u_memory.h"
#include "util/u_keymap.h"
 
 
struct keymap
{
struct cso_hash *cso;
unsigned key_size;
unsigned max_entries; /* XXX not obeyed net */
unsigned num_entries;
keymap_delete_func delete_func;
};
 
 
struct keymap_item
{
void *key, *value;
};
 
 
/**
* This the default key-delete function used when the client doesn't
* provide one.
*/
static void
default_delete_func(const struct keymap *map,
const void *key, void *data, void *user)
{
FREE((void*) data);
}
 
 
static INLINE struct keymap_item *
hash_table_item(struct cso_hash_iter iter)
{
return (struct keymap_item *) cso_hash_iter_data(iter);
}
 
 
/**
* Return 4-byte hash key for a block of bytes.
*/
static unsigned
hash(const void *key, unsigned keySize)
{
unsigned i, hash;
 
keySize /= 4; /* convert from bytes to uints */
 
hash = 0;
for (i = 0; i < keySize; i++) {
hash ^= (i + 1) * ((const unsigned *) key)[i];
}
 
/*hash = hash ^ (hash >> 11) ^ (hash >> 22);*/
 
return hash;
}
 
 
/**
* Create a new map.
* \param keySize size of the keys in bytes
* \param maxEntries max number of entries to allow (~0 = infinity)
* \param deleteFunc optional callback to call when entries
* are deleted/replaced
*/
struct keymap *
util_new_keymap(unsigned keySize, unsigned maxEntries,
keymap_delete_func deleteFunc)
{
struct keymap *map = MALLOC_STRUCT(keymap);
if (!map)
return NULL;
map->cso = cso_hash_create();
if (!map->cso) {
FREE(map);
return NULL;
}
map->max_entries = maxEntries;
map->num_entries = 0;
map->key_size = keySize;
map->delete_func = deleteFunc ? deleteFunc : default_delete_func;
 
return map;
}
 
 
/**
* Delete/free a keymap and all entries. The deleteFunc that was given at
* create time will be called for each entry.
* \param user user-provided pointer passed through to the delete callback
*/
void
util_delete_keymap(struct keymap *map, void *user)
{
util_keymap_remove_all(map, user);
cso_hash_delete(map->cso);
FREE(map);
}
 
 
static INLINE struct cso_hash_iter
hash_table_find_iter(const struct keymap *map, const void *key,
unsigned key_hash)
{
struct cso_hash_iter iter;
struct keymap_item *item;
iter = cso_hash_find(map->cso, key_hash);
while (!cso_hash_iter_is_null(iter)) {
item = (struct keymap_item *) cso_hash_iter_data(iter);
if (!memcmp(item->key, key, map->key_size))
break;
iter = cso_hash_iter_next(iter);
}
return iter;
}
 
 
static INLINE struct keymap_item *
hash_table_find_item(const struct keymap *map, const void *key,
unsigned key_hash)
{
struct cso_hash_iter iter = hash_table_find_iter(map, key, key_hash);
if (cso_hash_iter_is_null(iter)) {
return NULL;
}
else {
return hash_table_item(iter);
}
}
 
 
/**
* Insert a new key + data pointer into the table.
* Note: we create a copy of the key, but not the data!
* If the key is already present in the table, replace the existing
* entry (calling the delete callback on the previous entry).
* If the maximum capacity of the map is reached an old entry
* will be deleted (the delete callback will be called).
*/
boolean
util_keymap_insert(struct keymap *map, const void *key,
const void *data, void *user)
{
unsigned key_hash;
struct keymap_item *item;
struct cso_hash_iter iter;
 
assert(map);
if (!map)
return FALSE;
 
key_hash = hash(key, map->key_size);
 
item = hash_table_find_item(map, key, key_hash);
if (item) {
/* call delete callback for old entry/item */
map->delete_func(map, item->key, item->value, user);
item->value = (void *) data;
return TRUE;
}
item = MALLOC_STRUCT(keymap_item);
if (!item)
return FALSE;
 
item->key = mem_dup(key, map->key_size);
item->value = (void *) data;
iter = cso_hash_insert(map->cso, key_hash, item);
if (cso_hash_iter_is_null(iter)) {
FREE(item);
return FALSE;
}
 
map->num_entries++;
 
return TRUE;
}
 
 
/**
* Look up a key in the map and return the associated data pointer.
*/
const void *
util_keymap_lookup(const struct keymap *map, const void *key)
{
unsigned key_hash;
struct keymap_item *item;
 
assert(map);
if (!map)
return NULL;
 
key_hash = hash(key, map->key_size);
 
item = hash_table_find_item(map, key, key_hash);
if (!item)
return NULL;
return item->value;
}
 
 
/**
* Remove an entry from the map.
* The delete callback will be called if the given key/entry is found.
* \param user passed to the delete callback as the last param.
*/
void
util_keymap_remove(struct keymap *map, const void *key, void *user)
{
unsigned key_hash;
struct cso_hash_iter iter;
struct keymap_item *item;
 
assert(map);
if (!map)
return;
 
key_hash = hash(key, map->key_size);
 
iter = hash_table_find_iter(map, key, key_hash);
if (cso_hash_iter_is_null(iter))
return;
item = hash_table_item(iter);
assert(item);
if (!item)
return;
map->delete_func(map, item->key, item->value, user);
FREE(item->key);
FREE(item);
map->num_entries--;
 
cso_hash_erase(map->cso, iter);
}
 
 
/**
* Remove all entries from the map, calling the delete callback for each.
* \param user passed to the delete callback as the last param.
*/
void
util_keymap_remove_all(struct keymap *map, void *user)
{
struct cso_hash_iter iter;
struct keymap_item *item;
 
assert(map);
if (!map)
return;
 
iter = cso_hash_first_node(map->cso);
while (!cso_hash_iter_is_null(iter)) {
item = (struct keymap_item *)
cso_hash_take(map->cso, cso_hash_iter_key(iter));
map->delete_func(map, item->key, item->value, user);
FREE(item->key);
FREE(item);
iter = cso_hash_first_node(map->cso);
}
}
 
 
extern void
util_keymap_info(const struct keymap *map)
{
debug_printf("Keymap %p: %u of max %u entries\n",
(void *) map, map->num_entries, map->max_entries);
}
/drivers/video/Gallium/auxiliary/util/u_keymap.h
0,0 → 1,68
/**************************************************************************
*
* 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.
*
**************************************************************************/
 
#ifndef U_KEYMAP_H
#define U_KEYMAP_H
 
#include "pipe/p_compiler.h"
 
 
/** opaque keymap type */
struct keymap;
 
 
/** Delete/callback function type */
typedef void (*keymap_delete_func)(const struct keymap *map,
const void *key, void *data,
void *user);
 
 
extern struct keymap *
util_new_keymap(unsigned keySize, unsigned maxEntries,
keymap_delete_func deleteFunc);
 
extern void
util_delete_keymap(struct keymap *map, void *user);
 
extern boolean
util_keymap_insert(struct keymap *map, const void *key,
const void *data, void *user);
 
extern const void *
util_keymap_lookup(const struct keymap *map, const void *key);
 
extern void
util_keymap_remove(struct keymap *map, const void *key, void *user);
 
extern void
util_keymap_remove_all(struct keymap *map, void *user);
 
extern void
util_keymap_info(const struct keymap *map);
 
 
#endif /* U_KEYMAP_H */
/drivers/video/Gallium/auxiliary/util/u_linear.c
0,0 → 1,101
/**************************************************************************
*
* Copyright 2009 VMware, Inc.
* 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 VMWARE 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.
*
**************************************************************************/
 
/**
* Functions for converting tiled data to linear and vice versa.
*/
 
 
#include "util/u_debug.h"
#include "u_linear.h"
 
void
pipe_linear_to_tile(size_t src_stride, const void *src_ptr,
struct pipe_tile_info *t, void *dst_ptr)
{
int x, y, z;
char *ptr;
size_t bytes = t->cols * t->block.size;
char *dst_ptr2 = (char *) dst_ptr;
 
assert(pipe_linear_check_tile(t));
 
/* lets write lineary to the tiled buffer */
for (y = 0; y < t->tiles_y; y++) {
for (x = 0; x < t->tiles_x; x++) {
/* this inner loop could be replace with SSE magic */
ptr = (char*)src_ptr + src_stride * t->rows * y + bytes * x;
for (z = 0; z < t->rows; z++) {
memcpy(dst_ptr2, ptr, bytes);
dst_ptr2 += bytes;
ptr += src_stride;
}
}
}
}
 
void pipe_linear_from_tile(struct pipe_tile_info *t, const void *src_ptr,
size_t dst_stride, void *dst_ptr)
{
int x, y, z;
char *ptr;
size_t bytes = t->cols * t->block.size;
const char *src_ptr2 = (const char *) src_ptr;
 
/* lets read lineary from the tiled buffer */
for (y = 0; y < t->tiles_y; y++) {
for (x = 0; x < t->tiles_x; x++) {
/* this inner loop could be replace with SSE magic */
ptr = (char*)dst_ptr + dst_stride * t->rows * y + bytes * x;
for (z = 0; z < t->rows; z++) {
memcpy(ptr, src_ptr2, bytes);
src_ptr2 += bytes;
ptr += dst_stride;
}
}
}
}
 
void
pipe_linear_fill_info(struct pipe_tile_info *t,
const struct u_linear_format_block *block,
unsigned tile_width, unsigned tile_height,
unsigned tiles_x, unsigned tiles_y)
{
t->block = *block;
 
t->tile.width = tile_width;
t->tile.height = tile_height;
t->cols = t->tile.width / t->block.width;
t->rows = t->tile.height / t->block.height;
t->tile.size = t->cols * t->rows * t->block.size;
 
t->tiles_x = tiles_x;
t->tiles_y = tiles_y;
t->stride = t->cols * t->tiles_x * t->block.size;
t->size = t->tiles_x * t->tiles_y * t->tile.size;
}
/drivers/video/Gallium/auxiliary/util/u_linear.h
0,0 → 1,106
/**************************************************************************
*
* Copyright 2009 VMware, Inc.
* 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 VMWARE 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.
*
**************************************************************************/
 
/**
* Functions for converting tiled data to linear and vice versa.
*/
 
 
#ifndef U_LINEAR_H
#define U_LINEAR_H
 
#include "pipe/p_compiler.h"
#include "pipe/p_format.h"
 
struct u_linear_format_block
{
/** Block size in bytes */
unsigned size;
/** Block width in pixels */
unsigned width;
/** Block height in pixels */
unsigned height;
};
 
 
struct pipe_tile_info
{
unsigned size;
unsigned stride;
 
/* The number of tiles */
unsigned tiles_x;
unsigned tiles_y;
 
/* size of each tile expressed in blocks */
unsigned cols;
unsigned rows;
 
/* Describe the tile in pixels */
struct u_linear_format_block tile;
 
/* Describe each block within the tile */
struct u_linear_format_block block;
};
 
void pipe_linear_to_tile(size_t src_stride, const void *src_ptr,
struct pipe_tile_info *t, void *dst_ptr);
 
void pipe_linear_from_tile(struct pipe_tile_info *t, const void *src_ptr,
size_t dst_stride, void *dst_ptr);
 
/**
* Convenience function to fillout a pipe_tile_info struct.
* @t info to fill out.
* @block block info about pixel layout
* @tile_width the width of the tile in pixels
* @tile_height the height of the tile in pixels
* @tiles_x number of tiles in x axis
* @tiles_y number of tiles in y axis
*/
void pipe_linear_fill_info(struct pipe_tile_info *t,
const struct u_linear_format_block *block,
unsigned tile_width, unsigned tile_height,
unsigned tiles_x, unsigned tiles_y);
 
static INLINE boolean pipe_linear_check_tile(const struct pipe_tile_info *t)
{
if (t->tile.size != t->block.size * t->cols * t->rows)
return FALSE;
 
if (t->stride != t->block.size * t->cols * t->tiles_x)
return FALSE;
 
if (t->size < t->stride * t->rows * t->tiles_y)
return FALSE;
 
return TRUE;
}
 
#endif /* U_LINEAR_H */
/drivers/video/Gallium/auxiliary/util/u_linkage.c
0,0 → 1,149
/**************************************************************************
*
* Copyright 2010 Luca Barbieri
*
* 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, sublicense, 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 NONINFRINGEMENT.
* IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
*
**************************************************************************/
 
#include "util/u_debug.h"
#include "pipe/p_shader_tokens.h"
#include "tgsi/tgsi_parse.h"
#include "tgsi/tgsi_scan.h"
#include "util/u_linkage.h"
 
/* we must only record the registers that are actually used, not just declared */
static INLINE boolean
util_semantic_set_test_and_set(struct util_semantic_set *set, unsigned value)
{
unsigned mask = 1 << (value % (sizeof(long) * 8));
unsigned long *p = &set->masks[value / (sizeof(long) * 8)];
unsigned long v = *p & mask;
*p |= mask;
return !!v;
}
 
unsigned
util_semantic_set_from_program_file(struct util_semantic_set *set, const struct tgsi_token *tokens, enum tgsi_file_type file)
{
struct tgsi_shader_info info;
struct tgsi_parse_context parse;
unsigned count = 0;
ubyte *semantic_name;
ubyte *semantic_index;
 
tgsi_scan_shader(tokens, &info);
 
if(file == TGSI_FILE_INPUT)
{
semantic_name = info.input_semantic_name;
semantic_index = info.input_semantic_index;
}
else if(file == TGSI_FILE_OUTPUT)
{
semantic_name = info.output_semantic_name;
semantic_index = info.output_semantic_index;
}
else
{
assert(0);
semantic_name = NULL;
semantic_index = NULL;
}
 
tgsi_parse_init(&parse, tokens);
 
memset(set->masks, 0, sizeof(set->masks));
while(!tgsi_parse_end_of_tokens(&parse))
{
tgsi_parse_token(&parse);
 
if(parse.FullToken.Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION)
{
const struct tgsi_full_instruction *finst = &parse.FullToken.FullInstruction;
unsigned i;
for(i = 0; i < finst->Instruction.NumDstRegs; ++i)
{
if(finst->Dst[i].Register.File == file)
{
unsigned idx = finst->Dst[i].Register.Index;
if(semantic_name[idx] == TGSI_SEMANTIC_GENERIC)
{
if(!util_semantic_set_test_and_set(set, semantic_index[idx]))
++count;
}
}
}
 
for(i = 0; i < finst->Instruction.NumSrcRegs; ++i)
{
if(finst->Src[i].Register.File == file)
{
unsigned idx = finst->Src[i].Register.Index;
if(semantic_name[idx] == TGSI_SEMANTIC_GENERIC)
{
if(!util_semantic_set_test_and_set(set, semantic_index[idx]))
++count;
}
}
}
}
}
tgsi_parse_free(&parse);
 
return count;
}
 
#define UTIL_SEMANTIC_SET_FOR_EACH(i, set) for(i = 0; i < 256; ++i) if(set->masks[i / (sizeof(long) * 8)] & (1 << (i % (sizeof(long) * 8))))
 
void
util_semantic_layout_from_set(unsigned char *layout, const struct util_semantic_set *set, unsigned efficient_slots, unsigned num_slots)
{
int first = -1;
int last = -1;
unsigned i;
 
memset(layout, 0xff, num_slots);
 
UTIL_SEMANTIC_SET_FOR_EACH(i, set)
{
if(first < 0)
first = i;
last = i;
}
 
if (last < (int) efficient_slots)
{
UTIL_SEMANTIC_SET_FOR_EACH(i, set)
layout[i] = i;
}
else if ((last - first) < (int) efficient_slots)
{
UTIL_SEMANTIC_SET_FOR_EACH(i, set)
layout[i - first] = i;
}
else
{
unsigned idx = 0;
UTIL_SEMANTIC_SET_FOR_EACH(i, set)
layout[idx++] = i;
}
}
/drivers/video/Gallium/auxiliary/util/u_linkage.h
0,0 → 1,67
/**************************************************************************
*
* Copyright 2010 Luca Barbieri
*
* 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, sublicense, 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 NONINFRINGEMENT.
* IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
*
**************************************************************************/
 
#ifndef U_LINKAGE_H_
#define U_LINKAGE_H_
 
#include "pipe/p_compiler.h"
#include "pipe/p_shader_tokens.h"
 
struct util_semantic_set
{
unsigned long masks[256 / 8 / sizeof(unsigned long)];
};
 
static INLINE boolean
util_semantic_set_contains(struct util_semantic_set *set, unsigned char value)
{
return !!(set->masks[value / (sizeof(long) * 8)] & (1 << (value / (sizeof(long) * 8))));
}
 
unsigned util_semantic_set_from_program_file(struct util_semantic_set *set, const struct tgsi_token *tokens, enum tgsi_file_type file);
 
/* efficient_slots is the number of slots such that hardware performance is
* the same for using that amount, with holes, or less slots but with less
* holes.
*
* num_slots is the size of the layout array and hardware limit instead.
*
* efficient_slots == 0 or efficient_slots == num_slots are typical settings.
*/
void util_semantic_layout_from_set(unsigned char *layout, const struct util_semantic_set *set, unsigned efficient_slots, unsigned num_slots);
 
static INLINE void
util_semantic_table_from_layout(unsigned char *table, size_t table_size, unsigned char *layout,
unsigned char first_slot_value, unsigned char num_slots)
{
unsigned char i;
memset(table, 0xff, table_size);
 
for(i = 0; i < num_slots; ++i)
table[layout[i]] = first_slot_value + i;
}
 
#endif /* U_LINKAGE_H_ */
/drivers/video/Gallium/auxiliary/util/u_math.c
0,0 → 1,73
/**************************************************************************
*
* 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.
*
**************************************************************************/
 
 
 
#include "util/u_math.h"
 
 
/** 2^x, for x in [-1.0, 1.0) */
float pow2_table[POW2_TABLE_SIZE];
 
 
static void
init_pow2_table(void)
{
int i;
for (i = 0; i < POW2_TABLE_SIZE; i++)
pow2_table[i] = (float) pow(2.0, (i - POW2_TABLE_OFFSET) / POW2_TABLE_SCALE);
}
 
 
/** log2(x), for x in [1.0, 2.0) */
float log2_table[LOG2_TABLE_SIZE];
 
 
static void
init_log2_table(void)
{
unsigned i;
for (i = 0; i < LOG2_TABLE_SIZE; i++)
log2_table[i] = (float) log2(1.0 + i * (1.0 / LOG2_TABLE_SCALE));
}
 
 
/**
* One time init for math utilities.
*/
void
util_init_math(void)
{
static boolean initialized = FALSE;
if (!initialized) {
init_pow2_table();
init_log2_table();
initialized = TRUE;
}
}
 
 
/drivers/video/Gallium/auxiliary/util/u_math.h
0,0 → 1,772
/**************************************************************************
*
* 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.
*
**************************************************************************/
 
 
/**
* Math utilities and approximations for common math functions.
* Reduced precision is usually acceptable in shaders...
*
* "fast" is used in the names of functions which are low-precision,
* or at least lower-precision than the normal C lib functions.
*/
 
 
#ifndef U_MATH_H
#define U_MATH_H
 
 
#include "pipe/p_compiler.h"
 
 
#ifdef __cplusplus
extern "C" {
#endif
 
 
#include <math.h>
#include <stdarg.h>
 
#ifdef PIPE_OS_UNIX
#include <strings.h> /* for ffs */
#endif
 
 
#ifndef M_SQRT2
#define M_SQRT2 1.41421356237309504880
#endif
 
 
#if defined(_MSC_VER)
 
#if _MSC_VER < 1400 && !defined(__cplusplus)
static INLINE float cosf( float f )
{
return (float) cos( (double) f );
}
 
static INLINE float sinf( float f )
{
return (float) sin( (double) f );
}
 
static INLINE float ceilf( float f )
{
return (float) ceil( (double) f );
}
 
static INLINE float floorf( float f )
{
return (float) floor( (double) f );
}
 
static INLINE float powf( float f, float g )
{
return (float) pow( (double) f, (double) g );
}
 
static INLINE float sqrtf( float f )
{
return (float) sqrt( (double) f );
}
 
static INLINE float fabsf( float f )
{
return (float) fabs( (double) f );
}
 
static INLINE float logf( float f )
{
return (float) log( (double) f );
}
 
#else
/* Work-around an extra semi-colon in VS 2005 logf definition */
#ifdef logf
#undef logf
#define logf(x) ((float)log((double)(x)))
#endif /* logf */
 
#define isfinite(x) _finite((double)(x))
#define isnan(x) _isnan((double)(x))
#endif /* _MSC_VER < 1400 && !defined(__cplusplus) */
 
static INLINE double log2( double x )
{
const double invln2 = 1.442695041;
return log( x ) * invln2;
}
 
static INLINE double
round(double x)
{
return x >= 0.0 ? floor(x + 0.5) : ceil(x - 0.5);
}
 
static INLINE float
roundf(float x)
{
return x >= 0.0f ? floorf(x + 0.5f) : ceilf(x - 0.5f);
}
 
#endif /* _MSC_VER */
 
 
#ifdef PIPE_OS_ANDROID
 
static INLINE
double log2(double d)
{
return log(d) * (1.0 / M_LN2);
}
 
/* workaround a conflict with main/imports.h */
#ifdef log2f
#undef log2f
#endif
 
static INLINE
float log2f(float f)
{
return logf(f) * (float) (1.0 / M_LN2);
}
 
#endif
 
 
 
 
#define POW2_TABLE_SIZE_LOG2 9
#define POW2_TABLE_SIZE (1 << POW2_TABLE_SIZE_LOG2)
#define POW2_TABLE_OFFSET (POW2_TABLE_SIZE/2)
#define POW2_TABLE_SCALE ((float)(POW2_TABLE_SIZE/2))
extern float pow2_table[POW2_TABLE_SIZE];
 
 
/**
* Initialize math module. This should be called before using any
* other functions in this module.
*/
extern void
util_init_math(void);
 
 
union fi {
float f;
int32_t i;
uint32_t ui;
};
 
 
union di {
double d;
int64_t i;
uint64_t ui;
};
 
 
/**
* Fast version of 2^x
* Identity: exp2(a + b) = exp2(a) * exp2(b)
* Let ipart = int(x)
* Let fpart = x - ipart;
* So, exp2(x) = exp2(ipart) * exp2(fpart)
* Compute exp2(ipart) with i << ipart
* Compute exp2(fpart) with lookup table.
*/
static INLINE float
util_fast_exp2(float x)
{
int32_t ipart;
float fpart, mpart;
union fi epart;
 
if(x > 129.00000f)
return 3.402823466e+38f;
 
if (x < -126.99999f)
return 0.0f;
 
ipart = (int32_t) x;
fpart = x - (float) ipart;
 
/* same as
* epart.f = (float) (1 << ipart)
* but faster and without integer overflow for ipart > 31
*/
epart.i = (ipart + 127 ) << 23;
 
mpart = pow2_table[POW2_TABLE_OFFSET + (int)(fpart * POW2_TABLE_SCALE)];
 
return epart.f * mpart;
}
 
 
/**
* Fast approximation to exp(x).
*/
static INLINE float
util_fast_exp(float x)
{
const float k = 1.44269f; /* = log2(e) */
return util_fast_exp2(k * x);
}
 
 
#define LOG2_TABLE_SIZE_LOG2 16
#define LOG2_TABLE_SCALE (1 << LOG2_TABLE_SIZE_LOG2)
#define LOG2_TABLE_SIZE (LOG2_TABLE_SCALE + 1)
extern float log2_table[LOG2_TABLE_SIZE];
 
 
/**
* Fast approximation to log2(x).
*/
static INLINE float
util_fast_log2(float x)
{
union fi num;
float epart, mpart;
num.f = x;
epart = (float)(((num.i & 0x7f800000) >> 23) - 127);
/* mpart = log2_table[mantissa*LOG2_TABLE_SCALE + 0.5] */
mpart = log2_table[((num.i & 0x007fffff) + (1 << (22 - LOG2_TABLE_SIZE_LOG2))) >> (23 - LOG2_TABLE_SIZE_LOG2)];
return epart + mpart;
}
 
 
/**
* Fast approximation to x^y.
*/
static INLINE float
util_fast_pow(float x, float y)
{
return util_fast_exp2(util_fast_log2(x) * y);
}
 
/* Note that this counts zero as a power of two.
*/
static INLINE boolean
util_is_power_of_two( unsigned v )
{
return (v & (v-1)) == 0;
}
 
 
/**
* Floor(x), returned as int.
*/
static INLINE int
util_ifloor(float f)
{
int ai, bi;
double af, bf;
union fi u;
af = (3 << 22) + 0.5 + (double) f;
bf = (3 << 22) + 0.5 - (double) f;
u.f = (float) af; ai = u.i;
u.f = (float) bf; bi = u.i;
return (ai - bi) >> 1;
}
 
 
/**
* Round float to nearest int.
*/
static INLINE int
util_iround(float f)
{
#if defined(PIPE_CC_GCC) && defined(PIPE_ARCH_X86)
int r;
__asm__ ("fistpl %0" : "=m" (r) : "t" (f) : "st");
return r;
#elif defined(PIPE_CC_MSVC) && defined(PIPE_ARCH_X86)
int r;
_asm {
fld f
fistp r
}
return r;
#else
if (f >= 0.0f)
return (int) (f + 0.5f);
else
return (int) (f - 0.5f);
#endif
}
 
 
/**
* Approximate floating point comparison
*/
static INLINE boolean
util_is_approx(float a, float b, float tol)
{
return fabs(b - a) <= tol;
}
 
 
/**
* util_is_X_inf_or_nan = test if x is NaN or +/- Inf
* util_is_X_nan = test if x is NaN
* util_X_inf_sign = return +1 for +Inf, -1 for -Inf, or 0 for not Inf
*
* NaN can be checked with x != x, however this fails with the fast math flag
**/
 
 
/**
* Single-float
*/
static INLINE boolean
util_is_inf_or_nan(float x)
{
union fi tmp;
tmp.f = x;
return (tmp.ui & 0x7f800000) == 0x7f800000;
}
 
 
static INLINE boolean
util_is_nan(float x)
{
union fi tmp;
tmp.f = x;
return (tmp.ui & 0x7fffffff) > 0x7f800000;
}
 
 
static INLINE int
util_inf_sign(float x)
{
union fi tmp;
tmp.f = x;
if ((tmp.ui & 0x7fffffff) != 0x7f800000) {
return 0;
}
 
return (x < 0) ? -1 : 1;
}
 
 
/**
* Double-float
*/
static INLINE boolean
util_is_double_inf_or_nan(double x)
{
union di tmp;
tmp.d = x;
return (tmp.ui & 0x7ff0000000000000ULL) == 0x7ff0000000000000ULL;
}
 
 
static INLINE boolean
util_is_double_nan(double x)
{
union di tmp;
tmp.d = x;
return (tmp.ui & 0x7fffffffffffffffULL) > 0x7ff0000000000000ULL;
}
 
 
static INLINE int
util_double_inf_sign(double x)
{
union di tmp;
tmp.d = x;
if ((tmp.ui & 0x7fffffffffffffffULL) != 0x7ff0000000000000ULL) {
return 0;
}
 
return (x < 0) ? -1 : 1;
}
 
 
/**
* Half-float
*/
static INLINE boolean
util_is_half_inf_or_nan(int16_t x)
{
return (x & 0x7c00) == 0x7c00;
}
 
 
static INLINE boolean
util_is_half_nan(int16_t x)
{
return (x & 0x7fff) > 0x7c00;
}
 
 
static INLINE int
util_half_inf_sign(int16_t x)
{
if ((x & 0x7fff) != 0x7c00) {
return 0;
}
 
return (x < 0) ? -1 : 1;
}
 
 
/**
* Find first bit set in word. Least significant bit is 1.
* Return 0 if no bits set.
*/
#ifndef FFS_DEFINED
#define FFS_DEFINED 1
 
#if defined(_MSC_VER) && _MSC_VER >= 1300 && (_M_IX86 || _M_AMD64 || _M_IA64)
unsigned char _BitScanForward(unsigned long* Index, unsigned long Mask);
#pragma intrinsic(_BitScanForward)
static INLINE
unsigned long ffs( unsigned long u )
{
unsigned long i;
if (_BitScanForward(&i, u))
return i + 1;
else
return 0;
}
#elif defined(PIPE_CC_MSVC) && defined(PIPE_ARCH_X86)
static INLINE
unsigned ffs( unsigned u )
{
unsigned i;
 
if (u == 0) {
return 0;
}
 
__asm bsf eax, [u]
__asm inc eax
__asm mov [i], eax
 
return i;
}
#elif defined(__MINGW32__) || defined(PIPE_OS_ANDROID)
#define ffs __builtin_ffs
#endif
 
#endif /* FFS_DEFINED */
 
/**
* Find last bit set in a word. The least significant bit is 1.
* Return 0 if no bits are set.
*/
static INLINE unsigned util_last_bit(unsigned u)
{
#if defined(__GNUC__) && ((__GNUC__ * 100 + __GNUC_MINOR__) >= 304)
return u == 0 ? 0 : 32 - __builtin_clz(u);
#else
unsigned r = 0;
while (u) {
r++;
u >>= 1;
}
return r;
#endif
}
 
 
/* Destructively loop over all of the bits in a mask as in:
*
* while (mymask) {
* int i = u_bit_scan(&mymask);
* ... process element i
* }
*
*/
static INLINE int u_bit_scan(unsigned *mask)
{
int i = ffs(*mask) - 1;
*mask &= ~(1 << i);
return i;
}
 
 
/**
* Return float bits.
*/
static INLINE unsigned
fui( float f )
{
union fi fi;
fi.f = f;
return fi.ui;
}
 
 
/**
* Convert ubyte to float in [0, 1].
* XXX a 256-entry lookup table would be slightly faster.
*/
static INLINE float
ubyte_to_float(ubyte ub)
{
return (float) ub * (1.0f / 255.0f);
}
 
 
/**
* Convert float in [0,1] to ubyte in [0,255] with clamping.
*/
static INLINE ubyte
float_to_ubyte(float f)
{
union fi tmp;
 
tmp.f = f;
if (tmp.i < 0) {
return (ubyte) 0;
}
else if (tmp.i >= 0x3f800000 /* 1.0f */) {
return (ubyte) 255;
}
else {
tmp.f = tmp.f * (255.0f/256.0f) + 32768.0f;
return (ubyte) tmp.i;
}
}
 
static INLINE float
byte_to_float_tex(int8_t b)
{
return (b == -128) ? -1.0F : b * 1.0F / 127.0F;
}
 
static INLINE int8_t
float_to_byte_tex(float f)
{
return (int8_t) (127.0F * f);
}
 
/**
* Calc log base 2
*/
static INLINE unsigned
util_logbase2(unsigned n)
{
#if defined(PIPE_CC_GCC) && (PIPE_CC_GCC_VERSION >= 304)
return ((sizeof(unsigned) * 8 - 1) - __builtin_clz(n | 1));
#else
unsigned pos = 0;
if (n >= 1<<16) { n >>= 16; pos += 16; }
if (n >= 1<< 8) { n >>= 8; pos += 8; }
if (n >= 1<< 4) { n >>= 4; pos += 4; }
if (n >= 1<< 2) { n >>= 2; pos += 2; }
if (n >= 1<< 1) { pos += 1; }
return pos;
#endif
}
 
 
/**
* Returns the smallest power of two >= x
*/
static INLINE unsigned
util_next_power_of_two(unsigned x)
{
#if defined(PIPE_CC_GCC) && (PIPE_CC_GCC_VERSION >= 304)
if (x <= 1)
return 1;
 
return (1 << ((sizeof(unsigned) * 8) - __builtin_clz(x - 1)));
#else
unsigned val = x;
 
if (x <= 1)
return 1;
 
if (util_is_power_of_two(x))
return x;
 
val--;
val = (val >> 1) | val;
val = (val >> 2) | val;
val = (val >> 4) | val;
val = (val >> 8) | val;
val = (val >> 16) | val;
val++;
return val;
#endif
}
 
 
/**
* Return number of bits set in n.
*/
static INLINE unsigned
util_bitcount(unsigned n)
{
#if defined(PIPE_CC_GCC) && (PIPE_CC_GCC_VERSION >= 304)
return __builtin_popcount(n);
#else
/* K&R classic bitcount.
*
* For each iteration, clear the LSB from the bitfield.
* Requires only one iteration per set bit, instead of
* one iteration per bit less than highest set bit.
*/
unsigned bits = 0;
for (bits; n; bits++) {
n &= n - 1;
}
return bits;
#endif
}
 
 
/**
* Convert from little endian to CPU byte order.
*/
 
#ifdef PIPE_ARCH_BIG_ENDIAN
#define util_le32_to_cpu(x) util_bswap32(x)
#define util_le16_to_cpu(x) util_bswap16(x)
#else
#define util_le32_to_cpu(x) (x)
#define util_le16_to_cpu(x) (x)
#endif
 
 
/**
* Reverse byte order of a 32 bit word.
*/
static INLINE uint32_t
util_bswap32(uint32_t n)
{
#if defined(PIPE_CC_GCC) && (PIPE_CC_GCC_VERSION >= 403)
return __builtin_bswap32(n);
#else
return (n >> 24) |
((n >> 8) & 0x0000ff00) |
((n << 8) & 0x00ff0000) |
(n << 24);
#endif
}
 
 
/**
* Reverse byte order of a 16 bit word.
*/
static INLINE uint16_t
util_bswap16(uint16_t n)
{
return (n >> 8) |
(n << 8);
}
 
 
/**
* Clamp X to [MIN, MAX].
* This is a macro to allow float, int, uint, etc. types.
*/
#define CLAMP( X, MIN, MAX ) ( (X)<(MIN) ? (MIN) : ((X)>(MAX) ? (MAX) : (X)) )
 
#define MIN2( A, B ) ( (A)<(B) ? (A) : (B) )
#define MAX2( A, B ) ( (A)>(B) ? (A) : (B) )
 
#define MIN3( A, B, C ) ((A) < (B) ? MIN2(A, C) : MIN2(B, C))
#define MAX3( A, B, C ) ((A) > (B) ? MAX2(A, C) : MAX2(B, C))
 
#define MIN4( A, B, C, D ) ((A) < (B) ? MIN3(A, C, D) : MIN3(B, C, D))
#define MAX4( A, B, C, D ) ((A) > (B) ? MAX3(A, C, D) : MAX3(B, C, D))
 
 
/**
* Align a value, only works pot alignemnts.
*/
static INLINE int
align(int value, int alignment)
{
return (value + alignment - 1) & ~(alignment - 1);
}
 
/**
* Works like align but on npot alignments.
*/
static INLINE size_t
util_align_npot(size_t value, size_t alignment)
{
if (value % alignment)
return value + (alignment - (value % alignment));
return value;
}
 
static INLINE unsigned
u_minify(unsigned value, unsigned levels)
{
return MAX2(1, value >> levels);
}
 
#ifndef COPY_4V
#define COPY_4V( DST, SRC ) \
do { \
(DST)[0] = (SRC)[0]; \
(DST)[1] = (SRC)[1]; \
(DST)[2] = (SRC)[2]; \
(DST)[3] = (SRC)[3]; \
} while (0)
#endif
 
 
#ifndef COPY_4FV
#define COPY_4FV( DST, SRC ) COPY_4V(DST, SRC)
#endif
 
 
#ifndef ASSIGN_4V
#define ASSIGN_4V( DST, V0, V1, V2, V3 ) \
do { \
(DST)[0] = (V0); \
(DST)[1] = (V1); \
(DST)[2] = (V2); \
(DST)[3] = (V3); \
} while (0)
#endif
 
 
static INLINE uint32_t util_unsigned_fixed(float value, unsigned frac_bits)
{
return value < 0 ? 0 : (uint32_t)(value * (1<<frac_bits));
}
 
static INLINE int32_t util_signed_fixed(float value, unsigned frac_bits)
{
return (int32_t)(value * (1<<frac_bits));
}
 
 
 
#ifdef __cplusplus
}
#endif
 
#endif /* U_MATH_H */
/drivers/video/Gallium/auxiliary/util/u_memory.h
0,0 → 1,100
/**************************************************************************
*
* 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.
*
**************************************************************************/
 
 
/*
* Memory functions
*/
 
 
#ifndef U_MEMORY_H
#define U_MEMORY_H
 
 
#include "util/u_pointer.h"
#include "util/u_debug.h"
#include "os/os_memory.h"
 
 
#ifdef __cplusplus
extern "C" {
#endif
 
 
#define MALLOC(_size) os_malloc(_size)
 
#define CALLOC(_count, _size) os_calloc(_count, _size)
 
#define FREE(_ptr ) os_free(_ptr)
 
#define REALLOC(_ptr, _old_size, _size) os_realloc(_ptr, _old_size, _size)
 
#define MALLOC_STRUCT(T) (struct T *) MALLOC(sizeof(struct T))
 
#define CALLOC_STRUCT(T) (struct T *) CALLOC(1, sizeof(struct T))
 
#define CALLOC_VARIANT_LENGTH_STRUCT(T,more_size) ((struct T *) CALLOC(1, sizeof(struct T) + more_size))
 
 
#define align_malloc(_size, _alignment) os_malloc_aligned(_size, _alignment)
#define align_free(_ptr) os_free_aligned(_ptr)
 
 
/**
* Duplicate a block of memory.
*/
static INLINE void *
mem_dup(const void *src, uint size)
{
void *dup = MALLOC(size);
if (dup)
memcpy(dup, src, size);
return dup;
}
 
 
/**
* Number of elements in an array.
*/
#ifndef Elements
#define Elements(x) (sizeof(x)/sizeof((x)[0]))
#endif
 
 
/**
* Offset of a field in a struct, in bytes.
*/
#define Offset(TYPE, MEMBER) ((uintptr_t)&(((TYPE *)NULL)->MEMBER))
 
 
 
#ifdef __cplusplus
}
#endif
 
 
#endif /* U_MEMORY_H */
/drivers/video/Gallium/auxiliary/util/u_mm.c
0,0 → 1,296
/**************************************************************************
*
* Copyright (C) 1999 Wittawat Yamwong
*
* 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, sublicense,
* 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
* WITTAWAT YAMWONG, OR ANY OTHER CONTRIBUTORS 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.
*
**************************************************************************/
 
 
#include "pipe/p_compiler.h"
#include "util/u_debug.h"
 
#include "util/u_memory.h"
#include "util/u_mm.h"
 
 
void
u_mmDumpMemInfo(const struct mem_block *heap)
{
debug_printf("Memory heap %p:\n", (void *) heap);
if (heap == 0) {
debug_printf(" heap == 0\n");
}
else {
const struct mem_block *p;
int total_used = 0, total_free = 0;
 
for (p = heap->next; p != heap; p = p->next) {
debug_printf(" Offset:%08x, Size:%08x, %c%c\n", p->ofs, p->size,
p->free ? 'F':'.',
p->reserved ? 'R':'.');
if (p->free)
total_free += p->size;
else
total_used += p->size;
}
 
debug_printf("'\nMemory stats: total = %d, used = %d, free = %d\n",
total_used + total_free, total_used, total_free);
debug_printf("\nFree list:\n");
 
for (p = heap->next_free; p != heap; p = p->next_free) {
debug_printf(" FREE Offset:%08x, Size:%08x, %c%c\n", p->ofs, p->size,
p->free ? 'F':'.',
p->reserved ? 'R':'.');
}
 
}
debug_printf("End of memory blocks\n");
}
 
 
struct mem_block *
u_mmInit(int ofs, int size)
{
struct mem_block *heap, *block;
if (size <= 0)
return NULL;
 
heap = CALLOC_STRUCT(mem_block);
if (!heap)
return NULL;
block = CALLOC_STRUCT(mem_block);
if (!block) {
FREE(heap);
return NULL;
}
 
heap->next = block;
heap->prev = block;
heap->next_free = block;
heap->prev_free = block;
 
block->heap = heap;
block->next = heap;
block->prev = heap;
block->next_free = heap;
block->prev_free = heap;
 
block->ofs = ofs;
block->size = size;
block->free = 1;
 
return heap;
}
 
 
static struct mem_block *
SliceBlock(struct mem_block *p,
int startofs, int size,
int reserved, int alignment)
{
struct mem_block *newblock;
 
/* break left [p, newblock, p->next], then p = newblock */
if (startofs > p->ofs) {
newblock = CALLOC_STRUCT(mem_block);
if (!newblock)
return NULL;
newblock->ofs = startofs;
newblock->size = p->size - (startofs - p->ofs);
newblock->free = 1;
newblock->heap = p->heap;
 
newblock->next = p->next;
newblock->prev = p;
p->next->prev = newblock;
p->next = newblock;
 
newblock->next_free = p->next_free;
newblock->prev_free = p;
p->next_free->prev_free = newblock;
p->next_free = newblock;
 
p->size -= newblock->size;
p = newblock;
}
 
/* break right, also [p, newblock, p->next] */
if (size < p->size) {
newblock = CALLOC_STRUCT(mem_block);
if (!newblock)
return NULL;
newblock->ofs = startofs + size;
newblock->size = p->size - size;
newblock->free = 1;
newblock->heap = p->heap;
 
newblock->next = p->next;
newblock->prev = p;
p->next->prev = newblock;
p->next = newblock;
 
newblock->next_free = p->next_free;
newblock->prev_free = p;
p->next_free->prev_free = newblock;
p->next_free = newblock;
p->size = size;
}
 
/* p = middle block */
p->free = 0;
 
/* Remove p from the free list:
*/
p->next_free->prev_free = p->prev_free;
p->prev_free->next_free = p->next_free;
 
p->next_free = 0;
p->prev_free = 0;
 
p->reserved = reserved;
return p;
}
 
 
struct mem_block *
u_mmAllocMem(struct mem_block *heap, int size, int align2, int startSearch)
{
struct mem_block *p;
const int mask = (1 << align2)-1;
int startofs = 0;
int endofs;
 
assert(size >= 0);
assert(align2 >= 0);
assert(align2 <= 12); /* sanity check, 2^12 (4KB) enough? */
 
if (!heap || align2 < 0 || size <= 0)
return NULL;
 
for (p = heap->next_free; p != heap; p = p->next_free) {
assert(p->free);
 
startofs = (p->ofs + mask) & ~mask;
if ( startofs < startSearch ) {
startofs = startSearch;
}
endofs = startofs+size;
if (endofs <= (p->ofs+p->size))
break;
}
 
if (p == heap)
return NULL;
 
assert(p->free);
p = SliceBlock(p,startofs,size,0,mask+1);
 
return p;
}
 
 
struct mem_block *
u_mmFindBlock(struct mem_block *heap, int start)
{
struct mem_block *p;
 
for (p = heap->next; p != heap; p = p->next) {
if (p->ofs == start)
return p;
}
 
return NULL;
}
 
 
static INLINE int
Join2Blocks(struct mem_block *p)
{
/* XXX there should be some assertions here */
 
/* NOTE: heap->free == 0 */
 
if (p->free && p->next->free) {
struct mem_block *q = p->next;
 
assert(p->ofs + p->size == q->ofs);
p->size += q->size;
 
p->next = q->next;
q->next->prev = p;
 
q->next_free->prev_free = q->prev_free;
q->prev_free->next_free = q->next_free;
FREE(q);
return 1;
}
return 0;
}
 
int
u_mmFreeMem(struct mem_block *b)
{
if (!b)
return 0;
 
if (b->free) {
debug_printf("block already free\n");
return -1;
}
if (b->reserved) {
debug_printf("block is reserved\n");
return -1;
}
 
b->free = 1;
b->next_free = b->heap->next_free;
b->prev_free = b->heap;
b->next_free->prev_free = b;
b->prev_free->next_free = b;
 
Join2Blocks(b);
if (b->prev != b->heap)
Join2Blocks(b->prev);
 
return 0;
}
 
 
void
u_mmDestroy(struct mem_block *heap)
{
struct mem_block *p;
 
if (!heap)
return;
 
for (p = heap->next; p != heap; ) {
struct mem_block *next = p->next;
FREE(p);
p = next;
}
 
FREE(heap);
}
/drivers/video/Gallium/auxiliary/util/u_mm.h
0,0 → 1,91
/**************************************************************************
*
* Copyright (C) 1999 Wittawat Yamwong
*
* 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, sublicense,
* 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
* KEITH WHITWELL, OR ANY OTHER CONTRIBUTORS 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
* Memory manager code. Primarily used by device drivers to manage texture
* heaps, etc.
*/
 
 
#ifndef _U_MM_H_
#define _U_MM_H_
 
 
struct mem_block {
struct mem_block *next, *prev;
struct mem_block *next_free, *prev_free;
struct mem_block *heap;
int ofs,size;
unsigned int free:1;
unsigned int reserved:1;
};
 
 
 
/**
* input: total size in bytes
* return: a heap pointer if OK, NULL if error
*/
extern struct mem_block *u_mmInit(int ofs, int size);
 
/**
* Allocate 'size' bytes with 2^align2 bytes alignment,
* restrict the search to free memory after 'startSearch'
* depth and back buffers should be in different 4mb banks
* to get better page hits if possible
* input: size = size of block
* align2 = 2^align2 bytes alignment
* startSearch = linear offset from start of heap to begin search
* return: pointer to the allocated block, 0 if error
*/
extern struct mem_block *u_mmAllocMem(struct mem_block *heap, int size, int align2,
int startSearch);
 
/**
* Free block starts at offset
* input: pointer to a block
* return: 0 if OK, -1 if error
*/
extern int u_mmFreeMem(struct mem_block *b);
 
/**
* Free block starts at offset
* input: pointer to a heap, start offset
* return: pointer to a block
*/
extern struct mem_block *u_mmFindBlock(struct mem_block *heap, int start);
 
/**
* destroy MM
*/
extern void u_mmDestroy(struct mem_block *mmInit);
 
/**
* For debugging purposes.
*/
extern void u_mmDumpMemInfo(const struct mem_block *mmInit);
 
#endif
/drivers/video/Gallium/auxiliary/util/u_network.c
0,0 → 1,191
 
#include "pipe/p_compiler.h"
#include "util/u_network.h"
#include "util/u_debug.h"
 
#if defined(PIPE_SUBSYSTEM_WINDOWS_USER)
# include <winsock2.h>
# include <windows.h>
#elif defined(PIPE_OS_LINUX) || defined(PIPE_OS_HAIKU) || \
defined(PIPE_OS_APPLE) || defined(PIPE_OS_CYGWIN) || defined(PIPE_OS_SOLARIS)
# include <sys/socket.h>
# include <netinet/in.h>
# include <unistd.h>
# include <fcntl.h>
# include <netdb.h>
#else
# warning "No socket implementation"
#endif
 
boolean
u_socket_init()
{
#if defined(PIPE_SUBSYSTEM_WINDOWS_USER)
WORD wVersionRequested;
WSADATA wsaData;
int err;
 
/* Use the MAKEWORD(lowbyte, highbyte) macro declared in Windef.h */
wVersionRequested = MAKEWORD(1, 1);
 
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0) {
debug_printf("WSAStartup failed with error: %d\n", err);
return FALSE;
}
return TRUE;
#elif defined(PIPE_HAVE_SOCKETS)
return TRUE;
#else
return FALSE;
#endif
}
 
void
u_socket_stop()
{
#if defined(PIPE_SUBSYSTEM_WINDOWS_USER)
WSACleanup();
#endif
}
 
void
u_socket_close(int s)
{
if (s < 0)
return;
 
#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_HAIKU) \
|| defined(PIPE_OS_APPLE) || defined(PIPE_OS_SOLARIS)
shutdown(s, SHUT_RDWR);
close(s);
#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
shutdown(s, SD_BOTH);
closesocket(s);
#else
assert(0);
#endif
}
 
int u_socket_accept(int s)
{
#if defined(PIPE_HAVE_SOCKETS)
return accept(s, NULL, NULL);
#else
return -1;
#endif
}
 
int
u_socket_send(int s, void *data, size_t size)
{
#if defined(PIPE_HAVE_SOCKETS)
return send(s, data, size, 0);
#else
return -1;
#endif
}
 
int
u_socket_peek(int s, void *data, size_t size)
{
#if defined(PIPE_HAVE_SOCKETS)
return recv(s, data, size, MSG_PEEK);
#else
return -1;
#endif
}
 
int
u_socket_recv(int s, void *data, size_t size)
{
#if defined(PIPE_HAVE_SOCKETS)
return recv(s, data, size, 0);
#else
return -1;
#endif
}
 
int
u_socket_connect(const char *hostname, uint16_t port)
{
#if defined(PIPE_HAVE_SOCKETS)
int s;
struct sockaddr_in sa;
struct hostent *host = NULL;
 
memset(&sa, 0, sizeof(struct sockaddr_in));
host = gethostbyname(hostname);
if (!host)
return -1;
 
memcpy((char *)&sa.sin_addr,host->h_addr_list[0],host->h_length);
sa.sin_family= host->h_addrtype;
sa.sin_port = htons(port);
 
s = socket(host->h_addrtype, SOCK_STREAM, IPPROTO_TCP);
if (s < 0)
return -1;
 
if (connect(s, (struct sockaddr *)&sa, sizeof(sa))) {
u_socket_close(s);
return -1;
}
 
return s;
#else
assert(0);
return -1;
#endif
}
 
int
u_socket_listen_on_port(uint16_t portnum)
{
#if defined(PIPE_HAVE_SOCKETS)
int s;
struct sockaddr_in sa;
memset(&sa, 0, sizeof(struct sockaddr_in));
 
sa.sin_family = AF_INET;
sa.sin_port = htons(portnum);
 
s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (s < 0)
return -1;
 
if (bind(s, (struct sockaddr *)&sa, sizeof(struct sockaddr_in)) == -1) {
u_socket_close(s);
return -1;
}
 
listen(s, 0);
 
return s;
#else
assert(0);
return -1;
#endif
}
 
void
u_socket_block(int s, boolean block)
{
#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_HAIKU) \
|| defined(PIPE_OS_APPLE) || defined(PIPE_OS_SOLARIS)
int old = fcntl(s, F_GETFL, 0);
if (old == -1)
return;
 
/* TODO obey block */
if (block)
fcntl(s, F_SETFL, old & ~O_NONBLOCK);
else
fcntl(s, F_SETFL, old | O_NONBLOCK);
#elif defined(PIPE_SUBSYSTEM_WINDOWS_USER)
u_long iMode = block ? 0 : 1;
ioctlsocket(s, FIONBIO, &iMode);
#else
assert(0);
#endif
}
/drivers/video/Gallium/auxiliary/util/u_network.h
0,0 → 1,25
 
#ifndef _U_NETWORK_H_
#define _U_NETWORK_H_
 
#include "pipe/p_compiler.h"
 
#if defined(PIPE_SUBSYSTEM_WINDOWS_USER)
# define PIPE_HAVE_SOCKETS
#elif defined(PIPE_OS_LINUX) || defined(PIPE_OS_HAIKU) || \
defined(PIPE_OS_APPLE) || defined(PIPE_OS_SOLARIS)
# define PIPE_HAVE_SOCKETS
#endif
 
boolean u_socket_init(void);
void u_socket_stop(void);
void u_socket_close(int s);
int u_socket_listen_on_port(uint16_t portnum);
int u_socket_accept(int s);
int u_socket_connect(const char *host, uint16_t port);
int u_socket_send(int s, void *data, size_t size);
int u_socket_peek(int s, void *data, size_t size);
int u_socket_recv(int s, void *data, size_t size);
void u_socket_block(int s, boolean block);
 
#endif
/drivers/video/Gallium/auxiliary/util/u_pack_color.h
0,0 → 1,651
/**************************************************************************
*
* 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
* Functions to produce packed colors/Z from floats.
*/
 
 
#ifndef U_PACK_COLOR_H
#define U_PACK_COLOR_H
 
 
#include "pipe/p_compiler.h"
#include "pipe/p_format.h"
#include "util/u_debug.h"
#include "util/u_format.h"
#include "util/u_math.h"
 
 
/**
* Helper union for packing pixel values.
* Will often contain values in formats which are too complex to be described
* in simple terms, hence might just effectively contain a number of bytes.
* Must be big enough to hold data for all formats (currently 256 bits).
*/
union util_color {
ubyte ub;
ushort us;
uint ui;
ushort h[4]; /* half float */
float f[4];
double d[4];
};
 
/**
* Pack ubyte R,G,B,A into dest pixel.
*/
static INLINE void
util_pack_color_ub(ubyte r, ubyte g, ubyte b, ubyte a,
enum pipe_format format, union util_color *uc)
{
switch (format) {
case PIPE_FORMAT_ABGR8888_UNORM:
{
uc->ui = (r << 24) | (g << 16) | (b << 8) | a;
}
return;
case PIPE_FORMAT_XBGR8888_UNORM:
{
uc->ui = (r << 24) | (g << 16) | (b << 8) | 0xff;
}
return;
case PIPE_FORMAT_BGRA8888_UNORM:
{
uc->ui = (a << 24) | (r << 16) | (g << 8) | b;
}
return;
case PIPE_FORMAT_BGRX8888_UNORM:
{
uc->ui = (0xff << 24) | (r << 16) | (g << 8) | b;
}
return;
case PIPE_FORMAT_ARGB8888_UNORM:
{
uc->ui = (b << 24) | (g << 16) | (r << 8) | a;
}
return;
case PIPE_FORMAT_XRGB8888_UNORM:
{
uc->ui = (b << 24) | (g << 16) | (r << 8) | 0xff;
}
return;
case PIPE_FORMAT_B5G6R5_UNORM:
{
uc->us = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | (b >> 3);
}
return;
case PIPE_FORMAT_B5G5R5X1_UNORM:
{
uc->us = ((0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3);
}
return;
case PIPE_FORMAT_B5G5R5A1_UNORM:
{
uc->us = ((a & 0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3);
}
return;
case PIPE_FORMAT_B4G4R4A4_UNORM:
{
uc->us = ((a & 0xf0) << 8) | ((r & 0xf0) << 4) | ((g & 0xf0) << 0) | (b >> 4);
}
return;
case PIPE_FORMAT_A8_UNORM:
{
uc->ub = a;
}
return;
case PIPE_FORMAT_L8_UNORM:
case PIPE_FORMAT_I8_UNORM:
{
uc->ub = r;
}
return;
case PIPE_FORMAT_R32G32B32A32_FLOAT:
{
uc->f[0] = (float)r / 255.0f;
uc->f[1] = (float)g / 255.0f;
uc->f[2] = (float)b / 255.0f;
uc->f[3] = (float)a / 255.0f;
}
return;
case PIPE_FORMAT_R32G32B32_FLOAT:
{
uc->f[0] = (float)r / 255.0f;
uc->f[1] = (float)g / 255.0f;
uc->f[2] = (float)b / 255.0f;
}
return;
 
/* Handle other cases with a generic function.
*/
default:
{
ubyte src[4];
 
src[0] = r;
src[1] = g;
src[2] = b;
src[3] = a;
util_format_write_4ub(format, src, 0, uc, 0, 0, 0, 1, 1);
}
}
}
 
/**
* Unpack RGBA from a packed pixel, returning values as ubytes in [0,255].
*/
static INLINE void
util_unpack_color_ub(enum pipe_format format, union util_color *uc,
ubyte *r, ubyte *g, ubyte *b, ubyte *a)
{
switch (format) {
case PIPE_FORMAT_ABGR8888_UNORM:
{
uint p = uc->ui;
*r = (ubyte) ((p >> 24) & 0xff);
*g = (ubyte) ((p >> 16) & 0xff);
*b = (ubyte) ((p >> 8) & 0xff);
*a = (ubyte) ((p >> 0) & 0xff);
}
return;
case PIPE_FORMAT_XBGR8888_UNORM:
{
uint p = uc->ui;
*r = (ubyte) ((p >> 24) & 0xff);
*g = (ubyte) ((p >> 16) & 0xff);
*b = (ubyte) ((p >> 8) & 0xff);
*a = (ubyte) 0xff;
}
return;
case PIPE_FORMAT_BGRA8888_UNORM:
{
uint p = uc->ui;
*r = (ubyte) ((p >> 16) & 0xff);
*g = (ubyte) ((p >> 8) & 0xff);
*b = (ubyte) ((p >> 0) & 0xff);
*a = (ubyte) ((p >> 24) & 0xff);
}
return;
case PIPE_FORMAT_BGRX8888_UNORM:
{
uint p = uc->ui;
*r = (ubyte) ((p >> 16) & 0xff);
*g = (ubyte) ((p >> 8) & 0xff);
*b = (ubyte) ((p >> 0) & 0xff);
*a = (ubyte) 0xff;
}
return;
case PIPE_FORMAT_ARGB8888_UNORM:
{
uint p = uc->ui;
*r = (ubyte) ((p >> 8) & 0xff);
*g = (ubyte) ((p >> 16) & 0xff);
*b = (ubyte) ((p >> 24) & 0xff);
*a = (ubyte) ((p >> 0) & 0xff);
}
return;
case PIPE_FORMAT_XRGB8888_UNORM:
{
uint p = uc->ui;
*r = (ubyte) ((p >> 8) & 0xff);
*g = (ubyte) ((p >> 16) & 0xff);
*b = (ubyte) ((p >> 24) & 0xff);
*a = (ubyte) 0xff;
}
return;
case PIPE_FORMAT_B5G6R5_UNORM:
{
ushort p = uc->us;
*r = (ubyte) (((p >> 8) & 0xf8) | ((p >> 13) & 0x7));
*g = (ubyte) (((p >> 3) & 0xfc) | ((p >> 9) & 0x3));
*b = (ubyte) (((p << 3) & 0xf8) | ((p >> 2) & 0x7));
*a = (ubyte) 0xff;
}
return;
case PIPE_FORMAT_B5G5R5X1_UNORM:
{
ushort p = uc->us;
*r = (ubyte) (((p >> 7) & 0xf8) | ((p >> 12) & 0x7));
*g = (ubyte) (((p >> 2) & 0xf8) | ((p >> 7) & 0x7));
*b = (ubyte) (((p << 3) & 0xf8) | ((p >> 2) & 0x7));
*a = (ubyte) 0xff;
}
return;
case PIPE_FORMAT_B5G5R5A1_UNORM:
{
ushort p = uc->us;
*r = (ubyte) (((p >> 7) & 0xf8) | ((p >> 12) & 0x7));
*g = (ubyte) (((p >> 2) & 0xf8) | ((p >> 7) & 0x7));
*b = (ubyte) (((p << 3) & 0xf8) | ((p >> 2) & 0x7));
*a = (ubyte) (0xff * (p >> 15));
}
return;
case PIPE_FORMAT_B4G4R4A4_UNORM:
{
ushort p = uc->us;
*r = (ubyte) (((p >> 4) & 0xf0) | ((p >> 8) & 0xf));
*g = (ubyte) (((p >> 0) & 0xf0) | ((p >> 4) & 0xf));
*b = (ubyte) (((p << 4) & 0xf0) | ((p >> 0) & 0xf));
*a = (ubyte) (((p >> 8) & 0xf0) | ((p >> 12) & 0xf));
}
return;
case PIPE_FORMAT_A8_UNORM:
{
ubyte p = uc->ub;
*r = *g = *b = (ubyte) 0xff;
*a = p;
}
return;
case PIPE_FORMAT_L8_UNORM:
{
ubyte p = uc->ub;
*r = *g = *b = p;
*a = (ubyte) 0xff;
}
return;
case PIPE_FORMAT_I8_UNORM:
{
ubyte p = uc->ub;
*r = *g = *b = *a = p;
}
return;
case PIPE_FORMAT_R32G32B32A32_FLOAT:
{
const float *p = &uc->f[0];
*r = float_to_ubyte(p[0]);
*g = float_to_ubyte(p[1]);
*b = float_to_ubyte(p[2]);
*a = float_to_ubyte(p[3]);
}
return;
case PIPE_FORMAT_R32G32B32_FLOAT:
{
const float *p = &uc->f[0];
*r = float_to_ubyte(p[0]);
*g = float_to_ubyte(p[1]);
*b = float_to_ubyte(p[2]);
*a = (ubyte) 0xff;
}
return;
 
case PIPE_FORMAT_R32G32_FLOAT:
{
const float *p = &uc->f[0];
*r = float_to_ubyte(p[0]);
*g = float_to_ubyte(p[1]);
*b = *a = (ubyte) 0xff;
}
return;
 
case PIPE_FORMAT_R32_FLOAT:
{
const float *p = &uc->f[0];
*r = float_to_ubyte(p[0]);
*g = *b = *a = (ubyte) 0xff;
}
return;
 
/* Handle other cases with a generic function.
*/
default:
{
ubyte dst[4];
 
util_format_read_4ub(format, dst, 0, uc, 0, 0, 0, 1, 1);
*r = dst[0];
*g = dst[1];
*b = dst[2];
*a = dst[3];
}
}
}
 
 
/**
* Note rgba outside [0,1] will be clamped for int pixel formats.
* This will not work (and might not really be useful with float input)
* for pure integer formats (which lack the pack_rgba_float function).
*/
static INLINE void
util_pack_color(const float rgba[4], enum pipe_format format, union util_color *uc)
{
ubyte r = 0;
ubyte g = 0;
ubyte b = 0;
ubyte a = 0;
 
if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, 0) <= 8) {
/* format uses 8-bit components or less */
r = float_to_ubyte(rgba[0]);
g = float_to_ubyte(rgba[1]);
b = float_to_ubyte(rgba[2]);
a = float_to_ubyte(rgba[3]);
}
 
switch (format) {
case PIPE_FORMAT_ABGR8888_UNORM:
{
uc->ui = (r << 24) | (g << 16) | (b << 8) | a;
}
return;
case PIPE_FORMAT_XBGR8888_UNORM:
{
uc->ui = (r << 24) | (g << 16) | (b << 8) | 0xff;
}
return;
case PIPE_FORMAT_BGRA8888_UNORM:
{
uc->ui = (a << 24) | (r << 16) | (g << 8) | b;
}
return;
case PIPE_FORMAT_BGRX8888_UNORM:
{
uc->ui = (0xff << 24) | (r << 16) | (g << 8) | b;
}
return;
case PIPE_FORMAT_ARGB8888_UNORM:
{
uc->ui = (b << 24) | (g << 16) | (r << 8) | a;
}
return;
case PIPE_FORMAT_XRGB8888_UNORM:
{
uc->ui = (b << 24) | (g << 16) | (r << 8) | 0xff;
}
return;
case PIPE_FORMAT_B5G6R5_UNORM:
{
uc->us = ((r & 0xf8) << 8) | ((g & 0xfc) << 3) | (b >> 3);
}
return;
case PIPE_FORMAT_B5G5R5X1_UNORM:
{
uc->us = ((0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3);
}
return;
case PIPE_FORMAT_B5G5R5A1_UNORM:
{
uc->us = ((a & 0x80) << 8) | ((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3);
}
return;
case PIPE_FORMAT_B4G4R4A4_UNORM:
{
uc->us = ((a & 0xf0) << 8) | ((r & 0xf0) << 4) | ((g & 0xf0) << 0) | (b >> 4);
}
return;
case PIPE_FORMAT_A8_UNORM:
{
uc->ub = a;
}
return;
case PIPE_FORMAT_L8_UNORM:
case PIPE_FORMAT_I8_UNORM:
{
uc->ub = r;
}
return;
case PIPE_FORMAT_R32G32B32A32_FLOAT:
{
uc->f[0] = rgba[0];
uc->f[1] = rgba[1];
uc->f[2] = rgba[2];
uc->f[3] = rgba[3];
}
return;
case PIPE_FORMAT_R32G32B32_FLOAT:
{
uc->f[0] = rgba[0];
uc->f[1] = rgba[1];
uc->f[2] = rgba[2];
}
return;
 
/* Handle other cases with a generic function.
*/
default:
util_format_write_4f(format, rgba, 0, uc, 0, 0, 0, 1, 1);
}
}
/* Integer versions of util_pack_z and util_pack_z_stencil - useful for
* constructing clear masks.
*/
static INLINE uint32_t
util_pack_mask_z(enum pipe_format format, uint32_t z)
{
switch (format) {
case PIPE_FORMAT_Z16_UNORM:
return z & 0xffff;
case PIPE_FORMAT_Z32_UNORM:
case PIPE_FORMAT_Z32_FLOAT:
return z;
case PIPE_FORMAT_Z24_UNORM_S8_UINT:
case PIPE_FORMAT_Z24X8_UNORM:
return z & 0xffffff;
case PIPE_FORMAT_S8_UINT_Z24_UNORM:
case PIPE_FORMAT_X8Z24_UNORM:
return (z & 0xffffff) << 8;
case PIPE_FORMAT_S8_UINT:
return 0;
default:
debug_print_format("gallium: unhandled format in util_pack_mask_z()", format);
assert(0);
return 0;
}
}
 
 
static INLINE uint64_t
util_pack64_mask_z(enum pipe_format format, uint32_t z)
{
switch (format) {
case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
return z;
default:
return util_pack_mask_z(format, z);
}
}
 
 
static INLINE uint32_t
util_pack_mask_z_stencil(enum pipe_format format, uint32_t z, uint8_t s)
{
uint32_t packed = util_pack_mask_z(format, z);
 
switch (format) {
case PIPE_FORMAT_Z24_UNORM_S8_UINT:
packed |= (uint32_t)s << 24;
break;
case PIPE_FORMAT_S8_UINT_Z24_UNORM:
packed |= s;
break;
case PIPE_FORMAT_S8_UINT:
packed |= s;
break;
default:
break;
}
 
return packed;
}
 
 
static INLINE uint64_t
util_pack64_mask_z_stencil(enum pipe_format format, uint32_t z, uint8_t s)
{
uint64_t packed;
 
switch (format) {
case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
packed = util_pack64_mask_z(format, z);
packed |= (uint64_t)s << 32ull;
return packed;
default:
return util_pack_mask_z_stencil(format, z, s);
}
}
 
 
/**
* Note: it's assumed that z is in [0,1]
*/
static INLINE uint32_t
util_pack_z(enum pipe_format format, double z)
{
union fi fui;
 
if (z == 0.0)
return 0;
 
switch (format) {
case PIPE_FORMAT_Z16_UNORM:
if (z == 1.0)
return 0xffff;
return (uint32_t) (z * 0xffff);
case PIPE_FORMAT_Z32_UNORM:
/* special-case to avoid overflow */
if (z == 1.0)
return 0xffffffff;
return (uint32_t) (z * 0xffffffff);
case PIPE_FORMAT_Z32_FLOAT:
fui.f = (float)z;
return fui.ui;
case PIPE_FORMAT_Z24_UNORM_S8_UINT:
case PIPE_FORMAT_Z24X8_UNORM:
if (z == 1.0)
return 0xffffff;
return (uint32_t) (z * 0xffffff);
case PIPE_FORMAT_S8_UINT_Z24_UNORM:
case PIPE_FORMAT_X8Z24_UNORM:
if (z == 1.0)
return 0xffffff00;
return ((uint32_t) (z * 0xffffff)) << 8;
case PIPE_FORMAT_S8_UINT:
/* this case can get it via util_pack_z_stencil() */
return 0;
default:
debug_print_format("gallium: unhandled format in util_pack_z()", format);
assert(0);
return 0;
}
}
 
 
static INLINE uint64_t
util_pack64_z(enum pipe_format format, double z)
{
union fi fui;
 
if (z == 0)
return 0;
 
switch (format) {
case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
fui.f = (float)z;
return fui.ui;
default:
return util_pack_z(format, z);
}
}
 
/**
* Pack Z and/or stencil values into a 32-bit value described by format.
* Note: it's assumed that z is in [0,1] and s in [0,255]
*/
static INLINE uint32_t
util_pack_z_stencil(enum pipe_format format, double z, uint8_t s)
{
uint32_t packed = util_pack_z(format, z);
 
switch (format) {
case PIPE_FORMAT_Z24_UNORM_S8_UINT:
packed |= (uint32_t)s << 24;
break;
case PIPE_FORMAT_S8_UINT_Z24_UNORM:
packed |= s;
break;
case PIPE_FORMAT_S8_UINT:
packed |= s;
break;
default:
break;
}
 
return packed;
}
 
 
static INLINE uint64_t
util_pack64_z_stencil(enum pipe_format format, double z, uint8_t s)
{
uint64_t packed;
 
switch (format) {
case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
packed = util_pack64_z(format, z);
packed |= (uint64_t)s << 32ull;
break;
default:
return util_pack_z_stencil(format, z, s);
}
 
return packed;
}
 
 
/**
* Pack 4 ubytes into a 4-byte word
*/
static INLINE unsigned
pack_ub4(ubyte b0, ubyte b1, ubyte b2, ubyte b3)
{
return ((((unsigned int)b0) << 0) |
(((unsigned int)b1) << 8) |
(((unsigned int)b2) << 16) |
(((unsigned int)b3) << 24));
}
 
 
/**
* Pack/convert 4 floats into one 4-byte word.
*/
static INLINE unsigned
pack_ui32_float4(float a, float b, float c, float d)
{
return pack_ub4( float_to_ubyte(a),
float_to_ubyte(b),
float_to_ubyte(c),
float_to_ubyte(d) );
}
 
 
 
#endif /* U_PACK_COLOR_H */
/drivers/video/Gallium/auxiliary/util/u_pointer.h
0,0 → 1,130
/**************************************************************************
*
* Copyright 2007-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.
*
**************************************************************************/
 
#ifndef U_POINTER_H
#define U_POINTER_H
 
#include "pipe/p_compiler.h"
 
#ifdef __cplusplus
extern "C" {
#endif
 
static INLINE intptr_t
pointer_to_intptr( const void *p )
{
union {
const void *p;
intptr_t i;
} pi;
pi.p = p;
return pi.i;
}
 
static INLINE void *
intptr_to_pointer( intptr_t i )
{
union {
void *p;
intptr_t i;
} pi;
pi.i = i;
return pi.p;
}
 
static INLINE uintptr_t
pointer_to_uintptr( const void *ptr )
{
union {
const void *p;
uintptr_t u;
} pu;
pu.p = ptr;
return pu.u;
}
 
static INLINE void *
uintptr_to_pointer( uintptr_t u )
{
union {
void *p;
uintptr_t u;
} pu;
pu.u = u;
return pu.p;
}
 
/**
* Return a pointer aligned to next multiple of N bytes.
*/
static INLINE void *
align_pointer( const void *unaligned, uintptr_t alignment )
{
uintptr_t aligned = (pointer_to_uintptr( unaligned ) + alignment - 1) & ~(alignment - 1);
return uintptr_to_pointer( aligned );
}
 
 
/**
* Return a pointer aligned to next multiple of 16 bytes.
*/
static INLINE void *
align16( void *unaligned )
{
return align_pointer( unaligned, 16 );
}
 
typedef void (*func_pointer)(void);
 
static INLINE func_pointer
pointer_to_func( void *p )
{
union {
void *p;
func_pointer f;
} pf;
pf.p = p;
return pf.f;
}
 
static INLINE void *
func_to_pointer( func_pointer f )
{
union {
void *p;
func_pointer f;
} pf;
pf.f = f;
return pf.p;
}
 
 
#ifdef __cplusplus
}
#endif
 
#endif /* U_POINTER_H */
/drivers/video/Gallium/auxiliary/util/u_prim.h
0,0 → 1,268
/**************************************************************************
*
* 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.
*
**************************************************************************/
 
 
#ifndef U_PRIM_H
#define U_PRIM_H
 
 
#include "pipe/p_defines.h"
#include "util/u_debug.h"
 
#ifdef __cplusplus
extern "C" {
#endif
 
struct u_prim_vertex_count {
unsigned min;
unsigned incr;
};
 
/**
* Decompose a primitive that is a loop, a strip, or a fan. Return the
* original primitive if it is already decomposed.
*/
static INLINE unsigned
u_decomposed_prim(unsigned prim)
{
switch (prim) {
case PIPE_PRIM_LINE_LOOP:
case PIPE_PRIM_LINE_STRIP:
return PIPE_PRIM_LINES;
case PIPE_PRIM_TRIANGLE_STRIP:
case PIPE_PRIM_TRIANGLE_FAN:
return PIPE_PRIM_TRIANGLES;
case PIPE_PRIM_QUAD_STRIP:
return PIPE_PRIM_QUADS;
case PIPE_PRIM_LINE_STRIP_ADJACENCY:
return PIPE_PRIM_LINES_ADJACENCY;
case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
return PIPE_PRIM_TRIANGLES_ADJACENCY;
default:
return prim;
}
}
 
/**
* Reduce a primitive to one of PIPE_PRIM_POINTS, PIPE_PRIM_LINES, and
* PIPE_PRIM_TRIANGLES.
*/
static INLINE unsigned
u_reduced_prim(unsigned prim)
{
switch (prim) {
case PIPE_PRIM_POINTS:
return PIPE_PRIM_POINTS;
case PIPE_PRIM_LINES:
case PIPE_PRIM_LINE_LOOP:
case PIPE_PRIM_LINE_STRIP:
case PIPE_PRIM_LINES_ADJACENCY:
case PIPE_PRIM_LINE_STRIP_ADJACENCY:
return PIPE_PRIM_LINES;
default:
return PIPE_PRIM_TRIANGLES;
}
}
 
/**
* Re-assemble a primitive to remove its adjacency.
*/
static INLINE unsigned
u_assembled_prim(unsigned prim)
{
switch (prim) {
case PIPE_PRIM_LINES_ADJACENCY:
case PIPE_PRIM_LINE_STRIP_ADJACENCY:
return PIPE_PRIM_LINES;
case PIPE_PRIM_TRIANGLES_ADJACENCY:
case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
return PIPE_PRIM_TRIANGLES;
default:
return prim;
}
}
 
/**
* Return the vertex count information for a primitive.
*
* Note that if this function is called directly or indirectly anywhere in a
* source file, it will increase the size of the binary slightly more than
* expected because of the use of a table.
*/
static INLINE const struct u_prim_vertex_count *
u_prim_vertex_count(unsigned prim)
{
static const struct u_prim_vertex_count prim_table[PIPE_PRIM_MAX] = {
{ 1, 1 }, /* PIPE_PRIM_POINTS */
{ 2, 2 }, /* PIPE_PRIM_LINES */
{ 2, 1 }, /* PIPE_PRIM_LINE_LOOP */
{ 2, 1 }, /* PIPE_PRIM_LINE_STRIP */
{ 3, 3 }, /* PIPE_PRIM_TRIANGLES */
{ 3, 1 }, /* PIPE_PRIM_TRIANGLE_STRIP */
{ 3, 1 }, /* PIPE_PRIM_TRIANGLE_FAN */
{ 4, 4 }, /* PIPE_PRIM_QUADS */
{ 4, 2 }, /* PIPE_PRIM_QUAD_STRIP */
{ 3, 1 }, /* PIPE_PRIM_POLYGON */
{ 4, 4 }, /* PIPE_PRIM_LINES_ADJACENCY */
{ 4, 1 }, /* PIPE_PRIM_LINE_STRIP_ADJACENCY */
{ 6, 6 }, /* PIPE_PRIM_TRIANGLES_ADJACENCY */
{ 6, 2 }, /* PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY */
};
 
return (likely(prim < PIPE_PRIM_MAX)) ? &prim_table[prim] : NULL;
}
 
static INLINE boolean u_validate_pipe_prim( unsigned pipe_prim, unsigned nr )
{
const struct u_prim_vertex_count *count = u_prim_vertex_count(pipe_prim);
 
return (count && nr >= count->min);
}
 
 
static INLINE boolean u_trim_pipe_prim( unsigned pipe_prim, unsigned *nr )
{
const struct u_prim_vertex_count *count = u_prim_vertex_count(pipe_prim);
 
if (count && *nr >= count->min) {
if (count->incr > 1)
*nr -= (*nr % count->incr);
return TRUE;
}
else {
*nr = 0;
return FALSE;
}
}
 
static INLINE unsigned
u_vertices_per_prim(int primitive)
{
switch(primitive) {
case PIPE_PRIM_POINTS:
return 1;
case PIPE_PRIM_LINES:
case PIPE_PRIM_LINE_LOOP:
case PIPE_PRIM_LINE_STRIP:
return 2;
case PIPE_PRIM_TRIANGLES:
case PIPE_PRIM_TRIANGLE_STRIP:
case PIPE_PRIM_TRIANGLE_FAN:
return 3;
case PIPE_PRIM_LINES_ADJACENCY:
case PIPE_PRIM_LINE_STRIP_ADJACENCY:
return 4;
case PIPE_PRIM_TRIANGLES_ADJACENCY:
case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
return 6;
 
/* following primitives should never be used
* with geometry shaders abd their size is
* undefined */
case PIPE_PRIM_POLYGON:
case PIPE_PRIM_QUADS:
case PIPE_PRIM_QUAD_STRIP:
default:
debug_printf("Unrecognized geometry shader primitive");
return 3;
}
}
 
/**
* Returns the number of decomposed primitives for the given
* vertex count.
* Parts of the pipline are invoked once for each triangle in
* triangle strip, triangle fans and triangles and once
* for each line in line strip, line loop, lines. Also
* statistics depend on knowing the exact number of decomposed
* primitives for a set of vertices.
*/
static INLINE unsigned
u_decomposed_prims_for_vertices(int primitive, int vertices)
{
switch (primitive) {
case PIPE_PRIM_POINTS:
return vertices;
case PIPE_PRIM_LINES:
return vertices / 2;
case PIPE_PRIM_LINE_LOOP:
return (vertices >= 2) ? vertices : 0;
case PIPE_PRIM_LINE_STRIP:
return (vertices >= 2) ? vertices - 1 : 0;
case PIPE_PRIM_TRIANGLES:
return vertices / 3;
case PIPE_PRIM_TRIANGLE_STRIP:
return (vertices >= 3) ? vertices - 2 : 0;
case PIPE_PRIM_TRIANGLE_FAN:
return (vertices >= 3) ? vertices - 2 : 0;
case PIPE_PRIM_LINES_ADJACENCY:
return vertices / 4;
case PIPE_PRIM_LINE_STRIP_ADJACENCY:
return (vertices >= 4) ? vertices - 3 : 0;
case PIPE_PRIM_TRIANGLES_ADJACENCY:
return vertices / 6;
case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
return (vertices >= 6) ? 1 + (vertices - 6) / 2 : 0;
case PIPE_PRIM_QUADS:
return vertices / 4;
case PIPE_PRIM_QUAD_STRIP:
return (vertices >= 4) ? (vertices - 2) / 2 : 0;
/* Polygons can't be decomposed
* because the number of their vertices isn't known so
* for them and whatever else we don't recognize just
* return 1 if the number of vertices is greater than
* or equal to 3 and zero otherwise */
case PIPE_PRIM_POLYGON:
default:
debug_printf("Invalid decomposition primitive!\n");
return (vertices >= 3) ? 1 : 0;
}
}
 
/**
* Returns the number of reduced/tessellated primitives for the given vertex
* count. Each quad is treated as two triangles. Polygons are treated as
* triangle fans.
*/
static INLINE unsigned
u_reduced_prims_for_vertices(int primitive, int vertices)
{
switch (primitive) {
case PIPE_PRIM_QUADS:
case PIPE_PRIM_QUAD_STRIP:
return u_decomposed_prims_for_vertices(primitive, vertices) * 2;
case PIPE_PRIM_POLYGON:
primitive = PIPE_PRIM_TRIANGLE_FAN;
/* fall through */
default:
return u_decomposed_prims_for_vertices(primitive, vertices);
}
}
 
const char *u_prim_name( unsigned pipe_prim );
 
#endif
/drivers/video/Gallium/auxiliary/util/u_pstipple.c
0,0 → 1,456
/**************************************************************************
*
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* Copyright 2010 VMware, Inc.
* 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.
*
**************************************************************************/
 
/**
* Polygon stipple helper module. Drivers/GPUs which don't support polygon
* stipple natively can use this module to simulate it.
*
* Basically, modify fragment shader to sample the 32x32 stipple pattern
* texture and do a fragment kill for the 'off' bits.
*
* This was originally a 'draw' module stage, but since we don't need
* vertex window coords or anything, it can be a stand-alone utility module.
*
* Authors: Brian Paul
*/
 
 
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "pipe/p_shader_tokens.h"
#include "util/u_inlines.h"
 
#include "util/u_format.h"
#include "util/u_memory.h"
#include "util/u_pstipple.h"
#include "util/u_sampler.h"
 
#include "tgsi/tgsi_transform.h"
#include "tgsi/tgsi_dump.h"
#include "tgsi/tgsi_scan.h"
 
/** Approx number of new tokens for instructions in pstip_transform_inst() */
#define NUM_NEW_TOKENS 50
 
 
static void
util_pstipple_update_stipple_texture(struct pipe_context *pipe,
struct pipe_resource *tex,
const uint32_t pattern[32])
{
static const uint bit31 = 1 << 31;
struct pipe_transfer *transfer;
ubyte *data;
int i, j;
 
/* map texture memory */
data = pipe_transfer_map(pipe, tex, 0, 0,
PIPE_TRANSFER_WRITE, 0, 0, 32, 32, &transfer);
 
/*
* Load alpha texture.
* Note: 0 means keep the fragment, 255 means kill it.
* We'll negate the texel value and use KILP which kills if value
* is negative.
*/
for (i = 0; i < 32; i++) {
for (j = 0; j < 32; j++) {
if (pattern[i] & (bit31 >> j)) {
/* fragment "on" */
data[i * transfer->stride + j] = 0;
}
else {
/* fragment "off" */
data[i * transfer->stride + j] = 255;
}
}
}
 
/* unmap */
pipe->transfer_unmap(pipe, transfer);
}
 
 
/**
* Create a 32x32 alpha8 texture that encodes the given stipple pattern.
*/
struct pipe_resource *
util_pstipple_create_stipple_texture(struct pipe_context *pipe,
const uint32_t pattern[32])
{
struct pipe_screen *screen = pipe->screen;
struct pipe_resource templat, *tex;
 
memset(&templat, 0, sizeof(templat));
templat.target = PIPE_TEXTURE_2D;
templat.format = PIPE_FORMAT_A8_UNORM;
templat.last_level = 0;
templat.width0 = 32;
templat.height0 = 32;
templat.depth0 = 1;
templat.array_size = 1;
templat.bind = PIPE_BIND_SAMPLER_VIEW;
 
tex = screen->resource_create(screen, &templat);
 
if (tex)
util_pstipple_update_stipple_texture(pipe, tex, pattern);
 
return tex;
}
 
 
/**
* Create sampler view to sample the stipple texture.
*/
struct pipe_sampler_view *
util_pstipple_create_sampler_view(struct pipe_context *pipe,
struct pipe_resource *tex)
{
struct pipe_sampler_view templat, *sv;
 
u_sampler_view_default_template(&templat, tex, tex->format);
sv = pipe->create_sampler_view(pipe, tex, &templat);
 
return sv;
}
 
 
/**
* Create the sampler CSO that'll be used for stippling.
*/
void *
util_pstipple_create_sampler(struct pipe_context *pipe)
{
struct pipe_sampler_state templat;
void *s;
 
memset(&templat, 0, sizeof(templat));
templat.wrap_s = PIPE_TEX_WRAP_REPEAT;
templat.wrap_t = PIPE_TEX_WRAP_REPEAT;
templat.wrap_r = PIPE_TEX_WRAP_REPEAT;
templat.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
templat.min_img_filter = PIPE_TEX_FILTER_NEAREST;
templat.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
templat.normalized_coords = 1;
templat.min_lod = 0.0f;
templat.max_lod = 0.0f;
 
s = pipe->create_sampler_state(pipe, &templat);
return s;
}
 
 
 
/**
* Subclass of tgsi_transform_context, used for transforming the
* user's fragment shader to add the extra texture sample and fragment kill
* instructions.
*/
struct pstip_transform_context {
struct tgsi_transform_context base;
struct tgsi_shader_info info;
uint tempsUsed; /**< bitmask */
int wincoordInput;
int maxInput;
uint samplersUsed; /**< bitfield of samplers used */
int freeSampler; /** an available sampler for the pstipple */
int texTemp; /**< temp registers */
int numImmed;
boolean firstInstruction;
uint coordOrigin;
};
 
 
/**
* TGSI declaration transform callback.
* Track samplers used, temps used, inputs used.
*/
static void
pstip_transform_decl(struct tgsi_transform_context *ctx,
struct tgsi_full_declaration *decl)
{
struct pstip_transform_context *pctx =
(struct pstip_transform_context *) ctx;
 
/* XXX we can use tgsi_shader_info instead of some of this */
 
if (decl->Declaration.File == TGSI_FILE_SAMPLER) {
uint i;
for (i = decl->Range.First; i <= decl->Range.Last; i++) {
pctx->samplersUsed |= 1 << i;
}
}
else if (decl->Declaration.File == TGSI_FILE_INPUT) {
pctx->maxInput = MAX2(pctx->maxInput, (int) decl->Range.Last);
if (decl->Semantic.Name == TGSI_SEMANTIC_POSITION)
pctx->wincoordInput = (int) decl->Range.First;
}
else if (decl->Declaration.File == TGSI_FILE_TEMPORARY) {
uint i;
for (i = decl->Range.First; i <= decl->Range.Last; i++) {
pctx->tempsUsed |= (1 << i);
}
}
 
ctx->emit_declaration(ctx, decl);
}
 
 
static void
pstip_transform_immed(struct tgsi_transform_context *ctx,
struct tgsi_full_immediate *immed)
{
struct pstip_transform_context *pctx =
(struct pstip_transform_context *) ctx;
pctx->numImmed++;
}
 
 
/**
* Find the lowest zero bit in the given word, or -1 if bitfield is all ones.
*/
static int
free_bit(uint bitfield)
{
return ffs(~bitfield) - 1;
}
 
 
/**
* TGSI instruction transform callback.
* Before the first instruction, insert our new code to sample the
* stipple texture (using the fragment coord register) then kill the
* fragment if the stipple texture bit is off.
*
* Insert:
* declare new registers
* MUL texTemp, INPUT[wincoord], 1/32;
* TEX texTemp, texTemp, sampler;
* KIL -texTemp; # if -texTemp < 0, KILL fragment
* [...original code...]
*/
static void
pstip_transform_inst(struct tgsi_transform_context *ctx,
struct tgsi_full_instruction *inst)
{
struct pstip_transform_context *pctx =
(struct pstip_transform_context *) ctx;
 
if (pctx->firstInstruction) {
/* emit our new declarations before the first instruction */
 
struct tgsi_full_declaration decl;
struct tgsi_full_instruction newInst;
uint i;
int wincoordInput;
 
/* find free texture sampler */
pctx->freeSampler = free_bit(pctx->samplersUsed);
if (pctx->freeSampler >= PIPE_MAX_SAMPLERS)
pctx->freeSampler = PIPE_MAX_SAMPLERS - 1;
 
if (pctx->wincoordInput < 0)
wincoordInput = pctx->maxInput + 1;
else
wincoordInput = pctx->wincoordInput;
 
/* find one free temp register */
for (i = 0; i < 32; i++) {
if ((pctx->tempsUsed & (1 << i)) == 0) {
/* found a free temp */
if (pctx->texTemp < 0)
pctx->texTemp = i;
else
break;
}
}
assert(pctx->texTemp >= 0);
 
if (pctx->wincoordInput < 0) {
/* declare new position input reg */
decl = tgsi_default_full_declaration();
decl.Declaration.File = TGSI_FILE_INPUT;
decl.Declaration.Interpolate = 1;
decl.Declaration.Semantic = 1;
decl.Semantic.Name = TGSI_SEMANTIC_POSITION;
decl.Semantic.Index = 0;
decl.Range.First =
decl.Range.Last = wincoordInput;
decl.Interp.Interpolate = TGSI_INTERPOLATE_LINEAR;
ctx->emit_declaration(ctx, &decl);
}
 
/* declare new sampler */
decl = tgsi_default_full_declaration();
decl.Declaration.File = TGSI_FILE_SAMPLER;
decl.Range.First =
decl.Range.Last = pctx->freeSampler;
ctx->emit_declaration(ctx, &decl);
 
/* declare new temp regs */
decl = tgsi_default_full_declaration();
decl.Declaration.File = TGSI_FILE_TEMPORARY;
decl.Range.First =
decl.Range.Last = pctx->texTemp;
ctx->emit_declaration(ctx, &decl);
 
/* emit immediate = {1/32, 1/32, 1, 1}
* The index/position of this immediate will be pctx->numImmed
*/
{
static const float value[4] = { 1.0/32, 1.0/32, 1.0, 1.0 };
struct tgsi_full_immediate immed;
uint size = 4;
immed = tgsi_default_full_immediate();
immed.Immediate.NrTokens = 1 + size; /* one for the token itself */
immed.u[0].Float = value[0];
immed.u[1].Float = value[1];
immed.u[2].Float = value[2];
immed.u[3].Float = value[3];
ctx->emit_immediate(ctx, &immed);
}
 
pctx->firstInstruction = FALSE;
 
 
/*
* Insert new MUL/TEX/KILP instructions at start of program
* Take gl_FragCoord, divide by 32 (stipple size), sample the
* texture and kill fragment if needed.
*
* We'd like to use non-normalized texcoords to index into a RECT
* texture, but we can only use REPEAT wrap mode with normalized
* texcoords. Darn.
*/
 
/* XXX invert wincoord if origin isn't lower-left... */
 
/* MUL texTemp, INPUT[wincoord], 1/32; */
newInst = tgsi_default_full_instruction();
newInst.Instruction.Opcode = TGSI_OPCODE_MUL;
newInst.Instruction.NumDstRegs = 1;
newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY;
newInst.Dst[0].Register.Index = pctx->texTemp;
newInst.Instruction.NumSrcRegs = 2;
newInst.Src[0].Register.File = TGSI_FILE_INPUT;
newInst.Src[0].Register.Index = wincoordInput;
newInst.Src[1].Register.File = TGSI_FILE_IMMEDIATE;
newInst.Src[1].Register.Index = pctx->numImmed;
ctx->emit_instruction(ctx, &newInst);
 
/* TEX texTemp, texTemp, sampler; */
newInst = tgsi_default_full_instruction();
newInst.Instruction.Opcode = TGSI_OPCODE_TEX;
newInst.Instruction.NumDstRegs = 1;
newInst.Dst[0].Register.File = TGSI_FILE_TEMPORARY;
newInst.Dst[0].Register.Index = pctx->texTemp;
newInst.Instruction.NumSrcRegs = 2;
newInst.Instruction.Texture = TRUE;
newInst.Texture.Texture = TGSI_TEXTURE_2D;
newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY;
newInst.Src[0].Register.Index = pctx->texTemp;
newInst.Src[1].Register.File = TGSI_FILE_SAMPLER;
newInst.Src[1].Register.Index = pctx->freeSampler;
ctx->emit_instruction(ctx, &newInst);
 
/* KIL -texTemp; # if -texTemp < 0, KILL fragment */
newInst = tgsi_default_full_instruction();
newInst.Instruction.Opcode = TGSI_OPCODE_KIL;
newInst.Instruction.NumDstRegs = 0;
newInst.Instruction.NumSrcRegs = 1;
newInst.Src[0].Register.File = TGSI_FILE_TEMPORARY;
newInst.Src[0].Register.Index = pctx->texTemp;
newInst.Src[0].Register.Negate = 1;
ctx->emit_instruction(ctx, &newInst);
}
 
/* emit this instruction */
ctx->emit_instruction(ctx, inst);
}
 
 
/**
* Given a fragment shader, return a new fragment shader which
* samples a stipple texture and executes KILL.
*/
struct pipe_shader_state *
util_pstipple_create_fragment_shader(struct pipe_context *pipe,
struct pipe_shader_state *fs,
unsigned *samplerUnitOut)
{
struct pipe_shader_state *new_fs;
struct pstip_transform_context transform;
const uint newLen = tgsi_num_tokens(fs->tokens) + NUM_NEW_TOKENS;
unsigned i;
 
new_fs = MALLOC(sizeof(*new_fs));
if (!new_fs)
return NULL;
 
new_fs->tokens = tgsi_alloc_tokens(newLen);
if (!new_fs->tokens) {
FREE(new_fs);
return NULL;
}
 
/* Setup shader transformation info/context.
*/
memset(&transform, 0, sizeof(transform));
transform.wincoordInput = -1;
transform.maxInput = -1;
transform.texTemp = -1;
transform.firstInstruction = TRUE;
transform.coordOrigin = TGSI_FS_COORD_ORIGIN_UPPER_LEFT;
transform.base.transform_instruction = pstip_transform_inst;
transform.base.transform_declaration = pstip_transform_decl;
transform.base.transform_immediate = pstip_transform_immed;
 
tgsi_scan_shader(fs->tokens, &transform.info);
 
/* find fragment coordinate origin property */
for (i = 0; i < transform.info.num_properties; i++) {
if (transform.info.properties[i].name == TGSI_PROPERTY_FS_COORD_ORIGIN)
transform.coordOrigin = transform.info.properties[i].data[0];
}
 
tgsi_transform_shader(fs->tokens,
(struct tgsi_token *) new_fs->tokens,
newLen, &transform.base);
 
#if 0 /* DEBUG */
tgsi_dump(fs->tokens, 0);
tgsi_dump(new_fs->tokens, 0);
#endif
 
assert(transform.freeSampler < PIPE_MAX_SAMPLERS);
*samplerUnitOut = transform.freeSampler;
 
return new_fs;
}
 
/drivers/video/Gallium/auxiliary/util/u_pstipple.h
0,0 → 1,56
/**************************************************************************
*
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* Copyright 2010 VMware, Inc.
* 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.
*
**************************************************************************/
 
#ifndef U_PSTIPPLE_H
#define U_PSTIPPLE_H
 
#include "pipe/p_compiler.h"
 
struct pipe_context;
struct pipe_resource;
struct pipe_shader_state;
 
 
extern struct pipe_resource *
util_pstipple_create_stipple_texture(struct pipe_context *pipe,
const uint32_t pattern[32]);
 
extern struct pipe_sampler_view *
util_pstipple_create_sampler_view(struct pipe_context *pipe,
struct pipe_resource *tex);
 
extern void *
util_pstipple_create_sampler(struct pipe_context *pipe);
 
extern struct pipe_shader_state *
util_pstipple_create_fragment_shader(struct pipe_context *pipe,
struct pipe_shader_state *fs,
unsigned *samplerUnitOut);
 
 
#endif
/drivers/video/Gallium/auxiliary/util/u_range.h
0,0 → 1,89
/*
* Copyright 2013 Marek Olšák <maraeo@gmail.com>
*
* 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
* on 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
* THE AUTHOR(S) AND/OR THEIR 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
* 1D integer range, capable of the union and intersection operations.
*
* It only maintains a single interval which is extended when the union is
* done. This implementation is partially thread-safe (readers are not
* protected by a lock).
*
* @author Marek Olšák
*/
 
#ifndef U_RANGE_H
#define U_RANGE_H
 
#include "os/os_thread.h"
 
struct util_range {
unsigned start; /* inclusive */
unsigned end; /* exclusive */
 
/* for the range to be consistent with multiple contexts: */
pipe_mutex write_mutex;
};
 
 
static INLINE void
util_range_set_empty(struct util_range *range)
{
range->start = ~0;
range->end = 0;
}
 
/* This is like a union of two sets. */
static INLINE void
util_range_add(struct util_range *range, unsigned start, unsigned end)
{
if (start < range->start || end > range->end) {
pipe_mutex_lock(range->write_mutex);
range->start = MIN2(start, range->start);
range->end = MAX2(end, range->end);
pipe_mutex_unlock(range->write_mutex);
}
}
 
static INLINE boolean
util_ranges_intersect(struct util_range *range, unsigned start, unsigned end)
{
return MAX2(start, range->start) < MIN2(end, range->end);
}
 
 
/* Init/deinit */
 
static INLINE void
util_range_init(struct util_range *range)
{
pipe_mutex_init(range->write_mutex);
util_range_set_empty(range);
}
 
static INLINE void
util_range_destroy(struct util_range *range)
{
pipe_mutex_destroy(range->write_mutex);
}
 
#endif
/drivers/video/Gallium/auxiliary/util/u_rect.h
0,0 → 1,92
/**************************************************************************
*
* 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.
*
**************************************************************************/
 
 
#ifndef U_RECT_H
#define U_RECT_H
 
#include "pipe/p_compiler.h"
 
#ifdef __cplusplus
extern "C" {
#endif
 
struct u_rect {
int x0, x1;
int y0, y1;
};
 
/* Do two rectangles intersect?
*/
static INLINE boolean
u_rect_test_intersection(const struct u_rect *a,
const struct u_rect *b)
{
return (!(a->x1 < b->x0 ||
b->x1 < a->x0 ||
a->y1 < b->y0 ||
b->y1 < a->y0));
}
 
/* Find the intersection of two rectangles known to intersect.
*/
static INLINE void
u_rect_find_intersection(const struct u_rect *a,
struct u_rect *b)
{
/* Caller should verify intersection exists before calling.
*/
if (b->x0 < a->x0) b->x0 = a->x0;
if (b->x1 > a->x1) b->x1 = a->x1;
if (b->y0 < a->y0) b->y0 = a->y0;
if (b->y1 > a->y1) b->y1 = a->y1;
}
 
 
static INLINE void
u_rect_possible_intersection(const struct u_rect *a,
struct u_rect *b)
{
if (u_rect_test_intersection(a,b)) {
u_rect_find_intersection(a,b);
}
else {
b->x0 = b->x1 = b->y0 = b->y1 = 0;
}
}
 
#ifdef __cplusplus
}
#endif
 
 
/* Include pipe copy/fill rect helpers declarations for backwards compatibility
*/
#include "util/u_surface.h"
 
 
#endif /* U_RECT_H */
/drivers/video/Gallium/auxiliary/util/u_resource.c
0,0 → 1,65
/*
* Copyright 2013 VMware, Inc.
* 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 THE AUTHORS 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.
*/
 
 
#include "pipe/p_defines.h"
#include "pipe/p_state.h"
#include "util/u_format.h"
#include "util/u_math.h"
#include "util/u_resource.h"
 
 
/**
* Return the size of the resource in bytes.
*/
unsigned
util_resource_size(const struct pipe_resource *res)
{
unsigned width = res->width0;
unsigned height = res->height0;
unsigned depth = res->depth0;
unsigned size = 0;
unsigned level;
 
for (level = 0; level <= res->last_level; level++) {
unsigned slices;
 
if (res->target == PIPE_TEXTURE_CUBE)
slices = 6;
else if (res->target == PIPE_TEXTURE_3D)
slices = depth;
else
slices = res->array_size;
 
size += (util_format_get_nblocksy(res->format, height) *
util_format_get_stride(res->format, width) * slices);
 
width = u_minify(width, 1);
height = u_minify(height, 1);
depth = u_minify(depth, 1);
}
 
return size;
}
/drivers/video/Gallium/auxiliary/util/u_resource.h
0,0 → 1,52
/*
* Copyright 2013 VMware, Inc.
* 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 THE AUTHORS 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.
*/
 
#ifndef U_RESOURCE_H
#define U_RESOURCE_H
 
#include "pipe/p_state.h"
 
unsigned
util_resource_size(const struct pipe_resource *res);
 
/**
* Return true if the resource is an array texture.
*
* Note that this function returns true for single-layered array textures.
*/
static INLINE boolean
util_resource_is_array_texture(const struct pipe_resource *res)
{
switch (res->target) {
case PIPE_TEXTURE_1D_ARRAY:
case PIPE_TEXTURE_2D_ARRAY:
case PIPE_TEXTURE_CUBE_ARRAY:
return TRUE;
default:
return FALSE;
}
}
 
#endif
/drivers/video/Gallium/auxiliary/util/u_ringbuffer.c
0,0 → 1,160
 
#include "os/os_thread.h"
#include "pipe/p_defines.h"
#include "util/u_ringbuffer.h"
#include "util/u_math.h"
#include "util/u_memory.h"
 
/* Generic ringbuffer:
*/
struct util_ringbuffer
{
struct util_packet *buf;
unsigned mask;
 
/* Can this be done with atomic variables??
*/
unsigned head;
unsigned tail;
pipe_condvar change;
pipe_mutex mutex;
};
 
 
struct util_ringbuffer *util_ringbuffer_create( unsigned dwords )
{
struct util_ringbuffer *ring = CALLOC_STRUCT(util_ringbuffer);
if (ring == NULL)
return NULL;
 
assert(util_is_power_of_two(dwords));
ring->buf = MALLOC( dwords * sizeof(unsigned) );
if (ring->buf == NULL)
goto fail;
 
ring->mask = dwords - 1;
 
pipe_condvar_init(ring->change);
pipe_mutex_init(ring->mutex);
return ring;
 
fail:
FREE(ring->buf);
FREE(ring);
return NULL;
}
 
void util_ringbuffer_destroy( struct util_ringbuffer *ring )
{
pipe_condvar_destroy(ring->change);
pipe_mutex_destroy(ring->mutex);
FREE(ring->buf);
FREE(ring);
}
 
/**
* Return number of free entries in the ring
*/
static INLINE unsigned util_ringbuffer_space( const struct util_ringbuffer *ring )
{
return (ring->tail - (ring->head + 1)) & ring->mask;
}
 
/**
* Is the ring buffer empty?
*/
static INLINE boolean util_ringbuffer_empty( const struct util_ringbuffer *ring )
{
return util_ringbuffer_space(ring) == ring->mask;
}
 
void util_ringbuffer_enqueue( struct util_ringbuffer *ring,
const struct util_packet *packet )
{
unsigned i;
 
/* XXX: over-reliance on mutexes, etc:
*/
pipe_mutex_lock(ring->mutex);
 
/* make sure we don't request an impossible amount of space
*/
assert(packet->dwords <= ring->mask);
 
/* Wait for free space:
*/
while (util_ringbuffer_space(ring) < packet->dwords)
pipe_condvar_wait(ring->change, ring->mutex);
 
/* Copy data to ring:
*/
for (i = 0; i < packet->dwords; i++) {
 
/* Copy all dwords of the packet. Note we're abusing the
* typesystem a little - we're being passed a pointer to
* something, but probably not an array of packet structs:
*/
ring->buf[ring->head] = packet[i];
ring->head++;
ring->head &= ring->mask;
}
 
/* Signal change:
*/
pipe_condvar_signal(ring->change);
pipe_mutex_unlock(ring->mutex);
}
 
enum pipe_error util_ringbuffer_dequeue( struct util_ringbuffer *ring,
struct util_packet *packet,
unsigned max_dwords,
boolean wait )
{
const struct util_packet *ring_packet;
unsigned i;
int ret = PIPE_OK;
 
/* XXX: over-reliance on mutexes, etc:
*/
pipe_mutex_lock(ring->mutex);
 
/* Get next ring entry:
*/
if (wait) {
while (util_ringbuffer_empty(ring))
pipe_condvar_wait(ring->change, ring->mutex);
}
else {
if (util_ringbuffer_empty(ring)) {
ret = PIPE_ERROR_OUT_OF_MEMORY;
goto out;
}
}
 
ring_packet = &ring->buf[ring->tail];
 
/* Both of these are considered bugs. Raise an assert on debug builds.
*/
if (ring_packet->dwords > ring->mask + 1 - util_ringbuffer_space(ring) ||
ring_packet->dwords > max_dwords) {
assert(0);
ret = PIPE_ERROR_BAD_INPUT;
goto out;
}
 
/* Copy data from ring:
*/
for (i = 0; i < ring_packet->dwords; i++) {
packet[i] = ring->buf[ring->tail];
ring->tail++;
ring->tail &= ring->mask;
}
 
out:
/* Signal change:
*/
pipe_condvar_signal(ring->change);
pipe_mutex_unlock(ring->mutex);
return ret;
}
/drivers/video/Gallium/auxiliary/util/u_ringbuffer.h
0,0 → 1,29
 
#ifndef UTIL_RINGBUFFER_H
#define UTIL_RINGBUFFER_H
 
#include "pipe/p_compiler.h"
#include "pipe/p_defines.h" /* only for pipe_error! */
 
/* Generic header
*/
struct util_packet {
unsigned dwords:8;
unsigned data24:24;
};
 
struct util_ringbuffer;
 
struct util_ringbuffer *util_ringbuffer_create( unsigned dwords );
 
void util_ringbuffer_destroy( struct util_ringbuffer *ring );
 
void util_ringbuffer_enqueue( struct util_ringbuffer *ring,
const struct util_packet *packet );
 
enum pipe_error util_ringbuffer_dequeue( struct util_ringbuffer *ring,
struct util_packet *packet,
unsigned max_dwords,
boolean wait );
 
#endif
/drivers/video/Gallium/auxiliary/util/u_sampler.c
0,0 → 1,109
/**************************************************************************
*
* Copyright 2010 VMware, Inc.
* 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 VMWARE 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.
*
**************************************************************************/
 
 
#include "u_format.h"
#include "u_sampler.h"
 
 
/**
* Initialize a pipe_sampler_view. 'view' is considered to have
* uninitialized contents.
*/
static void
default_template(struct pipe_sampler_view *view,
const struct pipe_resource *texture,
enum pipe_format format,
unsigned expand_green_blue)
{
memset(view, 0, sizeof(*view));
 
/* XXX: Check if format is compatible with texture->format.
*/
 
view->format = format;
view->u.tex.first_level = 0;
view->u.tex.last_level = texture->last_level;
view->u.tex.first_layer = 0;
view->u.tex.last_layer = texture->target == PIPE_TEXTURE_3D ?
texture->depth0 - 1 : texture->array_size - 1;
view->swizzle_r = PIPE_SWIZZLE_RED;
view->swizzle_g = PIPE_SWIZZLE_GREEN;
view->swizzle_b = PIPE_SWIZZLE_BLUE;
view->swizzle_a = PIPE_SWIZZLE_ALPHA;
 
/* Override default green and blue component expansion to the requested
* one.
*
* Gallium expands nonexistent components to (0,0,0,1), DX9 expands
* to (1,1,1,1). Since alpha is always expanded to 1, and red is
* always present, we only really care about green and blue
* components.
*
* To make it look less hackish, one would have to add
* UTIL_FORMAT_SWIZZLE_EXPAND to indicate components for expansion
* and then override without exceptions or favoring one component
* over another.
*/
if (format != PIPE_FORMAT_A8_UNORM) {
const struct util_format_description *desc = util_format_description(format);
 
assert(desc);
if (desc) {
if (desc->swizzle[1] == UTIL_FORMAT_SWIZZLE_0) {
view->swizzle_g = expand_green_blue;
}
if (desc->swizzle[2] == UTIL_FORMAT_SWIZZLE_0) {
view->swizzle_b = expand_green_blue;
}
}
}
}
 
void
u_sampler_view_default_template(struct pipe_sampler_view *view,
const struct pipe_resource *texture,
enum pipe_format format)
{
/* Expand to (0, 0, 0, 1) */
default_template(view,
texture,
format,
PIPE_SWIZZLE_ZERO);
}
 
void
u_sampler_view_default_dx9_template(struct pipe_sampler_view *view,
const struct pipe_resource *texture,
enum pipe_format format)
{
/* Expand to (1, 1, 1, 1) */
default_template(view,
texture,
format,
PIPE_SWIZZLE_ONE);
}
/drivers/video/Gallium/auxiliary/util/u_sampler.h
0,0 → 1,57
/**************************************************************************
*
* Copyright 2010 VMware, Inc.
* 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 VMWARE 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.
*
**************************************************************************/
 
 
#ifndef U_SAMPLER_H
#define U_SAMPLER_H
 
 
#include "pipe/p_defines.h"
#include "pipe/p_format.h"
#include "pipe/p_state.h"
 
#ifdef __cplusplus
extern "C" {
#endif
 
 
void
u_sampler_view_default_template(struct pipe_sampler_view *view,
const struct pipe_resource *texture,
enum pipe_format format);
 
void
u_sampler_view_default_dx9_template(struct pipe_sampler_view *view,
const struct pipe_resource *texture,
enum pipe_format format);
 
 
#ifdef __cplusplus
} /* extern "C" { */
#endif
 
#endif /* U_SAMPLER_H */
/drivers/video/Gallium/auxiliary/util/u_simple_list.h
0,0 → 1,199
/**
* \file simple_list.h
* Simple macros for type-safe, intrusive lists.
*
* Intended to work with a list sentinal which is created as an empty
* list. Insert & delete are O(1).
*
* \author
* (C) 1997, Keith Whitwell
*/
 
/*
* Mesa 3-D graphics library
*
* Copyright (C) 1999-2001 Brian Paul 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, sublicense,
* 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 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 NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS 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.
*/
 
 
#ifndef _U_SIMPLE_LIST_H_
#define _U_SIMPLE_LIST_H_
 
/**
* Remove an element from list.
*
* \param elem element to remove.
*/
#define remove_from_list(elem) \
do { \
(elem)->next->prev = (elem)->prev; \
(elem)->prev->next = (elem)->next; \
(elem)->next = elem; \
(elem)->prev = elem; \
} while (0)
 
/**
* Insert an element to the list head.
*
* \param list list.
* \param elem element to insert.
*/
#define insert_at_head(list, elem) \
do { \
(elem)->prev = list; \
(elem)->next = (list)->next; \
(list)->next->prev = elem; \
(list)->next = elem; \
} while(0)
 
/**
* Insert an element to the list tail.
*
* \param list list.
* \param elem element to insert.
*/
#define insert_at_tail(list, elem) \
do { \
(elem)->next = list; \
(elem)->prev = (list)->prev; \
(list)->prev->next = elem; \
(list)->prev = elem; \
} while(0)
 
/**
* Move an element to the list head.
*
* \param list list.
* \param elem element to move.
*/
#define move_to_head(list, elem) \
do { \
remove_from_list(elem); \
insert_at_head(list, elem); \
} while (0)
 
/**
* Move an element to the list tail.
*
* \param list list.
* \param elem element to move.
*/
#define move_to_tail(list, elem) \
do { \
remove_from_list(elem); \
insert_at_tail(list, elem); \
} while (0)
 
/**
* Make a empty list empty.
*
* \param sentinal list (sentinal element).
*/
#define make_empty_list(sentinal) \
do { \
(sentinal)->next = sentinal; \
(sentinal)->prev = sentinal; \
} while (0)
 
/**
* Get list first element.
*
* \param list list.
*
* \return pointer to first element.
*/
#define first_elem(list) ((list)->next)
 
/**
* Get list last element.
*
* \param list list.
*
* \return pointer to last element.
*/
#define last_elem(list) ((list)->prev)
 
/**
* Get next element.
*
* \param elem element.
*
* \return pointer to next element.
*/
#define next_elem(elem) ((elem)->next)
 
/**
* Get previous element.
*
* \param elem element.
*
* \return pointer to previous element.
*/
#define prev_elem(elem) ((elem)->prev)
 
/**
* Test whether element is at end of the list.
*
* \param list list.
* \param elem element.
*
* \return non-zero if element is at end of list, or zero otherwise.
*/
#define at_end(list, elem) ((elem) == (list))
 
/**
* Test if a list is empty.
*
* \param list list.
*
* \return non-zero if list empty, or zero otherwise.
*/
#define is_empty_list(list) ((list)->next == (list))
 
/**
* Walk through the elements of a list.
*
* \param ptr pointer to the current element.
* \param list list.
*
* \note It should be followed by a { } block or a single statement, as in a \c
* for loop.
*/
#define foreach(ptr, list) \
for( ptr=(list)->next ; ptr!=list ; ptr=(ptr)->next )
 
/**
* Walk through the elements of a list.
*
* Same as #foreach but lets you unlink the current value during a list
* traversal. Useful for freeing a list, element by element.
*
* \param ptr pointer to the current element.
* \param t temporary pointer.
* \param list list.
*
* \note It should be followed by a { } block or a single statement, as in a \c
* for loop.
*/
#define foreach_s(ptr, t, list) \
for(ptr=(list)->next,t=(ptr)->next; list != ptr; ptr=t, t=(t)->next)
 
#endif /* _U_SIMPLE_LIST_H_ */
/drivers/video/Gallium/auxiliary/util/u_simple_shaders.c
0,0 → 1,529
/**************************************************************************
*
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
* Copyright 2009 Marek Olšák <maraeo@gmail.com>
*
* 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
* Simple vertex/fragment shader generators.
*
* @author Brian Paul
Marek Olšák
*/
 
 
#include "pipe/p_context.h"
#include "pipe/p_shader_tokens.h"
#include "pipe/p_state.h"
#include "util/u_simple_shaders.h"
#include "util/u_debug.h"
#include "util/u_memory.h"
#include "tgsi/tgsi_dump.h"
#include "tgsi/tgsi_strings.h"
#include "tgsi/tgsi_ureg.h"
#include "tgsi/tgsi_text.h"
#include <stdio.h> /* include last */
 
 
 
/**
* Make simple vertex pass-through shader.
* \param num_attribs number of attributes to pass through
* \param semantic_names array of semantic names for each attribute
* \param semantic_indexes array of semantic indexes for each attribute
*/
void *
util_make_vertex_passthrough_shader(struct pipe_context *pipe,
uint num_attribs,
const uint *semantic_names,
const uint *semantic_indexes)
{
return util_make_vertex_passthrough_shader_with_so(pipe, num_attribs,
semantic_names,
semantic_indexes, NULL);
}
 
void *
util_make_vertex_passthrough_shader_with_so(struct pipe_context *pipe,
uint num_attribs,
const uint *semantic_names,
const uint *semantic_indexes,
const struct pipe_stream_output_info *so)
{
struct ureg_program *ureg;
uint i;
 
ureg = ureg_create( TGSI_PROCESSOR_VERTEX );
if (ureg == NULL)
return NULL;
 
for (i = 0; i < num_attribs; i++) {
struct ureg_src src;
struct ureg_dst dst;
 
src = ureg_DECL_vs_input( ureg, i );
dst = ureg_DECL_output( ureg,
semantic_names[i],
semantic_indexes[i]);
ureg_MOV( ureg, dst, src );
}
 
ureg_END( ureg );
 
return ureg_create_shader_with_so_and_destroy( ureg, pipe, so );
}
 
 
/**
* Make simple fragment texture shader:
* IMM {0,0,0,1} // (if writemask != 0xf)
* MOV OUT[0], IMM[0] // (if writemask != 0xf)
* TEX OUT[0].writemask, IN[0], SAMP[0], 2D;
* END;
*
* \param tex_target one of PIPE_TEXTURE_x
* \parma interp_mode either TGSI_INTERPOLATE_LINEAR or PERSPECTIVE
* \param writemask mask of TGSI_WRITEMASK_x
*/
void *
util_make_fragment_tex_shader_writemask(struct pipe_context *pipe,
unsigned tex_target,
unsigned interp_mode,
unsigned writemask )
{
struct ureg_program *ureg;
struct ureg_src sampler;
struct ureg_src tex;
struct ureg_dst out;
 
assert(interp_mode == TGSI_INTERPOLATE_LINEAR ||
interp_mode == TGSI_INTERPOLATE_PERSPECTIVE);
 
ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
if (ureg == NULL)
return NULL;
sampler = ureg_DECL_sampler( ureg, 0 );
 
tex = ureg_DECL_fs_input( ureg,
TGSI_SEMANTIC_GENERIC, 0,
interp_mode );
 
out = ureg_DECL_output( ureg,
TGSI_SEMANTIC_COLOR,
0 );
 
if (writemask != TGSI_WRITEMASK_XYZW) {
struct ureg_src imm = ureg_imm4f( ureg, 0, 0, 0, 1 );
 
ureg_MOV( ureg, out, imm );
}
 
ureg_TEX( ureg,
ureg_writemask(out, writemask),
tex_target, tex, sampler );
ureg_END( ureg );
 
return ureg_create_shader_and_destroy( ureg, pipe );
}
 
 
/**
* Make a simple fragment shader that sets the output color to a color
* taken from a texture.
* \param tex_target one of PIPE_TEXTURE_x
*/
void *
util_make_fragment_tex_shader(struct pipe_context *pipe, unsigned tex_target,
unsigned interp_mode)
{
return util_make_fragment_tex_shader_writemask( pipe,
tex_target,
interp_mode,
TGSI_WRITEMASK_XYZW );
}
 
 
/**
* Make a simple fragment texture shader which reads an X component from
* a texture and writes it as depth.
*/
void *
util_make_fragment_tex_shader_writedepth(struct pipe_context *pipe,
unsigned tex_target,
unsigned interp_mode)
{
struct ureg_program *ureg;
struct ureg_src sampler;
struct ureg_src tex;
struct ureg_dst out, depth;
struct ureg_src imm;
 
ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
if (ureg == NULL)
return NULL;
 
sampler = ureg_DECL_sampler( ureg, 0 );
 
tex = ureg_DECL_fs_input( ureg,
TGSI_SEMANTIC_GENERIC, 0,
interp_mode );
 
out = ureg_DECL_output( ureg,
TGSI_SEMANTIC_COLOR,
0 );
 
depth = ureg_DECL_output( ureg,
TGSI_SEMANTIC_POSITION,
0 );
 
imm = ureg_imm4f( ureg, 0, 0, 0, 1 );
 
ureg_MOV( ureg, out, imm );
 
ureg_TEX( ureg,
ureg_writemask(depth, TGSI_WRITEMASK_Z),
tex_target, tex, sampler );
ureg_END( ureg );
 
return ureg_create_shader_and_destroy( ureg, pipe );
}
 
 
/**
* Make a simple fragment texture shader which reads the texture unit 0 and 1
* and writes it as depth and stencil, respectively.
*/
void *
util_make_fragment_tex_shader_writedepthstencil(struct pipe_context *pipe,
unsigned tex_target,
unsigned interp_mode)
{
struct ureg_program *ureg;
struct ureg_src depth_sampler, stencil_sampler;
struct ureg_src tex;
struct ureg_dst out, depth, stencil;
struct ureg_src imm;
 
ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
if (ureg == NULL)
return NULL;
 
depth_sampler = ureg_DECL_sampler( ureg, 0 );
stencil_sampler = ureg_DECL_sampler( ureg, 1 );
 
tex = ureg_DECL_fs_input( ureg,
TGSI_SEMANTIC_GENERIC, 0,
interp_mode );
 
out = ureg_DECL_output( ureg,
TGSI_SEMANTIC_COLOR,
0 );
 
depth = ureg_DECL_output( ureg,
TGSI_SEMANTIC_POSITION,
0 );
 
stencil = ureg_DECL_output( ureg,
TGSI_SEMANTIC_STENCIL,
0 );
 
imm = ureg_imm4f( ureg, 0, 0, 0, 1 );
 
ureg_MOV( ureg, out, imm );
 
ureg_TEX( ureg,
ureg_writemask(depth, TGSI_WRITEMASK_Z),
tex_target, tex, depth_sampler );
ureg_TEX( ureg,
ureg_writemask(stencil, TGSI_WRITEMASK_Y),
tex_target, tex, stencil_sampler );
ureg_END( ureg );
 
return ureg_create_shader_and_destroy( ureg, pipe );
}
 
 
/**
* Make a simple fragment texture shader which reads a texture and writes it
* as stencil.
*/
void *
util_make_fragment_tex_shader_writestencil(struct pipe_context *pipe,
unsigned tex_target,
unsigned interp_mode)
{
struct ureg_program *ureg;
struct ureg_src stencil_sampler;
struct ureg_src tex;
struct ureg_dst out, stencil;
struct ureg_src imm;
 
ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
if (ureg == NULL)
return NULL;
 
stencil_sampler = ureg_DECL_sampler( ureg, 0 );
 
tex = ureg_DECL_fs_input( ureg,
TGSI_SEMANTIC_GENERIC, 0,
interp_mode );
 
out = ureg_DECL_output( ureg,
TGSI_SEMANTIC_COLOR,
0 );
 
stencil = ureg_DECL_output( ureg,
TGSI_SEMANTIC_STENCIL,
0 );
 
imm = ureg_imm4f( ureg, 0, 0, 0, 1 );
 
ureg_MOV( ureg, out, imm );
 
ureg_TEX( ureg,
ureg_writemask(stencil, TGSI_WRITEMASK_Y),
tex_target, tex, stencil_sampler );
ureg_END( ureg );
 
return ureg_create_shader_and_destroy( ureg, pipe );
}
 
 
/**
* Make simple fragment color pass-through shader that replicates OUT[0]
* to all bound colorbuffers.
*/
void *
util_make_fragment_passthrough_shader(struct pipe_context *pipe,
int input_semantic,
int input_interpolate,
boolean write_all_cbufs)
{
static const char shader_templ[] =
"FRAG\n"
"%s"
"DCL IN[0], %s[0], %s\n"
"DCL OUT[0], COLOR[0]\n"
 
"MOV OUT[0], IN[0]\n"
"END\n";
 
char text[sizeof(shader_templ)+100];
struct tgsi_token tokens[1000];
struct pipe_shader_state state = {tokens};
 
sprintf(text, shader_templ,
write_all_cbufs ? "PROPERTY FS_COLOR0_WRITES_ALL_CBUFS 1\n" : "",
tgsi_semantic_names[input_semantic],
tgsi_interpolate_names[input_interpolate]);
 
if (!tgsi_text_translate(text, tokens, Elements(tokens))) {
assert(0);
return NULL;
}
#if 0
tgsi_dump(state.tokens, 0);
#endif
 
return pipe->create_fs_state(pipe, &state);
}
 
 
void *
util_make_empty_fragment_shader(struct pipe_context *pipe)
{
struct ureg_program *ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT);
if (ureg == NULL)
return NULL;
 
ureg_END(ureg);
return ureg_create_shader_and_destroy(ureg, pipe);
}
 
 
/**
* Make a fragment shader that copies the input color to N output colors.
*/
void *
util_make_fragment_cloneinput_shader(struct pipe_context *pipe, int num_cbufs,
int input_semantic,
int input_interpolate)
{
struct ureg_program *ureg;
struct ureg_src src;
struct ureg_dst dst[PIPE_MAX_COLOR_BUFS];
int i;
 
assert(num_cbufs <= PIPE_MAX_COLOR_BUFS);
 
ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
if (ureg == NULL)
return NULL;
 
src = ureg_DECL_fs_input( ureg, input_semantic, 0,
input_interpolate );
 
for (i = 0; i < num_cbufs; i++)
dst[i] = ureg_DECL_output( ureg, TGSI_SEMANTIC_COLOR, i );
 
for (i = 0; i < num_cbufs; i++)
ureg_MOV( ureg, dst[i], src );
 
ureg_END( ureg );
 
return ureg_create_shader_and_destroy( ureg, pipe );
}
 
 
static void *
util_make_fs_blit_msaa_gen(struct pipe_context *pipe,
unsigned tgsi_tex,
const char *output_semantic,
const char *output_mask)
{
static const char shader_templ[] =
"FRAG\n"
"DCL IN[0], GENERIC[0], LINEAR\n"
"DCL SAMP[0]\n"
"DCL OUT[0], %s\n"
"DCL TEMP[0]\n"
 
"F2U TEMP[0], IN[0]\n"
"TXF OUT[0]%s, TEMP[0], SAMP[0], %s\n"
"END\n";
 
const char *type = tgsi_texture_names[tgsi_tex];
char text[sizeof(shader_templ)+100];
struct tgsi_token tokens[1000];
struct pipe_shader_state state = {tokens};
 
assert(tgsi_tex == TGSI_TEXTURE_2D_MSAA ||
tgsi_tex == TGSI_TEXTURE_2D_ARRAY_MSAA);
 
sprintf(text, shader_templ, output_semantic, output_mask, type);
 
if (!tgsi_text_translate(text, tokens, Elements(tokens))) {
puts(text);
assert(0);
return NULL;
}
#if 0
tgsi_dump(state.tokens, 0);
#endif
 
return pipe->create_fs_state(pipe, &state);
}
 
 
/**
* Make a fragment shader that sets the output color to a color
* fetched from a multisample texture.
* \param tex_target one of PIPE_TEXTURE_x
*/
void *
util_make_fs_blit_msaa_color(struct pipe_context *pipe,
unsigned tgsi_tex)
{
return util_make_fs_blit_msaa_gen(pipe, tgsi_tex,
"COLOR[0]", "");
}
 
 
/**
* Make a fragment shader that sets the output depth to a depth value
* fetched from a multisample texture.
* \param tex_target one of PIPE_TEXTURE_x
*/
void *
util_make_fs_blit_msaa_depth(struct pipe_context *pipe,
unsigned tgsi_tex)
{
return util_make_fs_blit_msaa_gen(pipe, tgsi_tex,
"POSITION", ".z");
}
 
 
/**
* Make a fragment shader that sets the output stencil to a stencil value
* fetched from a multisample texture.
* \param tex_target one of PIPE_TEXTURE_x
*/
void *
util_make_fs_blit_msaa_stencil(struct pipe_context *pipe,
unsigned tgsi_tex)
{
return util_make_fs_blit_msaa_gen(pipe, tgsi_tex,
"STENCIL", ".y");
}
 
 
/**
* Make a fragment shader that sets the output depth and stencil to depth
* and stencil values fetched from two multisample textures / samplers.
* The sizes of both textures should match (it should be one depth-stencil
* texture).
* \param tex_target one of PIPE_TEXTURE_x
*/
void *
util_make_fs_blit_msaa_depthstencil(struct pipe_context *pipe,
unsigned tgsi_tex)
{
static const char shader_templ[] =
"FRAG\n"
"DCL IN[0], GENERIC[0], LINEAR\n"
"DCL SAMP[0..1]\n"
"DCL OUT[0], POSITION\n"
"DCL OUT[1], STENCIL\n"
"DCL TEMP[0]\n"
 
"F2U TEMP[0], IN[0]\n"
"TXF OUT[0].z, TEMP[0], SAMP[0], %s\n"
"TXF OUT[1].y, TEMP[0], SAMP[1], %s\n"
"END\n";
 
const char *type = tgsi_texture_names[tgsi_tex];
char text[sizeof(shader_templ)+100];
struct tgsi_token tokens[1000];
struct pipe_shader_state state = {tokens};
 
assert(tgsi_tex == TGSI_TEXTURE_2D_MSAA ||
tgsi_tex == TGSI_TEXTURE_2D_ARRAY_MSAA);
 
sprintf(text, shader_templ, type, type);
 
if (!tgsi_text_translate(text, tokens, Elements(tokens))) {
assert(0);
return NULL;
}
#if 0
tgsi_dump(state.tokens, 0);
#endif
 
return pipe->create_fs_state(pipe, &state);
}
/drivers/video/Gallium/auxiliary/util/u_simple_shaders.h
0,0 → 1,130
/**************************************************************************
*
* 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.
*
**************************************************************************/
 
 
#ifndef U_SIMPLE_SHADERS_H
#define U_SIMPLE_SHADERS_H
 
 
#include "pipe/p_compiler.h"
 
 
struct pipe_context;
struct pipe_shader_state;
struct pipe_stream_output_info;
 
 
#ifdef __cplusplus
extern "C" {
#endif
 
 
extern void *
util_make_vertex_passthrough_shader(struct pipe_context *pipe,
uint num_attribs,
const uint *semantic_names,
const uint *semantic_indexes);
 
extern void *
util_make_vertex_passthrough_shader_with_so(struct pipe_context *pipe,
uint num_attribs,
const uint *semantic_names,
const uint *semantic_indexes,
const struct pipe_stream_output_info *so);
 
 
extern void *
util_make_fragment_tex_shader_writemask(struct pipe_context *pipe,
unsigned tex_target,
unsigned interp_mode,
unsigned writemask);
 
extern void *
util_make_fragment_tex_shader(struct pipe_context *pipe, unsigned tex_target,
unsigned interp_mode);
 
 
extern void *
util_make_fragment_tex_shader_writedepth(struct pipe_context *pipe,
unsigned tex_target,
unsigned interp_mode);
 
 
extern void *
util_make_fragment_tex_shader_writedepthstencil(struct pipe_context *pipe,
unsigned tex_target,
unsigned interp_mode);
 
 
extern void *
util_make_fragment_tex_shader_writestencil(struct pipe_context *pipe,
unsigned tex_target,
unsigned interp_mode);
 
 
extern void *
util_make_fragment_passthrough_shader(struct pipe_context *pipe,
int input_semantic,
int input_interpolate,
boolean write_all_cbufs);
 
 
extern void *
util_make_empty_fragment_shader(struct pipe_context *pipe);
 
 
extern void *
util_make_fragment_cloneinput_shader(struct pipe_context *pipe, int num_cbufs,
int input_semantic,
int input_interpolate);
 
 
extern void *
util_make_fs_blit_msaa_color(struct pipe_context *pipe,
unsigned tgsi_tex);
 
 
extern void *
util_make_fs_blit_msaa_depth(struct pipe_context *pipe,
unsigned tgsi_tex);
 
 
extern void *
util_make_fs_blit_msaa_depthstencil(struct pipe_context *pipe,
unsigned tgsi_tex);
 
 
void *
util_make_fs_blit_msaa_stencil(struct pipe_context *pipe,
unsigned tgsi_tex);
 
#ifdef __cplusplus
}
#endif
 
 
#endif
/drivers/video/Gallium/auxiliary/util/u_slab.c
0,0 → 1,171
/*
* Copyright 2010 Marek Olšák <maraeo@gmail.com>
*
* 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
* on 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
* THE AUTHOR(S) AND/OR THEIR 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. */
 
#include "util/u_slab.h"
 
#include "util/u_math.h"
#include "util/u_memory.h"
#include "util/u_simple_list.h"
 
#include <stdio.h>
 
#define UTIL_SLAB_MAGIC 0xcafe4321
 
/* The block is either allocated memory or free space. */
struct util_slab_block {
/* The header. */
/* The first next free block. */
struct util_slab_block *next_free;
 
intptr_t magic;
 
/* Memory after the last member is dedicated to the block itself.
* The allocated size is always larger than this structure. */
};
 
static struct util_slab_block *
util_slab_get_block(struct util_slab_mempool *pool,
struct util_slab_page *page, unsigned index)
{
return (struct util_slab_block*)
((uint8_t*)page + sizeof(struct util_slab_page) +
(pool->block_size * index));
}
 
static void util_slab_add_new_page(struct util_slab_mempool *pool)
{
struct util_slab_page *page;
struct util_slab_block *block;
unsigned i;
 
page = MALLOC(pool->page_size);
insert_at_tail(&pool->list, page);
 
/* Mark all blocks as free. */
for (i = 0; i < pool->num_blocks-1; i++) {
block = util_slab_get_block(pool, page, i);
block->next_free = util_slab_get_block(pool, page, i+1);
block->magic = UTIL_SLAB_MAGIC;
}
 
block = util_slab_get_block(pool, page, pool->num_blocks-1);
block->next_free = pool->first_free;
block->magic = UTIL_SLAB_MAGIC;
pool->first_free = util_slab_get_block(pool, page, 0);
pool->num_pages++;
 
#if 0
fprintf(stderr, "New page! Num of pages: %i\n", pool->num_pages);
#endif
}
 
static void *util_slab_alloc_st(struct util_slab_mempool *pool)
{
struct util_slab_block *block;
 
if (!pool->first_free)
util_slab_add_new_page(pool);
 
block = pool->first_free;
assert(block->magic == UTIL_SLAB_MAGIC);
pool->first_free = block->next_free;
 
return (uint8_t*)block + sizeof(struct util_slab_block);
}
 
static void util_slab_free_st(struct util_slab_mempool *pool, void *ptr)
{
struct util_slab_block *block =
(struct util_slab_block*)
((uint8_t*)ptr - sizeof(struct util_slab_block));
 
assert(block->magic == UTIL_SLAB_MAGIC);
block->next_free = pool->first_free;
pool->first_free = block;
}
 
static void *util_slab_alloc_mt(struct util_slab_mempool *pool)
{
void *mem;
 
pipe_mutex_lock(pool->mutex);
mem = util_slab_alloc_st(pool);
pipe_mutex_unlock(pool->mutex);
return mem;
}
 
static void util_slab_free_mt(struct util_slab_mempool *pool, void *ptr)
{
pipe_mutex_lock(pool->mutex);
util_slab_free_st(pool, ptr);
pipe_mutex_unlock(pool->mutex);
}
 
void util_slab_set_thread_safety(struct util_slab_mempool *pool,
enum util_slab_threading threading)
{
pool->threading = threading;
 
if (threading) {
pool->alloc = util_slab_alloc_mt;
pool->free = util_slab_free_mt;
} else {
pool->alloc = util_slab_alloc_st;
pool->free = util_slab_free_st;
}
}
 
void util_slab_create(struct util_slab_mempool *pool,
unsigned item_size,
unsigned num_blocks,
enum util_slab_threading threading)
{
item_size = align(item_size, sizeof(intptr_t));
 
pool->num_pages = 0;
pool->num_blocks = num_blocks;
pool->block_size = sizeof(struct util_slab_block) + item_size;
pool->block_size = align(pool->block_size, sizeof(intptr_t));
pool->page_size = sizeof(struct util_slab_page) +
num_blocks * pool->block_size;
pool->first_free = NULL;
 
make_empty_list(&pool->list);
 
pipe_mutex_init(pool->mutex);
 
util_slab_set_thread_safety(pool, threading);
}
 
void util_slab_destroy(struct util_slab_mempool *pool)
{
struct util_slab_page *page, *temp;
 
if (pool->list.next) {
foreach_s(page, temp, &pool->list) {
remove_from_list(page);
FREE(page);
}
}
 
pipe_mutex_destroy(pool->mutex);
}
/drivers/video/Gallium/auxiliary/util/u_slab.h
0,0 → 1,87
/*
* Copyright 2010 Marek Olšák <maraeo@gmail.com>
*
* 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
* on 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
* THE AUTHOR(S) AND/OR THEIR 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
* Simple slab allocator for equally sized memory allocations.
* util_slab_alloc and util_slab_free have time complexity in O(1).
*
* Good for allocations which have very low lifetime and are allocated
* and freed very often. Use a profiler first to know if it's worth using it!
*
* Candidates: transfer_map
*
* @author Marek Olšák
*/
 
#ifndef U_SLAB_H
#define U_SLAB_H
 
#include "os/os_thread.h"
 
enum util_slab_threading {
UTIL_SLAB_SINGLETHREADED = FALSE,
UTIL_SLAB_MULTITHREADED = TRUE
};
 
/* The page is an array of blocks (allocations). */
struct util_slab_page {
/* The header (linked-list pointers). */
struct util_slab_page *prev, *next;
 
/* Memory after the last member is dedicated to the page itself.
* The allocated size is always larger than this structure. */
};
 
struct util_slab_mempool {
/* Public members. */
void *(*alloc)(struct util_slab_mempool *pool);
void (*free)(struct util_slab_mempool *pool, void *ptr);
 
/* Private members. */
struct util_slab_block *first_free;
 
struct util_slab_page list;
 
unsigned block_size;
unsigned page_size;
unsigned num_blocks;
unsigned num_pages;
enum util_slab_threading threading;
 
pipe_mutex mutex;
};
 
void util_slab_create(struct util_slab_mempool *pool,
unsigned item_size,
unsigned num_blocks,
enum util_slab_threading threading);
 
void util_slab_destroy(struct util_slab_mempool *pool);
 
void util_slab_set_thread_safety(struct util_slab_mempool *pool,
enum util_slab_threading threading);
 
#define util_slab_alloc(pool) (pool)->alloc(pool)
#define util_slab_free(pool, ptr) (pool)->free(pool, ptr)
 
#endif
/drivers/video/Gallium/auxiliary/util/u_snprintf.c
0,0 → 1,1489
/*
* Copyright (c) 1995 Patrick Powell.
*
* This code is based on code written by Patrick Powell <papowell@astart.com>.
* It may be used for any purpose as long as this notice remains intact on all
* source code distributions.
*/
 
/*
* Copyright (c) 2008 Holger Weiss.
*
* This version of the code is maintained by Holger Weiss <holger@jhweiss.de>.
* My changes to the code may freely be used, modified and/or redistributed for
* any purpose. It would be nice if additions and fixes to this file (including
* trivial code cleanups) would be sent back in order to let me include them in
* the version available at <http://www.jhweiss.de/software/snprintf.html>.
* However, this is not a requirement for using or redistributing (possibly
* modified) versions of this file, nor is leaving this notice intact mandatory.
*/
 
/*
* History
*
* 2008-01-20 Holger Weiss <holger@jhweiss.de> for C99-snprintf 1.1:
*
* Fixed the detection of infinite floating point values on IRIX (and
* possibly other systems) and applied another few minor cleanups.
*
* 2008-01-06 Holger Weiss <holger@jhweiss.de> for C99-snprintf 1.0:
*
* Added a lot of new features, fixed many bugs, and incorporated various
* improvements done by Andrew Tridgell <tridge@samba.org>, Russ Allbery
* <rra@stanford.edu>, Hrvoje Niksic <hniksic@xemacs.org>, Damien Miller
* <djm@mindrot.org>, and others for the Samba, INN, Wget, and OpenSSH
* projects. The additions include: support the "e", "E", "g", "G", and
* "F" conversion specifiers (and use conversion style "f" or "F" for the
* still unsupported "a" and "A" specifiers); support the "hh", "ll", "j",
* "t", and "z" length modifiers; support the "#" flag and the (non-C99)
* "'" flag; use localeconv(3) (if available) to get both the current
* locale's decimal point character and the separator between groups of
* digits; fix the handling of various corner cases of field width and
* precision specifications; fix various floating point conversion bugs;
* handle infinite and NaN floating point values; don't attempt to write to
* the output buffer (which may be NULL) if a size of zero was specified;
* check for integer overflow of the field width, precision, and return
* values and during the floating point conversion; use the OUTCHAR() macro
* instead of a function for better performance; provide asprintf(3) and
* vasprintf(3) functions; add new test cases. The replacement functions
* have been renamed to use an "rpl_" prefix, the function calls in the
* main project (and in this file) must be redefined accordingly for each
* replacement function which is needed (by using Autoconf or other means).
* Various other minor improvements have been applied and the coding style
* was cleaned up for consistency.
*
* 2007-07-23 Holger Weiss <holger@jhweiss.de> for Mutt 1.5.13:
*
* C99 compliant snprintf(3) and vsnprintf(3) functions return the number
* of characters that would have been written to a sufficiently sized
* buffer (excluding the '\0'). The original code simply returned the
* length of the resulting output string, so that's been fixed.
*
* 1998-03-05 Michael Elkins <me@mutt.org> for Mutt 0.90.8:
*
* The original code assumed that both snprintf(3) and vsnprintf(3) were
* missing. Some systems only have snprintf(3) but not vsnprintf(3), so
* the code is now broken down under HAVE_SNPRINTF and HAVE_VSNPRINTF.
*
* 1998-01-27 Thomas Roessler <roessler@does-not-exist.org> for Mutt 0.89i:
*
* The PGP code was using unsigned hexadecimal formats. Unfortunately,
* unsigned formats simply didn't work.
*
* 1997-10-22 Brandon Long <blong@fiction.net> for Mutt 0.87.1:
*
* Ok, added some minimal floating point support, which means this probably
* requires libm on most operating systems. Don't yet support the exponent
* (e,E) and sigfig (g,G). Also, fmtint() was pretty badly broken, it just
* wasn't being exercised in ways which showed it, so that's been fixed.
* Also, formatted the code to Mutt conventions, and removed dead code left
* over from the original. Also, there is now a builtin-test, run with:
* gcc -DTEST_SNPRINTF -o snprintf snprintf.c -lm && ./snprintf
*
* 2996-09-15 Brandon Long <blong@fiction.net> for Mutt 0.43:
*
* This was ugly. It is still ugly. I opted out of floating point
* numbers, but the formatter understands just about everything from the
* normal C string format, at least as far as I can tell from the Solaris
* 2.5 printf(3S) man page.
*/
 
/*
* ToDo
*
* - Add wide character support.
* - Add support for "%a" and "%A" conversions.
* - Create test routines which predefine the expected results. Our test cases
* usually expose bugs in system implementations rather than in ours :-)
*/
 
/*
* Usage
*
* 1) The following preprocessor macros should be defined to 1 if the feature or
* file in question is available on the target system (by using Autoconf or
* other means), though basic functionality should be available as long as
* HAVE_STDARG_H and HAVE_STDLIB_H are defined correctly:
*
* HAVE_VSNPRINTF
* HAVE_SNPRINTF
* HAVE_VASPRINTF
* HAVE_ASPRINTF
* HAVE_STDARG_H
* HAVE_STDDEF_H
* HAVE_STDINT_H
* HAVE_STDLIB_H
* HAVE_INTTYPES_H
* HAVE_LOCALE_H
* HAVE_LOCALECONV
* HAVE_LCONV_DECIMAL_POINT
* HAVE_LCONV_THOUSANDS_SEP
* HAVE_LONG_DOUBLE
* HAVE_LONG_LONG_INT
* HAVE_UNSIGNED_LONG_LONG_INT
* HAVE_INTMAX_T
* HAVE_UINTMAX_T
* HAVE_UINTPTR_T
* HAVE_PTRDIFF_T
* HAVE_VA_COPY
* HAVE___VA_COPY
*
* 2) The calls to the functions which should be replaced must be redefined
* throughout the project files (by using Autoconf or other means):
*
* #define vsnprintf rpl_vsnprintf
* #define snprintf rpl_snprintf
* #define vasprintf rpl_vasprintf
* #define asprintf rpl_asprintf
*
* 3) The required replacement functions should be declared in some header file
* included throughout the project files:
*
* #if HAVE_CONFIG_H
* #include <config.h>
* #endif
* #if HAVE_STDARG_H
* #include <stdarg.h>
* #if !HAVE_VSNPRINTF
* int rpl_vsnprintf(char *, size_t, const char *, va_list);
* #endif
* #if !HAVE_SNPRINTF
* int rpl_snprintf(char *, size_t, const char *, ...);
* #endif
* #if !HAVE_VASPRINTF
* int rpl_vasprintf(char **, const char *, va_list);
* #endif
* #if !HAVE_ASPRINTF
* int rpl_asprintf(char **, const char *, ...);
* #endif
* #endif
*
* Autoconf macros for handling step 1 and step 2 are available at
* <http://www.jhweiss.de/software/snprintf.html>.
*/
 
#include "pipe/p_config.h"
 
#if HAVE_CONFIG_H
#include <config.h>
#else
#ifdef _MSC_VER
#define vsnprintf util_vsnprintf
#define snprintf util_snprintf
#define HAVE_VSNPRINTF 0
#define HAVE_SNPRINTF 0
#define HAVE_VASPRINTF 1 /* not needed */
#define HAVE_ASPRINTF 1 /* not needed */
#define HAVE_STDARG_H 1
#define HAVE_STDDEF_H 1
#define HAVE_STDINT_H 0
#define HAVE_STDLIB_H 1
#define HAVE_INTTYPES_H 0
#define HAVE_LOCALE_H 0
#define HAVE_LOCALECONV 0
#define HAVE_LCONV_DECIMAL_POINT 0
#define HAVE_LCONV_THOUSANDS_SEP 0
#define HAVE_LONG_DOUBLE 0
#define HAVE_LONG_LONG_INT 1
#define HAVE_UNSIGNED_LONG_LONG_INT 1
#define HAVE_INTMAX_T 0
#define HAVE_UINTMAX_T 0
#define HAVE_UINTPTR_T 1
#define HAVE_PTRDIFF_T 1
#define HAVE_VA_COPY 0
#define HAVE___VA_COPY 0
#else
#define HAVE_VSNPRINTF 1
#define HAVE_SNPRINTF 1
#define HAVE_VASPRINTF 1
#define HAVE_ASPRINTF 1
#endif
#endif /* HAVE_CONFIG_H */
 
#if !HAVE_SNPRINTF || !HAVE_VSNPRINTF || !HAVE_ASPRINTF || !HAVE_VASPRINTF
#include <stdio.h> /* For NULL, size_t, vsnprintf(3), and vasprintf(3). */
#ifdef VA_START
#undef VA_START
#endif /* defined(VA_START) */
#ifdef VA_SHIFT
#undef VA_SHIFT
#endif /* defined(VA_SHIFT) */
#if HAVE_STDARG_H
#include <stdarg.h>
#define VA_START(ap, last) va_start(ap, last)
#define VA_SHIFT(ap, value, type) /* No-op for ANSI C. */
#else /* Assume <varargs.h> is available. */
#include <varargs.h>
#define VA_START(ap, last) va_start(ap) /* "last" is ignored. */
#define VA_SHIFT(ap, value, type) value = va_arg(ap, type)
#endif /* HAVE_STDARG_H */
 
#if !HAVE_VASPRINTF
#if HAVE_STDLIB_H
#include <stdlib.h> /* For malloc(3). */
#endif /* HAVE_STDLIB_H */
#ifdef VA_COPY
#undef VA_COPY
#endif /* defined(VA_COPY) */
#ifdef VA_END_COPY
#undef VA_END_COPY
#endif /* defined(VA_END_COPY) */
#if HAVE_VA_COPY
#define VA_COPY(dest, src) va_copy(dest, src)
#define VA_END_COPY(ap) va_end(ap)
#elif HAVE___VA_COPY
#define VA_COPY(dest, src) __va_copy(dest, src)
#define VA_END_COPY(ap) va_end(ap)
#else
#define VA_COPY(dest, src) (void)mymemcpy(&dest, &src, sizeof(va_list))
#define VA_END_COPY(ap) /* No-op. */
#define NEED_MYMEMCPY 1
static void *mymemcpy(void *, void *, size_t);
#endif /* HAVE_VA_COPY */
#endif /* !HAVE_VASPRINTF */
 
#if !HAVE_VSNPRINTF
#include <limits.h> /* For *_MAX. */
#if HAVE_INTTYPES_H
#include <inttypes.h> /* For intmax_t (if not defined in <stdint.h>). */
#endif /* HAVE_INTTYPES_H */
#if HAVE_LOCALE_H
#include <locale.h> /* For localeconv(3). */
#endif /* HAVE_LOCALE_H */
#if HAVE_STDDEF_H
#include <stddef.h> /* For ptrdiff_t. */
#endif /* HAVE_STDDEF_H */
#if HAVE_STDINT_H
#include <stdint.h> /* For intmax_t. */
#endif /* HAVE_STDINT_H */
 
/* Support for unsigned long long int. We may also need ULLONG_MAX. */
#ifndef ULONG_MAX /* We may need ULONG_MAX as a fallback. */
#ifdef UINT_MAX
#define ULONG_MAX UINT_MAX
#else
#define ULONG_MAX INT_MAX
#endif /* defined(UINT_MAX) */
#endif /* !defined(ULONG_MAX) */
#ifdef ULLONG
#undef ULLONG
#endif /* defined(ULLONG) */
#if HAVE_UNSIGNED_LONG_LONG_INT
#define ULLONG unsigned long long int
#ifndef ULLONG_MAX
#define ULLONG_MAX ULONG_MAX
#endif /* !defined(ULLONG_MAX) */
#else
#define ULLONG unsigned long int
#ifdef ULLONG_MAX
#undef ULLONG_MAX
#endif /* defined(ULLONG_MAX) */
#define ULLONG_MAX ULONG_MAX
#endif /* HAVE_LONG_LONG_INT */
 
/* Support for uintmax_t. We also need UINTMAX_MAX. */
#ifdef UINTMAX_T
#undef UINTMAX_T
#endif /* defined(UINTMAX_T) */
#if HAVE_UINTMAX_T || defined(uintmax_t)
#define UINTMAX_T uintmax_t
#ifndef UINTMAX_MAX
#define UINTMAX_MAX ULLONG_MAX
#endif /* !defined(UINTMAX_MAX) */
#else
#define UINTMAX_T ULLONG
#ifdef UINTMAX_MAX
#undef UINTMAX_MAX
#endif /* defined(UINTMAX_MAX) */
#define UINTMAX_MAX ULLONG_MAX
#endif /* HAVE_UINTMAX_T || defined(uintmax_t) */
 
/* Support for long double. */
#ifndef LDOUBLE
#if HAVE_LONG_DOUBLE
#define LDOUBLE long double
#else
#define LDOUBLE double
#endif /* HAVE_LONG_DOUBLE */
#endif /* !defined(LDOUBLE) */
 
/* Support for long long int. */
#ifndef LLONG
#if HAVE_LONG_LONG_INT
#define LLONG long long int
#else
#define LLONG long int
#endif /* HAVE_LONG_LONG_INT */
#endif /* !defined(LLONG) */
 
/* Support for intmax_t. */
#ifndef INTMAX_T
#if HAVE_INTMAX_T || defined(intmax_t)
#define INTMAX_T intmax_t
#else
#define INTMAX_T LLONG
#endif /* HAVE_INTMAX_T || defined(intmax_t) */
#endif /* !defined(INTMAX_T) */
 
/* Support for uintptr_t. */
#ifndef UINTPTR_T
#if HAVE_UINTPTR_T || defined(uintptr_t)
#define UINTPTR_T uintptr_t
#else
#define UINTPTR_T unsigned long int
#endif /* HAVE_UINTPTR_T || defined(uintptr_t) */
#endif /* !defined(UINTPTR_T) */
 
/* WinCE5.0 does not have uintptr_t defined */
#if (_WIN32_WCE < 600)
#ifdef UINTPTR_T
#undef UINTPTR_T
#endif
#define UINTPTR_T unsigned long int
#endif
 
 
/* Support for ptrdiff_t. */
#ifndef PTRDIFF_T
#if HAVE_PTRDIFF_T || defined(ptrdiff_t)
#define PTRDIFF_T ptrdiff_t
#else
#define PTRDIFF_T long int
#endif /* HAVE_PTRDIFF_T || defined(ptrdiff_t) */
#endif /* !defined(PTRDIFF_T) */
 
/*
* We need an unsigned integer type corresponding to ptrdiff_t (cf. C99:
* 7.19.6.1, 7). However, we'll simply use PTRDIFF_T and convert it to an
* unsigned type if necessary. This should work just fine in practice.
*/
#ifndef UPTRDIFF_T
#define UPTRDIFF_T PTRDIFF_T
#endif /* !defined(UPTRDIFF_T) */
 
/*
* We need a signed integer type corresponding to size_t (cf. C99: 7.19.6.1, 7).
* However, we'll simply use size_t and convert it to a signed type if
* necessary. This should work just fine in practice.
*/
#ifndef SSIZE_T
#define SSIZE_T size_t
#endif /* !defined(SSIZE_T) */
 
/* Either ERANGE or E2BIG should be available everywhere. */
#ifndef ERANGE
#define ERANGE E2BIG
#endif /* !defined(ERANGE) */
#ifndef EOVERFLOW
#define EOVERFLOW ERANGE
#endif /* !defined(EOVERFLOW) */
 
/*
* Buffer size to hold the octal string representation of UINT128_MAX without
* nul-termination ("3777777777777777777777777777777777777777777").
*/
#ifdef MAX_CONVERT_LENGTH
#undef MAX_CONVERT_LENGTH
#endif /* defined(MAX_CONVERT_LENGTH) */
#define MAX_CONVERT_LENGTH 43
 
/* Format read states. */
#define PRINT_S_DEFAULT 0
#define PRINT_S_FLAGS 1
#define PRINT_S_WIDTH 2
#define PRINT_S_DOT 3
#define PRINT_S_PRECISION 4
#define PRINT_S_MOD 5
#define PRINT_S_CONV 6
 
/* Format flags. */
#define PRINT_F_MINUS (1 << 0)
#define PRINT_F_PLUS (1 << 1)
#define PRINT_F_SPACE (1 << 2)
#define PRINT_F_NUM (1 << 3)
#define PRINT_F_ZERO (1 << 4)
#define PRINT_F_QUOTE (1 << 5)
#define PRINT_F_UP (1 << 6)
#define PRINT_F_UNSIGNED (1 << 7)
#define PRINT_F_TYPE_G (1 << 8)
#define PRINT_F_TYPE_E (1 << 9)
 
/* Conversion flags. */
#define PRINT_C_CHAR 1
#define PRINT_C_SHORT 2
#define PRINT_C_LONG 3
#define PRINT_C_LLONG 4
#define PRINT_C_LDOUBLE 5
#define PRINT_C_SIZE 6
#define PRINT_C_PTRDIFF 7
#define PRINT_C_INTMAX 8
 
#ifndef MAX
#define MAX(x, y) ((x >= y) ? x : y)
#endif /* !defined(MAX) */
#ifndef CHARTOINT
#define CHARTOINT(ch) (ch - '0')
#endif /* !defined(CHARTOINT) */
#ifndef ISDIGIT
#define ISDIGIT(ch) ('0' <= (unsigned char)ch && (unsigned char)ch <= '9')
#endif /* !defined(ISDIGIT) */
#ifndef ISNAN
#define ISNAN(x) (x != x)
#endif /* !defined(ISNAN) */
#ifndef ISINF
#define ISINF(x) (x != 0.0 && x + x == x)
#endif /* !defined(ISINF) */
 
#ifdef OUTCHAR
#undef OUTCHAR
#endif /* defined(OUTCHAR) */
#define OUTCHAR(str, len, size, ch) \
do { \
if (len + 1 < size) \
str[len] = ch; \
(len)++; \
} while (/* CONSTCOND */ 0)
 
static void fmtstr(char *, size_t *, size_t, const char *, int, int, int);
static void fmtint(char *, size_t *, size_t, INTMAX_T, int, int, int, int);
static void fmtflt(char *, size_t *, size_t, LDOUBLE, int, int, int, int *);
static void printsep(char *, size_t *, size_t);
static int getnumsep(int);
static int getexponent(LDOUBLE);
static int convert(UINTMAX_T, char *, size_t, int, int);
static UINTMAX_T cast(LDOUBLE);
static UINTMAX_T myround(LDOUBLE);
static LDOUBLE mypow10(int);
 
int
util_vsnprintf(char *str, size_t size, const char *format, va_list args)
{
LDOUBLE fvalue;
INTMAX_T value;
unsigned char cvalue;
const char *strvalue;
INTMAX_T *intmaxptr;
PTRDIFF_T *ptrdiffptr;
SSIZE_T *sizeptr;
LLONG *llongptr;
long int *longptr;
int *intptr;
short int *shortptr;
signed char *charptr;
size_t len = 0;
int overflow = 0;
int base = 0;
int cflags = 0;
int flags = 0;
int width = 0;
int precision = -1;
int state = PRINT_S_DEFAULT;
char ch = *format++;
 
/*
* C99 says: "If `n' is zero, nothing is written, and `s' may be a null
* pointer." (7.19.6.5, 2) We're forgiving and allow a NULL pointer
* even if a size larger than zero was specified. At least NetBSD's
* snprintf(3) does the same, as well as other versions of this file.
* (Though some of these versions will write to a non-NULL buffer even
* if a size of zero was specified, which violates the standard.)
*/
if (str == NULL && size != 0)
size = 0;
 
while (ch != '\0')
switch (state) {
case PRINT_S_DEFAULT:
if (ch == '%')
state = PRINT_S_FLAGS;
else
OUTCHAR(str, len, size, ch);
ch = *format++;
break;
case PRINT_S_FLAGS:
switch (ch) {
case '-':
flags |= PRINT_F_MINUS;
ch = *format++;
break;
case '+':
flags |= PRINT_F_PLUS;
ch = *format++;
break;
case ' ':
flags |= PRINT_F_SPACE;
ch = *format++;
break;
case '#':
flags |= PRINT_F_NUM;
ch = *format++;
break;
case '0':
flags |= PRINT_F_ZERO;
ch = *format++;
break;
case '\'': /* SUSv2 flag (not in C99). */
flags |= PRINT_F_QUOTE;
ch = *format++;
break;
default:
state = PRINT_S_WIDTH;
break;
}
break;
case PRINT_S_WIDTH:
if (ISDIGIT(ch)) {
ch = CHARTOINT(ch);
if (width > (INT_MAX - ch) / 10) {
overflow = 1;
goto out;
}
width = 10 * width + ch;
ch = *format++;
} else if (ch == '*') {
/*
* C99 says: "A negative field width argument is
* taken as a `-' flag followed by a positive
* field width." (7.19.6.1, 5)
*/
if ((width = va_arg(args, int)) < 0) {
flags |= PRINT_F_MINUS;
width = -width;
}
ch = *format++;
state = PRINT_S_DOT;
} else
state = PRINT_S_DOT;
break;
case PRINT_S_DOT:
if (ch == '.') {
state = PRINT_S_PRECISION;
ch = *format++;
} else
state = PRINT_S_MOD;
break;
case PRINT_S_PRECISION:
if (precision == -1)
precision = 0;
if (ISDIGIT(ch)) {
ch = CHARTOINT(ch);
if (precision > (INT_MAX - ch) / 10) {
overflow = 1;
goto out;
}
precision = 10 * precision + ch;
ch = *format++;
} else if (ch == '*') {
/*
* C99 says: "A negative precision argument is
* taken as if the precision were omitted."
* (7.19.6.1, 5)
*/
if ((precision = va_arg(args, int)) < 0)
precision = -1;
ch = *format++;
state = PRINT_S_MOD;
} else
state = PRINT_S_MOD;
break;
case PRINT_S_MOD:
switch (ch) {
case 'h':
ch = *format++;
if (ch == 'h') { /* It's a char. */
ch = *format++;
cflags = PRINT_C_CHAR;
} else
cflags = PRINT_C_SHORT;
break;
case 'l':
ch = *format++;
if (ch == 'l') { /* It's a long long. */
ch = *format++;
cflags = PRINT_C_LLONG;
} else
cflags = PRINT_C_LONG;
break;
case 'L':
cflags = PRINT_C_LDOUBLE;
ch = *format++;
break;
case 'j':
cflags = PRINT_C_INTMAX;
ch = *format++;
break;
case 't':
cflags = PRINT_C_PTRDIFF;
ch = *format++;
break;
case 'z':
cflags = PRINT_C_SIZE;
ch = *format++;
break;
}
state = PRINT_S_CONV;
break;
case PRINT_S_CONV:
switch (ch) {
case 'd':
/* FALLTHROUGH */
case 'i':
switch (cflags) {
case PRINT_C_CHAR:
value = (signed char)va_arg(args, int);
break;
case PRINT_C_SHORT:
value = (short int)va_arg(args, int);
break;
case PRINT_C_LONG:
value = va_arg(args, long int);
break;
case PRINT_C_LLONG:
value = va_arg(args, LLONG);
break;
case PRINT_C_SIZE:
value = va_arg(args, SSIZE_T);
break;
case PRINT_C_INTMAX:
value = va_arg(args, INTMAX_T);
break;
case PRINT_C_PTRDIFF:
value = va_arg(args, PTRDIFF_T);
break;
default:
value = va_arg(args, int);
break;
}
fmtint(str, &len, size, value, 10, width,
precision, flags);
break;
case 'X':
flags |= PRINT_F_UP;
/* FALLTHROUGH */
case 'x':
base = 16;
/* FALLTHROUGH */
case 'o':
if (base == 0)
base = 8;
/* FALLTHROUGH */
case 'u':
if (base == 0)
base = 10;
flags |= PRINT_F_UNSIGNED;
switch (cflags) {
case PRINT_C_CHAR:
value = (unsigned char)va_arg(args,
unsigned int);
break;
case PRINT_C_SHORT:
value = (unsigned short int)va_arg(args,
unsigned int);
break;
case PRINT_C_LONG:
value = va_arg(args, unsigned long int);
break;
case PRINT_C_LLONG:
value = va_arg(args, ULLONG);
break;
case PRINT_C_SIZE:
value = va_arg(args, size_t);
break;
case PRINT_C_INTMAX:
value = va_arg(args, UINTMAX_T);
break;
case PRINT_C_PTRDIFF:
value = va_arg(args, UPTRDIFF_T);
break;
default:
value = va_arg(args, unsigned int);
break;
}
fmtint(str, &len, size, value, base, width,
precision, flags);
break;
case 'A':
/* Not yet supported, we'll use "%F". */
/* FALLTHROUGH */
case 'F':
flags |= PRINT_F_UP;
case 'a':
/* Not yet supported, we'll use "%f". */
/* FALLTHROUGH */
case 'f':
if (cflags == PRINT_C_LDOUBLE)
fvalue = va_arg(args, LDOUBLE);
else
fvalue = va_arg(args, double);
fmtflt(str, &len, size, fvalue, width,
precision, flags, &overflow);
if (overflow)
goto out;
break;
case 'E':
flags |= PRINT_F_UP;
/* FALLTHROUGH */
case 'e':
flags |= PRINT_F_TYPE_E;
if (cflags == PRINT_C_LDOUBLE)
fvalue = va_arg(args, LDOUBLE);
else
fvalue = va_arg(args, double);
fmtflt(str, &len, size, fvalue, width,
precision, flags, &overflow);
if (overflow)
goto out;
break;
case 'G':
flags |= PRINT_F_UP;
/* FALLTHROUGH */
case 'g':
flags |= PRINT_F_TYPE_G;
if (cflags == PRINT_C_LDOUBLE)
fvalue = va_arg(args, LDOUBLE);
else
fvalue = va_arg(args, double);
/*
* If the precision is zero, it is treated as
* one (cf. C99: 7.19.6.1, 8).
*/
if (precision == 0)
precision = 1;
fmtflt(str, &len, size, fvalue, width,
precision, flags, &overflow);
if (overflow)
goto out;
break;
case 'c':
cvalue = (unsigned char)va_arg(args, int);
OUTCHAR(str, len, size, cvalue);
break;
case 's':
strvalue = va_arg(args, char *);
fmtstr(str, &len, size, strvalue, width,
precision, flags);
break;
case 'p':
/*
* C99 says: "The value of the pointer is
* converted to a sequence of printing
* characters, in an implementation-defined
* manner." (C99: 7.19.6.1, 8)
*/
if ((strvalue = va_arg(args, void *)) == NULL)
/*
* We use the glibc format. BSD prints
* "0x0", SysV "0".
*/
fmtstr(str, &len, size, "(nil)", width,
-1, flags);
else {
/*
* We use the BSD/glibc format. SysV
* omits the "0x" prefix (which we emit
* using the PRINT_F_NUM flag).
*/
flags |= PRINT_F_NUM;
flags |= PRINT_F_UNSIGNED;
fmtint(str, &len, size,
(UINTPTR_T)strvalue, 16, width,
precision, flags);
}
break;
case 'n':
switch (cflags) {
case PRINT_C_CHAR:
charptr = va_arg(args, signed char *);
*charptr = (signed char)len;
break;
case PRINT_C_SHORT:
shortptr = va_arg(args, short int *);
*shortptr = (short int)len;
break;
case PRINT_C_LONG:
longptr = va_arg(args, long int *);
*longptr = (long int)len;
break;
case PRINT_C_LLONG:
llongptr = va_arg(args, LLONG *);
*llongptr = (LLONG)len;
break;
case PRINT_C_SIZE:
/*
* C99 says that with the "z" length
* modifier, "a following `n' conversion
* specifier applies to a pointer to a
* signed integer type corresponding to
* size_t argument." (7.19.6.1, 7)
*/
sizeptr = va_arg(args, SSIZE_T *);
*sizeptr = len;
break;
case PRINT_C_INTMAX:
intmaxptr = va_arg(args, INTMAX_T *);
*intmaxptr = len;
break;
case PRINT_C_PTRDIFF:
ptrdiffptr = va_arg(args, PTRDIFF_T *);
*ptrdiffptr = len;
break;
default:
intptr = va_arg(args, int *);
*intptr = (int)len;
break;
}
break;
case '%': /* Print a "%" character verbatim. */
OUTCHAR(str, len, size, ch);
break;
default: /* Skip other characters. */
break;
}
ch = *format++;
state = PRINT_S_DEFAULT;
base = cflags = flags = width = 0;
precision = -1;
break;
}
out:
if (len < size)
str[len] = '\0';
else if (size > 0)
str[size - 1] = '\0';
 
if (overflow || len >= INT_MAX) {
return -1;
}
return (int)len;
}
 
static void
fmtstr(char *str, size_t *len, size_t size, const char *value, int width,
int precision, int flags)
{
int padlen, strln; /* Amount to pad. */
int noprecision = (precision == -1);
 
if (value == NULL) /* We're forgiving. */
value = "(null)";
 
/* If a precision was specified, don't read the string past it. */
for (strln = 0; value[strln] != '\0' &&
(noprecision || strln < precision); strln++)
continue;
 
if ((padlen = width - strln) < 0)
padlen = 0;
if (flags & PRINT_F_MINUS) /* Left justify. */
padlen = -padlen;
 
while (padlen > 0) { /* Leading spaces. */
OUTCHAR(str, *len, size, ' ');
padlen--;
}
while (*value != '\0' && (noprecision || precision-- > 0)) {
OUTCHAR(str, *len, size, *value);
value++;
}
while (padlen < 0) { /* Trailing spaces. */
OUTCHAR(str, *len, size, ' ');
padlen++;
}
}
 
static void
fmtint(char *str, size_t *len, size_t size, INTMAX_T value, int base, int width,
int precision, int flags)
{
UINTMAX_T uvalue;
char iconvert[MAX_CONVERT_LENGTH];
char sign = 0;
char hexprefix = 0;
int spadlen = 0; /* Amount to space pad. */
int zpadlen = 0; /* Amount to zero pad. */
int pos;
int separators = (flags & PRINT_F_QUOTE);
int noprecision = (precision == -1);
 
if (flags & PRINT_F_UNSIGNED)
uvalue = value;
else {
uvalue = (value >= 0) ? value : -value;
if (value < 0)
sign = '-';
else if (flags & PRINT_F_PLUS) /* Do a sign. */
sign = '+';
else if (flags & PRINT_F_SPACE)
sign = ' ';
}
 
pos = convert(uvalue, iconvert, sizeof(iconvert), base,
flags & PRINT_F_UP);
 
if (flags & PRINT_F_NUM && uvalue != 0) {
/*
* C99 says: "The result is converted to an `alternative form'.
* For `o' conversion, it increases the precision, if and only
* if necessary, to force the first digit of the result to be a
* zero (if the value and precision are both 0, a single 0 is
* printed). For `x' (or `X') conversion, a nonzero result has
* `0x' (or `0X') prefixed to it." (7.19.6.1, 6)
*/
switch (base) {
case 8:
if (precision <= pos)
precision = pos + 1;
break;
case 16:
hexprefix = (flags & PRINT_F_UP) ? 'X' : 'x';
break;
}
}
 
if (separators) /* Get the number of group separators we'll print. */
separators = getnumsep(pos);
 
zpadlen = precision - pos - separators;
spadlen = width /* Minimum field width. */
- separators /* Number of separators. */
- MAX(precision, pos) /* Number of integer digits. */
- ((sign != 0) ? 1 : 0) /* Will we print a sign? */
- ((hexprefix != 0) ? 2 : 0); /* Will we print a prefix? */
 
if (zpadlen < 0)
zpadlen = 0;
if (spadlen < 0)
spadlen = 0;
 
/*
* C99 says: "If the `0' and `-' flags both appear, the `0' flag is
* ignored. For `d', `i', `o', `u', `x', and `X' conversions, if a
* precision is specified, the `0' flag is ignored." (7.19.6.1, 6)
*/
if (flags & PRINT_F_MINUS) /* Left justify. */
spadlen = -spadlen;
else if (flags & PRINT_F_ZERO && noprecision) {
zpadlen += spadlen;
spadlen = 0;
}
while (spadlen > 0) { /* Leading spaces. */
OUTCHAR(str, *len, size, ' ');
spadlen--;
}
if (sign != 0) /* Sign. */
OUTCHAR(str, *len, size, sign);
if (hexprefix != 0) { /* A "0x" or "0X" prefix. */
OUTCHAR(str, *len, size, '0');
OUTCHAR(str, *len, size, hexprefix);
}
while (zpadlen > 0) { /* Leading zeros. */
OUTCHAR(str, *len, size, '0');
zpadlen--;
}
while (pos > 0) { /* The actual digits. */
pos--;
OUTCHAR(str, *len, size, iconvert[pos]);
if (separators > 0 && pos > 0 && pos % 3 == 0)
printsep(str, len, size);
}
while (spadlen < 0) { /* Trailing spaces. */
OUTCHAR(str, *len, size, ' ');
spadlen++;
}
}
 
static void
fmtflt(char *str, size_t *len, size_t size, LDOUBLE fvalue, int width,
int precision, int flags, int *overflow)
{
LDOUBLE ufvalue;
UINTMAX_T intpart;
UINTMAX_T fracpart;
UINTMAX_T mask;
const char *infnan = NULL;
char iconvert[MAX_CONVERT_LENGTH];
char fconvert[MAX_CONVERT_LENGTH];
char econvert[4]; /* "e-12" (without nul-termination). */
char esign = 0;
char sign = 0;
int leadfraczeros = 0;
int exponent = 0;
int emitpoint = 0;
int omitzeros = 0;
int omitcount = 0;
int padlen = 0;
int epos = 0;
int fpos = 0;
int ipos = 0;
int separators = (flags & PRINT_F_QUOTE);
int estyle = (flags & PRINT_F_TYPE_E);
#if HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT
struct lconv *lc = localeconv();
#endif /* HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT */
 
/*
* AIX' man page says the default is 0, but C99 and at least Solaris'
* and NetBSD's man pages say the default is 6, and sprintf(3) on AIX
* defaults to 6.
*/
if (precision == -1)
precision = 6;
 
if (fvalue < 0.0)
sign = '-';
else if (flags & PRINT_F_PLUS) /* Do a sign. */
sign = '+';
else if (flags & PRINT_F_SPACE)
sign = ' ';
 
if (ISNAN(fvalue))
infnan = (flags & PRINT_F_UP) ? "NAN" : "nan";
else if (ISINF(fvalue))
infnan = (flags & PRINT_F_UP) ? "INF" : "inf";
 
if (infnan != NULL) {
if (sign != 0)
iconvert[ipos++] = sign;
while (*infnan != '\0')
iconvert[ipos++] = *infnan++;
fmtstr(str, len, size, iconvert, width, ipos, flags);
return;
}
 
/* "%e" (or "%E") or "%g" (or "%G") conversion. */
if (flags & PRINT_F_TYPE_E || flags & PRINT_F_TYPE_G) {
if (flags & PRINT_F_TYPE_G) {
/*
* For "%g" (and "%G") conversions, the precision
* specifies the number of significant digits, which
* includes the digits in the integer part. The
* conversion will or will not be using "e-style" (like
* "%e" or "%E" conversions) depending on the precision
* and on the exponent. However, the exponent can be
* affected by rounding the converted value, so we'll
* leave this decision for later. Until then, we'll
* assume that we're going to do an "e-style" conversion
* (in order to get the exponent calculated). For
* "e-style", the precision must be decremented by one.
*/
precision--;
/*
* For "%g" (and "%G") conversions, trailing zeros are
* removed from the fractional portion of the result
* unless the "#" flag was specified.
*/
if (!(flags & PRINT_F_NUM))
omitzeros = 1;
}
exponent = getexponent(fvalue);
estyle = 1;
}
 
again:
/*
* Sorry, we only support 9, 19, or 38 digits (that is, the number of
* digits of the 32-bit, the 64-bit, or the 128-bit UINTMAX_MAX value
* minus one) past the decimal point due to our conversion method.
*/
switch (sizeof(UINTMAX_T)) {
case 16:
if (precision > 38)
precision = 38;
break;
case 8:
if (precision > 19)
precision = 19;
break;
default:
if (precision > 9)
precision = 9;
break;
}
 
ufvalue = (fvalue >= 0.0) ? fvalue : -fvalue;
if (estyle) /* We want exactly one integer digit. */
ufvalue /= mypow10(exponent);
 
if ((intpart = cast(ufvalue)) == UINTMAX_MAX) {
*overflow = 1;
return;
}
 
/*
* Factor of ten with the number of digits needed for the fractional
* part. For example, if the precision is 3, the mask will be 1000.
*/
mask = (UINTMAX_T)mypow10(precision);
/*
* We "cheat" by converting the fractional part to integer by
* multiplying by a factor of ten.
*/
if ((fracpart = myround(mask * (ufvalue - intpart))) >= mask) {
/*
* For example, ufvalue = 2.99962, intpart = 2, and mask = 1000
* (because precision = 3). Now, myround(1000 * 0.99962) will
* return 1000. So, the integer part must be incremented by one
* and the fractional part must be set to zero.
*/
intpart++;
fracpart = 0;
if (estyle && intpart == 10) {
/*
* The value was rounded up to ten, but we only want one
* integer digit if using "e-style". So, the integer
* part must be set to one and the exponent must be
* incremented by one.
*/
intpart = 1;
exponent++;
}
}
 
/*
* Now that we know the real exponent, we can check whether or not to
* use "e-style" for "%g" (and "%G") conversions. If we don't need
* "e-style", the precision must be adjusted and the integer and
* fractional parts must be recalculated from the original value.
*
* C99 says: "Let P equal the precision if nonzero, 6 if the precision
* is omitted, or 1 if the precision is zero. Then, if a conversion
* with style `E' would have an exponent of X:
*
* - if P > X >= -4, the conversion is with style `f' (or `F') and
* precision P - (X + 1).
*
* - otherwise, the conversion is with style `e' (or `E') and precision
* P - 1." (7.19.6.1, 8)
*
* Note that we had decremented the precision by one.
*/
if (flags & PRINT_F_TYPE_G && estyle &&
precision + 1 > exponent && exponent >= -4) {
precision -= exponent;
estyle = 0;
goto again;
}
 
if (estyle) {
if (exponent < 0) {
exponent = -exponent;
esign = '-';
} else
esign = '+';
 
/*
* Convert the exponent. The sizeof(econvert) is 4. So, the
* econvert buffer can hold e.g. "e+99" and "e-99". We don't
* support an exponent which contains more than two digits.
* Therefore, the following stores are safe.
*/
epos = convert(exponent, econvert, 2, 10, 0);
/*
* C99 says: "The exponent always contains at least two digits,
* and only as many more digits as necessary to represent the
* exponent." (7.19.6.1, 8)
*/
if (epos == 1)
econvert[epos++] = '0';
econvert[epos++] = esign;
econvert[epos++] = (flags & PRINT_F_UP) ? 'E' : 'e';
}
 
/* Convert the integer part and the fractional part. */
ipos = convert(intpart, iconvert, sizeof(iconvert), 10, 0);
if (fracpart != 0) /* convert() would return 1 if fracpart == 0. */
fpos = convert(fracpart, fconvert, sizeof(fconvert), 10, 0);
 
leadfraczeros = precision - fpos;
 
if (omitzeros) {
if (fpos > 0) /* Omit trailing fractional part zeros. */
while (omitcount < fpos && fconvert[omitcount] == '0')
omitcount++;
else { /* The fractional part is zero, omit it completely. */
omitcount = precision;
leadfraczeros = 0;
}
precision -= omitcount;
}
 
/*
* Print a decimal point if either the fractional part is non-zero
* and/or the "#" flag was specified.
*/
if (precision > 0 || flags & PRINT_F_NUM)
emitpoint = 1;
if (separators) /* Get the number of group separators we'll print. */
separators = getnumsep(ipos);
 
padlen = width /* Minimum field width. */
- ipos /* Number of integer digits. */
- epos /* Number of exponent characters. */
- precision /* Number of fractional digits. */
- separators /* Number of group separators. */
- (emitpoint ? 1 : 0) /* Will we print a decimal point? */
- ((sign != 0) ? 1 : 0); /* Will we print a sign character? */
 
if (padlen < 0)
padlen = 0;
 
/*
* C99 says: "If the `0' and `-' flags both appear, the `0' flag is
* ignored." (7.19.6.1, 6)
*/
if (flags & PRINT_F_MINUS) /* Left justifty. */
padlen = -padlen;
else if (flags & PRINT_F_ZERO && padlen > 0) {
if (sign != 0) { /* Sign. */
OUTCHAR(str, *len, size, sign);
sign = 0;
}
while (padlen > 0) { /* Leading zeros. */
OUTCHAR(str, *len, size, '0');
padlen--;
}
}
while (padlen > 0) { /* Leading spaces. */
OUTCHAR(str, *len, size, ' ');
padlen--;
}
if (sign != 0) /* Sign. */
OUTCHAR(str, *len, size, sign);
while (ipos > 0) { /* Integer part. */
ipos--;
OUTCHAR(str, *len, size, iconvert[ipos]);
if (separators > 0 && ipos > 0 && ipos % 3 == 0)
printsep(str, len, size);
}
if (emitpoint) { /* Decimal point. */
#if HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT
if (lc->decimal_point != NULL && *lc->decimal_point != '\0')
OUTCHAR(str, *len, size, *lc->decimal_point);
else /* We'll always print some decimal point character. */
#endif /* HAVE_LOCALECONV && HAVE_LCONV_DECIMAL_POINT */
OUTCHAR(str, *len, size, '.');
}
while (leadfraczeros > 0) { /* Leading fractional part zeros. */
OUTCHAR(str, *len, size, '0');
leadfraczeros--;
}
while (fpos > omitcount) { /* The remaining fractional part. */
fpos--;
OUTCHAR(str, *len, size, fconvert[fpos]);
}
while (epos > 0) { /* Exponent. */
epos--;
OUTCHAR(str, *len, size, econvert[epos]);
}
while (padlen < 0) { /* Trailing spaces. */
OUTCHAR(str, *len, size, ' ');
padlen++;
}
}
 
static void
printsep(char *str, size_t *len, size_t size)
{
#if HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP
struct lconv *lc = localeconv();
int i;
 
if (lc->thousands_sep != NULL)
for (i = 0; lc->thousands_sep[i] != '\0'; i++)
OUTCHAR(str, *len, size, lc->thousands_sep[i]);
else
#endif /* HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP */
OUTCHAR(str, *len, size, ',');
}
 
static int
getnumsep(int digits)
{
int separators = (digits - ((digits % 3 == 0) ? 1 : 0)) / 3;
#if HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP
int strln;
struct lconv *lc = localeconv();
 
/* We support an arbitrary separator length (including zero). */
if (lc->thousands_sep != NULL) {
for (strln = 0; lc->thousands_sep[strln] != '\0'; strln++)
continue;
separators *= strln;
}
#endif /* HAVE_LOCALECONV && HAVE_LCONV_THOUSANDS_SEP */
return separators;
}
 
static int
getexponent(LDOUBLE value)
{
LDOUBLE tmp = (value >= 0.0) ? value : -value;
int exponent = 0;
 
/*
* We check for 99 > exponent > -99 in order to work around possible
* endless loops which could happen (at least) in the second loop (at
* least) if we're called with an infinite value. However, we checked
* for infinity before calling this function using our ISINF() macro, so
* this might be somewhat paranoid.
*/
while (tmp < 1.0 && tmp > 0.0 && --exponent > -99)
tmp *= 10;
while (tmp >= 10.0 && ++exponent < 99)
tmp /= 10;
 
return exponent;
}
 
static int
convert(UINTMAX_T value, char *buf, size_t size, int base, int caps)
{
const char *digits = caps ? "0123456789ABCDEF" : "0123456789abcdef";
size_t pos = 0;
 
/* We return an unterminated buffer with the digits in reverse order. */
do {
buf[pos++] = digits[value % base];
value /= base;
} while (value != 0 && pos < size);
 
return (int)pos;
}
 
static UINTMAX_T
cast(LDOUBLE value)
{
UINTMAX_T result;
 
/*
* We check for ">=" and not for ">" because if UINTMAX_MAX cannot be
* represented exactly as an LDOUBLE value (but is less than LDBL_MAX),
* it may be increased to the nearest higher representable value for the
* comparison (cf. C99: 6.3.1.4, 2). It might then equal the LDOUBLE
* value although converting the latter to UINTMAX_T would overflow.
*/
if (value >= UINTMAX_MAX)
return UINTMAX_MAX;
 
result = (UINTMAX_T)value;
/*
* At least on NetBSD/sparc64 3.0.2 and 4.99.30, casting long double to
* an integer type converts e.g. 1.9 to 2 instead of 1 (which violates
* the standard). Sigh.
*/
return (result <= value) ? result : result - 1;
}
 
static UINTMAX_T
myround(LDOUBLE value)
{
UINTMAX_T intpart = cast(value);
 
return ((value -= intpart) < 0.5) ? intpart : intpart + 1;
}
 
static LDOUBLE
mypow10(int exponent)
{
LDOUBLE result = 1;
 
while (exponent > 0) {
result *= 10;
exponent--;
}
while (exponent < 0) {
result /= 10;
exponent++;
}
return result;
}
#endif /* !HAVE_VSNPRINTF */
 
#if !HAVE_VASPRINTF
#if NEED_MYMEMCPY
void *
mymemcpy(void *dst, void *src, size_t len)
{
const char *from = src;
char *to = dst;
 
/* No need for optimization, we use this only to replace va_copy(3). */
while (len-- > 0)
*to++ = *from++;
return dst;
}
#endif /* NEED_MYMEMCPY */
 
int
util_vasprintf(char **ret, const char *format, va_list ap)
{
size_t size;
int len;
va_list aq;
 
VA_COPY(aq, ap);
len = vsnprintf(NULL, 0, format, aq);
VA_END_COPY(aq);
if (len < 0 || (*ret = malloc(size = len + 1)) == NULL)
return -1;
return vsnprintf(*ret, size, format, ap);
}
#endif /* !HAVE_VASPRINTF */
 
#if !HAVE_SNPRINTF
#if HAVE_STDARG_H
int
util_snprintf(char *str, size_t size, const char *format, ...)
#else
int
util_snprintf(va_alist) va_dcl
#endif /* HAVE_STDARG_H */
{
#if !HAVE_STDARG_H
char *str;
size_t size;
char *format;
#endif /* HAVE_STDARG_H */
va_list ap;
int len;
 
VA_START(ap, format);
VA_SHIFT(ap, str, char *);
VA_SHIFT(ap, size, size_t);
VA_SHIFT(ap, format, const char *);
len = vsnprintf(str, size, format, ap);
va_end(ap);
return len;
}
#endif /* !HAVE_SNPRINTF */
 
#if !HAVE_ASPRINTF
#if HAVE_STDARG_H
int
util_asprintf(char **ret, const char *format, ...)
#else
int
util_asprintf(va_alist) va_dcl
#endif /* HAVE_STDARG_H */
{
#if !HAVE_STDARG_H
char **ret;
char *format;
#endif /* HAVE_STDARG_H */
va_list ap;
int len;
 
VA_START(ap, format);
VA_SHIFT(ap, ret, char **);
VA_SHIFT(ap, format, const char *);
len = vasprintf(ret, format, ap);
va_end(ap);
return len;
}
#endif /* !HAVE_ASPRINTF */
#else /* Dummy declaration to avoid empty translation unit warnings. */
int main(void);
#endif /* !HAVE_SNPRINTF || !HAVE_VSNPRINTF || !HAVE_ASPRINTF || [...] */
 
 
/* vim: set joinspaces textwidth=80: */
/drivers/video/Gallium/auxiliary/util/u_split_prim.h
0,0 → 1,114
/* Originally written by Ben Skeggs for the nv50 driver*/
 
#ifndef U_SPLIT_PRIM_H
#define U_SPLIT_PRIM_H
 
#include "pipe/p_defines.h"
#include "pipe/p_compiler.h"
 
#include "util/u_debug.h"
 
struct util_split_prim {
void *priv;
void (*emit)(void *priv, unsigned start, unsigned count);
void (*edge)(void *priv, boolean enabled);
 
unsigned mode;
unsigned start;
unsigned p_start;
unsigned p_end;
 
uint repeat_first:1;
uint close_first:1;
uint edgeflag_off:1;
};
 
static INLINE void
util_split_prim_init(struct util_split_prim *s,
unsigned mode, unsigned start, unsigned count)
{
if (mode == PIPE_PRIM_LINE_LOOP) {
s->mode = PIPE_PRIM_LINE_STRIP;
s->close_first = 1;
} else {
s->mode = mode;
s->close_first = 0;
}
s->start = start;
s->p_start = start;
s->p_end = start + count;
s->edgeflag_off = 0;
s->repeat_first = 0;
}
 
static INLINE boolean
util_split_prim_next(struct util_split_prim *s, unsigned max_verts)
{
int repeat = 0;
 
if (s->repeat_first) {
s->emit(s->priv, s->start, 1);
max_verts--;
if (s->edgeflag_off) {
s->edge(s->priv, TRUE);
s->edgeflag_off = FALSE;
}
}
 
if ((s->p_end - s->p_start) + s->close_first <= max_verts) {
s->emit(s->priv, s->p_start, s->p_end - s->p_start);
if (s->close_first)
s->emit(s->priv, s->start, 1);
return TRUE;
}
 
switch (s->mode) {
case PIPE_PRIM_LINES:
max_verts &= ~1;
break;
case PIPE_PRIM_LINE_STRIP:
repeat = 1;
break;
case PIPE_PRIM_POLYGON:
max_verts--;
s->emit(s->priv, s->p_start, max_verts);
s->edge(s->priv, FALSE);
s->emit(s->priv, s->p_start + max_verts, 1);
s->p_start += max_verts;
s->repeat_first = TRUE;
s->edgeflag_off = TRUE;
return FALSE;
case PIPE_PRIM_TRIANGLES:
max_verts = max_verts - (max_verts % 3);
break;
case PIPE_PRIM_TRIANGLE_STRIP:
/* to ensure winding stays correct, always split
* on an even number of generated triangles
*/
max_verts = max_verts & ~1;
repeat = 2;
break;
case PIPE_PRIM_TRIANGLE_FAN:
s->repeat_first = TRUE;
repeat = 1;
break;
case PIPE_PRIM_QUADS:
max_verts &= ~3;
break;
case PIPE_PRIM_QUAD_STRIP:
max_verts &= ~1;
repeat = 2;
break;
case PIPE_PRIM_POINTS:
break;
default:
/* TODO: implement adjacency primitives */
assert(0);
}
 
s->emit (s->priv, s->p_start, max_verts);
s->p_start += (max_verts - repeat);
return FALSE;
}
 
#endif /* U_SPLIT_PRIM_H */
/drivers/video/Gallium/auxiliary/util/u_sse.h
0,0 → 1,260
/**************************************************************************
*
* 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
* SSE intrinsics portability header.
*
* Although the SSE intrinsics are support by all modern x86 and x86-64
* compilers, there are some intrisincs missing in some implementations
* (especially older MSVC versions). This header abstracts that away.
*/
 
#ifndef U_SSE_H_
#define U_SSE_H_
 
#include "pipe/p_config.h"
 
#if defined(PIPE_ARCH_SSE)
 
#include <emmintrin.h>
 
 
/* MSVC before VC8 does not support the _mm_castxxx_yyy */
#if defined(_MSC_VER) && _MSC_VER < 1500
 
union __declspec(align(16)) m128_types {
__m128 m128;
__m128i m128i;
__m128d m128d;
};
 
static __inline __m128
_mm_castsi128_ps(__m128i a)
{
union m128_types u;
u.m128i = a;
return u.m128;
}
 
static __inline __m128i
_mm_castps_si128(__m128 a)
{
union m128_types u;
u.m128 = a;
return u.m128i;
}
 
#endif /* defined(_MSC_VER) && _MSC_VER < 1500 */
 
union m128i {
__m128i m;
ubyte ub[16];
ushort us[8];
uint ui[4];
};
 
static INLINE void u_print_epi8(const char *name, __m128i r)
{
union { __m128i m; ubyte ub[16]; } u;
u.m = r;
 
debug_printf("%s: "
"%02x/"
"%02x/"
"%02x/"
"%02x/"
"%02x/"
"%02x/"
"%02x/"
"%02x/"
"%02x/"
"%02x/"
"%02x/"
"%02x/"
"%02x/"
"%02x/"
"%02x/"
"%02x\n",
name,
u.ub[0], u.ub[1], u.ub[2], u.ub[3],
u.ub[4], u.ub[5], u.ub[6], u.ub[7],
u.ub[8], u.ub[9], u.ub[10], u.ub[11],
u.ub[12], u.ub[13], u.ub[14], u.ub[15]);
}
 
static INLINE void u_print_epi16(const char *name, __m128i r)
{
union { __m128i m; ushort us[8]; } u;
u.m = r;
 
debug_printf("%s: "
"%04x/"
"%04x/"
"%04x/"
"%04x/"
"%04x/"
"%04x/"
"%04x/"
"%04x\n",
name,
u.us[0], u.us[1], u.us[2], u.us[3],
u.us[4], u.us[5], u.us[6], u.us[7]);
}
 
static INLINE void u_print_epi32(const char *name, __m128i r)
{
union { __m128i m; uint ui[4]; } u;
u.m = r;
 
debug_printf("%s: "
"%08x/"
"%08x/"
"%08x/"
"%08x\n",
name,
u.ui[0], u.ui[1], u.ui[2], u.ui[3]);
}
 
static INLINE void u_print_ps(const char *name, __m128 r)
{
union { __m128 m; float f[4]; } u;
u.m = r;
 
debug_printf("%s: "
"%f/"
"%f/"
"%f/"
"%f\n",
name,
u.f[0], u.f[1], u.f[2], u.f[3]);
}
 
 
#define U_DUMP_EPI32(a) u_print_epi32(#a, a)
#define U_DUMP_EPI16(a) u_print_epi16(#a, a)
#define U_DUMP_EPI8(a) u_print_epi8(#a, a)
#define U_DUMP_PS(a) u_print_ps(#a, a)
 
 
 
#if defined(PIPE_ARCH_SSSE3)
 
#include <tmmintrin.h>
 
#else /* !PIPE_ARCH_SSSE3 */
 
/**
* Describe _mm_shuffle_epi8() with gcc extended inline assembly, for cases
* where -mssse3 is not supported/enabled.
*
* MSVC will never get in here as its intrinsics support do not rely on
* compiler command line options.
*/
static __inline __m128i
#ifdef __clang__
__attribute__((__always_inline__, __nodebug__))
#else
__attribute__((__gnu_inline__, __always_inline__, __artificial__))
#endif
_mm_shuffle_epi8(__m128i a, __m128i mask)
{
__m128i result;
__asm__("pshufb %1, %0"
: "=x" (result)
: "xm" (mask), "0" (a));
return result;
}
 
#endif /* !PIPE_ARCH_SSSE3 */
 
 
 
 
/* Provide an SSE2 implementation of _mm_mullo_epi32() in terms of
* _mm_mul_epu32().
*
* I suspect this works fine for us because one of our operands is
* always positive, but not sure that this can be used for general
* signed integer multiplication.
*
* This seems close enough to the speed of SSE4 and the real
* _mm_mullo_epi32() intrinsic as to not justify adding an sse4
* dependency at this point.
*/
static INLINE __m128i mm_mullo_epi32(const __m128i a, const __m128i b)
{
__m128i a4 = _mm_srli_epi64(a, 32); /* shift by one dword */
__m128i b4 = _mm_srli_epi64(b, 32); /* shift by one dword */
__m128i ba = _mm_mul_epu32(b, a); /* multply dwords 0, 2 */
__m128i b4a4 = _mm_mul_epu32(b4, a4); /* multiply dwords 1, 3 */
 
/* Interleave the results, either with shuffles or (slightly
* faster) direct bit operations:
*/
#if 0
__m128i ba8 = _mm_shuffle_epi32(ba, 8);
__m128i b4a48 = _mm_shuffle_epi32(b4a4, 8);
__m128i result = _mm_unpacklo_epi32(ba8, b4a48);
#else
__m128i mask = _mm_setr_epi32(~0,0,~0,0);
__m128i ba_mask = _mm_and_si128(ba, mask);
__m128i b4a4_mask_shift = _mm_slli_epi64(b4a4, 32);
__m128i result = _mm_or_si128(ba_mask, b4a4_mask_shift);
#endif
 
return result;
}
 
 
static INLINE void
transpose4_epi32(const __m128i * restrict a,
const __m128i * restrict b,
const __m128i * restrict c,
const __m128i * restrict d,
__m128i * restrict o,
__m128i * restrict p,
__m128i * restrict q,
__m128i * restrict r)
{
__m128i t0 = _mm_unpacklo_epi32(*a, *b);
__m128i t1 = _mm_unpacklo_epi32(*c, *d);
__m128i t2 = _mm_unpackhi_epi32(*a, *b);
__m128i t3 = _mm_unpackhi_epi32(*c, *d);
 
*o = _mm_unpacklo_epi64(t0, t1);
*p = _mm_unpackhi_epi64(t0, t1);
*q = _mm_unpacklo_epi64(t2, t3);
*r = _mm_unpackhi_epi64(t2, t3);
}
 
#define SCALAR_EPI32(m, i) _mm_shuffle_epi32((m), _MM_SHUFFLE(i,i,i,i))
 
 
#endif /* PIPE_ARCH_SSE */
 
#endif /* U_SSE_H_ */
/drivers/video/Gallium/auxiliary/util/u_staging.c
0,0 → 1,132
/**************************************************************************
*
* Copyright 2010 Luca Barbieri
*
* 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, sublicense, 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 NONINFRINGEMENT.
* IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
*
**************************************************************************/
 
#include "util/u_staging.h"
#include "pipe/p_context.h"
#include "util/u_memory.h"
#include "util/u_inlines.h"
 
static void
util_staging_resource_template(struct pipe_resource *pt, unsigned width, unsigned height, unsigned depth, struct pipe_resource *template)
{
memset(template, 0, sizeof(struct pipe_resource));
if(pt->target != PIPE_BUFFER && depth <= 1)
template->target = PIPE_TEXTURE_RECT;
else
template->target = pt->target;
template->format = pt->format;
template->width0 = width;
template->height0 = height;
template->depth0 = depth;
template->array_size = 1;
template->last_level = 0;
template->nr_samples = pt->nr_samples;
template->bind = 0;
template->usage = PIPE_USAGE_STAGING;
template->flags = 0;
}
 
struct util_staging_transfer *
util_staging_transfer_init(struct pipe_context *pipe,
struct pipe_resource *pt,
unsigned level,
unsigned usage,
const struct pipe_box *box,
boolean direct, struct util_staging_transfer *tx)
{
struct pipe_screen *pscreen = pipe->screen;
 
struct pipe_resource staging_resource_template;
 
pipe_resource_reference(&tx->base.resource, pt);
tx->base.level = level;
tx->base.usage = usage;
tx->base.box = *box;
 
if (direct)
{
tx->staging_resource = pt;
return tx;
}
 
util_staging_resource_template(pt, box->width, box->height, box->depth, &staging_resource_template);
tx->staging_resource = pscreen->resource_create(pscreen, &staging_resource_template);
if (!tx->staging_resource)
{
pipe_resource_reference(&tx->base.resource, NULL);
FREE(tx);
return NULL;
}
 
if (usage & PIPE_TRANSFER_READ)
{
/* XXX this looks wrong dst is always the same but looping over src z? */
int zi;
struct pipe_box sbox;
sbox.x = box->x;
sbox.y = box->y;
sbox.z = box->z;
sbox.width = box->width;
sbox.height = box->height;
sbox.depth = 1;
for(zi = 0; zi < box->depth; ++zi) {
sbox.z = sbox.z + zi;
pipe->resource_copy_region(pipe, tx->staging_resource, 0, 0, 0, 0,
tx->base.resource, level, &sbox);
}
}
 
return tx;
}
 
void
util_staging_transfer_destroy(struct pipe_context *pipe, struct pipe_transfer *ptx)
{
struct util_staging_transfer *tx = (struct util_staging_transfer *)ptx;
 
if (tx->staging_resource != tx->base.resource)
{
if(tx->base.usage & PIPE_TRANSFER_WRITE) {
/* XXX this looks wrong src is always the same but looping over dst z? */
int zi;
struct pipe_box sbox;
sbox.x = 0;
sbox.y = 0;
sbox.z = 0;
sbox.width = tx->base.box.width;
sbox.height = tx->base.box.height;
sbox.depth = 1;
for(zi = 0; zi < tx->base.box.depth; ++zi)
pipe->resource_copy_region(pipe, tx->base.resource, tx->base.level, tx->base.box.x, tx->base.box.y, tx->base.box.z + zi,
tx->staging_resource, 0, &sbox);
}
 
pipe_resource_reference(&tx->staging_resource, NULL);
}
 
pipe_resource_reference(&ptx->resource, NULL);
FREE(ptx);
}
/drivers/video/Gallium/auxiliary/util/u_staging.h
0,0 → 1,63
/**************************************************************************
*
* Copyright 2010 Luca Barbieri
*
* 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, sublicense, 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 NONINFRINGEMENT.
* IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
*
**************************************************************************/
 
/* Direct3D 10/11 has no concept of transfers. Applications instead
* create resources with a STAGING or DYNAMIC usage, copy between them
* and the real resource and use Map to map the STAGING/DYNAMIC resource.
*
* This util module allows to implement Gallium drivers as a Direct3D
* driver would be implemented: transfers allocate a resource with
* PIPE_USAGE_STAGING, and copy the data between it and the real resource
* with resource_copy_region.
*/
 
#ifndef U_STAGING_H
#define U_STAGING_H
 
#include "pipe/p_state.h"
 
struct util_staging_transfer {
struct pipe_transfer base;
 
/* if direct, same as base.resource, otherwise the temporary staging resource */
struct pipe_resource *staging_resource;
};
 
/* user must be stride, slice_stride and offset */
/* pt->usage == PIPE_USAGE_DYNAMIC || pt->usage == PIPE_USAGE_STAGING should be a good value to pass for direct */
/* staging resource is currently created with PIPE_USAGE_STAGING */
struct util_staging_transfer *
util_staging_transfer_init(struct pipe_context *pipe,
struct pipe_resource *pt,
unsigned level,
unsigned usage,
const struct pipe_box *box,
boolean direct, struct util_staging_transfer *tx);
 
void
util_staging_transfer_destroy(struct pipe_context *pipe, struct pipe_transfer *ptx);
 
#endif
/drivers/video/Gallium/auxiliary/util/u_string.h
0,0 → 1,232
/**************************************************************************
*
* 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
* Platform independent functions for string manipulation.
*
* @author Jose Fonseca <jrfonseca@tungstengraphics.com>
*/
 
#ifndef U_STRING_H_
#define U_STRING_H_
 
#if !defined(_MSC_VER) && !defined(XF86_LIBC_H)
#include <stdio.h>
#endif
#include <stddef.h>
#include <stdarg.h>
 
#include "pipe/p_compiler.h"
 
 
#ifdef __cplusplus
extern "C" {
#endif
 
#ifdef _GNU_SOURCE
 
#define util_strchrnul strchrnul
 
#else
 
static INLINE char *
util_strchrnul(const char *s, char c)
{
for (; *s && *s != c; ++s);
 
return (char *)s;
}
 
#endif
 
#ifdef _MSC_VER
 
int util_vsnprintf(char *, size_t, const char *, va_list);
int util_snprintf(char *str, size_t size, const char *format, ...);
 
static INLINE void
util_vsprintf(char *str, const char *format, va_list ap)
{
util_vsnprintf(str, (size_t)-1, format, ap);
}
 
static INLINE void
util_sprintf(char *str, const char *format, ...)
{
va_list ap;
va_start(ap, format);
util_vsnprintf(str, (size_t)-1, format, ap);
va_end(ap);
}
 
static INLINE char *
util_strchr(const char *s, char c)
{
char *p = util_strchrnul(s, c);
 
return *p ? p : NULL;
}
 
static INLINE char*
util_strncat(char *dst, const char *src, size_t n)
{
char *p = dst + strlen(dst);
const char *q = src;
size_t i;
 
for (i = 0; i < n && *q != '\0'; ++i)
*p++ = *q++;
*p = '\0';
 
return dst;
}
 
static INLINE int
util_strcmp(const char *s1, const char *s2)
{
unsigned char u1, u2;
 
while (1) {
u1 = (unsigned char) *s1++;
u2 = (unsigned char) *s2++;
if (u1 != u2)
return u1 - u2;
if (u1 == '\0')
return 0;
}
return 0;
}
 
static INLINE int
util_strncmp(const char *s1, const char *s2, size_t n)
{
unsigned char u1, u2;
 
while (n-- > 0) {
u1 = (unsigned char) *s1++;
u2 = (unsigned char) *s2++;
if (u1 != u2)
return u1 - u2;
if (u1 == '\0')
return 0;
}
return 0;
}
 
static INLINE char *
util_strstr(const char *haystack, const char *needle)
{
const char *p = haystack;
size_t len = strlen(needle);
 
for (; (p = util_strchr(p, *needle)) != 0; p++) {
if (util_strncmp(p, needle, len) == 0) {
return (char *)p;
}
}
return NULL;
}
 
static INLINE void *
util_memmove(void *dest, const void *src, size_t n)
{
char *p = (char *)dest;
const char *q = (const char *)src;
if (dest < src) {
while (n--)
*p++ = *q++;
}
else
{
p += n;
q += n;
while (n--)
*--p = *--q;
}
return dest;
}
 
 
#else
 
#define util_vsnprintf vsnprintf
#define util_snprintf snprintf
#define util_vsprintf vsprintf
#define util_sprintf sprintf
#define util_strchr strchr
#define util_strcmp strcmp
#define util_strncmp strncmp
#define util_strncat strncat
#define util_strstr strstr
#define util_memmove memmove
 
#endif
 
 
/**
* Printable string buffer
*/
struct util_strbuf
{
char *str;
char *ptr;
size_t left;
};
 
 
static INLINE void
util_strbuf_init(struct util_strbuf *sbuf, char *str, size_t size)
{
sbuf->str = str;
sbuf->str[0] = 0;
sbuf->ptr = sbuf->str;
sbuf->left = size;
}
 
 
static INLINE void
util_strbuf_printf(struct util_strbuf *sbuf, const char *format, ...)
{
if(sbuf->left > 1) {
size_t written;
va_list ap;
va_start(ap, format);
written = util_vsnprintf(sbuf->ptr, sbuf->left, format, ap);
va_end(ap);
sbuf->ptr += written;
sbuf->left -= written;
}
}
 
 
 
#ifdef __cplusplus
}
#endif
 
#endif /* U_STRING_H_ */
/drivers/video/Gallium/auxiliary/util/u_suballoc.c
0,0 → 1,132
/**************************************************************************
*
* Copyright 2009 VMware, Inc.
* Copyright 2012 Marek Olšák <maraeo@gmail.com>
* 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 THE AUTHORS 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.
*
**************************************************************************/
 
/* A simple allocator that suballocates memory from a large buffer. */
 
#include "pipe/p_defines.h"
#include "util/u_inlines.h"
#include "pipe/p_context.h"
#include "util/u_memory.h"
#include "util/u_math.h"
 
#include "u_suballoc.h"
 
 
struct u_suballocator {
struct pipe_context *pipe;
 
unsigned size; /* Size of the whole buffer, in bytes. */
unsigned alignment; /* Alignment of each sub-allocation. */
unsigned bind; /* Bitmask of PIPE_BIND_* flags. */
unsigned usage; /* One of PIPE_USAGE_* flags. */
boolean zero_buffer_memory; /* If the buffer contents should be zeroed. */
 
struct pipe_resource *buffer; /* The buffer we suballocate from. */
unsigned offset; /* Aligned offset pointing at the first unused byte. */
};
 
 
/**
* Create a suballocator.
*
* \p zero_buffer_memory determines whether the buffer contents should be
* cleared to 0 after the allocation.
*/
struct u_suballocator *
u_suballocator_create(struct pipe_context *pipe, unsigned size,
unsigned alignment, unsigned bind, unsigned usage,
boolean zero_buffer_memory)
{
struct u_suballocator *allocator = CALLOC_STRUCT(u_suballocator);
if (!allocator)
return NULL;
 
allocator->pipe = pipe;
allocator->size = align(size, alignment);
allocator->alignment = alignment;
allocator->bind = bind;
allocator->usage = usage;
allocator->zero_buffer_memory = zero_buffer_memory;
return allocator;
}
 
void
u_suballocator_destroy(struct u_suballocator *allocator)
{
pipe_resource_reference(&allocator->buffer, NULL);
FREE(allocator);
}
 
void
u_suballocator_alloc(struct u_suballocator *allocator, unsigned size,
unsigned *out_offset, struct pipe_resource **outbuf)
{
unsigned alloc_size = align(size, allocator->alignment);
 
/* Don't allow allocations larger than the buffer size. */
if (alloc_size > allocator->size)
goto fail;
 
/* Make sure we have enough space in the buffer. */
if (!allocator->buffer ||
allocator->offset + alloc_size > allocator->size) {
/* Allocate a new buffer. */
pipe_resource_reference(&allocator->buffer, NULL);
allocator->offset = 0;
allocator->buffer =
pipe_buffer_create(allocator->pipe->screen, allocator->bind,
allocator->usage, allocator->size);
if (!allocator->buffer)
goto fail;
 
/* Clear the memory if needed. */
if (allocator->zero_buffer_memory) {
struct pipe_transfer *transfer = NULL;
void *ptr;
 
ptr = pipe_buffer_map(allocator->pipe, allocator->buffer,
PIPE_TRANSFER_WRITE, &transfer);
memset(ptr, 0, allocator->size);
pipe_buffer_unmap(allocator->pipe, transfer);
}
}
 
assert(allocator->offset % allocator->alignment == 0);
assert(allocator->offset < allocator->buffer->width0);
assert(allocator->offset + alloc_size <= allocator->buffer->width0);
 
/* Return the buffer. */
*out_offset = allocator->offset;
pipe_resource_reference(outbuf, allocator->buffer);
 
allocator->offset += alloc_size;
return;
 
fail:
pipe_resource_reference(outbuf, NULL);
}
/drivers/video/Gallium/auxiliary/util/u_suballoc.h
0,0 → 1,48
/**************************************************************************
*
* Copyright 2009 VMware, Inc.
* Copyright 2012 Marek Olšák <maraeo@gmail.com>
* 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 THE AUTHORS 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.
*
**************************************************************************/
 
/* A simple allocator that suballocates memory from a large buffer. */
 
#ifndef U_SUBALLOC
#define U_SUBALLOC
 
struct u_suballocator;
 
struct u_suballocator *
u_suballocator_create(struct pipe_context *pipe, unsigned size,
unsigned alignment, unsigned bind, unsigned usage,
boolean zero_buffer_memory);
 
void
u_suballocator_destroy(struct u_suballocator *allocator);
 
void
u_suballocator_alloc(struct u_suballocator *allocator, unsigned size,
unsigned *out_offset, struct pipe_resource **outbuf);
 
#endif
/drivers/video/Gallium/auxiliary/util/u_surface.c
0,0 → 1,684
/**************************************************************************
*
* Copyright 2009 VMware, Inc. 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 VMWARE 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
* Surface utility functions.
*
* @author Brian Paul
*/
 
 
#include "pipe/p_defines.h"
#include "pipe/p_screen.h"
#include "pipe/p_state.h"
 
#include "util/u_format.h"
#include "util/u_inlines.h"
#include "util/u_rect.h"
#include "util/u_surface.h"
#include "util/u_pack_color.h"
 
 
/**
* Initialize a pipe_surface object. 'view' is considered to have
* uninitialized contents.
*/
void
u_surface_default_template(struct pipe_surface *surf,
const struct pipe_resource *texture)
{
memset(surf, 0, sizeof(*surf));
 
surf->format = texture->format;
}
 
 
/**
* Copy 2D rect from one place to another.
* Position and sizes are in pixels.
* src_stride may be negative to do vertical flip of pixels from source.
*/
void
util_copy_rect(ubyte * dst,
enum pipe_format format,
unsigned dst_stride,
unsigned dst_x,
unsigned dst_y,
unsigned width,
unsigned height,
const ubyte * src,
int src_stride,
unsigned src_x,
unsigned src_y)
{
unsigned i;
int src_stride_pos = src_stride < 0 ? -src_stride : src_stride;
int blocksize = util_format_get_blocksize(format);
int blockwidth = util_format_get_blockwidth(format);
int blockheight = util_format_get_blockheight(format);
 
assert(blocksize > 0);
assert(blockwidth > 0);
assert(blockheight > 0);
 
dst_x /= blockwidth;
dst_y /= blockheight;
width = (width + blockwidth - 1)/blockwidth;
height = (height + blockheight - 1)/blockheight;
src_x /= blockwidth;
src_y /= blockheight;
 
dst += dst_x * blocksize;
src += src_x * blocksize;
dst += dst_y * dst_stride;
src += src_y * src_stride_pos;
width *= blocksize;
 
if (width == dst_stride && width == src_stride)
memcpy(dst, src, height * width);
else {
for (i = 0; i < height; i++) {
memcpy(dst, src, width);
dst += dst_stride;
src += src_stride;
}
}
}
 
 
/**
* Copy 3D box from one place to another.
* Position and sizes are in pixels.
*/
void
util_copy_box(ubyte * dst,
enum pipe_format format,
unsigned dst_stride, unsigned dst_slice_stride,
unsigned dst_x, unsigned dst_y, unsigned dst_z,
unsigned width, unsigned height, unsigned depth,
const ubyte * src,
int src_stride, unsigned src_slice_stride,
unsigned src_x, unsigned src_y, unsigned src_z)
{
unsigned z;
dst += dst_z * dst_slice_stride;
src += src_z * src_slice_stride;
for (z = 0; z < depth; ++z) {
util_copy_rect(dst,
format,
dst_stride,
dst_x, dst_y,
width, height,
src,
src_stride,
src_x, src_y);
 
dst += dst_slice_stride;
src += src_slice_stride;
}
}
 
 
void
util_fill_rect(ubyte * dst,
enum pipe_format format,
unsigned dst_stride,
unsigned dst_x,
unsigned dst_y,
unsigned width,
unsigned height,
union util_color *uc)
{
const struct util_format_description *desc = util_format_description(format);
unsigned i, j;
unsigned width_size;
int blocksize = desc->block.bits / 8;
int blockwidth = desc->block.width;
int blockheight = desc->block.height;
 
assert(blocksize > 0);
assert(blockwidth > 0);
assert(blockheight > 0);
 
dst_x /= blockwidth;
dst_y /= blockheight;
width = (width + blockwidth - 1)/blockwidth;
height = (height + blockheight - 1)/blockheight;
 
dst += dst_x * blocksize;
dst += dst_y * dst_stride;
width_size = width * blocksize;
 
switch (blocksize) {
case 1:
if(dst_stride == width_size)
memset(dst, uc->ub, height * width_size);
else {
for (i = 0; i < height; i++) {
memset(dst, uc->ub, width_size);
dst += dst_stride;
}
}
break;
case 2:
for (i = 0; i < height; i++) {
uint16_t *row = (uint16_t *)dst;
for (j = 0; j < width; j++)
*row++ = uc->us;
dst += dst_stride;
}
break;
case 4:
for (i = 0; i < height; i++) {
uint32_t *row = (uint32_t *)dst;
for (j = 0; j < width; j++)
*row++ = uc->ui;
dst += dst_stride;
}
break;
default:
for (i = 0; i < height; i++) {
ubyte *row = dst;
for (j = 0; j < width; j++) {
memcpy(row, uc, blocksize);
row += blocksize;
}
dst += dst_stride;
}
break;
}
}
 
 
void
util_fill_box(ubyte * dst,
enum pipe_format format,
unsigned stride,
unsigned layer_stride,
unsigned x,
unsigned y,
unsigned z,
unsigned width,
unsigned height,
unsigned depth,
union util_color *uc)
{
unsigned layer;
dst += z * layer_stride;
for (layer = z; layer < depth; layer++) {
util_fill_rect(dst, format,
stride,
x, y, width, height, uc);
dst += layer_stride;
}
}
 
 
/**
* Fallback function for pipe->resource_copy_region().
* Note: (X,Y)=(0,0) is always the upper-left corner.
*/
void
util_resource_copy_region(struct pipe_context *pipe,
struct pipe_resource *dst,
unsigned dst_level,
unsigned dst_x, unsigned dst_y, unsigned dst_z,
struct pipe_resource *src,
unsigned src_level,
const struct pipe_box *src_box)
{
struct pipe_transfer *src_trans, *dst_trans;
uint8_t *dst_map;
const uint8_t *src_map;
enum pipe_format src_format, dst_format;
struct pipe_box dst_box;
 
assert(src && dst);
if (!src || !dst)
return;
 
assert((src->target == PIPE_BUFFER && dst->target == PIPE_BUFFER) ||
(src->target != PIPE_BUFFER && dst->target != PIPE_BUFFER));
 
src_format = src->format;
dst_format = dst->format;
 
assert(util_format_get_blocksize(dst_format) == util_format_get_blocksize(src_format));
assert(util_format_get_blockwidth(dst_format) == util_format_get_blockwidth(src_format));
assert(util_format_get_blockheight(dst_format) == util_format_get_blockheight(src_format));
 
src_map = pipe->transfer_map(pipe,
src,
src_level,
PIPE_TRANSFER_READ,
src_box, &src_trans);
assert(src_map);
if (!src_map) {
goto no_src_map;
}
 
dst_box.x = dst_x;
dst_box.y = dst_y;
dst_box.z = dst_z;
dst_box.width = src_box->width;
dst_box.height = src_box->height;
dst_box.depth = src_box->depth;
 
dst_map = pipe->transfer_map(pipe,
dst,
dst_level,
PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE,
&dst_box, &dst_trans);
assert(dst_map);
if (!dst_map) {
goto no_dst_map;
}
 
if (dst->target == PIPE_BUFFER && src->target == PIPE_BUFFER) {
assert(src_box->height == 1);
assert(src_box->depth == 1);
memcpy(dst_map, src_map, src_box->width);
} else {
util_copy_box(dst_map,
dst_format,
dst_trans->stride, dst_trans->layer_stride,
0, 0, 0,
src_box->width, src_box->height, src_box->depth,
src_map,
src_trans->stride, src_trans->layer_stride,
0, 0, 0);
}
 
pipe->transfer_unmap(pipe, dst_trans);
no_dst_map:
pipe->transfer_unmap(pipe, src_trans);
no_src_map:
;
}
 
 
 
#define UBYTE_TO_USHORT(B) ((B) | ((B) << 8))
 
 
/**
* Fallback for pipe->clear_render_target() function.
* XXX this looks too hackish to be really useful.
* cpp > 4 looks like a gross hack at best...
* Plus can't use these transfer fallbacks when clearing
* multisampled surfaces for instance.
* Clears all bound layers.
*/
void
util_clear_render_target(struct pipe_context *pipe,
struct pipe_surface *dst,
const union pipe_color_union *color,
unsigned dstx, unsigned dsty,
unsigned width, unsigned height)
{
struct pipe_transfer *dst_trans;
ubyte *dst_map;
union util_color uc;
unsigned max_layer;
 
assert(dst->texture);
if (!dst->texture)
return;
 
if (dst->texture->target == PIPE_BUFFER) {
/*
* The fill naturally works on the surface format, however
* the transfer uses resource format which is just bytes for buffers.
*/
unsigned dx, w;
unsigned pixstride = util_format_get_blocksize(dst->format);
dx = (dst->u.buf.first_element + dstx) * pixstride;
w = width * pixstride;
max_layer = 0;
dst_map = pipe_transfer_map(pipe,
dst->texture,
0, 0,
PIPE_TRANSFER_WRITE,
dx, 0, w, 1,
&dst_trans);
}
else {
max_layer = dst->u.tex.last_layer - dst->u.tex.first_layer;
dst_map = pipe_transfer_map_3d(pipe,
dst->texture,
dst->u.tex.level,
PIPE_TRANSFER_WRITE,
dstx, dsty, dst->u.tex.first_layer,
width, height, max_layer + 1, &dst_trans);
}
 
assert(dst_map);
 
if (dst_map) {
enum pipe_format format = dst->format;
assert(dst_trans->stride > 0);
 
if (util_format_is_pure_integer(format)) {
/*
* We expect int/uint clear values here, though some APIs
* might disagree (but in any case util_pack_color()
* couldn't handle it)...
*/
if (util_format_is_pure_sint(format)) {
util_format_write_4i(format, color->i, 0, &uc, 0, 0, 0, 1, 1);
}
else {
assert(util_format_is_pure_uint(format));
util_format_write_4ui(format, color->ui, 0, &uc, 0, 0, 0, 1, 1);
}
}
else {
util_pack_color(color->f, dst->format, &uc);
}
 
util_fill_box(dst_map, dst->format,
dst_trans->stride, dst_trans->layer_stride,
0, 0, 0, width, height, max_layer + 1, &uc);
 
pipe->transfer_unmap(pipe, dst_trans);
}
}
 
/**
* Fallback for pipe->clear_stencil() function.
* sw fallback doesn't look terribly useful here.
* Plus can't use these transfer fallbacks when clearing
* multisampled surfaces for instance.
* Clears all bound layers.
*/
void
util_clear_depth_stencil(struct pipe_context *pipe,
struct pipe_surface *dst,
unsigned clear_flags,
double depth,
unsigned stencil,
unsigned dstx, unsigned dsty,
unsigned width, unsigned height)
{
enum pipe_format format = dst->format;
struct pipe_transfer *dst_trans;
ubyte *dst_map;
boolean need_rmw = FALSE;
unsigned max_layer, layer;
 
if ((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) &&
((clear_flags & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) &&
util_format_is_depth_and_stencil(format))
need_rmw = TRUE;
 
assert(dst->texture);
if (!dst->texture)
return;
 
max_layer = dst->u.tex.last_layer - dst->u.tex.first_layer;
dst_map = pipe_transfer_map_3d(pipe,
dst->texture,
dst->u.tex.level,
(need_rmw ? PIPE_TRANSFER_READ_WRITE :
PIPE_TRANSFER_WRITE),
dstx, dsty, dst->u.tex.first_layer,
width, height, max_layer + 1, &dst_trans);
assert(dst_map);
 
if (dst_map) {
unsigned dst_stride = dst_trans->stride;
uint64_t zstencil = util_pack64_z_stencil(format, depth, stencil);
ubyte *dst_layer = dst_map;
unsigned i, j;
assert(dst_trans->stride > 0);
 
for (layer = 0; layer <= max_layer; layer++) {
dst_map = dst_layer;
 
switch (util_format_get_blocksize(format)) {
case 1:
assert(format == PIPE_FORMAT_S8_UINT);
if(dst_stride == width)
memset(dst_map, (uint8_t) zstencil, height * width);
else {
for (i = 0; i < height; i++) {
memset(dst_map, (uint8_t) zstencil, width);
dst_map += dst_stride;
}
}
break;
case 2:
assert(format == PIPE_FORMAT_Z16_UNORM);
for (i = 0; i < height; i++) {
uint16_t *row = (uint16_t *)dst_map;
for (j = 0; j < width; j++)
*row++ = (uint16_t) zstencil;
dst_map += dst_stride;
}
break;
case 4:
if (!need_rmw) {
for (i = 0; i < height; i++) {
uint32_t *row = (uint32_t *)dst_map;
for (j = 0; j < width; j++)
*row++ = (uint32_t) zstencil;
dst_map += dst_stride;
}
}
else {
uint32_t dst_mask;
if (format == PIPE_FORMAT_Z24_UNORM_S8_UINT)
dst_mask = 0x00ffffff;
else {
assert(format == PIPE_FORMAT_S8_UINT_Z24_UNORM);
dst_mask = 0xffffff00;
}
if (clear_flags & PIPE_CLEAR_DEPTH)
dst_mask = ~dst_mask;
for (i = 0; i < height; i++) {
uint32_t *row = (uint32_t *)dst_map;
for (j = 0; j < width; j++) {
uint32_t tmp = *row & dst_mask;
*row++ = tmp | ((uint32_t) zstencil & ~dst_mask);
}
dst_map += dst_stride;
}
}
break;
case 8:
if (!need_rmw) {
for (i = 0; i < height; i++) {
uint64_t *row = (uint64_t *)dst_map;
for (j = 0; j < width; j++)
*row++ = zstencil;
dst_map += dst_stride;
}
}
else {
uint64_t src_mask;
 
if (clear_flags & PIPE_CLEAR_DEPTH)
src_mask = 0x00000000ffffffffull;
else
src_mask = 0x000000ff00000000ull;
 
for (i = 0; i < height; i++) {
uint64_t *row = (uint64_t *)dst_map;
for (j = 0; j < width; j++) {
uint64_t tmp = *row & ~src_mask;
*row++ = tmp | (zstencil & src_mask);
}
dst_map += dst_stride;
}
}
break;
default:
assert(0);
break;
}
dst_layer += dst_trans->layer_stride;
}
 
pipe->transfer_unmap(pipe, dst_trans);
}
}
 
 
/* Return if the box is totally inside the resource.
*/
static boolean
is_box_inside_resource(const struct pipe_resource *res,
const struct pipe_box *box,
unsigned level)
{
unsigned width = 1, height = 1, depth = 1;
 
switch (res->target) {
case PIPE_BUFFER:
width = res->width0;
height = 1;
depth = 1;
break;
case PIPE_TEXTURE_1D:
width = u_minify(res->width0, level);
height = 1;
depth = 1;
break;
case PIPE_TEXTURE_2D:
case PIPE_TEXTURE_RECT:
width = u_minify(res->width0, level);
height = u_minify(res->height0, level);
depth = 1;
break;
case PIPE_TEXTURE_3D:
width = u_minify(res->width0, level);
height = u_minify(res->height0, level);
depth = u_minify(res->depth0, level);
break;
case PIPE_TEXTURE_CUBE:
width = u_minify(res->width0, level);
height = u_minify(res->height0, level);
depth = 6;
break;
case PIPE_TEXTURE_1D_ARRAY:
width = u_minify(res->width0, level);
height = 1;
depth = res->array_size;
break;
case PIPE_TEXTURE_2D_ARRAY:
width = u_minify(res->width0, level);
height = u_minify(res->height0, level);
depth = res->array_size;
break;
case PIPE_TEXTURE_CUBE_ARRAY:
width = u_minify(res->width0, level);
height = u_minify(res->height0, level);
depth = res->array_size;
assert(res->array_size % 6 == 0);
break;
case PIPE_MAX_TEXTURE_TYPES:;
}
 
return box->x >= 0 &&
box->x + box->width <= (int) width &&
box->y >= 0 &&
box->y + box->height <= (int) height &&
box->z >= 0 &&
box->z + box->depth <= (int) depth;
}
 
static unsigned
get_sample_count(const struct pipe_resource *res)
{
return res->nr_samples ? res->nr_samples : 1;
}
 
/**
* Try to do a blit using resource_copy_region. The function calls
* resource_copy_region if the blit description is compatible with it.
*
* It returns TRUE if the blit was done using resource_copy_region.
*
* It returns FALSE otherwise and the caller must fall back to a more generic
* codepath for the blit operation. (e.g. by using u_blitter)
*/
boolean
util_try_blit_via_copy_region(struct pipe_context *ctx,
const struct pipe_blit_info *blit)
{
unsigned mask = util_format_get_mask(blit->dst.format);
 
/* No format conversions. */
if (blit->src.resource->format != blit->src.format ||
blit->dst.resource->format != blit->dst.format ||
!util_is_format_compatible(
util_format_description(blit->src.resource->format),
util_format_description(blit->dst.resource->format))) {
return FALSE;
}
 
/* No masks, no filtering, no scissor. */
if ((blit->mask & mask) != mask ||
blit->filter != PIPE_TEX_FILTER_NEAREST ||
blit->scissor_enable) {
return FALSE;
}
 
/* No flipping. */
if (blit->src.box.width < 0 ||
blit->src.box.height < 0 ||
blit->src.box.depth < 0) {
return FALSE;
}
 
/* No scaling. */
if (blit->src.box.width != blit->dst.box.width ||
blit->src.box.height != blit->dst.box.height ||
blit->src.box.depth != blit->dst.box.depth) {
return FALSE;
}
 
/* No out-of-bounds access. */
if (!is_box_inside_resource(blit->src.resource, &blit->src.box,
blit->src.level) ||
!is_box_inside_resource(blit->dst.resource, &blit->dst.box,
blit->dst.level)) {
return FALSE;
}
 
/* Sample counts must match. */
if (get_sample_count(blit->src.resource) !=
get_sample_count(blit->dst.resource)) {
return FALSE;
}
 
ctx->resource_copy_region(ctx, blit->dst.resource, blit->dst.level,
blit->dst.box.x, blit->dst.box.y, blit->dst.box.z,
blit->src.resource, blit->src.level,
&blit->src.box);
return TRUE;
}
/drivers/video/Gallium/auxiliary/util/u_surface.h
0,0 → 1,111
/**************************************************************************
*
* Copyright 2009 VMware, Inc. 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 VMWARE 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.
*
**************************************************************************/
 
 
#ifndef U_SURFACE_H
#define U_SURFACE_H
 
 
#include "pipe/p_compiler.h"
#include "pipe/p_state.h"
 
#include "util/u_pack_color.h"
 
 
#ifdef __cplusplus
extern "C" {
#endif
 
 
extern void
u_surface_default_template(struct pipe_surface *view,
const struct pipe_resource *texture);
 
extern void
util_copy_rect(ubyte * dst, enum pipe_format format,
unsigned dst_stride, unsigned dst_x, unsigned dst_y,
unsigned width, unsigned height, const ubyte * src,
int src_stride, unsigned src_x, unsigned src_y);
 
extern void
util_copy_box(ubyte * dst,
enum pipe_format format,
unsigned dst_stride, unsigned dst_slice_stride,
unsigned dst_x, unsigned dst_y, unsigned dst_z,
unsigned width, unsigned height, unsigned depth,
const ubyte * src,
int src_stride, unsigned src_slice_stride,
unsigned src_x, unsigned src_y, unsigned src_z);
 
extern void
util_fill_rect(ubyte * dst, enum pipe_format format,
unsigned dst_stride, unsigned dst_x, unsigned dst_y,
unsigned width, unsigned height, union util_color *uc);
 
extern void
util_fill_box(ubyte * dst, enum pipe_format format,
unsigned stride, unsigned layer_stride,
unsigned x, unsigned y, unsigned z,
unsigned width, unsigned height, unsigned depth,
union util_color *uc);
 
 
extern void
util_resource_copy_region(struct pipe_context *pipe,
struct pipe_resource *dst,
unsigned dst_level,
unsigned dst_x, unsigned dst_y, unsigned dst_z,
struct pipe_resource *src,
unsigned src_level,
const struct pipe_box *src_box);
 
extern void
util_clear_render_target(struct pipe_context *pipe,
struct pipe_surface *dst,
const union pipe_color_union *color,
unsigned dstx, unsigned dsty,
unsigned width, unsigned height);
 
extern void
util_clear_depth_stencil(struct pipe_context *pipe,
struct pipe_surface *dst,
unsigned clear_flags,
double depth,
unsigned stencil,
unsigned dstx, unsigned dsty,
unsigned width, unsigned height);
 
extern boolean
util_try_blit_via_copy_region(struct pipe_context *ctx,
const struct pipe_blit_info *blit);
 
 
#ifdef __cplusplus
}
#endif
 
 
#endif /* U_SURFACE_H */
/drivers/video/Gallium/auxiliary/util/u_surfaces.c
0,0 → 1,124
/**************************************************************************
*
* Copyright 2010 Luca Barbieri
*
* 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, sublicense, 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 NONINFRINGEMENT.
* IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
*
**************************************************************************/
 
#include "u_surfaces.h"
#include "util/u_hash_table.h"
#include "util/u_inlines.h"
#include "util/u_memory.h"
 
boolean
util_surfaces_do_get(struct util_surfaces *us, unsigned surface_struct_size,
struct pipe_context *ctx, struct pipe_resource *pt,
unsigned level, unsigned layer,
struct pipe_surface **res)
{
struct pipe_surface *ps;
 
if(pt->target == PIPE_TEXTURE_3D || pt->target == PIPE_TEXTURE_CUBE)
{ /* or 2D array */
if(!us->u.hash)
us->u.hash = cso_hash_create();
 
ps = cso_hash_iter_data(cso_hash_find(us->u.hash, (layer << 8) | level));
}
else
{
if(!us->u.array)
us->u.array = CALLOC(pt->last_level + 1, sizeof(struct pipe_surface *));
ps = us->u.array[level];
}
 
if(ps && ps->context == ctx)
{
p_atomic_inc(&ps->reference.count);
*res = ps;
return FALSE;
}
 
ps = (struct pipe_surface *)CALLOC(1, surface_struct_size);
if(!ps)
{
*res = NULL;
return FALSE;
}
 
pipe_surface_init(ctx, ps, pt, level, layer);
 
if(pt->target == PIPE_TEXTURE_3D || pt->target == PIPE_TEXTURE_CUBE)
cso_hash_insert(us->u.hash, (layer << 8) | level, ps);
else
us->u.array[level] = ps;
 
*res = ps;
return TRUE;
}
 
void
util_surfaces_do_detach(struct util_surfaces *us, struct pipe_surface *ps)
{
struct pipe_resource *pt = ps->texture;
if(pt->target == PIPE_TEXTURE_3D || pt->target == PIPE_TEXTURE_CUBE)
{ /* or 2D array */
cso_hash_erase(us->u.hash, cso_hash_find(us->u.hash, (ps->u.tex.first_layer << 8) | ps->u.tex.level));
}
else
us->u.array[ps->u.tex.level] = 0;
}
 
void
util_surfaces_destroy(struct util_surfaces *us, struct pipe_resource *pt, void (*destroy_surface) (struct pipe_surface *))
{
if(pt->target == PIPE_TEXTURE_3D || pt->target == PIPE_TEXTURE_CUBE)
{ /* or 2D array */
if(us->u.hash)
{
struct cso_hash_iter iter;
iter = cso_hash_first_node(us->u.hash);
while (!cso_hash_iter_is_null(iter)) {
destroy_surface(cso_hash_iter_data(iter));
iter = cso_hash_iter_next(iter);
}
 
cso_hash_delete(us->u.hash);
us->u.hash = NULL;
}
}
else
{
if(us->u.array)
{
unsigned i;
for(i = 0; i <= pt->last_level; ++i)
{
struct pipe_surface *ps = us->u.array[i];
if(ps)
destroy_surface(ps);
}
FREE(us->u.array);
us->u.array = NULL;
}
}
}
/drivers/video/Gallium/auxiliary/util/u_surfaces.h
0,0 → 1,101
/**************************************************************************
*
* Copyright 2010 Luca Barbieri
*
* 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, sublicense, 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 NONINFRINGEMENT.
* IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
*
**************************************************************************/
 
#ifndef U_SURFACES_H_
#define U_SURFACES_H_
 
#include "pipe/p_compiler.h"
#include "pipe/p_state.h"
#include "util/u_atomic.h"
#include "cso_cache/cso_hash.h"
 
struct util_surfaces
{
union
{
struct cso_hash *hash;
struct pipe_surface **array;
void* pv;
} u;
};
 
/* Return value indicates if the pipe surface result is new */
boolean
util_surfaces_do_get(struct util_surfaces *us, unsigned surface_struct_size,
struct pipe_context *ctx, struct pipe_resource *pt,
unsigned level, unsigned layer,
struct pipe_surface **res);
 
/* fast inline path for the very common case */
static INLINE boolean
util_surfaces_get(struct util_surfaces *us, unsigned surface_struct_size,
struct pipe_context *ctx, struct pipe_resource *pt,
unsigned level, unsigned layer,
struct pipe_surface **res)
{
if(likely((pt->target == PIPE_TEXTURE_2D || pt->target == PIPE_TEXTURE_RECT) && us->u.array))
{
struct pipe_surface *ps = us->u.array[level];
if(ps && ps->context == ctx)
{
p_atomic_inc(&ps->reference.count);
*res = ps;
return FALSE;
}
}
 
return util_surfaces_do_get(us, surface_struct_size, ctx, pt, level, layer, res);
}
 
static INLINE struct pipe_surface *
util_surfaces_peek(struct util_surfaces *us, struct pipe_resource *pt, unsigned level, unsigned layer)
{
if(!us->u.pv)
return 0;
 
if(unlikely(pt->target == PIPE_TEXTURE_3D || pt->target == PIPE_TEXTURE_CUBE))
return cso_hash_iter_data(cso_hash_find(us->u.hash, (layer << 8) | level));
else
return us->u.array[level];
}
 
void util_surfaces_do_detach(struct util_surfaces *us, struct pipe_surface *ps);
 
static INLINE void
util_surfaces_detach(struct util_surfaces *us, struct pipe_surface *ps)
{
if(likely(ps->texture->target == PIPE_TEXTURE_2D || ps->texture->target == PIPE_TEXTURE_RECT))
{
us->u.array[ps->u.tex.level] = 0;
return;
}
 
util_surfaces_do_detach(us, ps);
}
 
void util_surfaces_destroy(struct util_surfaces *us, struct pipe_resource *pt, void (*destroy_surface) (struct pipe_surface *));
 
#endif
/drivers/video/Gallium/auxiliary/util/u_texture.c
0,0 → 1,103
/**************************************************************************
*
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
* Copyright 2008 VMware, Inc. All rights reserved.
* Copyright 2009 Marek Olšák <maraeo@gmail.com>
*
* 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
* Texture mapping utility functions.
*
* @author Brian Paul
* Marek Olšák
*/
 
#include "pipe/p_defines.h"
 
#include "util/u_debug.h"
#include "util/u_texture.h"
 
void util_map_texcoords2d_onto_cubemap(unsigned face,
const float *in_st, unsigned in_stride,
float *out_str, unsigned out_stride)
{
int i;
float rx, ry, rz;
 
/* loop over quad verts */
for (i = 0; i < 4; i++) {
/* Compute sc = +/-scale and tc = +/-scale.
* Not +/-1 to avoid cube face selection ambiguity near the edges,
* though that can still sometimes happen with this scale factor...
*/
const float scale = 0.9999f;
const float sc = (2 * in_st[0] - 1) * scale;
const float tc = (2 * in_st[1] - 1) * scale;
 
switch (face) {
case PIPE_TEX_FACE_POS_X:
rx = 1;
ry = -tc;
rz = -sc;
break;
case PIPE_TEX_FACE_NEG_X:
rx = -1;
ry = -tc;
rz = sc;
break;
case PIPE_TEX_FACE_POS_Y:
rx = sc;
ry = 1;
rz = tc;
break;
case PIPE_TEX_FACE_NEG_Y:
rx = sc;
ry = -1;
rz = -tc;
break;
case PIPE_TEX_FACE_POS_Z:
rx = sc;
ry = -tc;
rz = 1;
break;
case PIPE_TEX_FACE_NEG_Z:
rx = -sc;
ry = -tc;
rz = -1;
break;
default:
rx = ry = rz = 0;
assert(0);
}
 
out_str[0] = rx; /*s*/
out_str[1] = ry; /*t*/
out_str[2] = rz; /*r*/
 
in_st += in_stride;
out_str += out_stride;
}
}
/drivers/video/Gallium/auxiliary/util/u_texture.h
0,0 → 1,54
/**************************************************************************
*
* Copyright 2009 Marek Olšák <maraeo@gmail.com>
*
* 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.
*
**************************************************************************/
 
#ifndef U_TEXTURE_H
#define U_TEXTURE_H
 
#ifdef __cplusplus
extern "C" {
#endif
 
/**
* Convert 2D texture coordinates of 4 vertices into cubemap coordinates
* in the given face.
* Coordinates must be in the range [0,1].
*
* \param face Cubemap face.
* \param in_st 4 pairs of 2D texture coordinates to convert.
* \param in_stride Stride of in_st in floats.
* \param out_str STR cubemap texture coordinates to compute.
* \param out_stride Stride of out_str in floats.
*/
void util_map_texcoords2d_onto_cubemap(unsigned face,
const float *in_st, unsigned in_stride,
float *out_str, unsigned out_stride);
 
 
#ifdef __cplusplus
}
#endif
 
#endif
/drivers/video/Gallium/auxiliary/util/u_tile.c
0,0 → 1,895
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/**
* RGBA/float tile get/put functions.
* Usable both by drivers and state trackers.
*/
 
 
#include "pipe/p_defines.h"
#include "util/u_inlines.h"
 
#include "util/u_format.h"
#include "util/u_math.h"
#include "util/u_memory.h"
#include "util/u_rect.h"
#include "util/u_tile.h"
 
 
/**
* Move raw block of pixels from transfer object to user memory.
*/
void
pipe_get_tile_raw(struct pipe_transfer *pt,
const void *src,
uint x, uint y, uint w, uint h,
void *dst, int dst_stride)
{
if (dst_stride == 0)
dst_stride = util_format_get_stride(pt->resource->format, w);
 
if (u_clip_tile(x, y, &w, &h, &pt->box))
return;
 
util_copy_rect(dst, pt->resource->format, dst_stride, 0, 0, w, h, src, pt->stride, x, y);
}
 
 
/**
* Move raw block of pixels from user memory to transfer object.
*/
void
pipe_put_tile_raw(struct pipe_transfer *pt,
void *dst,
uint x, uint y, uint w, uint h,
const void *src, int src_stride)
{
enum pipe_format format = pt->resource->format;
 
if (src_stride == 0)
src_stride = util_format_get_stride(format, w);
 
if (u_clip_tile(x, y, &w, &h, &pt->box))
return;
 
util_copy_rect(dst, format, pt->stride, x, y, w, h, src, src_stride, 0, 0);
}
 
 
 
 
/** Convert short in [-32768,32767] to GLfloat in [-1.0,1.0] */
#define SHORT_TO_FLOAT(S) ((2.0F * (S) + 1.0F) * (1.0F/65535.0F))
 
#define UNCLAMPED_FLOAT_TO_SHORT(us, f) \
us = ( (short) ( CLAMP((f), -1.0, 1.0) * 32767.0F) )
 
 
 
/*** PIPE_FORMAT_Z16_UNORM ***/
 
/**
* Return each Z value as four floats in [0,1].
*/
static void
z16_get_tile_rgba(const ushort *src,
unsigned w, unsigned h,
float *p,
unsigned dst_stride)
{
const float scale = 1.0f / 65535.0f;
unsigned i, j;
 
for (i = 0; i < h; i++) {
float *pRow = p;
for (j = 0; j < w; j++, pRow += 4) {
pRow[0] =
pRow[1] =
pRow[2] =
pRow[3] = *src++ * scale;
}
p += dst_stride;
}
}
 
 
 
 
/*** PIPE_FORMAT_Z32_UNORM ***/
 
/**
* Return each Z value as four floats in [0,1].
*/
static void
z32_get_tile_rgba(const unsigned *src,
unsigned w, unsigned h,
float *p,
unsigned dst_stride)
{
const double scale = 1.0 / (double) 0xffffffff;
unsigned i, j;
 
for (i = 0; i < h; i++) {
float *pRow = p;
for (j = 0; j < w; j++, pRow += 4) {
pRow[0] =
pRow[1] =
pRow[2] =
pRow[3] = (float) (*src++ * scale);
}
p += dst_stride;
}
}
 
 
/*** PIPE_FORMAT_Z24_UNORM_S8_UINT ***/
 
/**
* Return Z component as four float in [0,1]. Stencil part ignored.
*/
static void
s8z24_get_tile_rgba(const unsigned *src,
unsigned w, unsigned h,
float *p,
unsigned dst_stride)
{
const double scale = 1.0 / ((1 << 24) - 1);
unsigned i, j;
 
for (i = 0; i < h; i++) {
float *pRow = p;
for (j = 0; j < w; j++, pRow += 4) {
pRow[0] =
pRow[1] =
pRow[2] =
pRow[3] = (float) (scale * (*src++ & 0xffffff));
}
p += dst_stride;
}
}
 
 
/*** PIPE_FORMAT_S8_UINT_Z24_UNORM ***/
 
/**
* Return Z component as four float in [0,1]. Stencil part ignored.
*/
static void
z24s8_get_tile_rgba(const unsigned *src,
unsigned w, unsigned h,
float *p,
unsigned dst_stride)
{
const double scale = 1.0 / ((1 << 24) - 1);
unsigned i, j;
 
for (i = 0; i < h; i++) {
float *pRow = p;
for (j = 0; j < w; j++, pRow += 4) {
pRow[0] =
pRow[1] =
pRow[2] =
pRow[3] = (float) (scale * (*src++ >> 8));
}
p += dst_stride;
}
}
 
/*** PIPE_FORMAT_S8X24_UINT ***/
 
/**
* Return S component as four uint32_t in [0..255]. Z part ignored.
*/
static void
s8x24_get_tile_rgba(const unsigned *src,
unsigned w, unsigned h,
float *p,
unsigned dst_stride)
{
unsigned i, j;
 
for (i = 0; i < h; i++) {
float *pRow = p;
 
for (j = 0; j < w; j++, pRow += 4) {
pRow[0] =
pRow[1] =
pRow[2] =
pRow[3] = (float)((*src++ >> 24) & 0xff);
}
 
p += dst_stride;
}
}
 
/*** PIPE_FORMAT_X24S8_UINT ***/
 
/**
* Return S component as four uint32_t in [0..255]. Z part ignored.
*/
static void
x24s8_get_tile_rgba(const unsigned *src,
unsigned w, unsigned h,
float *p,
unsigned dst_stride)
{
unsigned i, j;
 
for (i = 0; i < h; i++) {
float *pRow = p;
for (j = 0; j < w; j++, pRow += 4) {
pRow[0] =
pRow[1] =
pRow[2] =
pRow[3] = (float)(*src++ & 0xff);
}
p += dst_stride;
}
}
 
 
/**
* Return S component as four uint32_t in [0..255]. Z part ignored.
*/
static void
s8_get_tile_rgba(const unsigned char *src,
unsigned w, unsigned h,
float *p,
unsigned dst_stride)
{
unsigned i, j;
 
for (i = 0; i < h; i++) {
float *pRow = p;
for (j = 0; j < w; j++, pRow += 4) {
pRow[0] =
pRow[1] =
pRow[2] =
pRow[3] = (float)(*src++ & 0xff);
}
p += dst_stride;
}
}
 
/*** PIPE_FORMAT_Z32_FLOAT ***/
 
/**
* Return each Z value as four floats in [0,1].
*/
static void
z32f_get_tile_rgba(const float *src,
unsigned w, unsigned h,
float *p,
unsigned dst_stride)
{
unsigned i, j;
 
for (i = 0; i < h; i++) {
float *pRow = p;
for (j = 0; j < w; j++, pRow += 4) {
pRow[0] =
pRow[1] =
pRow[2] =
pRow[3] = *src++;
}
p += dst_stride;
}
}
 
/*** PIPE_FORMAT_Z32_FLOAT_S8X24_UINT ***/
 
/**
* Return each Z value as four floats in [0,1].
*/
static void
z32f_x24s8_get_tile_rgba(const float *src,
unsigned w, unsigned h,
float *p,
unsigned dst_stride)
{
unsigned i, j;
 
for (i = 0; i < h; i++) {
float *pRow = p;
for (j = 0; j < w; j++, pRow += 4) {
pRow[0] =
pRow[1] =
pRow[2] =
pRow[3] = *src;
src += 2;
}
p += dst_stride;
}
}
 
/*** PIPE_FORMAT_X32_S8X24_UINT ***/
 
/**
* Return S component as four uint32_t in [0..255]. Z part ignored.
*/
static void
x32_s8_get_tile_rgba(const unsigned *src,
unsigned w, unsigned h,
float *p,
unsigned dst_stride)
{
unsigned i, j;
 
for (i = 0; i < h; i++) {
float *pRow = p;
for (j = 0; j < w; j++, pRow += 4) {
src++;
pRow[0] =
pRow[1] =
pRow[2] =
pRow[3] = (float)(*src++ & 0xff);
}
p += dst_stride;
}
}
 
void
pipe_tile_raw_to_rgba(enum pipe_format format,
const void *src,
uint w, uint h,
float *dst, unsigned dst_stride)
{
switch (format) {
case PIPE_FORMAT_Z16_UNORM:
z16_get_tile_rgba((ushort *) src, w, h, dst, dst_stride);
break;
case PIPE_FORMAT_Z32_UNORM:
z32_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride);
break;
case PIPE_FORMAT_Z24_UNORM_S8_UINT:
case PIPE_FORMAT_Z24X8_UNORM:
s8z24_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride);
break;
case PIPE_FORMAT_S8_UINT:
s8_get_tile_rgba((unsigned char *) src, w, h, dst, dst_stride);
break;
case PIPE_FORMAT_X24S8_UINT:
s8x24_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride);
break;
case PIPE_FORMAT_S8_UINT_Z24_UNORM:
case PIPE_FORMAT_X8Z24_UNORM:
z24s8_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride);
break;
case PIPE_FORMAT_S8X24_UINT:
x24s8_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride);
break;
case PIPE_FORMAT_Z32_FLOAT:
z32f_get_tile_rgba((float *) src, w, h, dst, dst_stride);
break;
case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
z32f_x24s8_get_tile_rgba((float *) src, w, h, dst, dst_stride);
break;
case PIPE_FORMAT_X32_S8X24_UINT:
x32_s8_get_tile_rgba((unsigned *) src, w, h, dst, dst_stride);
break;
default:
util_format_read_4f(format,
dst, dst_stride * sizeof(float),
src, util_format_get_stride(format, w),
0, 0, w, h);
}
}
 
void
pipe_tile_raw_to_unsigned(enum pipe_format format,
const void *src,
uint w, uint h,
unsigned *dst, unsigned dst_stride)
{
util_format_read_4ui(format,
dst, dst_stride * sizeof(float),
src, util_format_get_stride(format, w),
0, 0, w, h);
}
 
void
pipe_tile_raw_to_signed(enum pipe_format format,
void *src,
uint w, uint h,
int *dst, unsigned dst_stride)
{
util_format_read_4i(format,
dst, dst_stride * sizeof(float),
src, util_format_get_stride(format, w),
0, 0, w, h);
}
 
void
pipe_get_tile_rgba(struct pipe_transfer *pt,
const void *src,
uint x, uint y, uint w, uint h,
float *p)
{
pipe_get_tile_rgba_format(pt, src, x, y, w, h, pt->resource->format, p);
}
 
 
void
pipe_get_tile_rgba_format(struct pipe_transfer *pt,
const void *src,
uint x, uint y, uint w, uint h,
enum pipe_format format,
float *p)
{
unsigned dst_stride = w * 4;
void *packed;
 
if (u_clip_tile(x, y, &w, &h, &pt->box)) {
return;
}
 
packed = MALLOC(util_format_get_nblocks(format, w, h) * util_format_get_blocksize(format));
if (!packed) {
return;
}
 
if (format == PIPE_FORMAT_UYVY || format == PIPE_FORMAT_YUYV) {
assert((x & 1) == 0);
}
 
pipe_get_tile_raw(pt, src, x, y, w, h, packed, 0);
 
pipe_tile_raw_to_rgba(format, packed, w, h, p, dst_stride);
 
FREE(packed);
}
 
 
void
pipe_put_tile_rgba(struct pipe_transfer *pt,
void *dst,
uint x, uint y, uint w, uint h,
const float *p)
{
pipe_put_tile_rgba_format(pt, dst, x, y, w, h, pt->resource->format, p);
}
 
 
void
pipe_put_tile_rgba_format(struct pipe_transfer *pt,
void *dst,
uint x, uint y, uint w, uint h,
enum pipe_format format,
const float *p)
{
unsigned src_stride = w * 4;
void *packed;
 
if (u_clip_tile(x, y, &w, &h, &pt->box))
return;
 
packed = MALLOC(util_format_get_nblocks(format, w, h) * util_format_get_blocksize(format));
 
if (!packed)
return;
 
switch (format) {
case PIPE_FORMAT_Z16_UNORM:
/*z16_put_tile_rgba((ushort *) packed, w, h, p, src_stride);*/
break;
case PIPE_FORMAT_Z32_UNORM:
/*z32_put_tile_rgba((unsigned *) packed, w, h, p, src_stride);*/
break;
case PIPE_FORMAT_Z24_UNORM_S8_UINT:
case PIPE_FORMAT_Z24X8_UNORM:
/*s8z24_put_tile_rgba((unsigned *) packed, w, h, p, src_stride);*/
break;
case PIPE_FORMAT_S8_UINT_Z24_UNORM:
case PIPE_FORMAT_X8Z24_UNORM:
/*z24s8_put_tile_rgba((unsigned *) packed, w, h, p, src_stride);*/
break;
case PIPE_FORMAT_Z32_FLOAT:
/*z32f_put_tile_rgba((unsigned *) packed, w, h, p, src_stride);*/
break;
case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
/*z32f_s8x24_put_tile_rgba((unsigned *) packed, w, h, p, src_stride);*/
break;
default:
util_format_write_4f(format,
p, src_stride * sizeof(float),
packed, util_format_get_stride(format, w),
0, 0, w, h);
}
 
pipe_put_tile_raw(pt, dst, x, y, w, h, packed, 0);
 
FREE(packed);
}
 
void
pipe_put_tile_i_format(struct pipe_transfer *pt,
void *dst,
uint x, uint y, uint w, uint h,
enum pipe_format format,
const int *p)
{
unsigned src_stride = w * 4;
void *packed;
 
if (u_clip_tile(x, y, &w, &h, &pt->box))
return;
 
packed = MALLOC(util_format_get_nblocks(format, w, h) * util_format_get_blocksize(format));
 
if (!packed)
return;
 
util_format_write_4i(format,
p, src_stride * sizeof(float),
packed, util_format_get_stride(format, w),
0, 0, w, h);
 
pipe_put_tile_raw(pt, dst, x, y, w, h, packed, 0);
 
FREE(packed);
}
 
void
pipe_put_tile_ui_format(struct pipe_transfer *pt,
void *dst,
uint x, uint y, uint w, uint h,
enum pipe_format format,
const unsigned int *p)
{
unsigned src_stride = w * 4;
void *packed;
 
if (u_clip_tile(x, y, &w, &h, &pt->box))
return;
 
packed = MALLOC(util_format_get_nblocks(format, w, h) * util_format_get_blocksize(format));
 
if (!packed)
return;
 
util_format_write_4ui(format,
p, src_stride * sizeof(float),
packed, util_format_get_stride(format, w),
0, 0, w, h);
 
pipe_put_tile_raw(pt, dst, x, y, w, h, packed, 0);
 
FREE(packed);
}
 
/**
* Get a block of Z values, converted to 32-bit range.
*/
void
pipe_get_tile_z(struct pipe_transfer *pt,
const void *src,
uint x, uint y, uint w, uint h,
uint *z)
{
const uint dstStride = w;
const ubyte *map = src;
uint *pDest = z;
uint i, j;
enum pipe_format format = pt->resource->format;
 
if (u_clip_tile(x, y, &w, &h, &pt->box))
return;
 
switch (format) {
case PIPE_FORMAT_Z32_UNORM:
{
const uint *ptrc
= (const uint *)(map + y * pt->stride + x*4);
for (i = 0; i < h; i++) {
memcpy(pDest, ptrc, 4 * w);
pDest += dstStride;
ptrc += pt->stride/4;
}
}
break;
case PIPE_FORMAT_Z24_UNORM_S8_UINT:
case PIPE_FORMAT_Z24X8_UNORM:
{
const uint *ptrc
= (const uint *)(map + y * pt->stride + x*4);
for (i = 0; i < h; i++) {
for (j = 0; j < w; j++) {
/* convert 24-bit Z to 32-bit Z */
pDest[j] = (ptrc[j] << 8) | ((ptrc[j] >> 16) & 0xff);
}
pDest += dstStride;
ptrc += pt->stride/4;
}
}
break;
case PIPE_FORMAT_S8_UINT_Z24_UNORM:
case PIPE_FORMAT_X8Z24_UNORM:
{
const uint *ptrc
= (const uint *)(map + y * pt->stride + x*4);
for (i = 0; i < h; i++) {
for (j = 0; j < w; j++) {
/* convert 24-bit Z to 32-bit Z */
pDest[j] = (ptrc[j] & 0xffffff00) | ((ptrc[j] >> 24) & 0xff);
}
pDest += dstStride;
ptrc += pt->stride/4;
}
}
break;
case PIPE_FORMAT_Z16_UNORM:
{
const ushort *ptrc
= (const ushort *)(map + y * pt->stride + x*2);
for (i = 0; i < h; i++) {
for (j = 0; j < w; j++) {
/* convert 16-bit Z to 32-bit Z */
pDest[j] = (ptrc[j] << 16) | ptrc[j];
}
pDest += dstStride;
ptrc += pt->stride/2;
}
}
break;
case PIPE_FORMAT_Z32_FLOAT:
{
const float *ptrc = (const float *)(map + y * pt->stride + x*4);
for (i = 0; i < h; i++) {
for (j = 0; j < w; j++) {
/* convert float Z to 32-bit Z */
if (ptrc[j] <= 0.0) {
pDest[j] = 0;
}
else if (ptrc[j] >= 1.0) {
pDest[j] = 0xffffffff;
}
else {
double z = ptrc[j] * 0xffffffff;
pDest[j] = (uint) z;
}
}
pDest += dstStride;
ptrc += pt->stride/4;
}
}
break;
case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
{
const float *ptrc = (const float *)(map + y * pt->stride + x*8);
for (i = 0; i < h; i++) {
for (j = 0; j < w; j++) {
/* convert float Z to 32-bit Z */
if (ptrc[j] <= 0.0) {
pDest[j*2] = 0;
}
else if (ptrc[j] >= 1.0) {
pDest[j*2] = 0xffffffff;
}
else {
double z = ptrc[j] * 0xffffffff;
pDest[j*2] = (uint) z;
}
}
pDest += dstStride;
ptrc += pt->stride/4;
}
}
break;
default:
assert(0);
}
}
 
 
void
pipe_put_tile_z(struct pipe_transfer *pt,
void *dst,
uint x, uint y, uint w, uint h,
const uint *zSrc)
{
const uint srcStride = w;
const uint *ptrc = zSrc;
ubyte *map = dst;
uint i, j;
enum pipe_format format = pt->resource->format;
 
if (u_clip_tile(x, y, &w, &h, &pt->box))
return;
 
switch (format) {
case PIPE_FORMAT_Z32_UNORM:
{
uint *pDest = (uint *) (map + y * pt->stride + x*4);
for (i = 0; i < h; i++) {
memcpy(pDest, ptrc, 4 * w);
pDest += pt->stride/4;
ptrc += srcStride;
}
}
break;
case PIPE_FORMAT_Z24_UNORM_S8_UINT:
{
uint *pDest = (uint *) (map + y * pt->stride + x*4);
/*assert((pt->usage & PIPE_TRANSFER_READ_WRITE) == PIPE_TRANSFER_READ_WRITE);*/
for (i = 0; i < h; i++) {
for (j = 0; j < w; j++) {
/* convert 32-bit Z to 24-bit Z, preserve stencil */
pDest[j] = (pDest[j] & 0xff000000) | ptrc[j] >> 8;
}
pDest += pt->stride/4;
ptrc += srcStride;
}
}
break;
case PIPE_FORMAT_Z24X8_UNORM:
{
uint *pDest = (uint *) (map + y * pt->stride + x*4);
for (i = 0; i < h; i++) {
for (j = 0; j < w; j++) {
/* convert 32-bit Z to 24-bit Z (0 stencil) */
pDest[j] = ptrc[j] >> 8;
}
pDest += pt->stride/4;
ptrc += srcStride;
}
}
break;
case PIPE_FORMAT_S8_UINT_Z24_UNORM:
{
uint *pDest = (uint *) (map + y * pt->stride + x*4);
/*assert((pt->usage & PIPE_TRANSFER_READ_WRITE) == PIPE_TRANSFER_READ_WRITE);*/
for (i = 0; i < h; i++) {
for (j = 0; j < w; j++) {
/* convert 32-bit Z to 24-bit Z, preserve stencil */
pDest[j] = (pDest[j] & 0xff) | (ptrc[j] & 0xffffff00);
}
pDest += pt->stride/4;
ptrc += srcStride;
}
}
break;
case PIPE_FORMAT_X8Z24_UNORM:
{
uint *pDest = (uint *) (map + y * pt->stride + x*4);
for (i = 0; i < h; i++) {
for (j = 0; j < w; j++) {
/* convert 32-bit Z to 24-bit Z (0 stencil) */
pDest[j] = ptrc[j] & 0xffffff00;
}
pDest += pt->stride/4;
ptrc += srcStride;
}
}
break;
case PIPE_FORMAT_Z16_UNORM:
{
ushort *pDest = (ushort *) (map + y * pt->stride + x*2);
for (i = 0; i < h; i++) {
for (j = 0; j < w; j++) {
/* convert 32-bit Z to 16-bit Z */
pDest[j] = ptrc[j] >> 16;
}
pDest += pt->stride/2;
ptrc += srcStride;
}
}
break;
case PIPE_FORMAT_Z32_FLOAT:
{
float *pDest = (float *) (map + y * pt->stride + x*4);
for (i = 0; i < h; i++) {
for (j = 0; j < w; j++) {
/* convert 32-bit integer Z to float Z */
const double scale = 1.0 / 0xffffffffU;
pDest[j] = (float) (ptrc[j] * scale);
}
pDest += pt->stride/4;
ptrc += srcStride;
}
}
break;
case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
{
float *pDest = (float *) (map + y * pt->stride + x*8);
for (i = 0; i < h; i++) {
for (j = 0; j < w; j++) {
/* convert 32-bit integer Z to float Z */
const double scale = 1.0 / 0xffffffffU;
pDest[j*2] = (float) (ptrc[j] * scale);
}
pDest += pt->stride/4;
ptrc += srcStride;
}
}
break;
default:
assert(0);
}
}
 
 
void
pipe_get_tile_ui_format(struct pipe_transfer *pt,
const void *src,
uint x, uint y, uint w, uint h,
enum pipe_format format,
unsigned int *p)
{
unsigned dst_stride = w * 4;
void *packed;
 
if (u_clip_tile(x, y, &w, &h, &pt->box)) {
return;
}
 
packed = MALLOC(util_format_get_nblocks(format, w, h) * util_format_get_blocksize(format));
if (!packed) {
return;
}
 
if (format == PIPE_FORMAT_UYVY || format == PIPE_FORMAT_YUYV) {
assert((x & 1) == 0);
}
 
pipe_get_tile_raw(pt, src, x, y, w, h, packed, 0);
 
pipe_tile_raw_to_unsigned(format, packed, w, h, p, dst_stride);
 
FREE(packed);
}
 
 
void
pipe_get_tile_i_format(struct pipe_transfer *pt,
const void *src,
uint x, uint y, uint w, uint h,
enum pipe_format format,
int *p)
{
unsigned dst_stride = w * 4;
void *packed;
 
if (u_clip_tile(x, y, &w, &h, &pt->box)) {
return;
}
 
packed = MALLOC(util_format_get_nblocks(format, w, h) * util_format_get_blocksize(format));
if (!packed) {
return;
}
 
if (format == PIPE_FORMAT_UYVY || format == PIPE_FORMAT_YUYV) {
assert((x & 1) == 0);
}
 
pipe_get_tile_raw(pt, src, x, y, w, h, packed, 0);
 
pipe_tile_raw_to_signed(format, packed, w, h, p, dst_stride);
 
FREE(packed);
}
/drivers/video/Gallium/auxiliary/util/u_tile.h
0,0 → 1,165
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
#ifndef P_TILE_H
#define P_TILE_H
 
#include "pipe/p_compiler.h"
#include "pipe/p_format.h"
#include "pipe/p_state.h"
 
struct pipe_context;
struct pipe_transfer;
 
/**
* Clip tile against transfer dims.
*
* XXX: this only clips width and height!
*
* \return TRUE if tile is totally clipped, FALSE otherwise
*/
static INLINE boolean
u_clip_tile(uint x, uint y, uint *w, uint *h, const struct pipe_box *box)
{
if ((int) x >= box->width)
return TRUE;
if ((int) y >= box->height)
return TRUE;
if ((int) (x + *w) > box->width)
*w = box->width - x;
if ((int) (y + *h) > box->height)
*h = box->height - y;
return FALSE;
}
 
#ifdef __cplusplus
extern "C" {
#endif
 
void
pipe_get_tile_raw(struct pipe_transfer *pt,
const void *src,
uint x, uint y, uint w, uint h,
void *p, int dst_stride);
 
void
pipe_put_tile_raw(struct pipe_transfer *pt,
void *dst,
uint x, uint y, uint w, uint h,
const void *p, int src_stride);
 
 
void
pipe_get_tile_rgba(struct pipe_transfer *pt,
const void *src,
uint x, uint y, uint w, uint h,
float *p);
 
void
pipe_get_tile_rgba_format(struct pipe_transfer *pt,
const void *src,
uint x, uint y, uint w, uint h,
enum pipe_format format,
float *p);
 
void
pipe_put_tile_rgba(struct pipe_transfer *pt,
void *dst,
uint x, uint y, uint w, uint h,
const float *p);
 
void
pipe_put_tile_rgba_format(struct pipe_transfer *pt,
void *dst,
uint x, uint y, uint w, uint h,
enum pipe_format format,
const float *p);
 
 
void
pipe_get_tile_z(struct pipe_transfer *pt,
const void *src,
uint x, uint y, uint w, uint h,
uint *z);
 
void
pipe_put_tile_z(struct pipe_transfer *pt,
void *dst,
uint x, uint y, uint w, uint h,
const uint *z);
 
void
pipe_tile_raw_to_rgba(enum pipe_format format,
const void *src,
uint w, uint h,
float *dst, unsigned dst_stride);
 
void
pipe_tile_raw_to_unsigned(enum pipe_format format,
const void *src,
uint w, uint h,
unsigned *dst, unsigned dst_stride);
 
void
pipe_tile_raw_to_signed(enum pipe_format format,
void *src,
uint w, uint h,
int *dst, unsigned dst_stride);
 
void
pipe_get_tile_ui_format(struct pipe_transfer *pt,
const void *src,
uint x, uint y, uint w, uint h,
enum pipe_format format,
unsigned int *p);
 
void
pipe_get_tile_i_format(struct pipe_transfer *pt,
const void *src,
uint x, uint y, uint w, uint h,
enum pipe_format format,
int *p);
 
void
pipe_put_tile_ui_format(struct pipe_transfer *pt,
void *dst,
uint x, uint y, uint w, uint h,
enum pipe_format format,
const unsigned *p);
 
void
pipe_put_tile_i_format(struct pipe_transfer *pt,
void *dst,
uint x, uint y, uint w, uint h,
enum pipe_format format,
const int *p);
 
#ifdef __cplusplus
}
#endif
 
#endif
/drivers/video/Gallium/auxiliary/util/u_time.h
0,0 → 1,150
/**************************************************************************
*
* 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
* OS independent time-manipulation functions.
*
* @author Jose Fonseca <jrfonseca@tungstengraphics.com>
*/
 
#ifndef U_TIME_H_
#define U_TIME_H_
 
 
#include "pipe/p_config.h"
 
#include "os/os_time.h"
 
#include "pipe/p_compiler.h"
 
 
#ifdef __cplusplus
extern "C" {
#endif
 
 
/**
* Time abstraction.
*
* Do not access this structure directly. Use the provided function instead.
*/
struct util_time
{
int64_t counter;
};
 
PIPE_DEPRECATED
static INLINE void
util_time_get(struct util_time *t)
{
t->counter = os_time_get();
}
 
 
/**
* Return t2 = t1 + usecs
*/
PIPE_DEPRECATED
static INLINE void
util_time_add(const struct util_time *t1,
int64_t usecs,
struct util_time *t2)
{
t2->counter = t1->counter + usecs;
}
 
 
/**
* Return difference between times, in microseconds
*/
PIPE_DEPRECATED
static INLINE int64_t
util_time_diff(const struct util_time *t1,
const struct util_time *t2)
{
return t2->counter - t1->counter;
}
 
 
/**
* Compare two time values.
*
* Not publicly available because it does not take in account wrap-arounds.
* Use util_time_timeout instead.
*/
static INLINE int
_util_time_compare(const struct util_time *t1,
const struct util_time *t2)
{
if (t1->counter < t2->counter)
return -1;
else if(t1->counter > t2->counter)
return 1;
else
return 0;
}
 
 
/**
* Returns non-zero when the timeout expires.
*/
PIPE_DEPRECATED
static INLINE boolean
util_time_timeout(const struct util_time *start,
const struct util_time *end,
const struct util_time *curr)
{
return os_time_timeout(start->counter, end->counter, curr->counter);
}
 
 
/**
* Return current time in microseconds
*/
PIPE_DEPRECATED
static INLINE int64_t
util_time_micros(void)
{
return os_time_get();
}
 
 
PIPE_DEPRECATED
static INLINE void
util_time_sleep(int64_t usecs)
{
os_time_sleep(usecs);
}
 
 
#ifdef __cplusplus
}
#endif
 
#endif /* U_TIME_H_ */
/drivers/video/Gallium/auxiliary/util/u_transfer.c
0,0 → 1,163
#include "pipe/p_context.h"
#include "util/u_surface.h"
#include "util/u_inlines.h"
#include "util/u_transfer.h"
#include "util/u_memory.h"
 
/* One-shot transfer operation with data supplied in a user
* pointer. XXX: strides??
*/
void u_default_transfer_inline_write( struct pipe_context *pipe,
struct pipe_resource *resource,
unsigned level,
unsigned usage,
const struct pipe_box *box,
const void *data,
unsigned stride,
unsigned layer_stride)
{
struct pipe_transfer *transfer = NULL;
uint8_t *map = NULL;
 
assert(!(usage & PIPE_TRANSFER_READ));
 
/* the write flag is implicit by the nature of transfer_inline_write */
usage |= PIPE_TRANSFER_WRITE;
 
/* transfer_inline_write implicitly discards the rewritten buffer range */
/* XXX this looks very broken for non-buffer resources having more than one dim. */
if (box->x == 0 && box->width == resource->width0) {
usage |= PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE;
} else {
usage |= PIPE_TRANSFER_DISCARD_RANGE;
}
 
map = pipe->transfer_map(pipe,
resource,
level,
usage,
box, &transfer);
if (map == NULL)
return;
 
if (resource->target == PIPE_BUFFER) {
assert(box->height == 1);
assert(box->depth == 1);
 
memcpy(map, data, box->width);
}
else {
const uint8_t *src_data = data;
 
util_copy_box(map,
resource->format,
transfer->stride, /* bytes */
transfer->layer_stride, /* bytes */
0, 0, 0,
box->width,
box->height,
box->depth,
src_data,
stride, /* bytes */
layer_stride, /* bytes */
0, 0, 0);
}
 
pipe_transfer_unmap(pipe, transfer);
}
 
 
boolean u_default_resource_get_handle(struct pipe_screen *screen,
struct pipe_resource *resource,
struct winsys_handle *handle)
{
return FALSE;
}
 
 
 
void u_default_transfer_flush_region( struct pipe_context *pipe,
struct pipe_transfer *transfer,
const struct pipe_box *box)
{
/* This is a no-op implementation, nothing to do.
*/
}
 
void u_default_transfer_unmap( struct pipe_context *pipe,
struct pipe_transfer *transfer )
{
}
 
 
static INLINE struct u_resource *
u_resource( struct pipe_resource *res )
{
return (struct u_resource *)res;
}
 
boolean u_resource_get_handle_vtbl(struct pipe_screen *screen,
struct pipe_resource *resource,
struct winsys_handle *handle)
{
struct u_resource *ur = u_resource(resource);
return ur->vtbl->resource_get_handle(screen, resource, handle);
}
 
void u_resource_destroy_vtbl(struct pipe_screen *screen,
struct pipe_resource *resource)
{
struct u_resource *ur = u_resource(resource);
ur->vtbl->resource_destroy(screen, resource);
}
 
void *u_transfer_map_vtbl(struct pipe_context *context,
struct pipe_resource *resource,
unsigned level,
unsigned usage,
const struct pipe_box *box,
struct pipe_transfer **transfer)
{
struct u_resource *ur = u_resource(resource);
return ur->vtbl->transfer_map(context, resource, level, usage, box,
transfer);
}
 
void u_transfer_flush_region_vtbl( struct pipe_context *pipe,
struct pipe_transfer *transfer,
const struct pipe_box *box)
{
struct u_resource *ur = u_resource(transfer->resource);
ur->vtbl->transfer_flush_region(pipe, transfer, box);
}
 
void u_transfer_unmap_vtbl( struct pipe_context *pipe,
struct pipe_transfer *transfer )
{
struct u_resource *ur = u_resource(transfer->resource);
ur->vtbl->transfer_unmap(pipe, transfer);
}
 
void u_transfer_inline_write_vtbl( struct pipe_context *pipe,
struct pipe_resource *resource,
unsigned level,
unsigned usage,
const struct pipe_box *box,
const void *data,
unsigned stride,
unsigned layer_stride)
{
struct u_resource *ur = u_resource(resource);
ur->vtbl->transfer_inline_write(pipe,
resource,
level,
usage,
box,
data,
stride,
layer_stride);
}
 
 
 
 
/drivers/video/Gallium/auxiliary/util/u_transfer.h
0,0 → 1,109
 
#ifndef U_TRANSFER_H
#define U_TRANSFER_H
 
/* Fallback implementations for inline read/writes which just go back
* to the regular transfer behaviour.
*/
#include "pipe/p_state.h"
 
struct pipe_context;
struct winsys_handle;
 
boolean u_default_resource_get_handle(struct pipe_screen *screen,
struct pipe_resource *resource,
struct winsys_handle *handle);
 
void u_default_transfer_inline_write( struct pipe_context *pipe,
struct pipe_resource *resource,
unsigned level,
unsigned usage,
const struct pipe_box *box,
const void *data,
unsigned stride,
unsigned layer_stride);
 
void u_default_transfer_flush_region( struct pipe_context *pipe,
struct pipe_transfer *transfer,
const struct pipe_box *box);
 
void u_default_transfer_unmap( struct pipe_context *pipe,
struct pipe_transfer *transfer );
 
 
 
/* Useful helper to allow >1 implementation of resource functionality
* to exist in a single driver. This is intended to be transitionary!
*/
struct u_resource_vtbl {
 
boolean (*resource_get_handle)(struct pipe_screen *,
struct pipe_resource *tex,
struct winsys_handle *handle);
 
void (*resource_destroy)(struct pipe_screen *,
struct pipe_resource *pt);
 
void *(*transfer_map)(struct pipe_context *,
struct pipe_resource *resource,
unsigned level,
unsigned usage,
const struct pipe_box *,
struct pipe_transfer **);
 
 
void (*transfer_flush_region)( struct pipe_context *,
struct pipe_transfer *transfer,
const struct pipe_box *);
 
void (*transfer_unmap)( struct pipe_context *,
struct pipe_transfer *transfer );
 
void (*transfer_inline_write)( struct pipe_context *pipe,
struct pipe_resource *resource,
unsigned level,
unsigned usage,
const struct pipe_box *box,
const void *data,
unsigned stride,
unsigned layer_stride);
};
 
 
struct u_resource {
struct pipe_resource b;
const struct u_resource_vtbl *vtbl;
};
 
 
boolean u_resource_get_handle_vtbl(struct pipe_screen *screen,
struct pipe_resource *resource,
struct winsys_handle *handle);
 
void u_resource_destroy_vtbl(struct pipe_screen *screen,
struct pipe_resource *resource);
 
void *u_transfer_map_vtbl(struct pipe_context *context,
struct pipe_resource *resource,
unsigned level,
unsigned usage,
const struct pipe_box *box,
struct pipe_transfer **transfer);
 
void u_transfer_flush_region_vtbl( struct pipe_context *pipe,
struct pipe_transfer *transfer,
const struct pipe_box *box);
 
void u_transfer_unmap_vtbl( struct pipe_context *rm_ctx,
struct pipe_transfer *transfer );
 
void u_transfer_inline_write_vtbl( struct pipe_context *rm_ctx,
struct pipe_resource *resource,
unsigned level,
unsigned usage,
const struct pipe_box *box,
const void *data,
unsigned stride,
unsigned layer_stride);
 
#endif
/drivers/video/Gallium/auxiliary/util/u_upload_mgr.c
0,0 → 1,271
/**************************************************************************
*
* Copyright 2009 VMware, Inc.
* 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 VMWARE 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.
*
**************************************************************************/
 
/* Helper utility for uploading user buffers & other data, and
* coalescing small buffers into larger ones.
*/
 
#include "pipe/p_defines.h"
#include "util/u_inlines.h"
#include "pipe/p_context.h"
#include "util/u_memory.h"
#include "util/u_math.h"
 
#include "u_upload_mgr.h"
 
 
struct u_upload_mgr {
struct pipe_context *pipe;
 
unsigned default_size; /* Minimum size of the upload buffer, in bytes. */
unsigned alignment; /* Alignment of each sub-allocation. */
unsigned bind; /* Bitmask of PIPE_BIND_* flags. */
 
struct pipe_resource *buffer; /* Upload buffer. */
struct pipe_transfer *transfer; /* Transfer object for the upload buffer. */
uint8_t *map; /* Pointer to the mapped upload buffer. */
unsigned size; /* Actual size of the upload buffer. */
unsigned offset; /* Aligned offset to the upload buffer, pointing
* at the first unused byte. */
};
 
 
struct u_upload_mgr *u_upload_create( struct pipe_context *pipe,
unsigned default_size,
unsigned alignment,
unsigned bind )
{
struct u_upload_mgr *upload = CALLOC_STRUCT( u_upload_mgr );
if (!upload)
return NULL;
 
upload->pipe = pipe;
upload->default_size = default_size;
upload->alignment = alignment;
upload->bind = bind;
upload->buffer = NULL;
 
return upload;
}
 
void u_upload_unmap( struct u_upload_mgr *upload )
{
if (upload->transfer) {
struct pipe_box *box = &upload->transfer->box;
if ((int) upload->offset > box->x) {
 
pipe_buffer_flush_mapped_range(upload->pipe, upload->transfer,
box->x, upload->offset - box->x);
}
pipe_transfer_unmap(upload->pipe, upload->transfer);
upload->transfer = NULL;
upload->map = NULL;
}
}
 
/* Release old buffer.
*
* This must usually be called prior to firing the command stream
* which references the upload buffer, as many memory managers will
* cause subsequent maps of a fired buffer to wait.
*
* Can improve this with a change to pipe_buffer_write to use the
* DONT_WAIT bit, but for now, it's easiest just to grab a new buffer.
*/
void u_upload_flush( struct u_upload_mgr *upload )
{
/* Unmap and unreference the upload buffer. */
u_upload_unmap(upload);
pipe_resource_reference( &upload->buffer, NULL );
upload->size = 0;
}
 
 
void u_upload_destroy( struct u_upload_mgr *upload )
{
u_upload_flush( upload );
FREE( upload );
}
 
 
static enum pipe_error
u_upload_alloc_buffer( struct u_upload_mgr *upload,
unsigned min_size )
{
unsigned size;
 
/* Release the old buffer, if present:
*/
u_upload_flush( upload );
 
/* Allocate a new one:
*/
size = align(MAX2(upload->default_size, min_size), 4096);
 
upload->buffer = pipe_buffer_create( upload->pipe->screen,
upload->bind,
PIPE_USAGE_STREAM,
size );
if (upload->buffer == NULL) {
return PIPE_ERROR_OUT_OF_MEMORY;
}
 
/* Map the new buffer. */
upload->map = pipe_buffer_map_range(upload->pipe, upload->buffer,
0, size,
PIPE_TRANSFER_WRITE |
PIPE_TRANSFER_FLUSH_EXPLICIT,
&upload->transfer);
if (upload->map == NULL) {
upload->transfer = NULL;
upload->size = 0;
pipe_resource_reference(&upload->buffer, NULL);
return PIPE_ERROR_OUT_OF_MEMORY;
}
 
upload->size = size;
upload->offset = 0;
return PIPE_OK;
}
 
enum pipe_error u_upload_alloc( struct u_upload_mgr *upload,
unsigned min_out_offset,
unsigned size,
unsigned *out_offset,
struct pipe_resource **outbuf,
void **ptr )
{
unsigned alloc_size = align( size, upload->alignment );
unsigned alloc_offset = align(min_out_offset, upload->alignment);
unsigned offset;
 
/* Init these return values here in case we fail below to make
* sure the caller doesn't get garbage values.
*/
*out_offset = ~0;
pipe_resource_reference(outbuf, NULL);
*ptr = NULL;
 
/* Make sure we have enough space in the upload buffer
* for the sub-allocation. */
if (MAX2(upload->offset, alloc_offset) + alloc_size > upload->size) {
enum pipe_error ret = u_upload_alloc_buffer(upload,
alloc_offset + alloc_size);
if (ret != PIPE_OK)
return ret;
}
 
offset = MAX2(upload->offset, alloc_offset);
 
if (!upload->map) {
upload->map = pipe_buffer_map_range(upload->pipe, upload->buffer,
offset, upload->size - offset,
PIPE_TRANSFER_WRITE |
PIPE_TRANSFER_FLUSH_EXPLICIT |
PIPE_TRANSFER_UNSYNCHRONIZED,
&upload->transfer);
if (!upload->map) {
upload->transfer = NULL;
return PIPE_ERROR_OUT_OF_MEMORY;
}
 
upload->map -= offset;
}
 
assert(offset < upload->buffer->width0);
assert(offset + size <= upload->buffer->width0);
assert(size);
 
/* Emit the return values: */
*ptr = upload->map + offset;
pipe_resource_reference( outbuf, upload->buffer );
*out_offset = offset;
 
upload->offset = offset + alloc_size;
return PIPE_OK;
}
 
enum pipe_error u_upload_data( struct u_upload_mgr *upload,
unsigned min_out_offset,
unsigned size,
const void *data,
unsigned *out_offset,
struct pipe_resource **outbuf)
{
uint8_t *ptr;
enum pipe_error ret = u_upload_alloc(upload, min_out_offset, size,
out_offset, outbuf,
(void**)&ptr);
if (ret != PIPE_OK)
return ret;
 
memcpy(ptr, data, size);
return PIPE_OK;
}
 
 
/* As above, but upload the full contents of a buffer. Useful for
* uploading user buffers, avoids generating an explosion of GPU
* buffers if you have an app that does lots of small vertex buffer
* renders or DrawElements calls.
*/
enum pipe_error u_upload_buffer( struct u_upload_mgr *upload,
unsigned min_out_offset,
unsigned offset,
unsigned size,
struct pipe_resource *inbuf,
unsigned *out_offset,
struct pipe_resource **outbuf)
{
enum pipe_error ret = PIPE_OK;
struct pipe_transfer *transfer = NULL;
const char *map = NULL;
 
map = (const char *)pipe_buffer_map_range(upload->pipe,
inbuf,
offset, size,
PIPE_TRANSFER_READ,
&transfer);
 
if (map == NULL) {
return PIPE_ERROR_OUT_OF_MEMORY;
}
 
if (0)
debug_printf("upload ptr %p ofs %d sz %d\n", map, offset, size);
 
ret = u_upload_data( upload,
min_out_offset,
size,
map,
out_offset,
outbuf);
 
pipe_buffer_unmap( upload->pipe, transfer );
 
return ret;
}
/drivers/video/Gallium/auxiliary/util/u_upload_mgr.h
0,0 → 1,130
/**************************************************************************
*
* Copyright 2009 VMware, Inc.
* 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 VMWARE 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.
*
**************************************************************************/
 
/* Helper utility for uploading user buffers & other data, and
* coalescing small buffers into larger ones.
*/
 
#ifndef U_UPLOAD_MGR_H
#define U_UPLOAD_MGR_H
 
#include "pipe/p_compiler.h"
 
struct pipe_context;
struct pipe_resource;
 
 
/**
* Create the upload manager.
*
* \param pipe Pipe driver.
* \param default_size Minimum size of the upload buffer, in bytes.
* \param alignment Alignment of each suballocation in the upload buffer.
* \param bind Bitmask of PIPE_BIND_* flags.
*/
struct u_upload_mgr *u_upload_create( struct pipe_context *pipe,
unsigned default_size,
unsigned alignment,
unsigned bind );
 
/**
* Destroy the upload manager.
*/
void u_upload_destroy( struct u_upload_mgr *upload );
 
/**
* Unmap and release old upload buffer.
*
* This is like u_upload_unmap() except the upload buffer is released for
* recycling. This should be called on real hardware flushes on systems
* that don't support the PIPE_TRANSFER_UNSYNCHRONIZED flag, as otherwise
* the next u_upload_buffer will cause a sync on the buffer.
*/
void u_upload_flush( struct u_upload_mgr *upload );
 
/**
* Unmap upload buffer
*
* \param upload Upload manager
*
* This must usually be called prior to firing the command stream
* which references the upload buffer, as many memory managers either
* don't like firing a mapped buffer or cause subsequent maps of a
* fired buffer to wait.
*/
void u_upload_unmap( struct u_upload_mgr *upload );
 
/**
* Sub-allocate new memory from the upload buffer.
*
* \param upload Upload manager
* \param min_out_offset Minimum offset that should be returned in out_offset.
* \param size Size of the allocation.
* \param out_offset Pointer to where the new buffer offset will be returned.
* \param outbuf Pointer to where the upload buffer will be returned.
* \param ptr Pointer to the allocated memory that is returned.
*/
enum pipe_error u_upload_alloc( struct u_upload_mgr *upload,
unsigned min_out_offset,
unsigned size,
unsigned *out_offset,
struct pipe_resource **outbuf,
void **ptr );
 
 
/**
* Allocate and write data to the upload buffer.
*
* Same as u_upload_alloc, but in addition to that, it copies "data"
* to the pointer returned from u_upload_alloc.
*/
enum pipe_error u_upload_data( struct u_upload_mgr *upload,
unsigned min_out_offset,
unsigned size,
const void *data,
unsigned *out_offset,
struct pipe_resource **outbuf);
 
 
/**
* Allocate space in an upload buffer and copy an input buffer to it.
*
* Same as u_upload_data, except that the input data comes from a buffer
* instead of a user pointer.
*/
enum pipe_error u_upload_buffer( struct u_upload_mgr *upload,
unsigned min_out_offset,
unsigned offset,
unsigned size,
struct pipe_resource *inbuf,
unsigned *out_offset,
struct pipe_resource **outbuf);
 
 
 
#endif
 
/drivers/video/Gallium/auxiliary/util/u_vbuf.c
0,0 → 1,1295
/**************************************************************************
*
* Copyright 2011 Marek Olšák <maraeo@gmail.com>
* 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 AUTHORS 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.
*
**************************************************************************/
 
/**
* This module uploads user buffers and translates the vertex buffers which
* contain incompatible vertices (i.e. not supported by the driver/hardware)
* into compatible ones, based on the Gallium CAPs.
*
* It does not upload index buffers.
*
* The module heavily uses bitmasks to represent per-buffer and
* per-vertex-element flags to avoid looping over the list of buffers just
* to see if there's a non-zero stride, or user buffer, or unsupported format,
* etc.
*
* There are 3 categories of vertex elements, which are processed separately:
* - per-vertex attribs (stride != 0, instance_divisor == 0)
* - instanced attribs (stride != 0, instance_divisor > 0)
* - constant attribs (stride == 0)
*
* All needed uploads and translations are performed every draw command, but
* only the subset of vertices needed for that draw command is uploaded or
* translated. (the module never translates whole buffers)
*
*
* The module consists of two main parts:
*
*
* 1) Translate (u_vbuf_translate_begin/end)
*
* This is pretty much a vertex fetch fallback. It translates vertices from
* one vertex buffer to another in an unused vertex buffer slot. It does
* whatever is needed to make the vertices readable by the hardware (changes
* vertex formats and aligns offsets and strides). The translate module is
* used here.
*
* Each of the 3 categories is translated to a separate buffer.
* Only the [min_index, max_index] range is translated. For instanced attribs,
* the range is [start_instance, start_instance+instance_count]. For constant
* attribs, the range is [0, 1].
*
*
* 2) User buffer uploading (u_vbuf_upload_buffers)
*
* Only the [min_index, max_index] range is uploaded (just like Translate)
* with a single memcpy.
*
* This method works best for non-indexed draw operations or indexed draw
* operations where the [min_index, max_index] range is not being way bigger
* than the vertex count.
*
* If the range is too big (e.g. one triangle with indices {0, 1, 10000}),
* the per-vertex attribs are uploaded via the translate module, all packed
* into one vertex buffer, and the indexed draw call is turned into
* a non-indexed one in the process. This adds additional complexity
* to the translate part, but it prevents bad apps from bringing your frame
* rate down.
*
*
* If there is nothing to do, it forwards every command to the driver.
* The module also has its own CSO cache of vertex element states.
*/
 
#include "util/u_vbuf.h"
 
#include "util/u_dump.h"
#include "util/u_format.h"
#include "util/u_inlines.h"
#include "util/u_memory.h"
#include "util/u_upload_mgr.h"
#include "translate/translate.h"
#include "translate/translate_cache.h"
#include "cso_cache/cso_cache.h"
#include "cso_cache/cso_hash.h"
 
struct u_vbuf_elements {
unsigned count;
struct pipe_vertex_element ve[PIPE_MAX_ATTRIBS];
 
unsigned src_format_size[PIPE_MAX_ATTRIBS];
 
/* If (velem[i].src_format != native_format[i]), the vertex buffer
* referenced by the vertex element cannot be used for rendering and
* its vertex data must be translated to native_format[i]. */
enum pipe_format native_format[PIPE_MAX_ATTRIBS];
unsigned native_format_size[PIPE_MAX_ATTRIBS];
 
/* Which buffers are used by the vertex element state. */
uint32_t used_vb_mask;
/* This might mean two things:
* - src_format != native_format, as discussed above.
* - src_offset % 4 != 0 (if the caps don't allow such an offset). */
uint32_t incompatible_elem_mask; /* each bit describes a corresp. attrib */
/* Which buffer has at least one vertex element referencing it
* incompatible. */
uint32_t incompatible_vb_mask_any;
/* Which buffer has all vertex elements referencing it incompatible. */
uint32_t incompatible_vb_mask_all;
/* Which buffer has at least one vertex element referencing it
* compatible. */
uint32_t compatible_vb_mask_any;
/* Which buffer has all vertex elements referencing it compatible. */
uint32_t compatible_vb_mask_all;
 
/* Which buffer has at least one vertex element referencing it
* non-instanced. */
uint32_t noninstance_vb_mask_any;
 
void *driver_cso;
};
 
enum {
VB_VERTEX = 0,
VB_INSTANCE = 1,
VB_CONST = 2,
VB_NUM = 3
};
 
struct u_vbuf {
struct u_vbuf_caps caps;
 
struct pipe_context *pipe;
struct translate_cache *translate_cache;
struct cso_cache *cso_cache;
struct u_upload_mgr *uploader;
 
/* This is what was set in set_vertex_buffers.
* May contain user buffers. */
struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
uint32_t enabled_vb_mask;
 
/* Saved vertex buffer. */
unsigned aux_vertex_buffer_slot;
struct pipe_vertex_buffer aux_vertex_buffer_saved;
 
/* Vertex buffers for the driver.
* There are usually no user buffers. */
struct pipe_vertex_buffer real_vertex_buffer[PIPE_MAX_ATTRIBS];
uint32_t dirty_real_vb_mask; /* which buffers are dirty since the last
call of set_vertex_buffers */
 
/* The index buffer. */
struct pipe_index_buffer index_buffer;
 
/* Vertex elements. */
struct u_vbuf_elements *ve, *ve_saved;
 
/* Vertex elements used for the translate fallback. */
struct pipe_vertex_element fallback_velems[PIPE_MAX_ATTRIBS];
/* If non-NULL, this is a vertex element state used for the translate
* fallback and therefore used for rendering too. */
boolean using_translate;
/* The vertex buffer slot index where translated vertices have been
* stored in. */
unsigned fallback_vbs[VB_NUM];
 
/* Which buffer is a user buffer. */
uint32_t user_vb_mask; /* each bit describes a corresp. buffer */
/* Which buffer is incompatible (unaligned). */
uint32_t incompatible_vb_mask; /* each bit describes a corresp. buffer */
/* Which buffer has a non-zero stride. */
uint32_t nonzero_stride_vb_mask; /* each bit describes a corresp. buffer */
};
 
static void *
u_vbuf_create_vertex_elements(struct u_vbuf *mgr, unsigned count,
const struct pipe_vertex_element *attribs);
static void u_vbuf_delete_vertex_elements(struct u_vbuf *mgr, void *cso);
 
 
void u_vbuf_get_caps(struct pipe_screen *screen, struct u_vbuf_caps *caps)
{
caps->format_fixed32 =
screen->is_format_supported(screen, PIPE_FORMAT_R32_FIXED, PIPE_BUFFER,
0, PIPE_BIND_VERTEX_BUFFER);
 
caps->format_float16 =
screen->is_format_supported(screen, PIPE_FORMAT_R16_FLOAT, PIPE_BUFFER,
0, PIPE_BIND_VERTEX_BUFFER);
 
caps->format_float64 =
screen->is_format_supported(screen, PIPE_FORMAT_R64_FLOAT, PIPE_BUFFER,
0, PIPE_BIND_VERTEX_BUFFER);
 
caps->format_norm32 =
screen->is_format_supported(screen, PIPE_FORMAT_R32_UNORM, PIPE_BUFFER,
0, PIPE_BIND_VERTEX_BUFFER) &&
screen->is_format_supported(screen, PIPE_FORMAT_R32_SNORM, PIPE_BUFFER,
0, PIPE_BIND_VERTEX_BUFFER);
 
caps->format_scaled32 =
screen->is_format_supported(screen, PIPE_FORMAT_R32_USCALED, PIPE_BUFFER,
0, PIPE_BIND_VERTEX_BUFFER) &&
screen->is_format_supported(screen, PIPE_FORMAT_R32_SSCALED, PIPE_BUFFER,
0, PIPE_BIND_VERTEX_BUFFER);
 
caps->buffer_offset_unaligned =
!screen->get_param(screen,
PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY);
 
caps->buffer_stride_unaligned =
!screen->get_param(screen,
PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY);
 
caps->velem_src_offset_unaligned =
!screen->get_param(screen,
PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY);
 
caps->user_vertex_buffers =
screen->get_param(screen, PIPE_CAP_USER_VERTEX_BUFFERS);
}
 
struct u_vbuf *
u_vbuf_create(struct pipe_context *pipe,
struct u_vbuf_caps *caps, unsigned aux_vertex_buffer_index)
{
struct u_vbuf *mgr = CALLOC_STRUCT(u_vbuf);
 
mgr->caps = *caps;
mgr->aux_vertex_buffer_slot = aux_vertex_buffer_index;
mgr->pipe = pipe;
mgr->cso_cache = cso_cache_create();
mgr->translate_cache = translate_cache_create();
memset(mgr->fallback_vbs, ~0, sizeof(mgr->fallback_vbs));
 
mgr->uploader = u_upload_create(pipe, 1024 * 1024, 4,
PIPE_BIND_VERTEX_BUFFER);
 
return mgr;
}
 
/* u_vbuf uses its own caching for vertex elements, because it needs to keep
* its own preprocessed state per vertex element CSO. */
static struct u_vbuf_elements *
u_vbuf_set_vertex_elements_internal(struct u_vbuf *mgr, unsigned count,
const struct pipe_vertex_element *states)
{
struct pipe_context *pipe = mgr->pipe;
unsigned key_size, hash_key;
struct cso_hash_iter iter;
struct u_vbuf_elements *ve;
struct cso_velems_state velems_state;
 
/* need to include the count into the stored state data too. */
key_size = sizeof(struct pipe_vertex_element) * count + sizeof(unsigned);
velems_state.count = count;
memcpy(velems_state.velems, states,
sizeof(struct pipe_vertex_element) * count);
hash_key = cso_construct_key((void*)&velems_state, key_size);
iter = cso_find_state_template(mgr->cso_cache, hash_key, CSO_VELEMENTS,
(void*)&velems_state, key_size);
 
if (cso_hash_iter_is_null(iter)) {
struct cso_velements *cso = MALLOC_STRUCT(cso_velements);
memcpy(&cso->state, &velems_state, key_size);
cso->data = u_vbuf_create_vertex_elements(mgr, count, states);
cso->delete_state = (cso_state_callback)u_vbuf_delete_vertex_elements;
cso->context = (void*)mgr;
 
iter = cso_insert_state(mgr->cso_cache, hash_key, CSO_VELEMENTS, cso);
ve = cso->data;
} else {
ve = ((struct cso_velements *)cso_hash_iter_data(iter))->data;
}
 
assert(ve);
 
if (ve != mgr->ve)
pipe->bind_vertex_elements_state(pipe, ve->driver_cso);
return ve;
}
 
void u_vbuf_set_vertex_elements(struct u_vbuf *mgr, unsigned count,
const struct pipe_vertex_element *states)
{
mgr->ve = u_vbuf_set_vertex_elements_internal(mgr, count, states);
}
 
void u_vbuf_destroy(struct u_vbuf *mgr)
{
struct pipe_screen *screen = mgr->pipe->screen;
unsigned i;
unsigned num_vb = screen->get_shader_param(screen, PIPE_SHADER_VERTEX,
PIPE_SHADER_CAP_MAX_INPUTS);
 
mgr->pipe->set_index_buffer(mgr->pipe, NULL);
pipe_resource_reference(&mgr->index_buffer.buffer, NULL);
 
mgr->pipe->set_vertex_buffers(mgr->pipe, 0, num_vb, NULL);
 
for (i = 0; i < PIPE_MAX_ATTRIBS; i++) {
pipe_resource_reference(&mgr->vertex_buffer[i].buffer, NULL);
}
for (i = 0; i < PIPE_MAX_ATTRIBS; i++) {
pipe_resource_reference(&mgr->real_vertex_buffer[i].buffer, NULL);
}
pipe_resource_reference(&mgr->aux_vertex_buffer_saved.buffer, NULL);
 
translate_cache_destroy(mgr->translate_cache);
u_upload_destroy(mgr->uploader);
cso_cache_delete(mgr->cso_cache);
FREE(mgr);
}
 
static enum pipe_error
u_vbuf_translate_buffers(struct u_vbuf *mgr, struct translate_key *key,
unsigned vb_mask, unsigned out_vb,
int start_vertex, unsigned num_vertices,
int start_index, unsigned num_indices, int min_index,
boolean unroll_indices)
{
struct translate *tr;
struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS] = {0};
struct pipe_resource *out_buffer = NULL;
uint8_t *out_map;
unsigned out_offset, mask;
enum pipe_error err;
 
/* Get a translate object. */
tr = translate_cache_find(mgr->translate_cache, key);
 
/* Map buffers we want to translate. */
mask = vb_mask;
while (mask) {
struct pipe_vertex_buffer *vb;
unsigned offset;
uint8_t *map;
unsigned i = u_bit_scan(&mask);
 
vb = &mgr->vertex_buffer[i];
offset = vb->buffer_offset + vb->stride * start_vertex;
 
if (vb->user_buffer) {
map = (uint8_t*)vb->user_buffer + offset;
} else {
unsigned size = vb->stride ? num_vertices * vb->stride
: sizeof(double)*4;
 
if (offset+size > vb->buffer->width0) {
size = vb->buffer->width0 - offset;
}
 
map = pipe_buffer_map_range(mgr->pipe, vb->buffer, offset, size,
PIPE_TRANSFER_READ, &vb_transfer[i]);
}
 
/* Subtract min_index so that indexing with the index buffer works. */
if (unroll_indices) {
map -= vb->stride * min_index;
}
 
tr->set_buffer(tr, i, map, vb->stride, ~0);
}
 
/* Translate. */
if (unroll_indices) {
struct pipe_index_buffer *ib = &mgr->index_buffer;
struct pipe_transfer *transfer = NULL;
unsigned offset = ib->offset + start_index * ib->index_size;
uint8_t *map;
 
assert((ib->buffer || ib->user_buffer) && ib->index_size);
 
/* Create and map the output buffer. */
err = u_upload_alloc(mgr->uploader, 0,
key->output_stride * num_indices,
&out_offset, &out_buffer,
(void**)&out_map);
if (err != PIPE_OK)
return err;
 
if (ib->user_buffer) {
map = (uint8_t*)ib->user_buffer + offset;
} else {
map = pipe_buffer_map_range(mgr->pipe, ib->buffer, offset,
num_indices * ib->index_size,
PIPE_TRANSFER_READ, &transfer);
}
 
switch (ib->index_size) {
case 4:
tr->run_elts(tr, (unsigned*)map, num_indices, 0, 0, out_map);
break;
case 2:
tr->run_elts16(tr, (uint16_t*)map, num_indices, 0, 0, out_map);
break;
case 1:
tr->run_elts8(tr, map, num_indices, 0, 0, out_map);
break;
}
 
if (transfer) {
pipe_buffer_unmap(mgr->pipe, transfer);
}
} else {
/* Create and map the output buffer. */
err = u_upload_alloc(mgr->uploader,
key->output_stride * start_vertex,
key->output_stride * num_vertices,
&out_offset, &out_buffer,
(void**)&out_map);
if (err != PIPE_OK)
return err;
 
out_offset -= key->output_stride * start_vertex;
 
tr->run(tr, 0, num_vertices, 0, 0, out_map);
}
 
/* Unmap all buffers. */
mask = vb_mask;
while (mask) {
unsigned i = u_bit_scan(&mask);
 
if (vb_transfer[i]) {
pipe_buffer_unmap(mgr->pipe, vb_transfer[i]);
}
}
 
/* Setup the new vertex buffer. */
mgr->real_vertex_buffer[out_vb].buffer_offset = out_offset;
mgr->real_vertex_buffer[out_vb].stride = key->output_stride;
 
/* Move the buffer reference. */
pipe_resource_reference(
&mgr->real_vertex_buffer[out_vb].buffer, NULL);
mgr->real_vertex_buffer[out_vb].buffer = out_buffer;
 
return PIPE_OK;
}
 
static boolean
u_vbuf_translate_find_free_vb_slots(struct u_vbuf *mgr,
unsigned mask[VB_NUM])
{
unsigned type;
unsigned fallback_vbs[VB_NUM];
/* Set the bit for each buffer which is incompatible, or isn't set. */
uint32_t unused_vb_mask =
mgr->ve->incompatible_vb_mask_all | mgr->incompatible_vb_mask |
~mgr->enabled_vb_mask;
 
memset(fallback_vbs, ~0, sizeof(fallback_vbs));
 
/* Find free slots for each type if needed. */
for (type = 0; type < VB_NUM; type++) {
if (mask[type]) {
uint32_t index;
 
if (!unused_vb_mask) {
return FALSE;
}
 
index = ffs(unused_vb_mask) - 1;
fallback_vbs[type] = index;
/*printf("found slot=%i for type=%i\n", index, type);*/
}
}
 
for (type = 0; type < VB_NUM; type++) {
if (mask[type]) {
mgr->dirty_real_vb_mask |= 1 << fallback_vbs[type];
}
}
 
memcpy(mgr->fallback_vbs, fallback_vbs, sizeof(fallback_vbs));
return TRUE;
}
 
static boolean
u_vbuf_translate_begin(struct u_vbuf *mgr,
int start_vertex, unsigned num_vertices,
int start_instance, unsigned num_instances,
int start_index, unsigned num_indices, int min_index,
boolean unroll_indices)
{
unsigned mask[VB_NUM] = {0};
struct translate_key key[VB_NUM];
unsigned elem_index[VB_NUM][PIPE_MAX_ATTRIBS]; /* ... into key.elements */
unsigned i, type;
unsigned incompatible_vb_mask = mgr->incompatible_vb_mask &
mgr->ve->used_vb_mask;
 
int start[VB_NUM] = {
start_vertex, /* VERTEX */
start_instance, /* INSTANCE */
0 /* CONST */
};
 
unsigned num[VB_NUM] = {
num_vertices, /* VERTEX */
num_instances, /* INSTANCE */
1 /* CONST */
};
 
memset(key, 0, sizeof(key));
memset(elem_index, ~0, sizeof(elem_index));
 
/* See if there are vertex attribs of each type to translate and
* which ones. */
for (i = 0; i < mgr->ve->count; i++) {
unsigned vb_index = mgr->ve->ve[i].vertex_buffer_index;
 
if (!mgr->vertex_buffer[vb_index].stride) {
if (!(mgr->ve->incompatible_elem_mask & (1 << i)) &&
!(incompatible_vb_mask & (1 << vb_index))) {
continue;
}
mask[VB_CONST] |= 1 << vb_index;
} else if (mgr->ve->ve[i].instance_divisor) {
if (!(mgr->ve->incompatible_elem_mask & (1 << i)) &&
!(incompatible_vb_mask & (1 << vb_index))) {
continue;
}
mask[VB_INSTANCE] |= 1 << vb_index;
} else {
if (!unroll_indices &&
!(mgr->ve->incompatible_elem_mask & (1 << i)) &&
!(incompatible_vb_mask & (1 << vb_index))) {
continue;
}
mask[VB_VERTEX] |= 1 << vb_index;
}
}
 
assert(mask[VB_VERTEX] || mask[VB_INSTANCE] || mask[VB_CONST]);
 
/* Find free vertex buffer slots. */
if (!u_vbuf_translate_find_free_vb_slots(mgr, mask)) {
return FALSE;
}
 
/* Initialize the translate keys. */
for (i = 0; i < mgr->ve->count; i++) {
struct translate_key *k;
struct translate_element *te;
unsigned bit, vb_index = mgr->ve->ve[i].vertex_buffer_index;
bit = 1 << vb_index;
 
if (!(mgr->ve->incompatible_elem_mask & (1 << i)) &&
!(incompatible_vb_mask & (1 << vb_index)) &&
(!unroll_indices || !(mask[VB_VERTEX] & bit))) {
continue;
}
 
/* Set type to what we will translate.
* Whether vertex, instance, or constant attribs. */
for (type = 0; type < VB_NUM; type++) {
if (mask[type] & bit) {
break;
}
}
assert(type < VB_NUM);
assert(translate_is_output_format_supported(mgr->ve->native_format[i]));
/*printf("velem=%i type=%i\n", i, type);*/
 
/* Add the vertex element. */
k = &key[type];
elem_index[type][i] = k->nr_elements;
 
te = &k->element[k->nr_elements];
te->type = TRANSLATE_ELEMENT_NORMAL;
te->instance_divisor = 0;
te->input_buffer = vb_index;
te->input_format = mgr->ve->ve[i].src_format;
te->input_offset = mgr->ve->ve[i].src_offset;
te->output_format = mgr->ve->native_format[i];
te->output_offset = k->output_stride;
 
k->output_stride += mgr->ve->native_format_size[i];
k->nr_elements++;
}
 
/* Translate buffers. */
for (type = 0; type < VB_NUM; type++) {
if (key[type].nr_elements) {
enum pipe_error err;
err = u_vbuf_translate_buffers(mgr, &key[type], mask[type],
mgr->fallback_vbs[type],
start[type], num[type],
start_index, num_indices, min_index,
unroll_indices && type == VB_VERTEX);
if (err != PIPE_OK)
return FALSE;
 
/* Fixup the stride for constant attribs. */
if (type == VB_CONST) {
mgr->real_vertex_buffer[mgr->fallback_vbs[VB_CONST]].stride = 0;
}
}
}
 
/* Setup new vertex elements. */
for (i = 0; i < mgr->ve->count; i++) {
for (type = 0; type < VB_NUM; type++) {
if (elem_index[type][i] < key[type].nr_elements) {
struct translate_element *te = &key[type].element[elem_index[type][i]];
mgr->fallback_velems[i].instance_divisor = mgr->ve->ve[i].instance_divisor;
mgr->fallback_velems[i].src_format = te->output_format;
mgr->fallback_velems[i].src_offset = te->output_offset;
mgr->fallback_velems[i].vertex_buffer_index = mgr->fallback_vbs[type];
 
/* elem_index[type][i] can only be set for one type. */
assert(type > VB_INSTANCE || elem_index[type+1][i] == ~0);
assert(type > VB_VERTEX || elem_index[type+2][i] == ~0);
break;
}
}
/* No translating, just copy the original vertex element over. */
if (type == VB_NUM) {
memcpy(&mgr->fallback_velems[i], &mgr->ve->ve[i],
sizeof(struct pipe_vertex_element));
}
}
 
u_vbuf_set_vertex_elements_internal(mgr, mgr->ve->count,
mgr->fallback_velems);
mgr->using_translate = TRUE;
return TRUE;
}
 
static void u_vbuf_translate_end(struct u_vbuf *mgr)
{
unsigned i;
 
/* Restore vertex elements. */
mgr->pipe->bind_vertex_elements_state(mgr->pipe, mgr->ve->driver_cso);
mgr->using_translate = FALSE;
 
/* Unreference the now-unused VBOs. */
for (i = 0; i < VB_NUM; i++) {
unsigned vb = mgr->fallback_vbs[i];
if (vb != ~0) {
pipe_resource_reference(&mgr->real_vertex_buffer[vb].buffer, NULL);
mgr->fallback_vbs[i] = ~0;
 
/* This will cause the buffer to be unbound in the driver later. */
mgr->dirty_real_vb_mask |= 1 << vb;
}
}
}
 
#define FORMAT_REPLACE(what, withwhat) \
case PIPE_FORMAT_##what: format = PIPE_FORMAT_##withwhat; break
 
static void *
u_vbuf_create_vertex_elements(struct u_vbuf *mgr, unsigned count,
const struct pipe_vertex_element *attribs)
{
struct pipe_context *pipe = mgr->pipe;
unsigned i;
struct pipe_vertex_element driver_attribs[PIPE_MAX_ATTRIBS];
struct u_vbuf_elements *ve = CALLOC_STRUCT(u_vbuf_elements);
uint32_t used_buffers = 0;
 
ve->count = count;
 
memcpy(ve->ve, attribs, sizeof(struct pipe_vertex_element) * count);
memcpy(driver_attribs, attribs, sizeof(struct pipe_vertex_element) * count);
 
/* Set the best native format in case the original format is not
* supported. */
for (i = 0; i < count; i++) {
enum pipe_format format = ve->ve[i].src_format;
 
ve->src_format_size[i] = util_format_get_blocksize(format);
 
used_buffers |= 1 << ve->ve[i].vertex_buffer_index;
 
if (!ve->ve[i].instance_divisor) {
ve->noninstance_vb_mask_any |= 1 << ve->ve[i].vertex_buffer_index;
}
 
/* Choose a native format.
* For now we don't care about the alignment, that's going to
* be sorted out later. */
if (!mgr->caps.format_fixed32) {
switch (format) {
FORMAT_REPLACE(R32_FIXED, R32_FLOAT);
FORMAT_REPLACE(R32G32_FIXED, R32G32_FLOAT);
FORMAT_REPLACE(R32G32B32_FIXED, R32G32B32_FLOAT);
FORMAT_REPLACE(R32G32B32A32_FIXED, R32G32B32A32_FLOAT);
default:;
}
}
if (!mgr->caps.format_float16) {
switch (format) {
FORMAT_REPLACE(R16_FLOAT, R32_FLOAT);
FORMAT_REPLACE(R16G16_FLOAT, R32G32_FLOAT);
FORMAT_REPLACE(R16G16B16_FLOAT, R32G32B32_FLOAT);
FORMAT_REPLACE(R16G16B16A16_FLOAT, R32G32B32A32_FLOAT);
default:;
}
}
if (!mgr->caps.format_float64) {
switch (format) {
FORMAT_REPLACE(R64_FLOAT, R32_FLOAT);
FORMAT_REPLACE(R64G64_FLOAT, R32G32_FLOAT);
FORMAT_REPLACE(R64G64B64_FLOAT, R32G32B32_FLOAT);
FORMAT_REPLACE(R64G64B64A64_FLOAT, R32G32B32A32_FLOAT);
default:;
}
}
if (!mgr->caps.format_norm32) {
switch (format) {
FORMAT_REPLACE(R32_UNORM, R32_FLOAT);
FORMAT_REPLACE(R32G32_UNORM, R32G32_FLOAT);
FORMAT_REPLACE(R32G32B32_UNORM, R32G32B32_FLOAT);
FORMAT_REPLACE(R32G32B32A32_UNORM, R32G32B32A32_FLOAT);
FORMAT_REPLACE(R32_SNORM, R32_FLOAT);
FORMAT_REPLACE(R32G32_SNORM, R32G32_FLOAT);
FORMAT_REPLACE(R32G32B32_SNORM, R32G32B32_FLOAT);
FORMAT_REPLACE(R32G32B32A32_SNORM, R32G32B32A32_FLOAT);
default:;
}
}
if (!mgr->caps.format_scaled32) {
switch (format) {
FORMAT_REPLACE(R32_USCALED, R32_FLOAT);
FORMAT_REPLACE(R32G32_USCALED, R32G32_FLOAT);
FORMAT_REPLACE(R32G32B32_USCALED, R32G32B32_FLOAT);
FORMAT_REPLACE(R32G32B32A32_USCALED,R32G32B32A32_FLOAT);
FORMAT_REPLACE(R32_SSCALED, R32_FLOAT);
FORMAT_REPLACE(R32G32_SSCALED, R32G32_FLOAT);
FORMAT_REPLACE(R32G32B32_SSCALED, R32G32B32_FLOAT);
FORMAT_REPLACE(R32G32B32A32_SSCALED,R32G32B32A32_FLOAT);
default:;
}
}
 
driver_attribs[i].src_format = format;
ve->native_format[i] = format;
ve->native_format_size[i] =
util_format_get_blocksize(ve->native_format[i]);
 
if (ve->ve[i].src_format != format ||
(!mgr->caps.velem_src_offset_unaligned &&
ve->ve[i].src_offset % 4 != 0)) {
ve->incompatible_elem_mask |= 1 << i;
ve->incompatible_vb_mask_any |= 1 << ve->ve[i].vertex_buffer_index;
} else {
ve->compatible_vb_mask_any |= 1 << ve->ve[i].vertex_buffer_index;
}
}
 
ve->used_vb_mask = used_buffers;
ve->compatible_vb_mask_all = ~ve->incompatible_vb_mask_any & used_buffers;
ve->incompatible_vb_mask_all = ~ve->compatible_vb_mask_any & used_buffers;
 
/* Align the formats to the size of DWORD if needed. */
if (!mgr->caps.velem_src_offset_unaligned) {
for (i = 0; i < count; i++) {
ve->native_format_size[i] = align(ve->native_format_size[i], 4);
}
}
 
ve->driver_cso =
pipe->create_vertex_elements_state(pipe, count, driver_attribs);
return ve;
}
 
static void u_vbuf_delete_vertex_elements(struct u_vbuf *mgr, void *cso)
{
struct pipe_context *pipe = mgr->pipe;
struct u_vbuf_elements *ve = cso;
 
pipe->delete_vertex_elements_state(pipe, ve->driver_cso);
FREE(ve);
}
 
void u_vbuf_set_vertex_buffers(struct u_vbuf *mgr,
unsigned start_slot, unsigned count,
const struct pipe_vertex_buffer *bufs)
{
unsigned i;
/* which buffers are enabled */
uint32_t enabled_vb_mask = 0;
/* which buffers are in user memory */
uint32_t user_vb_mask = 0;
/* which buffers are incompatible with the driver */
uint32_t incompatible_vb_mask = 0;
/* which buffers have a non-zero stride */
uint32_t nonzero_stride_vb_mask = 0;
uint32_t mask = ~(((1ull << count) - 1) << start_slot);
 
/* Zero out the bits we are going to rewrite completely. */
mgr->user_vb_mask &= mask;
mgr->incompatible_vb_mask &= mask;
mgr->nonzero_stride_vb_mask &= mask;
mgr->enabled_vb_mask &= mask;
 
if (!bufs) {
struct pipe_context *pipe = mgr->pipe;
/* Unbind. */
mgr->dirty_real_vb_mask &= mask;
 
for (i = 0; i < count; i++) {
unsigned dst_index = start_slot + i;
 
pipe_resource_reference(&mgr->vertex_buffer[dst_index].buffer, NULL);
pipe_resource_reference(&mgr->real_vertex_buffer[dst_index].buffer,
NULL);
}
 
pipe->set_vertex_buffers(pipe, start_slot, count, NULL);
return;
}
 
for (i = 0; i < count; i++) {
unsigned dst_index = start_slot + i;
const struct pipe_vertex_buffer *vb = &bufs[i];
struct pipe_vertex_buffer *orig_vb = &mgr->vertex_buffer[dst_index];
struct pipe_vertex_buffer *real_vb = &mgr->real_vertex_buffer[dst_index];
 
if (!vb->buffer && !vb->user_buffer) {
pipe_resource_reference(&orig_vb->buffer, NULL);
pipe_resource_reference(&real_vb->buffer, NULL);
real_vb->user_buffer = NULL;
continue;
}
 
pipe_resource_reference(&orig_vb->buffer, vb->buffer);
orig_vb->user_buffer = vb->user_buffer;
 
real_vb->buffer_offset = orig_vb->buffer_offset = vb->buffer_offset;
real_vb->stride = orig_vb->stride = vb->stride;
 
if (vb->stride) {
nonzero_stride_vb_mask |= 1 << dst_index;
}
enabled_vb_mask |= 1 << dst_index;
 
if ((!mgr->caps.buffer_offset_unaligned && vb->buffer_offset % 4 != 0) ||
(!mgr->caps.buffer_stride_unaligned && vb->stride % 4 != 0)) {
incompatible_vb_mask |= 1 << dst_index;
pipe_resource_reference(&real_vb->buffer, NULL);
continue;
}
 
if (!mgr->caps.user_vertex_buffers && vb->user_buffer) {
user_vb_mask |= 1 << dst_index;
pipe_resource_reference(&real_vb->buffer, NULL);
continue;
}
 
pipe_resource_reference(&real_vb->buffer, vb->buffer);
real_vb->user_buffer = vb->user_buffer;
}
 
mgr->user_vb_mask |= user_vb_mask;
mgr->incompatible_vb_mask |= incompatible_vb_mask;
mgr->nonzero_stride_vb_mask |= nonzero_stride_vb_mask;
mgr->enabled_vb_mask |= enabled_vb_mask;
 
/* All changed buffers are marked as dirty, even the NULL ones,
* which will cause the NULL buffers to be unbound in the driver later. */
mgr->dirty_real_vb_mask |= ~mask;
}
 
void u_vbuf_set_index_buffer(struct u_vbuf *mgr,
const struct pipe_index_buffer *ib)
{
struct pipe_context *pipe = mgr->pipe;
 
if (ib) {
assert(ib->offset % ib->index_size == 0);
pipe_resource_reference(&mgr->index_buffer.buffer, ib->buffer);
memcpy(&mgr->index_buffer, ib, sizeof(*ib));
} else {
pipe_resource_reference(&mgr->index_buffer.buffer, NULL);
}
 
pipe->set_index_buffer(pipe, ib);
}
 
static enum pipe_error
u_vbuf_upload_buffers(struct u_vbuf *mgr,
int start_vertex, unsigned num_vertices,
int start_instance, unsigned num_instances)
{
unsigned i;
unsigned nr_velems = mgr->ve->count;
struct pipe_vertex_element *velems =
mgr->using_translate ? mgr->fallback_velems : mgr->ve->ve;
unsigned start_offset[PIPE_MAX_ATTRIBS];
unsigned end_offset[PIPE_MAX_ATTRIBS];
uint32_t buffer_mask = 0;
 
/* Determine how much data needs to be uploaded. */
for (i = 0; i < nr_velems; i++) {
struct pipe_vertex_element *velem = &velems[i];
unsigned index = velem->vertex_buffer_index;
struct pipe_vertex_buffer *vb = &mgr->vertex_buffer[index];
unsigned instance_div, first, size, index_bit;
 
/* Skip the buffers generated by translate. */
if (index == mgr->fallback_vbs[VB_VERTEX] ||
index == mgr->fallback_vbs[VB_INSTANCE] ||
index == mgr->fallback_vbs[VB_CONST]) {
continue;
}
 
if (!vb->user_buffer) {
continue;
}
 
instance_div = velem->instance_divisor;
first = vb->buffer_offset + velem->src_offset;
 
if (!vb->stride) {
/* Constant attrib. */
size = mgr->ve->src_format_size[i];
} else if (instance_div) {
/* Per-instance attrib. */
unsigned count = (num_instances + instance_div - 1) / instance_div;
first += vb->stride * start_instance;
size = vb->stride * (count - 1) + mgr->ve->src_format_size[i];
} else {
/* Per-vertex attrib. */
first += vb->stride * start_vertex;
size = vb->stride * (num_vertices - 1) + mgr->ve->src_format_size[i];
}
 
index_bit = 1 << index;
 
/* Update offsets. */
if (!(buffer_mask & index_bit)) {
start_offset[index] = first;
end_offset[index] = first + size;
} else {
if (first < start_offset[index])
start_offset[index] = first;
if (first + size > end_offset[index])
end_offset[index] = first + size;
}
 
buffer_mask |= index_bit;
}
 
/* Upload buffers. */
while (buffer_mask) {
unsigned start, end;
struct pipe_vertex_buffer *real_vb;
const uint8_t *ptr;
enum pipe_error err;
 
i = u_bit_scan(&buffer_mask);
 
start = start_offset[i];
end = end_offset[i];
assert(start < end);
 
real_vb = &mgr->real_vertex_buffer[i];
ptr = mgr->vertex_buffer[i].user_buffer;
 
err = u_upload_data(mgr->uploader, start, end - start, ptr + start,
&real_vb->buffer_offset, &real_vb->buffer);
if (err != PIPE_OK)
return err;
 
real_vb->buffer_offset -= start;
}
 
return PIPE_OK;
}
 
static boolean u_vbuf_need_minmax_index(struct u_vbuf *mgr)
{
/* See if there are any per-vertex attribs which will be uploaded or
* translated. Use bitmasks to get the info instead of looping over vertex
* elements. */
return (mgr->ve->used_vb_mask &
((mgr->user_vb_mask | mgr->incompatible_vb_mask |
mgr->ve->incompatible_vb_mask_any) &
mgr->ve->noninstance_vb_mask_any & mgr->nonzero_stride_vb_mask)) != 0;
}
 
static boolean u_vbuf_mapping_vertex_buffer_blocks(struct u_vbuf *mgr)
{
/* Return true if there are hw buffers which don't need to be translated.
*
* We could query whether each buffer is busy, but that would
* be way more costly than this. */
return (mgr->ve->used_vb_mask &
(~mgr->user_vb_mask & ~mgr->incompatible_vb_mask &
mgr->ve->compatible_vb_mask_all & mgr->ve->noninstance_vb_mask_any &
mgr->nonzero_stride_vb_mask)) != 0;
}
 
static void u_vbuf_get_minmax_index(struct pipe_context *pipe,
struct pipe_index_buffer *ib,
const struct pipe_draw_info *info,
int *out_min_index,
int *out_max_index)
{
struct pipe_transfer *transfer = NULL;
const void *indices;
unsigned i;
unsigned restart_index = info->restart_index;
 
if (ib->user_buffer) {
indices = (uint8_t*)ib->user_buffer +
ib->offset + info->start * ib->index_size;
} else {
indices = pipe_buffer_map_range(pipe, ib->buffer,
ib->offset + info->start * ib->index_size,
info->count * ib->index_size,
PIPE_TRANSFER_READ, &transfer);
}
 
switch (ib->index_size) {
case 4: {
const unsigned *ui_indices = (const unsigned*)indices;
unsigned max_ui = 0;
unsigned min_ui = ~0U;
if (info->primitive_restart) {
for (i = 0; i < info->count; i++) {
if (ui_indices[i] != restart_index) {
if (ui_indices[i] > max_ui) max_ui = ui_indices[i];
if (ui_indices[i] < min_ui) min_ui = ui_indices[i];
}
}
}
else {
for (i = 0; i < info->count; i++) {
if (ui_indices[i] > max_ui) max_ui = ui_indices[i];
if (ui_indices[i] < min_ui) min_ui = ui_indices[i];
}
}
*out_min_index = min_ui;
*out_max_index = max_ui;
break;
}
case 2: {
const unsigned short *us_indices = (const unsigned short*)indices;
unsigned max_us = 0;
unsigned min_us = ~0U;
if (info->primitive_restart) {
for (i = 0; i < info->count; i++) {
if (us_indices[i] != restart_index) {
if (us_indices[i] > max_us) max_us = us_indices[i];
if (us_indices[i] < min_us) min_us = us_indices[i];
}
}
}
else {
for (i = 0; i < info->count; i++) {
if (us_indices[i] > max_us) max_us = us_indices[i];
if (us_indices[i] < min_us) min_us = us_indices[i];
}
}
*out_min_index = min_us;
*out_max_index = max_us;
break;
}
case 1: {
const unsigned char *ub_indices = (const unsigned char*)indices;
unsigned max_ub = 0;
unsigned min_ub = ~0U;
if (info->primitive_restart) {
for (i = 0; i < info->count; i++) {
if (ub_indices[i] != restart_index) {
if (ub_indices[i] > max_ub) max_ub = ub_indices[i];
if (ub_indices[i] < min_ub) min_ub = ub_indices[i];
}
}
}
else {
for (i = 0; i < info->count; i++) {
if (ub_indices[i] > max_ub) max_ub = ub_indices[i];
if (ub_indices[i] < min_ub) min_ub = ub_indices[i];
}
}
*out_min_index = min_ub;
*out_max_index = max_ub;
break;
}
default:
assert(0);
*out_min_index = 0;
*out_max_index = 0;
}
 
if (transfer) {
pipe_buffer_unmap(pipe, transfer);
}
}
 
static void u_vbuf_set_driver_vertex_buffers(struct u_vbuf *mgr)
{
struct pipe_context *pipe = mgr->pipe;
unsigned start_slot, count;
 
start_slot = ffs(mgr->dirty_real_vb_mask) - 1;
count = util_last_bit(mgr->dirty_real_vb_mask >> start_slot);
 
pipe->set_vertex_buffers(pipe, start_slot, count,
mgr->real_vertex_buffer + start_slot);
mgr->dirty_real_vb_mask = 0;
}
 
void u_vbuf_draw_vbo(struct u_vbuf *mgr, const struct pipe_draw_info *info)
{
struct pipe_context *pipe = mgr->pipe;
int start_vertex, min_index;
unsigned num_vertices;
boolean unroll_indices = FALSE;
uint32_t used_vb_mask = mgr->ve->used_vb_mask;
uint32_t user_vb_mask = mgr->user_vb_mask & used_vb_mask;
uint32_t incompatible_vb_mask = mgr->incompatible_vb_mask & used_vb_mask;
 
/* Normal draw. No fallback and no user buffers. */
if (!incompatible_vb_mask &&
!mgr->ve->incompatible_elem_mask &&
!user_vb_mask) {
 
/* Set vertex buffers if needed. */
if (mgr->dirty_real_vb_mask & used_vb_mask) {
u_vbuf_set_driver_vertex_buffers(mgr);
}
 
pipe->draw_vbo(pipe, info);
return;
}
 
if (info->indexed) {
/* See if anything needs to be done for per-vertex attribs. */
if (u_vbuf_need_minmax_index(mgr)) {
int max_index;
 
if (info->max_index != ~0) {
min_index = info->min_index;
max_index = info->max_index;
} else {
u_vbuf_get_minmax_index(mgr->pipe, &mgr->index_buffer, info,
&min_index, &max_index);
}
 
assert(min_index <= max_index);
 
start_vertex = min_index + info->index_bias;
num_vertices = max_index + 1 - min_index;
 
/* Primitive restart doesn't work when unrolling indices.
* We would have to break this drawing operation into several ones. */
/* Use some heuristic to see if unrolling indices improves
* performance. */
if (!info->primitive_restart &&
num_vertices > info->count*2 &&
num_vertices-info->count > 32 &&
!u_vbuf_mapping_vertex_buffer_blocks(mgr)) {
/*printf("num_vertices=%i count=%i\n", num_vertices, info->count);*/
unroll_indices = TRUE;
user_vb_mask &= ~(mgr->nonzero_stride_vb_mask &
mgr->ve->noninstance_vb_mask_any);
}
} else {
/* Nothing to do for per-vertex attribs. */
start_vertex = 0;
num_vertices = 0;
min_index = 0;
}
} else {
start_vertex = info->start;
num_vertices = info->count;
min_index = 0;
}
 
/* Translate vertices with non-native layouts or formats. */
if (unroll_indices ||
incompatible_vb_mask ||
mgr->ve->incompatible_elem_mask) {
if (!u_vbuf_translate_begin(mgr, start_vertex, num_vertices,
info->start_instance, info->instance_count,
info->start, info->count, min_index,
unroll_indices)) {
debug_warn_once("u_vbuf_translate_begin() failed");
return;
}
 
user_vb_mask &= ~(incompatible_vb_mask |
mgr->ve->incompatible_vb_mask_all);
}
 
/* Upload user buffers. */
if (user_vb_mask) {
if (u_vbuf_upload_buffers(mgr, start_vertex, num_vertices,
info->start_instance,
info->instance_count) != PIPE_OK) {
debug_warn_once("u_vbuf_upload_buffers() failed");
return;
}
 
mgr->dirty_real_vb_mask |= user_vb_mask;
}
 
/*
if (unroll_indices) {
printf("unrolling indices: start_vertex = %i, num_vertices = %i\n",
start_vertex, num_vertices);
util_dump_draw_info(stdout, info);
printf("\n");
}
 
unsigned i;
for (i = 0; i < mgr->nr_vertex_buffers; i++) {
printf("input %i: ", i);
util_dump_vertex_buffer(stdout, mgr->vertex_buffer+i);
printf("\n");
}
for (i = 0; i < mgr->nr_real_vertex_buffers; i++) {
printf("real %i: ", i);
util_dump_vertex_buffer(stdout, mgr->real_vertex_buffer+i);
printf("\n");
}
*/
 
u_upload_unmap(mgr->uploader);
u_vbuf_set_driver_vertex_buffers(mgr);
 
if (unlikely(unroll_indices)) {
struct pipe_draw_info new_info = *info;
new_info.indexed = FALSE;
new_info.index_bias = 0;
new_info.min_index = 0;
new_info.max_index = info->count - 1;
new_info.start = 0;
 
pipe->draw_vbo(pipe, &new_info);
} else {
pipe->draw_vbo(pipe, info);
}
 
if (mgr->using_translate) {
u_vbuf_translate_end(mgr);
}
}
 
void u_vbuf_save_vertex_elements(struct u_vbuf *mgr)
{
assert(!mgr->ve_saved);
mgr->ve_saved = mgr->ve;
}
 
void u_vbuf_restore_vertex_elements(struct u_vbuf *mgr)
{
if (mgr->ve != mgr->ve_saved) {
struct pipe_context *pipe = mgr->pipe;
 
mgr->ve = mgr->ve_saved;
pipe->bind_vertex_elements_state(pipe,
mgr->ve ? mgr->ve->driver_cso : NULL);
}
mgr->ve_saved = NULL;
}
 
void u_vbuf_save_aux_vertex_buffer_slot(struct u_vbuf *mgr)
{
struct pipe_vertex_buffer *vb =
&mgr->vertex_buffer[mgr->aux_vertex_buffer_slot];
 
pipe_resource_reference(&mgr->aux_vertex_buffer_saved.buffer, vb->buffer);
memcpy(&mgr->aux_vertex_buffer_saved, vb, sizeof(*vb));
}
 
void u_vbuf_restore_aux_vertex_buffer_slot(struct u_vbuf *mgr)
{
u_vbuf_set_vertex_buffers(mgr, mgr->aux_vertex_buffer_slot, 1,
&mgr->aux_vertex_buffer_saved);
pipe_resource_reference(&mgr->aux_vertex_buffer_saved.buffer, NULL);
}
/drivers/video/Gallium/auxiliary/util/u_vbuf.h
0,0 → 1,87
/**************************************************************************
*
* Copyright 2011 Marek Olšák <maraeo@gmail.com>
* 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 AUTHORS 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.
*
**************************************************************************/
 
#ifndef U_VBUF_H
#define U_VBUF_H
 
/* This module takes care of user buffer uploads and vertex format fallbacks.
* It's designed for the drivers which don't want to use the Draw module.
* There is a more detailed description at the beginning of the .c file.
*/
 
#include "pipe/p_context.h"
#include "pipe/p_state.h"
 
struct cso_context;
struct u_vbuf;
 
/* Hardware vertex fetcher limitations can be described by this structure. */
struct u_vbuf_caps {
/* Vertex format CAPs. */
/* TRUE if hardware supports it. */
unsigned format_fixed32:1; /* PIPE_FORMAT_*32*_FIXED */
unsigned format_float16:1; /* PIPE_FORMAT_*16*_FLOAT */
unsigned format_float64:1; /* PIPE_FORMAT_*64*_FLOAT */
unsigned format_norm32:1; /* PIPE_FORMAT_*32*NORM */
unsigned format_scaled32:1; /* PIPE_FORMAT_*32*SCALED */
 
/* Whether vertex fetches don't have to be 4-byte-aligned. */
/* TRUE if hardware supports it. */
unsigned buffer_offset_unaligned:1;
unsigned buffer_stride_unaligned:1;
unsigned velem_src_offset_unaligned:1;
 
/* Whether the driver supports user vertex buffers. */
unsigned user_vertex_buffers:1;
};
 
 
void u_vbuf_get_caps(struct pipe_screen *screen, struct u_vbuf_caps *caps);
 
struct u_vbuf *
u_vbuf_create(struct pipe_context *pipe,
struct u_vbuf_caps *caps, unsigned aux_vertex_buffer_index);
 
void u_vbuf_destroy(struct u_vbuf *mgr);
 
/* State and draw functions. */
void u_vbuf_set_vertex_elements(struct u_vbuf *mgr, unsigned count,
const struct pipe_vertex_element *states);
void u_vbuf_set_vertex_buffers(struct u_vbuf *mgr,
unsigned start_slot, unsigned count,
const struct pipe_vertex_buffer *bufs);
void u_vbuf_set_index_buffer(struct u_vbuf *mgr,
const struct pipe_index_buffer *ib);
void u_vbuf_draw_vbo(struct u_vbuf *mgr, const struct pipe_draw_info *info);
 
/* Save/restore functionality. */
void u_vbuf_save_vertex_elements(struct u_vbuf *mgr);
void u_vbuf_restore_vertex_elements(struct u_vbuf *mgr);
void u_vbuf_save_aux_vertex_buffer_slot(struct u_vbuf *mgr);
void u_vbuf_restore_aux_vertex_buffer_slot(struct u_vbuf *mgr);
 
#endif
/drivers/video/Gallium/auxiliary/util/u_video.h
0,0 → 1,75
/**************************************************************************
*
* Copyright 2009 Younes Manton.
* 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.
*
**************************************************************************/
 
#ifndef U_VIDEO_H
#define U_VIDEO_H
 
#ifdef __cplusplus
extern "C" {
#endif
 
#include "pipe/p_defines.h"
#include "pipe/p_video_enums.h"
 
/* u_reduce_video_profile() needs these */
#include "pipe/p_compiler.h"
#include "util/u_debug.h"
 
static INLINE enum pipe_video_codec
u_reduce_video_profile(enum pipe_video_profile profile)
{
switch (profile)
{
case PIPE_VIDEO_PROFILE_MPEG1:
case PIPE_VIDEO_PROFILE_MPEG2_SIMPLE:
case PIPE_VIDEO_PROFILE_MPEG2_MAIN:
return PIPE_VIDEO_CODEC_MPEG12;
 
case PIPE_VIDEO_PROFILE_MPEG4_SIMPLE:
case PIPE_VIDEO_PROFILE_MPEG4_ADVANCED_SIMPLE:
return PIPE_VIDEO_CODEC_MPEG4;
 
case PIPE_VIDEO_PROFILE_VC1_SIMPLE:
case PIPE_VIDEO_PROFILE_VC1_MAIN:
case PIPE_VIDEO_PROFILE_VC1_ADVANCED:
return PIPE_VIDEO_CODEC_VC1;
 
case PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE:
case PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN:
case PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH:
return PIPE_VIDEO_CODEC_MPEG4_AVC;
 
default:
return PIPE_VIDEO_CODEC_UNKNOWN;
}
}
 
#ifdef __cplusplus
}
#endif
 
#endif /* U_VIDEO_H */
/drivers/video/Gallium/auxiliary/vl/vl_compositor.c
0,0 → 1,1096
/**************************************************************************
*
* Copyright 2009 Younes Manton.
* 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.
*
**************************************************************************/
 
#include <assert.h>
 
#include "pipe/p_compiler.h"
#include "pipe/p_context.h"
 
#include "util/u_memory.h"
#include "util/u_draw.h"
#include "util/u_surface.h"
 
#include "tgsi/tgsi_ureg.h"
 
#include "vl_csc.h"
#include "vl_types.h"
#include "vl_compositor.h"
 
#define MIN_DIRTY (0)
#define MAX_DIRTY (1 << 15)
 
enum VS_OUTPUT
{
VS_O_VPOS = 0,
VS_O_COLOR = 0,
VS_O_VTEX = 0,
VS_O_VTOP,
VS_O_VBOTTOM,
};
 
static void *
create_vert_shader(struct vl_compositor *c)
{
struct ureg_program *shader;
struct ureg_src vpos, vtex, color;
struct ureg_dst tmp;
struct ureg_dst o_vpos, o_vtex, o_color;
struct ureg_dst o_vtop, o_vbottom;
 
shader = ureg_create(TGSI_PROCESSOR_VERTEX);
if (!shader)
return false;
 
vpos = ureg_DECL_vs_input(shader, 0);
vtex = ureg_DECL_vs_input(shader, 1);
color = ureg_DECL_vs_input(shader, 2);
tmp = ureg_DECL_temporary(shader);
o_vpos = ureg_DECL_output(shader, TGSI_SEMANTIC_POSITION, VS_O_VPOS);
o_color = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, VS_O_COLOR);
o_vtex = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX);
o_vtop = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTOP);
o_vbottom = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_VBOTTOM);
 
/*
* o_vpos = vpos
* o_vtex = vtex
* o_color = color
*/
ureg_MOV(shader, o_vpos, vpos);
ureg_MOV(shader, o_vtex, vtex);
ureg_MOV(shader, o_color, color);
 
/*
* tmp.x = vtex.w / 2
* tmp.y = vtex.w / 4
*
* o_vtop.x = vtex.x
* o_vtop.y = vtex.y * tmp.x + 0.25f
* o_vtop.z = vtex.y * tmp.y + 0.25f
* o_vtop.w = 1 / tmp.x
*
* o_vbottom.x = vtex.x
* o_vbottom.y = vtex.y * tmp.x - 0.25f
* o_vbottom.z = vtex.y * tmp.y - 0.25f
* o_vbottom.w = 1 / tmp.y
*/
ureg_MUL(shader, ureg_writemask(tmp, TGSI_WRITEMASK_X),
ureg_scalar(vtex, TGSI_SWIZZLE_W), ureg_imm1f(shader, 0.5f));
ureg_MUL(shader, ureg_writemask(tmp, TGSI_WRITEMASK_Y),
ureg_scalar(vtex, TGSI_SWIZZLE_W), ureg_imm1f(shader, 0.25f));
 
ureg_MOV(shader, ureg_writemask(o_vtop, TGSI_WRITEMASK_X), vtex);
ureg_MAD(shader, ureg_writemask(o_vtop, TGSI_WRITEMASK_Y), ureg_scalar(vtex, TGSI_SWIZZLE_Y),
ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X), ureg_imm1f(shader, 0.25f));
ureg_MAD(shader, ureg_writemask(o_vtop, TGSI_WRITEMASK_Z), ureg_scalar(vtex, TGSI_SWIZZLE_Y),
ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_Y), ureg_imm1f(shader, 0.25f));
ureg_RCP(shader, ureg_writemask(o_vtop, TGSI_WRITEMASK_W),
ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X));
 
ureg_MOV(shader, ureg_writemask(o_vbottom, TGSI_WRITEMASK_X), vtex);
ureg_MAD(shader, ureg_writemask(o_vbottom, TGSI_WRITEMASK_Y), ureg_scalar(vtex, TGSI_SWIZZLE_Y),
ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X), ureg_imm1f(shader, -0.25f));
ureg_MAD(shader, ureg_writemask(o_vbottom, TGSI_WRITEMASK_Z), ureg_scalar(vtex, TGSI_SWIZZLE_Y),
ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_Y), ureg_imm1f(shader, -0.25f));
ureg_RCP(shader, ureg_writemask(o_vbottom, TGSI_WRITEMASK_W),
ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_Y));
 
ureg_END(shader);
 
return ureg_create_shader_and_destroy(shader, c->pipe);
}
 
static void *
create_frag_shader_video_buffer(struct vl_compositor *c)
{
struct ureg_program *shader;
struct ureg_src tc;
struct ureg_src csc[3];
struct ureg_src sampler[3];
struct ureg_dst texel;
struct ureg_dst fragment;
unsigned i;
 
shader = ureg_create(TGSI_PROCESSOR_FRAGMENT);
if (!shader)
return false;
 
tc = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX, TGSI_INTERPOLATE_LINEAR);
for (i = 0; i < 3; ++i) {
csc[i] = ureg_DECL_constant(shader, i);
sampler[i] = ureg_DECL_sampler(shader, i);
}
texel = ureg_DECL_temporary(shader);
fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0);
 
/*
* texel.xyz = tex(tc, sampler[i])
* fragment = csc * texel
*/
for (i = 0; i < 3; ++i)
ureg_TEX(shader, ureg_writemask(texel, TGSI_WRITEMASK_X << i), TGSI_TEXTURE_2D_ARRAY, tc, sampler[i]);
 
ureg_MOV(shader, ureg_writemask(texel, TGSI_WRITEMASK_W), ureg_imm1f(shader, 1.0f));
 
for (i = 0; i < 3; ++i)
ureg_DP4(shader, ureg_writemask(fragment, TGSI_WRITEMASK_X << i), csc[i], ureg_src(texel));
 
ureg_MOV(shader, ureg_writemask(fragment, TGSI_WRITEMASK_W), ureg_imm1f(shader, 1.0f));
 
ureg_release_temporary(shader, texel);
ureg_END(shader);
 
return ureg_create_shader_and_destroy(shader, c->pipe);
}
 
static void *
create_frag_shader_weave(struct vl_compositor *c)
{
struct ureg_program *shader;
struct ureg_src i_tc[2];
struct ureg_src csc[3];
struct ureg_src sampler[3];
struct ureg_dst t_tc[2];
struct ureg_dst t_texel[2];
struct ureg_dst o_fragment;
unsigned i, j;
 
shader = ureg_create(TGSI_PROCESSOR_FRAGMENT);
if (!shader)
return false;
 
i_tc[0] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTOP, TGSI_INTERPOLATE_LINEAR);
i_tc[1] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VBOTTOM, TGSI_INTERPOLATE_LINEAR);
 
for (i = 0; i < 3; ++i) {
csc[i] = ureg_DECL_constant(shader, i);
sampler[i] = ureg_DECL_sampler(shader, i);
}
 
for (i = 0; i < 2; ++i) {
t_tc[i] = ureg_DECL_temporary(shader);
t_texel[i] = ureg_DECL_temporary(shader);
}
o_fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0);
 
/* calculate the texture offsets
* t_tc.x = i_tc.x
* t_tc.y = (round(i_tc.y - 0.5) + 0.5) / height * 2
*/
for (i = 0; i < 2; ++i) {
ureg_MOV(shader, ureg_writemask(t_tc[i], TGSI_WRITEMASK_X), i_tc[i]);
ureg_SUB(shader, ureg_writemask(t_tc[i], TGSI_WRITEMASK_YZ),
i_tc[i], ureg_imm1f(shader, 0.5f));
ureg_ROUND(shader, ureg_writemask(t_tc[i], TGSI_WRITEMASK_YZ), ureg_src(t_tc[i]));
ureg_MOV(shader, ureg_writemask(t_tc[i], TGSI_WRITEMASK_W),
ureg_imm1f(shader, i ? 1.0f : 0.0f));
ureg_ADD(shader, ureg_writemask(t_tc[i], TGSI_WRITEMASK_YZ),
ureg_src(t_tc[i]), ureg_imm1f(shader, 0.5f));
ureg_MUL(shader, ureg_writemask(t_tc[i], TGSI_WRITEMASK_Y),
ureg_src(t_tc[i]), ureg_scalar(i_tc[0], TGSI_SWIZZLE_W));
ureg_MUL(shader, ureg_writemask(t_tc[i], TGSI_WRITEMASK_Z),
ureg_src(t_tc[i]), ureg_scalar(i_tc[1], TGSI_SWIZZLE_W));
}
 
/* fetch the texels
* texel[0..1].x = tex(t_tc[0..1][0])
* texel[0..1].y = tex(t_tc[0..1][1])
* texel[0..1].z = tex(t_tc[0..1][2])
*/
for (i = 0; i < 2; ++i)
for (j = 0; j < 3; ++j) {
struct ureg_src src = ureg_swizzle(ureg_src(t_tc[i]),
TGSI_SWIZZLE_X, j ? TGSI_SWIZZLE_Z : TGSI_SWIZZLE_Y, TGSI_SWIZZLE_W, TGSI_SWIZZLE_W);
 
ureg_TEX(shader, ureg_writemask(t_texel[i], TGSI_WRITEMASK_X << j),
TGSI_TEXTURE_2D_ARRAY, src, sampler[j]);
}
 
/* calculate linear interpolation factor
* factor = |round(i_tc.y) - i_tc.y| * 2
*/
ureg_ROUND(shader, ureg_writemask(t_tc[0], TGSI_WRITEMASK_YZ), i_tc[0]);
ureg_ADD(shader, ureg_writemask(t_tc[0], TGSI_WRITEMASK_YZ),
ureg_src(t_tc[0]), ureg_negate(i_tc[0]));
ureg_MUL(shader, ureg_writemask(t_tc[0], TGSI_WRITEMASK_YZ),
ureg_abs(ureg_src(t_tc[0])), ureg_imm1f(shader, 2.0f));
ureg_LRP(shader, t_texel[0], ureg_swizzle(ureg_src(t_tc[0]),
TGSI_SWIZZLE_Y, TGSI_SWIZZLE_Z, TGSI_SWIZZLE_Z, TGSI_SWIZZLE_Z),
ureg_src(t_texel[0]), ureg_src(t_texel[1]));
 
/* and finally do colour space transformation
* fragment = csc * texel
*/
ureg_MOV(shader, ureg_writemask(t_texel[0], TGSI_WRITEMASK_W), ureg_imm1f(shader, 1.0f));
for (i = 0; i < 3; ++i)
ureg_DP4(shader, ureg_writemask(o_fragment, TGSI_WRITEMASK_X << i), csc[i], ureg_src(t_texel[0]));
 
ureg_MOV(shader, ureg_writemask(o_fragment, TGSI_WRITEMASK_W), ureg_imm1f(shader, 1.0f));
 
for (i = 0; i < 2; ++i) {
ureg_release_temporary(shader, t_texel[i]);
ureg_release_temporary(shader, t_tc[i]);
}
 
ureg_END(shader);
 
return ureg_create_shader_and_destroy(shader, c->pipe);
}
 
static void *
create_frag_shader_palette(struct vl_compositor *c, bool include_cc)
{
struct ureg_program *shader;
struct ureg_src csc[3];
struct ureg_src tc;
struct ureg_src sampler;
struct ureg_src palette;
struct ureg_dst texel;
struct ureg_dst fragment;
unsigned i;
 
shader = ureg_create(TGSI_PROCESSOR_FRAGMENT);
if (!shader)
return false;
 
for (i = 0; include_cc && i < 3; ++i)
csc[i] = ureg_DECL_constant(shader, i);
 
tc = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX, TGSI_INTERPOLATE_LINEAR);
sampler = ureg_DECL_sampler(shader, 0);
palette = ureg_DECL_sampler(shader, 1);
 
texel = ureg_DECL_temporary(shader);
fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0);
 
/*
* texel = tex(tc, sampler)
* fragment.xyz = tex(texel, palette) * csc
* fragment.a = texel.a
*/
ureg_TEX(shader, texel, TGSI_TEXTURE_2D, tc, sampler);
ureg_MOV(shader, ureg_writemask(fragment, TGSI_WRITEMASK_W), ureg_src(texel));
 
if (include_cc) {
ureg_TEX(shader, texel, TGSI_TEXTURE_1D, ureg_src(texel), palette);
for (i = 0; i < 3; ++i)
ureg_DP4(shader, ureg_writemask(fragment, TGSI_WRITEMASK_X << i), csc[i], ureg_src(texel));
} else {
ureg_TEX(shader, ureg_writemask(fragment, TGSI_WRITEMASK_XYZ),
TGSI_TEXTURE_1D, ureg_src(texel), palette);
}
 
ureg_release_temporary(shader, texel);
ureg_END(shader);
 
return ureg_create_shader_and_destroy(shader, c->pipe);
}
 
static void *
create_frag_shader_rgba(struct vl_compositor *c)
{
struct ureg_program *shader;
struct ureg_src tc, color, sampler;
struct ureg_dst texel, fragment;
 
shader = ureg_create(TGSI_PROCESSOR_FRAGMENT);
if (!shader)
return false;
 
tc = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX, TGSI_INTERPOLATE_LINEAR);
color = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_COLOR, VS_O_COLOR, TGSI_INTERPOLATE_LINEAR);
sampler = ureg_DECL_sampler(shader, 0);
texel = ureg_DECL_temporary(shader);
fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0);
 
/*
* fragment = tex(tc, sampler)
*/
ureg_TEX(shader, texel, TGSI_TEXTURE_2D, tc, sampler);
ureg_MUL(shader, fragment, ureg_src(texel), color);
ureg_END(shader);
 
return ureg_create_shader_and_destroy(shader, c->pipe);
}
 
static bool
init_shaders(struct vl_compositor *c)
{
assert(c);
 
c->vs = create_vert_shader(c);
if (!c->vs) {
debug_printf("Unable to create vertex shader.\n");
return false;
}
 
c->fs_video_buffer = create_frag_shader_video_buffer(c);
if (!c->fs_video_buffer) {
debug_printf("Unable to create YCbCr-to-RGB fragment shader.\n");
return false;
}
 
c->fs_weave = create_frag_shader_weave(c);
if (!c->fs_weave) {
debug_printf("Unable to create YCbCr-to-RGB weave fragment shader.\n");
return false;
}
 
c->fs_palette.yuv = create_frag_shader_palette(c, true);
if (!c->fs_palette.yuv) {
debug_printf("Unable to create YUV-Palette-to-RGB fragment shader.\n");
return false;
}
 
c->fs_palette.rgb = create_frag_shader_palette(c, false);
if (!c->fs_palette.rgb) {
debug_printf("Unable to create RGB-Palette-to-RGB fragment shader.\n");
return false;
}
 
c->fs_rgba = create_frag_shader_rgba(c);
if (!c->fs_rgba) {
debug_printf("Unable to create RGB-to-RGB fragment shader.\n");
return false;
}
 
return true;
}
 
static void cleanup_shaders(struct vl_compositor *c)
{
assert(c);
 
c->pipe->delete_vs_state(c->pipe, c->vs);
c->pipe->delete_fs_state(c->pipe, c->fs_video_buffer);
c->pipe->delete_fs_state(c->pipe, c->fs_weave);
c->pipe->delete_fs_state(c->pipe, c->fs_palette.yuv);
c->pipe->delete_fs_state(c->pipe, c->fs_palette.rgb);
c->pipe->delete_fs_state(c->pipe, c->fs_rgba);
}
 
static bool
init_pipe_state(struct vl_compositor *c)
{
struct pipe_rasterizer_state rast;
struct pipe_sampler_state sampler;
struct pipe_blend_state blend;
struct pipe_depth_stencil_alpha_state dsa;
unsigned i;
 
assert(c);
 
c->fb_state.nr_cbufs = 1;
c->fb_state.zsbuf = NULL;
 
memset(&sampler, 0, sizeof(sampler));
sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
sampler.wrap_r = PIPE_TEX_WRAP_REPEAT;
sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR;
sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR;
sampler.compare_mode = PIPE_TEX_COMPARE_NONE;
sampler.compare_func = PIPE_FUNC_ALWAYS;
sampler.normalized_coords = 1;
 
c->sampler_linear = c->pipe->create_sampler_state(c->pipe, &sampler);
 
sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
c->sampler_nearest = c->pipe->create_sampler_state(c->pipe, &sampler);
 
memset(&blend, 0, sizeof blend);
blend.independent_blend_enable = 0;
blend.rt[0].blend_enable = 0;
blend.logicop_enable = 0;
blend.logicop_func = PIPE_LOGICOP_CLEAR;
blend.rt[0].colormask = PIPE_MASK_RGBA;
blend.dither = 0;
c->blend_clear = c->pipe->create_blend_state(c->pipe, &blend);
 
blend.rt[0].blend_enable = 1;
blend.rt[0].rgb_func = PIPE_BLEND_ADD;
blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
blend.rt[0].alpha_func = PIPE_BLEND_ADD;
blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
c->blend_add = c->pipe->create_blend_state(c->pipe, &blend);
 
memset(&rast, 0, sizeof rast);
rast.flatshade = 0;
rast.front_ccw = 1;
rast.cull_face = PIPE_FACE_NONE;
rast.fill_back = PIPE_POLYGON_MODE_FILL;
rast.fill_front = PIPE_POLYGON_MODE_FILL;
rast.scissor = 1;
rast.line_width = 1;
rast.point_size_per_vertex = 1;
rast.offset_units = 1;
rast.offset_scale = 1;
rast.half_pixel_center = 1;
rast.bottom_edge_rule = 1;
rast.depth_clip = 1;
 
c->rast = c->pipe->create_rasterizer_state(c->pipe, &rast);
 
memset(&dsa, 0, sizeof dsa);
dsa.depth.enabled = 0;
dsa.depth.writemask = 0;
dsa.depth.func = PIPE_FUNC_ALWAYS;
for (i = 0; i < 2; ++i) {
dsa.stencil[i].enabled = 0;
dsa.stencil[i].func = PIPE_FUNC_ALWAYS;
dsa.stencil[i].fail_op = PIPE_STENCIL_OP_KEEP;
dsa.stencil[i].zpass_op = PIPE_STENCIL_OP_KEEP;
dsa.stencil[i].zfail_op = PIPE_STENCIL_OP_KEEP;
dsa.stencil[i].valuemask = 0;
dsa.stencil[i].writemask = 0;
}
dsa.alpha.enabled = 0;
dsa.alpha.func = PIPE_FUNC_ALWAYS;
dsa.alpha.ref_value = 0;
c->dsa = c->pipe->create_depth_stencil_alpha_state(c->pipe, &dsa);
c->pipe->bind_depth_stencil_alpha_state(c->pipe, c->dsa);
 
return true;
}
 
static void cleanup_pipe_state(struct vl_compositor *c)
{
assert(c);
 
/* Asserted in softpipe_delete_fs_state() for some reason */
c->pipe->bind_vs_state(c->pipe, NULL);
c->pipe->bind_fs_state(c->pipe, NULL);
 
c->pipe->delete_depth_stencil_alpha_state(c->pipe, c->dsa);
c->pipe->delete_sampler_state(c->pipe, c->sampler_linear);
c->pipe->delete_sampler_state(c->pipe, c->sampler_nearest);
c->pipe->delete_blend_state(c->pipe, c->blend_clear);
c->pipe->delete_blend_state(c->pipe, c->blend_add);
c->pipe->delete_rasterizer_state(c->pipe, c->rast);
}
 
static bool
create_vertex_buffer(struct vl_compositor *c)
{
assert(c);
 
pipe_resource_reference(&c->vertex_buf.buffer, NULL);
c->vertex_buf.buffer = pipe_buffer_create
(
c->pipe->screen,
PIPE_BIND_VERTEX_BUFFER,
PIPE_USAGE_STREAM,
c->vertex_buf.stride * VL_COMPOSITOR_MAX_LAYERS * 4
);
 
return c->vertex_buf.buffer != NULL;
}
 
static bool
init_buffers(struct vl_compositor *c)
{
struct pipe_vertex_element vertex_elems[3];
 
assert(c);
 
/*
* Create our vertex buffer and vertex buffer elements
*/
c->vertex_buf.stride = sizeof(struct vertex2f) + sizeof(struct vertex4f) * 2;
c->vertex_buf.buffer_offset = 0;
create_vertex_buffer(c);
 
vertex_elems[0].src_offset = 0;
vertex_elems[0].instance_divisor = 0;
vertex_elems[0].vertex_buffer_index = 0;
vertex_elems[0].src_format = PIPE_FORMAT_R32G32_FLOAT;
vertex_elems[1].src_offset = sizeof(struct vertex2f);
vertex_elems[1].instance_divisor = 0;
vertex_elems[1].vertex_buffer_index = 0;
vertex_elems[1].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
vertex_elems[2].src_offset = sizeof(struct vertex2f) + sizeof(struct vertex4f);
vertex_elems[2].instance_divisor = 0;
vertex_elems[2].vertex_buffer_index = 0;
vertex_elems[2].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
c->vertex_elems_state = c->pipe->create_vertex_elements_state(c->pipe, 3, vertex_elems);
 
return true;
}
 
static void
cleanup_buffers(struct vl_compositor *c)
{
assert(c);
 
c->pipe->delete_vertex_elements_state(c->pipe, c->vertex_elems_state);
pipe_resource_reference(&c->vertex_buf.buffer, NULL);
}
 
static INLINE struct u_rect
default_rect(struct vl_compositor_layer *layer)
{
struct pipe_resource *res = layer->sampler_views[0]->texture;
struct u_rect rect = { 0, res->width0, 0, res->height0 * res->array_size };
return rect;
}
 
static INLINE struct vertex2f
calc_topleft(struct vertex2f size, struct u_rect rect)
{
struct vertex2f res = { rect.x0 / size.x, rect.y0 / size.y };
return res;
}
 
static INLINE struct vertex2f
calc_bottomright(struct vertex2f size, struct u_rect rect)
{
struct vertex2f res = { rect.x1 / size.x, rect.y1 / size.y };
return res;
}
 
static INLINE void
calc_src_and_dst(struct vl_compositor_layer *layer, unsigned width, unsigned height,
struct u_rect src, struct u_rect dst)
{
struct vertex2f size = { width, height };
 
layer->src.tl = calc_topleft(size, src);
layer->src.br = calc_bottomright(size, src);
layer->dst.tl = calc_topleft(size, dst);
layer->dst.br = calc_bottomright(size, dst);
layer->zw.x = 0.0f;
layer->zw.y = size.y;
}
 
static void
gen_rect_verts(struct vertex2f *vb, struct vl_compositor_layer *layer)
{
assert(vb && layer);
 
vb[ 0].x = layer->dst.tl.x;
vb[ 0].y = layer->dst.tl.y;
vb[ 1].x = layer->src.tl.x;
vb[ 1].y = layer->src.tl.y;
vb[ 2] = layer->zw;
vb[ 3].x = layer->colors[0].x;
vb[ 3].y = layer->colors[0].y;
vb[ 4].x = layer->colors[0].z;
vb[ 4].y = layer->colors[0].w;
 
vb[ 5].x = layer->dst.br.x;
vb[ 5].y = layer->dst.tl.y;
vb[ 6].x = layer->src.br.x;
vb[ 6].y = layer->src.tl.y;
vb[ 7] = layer->zw;
vb[ 8].x = layer->colors[1].x;
vb[ 8].y = layer->colors[1].y;
vb[ 9].x = layer->colors[1].z;
vb[ 9].y = layer->colors[1].w;
 
vb[10].x = layer->dst.br.x;
vb[10].y = layer->dst.br.y;
vb[11].x = layer->src.br.x;
vb[11].y = layer->src.br.y;
vb[12] = layer->zw;
vb[13].x = layer->colors[2].x;
vb[13].y = layer->colors[2].y;
vb[14].x = layer->colors[2].z;
vb[14].y = layer->colors[2].w;
 
vb[15].x = layer->dst.tl.x;
vb[15].y = layer->dst.br.y;
vb[16].x = layer->src.tl.x;
vb[16].y = layer->src.br.y;
vb[17] = layer->zw;
vb[18].x = layer->colors[3].x;
vb[18].y = layer->colors[3].y;
vb[19].x = layer->colors[3].z;
vb[19].y = layer->colors[3].w;
}
 
static INLINE struct u_rect
calc_drawn_area(struct vl_compositor_state *s, struct vl_compositor_layer *layer)
{
struct u_rect result;
 
// scale
result.x0 = layer->dst.tl.x * layer->viewport.scale[0] + layer->viewport.translate[0];
result.y0 = layer->dst.tl.y * layer->viewport.scale[1] + layer->viewport.translate[1];
result.x1 = layer->dst.br.x * layer->viewport.scale[0] + layer->viewport.translate[0];
result.y1 = layer->dst.br.y * layer->viewport.scale[1] + layer->viewport.translate[1];
 
// and clip
result.x0 = MAX2(result.x0, s->scissor.minx);
result.y0 = MAX2(result.y0, s->scissor.miny);
result.x1 = MIN2(result.x1, s->scissor.maxx);
result.y1 = MIN2(result.y1, s->scissor.maxy);
return result;
}
 
static void
gen_vertex_data(struct vl_compositor *c, struct vl_compositor_state *s, struct u_rect *dirty)
{
struct vertex2f *vb;
struct pipe_transfer *buf_transfer;
unsigned i;
 
assert(c);
 
vb = pipe_buffer_map(c->pipe, c->vertex_buf.buffer,
PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE | PIPE_TRANSFER_DONTBLOCK,
&buf_transfer);
 
if (!vb) {
// If buffer is still locked from last draw create a new one
create_vertex_buffer(c);
vb = pipe_buffer_map(c->pipe, c->vertex_buf.buffer,
PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE,
&buf_transfer);
}
 
for (i = 0; i < VL_COMPOSITOR_MAX_LAYERS; i++) {
if (s->used_layers & (1 << i)) {
struct vl_compositor_layer *layer = &s->layers[i];
gen_rect_verts(vb, layer);
vb += 20;
 
if (!layer->viewport_valid) {
layer->viewport.scale[0] = c->fb_state.width;
layer->viewport.scale[1] = c->fb_state.height;
layer->viewport.translate[0] = 0;
layer->viewport.translate[1] = 0;
}
 
if (dirty && layer->clearing) {
struct u_rect drawn = calc_drawn_area(s, layer);
if (
dirty->x0 >= drawn.x0 &&
dirty->y0 >= drawn.y0 &&
dirty->x1 <= drawn.x1 &&
dirty->y1 <= drawn.y1) {
 
// We clear the dirty area anyway, no need for clear_render_target
dirty->x0 = dirty->y0 = MAX_DIRTY;
dirty->x1 = dirty->y1 = MIN_DIRTY;
}
}
}
}
 
pipe_buffer_unmap(c->pipe, buf_transfer);
}
 
static void
draw_layers(struct vl_compositor *c, struct vl_compositor_state *s, struct u_rect *dirty)
{
unsigned vb_index, i;
 
assert(c);
 
for (i = 0, vb_index = 0; i < VL_COMPOSITOR_MAX_LAYERS; ++i) {
if (s->used_layers & (1 << i)) {
struct vl_compositor_layer *layer = &s->layers[i];
struct pipe_sampler_view **samplers = &layer->sampler_views[0];
unsigned num_sampler_views = !samplers[1] ? 1 : !samplers[2] ? 2 : 3;
void *blend = layer->blend ? layer->blend : i ? c->blend_add : c->blend_clear;
 
c->pipe->bind_blend_state(c->pipe, blend);
c->pipe->set_viewport_states(c->pipe, 0, 1, &layer->viewport);
c->pipe->bind_fs_state(c->pipe, layer->fs);
c->pipe->bind_fragment_sampler_states(c->pipe, num_sampler_views, layer->samplers);
c->pipe->set_fragment_sampler_views(c->pipe, num_sampler_views, samplers);
util_draw_arrays(c->pipe, PIPE_PRIM_QUADS, vb_index * 4, 4);
vb_index++;
 
if (dirty) {
// Remember the currently drawn area as dirty for the next draw command
struct u_rect drawn = calc_drawn_area(s, layer);
dirty->x0 = MIN2(drawn.x0, dirty->x0);
dirty->y0 = MIN2(drawn.y0, dirty->y0);
dirty->x1 = MAX2(drawn.x1, dirty->x1);
dirty->y1 = MAX2(drawn.y1, dirty->y1);
}
}
}
}
 
void
vl_compositor_reset_dirty_area(struct u_rect *dirty)
{
assert(dirty);
 
dirty->x0 = dirty->y0 = MIN_DIRTY;
dirty->x1 = dirty->y1 = MAX_DIRTY;
}
 
void
vl_compositor_set_clear_color(struct vl_compositor_state *s, union pipe_color_union *color)
{
assert(s);
assert(color);
 
s->clear_color = *color;
}
 
void
vl_compositor_get_clear_color(struct vl_compositor_state *s, union pipe_color_union *color)
{
assert(s);
assert(color);
 
*color = s->clear_color;
}
 
void
vl_compositor_clear_layers(struct vl_compositor_state *s)
{
unsigned i, j;
 
assert(s);
 
s->used_layers = 0;
for ( i = 0; i < VL_COMPOSITOR_MAX_LAYERS; ++i) {
struct vertex4f v_one = { 1.0f, 1.0f, 1.0f, 1.0f };
s->layers[i].clearing = i ? false : true;
s->layers[i].blend = NULL;
s->layers[i].fs = NULL;
s->layers[i].viewport.scale[2] = 1;
s->layers[i].viewport.scale[3] = 1;
s->layers[i].viewport.translate[2] = 0;
s->layers[i].viewport.translate[3] = 0;
 
for ( j = 0; j < 3; j++)
pipe_sampler_view_reference(&s->layers[i].sampler_views[j], NULL);
for ( j = 0; j < 4; ++j)
s->layers[i].colors[j] = v_one;
}
}
 
void
vl_compositor_cleanup(struct vl_compositor *c)
{
assert(c);
 
cleanup_buffers(c);
cleanup_shaders(c);
cleanup_pipe_state(c);
}
 
void
vl_compositor_set_csc_matrix(struct vl_compositor_state *s, vl_csc_matrix const *matrix)
{
struct pipe_transfer *buf_transfer;
 
assert(s);
 
memcpy
(
pipe_buffer_map(s->pipe, s->csc_matrix,
PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE,
&buf_transfer),
matrix,
sizeof(vl_csc_matrix)
);
 
pipe_buffer_unmap(s->pipe, buf_transfer);
}
 
void
vl_compositor_set_dst_clip(struct vl_compositor_state *s, struct u_rect *dst_clip)
{
assert(s);
 
s->scissor_valid = dst_clip != NULL;
if (dst_clip) {
s->scissor.minx = dst_clip->x0;
s->scissor.miny = dst_clip->y0;
s->scissor.maxx = dst_clip->x1;
s->scissor.maxy = dst_clip->y1;
}
}
 
void
vl_compositor_set_layer_blend(struct vl_compositor_state *s,
unsigned layer, void *blend,
bool is_clearing)
{
assert(s && blend);
 
assert(layer < VL_COMPOSITOR_MAX_LAYERS);
 
s->layers[layer].clearing = is_clearing;
s->layers[layer].blend = blend;
}
 
void
vl_compositor_set_layer_dst_area(struct vl_compositor_state *s,
unsigned layer, struct u_rect *dst_area)
{
assert(s);
 
assert(layer < VL_COMPOSITOR_MAX_LAYERS);
 
s->layers[layer].viewport_valid = dst_area != NULL;
if (dst_area) {
s->layers[layer].viewport.scale[0] = dst_area->x1 - dst_area->x0;
s->layers[layer].viewport.scale[1] = dst_area->y1 - dst_area->y0;
s->layers[layer].viewport.translate[0] = dst_area->x0;
s->layers[layer].viewport.translate[1] = dst_area->y0;
}
}
 
void
vl_compositor_set_buffer_layer(struct vl_compositor_state *s,
struct vl_compositor *c,
unsigned layer,
struct pipe_video_buffer *buffer,
struct u_rect *src_rect,
struct u_rect *dst_rect,
enum vl_compositor_deinterlace deinterlace)
{
struct pipe_sampler_view **sampler_views;
unsigned i;
 
assert(s && c && buffer);
 
assert(layer < VL_COMPOSITOR_MAX_LAYERS);
 
s->used_layers |= 1 << layer;
sampler_views = buffer->get_sampler_view_components(buffer);
for (i = 0; i < 3; ++i) {
s->layers[layer].samplers[i] = c->sampler_linear;
pipe_sampler_view_reference(&s->layers[layer].sampler_views[i], sampler_views[i]);
}
 
calc_src_and_dst(&s->layers[layer], buffer->width, buffer->height,
src_rect ? *src_rect : default_rect(&s->layers[layer]),
dst_rect ? *dst_rect : default_rect(&s->layers[layer]));
 
if (buffer->interlaced) {
float half_a_line = 0.5f / s->layers[layer].zw.y;
switch(deinterlace) {
case VL_COMPOSITOR_WEAVE:
s->layers[layer].fs = c->fs_weave;
break;
 
case VL_COMPOSITOR_BOB_TOP:
s->layers[layer].zw.x = 0.0f;
s->layers[layer].src.tl.y += half_a_line;
s->layers[layer].src.br.y += half_a_line;
s->layers[layer].fs = c->fs_video_buffer;
break;
 
case VL_COMPOSITOR_BOB_BOTTOM:
s->layers[layer].zw.x = 1.0f;
s->layers[layer].src.tl.y -= half_a_line;
s->layers[layer].src.br.y -= half_a_line;
s->layers[layer].fs = c->fs_video_buffer;
break;
}
 
} else
s->layers[layer].fs = c->fs_video_buffer;
}
 
void
vl_compositor_set_palette_layer(struct vl_compositor_state *s,
struct vl_compositor *c,
unsigned layer,
struct pipe_sampler_view *indexes,
struct pipe_sampler_view *palette,
struct u_rect *src_rect,
struct u_rect *dst_rect,
bool include_color_conversion)
{
assert(s && c && indexes && palette);
 
assert(layer < VL_COMPOSITOR_MAX_LAYERS);
 
s->used_layers |= 1 << layer;
 
s->layers[layer].fs = include_color_conversion ?
c->fs_palette.yuv : c->fs_palette.rgb;
 
s->layers[layer].samplers[0] = c->sampler_linear;
s->layers[layer].samplers[1] = c->sampler_nearest;
s->layers[layer].samplers[2] = NULL;
pipe_sampler_view_reference(&s->layers[layer].sampler_views[0], indexes);
pipe_sampler_view_reference(&s->layers[layer].sampler_views[1], palette);
pipe_sampler_view_reference(&s->layers[layer].sampler_views[2], NULL);
calc_src_and_dst(&s->layers[layer], indexes->texture->width0, indexes->texture->height0,
src_rect ? *src_rect : default_rect(&s->layers[layer]),
dst_rect ? *dst_rect : default_rect(&s->layers[layer]));
}
 
void
vl_compositor_set_rgba_layer(struct vl_compositor_state *s,
struct vl_compositor *c,
unsigned layer,
struct pipe_sampler_view *rgba,
struct u_rect *src_rect,
struct u_rect *dst_rect,
struct vertex4f *colors)
{
unsigned i;
 
assert(s && c && rgba);
 
assert(layer < VL_COMPOSITOR_MAX_LAYERS);
 
s->used_layers |= 1 << layer;
s->layers[layer].fs = c->fs_rgba;
s->layers[layer].samplers[0] = c->sampler_linear;
s->layers[layer].samplers[1] = NULL;
s->layers[layer].samplers[2] = NULL;
pipe_sampler_view_reference(&s->layers[layer].sampler_views[0], rgba);
pipe_sampler_view_reference(&s->layers[layer].sampler_views[1], NULL);
pipe_sampler_view_reference(&s->layers[layer].sampler_views[2], NULL);
calc_src_and_dst(&s->layers[layer], rgba->texture->width0, rgba->texture->height0,
src_rect ? *src_rect : default_rect(&s->layers[layer]),
dst_rect ? *dst_rect : default_rect(&s->layers[layer]));
 
if (colors)
for (i = 0; i < 4; ++i)
s->layers[layer].colors[i] = colors[i];
}
 
void
vl_compositor_render(struct vl_compositor_state *s,
struct vl_compositor *c,
struct pipe_surface *dst_surface,
struct u_rect *dirty_area,
bool clear_dirty)
{
assert(c);
assert(dst_surface);
 
c->fb_state.width = dst_surface->width;
c->fb_state.height = dst_surface->height;
c->fb_state.cbufs[0] = dst_surface;
if (!s->scissor_valid) {
s->scissor.minx = 0;
s->scissor.miny = 0;
s->scissor.maxx = dst_surface->width;
s->scissor.maxy = dst_surface->height;
}
 
gen_vertex_data(c, s, dirty_area);
 
if (clear_dirty && dirty_area &&
(dirty_area->x0 < dirty_area->x1 || dirty_area->y0 < dirty_area->y1)) {
 
c->pipe->clear_render_target(c->pipe, dst_surface, &s->clear_color,
0, 0, dst_surface->width, dst_surface->height);
dirty_area->x0 = dirty_area->y0 = MAX_DIRTY;
dirty_area->x1 = dirty_area->y1 = MIN_DIRTY;
}
 
c->pipe->set_scissor_states(c->pipe, 0, 1, &s->scissor);
c->pipe->set_framebuffer_state(c->pipe, &c->fb_state);
c->pipe->bind_vs_state(c->pipe, c->vs);
c->pipe->set_vertex_buffers(c->pipe, 0, 1, &c->vertex_buf);
c->pipe->bind_vertex_elements_state(c->pipe, c->vertex_elems_state);
pipe_set_constant_buffer(c->pipe, PIPE_SHADER_FRAGMENT, 0, s->csc_matrix);
c->pipe->bind_rasterizer_state(c->pipe, c->rast);
 
draw_layers(c, s, dirty_area);
}
 
bool
vl_compositor_init(struct vl_compositor *c, struct pipe_context *pipe)
{
assert(c);
 
memset(c, 0, sizeof(*c));
 
c->pipe = pipe;
 
if (!init_pipe_state(c))
return false;
 
if (!init_shaders(c)) {
cleanup_pipe_state(c);
return false;
}
 
if (!init_buffers(c)) {
cleanup_shaders(c);
cleanup_pipe_state(c);
return false;
}
 
return true;
}
 
bool
vl_compositor_init_state(struct vl_compositor_state *s, struct pipe_context *pipe)
{
vl_csc_matrix csc_matrix;
 
assert(s);
 
memset(s, 0, sizeof(*s));
 
s->pipe = pipe;
 
s->clear_color.f[0] = s->clear_color.f[1] = 0.0f;
s->clear_color.f[2] = s->clear_color.f[3] = 0.0f;
 
/*
* Create our fragment shader's constant buffer
* Const buffer contains the color conversion matrix and bias vectors
*/
/* XXX: Create with IMMUTABLE/STATIC... although it does change every once in a long while... */
s->csc_matrix = pipe_buffer_create
(
pipe->screen,
PIPE_BIND_CONSTANT_BUFFER,
PIPE_USAGE_STATIC,
sizeof(csc_matrix)
);
 
vl_compositor_clear_layers(s);
 
vl_csc_get_matrix(VL_CSC_COLOR_STANDARD_IDENTITY, NULL, true, &csc_matrix);
vl_compositor_set_csc_matrix(s, (const vl_csc_matrix *)&csc_matrix);
 
return true;
}
 
void
vl_compositor_cleanup_state(struct vl_compositor_state *s)
{
assert(s);
 
vl_compositor_clear_layers(s);
pipe_resource_reference(&s->csc_matrix, NULL);
}
/drivers/video/Gallium/auxiliary/vl/vl_compositor.h
0,0 → 1,242
/**************************************************************************
*
* Copyright 2009 Younes Manton.
* 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.
*
**************************************************************************/
 
#ifndef vl_compositor_h
#define vl_compositor_h
 
#include "pipe/p_state.h"
#include "pipe/p_video_decoder.h"
#include "pipe/p_video_state.h"
 
#include "util/u_rect.h"
 
#include "vl_types.h"
#include "vl_csc.h"
 
struct pipe_context;
 
/**
* composing and displaying of image data
*/
 
#define VL_COMPOSITOR_MAX_LAYERS 16
 
/* deinterlace allgorithem */
enum vl_compositor_deinterlace
{
VL_COMPOSITOR_WEAVE,
VL_COMPOSITOR_BOB_TOP,
VL_COMPOSITOR_BOB_BOTTOM
};
 
struct vl_compositor_layer
{
bool clearing;
 
bool viewport_valid;
struct pipe_viewport_state viewport;
 
void *fs;
void *samplers[3];
void *blend;
 
struct pipe_sampler_view *sampler_views[3];
struct {
struct vertex2f tl, br;
} src, dst;
struct vertex2f zw;
struct vertex4f colors[4];
};
 
struct vl_compositor_state
{
struct pipe_context *pipe;
 
bool scissor_valid;
struct pipe_scissor_state scissor;
struct pipe_resource *csc_matrix;
 
union pipe_color_union clear_color;
 
unsigned used_layers:VL_COMPOSITOR_MAX_LAYERS;
struct vl_compositor_layer layers[VL_COMPOSITOR_MAX_LAYERS];
};
 
struct vl_compositor
{
struct pipe_context *pipe;
 
struct pipe_framebuffer_state fb_state;
struct pipe_vertex_buffer vertex_buf;
 
void *sampler_linear;
void *sampler_nearest;
void *blend_clear, *blend_add;
void *rast;
void *dsa;
void *vertex_elems_state;
 
void *vs;
void *fs_video_buffer;
void *fs_weave;
void *fs_rgba;
 
struct {
void *rgb;
void *yuv;
} fs_palette;
};
 
/**
* initialize this compositor
*/
bool
vl_compositor_init(struct vl_compositor *compositor, struct pipe_context *pipe);
 
/**
* init state bag
*/
bool
vl_compositor_init_state(struct vl_compositor_state *state, struct pipe_context *pipe);
 
/**
* set yuv -> rgba conversion matrix
*/
void
vl_compositor_set_csc_matrix(struct vl_compositor_state *settings, const vl_csc_matrix *matrix);
 
/**
* reset dirty area, so it's cleared with the clear colour
*/
void
vl_compositor_reset_dirty_area(struct u_rect *dirty);
 
/**
* set the clear color
*/
void
vl_compositor_set_clear_color(struct vl_compositor_state *settings, union pipe_color_union *color);
 
/**
* get the clear color
*/
void
vl_compositor_get_clear_color(struct vl_compositor_state *settings, union pipe_color_union *color);
 
/**
* set the destination clipping
*/
void
vl_compositor_set_dst_clip(struct vl_compositor_state *settings, struct u_rect *dst_clip);
 
/**
* set overlay samplers
*/
/*@{*/
 
/**
* reset all currently set layers
*/
void
vl_compositor_clear_layers(struct vl_compositor_state *state);
 
/**
* set the blender used to render a layer
*/
void
vl_compositor_set_layer_blend(struct vl_compositor_state *state,
unsigned layer, void *blend, bool is_clearing);
 
/**
* set the layer destination area
*/
void
vl_compositor_set_layer_dst_area(struct vl_compositor_state *settings,
unsigned layer, struct u_rect *dst_area);
 
/**
* set a video buffer as a layer to render
*/
void
vl_compositor_set_buffer_layer(struct vl_compositor_state *state,
struct vl_compositor *compositor,
unsigned layer,
struct pipe_video_buffer *buffer,
struct u_rect *src_rect,
struct u_rect *dst_rect,
enum vl_compositor_deinterlace deinterlace);
 
/**
* set a paletted sampler as a layer to render
*/
void
vl_compositor_set_palette_layer(struct vl_compositor_state *state,
struct vl_compositor *compositor,
unsigned layer,
struct pipe_sampler_view *indexes,
struct pipe_sampler_view *palette,
struct u_rect *src_rect,
struct u_rect *dst_rect,
bool include_color_conversion);
 
/**
* set a rgba sampler as a layer to render
*/
void
vl_compositor_set_rgba_layer(struct vl_compositor_state *state,
struct vl_compositor *compositor,
unsigned layer,
struct pipe_sampler_view *rgba,
struct u_rect *src_rect,
struct u_rect *dst_rect,
struct vertex4f *colors);
 
/*@}*/
 
/**
* render the layers to the frontbuffer
*/
void
vl_compositor_render(struct vl_compositor_state *state,
struct vl_compositor *compositor,
struct pipe_surface *dst_surface,
struct u_rect *dirty_area,
bool clear_dirty);
 
/**
* destroy this compositor
*/
void
vl_compositor_cleanup(struct vl_compositor *compositor);
 
/**
* destroy this state bag
*/
void
vl_compositor_cleanup_state(struct vl_compositor_state *state);
 
#endif /* vl_compositor_h */
/drivers/video/Gallium/auxiliary/vl/vl_csc.c
0,0 → 1,230
/**************************************************************************
*
* Copyright 2009 Younes Manton.
* 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.
*
**************************************************************************/
 
#include "util/u_math.h"
#include "util/u_debug.h"
 
#include "vl_csc.h"
 
/*
* Color space conversion formulas
*
* To convert YCbCr to RGB,
* vec4 ycbcr, rgb
* mat44 csc
* rgb = csc * ycbcr
*
* To calculate the color space conversion matrix csc with ProcAmp adjustments,
* mat44 csc, cstd, procamp, bias
* csc = cstd * (procamp * bias)
*
* Where cstd is a matrix corresponding to one of the color standards (BT.601, BT.709, etc)
* adjusted for the kind of YCbCr -> RGB mapping wanted (1:1, full),
* bias is a matrix corresponding to the kind of YCbCr -> RGB mapping wanted (1:1, full)
*
* To calculate procamp,
* mat44 procamp, hue, saturation, brightness, contrast
* procamp = brightness * (saturation * (contrast * hue))
* Alternatively,
* procamp = saturation * (brightness * (contrast * hue))
*
* contrast
* [ c, 0, 0, 0]
* [ 0, c, 0, 0]
* [ 0, 0, c, 0]
* [ 0, 0, 0, 1]
*
* brightness
* [ 1, 0, 0, b]
* [ 0, 1, 0, 0]
* [ 0, 0, 1, 0]
* [ 0, 0, 0, 1]
*
* saturation
* [ 1, 0, 0, 0]
* [ 0, s, 0, 0]
* [ 0, 0, s, 0]
* [ 0, 0, 0, 1]
*
* hue
* [ 1, 0, 0, 0]
* [ 0, cos(h), sin(h), 0]
* [ 0, -sin(h), cos(h), 0]
* [ 0, 0, 0, 1]
*
* procamp
* [ c, 0, 0, b]
* [ 0, c*s*cos(h), c*s*sin(h), 0]
* [ 0, -c*s*sin(h), c*s*cos(h), 0]
* [ 0, 0, 0, 1]
*
* bias
* [ 1, 0, 0, ybias]
* [ 0, 1, 0, cbbias]
* [ 0, 0, 1, crbias]
* [ 0, 0, 0, 1]
*
* csc
* [ c*cstd[ 0], c*cstd[ 1]*s*cos(h) - c*cstd[ 2]*s*sin(h), c*cstd[ 2]*s*cos(h) + c*cstd[ 1]*s*sin(h), cstd[ 3] + cstd[ 0]*(b + c*ybias) + cstd[ 1]*(c*cbbias*s*cos(h) + c*crbias*s*sin(h)) + cstd[ 2]*(c*crbias*s*cos(h) - c*cbbias*s*sin(h))]
* [ c*cstd[ 4], c*cstd[ 5]*s*cos(h) - c*cstd[ 6]*s*sin(h), c*cstd[ 6]*s*cos(h) + c*cstd[ 5]*s*sin(h), cstd[ 7] + cstd[ 4]*(b + c*ybias) + cstd[ 5]*(c*cbbias*s*cos(h) + c*crbias*s*sin(h)) + cstd[ 6]*(c*crbias*s*cos(h) - c*cbbias*s*sin(h))]
* [ c*cstd[ 8], c*cstd[ 9]*s*cos(h) - c*cstd[10]*s*sin(h), c*cstd[10]*s*cos(h) + c*cstd[ 9]*s*sin(h), cstd[11] + cstd[ 8]*(b + c*ybias) + cstd[ 9]*(c*cbbias*s*cos(h) + c*crbias*s*sin(h)) + cstd[10]*(c*crbias*s*cos(h) - c*cbbias*s*sin(h))]
* [ c*cstd[12], c*cstd[13]*s*cos(h) - c*cstd[14]*s*sin(h), c*cstd[14]*s*cos(h) + c*cstd[13]*s*sin(h), cstd[15] + cstd[12]*(b + c*ybias) + cstd[13]*(c*cbbias*s*cos(h) + c*crbias*s*sin(h)) + cstd[14]*(c*crbias*s*cos(h) - c*cbbias*s*sin(h))]
*/
 
/*
* Converts ITU-R BT.601 YCbCr pixels to RGB pixels where:
* Y is in [16,235], Cb and Cr are in [16,240]
* R, G, and B are in [16,235]
*/
static const vl_csc_matrix bt_601 =
{
{ 1.0f, 0.0f, 1.371f, 0.0f, },
{ 1.0f, -0.336f, -0.698f, 0.0f, },
{ 1.0f, 1.732f, 0.0f, 0.0f, }
};
 
/*
* Converts ITU-R BT.601 YCbCr pixels to RGB pixels where:
* Y is in [16,235], Cb and Cr are in [16,240]
* R, G, and B are in [0,255]
*/
static const vl_csc_matrix bt_601_full =
{
{ 1.164f, 0.0f, 1.596f, 0.0f, },
{ 1.164f, -0.391f, -0.813f, 0.0f, },
{ 1.164f, 2.018f, 0.0f, 0.0f, }
};
 
/*
* Converts ITU-R BT.709 YCbCr pixels to RGB pixels where:
* Y is in [16,235], Cb and Cr are in [16,240]
* R, G, and B are in [16,235]
*/
static const vl_csc_matrix bt_709 =
{
{ 1.0f, 0.0f, 1.540f, 0.0f, },
{ 1.0f, -0.183f, -0.459f, 0.0f, },
{ 1.0f, 1.816f, 0.0f, 0.0f, }
};
 
/*
* Converts ITU-R BT.709 YCbCr pixels to RGB pixels where:
* Y is in [16,235], Cb and Cr are in [16,240]
* R, G, and B are in [0,255]
*/
static const vl_csc_matrix bt_709_full =
{
{ 1.164f, 0.0f, 1.793f, 0.0f, },
{ 1.164f, -0.213f, -0.534f, 0.0f, },
{ 1.164f, 2.115f, 0.0f, 0.0f, }
};
 
static const vl_csc_matrix smpte240m =
{
{ 1.0f, 0.0f, 1.582f, 0.0f, },
{ 1.0f, -0.228f, -0.478f, 0.0f, },
{ 1.0f, 1.833f, 0.0f, 0.0f, }
};
 
static const vl_csc_matrix smpte240m_full =
{
{ 1.164f, 0.0f, 1.794f, 0.0f, },
{ 1.164f, -0.258f, -0.543f, 0.0f, },
{ 1.164f, 2.079f, 0.0f, 0.0f, }
};
 
static const vl_csc_matrix identity =
{
{ 1.0f, 0.0f, 0.0f, 0.0f, },
{ 0.0f, 1.0f, 0.0f, 0.0f, },
{ 0.0f, 0.0f, 1.0f, 0.0f, }
};
 
const struct vl_procamp vl_default_procamp = {
0.0f, /* brightness */
1.0f, /* contrast */
1.0f, /* saturation */
0.0f /* hue */
};
 
void vl_csc_get_matrix(enum VL_CSC_COLOR_STANDARD cs,
struct vl_procamp *procamp,
bool full_range,
vl_csc_matrix *matrix)
{
float ybias = full_range ? -16.0f/255.0f : 0.0f;
float cbbias = -128.0f/255.0f;
float crbias = -128.0f/255.0f;
 
const struct vl_procamp *p = procamp ? procamp : &vl_default_procamp;
float c = p->contrast;
float s = p->saturation;
float b = p->brightness;
float h = p->hue;
 
const vl_csc_matrix *cstd;
 
assert(matrix);
 
switch (cs) {
case VL_CSC_COLOR_STANDARD_BT_601:
cstd = full_range ? &bt_601_full : &bt_601;
break;
case VL_CSC_COLOR_STANDARD_BT_709:
cstd = full_range ? &bt_709_full : &bt_709;
break;
case VL_CSC_COLOR_STANDARD_SMPTE_240M:
cstd = full_range ? &smpte240m_full : &smpte240m;
break;
case VL_CSC_COLOR_STANDARD_IDENTITY:
default:
assert(cs == VL_CSC_COLOR_STANDARD_IDENTITY);
memcpy(matrix, identity, sizeof(vl_csc_matrix));
return;
}
 
(*matrix)[0][0] = c * (*cstd)[0][0];
(*matrix)[0][1] = c * (*cstd)[0][1] * s * cosf(h) - c * (*cstd)[0][2] * s * sinf(h);
(*matrix)[0][2] = c * (*cstd)[0][2] * s * cosf(h) + c * (*cstd)[0][1] * s * sinf(h);
(*matrix)[0][3] = (*cstd)[0][3] + (*cstd)[0][0] * (b + c * ybias) +
(*cstd)[0][1] * (c * cbbias * s * cosf(h) + c * crbias * s * sinf(h)) +
(*cstd)[0][2] * (c * crbias * s * cosf(h) - c * cbbias * s * sinf(h));
 
(*matrix)[1][0] = c * (*cstd)[1][0];
(*matrix)[1][1] = c * (*cstd)[1][1] * s * cosf(h) - c * (*cstd)[1][2] * s * sinf(h);
(*matrix)[1][2] = c * (*cstd)[1][2] * s * cosf(h) + c * (*cstd)[1][1] * s * sinf(h);
(*matrix)[1][3] = (*cstd)[1][3] + (*cstd)[1][0] * (b + c * ybias) +
(*cstd)[1][1] * (c * cbbias * s * cosf(h) + c * crbias * s * sinf(h)) +
(*cstd)[1][2] * (c * crbias * s * cosf(h) - c * cbbias * s * sinf(h));
 
(*matrix)[2][0] = c * (*cstd)[2][0];
(*matrix)[2][1] = c * (*cstd)[2][1] * s * cosf(h) - c * (*cstd)[2][2] * s * sinf(h);
(*matrix)[2][2] = c * (*cstd)[2][2] * s * cosf(h) + c * (*cstd)[2][1] * s * sinf(h);
(*matrix)[2][3] = (*cstd)[2][3] + (*cstd)[2][0] * (b + c * ybias) +
(*cstd)[2][1] * (c * cbbias * s * cosf(h) + c * crbias * s * sinf(h)) +
(*cstd)[2][2] * (c * crbias * s * cosf(h) - c * cbbias * s * sinf(h));
}
/drivers/video/Gallium/auxiliary/vl/vl_csc.h
0,0 → 1,58
/**************************************************************************
*
* Copyright 2009 Younes Manton.
* 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.
*
**************************************************************************/
 
#ifndef vl_csc_h
#define vl_csc_h
 
#include "pipe/p_compiler.h"
 
typedef float vl_csc_matrix[3][4];
 
struct vl_procamp
{
float brightness;
float contrast;
float saturation;
float hue;
};
 
enum VL_CSC_COLOR_STANDARD
{
VL_CSC_COLOR_STANDARD_IDENTITY,
VL_CSC_COLOR_STANDARD_BT_601,
VL_CSC_COLOR_STANDARD_BT_709,
VL_CSC_COLOR_STANDARD_SMPTE_240M
};
 
extern const struct vl_procamp vl_default_procamp;
 
void vl_csc_get_matrix(enum VL_CSC_COLOR_STANDARD cs,
struct vl_procamp *procamp,
bool full_range,
vl_csc_matrix *matrix);
 
#endif /* vl_csc_h */
/drivers/video/Gallium/auxiliary/vl/vl_decoder.c
0,0 → 1,80
/**************************************************************************
*
* Copyright 2009 Younes Manton.
* 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.
*
**************************************************************************/
 
#include "pipe/p_video_decoder.h"
 
#include "util/u_video.h"
 
#include "vl_decoder.h"
#include "vl_mpeg12_decoder.h"
 
bool
vl_profile_supported(struct pipe_screen *screen, enum pipe_video_profile profile)
{
assert(screen);
switch (u_reduce_video_profile(profile)) {
case PIPE_VIDEO_CODEC_MPEG12:
return true;
default:
return false;
}
}
 
struct pipe_video_decoder *
vl_create_decoder(struct pipe_context *pipe,
enum pipe_video_profile profile,
enum pipe_video_entrypoint entrypoint,
enum pipe_video_chroma_format chroma_format,
unsigned width, unsigned height, unsigned max_references,
bool expect_chunked_decode)
{
unsigned buffer_width, buffer_height;
bool pot_buffers;
 
assert(pipe);
assert(width > 0 && height > 0);
pot_buffers = !pipe->screen->get_video_param
(
pipe->screen,
profile,
PIPE_VIDEO_CAP_NPOT_TEXTURES
);
 
buffer_width = pot_buffers ? util_next_power_of_two(width) : align(width, VL_MACROBLOCK_WIDTH);
buffer_height = pot_buffers ? util_next_power_of_two(height) : align(height, VL_MACROBLOCK_HEIGHT);
 
switch (u_reduce_video_profile(profile)) {
case PIPE_VIDEO_CODEC_MPEG12:
return vl_create_mpeg12_decoder(pipe, profile, entrypoint, chroma_format,
buffer_width, buffer_height, max_references,
expect_chunked_decode);
default:
return NULL;
}
return NULL;
}
/drivers/video/Gallium/auxiliary/vl/vl_decoder.h
0,0 → 1,51
/**************************************************************************
*
* Copyright 2009 Younes Manton.
* Copyright 2011 Christian König.
* 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.
*
**************************************************************************/
 
#ifndef vl_decoder_h
#define vl_decoder_h
 
#include "pipe/p_video_decoder.h"
 
/**
* check if a given profile is supported with shader based decoding
*/
bool
vl_profile_supported(struct pipe_screen *screen, enum pipe_video_profile profile);
 
/**
* standard implementation of pipe->create_video_decoder
*/
struct pipe_video_decoder *
vl_create_decoder(struct pipe_context *pipe,
enum pipe_video_profile profile,
enum pipe_video_entrypoint entrypoint,
enum pipe_video_chroma_format chroma_format,
unsigned width, unsigned height, unsigned max_references,
bool expect_chunked_decode);
 
#endif /* vl_decoder_h */
/drivers/video/Gallium/auxiliary/vl/vl_defines.h
0,0 → 1,42
/**************************************************************************
*
* Copyright 2011 Christian König
* 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.
*
**************************************************************************/
 
#ifndef vl_defines_h
#define vl_defines_h
 
/* constants usually used with all known codecs */
#define VL_MACROBLOCK_WIDTH 16
#define VL_MACROBLOCK_HEIGHT 16
 
#define VL_BLOCK_WIDTH 8
#define VL_BLOCK_HEIGHT 8
 
#define VL_NUM_COMPONENTS 3
#define VL_MAX_SURFACES (VL_NUM_COMPONENTS * 2)
#define VL_MAX_REF_FRAMES 2
 
#endif
/drivers/video/Gallium/auxiliary/vl/vl_idct.c
0,0 → 1,856
/**************************************************************************
*
* Copyright 2010 Christian König
* 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.
*
**************************************************************************/
 
#include <assert.h>
 
#include "pipe/p_context.h"
#include "pipe/p_screen.h"
 
#include "util/u_draw.h"
#include "util/u_sampler.h"
#include "util/u_memory.h"
 
#include "tgsi/tgsi_ureg.h"
 
#include "vl_defines.h"
#include "vl_types.h"
#include "vl_vertex_buffers.h"
#include "vl_idct.h"
 
enum VS_OUTPUT
{
VS_O_VPOS = 0,
VS_O_L_ADDR0 = 0,
VS_O_L_ADDR1,
VS_O_R_ADDR0,
VS_O_R_ADDR1
};
 
/**
* The DCT matrix stored as hex representation of floats. Equal to the following equation:
* for (i = 0; i < 8; ++i)
* for (j = 0; j < 8; ++j)
* if (i == 0) const_matrix[i][j] = 1.0f / sqrtf(8.0f);
* else const_matrix[i][j] = sqrtf(2.0f / 8.0f) * cosf((2 * j + 1) * i * M_PI / (2.0f * 8.0f));
*/
static const uint32_t const_matrix[8][8] = {
{ 0x3eb504f3, 0x3eb504f3, 0x3eb504f3, 0x3eb504f3, 0x3eb504f3, 0x3eb504f3, 0x3eb504f3, 0x3eb504f3 },
{ 0x3efb14be, 0x3ed4db31, 0x3e8e39da, 0x3dc7c5c4, 0xbdc7c5c2, 0xbe8e39d9, 0xbed4db32, 0xbefb14bf },
{ 0x3eec835f, 0x3e43ef15, 0xbe43ef14, 0xbeec835e, 0xbeec835f, 0xbe43ef1a, 0x3e43ef1b, 0x3eec835f },
{ 0x3ed4db31, 0xbdc7c5c2, 0xbefb14bf, 0xbe8e39dd, 0x3e8e39d7, 0x3efb14bf, 0x3dc7c5d0, 0xbed4db34 },
{ 0x3eb504f3, 0xbeb504f3, 0xbeb504f4, 0x3eb504f1, 0x3eb504f3, 0xbeb504f0, 0xbeb504ef, 0x3eb504f4 },
{ 0x3e8e39da, 0xbefb14bf, 0x3dc7c5c8, 0x3ed4db32, 0xbed4db34, 0xbdc7c5bb, 0x3efb14bf, 0xbe8e39d7 },
{ 0x3e43ef15, 0xbeec835f, 0x3eec835f, 0xbe43ef07, 0xbe43ef23, 0x3eec8361, 0xbeec835c, 0x3e43ef25 },
{ 0x3dc7c5c4, 0xbe8e39dd, 0x3ed4db32, 0xbefb14c0, 0x3efb14be, 0xbed4db31, 0x3e8e39ce, 0xbdc7c596 },
};
 
static void
calc_addr(struct ureg_program *shader, struct ureg_dst addr[2],
struct ureg_src tc, struct ureg_src start, bool right_side,
bool transposed, float size)
{
unsigned wm_start = (right_side == transposed) ? TGSI_WRITEMASK_X : TGSI_WRITEMASK_Y;
unsigned sw_start = right_side ? TGSI_SWIZZLE_Y : TGSI_SWIZZLE_X;
 
unsigned wm_tc = (right_side == transposed) ? TGSI_WRITEMASK_Y : TGSI_WRITEMASK_X;
unsigned sw_tc = right_side ? TGSI_SWIZZLE_X : TGSI_SWIZZLE_Y;
 
/*
* addr[0..1].(start) = right_side ? start.x : tc.x
* addr[0..1].(tc) = right_side ? tc.y : start.y
* addr[0..1].z = tc.z
* addr[1].(start) += 1.0f / scale
*/
ureg_MOV(shader, ureg_writemask(addr[0], wm_start), ureg_scalar(start, sw_start));
ureg_MOV(shader, ureg_writemask(addr[0], wm_tc), ureg_scalar(tc, sw_tc));
 
ureg_ADD(shader, ureg_writemask(addr[1], wm_start), ureg_scalar(start, sw_start), ureg_imm1f(shader, 1.0f / size));
ureg_MOV(shader, ureg_writemask(addr[1], wm_tc), ureg_scalar(tc, sw_tc));
}
 
static void
increment_addr(struct ureg_program *shader, struct ureg_dst daddr[2],
struct ureg_src saddr[2], bool right_side, bool transposed,
int pos, float size)
{
unsigned wm_start = (right_side == transposed) ? TGSI_WRITEMASK_X : TGSI_WRITEMASK_Y;
unsigned wm_tc = (right_side == transposed) ? TGSI_WRITEMASK_Y : TGSI_WRITEMASK_X;
 
/*
* daddr[0..1].(start) = saddr[0..1].(start)
* daddr[0..1].(tc) = saddr[0..1].(tc)
*/
 
ureg_MOV(shader, ureg_writemask(daddr[0], wm_start), saddr[0]);
ureg_ADD(shader, ureg_writemask(daddr[0], wm_tc), saddr[0], ureg_imm1f(shader, pos / size));
ureg_MOV(shader, ureg_writemask(daddr[1], wm_start), saddr[1]);
ureg_ADD(shader, ureg_writemask(daddr[1], wm_tc), saddr[1], ureg_imm1f(shader, pos / size));
}
 
static void
fetch_four(struct ureg_program *shader, struct ureg_dst m[2], struct ureg_src addr[2],
struct ureg_src sampler, bool resource3d)
{
ureg_TEX(shader, m[0], resource3d ? TGSI_TEXTURE_3D : TGSI_TEXTURE_2D, addr[0], sampler);
ureg_TEX(shader, m[1], resource3d ? TGSI_TEXTURE_3D : TGSI_TEXTURE_2D, addr[1], sampler);
}
 
static void
matrix_mul(struct ureg_program *shader, struct ureg_dst dst, struct ureg_dst l[2], struct ureg_dst r[2])
{
struct ureg_dst tmp;
 
tmp = ureg_DECL_temporary(shader);
 
/*
* tmp.xy = dot4(m[0][0..1], m[1][0..1])
* dst = tmp.x + tmp.y
*/
ureg_DP4(shader, ureg_writemask(tmp, TGSI_WRITEMASK_X), ureg_src(l[0]), ureg_src(r[0]));
ureg_DP4(shader, ureg_writemask(tmp, TGSI_WRITEMASK_Y), ureg_src(l[1]), ureg_src(r[1]));
ureg_ADD(shader, dst,
ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X),
ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_Y));
 
ureg_release_temporary(shader, tmp);
}
 
static void *
create_mismatch_vert_shader(struct vl_idct *idct)
{
struct ureg_program *shader;
struct ureg_src vpos;
struct ureg_src scale;
struct ureg_dst t_tex;
struct ureg_dst o_vpos, o_addr[2];
 
shader = ureg_create(TGSI_PROCESSOR_VERTEX);
if (!shader)
return NULL;
 
vpos = ureg_DECL_vs_input(shader, VS_I_VPOS);
 
t_tex = ureg_DECL_temporary(shader);
 
o_vpos = ureg_DECL_output(shader, TGSI_SEMANTIC_POSITION, VS_O_VPOS);
 
o_addr[0] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_L_ADDR0);
o_addr[1] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_L_ADDR1);
 
/*
* scale = (VL_BLOCK_WIDTH, VL_BLOCK_HEIGHT) / (dst.width, dst.height)
*
* t_vpos = vpos + 7 / VL_BLOCK_WIDTH
* o_vpos.xy = t_vpos * scale
*
* o_addr = calc_addr(...)
*
*/
 
scale = ureg_imm2f(shader,
(float)VL_BLOCK_WIDTH / idct->buffer_width,
(float)VL_BLOCK_HEIGHT / idct->buffer_height);
 
ureg_MAD(shader, ureg_writemask(o_vpos, TGSI_WRITEMASK_XY), vpos, scale, scale);
ureg_MOV(shader, ureg_writemask(o_vpos, TGSI_WRITEMASK_ZW), ureg_imm1f(shader, 1.0f));
 
ureg_MUL(shader, ureg_writemask(t_tex, TGSI_WRITEMASK_XY), vpos, scale);
calc_addr(shader, o_addr, ureg_src(t_tex), ureg_src(t_tex), false, false, idct->buffer_width / 4);
 
ureg_release_temporary(shader, t_tex);
 
ureg_END(shader);
 
return ureg_create_shader_and_destroy(shader, idct->pipe);
}
 
static void *
create_mismatch_frag_shader(struct vl_idct *idct)
{
struct ureg_program *shader;
 
struct ureg_src addr[2];
 
struct ureg_dst m[8][2];
struct ureg_dst fragment;
 
unsigned i;
 
shader = ureg_create(TGSI_PROCESSOR_FRAGMENT);
if (!shader)
return NULL;
 
addr[0] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_L_ADDR0, TGSI_INTERPOLATE_LINEAR);
addr[1] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_L_ADDR1, TGSI_INTERPOLATE_LINEAR);
 
fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0);
 
for (i = 0; i < 8; ++i) {
m[i][0] = ureg_DECL_temporary(shader);
m[i][1] = ureg_DECL_temporary(shader);
}
 
for (i = 0; i < 8; ++i) {
increment_addr(shader, m[i], addr, false, false, i, idct->buffer_height);
}
 
for (i = 0; i < 8; ++i) {
struct ureg_src s_addr[2];
s_addr[0] = ureg_src(m[i][0]);
s_addr[1] = ureg_src(m[i][1]);
fetch_four(shader, m[i], s_addr, ureg_DECL_sampler(shader, 0), false);
}
 
for (i = 1; i < 8; ++i) {
ureg_ADD(shader, m[0][0], ureg_src(m[0][0]), ureg_src(m[i][0]));
ureg_ADD(shader, m[0][1], ureg_src(m[0][1]), ureg_src(m[i][1]));
}
 
ureg_ADD(shader, m[0][0], ureg_src(m[0][0]), ureg_src(m[0][1]));
ureg_DP4(shader, m[0][0], ureg_abs(ureg_src(m[0][0])), ureg_imm1f(shader, 1 << 14));
 
ureg_MUL(shader, ureg_writemask(m[0][0], TGSI_WRITEMASK_W), ureg_abs(ureg_src(m[7][1])), ureg_imm1f(shader, 1 << 14));
ureg_FRC(shader, m[0][0], ureg_src(m[0][0]));
ureg_SGT(shader, m[0][0], ureg_imm1f(shader, 0.5f), ureg_abs(ureg_src(m[0][0])));
 
ureg_CMP(shader, ureg_writemask(m[0][0], TGSI_WRITEMASK_W), ureg_negate(ureg_src(m[0][0])),
ureg_imm1f(shader, 1.0f / (1 << 15)), ureg_imm1f(shader, -1.0f / (1 << 15)));
ureg_MUL(shader, ureg_writemask(m[0][0], TGSI_WRITEMASK_W), ureg_src(m[0][0]),
ureg_scalar(ureg_src(m[0][0]), TGSI_SWIZZLE_X));
 
ureg_MOV(shader, ureg_writemask(fragment, TGSI_WRITEMASK_XYZ), ureg_src(m[7][1]));
ureg_ADD(shader, ureg_writemask(fragment, TGSI_WRITEMASK_W), ureg_src(m[0][0]), ureg_src(m[7][1]));
 
for (i = 0; i < 8; ++i) {
ureg_release_temporary(shader, m[i][0]);
ureg_release_temporary(shader, m[i][1]);
}
 
ureg_END(shader);
 
return ureg_create_shader_and_destroy(shader, idct->pipe);
}
 
static void *
create_stage1_vert_shader(struct vl_idct *idct)
{
struct ureg_program *shader;
struct ureg_src vrect, vpos;
struct ureg_src scale;
struct ureg_dst t_tex, t_start;
struct ureg_dst o_vpos, o_l_addr[2], o_r_addr[2];
 
shader = ureg_create(TGSI_PROCESSOR_VERTEX);
if (!shader)
return NULL;
 
vrect = ureg_DECL_vs_input(shader, VS_I_RECT);
vpos = ureg_DECL_vs_input(shader, VS_I_VPOS);
 
t_tex = ureg_DECL_temporary(shader);
t_start = ureg_DECL_temporary(shader);
 
o_vpos = ureg_DECL_output(shader, TGSI_SEMANTIC_POSITION, VS_O_VPOS);
 
o_l_addr[0] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_L_ADDR0);
o_l_addr[1] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_L_ADDR1);
 
o_r_addr[0] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_R_ADDR0);
o_r_addr[1] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_R_ADDR1);
 
/*
* scale = (VL_BLOCK_WIDTH, VL_BLOCK_HEIGHT) / (dst.width, dst.height)
*
* t_vpos = vpos + vrect
* o_vpos.xy = t_vpos * scale
* o_vpos.zw = vpos
*
* o_l_addr = calc_addr(...)
* o_r_addr = calc_addr(...)
*
*/
 
scale = ureg_imm2f(shader,
(float)VL_BLOCK_WIDTH / idct->buffer_width,
(float)VL_BLOCK_HEIGHT / idct->buffer_height);
 
ureg_ADD(shader, ureg_writemask(t_tex, TGSI_WRITEMASK_XY), vpos, vrect);
ureg_MUL(shader, ureg_writemask(t_tex, TGSI_WRITEMASK_XY), ureg_src(t_tex), scale);
 
ureg_MOV(shader, ureg_writemask(o_vpos, TGSI_WRITEMASK_XY), ureg_src(t_tex));
ureg_MOV(shader, ureg_writemask(o_vpos, TGSI_WRITEMASK_ZW), ureg_imm1f(shader, 1.0f));
 
ureg_MUL(shader, ureg_writemask(t_start, TGSI_WRITEMASK_XY), vpos, scale);
 
calc_addr(shader, o_l_addr, ureg_src(t_tex), ureg_src(t_start), false, false, idct->buffer_width / 4);
calc_addr(shader, o_r_addr, vrect, ureg_imm1f(shader, 0.0f), true, true, VL_BLOCK_WIDTH / 4);
 
ureg_release_temporary(shader, t_tex);
ureg_release_temporary(shader, t_start);
 
ureg_END(shader);
 
return ureg_create_shader_and_destroy(shader, idct->pipe);
}
 
static void *
create_stage1_frag_shader(struct vl_idct *idct)
{
struct ureg_program *shader;
 
struct ureg_src l_addr[2], r_addr[2];
 
struct ureg_dst l[4][2], r[2];
struct ureg_dst *fragment;
 
int i, j;
 
shader = ureg_create(TGSI_PROCESSOR_FRAGMENT);
if (!shader)
return NULL;
 
fragment = MALLOC(idct->nr_of_render_targets * sizeof(struct ureg_dst));
 
l_addr[0] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_L_ADDR0, TGSI_INTERPOLATE_LINEAR);
l_addr[1] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_L_ADDR1, TGSI_INTERPOLATE_LINEAR);
 
r_addr[0] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_R_ADDR0, TGSI_INTERPOLATE_LINEAR);
r_addr[1] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_R_ADDR1, TGSI_INTERPOLATE_LINEAR);
 
for (i = 0; i < idct->nr_of_render_targets; ++i)
fragment[i] = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, i);
 
for (i = 0; i < 4; ++i) {
l[i][0] = ureg_DECL_temporary(shader);
l[i][1] = ureg_DECL_temporary(shader);
}
 
r[0] = ureg_DECL_temporary(shader);
r[1] = ureg_DECL_temporary(shader);
 
for (i = 0; i < 4; ++i) {
increment_addr(shader, l[i], l_addr, false, false, i - 2, idct->buffer_height);
}
 
for (i = 0; i < 4; ++i) {
struct ureg_src s_addr[2];
s_addr[0] = ureg_src(l[i][0]);
s_addr[1] = ureg_src(l[i][1]);
fetch_four(shader, l[i], s_addr, ureg_DECL_sampler(shader, 0), false);
}
 
for (i = 0; i < idct->nr_of_render_targets; ++i) {
struct ureg_src s_addr[2];
 
increment_addr(shader, r, r_addr, true, true, i - (signed)idct->nr_of_render_targets / 2, VL_BLOCK_HEIGHT);
 
s_addr[0] = ureg_src(r[0]);
s_addr[1] = ureg_src(r[1]);
fetch_four(shader, r, s_addr, ureg_DECL_sampler(shader, 1), false);
 
for (j = 0; j < 4; ++j) {
matrix_mul(shader, ureg_writemask(fragment[i], TGSI_WRITEMASK_X << j), l[j], r);
}
}
 
for (i = 0; i < 4; ++i) {
ureg_release_temporary(shader, l[i][0]);
ureg_release_temporary(shader, l[i][1]);
}
ureg_release_temporary(shader, r[0]);
ureg_release_temporary(shader, r[1]);
 
ureg_END(shader);
 
FREE(fragment);
 
return ureg_create_shader_and_destroy(shader, idct->pipe);
}
 
void
vl_idct_stage2_vert_shader(struct vl_idct *idct, struct ureg_program *shader,
unsigned first_output, struct ureg_dst tex)
{
struct ureg_src vrect, vpos;
struct ureg_src scale;
struct ureg_dst t_start;
struct ureg_dst o_l_addr[2], o_r_addr[2];
 
vrect = ureg_DECL_vs_input(shader, VS_I_RECT);
vpos = ureg_DECL_vs_input(shader, VS_I_VPOS);
 
t_start = ureg_DECL_temporary(shader);
 
--first_output;
 
o_l_addr[0] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, first_output + VS_O_L_ADDR0);
o_l_addr[1] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, first_output + VS_O_L_ADDR1);
 
o_r_addr[0] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, first_output + VS_O_R_ADDR0);
o_r_addr[1] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, first_output + VS_O_R_ADDR1);
 
scale = ureg_imm2f(shader,
(float)VL_BLOCK_WIDTH / idct->buffer_width,
(float)VL_BLOCK_HEIGHT / idct->buffer_height);
 
ureg_MUL(shader, ureg_writemask(tex, TGSI_WRITEMASK_Z),
ureg_scalar(vrect, TGSI_SWIZZLE_X),
ureg_imm1f(shader, VL_BLOCK_WIDTH / idct->nr_of_render_targets));
ureg_MUL(shader, ureg_writemask(t_start, TGSI_WRITEMASK_XY), vpos, scale);
 
calc_addr(shader, o_l_addr, vrect, ureg_imm1f(shader, 0.0f), false, false, VL_BLOCK_WIDTH / 4);
calc_addr(shader, o_r_addr, ureg_src(tex), ureg_src(t_start), true, false, idct->buffer_height / 4);
 
ureg_MOV(shader, ureg_writemask(o_r_addr[0], TGSI_WRITEMASK_Z), ureg_src(tex));
ureg_MOV(shader, ureg_writemask(o_r_addr[1], TGSI_WRITEMASK_Z), ureg_src(tex));
}
 
void
vl_idct_stage2_frag_shader(struct vl_idct *idct, struct ureg_program *shader,
unsigned first_input, struct ureg_dst fragment)
{
struct ureg_src l_addr[2], r_addr[2];
 
struct ureg_dst l[2], r[2];
 
--first_input;
 
l_addr[0] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, first_input + VS_O_L_ADDR0, TGSI_INTERPOLATE_LINEAR);
l_addr[1] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, first_input + VS_O_L_ADDR1, TGSI_INTERPOLATE_LINEAR);
 
r_addr[0] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, first_input + VS_O_R_ADDR0, TGSI_INTERPOLATE_LINEAR);
r_addr[1] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, first_input + VS_O_R_ADDR1, TGSI_INTERPOLATE_LINEAR);
 
l[0] = ureg_DECL_temporary(shader);
l[1] = ureg_DECL_temporary(shader);
r[0] = ureg_DECL_temporary(shader);
r[1] = ureg_DECL_temporary(shader);
 
fetch_four(shader, l, l_addr, ureg_DECL_sampler(shader, 1), false);
fetch_four(shader, r, r_addr, ureg_DECL_sampler(shader, 0), true);
 
matrix_mul(shader, fragment, l, r);
 
ureg_release_temporary(shader, l[0]);
ureg_release_temporary(shader, l[1]);
ureg_release_temporary(shader, r[0]);
ureg_release_temporary(shader, r[1]);
}
 
static bool
init_shaders(struct vl_idct *idct)
{
idct->vs_mismatch = create_mismatch_vert_shader(idct);
if (!idct->vs_mismatch)
goto error_vs_mismatch;
 
idct->fs_mismatch = create_mismatch_frag_shader(idct);
if (!idct->fs_mismatch)
goto error_fs_mismatch;
 
idct->vs = create_stage1_vert_shader(idct);
if (!idct->vs)
goto error_vs;
 
idct->fs = create_stage1_frag_shader(idct);
if (!idct->fs)
goto error_fs;
 
return true;
 
error_fs:
idct->pipe->delete_vs_state(idct->pipe, idct->vs);
 
error_vs:
idct->pipe->delete_vs_state(idct->pipe, idct->vs_mismatch);
 
error_fs_mismatch:
idct->pipe->delete_vs_state(idct->pipe, idct->fs);
 
error_vs_mismatch:
return false;
}
 
static void
cleanup_shaders(struct vl_idct *idct)
{
idct->pipe->delete_vs_state(idct->pipe, idct->vs_mismatch);
idct->pipe->delete_fs_state(idct->pipe, idct->fs_mismatch);
idct->pipe->delete_vs_state(idct->pipe, idct->vs);
idct->pipe->delete_fs_state(idct->pipe, idct->fs);
}
 
static bool
init_state(struct vl_idct *idct)
{
struct pipe_blend_state blend;
struct pipe_rasterizer_state rs_state;
struct pipe_sampler_state sampler;
unsigned i;
 
assert(idct);
 
memset(&rs_state, 0, sizeof(rs_state));
rs_state.point_size = 1;
rs_state.half_pixel_center = true;
rs_state.bottom_edge_rule = true;
rs_state.depth_clip = 1;
idct->rs_state = idct->pipe->create_rasterizer_state(idct->pipe, &rs_state);
if (!idct->rs_state)
goto error_rs_state;
 
memset(&blend, 0, sizeof blend);
 
blend.independent_blend_enable = 0;
blend.rt[0].blend_enable = 0;
blend.rt[0].rgb_func = PIPE_BLEND_ADD;
blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ONE;
blend.rt[0].alpha_func = PIPE_BLEND_ADD;
blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
blend.logicop_enable = 0;
blend.logicop_func = PIPE_LOGICOP_CLEAR;
/* Needed to allow color writes to FB, even if blending disabled */
blend.rt[0].colormask = PIPE_MASK_RGBA;
blend.dither = 0;
idct->blend = idct->pipe->create_blend_state(idct->pipe, &blend);
if (!idct->blend)
goto error_blend;
 
for (i = 0; i < 2; ++i) {
memset(&sampler, 0, sizeof(sampler));
sampler.wrap_s = PIPE_TEX_WRAP_REPEAT;
sampler.wrap_t = PIPE_TEX_WRAP_REPEAT;
sampler.wrap_r = PIPE_TEX_WRAP_REPEAT;
sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
sampler.compare_mode = PIPE_TEX_COMPARE_NONE;
sampler.compare_func = PIPE_FUNC_ALWAYS;
sampler.normalized_coords = 1;
idct->samplers[i] = idct->pipe->create_sampler_state(idct->pipe, &sampler);
if (!idct->samplers[i])
goto error_samplers;
}
 
return true;
 
error_samplers:
for (i = 0; i < 2; ++i)
if (idct->samplers[i])
idct->pipe->delete_sampler_state(idct->pipe, idct->samplers[i]);
 
idct->pipe->delete_rasterizer_state(idct->pipe, idct->rs_state);
 
error_blend:
idct->pipe->delete_blend_state(idct->pipe, idct->blend);
 
error_rs_state:
return false;
}
 
static void
cleanup_state(struct vl_idct *idct)
{
unsigned i;
 
for (i = 0; i < 2; ++i)
idct->pipe->delete_sampler_state(idct->pipe, idct->samplers[i]);
 
idct->pipe->delete_rasterizer_state(idct->pipe, idct->rs_state);
idct->pipe->delete_blend_state(idct->pipe, idct->blend);
}
 
static bool
init_source(struct vl_idct *idct, struct vl_idct_buffer *buffer)
{
struct pipe_resource *tex;
struct pipe_surface surf_templ;
 
assert(idct && buffer);
 
tex = buffer->sampler_views.individual.source->texture;
 
buffer->fb_state_mismatch.width = tex->width0;
buffer->fb_state_mismatch.height = tex->height0;
buffer->fb_state_mismatch.nr_cbufs = 1;
 
memset(&surf_templ, 0, sizeof(surf_templ));
surf_templ.format = tex->format;
surf_templ.u.tex.first_layer = 0;
surf_templ.u.tex.last_layer = 0;
buffer->fb_state_mismatch.cbufs[0] = idct->pipe->create_surface(idct->pipe, tex, &surf_templ);
 
buffer->viewport_mismatch.scale[0] = tex->width0;
buffer->viewport_mismatch.scale[1] = tex->height0;
buffer->viewport_mismatch.scale[2] = 1;
buffer->viewport_mismatch.scale[3] = 1;
 
return true;
}
 
static void
cleanup_source(struct vl_idct_buffer *buffer)
{
assert(buffer);
 
pipe_surface_reference(&buffer->fb_state_mismatch.cbufs[0], NULL);
 
pipe_sampler_view_reference(&buffer->sampler_views.individual.source, NULL);
}
 
static bool
init_intermediate(struct vl_idct *idct, struct vl_idct_buffer *buffer)
{
struct pipe_resource *tex;
struct pipe_surface surf_templ;
unsigned i;
 
assert(idct && buffer);
 
tex = buffer->sampler_views.individual.intermediate->texture;
 
buffer->fb_state.width = tex->width0;
buffer->fb_state.height = tex->height0;
buffer->fb_state.nr_cbufs = idct->nr_of_render_targets;
for(i = 0; i < idct->nr_of_render_targets; ++i) {
memset(&surf_templ, 0, sizeof(surf_templ));
surf_templ.format = tex->format;
surf_templ.u.tex.first_layer = i;
surf_templ.u.tex.last_layer = i;
buffer->fb_state.cbufs[i] = idct->pipe->create_surface(
idct->pipe, tex, &surf_templ);
 
if (!buffer->fb_state.cbufs[i])
goto error_surfaces;
}
 
buffer->viewport.scale[0] = tex->width0;
buffer->viewport.scale[1] = tex->height0;
buffer->viewport.scale[2] = 1;
buffer->viewport.scale[3] = 1;
 
return true;
 
error_surfaces:
for(i = 0; i < idct->nr_of_render_targets; ++i)
pipe_surface_reference(&buffer->fb_state.cbufs[i], NULL);
 
return false;
}
 
static void
cleanup_intermediate(struct vl_idct_buffer *buffer)
{
unsigned i;
 
assert(buffer);
 
for(i = 0; i < PIPE_MAX_COLOR_BUFS; ++i)
pipe_surface_reference(&buffer->fb_state.cbufs[i], NULL);
 
pipe_sampler_view_reference(&buffer->sampler_views.individual.intermediate, NULL);
}
 
struct pipe_sampler_view *
vl_idct_upload_matrix(struct pipe_context *pipe, float scale)
{
struct pipe_resource tex_templ, *matrix;
struct pipe_sampler_view sv_templ, *sv;
struct pipe_transfer *buf_transfer;
unsigned i, j, pitch;
float *f;
 
struct pipe_box rect =
{
0, 0, 0,
VL_BLOCK_WIDTH / 4,
VL_BLOCK_HEIGHT,
1
};
 
assert(pipe);
 
memset(&tex_templ, 0, sizeof(tex_templ));
tex_templ.target = PIPE_TEXTURE_2D;
tex_templ.format = PIPE_FORMAT_R32G32B32A32_FLOAT;
tex_templ.last_level = 0;
tex_templ.width0 = 2;
tex_templ.height0 = 8;
tex_templ.depth0 = 1;
tex_templ.array_size = 1;
tex_templ.usage = PIPE_USAGE_IMMUTABLE;
tex_templ.bind = PIPE_BIND_SAMPLER_VIEW;
tex_templ.flags = 0;
 
matrix = pipe->screen->resource_create(pipe->screen, &tex_templ);
if (!matrix)
goto error_matrix;
 
f = pipe->transfer_map(pipe, matrix, 0,
PIPE_TRANSFER_WRITE |
PIPE_TRANSFER_DISCARD_RANGE,
&rect, &buf_transfer);
if (!f)
goto error_map;
 
pitch = buf_transfer->stride / sizeof(float);
 
for(i = 0; i < VL_BLOCK_HEIGHT; ++i)
for(j = 0; j < VL_BLOCK_WIDTH; ++j)
// transpose and scale
f[i * pitch + j] = ((const float (*)[8])const_matrix)[j][i] * scale;
 
pipe->transfer_unmap(pipe, buf_transfer);
 
memset(&sv_templ, 0, sizeof(sv_templ));
u_sampler_view_default_template(&sv_templ, matrix, matrix->format);
sv = pipe->create_sampler_view(pipe, matrix, &sv_templ);
pipe_resource_reference(&matrix, NULL);
if (!sv)
goto error_map;
 
return sv;
 
error_map:
pipe_resource_reference(&matrix, NULL);
 
error_matrix:
return NULL;
}
 
bool vl_idct_init(struct vl_idct *idct, struct pipe_context *pipe,
unsigned buffer_width, unsigned buffer_height,
unsigned nr_of_render_targets,
struct pipe_sampler_view *matrix,
struct pipe_sampler_view *transpose)
{
assert(idct && pipe);
assert(matrix && transpose);
 
idct->pipe = pipe;
idct->buffer_width = buffer_width;
idct->buffer_height = buffer_height;
idct->nr_of_render_targets = nr_of_render_targets;
 
pipe_sampler_view_reference(&idct->matrix, matrix);
pipe_sampler_view_reference(&idct->transpose, transpose);
 
if(!init_shaders(idct))
return false;
 
if(!init_state(idct)) {
cleanup_shaders(idct);
return false;
}
 
return true;
}
 
void
vl_idct_cleanup(struct vl_idct *idct)
{
cleanup_shaders(idct);
cleanup_state(idct);
 
pipe_sampler_view_reference(&idct->matrix, NULL);
pipe_sampler_view_reference(&idct->transpose, NULL);
}
 
bool
vl_idct_init_buffer(struct vl_idct *idct, struct vl_idct_buffer *buffer,
struct pipe_sampler_view *source,
struct pipe_sampler_view *intermediate)
{
assert(buffer && idct);
assert(source && intermediate);
 
memset(buffer, 0, sizeof(struct vl_idct_buffer));
 
pipe_sampler_view_reference(&buffer->sampler_views.individual.matrix, idct->matrix);
pipe_sampler_view_reference(&buffer->sampler_views.individual.source, source);
pipe_sampler_view_reference(&buffer->sampler_views.individual.transpose, idct->transpose);
pipe_sampler_view_reference(&buffer->sampler_views.individual.intermediate, intermediate);
 
if (!init_source(idct, buffer))
return false;
 
if (!init_intermediate(idct, buffer))
return false;
 
return true;
}
 
void
vl_idct_cleanup_buffer(struct vl_idct_buffer *buffer)
{
assert(buffer);
 
cleanup_source(buffer);
cleanup_intermediate(buffer);
 
pipe_sampler_view_reference(&buffer->sampler_views.individual.matrix, NULL);
pipe_sampler_view_reference(&buffer->sampler_views.individual.transpose, NULL);
}
 
void
vl_idct_flush(struct vl_idct *idct, struct vl_idct_buffer *buffer, unsigned num_instances)
{
assert(buffer);
 
idct->pipe->bind_rasterizer_state(idct->pipe, idct->rs_state);
idct->pipe->bind_blend_state(idct->pipe, idct->blend);
idct->pipe->bind_fragment_sampler_states(idct->pipe, 2, idct->samplers);
idct->pipe->set_fragment_sampler_views(idct->pipe, 2, buffer->sampler_views.stage[0]);
 
/* mismatch control */
idct->pipe->set_framebuffer_state(idct->pipe, &buffer->fb_state_mismatch);
idct->pipe->set_viewport_states(idct->pipe, 0, 1, &buffer->viewport_mismatch);
idct->pipe->bind_vs_state(idct->pipe, idct->vs_mismatch);
idct->pipe->bind_fs_state(idct->pipe, idct->fs_mismatch);
util_draw_arrays_instanced(idct->pipe, PIPE_PRIM_POINTS, 0, 1, 0, num_instances);
 
/* first stage */
idct->pipe->set_framebuffer_state(idct->pipe, &buffer->fb_state);
idct->pipe->set_viewport_states(idct->pipe, 0, 1, &buffer->viewport);
idct->pipe->bind_vs_state(idct->pipe, idct->vs);
idct->pipe->bind_fs_state(idct->pipe, idct->fs);
util_draw_arrays_instanced(idct->pipe, PIPE_PRIM_QUADS, 0, 4, 0, num_instances);
}
 
void
vl_idct_prepare_stage2(struct vl_idct *idct, struct vl_idct_buffer *buffer)
{
assert(buffer);
 
/* second stage */
idct->pipe->bind_rasterizer_state(idct->pipe, idct->rs_state);
idct->pipe->bind_fragment_sampler_states(idct->pipe, 2, idct->samplers);
idct->pipe->set_fragment_sampler_views(idct->pipe, 2, buffer->sampler_views.stage[1]);
}
 
/drivers/video/Gallium/auxiliary/vl/vl_idct.h
0,0 → 1,119
/**************************************************************************
*
* Copyright 2010 Christian König
* 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.
*
**************************************************************************/
 
#ifndef vl_idct_h
#define vl_idct_h
 
#include "pipe/p_state.h"
 
#include "tgsi/tgsi_ureg.h"
 
/* shader based inverse distinct cosinus transformation
* expect usage of vl_vertex_buffers as a todo list
*/
struct vl_idct
{
struct pipe_context *pipe;
 
unsigned buffer_width;
unsigned buffer_height;
unsigned nr_of_render_targets;
 
void *rs_state;
void *blend;
 
void *samplers[2];
 
void *vs_mismatch, *fs_mismatch;
void *vs, *fs;
 
struct pipe_sampler_view *matrix;
struct pipe_sampler_view *transpose;
};
 
/* a set of buffers to work with */
struct vl_idct_buffer
{
struct pipe_viewport_state viewport_mismatch;
struct pipe_viewport_state viewport;
 
struct pipe_framebuffer_state fb_state_mismatch;
struct pipe_framebuffer_state fb_state;
 
union
{
struct pipe_sampler_view *all[4];
struct pipe_sampler_view *stage[2][2];
struct {
struct pipe_sampler_view *source, *matrix;
struct pipe_sampler_view *intermediate, *transpose;
} individual;
} sampler_views;
};
 
/* upload the idct matrix, which can be shared by all idct instances of a pipe */
struct pipe_sampler_view *
vl_idct_upload_matrix(struct pipe_context *pipe, float scale);
 
void
vl_idct_stage2_vert_shader(struct vl_idct *idct, struct ureg_program *shader,
unsigned first_output, struct ureg_dst tex);
 
void
vl_idct_stage2_frag_shader(struct vl_idct *idct, struct ureg_program *shader,
unsigned first_input, struct ureg_dst fragment);
 
/* init an idct instance */
bool
vl_idct_init(struct vl_idct *idct, struct pipe_context *pipe,
unsigned buffer_width, unsigned buffer_height,
unsigned nr_of_render_targets,
struct pipe_sampler_view *matrix,
struct pipe_sampler_view *transpose);
 
/* destroy an idct instance */
void
vl_idct_cleanup(struct vl_idct *idct);
 
/* init a buffer assosiated with agiven idct instance */
bool
vl_idct_init_buffer(struct vl_idct *idct, struct vl_idct_buffer *buffer,
struct pipe_sampler_view *source,
struct pipe_sampler_view *intermediate);
 
/* cleanup a buffer of an idct instance */
void
vl_idct_cleanup_buffer(struct vl_idct_buffer *buffer);
 
/* flush the buffer and start rendering, vertex buffers needs to be setup before calling this */
void
vl_idct_flush(struct vl_idct *idct, struct vl_idct_buffer *buffer, unsigned num_verts);
 
void
vl_idct_prepare_stage2(struct vl_idct *idct, struct vl_idct_buffer *buffer);
 
#endif
/drivers/video/Gallium/auxiliary/vl/vl_matrix_filter.c
0,0 → 1,319
/**************************************************************************
*
* Copyright 2012 Christian König.
* 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.
*
**************************************************************************/
 
#include <stdio.h>
 
#include "pipe/p_context.h"
 
#include "tgsi/tgsi_ureg.h"
 
#include "util/u_draw.h"
#include "util/u_memory.h"
#include "util/u_math.h"
 
#include "vl_types.h"
#include "vl_vertex_buffers.h"
#include "vl_matrix_filter.h"
 
enum VS_OUTPUT
{
VS_O_VPOS = 0,
VS_O_VTEX = 0
};
 
static void *
create_vert_shader(struct vl_matrix_filter *filter)
{
struct ureg_program *shader;
struct ureg_src i_vpos;
struct ureg_dst o_vpos, o_vtex;
 
shader = ureg_create(TGSI_PROCESSOR_VERTEX);
if (!shader)
return NULL;
 
i_vpos = ureg_DECL_vs_input(shader, 0);
o_vpos = ureg_DECL_output(shader, TGSI_SEMANTIC_POSITION, VS_O_VPOS);
o_vtex = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX);
 
ureg_MOV(shader, o_vpos, i_vpos);
ureg_MOV(shader, o_vtex, i_vpos);
 
ureg_END(shader);
 
return ureg_create_shader_and_destroy(shader, filter->pipe);
}
 
static inline bool
is_vec_zero(struct vertex2f v)
{
return v.x == 0.0f && v.y == 0.0f;
}
 
static void *
create_frag_shader(struct vl_matrix_filter *filter, unsigned num_offsets,
struct vertex2f *offsets, const float *matrix_values)
{
struct ureg_program *shader;
struct ureg_src i_vtex;
struct ureg_src sampler;
struct ureg_dst *t_array = MALLOC(sizeof(struct ureg_dst) * num_offsets);
struct ureg_dst t_sum;
struct ureg_dst o_fragment;
bool first;
int i;
 
shader = ureg_create(TGSI_PROCESSOR_FRAGMENT);
if (!shader) {
FREE(t_array);
return NULL;
}
 
i_vtex = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX, TGSI_INTERPOLATE_LINEAR);
sampler = ureg_DECL_sampler(shader, 0);
 
for (i = 0; i < num_offsets; ++i)
if (matrix_values[i] != 0.0f)
t_array[i] = ureg_DECL_temporary(shader);
 
o_fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0);
 
/*
* t_array[0..*] = vtex + offset[0..*]
* t_array[0..*] = tex(t_array[0..*], sampler)
* o_fragment = sum(t_array[0..*] * matrix_values[0..*])
*/
 
for (i = 0; i < num_offsets; ++i) {
if (matrix_values[i] != 0.0f && !is_vec_zero(offsets[i])) {
ureg_ADD(shader, ureg_writemask(t_array[i], TGSI_WRITEMASK_XY),
i_vtex, ureg_imm2f(shader, offsets[i].x, offsets[i].y));
ureg_MOV(shader, ureg_writemask(t_array[i], TGSI_WRITEMASK_ZW),
ureg_imm1f(shader, 0.0f));
}
}
 
for (i = 0; i < num_offsets; ++i) {
if (matrix_values[i] != 0.0f) {
struct ureg_src src = is_vec_zero(offsets[i]) ? i_vtex : ureg_src(t_array[i]);
ureg_TEX(shader, t_array[i], TGSI_TEXTURE_2D, src, sampler);
}
}
 
for (i = 0, first = true; i < num_offsets; ++i) {
if (matrix_values[i] != 0.0f) {
if (first) {
t_sum = t_array[i];
ureg_MUL(shader, t_sum, ureg_src(t_array[i]),
ureg_imm1f(shader, matrix_values[i]));
first = false;
} else
ureg_MAD(shader, t_sum, ureg_src(t_array[i]),
ureg_imm1f(shader, matrix_values[i]), ureg_src(t_sum));
}
}
if (first)
ureg_MOV(shader, o_fragment, ureg_imm1f(shader, 0.0f));
else
ureg_MOV(shader, o_fragment, ureg_src(t_sum));
 
ureg_END(shader);
 
FREE(t_array);
return ureg_create_shader_and_destroy(shader, filter->pipe);
}
 
bool
vl_matrix_filter_init(struct vl_matrix_filter *filter, struct pipe_context *pipe,
unsigned video_width, unsigned video_height,
unsigned matrix_width, unsigned matrix_height,
const float *matrix_values)
{
struct pipe_rasterizer_state rs_state;
struct pipe_blend_state blend;
struct pipe_sampler_state sampler;
struct pipe_vertex_element ve;
struct vertex2f *offsets, v, sizes;
unsigned i, num_offsets = matrix_width * matrix_height;
 
assert(filter && pipe);
assert(video_width && video_height);
assert(matrix_width && matrix_height);
 
memset(filter, 0, sizeof(*filter));
filter->pipe = pipe;
 
memset(&rs_state, 0, sizeof(rs_state));
rs_state.half_pixel_center = true;
rs_state.bottom_edge_rule = true;
rs_state.depth_clip = 1;
filter->rs_state = pipe->create_rasterizer_state(pipe, &rs_state);
if (!filter->rs_state)
goto error_rs_state;
 
memset(&blend, 0, sizeof blend);
blend.rt[0].rgb_func = PIPE_BLEND_ADD;
blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ONE;
blend.rt[0].alpha_func = PIPE_BLEND_ADD;
blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
blend.logicop_func = PIPE_LOGICOP_CLEAR;
blend.rt[0].colormask = PIPE_MASK_RGBA;
filter->blend = pipe->create_blend_state(pipe, &blend);
if (!filter->blend)
goto error_blend;
 
memset(&sampler, 0, sizeof(sampler));
sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
sampler.compare_mode = PIPE_TEX_COMPARE_NONE;
sampler.compare_func = PIPE_FUNC_ALWAYS;
sampler.normalized_coords = 1;
filter->sampler = pipe->create_sampler_state(pipe, &sampler);
if (!filter->sampler)
goto error_sampler;
 
filter->quad = vl_vb_upload_quads(pipe);
if(!filter->quad.buffer)
goto error_quad;
 
memset(&ve, 0, sizeof(ve));
ve.src_offset = 0;
ve.instance_divisor = 0;
ve.vertex_buffer_index = 0;
ve.src_format = PIPE_FORMAT_R32G32_FLOAT;
filter->ves = pipe->create_vertex_elements_state(pipe, 1, &ve);
if (!filter->ves)
goto error_ves;
 
offsets = MALLOC(sizeof(struct vertex2f) * num_offsets);
if (!offsets)
goto error_offsets;
 
sizes.x = (float)(matrix_width - 1) / 2.0f;
sizes.y = (float)(matrix_height - 1) / 2.0f;
 
for (v.x = -sizes.x, i = 0; v.x <= sizes.x; v.x += 1.0f)
for (v.y = -sizes.y; v.y <= sizes.y; v.y += 1.0f)
offsets[i++] = v;
 
for (i = 0; i < num_offsets; ++i) {
offsets[i].x /= video_width;
offsets[i].y /= video_height;
}
 
filter->vs = create_vert_shader(filter);
if (!filter->vs)
goto error_vs;
 
filter->fs = create_frag_shader(filter, num_offsets, offsets, matrix_values);
if (!filter->fs)
goto error_fs;
 
FREE(offsets);
return true;
 
error_fs:
pipe->delete_vs_state(pipe, filter->vs);
 
error_vs:
FREE(offsets);
 
error_offsets:
pipe->delete_vertex_elements_state(pipe, filter->ves);
 
error_ves:
pipe_resource_reference(&filter->quad.buffer, NULL);
 
error_quad:
pipe->delete_sampler_state(pipe, filter->sampler);
 
error_sampler:
pipe->delete_blend_state(pipe, filter->blend);
 
error_blend:
pipe->delete_rasterizer_state(pipe, filter->rs_state);
 
error_rs_state:
return false;
}
 
void
vl_matrix_filter_cleanup(struct vl_matrix_filter *filter)
{
assert(filter);
 
filter->pipe->delete_sampler_state(filter->pipe, filter->sampler);
filter->pipe->delete_blend_state(filter->pipe, filter->blend);
filter->pipe->delete_rasterizer_state(filter->pipe, filter->rs_state);
filter->pipe->delete_vertex_elements_state(filter->pipe, filter->ves);
pipe_resource_reference(&filter->quad.buffer, NULL);
 
filter->pipe->delete_vs_state(filter->pipe, filter->vs);
filter->pipe->delete_fs_state(filter->pipe, filter->fs);
}
 
void
vl_matrix_filter_render(struct vl_matrix_filter *filter,
struct pipe_sampler_view *src,
struct pipe_surface *dst)
{
struct pipe_viewport_state viewport;
struct pipe_framebuffer_state fb_state;
 
assert(filter && src && dst);
 
memset(&viewport, 0, sizeof(viewport));
viewport.scale[0] = dst->width;
viewport.scale[1] = dst->height;
viewport.scale[2] = 1;
viewport.scale[3] = 1;
 
memset(&fb_state, 0, sizeof(fb_state));
fb_state.width = dst->width;
fb_state.height = dst->height;
fb_state.nr_cbufs = 1;
fb_state.cbufs[0] = dst;
 
filter->pipe->bind_rasterizer_state(filter->pipe, filter->rs_state);
filter->pipe->bind_blend_state(filter->pipe, filter->blend);
filter->pipe->bind_fragment_sampler_states(filter->pipe, 1, &filter->sampler);
filter->pipe->set_fragment_sampler_views(filter->pipe, 1, &src);
filter->pipe->bind_vs_state(filter->pipe, filter->vs);
filter->pipe->bind_fs_state(filter->pipe, filter->fs);
filter->pipe->set_framebuffer_state(filter->pipe, &fb_state);
filter->pipe->set_viewport_states(filter->pipe, 0, 1, &viewport);
filter->pipe->set_vertex_buffers(filter->pipe, 0, 1, &filter->quad);
filter->pipe->bind_vertex_elements_state(filter->pipe, filter->ves);
 
util_draw_arrays(filter->pipe, PIPE_PRIM_QUADS, 0, 4);
}
/drivers/video/Gallium/auxiliary/vl/vl_matrix_filter.h
0,0 → 1,64
/**************************************************************************
*
* Copyright 2012 Christian König.
* 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.
*
**************************************************************************/
 
/* implementation of all matrix based filters like
gaussian, mean, laplacian, emboss, sharpness etc.. */
 
#ifndef vl_matrix_filter_h
#define vl_matrix_filter_h
 
#include "pipe/p_state.h"
 
struct vl_matrix_filter
{
struct pipe_context *pipe;
struct pipe_vertex_buffer quad;
 
void *rs_state;
void *blend;
void *sampler;
void *ves;
void *vs, *fs;
};
 
bool
vl_matrix_filter_init(struct vl_matrix_filter *filter, struct pipe_context *pipe,
unsigned video_width, unsigned video_height,
unsigned matrix_width, unsigned matrix_height,
const float *matrix_values);
 
void
vl_matrix_filter_cleanup(struct vl_matrix_filter *filter);
 
 
void
vl_matrix_filter_render(struct vl_matrix_filter *filter,
struct pipe_sampler_view *src,
struct pipe_surface *dst);
 
 
#endif /* vl_matrix_filter_h */
/drivers/video/Gallium/auxiliary/vl/vl_mc.c
0,0 → 1,648
/**************************************************************************
*
* Copyright 2009 Younes Manton.
* 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.
*
**************************************************************************/
 
#include <assert.h>
 
#include "pipe/p_context.h"
 
#include "util/u_sampler.h"
#include "util/u_draw.h"
 
#include "tgsi/tgsi_ureg.h"
 
#include "vl_defines.h"
#include "vl_vertex_buffers.h"
#include "vl_mc.h"
#include "vl_idct.h"
 
enum VS_OUTPUT
{
VS_O_VPOS = 0,
VS_O_VTOP = 0,
VS_O_VBOTTOM,
 
VS_O_FLAGS = VS_O_VTOP,
VS_O_VTEX = VS_O_VBOTTOM
};
 
static struct ureg_dst
calc_position(struct vl_mc *r, struct ureg_program *shader, struct ureg_src block_scale)
{
struct ureg_src vrect, vpos;
struct ureg_dst t_vpos;
struct ureg_dst o_vpos;
 
vrect = ureg_DECL_vs_input(shader, VS_I_RECT);
vpos = ureg_DECL_vs_input(shader, VS_I_VPOS);
 
t_vpos = ureg_DECL_temporary(shader);
 
o_vpos = ureg_DECL_output(shader, TGSI_SEMANTIC_POSITION, VS_O_VPOS);
 
/*
* block_scale = (VL_MACROBLOCK_WIDTH, VL_MACROBLOCK_HEIGHT) / (dst.width, dst.height)
*
* t_vpos = (vpos + vrect) * block_scale
* o_vpos.xy = t_vpos
* o_vpos.zw = vpos
*/
ureg_ADD(shader, ureg_writemask(t_vpos, TGSI_WRITEMASK_XY), vpos, vrect);
ureg_MUL(shader, ureg_writemask(t_vpos, TGSI_WRITEMASK_XY), ureg_src(t_vpos), block_scale);
ureg_MOV(shader, ureg_writemask(o_vpos, TGSI_WRITEMASK_XY), ureg_src(t_vpos));
ureg_MOV(shader, ureg_writemask(o_vpos, TGSI_WRITEMASK_ZW), ureg_imm1f(shader, 1.0f));
 
return t_vpos;
}
 
static struct ureg_dst
calc_line(struct ureg_program *shader)
{
struct ureg_dst tmp;
struct ureg_src pos;
 
tmp = ureg_DECL_temporary(shader);
 
pos = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_POSITION, VS_O_VPOS, TGSI_INTERPOLATE_LINEAR);
 
/*
* tmp.y = fraction(pos.y / 2) >= 0.5 ? 1 : 0
*/
ureg_MUL(shader, ureg_writemask(tmp, TGSI_WRITEMASK_Y), pos, ureg_imm1f(shader, 0.5f));
ureg_FRC(shader, ureg_writemask(tmp, TGSI_WRITEMASK_Y), ureg_src(tmp));
ureg_SGE(shader, ureg_writemask(tmp, TGSI_WRITEMASK_Y), ureg_src(tmp), ureg_imm1f(shader, 0.5f));
 
return tmp;
}
 
static void *
create_ref_vert_shader(struct vl_mc *r)
{
struct ureg_program *shader;
struct ureg_src mv_scale;
struct ureg_src vmv[2];
struct ureg_dst t_vpos;
struct ureg_dst o_vmv[2];
unsigned i;
 
shader = ureg_create(TGSI_PROCESSOR_VERTEX);
if (!shader)
return NULL;
 
vmv[0] = ureg_DECL_vs_input(shader, VS_I_MV_TOP);
vmv[1] = ureg_DECL_vs_input(shader, VS_I_MV_BOTTOM);
 
t_vpos = calc_position(r, shader, ureg_imm2f(shader,
(float)VL_MACROBLOCK_WIDTH / r->buffer_width,
(float)VL_MACROBLOCK_HEIGHT / r->buffer_height)
);
 
o_vmv[0] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTOP);
o_vmv[1] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_VBOTTOM);
 
/*
* mv_scale.xy = 0.5 / (dst.width, dst.height);
* mv_scale.z = 1.0f / 4.0f
* mv_scale.w = 1.0f / 255.0f
*
* // Apply motion vectors
* o_vmv[0..1].xy = vmv[0..1] * mv_scale + t_vpos
* o_vmv[0..1].zw = vmv[0..1] * mv_scale
*
*/
 
mv_scale = ureg_imm4f(shader,
0.5f / r->buffer_width,
0.5f / r->buffer_height,
1.0f / 4.0f,
1.0f / PIPE_VIDEO_MV_WEIGHT_MAX);
 
for (i = 0; i < 2; ++i) {
ureg_MAD(shader, ureg_writemask(o_vmv[i], TGSI_WRITEMASK_XY), mv_scale, vmv[i], ureg_src(t_vpos));
ureg_MUL(shader, ureg_writemask(o_vmv[i], TGSI_WRITEMASK_ZW), mv_scale, vmv[i]);
}
 
ureg_release_temporary(shader, t_vpos);
 
ureg_END(shader);
 
return ureg_create_shader_and_destroy(shader, r->pipe);
}
 
static void *
create_ref_frag_shader(struct vl_mc *r)
{
const float y_scale =
r->buffer_height / 2 *
r->macroblock_size / VL_MACROBLOCK_HEIGHT;
 
struct ureg_program *shader;
struct ureg_src tc[2], sampler;
struct ureg_dst ref, field;
struct ureg_dst fragment;
unsigned label;
 
shader = ureg_create(TGSI_PROCESSOR_FRAGMENT);
if (!shader)
return NULL;
 
tc[0] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTOP, TGSI_INTERPOLATE_LINEAR);
tc[1] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VBOTTOM, TGSI_INTERPOLATE_LINEAR);
 
sampler = ureg_DECL_sampler(shader, 0);
ref = ureg_DECL_temporary(shader);
 
fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0);
 
field = calc_line(shader);
 
/*
* ref = field.z ? tc[1] : tc[0]
*
* // Adjust tc acording to top/bottom field selection
* if (|ref.z|) {
* ref.y *= y_scale
* ref.y = floor(ref.y)
* ref.y += ref.z
* ref.y /= y_scale
* }
* fragment.xyz = tex(ref, sampler[0])
*/
ureg_CMP(shader, ureg_writemask(ref, TGSI_WRITEMASK_XYZ),
ureg_negate(ureg_scalar(ureg_src(field), TGSI_SWIZZLE_Y)),
tc[1], tc[0]);
ureg_CMP(shader, ureg_writemask(fragment, TGSI_WRITEMASK_W),
ureg_negate(ureg_scalar(ureg_src(field), TGSI_SWIZZLE_Y)),
tc[1], tc[0]);
 
ureg_IF(shader, ureg_scalar(ureg_src(ref), TGSI_SWIZZLE_Z), &label);
 
ureg_MUL(shader, ureg_writemask(ref, TGSI_WRITEMASK_Y),
ureg_src(ref), ureg_imm1f(shader, y_scale));
ureg_FLR(shader, ureg_writemask(ref, TGSI_WRITEMASK_Y), ureg_src(ref));
ureg_ADD(shader, ureg_writemask(ref, TGSI_WRITEMASK_Y),
ureg_src(ref), ureg_scalar(ureg_src(ref), TGSI_SWIZZLE_Z));
ureg_MUL(shader, ureg_writemask(ref, TGSI_WRITEMASK_Y),
ureg_src(ref), ureg_imm1f(shader, 1.0f / y_scale));
 
ureg_fixup_label(shader, label, ureg_get_instruction_number(shader));
ureg_ENDIF(shader);
 
ureg_TEX(shader, ureg_writemask(fragment, TGSI_WRITEMASK_XYZ), TGSI_TEXTURE_2D, ureg_src(ref), sampler);
 
ureg_release_temporary(shader, ref);
 
ureg_release_temporary(shader, field);
ureg_END(shader);
 
return ureg_create_shader_and_destroy(shader, r->pipe);
}
 
static void *
create_ycbcr_vert_shader(struct vl_mc *r, vl_mc_ycbcr_vert_shader vs_callback, void *callback_priv)
{
struct ureg_program *shader;
 
struct ureg_src vrect, vpos;
struct ureg_dst t_vpos, t_vtex;
struct ureg_dst o_vpos, o_flags;
 
struct vertex2f scale = {
(float)VL_BLOCK_WIDTH / r->buffer_width * VL_MACROBLOCK_WIDTH / r->macroblock_size,
(float)VL_BLOCK_HEIGHT / r->buffer_height * VL_MACROBLOCK_HEIGHT / r->macroblock_size
};
 
unsigned label;
 
shader = ureg_create(TGSI_PROCESSOR_VERTEX);
if (!shader)
return NULL;
 
vrect = ureg_DECL_vs_input(shader, VS_I_RECT);
vpos = ureg_DECL_vs_input(shader, VS_I_VPOS);
 
t_vpos = calc_position(r, shader, ureg_imm2f(shader, scale.x, scale.y));
t_vtex = ureg_DECL_temporary(shader);
 
o_vpos = ureg_DECL_output(shader, TGSI_SEMANTIC_POSITION, VS_O_VPOS);
o_flags = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_FLAGS);
 
/*
* o_vtex.xy = t_vpos
* o_flags.z = intra * 0.5
*
* if(interlaced) {
* t_vtex.xy = vrect.y ? { 0, scale.y } : { -scale.y : 0 }
* t_vtex.z = vpos.y % 2
* t_vtex.y = t_vtex.z ? t_vtex.x : t_vtex.y
* o_vpos.y = t_vtex.y + t_vpos.y
*
* o_flags.w = t_vtex.z ? 0 : 1
* }
*
*/
 
vs_callback(callback_priv, r, shader, VS_O_VTEX, t_vpos);
 
ureg_MUL(shader, ureg_writemask(o_flags, TGSI_WRITEMASK_Z),
ureg_scalar(vpos, TGSI_SWIZZLE_Z), ureg_imm1f(shader, 0.5f));
ureg_MOV(shader, ureg_writemask(o_flags, TGSI_WRITEMASK_W), ureg_imm1f(shader, -1.0f));
 
if (r->macroblock_size == VL_MACROBLOCK_HEIGHT) { //TODO
ureg_IF(shader, ureg_scalar(vpos, TGSI_SWIZZLE_W), &label);
 
ureg_CMP(shader, ureg_writemask(t_vtex, TGSI_WRITEMASK_XY),
ureg_negate(ureg_scalar(vrect, TGSI_SWIZZLE_Y)),
ureg_imm2f(shader, 0.0f, scale.y),
ureg_imm2f(shader, -scale.y, 0.0f));
ureg_MUL(shader, ureg_writemask(t_vtex, TGSI_WRITEMASK_Z),
ureg_scalar(vpos, TGSI_SWIZZLE_Y), ureg_imm1f(shader, 0.5f));
 
ureg_FRC(shader, ureg_writemask(t_vtex, TGSI_WRITEMASK_Z), ureg_src(t_vtex));
 
ureg_CMP(shader, ureg_writemask(t_vtex, TGSI_WRITEMASK_Y),
ureg_negate(ureg_scalar(ureg_src(t_vtex), TGSI_SWIZZLE_Z)),
ureg_scalar(ureg_src(t_vtex), TGSI_SWIZZLE_X),
ureg_scalar(ureg_src(t_vtex), TGSI_SWIZZLE_Y));
ureg_ADD(shader, ureg_writemask(o_vpos, TGSI_WRITEMASK_Y),
ureg_src(t_vpos), ureg_src(t_vtex));
 
ureg_CMP(shader, ureg_writemask(o_flags, TGSI_WRITEMASK_W),
ureg_negate(ureg_scalar(ureg_src(t_vtex), TGSI_SWIZZLE_Z)),
ureg_imm1f(shader, 0.0f), ureg_imm1f(shader, 1.0f));
 
ureg_fixup_label(shader, label, ureg_get_instruction_number(shader));
ureg_ENDIF(shader);
}
 
ureg_release_temporary(shader, t_vtex);
ureg_release_temporary(shader, t_vpos);
 
ureg_END(shader);
 
return ureg_create_shader_and_destroy(shader, r->pipe);
}
 
static void *
create_ycbcr_frag_shader(struct vl_mc *r, float scale, bool invert,
vl_mc_ycbcr_frag_shader fs_callback, void *callback_priv)
{
struct ureg_program *shader;
struct ureg_src flags;
struct ureg_dst tmp;
struct ureg_dst fragment;
unsigned label;
 
shader = ureg_create(TGSI_PROCESSOR_FRAGMENT);
if (!shader)
return NULL;
 
flags = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_FLAGS, TGSI_INTERPOLATE_LINEAR);
 
fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0);
 
tmp = calc_line(shader);
 
/*
* if (field == tc.w)
* kill();
* else {
* fragment.xyz = tex(tc, sampler) * scale + tc.z
* fragment.w = 1.0f
* }
*/
 
ureg_SEQ(shader, ureg_writemask(tmp, TGSI_WRITEMASK_Y),
ureg_scalar(flags, TGSI_SWIZZLE_W), ureg_src(tmp));
 
ureg_IF(shader, ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_Y), &label);
 
ureg_KILP(shader);
 
ureg_fixup_label(shader, label, ureg_get_instruction_number(shader));
ureg_ELSE(shader, &label);
 
fs_callback(callback_priv, r, shader, VS_O_VTEX, tmp);
 
if (scale != 1.0f)
ureg_MAD(shader, ureg_writemask(tmp, TGSI_WRITEMASK_XYZ),
ureg_src(tmp), ureg_imm1f(shader, scale),
ureg_scalar(flags, TGSI_SWIZZLE_Z));
else
ureg_ADD(shader, ureg_writemask(tmp, TGSI_WRITEMASK_XYZ),
ureg_src(tmp), ureg_scalar(flags, TGSI_SWIZZLE_Z));
ureg_MUL(shader, ureg_writemask(fragment, TGSI_WRITEMASK_XYZ), ureg_src(tmp), ureg_imm1f(shader, invert ? -1.0f : 1.0f));
ureg_MOV(shader, ureg_writemask(fragment, TGSI_WRITEMASK_W), ureg_imm1f(shader, 1.0f));
 
ureg_fixup_label(shader, label, ureg_get_instruction_number(shader));
ureg_ENDIF(shader);
 
ureg_release_temporary(shader, tmp);
 
ureg_END(shader);
 
return ureg_create_shader_and_destroy(shader, r->pipe);
}
 
static bool
init_pipe_state(struct vl_mc *r)
{
struct pipe_sampler_state sampler;
struct pipe_blend_state blend;
struct pipe_rasterizer_state rs_state;
unsigned i;
 
assert(r);
 
memset(&sampler, 0, sizeof(sampler));
sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_BORDER;
sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR;
sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR;
sampler.compare_mode = PIPE_TEX_COMPARE_NONE;
sampler.compare_func = PIPE_FUNC_ALWAYS;
sampler.normalized_coords = 1;
r->sampler_ref = r->pipe->create_sampler_state(r->pipe, &sampler);
if (!r->sampler_ref)
goto error_sampler_ref;
 
for (i = 0; i < VL_MC_NUM_BLENDERS; ++i) {
memset(&blend, 0, sizeof blend);
blend.independent_blend_enable = 0;
blend.rt[0].blend_enable = 1;
blend.rt[0].rgb_func = PIPE_BLEND_ADD;
blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
blend.rt[0].alpha_func = PIPE_BLEND_ADD;
blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
blend.logicop_enable = 0;
blend.logicop_func = PIPE_LOGICOP_CLEAR;
blend.rt[0].colormask = i;
blend.dither = 0;
r->blend_clear[i] = r->pipe->create_blend_state(r->pipe, &blend);
if (!r->blend_clear[i])
goto error_blend;
 
blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ONE;
blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
r->blend_add[i] = r->pipe->create_blend_state(r->pipe, &blend);
if (!r->blend_add[i])
goto error_blend;
 
blend.rt[0].rgb_func = PIPE_BLEND_REVERSE_SUBTRACT;
blend.rt[0].alpha_dst_factor = PIPE_BLEND_REVERSE_SUBTRACT;
r->blend_sub[i] = r->pipe->create_blend_state(r->pipe, &blend);
if (!r->blend_sub[i])
goto error_blend;
}
 
memset(&rs_state, 0, sizeof(rs_state));
/*rs_state.sprite_coord_enable */
rs_state.sprite_coord_mode = PIPE_SPRITE_COORD_UPPER_LEFT;
rs_state.point_quad_rasterization = true;
rs_state.point_size = VL_BLOCK_WIDTH;
rs_state.half_pixel_center = true;
rs_state.bottom_edge_rule = true;
rs_state.depth_clip = 1;
r->rs_state = r->pipe->create_rasterizer_state(r->pipe, &rs_state);
if (!r->rs_state)
goto error_rs_state;
 
return true;
 
error_rs_state:
error_blend:
for (i = 0; i < VL_MC_NUM_BLENDERS; ++i) {
if (r->blend_sub[i])
r->pipe->delete_blend_state(r->pipe, r->blend_sub[i]);
 
if (r->blend_add[i])
r->pipe->delete_blend_state(r->pipe, r->blend_add[i]);
 
if (r->blend_clear[i])
r->pipe->delete_blend_state(r->pipe, r->blend_clear[i]);
}
 
r->pipe->delete_sampler_state(r->pipe, r->sampler_ref);
 
error_sampler_ref:
return false;
}
 
static void
cleanup_pipe_state(struct vl_mc *r)
{
unsigned i;
 
assert(r);
 
r->pipe->delete_sampler_state(r->pipe, r->sampler_ref);
for (i = 0; i < VL_MC_NUM_BLENDERS; ++i) {
r->pipe->delete_blend_state(r->pipe, r->blend_clear[i]);
r->pipe->delete_blend_state(r->pipe, r->blend_add[i]);
r->pipe->delete_blend_state(r->pipe, r->blend_sub[i]);
}
r->pipe->delete_rasterizer_state(r->pipe, r->rs_state);
}
 
bool
vl_mc_init(struct vl_mc *renderer, struct pipe_context *pipe,
unsigned buffer_width, unsigned buffer_height,
unsigned macroblock_size, float scale,
vl_mc_ycbcr_vert_shader vs_callback,
vl_mc_ycbcr_frag_shader fs_callback,
void *callback_priv)
{
assert(renderer);
assert(pipe);
 
memset(renderer, 0, sizeof(struct vl_mc));
 
renderer->pipe = pipe;
renderer->buffer_width = buffer_width;
renderer->buffer_height = buffer_height;
renderer->macroblock_size = macroblock_size;
 
if (!init_pipe_state(renderer))
goto error_pipe_state;
 
renderer->vs_ref = create_ref_vert_shader(renderer);
if (!renderer->vs_ref)
goto error_vs_ref;
 
renderer->vs_ycbcr = create_ycbcr_vert_shader(renderer, vs_callback, callback_priv);
if (!renderer->vs_ycbcr)
goto error_vs_ycbcr;
 
renderer->fs_ref = create_ref_frag_shader(renderer);
if (!renderer->fs_ref)
goto error_fs_ref;
 
renderer->fs_ycbcr = create_ycbcr_frag_shader(renderer, scale, false, fs_callback, callback_priv);
if (!renderer->fs_ycbcr)
goto error_fs_ycbcr;
 
renderer->fs_ycbcr_sub = create_ycbcr_frag_shader(renderer, scale, true, fs_callback, callback_priv);
if (!renderer->fs_ycbcr_sub)
goto error_fs_ycbcr_sub;
 
return true;
error_fs_ycbcr_sub:
renderer->pipe->delete_fs_state(renderer->pipe, renderer->fs_ycbcr);
 
error_fs_ycbcr:
renderer->pipe->delete_fs_state(renderer->pipe, renderer->fs_ref);
 
error_fs_ref:
renderer->pipe->delete_vs_state(renderer->pipe, renderer->vs_ycbcr);
 
error_vs_ycbcr:
renderer->pipe->delete_vs_state(renderer->pipe, renderer->vs_ref);
 
error_vs_ref:
cleanup_pipe_state(renderer);
 
error_pipe_state:
return false;
}
 
void
vl_mc_cleanup(struct vl_mc *renderer)
{
assert(renderer);
 
cleanup_pipe_state(renderer);
 
renderer->pipe->delete_vs_state(renderer->pipe, renderer->vs_ref);
renderer->pipe->delete_vs_state(renderer->pipe, renderer->vs_ycbcr);
renderer->pipe->delete_fs_state(renderer->pipe, renderer->fs_ref);
renderer->pipe->delete_fs_state(renderer->pipe, renderer->fs_ycbcr);
renderer->pipe->delete_fs_state(renderer->pipe, renderer->fs_ycbcr_sub);
}
 
bool
vl_mc_init_buffer(struct vl_mc *renderer, struct vl_mc_buffer *buffer)
{
assert(renderer && buffer);
 
buffer->viewport.scale[2] = 1;
buffer->viewport.scale[3] = 1;
buffer->viewport.translate[0] = 0;
buffer->viewport.translate[1] = 0;
buffer->viewport.translate[2] = 0;
buffer->viewport.translate[3] = 0;
 
buffer->fb_state.nr_cbufs = 1;
buffer->fb_state.zsbuf = NULL;
 
return true;
}
 
void
vl_mc_cleanup_buffer(struct vl_mc_buffer *buffer)
{
assert(buffer);
}
 
void
vl_mc_set_surface(struct vl_mc_buffer *buffer, struct pipe_surface *surface)
{
assert(buffer && surface);
 
buffer->surface_cleared = false;
 
buffer->viewport.scale[0] = surface->width;
buffer->viewport.scale[1] = surface->height;
 
buffer->fb_state.width = surface->width;
buffer->fb_state.height = surface->height;
buffer->fb_state.cbufs[0] = surface;
}
 
static void
prepare_pipe_4_rendering(struct vl_mc *renderer, struct vl_mc_buffer *buffer, unsigned mask)
{
assert(buffer);
 
renderer->pipe->bind_rasterizer_state(renderer->pipe, renderer->rs_state);
 
if (buffer->surface_cleared)
renderer->pipe->bind_blend_state(renderer->pipe, renderer->blend_add[mask]);
else
renderer->pipe->bind_blend_state(renderer->pipe, renderer->blend_clear[mask]);
 
renderer->pipe->set_framebuffer_state(renderer->pipe, &buffer->fb_state);
renderer->pipe->set_viewport_states(renderer->pipe, 0, 1, &buffer->viewport);
}
 
void
vl_mc_render_ref(struct vl_mc *renderer, struct vl_mc_buffer *buffer, struct pipe_sampler_view *ref)
{
assert(buffer && ref);
 
prepare_pipe_4_rendering(renderer, buffer, PIPE_MASK_R | PIPE_MASK_G | PIPE_MASK_B);
 
renderer->pipe->bind_vs_state(renderer->pipe, renderer->vs_ref);
renderer->pipe->bind_fs_state(renderer->pipe, renderer->fs_ref);
 
renderer->pipe->set_fragment_sampler_views(renderer->pipe, 1, &ref);
renderer->pipe->bind_fragment_sampler_states(renderer->pipe, 1, &renderer->sampler_ref);
 
util_draw_arrays_instanced(renderer->pipe, PIPE_PRIM_QUADS, 0, 4, 0,
renderer->buffer_width / VL_MACROBLOCK_WIDTH *
renderer->buffer_height / VL_MACROBLOCK_HEIGHT);
 
buffer->surface_cleared = true;
}
 
void
vl_mc_render_ycbcr(struct vl_mc *renderer, struct vl_mc_buffer *buffer, unsigned component, unsigned num_instances)
{
unsigned mask = 1 << component;
 
assert(buffer);
 
if (num_instances == 0)
return;
 
prepare_pipe_4_rendering(renderer, buffer, mask);
 
renderer->pipe->bind_vs_state(renderer->pipe, renderer->vs_ycbcr);
renderer->pipe->bind_fs_state(renderer->pipe, renderer->fs_ycbcr);
 
util_draw_arrays_instanced(renderer->pipe, PIPE_PRIM_QUADS, 0, 4, 0, num_instances);
if (buffer->surface_cleared) {
renderer->pipe->bind_blend_state(renderer->pipe, renderer->blend_sub[mask]);
renderer->pipe->bind_fs_state(renderer->pipe, renderer->fs_ycbcr_sub);
util_draw_arrays_instanced(renderer->pipe, PIPE_PRIM_QUADS, 0, 4, 0, num_instances);
}
}
/drivers/video/Gallium/auxiliary/vl/vl_mc.h
0,0 → 1,97
/**************************************************************************
*
* Copyright 2009 Younes Manton.
* 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.
*
**************************************************************************/
 
#ifndef vl_mc_h
#define vl_mc_h
 
#include "pipe/p_state.h"
#include "pipe/p_video_state.h"
 
#include "tgsi/tgsi_ureg.h"
 
#include "vl_defines.h"
#include "vl_types.h"
 
#define VL_MC_NUM_BLENDERS (1 << VL_NUM_COMPONENTS)
 
struct pipe_context;
 
struct vl_mc
{
struct pipe_context *pipe;
unsigned buffer_width;
unsigned buffer_height;
unsigned macroblock_size;
 
void *rs_state;
 
void *blend_clear[VL_MC_NUM_BLENDERS];
void *blend_add[VL_MC_NUM_BLENDERS];
void *blend_sub[VL_MC_NUM_BLENDERS];
void *vs_ref, *vs_ycbcr;
void *fs_ref, *fs_ycbcr, *fs_ycbcr_sub;
void *sampler_ref;
};
 
struct vl_mc_buffer
{
bool surface_cleared;
 
struct pipe_viewport_state viewport;
struct pipe_framebuffer_state fb_state;
};
 
typedef void (*vl_mc_ycbcr_vert_shader)(void *priv, struct vl_mc *mc,
struct ureg_program *shader,
unsigned first_output,
struct ureg_dst tex);
 
typedef void (*vl_mc_ycbcr_frag_shader)(void *priv, struct vl_mc *mc,
struct ureg_program *shader,
unsigned first_input,
struct ureg_dst dst);
 
bool vl_mc_init(struct vl_mc *renderer, struct pipe_context *pipe,
unsigned picture_width, unsigned picture_height,
unsigned macroblock_size, float scale,
vl_mc_ycbcr_vert_shader vs_callback,
vl_mc_ycbcr_frag_shader fs_callback,
void *callback_priv);
 
void vl_mc_cleanup(struct vl_mc *renderer);
 
bool vl_mc_init_buffer(struct vl_mc *renderer, struct vl_mc_buffer *buffer);
 
void vl_mc_cleanup_buffer(struct vl_mc_buffer *buffer);
 
void vl_mc_set_surface(struct vl_mc_buffer *buffer, struct pipe_surface *surface);
 
void vl_mc_render_ref(struct vl_mc *renderer, struct vl_mc_buffer *buffer, struct pipe_sampler_view *ref);
 
void vl_mc_render_ycbcr(struct vl_mc *renderer, struct vl_mc_buffer *buffer, unsigned component, unsigned num_instances);
 
#endif /* vl_mc_h */
/drivers/video/Gallium/auxiliary/vl/vl_median_filter.c
0,0 → 1,398
/**************************************************************************
*
* Copyright 2012 Christian König.
* 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.
*
**************************************************************************/
 
#include "pipe/p_context.h"
 
#include "tgsi/tgsi_ureg.h"
 
#include "util/u_draw.h"
#include "util/u_memory.h"
#include "util/u_math.h"
 
#include "vl_types.h"
#include "vl_vertex_buffers.h"
#include "vl_median_filter.h"
 
enum VS_OUTPUT
{
VS_O_VPOS = 0,
VS_O_VTEX = 0
};
 
static void *
create_vert_shader(struct vl_median_filter *filter)
{
struct ureg_program *shader;
struct ureg_src i_vpos;
struct ureg_dst o_vpos, o_vtex;
 
shader = ureg_create(TGSI_PROCESSOR_VERTEX);
if (!shader)
return NULL;
 
i_vpos = ureg_DECL_vs_input(shader, 0);
o_vpos = ureg_DECL_output(shader, TGSI_SEMANTIC_POSITION, VS_O_VPOS);
o_vtex = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX);
 
ureg_MOV(shader, o_vpos, i_vpos);
ureg_MOV(shader, o_vtex, i_vpos);
 
ureg_END(shader);
 
return ureg_create_shader_and_destroy(shader, filter->pipe);
}
 
static inline bool
is_vec_zero(struct vertex2f v)
{
return v.x == 0.0f && v.y == 0.0f;
}
 
static void *
create_frag_shader(struct vl_median_filter *filter,
struct vertex2f *offsets,
unsigned num_offsets)
{
struct pipe_screen *screen = filter->pipe->screen;
struct ureg_program *shader;
struct ureg_src i_vtex;
struct ureg_src sampler;
struct ureg_dst *t_array = MALLOC(sizeof(struct ureg_dst) * num_offsets);
struct ureg_dst o_fragment;
const unsigned median = num_offsets >> 1;
int i, j;
 
assert(num_offsets & 1); /* we need an odd number of offsets */
if (!(num_offsets & 1)) { /* yeah, we REALLY need an odd number of offsets!!! */
FREE(t_array);
return NULL;
}
 
if (num_offsets > screen->get_shader_param(
screen, TGSI_PROCESSOR_FRAGMENT, PIPE_SHADER_CAP_MAX_TEMPS)) {
 
FREE(t_array);
return NULL;
}
 
shader = ureg_create(TGSI_PROCESSOR_FRAGMENT);
if (!shader) {
FREE(t_array);
return NULL;
}
 
i_vtex = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX, TGSI_INTERPOLATE_LINEAR);
sampler = ureg_DECL_sampler(shader, 0);
 
for (i = 0; i < num_offsets; ++i)
t_array[i] = ureg_DECL_temporary(shader);
o_fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0);
 
/*
* t_array[0..*] = vtex + offset[0..*]
* t_array[0..*] = tex(t_array[0..*], sampler)
* result = partial_bubblesort(t_array)[mid]
*/
 
for (i = 0; i < num_offsets; ++i) {
if (!is_vec_zero(offsets[i])) {
ureg_ADD(shader, ureg_writemask(t_array[i], TGSI_WRITEMASK_XY),
i_vtex, ureg_imm2f(shader, offsets[i].x, offsets[i].y));
ureg_MOV(shader, ureg_writemask(t_array[i], TGSI_WRITEMASK_ZW),
ureg_imm1f(shader, 0.0f));
}
}
 
for (i = 0; i < num_offsets; ++i) {
struct ureg_src src = is_vec_zero(offsets[i]) ? i_vtex : ureg_src(t_array[i]);
ureg_TEX(shader, t_array[i], TGSI_TEXTURE_2D, src, sampler);
}
 
// TODO: Couldn't this be improved even more?
for (i = 0; i <= median; ++i) {
for (j = 1; j < (num_offsets - i - 1); ++j) {
struct ureg_dst tmp = ureg_DECL_temporary(shader);
ureg_MOV(shader, tmp, ureg_src(t_array[j]));
ureg_MAX(shader, t_array[j], ureg_src(t_array[j]), ureg_src(t_array[j - 1]));
ureg_MIN(shader, t_array[j - 1], ureg_src(tmp), ureg_src(t_array[j - 1]));
ureg_release_temporary(shader, tmp);
}
if (i == median)
ureg_MAX(shader, t_array[j], ureg_src(t_array[j]), ureg_src(t_array[j - 1]));
else
ureg_MIN(shader, t_array[j - 1], ureg_src(t_array[j]), ureg_src(t_array[j - 1]));
}
ureg_MOV(shader, o_fragment, ureg_src(t_array[median]));
 
ureg_END(shader);
 
FREE(t_array);
return ureg_create_shader_and_destroy(shader, filter->pipe);
}
 
static void
generate_offsets(enum vl_median_filter_shape shape, unsigned size,
struct vertex2f **offsets, unsigned *num_offsets)
{
int i = 0, half_size;
struct vertex2f v;
 
assert(offsets && num_offsets);
 
/* size needs to be odd */
size = align(size + 1, 2) - 1;
half_size = size >> 1;
 
switch(shape) {
case VL_MEDIAN_FILTER_BOX:
*num_offsets = size*size;
break;
 
case VL_MEDIAN_FILTER_CROSS:
case VL_MEDIAN_FILTER_X:
*num_offsets = size + size - 1;
break;
 
case VL_MEDIAN_FILTER_HORIZONTAL:
case VL_MEDIAN_FILTER_VERTICAL:
*num_offsets = size;
break;
 
default:
*num_offsets = 0;
return;
}
 
*offsets = MALLOC(sizeof(struct vertex2f) * *num_offsets);
if (!*offsets)
return;
 
switch(shape) {
case VL_MEDIAN_FILTER_BOX:
for (v.x = -half_size; v.x <= half_size; ++v.x)
for (v.y = -half_size; v.y <= half_size; ++v.y)
(*offsets)[i++] = v;
break;
 
case VL_MEDIAN_FILTER_CROSS:
v.y = 0.0f;
for (v.x = -half_size; v.x <= half_size; ++v.x)
(*offsets)[i++] = v;
 
v.x = 0.0f;
for (v.y = -half_size; v.y <= half_size; ++v.y)
if (v.y != 0.0f)
(*offsets)[i++] = v;
break;
 
case VL_MEDIAN_FILTER_X:
for (v.x = v.y = -half_size; v.x <= half_size; ++v.x, ++v.y)
(*offsets)[i++] = v;
 
for (v.x = -half_size, v.y = half_size; v.x <= half_size; ++v.x, --v.y)
if (v.y != 0.0f)
(*offsets)[i++] = v;
break;
 
case VL_MEDIAN_FILTER_HORIZONTAL:
v.y = 0.0f;
for (v.x = -half_size; v.x <= half_size; ++v.x)
(*offsets)[i++] = v;
break;
 
case VL_MEDIAN_FILTER_VERTICAL:
v.x = 0.0f;
for (v.y = -half_size; v.y <= half_size; ++v.y)
(*offsets)[i++] = v;
break;
}
 
assert(i == *num_offsets);
}
 
bool
vl_median_filter_init(struct vl_median_filter *filter, struct pipe_context *pipe,
unsigned width, unsigned height, unsigned size,
enum vl_median_filter_shape shape)
{
struct pipe_rasterizer_state rs_state;
struct pipe_blend_state blend;
struct pipe_sampler_state sampler;
struct vertex2f *offsets = NULL;
struct pipe_vertex_element ve;
unsigned i, num_offsets = 0;
 
assert(filter && pipe);
assert(width && height);
assert(size > 1 && size < 20);
 
memset(filter, 0, sizeof(*filter));
filter->pipe = pipe;
 
memset(&rs_state, 0, sizeof(rs_state));
rs_state.half_pixel_center = true;
rs_state.bottom_edge_rule = true;
rs_state.depth_clip = 1;
filter->rs_state = pipe->create_rasterizer_state(pipe, &rs_state);
if (!filter->rs_state)
goto error_rs_state;
 
memset(&blend, 0, sizeof blend);
blend.rt[0].rgb_func = PIPE_BLEND_ADD;
blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ONE;
blend.rt[0].alpha_func = PIPE_BLEND_ADD;
blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
blend.logicop_func = PIPE_LOGICOP_CLEAR;
blend.rt[0].colormask = PIPE_MASK_RGBA;
filter->blend = pipe->create_blend_state(pipe, &blend);
if (!filter->blend)
goto error_blend;
 
memset(&sampler, 0, sizeof(sampler));
sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
sampler.compare_mode = PIPE_TEX_COMPARE_NONE;
sampler.compare_func = PIPE_FUNC_ALWAYS;
sampler.normalized_coords = 1;
filter->sampler = pipe->create_sampler_state(pipe, &sampler);
if (!filter->sampler)
goto error_sampler;
 
filter->quad = vl_vb_upload_quads(pipe);
if(!filter->quad.buffer)
goto error_quad;
 
memset(&ve, 0, sizeof(ve));
ve.src_offset = 0;
ve.instance_divisor = 0;
ve.vertex_buffer_index = 0;
ve.src_format = PIPE_FORMAT_R32G32_FLOAT;
filter->ves = pipe->create_vertex_elements_state(pipe, 1, &ve);
if (!filter->ves)
goto error_ves;
 
generate_offsets(shape, size, &offsets, &num_offsets);
if (!offsets)
goto error_offsets;
 
for (i = 0; i < num_offsets; ++i) {
offsets[i].x /= width;
offsets[i].y /= height;
}
 
filter->vs = create_vert_shader(filter);
if (!filter->vs)
goto error_vs;
 
filter->fs = create_frag_shader(filter, offsets, num_offsets);
if (!filter->fs)
goto error_fs;
 
FREE(offsets);
return true;
 
error_fs:
pipe->delete_vs_state(pipe, filter->vs);
 
error_vs:
FREE(offsets);
 
error_offsets:
pipe->delete_vertex_elements_state(pipe, filter->ves);
 
error_ves:
pipe_resource_reference(&filter->quad.buffer, NULL);
 
error_quad:
pipe->delete_sampler_state(pipe, filter->sampler);
 
error_sampler:
pipe->delete_blend_state(pipe, filter->blend);
 
error_blend:
pipe->delete_rasterizer_state(pipe, filter->rs_state);
 
error_rs_state:
return false;
}
 
void
vl_median_filter_cleanup(struct vl_median_filter *filter)
{
assert(filter);
 
filter->pipe->delete_sampler_state(filter->pipe, filter->sampler);
filter->pipe->delete_blend_state(filter->pipe, filter->blend);
filter->pipe->delete_rasterizer_state(filter->pipe, filter->rs_state);
filter->pipe->delete_vertex_elements_state(filter->pipe, filter->ves);
pipe_resource_reference(&filter->quad.buffer, NULL);
 
filter->pipe->delete_vs_state(filter->pipe, filter->vs);
filter->pipe->delete_fs_state(filter->pipe, filter->fs);
}
 
void
vl_median_filter_render(struct vl_median_filter *filter,
struct pipe_sampler_view *src,
struct pipe_surface *dst)
{
struct pipe_viewport_state viewport;
struct pipe_framebuffer_state fb_state;
 
assert(filter && src && dst);
 
memset(&viewport, 0, sizeof(viewport));
viewport.scale[0] = dst->width;
viewport.scale[1] = dst->height;
viewport.scale[2] = 1;
viewport.scale[3] = 1;
 
memset(&fb_state, 0, sizeof(fb_state));
fb_state.width = dst->width;
fb_state.height = dst->height;
fb_state.nr_cbufs = 1;
fb_state.cbufs[0] = dst;
 
filter->pipe->bind_rasterizer_state(filter->pipe, filter->rs_state);
filter->pipe->bind_blend_state(filter->pipe, filter->blend);
filter->pipe->bind_fragment_sampler_states(filter->pipe, 1, &filter->sampler);
filter->pipe->set_fragment_sampler_views(filter->pipe, 1, &src);
filter->pipe->bind_vs_state(filter->pipe, filter->vs);
filter->pipe->bind_fs_state(filter->pipe, filter->fs);
filter->pipe->set_framebuffer_state(filter->pipe, &fb_state);
filter->pipe->set_viewport_states(filter->pipe, 0, 1, &viewport);
filter->pipe->set_vertex_buffers(filter->pipe, 0, 1, &filter->quad);
filter->pipe->bind_vertex_elements_state(filter->pipe, filter->ves);
 
util_draw_arrays(filter->pipe, PIPE_PRIM_QUADS, 0, 4);
}
/drivers/video/Gallium/auxiliary/vl/vl_median_filter.h
0,0 → 1,70
/**************************************************************************
*
* Copyright 2012 Christian König.
* 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.
*
**************************************************************************/
 
/* implementation of a median filter for noise reduction */
 
#ifndef vl_median_filter_h
#define vl_median_filter_h
 
#include "pipe/p_state.h"
 
enum vl_median_filter_shape
{
VL_MEDIAN_FILTER_BOX,
VL_MEDIAN_FILTER_CROSS,
VL_MEDIAN_FILTER_X,
VL_MEDIAN_FILTER_HORIZONTAL,
VL_MEDIAN_FILTER_VERTICAL
};
 
struct vl_median_filter
{
struct pipe_context *pipe;
struct pipe_vertex_buffer quad;
 
void *rs_state;
void *blend;
void *sampler;
void *ves;
void *vs, *fs;
};
 
bool
vl_median_filter_init(struct vl_median_filter *filter, struct pipe_context *pipe,
unsigned width, unsigned height, unsigned size,
enum vl_median_filter_shape shape);
 
void
vl_median_filter_cleanup(struct vl_median_filter *filter);
 
 
void
vl_median_filter_render(struct vl_median_filter *filter,
struct pipe_sampler_view *src,
struct pipe_surface *dst);
 
#endif /* vl_median_filter_h */
/drivers/video/Gallium/auxiliary/vl/vl_mpeg12_bitstream.c
0,0 → 1,1014
/**************************************************************************
*
* Copyright 2011 Maarten Lankhorst
* Copyright 2011 Christian König
* 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.
*
**************************************************************************/
 
#include "pipe/p_video_decoder.h"
#include "util/u_memory.h"
 
#include "vl_vlc.h"
#include "vl_mpeg12_bitstream.h"
 
enum {
dct_End_of_Block = 0xFF,
dct_Escape = 0xFE,
dct_DC = 0xFD,
dct_AC = 0xFC
};
 
struct dct_coeff
{
uint8_t length;
uint8_t run;
int16_t level;
};
 
struct dct_coeff_compressed
{
uint32_t bitcode;
struct dct_coeff coeff;
};
 
/* coding table as found in the spec annex B.5 table B-1 */
static const struct vl_vlc_compressed macroblock_address_increment[] = {
{ 0x8000, { 1, 1 } },
{ 0x6000, { 3, 2 } },
{ 0x4000, { 3, 3 } },
{ 0x3000, { 4, 4 } },
{ 0x2000, { 4, 5 } },
{ 0x1800, { 5, 6 } },
{ 0x1000, { 5, 7 } },
{ 0x0e00, { 7, 8 } },
{ 0x0c00, { 7, 9 } },
{ 0x0b00, { 8, 10 } },
{ 0x0a00, { 8, 11 } },
{ 0x0900, { 8, 12 } },
{ 0x0800, { 8, 13 } },
{ 0x0700, { 8, 14 } },
{ 0x0600, { 8, 15 } },
{ 0x05c0, { 10, 16 } },
{ 0x0580, { 10, 17 } },
{ 0x0540, { 10, 18 } },
{ 0x0500, { 10, 19 } },
{ 0x04c0, { 10, 20 } },
{ 0x0480, { 10, 21 } },
{ 0x0460, { 11, 22 } },
{ 0x0440, { 11, 23 } },
{ 0x0420, { 11, 24 } },
{ 0x0400, { 11, 25 } },
{ 0x03e0, { 11, 26 } },
{ 0x03c0, { 11, 27 } },
{ 0x03a0, { 11, 28 } },
{ 0x0380, { 11, 29 } },
{ 0x0360, { 11, 30 } },
{ 0x0340, { 11, 31 } },
{ 0x0320, { 11, 32 } },
{ 0x0300, { 11, 33 } }
};
 
#define Q PIPE_MPEG12_MB_TYPE_QUANT
#define F PIPE_MPEG12_MB_TYPE_MOTION_FORWARD
#define B PIPE_MPEG12_MB_TYPE_MOTION_BACKWARD
#define P PIPE_MPEG12_MB_TYPE_PATTERN
#define I PIPE_MPEG12_MB_TYPE_INTRA
 
/* coding table as found in the spec annex B.5 table B-2 */
static const struct vl_vlc_compressed macroblock_type_i[] = {
{ 0x8000, { 1, I } },
{ 0x4000, { 2, Q|I } }
};
 
/* coding table as found in the spec annex B.5 table B-3 */
static const struct vl_vlc_compressed macroblock_type_p[] = {
{ 0x8000, { 1, F|P } },
{ 0x4000, { 2, P } },
{ 0x2000, { 3, F } },
{ 0x1800, { 5, I } },
{ 0x1000, { 5, Q|F|P } },
{ 0x0800, { 5, Q|P } },
{ 0x0400, { 6, Q|I } }
};
 
/* coding table as found in the spec annex B.5 table B-4 */
static const struct vl_vlc_compressed macroblock_type_b[] = {
{ 0x8000, { 2, F|B } },
{ 0xC000, { 2, F|B|P } },
{ 0x4000, { 3, B } },
{ 0x6000, { 3, B|P } },
{ 0x2000, { 4, F } },
{ 0x3000, { 4, F|P } },
{ 0x1800, { 5, I } },
{ 0x1000, { 5, Q|F|B|P } },
{ 0x0C00, { 6, Q|F|P } },
{ 0x0800, { 6, Q|B|P } },
{ 0x0400, { 6, Q|I } }
};
 
#undef Q
#undef F
#undef B
#undef P
#undef I
 
/* coding table as found in the spec annex B.5 table B-9 */
static const struct vl_vlc_compressed coded_block_pattern[] = {
{ 0xE000, { 3, 60 } },
{ 0xD000, { 4, 4 } },
{ 0xC000, { 4, 8 } },
{ 0xB000, { 4, 16 } },
{ 0xA000, { 4, 32 } },
{ 0x9800, { 5, 12 } },
{ 0x9000, { 5, 48 } },
{ 0x8800, { 5, 20 } },
{ 0x8000, { 5, 40 } },
{ 0x7800, { 5, 28 } },
{ 0x7000, { 5, 44 } },
{ 0x6800, { 5, 52 } },
{ 0x6000, { 5, 56 } },
{ 0x5800, { 5, 1 } },
{ 0x5000, { 5, 61 } },
{ 0x4800, { 5, 2 } },
{ 0x4000, { 5, 62 } },
{ 0x3C00, { 6, 24 } },
{ 0x3800, { 6, 36 } },
{ 0x3400, { 6, 3 } },
{ 0x3000, { 6, 63 } },
{ 0x2E00, { 7, 5 } },
{ 0x2C00, { 7, 9 } },
{ 0x2A00, { 7, 17 } },
{ 0x2800, { 7, 33 } },
{ 0x2600, { 7, 6 } },
{ 0x2400, { 7, 10 } },
{ 0x2200, { 7, 18 } },
{ 0x2000, { 7, 34 } },
{ 0x1F00, { 8, 7 } },
{ 0x1E00, { 8, 11 } },
{ 0x1D00, { 8, 19 } },
{ 0x1C00, { 8, 35 } },
{ 0x1B00, { 8, 13 } },
{ 0x1A00, { 8, 49 } },
{ 0x1900, { 8, 21 } },
{ 0x1800, { 8, 41 } },
{ 0x1700, { 8, 14 } },
{ 0x1600, { 8, 50 } },
{ 0x1500, { 8, 22 } },
{ 0x1400, { 8, 42 } },
{ 0x1300, { 8, 15 } },
{ 0x1200, { 8, 51 } },
{ 0x1100, { 8, 23 } },
{ 0x1000, { 8, 43 } },
{ 0x0F00, { 8, 25 } },
{ 0x0E00, { 8, 37 } },
{ 0x0D00, { 8, 26 } },
{ 0x0C00, { 8, 38 } },
{ 0x0B00, { 8, 29 } },
{ 0x0A00, { 8, 45 } },
{ 0x0900, { 8, 53 } },
{ 0x0800, { 8, 57 } },
{ 0x0700, { 8, 30 } },
{ 0x0600, { 8, 46 } },
{ 0x0500, { 8, 54 } },
{ 0x0400, { 8, 58 } },
{ 0x0380, { 9, 31 } },
{ 0x0300, { 9, 47 } },
{ 0x0280, { 9, 55 } },
{ 0x0200, { 9, 59 } },
{ 0x0180, { 9, 27 } },
{ 0x0100, { 9, 39 } },
{ 0x0080, { 9, 0 } }
};
 
/* coding table as found in the spec annex B.5 table B-10 */
static const struct vl_vlc_compressed motion_code[] = {
{ 0x0320, { 11, -16 } },
{ 0x0360, { 11, -15 } },
{ 0x03a0, { 11, -14 } },
{ 0x03e0, { 11, -13 } },
{ 0x0420, { 11, -12 } },
{ 0x0460, { 11, -11 } },
{ 0x04c0, { 10, -10 } },
{ 0x0540, { 10, -9 } },
{ 0x05c0, { 10, -8 } },
{ 0x0700, { 8, -7 } },
{ 0x0900, { 8, -6 } },
{ 0x0b00, { 8, -5 } },
{ 0x0e00, { 7, -4 } },
{ 0x1800, { 5, -3 } },
{ 0x3000, { 4, -2 } },
{ 0x6000, { 3, -1 } },
{ 0x8000, { 1, 0 } },
{ 0x4000, { 3, 1 } },
{ 0x2000, { 4, 2 } },
{ 0x1000, { 5, 3 } },
{ 0x0c00, { 7, 4 } },
{ 0x0a00, { 8, 5 } },
{ 0x0800, { 8, 6 } },
{ 0x0600, { 8, 7 } },
{ 0x0580, { 10, 8 } },
{ 0x0500, { 10, 9 } },
{ 0x0480, { 10, 10 } },
{ 0x0440, { 11, 11 } },
{ 0x0400, { 11, 12 } },
{ 0x03c0, { 11, 13 } },
{ 0x0380, { 11, 14 } },
{ 0x0340, { 11, 15 } },
{ 0x0300, { 11, 16 } }
};
 
/* coding table as found in the spec annex B.5 table B-11 */
static const struct vl_vlc_compressed dmvector[] = {
{ 0x0000, { 1, 0 } },
{ 0x8000, { 2, 1 } },
{ 0xc000, { 2, -1 } }
};
 
/* coding table as found in the spec annex B.5 table B-12 */
static const struct vl_vlc_compressed dct_dc_size_luminance[] = {
{ 0x8000, { 3, 0 } },
{ 0x0000, { 2, 1 } },
{ 0x4000, { 2, 2 } },
{ 0xA000, { 3, 3 } },
{ 0xC000, { 3, 4 } },
{ 0xE000, { 4, 5 } },
{ 0xF000, { 5, 6 } },
{ 0xF800, { 6, 7 } },
{ 0xFC00, { 7, 8 } },
{ 0xFE00, { 8, 9 } },
{ 0xFF00, { 9, 10 } },
{ 0xFF80, { 9, 11 } }
};
 
/* coding table as found in the spec annex B.5 table B-13 */
static const struct vl_vlc_compressed dct_dc_size_chrominance[] = {
{ 0x0000, { 2, 0 } },
{ 0x4000, { 2, 1 } },
{ 0x8000, { 2, 2 } },
{ 0xC000, { 3, 3 } },
{ 0xE000, { 4, 4 } },
{ 0xF000, { 5, 5 } },
{ 0xF800, { 6, 6 } },
{ 0xFC00, { 7, 7 } },
{ 0xFE00, { 8, 8 } },
{ 0xFF00, { 9, 9 } },
{ 0xFF80, { 10, 10 } },
{ 0xFFC0, { 10, 11 } }
};
 
/* coding table as found in the spec annex B.5 table B-14 */
static const struct dct_coeff_compressed dct_coeff_tbl_zero[] = {
{ 0x8000, { 2, dct_End_of_Block, 0 } },
{ 0x8000, { 1, dct_DC, 1 } },
{ 0xC000, { 2, dct_AC, 1 } },
{ 0x6000, { 3, 1, 1 } },
{ 0x4000, { 4, 0, 2 } },
{ 0x5000, { 4, 2, 1 } },
{ 0x2800, { 5, 0, 3 } },
{ 0x3800, { 5, 3, 1 } },
{ 0x3000, { 5, 4, 1 } },
{ 0x1800, { 6, 1, 2 } },
{ 0x1C00, { 6, 5, 1 } },
{ 0x1400, { 6, 6, 1 } },
{ 0x1000, { 6, 7, 1 } },
{ 0x0C00, { 7, 0, 4 } },
{ 0x0800, { 7, 2, 2 } },
{ 0x0E00, { 7, 8, 1 } },
{ 0x0A00, { 7, 9, 1 } },
{ 0x0400, { 6, dct_Escape, 0 } },
{ 0x2600, { 8, 0, 5 } },
{ 0x2100, { 8, 0, 6 } },
{ 0x2500, { 8, 1, 3 } },
{ 0x2400, { 8, 3, 2 } },
{ 0x2700, { 8, 10, 1 } },
{ 0x2300, { 8, 11, 1 } },
{ 0x2200, { 8, 12, 1 } },
{ 0x2000, { 8, 13, 1 } },
{ 0x0280, { 10, 0, 7 } },
{ 0x0300, { 10, 1, 4 } },
{ 0x02C0, { 10, 2, 3 } },
{ 0x03C0, { 10, 4, 2 } },
{ 0x0240, { 10, 5, 2 } },
{ 0x0380, { 10, 14, 1 } },
{ 0x0340, { 10, 15, 1 } },
{ 0x0200, { 10, 16, 1 } },
{ 0x01D0, { 12, 0, 8 } },
{ 0x0180, { 12, 0, 9 } },
{ 0x0130, { 12, 0, 10 } },
{ 0x0100, { 12, 0, 11 } },
{ 0x01B0, { 12, 1, 5 } },
{ 0x0140, { 12, 2, 4 } },
{ 0x01C0, { 12, 3, 3 } },
{ 0x0120, { 12, 4, 3 } },
{ 0x01E0, { 12, 6, 2 } },
{ 0x0150, { 12, 7, 2 } },
{ 0x0110, { 12, 8, 2 } },
{ 0x01F0, { 12, 17, 1 } },
{ 0x01A0, { 12, 18, 1 } },
{ 0x0190, { 12, 19, 1 } },
{ 0x0170, { 12, 20, 1 } },
{ 0x0160, { 12, 21, 1 } },
{ 0x00D0, { 13, 0, 12 } },
{ 0x00C8, { 13, 0, 13 } },
{ 0x00C0, { 13, 0, 14 } },
{ 0x00B8, { 13, 0, 15 } },
{ 0x00B0, { 13, 1, 6 } },
{ 0x00A8, { 13, 1, 7 } },
{ 0x00A0, { 13, 2, 5 } },
{ 0x0098, { 13, 3, 4 } },
{ 0x0090, { 13, 5, 3 } },
{ 0x0088, { 13, 9, 2 } },
{ 0x0080, { 13, 10, 2 } },
{ 0x00F8, { 13, 22, 1 } },
{ 0x00F0, { 13, 23, 1 } },
{ 0x00E8, { 13, 24, 1 } },
{ 0x00E0, { 13, 25, 1 } },
{ 0x00D8, { 13, 26, 1 } },
{ 0x007C, { 14, 0, 16 } },
{ 0x0078, { 14, 0, 17 } },
{ 0x0074, { 14, 0, 18 } },
{ 0x0070, { 14, 0, 19 } },
{ 0x006C, { 14, 0, 20 } },
{ 0x0068, { 14, 0, 21 } },
{ 0x0064, { 14, 0, 22 } },
{ 0x0060, { 14, 0, 23 } },
{ 0x005C, { 14, 0, 24 } },
{ 0x0058, { 14, 0, 25 } },
{ 0x0054, { 14, 0, 26 } },
{ 0x0050, { 14, 0, 27 } },
{ 0x004C, { 14, 0, 28 } },
{ 0x0048, { 14, 0, 29 } },
{ 0x0044, { 14, 0, 30 } },
{ 0x0040, { 14, 0, 31 } },
{ 0x0030, { 15, 0, 32 } },
{ 0x002E, { 15, 0, 33 } },
{ 0x002C, { 15, 0, 34 } },
{ 0x002A, { 15, 0, 35 } },
{ 0x0028, { 15, 0, 36 } },
{ 0x0026, { 15, 0, 37 } },
{ 0x0024, { 15, 0, 38 } },
{ 0x0022, { 15, 0, 39 } },
{ 0x0020, { 15, 0, 40 } },
{ 0x003E, { 15, 1, 8 } },
{ 0x003C, { 15, 1, 9 } },
{ 0x003A, { 15, 1, 10 } },
{ 0x0038, { 15, 1, 11 } },
{ 0x0036, { 15, 1, 12 } },
{ 0x0034, { 15, 1, 13 } },
{ 0x0032, { 15, 1, 14 } },
{ 0x0013, { 16, 1, 15 } },
{ 0x0012, { 16, 1, 16 } },
{ 0x0011, { 16, 1, 17 } },
{ 0x0010, { 16, 1, 18 } },
{ 0x0014, { 16, 6, 3 } },
{ 0x001A, { 16, 11, 2 } },
{ 0x0019, { 16, 12, 2 } },
{ 0x0018, { 16, 13, 2 } },
{ 0x0017, { 16, 14, 2 } },
{ 0x0016, { 16, 15, 2 } },
{ 0x0015, { 16, 16, 2 } },
{ 0x001F, { 16, 27, 1 } },
{ 0x001E, { 16, 28, 1 } },
{ 0x001D, { 16, 29, 1 } },
{ 0x001C, { 16, 30, 1 } },
{ 0x001B, { 16, 31, 1 } }
};
 
/* coding table as found in the spec annex B.5 table B-15 */
static const struct dct_coeff_compressed dct_coeff_tbl_one[] = {
{ 0x6000, { 4, dct_End_of_Block, 0 } },
{ 0x8000, { 2, 0, 1 } },
{ 0x4000, { 3, 1, 1 } },
{ 0xC000, { 3, 0, 2 } },
{ 0x2800, { 5, 2, 1 } },
{ 0x7000, { 4, 0, 3 } },
{ 0x3800, { 5, 3, 1 } },
{ 0x1800, { 6, 4, 1 } },
{ 0x3000, { 5, 1, 2 } },
{ 0x1C00, { 6, 5, 1 } },
{ 0x0C00, { 7, 6, 1 } },
{ 0x0800, { 7, 7, 1 } },
{ 0xE000, { 5, 0, 4 } },
{ 0x0E00, { 7, 2, 2 } },
{ 0x0A00, { 7, 8, 1 } },
{ 0xF000, { 7, 9, 1 } },
{ 0x0400, { 6, dct_Escape, 0 } },
{ 0xE800, { 5, 0, 5 } },
{ 0x1400, { 6, 0, 6 } },
{ 0xF200, { 7, 1, 3 } },
{ 0x2600, { 8, 3, 2 } },
{ 0xF400, { 7, 10, 1 } },
{ 0x2100, { 8, 11, 1 } },
{ 0x2500, { 8, 12, 1 } },
{ 0x2400, { 8, 13, 1 } },
{ 0x1000, { 6, 0, 7 } },
{ 0x2700, { 8, 1, 4 } },
{ 0xFC00, { 8, 2, 3 } },
{ 0xFD00, { 8, 4, 2 } },
{ 0x0200, { 9, 5, 2 } },
{ 0x0280, { 9, 14, 1 } },
{ 0x0380, { 9, 15, 1 } },
{ 0x0340, { 10, 16, 1 } },
{ 0xF600, { 7, 0, 8 } },
{ 0xF800, { 7, 0, 9 } },
{ 0x2300, { 8, 0, 10 } },
{ 0x2200, { 8, 0, 11 } },
{ 0x2000, { 8, 1, 5 } },
{ 0x0300, { 10, 2, 4 } },
{ 0x01C0, { 12, 3, 3 } },
{ 0x0120, { 12, 4, 3 } },
{ 0x01E0, { 12, 6, 2 } },
{ 0x0150, { 12, 7, 2 } },
{ 0x0110, { 12, 8, 2 } },
{ 0x01F0, { 12, 17, 1 } },
{ 0x01A0, { 12, 18, 1 } },
{ 0x0190, { 12, 19, 1 } },
{ 0x0170, { 12, 20, 1 } },
{ 0x0160, { 12, 21, 1 } },
{ 0xFA00, { 8, 0, 12 } },
{ 0xFB00, { 8, 0, 13 } },
{ 0xFE00, { 8, 0, 14 } },
{ 0xFF00, { 8, 0, 15 } },
{ 0x00B0, { 13, 1, 6 } },
{ 0x00A8, { 13, 1, 7 } },
{ 0x00A0, { 13, 2, 5 } },
{ 0x0098, { 13, 3, 4 } },
{ 0x0090, { 13, 5, 3 } },
{ 0x0088, { 13, 9, 2 } },
{ 0x0080, { 13, 10, 2 } },
{ 0x00F8, { 13, 22, 1 } },
{ 0x00F0, { 13, 23, 1 } },
{ 0x00E8, { 13, 24, 1 } },
{ 0x00E0, { 13, 25, 1 } },
{ 0x00D8, { 13, 26, 1 } },
{ 0x007C, { 14, 0, 16 } },
{ 0x0078, { 14, 0, 17 } },
{ 0x0074, { 14, 0, 18 } },
{ 0x0070, { 14, 0, 19 } },
{ 0x006C, { 14, 0, 20 } },
{ 0x0068, { 14, 0, 21 } },
{ 0x0064, { 14, 0, 22 } },
{ 0x0060, { 14, 0, 23 } },
{ 0x005C, { 14, 0, 24 } },
{ 0x0058, { 14, 0, 25 } },
{ 0x0054, { 14, 0, 26 } },
{ 0x0050, { 14, 0, 27 } },
{ 0x004C, { 14, 0, 28 } },
{ 0x0048, { 14, 0, 29 } },
{ 0x0044, { 14, 0, 30 } },
{ 0x0040, { 14, 0, 31 } },
{ 0x0030, { 15, 0, 32 } },
{ 0x002E, { 15, 0, 33 } },
{ 0x002C, { 15, 0, 34 } },
{ 0x002A, { 15, 0, 35 } },
{ 0x0028, { 15, 0, 36 } },
{ 0x0026, { 15, 0, 37 } },
{ 0x0024, { 15, 0, 38 } },
{ 0x0022, { 15, 0, 39 } },
{ 0x0020, { 15, 0, 40 } },
{ 0x003E, { 15, 1, 8 } },
{ 0x003C, { 15, 1, 9 } },
{ 0x003A, { 15, 1, 10 } },
{ 0x0038, { 15, 1, 11 } },
{ 0x0036, { 15, 1, 12 } },
{ 0x0034, { 15, 1, 13 } },
{ 0x0032, { 15, 1, 14 } },
{ 0x0013, { 16, 1, 15 } },
{ 0x0012, { 16, 1, 16 } },
{ 0x0011, { 16, 1, 17 } },
{ 0x0010, { 16, 1, 18 } },
{ 0x0014, { 16, 6, 3 } },
{ 0x001A, { 16, 11, 2 } },
{ 0x0019, { 16, 12, 2 } },
{ 0x0018, { 16, 13, 2 } },
{ 0x0017, { 16, 14, 2 } },
{ 0x0016, { 16, 15, 2 } },
{ 0x0015, { 16, 16, 2 } },
{ 0x001F, { 16, 27, 1 } },
{ 0x001E, { 16, 28, 1 } },
{ 0x001D, { 16, 29, 1 } },
{ 0x001C, { 16, 30, 1 } },
{ 0x001B, { 16, 31, 1 } }
};
 
/* q_scale_type */
static const unsigned quant_scale[2][32] = {
{ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30,
32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62 },
{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 18, 20, 22, 24,
28, 32, 36, 40, 44, 48, 52, 56, 64, 72, 80, 88, 96, 104, 112 }
};
 
static struct vl_vlc_entry tbl_B1[1 << 11];
static struct vl_vlc_entry tbl_B2[1 << 2];
static struct vl_vlc_entry tbl_B3[1 << 6];
static struct vl_vlc_entry tbl_B4[1 << 6];
static struct vl_vlc_entry tbl_B9[1 << 9];
static struct vl_vlc_entry tbl_B10[1 << 11];
static struct vl_vlc_entry tbl_B11[1 << 2];
static struct vl_vlc_entry tbl_B12[1 << 10];
static struct vl_vlc_entry tbl_B13[1 << 10];
static struct dct_coeff tbl_B14_DC[1 << 17];
static struct dct_coeff tbl_B14_AC[1 << 17];
static struct dct_coeff tbl_B15[1 << 17];
 
static INLINE void
init_dct_coeff_table(struct dct_coeff *dst, const struct dct_coeff_compressed *src,
unsigned size, bool is_DC)
{
unsigned i;
 
for (i=0;i<(1<<17);++i) {
dst[i].length = 0;
dst[i].level = 0;
dst[i].run = dct_End_of_Block;
}
 
for(; size > 0; --size, ++src) {
struct dct_coeff coeff = src->coeff;
bool has_sign = true;
 
switch (coeff.run) {
case dct_End_of_Block:
if (is_DC)
continue;
 
has_sign = false;
break;
 
case dct_Escape:
has_sign = false;
break;
 
case dct_DC:
if (!is_DC)
continue;
 
coeff.length += 1;
coeff.run = 1;
break;
 
case dct_AC:
if (is_DC)
continue;
 
coeff.length += 1;
coeff.run = 1;
break;
 
default:
coeff.length += 1;
coeff.run += 1;
break;
}
 
for(i=0; i<(1 << (17 - coeff.length)); ++i)
dst[src->bitcode << 1 | i] = coeff;
 
if (has_sign) {
coeff.level = -coeff.level;
for(; i<(1 << (18 - coeff.length)); ++i)
dst[src->bitcode << 1 | i] = coeff;
}
}
}
 
static INLINE void
init_tables()
{
vl_vlc_init_table(tbl_B1, Elements(tbl_B1), macroblock_address_increment, Elements(macroblock_address_increment));
vl_vlc_init_table(tbl_B2, Elements(tbl_B2), macroblock_type_i, Elements(macroblock_type_i));
vl_vlc_init_table(tbl_B3, Elements(tbl_B3), macroblock_type_p, Elements(macroblock_type_p));
vl_vlc_init_table(tbl_B4, Elements(tbl_B4), macroblock_type_b, Elements(macroblock_type_b));
vl_vlc_init_table(tbl_B9, Elements(tbl_B9), coded_block_pattern, Elements(coded_block_pattern));
vl_vlc_init_table(tbl_B10, Elements(tbl_B10), motion_code, Elements(motion_code));
vl_vlc_init_table(tbl_B11, Elements(tbl_B11), dmvector, Elements(dmvector));
vl_vlc_init_table(tbl_B12, Elements(tbl_B12), dct_dc_size_luminance, Elements(dct_dc_size_luminance));
vl_vlc_init_table(tbl_B13, Elements(tbl_B13), dct_dc_size_chrominance, Elements(dct_dc_size_chrominance));
init_dct_coeff_table(tbl_B14_DC, dct_coeff_tbl_zero, Elements(dct_coeff_tbl_zero), true);
init_dct_coeff_table(tbl_B14_AC, dct_coeff_tbl_zero, Elements(dct_coeff_tbl_zero), false);
init_dct_coeff_table(tbl_B15, dct_coeff_tbl_one, Elements(dct_coeff_tbl_one), false);
}
 
static INLINE int
DIV2DOWN(int todiv)
{
return (todiv&~1)/2;
}
 
static INLINE int
DIV2UP(int todiv)
{
return (todiv+1)/2;
}
 
static INLINE void
motion_vector(struct vl_mpg12_bs *bs, int r, int s, int dmv, short delta[2], short dmvector[2])
{
int t;
for (t = 0; t < 2; ++t) {
int motion_code;
int r_size = bs->desc->f_code[s][t];
 
vl_vlc_fillbits(&bs->vlc);
motion_code = vl_vlc_get_vlclbf(&bs->vlc, tbl_B10, 11);
 
assert(r_size >= 0);
if (r_size && motion_code) {
int residual = vl_vlc_get_uimsbf(&bs->vlc, r_size) + 1;
delta[t] = ((abs(motion_code) - 1) << r_size) + residual;
if (motion_code < 0)
delta[t] = -delta[t];
} else
delta[t] = motion_code;
if (dmv)
dmvector[t] = vl_vlc_get_vlclbf(&bs->vlc, tbl_B11, 2);
}
}
 
static INLINE int
wrap(short f, int shift)
{
if (f < (-16 << shift))
return f + (32 << shift);
else if (f >= 16 << shift)
return f - (32 << shift);
else
return f;
}
 
static INLINE void
motion_vector_frame(struct vl_mpg12_bs *bs, int s, struct pipe_mpeg12_macroblock *mb)
{
int dmv = mb->macroblock_modes.bits.frame_motion_type == PIPE_MPEG12_MO_TYPE_DUAL_PRIME;
short dmvector[2], delta[2];
 
if (mb->macroblock_modes.bits.frame_motion_type == PIPE_MPEG12_MO_TYPE_FIELD) {
mb->motion_vertical_field_select |= vl_vlc_get_uimsbf(&bs->vlc, 1) << s;
motion_vector(bs, 0, s, dmv, delta, dmvector);
mb->PMV[0][s][0] = wrap(mb->PMV[0][s][0] + delta[0], bs->desc->f_code[s][0]);
mb->PMV[0][s][1] = wrap(DIV2DOWN(mb->PMV[0][s][1]) + delta[1], bs->desc->f_code[s][1]) * 2;
 
mb->motion_vertical_field_select |= vl_vlc_get_uimsbf(&bs->vlc, 1) << (s + 2);
motion_vector(bs, 1, s, dmv, delta, dmvector);
mb->PMV[1][s][0] = wrap(mb->PMV[1][s][0] + delta[0], bs->desc->f_code[s][0]);
mb->PMV[1][s][1] = wrap(DIV2DOWN(mb->PMV[1][s][1]) + delta[1], bs->desc->f_code[s][1]) * 2;
 
} else {
motion_vector(bs, 0, s, dmv, delta, dmvector);
mb->PMV[0][s][0] = wrap(mb->PMV[0][s][0] + delta[0], bs->desc->f_code[s][0]);
mb->PMV[0][s][1] = wrap(mb->PMV[0][s][1] + delta[1], bs->desc->f_code[s][1]);
}
}
 
static INLINE void
motion_vector_field(struct vl_mpg12_bs *bs, int s, struct pipe_mpeg12_macroblock *mb)
{
int dmv = mb->macroblock_modes.bits.field_motion_type == PIPE_MPEG12_MO_TYPE_DUAL_PRIME;
short dmvector[2], delta[2];
 
if (mb->macroblock_modes.bits.field_motion_type == PIPE_MPEG12_MO_TYPE_16x8) {
mb->motion_vertical_field_select |= vl_vlc_get_uimsbf(&bs->vlc, 1) << s;
motion_vector(bs, 0, s, dmv, delta, dmvector);
 
mb->motion_vertical_field_select |= vl_vlc_get_uimsbf(&bs->vlc, 1) << (s + 2);
motion_vector(bs, 1, s, dmv, delta, dmvector);
} else {
if (!dmv)
mb->motion_vertical_field_select |= vl_vlc_get_uimsbf(&bs->vlc, 1) << s;
motion_vector(bs, 0, s, dmv, delta, dmvector);
}
}
 
static INLINE void
reset_predictor(struct vl_mpg12_bs *bs) {
bs->pred_dc[0] = bs->pred_dc[1] = bs->pred_dc[2] = 0;
}
 
static INLINE void
decode_dct(struct vl_mpg12_bs *bs, struct pipe_mpeg12_macroblock *mb, int scale)
{
static const unsigned blk2cc[] = { 0, 0, 0, 0, 1, 2 };
static const struct vl_vlc_entry *blk2dcsize[] = {
tbl_B12, tbl_B12, tbl_B12, tbl_B12, tbl_B13, tbl_B13
};
 
bool intra = mb->macroblock_type & PIPE_MPEG12_MB_TYPE_INTRA;
const struct dct_coeff *table = intra ? bs->intra_dct_tbl : tbl_B14_AC;
const struct dct_coeff *entry;
int i, cbp, blk = 0;
short *dst = mb->blocks;
 
vl_vlc_fillbits(&bs->vlc);
mb->coded_block_pattern = cbp = intra ? 0x3F : vl_vlc_get_vlclbf(&bs->vlc, tbl_B9, 9);
 
goto entry;
 
while(1) {
vl_vlc_eatbits(&bs->vlc, entry->length);
if (entry->run == dct_End_of_Block) {
 
next_d:
dst += 64;
cbp <<= 1;
cbp &= 0x3F;
blk++;
 
entry:
if (!cbp)
break;
 
while(!(cbp & 0x20)) {
cbp <<= 1;
blk++;
}
 
vl_vlc_fillbits(&bs->vlc);
 
if (intra) {
unsigned cc = blk2cc[blk];
unsigned size = vl_vlc_get_vlclbf(&bs->vlc, blk2dcsize[blk], 10);
 
if (size) {
int dct_diff = vl_vlc_get_uimsbf(&bs->vlc, size);
int half_range = 1 << (size - 1);
if (dct_diff < half_range)
dct_diff = (dct_diff + 1) - (2 * half_range);
bs->pred_dc[cc] += dct_diff;
}
 
dst[0] = bs->pred_dc[cc];
i = 0;
 
if (bs->desc->picture_coding_type == PIPE_MPEG12_PICTURE_CODING_TYPE_D)
goto next_d;
} else {
entry = tbl_B14_DC + vl_vlc_peekbits(&bs->vlc, 17);
i = -1;
continue;
}
 
} else if (entry->run == dct_Escape &&
bs->decoder->profile == PIPE_VIDEO_PROFILE_MPEG1) {
i += vl_vlc_get_uimsbf(&bs->vlc, 6) + 1;
if (i > 64)
break;
 
dst[i] = vl_vlc_get_simsbf(&bs->vlc, 8);
if (dst[i] == -128)
dst[i] = vl_vlc_get_uimsbf(&bs->vlc, 8) - 256;
else if (dst[i] == 0)
dst[i] = vl_vlc_get_uimsbf(&bs->vlc, 8);
 
dst[i] *= scale;
} else if (entry->run == dct_Escape) {
i += vl_vlc_get_uimsbf(&bs->vlc, 6) + 1;
if (i > 64)
break;
 
dst[i] = vl_vlc_get_simsbf(&bs->vlc, 12) * scale;
 
} else {
i += entry->run;
if (i > 64)
break;
 
dst[i] = entry->level * scale;
}
 
vl_vlc_fillbits(&bs->vlc);
entry = table + vl_vlc_peekbits(&bs->vlc, 17);
}
 
if (bs->desc->picture_coding_type == PIPE_MPEG12_PICTURE_CODING_TYPE_D)
vl_vlc_eatbits(&bs->vlc, 1);
}
 
static INLINE void
decode_slice(struct vl_mpg12_bs *bs, struct pipe_video_buffer *target)
{
struct pipe_mpeg12_macroblock mb;
short dct_blocks[64*6];
unsigned dct_scale;
signed x = -1;
 
memset(&mb, 0, sizeof(mb));
mb.base.codec = PIPE_VIDEO_CODEC_MPEG12;
mb.y = vl_vlc_get_uimsbf(&bs->vlc, 8) - 1;
mb.blocks = dct_blocks;
 
reset_predictor(bs);
vl_vlc_fillbits(&bs->vlc);
dct_scale = quant_scale[bs->desc->q_scale_type][vl_vlc_get_uimsbf(&bs->vlc, 5)];
 
if (vl_vlc_get_uimsbf(&bs->vlc, 1))
while (vl_vlc_get_uimsbf(&bs->vlc, 9) & 1)
vl_vlc_fillbits(&bs->vlc);
 
vl_vlc_fillbits(&bs->vlc);
assert(vl_vlc_peekbits(&bs->vlc, 23));
do {
int inc = 0;
 
while (1) {
/* MPEG-1 macroblock stuffing, can appear an arbitrary number of times. */
while (vl_vlc_peekbits(&bs->vlc, 11) == 15) {
vl_vlc_eatbits(&bs->vlc, 11);
vl_vlc_fillbits(&bs->vlc);
}
 
if (vl_vlc_peekbits(&bs->vlc, 11) == 8) {
vl_vlc_eatbits(&bs->vlc, 11);
vl_vlc_fillbits(&bs->vlc);
inc += 33;
} else {
inc += vl_vlc_get_vlclbf(&bs->vlc, tbl_B1, 11);
break;
}
}
 
if (x != -1) {
if (!inc)
return;
mb.num_skipped_macroblocks = inc - 1;
bs->decoder->decode_macroblock(bs->decoder, target, &bs->desc->base, &mb.base, 1);
}
mb.x = x += inc;
if (bs->decoder->profile == PIPE_VIDEO_PROFILE_MPEG1) {
int width = align(bs->decoder->width, 16) / 16;
mb.y += mb.x / width;
mb.x = x %= width;
}
 
switch (bs->desc->picture_coding_type) {
case PIPE_MPEG12_PICTURE_CODING_TYPE_I:
mb.macroblock_type = vl_vlc_get_vlclbf(&bs->vlc, tbl_B2, 2);
break;
 
case PIPE_MPEG12_PICTURE_CODING_TYPE_P:
mb.macroblock_type = vl_vlc_get_vlclbf(&bs->vlc, tbl_B3, 6);
break;
 
case PIPE_MPEG12_PICTURE_CODING_TYPE_B:
mb.macroblock_type = vl_vlc_get_vlclbf(&bs->vlc, tbl_B4, 6);
break;
 
case PIPE_MPEG12_PICTURE_CODING_TYPE_D:
vl_vlc_eatbits(&bs->vlc, 1);
mb.macroblock_type = PIPE_MPEG12_MB_TYPE_INTRA;
break;
}
 
mb.macroblock_modes.value = 0;
if (mb.macroblock_type & (PIPE_MPEG12_MB_TYPE_MOTION_FORWARD | PIPE_MPEG12_MB_TYPE_MOTION_BACKWARD)) {
if (bs->desc->picture_structure == PIPE_MPEG12_PICTURE_STRUCTURE_FRAME) {
if (bs->desc->frame_pred_frame_dct == 0)
mb.macroblock_modes.bits.frame_motion_type = vl_vlc_get_uimsbf(&bs->vlc, 2);
else
mb.macroblock_modes.bits.frame_motion_type = 2;
} else
mb.macroblock_modes.bits.field_motion_type = vl_vlc_get_uimsbf(&bs->vlc, 2);
 
} else if ((mb.macroblock_type & PIPE_MPEG12_MB_TYPE_INTRA) && bs->desc->concealment_motion_vectors) {
if (bs->desc->picture_structure == PIPE_MPEG12_PICTURE_STRUCTURE_FRAME)
mb.macroblock_modes.bits.frame_motion_type = 2;
else
mb.macroblock_modes.bits.field_motion_type = 1;
}
 
if (bs->desc->picture_structure == PIPE_MPEG12_PICTURE_STRUCTURE_FRAME &&
bs->desc->frame_pred_frame_dct == 0 &&
mb.macroblock_type & (PIPE_MPEG12_MB_TYPE_INTRA | PIPE_MPEG12_MB_TYPE_PATTERN))
mb.macroblock_modes.bits.dct_type = vl_vlc_get_uimsbf(&bs->vlc, 1);
 
if (mb.macroblock_type & PIPE_MPEG12_MB_TYPE_QUANT)
dct_scale = quant_scale[bs->desc->q_scale_type][vl_vlc_get_uimsbf(&bs->vlc, 5)];
 
if (inc > 1 && bs->desc->picture_coding_type == PIPE_MPEG12_PICTURE_CODING_TYPE_P)
memset(mb.PMV, 0, sizeof(mb.PMV));
 
mb.motion_vertical_field_select = 0;
if ((mb.macroblock_type & PIPE_MPEG12_MB_TYPE_MOTION_FORWARD) ||
(mb.macroblock_type & PIPE_MPEG12_MB_TYPE_INTRA && bs->desc->concealment_motion_vectors)) {
if (bs->desc->picture_structure == PIPE_MPEG12_PICTURE_STRUCTURE_FRAME)
motion_vector_frame(bs, 0, &mb);
else
motion_vector_field(bs, 0, &mb);
}
 
if (mb.macroblock_type & PIPE_MPEG12_MB_TYPE_MOTION_BACKWARD) {
if (bs->desc->picture_structure == PIPE_MPEG12_PICTURE_STRUCTURE_FRAME)
motion_vector_frame(bs, 1, &mb);
else
motion_vector_field(bs, 1, &mb);
}
 
if (mb.macroblock_type & PIPE_MPEG12_MB_TYPE_INTRA && bs->desc->concealment_motion_vectors) {
unsigned extra = vl_vlc_get_uimsbf(&bs->vlc, 1);
mb.PMV[1][0][0] = mb.PMV[0][0][0];
mb.PMV[1][0][1] = mb.PMV[0][0][1];
assert(extra);
} else if (mb.macroblock_type & PIPE_MPEG12_MB_TYPE_INTRA ||
!(mb.macroblock_type & (PIPE_MPEG12_MB_TYPE_MOTION_FORWARD |
PIPE_MPEG12_MB_TYPE_MOTION_BACKWARD))) {
memset(mb.PMV, 0, sizeof(mb.PMV));
}
 
if ((mb.macroblock_type & PIPE_MPEG12_MB_TYPE_MOTION_FORWARD &&
mb.macroblock_modes.bits.frame_motion_type == 2) ||
(mb.macroblock_modes.bits.frame_motion_type == 3)) {
mb.PMV[1][0][0] = mb.PMV[0][0][0];
mb.PMV[1][0][1] = mb.PMV[0][0][1];
}
 
if (mb.macroblock_type & PIPE_MPEG12_MB_TYPE_MOTION_BACKWARD &&
mb.macroblock_modes.bits.frame_motion_type == 2) {
mb.PMV[1][1][0] = mb.PMV[0][1][0];
mb.PMV[1][1][1] = mb.PMV[0][1][1];
}
 
if (inc > 1 || !(mb.macroblock_type & PIPE_MPEG12_MB_TYPE_INTRA))
reset_predictor(bs);
 
if (mb.macroblock_type & (PIPE_MPEG12_MB_TYPE_INTRA | PIPE_MPEG12_MB_TYPE_PATTERN)) {
memset(dct_blocks, 0, sizeof(dct_blocks));
decode_dct(bs, &mb, dct_scale);
} else
mb.coded_block_pattern = 0;
 
vl_vlc_fillbits(&bs->vlc);
} while (vl_vlc_bits_left(&bs->vlc) && vl_vlc_peekbits(&bs->vlc, 23));
 
mb.num_skipped_macroblocks = 0;
bs->decoder->decode_macroblock(bs->decoder, target, &bs->desc->base, &mb.base, 1);
}
 
void
vl_mpg12_bs_init(struct vl_mpg12_bs *bs, struct pipe_video_decoder *decoder)
{
static bool tables_initialized = false;
 
assert(bs);
 
memset(bs, 0, sizeof(struct vl_mpg12_bs));
 
bs->decoder = decoder;
 
if (!tables_initialized) {
init_tables();
tables_initialized = true;
}
}
 
void
vl_mpg12_bs_decode(struct vl_mpg12_bs *bs,
struct pipe_video_buffer *target,
struct pipe_mpeg12_picture_desc *picture,
unsigned num_buffers,
const void * const *buffers,
const unsigned *sizes)
{
assert(bs);
 
bs->desc = picture;
bs->intra_dct_tbl = picture->intra_vlc_format ? tbl_B15 : tbl_B14_AC;
 
vl_vlc_init(&bs->vlc, num_buffers, buffers, sizes);
while (vl_vlc_bits_left(&bs->vlc) > 32) {
uint32_t code = vl_vlc_peekbits(&bs->vlc, 32);
 
if (code >= 0x101 && code <= 0x1AF) {
vl_vlc_eatbits(&bs->vlc, 24);
decode_slice(bs, target);
 
/* align to a byte again */
vl_vlc_eatbits(&bs->vlc, vl_vlc_valid_bits(&bs->vlc) & 7);
 
} else {
vl_vlc_eatbits(&bs->vlc, 8);
}
 
vl_vlc_fillbits(&bs->vlc);
}
}
/drivers/video/Gallium/auxiliary/vl/vl_mpeg12_bitstream.h
0,0 → 1,56
/**************************************************************************
*
* Copyright 2011 Christian König.
* 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.
*
**************************************************************************/
 
#ifndef vl_mpeg12_bitstream_h
#define vl_mpeg12_bitstream_h
 
#include "vl_defines.h"
#include "vl_vlc.h"
 
struct vl_mpg12_bs
{
struct pipe_video_decoder *decoder;
 
struct pipe_mpeg12_picture_desc *desc;
struct dct_coeff *intra_dct_tbl;
 
struct vl_vlc vlc;
short pred_dc[3];
};
 
void
vl_mpg12_bs_init(struct vl_mpg12_bs *bs, struct pipe_video_decoder *decoder);
 
void
vl_mpg12_bs_decode(struct vl_mpg12_bs *bs,
struct pipe_video_buffer *target,
struct pipe_mpeg12_picture_desc *picture,
unsigned num_buffers,
const void * const *buffers,
const unsigned *sizes);
 
#endif /* vl_mpeg12_bitstream_h */
/drivers/video/Gallium/auxiliary/vl/vl_mpeg12_decoder.c
0,0 → 1,1157
/**************************************************************************
*
* Copyright 2009 Younes Manton.
* 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.
*
**************************************************************************/
 
#include <math.h>
#include <assert.h>
 
#include "util/u_memory.h"
#include "util/u_rect.h"
#include "util/u_sampler.h"
#include "util/u_video.h"
 
#include "vl_mpeg12_decoder.h"
#include "vl_defines.h"
 
#define SCALE_FACTOR_SNORM (32768.0f / 256.0f)
#define SCALE_FACTOR_SSCALED (1.0f / 256.0f)
 
struct format_config {
enum pipe_format zscan_source_format;
enum pipe_format idct_source_format;
enum pipe_format mc_source_format;
 
float idct_scale;
float mc_scale;
};
 
static const struct format_config bitstream_format_config[] = {
// { PIPE_FORMAT_R16_SSCALED, PIPE_FORMAT_R16G16B16A16_SSCALED, PIPE_FORMAT_R16G16B16A16_FLOAT, 1.0f, SCALE_FACTOR_SSCALED },
// { PIPE_FORMAT_R16_SSCALED, PIPE_FORMAT_R16G16B16A16_SSCALED, PIPE_FORMAT_R16G16B16A16_SSCALED, 1.0f, SCALE_FACTOR_SSCALED },
{ PIPE_FORMAT_R16_SNORM, PIPE_FORMAT_R16G16B16A16_SNORM, PIPE_FORMAT_R16G16B16A16_FLOAT, 1.0f, SCALE_FACTOR_SNORM },
{ PIPE_FORMAT_R16_SNORM, PIPE_FORMAT_R16G16B16A16_SNORM, PIPE_FORMAT_R16G16B16A16_SNORM, 1.0f, SCALE_FACTOR_SNORM }
};
 
static const unsigned num_bitstream_format_configs =
sizeof(bitstream_format_config) / sizeof(struct format_config);
 
static const struct format_config idct_format_config[] = {
// { PIPE_FORMAT_R16_SSCALED, PIPE_FORMAT_R16G16B16A16_SSCALED, PIPE_FORMAT_R16G16B16A16_FLOAT, 1.0f, SCALE_FACTOR_SSCALED },
// { PIPE_FORMAT_R16_SSCALED, PIPE_FORMAT_R16G16B16A16_SSCALED, PIPE_FORMAT_R16G16B16A16_SSCALED, 1.0f, SCALE_FACTOR_SSCALED },
{ PIPE_FORMAT_R16_SNORM, PIPE_FORMAT_R16G16B16A16_SNORM, PIPE_FORMAT_R16G16B16A16_FLOAT, 1.0f, SCALE_FACTOR_SNORM },
{ PIPE_FORMAT_R16_SNORM, PIPE_FORMAT_R16G16B16A16_SNORM, PIPE_FORMAT_R16G16B16A16_SNORM, 1.0f, SCALE_FACTOR_SNORM }
};
 
static const unsigned num_idct_format_configs =
sizeof(idct_format_config) / sizeof(struct format_config);
 
static const struct format_config mc_format_config[] = {
//{ PIPE_FORMAT_R16_SSCALED, PIPE_FORMAT_NONE, PIPE_FORMAT_R16_SSCALED, 0.0f, SCALE_FACTOR_SSCALED },
{ PIPE_FORMAT_R16_SNORM, PIPE_FORMAT_NONE, PIPE_FORMAT_R16_SNORM, 0.0f, SCALE_FACTOR_SNORM }
};
 
static const unsigned num_mc_format_configs =
sizeof(mc_format_config) / sizeof(struct format_config);
 
static const unsigned const_empty_block_mask_420[3][2][2] = {
{ { 0x20, 0x10 }, { 0x08, 0x04 } },
{ { 0x02, 0x02 }, { 0x02, 0x02 } },
{ { 0x01, 0x01 }, { 0x01, 0x01 } }
};
 
static bool
init_zscan_buffer(struct vl_mpeg12_decoder *dec, struct vl_mpeg12_buffer *buffer)
{
struct pipe_resource *res, res_tmpl;
struct pipe_sampler_view sv_tmpl;
struct pipe_surface **destination;
 
unsigned i;
 
assert(dec && buffer);
 
memset(&res_tmpl, 0, sizeof(res_tmpl));
res_tmpl.target = PIPE_TEXTURE_2D;
res_tmpl.format = dec->zscan_source_format;
res_tmpl.width0 = dec->blocks_per_line * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT;
res_tmpl.height0 = align(dec->num_blocks, dec->blocks_per_line) / dec->blocks_per_line;
res_tmpl.depth0 = 1;
res_tmpl.array_size = 1;
res_tmpl.usage = PIPE_USAGE_STREAM;
res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW;
 
res = dec->base.context->screen->resource_create(dec->base.context->screen, &res_tmpl);
if (!res)
goto error_source;
 
 
memset(&sv_tmpl, 0, sizeof(sv_tmpl));
u_sampler_view_default_template(&sv_tmpl, res, res->format);
sv_tmpl.swizzle_r = sv_tmpl.swizzle_g = sv_tmpl.swizzle_b = sv_tmpl.swizzle_a = PIPE_SWIZZLE_RED;
buffer->zscan_source = dec->base.context->create_sampler_view(dec->base.context, res, &sv_tmpl);
pipe_resource_reference(&res, NULL);
if (!buffer->zscan_source)
goto error_sampler;
 
if (dec->base.entrypoint <= PIPE_VIDEO_ENTRYPOINT_IDCT)
destination = dec->idct_source->get_surfaces(dec->idct_source);
else
destination = dec->mc_source->get_surfaces(dec->mc_source);
 
if (!destination)
goto error_surface;
 
for (i = 0; i < VL_NUM_COMPONENTS; ++i)
if (!vl_zscan_init_buffer(i == 0 ? &dec->zscan_y : &dec->zscan_c,
&buffer->zscan[i], buffer->zscan_source, destination[i]))
goto error_plane;
 
return true;
 
error_plane:
for (; i > 0; --i)
vl_zscan_cleanup_buffer(&buffer->zscan[i - 1]);
 
error_surface:
error_sampler:
pipe_sampler_view_reference(&buffer->zscan_source, NULL);
 
error_source:
return false;
}
 
static void
cleanup_zscan_buffer(struct vl_mpeg12_buffer *buffer)
{
unsigned i;
 
assert(buffer);
 
for (i = 0; i < VL_NUM_COMPONENTS; ++i)
vl_zscan_cleanup_buffer(&buffer->zscan[i]);
 
pipe_sampler_view_reference(&buffer->zscan_source, NULL);
}
 
static bool
init_idct_buffer(struct vl_mpeg12_decoder *dec, struct vl_mpeg12_buffer *buffer)
{
struct pipe_sampler_view **idct_source_sv, **mc_source_sv;
 
unsigned i;
 
assert(dec && buffer);
 
idct_source_sv = dec->idct_source->get_sampler_view_planes(dec->idct_source);
if (!idct_source_sv)
goto error_source_sv;
 
mc_source_sv = dec->mc_source->get_sampler_view_planes(dec->mc_source);
if (!mc_source_sv)
goto error_mc_source_sv;
 
for (i = 0; i < 3; ++i)
if (!vl_idct_init_buffer(i == 0 ? &dec->idct_y : &dec->idct_c,
&buffer->idct[i], idct_source_sv[i],
mc_source_sv[i]))
goto error_plane;
 
return true;
 
error_plane:
for (; i > 0; --i)
vl_idct_cleanup_buffer(&buffer->idct[i - 1]);
 
error_mc_source_sv:
error_source_sv:
return false;
}
 
static void
cleanup_idct_buffer(struct vl_mpeg12_buffer *buf)
{
unsigned i;
assert(buf);
 
for (i = 0; i < 3; ++i)
vl_idct_cleanup_buffer(&buf->idct[0]);
}
 
static bool
init_mc_buffer(struct vl_mpeg12_decoder *dec, struct vl_mpeg12_buffer *buf)
{
assert(dec && buf);
 
if(!vl_mc_init_buffer(&dec->mc_y, &buf->mc[0]))
goto error_mc_y;
 
if(!vl_mc_init_buffer(&dec->mc_c, &buf->mc[1]))
goto error_mc_cb;
 
if(!vl_mc_init_buffer(&dec->mc_c, &buf->mc[2]))
goto error_mc_cr;
 
return true;
 
error_mc_cr:
vl_mc_cleanup_buffer(&buf->mc[1]);
 
error_mc_cb:
vl_mc_cleanup_buffer(&buf->mc[0]);
 
error_mc_y:
return false;
}
 
static void
cleanup_mc_buffer(struct vl_mpeg12_buffer *buf)
{
unsigned i;
 
assert(buf);
 
for (i = 0; i < VL_NUM_COMPONENTS; ++i)
vl_mc_cleanup_buffer(&buf->mc[i]);
}
 
static INLINE void
MacroBlockTypeToPipeWeights(const struct pipe_mpeg12_macroblock *mb, unsigned weights[2])
{
assert(mb);
 
switch (mb->macroblock_type & (PIPE_MPEG12_MB_TYPE_MOTION_FORWARD | PIPE_MPEG12_MB_TYPE_MOTION_BACKWARD)) {
case PIPE_MPEG12_MB_TYPE_MOTION_FORWARD:
weights[0] = PIPE_VIDEO_MV_WEIGHT_MAX;
weights[1] = PIPE_VIDEO_MV_WEIGHT_MIN;
break;
 
case (PIPE_MPEG12_MB_TYPE_MOTION_FORWARD | PIPE_MPEG12_MB_TYPE_MOTION_BACKWARD):
weights[0] = PIPE_VIDEO_MV_WEIGHT_HALF;
weights[1] = PIPE_VIDEO_MV_WEIGHT_HALF;
break;
 
case PIPE_MPEG12_MB_TYPE_MOTION_BACKWARD:
weights[0] = PIPE_VIDEO_MV_WEIGHT_MIN;
weights[1] = PIPE_VIDEO_MV_WEIGHT_MAX;
break;
 
default:
if (mb->macroblock_type & PIPE_MPEG12_MB_TYPE_INTRA) {
weights[0] = PIPE_VIDEO_MV_WEIGHT_MIN;
weights[1] = PIPE_VIDEO_MV_WEIGHT_MIN;
} else {
/* no motion vector, but also not intra mb ->
just copy the old frame content */
weights[0] = PIPE_VIDEO_MV_WEIGHT_MAX;
weights[1] = PIPE_VIDEO_MV_WEIGHT_MIN;
}
break;
}
}
 
static INLINE struct vl_motionvector
MotionVectorToPipe(const struct pipe_mpeg12_macroblock *mb, unsigned vector,
unsigned field_select_mask, unsigned weight)
{
struct vl_motionvector mv;
 
assert(mb);
 
if (mb->macroblock_type & (PIPE_MPEG12_MB_TYPE_MOTION_FORWARD | PIPE_MPEG12_MB_TYPE_MOTION_BACKWARD)) {
switch (mb->macroblock_modes.bits.frame_motion_type) {
case PIPE_MPEG12_MO_TYPE_FRAME:
mv.top.x = mb->PMV[0][vector][0];
mv.top.y = mb->PMV[0][vector][1];
mv.top.field_select = PIPE_VIDEO_FRAME;
mv.top.weight = weight;
 
mv.bottom.x = mb->PMV[0][vector][0];
mv.bottom.y = mb->PMV[0][vector][1];
mv.bottom.weight = weight;
mv.bottom.field_select = PIPE_VIDEO_FRAME;
break;
 
case PIPE_MPEG12_MO_TYPE_FIELD:
mv.top.x = mb->PMV[0][vector][0];
mv.top.y = mb->PMV[0][vector][1];
mv.top.field_select = (mb->motion_vertical_field_select & field_select_mask) ?
PIPE_VIDEO_BOTTOM_FIELD : PIPE_VIDEO_TOP_FIELD;
mv.top.weight = weight;
 
mv.bottom.x = mb->PMV[1][vector][0];
mv.bottom.y = mb->PMV[1][vector][1];
mv.bottom.field_select = (mb->motion_vertical_field_select & (field_select_mask << 2)) ?
PIPE_VIDEO_BOTTOM_FIELD : PIPE_VIDEO_TOP_FIELD;
mv.bottom.weight = weight;
break;
 
default: // TODO: Support DUALPRIME and 16x8
break;
}
} else {
mv.top.x = mv.top.y = 0;
mv.top.field_select = PIPE_VIDEO_FRAME;
mv.top.weight = weight;
 
mv.bottom.x = mv.bottom.y = 0;
mv.bottom.field_select = PIPE_VIDEO_FRAME;
mv.bottom.weight = weight;
}
return mv;
}
 
static INLINE void
UploadYcbcrBlocks(struct vl_mpeg12_decoder *dec,
struct vl_mpeg12_buffer *buf,
const struct pipe_mpeg12_macroblock *mb)
{
unsigned intra;
unsigned tb, x, y, num_blocks = 0;
 
assert(dec && buf);
assert(mb);
 
if (!mb->coded_block_pattern)
return;
 
intra = mb->macroblock_type & PIPE_MPEG12_MB_TYPE_INTRA ? 1 : 0;
 
for (y = 0; y < 2; ++y) {
for (x = 0; x < 2; ++x) {
if (mb->coded_block_pattern & const_empty_block_mask_420[0][y][x]) {
 
struct vl_ycbcr_block *stream = buf->ycbcr_stream[0];
stream->x = mb->x * 2 + x;
stream->y = mb->y * 2 + y;
stream->intra = intra;
stream->coding = mb->macroblock_modes.bits.dct_type;
stream->block_num = buf->block_num++;
 
buf->num_ycbcr_blocks[0]++;
buf->ycbcr_stream[0]++;
 
num_blocks++;
}
}
}
 
/* TODO: Implement 422, 444 */
//assert(ctx->base.chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420);
 
for (tb = 1; tb < 3; ++tb) {
if (mb->coded_block_pattern & const_empty_block_mask_420[tb][0][0]) {
 
struct vl_ycbcr_block *stream = buf->ycbcr_stream[tb];
stream->x = mb->x;
stream->y = mb->y;
stream->intra = intra;
stream->coding = 0;
stream->block_num = buf->block_num++;
 
buf->num_ycbcr_blocks[tb]++;
buf->ycbcr_stream[tb]++;
 
num_blocks++;
}
}
 
memcpy(buf->texels, mb->blocks, 64 * sizeof(short) * num_blocks);
buf->texels += 64 * num_blocks;
}
 
static void
vl_mpeg12_destroy_buffer(void *buffer)
{
struct vl_mpeg12_buffer *buf = buffer;
 
assert(buf);
 
cleanup_zscan_buffer(buf);
cleanup_idct_buffer(buf);
cleanup_mc_buffer(buf);
vl_vb_cleanup(&buf->vertex_stream);
 
FREE(buf);
}
 
static void
vl_mpeg12_destroy(struct pipe_video_decoder *decoder)
{
struct vl_mpeg12_decoder *dec = (struct vl_mpeg12_decoder*)decoder;
unsigned i;
 
assert(decoder);
 
/* Asserted in softpipe_delete_fs_state() for some reason */
dec->base.context->bind_vs_state(dec->base.context, NULL);
dec->base.context->bind_fs_state(dec->base.context, NULL);
 
dec->base.context->delete_depth_stencil_alpha_state(dec->base.context, dec->dsa);
dec->base.context->delete_sampler_state(dec->base.context, dec->sampler_ycbcr);
 
vl_mc_cleanup(&dec->mc_y);
vl_mc_cleanup(&dec->mc_c);
dec->mc_source->destroy(dec->mc_source);
 
if (dec->base.entrypoint <= PIPE_VIDEO_ENTRYPOINT_IDCT) {
vl_idct_cleanup(&dec->idct_y);
vl_idct_cleanup(&dec->idct_c);
dec->idct_source->destroy(dec->idct_source);
}
 
vl_zscan_cleanup(&dec->zscan_y);
vl_zscan_cleanup(&dec->zscan_c);
 
dec->base.context->delete_vertex_elements_state(dec->base.context, dec->ves_ycbcr);
dec->base.context->delete_vertex_elements_state(dec->base.context, dec->ves_mv);
 
pipe_resource_reference(&dec->quads.buffer, NULL);
pipe_resource_reference(&dec->pos.buffer, NULL);
 
pipe_sampler_view_reference(&dec->zscan_linear, NULL);
pipe_sampler_view_reference(&dec->zscan_normal, NULL);
pipe_sampler_view_reference(&dec->zscan_alternate, NULL);
 
for (i = 0; i < 4; ++i)
if (dec->dec_buffers[i])
vl_mpeg12_destroy_buffer(dec->dec_buffers[i]);
 
FREE(dec);
}
 
static struct vl_mpeg12_buffer *
vl_mpeg12_get_decode_buffer(struct vl_mpeg12_decoder *dec, struct pipe_video_buffer *target)
{
struct vl_mpeg12_buffer *buffer;
 
assert(dec);
 
buffer = vl_video_buffer_get_associated_data(target, &dec->base);
if (buffer)
return buffer;
 
buffer = dec->dec_buffers[dec->current_buffer];
if (buffer)
return buffer;
 
buffer = CALLOC_STRUCT(vl_mpeg12_buffer);
if (buffer == NULL)
return NULL;
 
if (!vl_vb_init(&buffer->vertex_stream, dec->base.context,
dec->base.width / VL_MACROBLOCK_WIDTH,
dec->base.height / VL_MACROBLOCK_HEIGHT))
goto error_vertex_buffer;
 
if (!init_mc_buffer(dec, buffer))
goto error_mc;
 
if (dec->base.entrypoint <= PIPE_VIDEO_ENTRYPOINT_IDCT)
if (!init_idct_buffer(dec, buffer))
goto error_idct;
 
if (!init_zscan_buffer(dec, buffer))
goto error_zscan;
 
if (dec->base.entrypoint == PIPE_VIDEO_ENTRYPOINT_BITSTREAM)
vl_mpg12_bs_init(&buffer->bs, &dec->base);
 
if (dec->expect_chunked_decode)
vl_video_buffer_set_associated_data(target, &dec->base,
buffer, vl_mpeg12_destroy_buffer);
else
dec->dec_buffers[dec->current_buffer] = buffer;
 
return buffer;
 
error_zscan:
cleanup_idct_buffer(buffer);
 
error_idct:
cleanup_mc_buffer(buffer);
 
error_mc:
vl_vb_cleanup(&buffer->vertex_stream);
 
error_vertex_buffer:
FREE(buffer);
return NULL;
}
 
static void
vl_mpeg12_begin_frame(struct pipe_video_decoder *decoder,
struct pipe_video_buffer *target,
struct pipe_picture_desc *picture)
{
struct vl_mpeg12_decoder *dec = (struct vl_mpeg12_decoder *)decoder;
struct pipe_mpeg12_picture_desc *desc = (struct pipe_mpeg12_picture_desc *)picture;
struct vl_mpeg12_buffer *buf;
 
struct pipe_resource *tex;
struct pipe_box rect = { 0, 0, 0, 1, 1, 1 };
 
uint8_t intra_matrix[64];
uint8_t non_intra_matrix[64];
 
unsigned i;
 
assert(dec && target && picture);
 
buf = vl_mpeg12_get_decode_buffer(dec, target);
assert(buf);
 
if (dec->base.entrypoint == PIPE_VIDEO_ENTRYPOINT_BITSTREAM) {
memcpy(intra_matrix, desc->intra_matrix, sizeof(intra_matrix));
memcpy(non_intra_matrix, desc->non_intra_matrix, sizeof(non_intra_matrix));
intra_matrix[0] = 1 << (7 - desc->intra_dc_precision);
} else {
memset(intra_matrix, 0x10, sizeof(intra_matrix));
memset(non_intra_matrix, 0x10, sizeof(non_intra_matrix));
}
 
for (i = 0; i < VL_NUM_COMPONENTS; ++i) {
struct vl_zscan *zscan = i == 0 ? &dec->zscan_y : &dec->zscan_c;
vl_zscan_upload_quant(zscan, &buf->zscan[i], intra_matrix, true);
vl_zscan_upload_quant(zscan, &buf->zscan[i], non_intra_matrix, false);
}
 
vl_vb_map(&buf->vertex_stream, dec->base.context);
 
tex = buf->zscan_source->texture;
rect.width = tex->width0;
rect.height = tex->height0;
 
buf->texels =
dec->base.context->transfer_map(dec->base.context, tex, 0,
PIPE_TRANSFER_WRITE |
PIPE_TRANSFER_DISCARD_RANGE,
&rect, &buf->tex_transfer);
 
buf->block_num = 0;
 
for (i = 0; i < VL_NUM_COMPONENTS; ++i) {
buf->ycbcr_stream[i] = vl_vb_get_ycbcr_stream(&buf->vertex_stream, i);
buf->num_ycbcr_blocks[i] = 0;
}
 
for (i = 0; i < VL_MAX_REF_FRAMES; ++i)
buf->mv_stream[i] = vl_vb_get_mv_stream(&buf->vertex_stream, i);
 
if (dec->base.entrypoint >= PIPE_VIDEO_ENTRYPOINT_IDCT) {
for (i = 0; i < VL_NUM_COMPONENTS; ++i)
vl_zscan_set_layout(&buf->zscan[i], dec->zscan_linear);
}
}
 
static void
vl_mpeg12_decode_macroblock(struct pipe_video_decoder *decoder,
struct pipe_video_buffer *target,
struct pipe_picture_desc *picture,
const struct pipe_macroblock *macroblocks,
unsigned num_macroblocks)
{
struct vl_mpeg12_decoder *dec = (struct vl_mpeg12_decoder *)decoder;
const struct pipe_mpeg12_macroblock *mb = (const struct pipe_mpeg12_macroblock *)macroblocks;
struct pipe_mpeg12_picture_desc *desc = (struct pipe_mpeg12_picture_desc *)picture;
struct vl_mpeg12_buffer *buf;
 
unsigned i, j, mv_weights[2];
 
assert(dec && target && picture);
assert(macroblocks && macroblocks->codec == PIPE_VIDEO_CODEC_MPEG12);
 
buf = vl_mpeg12_get_decode_buffer(dec, target);
assert(buf);
 
for (; num_macroblocks > 0; --num_macroblocks) {
unsigned mb_addr = mb->y * dec->width_in_macroblocks + mb->x;
 
if (mb->macroblock_type & (PIPE_MPEG12_MB_TYPE_PATTERN | PIPE_MPEG12_MB_TYPE_INTRA))
UploadYcbcrBlocks(dec, buf, mb);
 
MacroBlockTypeToPipeWeights(mb, mv_weights);
 
for (i = 0; i < 2; ++i) {
if (!desc->ref[i]) continue;
 
buf->mv_stream[i][mb_addr] = MotionVectorToPipe
(
mb, i,
i ? PIPE_MPEG12_FS_FIRST_BACKWARD : PIPE_MPEG12_FS_FIRST_FORWARD,
mv_weights[i]
);
}
 
/* see section 7.6.6 of the spec */
if (mb->num_skipped_macroblocks > 0) {
struct vl_motionvector skipped_mv[2];
 
if (desc->ref[0] && !desc->ref[1]) {
skipped_mv[0].top.x = skipped_mv[0].top.y = 0;
skipped_mv[0].top.weight = PIPE_VIDEO_MV_WEIGHT_MAX;
} else {
skipped_mv[0] = buf->mv_stream[0][mb_addr];
skipped_mv[1] = buf->mv_stream[1][mb_addr];
}
skipped_mv[0].top.field_select = PIPE_VIDEO_FRAME;
skipped_mv[1].top.field_select = PIPE_VIDEO_FRAME;
 
skipped_mv[0].bottom = skipped_mv[0].top;
skipped_mv[1].bottom = skipped_mv[1].top;
 
++mb_addr;
for (i = 0; i < mb->num_skipped_macroblocks; ++i, ++mb_addr) {
for (j = 0; j < 2; ++j) {
if (!desc->ref[j]) continue;
buf->mv_stream[j][mb_addr] = skipped_mv[j];
 
}
}
}
 
++mb;
}
}
 
static void
vl_mpeg12_decode_bitstream(struct pipe_video_decoder *decoder,
struct pipe_video_buffer *target,
struct pipe_picture_desc *picture,
unsigned num_buffers,
const void * const *buffers,
const unsigned *sizes)
{
struct vl_mpeg12_decoder *dec = (struct vl_mpeg12_decoder *)decoder;
struct pipe_mpeg12_picture_desc *desc = (struct pipe_mpeg12_picture_desc *)picture;
struct vl_mpeg12_buffer *buf;
unsigned i;
 
assert(dec && target && picture);
 
buf = vl_mpeg12_get_decode_buffer(dec, target);
assert(buf);
 
for (i = 0; i < VL_NUM_COMPONENTS; ++i)
vl_zscan_set_layout(&buf->zscan[i], desc->alternate_scan ?
dec->zscan_alternate : dec->zscan_normal);
 
vl_mpg12_bs_decode(&buf->bs, target, desc, num_buffers, buffers, sizes);
}
 
static void
vl_mpeg12_end_frame(struct pipe_video_decoder *decoder,
struct pipe_video_buffer *target,
struct pipe_picture_desc *picture)
{
struct vl_mpeg12_decoder *dec = (struct vl_mpeg12_decoder *)decoder;
struct pipe_mpeg12_picture_desc *desc = (struct pipe_mpeg12_picture_desc *)picture;
struct pipe_sampler_view **ref_frames[2];
struct pipe_sampler_view **mc_source_sv;
struct pipe_surface **target_surfaces;
struct pipe_vertex_buffer vb[3];
struct vl_mpeg12_buffer *buf;
 
const unsigned *plane_order;
unsigned i, j, component;
unsigned nr_components;
 
assert(dec && target && picture);
assert(!target->interlaced);
 
buf = vl_mpeg12_get_decode_buffer(dec, target);
 
vl_vb_unmap(&buf->vertex_stream, dec->base.context);
 
dec->base.context->transfer_unmap(dec->base.context, buf->tex_transfer);
 
vb[0] = dec->quads;
vb[1] = dec->pos;
 
target_surfaces = target->get_surfaces(target);
 
for (i = 0; i < VL_MAX_REF_FRAMES; ++i) {
if (desc->ref[i])
ref_frames[i] = desc->ref[i]->get_sampler_view_planes(desc->ref[i]);
else
ref_frames[i] = NULL;
}
 
dec->base.context->bind_vertex_elements_state(dec->base.context, dec->ves_mv);
for (i = 0; i < VL_NUM_COMPONENTS; ++i) {
if (!target_surfaces[i]) continue;
 
vl_mc_set_surface(&buf->mc[i], target_surfaces[i]);
 
for (j = 0; j < VL_MAX_REF_FRAMES; ++j) {
if (!ref_frames[j] || !ref_frames[j][i]) continue;
 
vb[2] = vl_vb_get_mv(&buf->vertex_stream, j);;
dec->base.context->set_vertex_buffers(dec->base.context, 0, 3, vb);
 
vl_mc_render_ref(i ? &dec->mc_c : &dec->mc_y, &buf->mc[i], ref_frames[j][i]);
}
}
 
dec->base.context->bind_vertex_elements_state(dec->base.context, dec->ves_ycbcr);
for (i = 0; i < VL_NUM_COMPONENTS; ++i) {
if (!buf->num_ycbcr_blocks[i]) continue;
 
vb[1] = vl_vb_get_ycbcr(&buf->vertex_stream, i);
dec->base.context->set_vertex_buffers(dec->base.context, 0, 2, vb);
 
vl_zscan_render(i ? &dec->zscan_c : & dec->zscan_y, &buf->zscan[i] , buf->num_ycbcr_blocks[i]);
 
if (dec->base.entrypoint <= PIPE_VIDEO_ENTRYPOINT_IDCT)
vl_idct_flush(i ? &dec->idct_c : &dec->idct_y, &buf->idct[i], buf->num_ycbcr_blocks[i]);
}
 
plane_order = vl_video_buffer_plane_order(target->buffer_format);
mc_source_sv = dec->mc_source->get_sampler_view_planes(dec->mc_source);
for (i = 0, component = 0; component < VL_NUM_COMPONENTS; ++i) {
if (!target_surfaces[i]) continue;
 
nr_components = util_format_get_nr_components(target_surfaces[i]->texture->format);
for (j = 0; j < nr_components; ++j, ++component) {
unsigned plane = plane_order[component];
if (!buf->num_ycbcr_blocks[plane]) continue;
 
vb[1] = vl_vb_get_ycbcr(&buf->vertex_stream, plane);
dec->base.context->set_vertex_buffers(dec->base.context, 0, 2, vb);
 
if (dec->base.entrypoint <= PIPE_VIDEO_ENTRYPOINT_IDCT)
vl_idct_prepare_stage2(i ? &dec->idct_c : &dec->idct_y, &buf->idct[plane]);
else {
dec->base.context->set_fragment_sampler_views(dec->base.context, 1, &mc_source_sv[plane]);
dec->base.context->bind_fragment_sampler_states(dec->base.context, 1, &dec->sampler_ycbcr);
}
vl_mc_render_ycbcr(i ? &dec->mc_c : &dec->mc_y, &buf->mc[i], j, buf->num_ycbcr_blocks[plane]);
}
}
++dec->current_buffer;
dec->current_buffer %= 4;
}
 
static void
vl_mpeg12_flush(struct pipe_video_decoder *decoder)
{
assert(decoder);
 
//Noop, for shaders it is much faster to flush everything in end_frame
}
 
static bool
init_pipe_state(struct vl_mpeg12_decoder *dec)
{
struct pipe_depth_stencil_alpha_state dsa;
struct pipe_sampler_state sampler;
unsigned i;
 
assert(dec);
 
memset(&dsa, 0, sizeof dsa);
dsa.depth.enabled = 0;
dsa.depth.writemask = 0;
dsa.depth.func = PIPE_FUNC_ALWAYS;
for (i = 0; i < 2; ++i) {
dsa.stencil[i].enabled = 0;
dsa.stencil[i].func = PIPE_FUNC_ALWAYS;
dsa.stencil[i].fail_op = PIPE_STENCIL_OP_KEEP;
dsa.stencil[i].zpass_op = PIPE_STENCIL_OP_KEEP;
dsa.stencil[i].zfail_op = PIPE_STENCIL_OP_KEEP;
dsa.stencil[i].valuemask = 0;
dsa.stencil[i].writemask = 0;
}
dsa.alpha.enabled = 0;
dsa.alpha.func = PIPE_FUNC_ALWAYS;
dsa.alpha.ref_value = 0;
dec->dsa = dec->base.context->create_depth_stencil_alpha_state(dec->base.context, &dsa);
dec->base.context->bind_depth_stencil_alpha_state(dec->base.context, dec->dsa);
 
memset(&sampler, 0, sizeof(sampler));
sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_BORDER;
sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
sampler.compare_mode = PIPE_TEX_COMPARE_NONE;
sampler.compare_func = PIPE_FUNC_ALWAYS;
sampler.normalized_coords = 1;
dec->sampler_ycbcr = dec->base.context->create_sampler_state(dec->base.context, &sampler);
if (!dec->sampler_ycbcr)
return false;
 
return true;
}
 
static const struct format_config*
find_format_config(struct vl_mpeg12_decoder *dec, const struct format_config configs[], unsigned num_configs)
{
struct pipe_screen *screen;
unsigned i;
 
assert(dec);
 
screen = dec->base.context->screen;
 
for (i = 0; i < num_configs; ++i) {
if (!screen->is_format_supported(screen, configs[i].zscan_source_format, PIPE_TEXTURE_2D,
1, PIPE_BIND_SAMPLER_VIEW))
continue;
 
if (configs[i].idct_source_format != PIPE_FORMAT_NONE) {
if (!screen->is_format_supported(screen, configs[i].idct_source_format, PIPE_TEXTURE_2D,
1, PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET))
continue;
 
if (!screen->is_format_supported(screen, configs[i].mc_source_format, PIPE_TEXTURE_3D,
1, PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET))
continue;
} else {
if (!screen->is_format_supported(screen, configs[i].mc_source_format, PIPE_TEXTURE_2D,
1, PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET))
continue;
}
return &configs[i];
}
 
return NULL;
}
 
static bool
init_zscan(struct vl_mpeg12_decoder *dec, const struct format_config* format_config)
{
unsigned num_channels;
 
assert(dec);
 
dec->zscan_source_format = format_config->zscan_source_format;
dec->zscan_linear = vl_zscan_layout(dec->base.context, vl_zscan_linear, dec->blocks_per_line);
dec->zscan_normal = vl_zscan_layout(dec->base.context, vl_zscan_normal, dec->blocks_per_line);
dec->zscan_alternate = vl_zscan_layout(dec->base.context, vl_zscan_alternate, dec->blocks_per_line);
 
num_channels = dec->base.entrypoint <= PIPE_VIDEO_ENTRYPOINT_IDCT ? 4 : 1;
 
if (!vl_zscan_init(&dec->zscan_y, dec->base.context, dec->base.width, dec->base.height,
dec->blocks_per_line, dec->num_blocks, num_channels))
return false;
 
if (!vl_zscan_init(&dec->zscan_c, dec->base.context, dec->chroma_width, dec->chroma_height,
dec->blocks_per_line, dec->num_blocks, num_channels))
return false;
 
return true;
}
 
static bool
init_idct(struct vl_mpeg12_decoder *dec, const struct format_config* format_config)
{
unsigned nr_of_idct_render_targets, max_inst;
enum pipe_format formats[3];
struct pipe_video_buffer templat;
 
struct pipe_sampler_view *matrix = NULL;
 
nr_of_idct_render_targets = dec->base.context->screen->get_param
(
dec->base.context->screen, PIPE_CAP_MAX_RENDER_TARGETS
);
max_inst = dec->base.context->screen->get_shader_param
(
dec->base.context->screen, PIPE_SHADER_FRAGMENT, PIPE_SHADER_CAP_MAX_INSTRUCTIONS
);
 
// Just assume we need 32 inst per render target, not 100% true, but should work in most cases
if (nr_of_idct_render_targets >= 4 && max_inst >= 32*4)
// more than 4 render targets usually doesn't makes any seens
nr_of_idct_render_targets = 4;
else
nr_of_idct_render_targets = 1;
 
formats[0] = formats[1] = formats[2] = format_config->idct_source_format;
memset(&templat, 0, sizeof(templat));
templat.width = dec->base.width / 4;
templat.height = dec->base.height;
templat.chroma_format = dec->base.chroma_format;
dec->idct_source = vl_video_buffer_create_ex
(
dec->base.context, &templat,
formats, 1, 1, PIPE_USAGE_STATIC
);
 
if (!dec->idct_source)
goto error_idct_source;
 
formats[0] = formats[1] = formats[2] = format_config->mc_source_format;
memset(&templat, 0, sizeof(templat));
templat.width = dec->base.width / nr_of_idct_render_targets;
templat.height = dec->base.height / 4;
templat.chroma_format = dec->base.chroma_format;
dec->mc_source = vl_video_buffer_create_ex
(
dec->base.context, &templat,
formats, nr_of_idct_render_targets, 1, PIPE_USAGE_STATIC
);
 
if (!dec->mc_source)
goto error_mc_source;
 
if (!(matrix = vl_idct_upload_matrix(dec->base.context, format_config->idct_scale)))
goto error_matrix;
 
if (!vl_idct_init(&dec->idct_y, dec->base.context, dec->base.width, dec->base.height,
nr_of_idct_render_targets, matrix, matrix))
goto error_y;
 
if(!vl_idct_init(&dec->idct_c, dec->base.context, dec->chroma_width, dec->chroma_height,
nr_of_idct_render_targets, matrix, matrix))
goto error_c;
 
pipe_sampler_view_reference(&matrix, NULL);
 
return true;
 
error_c:
vl_idct_cleanup(&dec->idct_y);
 
error_y:
pipe_sampler_view_reference(&matrix, NULL);
 
error_matrix:
dec->mc_source->destroy(dec->mc_source);
 
error_mc_source:
dec->idct_source->destroy(dec->idct_source);
 
error_idct_source:
return false;
}
 
static bool
init_mc_source_widthout_idct(struct vl_mpeg12_decoder *dec, const struct format_config* format_config)
{
enum pipe_format formats[3];
struct pipe_video_buffer templat;
 
formats[0] = formats[1] = formats[2] = format_config->mc_source_format;
memset(&templat, 0, sizeof(templat));
templat.width = dec->base.width;
templat.height = dec->base.height;
templat.chroma_format = dec->base.chroma_format;
dec->mc_source = vl_video_buffer_create_ex
(
dec->base.context, &templat,
formats, 1, 1, PIPE_USAGE_STATIC
);
return dec->mc_source != NULL;
}
 
static void
mc_vert_shader_callback(void *priv, struct vl_mc *mc,
struct ureg_program *shader,
unsigned first_output,
struct ureg_dst tex)
{
struct vl_mpeg12_decoder *dec = priv;
struct ureg_dst o_vtex;
 
assert(priv && mc);
assert(shader);
 
if (dec->base.entrypoint <= PIPE_VIDEO_ENTRYPOINT_IDCT) {
struct vl_idct *idct = mc == &dec->mc_y ? &dec->idct_y : &dec->idct_c;
vl_idct_stage2_vert_shader(idct, shader, first_output, tex);
} else {
o_vtex = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, first_output);
ureg_MOV(shader, ureg_writemask(o_vtex, TGSI_WRITEMASK_XY), ureg_src(tex));
}
}
 
static void
mc_frag_shader_callback(void *priv, struct vl_mc *mc,
struct ureg_program *shader,
unsigned first_input,
struct ureg_dst dst)
{
struct vl_mpeg12_decoder *dec = priv;
struct ureg_src src, sampler;
 
assert(priv && mc);
assert(shader);
 
if (dec->base.entrypoint <= PIPE_VIDEO_ENTRYPOINT_IDCT) {
struct vl_idct *idct = mc == &dec->mc_y ? &dec->idct_y : &dec->idct_c;
vl_idct_stage2_frag_shader(idct, shader, first_input, dst);
} else {
src = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, first_input, TGSI_INTERPOLATE_LINEAR);
sampler = ureg_DECL_sampler(shader, 0);
ureg_TEX(shader, dst, TGSI_TEXTURE_2D, src, sampler);
}
}
 
struct pipe_video_decoder *
vl_create_mpeg12_decoder(struct pipe_context *context,
enum pipe_video_profile profile,
enum pipe_video_entrypoint entrypoint,
enum pipe_video_chroma_format chroma_format,
unsigned width, unsigned height, unsigned max_references,
bool expect_chunked_decode)
{
const unsigned block_size_pixels = VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT;
const struct format_config *format_config;
struct vl_mpeg12_decoder *dec;
 
assert(u_reduce_video_profile(profile) == PIPE_VIDEO_CODEC_MPEG12);
 
dec = CALLOC_STRUCT(vl_mpeg12_decoder);
 
if (!dec)
return NULL;
 
dec->base.context = context;
dec->base.profile = profile;
dec->base.entrypoint = entrypoint;
dec->base.chroma_format = chroma_format;
dec->base.width = width;
dec->base.height = height;
dec->base.max_references = max_references;
 
dec->base.destroy = vl_mpeg12_destroy;
dec->base.begin_frame = vl_mpeg12_begin_frame;
dec->base.decode_macroblock = vl_mpeg12_decode_macroblock;
dec->base.decode_bitstream = vl_mpeg12_decode_bitstream;
dec->base.end_frame = vl_mpeg12_end_frame;
dec->base.flush = vl_mpeg12_flush;
 
dec->blocks_per_line = MAX2(util_next_power_of_two(dec->base.width) / block_size_pixels, 4);
dec->num_blocks = (dec->base.width * dec->base.height) / block_size_pixels;
dec->width_in_macroblocks = align(dec->base.width, VL_MACROBLOCK_WIDTH) / VL_MACROBLOCK_WIDTH;
dec->expect_chunked_decode = expect_chunked_decode;
 
/* TODO: Implement 422, 444 */
assert(dec->base.chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420);
 
if (dec->base.chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420) {
dec->chroma_width = dec->base.width / 2;
dec->chroma_height = dec->base.height / 2;
dec->num_blocks = dec->num_blocks * 2;
} else if (dec->base.chroma_format == PIPE_VIDEO_CHROMA_FORMAT_422) {
dec->chroma_width = dec->base.width;
dec->chroma_height = dec->base.height / 2;
dec->num_blocks = dec->num_blocks * 2 + dec->num_blocks;
} else {
dec->chroma_width = dec->base.width;
dec->chroma_height = dec->base.height;
dec->num_blocks = dec->num_blocks * 3;
}
 
dec->quads = vl_vb_upload_quads(dec->base.context);
dec->pos = vl_vb_upload_pos(
dec->base.context,
dec->base.width / VL_MACROBLOCK_WIDTH,
dec->base.height / VL_MACROBLOCK_HEIGHT
);
 
dec->ves_ycbcr = vl_vb_get_ves_ycbcr(dec->base.context);
dec->ves_mv = vl_vb_get_ves_mv(dec->base.context);
 
switch (entrypoint) {
case PIPE_VIDEO_ENTRYPOINT_BITSTREAM:
format_config = find_format_config(dec, bitstream_format_config, num_bitstream_format_configs);
break;
 
case PIPE_VIDEO_ENTRYPOINT_IDCT:
format_config = find_format_config(dec, idct_format_config, num_idct_format_configs);
break;
 
case PIPE_VIDEO_ENTRYPOINT_MC:
format_config = find_format_config(dec, mc_format_config, num_mc_format_configs);
break;
 
default:
assert(0);
FREE(dec);
return NULL;
}
 
if (!format_config) {
FREE(dec);
return NULL;
}
 
if (!init_zscan(dec, format_config))
goto error_zscan;
 
if (entrypoint <= PIPE_VIDEO_ENTRYPOINT_IDCT) {
if (!init_idct(dec, format_config))
goto error_sources;
} else {
if (!init_mc_source_widthout_idct(dec, format_config))
goto error_sources;
}
 
if (!vl_mc_init(&dec->mc_y, dec->base.context, dec->base.width, dec->base.height,
VL_MACROBLOCK_HEIGHT, format_config->mc_scale,
mc_vert_shader_callback, mc_frag_shader_callback, dec))
goto error_mc_y;
 
// TODO
if (!vl_mc_init(&dec->mc_c, dec->base.context, dec->base.width, dec->base.height,
VL_BLOCK_HEIGHT, format_config->mc_scale,
mc_vert_shader_callback, mc_frag_shader_callback, dec))
goto error_mc_c;
 
if (!init_pipe_state(dec))
goto error_pipe_state;
 
return &dec->base;
 
error_pipe_state:
vl_mc_cleanup(&dec->mc_c);
 
error_mc_c:
vl_mc_cleanup(&dec->mc_y);
 
error_mc_y:
if (entrypoint <= PIPE_VIDEO_ENTRYPOINT_IDCT) {
vl_idct_cleanup(&dec->idct_y);
vl_idct_cleanup(&dec->idct_c);
dec->idct_source->destroy(dec->idct_source);
}
dec->mc_source->destroy(dec->mc_source);
 
error_sources:
vl_zscan_cleanup(&dec->zscan_y);
vl_zscan_cleanup(&dec->zscan_c);
 
error_zscan:
FREE(dec);
return NULL;
}
/drivers/video/Gallium/auxiliary/vl/vl_mpeg12_decoder.h
0,0 → 1,114
/**************************************************************************
*
* Copyright 2009 Younes Manton.
* 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.
*
**************************************************************************/
 
#ifndef vl_mpeg12_decoder_h
#define vl_mpeg12_decoder_h
 
#include "pipe/p_video_decoder.h"
 
#include "vl_mpeg12_bitstream.h"
#include "vl_zscan.h"
#include "vl_idct.h"
#include "vl_mc.h"
 
#include "vl_vertex_buffers.h"
#include "vl_video_buffer.h"
 
struct pipe_screen;
struct pipe_context;
 
struct vl_mpeg12_decoder
{
struct pipe_video_decoder base;
 
unsigned chroma_width, chroma_height;
 
unsigned blocks_per_line;
unsigned num_blocks;
unsigned width_in_macroblocks;
bool expect_chunked_decode;
 
enum pipe_format zscan_source_format;
 
struct pipe_vertex_buffer quads;
struct pipe_vertex_buffer pos;
 
void *ves_ycbcr;
void *ves_mv;
 
void *sampler_ycbcr;
 
struct pipe_sampler_view *zscan_linear;
struct pipe_sampler_view *zscan_normal;
struct pipe_sampler_view *zscan_alternate;
 
struct pipe_video_buffer *idct_source;
struct pipe_video_buffer *mc_source;
 
struct vl_zscan zscan_y, zscan_c;
struct vl_idct idct_y, idct_c;
struct vl_mc mc_y, mc_c;
 
void *dsa;
 
unsigned current_buffer;
struct vl_mpeg12_buffer *dec_buffers[4];
};
 
struct vl_mpeg12_buffer
{
struct vl_vertex_buffer vertex_stream;
 
unsigned block_num;
unsigned num_ycbcr_blocks[3];
 
struct pipe_sampler_view *zscan_source;
 
struct vl_mpg12_bs bs;
struct vl_zscan_buffer zscan[VL_NUM_COMPONENTS];
struct vl_idct_buffer idct[VL_NUM_COMPONENTS];
struct vl_mc_buffer mc[VL_NUM_COMPONENTS];
 
struct pipe_transfer *tex_transfer;
short *texels;
 
struct vl_ycbcr_block *ycbcr_stream[VL_NUM_COMPONENTS];
struct vl_motionvector *mv_stream[VL_MAX_REF_FRAMES];
};
 
/**
* creates a shader based mpeg12 decoder
*/
struct pipe_video_decoder *
vl_create_mpeg12_decoder(struct pipe_context *pipe,
enum pipe_video_profile profile,
enum pipe_video_entrypoint entrypoint,
enum pipe_video_chroma_format chroma_format,
unsigned width, unsigned height, unsigned max_references,
bool expect_chunked_decode);
 
#endif /* vl_mpeg12_decoder_h */
/drivers/video/Gallium/auxiliary/vl/vl_types.h
0,0 → 1,51
/**************************************************************************
*
* Copyright 2009 Younes Manton.
* 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.
*
**************************************************************************/
 
#ifndef vl_types_h
#define vl_types_h
 
struct vertex2f
{
float x, y;
};
 
struct vertex2s
{
short x, y;
};
 
struct vertex4f
{
float x, y, z, w;
};
 
struct vertex4s
{
short x, y, z, w;
};
 
#endif /* vl_types_h */
/drivers/video/Gallium/auxiliary/vl/vl_vertex_buffers.c
0,0 → 1,378
/**************************************************************************
*
* Copyright 2010 Christian König
* 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.
*
**************************************************************************/
 
#include <assert.h>
#include "util/u_format.h"
#include "vl_vertex_buffers.h"
#include "vl_types.h"
 
/* vertices for a quad covering a block */
static const struct vertex2f block_quad[4] = {
{0.0f, 0.0f}, {1.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 1.0f}
};
 
struct pipe_vertex_buffer
vl_vb_upload_quads(struct pipe_context *pipe)
{
struct pipe_vertex_buffer quad;
struct pipe_transfer *buf_transfer;
struct vertex2f *v;
 
unsigned i;
 
assert(pipe);
 
/* create buffer */
quad.stride = sizeof(struct vertex2f);
quad.buffer_offset = 0;
quad.buffer = pipe_buffer_create
(
pipe->screen,
PIPE_BIND_VERTEX_BUFFER,
PIPE_USAGE_STATIC,
sizeof(struct vertex2f) * 4
);
quad.user_buffer = NULL;
 
if(!quad.buffer)
return quad;
 
/* and fill it */
v = pipe_buffer_map
(
pipe,
quad.buffer,
PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE,
&buf_transfer
);
 
for (i = 0; i < 4; ++i, ++v) {
v->x = block_quad[i].x;
v->y = block_quad[i].y;
}
 
pipe_buffer_unmap(pipe, buf_transfer);
 
return quad;
}
 
struct pipe_vertex_buffer
vl_vb_upload_pos(struct pipe_context *pipe, unsigned width, unsigned height)
{
struct pipe_vertex_buffer pos;
struct pipe_transfer *buf_transfer;
struct vertex2s *v;
 
unsigned x, y;
 
assert(pipe);
 
/* create buffer */
pos.stride = sizeof(struct vertex2s);
pos.buffer_offset = 0;
pos.buffer = pipe_buffer_create
(
pipe->screen,
PIPE_BIND_VERTEX_BUFFER,
PIPE_USAGE_STATIC,
sizeof(struct vertex2s) * width * height
);
pos.user_buffer = NULL;
 
if(!pos.buffer)
return pos;
 
/* and fill it */
v = pipe_buffer_map
(
pipe,
pos.buffer,
PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE,
&buf_transfer
);
 
for ( y = 0; y < height; ++y) {
for ( x = 0; x < width; ++x, ++v) {
v->x = x;
v->y = y;
}
}
 
pipe_buffer_unmap(pipe, buf_transfer);
 
return pos;
}
 
static struct pipe_vertex_element
vl_vb_get_quad_vertex_element(void)
{
struct pipe_vertex_element element;
 
/* setup rectangle element */
element.src_offset = 0;
element.instance_divisor = 0;
element.vertex_buffer_index = 0;
element.src_format = PIPE_FORMAT_R32G32_FLOAT;
 
return element;
}
 
static void
vl_vb_element_helper(struct pipe_vertex_element* elements, unsigned num_elements,
unsigned vertex_buffer_index)
{
unsigned i, offset = 0;
 
assert(elements && num_elements);
 
for ( i = 0; i < num_elements; ++i ) {
elements[i].src_offset = offset;
elements[i].instance_divisor = 1;
elements[i].vertex_buffer_index = vertex_buffer_index;
offset += util_format_get_blocksize(elements[i].src_format);
}
}
 
void *
vl_vb_get_ves_ycbcr(struct pipe_context *pipe)
{
struct pipe_vertex_element vertex_elems[NUM_VS_INPUTS];
 
assert(pipe);
 
memset(&vertex_elems, 0, sizeof(vertex_elems));
vertex_elems[VS_I_RECT] = vl_vb_get_quad_vertex_element();
 
/* Position element */
vertex_elems[VS_I_VPOS].src_format = PIPE_FORMAT_R8G8B8A8_USCALED;
 
/* block num element */
vertex_elems[VS_I_BLOCK_NUM].src_format = PIPE_FORMAT_R32_FLOAT;
 
vl_vb_element_helper(&vertex_elems[VS_I_VPOS], 2, 1);
 
return pipe->create_vertex_elements_state(pipe, 3, vertex_elems);
}
 
void *
vl_vb_get_ves_mv(struct pipe_context *pipe)
{
struct pipe_vertex_element vertex_elems[NUM_VS_INPUTS];
 
assert(pipe);
 
memset(&vertex_elems, 0, sizeof(vertex_elems));
vertex_elems[VS_I_RECT] = vl_vb_get_quad_vertex_element();
 
/* Position element */
vertex_elems[VS_I_VPOS].src_format = PIPE_FORMAT_R16G16_SSCALED;
 
vl_vb_element_helper(&vertex_elems[VS_I_VPOS], 1, 1);
 
/* motion vector TOP element */
vertex_elems[VS_I_MV_TOP].src_format = PIPE_FORMAT_R16G16B16A16_SSCALED;
 
/* motion vector BOTTOM element */
vertex_elems[VS_I_MV_BOTTOM].src_format = PIPE_FORMAT_R16G16B16A16_SSCALED;
 
vl_vb_element_helper(&vertex_elems[VS_I_MV_TOP], 2, 2);
 
return pipe->create_vertex_elements_state(pipe, NUM_VS_INPUTS, vertex_elems);
}
 
bool
vl_vb_init(struct vl_vertex_buffer *buffer, struct pipe_context *pipe,
unsigned width, unsigned height)
{
unsigned i, size;
 
assert(buffer);
 
buffer->width = width;
buffer->height = height;
 
size = width * height;
 
for (i = 0; i < VL_NUM_COMPONENTS; ++i) {
buffer->ycbcr[i].resource = pipe_buffer_create
(
pipe->screen,
PIPE_BIND_VERTEX_BUFFER,
PIPE_USAGE_STREAM,
sizeof(struct vl_ycbcr_block) * size * 4
);
if (!buffer->ycbcr[i].resource)
goto error_ycbcr;
}
 
for (i = 0; i < VL_MAX_REF_FRAMES; ++i) {
buffer->mv[i].resource = pipe_buffer_create
(
pipe->screen,
PIPE_BIND_VERTEX_BUFFER,
PIPE_USAGE_STREAM,
sizeof(struct vl_motionvector) * size
);
if (!buffer->mv[i].resource)
goto error_mv;
}
 
vl_vb_map(buffer, pipe);
return true;
 
error_mv:
for (i = 0; i < VL_NUM_COMPONENTS; ++i)
pipe_resource_reference(&buffer->mv[i].resource, NULL);
 
error_ycbcr:
for (i = 0; i < VL_NUM_COMPONENTS; ++i)
pipe_resource_reference(&buffer->ycbcr[i].resource, NULL);
return false;
}
 
unsigned
vl_vb_attributes_per_plock(struct vl_vertex_buffer *buffer)
{
return 1;
}
 
struct pipe_vertex_buffer
vl_vb_get_ycbcr(struct vl_vertex_buffer *buffer, int component)
{
struct pipe_vertex_buffer buf;
 
assert(buffer);
 
buf.stride = sizeof(struct vl_ycbcr_block);
buf.buffer_offset = 0;
buf.buffer = buffer->ycbcr[component].resource;
buf.user_buffer = NULL;
 
return buf;
}
 
struct pipe_vertex_buffer
vl_vb_get_mv(struct vl_vertex_buffer *buffer, int motionvector)
{
struct pipe_vertex_buffer buf;
 
assert(buffer);
 
buf.stride = sizeof(struct vl_motionvector);
buf.buffer_offset = 0;
buf.buffer = buffer->mv[motionvector].resource;
buf.user_buffer = NULL;
 
return buf;
}
 
void
vl_vb_map(struct vl_vertex_buffer *buffer, struct pipe_context *pipe)
{
unsigned i;
 
assert(buffer && pipe);
 
for (i = 0; i < VL_NUM_COMPONENTS; ++i) {
buffer->ycbcr[i].vertex_stream = pipe_buffer_map
(
pipe,
buffer->ycbcr[i].resource,
PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE,
&buffer->ycbcr[i].transfer
);
}
 
for (i = 0; i < VL_MAX_REF_FRAMES; ++i) {
buffer->mv[i].vertex_stream = pipe_buffer_map
(
pipe,
buffer->mv[i].resource,
PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE,
&buffer->mv[i].transfer
);
}
 
}
 
struct vl_ycbcr_block *
vl_vb_get_ycbcr_stream(struct vl_vertex_buffer *buffer, int component)
{
assert(buffer);
assert(component < VL_NUM_COMPONENTS);
 
return buffer->ycbcr[component].vertex_stream;
}
 
unsigned
vl_vb_get_mv_stream_stride(struct vl_vertex_buffer *buffer)
{
assert(buffer);
 
return buffer->width;
}
 
struct vl_motionvector *
vl_vb_get_mv_stream(struct vl_vertex_buffer *buffer, int ref_frame)
{
assert(buffer);
assert(ref_frame < VL_MAX_REF_FRAMES);
 
return buffer->mv[ref_frame].vertex_stream;
}
 
void
vl_vb_unmap(struct vl_vertex_buffer *buffer, struct pipe_context *pipe)
{
unsigned i;
 
assert(buffer && pipe);
 
for (i = 0; i < VL_NUM_COMPONENTS; ++i) {
pipe_buffer_unmap(pipe, buffer->ycbcr[i].transfer);
}
 
for (i = 0; i < VL_MAX_REF_FRAMES; ++i) {
pipe_buffer_unmap(pipe, buffer->mv[i].transfer);
}
}
 
void
vl_vb_cleanup(struct vl_vertex_buffer *buffer)
{
unsigned i;
 
assert(buffer);
 
for (i = 0; i < VL_NUM_COMPONENTS; ++i) {
pipe_resource_reference(&buffer->ycbcr[i].resource, NULL);
}
 
for (i = 0; i < VL_MAX_REF_FRAMES; ++i) {
pipe_resource_reference(&buffer->mv[i].resource, NULL);
}
}
/drivers/video/Gallium/auxiliary/vl/vl_vertex_buffers.h
0,0 → 1,138
/**************************************************************************
*
* Copyright 2010 Christian König
* 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.
*
**************************************************************************/
#ifndef vl_vertex_buffers_h
#define vl_vertex_buffers_h
 
#include "pipe/p_state.h"
#include "pipe/p_video_state.h"
 
#include "vl_defines.h"
#include "vl_types.h"
 
/* vertex buffers act as a todo list
* uploading all the usefull informations to video ram
* so a vertex shader can work with them
*/
 
/* inputs to the vertex shaders */
enum VS_INPUT
{
VS_I_RECT = 0,
VS_I_VPOS = 1,
 
VS_I_BLOCK_NUM = 2,
 
VS_I_MV_TOP = 2,
VS_I_MV_BOTTOM = 3,
 
NUM_VS_INPUTS = 4
};
 
enum vl_mv_weight
{
PIPE_VIDEO_MV_WEIGHT_MIN = 0,
PIPE_VIDEO_MV_WEIGHT_HALF = 128,
PIPE_VIDEO_MV_WEIGHT_MAX = 256
};
 
enum vl_field_select
{
PIPE_VIDEO_FRAME = 0,
PIPE_VIDEO_TOP_FIELD = 1,
PIPE_VIDEO_BOTTOM_FIELD = 3,
 
/* TODO
PIPE_VIDEO_DUALPRIME
PIPE_VIDEO_16x8
*/
};
 
struct vl_motionvector
{
struct {
int16_t x, y;
int16_t field_select; /**< enum pipe_video_field_select */
int16_t weight; /**< enum pipe_video_mv_weight */
} top, bottom;
};
 
struct vl_ycbcr_block
{
uint8_t x, y;
uint8_t intra;
uint8_t coding;
float block_num;
};
 
struct vl_vertex_buffer
{
unsigned width, height;
 
struct {
struct pipe_resource *resource;
struct pipe_transfer *transfer;
struct vl_ycbcr_block *vertex_stream;
} ycbcr[VL_NUM_COMPONENTS];
 
struct {
struct pipe_resource *resource;
struct pipe_transfer *transfer;
struct vl_motionvector *vertex_stream;
} mv[VL_MAX_REF_FRAMES];
};
 
struct pipe_vertex_buffer vl_vb_upload_quads(struct pipe_context *pipe);
 
struct pipe_vertex_buffer vl_vb_upload_pos(struct pipe_context *pipe, unsigned width, unsigned height);
 
void *vl_vb_get_ves_ycbcr(struct pipe_context *pipe);
 
void *vl_vb_get_ves_mv(struct pipe_context *pipe);
 
bool vl_vb_init(struct vl_vertex_buffer *buffer,
struct pipe_context *pipe,
unsigned width, unsigned height);
 
unsigned vl_vb_attributes_per_plock(struct vl_vertex_buffer *buffer);
 
void vl_vb_map(struct vl_vertex_buffer *buffer, struct pipe_context *pipe);
 
struct pipe_vertex_buffer vl_vb_get_ycbcr(struct vl_vertex_buffer *buffer, int component);
 
struct vl_ycbcr_block *vl_vb_get_ycbcr_stream(struct vl_vertex_buffer *buffer, int component);
 
struct pipe_vertex_buffer vl_vb_get_mv(struct vl_vertex_buffer *buffer, int ref_frame);
 
unsigned vl_vb_get_mv_stream_stride(struct vl_vertex_buffer *buffer);
 
struct vl_motionvector *vl_vb_get_mv_stream(struct vl_vertex_buffer *buffer, int ref_frame);
 
void vl_vb_unmap(struct vl_vertex_buffer *buffer, struct pipe_context *pipe);
 
void vl_vb_cleanup(struct vl_vertex_buffer *buffer);
 
#endif /* vl_vertex_buffers_h */
/drivers/video/Gallium/auxiliary/vl/vl_video_buffer.c
0,0 → 1,509
/**************************************************************************
*
* Copyright 2011 Christian König.
* 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.
*
**************************************************************************/
 
#include <assert.h>
 
#include "pipe/p_screen.h"
#include "pipe/p_context.h"
#include "pipe/p_state.h"
 
#include "util/u_format.h"
#include "util/u_inlines.h"
#include "util/u_sampler.h"
#include "util/u_memory.h"
 
#include "vl_video_buffer.h"
 
const enum pipe_format const_resource_formats_YV12[3] = {
PIPE_FORMAT_R8_UNORM,
PIPE_FORMAT_R8_UNORM,
PIPE_FORMAT_R8_UNORM
};
 
const enum pipe_format const_resource_formats_NV12[3] = {
PIPE_FORMAT_R8_UNORM,
PIPE_FORMAT_R8G8_UNORM,
PIPE_FORMAT_NONE
};
 
const enum pipe_format const_resource_formats_YUVA[3] = {
PIPE_FORMAT_R8G8B8A8_UNORM,
PIPE_FORMAT_NONE,
PIPE_FORMAT_NONE
};
 
const enum pipe_format const_resource_formats_VUYA[3] = {
PIPE_FORMAT_B8G8R8A8_UNORM,
PIPE_FORMAT_NONE,
PIPE_FORMAT_NONE
};
 
const enum pipe_format const_resource_formats_YUYV[3] = {
PIPE_FORMAT_R8G8_R8B8_UNORM,
PIPE_FORMAT_NONE,
PIPE_FORMAT_NONE
};
 
const enum pipe_format const_resource_formats_UYVY[3] = {
PIPE_FORMAT_G8R8_B8R8_UNORM,
PIPE_FORMAT_NONE,
PIPE_FORMAT_NONE
};
 
const unsigned const_resource_plane_order_YUV[3] = {
0,
1,
2
};
 
const unsigned const_resource_plane_order_YVU[3] = {
0,
2,
1
};
 
const enum pipe_format *
vl_video_buffer_formats(struct pipe_screen *screen, enum pipe_format format)
{
switch(format) {
case PIPE_FORMAT_YV12:
return const_resource_formats_YV12;
 
case PIPE_FORMAT_NV12:
return const_resource_formats_NV12;
 
case PIPE_FORMAT_R8G8B8A8_UNORM:
return const_resource_formats_YUVA;
 
case PIPE_FORMAT_B8G8R8A8_UNORM:
return const_resource_formats_VUYA;
 
case PIPE_FORMAT_YUYV:
return const_resource_formats_YUYV;
 
case PIPE_FORMAT_UYVY:
return const_resource_formats_UYVY;
 
default:
return NULL;
}
}
 
const unsigned *
vl_video_buffer_plane_order(enum pipe_format format)
{
switch(format) {
case PIPE_FORMAT_YV12:
return const_resource_plane_order_YVU;
 
case PIPE_FORMAT_NV12:
case PIPE_FORMAT_R8G8B8A8_UNORM:
case PIPE_FORMAT_B8G8R8A8_UNORM:
case PIPE_FORMAT_YUYV:
case PIPE_FORMAT_UYVY:
return const_resource_plane_order_YUV;
 
default:
return NULL;
}
}
 
static enum pipe_format
vl_video_buffer_surface_format(enum pipe_format format)
{
const struct util_format_description *desc = util_format_description(format);
 
/* a subsampled formats can't work as surface use RGBA instead */
if (desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED)
return PIPE_FORMAT_R8G8B8A8_UNORM;
 
return format;
}
 
boolean
vl_video_buffer_is_format_supported(struct pipe_screen *screen,
enum pipe_format format,
enum pipe_video_profile profile)
{
const enum pipe_format *resource_formats;
unsigned i;
 
resource_formats = vl_video_buffer_formats(screen, format);
if (!resource_formats)
return false;
 
for (i = 0; i < VL_NUM_COMPONENTS; ++i) {
enum pipe_format format = resource_formats[i];
 
if (format == PIPE_FORMAT_NONE)
continue;
 
/* we at least need to sample from it */
if (!screen->is_format_supported(screen, format, PIPE_TEXTURE_2D, 0, PIPE_BIND_SAMPLER_VIEW))
return false;
 
format = vl_video_buffer_surface_format(format);
if (!screen->is_format_supported(screen, format, PIPE_TEXTURE_2D, 0, PIPE_BIND_RENDER_TARGET))
return false;
}
 
return true;
}
 
unsigned
vl_video_buffer_max_size(struct pipe_screen *screen)
{
uint32_t max_2d_texture_level;
 
max_2d_texture_level = screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS);
 
return 1 << (max_2d_texture_level-1);
}
 
void
vl_video_buffer_set_associated_data(struct pipe_video_buffer *vbuf,
struct pipe_video_decoder *vdec,
void *associated_data,
void (*destroy_associated_data)(void *))
{
vbuf->decoder = vdec;
 
if (vbuf->associated_data == associated_data)
return;
 
if (vbuf->associated_data)
vbuf->destroy_associated_data(vbuf->associated_data);
 
vbuf->associated_data = associated_data;
vbuf->destroy_associated_data = destroy_associated_data;
}
 
void *
vl_video_buffer_get_associated_data(struct pipe_video_buffer *vbuf,
struct pipe_video_decoder *vdec)
{
if (vbuf->decoder == vdec)
return vbuf->associated_data;
else
return NULL;
}
 
void
vl_video_buffer_template(struct pipe_resource *templ,
const struct pipe_video_buffer *tmpl,
enum pipe_format resource_format,
unsigned depth, unsigned array_size,
unsigned usage, unsigned plane)
{
memset(templ, 0, sizeof(*templ));
if (depth > 1)
templ->target = PIPE_TEXTURE_3D;
else if (array_size > 1)
templ->target = PIPE_TEXTURE_2D_ARRAY;
else
templ->target = PIPE_TEXTURE_2D;
templ->format = resource_format;
templ->width0 = tmpl->width;
templ->height0 = tmpl->height;
templ->depth0 = depth;
templ->array_size = array_size;
templ->bind = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
templ->usage = usage;
 
if (plane > 0) {
if (tmpl->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_420) {
templ->width0 /= 2;
templ->height0 /= 2;
} else if (tmpl->chroma_format == PIPE_VIDEO_CHROMA_FORMAT_422) {
templ->height0 /= 2;
}
}
}
 
static void
vl_video_buffer_destroy(struct pipe_video_buffer *buffer)
{
struct vl_video_buffer *buf = (struct vl_video_buffer *)buffer;
unsigned i;
 
assert(buf);
 
for (i = 0; i < VL_NUM_COMPONENTS; ++i) {
pipe_sampler_view_reference(&buf->sampler_view_planes[i], NULL);
pipe_sampler_view_reference(&buf->sampler_view_components[i], NULL);
pipe_resource_reference(&buf->resources[i], NULL);
}
 
for (i = 0; i < VL_NUM_COMPONENTS * 2; ++i)
pipe_surface_reference(&buf->surfaces[i], NULL);
 
vl_video_buffer_set_associated_data(buffer, NULL, NULL, NULL);
 
FREE(buffer);
}
 
static struct pipe_sampler_view **
vl_video_buffer_sampler_view_planes(struct pipe_video_buffer *buffer)
{
struct vl_video_buffer *buf = (struct vl_video_buffer *)buffer;
struct pipe_sampler_view sv_templ;
struct pipe_context *pipe;
unsigned i;
 
assert(buf);
 
pipe = buf->base.context;
 
for (i = 0; i < buf->num_planes; ++i ) {
if (!buf->sampler_view_planes[i]) {
memset(&sv_templ, 0, sizeof(sv_templ));
u_sampler_view_default_template(&sv_templ, buf->resources[i], buf->resources[i]->format);
 
if (util_format_get_nr_components(buf->resources[i]->format) == 1)
sv_templ.swizzle_r = sv_templ.swizzle_g = sv_templ.swizzle_b = sv_templ.swizzle_a = PIPE_SWIZZLE_RED;
 
buf->sampler_view_planes[i] = pipe->create_sampler_view(pipe, buf->resources[i], &sv_templ);
if (!buf->sampler_view_planes[i])
goto error;
}
}
 
return buf->sampler_view_planes;
 
error:
for (i = 0; i < buf->num_planes; ++i )
pipe_sampler_view_reference(&buf->sampler_view_planes[i], NULL);
 
return NULL;
}
 
static struct pipe_sampler_view **
vl_video_buffer_sampler_view_components(struct pipe_video_buffer *buffer)
{
struct vl_video_buffer *buf = (struct vl_video_buffer *)buffer;
struct pipe_sampler_view sv_templ;
struct pipe_context *pipe;
const enum pipe_format *sampler_format;
const unsigned *plane_order;
unsigned i, j, component;
 
assert(buf);
 
pipe = buf->base.context;
 
sampler_format = vl_video_buffer_formats(pipe->screen, buf->base.buffer_format);
plane_order = vl_video_buffer_plane_order(buf->base.buffer_format);
 
for (component = 0, i = 0; i < buf->num_planes; ++i ) {
struct pipe_resource *res = buf->resources[plane_order[i]];
const struct util_format_description *desc = util_format_description(res->format);
unsigned nr_components = util_format_get_nr_components(res->format);
if (desc->layout == UTIL_FORMAT_LAYOUT_SUBSAMPLED)
nr_components = 3;
 
for (j = 0; j < nr_components && component < VL_NUM_COMPONENTS; ++j, ++component) {
if (buf->sampler_view_components[component])
continue;
 
memset(&sv_templ, 0, sizeof(sv_templ));
u_sampler_view_default_template(&sv_templ, res, sampler_format[plane_order[i]]);
sv_templ.swizzle_r = sv_templ.swizzle_g = sv_templ.swizzle_b = PIPE_SWIZZLE_RED + j;
sv_templ.swizzle_a = PIPE_SWIZZLE_ONE;
buf->sampler_view_components[component] = pipe->create_sampler_view(pipe, res, &sv_templ);
if (!buf->sampler_view_components[component])
goto error;
}
}
assert(component == VL_NUM_COMPONENTS);
 
return buf->sampler_view_components;
 
error:
for (i = 0; i < VL_NUM_COMPONENTS; ++i )
pipe_sampler_view_reference(&buf->sampler_view_components[i], NULL);
 
return NULL;
}
 
static struct pipe_surface **
vl_video_buffer_surfaces(struct pipe_video_buffer *buffer)
{
struct vl_video_buffer *buf = (struct vl_video_buffer *)buffer;
struct pipe_surface surf_templ;
struct pipe_context *pipe;
unsigned i, j, array_size, surf;
 
assert(buf);
 
pipe = buf->base.context;
 
array_size = buffer->interlaced ? 2 : 1;
for (i = 0, surf = 0; i < VL_NUM_COMPONENTS; ++i) {
for (j = 0; j < array_size; ++j, ++surf) {
assert(surf < (VL_NUM_COMPONENTS * 2));
 
if (!buf->resources[i]) {
pipe_surface_reference(&buf->surfaces[surf], NULL);
continue;
}
 
if (!buf->surfaces[surf]) {
memset(&surf_templ, 0, sizeof(surf_templ));
surf_templ.format = vl_video_buffer_surface_format(buf->resources[i]->format);
surf_templ.u.tex.first_layer = surf_templ.u.tex.last_layer = j;
buf->surfaces[surf] = pipe->create_surface(pipe, buf->resources[i], &surf_templ);
if (!buf->surfaces[surf])
goto error;
}
}
}
 
return buf->surfaces;
 
error:
for (i = 0; i < (VL_NUM_COMPONENTS * 2); ++i )
pipe_surface_reference(&buf->surfaces[i], NULL);
 
return NULL;
}
 
struct pipe_video_buffer *
vl_video_buffer_create(struct pipe_context *pipe,
const struct pipe_video_buffer *tmpl)
{
const enum pipe_format *resource_formats;
struct pipe_video_buffer templat, *result;
bool pot_buffers;
 
assert(pipe);
assert(tmpl->width > 0 && tmpl->height > 0);
 
pot_buffers = !pipe->screen->get_video_param
(
pipe->screen,
PIPE_VIDEO_PROFILE_UNKNOWN,
PIPE_VIDEO_CAP_NPOT_TEXTURES
);
 
resource_formats = vl_video_buffer_formats(pipe->screen, tmpl->buffer_format);
if (!resource_formats)
return NULL;
 
templat = *tmpl;
templat.width = pot_buffers ? util_next_power_of_two(tmpl->width)
: align(tmpl->width, VL_MACROBLOCK_WIDTH);
templat.height = pot_buffers ? util_next_power_of_two(tmpl->height)
: align(tmpl->height, VL_MACROBLOCK_HEIGHT);
 
if (tmpl->interlaced)
templat.height /= 2;
 
result = vl_video_buffer_create_ex
(
pipe, &templat, resource_formats,
1, tmpl->interlaced ? 2 : 1, PIPE_USAGE_STATIC
);
 
 
if (result && tmpl->interlaced)
result->height *= 2;
 
return result;
}
 
struct pipe_video_buffer *
vl_video_buffer_create_ex(struct pipe_context *pipe,
const struct pipe_video_buffer *tmpl,
const enum pipe_format resource_formats[VL_NUM_COMPONENTS],
unsigned depth, unsigned array_size, unsigned usage)
{
struct pipe_resource res_tmpl;
struct pipe_resource *resources[VL_NUM_COMPONENTS];
unsigned i;
 
assert(pipe);
 
memset(resources, 0, sizeof resources);
 
vl_video_buffer_template(&res_tmpl, tmpl, resource_formats[0], depth, array_size, usage, 0);
resources[0] = pipe->screen->resource_create(pipe->screen, &res_tmpl);
if (!resources[0])
goto error;
 
if (resource_formats[1] == PIPE_FORMAT_NONE) {
assert(resource_formats[2] == PIPE_FORMAT_NONE);
return vl_video_buffer_create_ex2(pipe, tmpl, resources);
}
 
vl_video_buffer_template(&res_tmpl, tmpl, resource_formats[1], depth, array_size, usage, 1);
resources[1] = pipe->screen->resource_create(pipe->screen, &res_tmpl);
if (!resources[1])
goto error;
 
if (resource_formats[2] == PIPE_FORMAT_NONE)
return vl_video_buffer_create_ex2(pipe, tmpl, resources);
 
vl_video_buffer_template(&res_tmpl, tmpl, resource_formats[2], depth, array_size, usage, 2);
resources[2] = pipe->screen->resource_create(pipe->screen, &res_tmpl);
if (!resources[2])
goto error;
 
return vl_video_buffer_create_ex2(pipe, tmpl, resources);
 
error:
for (i = 0; i < VL_NUM_COMPONENTS; ++i)
pipe_resource_reference(&resources[i], NULL);
 
return NULL;
}
 
struct pipe_video_buffer *
vl_video_buffer_create_ex2(struct pipe_context *pipe,
const struct pipe_video_buffer *tmpl,
struct pipe_resource *resources[VL_NUM_COMPONENTS])
{
struct vl_video_buffer *buffer;
unsigned i;
 
buffer = CALLOC_STRUCT(vl_video_buffer);
 
buffer->base = *tmpl;
buffer->base.context = pipe;
buffer->base.destroy = vl_video_buffer_destroy;
buffer->base.get_sampler_view_planes = vl_video_buffer_sampler_view_planes;
buffer->base.get_sampler_view_components = vl_video_buffer_sampler_view_components;
buffer->base.get_surfaces = vl_video_buffer_surfaces;
buffer->num_planes = 0;
 
for (i = 0; i < VL_NUM_COMPONENTS; ++i) {
buffer->resources[i] = resources[i];
if (resources[i])
buffer->num_planes++;
}
 
return &buffer->base;
}
/drivers/video/Gallium/auxiliary/vl/vl_video_buffer.h
0,0 → 1,128
/**************************************************************************
*
* Copyright 2011 Christian König.
* 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.
*
**************************************************************************/
 
#ifndef vl_video_buffer_h
#define vl_video_buffer_h
 
#include "pipe/p_context.h"
#include "pipe/p_video_decoder.h"
 
#include "vl_defines.h"
 
/**
* implementation of a planar ycbcr buffer
*/
 
/* planar buffer for vl data upload and manipulation */
struct vl_video_buffer
{
struct pipe_video_buffer base;
unsigned num_planes;
struct pipe_resource *resources[VL_NUM_COMPONENTS];
struct pipe_sampler_view *sampler_view_planes[VL_NUM_COMPONENTS];
struct pipe_sampler_view *sampler_view_components[VL_NUM_COMPONENTS];
struct pipe_surface *surfaces[VL_MAX_SURFACES];
};
 
/**
* get subformats for each plane
*/
const enum pipe_format *
vl_video_buffer_formats(struct pipe_screen *screen, enum pipe_format format);
 
/**
* get YUV plane order
*/
const unsigned *
vl_video_buffer_plane_order(enum pipe_format format);
 
/**
* get maximum size of video buffers
*/
unsigned
vl_video_buffer_max_size(struct pipe_screen *screen);
 
/**
* check if video buffer format is supported for a codec/profile
* can be used as default implementation of screen->is_video_format_supported
*/
boolean
vl_video_buffer_is_format_supported(struct pipe_screen *screen,
enum pipe_format format,
enum pipe_video_profile profile);
 
/*
* set the associated data for the given video buffer
*/
void
vl_video_buffer_set_associated_data(struct pipe_video_buffer *vbuf,
struct pipe_video_decoder *vdec,
void *associated_data,
void (*destroy_associated_data)(void *));
 
/*
* get the associated data for the given video buffer
*/
void *
vl_video_buffer_get_associated_data(struct pipe_video_buffer *vbuf,
struct pipe_video_decoder *vdec);
 
/**
* fill a resource template for the given plane
*/
void
vl_video_buffer_template(struct pipe_resource *templ,
const struct pipe_video_buffer *templat,
enum pipe_format resource_format,
unsigned depth, unsigned array_size,
unsigned usage, unsigned plane);
 
/**
* creates a video buffer, can be used as a standard implementation for pipe->create_video_buffer
*/
struct pipe_video_buffer *
vl_video_buffer_create(struct pipe_context *pipe,
const struct pipe_video_buffer *templat);
 
/**
* extended create function, gets depth, array_size, usage and formats for each plane seperately
*/
struct pipe_video_buffer *
vl_video_buffer_create_ex(struct pipe_context *pipe,
const struct pipe_video_buffer *templat,
const enum pipe_format resource_formats[VL_NUM_COMPONENTS],
unsigned depth, unsigned array_size, unsigned usage);
 
/**
* even more extended create function, provide the pipe_resource for each plane
*/
struct pipe_video_buffer *
vl_video_buffer_create_ex2(struct pipe_context *pipe,
const struct pipe_video_buffer *templat,
struct pipe_resource *resources[VL_NUM_COMPONENTS]);
 
#endif /* vl_video_buffer_h */
/drivers/video/Gallium/auxiliary/vl/vl_vlc.h
0,0 → 1,277
/**************************************************************************
*
* Copyright 2011 Christian König.
* 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.
*
**************************************************************************/
 
/*
* Functions for fast bitwise access to multiple probably unaligned input buffers
*/
 
#ifndef vl_vlc_h
#define vl_vlc_h
 
#include "pipe/p_compiler.h"
 
#include "util/u_math.h"
#include "util/u_pointer.h"
#include "util/u_debug.h"
 
struct vl_vlc
{
uint64_t buffer;
signed invalid_bits;
const uint8_t *data;
const uint8_t *end;
 
unsigned num_inputs;
const void *const *inputs;
const unsigned *sizes;
unsigned bytes_left;
};
 
struct vl_vlc_entry
{
int8_t length;
int8_t value;
};
 
struct vl_vlc_compressed
{
uint16_t bitcode;
struct vl_vlc_entry entry;
};
 
/**
* initalize and decompress a lookup table
*/
static INLINE void
vl_vlc_init_table(struct vl_vlc_entry *dst, unsigned dst_size, const struct vl_vlc_compressed *src, unsigned src_size)
{
unsigned i, bits = util_logbase2(dst_size);
 
assert(dst && dst_size);
assert(src && src_size);
 
for (i=0;i<dst_size;++i) {
dst[i].length = 0;
dst[i].value = 0;
}
 
for(; src_size > 0; --src_size, ++src) {
for(i=0; i<(1 << (bits - src->entry.length)); ++i)
dst[src->bitcode >> (16 - bits) | i] = src->entry;
}
}
 
/**
* switch over to next input buffer
*/
static INLINE void
vl_vlc_next_input(struct vl_vlc *vlc)
{
const uint8_t* data = vlc->inputs[0];
unsigned len = vlc->sizes[0];
 
assert(vlc);
assert(vlc->num_inputs);
 
vlc->bytes_left -= len;
 
/* align the data pointer */
while (len && pointer_to_uintptr(data) & 3) {
vlc->buffer |= (uint64_t)*data << (24 + vlc->invalid_bits);
++data;
--len;
vlc->invalid_bits -= 8;
}
vlc->data = data;
vlc->end = data + len;
 
--vlc->num_inputs;
++vlc->inputs;
++vlc->sizes;
}
 
/**
* fill the bit buffer, so that at least 32 bits are valid
*/
static INLINE void
vl_vlc_fillbits(struct vl_vlc *vlc)
{
assert(vlc);
 
/* as long as the buffer needs to be filled */
while (vlc->invalid_bits > 0) {
unsigned bytes_left = vlc->end - vlc->data;
 
/* if this input is depleted */
if (bytes_left == 0) {
 
if (vlc->num_inputs)
/* go on to next input */
vl_vlc_next_input(vlc);
else
/* or give up since we don't have anymore inputs */
return;
 
} else if (bytes_left >= 4) {
 
/* enough bytes in buffer, read in a whole dword */
uint64_t value = *(const uint32_t*)vlc->data;
 
#ifndef PIPE_ARCH_BIG_ENDIAN
value = util_bswap32(value);
#endif
 
vlc->buffer |= value << vlc->invalid_bits;
vlc->data += 4;
vlc->invalid_bits -= 32;
 
/* buffer is now definitely filled up avoid the loop test */
break;
 
} else while (vlc->data < vlc->end) {
 
/* not enough bytes left in buffer, read single bytes */
vlc->buffer |= (uint64_t)*vlc->data << (24 + vlc->invalid_bits);
++vlc->data;
vlc->invalid_bits -= 8;
}
}
}
 
/**
* initialize vlc structure and start reading from first input buffer
*/
static INLINE void
vl_vlc_init(struct vl_vlc *vlc, unsigned num_inputs,
const void *const *inputs, const unsigned *sizes)
{
unsigned i;
 
assert(vlc);
assert(num_inputs);
 
vlc->buffer = 0;
vlc->invalid_bits = 32;
vlc->num_inputs = num_inputs;
vlc->inputs = inputs;
vlc->sizes = sizes;
vlc->bytes_left = 0;
 
for (i = 0; i < num_inputs; ++i)
vlc->bytes_left += sizes[i];
 
vl_vlc_next_input(vlc);
vl_vlc_fillbits(vlc);
vl_vlc_fillbits(vlc);
}
 
/**
* number of bits still valid in bit buffer
*/
static INLINE unsigned
vl_vlc_valid_bits(struct vl_vlc *vlc)
{
return 32 - vlc->invalid_bits;
}
 
/**
* number of bits left over all inbut buffers
*/
static INLINE unsigned
vl_vlc_bits_left(struct vl_vlc *vlc)
{
signed bytes_left = vlc->end - vlc->data;
bytes_left += vlc->bytes_left;
return bytes_left * 8 + vl_vlc_valid_bits(vlc);
}
 
/**
* get num_bits from bit buffer without removing them
*/
static INLINE unsigned
vl_vlc_peekbits(struct vl_vlc *vlc, unsigned num_bits)
{
assert(vl_vlc_valid_bits(vlc) >= num_bits || vlc->data >= vlc->end);
return vlc->buffer >> (64 - num_bits);
}
 
/**
* remove num_bits from bit buffer
*/
static INLINE void
vl_vlc_eatbits(struct vl_vlc *vlc, unsigned num_bits)
{
assert(vl_vlc_valid_bits(vlc) >= num_bits);
 
vlc->buffer <<= num_bits;
vlc->invalid_bits += num_bits;
}
 
/**
* get num_bits from bit buffer with removing them
*/
static INLINE unsigned
vl_vlc_get_uimsbf(struct vl_vlc *vlc, unsigned num_bits)
{
unsigned value;
 
assert(vl_vlc_valid_bits(vlc) >= num_bits);
 
value = vlc->buffer >> (64 - num_bits);
vl_vlc_eatbits(vlc, num_bits);
 
return value;
}
 
/**
* treat num_bits as signed value and remove them from bit buffer
*/
static INLINE signed
vl_vlc_get_simsbf(struct vl_vlc *vlc, unsigned num_bits)
{
signed value;
 
assert(vl_vlc_valid_bits(vlc) >= num_bits);
 
value = ((int64_t)vlc->buffer) >> (64 - num_bits);
vl_vlc_eatbits(vlc, num_bits);
 
return value;
}
 
/**
* lookup a value and length in a decompressed table
*/
static INLINE int8_t
vl_vlc_get_vlclbf(struct vl_vlc *vlc, const struct vl_vlc_entry *tbl, unsigned num_bits)
{
tbl += vl_vlc_peekbits(vlc, num_bits);
vl_vlc_eatbits(vlc, tbl->length);
return tbl->value;
}
 
#endif /* vl_vlc_h */
/drivers/video/Gallium/auxiliary/vl/vl_winsys.h
0,0 → 1,69
/**************************************************************************
*
* Copyright 2009 Younes Manton.
* 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.
*
**************************************************************************/
 
/*
* vl targets use either a dri or sw based winsys backend, so their
* Makefiles directly refer to either vl_winsys_dri.c or vl_winsys_xsp.c.
* Both files implement the interface described in this header.
*/
 
#ifndef vl_winsys_h
#define vl_winsys_h
 
#include <X11/Xlib.h>
#include "pipe/p_defines.h"
#include "pipe/p_format.h"
 
struct pipe_screen;
struct pipe_surface;
 
struct vl_screen
{
struct pipe_screen *pscreen;
};
 
struct vl_screen*
vl_screen_create(Display *display, int screen);
 
void vl_screen_destroy(struct vl_screen *vscreen);
 
struct pipe_resource*
vl_screen_texture_from_drawable(struct vl_screen *vscreen, Drawable drawable);
 
struct u_rect *
vl_screen_get_dirty_area(struct vl_screen *vscreen);
 
uint64_t
vl_screen_get_timestamp(struct vl_screen *vscreen, Drawable drawable);
 
void
vl_screen_set_next_timestamp(struct vl_screen *vscreen, uint64_t stamp);
 
void*
vl_screen_get_private(struct vl_screen *vscreen);
 
#endif
/drivers/video/Gallium/auxiliary/vl/vl_winsys_dri.c
0,0 → 1,398
/**************************************************************************
*
* Copyright 2009 Younes Manton.
* 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.
*
**************************************************************************/
 
/* directly referenced from target Makefile, because of X dependencies */
 
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
 
#include <X11/Xlib-xcb.h>
#include <xcb/dri2.h>
#include <xf86drm.h>
 
#include "pipe/p_screen.h"
#include "pipe/p_context.h"
#include "pipe/p_state.h"
#include "state_tracker/drm_driver.h"
 
#include "util/u_memory.h"
#include "util/u_hash.h"
#include "util/u_hash_table.h"
#include "util/u_inlines.h"
 
#include "vl/vl_compositor.h"
#include "vl/vl_winsys.h"
 
struct vl_dri_screen
{
struct vl_screen base;
xcb_connection_t *conn;
xcb_drawable_t drawable;
 
unsigned width, height;
 
bool current_buffer;
uint32_t buffer_names[2];
struct u_rect dirty_areas[2];
 
bool flushed;
xcb_dri2_swap_buffers_cookie_t swap_cookie;
xcb_dri2_wait_sbc_cookie_t wait_cookie;
xcb_dri2_get_buffers_cookie_t buffers_cookie;
 
int64_t last_ust, ns_frame, last_msc, next_msc;
};
 
static const unsigned int attachments[1] = { XCB_DRI2_ATTACHMENT_BUFFER_BACK_LEFT };
 
static void
vl_dri2_handle_stamps(struct vl_dri_screen* scrn,
uint32_t ust_hi, uint32_t ust_lo,
uint32_t msc_hi, uint32_t msc_lo)
{
int64_t ust = ((((uint64_t)ust_hi) << 32) | ust_lo) * 1000;
int64_t msc = (((uint64_t)msc_hi) << 32) | msc_lo;
 
if (scrn->last_ust && scrn->last_msc && (ust > scrn->last_ust) && (msc > scrn->last_msc))
scrn->ns_frame = (ust - scrn->last_ust) / (msc - scrn->last_msc);
 
scrn->last_ust = ust;
scrn->last_msc = msc;
}
 
static xcb_dri2_get_buffers_reply_t*
vl_dri2_get_flush_reply(struct vl_dri_screen *scrn)
{
xcb_dri2_wait_sbc_reply_t *wait_sbc_reply;
 
assert(scrn);
 
if (!scrn->flushed)
return NULL;
 
scrn->flushed = false;
 
free(xcb_dri2_swap_buffers_reply(scrn->conn, scrn->swap_cookie, NULL));
 
wait_sbc_reply = xcb_dri2_wait_sbc_reply(scrn->conn, scrn->wait_cookie, NULL);
if (!wait_sbc_reply)
return NULL;
vl_dri2_handle_stamps(scrn, wait_sbc_reply->ust_hi, wait_sbc_reply->ust_lo,
wait_sbc_reply->msc_hi, wait_sbc_reply->msc_lo);
free(wait_sbc_reply);
 
return xcb_dri2_get_buffers_reply(scrn->conn, scrn->buffers_cookie, NULL);
}
 
static void
vl_dri2_flush_frontbuffer(struct pipe_screen *screen,
struct pipe_resource *resource,
unsigned level, unsigned layer,
void *context_private)
{
struct vl_dri_screen *scrn = (struct vl_dri_screen*)context_private;
uint32_t msc_hi, msc_lo;
 
assert(screen);
assert(resource);
assert(context_private);
 
free(vl_dri2_get_flush_reply(scrn));
 
msc_hi = scrn->next_msc >> 32;
msc_lo = scrn->next_msc & 0xFFFFFFFF;
 
scrn->swap_cookie = xcb_dri2_swap_buffers_unchecked(scrn->conn, scrn->drawable, msc_hi, msc_lo, 0, 0, 0, 0);
scrn->wait_cookie = xcb_dri2_wait_sbc_unchecked(scrn->conn, scrn->drawable, 0, 0);
scrn->buffers_cookie = xcb_dri2_get_buffers_unchecked(scrn->conn, scrn->drawable, 1, 1, attachments);
 
scrn->flushed = true;
scrn->current_buffer = !scrn->current_buffer;
}
 
static void
vl_dri2_destroy_drawable(struct vl_dri_screen *scrn)
{
xcb_void_cookie_t destroy_cookie;
if (scrn->drawable) {
free(vl_dri2_get_flush_reply(scrn));
destroy_cookie = xcb_dri2_destroy_drawable_checked(scrn->conn, scrn->drawable);
/* ignore any error here, since the drawable can be destroyed long ago */
free(xcb_request_check(scrn->conn, destroy_cookie));
}
}
 
static void
vl_dri2_set_drawable(struct vl_dri_screen *scrn, Drawable drawable)
{
assert(scrn);
assert(drawable);
 
if (scrn->drawable == drawable)
return;
 
vl_dri2_destroy_drawable(scrn);
 
xcb_dri2_create_drawable(scrn->conn, drawable);
scrn->current_buffer = false;
vl_compositor_reset_dirty_area(&scrn->dirty_areas[0]);
vl_compositor_reset_dirty_area(&scrn->dirty_areas[1]);
scrn->drawable = drawable;
}
 
struct pipe_resource*
vl_screen_texture_from_drawable(struct vl_screen *vscreen, Drawable drawable)
{
struct vl_dri_screen *scrn = (struct vl_dri_screen*)vscreen;
 
struct winsys_handle dri2_handle;
struct pipe_resource template, *tex;
 
xcb_dri2_get_buffers_reply_t *reply;
xcb_dri2_dri2_buffer_t *buffers, *back_left;
 
unsigned i;
 
assert(scrn);
 
vl_dri2_set_drawable(scrn, drawable);
reply = vl_dri2_get_flush_reply(scrn);
if (!reply) {
xcb_dri2_get_buffers_cookie_t cookie;
cookie = xcb_dri2_get_buffers_unchecked(scrn->conn, drawable, 1, 1, attachments);
reply = xcb_dri2_get_buffers_reply(scrn->conn, cookie, NULL);
}
if (!reply)
return NULL;
 
buffers = xcb_dri2_get_buffers_buffers(reply);
if (!buffers) {
free(reply);
return NULL;
}
 
for (i = 0; i < reply->count; ++i) {
if (buffers[i].attachment == XCB_DRI2_ATTACHMENT_BUFFER_BACK_LEFT) {
back_left = &buffers[i];
break;
}
}
 
if (i == reply->count) {
free(reply);
return NULL;
}
 
if (reply->width != scrn->width || reply->height != scrn->height) {
vl_compositor_reset_dirty_area(&scrn->dirty_areas[0]);
vl_compositor_reset_dirty_area(&scrn->dirty_areas[1]);
scrn->width = reply->width;
scrn->height = reply->height;
 
} else if (back_left->name != scrn->buffer_names[scrn->current_buffer]) {
vl_compositor_reset_dirty_area(&scrn->dirty_areas[scrn->current_buffer]);
scrn->buffer_names[scrn->current_buffer] = back_left->name;
}
 
memset(&dri2_handle, 0, sizeof(dri2_handle));
dri2_handle.type = DRM_API_HANDLE_TYPE_SHARED;
dri2_handle.handle = back_left->name;
dri2_handle.stride = back_left->pitch;
 
memset(&template, 0, sizeof(template));
template.target = PIPE_TEXTURE_2D;
template.format = PIPE_FORMAT_B8G8R8X8_UNORM;
template.last_level = 0;
template.width0 = reply->width;
template.height0 = reply->height;
template.depth0 = 1;
template.array_size = 1;
template.usage = PIPE_USAGE_STATIC;
template.bind = PIPE_BIND_RENDER_TARGET;
template.flags = 0;
 
tex = scrn->base.pscreen->resource_from_handle(scrn->base.pscreen, &template, &dri2_handle);
free(reply);
 
return tex;
}
 
struct u_rect *
vl_screen_get_dirty_area(struct vl_screen *vscreen)
{
struct vl_dri_screen *scrn = (struct vl_dri_screen*)vscreen;
assert(scrn);
return &scrn->dirty_areas[scrn->current_buffer];
}
 
uint64_t
vl_screen_get_timestamp(struct vl_screen *vscreen, Drawable drawable)
{
struct vl_dri_screen *scrn = (struct vl_dri_screen*)vscreen;
xcb_dri2_get_msc_cookie_t cookie;
xcb_dri2_get_msc_reply_t *reply;
 
assert(scrn);
 
vl_dri2_set_drawable(scrn, drawable);
if (!scrn->last_ust) {
cookie = xcb_dri2_get_msc_unchecked(scrn->conn, drawable);
reply = xcb_dri2_get_msc_reply(scrn->conn, cookie, NULL);
 
if (reply) {
vl_dri2_handle_stamps(scrn, reply->ust_hi, reply->ust_lo,
reply->msc_hi, reply->msc_lo);
free(reply);
}
}
return scrn->last_ust;
}
 
void
vl_screen_set_next_timestamp(struct vl_screen *vscreen, uint64_t stamp)
{
struct vl_dri_screen *scrn = (struct vl_dri_screen*)vscreen;
assert(scrn);
if (stamp && scrn->last_ust && scrn->ns_frame && scrn->last_msc)
scrn->next_msc = ((int64_t)stamp - scrn->last_ust + scrn->ns_frame/2) / scrn->ns_frame + scrn->last_msc;
else
scrn->next_msc = 0;
}
 
void*
vl_screen_get_private(struct vl_screen *vscreen)
{
return vscreen;
}
 
struct vl_screen*
vl_screen_create(Display *display, int screen)
{
struct vl_dri_screen *scrn;
const xcb_query_extension_reply_t *extension;
xcb_dri2_query_version_cookie_t dri2_query_cookie;
xcb_dri2_query_version_reply_t *dri2_query = NULL;
xcb_dri2_connect_cookie_t connect_cookie;
xcb_dri2_connect_reply_t *connect = NULL;
xcb_dri2_authenticate_cookie_t authenticate_cookie;
xcb_dri2_authenticate_reply_t *authenticate = NULL;
xcb_screen_iterator_t s;
xcb_generic_error_t *error = NULL;
char *device_name;
int fd, device_name_length;
 
drm_magic_t magic;
 
assert(display);
 
scrn = CALLOC_STRUCT(vl_dri_screen);
if (!scrn)
return NULL;
 
scrn->conn = XGetXCBConnection(display);
if (!scrn->conn)
goto free_screen;
 
xcb_prefetch_extension_data(scrn->conn, &xcb_dri2_id);
 
extension = xcb_get_extension_data(scrn->conn, &xcb_dri2_id);
if (!(extension && extension->present))
goto free_screen;
 
dri2_query_cookie = xcb_dri2_query_version (scrn->conn, XCB_DRI2_MAJOR_VERSION, XCB_DRI2_MINOR_VERSION);
dri2_query = xcb_dri2_query_version_reply (scrn->conn, dri2_query_cookie, &error);
if (dri2_query == NULL || error != NULL || dri2_query->minor_version < 2)
goto free_screen;
 
s = xcb_setup_roots_iterator(xcb_get_setup(scrn->conn));
while (screen--)
xcb_screen_next(&s);
connect_cookie = xcb_dri2_connect_unchecked(scrn->conn, s.data->root, XCB_DRI2_DRIVER_TYPE_DRI);
connect = xcb_dri2_connect_reply(scrn->conn, connect_cookie, NULL);
if (connect == NULL || connect->driver_name_length + connect->device_name_length == 0)
goto free_screen;
 
device_name_length = xcb_dri2_connect_device_name_length(connect);
device_name = CALLOC(1, device_name_length + 1);
memcpy(device_name, xcb_dri2_connect_device_name(connect), device_name_length);
fd = open(device_name, O_RDWR);
free(device_name);
 
if (fd < 0)
goto free_screen;
 
if (drmGetMagic(fd, &magic))
goto free_screen;
 
authenticate_cookie = xcb_dri2_authenticate_unchecked(scrn->conn, s.data->root, magic);
authenticate = xcb_dri2_authenticate_reply(scrn->conn, authenticate_cookie, NULL);
 
if (authenticate == NULL || !authenticate->authenticated)
goto free_screen;
 
scrn->base.pscreen = driver_descriptor.create_screen(fd);
if (!scrn->base.pscreen)
goto free_screen;
 
scrn->base.pscreen->flush_frontbuffer = vl_dri2_flush_frontbuffer;
vl_compositor_reset_dirty_area(&scrn->dirty_areas[0]);
vl_compositor_reset_dirty_area(&scrn->dirty_areas[1]);
 
free(dri2_query);
free(connect);
free(authenticate);
 
return &scrn->base;
 
free_screen:
FREE(scrn);
 
free(dri2_query);
free(connect);
free(authenticate);
free(error);
 
return NULL;
}
 
void vl_screen_destroy(struct vl_screen *vscreen)
{
struct vl_dri_screen *scrn = (struct vl_dri_screen*)vscreen;
 
assert(vscreen);
 
if (scrn->flushed) {
free(xcb_dri2_swap_buffers_reply(scrn->conn, scrn->swap_cookie, NULL));
free(xcb_dri2_wait_sbc_reply(scrn->conn, scrn->wait_cookie, NULL));
free(xcb_dri2_get_buffers_reply(scrn->conn, scrn->buffers_cookie, NULL));
}
 
vl_dri2_destroy_drawable(scrn);
scrn->base.pscreen->destroy(scrn->base.pscreen);
FREE(scrn);
}
/drivers/video/Gallium/auxiliary/vl/vl_winsys_xsp.c
0,0 → 1,170
/**************************************************************************
*
* Copyright 2009 Younes Manton.
* 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.
*
**************************************************************************/
 
/* directly referenced from target Makefile, because of X dependencies */
 
#include <sys/time.h>
 
#include "pipe/p_state.h"
 
#include "util/u_memory.h"
#include "util/u_format.h"
#include "util/u_inlines.h"
 
#include "state_tracker/xlib_sw_winsys.h"
#include "softpipe/sp_public.h"
 
#include "vl/vl_compositor.h"
#include "vl/vl_winsys.h"
 
struct vl_xsp_screen
{
struct vl_screen base;
Display *display;
int screen;
Visual visual;
struct xlib_drawable xdraw;
struct pipe_resource *tex;
struct u_rect dirty_area;
};
 
struct pipe_resource*
vl_screen_texture_from_drawable(struct vl_screen *vscreen, Drawable drawable)
{
struct vl_xsp_screen *xsp_screen = (struct vl_xsp_screen*)vscreen;
Window root;
int x, y;
unsigned int width, height;
unsigned int border_width;
unsigned int depth;
struct pipe_resource templat;
 
assert(vscreen);
assert(drawable != None);
 
if (XGetGeometry(xsp_screen->display, drawable, &root, &x, &y, &width, &height, &border_width, &depth) == BadDrawable)
return NULL;
 
xsp_screen->xdraw.drawable = drawable;
 
if (xsp_screen->tex) {
if (xsp_screen->tex->width0 == width && xsp_screen->tex->height0 == height)
return xsp_screen->tex;
pipe_resource_reference(&xsp_screen->tex, NULL);
vl_compositor_reset_dirty_area(&xsp_screen->dirty_area);
}
 
memset(&templat, 0, sizeof(struct pipe_resource));
templat.target = PIPE_TEXTURE_2D;
/* XXX: Need to figure out drawable's format */
templat.format = PIPE_FORMAT_B8G8R8X8_UNORM;
templat.last_level = 0;
templat.width0 = width;
templat.height0 = height;
templat.depth0 = 1;
templat.usage = PIPE_USAGE_DEFAULT;
templat.bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_DISPLAY_TARGET;
templat.flags = 0;
 
xsp_screen->xdraw.depth = 24/*util_format_get_blocksizebits(templat.format) /
util_format_get_blockwidth(templat.format)*/;
 
pipe_resource_reference(&xsp_screen->tex, vscreen->pscreen->resource_create(vscreen->pscreen, &templat));
return xsp_screen->tex;
}
 
struct u_rect *
vl_screen_get_dirty_area(struct vl_screen *vscreen)
{
struct vl_xsp_screen *xsp_screen = (struct vl_xsp_screen*)vscreen;
return &xsp_screen->dirty_area;
}
 
uint64_t
vl_screen_get_timestamp(struct vl_screen *vscreen, Drawable drawable)
{
struct timeval tv;
gettimeofday(&tv, NULL);
return (uint64_t)tv.tv_sec * 1000000000LL + (uint64_t)tv.tv_usec * 1000LL;
}
 
void
vl_screen_set_next_timestamp(struct vl_screen *vscreen, uint64_t stamp)
{
/* not supported on softpipe and so only a dummy */
}
 
void*
vl_screen_get_private(struct vl_screen *vscreen)
{
struct vl_xsp_screen *xsp_screen = (struct vl_xsp_screen*)vscreen;
return &xsp_screen->xdraw;
}
 
struct vl_screen*
vl_screen_create(Display *display, int screen)
{
struct vl_xsp_screen *xsp_screen;
struct sw_winsys *winsys;
 
assert(display);
 
xsp_screen = CALLOC_STRUCT(vl_xsp_screen);
if (!xsp_screen)
return NULL;
 
winsys = xlib_create_sw_winsys(display);
if (!winsys) {
FREE(xsp_screen);
return NULL;
}
 
xsp_screen->base.pscreen = softpipe_create_screen(winsys);
if (!xsp_screen->base.pscreen) {
winsys->destroy(winsys);
FREE(xsp_screen);
return NULL;
}
 
xsp_screen->display = display;
xsp_screen->screen = screen;
xsp_screen->xdraw.visual = XDefaultVisual(display, screen);
vl_compositor_reset_dirty_area(&xsp_screen->dirty_area);
 
return &xsp_screen->base;
}
 
void vl_screen_destroy(struct vl_screen *vscreen)
{
struct vl_xsp_screen *xsp_screen = (struct vl_xsp_screen*)vscreen;
 
assert(vscreen);
 
pipe_resource_reference(&xsp_screen->tex, NULL);
vscreen->pscreen->destroy(vscreen->pscreen);
FREE(vscreen);
}
/drivers/video/Gallium/auxiliary/vl/vl_zscan.c
0,0 → 1,584
/**************************************************************************
*
* Copyright 2011 Christian König
* 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.
*
**************************************************************************/
 
#include <assert.h>
 
#include "pipe/p_screen.h"
#include "pipe/p_context.h"
 
#include "util/u_draw.h"
#include "util/u_sampler.h"
#include "util/u_inlines.h"
#include "util/u_memory.h"
 
#include "tgsi/tgsi_ureg.h"
 
#include "vl_defines.h"
#include "vl_types.h"
 
#include "vl_zscan.h"
#include "vl_vertex_buffers.h"
 
enum VS_OUTPUT
{
VS_O_VPOS = 0,
VS_O_VTEX = 0
};
 
const int vl_zscan_linear[] =
{
/* Linear scan pattern */
0, 1, 2, 3, 4, 5, 6, 7,
8, 9,10,11,12,13,14,15,
16,17,18,19,20,21,22,23,
24,25,26,27,28,29,30,31,
32,33,34,35,36,37,38,39,
40,41,42,43,44,45,46,47,
48,49,50,51,52,53,54,55,
56,57,58,59,60,61,62,63
};
 
const int vl_zscan_normal[] =
{
/* Zig-Zag scan pattern */
0, 1, 8,16, 9, 2, 3,10,
17,24,32,25,18,11, 4, 5,
12,19,26,33,40,48,41,34,
27,20,13, 6, 7,14,21,28,
35,42,49,56,57,50,43,36,
29,22,15,23,30,37,44,51,
58,59,52,45,38,31,39,46,
53,60,61,54,47,55,62,63
};
 
const int vl_zscan_alternate[] =
{
/* Alternate scan pattern */
0, 8,16,24, 1, 9, 2,10,
17,25,32,40,48,56,57,49,
41,33,26,18, 3,11, 4,12,
19,27,34,42,50,58,35,43,
51,59,20,28, 5,13, 6,14,
21,29,36,44,52,60,37,45,
53,61,22,30, 7,15,23,31,
38,46,54,62,39,47,55,63
};
 
static void *
create_vert_shader(struct vl_zscan *zscan)
{
struct ureg_program *shader;
 
struct ureg_src scale;
struct ureg_src vrect, vpos, block_num;
 
struct ureg_dst tmp;
struct ureg_dst o_vpos;
struct ureg_dst *o_vtex;
 
signed i;
 
shader = ureg_create(TGSI_PROCESSOR_VERTEX);
if (!shader)
return NULL;
 
o_vtex = MALLOC(zscan->num_channels * sizeof(struct ureg_dst));
 
scale = ureg_imm2f(shader,
(float)VL_BLOCK_WIDTH / zscan->buffer_width,
(float)VL_BLOCK_HEIGHT / zscan->buffer_height);
 
vrect = ureg_DECL_vs_input(shader, VS_I_RECT);
vpos = ureg_DECL_vs_input(shader, VS_I_VPOS);
block_num = ureg_DECL_vs_input(shader, VS_I_BLOCK_NUM);
 
tmp = ureg_DECL_temporary(shader);
 
o_vpos = ureg_DECL_output(shader, TGSI_SEMANTIC_POSITION, VS_O_VPOS);
 
for (i = 0; i < zscan->num_channels; ++i)
o_vtex[i] = ureg_DECL_output(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX + i);
 
/*
* o_vpos.xy = (vpos + vrect) * scale
* o_vpos.zw = 1.0f
*
* tmp.xy = InstanceID / blocks_per_line
* tmp.x = frac(tmp.x)
* tmp.y = floor(tmp.y)
*
* o_vtex.x = vrect.x / blocks_per_line + tmp.x
* o_vtex.y = vrect.y
* o_vtex.z = tmp.z * blocks_per_line / blocks_total
*/
ureg_ADD(shader, ureg_writemask(tmp, TGSI_WRITEMASK_XY), vpos, vrect);
ureg_MUL(shader, ureg_writemask(o_vpos, TGSI_WRITEMASK_XY), ureg_src(tmp), scale);
ureg_MOV(shader, ureg_writemask(o_vpos, TGSI_WRITEMASK_ZW), ureg_imm1f(shader, 1.0f));
 
ureg_MUL(shader, ureg_writemask(tmp, TGSI_WRITEMASK_XW), ureg_scalar(block_num, TGSI_SWIZZLE_X),
ureg_imm1f(shader, 1.0f / zscan->blocks_per_line));
 
ureg_FRC(shader, ureg_writemask(tmp, TGSI_WRITEMASK_Y), ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_X));
ureg_FLR(shader, ureg_writemask(tmp, TGSI_WRITEMASK_W), ureg_src(tmp));
 
for (i = 0; i < zscan->num_channels; ++i) {
ureg_ADD(shader, ureg_writemask(tmp, TGSI_WRITEMASK_X), ureg_scalar(ureg_src(tmp), TGSI_SWIZZLE_Y),
ureg_imm1f(shader, 1.0f / (zscan->blocks_per_line * VL_BLOCK_WIDTH)
* (i - (signed)zscan->num_channels / 2)));
 
ureg_MAD(shader, ureg_writemask(o_vtex[i], TGSI_WRITEMASK_X), vrect,
ureg_imm1f(shader, 1.0f / zscan->blocks_per_line), ureg_src(tmp));
ureg_MOV(shader, ureg_writemask(o_vtex[i], TGSI_WRITEMASK_Y), vrect);
ureg_MOV(shader, ureg_writemask(o_vtex[i], TGSI_WRITEMASK_Z), vpos);
ureg_MUL(shader, ureg_writemask(o_vtex[i], TGSI_WRITEMASK_W), ureg_src(tmp),
ureg_imm1f(shader, (float)zscan->blocks_per_line / zscan->blocks_total));
}
 
ureg_release_temporary(shader, tmp);
ureg_END(shader);
 
FREE(o_vtex);
 
return ureg_create_shader_and_destroy(shader, zscan->pipe);
}
 
static void *
create_frag_shader(struct vl_zscan *zscan)
{
struct ureg_program *shader;
struct ureg_src *vtex;
 
struct ureg_src samp_src, samp_scan, samp_quant;
 
struct ureg_dst *tmp;
struct ureg_dst quant, fragment;
 
unsigned i;
 
shader = ureg_create(TGSI_PROCESSOR_FRAGMENT);
if (!shader)
return NULL;
 
vtex = MALLOC(zscan->num_channels * sizeof(struct ureg_src));
tmp = MALLOC(zscan->num_channels * sizeof(struct ureg_dst));
 
for (i = 0; i < zscan->num_channels; ++i)
vtex[i] = ureg_DECL_fs_input(shader, TGSI_SEMANTIC_GENERIC, VS_O_VTEX + i, TGSI_INTERPOLATE_LINEAR);
 
samp_src = ureg_DECL_sampler(shader, 0);
samp_scan = ureg_DECL_sampler(shader, 1);
samp_quant = ureg_DECL_sampler(shader, 2);
 
for (i = 0; i < zscan->num_channels; ++i)
tmp[i] = ureg_DECL_temporary(shader);
quant = ureg_DECL_temporary(shader);
 
fragment = ureg_DECL_output(shader, TGSI_SEMANTIC_COLOR, 0);
 
/*
* tmp.x = tex(vtex, 1)
* tmp.y = vtex.z
* fragment = tex(tmp, 0) * quant
*/
for (i = 0; i < zscan->num_channels; ++i)
ureg_TEX(shader, ureg_writemask(tmp[i], TGSI_WRITEMASK_X), TGSI_TEXTURE_2D, vtex[i], samp_scan);
 
for (i = 0; i < zscan->num_channels; ++i)
ureg_MOV(shader, ureg_writemask(tmp[i], TGSI_WRITEMASK_Y), ureg_scalar(vtex[i], TGSI_SWIZZLE_W));
 
for (i = 0; i < zscan->num_channels; ++i) {
ureg_TEX(shader, ureg_writemask(tmp[0], TGSI_WRITEMASK_X << i), TGSI_TEXTURE_2D, ureg_src(tmp[i]), samp_src);
ureg_TEX(shader, ureg_writemask(quant, TGSI_WRITEMASK_X << i), TGSI_TEXTURE_3D, vtex[i], samp_quant);
}
 
ureg_MUL(shader, quant, ureg_src(quant), ureg_imm1f(shader, 16.0f));
ureg_MUL(shader, fragment, ureg_src(tmp[0]), ureg_src(quant));
 
for (i = 0; i < zscan->num_channels; ++i)
ureg_release_temporary(shader, tmp[i]);
ureg_END(shader);
 
FREE(vtex);
FREE(tmp);
 
return ureg_create_shader_and_destroy(shader, zscan->pipe);
}
 
static bool
init_shaders(struct vl_zscan *zscan)
{
assert(zscan);
 
zscan->vs = create_vert_shader(zscan);
if (!zscan->vs)
goto error_vs;
 
zscan->fs = create_frag_shader(zscan);
if (!zscan->fs)
goto error_fs;
 
return true;
 
error_fs:
zscan->pipe->delete_vs_state(zscan->pipe, zscan->vs);
 
error_vs:
return false;
}
 
static void
cleanup_shaders(struct vl_zscan *zscan)
{
assert(zscan);
 
zscan->pipe->delete_vs_state(zscan->pipe, zscan->vs);
zscan->pipe->delete_fs_state(zscan->pipe, zscan->fs);
}
 
static bool
init_state(struct vl_zscan *zscan)
{
struct pipe_blend_state blend;
struct pipe_rasterizer_state rs_state;
struct pipe_sampler_state sampler;
unsigned i;
 
assert(zscan);
 
memset(&rs_state, 0, sizeof(rs_state));
rs_state.half_pixel_center = true;
rs_state.bottom_edge_rule = true;
rs_state.depth_clip = 1;
zscan->rs_state = zscan->pipe->create_rasterizer_state(zscan->pipe, &rs_state);
if (!zscan->rs_state)
goto error_rs_state;
 
memset(&blend, 0, sizeof blend);
 
blend.independent_blend_enable = 0;
blend.rt[0].blend_enable = 0;
blend.rt[0].rgb_func = PIPE_BLEND_ADD;
blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ONE;
blend.rt[0].alpha_func = PIPE_BLEND_ADD;
blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
blend.logicop_enable = 0;
blend.logicop_func = PIPE_LOGICOP_CLEAR;
/* Needed to allow color writes to FB, even if blending disabled */
blend.rt[0].colormask = PIPE_MASK_RGBA;
blend.dither = 0;
zscan->blend = zscan->pipe->create_blend_state(zscan->pipe, &blend);
if (!zscan->blend)
goto error_blend;
 
for (i = 0; i < 3; ++i) {
memset(&sampler, 0, sizeof(sampler));
sampler.wrap_s = PIPE_TEX_WRAP_REPEAT;
sampler.wrap_t = PIPE_TEX_WRAP_REPEAT;
sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
sampler.compare_mode = PIPE_TEX_COMPARE_NONE;
sampler.compare_func = PIPE_FUNC_ALWAYS;
sampler.normalized_coords = 1;
zscan->samplers[i] = zscan->pipe->create_sampler_state(zscan->pipe, &sampler);
if (!zscan->samplers[i])
goto error_samplers;
}
 
return true;
 
error_samplers:
for (i = 0; i < 2; ++i)
if (zscan->samplers[i])
zscan->pipe->delete_sampler_state(zscan->pipe, zscan->samplers[i]);
 
zscan->pipe->delete_rasterizer_state(zscan->pipe, zscan->rs_state);
 
error_blend:
zscan->pipe->delete_blend_state(zscan->pipe, zscan->blend);
 
error_rs_state:
return false;
}
 
static void
cleanup_state(struct vl_zscan *zscan)
{
unsigned i;
 
assert(zscan);
 
for (i = 0; i < 3; ++i)
zscan->pipe->delete_sampler_state(zscan->pipe, zscan->samplers[i]);
 
zscan->pipe->delete_rasterizer_state(zscan->pipe, zscan->rs_state);
zscan->pipe->delete_blend_state(zscan->pipe, zscan->blend);
}
 
struct pipe_sampler_view *
vl_zscan_layout(struct pipe_context *pipe, const int layout[64], unsigned blocks_per_line)
{
const unsigned total_size = blocks_per_line * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT;
 
int patched_layout[64];
 
struct pipe_resource res_tmpl, *res;
struct pipe_sampler_view sv_tmpl, *sv;
struct pipe_transfer *buf_transfer;
unsigned x, y, i, pitch;
float *f;
 
struct pipe_box rect =
{
0, 0, 0,
VL_BLOCK_WIDTH * blocks_per_line,
VL_BLOCK_HEIGHT,
1
};
 
assert(pipe && layout && blocks_per_line);
 
for (i = 0; i < 64; ++i)
patched_layout[layout[i]] = i;
 
memset(&res_tmpl, 0, sizeof(res_tmpl));
res_tmpl.target = PIPE_TEXTURE_2D;
res_tmpl.format = PIPE_FORMAT_R32_FLOAT;
res_tmpl.width0 = VL_BLOCK_WIDTH * blocks_per_line;
res_tmpl.height0 = VL_BLOCK_HEIGHT;
res_tmpl.depth0 = 1;
res_tmpl.array_size = 1;
res_tmpl.usage = PIPE_USAGE_IMMUTABLE;
res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW;
 
res = pipe->screen->resource_create(pipe->screen, &res_tmpl);
if (!res)
goto error_resource;
 
f = pipe->transfer_map(pipe, res,
0, PIPE_TRANSFER_WRITE | PIPE_TRANSFER_DISCARD_RANGE,
&rect, &buf_transfer);
if (!f)
goto error_map;
 
pitch = buf_transfer->stride / sizeof(float);
 
for (i = 0; i < blocks_per_line; ++i)
for (y = 0; y < VL_BLOCK_HEIGHT; ++y)
for (x = 0; x < VL_BLOCK_WIDTH; ++x) {
float addr = patched_layout[x + y * VL_BLOCK_WIDTH] +
i * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT;
 
addr /= total_size;
 
f[i * VL_BLOCK_WIDTH + y * pitch + x] = addr;
}
 
pipe->transfer_unmap(pipe, buf_transfer);
 
memset(&sv_tmpl, 0, sizeof(sv_tmpl));
u_sampler_view_default_template(&sv_tmpl, res, res->format);
sv = pipe->create_sampler_view(pipe, res, &sv_tmpl);
pipe_resource_reference(&res, NULL);
if (!sv)
goto error_map;
 
return sv;
 
error_map:
pipe_resource_reference(&res, NULL);
 
error_resource:
return NULL;
}
 
bool
vl_zscan_init(struct vl_zscan *zscan, struct pipe_context *pipe,
unsigned buffer_width, unsigned buffer_height,
unsigned blocks_per_line, unsigned blocks_total,
unsigned num_channels)
{
assert(zscan && pipe);
 
zscan->pipe = pipe;
zscan->buffer_width = buffer_width;
zscan->buffer_height = buffer_height;
zscan->num_channels = num_channels;
zscan->blocks_per_line = blocks_per_line;
zscan->blocks_total = blocks_total;
 
if(!init_shaders(zscan))
return false;
 
if(!init_state(zscan)) {
cleanup_shaders(zscan);
return false;
}
 
return true;
}
 
void
vl_zscan_cleanup(struct vl_zscan *zscan)
{
assert(zscan);
 
cleanup_shaders(zscan);
cleanup_state(zscan);
}
 
bool
vl_zscan_init_buffer(struct vl_zscan *zscan, struct vl_zscan_buffer *buffer,
struct pipe_sampler_view *src, struct pipe_surface *dst)
{
struct pipe_resource res_tmpl, *res;
struct pipe_sampler_view sv_tmpl;
 
assert(zscan && buffer);
 
memset(buffer, 0, sizeof(struct vl_zscan_buffer));
 
pipe_sampler_view_reference(&buffer->src, src);
 
buffer->viewport.scale[0] = dst->width;
buffer->viewport.scale[1] = dst->height;
buffer->viewport.scale[2] = 1;
buffer->viewport.scale[3] = 1;
buffer->viewport.translate[0] = 0;
buffer->viewport.translate[1] = 0;
buffer->viewport.translate[2] = 0;
buffer->viewport.translate[3] = 0;
 
buffer->fb_state.width = dst->width;
buffer->fb_state.height = dst->height;
buffer->fb_state.nr_cbufs = 1;
pipe_surface_reference(&buffer->fb_state.cbufs[0], dst);
 
memset(&res_tmpl, 0, sizeof(res_tmpl));
res_tmpl.target = PIPE_TEXTURE_3D;
res_tmpl.format = PIPE_FORMAT_R8_UNORM;
res_tmpl.width0 = VL_BLOCK_WIDTH * zscan->blocks_per_line;
res_tmpl.height0 = VL_BLOCK_HEIGHT;
res_tmpl.depth0 = 2;
res_tmpl.array_size = 1;
res_tmpl.usage = PIPE_USAGE_IMMUTABLE;
res_tmpl.bind = PIPE_BIND_SAMPLER_VIEW;
 
res = zscan->pipe->screen->resource_create(zscan->pipe->screen, &res_tmpl);
if (!res)
return false;
 
memset(&sv_tmpl, 0, sizeof(sv_tmpl));
u_sampler_view_default_template(&sv_tmpl, res, res->format);
sv_tmpl.swizzle_r = sv_tmpl.swizzle_g = sv_tmpl.swizzle_b = sv_tmpl.swizzle_a = TGSI_SWIZZLE_X;
buffer->quant = zscan->pipe->create_sampler_view(zscan->pipe, res, &sv_tmpl);
pipe_resource_reference(&res, NULL);
if (!buffer->quant)
return false;
 
return true;
}
 
void
vl_zscan_cleanup_buffer(struct vl_zscan_buffer *buffer)
{
assert(buffer);
 
pipe_sampler_view_reference(&buffer->src, NULL);
pipe_sampler_view_reference(&buffer->layout, NULL);
pipe_sampler_view_reference(&buffer->quant, NULL);
pipe_surface_reference(&buffer->fb_state.cbufs[0], NULL);
}
 
void
vl_zscan_set_layout(struct vl_zscan_buffer *buffer, struct pipe_sampler_view *layout)
{
assert(buffer);
assert(layout);
 
pipe_sampler_view_reference(&buffer->layout, layout);
}
 
void
vl_zscan_upload_quant(struct vl_zscan *zscan, struct vl_zscan_buffer *buffer,
const uint8_t matrix[64], bool intra)
{
struct pipe_context *pipe;
struct pipe_transfer *buf_transfer;
unsigned x, y, i, pitch;
uint8_t *data;
 
struct pipe_box rect =
{
0, 0, intra ? 1 : 0,
VL_BLOCK_WIDTH,
VL_BLOCK_HEIGHT,
1
};
 
assert(buffer);
assert(matrix);
 
pipe = zscan->pipe;
 
rect.width *= zscan->blocks_per_line;
 
data = pipe->transfer_map(pipe, buffer->quant->texture,
0, PIPE_TRANSFER_WRITE |
PIPE_TRANSFER_DISCARD_RANGE,
&rect, &buf_transfer);
if (!data)
return;
 
pitch = buf_transfer->stride;
 
for (i = 0; i < zscan->blocks_per_line; ++i)
for (y = 0; y < VL_BLOCK_HEIGHT; ++y)
for (x = 0; x < VL_BLOCK_WIDTH; ++x)
data[i * VL_BLOCK_WIDTH + y * pitch + x] = matrix[x + y * VL_BLOCK_WIDTH];
 
pipe->transfer_unmap(pipe, buf_transfer);
}
 
void
vl_zscan_render(struct vl_zscan *zscan, struct vl_zscan_buffer *buffer, unsigned num_instances)
{
assert(buffer);
 
zscan->pipe->bind_rasterizer_state(zscan->pipe, zscan->rs_state);
zscan->pipe->bind_blend_state(zscan->pipe, zscan->blend);
zscan->pipe->bind_fragment_sampler_states(zscan->pipe, 3, zscan->samplers);
zscan->pipe->set_framebuffer_state(zscan->pipe, &buffer->fb_state);
zscan->pipe->set_viewport_states(zscan->pipe, 0, 1, &buffer->viewport);
zscan->pipe->set_fragment_sampler_views(zscan->pipe, 3, &buffer->src);
zscan->pipe->bind_vs_state(zscan->pipe, zscan->vs);
zscan->pipe->bind_fs_state(zscan->pipe, zscan->fs);
util_draw_arrays_instanced(zscan->pipe, PIPE_PRIM_QUADS, 0, 4, 0, num_instances);
}
/drivers/video/Gallium/auxiliary/vl/vl_zscan.h
0,0 → 1,100
/**************************************************************************
*
* Copyright 2011 Christian König
* 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.
*
**************************************************************************/
 
#ifndef vl_zscan_h
#define vl_zscan_h
 
#include "pipe/p_compiler.h"
#include "pipe/p_state.h"
 
/*
* shader based zscan and quantification
* expect usage of vl_vertex_buffers as a todo list
*/
struct vl_zscan
{
struct pipe_context *pipe;
 
unsigned buffer_width;
unsigned buffer_height;
 
unsigned num_channels;
 
unsigned blocks_per_line;
unsigned blocks_total;
 
void *rs_state;
void *blend;
 
void *samplers[3];
 
void *vs, *fs;
};
 
struct vl_zscan_buffer
{
struct pipe_viewport_state viewport;
struct pipe_framebuffer_state fb_state;
 
struct pipe_sampler_view *src, *layout, *quant;
struct pipe_surface *dst;
};
 
extern const int vl_zscan_linear[];
extern const int vl_zscan_normal[];
extern const int vl_zscan_alternate[];
 
struct pipe_sampler_view *
vl_zscan_layout(struct pipe_context *pipe, const int layout[64], unsigned blocks_per_line);
 
bool
vl_zscan_init(struct vl_zscan *zscan, struct pipe_context *pipe,
unsigned buffer_width, unsigned buffer_height,
unsigned blocks_per_line, unsigned blocks_total,
unsigned num_channels);
 
void
vl_zscan_cleanup(struct vl_zscan *zscan);
 
bool
vl_zscan_init_buffer(struct vl_zscan *zscan, struct vl_zscan_buffer *buffer,
struct pipe_sampler_view *src, struct pipe_surface *dst);
 
void
vl_zscan_cleanup_buffer(struct vl_zscan_buffer *buffer);
 
void
vl_zscan_set_layout(struct vl_zscan_buffer *buffer, struct pipe_sampler_view *layout);
 
void
vl_zscan_upload_quant(struct vl_zscan *zscan, struct vl_zscan_buffer *buffer,
const uint8_t matrix[64], bool intra);
 
void
vl_zscan_render(struct vl_zscan *zscan, struct vl_zscan_buffer *buffer, unsigned num_instances);
 
#endif
/drivers/video/Gallium/drivers/softpipe/sp_clear.c
0,0 → 1,90
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
* Copyright 2009 VMware, Inc. 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.
*
**************************************************************************/
 
/* Author:
* Brian Paul
* Michel Dänzer
*/
 
 
#include "pipe/p_defines.h"
#include "util/u_pack_color.h"
#include "util/u_surface.h"
#include "sp_clear.h"
#include "sp_context.h"
#include "sp_query.h"
#include "sp_tile_cache.h"
 
 
/**
* Clear the given buffers to the specified values.
* No masking, no scissor (clear entire buffer).
*/
void
softpipe_clear(struct pipe_context *pipe, unsigned buffers,
const union pipe_color_union *color,
double depth, unsigned stencil)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
struct pipe_surface *zsbuf = softpipe->framebuffer.zsbuf;
unsigned zs_buffers = buffers & PIPE_CLEAR_DEPTHSTENCIL;
uint64_t cv;
uint i;
 
if (softpipe->no_rast)
return;
 
if (!softpipe_check_render_cond(softpipe))
return;
 
#if 0
softpipe_update_derived(softpipe, PIPE_PRIM_TRIANGLES); /* not needed?? */
#endif
 
if (buffers & PIPE_CLEAR_COLOR) {
for (i = 0; i < softpipe->framebuffer.nr_cbufs; i++) {
sp_tile_cache_clear(softpipe->cbuf_cache[i], color, 0);
}
}
 
if (zs_buffers &&
util_format_is_depth_and_stencil(zsbuf->texture->format) &&
zs_buffers != PIPE_CLEAR_DEPTHSTENCIL) {
/* Clearing only depth or stencil in a combined depth-stencil buffer. */
util_clear_depth_stencil(pipe, zsbuf, zs_buffers, depth, stencil,
0, 0, zsbuf->width, zsbuf->height);
}
else if (zs_buffers) {
static const union pipe_color_union zero;
 
cv = util_pack64_z_stencil(zsbuf->format, depth, stencil);
sp_tile_cache_clear(softpipe->zsbuf_cache, &zero, cv);
}
 
softpipe->dirty_render_cache = TRUE;
}
/drivers/video/Gallium/drivers/softpipe/sp_clear.h
0,0 → 1,43
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/* Author:
* Brian Paul
*/
 
#ifndef SP_CLEAR_H
#define SP_CLEAR_H
 
struct pipe_context;
 
extern void
softpipe_clear(struct pipe_context *pipe, unsigned buffers,
const union pipe_color_union *color,
double depth, unsigned stencil);
 
 
#endif /* SP_CLEAR_H */
/drivers/video/Gallium/drivers/softpipe/sp_context.c
0,0 → 1,325
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
* Copyright 2008 VMware, Inc. 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.
*
**************************************************************************/
 
/* Author:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
#include "draw/draw_context.h"
#include "draw/draw_vbuf.h"
#include "pipe/p_defines.h"
#include "util/u_math.h"
#include "util/u_memory.h"
#include "util/u_pstipple.h"
#include "util/u_inlines.h"
#include "tgsi/tgsi_exec.h"
#include "vl/vl_decoder.h"
#include "vl/vl_video_buffer.h"
#include "sp_clear.h"
#include "sp_context.h"
#include "sp_flush.h"
#include "sp_prim_vbuf.h"
#include "sp_state.h"
#include "sp_surface.h"
#include "sp_tile_cache.h"
#include "sp_tex_tile_cache.h"
#include "sp_texture.h"
#include "sp_query.h"
#include "sp_screen.h"
#include "sp_tex_sample.h"
 
 
static void
softpipe_destroy( struct pipe_context *pipe )
{
struct softpipe_context *softpipe = softpipe_context( pipe );
uint i, sh;
 
#if DO_PSTIPPLE_IN_HELPER_MODULE
if (softpipe->pstipple.sampler)
pipe->delete_sampler_state(pipe, softpipe->pstipple.sampler);
 
pipe_resource_reference(&softpipe->pstipple.texture, NULL);
pipe_sampler_view_reference(&softpipe->pstipple.sampler_view, NULL);
#endif
 
if (softpipe->blitter) {
util_blitter_destroy(softpipe->blitter);
}
 
if (softpipe->draw)
draw_destroy( softpipe->draw );
 
if (softpipe->quad.shade)
softpipe->quad.shade->destroy( softpipe->quad.shade );
 
if (softpipe->quad.depth_test)
softpipe->quad.depth_test->destroy( softpipe->quad.depth_test );
 
if (softpipe->quad.blend)
softpipe->quad.blend->destroy( softpipe->quad.blend );
 
if (softpipe->quad.pstipple)
softpipe->quad.pstipple->destroy( softpipe->quad.pstipple );
 
for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
sp_destroy_tile_cache(softpipe->cbuf_cache[i]);
pipe_surface_reference(&softpipe->framebuffer.cbufs[i], NULL);
}
 
sp_destroy_tile_cache(softpipe->zsbuf_cache);
pipe_surface_reference(&softpipe->framebuffer.zsbuf, NULL);
 
for (sh = 0; sh < Elements(softpipe->tex_cache); sh++) {
for (i = 0; i < Elements(softpipe->tex_cache[0]); i++) {
sp_destroy_tex_tile_cache(softpipe->tex_cache[sh][i]);
pipe_sampler_view_reference(&softpipe->sampler_views[sh][i], NULL);
}
}
 
for (sh = 0; sh < Elements(softpipe->constants); sh++) {
for (i = 0; i < Elements(softpipe->constants[0]); i++) {
if (softpipe->constants[sh][i]) {
pipe_resource_reference(&softpipe->constants[sh][i], NULL);
}
}
}
 
for (i = 0; i < softpipe->num_vertex_buffers; i++) {
pipe_resource_reference(&softpipe->vertex_buffer[i].buffer, NULL);
}
 
tgsi_exec_machine_destroy(softpipe->fs_machine);
 
for (i = 0; i < PIPE_SHADER_TYPES; i++) {
FREE(softpipe->tgsi.sampler[i]);
}
 
FREE( softpipe );
}
 
 
/**
* if (the texture is being used as a framebuffer surface)
* return SP_REFERENCED_FOR_WRITE
* else if (the texture is a bound texture source)
* return SP_REFERENCED_FOR_READ
* else
* return SP_UNREFERENCED
*/
unsigned int
softpipe_is_resource_referenced( struct pipe_context *pipe,
struct pipe_resource *texture,
unsigned level, int layer)
{
struct softpipe_context *softpipe = softpipe_context( pipe );
unsigned i, sh;
 
if (texture->target == PIPE_BUFFER)
return SP_UNREFERENCED;
 
/* check if any of the bound drawing surfaces are this texture */
if (softpipe->dirty_render_cache) {
for (i = 0; i < softpipe->framebuffer.nr_cbufs; i++) {
if (softpipe->framebuffer.cbufs[i] &&
softpipe->framebuffer.cbufs[i]->texture == texture) {
return SP_REFERENCED_FOR_WRITE;
}
}
if (softpipe->framebuffer.zsbuf &&
softpipe->framebuffer.zsbuf->texture == texture) {
return SP_REFERENCED_FOR_WRITE;
}
}
/* check if any of the tex_cache textures are this texture */
for (sh = 0; sh < Elements(softpipe->tex_cache); sh++) {
for (i = 0; i < Elements(softpipe->tex_cache[0]); i++) {
if (softpipe->tex_cache[sh][i] &&
softpipe->tex_cache[sh][i]->texture == texture)
return SP_REFERENCED_FOR_READ;
}
}
 
return SP_UNREFERENCED;
}
 
 
 
 
static void
softpipe_render_condition( struct pipe_context *pipe,
struct pipe_query *query,
boolean condition,
uint mode )
{
struct softpipe_context *softpipe = softpipe_context( pipe );
 
softpipe->render_cond_query = query;
softpipe->render_cond_mode = mode;
softpipe->render_cond_cond = condition;
}
 
 
 
struct pipe_context *
softpipe_create_context( struct pipe_screen *screen,
void *priv )
{
struct softpipe_screen *sp_screen = softpipe_screen(screen);
struct softpipe_context *softpipe = CALLOC_STRUCT(softpipe_context);
uint i, sh;
 
util_init_math();
 
for (i = 0; i < PIPE_SHADER_TYPES; i++) {
softpipe->tgsi.sampler[i] = sp_create_tgsi_sampler();
}
 
softpipe->dump_fs = debug_get_bool_option( "SOFTPIPE_DUMP_FS", FALSE );
softpipe->dump_gs = debug_get_bool_option( "SOFTPIPE_DUMP_GS", FALSE );
 
softpipe->pipe.screen = screen;
softpipe->pipe.destroy = softpipe_destroy;
softpipe->pipe.priv = priv;
 
/* state setters */
softpipe_init_blend_funcs(&softpipe->pipe);
softpipe_init_clip_funcs(&softpipe->pipe);
softpipe_init_query_funcs( softpipe );
softpipe_init_rasterizer_funcs(&softpipe->pipe);
softpipe_init_sampler_funcs(&softpipe->pipe);
softpipe_init_shader_funcs(&softpipe->pipe);
softpipe_init_streamout_funcs(&softpipe->pipe);
softpipe_init_texture_funcs( &softpipe->pipe );
softpipe_init_vertex_funcs(&softpipe->pipe);
 
softpipe->pipe.set_framebuffer_state = softpipe_set_framebuffer_state;
 
softpipe->pipe.draw_vbo = softpipe_draw_vbo;
 
softpipe->pipe.clear = softpipe_clear;
softpipe->pipe.flush = softpipe_flush_wrapped;
 
softpipe->pipe.render_condition = softpipe_render_condition;
softpipe->pipe.create_video_decoder = vl_create_decoder;
softpipe->pipe.create_video_buffer = vl_video_buffer_create;
 
/*
* Alloc caches for accessing drawing surfaces and textures.
* Must be before quad stage setup!
*/
for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++)
softpipe->cbuf_cache[i] = sp_create_tile_cache( &softpipe->pipe );
softpipe->zsbuf_cache = sp_create_tile_cache( &softpipe->pipe );
 
/* Allocate texture caches */
for (sh = 0; sh < Elements(softpipe->tex_cache); sh++) {
for (i = 0; i < Elements(softpipe->tex_cache[0]); i++) {
softpipe->tex_cache[sh][i] = sp_create_tex_tile_cache(&softpipe->pipe);
if (!softpipe->tex_cache[sh][i])
goto fail;
}
}
 
softpipe->fs_machine = tgsi_exec_machine_create();
 
/* setup quad rendering stages */
softpipe->quad.shade = sp_quad_shade_stage(softpipe);
softpipe->quad.depth_test = sp_quad_depth_test_stage(softpipe);
softpipe->quad.blend = sp_quad_blend_stage(softpipe);
softpipe->quad.pstipple = sp_quad_polygon_stipple_stage(softpipe);
 
 
/*
* Create drawing context and plug our rendering stage into it.
*/
if (sp_screen->use_llvm)
softpipe->draw = draw_create(&softpipe->pipe);
else
softpipe->draw = draw_create_no_llvm(&softpipe->pipe);
if (!softpipe->draw)
goto fail;
 
draw_texture_sampler(softpipe->draw,
PIPE_SHADER_VERTEX,
(struct tgsi_sampler *)
softpipe->tgsi.sampler[PIPE_SHADER_VERTEX]);
 
draw_texture_sampler(softpipe->draw,
PIPE_SHADER_GEOMETRY,
(struct tgsi_sampler *)
softpipe->tgsi.sampler[PIPE_SHADER_GEOMETRY]);
 
if (debug_get_bool_option( "SOFTPIPE_NO_RAST", FALSE ))
softpipe->no_rast = TRUE;
 
softpipe->vbuf_backend = sp_create_vbuf_backend(softpipe);
if (!softpipe->vbuf_backend)
goto fail;
 
softpipe->vbuf = draw_vbuf_stage(softpipe->draw, softpipe->vbuf_backend);
if (!softpipe->vbuf)
goto fail;
 
draw_set_rasterize_stage(softpipe->draw, softpipe->vbuf);
draw_set_render(softpipe->draw, softpipe->vbuf_backend);
 
softpipe->blitter = util_blitter_create(&softpipe->pipe);
if (!softpipe->blitter) {
goto fail;
}
 
/* must be done before installing Draw stages */
util_blitter_cache_all_shaders(softpipe->blitter);
 
/* plug in AA line/point stages */
draw_install_aaline_stage(softpipe->draw, &softpipe->pipe);
draw_install_aapoint_stage(softpipe->draw, &softpipe->pipe);
 
/* Do polygon stipple w/ texture map + frag prog? */
#if DO_PSTIPPLE_IN_DRAW_MODULE
draw_install_pstipple_stage(softpipe->draw, &softpipe->pipe);
#endif
 
draw_wide_point_sprites(softpipe->draw, TRUE);
 
sp_init_surface_functions(softpipe);
 
#if DO_PSTIPPLE_IN_HELPER_MODULE
/* create the polgon stipple sampler */
softpipe->pstipple.sampler = util_pstipple_create_sampler(&softpipe->pipe);
#endif
 
return &softpipe->pipe;
 
fail:
softpipe_destroy(&softpipe->pipe);
return NULL;
}
/drivers/video/Gallium/drivers/softpipe/sp_context.h
0,0 → 1,227
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/* Authors: Keith Whitwell <keith@tungstengraphics.com>
*/
 
#ifndef SP_CONTEXT_H
#define SP_CONTEXT_H
 
#include "pipe/p_context.h"
#include "util/u_blitter.h"
 
#include "draw/draw_vertex.h"
 
#include "sp_quad_pipe.h"
 
 
/** Do polygon stipple in the draw module? */
#define DO_PSTIPPLE_IN_DRAW_MODULE 0
 
/** Do polygon stipple with the util module? */
#define DO_PSTIPPLE_IN_HELPER_MODULE 1
 
 
struct softpipe_vbuf_render;
struct draw_context;
struct draw_stage;
struct softpipe_tile_cache;
struct softpipe_tex_tile_cache;
struct sp_fragment_shader;
struct sp_vertex_shader;
struct sp_velems_state;
struct sp_so_state;
 
struct softpipe_context {
struct pipe_context pipe; /**< base class */
 
/** Constant state objects */
struct pipe_blend_state *blend;
struct pipe_sampler_state *samplers[PIPE_SHADER_TYPES][PIPE_MAX_SAMPLERS];
struct pipe_depth_stencil_alpha_state *depth_stencil;
struct pipe_rasterizer_state *rasterizer;
struct sp_fragment_shader *fs;
struct sp_fragment_shader_variant *fs_variant;
struct sp_vertex_shader *vs;
struct sp_geometry_shader *gs;
struct sp_velems_state *velems;
struct sp_so_state *so;
 
/** Other rendering state */
struct pipe_blend_color blend_color;
struct pipe_blend_color blend_color_clamped;
struct pipe_stencil_ref stencil_ref;
struct pipe_clip_state clip;
struct pipe_resource *constants[PIPE_SHADER_TYPES][PIPE_MAX_CONSTANT_BUFFERS];
struct pipe_framebuffer_state framebuffer;
struct pipe_poly_stipple poly_stipple;
struct pipe_scissor_state scissor;
struct pipe_sampler_view *sampler_views[PIPE_SHADER_TYPES][PIPE_MAX_SHADER_SAMPLER_VIEWS];
 
struct pipe_viewport_state viewport;
struct pipe_vertex_buffer vertex_buffer[PIPE_MAX_ATTRIBS];
struct pipe_index_buffer index_buffer;
 
struct draw_so_target *so_targets[PIPE_MAX_SO_BUFFERS];
unsigned num_so_targets;
struct pipe_query_data_so_statistics so_stats;
unsigned num_primitives_generated;
 
struct pipe_query_data_pipeline_statistics pipeline_statistics;
unsigned active_statistics_queries;
 
unsigned num_samplers[PIPE_SHADER_TYPES];
unsigned num_sampler_views[PIPE_SHADER_TYPES];
 
unsigned num_vertex_buffers;
 
unsigned dirty; /**< Mask of SP_NEW_x flags */
 
/* Counter for occlusion queries. Note this supports overlapping
* queries.
*/
uint64_t occlusion_count;
unsigned active_query_count;
 
/** Mapped vertex buffers */
ubyte *mapped_vbuffer[PIPE_MAX_ATTRIBS];
 
/** Mapped constant buffers */
const void *mapped_constants[PIPE_SHADER_TYPES][PIPE_MAX_CONSTANT_BUFFERS];
unsigned const_buffer_size[PIPE_SHADER_TYPES][PIPE_MAX_CONSTANT_BUFFERS];
 
/** Vertex format */
struct vertex_info vertex_info;
struct vertex_info vertex_info_vbuf;
 
/** Which vertex shader output slot contains point size */
int psize_slot;
 
/** The reduced version of the primitive supplied by the state tracker */
unsigned reduced_api_prim;
 
/** Derived information about which winding orders to cull */
unsigned cull_mode;
 
/**
* The reduced primitive after unfilled triangles, wide-line decomposition,
* etc, are taken into account. This is the primitive type that's actually
* rasterized.
*/
unsigned reduced_prim;
 
/** Derived from scissor and surface bounds: */
struct pipe_scissor_state cliprect;
 
unsigned line_stipple_counter;
 
/** Conditional query object and mode */
struct pipe_query *render_cond_query;
uint render_cond_mode;
boolean render_cond_cond;
 
/** Polygon stipple items */
struct {
struct pipe_resource *texture;
struct pipe_sampler_state *sampler;
struct pipe_sampler_view *sampler_view;
} pstipple;
 
/** Software quad rendering pipeline */
struct {
struct quad_stage *shade;
struct quad_stage *depth_test;
struct quad_stage *blend;
struct quad_stage *pstipple;
struct quad_stage *first; /**< points to one of the above stages */
} quad;
 
/** TGSI exec things */
struct {
struct sp_tgsi_sampler *sampler[PIPE_SHADER_TYPES];
} tgsi;
 
struct tgsi_exec_machine *fs_machine;
 
/** The primitive drawing context */
struct draw_context *draw;
 
/** Draw module backend */
struct vbuf_render *vbuf_backend;
struct draw_stage *vbuf;
 
struct blitter_context *blitter;
 
boolean dirty_render_cache;
 
struct softpipe_tile_cache *cbuf_cache[PIPE_MAX_COLOR_BUFS];
struct softpipe_tile_cache *zsbuf_cache;
 
unsigned tex_timestamp;
 
/*
* Texture caches for vertex, fragment, geometry stages.
* Don't use PIPE_SHADER_TYPES here to avoid allocating unused memory
* for compute shaders.
* XXX wouldn't it make more sense for the tile cache to just be part
* of sp_sampler_view?
*/
struct softpipe_tex_tile_cache *tex_cache[PIPE_SHADER_GEOMETRY+1][PIPE_MAX_SHADER_SAMPLER_VIEWS];
 
unsigned dump_fs : 1;
unsigned dump_gs : 1;
unsigned no_rast : 1;
};
 
 
static INLINE struct softpipe_context *
softpipe_context( struct pipe_context *pipe )
{
return (struct softpipe_context *)pipe;
}
 
 
struct pipe_context *
softpipe_create_context( struct pipe_screen *, void *priv );
 
struct pipe_resource *
softpipe_user_buffer_create(struct pipe_screen *screen,
void *ptr,
unsigned bytes,
unsigned bind_flags);
 
#define SP_UNREFERENCED 0
#define SP_REFERENCED_FOR_READ (1 << 0)
#define SP_REFERENCED_FOR_WRITE (1 << 1)
 
unsigned int
softpipe_is_resource_referenced( struct pipe_context *pipe,
struct pipe_resource *texture,
unsigned level, int layer);
 
#endif /* SP_CONTEXT_H */
/drivers/video/Gallium/drivers/softpipe/sp_draw_arrays.c
0,0 → 1,149
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/* Author:
* Brian Paul
* Keith Whitwell
*/
 
 
#include "pipe/p_defines.h"
#include "pipe/p_context.h"
#include "util/u_inlines.h"
#include "util/u_prim.h"
 
#include "sp_context.h"
#include "sp_query.h"
#include "sp_state.h"
#include "sp_texture.h"
 
#include "draw/draw_context.h"
 
/**
* This function handles drawing indexed and non-indexed prims,
* instanced and non-instanced drawing, with or without min/max element
* indexes.
* All the other drawing functions are expressed in terms of this
* function.
*
* For non-indexed prims, indexBuffer should be NULL.
* For non-instanced drawing, instanceCount should be 1.
* When the min/max element indexes aren't known, minIndex should be 0
* and maxIndex should be ~0.
*/
void
softpipe_draw_vbo(struct pipe_context *pipe,
const struct pipe_draw_info *info)
{
struct softpipe_context *sp = softpipe_context(pipe);
struct draw_context *draw = sp->draw;
const void *mapped_indices = NULL;
unsigned i;
 
if (!softpipe_check_render_cond(sp))
return;
 
sp->reduced_api_prim = u_reduced_prim(info->mode);
 
if (sp->dirty) {
softpipe_update_derived(sp, sp->reduced_api_prim);
}
 
/* Map vertex buffers */
for (i = 0; i < sp->num_vertex_buffers; i++) {
const void *buf = sp->vertex_buffer[i].user_buffer;
size_t size = ~0;
if (!buf) {
if (!sp->vertex_buffer[i].buffer) {
continue;
}
buf = softpipe_resource(sp->vertex_buffer[i].buffer)->data;
size = sp->vertex_buffer[i].buffer->width0;
}
draw_set_mapped_vertex_buffer(draw, i, buf, size);
}
 
/* Map index buffer, if present */
if (info->indexed) {
unsigned available_space = ~0;
mapped_indices = sp->index_buffer.user_buffer;
if (!mapped_indices) {
mapped_indices = softpipe_resource(sp->index_buffer.buffer)->data;
if (sp->index_buffer.buffer->width0 > sp->index_buffer.offset)
available_space =
(sp->index_buffer.buffer->width0 - sp->index_buffer.offset);
else
available_space = 0;
}
 
draw_set_indexes(draw,
(ubyte *) mapped_indices + sp->index_buffer.offset,
sp->index_buffer.index_size, available_space);
}
 
 
for (i = 0; i < sp->num_so_targets; i++) {
void *buf = softpipe_resource(sp->so_targets[i]->target.buffer)->data;
sp->so_targets[i]->mapping = buf;
}
 
draw_set_mapped_so_targets(draw, sp->num_so_targets,
sp->so_targets);
 
if (sp->gs && !sp->gs->shader.tokens) {
/* we have an empty geometry shader with stream output, so
attach the stream output info to the current vertex shader */
if (sp->vs) {
draw_vs_attach_so(sp->vs->draw_data, &sp->gs->shader.stream_output);
}
}
draw_collect_pipeline_statistics(draw,
sp->active_statistics_queries > 0);
 
/* draw! */
draw_vbo(draw, info);
 
/* unmap vertex/index buffers - will cause draw module to flush */
for (i = 0; i < sp->num_vertex_buffers; i++) {
draw_set_mapped_vertex_buffer(draw, i, NULL, 0);
}
if (mapped_indices) {
draw_set_indexes(draw, NULL, 0, 0);
}
 
draw_set_mapped_so_targets(draw, 0, NULL);
 
/*
* TODO: Flush only when a user vertex/index buffer is present
* (or even better, modify draw module to do this
* internally when this condition is seen?)
*/
draw_flush(draw);
 
/* Note: leave drawing surfaces mapped */
sp->dirty_render_cache = TRUE;
}
/drivers/video/Gallium/drivers/softpipe/sp_fence.c
0,0 → 1,68
/**************************************************************************
*
* Copyright 2010 VMware, Inc.
* 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 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
* THE COPYRIGHT HOLDERS, AUTHORS 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.
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
**************************************************************************/
 
 
#include "pipe/p_screen.h"
#include "util/u_debug.h"
#include "sp_fence.h"
 
 
static void
softpipe_fence_reference(struct pipe_screen *screen,
struct pipe_fence_handle **ptr,
struct pipe_fence_handle *fence)
{
*ptr = fence;
}
 
 
static boolean
softpipe_fence_signalled(struct pipe_screen *screen,
struct pipe_fence_handle *fence)
{
assert(fence);
return TRUE;
}
 
 
static boolean
softpipe_fence_finish(struct pipe_screen *screen,
struct pipe_fence_handle *fence,
uint64_t timeout)
{
assert(fence);
return TRUE;
}
 
 
void
softpipe_init_screen_fence_funcs(struct pipe_screen *screen)
{
screen->fence_reference = softpipe_fence_reference;
screen->fence_finish = softpipe_fence_finish;
screen->fence_signalled = softpipe_fence_signalled;
}
/drivers/video/Gallium/drivers/softpipe/sp_fence.h
0,0 → 1,40
/**************************************************************************
*
* Copyright 2010 VMware, Inc.
* 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 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
* THE COPYRIGHT HOLDERS, AUTHORS 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.
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
**************************************************************************/
 
 
#ifndef SP_FENCE_H_
#define SP_FENCE_H_
 
 
struct pipe_screen;
 
 
void
softpipe_init_screen_fence_funcs(struct pipe_screen *screen);
 
 
#endif /* SP_FENCE_H_ */
/drivers/video/Gallium/drivers/softpipe/sp_flush.c
0,0 → 1,169
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/* Author:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
 
#include "pipe/p_defines.h"
#include "pipe/p_screen.h"
#include "draw/draw_context.h"
#include "sp_flush.h"
#include "sp_context.h"
#include "sp_state.h"
#include "sp_tile_cache.h"
#include "sp_tex_tile_cache.h"
#include "util/u_memory.h"
#include "util/u_string.h"
 
 
void
softpipe_flush( struct pipe_context *pipe,
unsigned flags,
struct pipe_fence_handle **fence )
{
struct softpipe_context *softpipe = softpipe_context(pipe);
uint i;
 
draw_flush(softpipe->draw);
 
if (flags & SP_FLUSH_TEXTURE_CACHE) {
unsigned sh;
 
for (sh = 0; sh < Elements(softpipe->tex_cache); sh++) {
for (i = 0; i < softpipe->num_sampler_views[sh]; i++) {
sp_flush_tex_tile_cache(softpipe->tex_cache[sh][i]);
}
}
}
 
/* If this is a swapbuffers, just flush color buffers.
*
* The zbuffer changes are not discarded, but held in the cache
* in the hope that a later clear will wipe them out.
*/
for (i = 0; i < softpipe->framebuffer.nr_cbufs; i++)
if (softpipe->cbuf_cache[i])
sp_flush_tile_cache(softpipe->cbuf_cache[i]);
 
if (softpipe->zsbuf_cache)
sp_flush_tile_cache(softpipe->zsbuf_cache);
 
softpipe->dirty_render_cache = FALSE;
 
/* Enable to dump BMPs of the color/depth buffers each frame */
#if 0
if (flags & PIPE_FLUSH_END_OF_FRAME) {
static unsigned frame_no = 1;
static char filename[256];
util_snprintf(filename, sizeof(filename), "cbuf_%u.bmp", frame_no);
debug_dump_surface_bmp(pipe, filename, softpipe->framebuffer.cbufs[0]);
util_snprintf(filename, sizeof(filename), "zsbuf_%u.bmp", frame_no);
debug_dump_surface_bmp(pipe, filename, softpipe->framebuffer.zsbuf);
++frame_no;
}
#endif
 
if (fence)
*fence = (void*)(intptr_t)1;
}
 
void
softpipe_flush_wrapped(struct pipe_context *pipe,
struct pipe_fence_handle **fence,
unsigned flags)
{
softpipe_flush(pipe, SP_FLUSH_TEXTURE_CACHE, fence);
}
 
 
/**
* Flush context if necessary.
*
* Returns FALSE if it would have block, but do_not_block was set, TRUE
* otherwise.
*
* TODO: move this logic to an auxiliary library?
*/
boolean
softpipe_flush_resource(struct pipe_context *pipe,
struct pipe_resource *texture,
unsigned level,
int layer,
unsigned flush_flags,
boolean read_only,
boolean cpu_access,
boolean do_not_block)
{
unsigned referenced;
 
referenced = softpipe_is_resource_referenced(pipe, texture, level, layer);
 
if ((referenced & SP_REFERENCED_FOR_WRITE) ||
((referenced & SP_REFERENCED_FOR_READ) && !read_only)) {
 
/*
* TODO: The semantics of these flush flags are too obtuse. They should
* disappear and the pipe driver should just ensure that all visible
* side-effects happen when they need to happen.
*/
if (referenced & SP_REFERENCED_FOR_READ)
flush_flags |= SP_FLUSH_TEXTURE_CACHE;
 
if (cpu_access) {
/*
* Flush and wait.
*/
 
struct pipe_fence_handle *fence = NULL;
 
if (do_not_block)
return FALSE;
 
softpipe_flush(pipe, flush_flags, &fence);
 
if (fence) {
/*
* This is for illustrative purposes only, as softpipe does not
* have fences.
*/
pipe->screen->fence_finish(pipe->screen, fence,
PIPE_TIMEOUT_INFINITE);
pipe->screen->fence_reference(pipe->screen, &fence, NULL);
}
} else {
/*
* Just flush.
*/
 
softpipe_flush(pipe, flush_flags, NULL);
}
}
 
return TRUE;
}
/drivers/video/Gallium/drivers/softpipe/sp_flush.h
0,0 → 1,58
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
#ifndef SP_FLUSH_H
#define SP_FLUSH_H
 
#include "pipe/p_compiler.h"
 
struct pipe_context;
struct pipe_fence_handle;
 
#define SP_FLUSH_TEXTURE_CACHE 0x2
 
void
softpipe_flush(struct pipe_context *pipe,
unsigned flags,
struct pipe_fence_handle **fence);
 
void
softpipe_flush_wrapped(struct pipe_context *pipe,
struct pipe_fence_handle **fence,
unsigned flags);
 
boolean
softpipe_flush_resource(struct pipe_context *pipe,
struct pipe_resource *texture,
unsigned level,
int layer,
unsigned flush_flags,
boolean read_only,
boolean cpu_access,
boolean do_not_block);
 
#endif
/drivers/video/Gallium/drivers/softpipe/sp_fs.h
0,0 → 1,48
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/* Authors: Keith Whitwell <keith@tungstengraphics.com>
*/
 
#ifndef SP_FS_H
#define SP_FS_H
 
 
struct sp_fragment_shader_variant *
softpipe_create_fs_variant_exec(struct softpipe_context *softpipe,
const struct pipe_shader_state *templ);
 
 
struct tgsi_interp_coef;
struct tgsi_exec_vector;
 
void sp_setup_pos_vector(const struct tgsi_interp_coef *coef,
float x, float y,
struct tgsi_exec_vector *quadpos);
 
 
#endif
/drivers/video/Gallium/drivers/softpipe/sp_fs_exec.c
0,0 → 1,206
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/**
* Execute fragment shader using the TGSI interpreter.
*/
 
#include "sp_context.h"
#include "sp_state.h"
#include "sp_fs.h"
#include "sp_quad.h"
 
#include "pipe/p_state.h"
#include "pipe/p_defines.h"
#include "util/u_memory.h"
#include "tgsi/tgsi_exec.h"
#include "tgsi/tgsi_parse.h"
 
 
/**
* Subclass of sp_fragment_shader_variant
*/
struct sp_exec_fragment_shader
{
struct sp_fragment_shader_variant base;
/* No other members for now */
};
 
 
/** cast wrapper */
static INLINE struct sp_exec_fragment_shader *
sp_exec_fragment_shader(const struct sp_fragment_shader_variant *var)
{
return (struct sp_exec_fragment_shader *) var;
}
 
 
static void
exec_prepare( const struct sp_fragment_shader_variant *var,
struct tgsi_exec_machine *machine,
struct tgsi_sampler *sampler )
{
/*
* Bind tokens/shader to the interpreter's machine state.
*/
tgsi_exec_machine_bind_shader(machine,
var->tokens,
sampler);
}
 
 
 
/**
* Compute quad X,Y,Z,W for the four fragments in a quad.
*
* This should really be part of the compiled shader.
*/
static void
setup_pos_vector(const struct tgsi_interp_coef *coef,
float x, float y,
struct tgsi_exec_vector *quadpos)
{
uint chan;
/* do X */
quadpos->xyzw[0].f[0] = x;
quadpos->xyzw[0].f[1] = x + 1;
quadpos->xyzw[0].f[2] = x;
quadpos->xyzw[0].f[3] = x + 1;
 
/* do Y */
quadpos->xyzw[1].f[0] = y;
quadpos->xyzw[1].f[1] = y;
quadpos->xyzw[1].f[2] = y + 1;
quadpos->xyzw[1].f[3] = y + 1;
 
/* do Z and W for all fragments in the quad */
for (chan = 2; chan < 4; chan++) {
const float dadx = coef->dadx[chan];
const float dady = coef->dady[chan];
const float a0 = coef->a0[chan] + dadx * x + dady * y;
quadpos->xyzw[chan].f[0] = a0;
quadpos->xyzw[chan].f[1] = a0 + dadx;
quadpos->xyzw[chan].f[2] = a0 + dady;
quadpos->xyzw[chan].f[3] = a0 + dadx + dady;
}
}
 
 
/* TODO: hide the machine struct in here somewhere, remove from this
* interface:
*/
static unsigned
exec_run( const struct sp_fragment_shader_variant *var,
struct tgsi_exec_machine *machine,
struct quad_header *quad )
{
/* Compute X, Y, Z, W vals for this quad */
setup_pos_vector(quad->posCoef,
(float)quad->input.x0, (float)quad->input.y0,
&machine->QuadPos);
 
/* convert 0 to 1.0 and 1 to -1.0 */
machine->Face = (float) (quad->input.facing * -2 + 1);
 
quad->inout.mask &= tgsi_exec_machine_run( machine );
if (quad->inout.mask == 0)
return FALSE;
 
/* store outputs */
{
const ubyte *sem_name = var->info.output_semantic_name;
const ubyte *sem_index = var->info.output_semantic_index;
const uint n = var->info.num_outputs;
uint i;
for (i = 0; i < n; i++) {
switch (sem_name[i]) {
case TGSI_SEMANTIC_COLOR:
{
uint cbuf = sem_index[i];
 
assert(sizeof(quad->output.color[cbuf]) ==
sizeof(machine->Outputs[i]));
 
/* copy float[4][4] result */
memcpy(quad->output.color[cbuf],
&machine->Outputs[i],
sizeof(quad->output.color[0]) );
}
break;
case TGSI_SEMANTIC_POSITION:
{
uint j;
 
for (j = 0; j < 4; j++)
quad->output.depth[j] = machine->Outputs[i].xyzw[2].f[j];
}
break;
case TGSI_SEMANTIC_STENCIL:
{
uint j;
 
for (j = 0; j < 4; j++)
quad->output.stencil[j] = (unsigned)machine->Outputs[i].xyzw[1].f[j];
}
break;
}
}
}
 
return TRUE;
}
 
 
static void
exec_delete(struct sp_fragment_shader_variant *var,
struct tgsi_exec_machine *machine)
{
if (machine->Tokens == var->tokens) {
tgsi_exec_machine_bind_shader(machine, NULL, NULL);
}
 
FREE( (void *) var->tokens );
FREE(var);
}
 
 
struct sp_fragment_shader_variant *
softpipe_create_fs_variant_exec(struct softpipe_context *softpipe,
const struct pipe_shader_state *templ)
{
struct sp_exec_fragment_shader *shader;
 
shader = CALLOC_STRUCT(sp_exec_fragment_shader);
if (!shader)
return NULL;
 
shader->base.prepare = exec_prepare;
shader->base.run = exec_run;
shader->base.delete = exec_delete;
 
return &shader->base;
}
/drivers/video/Gallium/drivers/softpipe/sp_limits.h
0,0 → 1,43
/**************************************************************************
*
* Copyright 2010 VMware, Inc.
* 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 THE AUTHORS 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.
*
**************************************************************************/
 
#ifndef SP_LIMITS_H
#define SP_LIMITS_H
 
 
#define SP_MAX_TEXTURE_SIZE (1 * 1024 * 1024 * 1024ULL) /* 1GB for now */
#define SP_MAX_TEXTURE_2D_LEVELS 15 /* 16K x 16K */
#define SP_MAX_TEXTURE_3D_LEVELS 9 /* 256 x 256 x 256 */
#define SP_MAX_TEXTURE_CUBE_LEVELS 13 /* 4K x 4K */
 
 
/** Max surface size */
#define MAX_WIDTH (1 << (SP_MAX_TEXTURE_2D_LEVELS - 1))
#define MAX_HEIGHT (1 << (SP_MAX_TEXTURE_2D_LEVELS - 1))
 
 
#endif /* SP_LIMITS_H */
/drivers/video/Gallium/drivers/softpipe/sp_prim_vbuf.c
0,0 → 1,667
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/**
* Interface between 'draw' module's output and the softpipe rasterizer/setup
* code. When the 'draw' module has finished filling a vertex buffer, the
* draw_arrays() functions below will be called. Loop over the vertices and
* call the point/line/tri setup functions.
*
* Authors
* Brian Paul
*/
 
 
#include "sp_context.h"
#include "sp_setup.h"
#include "sp_state.h"
#include "sp_prim_vbuf.h"
#include "draw/draw_context.h"
#include "draw/draw_vbuf.h"
#include "util/u_memory.h"
#include "util/u_prim.h"
 
 
#define SP_MAX_VBUF_INDEXES 1024
#define SP_MAX_VBUF_SIZE 4096
 
typedef const float (*cptrf4)[4];
 
/**
* Subclass of vbuf_render.
*/
struct softpipe_vbuf_render
{
struct vbuf_render base;
struct softpipe_context *softpipe;
struct setup_context *setup;
 
uint prim;
uint vertex_size;
uint nr_vertices;
uint vertex_buffer_size;
void *vertex_buffer;
};
 
 
/** cast wrapper */
static struct softpipe_vbuf_render *
softpipe_vbuf_render(struct vbuf_render *vbr)
{
return (struct softpipe_vbuf_render *) vbr;
}
 
 
/** This tells the draw module about our desired vertex layout */
static const struct vertex_info *
sp_vbuf_get_vertex_info(struct vbuf_render *vbr)
{
struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
return softpipe_get_vbuf_vertex_info(cvbr->softpipe);
}
 
 
static boolean
sp_vbuf_allocate_vertices(struct vbuf_render *vbr,
ushort vertex_size, ushort nr_vertices)
{
struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
unsigned size = vertex_size * nr_vertices;
 
if (cvbr->vertex_buffer_size < size) {
align_free(cvbr->vertex_buffer);
cvbr->vertex_buffer = align_malloc(size, 16);
cvbr->vertex_buffer_size = size;
}
 
cvbr->vertex_size = vertex_size;
cvbr->nr_vertices = nr_vertices;
return cvbr->vertex_buffer != NULL;
}
 
 
static void
sp_vbuf_release_vertices(struct vbuf_render *vbr)
{
/* keep the old allocation for next time */
}
 
 
static void *
sp_vbuf_map_vertices(struct vbuf_render *vbr)
{
struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
return cvbr->vertex_buffer;
}
 
 
static void
sp_vbuf_unmap_vertices(struct vbuf_render *vbr,
ushort min_index,
ushort max_index )
{
struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
assert( cvbr->vertex_buffer_size >= (max_index+1) * cvbr->vertex_size );
(void) cvbr;
/* do nothing */
}
 
 
static void
sp_vbuf_set_primitive(struct vbuf_render *vbr, unsigned prim)
{
struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
struct setup_context *setup_ctx = cvbr->setup;
sp_setup_prepare( setup_ctx );
 
cvbr->softpipe->reduced_prim = u_reduced_prim(prim);
cvbr->prim = prim;
}
 
 
static INLINE cptrf4 get_vert( const void *vertex_buffer,
int index,
int stride )
{
return (cptrf4)((char *)vertex_buffer + index * stride);
}
 
 
/**
* draw elements / indexed primitives
*/
static void
sp_vbuf_draw_elements(struct vbuf_render *vbr, const ushort *indices, uint nr)
{
struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
struct softpipe_context *softpipe = cvbr->softpipe;
const unsigned stride = softpipe->vertex_info_vbuf.size * sizeof(float);
const void *vertex_buffer = cvbr->vertex_buffer;
struct setup_context *setup = cvbr->setup;
const boolean flatshade_first = softpipe->rasterizer->flatshade_first;
unsigned i;
 
switch (cvbr->prim) {
case PIPE_PRIM_POINTS:
for (i = 0; i < nr; i++) {
sp_setup_point( setup,
get_vert(vertex_buffer, indices[i-0], stride) );
}
break;
 
case PIPE_PRIM_LINES:
for (i = 1; i < nr; i += 2) {
sp_setup_line( setup,
get_vert(vertex_buffer, indices[i-1], stride),
get_vert(vertex_buffer, indices[i-0], stride) );
}
break;
 
case PIPE_PRIM_LINE_STRIP:
for (i = 1; i < nr; i ++) {
sp_setup_line( setup,
get_vert(vertex_buffer, indices[i-1], stride),
get_vert(vertex_buffer, indices[i-0], stride) );
}
break;
 
case PIPE_PRIM_LINE_LOOP:
for (i = 1; i < nr; i ++) {
sp_setup_line( setup,
get_vert(vertex_buffer, indices[i-1], stride),
get_vert(vertex_buffer, indices[i-0], stride) );
}
if (nr) {
sp_setup_line( setup,
get_vert(vertex_buffer, indices[nr-1], stride),
get_vert(vertex_buffer, indices[0], stride) );
}
break;
 
case PIPE_PRIM_TRIANGLES:
for (i = 2; i < nr; i += 3) {
sp_setup_tri( setup,
get_vert(vertex_buffer, indices[i-2], stride),
get_vert(vertex_buffer, indices[i-1], stride),
get_vert(vertex_buffer, indices[i-0], stride) );
}
break;
 
case PIPE_PRIM_TRIANGLE_STRIP:
if (flatshade_first) {
for (i = 2; i < nr; i += 1) {
/* emit first triangle vertex as first triangle vertex */
sp_setup_tri( setup,
get_vert(vertex_buffer, indices[i-2], stride),
get_vert(vertex_buffer, indices[i+(i&1)-1], stride),
get_vert(vertex_buffer, indices[i-(i&1)], stride) );
 
}
}
else {
for (i = 2; i < nr; i += 1) {
/* emit last triangle vertex as last triangle vertex */
sp_setup_tri( setup,
get_vert(vertex_buffer, indices[i+(i&1)-2], stride),
get_vert(vertex_buffer, indices[i-(i&1)-1], stride),
get_vert(vertex_buffer, indices[i-0], stride) );
}
}
break;
 
case PIPE_PRIM_TRIANGLE_FAN:
if (flatshade_first) {
for (i = 2; i < nr; i += 1) {
/* emit first non-spoke vertex as first vertex */
sp_setup_tri( setup,
get_vert(vertex_buffer, indices[i-1], stride),
get_vert(vertex_buffer, indices[i-0], stride),
get_vert(vertex_buffer, indices[0], stride) );
}
}
else {
for (i = 2; i < nr; i += 1) {
/* emit last non-spoke vertex as last vertex */
sp_setup_tri( setup,
get_vert(vertex_buffer, indices[0], stride),
get_vert(vertex_buffer, indices[i-1], stride),
get_vert(vertex_buffer, indices[i-0], stride) );
}
}
break;
 
case PIPE_PRIM_QUADS:
/* GL quads don't follow provoking vertex convention */
if (flatshade_first) {
/* emit last quad vertex as first triangle vertex */
for (i = 3; i < nr; i += 4) {
sp_setup_tri( setup,
get_vert(vertex_buffer, indices[i-0], stride),
get_vert(vertex_buffer, indices[i-3], stride),
get_vert(vertex_buffer, indices[i-2], stride) );
 
sp_setup_tri( setup,
get_vert(vertex_buffer, indices[i-0], stride),
get_vert(vertex_buffer, indices[i-2], stride),
get_vert(vertex_buffer, indices[i-1], stride) );
}
}
else {
/* emit last quad vertex as last triangle vertex */
for (i = 3; i < nr; i += 4) {
sp_setup_tri( setup,
get_vert(vertex_buffer, indices[i-3], stride),
get_vert(vertex_buffer, indices[i-2], stride),
get_vert(vertex_buffer, indices[i-0], stride) );
 
sp_setup_tri( setup,
get_vert(vertex_buffer, indices[i-2], stride),
get_vert(vertex_buffer, indices[i-1], stride),
get_vert(vertex_buffer, indices[i-0], stride) );
}
}
break;
 
case PIPE_PRIM_QUAD_STRIP:
/* GL quad strips don't follow provoking vertex convention */
if (flatshade_first) {
/* emit last quad vertex as first triangle vertex */
for (i = 3; i < nr; i += 2) {
sp_setup_tri( setup,
get_vert(vertex_buffer, indices[i-0], stride),
get_vert(vertex_buffer, indices[i-3], stride),
get_vert(vertex_buffer, indices[i-2], stride) );
sp_setup_tri( setup,
get_vert(vertex_buffer, indices[i-0], stride),
get_vert(vertex_buffer, indices[i-1], stride),
get_vert(vertex_buffer, indices[i-3], stride) );
}
}
else {
/* emit last quad vertex as last triangle vertex */
for (i = 3; i < nr; i += 2) {
sp_setup_tri( setup,
get_vert(vertex_buffer, indices[i-3], stride),
get_vert(vertex_buffer, indices[i-2], stride),
get_vert(vertex_buffer, indices[i-0], stride) );
sp_setup_tri( setup,
get_vert(vertex_buffer, indices[i-1], stride),
get_vert(vertex_buffer, indices[i-3], stride),
get_vert(vertex_buffer, indices[i-0], stride) );
}
}
break;
 
case PIPE_PRIM_POLYGON:
/* Almost same as tri fan but the _first_ vertex specifies the flat
* shading color.
*/
if (flatshade_first) {
/* emit first polygon vertex as first triangle vertex */
for (i = 2; i < nr; i += 1) {
sp_setup_tri( setup,
get_vert(vertex_buffer, indices[0], stride),
get_vert(vertex_buffer, indices[i-1], stride),
get_vert(vertex_buffer, indices[i-0], stride) );
}
}
else {
/* emit first polygon vertex as last triangle vertex */
for (i = 2; i < nr; i += 1) {
sp_setup_tri( setup,
get_vert(vertex_buffer, indices[i-1], stride),
get_vert(vertex_buffer, indices[i-0], stride),
get_vert(vertex_buffer, indices[0], stride) );
}
}
break;
 
default:
assert(0);
}
}
 
 
/**
* This function is hit when the draw module is working in pass-through mode.
* It's up to us to convert the vertex array into point/line/tri prims.
*/
static void
sp_vbuf_draw_arrays(struct vbuf_render *vbr, uint start, uint nr)
{
struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
struct softpipe_context *softpipe = cvbr->softpipe;
struct setup_context *setup = cvbr->setup;
const unsigned stride = softpipe->vertex_info_vbuf.size * sizeof(float);
const void *vertex_buffer =
(void *) get_vert(cvbr->vertex_buffer, start, stride);
const boolean flatshade_first = softpipe->rasterizer->flatshade_first;
unsigned i;
 
switch (cvbr->prim) {
case PIPE_PRIM_POINTS:
for (i = 0; i < nr; i++) {
sp_setup_point( setup,
get_vert(vertex_buffer, i-0, stride) );
}
break;
 
case PIPE_PRIM_LINES:
for (i = 1; i < nr; i += 2) {
sp_setup_line( setup,
get_vert(vertex_buffer, i-1, stride),
get_vert(vertex_buffer, i-0, stride) );
}
break;
 
case PIPE_PRIM_LINES_ADJACENCY:
for (i = 3; i < nr; i += 4) {
sp_setup_line( setup,
get_vert(vertex_buffer, i-2, stride),
get_vert(vertex_buffer, i-1, stride) );
}
break;
 
case PIPE_PRIM_LINE_STRIP:
for (i = 1; i < nr; i ++) {
sp_setup_line( setup,
get_vert(vertex_buffer, i-1, stride),
get_vert(vertex_buffer, i-0, stride) );
}
break;
 
case PIPE_PRIM_LINE_STRIP_ADJACENCY:
for (i = 3; i < nr; i++) {
sp_setup_line( setup,
get_vert(vertex_buffer, i-2, stride),
get_vert(vertex_buffer, i-1, stride) );
}
break;
 
case PIPE_PRIM_LINE_LOOP:
for (i = 1; i < nr; i ++) {
sp_setup_line( setup,
get_vert(vertex_buffer, i-1, stride),
get_vert(vertex_buffer, i-0, stride) );
}
if (nr) {
sp_setup_line( setup,
get_vert(vertex_buffer, nr-1, stride),
get_vert(vertex_buffer, 0, stride) );
}
break;
 
case PIPE_PRIM_TRIANGLES:
for (i = 2; i < nr; i += 3) {
sp_setup_tri( setup,
get_vert(vertex_buffer, i-2, stride),
get_vert(vertex_buffer, i-1, stride),
get_vert(vertex_buffer, i-0, stride) );
}
break;
 
case PIPE_PRIM_TRIANGLES_ADJACENCY:
for (i = 5; i < nr; i += 6) {
sp_setup_tri( setup,
get_vert(vertex_buffer, i-5, stride),
get_vert(vertex_buffer, i-3, stride),
get_vert(vertex_buffer, i-1, stride) );
}
break;
 
case PIPE_PRIM_TRIANGLE_STRIP:
if (flatshade_first) {
for (i = 2; i < nr; i++) {
/* emit first triangle vertex as first triangle vertex */
sp_setup_tri( setup,
get_vert(vertex_buffer, i-2, stride),
get_vert(vertex_buffer, i+(i&1)-1, stride),
get_vert(vertex_buffer, i-(i&1), stride) );
}
}
else {
for (i = 2; i < nr; i++) {
/* emit last triangle vertex as last triangle vertex */
sp_setup_tri( setup,
get_vert(vertex_buffer, i+(i&1)-2, stride),
get_vert(vertex_buffer, i-(i&1)-1, stride),
get_vert(vertex_buffer, i-0, stride) );
}
}
break;
 
case PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY:
if (flatshade_first) {
for (i = 5; i < nr; i += 2) {
/* emit first triangle vertex as first triangle vertex */
sp_setup_tri( setup,
get_vert(vertex_buffer, i-5, stride),
get_vert(vertex_buffer, i+(i&1)*2-3, stride),
get_vert(vertex_buffer, i-(i&1)*2-1, stride) );
}
}
else {
for (i = 5; i < nr; i += 2) {
/* emit last triangle vertex as last triangle vertex */
sp_setup_tri( setup,
get_vert(vertex_buffer, i+(i&1)*2-5, stride),
get_vert(vertex_buffer, i-(i&1)*2-3, stride),
get_vert(vertex_buffer, i-1, stride) );
}
}
break;
 
case PIPE_PRIM_TRIANGLE_FAN:
if (flatshade_first) {
for (i = 2; i < nr; i += 1) {
/* emit first non-spoke vertex as first vertex */
sp_setup_tri( setup,
get_vert(vertex_buffer, i-1, stride),
get_vert(vertex_buffer, i-0, stride),
get_vert(vertex_buffer, 0, stride) );
}
}
else {
for (i = 2; i < nr; i += 1) {
/* emit last non-spoke vertex as last vertex */
sp_setup_tri( setup,
get_vert(vertex_buffer, 0, stride),
get_vert(vertex_buffer, i-1, stride),
get_vert(vertex_buffer, i-0, stride) );
}
}
break;
 
case PIPE_PRIM_QUADS:
/* GL quads don't follow provoking vertex convention */
if (flatshade_first) {
/* emit last quad vertex as first triangle vertex */
for (i = 3; i < nr; i += 4) {
sp_setup_tri( setup,
get_vert(vertex_buffer, i-0, stride),
get_vert(vertex_buffer, i-3, stride),
get_vert(vertex_buffer, i-2, stride) );
sp_setup_tri( setup,
get_vert(vertex_buffer, i-0, stride),
get_vert(vertex_buffer, i-2, stride),
get_vert(vertex_buffer, i-1, stride) );
}
}
else {
/* emit last quad vertex as last triangle vertex */
for (i = 3; i < nr; i += 4) {
sp_setup_tri( setup,
get_vert(vertex_buffer, i-3, stride),
get_vert(vertex_buffer, i-2, stride),
get_vert(vertex_buffer, i-0, stride) );
sp_setup_tri( setup,
get_vert(vertex_buffer, i-2, stride),
get_vert(vertex_buffer, i-1, stride),
get_vert(vertex_buffer, i-0, stride) );
}
}
break;
 
case PIPE_PRIM_QUAD_STRIP:
/* GL quad strips don't follow provoking vertex convention */
if (flatshade_first) {
/* emit last quad vertex as first triangle vertex */
for (i = 3; i < nr; i += 2) {
sp_setup_tri( setup,
get_vert(vertex_buffer, i-0, stride),
get_vert(vertex_buffer, i-3, stride),
get_vert(vertex_buffer, i-2, stride) );
sp_setup_tri( setup,
get_vert(vertex_buffer, i-0, stride),
get_vert(vertex_buffer, i-1, stride),
get_vert(vertex_buffer, i-3, stride) );
}
}
else {
/* emit last quad vertex as last triangle vertex */
for (i = 3; i < nr; i += 2) {
sp_setup_tri( setup,
get_vert(vertex_buffer, i-3, stride),
get_vert(vertex_buffer, i-2, stride),
get_vert(vertex_buffer, i-0, stride) );
sp_setup_tri( setup,
get_vert(vertex_buffer, i-1, stride),
get_vert(vertex_buffer, i-3, stride),
get_vert(vertex_buffer, i-0, stride) );
}
}
break;
 
case PIPE_PRIM_POLYGON:
/* Almost same as tri fan but the _first_ vertex specifies the flat
* shading color.
*/
if (flatshade_first) {
/* emit first polygon vertex as first triangle vertex */
for (i = 2; i < nr; i += 1) {
sp_setup_tri( setup,
get_vert(vertex_buffer, 0, stride),
get_vert(vertex_buffer, i-1, stride),
get_vert(vertex_buffer, i-0, stride) );
}
}
else {
/* emit first polygon vertex as last triangle vertex */
for (i = 2; i < nr; i += 1) {
sp_setup_tri( setup,
get_vert(vertex_buffer, i-1, stride),
get_vert(vertex_buffer, i-0, stride),
get_vert(vertex_buffer, 0, stride) );
}
}
break;
 
default:
assert(0);
}
}
 
static void
sp_vbuf_so_info(struct vbuf_render *vbr, uint primitives, uint vertices,
uint prim_generated)
{
struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
struct softpipe_context *softpipe = cvbr->softpipe;
 
softpipe->so_stats.num_primitives_written += primitives;
softpipe->so_stats.primitives_storage_needed =
vertices * 4 /*sizeof(float|int32)*/ * 4 /*x,y,z,w*/;
softpipe->num_primitives_generated += prim_generated;
}
 
static void
sp_vbuf_pipeline_statistics(
struct vbuf_render *vbr,
const struct pipe_query_data_pipeline_statistics *stats)
{
struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
struct softpipe_context *softpipe = cvbr->softpipe;
 
softpipe->pipeline_statistics.ia_vertices +=
stats->ia_vertices;
softpipe->pipeline_statistics.ia_primitives +=
stats->ia_primitives;
softpipe->pipeline_statistics.vs_invocations +=
stats->vs_invocations;
softpipe->pipeline_statistics.gs_invocations +=
stats->gs_invocations;
softpipe->pipeline_statistics.gs_primitives +=
stats->gs_primitives;
softpipe->pipeline_statistics.c_invocations +=
stats->c_invocations;
}
 
 
static void
sp_vbuf_destroy(struct vbuf_render *vbr)
{
struct softpipe_vbuf_render *cvbr = softpipe_vbuf_render(vbr);
if (cvbr->vertex_buffer)
align_free(cvbr->vertex_buffer);
sp_setup_destroy_context(cvbr->setup);
FREE(cvbr);
}
 
 
/**
* Create the post-transform vertex handler for the given context.
*/
struct vbuf_render *
sp_create_vbuf_backend(struct softpipe_context *sp)
{
struct softpipe_vbuf_render *cvbr = CALLOC_STRUCT(softpipe_vbuf_render);
 
assert(sp->draw);
 
cvbr->base.max_indices = SP_MAX_VBUF_INDEXES;
cvbr->base.max_vertex_buffer_bytes = SP_MAX_VBUF_SIZE;
 
cvbr->base.get_vertex_info = sp_vbuf_get_vertex_info;
cvbr->base.allocate_vertices = sp_vbuf_allocate_vertices;
cvbr->base.map_vertices = sp_vbuf_map_vertices;
cvbr->base.unmap_vertices = sp_vbuf_unmap_vertices;
cvbr->base.set_primitive = sp_vbuf_set_primitive;
cvbr->base.draw_elements = sp_vbuf_draw_elements;
cvbr->base.draw_arrays = sp_vbuf_draw_arrays;
cvbr->base.release_vertices = sp_vbuf_release_vertices;
cvbr->base.set_stream_output_info = sp_vbuf_so_info;
cvbr->base.pipeline_statistics = sp_vbuf_pipeline_statistics;
cvbr->base.destroy = sp_vbuf_destroy;
 
cvbr->softpipe = sp;
 
cvbr->setup = sp_setup_create_context(cvbr->softpipe);
 
return &cvbr->base;
}
/drivers/video/Gallium/drivers/softpipe/sp_prim_vbuf.h
0,0 → 1,38
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
#ifndef SP_VBUF_H
#define SP_VBUF_H
 
 
struct softpipe_context;
 
extern struct vbuf_render *
sp_create_vbuf_backend(struct softpipe_context *softpipe);
 
 
#endif /* SP_VBUF_H */
/drivers/video/Gallium/drivers/softpipe/sp_public.h
0,0 → 1,10
#ifndef SP_PUBLIC_H
#define SP_PUBLIC_H
 
struct pipe_screen;
struct sw_winsys;
 
struct pipe_screen *
softpipe_create_screen(struct sw_winsys *winsys);
 
#endif
/drivers/video/Gallium/drivers/softpipe/sp_quad.h
0,0 → 1,107
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/* Authors: Keith Whitwell <keith@tungstengraphics.com>
*/
 
#ifndef SP_QUAD_H
#define SP_QUAD_H
 
#include "pipe/p_state.h"
#include "tgsi/tgsi_exec.h"
 
 
#define QUAD_PRIM_POINT 1
#define QUAD_PRIM_LINE 2
#define QUAD_PRIM_TRI 3
 
 
/* The rasterizer generates 2x2 quads of fragment and feeds them to
* the current fp_machine (see below).
* Remember that Y=0=top with Y increasing down the window.
*/
#define QUAD_TOP_LEFT 0
#define QUAD_TOP_RIGHT 1
#define QUAD_BOTTOM_LEFT 2
#define QUAD_BOTTOM_RIGHT 3
 
#define MASK_TOP_LEFT (1 << QUAD_TOP_LEFT)
#define MASK_TOP_RIGHT (1 << QUAD_TOP_RIGHT)
#define MASK_BOTTOM_LEFT (1 << QUAD_BOTTOM_LEFT)
#define MASK_BOTTOM_RIGHT (1 << QUAD_BOTTOM_RIGHT)
#define MASK_ALL 0xf
 
 
/**
* Quad stage inputs (pos, coverage, front/back face, etc)
*/
struct quad_header_input
{
int x0, y0; /**< quad window pos, always even */
float coverage[TGSI_QUAD_SIZE]; /**< fragment coverage for antialiasing */
unsigned facing:1; /**< Front (0) or back (1) facing? */
unsigned prim:2; /**< QUAD_PRIM_POINT, LINE, TRI */
};
 
 
/**
* Quad stage inputs/outputs.
*/
struct quad_header_inout
{
unsigned mask:4;
};
 
 
/**
* Quad stage outputs (color & depth).
*/
struct quad_header_output
{
/** colors in SOA format (rrrr, gggg, bbbb, aaaa) */
float color[PIPE_MAX_COLOR_BUFS][TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
float depth[TGSI_QUAD_SIZE];
uint8_t stencil[TGSI_QUAD_SIZE];
};
 
 
/**
* Encodes everything we need to know about a 2x2 pixel block. Uses
* "Channel-Serial" or "SoA" layout.
*/
struct quad_header {
struct quad_header_input input;
struct quad_header_inout inout;
struct quad_header_output output;
 
/* Redundant/duplicated:
*/
const struct tgsi_interp_coef *posCoef;
const struct tgsi_interp_coef *coef;
};
 
#endif /* SP_QUAD_H */
/drivers/video/Gallium/drivers/softpipe/sp_quad_blend.c
0,0 → 1,1306
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/**
* quad blending
* \author Brian Paul
*/
 
#include "pipe/p_defines.h"
#include "util/u_math.h"
#include "util/u_memory.h"
#include "util/u_format.h"
#include "util/u_dual_blend.h"
#include "sp_context.h"
#include "sp_state.h"
#include "sp_quad.h"
#include "sp_tile_cache.h"
#include "sp_quad_pipe.h"
 
 
enum format
{
RGBA,
RGB,
LUMINANCE,
LUMINANCE_ALPHA,
INTENSITY
};
 
 
/** Subclass of quad_stage */
struct blend_quad_stage
{
struct quad_stage base;
boolean clamp[PIPE_MAX_COLOR_BUFS]; /**< clamp colors to [0,1]? */
enum format base_format[PIPE_MAX_COLOR_BUFS];
enum util_format_type format_type[PIPE_MAX_COLOR_BUFS];
};
 
 
/** cast wrapper */
static INLINE struct blend_quad_stage *
blend_quad_stage(struct quad_stage *stage)
{
return (struct blend_quad_stage *) stage;
}
 
 
#define VEC4_COPY(DST, SRC) \
do { \
DST[0] = SRC[0]; \
DST[1] = SRC[1]; \
DST[2] = SRC[2]; \
DST[3] = SRC[3]; \
} while(0)
 
#define VEC4_SCALAR(DST, SRC) \
do { \
DST[0] = SRC; \
DST[1] = SRC; \
DST[2] = SRC; \
DST[3] = SRC; \
} while(0)
 
#define VEC4_ADD(R, A, B) \
do { \
R[0] = A[0] + B[0]; \
R[1] = A[1] + B[1]; \
R[2] = A[2] + B[2]; \
R[3] = A[3] + B[3]; \
} while (0)
 
#define VEC4_SUB(R, A, B) \
do { \
R[0] = A[0] - B[0]; \
R[1] = A[1] - B[1]; \
R[2] = A[2] - B[2]; \
R[3] = A[3] - B[3]; \
} while (0)
 
/** Add and limit result to ceiling of 1.0 */
#define VEC4_ADD_SAT(R, A, B) \
do { \
R[0] = A[0] + B[0]; if (R[0] > 1.0f) R[0] = 1.0f; \
R[1] = A[1] + B[1]; if (R[1] > 1.0f) R[1] = 1.0f; \
R[2] = A[2] + B[2]; if (R[2] > 1.0f) R[2] = 1.0f; \
R[3] = A[3] + B[3]; if (R[3] > 1.0f) R[3] = 1.0f; \
} while (0)
 
/** Subtract and limit result to floor of 0.0 */
#define VEC4_SUB_SAT(R, A, B) \
do { \
R[0] = A[0] - B[0]; if (R[0] < 0.0f) R[0] = 0.0f; \
R[1] = A[1] - B[1]; if (R[1] < 0.0f) R[1] = 0.0f; \
R[2] = A[2] - B[2]; if (R[2] < 0.0f) R[2] = 0.0f; \
R[3] = A[3] - B[3]; if (R[3] < 0.0f) R[3] = 0.0f; \
} while (0)
 
#define VEC4_MUL(R, A, B) \
do { \
R[0] = A[0] * B[0]; \
R[1] = A[1] * B[1]; \
R[2] = A[2] * B[2]; \
R[3] = A[3] * B[3]; \
} while (0)
 
#define VEC4_MIN(R, A, B) \
do { \
R[0] = (A[0] < B[0]) ? A[0] : B[0]; \
R[1] = (A[1] < B[1]) ? A[1] : B[1]; \
R[2] = (A[2] < B[2]) ? A[2] : B[2]; \
R[3] = (A[3] < B[3]) ? A[3] : B[3]; \
} while (0)
 
#define VEC4_MAX(R, A, B) \
do { \
R[0] = (A[0] > B[0]) ? A[0] : B[0]; \
R[1] = (A[1] > B[1]) ? A[1] : B[1]; \
R[2] = (A[2] > B[2]) ? A[2] : B[2]; \
R[3] = (A[3] > B[3]) ? A[3] : B[3]; \
} while (0)
 
 
 
static void
logicop_quad(struct quad_stage *qs,
float (*quadColor)[4],
float (*dest)[4])
{
struct softpipe_context *softpipe = qs->softpipe;
ubyte src[4][4], dst[4][4], res[4][4];
uint *src4 = (uint *) src;
uint *dst4 = (uint *) dst;
uint *res4 = (uint *) res;
uint j;
 
 
/* convert to ubyte */
for (j = 0; j < 4; j++) { /* loop over R,G,B,A channels */
dst[j][0] = float_to_ubyte(dest[j][0]); /* P0 */
dst[j][1] = float_to_ubyte(dest[j][1]); /* P1 */
dst[j][2] = float_to_ubyte(dest[j][2]); /* P2 */
dst[j][3] = float_to_ubyte(dest[j][3]); /* P3 */
 
src[j][0] = float_to_ubyte(quadColor[j][0]); /* P0 */
src[j][1] = float_to_ubyte(quadColor[j][1]); /* P1 */
src[j][2] = float_to_ubyte(quadColor[j][2]); /* P2 */
src[j][3] = float_to_ubyte(quadColor[j][3]); /* P3 */
}
 
switch (softpipe->blend->logicop_func) {
case PIPE_LOGICOP_CLEAR:
for (j = 0; j < 4; j++)
res4[j] = 0;
break;
case PIPE_LOGICOP_NOR:
for (j = 0; j < 4; j++)
res4[j] = ~(src4[j] | dst4[j]);
break;
case PIPE_LOGICOP_AND_INVERTED:
for (j = 0; j < 4; j++)
res4[j] = ~src4[j] & dst4[j];
break;
case PIPE_LOGICOP_COPY_INVERTED:
for (j = 0; j < 4; j++)
res4[j] = ~src4[j];
break;
case PIPE_LOGICOP_AND_REVERSE:
for (j = 0; j < 4; j++)
res4[j] = src4[j] & ~dst4[j];
break;
case PIPE_LOGICOP_INVERT:
for (j = 0; j < 4; j++)
res4[j] = ~dst4[j];
break;
case PIPE_LOGICOP_XOR:
for (j = 0; j < 4; j++)
res4[j] = dst4[j] ^ src4[j];
break;
case PIPE_LOGICOP_NAND:
for (j = 0; j < 4; j++)
res4[j] = ~(src4[j] & dst4[j]);
break;
case PIPE_LOGICOP_AND:
for (j = 0; j < 4; j++)
res4[j] = src4[j] & dst4[j];
break;
case PIPE_LOGICOP_EQUIV:
for (j = 0; j < 4; j++)
res4[j] = ~(src4[j] ^ dst4[j]);
break;
case PIPE_LOGICOP_NOOP:
for (j = 0; j < 4; j++)
res4[j] = dst4[j];
break;
case PIPE_LOGICOP_OR_INVERTED:
for (j = 0; j < 4; j++)
res4[j] = ~src4[j] | dst4[j];
break;
case PIPE_LOGICOP_COPY:
for (j = 0; j < 4; j++)
res4[j] = src4[j];
break;
case PIPE_LOGICOP_OR_REVERSE:
for (j = 0; j < 4; j++)
res4[j] = src4[j] | ~dst4[j];
break;
case PIPE_LOGICOP_OR:
for (j = 0; j < 4; j++)
res4[j] = src4[j] | dst4[j];
break;
case PIPE_LOGICOP_SET:
for (j = 0; j < 4; j++)
res4[j] = ~0;
break;
default:
assert(0 && "invalid logicop mode");
}
 
for (j = 0; j < 4; j++) {
quadColor[j][0] = ubyte_to_float(res[j][0]);
quadColor[j][1] = ubyte_to_float(res[j][1]);
quadColor[j][2] = ubyte_to_float(res[j][2]);
quadColor[j][3] = ubyte_to_float(res[j][3]);
}
}
 
 
 
/**
* Do blending for a 2x2 quad for one color buffer.
* \param quadColor the incoming quad colors
* \param dest the destination/framebuffer quad colors
* \param const_blend_color the constant blend color
* \param blend_index which set of blending terms to use
*/
static void
blend_quad(struct quad_stage *qs,
float (*quadColor)[4],
float (*quadColor2)[4],
float (*dest)[4],
const float const_blend_color[4],
unsigned blend_index)
{
static const float zero[4] = { 0, 0, 0, 0 };
static const float one[4] = { 1, 1, 1, 1 };
struct softpipe_context *softpipe = qs->softpipe;
float source[4][TGSI_QUAD_SIZE] = { { 0 } };
float blend_dest[4][TGSI_QUAD_SIZE];
 
/*
* Compute src/first term RGB
*/
switch (softpipe->blend->rt[blend_index].rgb_src_factor) {
case PIPE_BLENDFACTOR_ONE:
VEC4_COPY(source[0], quadColor[0]); /* R */
VEC4_COPY(source[1], quadColor[1]); /* G */
VEC4_COPY(source[2], quadColor[2]); /* B */
break;
case PIPE_BLENDFACTOR_SRC_COLOR:
VEC4_MUL(source[0], quadColor[0], quadColor[0]); /* R */
VEC4_MUL(source[1], quadColor[1], quadColor[1]); /* G */
VEC4_MUL(source[2], quadColor[2], quadColor[2]); /* B */
break;
case PIPE_BLENDFACTOR_SRC_ALPHA:
{
const float *alpha = quadColor[3];
VEC4_MUL(source[0], quadColor[0], alpha); /* R */
VEC4_MUL(source[1], quadColor[1], alpha); /* G */
VEC4_MUL(source[2], quadColor[2], alpha); /* B */
}
break;
case PIPE_BLENDFACTOR_DST_COLOR:
VEC4_MUL(source[0], quadColor[0], dest[0]); /* R */
VEC4_MUL(source[1], quadColor[1], dest[1]); /* G */
VEC4_MUL(source[2], quadColor[2], dest[2]); /* B */
break;
case PIPE_BLENDFACTOR_DST_ALPHA:
{
const float *alpha = dest[3];
VEC4_MUL(source[0], quadColor[0], alpha); /* R */
VEC4_MUL(source[1], quadColor[1], alpha); /* G */
VEC4_MUL(source[2], quadColor[2], alpha); /* B */
}
break;
case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
{
const float *alpha = quadColor[3];
float diff[4], temp[4];
VEC4_SUB(diff, one, dest[3]);
VEC4_MIN(temp, alpha, diff);
VEC4_MUL(source[0], quadColor[0], temp); /* R */
VEC4_MUL(source[1], quadColor[1], temp); /* G */
VEC4_MUL(source[2], quadColor[2], temp); /* B */
}
break;
case PIPE_BLENDFACTOR_CONST_COLOR:
{
float comp[4];
VEC4_SCALAR(comp, const_blend_color[0]); /* R */
VEC4_MUL(source[0], quadColor[0], comp); /* R */
VEC4_SCALAR(comp, const_blend_color[1]); /* G */
VEC4_MUL(source[1], quadColor[1], comp); /* G */
VEC4_SCALAR(comp, const_blend_color[2]); /* B */
VEC4_MUL(source[2], quadColor[2], comp); /* B */
}
break;
case PIPE_BLENDFACTOR_CONST_ALPHA:
{
float alpha[4];
VEC4_SCALAR(alpha, const_blend_color[3]);
VEC4_MUL(source[0], quadColor[0], alpha); /* R */
VEC4_MUL(source[1], quadColor[1], alpha); /* G */
VEC4_MUL(source[2], quadColor[2], alpha); /* B */
}
break;
case PIPE_BLENDFACTOR_SRC1_COLOR:
VEC4_MUL(source[0], quadColor[0], quadColor2[0]); /* R */
VEC4_MUL(source[1], quadColor[1], quadColor2[1]); /* G */
VEC4_MUL(source[2], quadColor[2], quadColor2[2]); /* B */
break;
case PIPE_BLENDFACTOR_SRC1_ALPHA:
{
const float *alpha = quadColor2[3];
VEC4_MUL(source[0], quadColor[0], alpha); /* R */
VEC4_MUL(source[1], quadColor[1], alpha); /* G */
VEC4_MUL(source[2], quadColor[2], alpha); /* B */
}
break;
case PIPE_BLENDFACTOR_ZERO:
VEC4_COPY(source[0], zero); /* R */
VEC4_COPY(source[1], zero); /* G */
VEC4_COPY(source[2], zero); /* B */
break;
case PIPE_BLENDFACTOR_INV_SRC_COLOR:
{
float inv_comp[4];
VEC4_SUB(inv_comp, one, quadColor[0]); /* R */
VEC4_MUL(source[0], quadColor[0], inv_comp); /* R */
VEC4_SUB(inv_comp, one, quadColor[1]); /* G */
VEC4_MUL(source[1], quadColor[1], inv_comp); /* G */
VEC4_SUB(inv_comp, one, quadColor[2]); /* B */
VEC4_MUL(source[2], quadColor[2], inv_comp); /* B */
}
break;
case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
{
float inv_alpha[4];
VEC4_SUB(inv_alpha, one, quadColor[3]);
VEC4_MUL(source[0], quadColor[0], inv_alpha); /* R */
VEC4_MUL(source[1], quadColor[1], inv_alpha); /* G */
VEC4_MUL(source[2], quadColor[2], inv_alpha); /* B */
}
break;
case PIPE_BLENDFACTOR_INV_DST_ALPHA:
{
float inv_alpha[4];
VEC4_SUB(inv_alpha, one, dest[3]);
VEC4_MUL(source[0], quadColor[0], inv_alpha); /* R */
VEC4_MUL(source[1], quadColor[1], inv_alpha); /* G */
VEC4_MUL(source[2], quadColor[2], inv_alpha); /* B */
}
break;
case PIPE_BLENDFACTOR_INV_DST_COLOR:
{
float inv_comp[4];
VEC4_SUB(inv_comp, one, dest[0]); /* R */
VEC4_MUL(source[0], quadColor[0], inv_comp); /* R */
VEC4_SUB(inv_comp, one, dest[1]); /* G */
VEC4_MUL(source[1], quadColor[1], inv_comp); /* G */
VEC4_SUB(inv_comp, one, dest[2]); /* B */
VEC4_MUL(source[2], quadColor[2], inv_comp); /* B */
}
break;
case PIPE_BLENDFACTOR_INV_CONST_COLOR:
{
float inv_comp[4];
/* R */
VEC4_SCALAR(inv_comp, 1.0f - const_blend_color[0]);
VEC4_MUL(source[0], quadColor[0], inv_comp);
/* G */
VEC4_SCALAR(inv_comp, 1.0f - const_blend_color[1]);
VEC4_MUL(source[1], quadColor[1], inv_comp);
/* B */
VEC4_SCALAR(inv_comp, 1.0f - const_blend_color[2]);
VEC4_MUL(source[2], quadColor[2], inv_comp);
}
break;
case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
{
float inv_alpha[4];
VEC4_SCALAR(inv_alpha, 1.0f - const_blend_color[3]);
VEC4_MUL(source[0], quadColor[0], inv_alpha); /* R */
VEC4_MUL(source[1], quadColor[1], inv_alpha); /* G */
VEC4_MUL(source[2], quadColor[2], inv_alpha); /* B */
}
break;
case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
{
float inv_comp[4];
VEC4_SUB(inv_comp, one, quadColor2[0]); /* R */
VEC4_MUL(source[0], quadColor[0], inv_comp); /* R */
VEC4_SUB(inv_comp, one, quadColor2[1]); /* G */
VEC4_MUL(source[1], quadColor[1], inv_comp); /* G */
VEC4_SUB(inv_comp, one, quadColor2[2]); /* B */
VEC4_MUL(source[2], quadColor[2], inv_comp); /* B */
}
break;
case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
{
float inv_alpha[4];
VEC4_SUB(inv_alpha, one, quadColor2[3]);
VEC4_MUL(source[0], quadColor[0], inv_alpha); /* R */
VEC4_MUL(source[1], quadColor[1], inv_alpha); /* G */
VEC4_MUL(source[2], quadColor[2], inv_alpha); /* B */
}
break;
default:
assert(0 && "invalid rgb src factor");
}
 
/*
* Compute src/first term A
*/
switch (softpipe->blend->rt[blend_index].alpha_src_factor) {
case PIPE_BLENDFACTOR_ONE:
VEC4_COPY(source[3], quadColor[3]); /* A */
break;
case PIPE_BLENDFACTOR_SRC_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_SRC_ALPHA:
{
const float *alpha = quadColor[3];
VEC4_MUL(source[3], quadColor[3], alpha); /* A */
}
break;
case PIPE_BLENDFACTOR_DST_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_DST_ALPHA:
VEC4_MUL(source[3], quadColor[3], dest[3]); /* A */
break;
case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
/* multiply alpha by 1.0 */
VEC4_COPY(source[3], quadColor[3]); /* A */
break;
case PIPE_BLENDFACTOR_CONST_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_CONST_ALPHA:
{
float comp[4];
VEC4_SCALAR(comp, const_blend_color[3]); /* A */
VEC4_MUL(source[3], quadColor[3], comp); /* A */
}
break;
case PIPE_BLENDFACTOR_ZERO:
VEC4_COPY(source[3], zero); /* A */
break;
case PIPE_BLENDFACTOR_INV_SRC_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
{
float inv_alpha[4];
VEC4_SUB(inv_alpha, one, quadColor[3]);
VEC4_MUL(source[3], quadColor[3], inv_alpha); /* A */
}
break;
case PIPE_BLENDFACTOR_INV_DST_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_INV_DST_ALPHA:
{
float inv_alpha[4];
VEC4_SUB(inv_alpha, one, dest[3]);
VEC4_MUL(source[3], quadColor[3], inv_alpha); /* A */
}
break;
case PIPE_BLENDFACTOR_INV_CONST_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
{
float inv_comp[4];
/* A */
VEC4_SCALAR(inv_comp, 1.0f - const_blend_color[3]);
VEC4_MUL(source[3], quadColor[3], inv_comp);
}
break;
case PIPE_BLENDFACTOR_SRC1_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_SRC1_ALPHA:
{
const float *alpha = quadColor2[3];
VEC4_MUL(source[3], quadColor[3], alpha); /* A */
}
break;
case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
{
float inv_alpha[4];
VEC4_SUB(inv_alpha, one, quadColor2[3]);
VEC4_MUL(source[3], quadColor[3], inv_alpha); /* A */
}
break;
default:
assert(0 && "invalid alpha src factor");
}
 
/* Save the original dest for use in masking */
VEC4_COPY(blend_dest[0], dest[0]);
VEC4_COPY(blend_dest[1], dest[1]);
VEC4_COPY(blend_dest[2], dest[2]);
VEC4_COPY(blend_dest[3], dest[3]);
 
 
/*
* Compute blend_dest/second term RGB
*/
switch (softpipe->blend->rt[blend_index].rgb_dst_factor) {
case PIPE_BLENDFACTOR_ONE:
/* blend_dest = blend_dest * 1 NO-OP, leave blend_dest as-is */
break;
case PIPE_BLENDFACTOR_SRC_COLOR:
VEC4_MUL(blend_dest[0], blend_dest[0], quadColor[0]); /* R */
VEC4_MUL(blend_dest[1], blend_dest[1], quadColor[1]); /* G */
VEC4_MUL(blend_dest[2], blend_dest[2], quadColor[2]); /* B */
break;
case PIPE_BLENDFACTOR_SRC_ALPHA:
VEC4_MUL(blend_dest[0], blend_dest[0], quadColor[3]); /* R * A */
VEC4_MUL(blend_dest[1], blend_dest[1], quadColor[3]); /* G * A */
VEC4_MUL(blend_dest[2], blend_dest[2], quadColor[3]); /* B * A */
break;
case PIPE_BLENDFACTOR_DST_ALPHA:
VEC4_MUL(blend_dest[0], blend_dest[0], blend_dest[3]); /* R * A */
VEC4_MUL(blend_dest[1], blend_dest[1], blend_dest[3]); /* G * A */
VEC4_MUL(blend_dest[2], blend_dest[2], blend_dest[3]); /* B * A */
break;
case PIPE_BLENDFACTOR_DST_COLOR:
VEC4_MUL(blend_dest[0], blend_dest[0], blend_dest[0]); /* R */
VEC4_MUL(blend_dest[1], blend_dest[1], blend_dest[1]); /* G */
VEC4_MUL(blend_dest[2], blend_dest[2], blend_dest[2]); /* B */
break;
case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
{
const float *alpha = quadColor[3];
float diff[4], temp[4];
VEC4_SUB(diff, one, blend_dest[3]);
VEC4_MIN(temp, alpha, diff);
VEC4_MUL(blend_dest[0], blend_dest[0], temp); /* R */
VEC4_MUL(blend_dest[1], blend_dest[1], temp); /* G */
VEC4_MUL(blend_dest[2], blend_dest[2], temp); /* B */
}
break;
case PIPE_BLENDFACTOR_CONST_COLOR:
{
float comp[4];
VEC4_SCALAR(comp, const_blend_color[0]); /* R */
VEC4_MUL(blend_dest[0], blend_dest[0], comp); /* R */
VEC4_SCALAR(comp, const_blend_color[1]); /* G */
VEC4_MUL(blend_dest[1], blend_dest[1], comp); /* G */
VEC4_SCALAR(comp, const_blend_color[2]); /* B */
VEC4_MUL(blend_dest[2], blend_dest[2], comp); /* B */
}
break;
case PIPE_BLENDFACTOR_CONST_ALPHA:
{
float comp[4];
VEC4_SCALAR(comp, const_blend_color[3]); /* A */
VEC4_MUL(blend_dest[0], blend_dest[0], comp); /* R */
VEC4_MUL(blend_dest[1], blend_dest[1], comp); /* G */
VEC4_MUL(blend_dest[2], blend_dest[2], comp); /* B */
}
break;
case PIPE_BLENDFACTOR_ZERO:
VEC4_COPY(blend_dest[0], zero); /* R */
VEC4_COPY(blend_dest[1], zero); /* G */
VEC4_COPY(blend_dest[2], zero); /* B */
break;
case PIPE_BLENDFACTOR_SRC1_COLOR:
VEC4_MUL(blend_dest[0], blend_dest[0], quadColor2[0]); /* R */
VEC4_MUL(blend_dest[1], blend_dest[1], quadColor2[1]); /* G */
VEC4_MUL(blend_dest[2], blend_dest[2], quadColor2[2]); /* B */
break;
case PIPE_BLENDFACTOR_SRC1_ALPHA:
VEC4_MUL(blend_dest[0], blend_dest[0], quadColor2[3]); /* R * A */
VEC4_MUL(blend_dest[1], blend_dest[1], quadColor2[3]); /* G * A */
VEC4_MUL(blend_dest[2], blend_dest[2], quadColor2[3]); /* B * A */
break;
case PIPE_BLENDFACTOR_INV_SRC_COLOR:
{
float inv_comp[4];
VEC4_SUB(inv_comp, one, quadColor[0]); /* R */
VEC4_MUL(blend_dest[0], inv_comp, blend_dest[0]); /* R */
VEC4_SUB(inv_comp, one, quadColor[1]); /* G */
VEC4_MUL(blend_dest[1], inv_comp, blend_dest[1]); /* G */
VEC4_SUB(inv_comp, one, quadColor[2]); /* B */
VEC4_MUL(blend_dest[2], inv_comp, blend_dest[2]); /* B */
}
break;
case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
{
float one_minus_alpha[TGSI_QUAD_SIZE];
VEC4_SUB(one_minus_alpha, one, quadColor[3]);
VEC4_MUL(blend_dest[0], blend_dest[0], one_minus_alpha); /* R */
VEC4_MUL(blend_dest[1], blend_dest[1], one_minus_alpha); /* G */
VEC4_MUL(blend_dest[2], blend_dest[2], one_minus_alpha); /* B */
}
break;
case PIPE_BLENDFACTOR_INV_DST_ALPHA:
{
float inv_comp[4];
VEC4_SUB(inv_comp, one, blend_dest[3]); /* A */
VEC4_MUL(blend_dest[0], inv_comp, blend_dest[0]); /* R */
VEC4_MUL(blend_dest[1], inv_comp, blend_dest[1]); /* G */
VEC4_MUL(blend_dest[2], inv_comp, blend_dest[2]); /* B */
}
break;
case PIPE_BLENDFACTOR_INV_DST_COLOR:
{
float inv_comp[4];
VEC4_SUB(inv_comp, one, blend_dest[0]); /* R */
VEC4_MUL(blend_dest[0], blend_dest[0], inv_comp); /* R */
VEC4_SUB(inv_comp, one, blend_dest[1]); /* G */
VEC4_MUL(blend_dest[1], blend_dest[1], inv_comp); /* G */
VEC4_SUB(inv_comp, one, blend_dest[2]); /* B */
VEC4_MUL(blend_dest[2], blend_dest[2], inv_comp); /* B */
}
break;
case PIPE_BLENDFACTOR_INV_CONST_COLOR:
{
float inv_comp[4];
/* R */
VEC4_SCALAR(inv_comp, 1.0f - const_blend_color[0]);
VEC4_MUL(blend_dest[0], blend_dest[0], inv_comp);
/* G */
VEC4_SCALAR(inv_comp, 1.0f - const_blend_color[1]);
VEC4_MUL(blend_dest[1], blend_dest[1], inv_comp);
/* B */
VEC4_SCALAR(inv_comp, 1.0f - const_blend_color[2]);
VEC4_MUL(blend_dest[2], blend_dest[2], inv_comp);
}
break;
case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
{
float inv_comp[4];
VEC4_SCALAR(inv_comp, 1.0f - const_blend_color[3]);
VEC4_MUL(blend_dest[0], blend_dest[0], inv_comp);
VEC4_MUL(blend_dest[1], blend_dest[1], inv_comp);
VEC4_MUL(blend_dest[2], blend_dest[2], inv_comp);
}
break;
case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
{
float inv_comp[4];
VEC4_SUB(inv_comp, one, quadColor2[0]); /* R */
VEC4_MUL(blend_dest[0], inv_comp, blend_dest[0]); /* R */
VEC4_SUB(inv_comp, one, quadColor2[1]); /* G */
VEC4_MUL(blend_dest[1], inv_comp, blend_dest[1]); /* G */
VEC4_SUB(inv_comp, one, quadColor2[2]); /* B */
VEC4_MUL(blend_dest[2], inv_comp, blend_dest[2]); /* B */
}
break;
case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
{
float one_minus_alpha[TGSI_QUAD_SIZE];
VEC4_SUB(one_minus_alpha, one, quadColor2[3]);
VEC4_MUL(blend_dest[0], blend_dest[0], one_minus_alpha); /* R */
VEC4_MUL(blend_dest[1], blend_dest[1], one_minus_alpha); /* G */
VEC4_MUL(blend_dest[2], blend_dest[2], one_minus_alpha); /* B */
}
break;
default:
assert(0 && "invalid rgb dst factor");
}
 
/*
* Compute blend_dest/second term A
*/
switch (softpipe->blend->rt[blend_index].alpha_dst_factor) {
case PIPE_BLENDFACTOR_ONE:
/* blend_dest = blend_dest * 1 NO-OP, leave blend_dest as-is */
break;
case PIPE_BLENDFACTOR_SRC_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_SRC_ALPHA:
VEC4_MUL(blend_dest[3], blend_dest[3], quadColor[3]); /* A * A */
break;
case PIPE_BLENDFACTOR_DST_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_DST_ALPHA:
VEC4_MUL(blend_dest[3], blend_dest[3], blend_dest[3]); /* A */
break;
case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
/* blend_dest = blend_dest * 1 NO-OP, leave blend_dest as-is */
break;
case PIPE_BLENDFACTOR_CONST_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_CONST_ALPHA:
{
float comp[4];
VEC4_SCALAR(comp, const_blend_color[3]); /* A */
VEC4_MUL(blend_dest[3], blend_dest[3], comp); /* A */
}
break;
case PIPE_BLENDFACTOR_ZERO:
VEC4_COPY(blend_dest[3], zero); /* A */
break;
case PIPE_BLENDFACTOR_INV_SRC_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
{
float one_minus_alpha[TGSI_QUAD_SIZE];
VEC4_SUB(one_minus_alpha, one, quadColor[3]);
VEC4_MUL(blend_dest[3], blend_dest[3], one_minus_alpha); /* A */
}
break;
case PIPE_BLENDFACTOR_INV_DST_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_INV_DST_ALPHA:
{
float inv_comp[4];
VEC4_SUB(inv_comp, one, blend_dest[3]); /* A */
VEC4_MUL(blend_dest[3], inv_comp, blend_dest[3]); /* A */
}
break;
case PIPE_BLENDFACTOR_INV_CONST_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
{
float inv_comp[4];
VEC4_SCALAR(inv_comp, 1.0f - const_blend_color[3]);
VEC4_MUL(blend_dest[3], blend_dest[3], inv_comp);
}
break;
case PIPE_BLENDFACTOR_SRC1_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_SRC1_ALPHA:
VEC4_MUL(blend_dest[3], blend_dest[3], quadColor2[3]); /* A * A */
break;
case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
/* fall-through */
case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
{
float one_minus_alpha[TGSI_QUAD_SIZE];
VEC4_SUB(one_minus_alpha, one, quadColor2[3]);
VEC4_MUL(blend_dest[3], blend_dest[3], one_minus_alpha); /* A */
}
break;
default:
assert(0 && "invalid alpha dst factor");
}
 
/*
* Combine RGB terms
*/
switch (softpipe->blend->rt[blend_index].rgb_func) {
case PIPE_BLEND_ADD:
VEC4_ADD(quadColor[0], source[0], blend_dest[0]); /* R */
VEC4_ADD(quadColor[1], source[1], blend_dest[1]); /* G */
VEC4_ADD(quadColor[2], source[2], blend_dest[2]); /* B */
break;
case PIPE_BLEND_SUBTRACT:
VEC4_SUB(quadColor[0], source[0], blend_dest[0]); /* R */
VEC4_SUB(quadColor[1], source[1], blend_dest[1]); /* G */
VEC4_SUB(quadColor[2], source[2], blend_dest[2]); /* B */
break;
case PIPE_BLEND_REVERSE_SUBTRACT:
VEC4_SUB(quadColor[0], blend_dest[0], source[0]); /* R */
VEC4_SUB(quadColor[1], blend_dest[1], source[1]); /* G */
VEC4_SUB(quadColor[2], blend_dest[2], source[2]); /* B */
break;
case PIPE_BLEND_MIN:
VEC4_MIN(quadColor[0], source[0], blend_dest[0]); /* R */
VEC4_MIN(quadColor[1], source[1], blend_dest[1]); /* G */
VEC4_MIN(quadColor[2], source[2], blend_dest[2]); /* B */
break;
case PIPE_BLEND_MAX:
VEC4_MAX(quadColor[0], source[0], blend_dest[0]); /* R */
VEC4_MAX(quadColor[1], source[1], blend_dest[1]); /* G */
VEC4_MAX(quadColor[2], source[2], blend_dest[2]); /* B */
break;
default:
assert(0 && "invalid rgb blend func");
}
 
/*
* Combine A terms
*/
switch (softpipe->blend->rt[blend_index].alpha_func) {
case PIPE_BLEND_ADD:
VEC4_ADD(quadColor[3], source[3], blend_dest[3]); /* A */
break;
case PIPE_BLEND_SUBTRACT:
VEC4_SUB(quadColor[3], source[3], blend_dest[3]); /* A */
break;
case PIPE_BLEND_REVERSE_SUBTRACT:
VEC4_SUB(quadColor[3], blend_dest[3], source[3]); /* A */
break;
case PIPE_BLEND_MIN:
VEC4_MIN(quadColor[3], source[3], blend_dest[3]); /* A */
break;
case PIPE_BLEND_MAX:
VEC4_MAX(quadColor[3], source[3], blend_dest[3]); /* A */
break;
default:
assert(0 && "invalid alpha blend func");
}
}
 
static void
colormask_quad(unsigned colormask,
float (*quadColor)[4],
float (*dest)[4])
{
/* R */
if (!(colormask & PIPE_MASK_R))
COPY_4V(quadColor[0], dest[0]);
 
/* G */
if (!(colormask & PIPE_MASK_G))
COPY_4V(quadColor[1], dest[1]);
 
/* B */
if (!(colormask & PIPE_MASK_B))
COPY_4V(quadColor[2], dest[2]);
 
/* A */
if (!(colormask & PIPE_MASK_A))
COPY_4V(quadColor[3], dest[3]);
}
 
 
/**
* Clamp all colors in a quad to [0, 1]
*/
static void
clamp_colors(float (*quadColor)[4])
{
unsigned i, j;
 
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
for (i = 0; i < 4; i++) {
quadColor[i][j] = CLAMP(quadColor[i][j], 0.0F, 1.0F);
}
}
}
 
 
/**
* If we're drawing to a luminance, luminance/alpha or intensity surface
* we have to adjust (rebase) the fragment/quad colors before writing them
* to the tile cache. The tile cache always stores RGBA colors but if
* we're caching a L/A surface (for example) we need to be sure that R=G=B
* so that subsequent reads from the surface cache appear to return L/A
* values.
* The piglit fbo-blending-formats test will exercise this.
*/
static void
rebase_colors(enum format base_format, float (*quadColor)[4])
{
unsigned i;
 
switch (base_format) {
case RGB:
for (i = 0; i < 4; i++) {
/* A = 1 */
quadColor[3][i] = 1.0F;
}
break;
case LUMINANCE:
for (i = 0; i < 4; i++) {
/* B = G = R */
quadColor[2][i] = quadColor[1][i] = quadColor[0][i];
/* A = 1 */
quadColor[3][i] = 1.0F;
}
break;
case LUMINANCE_ALPHA:
for (i = 0; i < 4; i++) {
/* B = G = R */
quadColor[2][i] = quadColor[1][i] = quadColor[0][i];
}
break;
case INTENSITY:
for (i = 0; i < 4; i++) {
/* A = B = G = R */
quadColor[3][i] = quadColor[2][i] = quadColor[1][i] = quadColor[0][i];
}
break;
default:
; /* nothing */
}
}
 
static void
blend_fallback(struct quad_stage *qs,
struct quad_header *quads[],
unsigned nr)
{
const struct blend_quad_stage *bqs = blend_quad_stage(qs);
struct softpipe_context *softpipe = qs->softpipe;
const struct pipe_blend_state *blend = softpipe->blend;
unsigned cbuf;
boolean write_all;
 
write_all = softpipe->fs_variant->info.color0_writes_all_cbufs;
 
for (cbuf = 0; cbuf < softpipe->framebuffer.nr_cbufs; cbuf++)
{
/* which blend/mask state index to use: */
const uint blend_buf = blend->independent_blend_enable ? cbuf : 0;
float dest[4][TGSI_QUAD_SIZE];
struct softpipe_cached_tile *tile
= sp_get_cached_tile(softpipe->cbuf_cache[cbuf],
quads[0]->input.x0,
quads[0]->input.y0);
const boolean clamp = bqs->clamp[cbuf];
const float *blend_color;
const boolean dual_source_blend = util_blend_state_is_dual(blend, cbuf);
uint q, i, j;
 
if (clamp)
blend_color = softpipe->blend_color_clamped.color;
else
blend_color = softpipe->blend_color.color;
 
for (q = 0; q < nr; q++) {
struct quad_header *quad = quads[q];
float (*quadColor)[4];
float (*quadColor2)[4] = NULL;
float temp_quad_color[TGSI_QUAD_SIZE][4];
const int itx = (quad->input.x0 & (TILE_SIZE-1));
const int ity = (quad->input.y0 & (TILE_SIZE-1));
 
if (write_all) {
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
for (i = 0; i < 4; i++) {
temp_quad_color[i][j] = quad->output.color[0][i][j];
}
}
quadColor = temp_quad_color;
} else {
quadColor = quad->output.color[cbuf];
if (dual_source_blend)
quadColor2 = quad->output.color[cbuf + 1];
}
 
/* If fixed-point dest color buffer, need to clamp the incoming
* fragment colors now.
*/
if (clamp || softpipe->rasterizer->clamp_fragment_color) {
clamp_colors(quadColor);
}
 
/* get/swizzle dest colors
*/
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int x = itx + (j & 1);
int y = ity + (j >> 1);
for (i = 0; i < 4; i++) {
dest[i][j] = tile->data.color[y][x][i];
}
}
 
 
if (blend->logicop_enable) {
if (bqs->format_type[cbuf] != UTIL_FORMAT_TYPE_FLOAT) {
logicop_quad( qs, quadColor, dest );
}
}
else if (blend->rt[blend_buf].blend_enable) {
blend_quad(qs, quadColor, quadColor2, dest, blend_color, blend_buf);
 
/* If fixed-point dest color buffer, need to clamp the outgoing
* fragment colors now.
*/
if (clamp) {
clamp_colors(quadColor);
}
}
 
rebase_colors(bqs->base_format[cbuf], quadColor);
 
if (blend->rt[blend_buf].colormask != 0xf)
colormask_quad( blend->rt[cbuf].colormask, quadColor, dest);
/* Output color values
*/
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (quad->inout.mask & (1 << j)) {
int x = itx + (j & 1);
int y = ity + (j >> 1);
for (i = 0; i < 4; i++) { /* loop over color chans */
tile->data.color[y][x][i] = quadColor[i][j];
}
}
}
}
}
}
 
 
static void
blend_single_add_src_alpha_inv_src_alpha(struct quad_stage *qs,
struct quad_header *quads[],
unsigned nr)
{
const struct blend_quad_stage *bqs = blend_quad_stage(qs);
static const float one[4] = { 1, 1, 1, 1 };
float one_minus_alpha[TGSI_QUAD_SIZE];
float dest[4][TGSI_QUAD_SIZE];
float source[4][TGSI_QUAD_SIZE];
uint i, j, q;
 
struct softpipe_cached_tile *tile
= sp_get_cached_tile(qs->softpipe->cbuf_cache[0],
quads[0]->input.x0,
quads[0]->input.y0);
 
for (q = 0; q < nr; q++) {
struct quad_header *quad = quads[q];
float (*quadColor)[4] = quad->output.color[0];
const float *alpha = quadColor[3];
const int itx = (quad->input.x0 & (TILE_SIZE-1));
const int ity = (quad->input.y0 & (TILE_SIZE-1));
/* get/swizzle dest colors */
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int x = itx + (j & 1);
int y = ity + (j >> 1);
for (i = 0; i < 4; i++) {
dest[i][j] = tile->data.color[y][x][i];
}
}
 
/* If fixed-point dest color buffer, need to clamp the incoming
* fragment colors now.
*/
if (bqs->clamp[0] || qs->softpipe->rasterizer->clamp_fragment_color) {
clamp_colors(quadColor);
}
 
VEC4_MUL(source[0], quadColor[0], alpha); /* R */
VEC4_MUL(source[1], quadColor[1], alpha); /* G */
VEC4_MUL(source[2], quadColor[2], alpha); /* B */
VEC4_MUL(source[3], quadColor[3], alpha); /* A */
 
VEC4_SUB(one_minus_alpha, one, alpha);
VEC4_MUL(dest[0], dest[0], one_minus_alpha); /* R */
VEC4_MUL(dest[1], dest[1], one_minus_alpha); /* G */
VEC4_MUL(dest[2], dest[2], one_minus_alpha); /* B */
VEC4_MUL(dest[3], dest[3], one_minus_alpha); /* A */
 
VEC4_ADD(quadColor[0], source[0], dest[0]); /* R */
VEC4_ADD(quadColor[1], source[1], dest[1]); /* G */
VEC4_ADD(quadColor[2], source[2], dest[2]); /* B */
VEC4_ADD(quadColor[3], source[3], dest[3]); /* A */
 
/* If fixed-point dest color buffer, need to clamp the outgoing
* fragment colors now.
*/
if (bqs->clamp[0]) {
clamp_colors(quadColor);
}
 
rebase_colors(bqs->base_format[0], quadColor);
 
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (quad->inout.mask & (1 << j)) {
int x = itx + (j & 1);
int y = ity + (j >> 1);
for (i = 0; i < 4; i++) { /* loop over color chans */
tile->data.color[y][x][i] = quadColor[i][j];
}
}
}
}
}
 
static void
blend_single_add_one_one(struct quad_stage *qs,
struct quad_header *quads[],
unsigned nr)
{
const struct blend_quad_stage *bqs = blend_quad_stage(qs);
float dest[4][TGSI_QUAD_SIZE];
uint i, j, q;
 
struct softpipe_cached_tile *tile
= sp_get_cached_tile(qs->softpipe->cbuf_cache[0],
quads[0]->input.x0,
quads[0]->input.y0);
 
for (q = 0; q < nr; q++) {
struct quad_header *quad = quads[q];
float (*quadColor)[4] = quad->output.color[0];
const int itx = (quad->input.x0 & (TILE_SIZE-1));
const int ity = (quad->input.y0 & (TILE_SIZE-1));
/* get/swizzle dest colors */
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int x = itx + (j & 1);
int y = ity + (j >> 1);
for (i = 0; i < 4; i++) {
dest[i][j] = tile->data.color[y][x][i];
}
}
/* If fixed-point dest color buffer, need to clamp the incoming
* fragment colors now.
*/
if (bqs->clamp[0] || qs->softpipe->rasterizer->clamp_fragment_color) {
clamp_colors(quadColor);
}
 
VEC4_ADD(quadColor[0], quadColor[0], dest[0]); /* R */
VEC4_ADD(quadColor[1], quadColor[1], dest[1]); /* G */
VEC4_ADD(quadColor[2], quadColor[2], dest[2]); /* B */
VEC4_ADD(quadColor[3], quadColor[3], dest[3]); /* A */
 
/* If fixed-point dest color buffer, need to clamp the outgoing
* fragment colors now.
*/
if (bqs->clamp[0]) {
clamp_colors(quadColor);
}
 
rebase_colors(bqs->base_format[0], quadColor);
 
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (quad->inout.mask & (1 << j)) {
int x = itx + (j & 1);
int y = ity + (j >> 1);
for (i = 0; i < 4; i++) { /* loop over color chans */
tile->data.color[y][x][i] = quadColor[i][j];
}
}
}
}
}
 
 
/**
* Just copy the quad color to the framebuffer tile (respecting the writemask),
* for one color buffer.
* Clamping will be done, if needed (depending on the color buffer's
* datatype) when we write/pack the colors later.
*/
static void
single_output_color(struct quad_stage *qs,
struct quad_header *quads[],
unsigned nr)
{
const struct blend_quad_stage *bqs = blend_quad_stage(qs);
uint i, j, q;
 
struct softpipe_cached_tile *tile
= sp_get_cached_tile(qs->softpipe->cbuf_cache[0],
quads[0]->input.x0,
quads[0]->input.y0);
 
for (q = 0; q < nr; q++) {
struct quad_header *quad = quads[q];
float (*quadColor)[4] = quad->output.color[0];
const int itx = (quad->input.x0 & (TILE_SIZE-1));
const int ity = (quad->input.y0 & (TILE_SIZE-1));
 
if (qs->softpipe->rasterizer->clamp_fragment_color)
clamp_colors(quadColor);
 
rebase_colors(bqs->base_format[0], quadColor);
 
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (quad->inout.mask & (1 << j)) {
int x = itx + (j & 1);
int y = ity + (j >> 1);
for (i = 0; i < 4; i++) { /* loop over color chans */
tile->data.color[y][x][i] = quadColor[i][j];
}
}
}
}
}
 
static void
blend_noop(struct quad_stage *qs,
struct quad_header *quads[],
unsigned nr)
{
}
 
 
static void
choose_blend_quad(struct quad_stage *qs,
struct quad_header *quads[],
unsigned nr)
{
struct blend_quad_stage *bqs = blend_quad_stage(qs);
struct softpipe_context *softpipe = qs->softpipe;
const struct pipe_blend_state *blend = softpipe->blend;
unsigned i;
 
qs->run = blend_fallback;
if (softpipe->framebuffer.nr_cbufs == 0) {
qs->run = blend_noop;
}
else if (!softpipe->blend->logicop_enable &&
softpipe->blend->rt[0].colormask == 0xf &&
softpipe->framebuffer.nr_cbufs == 1)
{
if (!blend->rt[0].blend_enable) {
qs->run = single_output_color;
}
else if (blend->rt[0].rgb_src_factor == blend->rt[0].alpha_src_factor &&
blend->rt[0].rgb_dst_factor == blend->rt[0].alpha_dst_factor &&
blend->rt[0].rgb_func == blend->rt[0].alpha_func)
{
if (blend->rt[0].alpha_func == PIPE_BLEND_ADD) {
if (blend->rt[0].rgb_src_factor == PIPE_BLENDFACTOR_ONE &&
blend->rt[0].rgb_dst_factor == PIPE_BLENDFACTOR_ONE) {
qs->run = blend_single_add_one_one;
}
else if (blend->rt[0].rgb_src_factor == PIPE_BLENDFACTOR_SRC_ALPHA &&
blend->rt[0].rgb_dst_factor == PIPE_BLENDFACTOR_INV_SRC_ALPHA)
qs->run = blend_single_add_src_alpha_inv_src_alpha;
 
}
}
}
 
/* For each color buffer, determine if the buffer has destination alpha and
* whether color clamping is needed.
*/
for (i = 0; i < softpipe->framebuffer.nr_cbufs; i++) {
const enum pipe_format format = softpipe->framebuffer.cbufs[i]->format;
const struct util_format_description *desc =
util_format_description(format);
/* assuming all or no color channels are normalized: */
bqs->clamp[i] = desc->channel[0].normalized;
bqs->format_type[i] = desc->channel[0].type;
 
if (util_format_is_intensity(format))
bqs->base_format[i] = INTENSITY;
else if (util_format_is_luminance(format))
bqs->base_format[i] = LUMINANCE;
else if (util_format_is_luminance_alpha(format))
bqs->base_format[i] = LUMINANCE_ALPHA;
else if (!util_format_has_alpha(format))
bqs->base_format[i] = RGB;
else
bqs->base_format[i] = RGBA;
}
 
qs->run(qs, quads, nr);
}
 
 
static void blend_begin(struct quad_stage *qs)
{
qs->run = choose_blend_quad;
}
 
 
static void blend_destroy(struct quad_stage *qs)
{
FREE( qs );
}
 
 
struct quad_stage *sp_quad_blend_stage( struct softpipe_context *softpipe )
{
struct blend_quad_stage *stage = CALLOC_STRUCT(blend_quad_stage);
 
if (!stage)
return NULL;
 
stage->base.softpipe = softpipe;
stage->base.begin = blend_begin;
stage->base.run = choose_blend_quad;
stage->base.destroy = blend_destroy;
 
return &stage->base;
}
/drivers/video/Gallium/drivers/softpipe/sp_quad_depth_test.c
0,0 → 1,983
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* Copyright 2010 VMware, Inc.
* 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 THE AUTHORS 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.
*
**************************************************************************/
 
/**
* \brief Quad depth / stencil testing
*/
 
#include "pipe/p_defines.h"
#include "util/u_format.h"
#include "util/u_math.h"
#include "util/u_memory.h"
#include "tgsi/tgsi_scan.h"
#include "sp_context.h"
#include "sp_quad.h"
#include "sp_quad_pipe.h"
#include "sp_tile_cache.h"
#include "sp_state.h" /* for sp_fragment_shader */
 
 
struct depth_data {
struct pipe_surface *ps;
enum pipe_format format;
unsigned bzzzz[TGSI_QUAD_SIZE]; /**< Z values fetched from depth buffer */
unsigned qzzzz[TGSI_QUAD_SIZE]; /**< Z values from the quad */
ubyte stencilVals[TGSI_QUAD_SIZE];
boolean use_shader_stencil_refs;
ubyte shader_stencil_refs[TGSI_QUAD_SIZE];
struct softpipe_cached_tile *tile;
};
 
 
 
static void
get_depth_stencil_values( struct depth_data *data,
const struct quad_header *quad )
{
unsigned j;
const struct softpipe_cached_tile *tile = data->tile;
 
switch (data->format) {
case PIPE_FORMAT_Z16_UNORM:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int x = quad->input.x0 % TILE_SIZE + (j & 1);
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
data->bzzzz[j] = tile->data.depth16[y][x];
}
break;
case PIPE_FORMAT_Z32_UNORM:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int x = quad->input.x0 % TILE_SIZE + (j & 1);
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
data->bzzzz[j] = tile->data.depth32[y][x];
}
break;
case PIPE_FORMAT_Z24X8_UNORM:
case PIPE_FORMAT_Z24_UNORM_S8_UINT:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int x = quad->input.x0 % TILE_SIZE + (j & 1);
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
data->bzzzz[j] = tile->data.depth32[y][x] & 0xffffff;
data->stencilVals[j] = tile->data.depth32[y][x] >> 24;
}
break;
case PIPE_FORMAT_X8Z24_UNORM:
case PIPE_FORMAT_S8_UINT_Z24_UNORM:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int x = quad->input.x0 % TILE_SIZE + (j & 1);
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
data->bzzzz[j] = tile->data.depth32[y][x] >> 8;
data->stencilVals[j] = tile->data.depth32[y][x] & 0xff;
}
break;
case PIPE_FORMAT_S8_UINT:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int x = quad->input.x0 % TILE_SIZE + (j & 1);
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
data->bzzzz[j] = 0;
data->stencilVals[j] = tile->data.stencil8[y][x];
}
break;
case PIPE_FORMAT_Z32_FLOAT:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int x = quad->input.x0 % TILE_SIZE + (j & 1);
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
data->bzzzz[j] = tile->data.depth32[y][x];
}
break;
case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int x = quad->input.x0 % TILE_SIZE + (j & 1);
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
data->bzzzz[j] = tile->data.depth64[y][x] & 0xffffffff;
data->stencilVals[j] = (tile->data.depth64[y][x] >> 32) & 0xff;
}
break;
default:
assert(0);
}
}
 
 
/**
* If the shader has not been run, interpolate the depth values
* ourselves.
*/
static void
interpolate_quad_depth( struct quad_header *quad )
{
const float fx = (float) quad->input.x0;
const float fy = (float) quad->input.y0;
const float dzdx = quad->posCoef->dadx[2];
const float dzdy = quad->posCoef->dady[2];
const float z0 = quad->posCoef->a0[2] + dzdx * fx + dzdy * fy;
 
quad->output.depth[0] = z0;
quad->output.depth[1] = z0 + dzdx;
quad->output.depth[2] = z0 + dzdy;
quad->output.depth[3] = z0 + dzdx + dzdy;
}
 
 
/**
* Compute the depth_data::qzzzz[] values from the float fragment Z values.
*/
static void
convert_quad_depth( struct depth_data *data,
const struct quad_header *quad )
{
unsigned j;
 
/* Convert quad's float depth values to int depth values (qzzzz).
* If the Z buffer stores integer values, we _have_ to do the depth
* compares with integers (not floats). Otherwise, the float->int->float
* conversion of Z values (which isn't an identity function) will cause
* Z-fighting errors.
*/
switch (data->format) {
case PIPE_FORMAT_Z16_UNORM:
{
float scale = 65535.0;
 
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
data->qzzzz[j] = (unsigned) (quad->output.depth[j] * scale);
}
}
break;
case PIPE_FORMAT_Z32_UNORM:
{
double scale = (double) (uint) ~0UL;
 
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
data->qzzzz[j] = (unsigned) (quad->output.depth[j] * scale);
}
}
break;
case PIPE_FORMAT_Z24X8_UNORM:
case PIPE_FORMAT_Z24_UNORM_S8_UINT:
{
float scale = (float) ((1 << 24) - 1);
 
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
data->qzzzz[j] = (unsigned) (quad->output.depth[j] * scale);
}
}
break;
case PIPE_FORMAT_X8Z24_UNORM:
case PIPE_FORMAT_S8_UINT_Z24_UNORM:
{
float scale = (float) ((1 << 24) - 1);
 
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
data->qzzzz[j] = (unsigned) (quad->output.depth[j] * scale);
}
}
break;
case PIPE_FORMAT_Z32_FLOAT:
case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
{
union fi fui;
 
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
fui.f = quad->output.depth[j];
data->qzzzz[j] = fui.ui;
}
}
break;
default:
assert(0);
}
}
 
 
/**
* Compute the depth_data::shader_stencil_refs[] values from the float
* fragment stencil values.
*/
static void
convert_quad_stencil( struct depth_data *data,
const struct quad_header *quad )
{
unsigned j;
 
data->use_shader_stencil_refs = TRUE;
/* Copy quads stencil values
*/
switch (data->format) {
case PIPE_FORMAT_Z24X8_UNORM:
case PIPE_FORMAT_Z24_UNORM_S8_UINT:
case PIPE_FORMAT_X8Z24_UNORM:
case PIPE_FORMAT_S8_UINT_Z24_UNORM:
case PIPE_FORMAT_S8_UINT:
case PIPE_FORMAT_Z32_FLOAT:
case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
data->shader_stencil_refs[j] = ((unsigned)(quad->output.stencil[j]));
}
break;
default:
assert(0);
}
}
 
 
/**
* Write data->bzzzz[] values and data->stencilVals into the Z/stencil buffer.
*/
static void
write_depth_stencil_values( struct depth_data *data,
struct quad_header *quad )
{
struct softpipe_cached_tile *tile = data->tile;
unsigned j;
 
/* put updated Z values back into cached tile */
switch (data->format) {
case PIPE_FORMAT_Z16_UNORM:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int x = quad->input.x0 % TILE_SIZE + (j & 1);
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
tile->data.depth16[y][x] = (ushort) data->bzzzz[j];
}
break;
case PIPE_FORMAT_Z24X8_UNORM:
case PIPE_FORMAT_Z32_UNORM:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int x = quad->input.x0 % TILE_SIZE + (j & 1);
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
tile->data.depth32[y][x] = data->bzzzz[j];
}
break;
case PIPE_FORMAT_Z24_UNORM_S8_UINT:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int x = quad->input.x0 % TILE_SIZE + (j & 1);
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
tile->data.depth32[y][x] = (data->stencilVals[j] << 24) | data->bzzzz[j];
}
break;
case PIPE_FORMAT_S8_UINT_Z24_UNORM:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int x = quad->input.x0 % TILE_SIZE + (j & 1);
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
tile->data.depth32[y][x] = (data->bzzzz[j] << 8) | data->stencilVals[j];
}
break;
case PIPE_FORMAT_X8Z24_UNORM:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int x = quad->input.x0 % TILE_SIZE + (j & 1);
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
tile->data.depth32[y][x] = data->bzzzz[j] << 8;
}
break;
case PIPE_FORMAT_S8_UINT:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int x = quad->input.x0 % TILE_SIZE + (j & 1);
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
tile->data.stencil8[y][x] = data->stencilVals[j];
}
break;
case PIPE_FORMAT_Z32_FLOAT:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int x = quad->input.x0 % TILE_SIZE + (j & 1);
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
tile->data.depth32[y][x] = data->bzzzz[j];
}
break;
case PIPE_FORMAT_Z32_FLOAT_S8X24_UINT:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int x = quad->input.x0 % TILE_SIZE + (j & 1);
int y = quad->input.y0 % TILE_SIZE + (j >> 1);
tile->data.depth64[y][x] = (uint64_t)data->bzzzz[j] | ((uint64_t)data->stencilVals[j] << 32);
}
break;
default:
assert(0);
}
}
 
 
 
/** Only 8-bit stencil supported */
#define STENCIL_MAX 0xff
 
 
/**
* Do the basic stencil test (compare stencil buffer values against the
* reference value.
*
* \param data->stencilVals the stencil values from the stencil buffer
* \param func the stencil func (PIPE_FUNC_x)
* \param ref the stencil reference value
* \param valMask the stencil value mask indicating which bits of the stencil
* values and ref value are to be used.
* \return mask indicating which pixels passed the stencil test
*/
static unsigned
do_stencil_test(struct depth_data *data,
unsigned func,
unsigned ref, unsigned valMask)
{
unsigned passMask = 0x0;
unsigned j;
ubyte refs[TGSI_QUAD_SIZE];
 
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (data->use_shader_stencil_refs)
refs[j] = data->shader_stencil_refs[j] & valMask;
else
refs[j] = ref & valMask;
}
 
switch (func) {
case PIPE_FUNC_NEVER:
/* passMask = 0x0 */
break;
case PIPE_FUNC_LESS:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (refs[j] < (data->stencilVals[j] & valMask)) {
passMask |= (1 << j);
}
}
break;
case PIPE_FUNC_EQUAL:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (refs[j] == (data->stencilVals[j] & valMask)) {
passMask |= (1 << j);
}
}
break;
case PIPE_FUNC_LEQUAL:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (refs[j] <= (data->stencilVals[j] & valMask)) {
passMask |= (1 << j);
}
}
break;
case PIPE_FUNC_GREATER:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (refs[j] > (data->stencilVals[j] & valMask)) {
passMask |= (1 << j);
}
}
break;
case PIPE_FUNC_NOTEQUAL:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (refs[j] != (data->stencilVals[j] & valMask)) {
passMask |= (1 << j);
}
}
break;
case PIPE_FUNC_GEQUAL:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (refs[j] >= (data->stencilVals[j] & valMask)) {
passMask |= (1 << j);
}
}
break;
case PIPE_FUNC_ALWAYS:
passMask = MASK_ALL;
break;
default:
assert(0);
}
 
return passMask;
}
 
 
/**
* Apply the stencil operator to stencil values.
*
* \param data->stencilVals the stencil buffer values (read and written)
* \param mask indicates which pixels to update
* \param op the stencil operator (PIPE_STENCIL_OP_x)
* \param ref the stencil reference value
* \param wrtMask writemask controlling which bits are changed in the
* stencil values
*/
static void
apply_stencil_op(struct depth_data *data,
unsigned mask, unsigned op, ubyte ref, ubyte wrtMask)
{
unsigned j;
ubyte newstencil[TGSI_QUAD_SIZE];
ubyte refs[TGSI_QUAD_SIZE];
 
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
newstencil[j] = data->stencilVals[j];
if (data->use_shader_stencil_refs)
refs[j] = data->shader_stencil_refs[j];
else
refs[j] = ref;
}
 
switch (op) {
case PIPE_STENCIL_OP_KEEP:
/* no-op */
break;
case PIPE_STENCIL_OP_ZERO:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (mask & (1 << j)) {
newstencil[j] = 0;
}
}
break;
case PIPE_STENCIL_OP_REPLACE:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (mask & (1 << j)) {
newstencil[j] = refs[j];
}
}
break;
case PIPE_STENCIL_OP_INCR:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (mask & (1 << j)) {
if (data->stencilVals[j] < STENCIL_MAX) {
newstencil[j] = data->stencilVals[j] + 1;
}
}
}
break;
case PIPE_STENCIL_OP_DECR:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (mask & (1 << j)) {
if (data->stencilVals[j] > 0) {
newstencil[j] = data->stencilVals[j] - 1;
}
}
}
break;
case PIPE_STENCIL_OP_INCR_WRAP:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (mask & (1 << j)) {
newstencil[j] = data->stencilVals[j] + 1;
}
}
break;
case PIPE_STENCIL_OP_DECR_WRAP:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (mask & (1 << j)) {
newstencil[j] = data->stencilVals[j] - 1;
}
}
break;
case PIPE_STENCIL_OP_INVERT:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (mask & (1 << j)) {
newstencil[j] = ~data->stencilVals[j];
}
}
break;
default:
assert(0);
}
 
/*
* update the stencil values
*/
if (wrtMask != STENCIL_MAX) {
/* apply bit-wise stencil buffer writemask */
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
data->stencilVals[j] = (wrtMask & newstencil[j]) | (~wrtMask & data->stencilVals[j]);
}
}
else {
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
data->stencilVals[j] = newstencil[j];
}
}
}
 
 
/**
* To increase efficiency, we should probably have multiple versions
* of this function that are specifically for Z16, Z32 and FP Z buffers.
* Try to effectively do that with codegen...
*/
static boolean
depth_test_quad(struct quad_stage *qs,
struct depth_data *data,
struct quad_header *quad)
{
struct softpipe_context *softpipe = qs->softpipe;
unsigned zmask = 0;
unsigned j;
 
switch (softpipe->depth_stencil->depth.func) {
case PIPE_FUNC_NEVER:
/* zmask = 0 */
break;
case PIPE_FUNC_LESS:
/* Note this is pretty much a single sse or cell instruction.
* Like this: quad->mask &= (quad->outputs.depth < zzzz);
*/
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (data->qzzzz[j] < data->bzzzz[j])
zmask |= 1 << j;
}
break;
case PIPE_FUNC_EQUAL:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (data->qzzzz[j] == data->bzzzz[j])
zmask |= 1 << j;
}
break;
case PIPE_FUNC_LEQUAL:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (data->qzzzz[j] <= data->bzzzz[j])
zmask |= (1 << j);
}
break;
case PIPE_FUNC_GREATER:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (data->qzzzz[j] > data->bzzzz[j])
zmask |= (1 << j);
}
break;
case PIPE_FUNC_NOTEQUAL:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (data->qzzzz[j] != data->bzzzz[j])
zmask |= (1 << j);
}
break;
case PIPE_FUNC_GEQUAL:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (data->qzzzz[j] >= data->bzzzz[j])
zmask |= (1 << j);
}
break;
case PIPE_FUNC_ALWAYS:
zmask = MASK_ALL;
break;
default:
assert(0);
}
 
quad->inout.mask &= zmask;
if (quad->inout.mask == 0)
return FALSE;
 
/* Update our internal copy only if writemask set. Even if
* depth.writemask is FALSE, may still need to write out buffer
* data due to stencil changes.
*/
if (softpipe->depth_stencil->depth.writemask) {
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (quad->inout.mask & (1 << j)) {
data->bzzzz[j] = data->qzzzz[j];
}
}
}
 
return TRUE;
}
 
 
 
/**
* Do stencil (and depth) testing. Stenciling depends on the outcome of
* depth testing.
*/
static void
depth_stencil_test_quad(struct quad_stage *qs,
struct depth_data *data,
struct quad_header *quad)
{
struct softpipe_context *softpipe = qs->softpipe;
unsigned func, zFailOp, zPassOp, failOp;
ubyte ref, wrtMask, valMask;
uint face = quad->input.facing;
 
if (!softpipe->depth_stencil->stencil[1].enabled) {
/* single-sided stencil test, use front (face=0) state */
face = 0;
}
 
/* 0 = front-face, 1 = back-face */
assert(face == 0 || face == 1);
 
/* choose front or back face function, operator, etc */
/* XXX we could do these initializations once per primitive */
func = softpipe->depth_stencil->stencil[face].func;
failOp = softpipe->depth_stencil->stencil[face].fail_op;
zFailOp = softpipe->depth_stencil->stencil[face].zfail_op;
zPassOp = softpipe->depth_stencil->stencil[face].zpass_op;
ref = softpipe->stencil_ref.ref_value[face];
wrtMask = softpipe->depth_stencil->stencil[face].writemask;
valMask = softpipe->depth_stencil->stencil[face].valuemask;
 
/* do the stencil test first */
{
unsigned passMask, failMask;
passMask = do_stencil_test(data, func, ref, valMask);
failMask = quad->inout.mask & ~passMask;
quad->inout.mask &= passMask;
 
if (failOp != PIPE_STENCIL_OP_KEEP) {
apply_stencil_op(data, failMask, failOp, ref, wrtMask);
}
}
 
if (quad->inout.mask) {
/* now the pixels that passed the stencil test are depth tested */
if (softpipe->depth_stencil->depth.enabled) {
const unsigned origMask = quad->inout.mask;
 
depth_test_quad(qs, data, quad); /* quad->mask is updated */
 
/* update stencil buffer values according to z pass/fail result */
if (zFailOp != PIPE_STENCIL_OP_KEEP) {
const unsigned zFailMask = origMask & ~quad->inout.mask;
apply_stencil_op(data, zFailMask, zFailOp, ref, wrtMask);
}
 
if (zPassOp != PIPE_STENCIL_OP_KEEP) {
const unsigned zPassMask = origMask & quad->inout.mask;
apply_stencil_op(data, zPassMask, zPassOp, ref, wrtMask);
}
}
else {
/* no depth test, apply Zpass operator to stencil buffer values */
apply_stencil_op(data, quad->inout.mask, zPassOp, ref, wrtMask);
}
}
}
 
 
#define ALPHATEST( FUNC, COMP ) \
static unsigned \
alpha_test_quads_##FUNC( struct quad_stage *qs, \
struct quad_header *quads[], \
unsigned nr ) \
{ \
const float ref = qs->softpipe->depth_stencil->alpha.ref_value; \
const uint cbuf = 0; /* only output[0].alpha is tested */ \
unsigned pass_nr = 0; \
unsigned i; \
\
for (i = 0; i < nr; i++) { \
const float *aaaa = quads[i]->output.color[cbuf][3]; \
unsigned passMask = 0; \
\
if (aaaa[0] COMP ref) passMask |= (1 << 0); \
if (aaaa[1] COMP ref) passMask |= (1 << 1); \
if (aaaa[2] COMP ref) passMask |= (1 << 2); \
if (aaaa[3] COMP ref) passMask |= (1 << 3); \
\
quads[i]->inout.mask &= passMask; \
\
if (quads[i]->inout.mask) \
quads[pass_nr++] = quads[i]; \
} \
\
return pass_nr; \
}
 
 
ALPHATEST( LESS, < )
ALPHATEST( EQUAL, == )
ALPHATEST( LEQUAL, <= )
ALPHATEST( GREATER, > )
ALPHATEST( NOTEQUAL, != )
ALPHATEST( GEQUAL, >= )
 
 
/* XXX: Incorporate into shader using KILP.
*/
static unsigned
alpha_test_quads(struct quad_stage *qs,
struct quad_header *quads[],
unsigned nr)
{
switch (qs->softpipe->depth_stencil->alpha.func) {
case PIPE_FUNC_LESS:
return alpha_test_quads_LESS( qs, quads, nr );
case PIPE_FUNC_EQUAL:
return alpha_test_quads_EQUAL( qs, quads, nr );
case PIPE_FUNC_LEQUAL:
return alpha_test_quads_LEQUAL( qs, quads, nr );
case PIPE_FUNC_GREATER:
return alpha_test_quads_GREATER( qs, quads, nr );
case PIPE_FUNC_NOTEQUAL:
return alpha_test_quads_NOTEQUAL( qs, quads, nr );
case PIPE_FUNC_GEQUAL:
return alpha_test_quads_GEQUAL( qs, quads, nr );
case PIPE_FUNC_ALWAYS:
return nr;
case PIPE_FUNC_NEVER:
default:
return 0;
}
}
 
 
static unsigned mask_count[16] =
{
0, /* 0x0 */
1, /* 0x1 */
1, /* 0x2 */
2, /* 0x3 */
1, /* 0x4 */
2, /* 0x5 */
2, /* 0x6 */
3, /* 0x7 */
1, /* 0x8 */
2, /* 0x9 */
2, /* 0xa */
3, /* 0xb */
2, /* 0xc */
3, /* 0xd */
3, /* 0xe */
4, /* 0xf */
};
 
 
 
/**
* General depth/stencil test function. Used when there's no fast-path.
*/
static void
depth_test_quads_fallback(struct quad_stage *qs,
struct quad_header *quads[],
unsigned nr)
{
unsigned i, pass = 0;
const struct tgsi_shader_info *fsInfo = &qs->softpipe->fs_variant->info;
boolean interp_depth = !fsInfo->writes_z;
boolean shader_stencil_ref = fsInfo->writes_stencil;
struct depth_data data;
 
data.use_shader_stencil_refs = FALSE;
 
if (qs->softpipe->depth_stencil->alpha.enabled) {
nr = alpha_test_quads(qs, quads, nr);
}
 
if (qs->softpipe->framebuffer.zsbuf &&
(qs->softpipe->depth_stencil->depth.enabled ||
qs->softpipe->depth_stencil->stencil[0].enabled)) {
 
data.ps = qs->softpipe->framebuffer.zsbuf;
data.format = data.ps->format;
data.tile = sp_get_cached_tile(qs->softpipe->zsbuf_cache,
quads[0]->input.x0,
quads[0]->input.y0);
 
for (i = 0; i < nr; i++) {
get_depth_stencil_values(&data, quads[i]);
 
if (qs->softpipe->depth_stencil->depth.enabled) {
if (interp_depth)
interpolate_quad_depth(quads[i]);
 
convert_quad_depth(&data, quads[i]);
}
 
if (qs->softpipe->depth_stencil->stencil[0].enabled) {
if (shader_stencil_ref)
convert_quad_stencil(&data, quads[i]);
depth_stencil_test_quad(qs, &data, quads[i]);
write_depth_stencil_values(&data, quads[i]);
}
else {
if (!depth_test_quad(qs, &data, quads[i]))
continue;
 
if (qs->softpipe->depth_stencil->depth.writemask)
write_depth_stencil_values(&data, quads[i]);
}
 
quads[pass++] = quads[i];
}
 
nr = pass;
}
 
if (qs->softpipe->active_query_count) {
for (i = 0; i < nr; i++)
qs->softpipe->occlusion_count += mask_count[quads[i]->inout.mask];
}
 
if (nr)
qs->next->run(qs->next, quads, nr);
}
 
 
/**
* Special-case Z testing for 16-bit Zbuffer and Z buffer writes enabled.
*/
 
#define NAME depth_interp_z16_less_write
#define OPERATOR <
#include "sp_quad_depth_test_tmp.h"
 
#define NAME depth_interp_z16_equal_write
#define OPERATOR ==
#include "sp_quad_depth_test_tmp.h"
 
#define NAME depth_interp_z16_lequal_write
#define OPERATOR <=
#include "sp_quad_depth_test_tmp.h"
 
#define NAME depth_interp_z16_greater_write
#define OPERATOR >
#include "sp_quad_depth_test_tmp.h"
 
#define NAME depth_interp_z16_notequal_write
#define OPERATOR !=
#include "sp_quad_depth_test_tmp.h"
 
#define NAME depth_interp_z16_gequal_write
#define OPERATOR >=
#include "sp_quad_depth_test_tmp.h"
 
#define NAME depth_interp_z16_always_write
#define ALWAYS 1
#include "sp_quad_depth_test_tmp.h"
 
 
 
static void
depth_noop(struct quad_stage *qs,
struct quad_header *quads[],
unsigned nr)
{
qs->next->run(qs->next, quads, nr);
}
 
 
 
static void
choose_depth_test(struct quad_stage *qs,
struct quad_header *quads[],
unsigned nr)
{
const struct tgsi_shader_info *fsInfo = &qs->softpipe->fs_variant->info;
 
boolean interp_depth = !fsInfo->writes_z;
 
boolean alpha = qs->softpipe->depth_stencil->alpha.enabled;
 
boolean depth = qs->softpipe->depth_stencil->depth.enabled;
 
unsigned depthfunc = qs->softpipe->depth_stencil->depth.func;
 
boolean stencil = qs->softpipe->depth_stencil->stencil[0].enabled;
 
boolean depthwrite = qs->softpipe->depth_stencil->depth.writemask;
 
boolean occlusion = qs->softpipe->active_query_count;
 
if(!qs->softpipe->framebuffer.zsbuf)
depth = depthwrite = stencil = FALSE;
 
/* default */
qs->run = depth_test_quads_fallback;
 
/* look for special cases */
if (!alpha &&
!depth &&
!occlusion &&
!stencil) {
qs->run = depth_noop;
}
else if (!alpha &&
interp_depth &&
depth &&
depthwrite &&
!occlusion &&
!stencil)
{
if (qs->softpipe->framebuffer.zsbuf->format == PIPE_FORMAT_Z16_UNORM) {
switch (depthfunc) {
case PIPE_FUNC_NEVER:
qs->run = depth_test_quads_fallback;
break;
case PIPE_FUNC_LESS:
qs->run = depth_interp_z16_less_write;
break;
case PIPE_FUNC_EQUAL:
qs->run = depth_interp_z16_equal_write;
break;
case PIPE_FUNC_LEQUAL:
qs->run = depth_interp_z16_lequal_write;
break;
case PIPE_FUNC_GREATER:
qs->run = depth_interp_z16_greater_write;
break;
case PIPE_FUNC_NOTEQUAL:
qs->run = depth_interp_z16_notequal_write;
break;
case PIPE_FUNC_GEQUAL:
qs->run = depth_interp_z16_gequal_write;
break;
case PIPE_FUNC_ALWAYS:
qs->run = depth_interp_z16_always_write;
break;
default:
qs->run = depth_test_quads_fallback;
break;
}
}
}
 
/* next quad/fragment stage */
qs->run( qs, quads, nr );
}
 
 
 
static void
depth_test_begin(struct quad_stage *qs)
{
qs->run = choose_depth_test;
qs->next->begin(qs->next);
}
 
 
static void
depth_test_destroy(struct quad_stage *qs)
{
FREE( qs );
}
 
 
struct quad_stage *
sp_quad_depth_test_stage(struct softpipe_context *softpipe)
{
struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
 
stage->softpipe = softpipe;
stage->begin = depth_test_begin;
stage->run = choose_depth_test;
stage->destroy = depth_test_destroy;
 
return stage;
}
/drivers/video/Gallium/drivers/softpipe/sp_quad_depth_test_tmp.h
0,0 → 1,147
/**************************************************************************
*
* Copyright 2010 VMware, Inc. 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 THE AUTHORS 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.
*
**************************************************************************/
 
 
/*
* Template for generating Z test functions
* Only PIPE_FORMAT_Z16_UNORM supported at this time.
*/
 
 
#ifndef NAME
#error "NAME is not defined!"
#endif
 
#if !defined(OPERATOR) && !defined(ALWAYS)
#error "neither OPERATOR nor ALWAYS is defined!"
#endif
 
 
/*
* NOTE: there's no guarantee that the quads are sequentially side by
* side. The fragment shader may have culled some quads, etc. Sliver
* triangles may generate non-sequential quads.
*/
static void
NAME(struct quad_stage *qs,
struct quad_header *quads[],
unsigned nr)
{
unsigned i, pass = 0;
const unsigned ix = quads[0]->input.x0;
const unsigned iy = quads[0]->input.y0;
const float fx = (float) ix;
const float fy = (float) iy;
const float dzdx = quads[0]->posCoef->dadx[2];
const float dzdy = quads[0]->posCoef->dady[2];
const float z0 = quads[0]->posCoef->a0[2] + dzdx * fx + dzdy * fy;
struct softpipe_cached_tile *tile;
ushort (*depth16)[TILE_SIZE];
ushort init_idepth[4], idepth[4], depth_step;
const float scale = 65535.0;
 
/* compute scaled depth of the four pixels in first quad */
init_idepth[0] = (ushort)((z0) * scale);
init_idepth[1] = (ushort)((z0 + dzdx) * scale);
init_idepth[2] = (ushort)((z0 + dzdy) * scale);
init_idepth[3] = (ushort)((z0 + dzdx + dzdy) * scale);
 
depth_step = (ushort)(dzdx * scale);
 
tile = sp_get_cached_tile(qs->softpipe->zsbuf_cache, ix, iy);
 
for (i = 0; i < nr; i++) {
const unsigned outmask = quads[i]->inout.mask;
const int dx = quads[i]->input.x0 - ix;
unsigned mask = 0;
/* compute depth for this quad */
idepth[0] = init_idepth[0] + dx * depth_step;
idepth[1] = init_idepth[1] + dx * depth_step;
idepth[2] = init_idepth[2] + dx * depth_step;
idepth[3] = init_idepth[3] + dx * depth_step;
 
depth16 = (ushort (*)[TILE_SIZE])
&tile->data.depth16[iy % TILE_SIZE][(ix + dx)% TILE_SIZE];
 
#ifdef ALWAYS
if (outmask & 1) {
depth16[0][0] = idepth[0];
mask |= (1 << 0);
}
 
if (outmask & 2) {
depth16[0][1] = idepth[1];
mask |= (1 << 1);
}
 
if (outmask & 4) {
depth16[1][0] = idepth[2];
mask |= (1 << 2);
}
 
if (outmask & 8) {
depth16[1][1] = idepth[3];
mask |= (1 << 3);
}
#else
/* Note: OPERATOR appears here: */
if ((outmask & 1) && (idepth[0] OPERATOR depth16[0][0])) {
depth16[0][0] = idepth[0];
mask |= (1 << 0);
}
 
if ((outmask & 2) && (idepth[1] OPERATOR depth16[0][1])) {
depth16[0][1] = idepth[1];
mask |= (1 << 1);
}
 
if ((outmask & 4) && (idepth[2] OPERATOR depth16[1][0])) {
depth16[1][0] = idepth[2];
mask |= (1 << 2);
}
 
if ((outmask & 8) && (idepth[3] OPERATOR depth16[1][1])) {
depth16[1][1] = idepth[3];
mask |= (1 << 3);
}
#endif
 
depth16 = (ushort (*)[TILE_SIZE]) &depth16[0][2];
 
quads[i]->inout.mask = mask;
if (quads[i]->inout.mask)
quads[pass++] = quads[i];
}
 
if (pass)
qs->next->run(qs->next, quads, pass);
}
 
 
#undef NAME
#undef OPERATOR
#undef ALWAYS
/drivers/video/Gallium/drivers/softpipe/sp_quad_fs.c
0,0 → 1,184
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
* Copyright 2008 VMware, Inc. 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.
*
**************************************************************************/
 
/* Vertices are just an array of floats, with all the attributes
* packed. We currently assume a layout like:
*
* attr[0][0..3] - window position
* attr[1..n][0..3] - remaining attributes.
*
* Attributes are assumed to be 4 floats wide but are packed so that
* all the enabled attributes run contiguously.
*/
 
#include "util/u_math.h"
#include "util/u_memory.h"
#include "pipe/p_defines.h"
#include "pipe/p_shader_tokens.h"
 
#include "sp_context.h"
#include "sp_state.h"
#include "sp_quad.h"
#include "sp_quad_pipe.h"
 
 
struct quad_shade_stage
{
struct quad_stage stage; /**< base class */
 
/* no other fields at this time */
};
 
 
/** cast wrapper */
static INLINE struct quad_shade_stage *
quad_shade_stage(struct quad_stage *qs)
{
return (struct quad_shade_stage *) qs;
}
 
 
/**
* Execute fragment shader for the four fragments in the quad.
* \return TRUE if quad is alive, FALSE if all four pixels are killed
*/
static INLINE boolean
shade_quad(struct quad_stage *qs, struct quad_header *quad)
{
struct softpipe_context *softpipe = qs->softpipe;
struct tgsi_exec_machine *machine = softpipe->fs_machine;
 
if (softpipe->active_statistics_queries) {
softpipe->pipeline_statistics.ps_invocations +=
util_bitcount(quad->inout.mask);
}
 
/* run shader */
machine->flatshade_color = softpipe->rasterizer->flatshade ? TRUE : FALSE;
return softpipe->fs_variant->run( softpipe->fs_variant, machine, quad );
}
 
 
 
static void
coverage_quad(struct quad_stage *qs, struct quad_header *quad)
{
struct softpipe_context *softpipe = qs->softpipe;
uint cbuf;
 
/* loop over colorbuffer outputs */
for (cbuf = 0; cbuf < softpipe->framebuffer.nr_cbufs; cbuf++) {
float (*quadColor)[4] = quad->output.color[cbuf];
unsigned j;
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
assert(quad->input.coverage[j] >= 0.0);
assert(quad->input.coverage[j] <= 1.0);
quadColor[3][j] *= quad->input.coverage[j];
}
}
}
 
 
/**
* Shade/write an array of quads
* Called via quad_stage::run()
*/
static void
shade_quads(struct quad_stage *qs,
struct quad_header *quads[],
unsigned nr)
{
struct softpipe_context *softpipe = qs->softpipe;
struct tgsi_exec_machine *machine = softpipe->fs_machine;
unsigned i, nr_quads = 0;
 
tgsi_exec_set_constant_buffers(machine, PIPE_MAX_CONSTANT_BUFFERS,
softpipe->mapped_constants[PIPE_SHADER_FRAGMENT],
softpipe->const_buffer_size[PIPE_SHADER_FRAGMENT]);
 
machine->InterpCoefs = quads[0]->coef;
 
for (i = 0; i < nr; i++) {
/* Only omit this quad from the output list if all the fragments
* are killed _AND_ it's not the first quad in the list.
* The first quad is special in the (optimized) depth-testing code:
* the quads' Z coordinates are step-wise interpolated with respect
* to the first quad in the list.
* For multi-pass algorithms we need to produce exactly the same
* Z values in each pass. If interpolation starts with different quads
* we can get different Z values for the same (x,y).
*/
if (!shade_quad(qs, quads[i]) && i > 0)
continue; /* quad totally culled/killed */
 
if (/*do_coverage*/ 0)
coverage_quad( qs, quads[i] );
 
quads[nr_quads++] = quads[i];
}
if (nr_quads)
qs->next->run(qs->next, quads, nr_quads);
}
 
/**
* Per-primitive (or per-begin?) setup
*/
static void
shade_begin(struct quad_stage *qs)
{
qs->next->begin(qs->next);
}
 
 
static void
shade_destroy(struct quad_stage *qs)
{
FREE( qs );
}
 
 
struct quad_stage *
sp_quad_shade_stage( struct softpipe_context *softpipe )
{
struct quad_shade_stage *qss = CALLOC_STRUCT(quad_shade_stage);
if (!qss)
goto fail;
 
qss->stage.softpipe = softpipe;
qss->stage.begin = shade_begin;
qss->stage.run = shade_quads;
qss->stage.destroy = shade_destroy;
 
return &qss->stage;
 
fail:
FREE(qss);
return NULL;
}
/drivers/video/Gallium/drivers/softpipe/sp_quad_pipe.c
0,0 → 1,69
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
 
#include "sp_context.h"
#include "sp_state.h"
#include "pipe/p_shader_tokens.h"
 
 
static void
insert_stage_at_head(struct softpipe_context *sp, struct quad_stage *quad)
{
quad->next = sp->quad.first;
sp->quad.first = quad;
}
 
 
void
sp_build_quad_pipeline(struct softpipe_context *sp)
{
boolean early_depth_test =
sp->depth_stencil->depth.enabled &&
sp->framebuffer.zsbuf &&
!sp->depth_stencil->alpha.enabled &&
!sp->fs_variant->info.uses_kill &&
!sp->fs_variant->info.writes_z &&
!sp->fs_variant->info.writes_stencil;
 
sp->quad.first = sp->quad.blend;
 
if (early_depth_test) {
insert_stage_at_head( sp, sp->quad.shade );
insert_stage_at_head( sp, sp->quad.depth_test );
}
else {
insert_stage_at_head( sp, sp->quad.depth_test );
insert_stage_at_head( sp, sp->quad.shade );
}
 
#if !DO_PSTIPPLE_IN_DRAW_MODULE && !DO_PSTIPPLE_IN_HELPER_MODULE
if (sp->rasterizer->poly_stipple_enable)
insert_stage_at_head( sp, sp->quad.pstipple );
#endif
}
 
/drivers/video/Gallium/drivers/softpipe/sp_quad_pipe.h
0,0 → 1,72
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/* Authors: Keith Whitwell <keith@tungstengraphics.com>
*/
 
#ifndef SP_QUAD_PIPE_H
#define SP_QUAD_PIPE_H
 
 
struct softpipe_context;
struct quad_header;
 
 
/**
* Fragment processing is performed on 2x2 blocks of pixels called "quads".
* Quad processing is performed with a pipeline of stages represented by
* this type.
*/
struct quad_stage {
struct softpipe_context *softpipe;
 
struct quad_stage *next;
 
void (*begin)(struct quad_stage *qs);
 
/** the stage action */
void (*run)(struct quad_stage *qs, struct quad_header *quad[], unsigned nr);
 
void (*destroy)(struct quad_stage *qs);
};
 
 
struct quad_stage *sp_quad_polygon_stipple_stage( struct softpipe_context *softpipe );
struct quad_stage *sp_quad_earlyz_stage( struct softpipe_context *softpipe );
struct quad_stage *sp_quad_shade_stage( struct softpipe_context *softpipe );
struct quad_stage *sp_quad_alpha_test_stage( struct softpipe_context *softpipe );
struct quad_stage *sp_quad_stencil_test_stage( struct softpipe_context *softpipe );
struct quad_stage *sp_quad_depth_test_stage( struct softpipe_context *softpipe );
struct quad_stage *sp_quad_occlusion_stage( struct softpipe_context *softpipe );
struct quad_stage *sp_quad_coverage_stage( struct softpipe_context *softpipe );
struct quad_stage *sp_quad_blend_stage( struct softpipe_context *softpipe );
struct quad_stage *sp_quad_colormask_stage( struct softpipe_context *softpipe );
struct quad_stage *sp_quad_output_stage( struct softpipe_context *softpipe );
 
void sp_build_quad_pipeline(struct softpipe_context *sp);
 
#endif /* SP_QUAD_PIPE_H */
/drivers/video/Gallium/drivers/softpipe/sp_quad_stipple.c
0,0 → 1,81
 
/**
* quad polygon stipple stage
*/
 
#include "sp_context.h"
#include "sp_quad.h"
#include "sp_quad_pipe.h"
#include "pipe/p_defines.h"
#include "util/u_memory.h"
 
 
/**
* Apply polygon stipple to quads produced by triangle rasterization
*/
static void
stipple_quad(struct quad_stage *qs, struct quad_header *quads[], unsigned nr)
{
static const uint bit31 = 1 << 31;
static const uint bit30 = 1 << 30;
unsigned pass = nr;
 
struct softpipe_context *softpipe = qs->softpipe;
unsigned q;
 
pass = 0;
 
for (q = 0; q < nr; q++) {
struct quad_header *quad = quads[q];
 
const int col0 = quad->input.x0 % 32;
const int y0 = quad->input.y0;
const int y1 = y0 + 1;
const uint stipple0 = softpipe->poly_stipple.stipple[y0 % 32];
const uint stipple1 = softpipe->poly_stipple.stipple[y1 % 32];
 
/* turn off quad mask bits that fail the stipple test */
if ((stipple0 & (bit31 >> col0)) == 0)
quad->inout.mask &= ~MASK_TOP_LEFT;
 
if ((stipple0 & (bit30 >> col0)) == 0)
quad->inout.mask &= ~MASK_TOP_RIGHT;
 
if ((stipple1 & (bit31 >> col0)) == 0)
quad->inout.mask &= ~MASK_BOTTOM_LEFT;
 
if ((stipple1 & (bit30 >> col0)) == 0)
quad->inout.mask &= ~MASK_BOTTOM_RIGHT;
 
if (quad->inout.mask)
quads[pass++] = quad;
}
 
qs->next->run(qs->next, quads, pass);
}
 
 
static void stipple_begin(struct quad_stage *qs)
{
qs->next->begin(qs->next);
}
 
 
static void stipple_destroy(struct quad_stage *qs)
{
FREE( qs );
}
 
 
struct quad_stage *
sp_quad_polygon_stipple_stage( struct softpipe_context *softpipe )
{
struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
 
stage->softpipe = softpipe;
stage->begin = stipple_begin;
stage->run = stipple_quad;
stage->destroy = stipple_destroy;
 
return stage;
}
/drivers/video/Gallium/drivers/softpipe/sp_query.c
0,0 → 1,296
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/* Author:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
#include "draw/draw_context.h"
#include "os/os_time.h"
#include "pipe/p_defines.h"
#include "util/u_memory.h"
#include "sp_context.h"
#include "sp_query.h"
#include "sp_state.h"
 
struct softpipe_query {
unsigned type;
uint64_t start;
uint64_t end;
struct pipe_query_data_so_statistics so;
unsigned num_primitives_generated;
 
struct pipe_query_data_pipeline_statistics stats;
};
 
 
static struct softpipe_query *softpipe_query( struct pipe_query *p )
{
return (struct softpipe_query *)p;
}
 
static struct pipe_query *
softpipe_create_query(struct pipe_context *pipe,
unsigned type)
{
struct softpipe_query* sq;
 
assert(type == PIPE_QUERY_OCCLUSION_COUNTER ||
type == PIPE_QUERY_OCCLUSION_PREDICATE ||
type == PIPE_QUERY_TIME_ELAPSED ||
type == PIPE_QUERY_SO_STATISTICS ||
type == PIPE_QUERY_SO_OVERFLOW_PREDICATE ||
type == PIPE_QUERY_PRIMITIVES_EMITTED ||
type == PIPE_QUERY_PRIMITIVES_GENERATED ||
type == PIPE_QUERY_PIPELINE_STATISTICS ||
type == PIPE_QUERY_GPU_FINISHED ||
type == PIPE_QUERY_TIMESTAMP ||
type == PIPE_QUERY_TIMESTAMP_DISJOINT);
sq = CALLOC_STRUCT( softpipe_query );
sq->type = type;
 
return (struct pipe_query *)sq;
}
 
 
static void
softpipe_destroy_query(struct pipe_context *pipe, struct pipe_query *q)
{
FREE(q);
}
 
 
static void
softpipe_begin_query(struct pipe_context *pipe, struct pipe_query *q)
{
struct softpipe_context *softpipe = softpipe_context( pipe );
struct softpipe_query *sq = softpipe_query(q);
 
switch (sq->type) {
case PIPE_QUERY_OCCLUSION_COUNTER:
case PIPE_QUERY_OCCLUSION_PREDICATE:
sq->start = softpipe->occlusion_count;
break;
case PIPE_QUERY_TIME_ELAPSED:
sq->start = os_time_get_nano();
break;
case PIPE_QUERY_SO_STATISTICS:
sq->so.primitives_storage_needed = 0;
sq->num_primitives_generated = 0;
softpipe->num_primitives_generated = 0;
sq->so.num_primitives_written = 0;
softpipe->so_stats.num_primitives_written = 0;
break;
case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
sq->end = FALSE;
break;
case PIPE_QUERY_PRIMITIVES_EMITTED:
sq->so.num_primitives_written = 0;
softpipe->so_stats.num_primitives_written = 0;
break;
case PIPE_QUERY_PRIMITIVES_GENERATED:
sq->num_primitives_generated = 0;
softpipe->num_primitives_generated = 0;
break;
case PIPE_QUERY_TIMESTAMP:
case PIPE_QUERY_GPU_FINISHED:
case PIPE_QUERY_TIMESTAMP_DISJOINT:
break;
case PIPE_QUERY_PIPELINE_STATISTICS:
/* reset our cache */
if (softpipe->active_statistics_queries == 0) {
memset(&softpipe->pipeline_statistics, 0,
sizeof(softpipe->pipeline_statistics));
}
memcpy(&sq->stats, &softpipe->pipeline_statistics,
sizeof(sq->stats));
softpipe->active_statistics_queries++;
break;
default:
assert(0);
break;
}
softpipe->active_query_count++;
softpipe->dirty |= SP_NEW_QUERY;
}
 
 
static void
softpipe_end_query(struct pipe_context *pipe, struct pipe_query *q)
{
struct softpipe_context *softpipe = softpipe_context( pipe );
struct softpipe_query *sq = softpipe_query(q);
 
softpipe->active_query_count--;
switch (sq->type) {
case PIPE_QUERY_OCCLUSION_COUNTER:
case PIPE_QUERY_OCCLUSION_PREDICATE:
sq->end = softpipe->occlusion_count;
break;
case PIPE_QUERY_TIMESTAMP:
sq->start = 0;
/* fall through */
case PIPE_QUERY_TIME_ELAPSED:
sq->end = os_time_get_nano();
break;
case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
sq->end = (softpipe->num_primitives_generated >
softpipe->so_stats.num_primitives_written);
break;
case PIPE_QUERY_SO_STATISTICS:
sq->num_primitives_generated =
softpipe->num_primitives_generated;
sq->so.num_primitives_written =
softpipe->so_stats.num_primitives_written;
break;
case PIPE_QUERY_PRIMITIVES_EMITTED:
sq->so.num_primitives_written =
softpipe->so_stats.num_primitives_written;
break;
case PIPE_QUERY_PRIMITIVES_GENERATED:
sq->num_primitives_generated = softpipe->num_primitives_generated;
break;
case PIPE_QUERY_GPU_FINISHED:
case PIPE_QUERY_TIMESTAMP_DISJOINT:
break;
case PIPE_QUERY_PIPELINE_STATISTICS:
sq->stats.ia_vertices =
softpipe->pipeline_statistics.ia_vertices - sq->stats.ia_vertices;
sq->stats.ia_primitives =
softpipe->pipeline_statistics.ia_primitives - sq->stats.ia_primitives;
sq->stats.vs_invocations =
softpipe->pipeline_statistics.vs_invocations - sq->stats.vs_invocations;
sq->stats.gs_invocations =
softpipe->pipeline_statistics.gs_invocations - sq->stats.gs_invocations;
sq->stats.gs_primitives =
softpipe->pipeline_statistics.gs_primitives - sq->stats.gs_primitives;
sq->stats.c_invocations =
softpipe->pipeline_statistics.c_invocations - sq->stats.c_invocations;
sq->stats.c_primitives =
softpipe->pipeline_statistics.c_primitives - sq->stats.c_primitives;
sq->stats.ps_invocations =
softpipe->pipeline_statistics.ps_invocations - sq->stats.ps_invocations;
 
softpipe->active_statistics_queries--;
break;
default:
assert(0);
break;
}
softpipe->dirty |= SP_NEW_QUERY;
}
 
 
static boolean
softpipe_get_query_result(struct pipe_context *pipe,
struct pipe_query *q,
boolean wait,
union pipe_query_result *vresult)
{
struct softpipe_query *sq = softpipe_query(q);
uint64_t *result = (uint64_t*)vresult;
 
switch (sq->type) {
case PIPE_QUERY_SO_STATISTICS: {
struct pipe_query_data_so_statistics *stats =
(struct pipe_query_data_so_statistics *)vresult;
stats->num_primitives_written = sq->so.num_primitives_written;
stats->primitives_storage_needed = sq->num_primitives_generated;
}
break;
case PIPE_QUERY_PIPELINE_STATISTICS:
memcpy(vresult, &sq->stats,
sizeof(struct pipe_query_data_pipeline_statistics));;
break;
case PIPE_QUERY_GPU_FINISHED:
vresult->b = TRUE;
break;
case PIPE_QUERY_SO_OVERFLOW_PREDICATE:
vresult->b = sq->end != 0;
break;
case PIPE_QUERY_TIMESTAMP_DISJOINT: {
struct pipe_query_data_timestamp_disjoint *td =
(struct pipe_query_data_timestamp_disjoint *)vresult;
/* os_get_time_nano return nanoseconds */
td->frequency = UINT64_C(1000000000);
td->disjoint = FALSE;
}
break;
case PIPE_QUERY_PRIMITIVES_EMITTED:
*result = sq->so.num_primitives_written;
break;
case PIPE_QUERY_PRIMITIVES_GENERATED:
*result = sq->num_primitives_generated;
break;
case PIPE_QUERY_OCCLUSION_PREDICATE:
vresult->b = sq->end - sq->start != 0;
break;
default:
*result = sq->end - sq->start;
break;
}
return TRUE;
}
 
 
/**
* Called by rendering function to check rendering is conditional.
* \return TRUE if we should render, FALSE if we should skip rendering
*/
boolean
softpipe_check_render_cond(struct softpipe_context *sp)
{
struct pipe_context *pipe = &sp->pipe;
boolean b, wait;
uint64_t result;
 
if (!sp->render_cond_query) {
return TRUE; /* no query predicate, draw normally */
}
 
wait = (sp->render_cond_mode == PIPE_RENDER_COND_WAIT ||
sp->render_cond_mode == PIPE_RENDER_COND_BY_REGION_WAIT);
 
b = pipe->get_query_result(pipe, sp->render_cond_query, wait,
(void*)&result);
if (b)
return (!result == sp->render_cond_cond);
else
return TRUE;
}
 
 
void softpipe_init_query_funcs(struct softpipe_context *softpipe )
{
softpipe->pipe.create_query = softpipe_create_query;
softpipe->pipe.destroy_query = softpipe_destroy_query;
softpipe->pipe.begin_query = softpipe_begin_query;
softpipe->pipe.end_query = softpipe_end_query;
softpipe->pipe.get_query_result = softpipe_get_query_result;
}
 
 
/drivers/video/Gallium/drivers/softpipe/sp_query.h
0,0 → 1,43
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/* Author:
* Keith Whitwell
*/
 
#ifndef SP_QUERY_H
#define SP_QUERY_H
 
extern boolean
softpipe_check_render_cond(struct softpipe_context *sp);
 
 
struct softpipe_context;
extern void softpipe_init_query_funcs(struct softpipe_context * );
 
 
#endif /* SP_QUERY_H */
/drivers/video/Gallium/drivers/softpipe/sp_screen.c
0,0 → 1,418
/**************************************************************************
*
* 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.
*
**************************************************************************/
 
 
#include "util/u_memory.h"
#include "util/u_format.h"
#include "util/u_format_s3tc.h"
#include "util/u_video.h"
#include "os/os_time.h"
#include "pipe/p_defines.h"
#include "pipe/p_screen.h"
#include "draw/draw_context.h"
#include "vl/vl_decoder.h"
#include "vl/vl_video_buffer.h"
 
#include "state_tracker/sw_winsys.h"
#include "tgsi/tgsi_exec.h"
 
#include "sp_texture.h"
#include "sp_screen.h"
#include "sp_context.h"
#include "sp_fence.h"
#include "sp_public.h"
 
DEBUG_GET_ONCE_BOOL_OPTION(use_llvm, "SOFTPIPE_USE_LLVM", FALSE)
 
static const char *
softpipe_get_vendor(struct pipe_screen *screen)
{
return "VMware, Inc.";
}
 
 
static const char *
softpipe_get_name(struct pipe_screen *screen)
{
return "softpipe";
}
 
 
static int
softpipe_get_param(struct pipe_screen *screen, enum pipe_cap param)
{
switch (param) {
case PIPE_CAP_MAX_COMBINED_SAMPLERS:
return 2 * PIPE_MAX_SAMPLERS; /* VS + FS */
case PIPE_CAP_NPOT_TEXTURES:
return 1;
case PIPE_CAP_TWO_SIDED_STENCIL:
return 1;
case PIPE_CAP_SM3:
return 1;
case PIPE_CAP_ANISOTROPIC_FILTER:
return 1;
case PIPE_CAP_POINT_SPRITE:
return 1;
case PIPE_CAP_MAX_RENDER_TARGETS:
return PIPE_MAX_COLOR_BUFS;
case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS:
return 1;
case PIPE_CAP_OCCLUSION_QUERY:
return 1;
case PIPE_CAP_QUERY_TIME_ELAPSED:
return 1;
case PIPE_CAP_QUERY_PIPELINE_STATISTICS:
return 1;
case PIPE_CAP_TEXTURE_MIRROR_CLAMP:
return 1;
case PIPE_CAP_TEXTURE_SHADOW_MAP:
return 1;
case PIPE_CAP_TEXTURE_SWIZZLE:
return 1;
case PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK:
return 0;
case PIPE_CAP_MAX_TEXTURE_2D_LEVELS:
return SP_MAX_TEXTURE_2D_LEVELS;
case PIPE_CAP_MAX_TEXTURE_3D_LEVELS:
return SP_MAX_TEXTURE_3D_LEVELS;
case PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS:
return SP_MAX_TEXTURE_CUBE_LEVELS;
case PIPE_CAP_BLEND_EQUATION_SEPARATE:
return 1;
case PIPE_CAP_INDEP_BLEND_ENABLE:
return 1;
case PIPE_CAP_INDEP_BLEND_FUNC:
return 1;
case PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT:
case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT:
case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER:
case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER:
return 1;
case PIPE_CAP_DEPTH_CLIP_DISABLE:
return 0;
case PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS:
return PIPE_MAX_SO_BUFFERS;
case PIPE_CAP_MAX_STREAM_OUTPUT_SEPARATE_COMPONENTS:
case PIPE_CAP_MAX_STREAM_OUTPUT_INTERLEAVED_COMPONENTS:
return 16*4;
case PIPE_CAP_PRIMITIVE_RESTART:
return 1;
case PIPE_CAP_SHADER_STENCIL_EXPORT:
return 1;
case PIPE_CAP_TGSI_INSTANCEID:
case PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR:
return 1;
case PIPE_CAP_SEAMLESS_CUBE_MAP:
case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE:
return 1;
case PIPE_CAP_SCALED_RESOLVE:
return 0;
case PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS:
return 256; /* for GL3 */
case PIPE_CAP_MIN_TEXEL_OFFSET:
return -8;
case PIPE_CAP_MAX_TEXEL_OFFSET:
return 7;
case PIPE_CAP_CONDITIONAL_RENDER:
return 1;
case PIPE_CAP_TEXTURE_BARRIER:
return 0;
case PIPE_CAP_FRAGMENT_COLOR_CLAMPED:
case PIPE_CAP_VERTEX_COLOR_UNCLAMPED: /* draw module */
case PIPE_CAP_VERTEX_COLOR_CLAMPED: /* draw module */
return 1;
case PIPE_CAP_MIXED_COLORBUFFER_FORMATS:
return 0;
case PIPE_CAP_GLSL_FEATURE_LEVEL:
return 140;
case PIPE_CAP_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION:
return 0;
case PIPE_CAP_COMPUTE:
return 0;
case PIPE_CAP_USER_VERTEX_BUFFERS:
case PIPE_CAP_USER_INDEX_BUFFERS:
case PIPE_CAP_USER_CONSTANT_BUFFERS:
case PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME:
return 1;
case PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT:
return 16;
case PIPE_CAP_TGSI_CAN_COMPACT_CONSTANTS:
case PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY:
case PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY:
case PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY:
case PIPE_CAP_START_INSTANCE:
case PIPE_CAP_TEXTURE_MULTISAMPLE:
case PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT:
return 0;
case PIPE_CAP_QUERY_TIMESTAMP:
case PIPE_CAP_CUBE_MAP_ARRAY:
return 1;
case PIPE_CAP_TEXTURE_BUFFER_OBJECTS:
return 1;
case PIPE_CAP_MAX_TEXTURE_BUFFER_SIZE:
return 65536;
case PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT:
return 0;
case PIPE_CAP_TGSI_TEXCOORD:
case PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER:
return 0;
case PIPE_CAP_MAX_VIEWPORTS:
return 1;
}
/* should only get here on unhandled cases */
debug_printf("Unexpected PIPE_CAP %d query\n", param);
return 0;
}
 
static int
softpipe_get_shader_param(struct pipe_screen *screen, unsigned shader, enum pipe_shader_cap param)
{
struct softpipe_screen *sp_screen = softpipe_screen(screen);
switch(shader)
{
case PIPE_SHADER_FRAGMENT:
return tgsi_exec_get_shader_param(param);
case PIPE_SHADER_VERTEX:
case PIPE_SHADER_GEOMETRY:
switch (param) {
case PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS:
if (sp_screen->use_llvm)
/* Softpipe doesn't yet know how to tell draw/llvm about textures */
return 0;
else
return PIPE_MAX_SAMPLERS;
default:
if (sp_screen->use_llvm)
return draw_get_shader_param(shader, param);
else
return draw_get_shader_param_no_llvm(shader, param);
}
default:
return 0;
}
}
 
static float
softpipe_get_paramf(struct pipe_screen *screen, enum pipe_capf param)
{
switch (param) {
case PIPE_CAPF_MAX_LINE_WIDTH:
/* fall-through */
case PIPE_CAPF_MAX_LINE_WIDTH_AA:
return 255.0; /* arbitrary */
case PIPE_CAPF_MAX_POINT_WIDTH:
/* fall-through */
case PIPE_CAPF_MAX_POINT_WIDTH_AA:
return 255.0; /* arbitrary */
case PIPE_CAPF_MAX_TEXTURE_ANISOTROPY:
return 16.0;
case PIPE_CAPF_MAX_TEXTURE_LOD_BIAS:
return 16.0; /* arbitrary */
case PIPE_CAPF_GUARD_BAND_LEFT:
case PIPE_CAPF_GUARD_BAND_TOP:
case PIPE_CAPF_GUARD_BAND_RIGHT:
case PIPE_CAPF_GUARD_BAND_BOTTOM:
return 0.0;
}
/* should only get here on unhandled cases */
debug_printf("Unexpected PIPE_CAPF %d query\n", param);
return 0.0;
}
 
static int
softpipe_get_video_param(struct pipe_screen *screen,
enum pipe_video_profile profile,
enum pipe_video_cap param)
{
switch (param) {
case PIPE_VIDEO_CAP_SUPPORTED:
return vl_profile_supported(screen, profile);
case PIPE_VIDEO_CAP_NPOT_TEXTURES:
return 0;
case PIPE_VIDEO_CAP_MAX_WIDTH:
case PIPE_VIDEO_CAP_MAX_HEIGHT:
return vl_video_buffer_max_size(screen);
case PIPE_VIDEO_CAP_PREFERED_FORMAT:
return PIPE_FORMAT_NV12;
case PIPE_VIDEO_CAP_PREFERS_INTERLACED:
return false;
case PIPE_VIDEO_CAP_SUPPORTS_INTERLACED:
return false;
case PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE:
return true;
default:
return 0;
}
}
 
/**
* Query format support for creating a texture, drawing surface, etc.
* \param format the format to test
* \param type one of PIPE_TEXTURE, PIPE_SURFACE
*/
static boolean
softpipe_is_format_supported( struct pipe_screen *screen,
enum pipe_format format,
enum pipe_texture_target target,
unsigned sample_count,
unsigned bind)
{
struct sw_winsys *winsys = softpipe_screen(screen)->winsys;
const struct util_format_description *format_desc;
 
assert(target == PIPE_BUFFER ||
target == PIPE_TEXTURE_1D ||
target == PIPE_TEXTURE_1D_ARRAY ||
target == PIPE_TEXTURE_2D ||
target == PIPE_TEXTURE_2D_ARRAY ||
target == PIPE_TEXTURE_RECT ||
target == PIPE_TEXTURE_3D ||
target == PIPE_TEXTURE_CUBE ||
target == PIPE_TEXTURE_CUBE_ARRAY);
 
format_desc = util_format_description(format);
if (!format_desc)
return FALSE;
 
if (sample_count > 1)
return FALSE;
 
if (bind & (PIPE_BIND_DISPLAY_TARGET |
PIPE_BIND_SCANOUT |
PIPE_BIND_SHARED)) {
if(!winsys->is_displaytarget_format_supported(winsys, bind, format))
return FALSE;
}
 
if (bind & PIPE_BIND_RENDER_TARGET) {
if (format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS)
return FALSE;
 
/*
* Although possible, it is unnatural to render into compressed or YUV
* surfaces. So disable these here to avoid going into weird paths
* inside the state trackers.
*/
if (format_desc->block.width != 1 ||
format_desc->block.height != 1)
return FALSE;
}
 
if (bind & PIPE_BIND_DEPTH_STENCIL) {
if (format_desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS)
return FALSE;
}
 
/*
* All other operations (sampling, transfer, etc).
*/
 
if (format_desc->layout == UTIL_FORMAT_LAYOUT_S3TC) {
return util_format_s3tc_enabled;
}
 
/*
* Everything else should be supported by u_format.
*/
return TRUE;
}
 
 
static void
softpipe_destroy_screen( struct pipe_screen *screen )
{
struct softpipe_screen *sp_screen = softpipe_screen(screen);
struct sw_winsys *winsys = sp_screen->winsys;
 
if(winsys->destroy)
winsys->destroy(winsys);
 
FREE(screen);
}
 
 
/* This is often overriden by the co-state tracker.
*/
static void
softpipe_flush_frontbuffer(struct pipe_screen *_screen,
struct pipe_resource *resource,
unsigned level, unsigned layer,
void *context_private)
{
struct softpipe_screen *screen = softpipe_screen(_screen);
struct sw_winsys *winsys = screen->winsys;
struct softpipe_resource *texture = softpipe_resource(resource);
 
assert(texture->dt);
if (texture->dt)
winsys->displaytarget_display(winsys, texture->dt, context_private);
}
 
static uint64_t
softpipe_get_timestamp(struct pipe_screen *_screen)
{
return os_time_get_nano();
}
 
/**
* Create a new pipe_screen object
* Note: we're not presently subclassing pipe_screen (no softpipe_screen).
*/
struct pipe_screen *
softpipe_create_screen(struct sw_winsys *winsys)
{
struct softpipe_screen *screen = CALLOC_STRUCT(softpipe_screen);
 
if (!screen)
return NULL;
 
screen->winsys = winsys;
 
screen->base.destroy = softpipe_destroy_screen;
 
screen->base.get_name = softpipe_get_name;
screen->base.get_vendor = softpipe_get_vendor;
screen->base.get_param = softpipe_get_param;
screen->base.get_shader_param = softpipe_get_shader_param;
screen->base.get_paramf = softpipe_get_paramf;
screen->base.get_video_param = softpipe_get_video_param;
screen->base.get_timestamp = softpipe_get_timestamp;
screen->base.is_format_supported = softpipe_is_format_supported;
screen->base.is_video_format_supported = vl_video_buffer_is_format_supported;
screen->base.context_create = softpipe_create_context;
screen->base.flush_frontbuffer = softpipe_flush_frontbuffer;
 
screen->use_llvm = debug_get_option_use_llvm();
 
util_format_s3tc_init();
 
softpipe_init_screen_texture_funcs(&screen->base);
softpipe_init_screen_fence_funcs(&screen->base);
 
return &screen->base;
}
/drivers/video/Gallium/drivers/softpipe/sp_screen.h
0,0 → 1,60
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/* Authors: Keith Whitwell <keith@tungstengraphics.com>
*/
 
#ifndef SP_SCREEN_H
#define SP_SCREEN_H
 
#include "pipe/p_screen.h"
#include "pipe/p_defines.h"
 
 
struct sw_winsys;
 
struct softpipe_screen {
struct pipe_screen base;
 
struct sw_winsys *winsys;
 
/* Increments whenever textures are modified. Contexts can track
* this.
*/
unsigned timestamp;
boolean use_llvm;
};
 
static INLINE struct softpipe_screen *
softpipe_screen( struct pipe_screen *pipe )
{
return (struct softpipe_screen *)pipe;
}
 
 
 
#endif /* SP_SCREEN_H */
/drivers/video/Gallium/drivers/softpipe/sp_setup.c
0,0 → 1,1459
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/**
* \brief Primitive rasterization/rendering (points, lines, triangles)
*
* \author Keith Whitwell <keith@tungstengraphics.com>
* \author Brian Paul
*/
 
#include "sp_context.h"
#include "sp_quad.h"
#include "sp_quad_pipe.h"
#include "sp_setup.h"
#include "sp_state.h"
#include "draw/draw_context.h"
#include "draw/draw_vertex.h"
#include "pipe/p_shader_tokens.h"
#include "util/u_math.h"
#include "util/u_memory.h"
 
 
#define DEBUG_VERTS 0
#define DEBUG_FRAGS 0
 
 
/**
* Triangle edge info
*/
struct edge {
float dx; /**< X(v1) - X(v0), used only during setup */
float dy; /**< Y(v1) - Y(v0), used only during setup */
float dxdy; /**< dx/dy */
float sx, sy; /**< first sample point coord */
int lines; /**< number of lines on this edge */
};
 
 
/**
* Max number of quads (2x2 pixel blocks) to process per batch.
* This can't be arbitrarily increased since we depend on some 32-bit
* bitmasks (two bits per quad).
*/
#define MAX_QUADS 16
 
 
/**
* Triangle setup info.
* Also used for line drawing (taking some liberties).
*/
struct setup_context {
struct softpipe_context *softpipe;
 
/* Vertices are just an array of floats making up each attribute in
* turn. Currently fixed at 4 floats, but should change in time.
* Codegen will help cope with this.
*/
const float (*vmax)[4];
const float (*vmid)[4];
const float (*vmin)[4];
const float (*vprovoke)[4];
 
struct edge ebot;
struct edge etop;
struct edge emaj;
 
float oneoverarea;
int facing;
 
float pixel_offset;
 
struct quad_header quad[MAX_QUADS];
struct quad_header *quad_ptrs[MAX_QUADS];
unsigned count;
 
struct tgsi_interp_coef coef[PIPE_MAX_SHADER_INPUTS];
struct tgsi_interp_coef posCoef; /* For Z, W */
 
struct {
int left[2]; /**< [0] = row0, [1] = row1 */
int right[2];
int y;
} span;
 
#if DEBUG_FRAGS
uint numFragsEmitted; /**< per primitive */
uint numFragsWritten; /**< per primitive */
#endif
 
unsigned cull_face; /* which faces cull */
unsigned nr_vertex_attrs;
};
 
 
 
 
 
 
 
/**
* Clip setup->quad against the scissor/surface bounds.
*/
static INLINE void
quad_clip(struct setup_context *setup, struct quad_header *quad)
{
const struct pipe_scissor_state *cliprect = &setup->softpipe->cliprect;
const int minx = (int) cliprect->minx;
const int maxx = (int) cliprect->maxx;
const int miny = (int) cliprect->miny;
const int maxy = (int) cliprect->maxy;
 
if (quad->input.x0 >= maxx ||
quad->input.y0 >= maxy ||
quad->input.x0 + 1 < minx ||
quad->input.y0 + 1 < miny) {
/* totally clipped */
quad->inout.mask = 0x0;
return;
}
if (quad->input.x0 < minx)
quad->inout.mask &= (MASK_BOTTOM_RIGHT | MASK_TOP_RIGHT);
if (quad->input.y0 < miny)
quad->inout.mask &= (MASK_BOTTOM_LEFT | MASK_BOTTOM_RIGHT);
if (quad->input.x0 == maxx - 1)
quad->inout.mask &= (MASK_BOTTOM_LEFT | MASK_TOP_LEFT);
if (quad->input.y0 == maxy - 1)
quad->inout.mask &= (MASK_TOP_LEFT | MASK_TOP_RIGHT);
}
 
 
/**
* Emit a quad (pass to next stage) with clipping.
*/
static INLINE void
clip_emit_quad(struct setup_context *setup, struct quad_header *quad)
{
quad_clip( setup, quad );
 
if (quad->inout.mask) {
struct softpipe_context *sp = setup->softpipe;
 
#if DEBUG_FRAGS
setup->numFragsEmitted += util_bitcount(quad->inout.mask);
#endif
 
sp->quad.first->run( sp->quad.first, &quad, 1 );
}
}
 
 
 
/**
* Given an X or Y coordinate, return the block/quad coordinate that it
* belongs to.
*/
static INLINE int
block(int x)
{
return x & ~(2-1);
}
 
 
static INLINE int
block_x(int x)
{
return x & ~(16-1);
}
 
 
/**
* Render a horizontal span of quads
*/
static void
flush_spans(struct setup_context *setup)
{
const int step = MAX_QUADS;
const int xleft0 = setup->span.left[0];
const int xleft1 = setup->span.left[1];
const int xright0 = setup->span.right[0];
const int xright1 = setup->span.right[1];
struct quad_stage *pipe = setup->softpipe->quad.first;
 
const int minleft = block_x(MIN2(xleft0, xleft1));
const int maxright = MAX2(xright0, xright1);
int x;
 
/* process quads in horizontal chunks of 16 */
for (x = minleft; x < maxright; x += step) {
unsigned skip_left0 = CLAMP(xleft0 - x, 0, step);
unsigned skip_left1 = CLAMP(xleft1 - x, 0, step);
unsigned skip_right0 = CLAMP(x + step - xright0, 0, step);
unsigned skip_right1 = CLAMP(x + step - xright1, 0, step);
unsigned lx = x;
unsigned q = 0;
 
unsigned skipmask_left0 = (1U << skip_left0) - 1U;
unsigned skipmask_left1 = (1U << skip_left1) - 1U;
 
/* These calculations fail when step == 32 and skip_right == 0.
*/
unsigned skipmask_right0 = ~0U << (unsigned)(step - skip_right0);
unsigned skipmask_right1 = ~0U << (unsigned)(step - skip_right1);
 
unsigned mask0 = ~skipmask_left0 & ~skipmask_right0;
unsigned mask1 = ~skipmask_left1 & ~skipmask_right1;
 
if (mask0 | mask1) {
do {
unsigned quadmask = (mask0 & 3) | ((mask1 & 3) << 2);
if (quadmask) {
setup->quad[q].input.x0 = lx;
setup->quad[q].input.y0 = setup->span.y;
setup->quad[q].input.facing = setup->facing;
setup->quad[q].inout.mask = quadmask;
setup->quad_ptrs[q] = &setup->quad[q];
q++;
#if DEBUG_FRAGS
setup->numFragsEmitted += util_bitcount(quadmask);
#endif
}
mask0 >>= 2;
mask1 >>= 2;
lx += 2;
} while (mask0 | mask1);
 
pipe->run( pipe, setup->quad_ptrs, q );
}
}
 
 
setup->span.y = 0;
setup->span.right[0] = 0;
setup->span.right[1] = 0;
setup->span.left[0] = 1000000; /* greater than right[0] */
setup->span.left[1] = 1000000; /* greater than right[1] */
}
 
 
#if DEBUG_VERTS
static void
print_vertex(const struct setup_context *setup,
const float (*v)[4])
{
int i;
debug_printf(" Vertex: (%p)\n", (void *) v);
for (i = 0; i < setup->nr_vertex_attrs; i++) {
debug_printf(" %d: %f %f %f %f\n", i,
v[i][0], v[i][1], v[i][2], v[i][3]);
if (util_is_inf_or_nan(v[i][0])) {
debug_printf(" NaN!\n");
}
}
}
#endif
 
 
/**
* Sort the vertices from top to bottom order, setting up the triangle
* edge fields (ebot, emaj, etop).
* \return FALSE if coords are inf/nan (cull the tri), TRUE otherwise
*/
static boolean
setup_sort_vertices(struct setup_context *setup,
float det,
const float (*v0)[4],
const float (*v1)[4],
const float (*v2)[4])
{
if (setup->softpipe->rasterizer->flatshade_first)
setup->vprovoke = v0;
else
setup->vprovoke = v2;
 
/* determine bottom to top order of vertices */
{
float y0 = v0[0][1];
float y1 = v1[0][1];
float y2 = v2[0][1];
if (y0 <= y1) {
if (y1 <= y2) {
/* y0<=y1<=y2 */
setup->vmin = v0;
setup->vmid = v1;
setup->vmax = v2;
}
else if (y2 <= y0) {
/* y2<=y0<=y1 */
setup->vmin = v2;
setup->vmid = v0;
setup->vmax = v1;
}
else {
/* y0<=y2<=y1 */
setup->vmin = v0;
setup->vmid = v2;
setup->vmax = v1;
}
}
else {
if (y0 <= y2) {
/* y1<=y0<=y2 */
setup->vmin = v1;
setup->vmid = v0;
setup->vmax = v2;
}
else if (y2 <= y1) {
/* y2<=y1<=y0 */
setup->vmin = v2;
setup->vmid = v1;
setup->vmax = v0;
}
else {
/* y1<=y2<=y0 */
setup->vmin = v1;
setup->vmid = v2;
setup->vmax = v0;
}
}
}
 
setup->ebot.dx = setup->vmid[0][0] - setup->vmin[0][0];
setup->ebot.dy = setup->vmid[0][1] - setup->vmin[0][1];
setup->emaj.dx = setup->vmax[0][0] - setup->vmin[0][0];
setup->emaj.dy = setup->vmax[0][1] - setup->vmin[0][1];
setup->etop.dx = setup->vmax[0][0] - setup->vmid[0][0];
setup->etop.dy = setup->vmax[0][1] - setup->vmid[0][1];
 
/*
* Compute triangle's area. Use 1/area to compute partial
* derivatives of attributes later.
*
* The area will be the same as prim->det, but the sign may be
* different depending on how the vertices get sorted above.
*
* To determine whether the primitive is front or back facing we
* use the prim->det value because its sign is correct.
*/
{
const float area = (setup->emaj.dx * setup->ebot.dy -
setup->ebot.dx * setup->emaj.dy);
 
setup->oneoverarea = 1.0f / area;
 
/*
debug_printf("%s one-over-area %f area %f det %f\n",
__FUNCTION__, setup->oneoverarea, area, det );
*/
if (util_is_inf_or_nan(setup->oneoverarea))
return FALSE;
}
 
/* We need to know if this is a front or back-facing triangle for:
* - the GLSL gl_FrontFacing fragment attribute (bool)
* - two-sided stencil test
* 0 = front-facing, 1 = back-facing
*/
setup->facing =
((det < 0.0) ^
(setup->softpipe->rasterizer->front_ccw));
 
{
unsigned face = setup->facing == 0 ? PIPE_FACE_FRONT : PIPE_FACE_BACK;
 
if (face & setup->cull_face)
return FALSE;
}
 
 
/* Prepare pixel offset for rasterisation:
* - pixel center (0.5, 0.5) for GL, or
* - assume (0.0, 0.0) for other APIs.
*/
if (setup->softpipe->rasterizer->half_pixel_center) {
setup->pixel_offset = 0.5f;
} else {
setup->pixel_offset = 0.0f;
}
 
return TRUE;
}
 
 
/* Apply cylindrical wrapping to v0, v1, v2 coordinates, if enabled.
* Input coordinates must be in [0, 1] range, otherwise results are undefined.
* Some combinations of coordinates produce invalid results,
* but this behaviour is acceptable.
*/
static void
tri_apply_cylindrical_wrap(float v0,
float v1,
float v2,
uint cylindrical_wrap,
float output[3])
{
if (cylindrical_wrap) {
float delta;
 
delta = v1 - v0;
if (delta > 0.5f) {
v0 += 1.0f;
}
else if (delta < -0.5f) {
v1 += 1.0f;
}
 
delta = v2 - v1;
if (delta > 0.5f) {
v1 += 1.0f;
}
else if (delta < -0.5f) {
v2 += 1.0f;
}
 
delta = v0 - v2;
if (delta > 0.5f) {
v2 += 1.0f;
}
else if (delta < -0.5f) {
v0 += 1.0f;
}
}
 
output[0] = v0;
output[1] = v1;
output[2] = v2;
}
 
 
/**
* Compute a0 for a constant-valued coefficient (GL_FLAT shading).
* The value value comes from vertex[slot][i].
* The result will be put into setup->coef[slot].a0[i].
* \param slot which attribute slot
* \param i which component of the slot (0..3)
*/
static void
const_coeff(struct setup_context *setup,
struct tgsi_interp_coef *coef,
uint vertSlot, uint i)
{
assert(i <= 3);
 
coef->dadx[i] = 0;
coef->dady[i] = 0;
 
/* need provoking vertex info!
*/
coef->a0[i] = setup->vprovoke[vertSlot][i];
}
 
 
/**
* Compute a0, dadx and dady for a linearly interpolated coefficient,
* for a triangle.
* v[0], v[1] and v[2] are vmin, vmid and vmax, respectively.
*/
static void
tri_linear_coeff(struct setup_context *setup,
struct tgsi_interp_coef *coef,
uint i,
const float v[3])
{
float botda = v[1] - v[0];
float majda = v[2] - v[0];
float a = setup->ebot.dy * majda - botda * setup->emaj.dy;
float b = setup->emaj.dx * botda - majda * setup->ebot.dx;
float dadx = a * setup->oneoverarea;
float dady = b * setup->oneoverarea;
 
assert(i <= 3);
 
coef->dadx[i] = dadx;
coef->dady[i] = dady;
 
/* calculate a0 as the value which would be sampled for the
* fragment at (0,0), taking into account that we want to sample at
* pixel centers, in other words (pixel_offset, pixel_offset).
*
* this is neat but unfortunately not a good way to do things for
* triangles with very large values of dadx or dady as it will
* result in the subtraction and re-addition from a0 of a very
* large number, which means we'll end up loosing a lot of the
* fractional bits and precision from a0. the way to fix this is
* to define a0 as the sample at a pixel center somewhere near vmin
* instead - i'll switch to this later.
*/
coef->a0[i] = (v[0] -
(dadx * (setup->vmin[0][0] - setup->pixel_offset) +
dady * (setup->vmin[0][1] - setup->pixel_offset)));
 
/*
debug_printf("attr[%d].%c: %f dx:%f dy:%f\n",
slot, "xyzw"[i],
setup->coef[slot].a0[i],
setup->coef[slot].dadx[i],
setup->coef[slot].dady[i]);
*/
}
 
 
/**
* Compute a0, dadx and dady for a perspective-corrected interpolant,
* for a triangle.
* We basically multiply the vertex value by 1/w before computing
* the plane coefficients (a0, dadx, dady).
* Later, when we compute the value at a particular fragment position we'll
* divide the interpolated value by the interpolated W at that fragment.
* v[0], v[1] and v[2] are vmin, vmid and vmax, respectively.
*/
static void
tri_persp_coeff(struct setup_context *setup,
struct tgsi_interp_coef *coef,
uint i,
const float v[3])
{
/* premultiply by 1/w (v[0][3] is always W):
*/
float mina = v[0] * setup->vmin[0][3];
float mida = v[1] * setup->vmid[0][3];
float maxa = v[2] * setup->vmax[0][3];
float botda = mida - mina;
float majda = maxa - mina;
float a = setup->ebot.dy * majda - botda * setup->emaj.dy;
float b = setup->emaj.dx * botda - majda * setup->ebot.dx;
float dadx = a * setup->oneoverarea;
float dady = b * setup->oneoverarea;
 
/*
debug_printf("tri persp %d,%d: %f %f %f\n", vertSlot, i,
setup->vmin[vertSlot][i],
setup->vmid[vertSlot][i],
setup->vmax[vertSlot][i]
);
*/
assert(i <= 3);
 
coef->dadx[i] = dadx;
coef->dady[i] = dady;
coef->a0[i] = (mina -
(dadx * (setup->vmin[0][0] - setup->pixel_offset) +
dady * (setup->vmin[0][1] - setup->pixel_offset)));
}
 
 
/**
* Special coefficient setup for gl_FragCoord.
* X and Y are trivial, though Y may have to be inverted for OpenGL.
* Z and W are copied from posCoef which should have already been computed.
* We could do a bit less work if we'd examine gl_FragCoord's swizzle mask.
*/
static void
setup_fragcoord_coeff(struct setup_context *setup, uint slot)
{
const struct tgsi_shader_info *fsInfo = &setup->softpipe->fs_variant->info;
 
/*X*/
setup->coef[slot].a0[0] = fsInfo->pixel_center_integer ? 0.0f : 0.5f;
setup->coef[slot].dadx[0] = 1.0f;
setup->coef[slot].dady[0] = 0.0f;
/*Y*/
setup->coef[slot].a0[1] =
(fsInfo->origin_lower_left ? setup->softpipe->framebuffer.height-1 : 0)
+ (fsInfo->pixel_center_integer ? 0.0f : 0.5f);
setup->coef[slot].dadx[1] = 0.0f;
setup->coef[slot].dady[1] = fsInfo->origin_lower_left ? -1.0f : 1.0f;
/*Z*/
setup->coef[slot].a0[2] = setup->posCoef.a0[2];
setup->coef[slot].dadx[2] = setup->posCoef.dadx[2];
setup->coef[slot].dady[2] = setup->posCoef.dady[2];
/*W*/
setup->coef[slot].a0[3] = setup->posCoef.a0[3];
setup->coef[slot].dadx[3] = setup->posCoef.dadx[3];
setup->coef[slot].dady[3] = setup->posCoef.dady[3];
}
 
 
 
/**
* Compute the setup->coef[] array dadx, dady, a0 values.
* Must be called after setup->vmin,vmid,vmax,vprovoke are initialized.
*/
static void
setup_tri_coefficients(struct setup_context *setup)
{
struct softpipe_context *softpipe = setup->softpipe;
const struct tgsi_shader_info *fsInfo = &setup->softpipe->fs_variant->info;
const struct vertex_info *vinfo = softpipe_get_vertex_info(softpipe);
uint fragSlot;
float v[3];
 
/* z and w are done by linear interpolation:
*/
v[0] = setup->vmin[0][2];
v[1] = setup->vmid[0][2];
v[2] = setup->vmax[0][2];
tri_linear_coeff(setup, &setup->posCoef, 2, v);
 
v[0] = setup->vmin[0][3];
v[1] = setup->vmid[0][3];
v[2] = setup->vmax[0][3];
tri_linear_coeff(setup, &setup->posCoef, 3, v);
 
/* setup interpolation for all the remaining attributes:
*/
for (fragSlot = 0; fragSlot < fsInfo->num_inputs; fragSlot++) {
const uint vertSlot = vinfo->attrib[fragSlot].src_index;
uint j;
 
switch (vinfo->attrib[fragSlot].interp_mode) {
case INTERP_CONSTANT:
for (j = 0; j < TGSI_NUM_CHANNELS; j++)
const_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
break;
case INTERP_LINEAR:
for (j = 0; j < TGSI_NUM_CHANNELS; j++) {
tri_apply_cylindrical_wrap(setup->vmin[vertSlot][j],
setup->vmid[vertSlot][j],
setup->vmax[vertSlot][j],
fsInfo->input_cylindrical_wrap[fragSlot] & (1 << j),
v);
tri_linear_coeff(setup, &setup->coef[fragSlot], j, v);
}
break;
case INTERP_PERSPECTIVE:
for (j = 0; j < TGSI_NUM_CHANNELS; j++) {
tri_apply_cylindrical_wrap(setup->vmin[vertSlot][j],
setup->vmid[vertSlot][j],
setup->vmax[vertSlot][j],
fsInfo->input_cylindrical_wrap[fragSlot] & (1 << j),
v);
tri_persp_coeff(setup, &setup->coef[fragSlot], j, v);
}
break;
case INTERP_POS:
setup_fragcoord_coeff(setup, fragSlot);
break;
default:
assert(0);
}
 
if (fsInfo->input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) {
/* convert 0 to 1.0 and 1 to -1.0 */
setup->coef[fragSlot].a0[0] = setup->facing * -2.0f + 1.0f;
setup->coef[fragSlot].dadx[0] = 0.0;
setup->coef[fragSlot].dady[0] = 0.0;
}
}
}
 
 
static void
setup_tri_edges(struct setup_context *setup)
{
float vmin_x = setup->vmin[0][0] + setup->pixel_offset;
float vmid_x = setup->vmid[0][0] + setup->pixel_offset;
 
float vmin_y = setup->vmin[0][1] - setup->pixel_offset;
float vmid_y = setup->vmid[0][1] - setup->pixel_offset;
float vmax_y = setup->vmax[0][1] - setup->pixel_offset;
 
setup->emaj.sy = ceilf(vmin_y);
setup->emaj.lines = (int) ceilf(vmax_y - setup->emaj.sy);
setup->emaj.dxdy = setup->emaj.dy ? setup->emaj.dx / setup->emaj.dy : .0f;
setup->emaj.sx = vmin_x + (setup->emaj.sy - vmin_y) * setup->emaj.dxdy;
 
setup->etop.sy = ceilf(vmid_y);
setup->etop.lines = (int) ceilf(vmax_y - setup->etop.sy);
setup->etop.dxdy = setup->etop.dy ? setup->etop.dx / setup->etop.dy : .0f;
setup->etop.sx = vmid_x + (setup->etop.sy - vmid_y) * setup->etop.dxdy;
 
setup->ebot.sy = ceilf(vmin_y);
setup->ebot.lines = (int) ceilf(vmid_y - setup->ebot.sy);
setup->ebot.dxdy = setup->ebot.dy ? setup->ebot.dx / setup->ebot.dy : .0f;
setup->ebot.sx = vmin_x + (setup->ebot.sy - vmin_y) * setup->ebot.dxdy;
}
 
 
/**
* Render the upper or lower half of a triangle.
* Scissoring/cliprect is applied here too.
*/
static void
subtriangle(struct setup_context *setup,
struct edge *eleft,
struct edge *eright,
int lines)
{
const struct pipe_scissor_state *cliprect = &setup->softpipe->cliprect;
const int minx = (int) cliprect->minx;
const int maxx = (int) cliprect->maxx;
const int miny = (int) cliprect->miny;
const int maxy = (int) cliprect->maxy;
int y, start_y, finish_y;
int sy = (int)eleft->sy;
 
assert((int)eleft->sy == (int) eright->sy);
assert(lines >= 0);
 
/* clip top/bottom */
start_y = sy;
if (start_y < miny)
start_y = miny;
 
finish_y = sy + lines;
if (finish_y > maxy)
finish_y = maxy;
 
start_y -= sy;
finish_y -= sy;
 
/*
debug_printf("%s %d %d\n", __FUNCTION__, start_y, finish_y);
*/
 
for (y = start_y; y < finish_y; y++) {
 
/* avoid accumulating adds as floats don't have the precision to
* accurately iterate large triangle edges that way. luckily we
* can just multiply these days.
*
* this is all drowned out by the attribute interpolation anyway.
*/
int left = (int)(eleft->sx + y * eleft->dxdy);
int right = (int)(eright->sx + y * eright->dxdy);
 
/* clip left/right */
if (left < minx)
left = minx;
if (right > maxx)
right = maxx;
 
if (left < right) {
int _y = sy + y;
if (block(_y) != setup->span.y) {
flush_spans(setup);
setup->span.y = block(_y);
}
 
setup->span.left[_y&1] = left;
setup->span.right[_y&1] = right;
}
}
 
 
/* save the values so that emaj can be restarted:
*/
eleft->sx += lines * eleft->dxdy;
eright->sx += lines * eright->dxdy;
eleft->sy += lines;
eright->sy += lines;
}
 
 
/**
* Recalculate prim's determinant. This is needed as we don't have
* get this information through the vbuf_render interface & we must
* calculate it here.
*/
static float
calc_det(const float (*v0)[4],
const float (*v1)[4],
const float (*v2)[4])
{
/* edge vectors e = v0 - v2, f = v1 - v2 */
const float ex = v0[0][0] - v2[0][0];
const float ey = v0[0][1] - v2[0][1];
const float fx = v1[0][0] - v2[0][0];
const float fy = v1[0][1] - v2[0][1];
 
/* det = cross(e,f).z */
return ex * fy - ey * fx;
}
 
 
/**
* Do setup for triangle rasterization, then render the triangle.
*/
void
sp_setup_tri(struct setup_context *setup,
const float (*v0)[4],
const float (*v1)[4],
const float (*v2)[4])
{
float det;
 
#if DEBUG_VERTS
debug_printf("Setup triangle:\n");
print_vertex(setup, v0);
print_vertex(setup, v1);
print_vertex(setup, v2);
#endif
 
if (setup->softpipe->no_rast || setup->softpipe->rasterizer->rasterizer_discard)
return;
det = calc_det(v0, v1, v2);
/*
debug_printf("%s\n", __FUNCTION__ );
*/
 
#if DEBUG_FRAGS
setup->numFragsEmitted = 0;
setup->numFragsWritten = 0;
#endif
 
if (!setup_sort_vertices( setup, det, v0, v1, v2 ))
return;
 
setup_tri_coefficients( setup );
setup_tri_edges( setup );
 
assert(setup->softpipe->reduced_prim == PIPE_PRIM_TRIANGLES);
 
setup->span.y = 0;
setup->span.right[0] = 0;
setup->span.right[1] = 0;
/* setup->span.z_mode = tri_z_mode( setup->ctx ); */
 
/* init_constant_attribs( setup ); */
 
if (setup->oneoverarea < 0.0) {
/* emaj on left:
*/
subtriangle( setup, &setup->emaj, &setup->ebot, setup->ebot.lines );
subtriangle( setup, &setup->emaj, &setup->etop, setup->etop.lines );
}
else {
/* emaj on right:
*/
subtriangle( setup, &setup->ebot, &setup->emaj, setup->ebot.lines );
subtriangle( setup, &setup->etop, &setup->emaj, setup->etop.lines );
}
 
flush_spans( setup );
 
if (setup->softpipe->active_statistics_queries) {
setup->softpipe->pipeline_statistics.c_primitives++;
}
 
#if DEBUG_FRAGS
printf("Tri: %u frags emitted, %u written\n",
setup->numFragsEmitted,
setup->numFragsWritten);
#endif
}
 
 
/* Apply cylindrical wrapping to v0, v1 coordinates, if enabled.
* Input coordinates must be in [0, 1] range, otherwise results are undefined.
*/
static void
line_apply_cylindrical_wrap(float v0,
float v1,
uint cylindrical_wrap,
float output[2])
{
if (cylindrical_wrap) {
float delta;
 
delta = v1 - v0;
if (delta > 0.5f) {
v0 += 1.0f;
}
else if (delta < -0.5f) {
v1 += 1.0f;
}
}
 
output[0] = v0;
output[1] = v1;
}
 
 
/**
* Compute a0, dadx and dady for a linearly interpolated coefficient,
* for a line.
* v[0] and v[1] are vmin and vmax, respectively.
*/
static void
line_linear_coeff(const struct setup_context *setup,
struct tgsi_interp_coef *coef,
uint i,
const float v[2])
{
const float da = v[1] - v[0];
const float dadx = da * setup->emaj.dx * setup->oneoverarea;
const float dady = da * setup->emaj.dy * setup->oneoverarea;
coef->dadx[i] = dadx;
coef->dady[i] = dady;
coef->a0[i] = (v[0] -
(dadx * (setup->vmin[0][0] - setup->pixel_offset) +
dady * (setup->vmin[0][1] - setup->pixel_offset)));
}
 
 
/**
* Compute a0, dadx and dady for a perspective-corrected interpolant,
* for a line.
* v[0] and v[1] are vmin and vmax, respectively.
*/
static void
line_persp_coeff(const struct setup_context *setup,
struct tgsi_interp_coef *coef,
uint i,
const float v[2])
{
const float a0 = v[0] * setup->vmin[0][3];
const float a1 = v[1] * setup->vmax[0][3];
const float da = a1 - a0;
const float dadx = da * setup->emaj.dx * setup->oneoverarea;
const float dady = da * setup->emaj.dy * setup->oneoverarea;
coef->dadx[i] = dadx;
coef->dady[i] = dady;
coef->a0[i] = (a0 -
(dadx * (setup->vmin[0][0] - setup->pixel_offset) +
dady * (setup->vmin[0][1] - setup->pixel_offset)));
}
 
 
/**
* Compute the setup->coef[] array dadx, dady, a0 values.
* Must be called after setup->vmin,vmax are initialized.
*/
static boolean
setup_line_coefficients(struct setup_context *setup,
const float (*v0)[4],
const float (*v1)[4])
{
struct softpipe_context *softpipe = setup->softpipe;
const struct tgsi_shader_info *fsInfo = &setup->softpipe->fs_variant->info;
const struct vertex_info *vinfo = softpipe_get_vertex_info(softpipe);
uint fragSlot;
float area;
float v[2];
 
/* use setup->vmin, vmax to point to vertices */
if (softpipe->rasterizer->flatshade_first)
setup->vprovoke = v0;
else
setup->vprovoke = v1;
setup->vmin = v0;
setup->vmax = v1;
 
setup->emaj.dx = setup->vmax[0][0] - setup->vmin[0][0];
setup->emaj.dy = setup->vmax[0][1] - setup->vmin[0][1];
 
/* NOTE: this is not really area but something proportional to it */
area = setup->emaj.dx * setup->emaj.dx + setup->emaj.dy * setup->emaj.dy;
if (area == 0.0f || util_is_inf_or_nan(area))
return FALSE;
setup->oneoverarea = 1.0f / area;
 
/* z and w are done by linear interpolation:
*/
v[0] = setup->vmin[0][2];
v[1] = setup->vmax[0][2];
line_linear_coeff(setup, &setup->posCoef, 2, v);
 
v[0] = setup->vmin[0][3];
v[1] = setup->vmax[0][3];
line_linear_coeff(setup, &setup->posCoef, 3, v);
 
/* setup interpolation for all the remaining attributes:
*/
for (fragSlot = 0; fragSlot < fsInfo->num_inputs; fragSlot++) {
const uint vertSlot = vinfo->attrib[fragSlot].src_index;
uint j;
 
switch (vinfo->attrib[fragSlot].interp_mode) {
case INTERP_CONSTANT:
for (j = 0; j < TGSI_NUM_CHANNELS; j++)
const_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
break;
case INTERP_LINEAR:
for (j = 0; j < TGSI_NUM_CHANNELS; j++) {
line_apply_cylindrical_wrap(setup->vmin[vertSlot][j],
setup->vmax[vertSlot][j],
fsInfo->input_cylindrical_wrap[fragSlot] & (1 << j),
v);
line_linear_coeff(setup, &setup->coef[fragSlot], j, v);
}
break;
case INTERP_PERSPECTIVE:
for (j = 0; j < TGSI_NUM_CHANNELS; j++) {
line_apply_cylindrical_wrap(setup->vmin[vertSlot][j],
setup->vmax[vertSlot][j],
fsInfo->input_cylindrical_wrap[fragSlot] & (1 << j),
v);
line_persp_coeff(setup, &setup->coef[fragSlot], j, v);
}
break;
case INTERP_POS:
setup_fragcoord_coeff(setup, fragSlot);
break;
default:
assert(0);
}
 
if (fsInfo->input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) {
/* convert 0 to 1.0 and 1 to -1.0 */
setup->coef[fragSlot].a0[0] = setup->facing * -2.0f + 1.0f;
setup->coef[fragSlot].dadx[0] = 0.0;
setup->coef[fragSlot].dady[0] = 0.0;
}
}
return TRUE;
}
 
 
/**
* Plot a pixel in a line segment.
*/
static INLINE void
plot(struct setup_context *setup, int x, int y)
{
const int iy = y & 1;
const int ix = x & 1;
const int quadX = x - ix;
const int quadY = y - iy;
const int mask = (1 << ix) << (2 * iy);
 
if (quadX != setup->quad[0].input.x0 ||
quadY != setup->quad[0].input.y0)
{
/* flush prev quad, start new quad */
 
if (setup->quad[0].input.x0 != -1)
clip_emit_quad( setup, &setup->quad[0] );
 
setup->quad[0].input.x0 = quadX;
setup->quad[0].input.y0 = quadY;
setup->quad[0].inout.mask = 0x0;
}
 
setup->quad[0].inout.mask |= mask;
}
 
 
/**
* Do setup for line rasterization, then render the line.
* Single-pixel width, no stipple, etc. We rely on the 'draw' module
* to handle stippling and wide lines.
*/
void
sp_setup_line(struct setup_context *setup,
const float (*v0)[4],
const float (*v1)[4])
{
int x0 = (int) v0[0][0];
int x1 = (int) v1[0][0];
int y0 = (int) v0[0][1];
int y1 = (int) v1[0][1];
int dx = x1 - x0;
int dy = y1 - y0;
int xstep, ystep;
 
#if DEBUG_VERTS
debug_printf("Setup line:\n");
print_vertex(setup, v0);
print_vertex(setup, v1);
#endif
 
if (setup->softpipe->no_rast || setup->softpipe->rasterizer->rasterizer_discard)
return;
 
if (dx == 0 && dy == 0)
return;
 
if (!setup_line_coefficients(setup, v0, v1))
return;
 
assert(v0[0][0] < 1.0e9);
assert(v0[0][1] < 1.0e9);
assert(v1[0][0] < 1.0e9);
assert(v1[0][1] < 1.0e9);
 
if (dx < 0) {
dx = -dx; /* make positive */
xstep = -1;
}
else {
xstep = 1;
}
 
if (dy < 0) {
dy = -dy; /* make positive */
ystep = -1;
}
else {
ystep = 1;
}
 
assert(dx >= 0);
assert(dy >= 0);
assert(setup->softpipe->reduced_prim == PIPE_PRIM_LINES);
 
setup->quad[0].input.x0 = setup->quad[0].input.y0 = -1;
setup->quad[0].inout.mask = 0x0;
 
/* XXX temporary: set coverage to 1.0 so the line appears
* if AA mode happens to be enabled.
*/
setup->quad[0].input.coverage[0] =
setup->quad[0].input.coverage[1] =
setup->quad[0].input.coverage[2] =
setup->quad[0].input.coverage[3] = 1.0;
 
if (dx > dy) {
/*** X-major line ***/
int i;
const int errorInc = dy + dy;
int error = errorInc - dx;
const int errorDec = error - dx;
 
for (i = 0; i < dx; i++) {
plot(setup, x0, y0);
 
x0 += xstep;
if (error < 0) {
error += errorInc;
}
else {
error += errorDec;
y0 += ystep;
}
}
}
else {
/*** Y-major line ***/
int i;
const int errorInc = dx + dx;
int error = errorInc - dy;
const int errorDec = error - dy;
 
for (i = 0; i < dy; i++) {
plot(setup, x0, y0);
 
y0 += ystep;
if (error < 0) {
error += errorInc;
}
else {
error += errorDec;
x0 += xstep;
}
}
}
 
/* draw final quad */
if (setup->quad[0].inout.mask) {
clip_emit_quad( setup, &setup->quad[0] );
}
}
 
 
static void
point_persp_coeff(const struct setup_context *setup,
const float (*vert)[4],
struct tgsi_interp_coef *coef,
uint vertSlot, uint i)
{
assert(i <= 3);
coef->dadx[i] = 0.0F;
coef->dady[i] = 0.0F;
coef->a0[i] = vert[vertSlot][i] * vert[0][3];
}
 
 
/**
* Do setup for point rasterization, then render the point.
* Round or square points...
* XXX could optimize a lot for 1-pixel points.
*/
void
sp_setup_point(struct setup_context *setup,
const float (*v0)[4])
{
struct softpipe_context *softpipe = setup->softpipe;
const struct tgsi_shader_info *fsInfo = &setup->softpipe->fs_variant->info;
const int sizeAttr = setup->softpipe->psize_slot;
const float size
= sizeAttr > 0 ? v0[sizeAttr][0]
: setup->softpipe->rasterizer->point_size;
const float halfSize = 0.5F * size;
const boolean round = (boolean) setup->softpipe->rasterizer->point_smooth;
const float x = v0[0][0]; /* Note: data[0] is always position */
const float y = v0[0][1];
const struct vertex_info *vinfo = softpipe_get_vertex_info(softpipe);
uint fragSlot;
 
#if DEBUG_VERTS
debug_printf("Setup point:\n");
print_vertex(setup, v0);
#endif
 
if (setup->softpipe->no_rast || setup->softpipe->rasterizer->rasterizer_discard)
return;
 
assert(setup->softpipe->reduced_prim == PIPE_PRIM_POINTS);
 
/* For points, all interpolants are constant-valued.
* However, for point sprites, we'll need to setup texcoords appropriately.
* XXX: which coefficients are the texcoords???
* We may do point sprites as textured quads...
*
* KW: We don't know which coefficients are texcoords - ultimately
* the choice of what interpolation mode to use for each attribute
* should be determined by the fragment program, using
* per-attribute declaration statements that include interpolation
* mode as a parameter. So either the fragment program will have
* to be adjusted for pointsprite vs normal point behaviour, or
* otherwise a special interpolation mode will have to be defined
* which matches the required behaviour for point sprites. But -
* the latter is not a feature of normal hardware, and as such
* probably should be ruled out on that basis.
*/
setup->vprovoke = v0;
 
/* setup Z, W */
const_coeff(setup, &setup->posCoef, 0, 2);
const_coeff(setup, &setup->posCoef, 0, 3);
 
for (fragSlot = 0; fragSlot < fsInfo->num_inputs; fragSlot++) {
const uint vertSlot = vinfo->attrib[fragSlot].src_index;
uint j;
 
switch (vinfo->attrib[fragSlot].interp_mode) {
case INTERP_CONSTANT:
/* fall-through */
case INTERP_LINEAR:
for (j = 0; j < TGSI_NUM_CHANNELS; j++)
const_coeff(setup, &setup->coef[fragSlot], vertSlot, j);
break;
case INTERP_PERSPECTIVE:
for (j = 0; j < TGSI_NUM_CHANNELS; j++)
point_persp_coeff(setup, setup->vprovoke,
&setup->coef[fragSlot], vertSlot, j);
break;
case INTERP_POS:
setup_fragcoord_coeff(setup, fragSlot);
break;
default:
assert(0);
}
 
if (fsInfo->input_semantic_name[fragSlot] == TGSI_SEMANTIC_FACE) {
/* convert 0 to 1.0 and 1 to -1.0 */
setup->coef[fragSlot].a0[0] = setup->facing * -2.0f + 1.0f;
setup->coef[fragSlot].dadx[0] = 0.0;
setup->coef[fragSlot].dady[0] = 0.0;
}
}
 
 
if (halfSize <= 0.5 && !round) {
/* special case for 1-pixel points */
const int ix = ((int) x) & 1;
const int iy = ((int) y) & 1;
setup->quad[0].input.x0 = (int) x - ix;
setup->quad[0].input.y0 = (int) y - iy;
setup->quad[0].inout.mask = (1 << ix) << (2 * iy);
clip_emit_quad( setup, &setup->quad[0] );
}
else {
if (round) {
/* rounded points */
const int ixmin = block((int) (x - halfSize));
const int ixmax = block((int) (x + halfSize));
const int iymin = block((int) (y - halfSize));
const int iymax = block((int) (y + halfSize));
const float rmin = halfSize - 0.7071F; /* 0.7071 = sqrt(2)/2 */
const float rmax = halfSize + 0.7071F;
const float rmin2 = MAX2(0.0F, rmin * rmin);
const float rmax2 = rmax * rmax;
const float cscale = 1.0F / (rmax2 - rmin2);
int ix, iy;
 
for (iy = iymin; iy <= iymax; iy += 2) {
for (ix = ixmin; ix <= ixmax; ix += 2) {
float dx, dy, dist2, cover;
 
setup->quad[0].inout.mask = 0x0;
 
dx = (ix + 0.5f) - x;
dy = (iy + 0.5f) - y;
dist2 = dx * dx + dy * dy;
if (dist2 <= rmax2) {
cover = 1.0F - (dist2 - rmin2) * cscale;
setup->quad[0].input.coverage[QUAD_TOP_LEFT] = MIN2(cover, 1.0f);
setup->quad[0].inout.mask |= MASK_TOP_LEFT;
}
 
dx = (ix + 1.5f) - x;
dy = (iy + 0.5f) - y;
dist2 = dx * dx + dy * dy;
if (dist2 <= rmax2) {
cover = 1.0F - (dist2 - rmin2) * cscale;
setup->quad[0].input.coverage[QUAD_TOP_RIGHT] = MIN2(cover, 1.0f);
setup->quad[0].inout.mask |= MASK_TOP_RIGHT;
}
 
dx = (ix + 0.5f) - x;
dy = (iy + 1.5f) - y;
dist2 = dx * dx + dy * dy;
if (dist2 <= rmax2) {
cover = 1.0F - (dist2 - rmin2) * cscale;
setup->quad[0].input.coverage[QUAD_BOTTOM_LEFT] = MIN2(cover, 1.0f);
setup->quad[0].inout.mask |= MASK_BOTTOM_LEFT;
}
 
dx = (ix + 1.5f) - x;
dy = (iy + 1.5f) - y;
dist2 = dx * dx + dy * dy;
if (dist2 <= rmax2) {
cover = 1.0F - (dist2 - rmin2) * cscale;
setup->quad[0].input.coverage[QUAD_BOTTOM_RIGHT] = MIN2(cover, 1.0f);
setup->quad[0].inout.mask |= MASK_BOTTOM_RIGHT;
}
 
if (setup->quad[0].inout.mask) {
setup->quad[0].input.x0 = ix;
setup->quad[0].input.y0 = iy;
clip_emit_quad( setup, &setup->quad[0] );
}
}
}
}
else {
/* square points */
const int xmin = (int) (x + 0.75 - halfSize);
const int ymin = (int) (y + 0.25 - halfSize);
const int xmax = xmin + (int) size;
const int ymax = ymin + (int) size;
/* XXX could apply scissor to xmin,ymin,xmax,ymax now */
const int ixmin = block(xmin);
const int ixmax = block(xmax - 1);
const int iymin = block(ymin);
const int iymax = block(ymax - 1);
int ix, iy;
 
/*
debug_printf("(%f, %f) -> X:%d..%d Y:%d..%d\n", x, y, xmin, xmax,ymin,ymax);
*/
for (iy = iymin; iy <= iymax; iy += 2) {
uint rowMask = 0xf;
if (iy < ymin) {
/* above the top edge */
rowMask &= (MASK_BOTTOM_LEFT | MASK_BOTTOM_RIGHT);
}
if (iy + 1 >= ymax) {
/* below the bottom edge */
rowMask &= (MASK_TOP_LEFT | MASK_TOP_RIGHT);
}
 
for (ix = ixmin; ix <= ixmax; ix += 2) {
uint mask = rowMask;
 
if (ix < xmin) {
/* fragment is past left edge of point, turn off left bits */
mask &= (MASK_BOTTOM_RIGHT | MASK_TOP_RIGHT);
}
if (ix + 1 >= xmax) {
/* past the right edge */
mask &= (MASK_BOTTOM_LEFT | MASK_TOP_LEFT);
}
 
setup->quad[0].inout.mask = mask;
setup->quad[0].input.x0 = ix;
setup->quad[0].input.y0 = iy;
clip_emit_quad( setup, &setup->quad[0] );
}
}
}
}
}
 
 
/**
* Called by vbuf code just before we start buffering primitives.
*/
void
sp_setup_prepare(struct setup_context *setup)
{
struct softpipe_context *sp = setup->softpipe;
 
if (sp->dirty) {
softpipe_update_derived(sp, sp->reduced_api_prim);
}
 
/* Note: nr_attrs is only used for debugging (vertex printing) */
setup->nr_vertex_attrs = draw_num_shader_outputs(sp->draw);
 
sp->quad.first->begin( sp->quad.first );
 
if (sp->reduced_api_prim == PIPE_PRIM_TRIANGLES &&
sp->rasterizer->fill_front == PIPE_POLYGON_MODE_FILL &&
sp->rasterizer->fill_back == PIPE_POLYGON_MODE_FILL) {
/* we'll do culling */
setup->cull_face = sp->rasterizer->cull_face;
}
else {
/* 'draw' will do culling */
setup->cull_face = PIPE_FACE_NONE;
}
}
 
 
void
sp_setup_destroy_context(struct setup_context *setup)
{
FREE( setup );
}
 
 
/**
* Create a new primitive setup/render stage.
*/
struct setup_context *
sp_setup_create_context(struct softpipe_context *softpipe)
{
struct setup_context *setup = CALLOC_STRUCT(setup_context);
unsigned i;
 
setup->softpipe = softpipe;
 
for (i = 0; i < MAX_QUADS; i++) {
setup->quad[i].coef = setup->coef;
setup->quad[i].posCoef = &setup->posCoef;
}
 
setup->span.left[0] = 1000000; /* greater than right[0] */
setup->span.left[1] = 1000000; /* greater than right[1] */
 
return setup;
}
/drivers/video/Gallium/drivers/softpipe/sp_setup.h
0,0 → 1,53
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
#ifndef SP_SETUP_H
#define SP_SETUP_H
 
struct setup_context;
struct softpipe_context;
 
void
sp_setup_tri( struct setup_context *setup,
const float (*v0)[4],
const float (*v1)[4],
const float (*v2)[4] );
 
void
sp_setup_line(struct setup_context *setup,
const float (*v0)[4],
const float (*v1)[4]);
 
void
sp_setup_point( struct setup_context *setup,
const float (*v0)[4] );
 
 
struct setup_context *sp_setup_create_context( struct softpipe_context *softpipe );
void sp_setup_prepare( struct setup_context *setup );
void sp_setup_destroy_context( struct setup_context *setup );
 
#endif
/drivers/video/Gallium/drivers/softpipe/sp_state.h
0,0 → 1,196
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/* Authors: Keith Whitwell <keith@tungstengraphics.com>
*/
 
#ifndef SP_STATE_H
#define SP_STATE_H
 
#include "pipe/p_state.h"
#include "tgsi/tgsi_scan.h"
 
 
#define SP_NEW_VIEWPORT 0x1
#define SP_NEW_RASTERIZER 0x2
#define SP_NEW_FS 0x4
#define SP_NEW_BLEND 0x8
#define SP_NEW_CLIP 0x10
#define SP_NEW_SCISSOR 0x20
#define SP_NEW_STIPPLE 0x40
#define SP_NEW_FRAMEBUFFER 0x80
#define SP_NEW_DEPTH_STENCIL_ALPHA 0x100
#define SP_NEW_CONSTANTS 0x200
#define SP_NEW_SAMPLER 0x400
#define SP_NEW_TEXTURE 0x800
#define SP_NEW_VERTEX 0x1000
#define SP_NEW_VS 0x2000
#define SP_NEW_QUERY 0x4000
#define SP_NEW_GS 0x8000
#define SP_NEW_SO 0x10000
#define SP_NEW_SO_BUFFERS 0x20000
 
 
struct tgsi_sampler;
struct tgsi_exec_machine;
struct vertex_info;
 
 
struct sp_fragment_shader_variant_key
{
boolean polygon_stipple;
};
 
 
struct sp_fragment_shader_variant
{
const struct tgsi_token *tokens;
struct sp_fragment_shader_variant_key key;
struct tgsi_shader_info info;
 
unsigned stipple_sampler_unit;
 
/* See comments about this elsewhere */
#if 0
struct draw_fragment_shader *draw_shader;
#endif
 
void (*prepare)(const struct sp_fragment_shader_variant *shader,
struct tgsi_exec_machine *machine,
struct tgsi_sampler *sampler);
 
unsigned (*run)(const struct sp_fragment_shader_variant *shader,
struct tgsi_exec_machine *machine,
struct quad_header *quad);
 
/* Deletes this instance of the object */
void (*delete)(struct sp_fragment_shader_variant *shader,
struct tgsi_exec_machine *machine);
 
struct sp_fragment_shader_variant *next;
};
 
 
/** Subclass of pipe_shader_state */
struct sp_fragment_shader {
struct pipe_shader_state shader;
struct sp_fragment_shader_variant *variants;
struct draw_fragment_shader *draw_shader;
};
 
 
/** Subclass of pipe_shader_state */
struct sp_vertex_shader {
struct pipe_shader_state shader;
struct draw_vertex_shader *draw_data;
int max_sampler; /* -1 if no samplers */
};
 
/** Subclass of pipe_shader_state */
struct sp_geometry_shader {
struct pipe_shader_state shader;
struct draw_geometry_shader *draw_data;
int max_sampler;
};
 
struct sp_velems_state {
unsigned count;
struct pipe_vertex_element velem[PIPE_MAX_ATTRIBS];
};
 
struct sp_so_state {
struct pipe_stream_output_info base;
};
 
 
void
softpipe_init_blend_funcs(struct pipe_context *pipe);
 
void
softpipe_init_clip_funcs(struct pipe_context *pipe);
 
void
softpipe_init_sampler_funcs(struct pipe_context *pipe);
 
void
softpipe_init_rasterizer_funcs(struct pipe_context *pipe);
 
void
softpipe_init_shader_funcs(struct pipe_context *pipe);
 
void
softpipe_init_streamout_funcs(struct pipe_context *pipe);
 
void
softpipe_init_vertex_funcs(struct pipe_context *pipe);
 
void
softpipe_set_framebuffer_state(struct pipe_context *,
const struct pipe_framebuffer_state *);
 
void
softpipe_update_derived(struct softpipe_context *softpipe, unsigned prim);
 
void
softpipe_set_sampler_views(struct pipe_context *pipe,
unsigned shader,
unsigned start,
unsigned num,
struct pipe_sampler_view **views);
 
 
void
softpipe_draw_vbo(struct pipe_context *pipe,
const struct pipe_draw_info *info);
 
void
softpipe_map_texture_surfaces(struct softpipe_context *sp);
 
void
softpipe_unmap_texture_surfaces(struct softpipe_context *sp);
 
 
struct vertex_info *
softpipe_get_vertex_info(struct softpipe_context *softpipe);
 
struct vertex_info *
softpipe_get_vbuf_vertex_info(struct softpipe_context *softpipe);
 
 
struct sp_fragment_shader_variant *
softpipe_find_fs_variant(struct softpipe_context *softpipe,
struct sp_fragment_shader *fs,
const struct sp_fragment_shader_variant_key *key);
 
 
struct sp_fragment_shader_variant *
softpipe_find_fs_variant(struct softpipe_context *softpipe,
struct sp_fragment_shader *fs,
const struct sp_fragment_shader_variant_key *key);
 
 
#endif
/drivers/video/Gallium/drivers/softpipe/sp_state_blend.c
0,0 → 1,150
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/* Authors: Keith Whitwell <keith@tungstengraphics.com>
*/
 
#include "util/u_math.h"
#include "util/u_memory.h"
#include "draw/draw_context.h"
#include "sp_context.h"
#include "sp_state.h"
 
 
static void *
softpipe_create_blend_state(struct pipe_context *pipe,
const struct pipe_blend_state *blend)
{
return mem_dup(blend, sizeof(*blend));
}
 
 
static void
softpipe_bind_blend_state(struct pipe_context *pipe,
void *blend)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
 
draw_flush(softpipe->draw);
 
softpipe->blend = (struct pipe_blend_state *)blend;
 
softpipe->dirty |= SP_NEW_BLEND;
}
 
 
static void
softpipe_delete_blend_state(struct pipe_context *pipe,
void *blend)
{
FREE( blend );
}
 
 
static void
softpipe_set_blend_color(struct pipe_context *pipe,
const struct pipe_blend_color *blend_color)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
unsigned i;
 
draw_flush(softpipe->draw);
 
softpipe->blend_color = *blend_color;
 
/* save clamped color too */
for (i = 0; i < 4; i++)
softpipe->blend_color_clamped.color[i] =
CLAMP(blend_color->color[i], 0.0f, 1.0f);
 
softpipe->dirty |= SP_NEW_BLEND;
}
 
 
static void *
softpipe_create_depth_stencil_state(struct pipe_context *pipe,
const struct pipe_depth_stencil_alpha_state *depth_stencil)
{
return mem_dup(depth_stencil, sizeof(*depth_stencil));
}
 
 
static void
softpipe_bind_depth_stencil_state(struct pipe_context *pipe,
void *depth_stencil)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
 
softpipe->depth_stencil = (struct pipe_depth_stencil_alpha_state *)depth_stencil;
 
softpipe->dirty |= SP_NEW_DEPTH_STENCIL_ALPHA;
}
 
 
static void
softpipe_delete_depth_stencil_state(struct pipe_context *pipe, void *depth)
{
FREE( depth );
}
 
 
static void
softpipe_set_stencil_ref(struct pipe_context *pipe,
const struct pipe_stencil_ref *stencil_ref)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
 
softpipe->stencil_ref = *stencil_ref;
 
softpipe->dirty |= SP_NEW_DEPTH_STENCIL_ALPHA;
}
 
 
static void
softpipe_set_sample_mask(struct pipe_context *pipe,
unsigned sample_mask)
{
}
 
 
void
softpipe_init_blend_funcs(struct pipe_context *pipe)
{
pipe->create_blend_state = softpipe_create_blend_state;
pipe->bind_blend_state = softpipe_bind_blend_state;
pipe->delete_blend_state = softpipe_delete_blend_state;
 
pipe->set_blend_color = softpipe_set_blend_color;
 
pipe->create_depth_stencil_alpha_state = softpipe_create_depth_stencil_state;
pipe->bind_depth_stencil_alpha_state = softpipe_bind_depth_stencil_state;
pipe->delete_depth_stencil_alpha_state = softpipe_delete_depth_stencil_state;
 
pipe->set_stencil_ref = softpipe_set_stencil_ref;
 
pipe->set_sample_mask = softpipe_set_sample_mask;
}
/drivers/video/Gallium/drivers/softpipe/sp_state_clip.c
0,0 → 1,98
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/* Authors: Keith Whitwell <keith@tungstengraphics.com>
*/
#include "sp_context.h"
#include "sp_state.h"
#include "draw/draw_context.h"
 
 
static void
softpipe_set_clip_state(struct pipe_context *pipe,
const struct pipe_clip_state *clip)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
 
/* pass the clip state to the draw module */
draw_set_clip_state(softpipe->draw, clip);
}
 
 
static void
softpipe_set_viewport_states(struct pipe_context *pipe,
unsigned start_slot,
unsigned num_viewports,
const struct pipe_viewport_state *viewport)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
 
/* pass the viewport info to the draw module */
draw_set_viewport_states(softpipe->draw, start_slot, num_viewports,
viewport);
 
softpipe->viewport = *viewport; /* struct copy */
softpipe->dirty |= SP_NEW_VIEWPORT;
}
 
 
static void
softpipe_set_scissor_states(struct pipe_context *pipe,
unsigned start_slot,
unsigned num_scissors,
const struct pipe_scissor_state *scissor)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
 
draw_flush(softpipe->draw);
 
softpipe->scissor = *scissor; /* struct copy */
softpipe->dirty |= SP_NEW_SCISSOR;
}
 
 
static void
softpipe_set_polygon_stipple(struct pipe_context *pipe,
const struct pipe_poly_stipple *stipple)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
 
draw_flush(softpipe->draw);
 
softpipe->poly_stipple = *stipple; /* struct copy */
softpipe->dirty |= SP_NEW_STIPPLE;
}
 
 
void
softpipe_init_clip_funcs(struct pipe_context *pipe)
{
pipe->set_clip_state = softpipe_set_clip_state;
pipe->set_viewport_states = softpipe_set_viewport_states;
pipe->set_scissor_states = softpipe_set_scissor_states;
pipe->set_polygon_stipple = softpipe_set_polygon_stipple;
}
/drivers/video/Gallium/drivers/softpipe/sp_state_derived.c
0,0 → 1,403
/**************************************************************************
*
* Copyright 2003 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.
*
**************************************************************************/
 
#include "util/u_inlines.h"
#include "util/u_math.h"
#include "util/u_memory.h"
#include "util/u_pstipple.h"
#include "pipe/p_shader_tokens.h"
#include "draw/draw_context.h"
#include "draw/draw_vertex.h"
#include "sp_context.h"
#include "sp_screen.h"
#include "sp_state.h"
#include "sp_texture.h"
#include "sp_tex_sample.h"
#include "sp_tex_tile_cache.h"
 
 
/**
* Mark the current vertex layout as "invalid".
* We'll validate the vertex layout later, when we start to actually
* render a point or line or tri.
*/
static void
invalidate_vertex_layout(struct softpipe_context *softpipe)
{
softpipe->vertex_info.num_attribs = 0;
}
 
 
/**
* The vertex info describes how to convert the post-transformed vertices
* (simple float[][4]) used by the 'draw' module into vertices for
* rasterization.
*
* This function validates the vertex layout and returns a pointer to a
* vertex_info object.
*/
struct vertex_info *
softpipe_get_vertex_info(struct softpipe_context *softpipe)
{
struct vertex_info *vinfo = &softpipe->vertex_info;
 
if (vinfo->num_attribs == 0) {
/* compute vertex layout now */
const struct tgsi_shader_info *fsInfo = &softpipe->fs_variant->info;
struct vertex_info *vinfo_vbuf = &softpipe->vertex_info_vbuf;
const uint num = draw_num_shader_outputs(softpipe->draw);
uint i;
 
/* Tell draw_vbuf to simply emit the whole post-xform vertex
* as-is. No longer any need to try and emit draw vertex_header
* info.
*/
vinfo_vbuf->num_attribs = 0;
for (i = 0; i < num; i++) {
draw_emit_vertex_attr(vinfo_vbuf, EMIT_4F, INTERP_PERSPECTIVE, i);
}
draw_compute_vertex_size(vinfo_vbuf);
 
/*
* Loop over fragment shader inputs, searching for the matching output
* from the vertex shader.
*/
vinfo->num_attribs = 0;
for (i = 0; i < fsInfo->num_inputs; i++) {
int src;
enum interp_mode interp = INTERP_LINEAR;
 
switch (fsInfo->input_interpolate[i]) {
case TGSI_INTERPOLATE_CONSTANT:
interp = INTERP_CONSTANT;
break;
case TGSI_INTERPOLATE_LINEAR:
interp = INTERP_LINEAR;
break;
case TGSI_INTERPOLATE_PERSPECTIVE:
interp = INTERP_PERSPECTIVE;
break;
case TGSI_INTERPOLATE_COLOR:
assert(fsInfo->input_semantic_name[i] == TGSI_SEMANTIC_COLOR);
break;
default:
assert(0);
}
 
switch (fsInfo->input_semantic_name[i]) {
case TGSI_SEMANTIC_POSITION:
interp = INTERP_POS;
break;
 
case TGSI_SEMANTIC_COLOR:
if (fsInfo->input_interpolate[i] == TGSI_INTERPOLATE_COLOR) {
if (softpipe->rasterizer->flatshade)
interp = INTERP_CONSTANT;
else
interp = INTERP_PERSPECTIVE;
}
break;
}
 
/* this includes texcoords and varying vars */
src = draw_find_shader_output(softpipe->draw,
fsInfo->input_semantic_name[i],
fsInfo->input_semantic_index[i]);
if (fsInfo->input_semantic_name[i] == TGSI_SEMANTIC_COLOR && src == -1)
/* try and find a bcolor */
src = draw_find_shader_output(softpipe->draw,
TGSI_SEMANTIC_BCOLOR, fsInfo->input_semantic_index[i]);
 
draw_emit_vertex_attr(vinfo, EMIT_4F, interp, src);
}
 
softpipe->psize_slot = draw_find_shader_output(softpipe->draw,
TGSI_SEMANTIC_PSIZE, 0);
if (softpipe->psize_slot >= 0) {
draw_emit_vertex_attr(vinfo, EMIT_4F, INTERP_CONSTANT,
softpipe->psize_slot);
}
 
draw_compute_vertex_size(vinfo);
}
 
return vinfo;
}
 
 
/**
* Called from vbuf module.
*
* Note that there's actually two different vertex layouts in softpipe.
*
* The normal one is computed in softpipe_get_vertex_info() above and is
* used by the point/line/tri "setup" code.
*
* The other one (this one) is only used by the vbuf module (which is
* not normally used by default but used in testing). For the vbuf module,
* we basically want to pass-through the draw module's vertex layout as-is.
* When the softpipe vbuf code begins drawing, the normal vertex layout
* will come into play again.
*/
struct vertex_info *
softpipe_get_vbuf_vertex_info(struct softpipe_context *softpipe)
{
(void) softpipe_get_vertex_info(softpipe);
return &softpipe->vertex_info_vbuf;
}
 
 
/**
* Recompute cliprect from scissor bounds, scissor enable and surface size.
*/
static void
compute_cliprect(struct softpipe_context *sp)
{
/* SP_NEW_FRAMEBUFFER
*/
uint surfWidth = sp->framebuffer.width;
uint surfHeight = sp->framebuffer.height;
 
/* SP_NEW_RASTERIZER
*/
if (sp->rasterizer->scissor) {
 
/* SP_NEW_SCISSOR
*
* clip to scissor rect:
*/
sp->cliprect.minx = MAX2(sp->scissor.minx, 0);
sp->cliprect.miny = MAX2(sp->scissor.miny, 0);
sp->cliprect.maxx = MIN2(sp->scissor.maxx, surfWidth);
sp->cliprect.maxy = MIN2(sp->scissor.maxy, surfHeight);
}
else {
/* clip to surface bounds */
sp->cliprect.minx = 0;
sp->cliprect.miny = 0;
sp->cliprect.maxx = surfWidth;
sp->cliprect.maxy = surfHeight;
}
}
 
 
static void
set_shader_sampler(struct softpipe_context *softpipe,
unsigned shader,
int max_sampler)
{
int i;
for (i = 0; i <= max_sampler; i++) {
softpipe->tgsi.sampler[shader]->sp_sampler[i] =
(struct sp_sampler *)(softpipe->samplers[shader][i]);
}
}
 
static void
update_tgsi_samplers( struct softpipe_context *softpipe )
{
unsigned i, sh;
 
set_shader_sampler(softpipe, PIPE_SHADER_VERTEX,
softpipe->vs->max_sampler);
set_shader_sampler(softpipe, PIPE_SHADER_FRAGMENT,
softpipe->fs_variant->info.file_max[TGSI_FILE_SAMPLER]);
if (softpipe->gs) {
set_shader_sampler(softpipe, PIPE_SHADER_GEOMETRY,
softpipe->gs->max_sampler);
}
 
/* XXX is this really necessary here??? */
for (sh = 0; sh < Elements(softpipe->tex_cache); sh++) {
for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
struct softpipe_tex_tile_cache *tc = softpipe->tex_cache[sh][i];
if (tc && tc->texture) {
struct softpipe_resource *spt = softpipe_resource(tc->texture);
if (spt->timestamp != tc->timestamp) {
sp_tex_tile_cache_validate_texture( tc );
/*
_debug_printf("INV %d %d\n", tc->timestamp, spt->timestamp);
*/
tc->timestamp = spt->timestamp;
}
}
}
}
}
 
 
static void
update_fragment_shader(struct softpipe_context *softpipe, unsigned prim)
{
struct sp_fragment_shader_variant_key key;
 
memset(&key, 0, sizeof(key));
 
if (prim == PIPE_PRIM_TRIANGLES)
key.polygon_stipple = softpipe->rasterizer->poly_stipple_enable;
 
if (softpipe->fs) {
softpipe->fs_variant = softpipe_find_fs_variant(softpipe,
softpipe->fs, &key);
 
/* prepare the TGSI interpreter for FS execution */
softpipe->fs_variant->prepare(softpipe->fs_variant,
softpipe->fs_machine,
(struct tgsi_sampler *) softpipe->
tgsi.sampler[PIPE_SHADER_FRAGMENT]);
}
else {
softpipe->fs_variant = NULL;
}
 
/* This would be the logical place to pass the fragment shader
* to the draw module. However, doing this here, during state
* validation, causes problems with the 'draw' module helpers for
* wide/AA/stippled lines.
* In principle, the draw's fragment shader should be per-variant
* but that doesn't work. So we use a single draw fragment shader
* per fragment shader, not per variant.
*/
#if 0
if (softpipe->fs_variant) {
draw_bind_fragment_shader(softpipe->draw,
softpipe->fs_variant->draw_shader);
}
else {
draw_bind_fragment_shader(softpipe->draw, NULL);
}
#endif
}
 
 
/**
* This should be called when the polygon stipple pattern changes.
* We create a new texture from the stipple pattern and create a new
* sampler view.
*/
static void
update_polygon_stipple_pattern(struct softpipe_context *softpipe)
{
struct pipe_resource *tex;
struct pipe_sampler_view *view;
 
tex = util_pstipple_create_stipple_texture(&softpipe->pipe,
softpipe->poly_stipple.stipple);
pipe_resource_reference(&softpipe->pstipple.texture, tex);
pipe_resource_reference(&tex, NULL);
 
view = util_pstipple_create_sampler_view(&softpipe->pipe,
softpipe->pstipple.texture);
pipe_sampler_view_reference(&softpipe->pstipple.sampler_view, view);
pipe_sampler_view_reference(&view, NULL);
}
 
 
/**
* Should be called when polygon stipple is enabled/disabled or when
* the fragment shader changes.
* We add/update the fragment sampler and sampler views to sample from
* the polygon stipple texture. The texture unit that we use depends on
* the fragment shader (we need to use a unit not otherwise used by the
* shader).
*/
static void
update_polygon_stipple_enable(struct softpipe_context *softpipe, unsigned prim)
{
if (prim == PIPE_PRIM_TRIANGLES &&
softpipe->fs_variant->key.polygon_stipple) {
const unsigned unit = softpipe->fs_variant->stipple_sampler_unit;
 
/* sampler state */
softpipe->samplers[PIPE_SHADER_FRAGMENT][unit] = softpipe->pstipple.sampler;
 
/* sampler view state */
softpipe_set_sampler_views(&softpipe->pipe, PIPE_SHADER_FRAGMENT,
unit, 1, &softpipe->pstipple.sampler_view);
 
softpipe->dirty |= SP_NEW_SAMPLER;
}
}
 
 
/* Hopefully this will remain quite simple, otherwise need to pull in
* something like the state tracker mechanism.
*/
void
softpipe_update_derived(struct softpipe_context *softpipe, unsigned prim)
{
struct softpipe_screen *sp_screen = softpipe_screen(softpipe->pipe.screen);
 
/* Check for updated textures.
*/
if (softpipe->tex_timestamp != sp_screen->timestamp) {
softpipe->tex_timestamp = sp_screen->timestamp;
softpipe->dirty |= SP_NEW_TEXTURE;
}
 
#if DO_PSTIPPLE_IN_HELPER_MODULE
if (softpipe->dirty & SP_NEW_STIPPLE)
/* before updating samplers! */
update_polygon_stipple_pattern(softpipe);
#endif
 
if (softpipe->dirty & (SP_NEW_RASTERIZER |
SP_NEW_FS))
update_fragment_shader(softpipe, prim);
 
#if DO_PSTIPPLE_IN_HELPER_MODULE
if (softpipe->dirty & (SP_NEW_RASTERIZER |
SP_NEW_STIPPLE |
SP_NEW_FS))
update_polygon_stipple_enable(softpipe, prim);
#endif
 
/* TODO: this looks suboptimal */
if (softpipe->dirty & (SP_NEW_SAMPLER |
SP_NEW_TEXTURE |
SP_NEW_FS |
SP_NEW_VS))
update_tgsi_samplers( softpipe );
 
if (softpipe->dirty & (SP_NEW_RASTERIZER |
SP_NEW_FS |
SP_NEW_VS))
invalidate_vertex_layout( softpipe );
 
if (softpipe->dirty & (SP_NEW_SCISSOR |
SP_NEW_RASTERIZER |
SP_NEW_FRAMEBUFFER))
compute_cliprect(softpipe);
 
if (softpipe->dirty & (SP_NEW_BLEND |
SP_NEW_DEPTH_STENCIL_ALPHA |
SP_NEW_FRAMEBUFFER |
SP_NEW_FS))
sp_build_quad_pipeline(softpipe);
 
softpipe->dirty = 0;
}
/drivers/video/Gallium/drivers/softpipe/sp_state_rasterizer.c
0,0 → 1,76
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
#include "pipe/p_defines.h"
#include "util/u_memory.h"
#include "sp_context.h"
#include "sp_state.h"
#include "draw/draw_context.h"
 
 
 
static void *
softpipe_create_rasterizer_state(struct pipe_context *pipe,
const struct pipe_rasterizer_state *rast)
{
return mem_dup(rast, sizeof(*rast));
}
 
 
static void
softpipe_bind_rasterizer_state(struct pipe_context *pipe,
void *rasterizer)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
 
if (softpipe->rasterizer == rasterizer)
return;
 
/* pass-through to draw module */
draw_set_rasterizer_state(softpipe->draw, rasterizer, rasterizer);
 
softpipe->rasterizer = rasterizer;
 
softpipe->dirty |= SP_NEW_RASTERIZER;
}
 
 
static void
softpipe_delete_rasterizer_state(struct pipe_context *pipe,
void *rasterizer)
{
FREE( rasterizer );
}
 
 
void
softpipe_init_rasterizer_funcs(struct pipe_context *pipe)
{
pipe->create_rasterizer_state = softpipe_create_rasterizer_state;
pipe->bind_rasterizer_state = softpipe_bind_rasterizer_state;
pipe->delete_rasterizer_state = softpipe_delete_rasterizer_state;
}
/drivers/video/Gallium/drivers/softpipe/sp_state_sampler.c
0,0 → 1,247
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/* Authors:
* Brian Paul
*/
 
#include "util/u_memory.h"
#include "util/u_inlines.h"
 
#include "draw/draw_context.h"
 
#include "sp_context.h"
#include "sp_state.h"
#include "sp_texture.h"
#include "sp_tex_sample.h"
#include "sp_tex_tile_cache.h"
 
 
/**
* Bind a range [start, start+num-1] of samplers for a shader stage.
*/
static void
softpipe_bind_sampler_states(struct pipe_context *pipe,
unsigned shader,
unsigned start,
unsigned num,
void **samplers)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
unsigned i;
 
assert(shader < PIPE_SHADER_TYPES);
assert(start + num <= Elements(softpipe->samplers[shader]));
 
/* Check for no-op */
if (start + num <= softpipe->num_samplers[shader] &&
!memcmp(softpipe->samplers[shader] + start, samplers,
num * sizeof(void *))) {
return;
}
 
draw_flush(softpipe->draw);
 
/* set the new samplers */
for (i = 0; i < num; i++) {
softpipe->samplers[shader][start + i] = samplers[i];
}
 
/* find highest non-null samplers[] entry */
{
unsigned j = MAX2(softpipe->num_samplers[shader], start + num);
while (j > 0 && softpipe->samplers[shader][j - 1] == NULL)
j--;
softpipe->num_samplers[shader] = j;
}
 
if (shader == PIPE_SHADER_VERTEX || shader == PIPE_SHADER_GEOMETRY) {
draw_set_samplers(softpipe->draw,
shader,
softpipe->samplers[shader],
softpipe->num_samplers[shader]);
}
 
softpipe->dirty |= SP_NEW_SAMPLER;
}
 
 
 
static void
softpipe_bind_fragment_sampler_states(struct pipe_context *pipe,
unsigned num, void **samplers)
{
softpipe_bind_sampler_states(pipe, PIPE_SHADER_FRAGMENT, 0, num, samplers);
}
 
 
static void
softpipe_bind_vertex_sampler_states(struct pipe_context *pipe,
unsigned num,
void **samplers)
{
softpipe_bind_sampler_states(pipe, PIPE_SHADER_VERTEX, 0, num, samplers);
}
 
 
static void
softpipe_bind_geometry_sampler_states(struct pipe_context *pipe,
unsigned num,
void **samplers)
{
softpipe_bind_sampler_states(pipe, PIPE_SHADER_GEOMETRY, 0, num, samplers);
}
 
 
 
static void
softpipe_sampler_view_destroy(struct pipe_context *pipe,
struct pipe_sampler_view *view)
{
pipe_resource_reference(&view->texture, NULL);
FREE(view);
}
 
 
void
softpipe_set_sampler_views(struct pipe_context *pipe,
unsigned shader,
unsigned start,
unsigned num,
struct pipe_sampler_view **views)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
uint i;
 
assert(shader < PIPE_SHADER_TYPES);
assert(start + num <= Elements(softpipe->sampler_views[shader]));
 
/* Check for no-op */
if (start + num <= softpipe->num_sampler_views[shader] &&
!memcmp(softpipe->sampler_views[shader] + start, views,
num * sizeof(struct pipe_sampler_view *))) {
return;
}
 
draw_flush(softpipe->draw);
 
/* set the new sampler views */
for (i = 0; i < num; i++) {
struct sp_sampler_view *sp_sviewsrc;
struct sp_sampler_view *sp_sviewdst =
&softpipe->tgsi.sampler[shader]->sp_sview[start + i];
struct pipe_sampler_view **pview = &softpipe->sampler_views[shader][start + i];
pipe_sampler_view_reference(pview, views[i]);
sp_tex_tile_cache_set_sampler_view(softpipe->tex_cache[shader][start + i],
views[i]);
/*
* We don't really have variants, however some bits are different per shader,
* so just copy?
*/
sp_sviewsrc = (struct sp_sampler_view *)*pview;
if (sp_sviewsrc) {
memcpy(sp_sviewdst, sp_sviewsrc, sizeof(*sp_sviewsrc));
sp_sviewdst->compute_lambda = softpipe_get_lambda_func(&sp_sviewdst->base, shader);
sp_sviewdst->cache = softpipe->tex_cache[shader][start + i];
}
else {
memset(sp_sviewdst, 0, sizeof(*sp_sviewsrc));
}
}
 
 
/* find highest non-null sampler_views[] entry */
{
unsigned j = MAX2(softpipe->num_sampler_views[shader], start + num);
while (j > 0 && softpipe->sampler_views[shader][j - 1] == NULL)
j--;
softpipe->num_sampler_views[shader] = j;
}
 
if (shader == PIPE_SHADER_VERTEX || shader == PIPE_SHADER_GEOMETRY) {
draw_set_sampler_views(softpipe->draw,
shader,
softpipe->sampler_views[shader],
softpipe->num_sampler_views[shader]);
}
 
softpipe->dirty |= SP_NEW_TEXTURE;
}
 
 
static void
softpipe_set_fragment_sampler_views(struct pipe_context *pipe,
unsigned num,
struct pipe_sampler_view **views)
{
softpipe_set_sampler_views(pipe, PIPE_SHADER_FRAGMENT, 0, num, views);
}
 
 
static void
softpipe_set_vertex_sampler_views(struct pipe_context *pipe,
unsigned num,
struct pipe_sampler_view **views)
{
softpipe_set_sampler_views(pipe, PIPE_SHADER_VERTEX, 0, num, views);
}
 
 
static void
softpipe_set_geometry_sampler_views(struct pipe_context *pipe,
unsigned num,
struct pipe_sampler_view **views)
{
softpipe_set_sampler_views(pipe, PIPE_SHADER_GEOMETRY, 0, num, views);
}
 
 
static void
softpipe_delete_sampler_state(struct pipe_context *pipe,
void *sampler)
{
FREE( sampler );
}
 
 
void
softpipe_init_sampler_funcs(struct pipe_context *pipe)
{
pipe->create_sampler_state = softpipe_create_sampler_state;
pipe->bind_fragment_sampler_states = softpipe_bind_fragment_sampler_states;
pipe->bind_vertex_sampler_states = softpipe_bind_vertex_sampler_states;
pipe->bind_geometry_sampler_states = softpipe_bind_geometry_sampler_states;
pipe->delete_sampler_state = softpipe_delete_sampler_state;
 
pipe->set_fragment_sampler_views = softpipe_set_fragment_sampler_views;
pipe->set_vertex_sampler_views = softpipe_set_vertex_sampler_views;
pipe->set_geometry_sampler_views = softpipe_set_geometry_sampler_views;
 
pipe->create_sampler_view = softpipe_create_sampler_view;
pipe->sampler_view_destroy = softpipe_sampler_view_destroy;
}
 
/drivers/video/Gallium/drivers/softpipe/sp_state_shader.c
0,0 → 1,398
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
#include "sp_context.h"
#include "sp_state.h"
#include "sp_fs.h"
#include "sp_texture.h"
 
#include "pipe/p_defines.h"
#include "util/u_memory.h"
#include "util/u_inlines.h"
#include "util/u_pstipple.h"
#include "draw/draw_context.h"
#include "draw/draw_vs.h"
#include "draw/draw_gs.h"
#include "tgsi/tgsi_dump.h"
#include "tgsi/tgsi_scan.h"
#include "tgsi/tgsi_parse.h"
 
 
/**
* Create a new fragment shader variant.
*/
static struct sp_fragment_shader_variant *
create_fs_variant(struct softpipe_context *softpipe,
struct sp_fragment_shader *fs,
const struct sp_fragment_shader_variant_key *key)
{
struct sp_fragment_shader_variant *var;
struct pipe_shader_state *stipple_fs = NULL, *curfs = &fs->shader;
unsigned unit = 0;
 
#if DO_PSTIPPLE_IN_HELPER_MODULE
if (key->polygon_stipple) {
/* get new shader that implements polygon stippling */
stipple_fs = util_pstipple_create_fragment_shader(&softpipe->pipe,
curfs, &unit);
curfs = stipple_fs;
}
#endif
 
/* codegen, create variant object */
var = softpipe_create_fs_variant_exec(softpipe, curfs);
 
if (var) {
var->key = *key;
var->tokens = tgsi_dup_tokens(curfs->tokens);
var->stipple_sampler_unit = unit;
 
tgsi_scan_shader(var->tokens, &var->info);
 
/* See comments elsewhere about draw fragment shaders */
#if 0
/* draw's fs state */
var->draw_shader = draw_create_fragment_shader(softpipe->draw,
&fs->shader);
if (!var->draw_shader) {
var->delete(var);
FREE((void *) var->tokens);
return NULL;
}
#endif
 
/* insert variant into linked list */
var->next = fs->variants;
fs->variants = var;
}
 
if (stipple_fs) {
FREE((void *) stipple_fs->tokens);
FREE(stipple_fs);
}
 
return var;
}
 
 
struct sp_fragment_shader_variant *
softpipe_find_fs_variant(struct softpipe_context *sp,
struct sp_fragment_shader *fs,
const struct sp_fragment_shader_variant_key *key)
{
struct sp_fragment_shader_variant *var;
 
for (var = fs->variants; var; var = var->next) {
if (memcmp(&var->key, key, sizeof(*key)) == 0) {
/* found it */
return var;
}
}
 
return create_fs_variant(sp, fs, key);
}
 
 
static void *
softpipe_create_fs_state(struct pipe_context *pipe,
const struct pipe_shader_state *templ)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
struct sp_fragment_shader *state = CALLOC_STRUCT(sp_fragment_shader);
 
/* debug */
if (softpipe->dump_fs)
tgsi_dump(templ->tokens, 0);
 
/* we need to keep a local copy of the tokens */
state->shader.tokens = tgsi_dup_tokens(templ->tokens);
 
/* draw's fs state */
state->draw_shader = draw_create_fragment_shader(softpipe->draw,
&state->shader);
if (!state->draw_shader) {
FREE((void *) state->shader.tokens);
FREE(state);
return NULL;
}
 
return state;
}
 
 
static void
softpipe_bind_fs_state(struct pipe_context *pipe, void *fs)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
struct sp_fragment_shader *state = (struct sp_fragment_shader *) fs;
 
if (softpipe->fs == fs)
return;
 
draw_flush(softpipe->draw);
 
softpipe->fs = fs;
 
/* This depends on the current fragment shader and must always be
* re-validated before use.
*/
softpipe->fs_variant = NULL;
 
if (state)
draw_bind_fragment_shader(softpipe->draw,
state->draw_shader);
else
draw_bind_fragment_shader(softpipe->draw, NULL);
 
softpipe->dirty |= SP_NEW_FS;
}
 
 
static void
softpipe_delete_fs_state(struct pipe_context *pipe, void *fs)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
struct sp_fragment_shader *state = fs;
struct sp_fragment_shader_variant *var, *next_var;
 
assert(fs != softpipe->fs);
 
/* delete variants */
for (var = state->variants; var; var = next_var) {
next_var = var->next;
 
assert(var != softpipe->fs_variant);
 
/* See comments elsewhere about draw fragment shaders */
#if 0
draw_delete_fragment_shader(softpipe->draw, var->draw_shader);
#endif
 
var->delete(var, softpipe->fs_machine);
}
 
draw_delete_fragment_shader(softpipe->draw, state->draw_shader);
 
FREE((void *) state->shader.tokens);
FREE(state);
}
 
 
static void *
softpipe_create_vs_state(struct pipe_context *pipe,
const struct pipe_shader_state *templ)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
struct sp_vertex_shader *state;
 
state = CALLOC_STRUCT(sp_vertex_shader);
if (state == NULL )
goto fail;
 
/* copy shader tokens, the ones passed in will go away.
*/
state->shader.tokens = tgsi_dup_tokens(templ->tokens);
if (state->shader.tokens == NULL)
goto fail;
 
state->draw_data = draw_create_vertex_shader(softpipe->draw, templ);
if (state->draw_data == NULL)
goto fail;
 
state->max_sampler = state->draw_data->info.file_max[TGSI_FILE_SAMPLER];
 
return state;
 
fail:
if (state) {
FREE( (void *)state->shader.tokens );
FREE( state->draw_data );
FREE( state );
}
return NULL;
}
 
 
static void
softpipe_bind_vs_state(struct pipe_context *pipe, void *vs)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
 
softpipe->vs = (struct sp_vertex_shader *) vs;
 
draw_bind_vertex_shader(softpipe->draw,
(softpipe->vs ? softpipe->vs->draw_data : NULL));
 
softpipe->dirty |= SP_NEW_VS;
}
 
 
static void
softpipe_delete_vs_state(struct pipe_context *pipe, void *vs)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
 
struct sp_vertex_shader *state = (struct sp_vertex_shader *) vs;
 
draw_delete_vertex_shader(softpipe->draw, state->draw_data);
FREE( (void *)state->shader.tokens );
FREE( state );
}
 
 
static void *
softpipe_create_gs_state(struct pipe_context *pipe,
const struct pipe_shader_state *templ)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
struct sp_geometry_shader *state;
 
state = CALLOC_STRUCT(sp_geometry_shader);
if (state == NULL )
goto fail;
 
state->shader = *templ;
 
if (templ->tokens) {
/* debug */
if (softpipe->dump_gs)
tgsi_dump(templ->tokens, 0);
 
/* copy shader tokens, the ones passed in will go away.
*/
state->shader.tokens = tgsi_dup_tokens(templ->tokens);
if (state->shader.tokens == NULL)
goto fail;
 
state->draw_data = draw_create_geometry_shader(softpipe->draw, templ);
if (state->draw_data == NULL)
goto fail;
 
state->max_sampler = state->draw_data->info.file_max[TGSI_FILE_SAMPLER];
}
 
return state;
 
fail:
if (state) {
FREE( (void *)state->shader.tokens );
FREE( state->draw_data );
FREE( state );
}
return NULL;
}
 
 
static void
softpipe_bind_gs_state(struct pipe_context *pipe, void *gs)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
 
softpipe->gs = (struct sp_geometry_shader *)gs;
 
draw_bind_geometry_shader(softpipe->draw,
(softpipe->gs ? softpipe->gs->draw_data : NULL));
 
softpipe->dirty |= SP_NEW_GS;
}
 
 
static void
softpipe_delete_gs_state(struct pipe_context *pipe, void *gs)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
 
struct sp_geometry_shader *state =
(struct sp_geometry_shader *)gs;
 
draw_delete_geometry_shader(softpipe->draw,
(state) ? state->draw_data : 0);
 
FREE((void *) state->shader.tokens);
FREE(state);
}
 
 
static void
softpipe_set_constant_buffer(struct pipe_context *pipe,
uint shader, uint index,
struct pipe_constant_buffer *cb)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
struct pipe_resource *constants = cb ? cb->buffer : NULL;
unsigned size;
const void *data;
 
if (cb && cb->user_buffer) {
constants = softpipe_user_buffer_create(pipe->screen,
(void *) cb->user_buffer,
cb->buffer_size,
PIPE_BIND_CONSTANT_BUFFER);
}
 
size = constants ? constants->width0 : 0;
data = constants ? softpipe_resource(constants)->data : NULL;
 
assert(shader < PIPE_SHADER_TYPES);
 
draw_flush(softpipe->draw);
 
/* note: reference counting */
pipe_resource_reference(&softpipe->constants[shader][index], constants);
 
if (shader == PIPE_SHADER_VERTEX || shader == PIPE_SHADER_GEOMETRY) {
draw_set_mapped_constant_buffer(softpipe->draw, shader, index, data, size);
}
 
softpipe->mapped_constants[shader][index] = data;
softpipe->const_buffer_size[shader][index] = size;
 
softpipe->dirty |= SP_NEW_CONSTANTS;
 
if (cb && cb->user_buffer) {
pipe_resource_reference(&constants, NULL);
}
}
 
 
void
softpipe_init_shader_funcs(struct pipe_context *pipe)
{
pipe->create_fs_state = softpipe_create_fs_state;
pipe->bind_fs_state = softpipe_bind_fs_state;
pipe->delete_fs_state = softpipe_delete_fs_state;
 
pipe->create_vs_state = softpipe_create_vs_state;
pipe->bind_vs_state = softpipe_bind_vs_state;
pipe->delete_vs_state = softpipe_delete_vs_state;
 
pipe->create_gs_state = softpipe_create_gs_state;
pipe->bind_gs_state = softpipe_bind_gs_state;
pipe->delete_gs_state = softpipe_delete_gs_state;
 
pipe->set_constant_buffer = softpipe_set_constant_buffer;
}
/drivers/video/Gallium/drivers/softpipe/sp_state_so.c
0,0 → 1,89
/**************************************************************************
*
* Copyright 2010 VMware, Inc.
* 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.
*
**************************************************************************/
 
#include "sp_context.h"
#include "sp_state.h"
#include "sp_texture.h"
 
#include "util/u_format.h"
#include "util/u_memory.h"
#include "draw/draw_context.h"
#include "pipebuffer/pb_buffer.h"
 
static struct pipe_stream_output_target *
softpipe_create_so_target(struct pipe_context *pipe,
struct pipe_resource *buffer,
unsigned buffer_offset,
unsigned buffer_size)
{
struct draw_so_target *t;
 
t = CALLOC_STRUCT(draw_so_target);
t->target.context = pipe;
t->target.reference.count = 1;
pipe_resource_reference(&t->target.buffer, buffer);
t->target.buffer_offset = buffer_offset;
t->target.buffer_size = buffer_size;
return &t->target;
}
 
static void
softpipe_so_target_destroy(struct pipe_context *pipe,
struct pipe_stream_output_target *target)
{
pipe_resource_reference(&target->buffer, NULL);
FREE(target);
}
 
static void
softpipe_set_so_targets(struct pipe_context *pipe,
unsigned num_targets,
struct pipe_stream_output_target **targets,
unsigned append_bitmask)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
unsigned i;
 
for (i = 0; i < num_targets; i++) {
pipe_so_target_reference((struct pipe_stream_output_target **)&softpipe->so_targets[i], targets[i]);
}
 
for (; i < softpipe->num_so_targets; i++) {
pipe_so_target_reference((struct pipe_stream_output_target **)&softpipe->so_targets[i], NULL);
}
 
softpipe->num_so_targets = num_targets;
}
 
void
softpipe_init_streamout_funcs(struct pipe_context *pipe)
{
pipe->create_stream_output_target = softpipe_create_so_target;
pipe->stream_output_target_destroy = softpipe_so_target_destroy;
pipe->set_stream_output_targets = softpipe_set_so_targets;
}
 
/drivers/video/Gallium/drivers/softpipe/sp_state_surface.c
0,0 → 1,106
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/* Authors: Keith Whitwell <keith@tungstengraphics.com>
*/
 
#include "sp_context.h"
#include "sp_state.h"
#include "sp_tile_cache.h"
 
#include "draw/draw_context.h"
 
#include "util/u_format.h"
#include "util/u_inlines.h"
 
 
/**
* XXX this might get moved someday
* Set the framebuffer surface info: color buffers, zbuffer, stencil buffer.
* Here, we flush the old surfaces and update the tile cache to point to the new
* surfaces.
*/
void
softpipe_set_framebuffer_state(struct pipe_context *pipe,
const struct pipe_framebuffer_state *fb)
{
struct softpipe_context *sp = softpipe_context(pipe);
uint i;
 
draw_flush(sp->draw);
 
for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
struct pipe_surface *cb = i < fb->nr_cbufs ? fb->cbufs[i] : NULL;
 
/* check if changing cbuf */
if (sp->framebuffer.cbufs[i] != cb) {
/* flush old */
sp_flush_tile_cache(sp->cbuf_cache[i]);
 
/* assign new */
pipe_surface_reference(&sp->framebuffer.cbufs[i], cb);
 
/* update cache */
sp_tile_cache_set_surface(sp->cbuf_cache[i], cb);
}
}
 
sp->framebuffer.nr_cbufs = fb->nr_cbufs;
 
/* zbuf changing? */
if (sp->framebuffer.zsbuf != fb->zsbuf) {
/* flush old */
sp_flush_tile_cache(sp->zsbuf_cache);
 
/* assign new */
pipe_surface_reference(&sp->framebuffer.zsbuf, fb->zsbuf);
 
/* update cache */
sp_tile_cache_set_surface(sp->zsbuf_cache, fb->zsbuf);
 
/* Tell draw module how deep the Z/depth buffer is */
if (sp->framebuffer.zsbuf) {
int depth_bits;
double mrd;
depth_bits = util_format_get_component_bits(sp->framebuffer.zsbuf->format,
UTIL_FORMAT_COLORSPACE_ZS,
0);
if (depth_bits > 16) {
mrd = 0.0000001;
}
else {
mrd = 0.00002;
}
draw_set_mrd(sp->draw, mrd);
}
}
 
sp->framebuffer.width = fb->width;
sp->framebuffer.height = fb->height;
 
sp->dirty |= SP_NEW_FRAMEBUFFER;
}
/drivers/video/Gallium/drivers/softpipe/sp_state_vertex.c
0,0 → 1,122
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/* Authors: Keith Whitwell <keith@tungstengraphics.com>
*/
 
 
#include "sp_context.h"
#include "sp_state.h"
 
#include "util/u_memory.h"
#include "util/u_helpers.h"
#include "util/u_inlines.h"
#include "util/u_transfer.h"
#include "draw/draw_context.h"
 
 
static void *
softpipe_create_vertex_elements_state(struct pipe_context *pipe,
unsigned count,
const struct pipe_vertex_element *attribs)
{
struct sp_velems_state *velems;
assert(count <= PIPE_MAX_ATTRIBS);
velems = (struct sp_velems_state *) MALLOC(sizeof(struct sp_velems_state));
if (velems) {
velems->count = count;
memcpy(velems->velem, attribs, sizeof(*attribs) * count);
}
return velems;
}
 
 
static void
softpipe_bind_vertex_elements_state(struct pipe_context *pipe,
void *velems)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
struct sp_velems_state *sp_velems = (struct sp_velems_state *) velems;
 
softpipe->velems = sp_velems;
 
softpipe->dirty |= SP_NEW_VERTEX;
 
if (sp_velems)
draw_set_vertex_elements(softpipe->draw, sp_velems->count, sp_velems->velem);
}
 
 
static void
softpipe_delete_vertex_elements_state(struct pipe_context *pipe, void *velems)
{
FREE( velems );
}
 
 
static void
softpipe_set_vertex_buffers(struct pipe_context *pipe,
unsigned start_slot, unsigned count,
const struct pipe_vertex_buffer *buffers)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
 
assert(count <= PIPE_MAX_ATTRIBS);
 
util_set_vertex_buffers_count(softpipe->vertex_buffer,
&softpipe->num_vertex_buffers,
buffers, start_slot, count);
 
softpipe->dirty |= SP_NEW_VERTEX;
 
draw_set_vertex_buffers(softpipe->draw, start_slot, count, buffers);
}
 
 
static void
softpipe_set_index_buffer(struct pipe_context *pipe,
const struct pipe_index_buffer *ib)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
 
if (ib)
memcpy(&softpipe->index_buffer, ib, sizeof(softpipe->index_buffer));
else
memset(&softpipe->index_buffer, 0, sizeof(softpipe->index_buffer));
}
 
 
void
softpipe_init_vertex_funcs(struct pipe_context *pipe)
{
pipe->create_vertex_elements_state = softpipe_create_vertex_elements_state;
pipe->bind_vertex_elements_state = softpipe_bind_vertex_elements_state;
pipe->delete_vertex_elements_state = softpipe_delete_vertex_elements_state;
 
pipe->set_vertex_buffers = softpipe_set_vertex_buffers;
pipe->set_index_buffer = softpipe_set_index_buffer;
}
/drivers/video/Gallium/drivers/softpipe/sp_surface.c
0,0 → 1,130
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
#include "util/u_format.h"
#include "util/u_surface.h"
#include "sp_context.h"
#include "sp_surface.h"
#include "sp_query.h"
 
static void sp_blit(struct pipe_context *pipe,
const struct pipe_blit_info *info)
{
struct softpipe_context *sp = softpipe_context(pipe);
 
if (info->src.resource->nr_samples > 1 &&
info->dst.resource->nr_samples <= 1 &&
!util_format_is_depth_or_stencil(info->src.resource->format) &&
!util_format_is_pure_integer(info->src.resource->format)) {
debug_printf("softpipe: color resolve unimplemented\n");
return;
}
 
if (util_try_blit_via_copy_region(pipe, info)) {
return; /* done */
}
 
if (!util_blitter_is_blit_supported(sp->blitter, info)) {
debug_printf("softpipe: blit unsupported %s -> %s\n",
util_format_short_name(info->src.resource->format),
util_format_short_name(info->dst.resource->format));
return;
}
 
/* XXX turn off occlusion and streamout queries */
 
util_blitter_save_vertex_buffer_slot(sp->blitter, sp->vertex_buffer);
util_blitter_save_vertex_elements(sp->blitter, sp->velems);
util_blitter_save_vertex_shader(sp->blitter, sp->vs);
util_blitter_save_geometry_shader(sp->blitter, sp->gs);
util_blitter_save_so_targets(sp->blitter, sp->num_so_targets,
(struct pipe_stream_output_target**)sp->so_targets);
util_blitter_save_rasterizer(sp->blitter, sp->rasterizer);
util_blitter_save_viewport(sp->blitter, &sp->viewport);
util_blitter_save_scissor(sp->blitter, &sp->scissor);
util_blitter_save_fragment_shader(sp->blitter, sp->fs);
util_blitter_save_blend(sp->blitter, sp->blend);
util_blitter_save_depth_stencil_alpha(sp->blitter, sp->depth_stencil);
util_blitter_save_stencil_ref(sp->blitter, &sp->stencil_ref);
/*util_blitter_save_sample_mask(sp->blitter, sp->sample_mask);*/
util_blitter_save_framebuffer(sp->blitter, &sp->framebuffer);
util_blitter_save_fragment_sampler_states(sp->blitter,
sp->num_samplers[PIPE_SHADER_FRAGMENT],
(void**)sp->samplers[PIPE_SHADER_FRAGMENT]);
util_blitter_save_fragment_sampler_views(sp->blitter,
sp->num_sampler_views[PIPE_SHADER_FRAGMENT],
sp->sampler_views[PIPE_SHADER_FRAGMENT]);
util_blitter_save_render_condition(sp->blitter, sp->render_cond_query,
sp->render_cond_cond, sp->render_cond_mode);
util_blitter_blit(sp->blitter, info);
}
 
static void
softpipe_clear_render_target(struct pipe_context *pipe,
struct pipe_surface *dst,
const union pipe_color_union *color,
unsigned dstx, unsigned dsty,
unsigned width, unsigned height)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
 
if (!softpipe_check_render_cond(softpipe))
return;
 
util_clear_render_target(pipe, dst, color,
dstx, dsty, width, height);
}
 
 
static void
softpipe_clear_depth_stencil(struct pipe_context *pipe,
struct pipe_surface *dst,
unsigned clear_flags,
double depth,
unsigned stencil,
unsigned dstx, unsigned dsty,
unsigned width, unsigned height)
{
struct softpipe_context *softpipe = softpipe_context(pipe);
 
if (!softpipe_check_render_cond(softpipe))
return;
 
util_clear_depth_stencil(pipe, dst, clear_flags,
depth, stencil,
dstx, dsty, width, height);
}
 
 
void
sp_init_surface_functions(struct softpipe_context *sp)
{
sp->pipe.resource_copy_region = util_resource_copy_region;
sp->pipe.clear_render_target = softpipe_clear_render_target;
sp->pipe.clear_depth_stencil = softpipe_clear_depth_stencil;
sp->pipe.blit = sp_blit;
}
/drivers/video/Gallium/drivers/softpipe/sp_surface.h
0,0 → 1,42
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/* Authors: Keith Whitwell <keith@tungstengraphics.com>
*/
 
#ifndef SP_SURFACE_H
#define SP_SURFACE_H
 
 
struct softpipe_context;
 
 
extern void
sp_init_surface_functions(struct softpipe_context *sp);
 
 
#endif /* SP_SURFACE_H */
/drivers/video/Gallium/drivers/softpipe/sp_tex_sample.c
0,0 → 1,3157
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
* Copyright 2008-2010 VMware, Inc. 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.
*
**************************************************************************/
 
/**
* Texture sampling
*
* Authors:
* Brian Paul
* Keith Whitwell
*/
 
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "pipe/p_shader_tokens.h"
#include "util/u_math.h"
#include "util/u_format.h"
#include "util/u_memory.h"
#include "util/u_inlines.h"
#include "sp_quad.h" /* only for #define QUAD_* tokens */
#include "sp_tex_sample.h"
#include "sp_texture.h"
#include "sp_tex_tile_cache.h"
 
 
/** Set to one to help debug texture sampling */
#define DEBUG_TEX 0
 
 
/*
* Return fractional part of 'f'. Used for computing interpolation weights.
* Need to be careful with negative values.
* Note, if this function isn't perfect you'll sometimes see 1-pixel bands
* of improperly weighted linear-filtered textures.
* The tests/texwrap.c demo is a good test.
*/
static INLINE float
frac(float f)
{
return f - floorf(f);
}
 
 
 
/**
* Linear interpolation macro
*/
static INLINE float
lerp(float a, float v0, float v1)
{
return v0 + a * (v1 - v0);
}
 
 
/**
* Do 2D/bilinear interpolation of float values.
* v00, v10, v01 and v11 are typically four texture samples in a square/box.
* a and b are the horizontal and vertical interpolants.
* It's important that this function is inlined when compiled with
* optimization! If we find that's not true on some systems, convert
* to a macro.
*/
static INLINE float
lerp_2d(float a, float b,
float v00, float v10, float v01, float v11)
{
const float temp0 = lerp(a, v00, v10);
const float temp1 = lerp(a, v01, v11);
return lerp(b, temp0, temp1);
}
 
 
/**
* As above, but 3D interpolation of 8 values.
*/
static INLINE float
lerp_3d(float a, float b, float c,
float v000, float v100, float v010, float v110,
float v001, float v101, float v011, float v111)
{
const float temp0 = lerp_2d(a, b, v000, v100, v010, v110);
const float temp1 = lerp_2d(a, b, v001, v101, v011, v111);
return lerp(c, temp0, temp1);
}
 
 
 
/**
* Compute coord % size for repeat wrap modes.
* Note that if coord is negative, coord % size doesn't give the right
* value. To avoid that problem we add a large multiple of the size
* (rather than using a conditional).
*/
static INLINE int
repeat(int coord, unsigned size)
{
return (coord + size * 1024) % size;
}
 
 
/**
* Apply texture coord wrapping mode and return integer texture indexes
* for a vector of four texcoords (S or T or P).
* \param wrapMode PIPE_TEX_WRAP_x
* \param s the incoming texcoords
* \param size the texture image size
* \param icoord returns the integer texcoords
*/
static void
wrap_nearest_repeat(float s, unsigned size, int *icoord)
{
/* s limited to [0,1) */
/* i limited to [0,size-1] */
int i = util_ifloor(s * size);
*icoord = repeat(i, size);
}
 
 
static void
wrap_nearest_clamp(float s, unsigned size, int *icoord)
{
/* s limited to [0,1] */
/* i limited to [0,size-1] */
if (s <= 0.0F)
*icoord = 0;
else if (s >= 1.0F)
*icoord = size - 1;
else
*icoord = util_ifloor(s * size);
}
 
 
static void
wrap_nearest_clamp_to_edge(float s, unsigned size, int *icoord)
{
/* s limited to [min,max] */
/* i limited to [0, size-1] */
const float min = 1.0F / (2.0F * size);
const float max = 1.0F - min;
if (s < min)
*icoord = 0;
else if (s > max)
*icoord = size - 1;
else
*icoord = util_ifloor(s * size);
}
 
 
static void
wrap_nearest_clamp_to_border(float s, unsigned size, int *icoord)
{
/* s limited to [min,max] */
/* i limited to [-1, size] */
const float min = -1.0F / (2.0F * size);
const float max = 1.0F - min;
if (s <= min)
*icoord = -1;
else if (s >= max)
*icoord = size;
else
*icoord = util_ifloor(s * size);
}
 
 
static void
wrap_nearest_mirror_repeat(float s, unsigned size, int *icoord)
{
const float min = 1.0F / (2.0F * size);
const float max = 1.0F - min;
const int flr = util_ifloor(s);
float u = frac(s);
if (flr & 1)
u = 1.0F - u;
if (u < min)
*icoord = 0;
else if (u > max)
*icoord = size - 1;
else
*icoord = util_ifloor(u * size);
}
 
 
static void
wrap_nearest_mirror_clamp(float s, unsigned size, int *icoord)
{
/* s limited to [0,1] */
/* i limited to [0,size-1] */
const float u = fabsf(s);
if (u <= 0.0F)
*icoord = 0;
else if (u >= 1.0F)
*icoord = size - 1;
else
*icoord = util_ifloor(u * size);
}
 
 
static void
wrap_nearest_mirror_clamp_to_edge(float s, unsigned size, int *icoord)
{
/* s limited to [min,max] */
/* i limited to [0, size-1] */
const float min = 1.0F / (2.0F * size);
const float max = 1.0F - min;
const float u = fabsf(s);
if (u < min)
*icoord = 0;
else if (u > max)
*icoord = size - 1;
else
*icoord = util_ifloor(u * size);
}
 
 
static void
wrap_nearest_mirror_clamp_to_border(float s, unsigned size, int *icoord)
{
/* s limited to [min,max] */
/* i limited to [0, size-1] */
const float min = -1.0F / (2.0F * size);
const float max = 1.0F - min;
const float u = fabsf(s);
if (u < min)
*icoord = -1;
else if (u > max)
*icoord = size;
else
*icoord = util_ifloor(u * size);
}
 
 
/**
* Used to compute texel locations for linear sampling
* \param wrapMode PIPE_TEX_WRAP_x
* \param s the texcoord
* \param size the texture image size
* \param icoord0 returns first texture index
* \param icoord1 returns second texture index (usually icoord0 + 1)
* \param w returns blend factor/weight between texture indices
* \param icoord returns the computed integer texture coord
*/
static void
wrap_linear_repeat(float s, unsigned size,
int *icoord0, int *icoord1, float *w)
{
float u = s * size - 0.5F;
*icoord0 = repeat(util_ifloor(u), size);
*icoord1 = repeat(*icoord0 + 1, size);
*w = frac(u);
}
 
 
static void
wrap_linear_clamp(float s, unsigned size,
int *icoord0, int *icoord1, float *w)
{
float u = CLAMP(s, 0.0F, 1.0F);
u = u * size - 0.5f;
*icoord0 = util_ifloor(u);
*icoord1 = *icoord0 + 1;
*w = frac(u);
}
 
 
static void
wrap_linear_clamp_to_edge(float s, unsigned size,
int *icoord0, int *icoord1, float *w)
{
float u = CLAMP(s, 0.0F, 1.0F);
u = u * size - 0.5f;
*icoord0 = util_ifloor(u);
*icoord1 = *icoord0 + 1;
if (*icoord0 < 0)
*icoord0 = 0;
if (*icoord1 >= (int) size)
*icoord1 = size - 1;
*w = frac(u);
}
 
 
static void
wrap_linear_clamp_to_border(float s, unsigned size,
int *icoord0, int *icoord1, float *w)
{
const float min = -1.0F / (2.0F * size);
const float max = 1.0F - min;
float u = CLAMP(s, min, max);
u = u * size - 0.5f;
*icoord0 = util_ifloor(u);
*icoord1 = *icoord0 + 1;
*w = frac(u);
}
 
 
static void
wrap_linear_mirror_repeat(float s, unsigned size,
int *icoord0, int *icoord1, float *w)
{
const int flr = util_ifloor(s);
float u = frac(s);
if (flr & 1)
u = 1.0F - u;
u = u * size - 0.5F;
*icoord0 = util_ifloor(u);
*icoord1 = *icoord0 + 1;
if (*icoord0 < 0)
*icoord0 = 0;
if (*icoord1 >= (int) size)
*icoord1 = size - 1;
*w = frac(u);
}
 
 
static void
wrap_linear_mirror_clamp(float s, unsigned size,
int *icoord0, int *icoord1, float *w)
{
float u = fabsf(s);
if (u >= 1.0F)
u = (float) size;
else
u *= size;
u -= 0.5F;
*icoord0 = util_ifloor(u);
*icoord1 = *icoord0 + 1;
*w = frac(u);
}
 
 
static void
wrap_linear_mirror_clamp_to_edge(float s, unsigned size,
int *icoord0, int *icoord1, float *w)
{
float u = fabsf(s);
if (u >= 1.0F)
u = (float) size;
else
u *= size;
u -= 0.5F;
*icoord0 = util_ifloor(u);
*icoord1 = *icoord0 + 1;
if (*icoord0 < 0)
*icoord0 = 0;
if (*icoord1 >= (int) size)
*icoord1 = size - 1;
*w = frac(u);
}
 
 
static void
wrap_linear_mirror_clamp_to_border(float s, unsigned size,
int *icoord0, int *icoord1, float *w)
{
const float min = -1.0F / (2.0F * size);
const float max = 1.0F - min;
float u = fabsf(s);
if (u <= min)
u = min * size;
else if (u >= max)
u = max * size;
else
u *= size;
u -= 0.5F;
*icoord0 = util_ifloor(u);
*icoord1 = *icoord0 + 1;
*w = frac(u);
}
 
 
/**
* PIPE_TEX_WRAP_CLAMP for nearest sampling, unnormalized coords.
*/
static void
wrap_nearest_unorm_clamp(float s, unsigned size, int *icoord)
{
int i = util_ifloor(s);
*icoord = CLAMP(i, 0, (int) size-1);
}
 
 
/**
* PIPE_TEX_WRAP_CLAMP_TO_BORDER for nearest sampling, unnormalized coords.
*/
static void
wrap_nearest_unorm_clamp_to_border(float s, unsigned size, int *icoord)
{
*icoord = util_ifloor( CLAMP(s, -0.5F, (float) size + 0.5F) );
}
 
 
/**
* PIPE_TEX_WRAP_CLAMP_TO_EDGE for nearest sampling, unnormalized coords.
*/
static void
wrap_nearest_unorm_clamp_to_edge(float s, unsigned size, int *icoord)
{
*icoord = util_ifloor( CLAMP(s, 0.5F, (float) size - 0.5F) );
}
 
 
/**
* PIPE_TEX_WRAP_CLAMP for linear sampling, unnormalized coords.
*/
static void
wrap_linear_unorm_clamp(float s, unsigned size,
int *icoord0, int *icoord1, float *w)
{
/* Not exactly what the spec says, but it matches NVIDIA output */
float u = CLAMP(s - 0.5F, 0.0f, (float) size - 1.0f);
*icoord0 = util_ifloor(u);
*icoord1 = *icoord0 + 1;
*w = frac(u);
}
 
 
/**
* PIPE_TEX_WRAP_CLAMP_TO_BORDER for linear sampling, unnormalized coords.
*/
static void
wrap_linear_unorm_clamp_to_border(float s, unsigned size,
int *icoord0, int *icoord1, float *w)
{
float u = CLAMP(s, -0.5F, (float) size + 0.5F);
u -= 0.5F;
*icoord0 = util_ifloor(u);
*icoord1 = *icoord0 + 1;
if (*icoord1 > (int) size - 1)
*icoord1 = size - 1;
*w = frac(u);
}
 
 
/**
* PIPE_TEX_WRAP_CLAMP_TO_EDGE for linear sampling, unnormalized coords.
*/
static void
wrap_linear_unorm_clamp_to_edge(float s, unsigned size,
int *icoord0, int *icoord1, float *w)
{
float u = CLAMP(s, +0.5F, (float) size - 0.5F);
u -= 0.5F;
*icoord0 = util_ifloor(u);
*icoord1 = *icoord0 + 1;
if (*icoord1 > (int) size - 1)
*icoord1 = size - 1;
*w = frac(u);
}
 
 
/**
* Do coordinate to array index conversion. For array textures.
*/
static INLINE void
wrap_array_layer(float coord, unsigned size, int *layer)
{
int c = util_ifloor(coord + 0.5F);
*layer = CLAMP(c, 0, (int) size - 1);
}
 
 
/**
* Examine the quad's texture coordinates to compute the partial
* derivatives w.r.t X and Y, then compute lambda (level of detail).
*/
static float
compute_lambda_1d(const struct sp_sampler_view *sview,
const float s[TGSI_QUAD_SIZE],
const float t[TGSI_QUAD_SIZE],
const float p[TGSI_QUAD_SIZE])
{
const struct pipe_resource *texture = sview->base.texture;
float dsdx = fabsf(s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]);
float dsdy = fabsf(s[QUAD_TOP_LEFT] - s[QUAD_BOTTOM_LEFT]);
float rho = MAX2(dsdx, dsdy) * u_minify(texture->width0, sview->base.u.tex.first_level);
 
return util_fast_log2(rho);
}
 
 
static float
compute_lambda_2d(const struct sp_sampler_view *sview,
const float s[TGSI_QUAD_SIZE],
const float t[TGSI_QUAD_SIZE],
const float p[TGSI_QUAD_SIZE])
{
const struct pipe_resource *texture = sview->base.texture;
float dsdx = fabsf(s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]);
float dsdy = fabsf(s[QUAD_TOP_LEFT] - s[QUAD_BOTTOM_LEFT]);
float dtdx = fabsf(t[QUAD_BOTTOM_RIGHT] - t[QUAD_BOTTOM_LEFT]);
float dtdy = fabsf(t[QUAD_TOP_LEFT] - t[QUAD_BOTTOM_LEFT]);
float maxx = MAX2(dsdx, dsdy) * u_minify(texture->width0, sview->base.u.tex.first_level);
float maxy = MAX2(dtdx, dtdy) * u_minify(texture->height0, sview->base.u.tex.first_level);
float rho = MAX2(maxx, maxy);
 
return util_fast_log2(rho);
}
 
 
static float
compute_lambda_3d(const struct sp_sampler_view *sview,
const float s[TGSI_QUAD_SIZE],
const float t[TGSI_QUAD_SIZE],
const float p[TGSI_QUAD_SIZE])
{
const struct pipe_resource *texture = sview->base.texture;
float dsdx = fabsf(s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]);
float dsdy = fabsf(s[QUAD_TOP_LEFT] - s[QUAD_BOTTOM_LEFT]);
float dtdx = fabsf(t[QUAD_BOTTOM_RIGHT] - t[QUAD_BOTTOM_LEFT]);
float dtdy = fabsf(t[QUAD_TOP_LEFT] - t[QUAD_BOTTOM_LEFT]);
float dpdx = fabsf(p[QUAD_BOTTOM_RIGHT] - p[QUAD_BOTTOM_LEFT]);
float dpdy = fabsf(p[QUAD_TOP_LEFT] - p[QUAD_BOTTOM_LEFT]);
float maxx = MAX2(dsdx, dsdy) * u_minify(texture->width0, sview->base.u.tex.first_level);
float maxy = MAX2(dtdx, dtdy) * u_minify(texture->height0, sview->base.u.tex.first_level);
float maxz = MAX2(dpdx, dpdy) * u_minify(texture->depth0, sview->base.u.tex.first_level);
float rho;
 
rho = MAX2(maxx, maxy);
rho = MAX2(rho, maxz);
 
return util_fast_log2(rho);
}
 
 
/**
* Compute lambda for a vertex texture sampler.
* Since there aren't derivatives to use, just return 0.
*/
static float
compute_lambda_vert(const struct sp_sampler_view *sview,
const float s[TGSI_QUAD_SIZE],
const float t[TGSI_QUAD_SIZE],
const float p[TGSI_QUAD_SIZE])
{
return 0.0f;
}
 
 
 
/**
* Get a texel from a texture, using the texture tile cache.
*
* \param addr the template tex address containing cube, z, face info.
* \param x the x coord of texel within 2D image
* \param y the y coord of texel within 2D image
* \param rgba the quad to put the texel/color into
*
* XXX maybe move this into sp_tex_tile_cache.c and merge with the
* sp_get_cached_tile_tex() function.
*/
 
 
 
 
static INLINE const float *
get_texel_2d_no_border(const struct sp_sampler_view *sp_sview,
union tex_tile_address addr, int x, int y)
{
const struct softpipe_tex_cached_tile *tile;
addr.bits.x = x / TEX_TILE_SIZE;
addr.bits.y = y / TEX_TILE_SIZE;
y %= TEX_TILE_SIZE;
x %= TEX_TILE_SIZE;
 
tile = sp_get_cached_tile_tex(sp_sview->cache, addr);
 
return &tile->data.color[y][x][0];
}
 
 
static INLINE const float *
get_texel_2d(const struct sp_sampler_view *sp_sview,
const struct sp_sampler *sp_samp,
union tex_tile_address addr, int x, int y)
{
const struct pipe_resource *texture = sp_sview->base.texture;
unsigned level = addr.bits.level;
 
if (x < 0 || x >= (int) u_minify(texture->width0, level) ||
y < 0 || y >= (int) u_minify(texture->height0, level)) {
return sp_samp->base.border_color.f;
}
else {
return get_texel_2d_no_border( sp_sview, addr, x, y );
}
}
 
/*
* seamless cubemap neighbour array.
* this array is used to find the adjacent face in each of 4 directions,
* left, right, up, down. (or -x, +x, -y, +y).
*/
static const unsigned face_array[PIPE_TEX_FACE_MAX][4] = {
/* pos X first then neg X is Z different, Y the same */
/* PIPE_TEX_FACE_POS_X,*/
{ PIPE_TEX_FACE_POS_Z, PIPE_TEX_FACE_NEG_Z,
PIPE_TEX_FACE_NEG_Y, PIPE_TEX_FACE_POS_Y },
/* PIPE_TEX_FACE_NEG_X */
{ PIPE_TEX_FACE_NEG_Z, PIPE_TEX_FACE_POS_Z,
PIPE_TEX_FACE_NEG_Y, PIPE_TEX_FACE_POS_Y },
 
/* pos Y first then neg Y is X different, X the same */
/* PIPE_TEX_FACE_POS_Y */
{ PIPE_TEX_FACE_NEG_X, PIPE_TEX_FACE_POS_X,
PIPE_TEX_FACE_POS_Z, PIPE_TEX_FACE_NEG_Z },
 
/* PIPE_TEX_FACE_NEG_Y */
{ PIPE_TEX_FACE_NEG_X, PIPE_TEX_FACE_POS_X,
PIPE_TEX_FACE_NEG_Z, PIPE_TEX_FACE_POS_Z },
 
/* pos Z first then neg Y is X different, X the same */
/* PIPE_TEX_FACE_POS_Z */
{ PIPE_TEX_FACE_NEG_X, PIPE_TEX_FACE_POS_X,
PIPE_TEX_FACE_NEG_Y, PIPE_TEX_FACE_POS_Y },
 
/* PIPE_TEX_FACE_NEG_Z */
{ PIPE_TEX_FACE_POS_X, PIPE_TEX_FACE_NEG_X,
PIPE_TEX_FACE_NEG_Y, PIPE_TEX_FACE_POS_Y }
};
 
static INLINE unsigned
get_next_face(unsigned face, int x, int y)
{
int idx = 0;
 
if (x == 0 && y == 0)
return face;
if (x == -1)
idx = 0;
else if (x == 1)
idx = 1;
else if (y == -1)
idx = 2;
else if (y == 1)
idx = 3;
 
return face_array[face][idx];
}
 
static INLINE const float *
get_texel_cube_seamless(const struct sp_sampler_view *sp_sview,
union tex_tile_address addr, int x, int y,
float *corner)
{
const struct pipe_resource *texture = sp_sview->base.texture;
unsigned level = addr.bits.level;
unsigned face = addr.bits.face;
int new_x, new_y;
int max_x, max_y;
int c;
 
max_x = (int) u_minify(texture->width0, level);
max_y = (int) u_minify(texture->height0, level);
new_x = x;
new_y = y;
 
/* the corner case */
if ((x < 0 || x >= max_x) &&
(y < 0 || y >= max_y)) {
const float *c1, *c2, *c3;
int fx = x < 0 ? 0 : max_x - 1;
int fy = y < 0 ? 0 : max_y - 1;
c1 = get_texel_2d_no_border( sp_sview, addr, fx, fy);
addr.bits.face = get_next_face(face, (x < 0) ? -1 : 1, 0);
c2 = get_texel_2d_no_border( sp_sview, addr, (x < 0) ? max_x - 1 : 0, fy);
addr.bits.face = get_next_face(face, 0, (y < 0) ? -1 : 1);
c3 = get_texel_2d_no_border( sp_sview, addr, fx, (y < 0) ? max_y - 1 : 0);
for (c = 0; c < TGSI_QUAD_SIZE; c++)
corner[c] = CLAMP((c1[c] + c2[c] + c3[c]), 0.0F, 1.0F) / 3;
 
return corner;
}
/* change the face */
if (x < 0) {
new_x = max_x - 1;
face = get_next_face(face, -1, 0);
} else if (x >= max_x) {
new_x = 0;
face = get_next_face(face, 1, 0);
} else if (y < 0) {
new_y = max_y - 1;
face = get_next_face(face, 0, -1);
} else if (y >= max_y) {
new_y = 0;
face = get_next_face(face, 0, 1);
}
 
addr.bits.face = face;
return get_texel_2d_no_border( sp_sview, addr, new_x, new_y );
}
 
/* Gather a quad of adjacent texels within a tile:
*/
static INLINE void
get_texel_quad_2d_no_border_single_tile(const struct sp_sampler_view *sp_sview,
union tex_tile_address addr,
unsigned x, unsigned y,
const float *out[4])
{
const struct softpipe_tex_cached_tile *tile;
 
addr.bits.x = x / TEX_TILE_SIZE;
addr.bits.y = y / TEX_TILE_SIZE;
y %= TEX_TILE_SIZE;
x %= TEX_TILE_SIZE;
 
tile = sp_get_cached_tile_tex(sp_sview->cache, addr);
out[0] = &tile->data.color[y ][x ][0];
out[1] = &tile->data.color[y ][x+1][0];
out[2] = &tile->data.color[y+1][x ][0];
out[3] = &tile->data.color[y+1][x+1][0];
}
 
 
/* Gather a quad of potentially non-adjacent texels:
*/
static INLINE void
get_texel_quad_2d_no_border(const struct sp_sampler_view *sp_sview,
union tex_tile_address addr,
int x0, int y0,
int x1, int y1,
const float *out[4])
{
out[0] = get_texel_2d_no_border( sp_sview, addr, x0, y0 );
out[1] = get_texel_2d_no_border( sp_sview, addr, x1, y0 );
out[2] = get_texel_2d_no_border( sp_sview, addr, x0, y1 );
out[3] = get_texel_2d_no_border( sp_sview, addr, x1, y1 );
}
 
/* Can involve a lot of unnecessary checks for border color:
*/
static INLINE void
get_texel_quad_2d(const struct sp_sampler_view *sp_sview,
const struct sp_sampler *sp_samp,
union tex_tile_address addr,
int x0, int y0,
int x1, int y1,
const float *out[4])
{
out[0] = get_texel_2d( sp_sview, sp_samp, addr, x0, y0 );
out[1] = get_texel_2d( sp_sview, sp_samp, addr, x1, y0 );
out[3] = get_texel_2d( sp_sview, sp_samp, addr, x1, y1 );
out[2] = get_texel_2d( sp_sview, sp_samp, addr, x0, y1 );
}
 
 
 
/* 3d variants:
*/
static INLINE const float *
get_texel_3d_no_border(const struct sp_sampler_view *sp_sview,
union tex_tile_address addr, int x, int y, int z)
{
const struct softpipe_tex_cached_tile *tile;
 
addr.bits.x = x / TEX_TILE_SIZE;
addr.bits.y = y / TEX_TILE_SIZE;
addr.bits.z = z;
y %= TEX_TILE_SIZE;
x %= TEX_TILE_SIZE;
 
tile = sp_get_cached_tile_tex(sp_sview->cache, addr);
 
return &tile->data.color[y][x][0];
}
 
 
static INLINE const float *
get_texel_3d(const struct sp_sampler_view *sp_sview,
const struct sp_sampler *sp_samp,
union tex_tile_address addr, int x, int y, int z)
{
const struct pipe_resource *texture = sp_sview->base.texture;
unsigned level = addr.bits.level;
 
if (x < 0 || x >= (int) u_minify(texture->width0, level) ||
y < 0 || y >= (int) u_minify(texture->height0, level) ||
z < 0 || z >= (int) u_minify(texture->depth0, level)) {
return sp_samp->base.border_color.f;
}
else {
return get_texel_3d_no_border( sp_sview, addr, x, y, z );
}
}
 
 
/* Get texel pointer for 1D array texture */
static INLINE const float *
get_texel_1d_array(const struct sp_sampler_view *sp_sview,
const struct sp_sampler *sp_samp,
union tex_tile_address addr, int x, int y)
{
const struct pipe_resource *texture = sp_sview->base.texture;
unsigned level = addr.bits.level;
 
if (x < 0 || x >= (int) u_minify(texture->width0, level)) {
return sp_samp->base.border_color.f;
}
else {
return get_texel_2d_no_border(sp_sview, addr, x, y);
}
}
 
 
/* Get texel pointer for 2D array texture */
static INLINE const float *
get_texel_2d_array(const struct sp_sampler_view *sp_sview,
const struct sp_sampler *sp_samp,
union tex_tile_address addr, int x, int y, int layer)
{
const struct pipe_resource *texture = sp_sview->base.texture;
unsigned level = addr.bits.level;
 
assert(layer < (int) texture->array_size);
assert(layer >= 0);
 
if (x < 0 || x >= (int) u_minify(texture->width0, level) ||
y < 0 || y >= (int) u_minify(texture->height0, level)) {
return sp_samp->base.border_color.f;
}
else {
return get_texel_3d_no_border(sp_sview, addr, x, y, layer);
}
}
 
 
/* Get texel pointer for cube array texture */
static INLINE const float *
get_texel_cube_array(const struct sp_sampler_view *sp_sview,
const struct sp_sampler *sp_samp,
union tex_tile_address addr, int x, int y, int layer)
{
const struct pipe_resource *texture = sp_sview->base.texture;
unsigned level = addr.bits.level;
 
assert(layer < (int) texture->array_size);
assert(layer >= 0);
 
if (x < 0 || x >= (int) u_minify(texture->width0, level) ||
y < 0 || y >= (int) u_minify(texture->height0, level)) {
return sp_samp->base.border_color.f;
}
else {
return get_texel_3d_no_border(sp_sview, addr, x, y, layer);
}
}
/**
* Given the logbase2 of a mipmap's base level size and a mipmap level,
* return the size (in texels) of that mipmap level.
* For example, if level[0].width = 256 then base_pot will be 8.
* If level = 2, then we'll return 64 (the width at level=2).
* Return 1 if level > base_pot.
*/
static INLINE unsigned
pot_level_size(unsigned base_pot, unsigned level)
{
return (base_pot >= level) ? (1 << (base_pot - level)) : 1;
}
 
 
static void
print_sample(const char *function, const float *rgba)
{
debug_printf("%s %g %g %g %g\n",
function,
rgba[0], rgba[TGSI_NUM_CHANNELS], rgba[2*TGSI_NUM_CHANNELS], rgba[3*TGSI_NUM_CHANNELS]);
}
 
 
static void
print_sample_4(const char *function, float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
{
debug_printf("%s %g %g %g %g, %g %g %g %g, %g %g %g %g, %g %g %g %g\n",
function,
rgba[0][0], rgba[1][0], rgba[2][0], rgba[3][0],
rgba[0][1], rgba[1][1], rgba[2][1], rgba[3][1],
rgba[0][2], rgba[1][2], rgba[2][2], rgba[3][2],
rgba[0][3], rgba[1][3], rgba[2][3], rgba[3][3]);
}
 
 
/* Some image-filter fastpaths:
*/
static INLINE void
img_filter_2d_linear_repeat_POT(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
float s,
float t,
float p,
unsigned level,
unsigned face_id,
float *rgba)
{
unsigned xpot = pot_level_size(sp_sview->xpot, level);
unsigned ypot = pot_level_size(sp_sview->ypot, level);
unsigned xmax = (xpot - 1) & (TEX_TILE_SIZE - 1); /* MIN2(TEX_TILE_SIZE, xpot) - 1; */
unsigned ymax = (ypot - 1) & (TEX_TILE_SIZE - 1); /* MIN2(TEX_TILE_SIZE, ypot) - 1; */
union tex_tile_address addr;
int c;
 
float u = s * xpot - 0.5F;
float v = t * ypot - 0.5F;
 
int uflr = util_ifloor(u);
int vflr = util_ifloor(v);
 
float xw = u - (float)uflr;
float yw = v - (float)vflr;
 
int x0 = uflr & (xpot - 1);
int y0 = vflr & (ypot - 1);
 
const float *tx[4];
addr.value = 0;
addr.bits.level = level;
 
/* Can we fetch all four at once:
*/
if (x0 < xmax && y0 < ymax) {
get_texel_quad_2d_no_border_single_tile(sp_sview, addr, x0, y0, tx);
}
else {
unsigned x1 = (x0 + 1) & (xpot - 1);
unsigned y1 = (y0 + 1) & (ypot - 1);
get_texel_quad_2d_no_border(sp_sview, addr, x0, y0, x1, y1, tx);
}
 
/* interpolate R, G, B, A */
for (c = 0; c < TGSI_QUAD_SIZE; c++) {
rgba[TGSI_NUM_CHANNELS*c] = lerp_2d(xw, yw,
tx[0][c], tx[1][c],
tx[2][c], tx[3][c]);
}
 
if (DEBUG_TEX) {
print_sample(__FUNCTION__, rgba);
}
}
 
 
static INLINE void
img_filter_2d_nearest_repeat_POT(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
float s,
float t,
float p,
unsigned level,
unsigned face_id,
float rgba[TGSI_QUAD_SIZE])
{
unsigned xpot = pot_level_size(sp_sview->xpot, level);
unsigned ypot = pot_level_size(sp_sview->ypot, level);
const float *out;
union tex_tile_address addr;
int c;
 
float u = s * xpot;
float v = t * ypot;
 
int uflr = util_ifloor(u);
int vflr = util_ifloor(v);
 
int x0 = uflr & (xpot - 1);
int y0 = vflr & (ypot - 1);
 
addr.value = 0;
addr.bits.level = level;
 
out = get_texel_2d_no_border(sp_sview, addr, x0, y0);
for (c = 0; c < TGSI_QUAD_SIZE; c++)
rgba[TGSI_NUM_CHANNELS*c] = out[c];
 
if (DEBUG_TEX) {
print_sample(__FUNCTION__, rgba);
}
}
 
 
static INLINE void
img_filter_2d_nearest_clamp_POT(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
float s,
float t,
float p,
unsigned level,
unsigned face_id,
float rgba[TGSI_QUAD_SIZE])
{
unsigned xpot = pot_level_size(sp_sview->xpot, level);
unsigned ypot = pot_level_size(sp_sview->ypot, level);
union tex_tile_address addr;
int c;
 
float u = s * xpot;
float v = t * ypot;
 
int x0, y0;
const float *out;
 
addr.value = 0;
addr.bits.level = level;
 
x0 = util_ifloor(u);
if (x0 < 0)
x0 = 0;
else if (x0 > xpot - 1)
x0 = xpot - 1;
 
y0 = util_ifloor(v);
if (y0 < 0)
y0 = 0;
else if (y0 > ypot - 1)
y0 = ypot - 1;
out = get_texel_2d_no_border(sp_sview, addr, x0, y0);
for (c = 0; c < TGSI_QUAD_SIZE; c++)
rgba[TGSI_NUM_CHANNELS*c] = out[c];
 
if (DEBUG_TEX) {
print_sample(__FUNCTION__, rgba);
}
}
 
 
static void
img_filter_1d_nearest(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
float s,
float t,
float p,
unsigned level,
unsigned face_id,
float rgba[TGSI_QUAD_SIZE])
{
const struct pipe_resource *texture = sp_sview->base.texture;
int width;
int x;
union tex_tile_address addr;
const float *out;
int c;
 
width = u_minify(texture->width0, level);
 
assert(width > 0);
 
addr.value = 0;
addr.bits.level = level;
 
sp_samp->nearest_texcoord_s(s, width, &x);
 
out = get_texel_2d(sp_sview, sp_samp, addr, x, 0);
for (c = 0; c < TGSI_QUAD_SIZE; c++)
rgba[TGSI_NUM_CHANNELS*c] = out[c];
 
if (DEBUG_TEX) {
print_sample(__FUNCTION__, rgba);
}
}
 
 
static void
img_filter_1d_array_nearest(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
float s,
float t,
float p,
unsigned level,
unsigned face_id,
float *rgba)
{
const struct pipe_resource *texture = sp_sview->base.texture;
int width;
int x, layer;
union tex_tile_address addr;
const float *out;
int c;
 
width = u_minify(texture->width0, level);
 
assert(width > 0);
 
addr.value = 0;
addr.bits.level = level;
 
sp_samp->nearest_texcoord_s(s, width, &x);
wrap_array_layer(t, texture->array_size, &layer);
 
out = get_texel_1d_array(sp_sview, sp_samp, addr, x, layer);
for (c = 0; c < TGSI_QUAD_SIZE; c++)
rgba[TGSI_NUM_CHANNELS*c] = out[c];
 
if (DEBUG_TEX) {
print_sample(__FUNCTION__, rgba);
}
}
 
 
static void
img_filter_2d_nearest(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
float s,
float t,
float p,
unsigned level,
unsigned face_id,
float *rgba)
{
const struct pipe_resource *texture = sp_sview->base.texture;
int width, height;
int x, y;
union tex_tile_address addr;
const float *out;
int c;
 
width = u_minify(texture->width0, level);
height = u_minify(texture->height0, level);
 
assert(width > 0);
assert(height > 0);
addr.value = 0;
addr.bits.level = level;
 
sp_samp->nearest_texcoord_s(s, width, &x);
sp_samp->nearest_texcoord_t(t, height, &y);
 
out = get_texel_2d(sp_sview, sp_samp, addr, x, y);
for (c = 0; c < TGSI_QUAD_SIZE; c++)
rgba[TGSI_NUM_CHANNELS*c] = out[c];
 
if (DEBUG_TEX) {
print_sample(__FUNCTION__, rgba);
}
}
 
 
static void
img_filter_2d_array_nearest(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
float s,
float t,
float p,
unsigned level,
unsigned face_id,
float *rgba)
{
const struct pipe_resource *texture = sp_sview->base.texture;
int width, height;
int x, y, layer;
union tex_tile_address addr;
const float *out;
int c;
 
width = u_minify(texture->width0, level);
height = u_minify(texture->height0, level);
 
assert(width > 0);
assert(height > 0);
addr.value = 0;
addr.bits.level = level;
 
sp_samp->nearest_texcoord_s(s, width, &x);
sp_samp->nearest_texcoord_t(t, height, &y);
wrap_array_layer(p, texture->array_size, &layer);
 
out = get_texel_2d_array(sp_sview, sp_samp, addr, x, y, layer);
for (c = 0; c < TGSI_QUAD_SIZE; c++)
rgba[TGSI_NUM_CHANNELS*c] = out[c];
 
if (DEBUG_TEX) {
print_sample(__FUNCTION__, rgba);
}
}
 
 
static INLINE union tex_tile_address
face(union tex_tile_address addr, unsigned face )
{
addr.bits.face = face;
return addr;
}
 
 
static void
img_filter_cube_nearest(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
float s,
float t,
float p,
unsigned level,
unsigned face_id,
float *rgba)
{
const struct pipe_resource *texture = sp_sview->base.texture;
int width, height;
int x, y;
union tex_tile_address addr;
const float *out;
int c;
 
width = u_minify(texture->width0, level);
height = u_minify(texture->height0, level);
 
assert(width > 0);
assert(height > 0);
addr.value = 0;
addr.bits.level = level;
 
/*
* If NEAREST filtering is done within a miplevel, always apply wrap
* mode CLAMP_TO_EDGE.
*/
if (sp_samp->base.seamless_cube_map) {
wrap_nearest_clamp_to_edge(s, width, &x);
wrap_nearest_clamp_to_edge(t, height, &y);
} else {
sp_samp->nearest_texcoord_s(s, width, &x);
sp_samp->nearest_texcoord_t(t, height, &y);
}
 
out = get_texel_2d(sp_sview, sp_samp, face(addr, face_id), x, y);
for (c = 0; c < TGSI_QUAD_SIZE; c++)
rgba[TGSI_NUM_CHANNELS*c] = out[c];
 
if (DEBUG_TEX) {
print_sample(__FUNCTION__, rgba);
}
}
 
static void
img_filter_cube_array_nearest(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
float s,
float t,
float p,
unsigned level,
unsigned face_id,
float *rgba)
{
const struct pipe_resource *texture = sp_sview->base.texture;
int width, height;
int x, y, layer;
union tex_tile_address addr;
const float *out;
int c;
 
width = u_minify(texture->width0, level);
height = u_minify(texture->height0, level);
 
assert(width > 0);
assert(height > 0);
addr.value = 0;
addr.bits.level = level;
 
sp_samp->nearest_texcoord_s(s, width, &x);
sp_samp->nearest_texcoord_t(t, height, &y);
wrap_array_layer(p, texture->array_size, &layer);
 
out = get_texel_cube_array(sp_sview, sp_samp, addr, x, y, layer * 6 + face_id);
for (c = 0; c < TGSI_QUAD_SIZE; c++)
rgba[TGSI_NUM_CHANNELS*c] = out[c];
 
if (DEBUG_TEX) {
print_sample(__FUNCTION__, rgba);
}
}
 
static void
img_filter_3d_nearest(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
float s,
float t,
float p,
unsigned level,
unsigned face_id,
float *rgba)
{
const struct pipe_resource *texture = sp_sview->base.texture;
int width, height, depth;
int x, y, z;
union tex_tile_address addr;
const float *out;
int c;
 
width = u_minify(texture->width0, level);
height = u_minify(texture->height0, level);
depth = u_minify(texture->depth0, level);
 
assert(width > 0);
assert(height > 0);
assert(depth > 0);
 
sp_samp->nearest_texcoord_s(s, width, &x);
sp_samp->nearest_texcoord_t(t, height, &y);
sp_samp->nearest_texcoord_p(p, depth, &z);
 
addr.value = 0;
addr.bits.level = level;
 
out = get_texel_3d(sp_sview, sp_samp, addr, x, y, z);
for (c = 0; c < TGSI_QUAD_SIZE; c++)
rgba[TGSI_NUM_CHANNELS*c] = out[c];
}
 
 
static void
img_filter_1d_linear(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
float s,
float t,
float p,
unsigned level,
unsigned face_id,
float *rgba)
{
const struct pipe_resource *texture = sp_sview->base.texture;
int width;
int x0, x1;
float xw; /* weights */
union tex_tile_address addr;
const float *tx0, *tx1;
int c;
 
width = u_minify(texture->width0, level);
 
assert(width > 0);
 
addr.value = 0;
addr.bits.level = level;
 
sp_samp->linear_texcoord_s(s, width, &x0, &x1, &xw);
 
tx0 = get_texel_2d(sp_sview, sp_samp, addr, x0, 0);
tx1 = get_texel_2d(sp_sview, sp_samp, addr, x1, 0);
 
/* interpolate R, G, B, A */
for (c = 0; c < TGSI_QUAD_SIZE; c++)
rgba[TGSI_NUM_CHANNELS*c] = lerp(xw, tx0[c], tx1[c]);
}
 
 
static void
img_filter_1d_array_linear(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
float s,
float t,
float p,
unsigned level,
unsigned face_id,
float *rgba)
{
const struct pipe_resource *texture = sp_sview->base.texture;
int width;
int x0, x1, layer;
float xw; /* weights */
union tex_tile_address addr;
const float *tx0, *tx1;
int c;
 
width = u_minify(texture->width0, level);
 
assert(width > 0);
 
addr.value = 0;
addr.bits.level = level;
 
sp_samp->linear_texcoord_s(s, width, &x0, &x1, &xw);
wrap_array_layer(t, texture->array_size, &layer);
 
tx0 = get_texel_1d_array(sp_sview, sp_samp, addr, x0, layer);
tx1 = get_texel_1d_array(sp_sview, sp_samp, addr, x1, layer);
 
/* interpolate R, G, B, A */
for (c = 0; c < TGSI_QUAD_SIZE; c++)
rgba[TGSI_NUM_CHANNELS*c] = lerp(xw, tx0[c], tx1[c]);
}
 
 
static void
img_filter_2d_linear(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
float s,
float t,
float p,
unsigned level,
unsigned face_id,
float *rgba)
{
const struct pipe_resource *texture = sp_sview->base.texture;
int width, height;
int x0, y0, x1, y1;
float xw, yw; /* weights */
union tex_tile_address addr;
const float *tx0, *tx1, *tx2, *tx3;
int c;
 
width = u_minify(texture->width0, level);
height = u_minify(texture->height0, level);
 
assert(width > 0);
assert(height > 0);
 
addr.value = 0;
addr.bits.level = level;
 
sp_samp->linear_texcoord_s(s, width, &x0, &x1, &xw);
sp_samp->linear_texcoord_t(t, height, &y0, &y1, &yw);
 
tx0 = get_texel_2d(sp_sview, sp_samp, addr, x0, y0);
tx1 = get_texel_2d(sp_sview, sp_samp, addr, x1, y0);
tx2 = get_texel_2d(sp_sview, sp_samp, addr, x0, y1);
tx3 = get_texel_2d(sp_sview, sp_samp, addr, x1, y1);
 
/* interpolate R, G, B, A */
for (c = 0; c < TGSI_QUAD_SIZE; c++)
rgba[TGSI_NUM_CHANNELS*c] = lerp_2d(xw, yw,
tx0[c], tx1[c],
tx2[c], tx3[c]);
}
 
 
static void
img_filter_2d_array_linear(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
float s,
float t,
float p,
unsigned level,
unsigned face_id,
float *rgba)
{
const struct pipe_resource *texture = sp_sview->base.texture;
int width, height;
int x0, y0, x1, y1, layer;
float xw, yw; /* weights */
union tex_tile_address addr;
const float *tx0, *tx1, *tx2, *tx3;
int c;
 
width = u_minify(texture->width0, level);
height = u_minify(texture->height0, level);
 
assert(width > 0);
assert(height > 0);
 
addr.value = 0;
addr.bits.level = level;
 
sp_samp->linear_texcoord_s(s, width, &x0, &x1, &xw);
sp_samp->linear_texcoord_t(t, height, &y0, &y1, &yw);
wrap_array_layer(p, texture->array_size, &layer);
 
tx0 = get_texel_2d_array(sp_sview, sp_samp, addr, x0, y0, layer);
tx1 = get_texel_2d_array(sp_sview, sp_samp, addr, x1, y0, layer);
tx2 = get_texel_2d_array(sp_sview, sp_samp, addr, x0, y1, layer);
tx3 = get_texel_2d_array(sp_sview, sp_samp, addr, x1, y1, layer);
 
/* interpolate R, G, B, A */
for (c = 0; c < TGSI_QUAD_SIZE; c++)
rgba[TGSI_NUM_CHANNELS*c] = lerp_2d(xw, yw,
tx0[c], tx1[c],
tx2[c], tx3[c]);
}
 
 
static void
img_filter_cube_linear(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
float s,
float t,
float p,
unsigned level,
unsigned face_id,
float *rgba)
{
const struct pipe_resource *texture = sp_sview->base.texture;
int width, height;
int x0, y0, x1, y1;
float xw, yw; /* weights */
union tex_tile_address addr, addrj;
const float *tx0, *tx1, *tx2, *tx3;
float corner0[TGSI_QUAD_SIZE], corner1[TGSI_QUAD_SIZE],
corner2[TGSI_QUAD_SIZE], corner3[TGSI_QUAD_SIZE];
int c;
 
width = u_minify(texture->width0, level);
height = u_minify(texture->height0, level);
 
assert(width > 0);
assert(height > 0);
 
addr.value = 0;
addr.bits.level = level;
 
/*
* For seamless if LINEAR filtering is done within a miplevel,
* always apply wrap mode CLAMP_TO_BORDER.
*/
if (sp_samp->base.seamless_cube_map) {
wrap_linear_clamp_to_border(s, width, &x0, &x1, &xw);
wrap_linear_clamp_to_border(t, height, &y0, &y1, &yw);
} else {
sp_samp->linear_texcoord_s(s, width, &x0, &x1, &xw);
sp_samp->linear_texcoord_t(t, height, &y0, &y1, &yw);
}
 
addrj = face(addr, face_id);
 
if (sp_samp->base.seamless_cube_map) {
tx0 = get_texel_cube_seamless(sp_sview, addrj, x0, y0, corner0);
tx1 = get_texel_cube_seamless(sp_sview, addrj, x1, y0, corner1);
tx2 = get_texel_cube_seamless(sp_sview, addrj, x0, y1, corner2);
tx3 = get_texel_cube_seamless(sp_sview, addrj, x1, y1, corner3);
} else {
tx0 = get_texel_2d(sp_sview, sp_samp, addrj, x0, y0);
tx1 = get_texel_2d(sp_sview, sp_samp, addrj, x1, y0);
tx2 = get_texel_2d(sp_sview, sp_samp, addrj, x0, y1);
tx3 = get_texel_2d(sp_sview, sp_samp, addrj, x1, y1);
}
/* interpolate R, G, B, A */
for (c = 0; c < TGSI_QUAD_SIZE; c++)
rgba[TGSI_NUM_CHANNELS*c] = lerp_2d(xw, yw,
tx0[c], tx1[c],
tx2[c], tx3[c]);
}
 
 
static void
img_filter_cube_array_linear(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
float s,
float t,
float p,
unsigned level,
unsigned face_id,
float *rgba)
{
const struct pipe_resource *texture = sp_sview->base.texture;
int width, height;
int x0, y0, x1, y1, layer;
float xw, yw; /* weights */
union tex_tile_address addr;
const float *tx0, *tx1, *tx2, *tx3;
int c;
 
width = u_minify(texture->width0, level);
height = u_minify(texture->height0, level);
 
assert(width > 0);
assert(height > 0);
 
addr.value = 0;
addr.bits.level = level;
 
sp_samp->linear_texcoord_s(s, width, &x0, &x1, &xw);
sp_samp->linear_texcoord_t(t, height, &y0, &y1, &yw);
wrap_array_layer(p, texture->array_size, &layer);
 
tx0 = get_texel_cube_array(sp_sview, sp_samp, addr, x0, y0, layer * 6 + face_id);
tx1 = get_texel_cube_array(sp_sview, sp_samp, addr, x1, y0, layer * 6 + face_id);
tx2 = get_texel_cube_array(sp_sview, sp_samp, addr, x0, y1, layer * 6 + face_id);
tx3 = get_texel_cube_array(sp_sview, sp_samp, addr, x1, y1, layer * 6 + face_id);
 
/* interpolate R, G, B, A */
for (c = 0; c < TGSI_QUAD_SIZE; c++)
rgba[TGSI_NUM_CHANNELS*c] = lerp_2d(xw, yw,
tx0[c], tx1[c],
tx2[c], tx3[c]);
}
 
static void
img_filter_3d_linear(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
float s,
float t,
float p,
unsigned level,
unsigned face_id,
float *rgba)
{
const struct pipe_resource *texture = sp_sview->base.texture;
int width, height, depth;
int x0, x1, y0, y1, z0, z1;
float xw, yw, zw; /* interpolation weights */
union tex_tile_address addr;
const float *tx00, *tx01, *tx02, *tx03, *tx10, *tx11, *tx12, *tx13;
int c;
 
width = u_minify(texture->width0, level);
height = u_minify(texture->height0, level);
depth = u_minify(texture->depth0, level);
 
addr.value = 0;
addr.bits.level = level;
 
assert(width > 0);
assert(height > 0);
assert(depth > 0);
 
sp_samp->linear_texcoord_s(s, width, &x0, &x1, &xw);
sp_samp->linear_texcoord_t(t, height, &y0, &y1, &yw);
sp_samp->linear_texcoord_p(p, depth, &z0, &z1, &zw);
 
 
tx00 = get_texel_3d(sp_sview, sp_samp, addr, x0, y0, z0);
tx01 = get_texel_3d(sp_sview, sp_samp, addr, x1, y0, z0);
tx02 = get_texel_3d(sp_sview, sp_samp, addr, x0, y1, z0);
tx03 = get_texel_3d(sp_sview, sp_samp, addr, x1, y1, z0);
tx10 = get_texel_3d(sp_sview, sp_samp, addr, x0, y0, z1);
tx11 = get_texel_3d(sp_sview, sp_samp, addr, x1, y0, z1);
tx12 = get_texel_3d(sp_sview, sp_samp, addr, x0, y1, z1);
tx13 = get_texel_3d(sp_sview, sp_samp, addr, x1, y1, z1);
/* interpolate R, G, B, A */
for (c = 0; c < TGSI_QUAD_SIZE; c++)
rgba[TGSI_NUM_CHANNELS*c] = lerp_3d(xw, yw, zw,
tx00[c], tx01[c],
tx02[c], tx03[c],
tx10[c], tx11[c],
tx12[c], tx13[c]);
}
 
 
/* Calculate level of detail for every fragment,
* with lambda already computed.
* Note that lambda has already been biased by global LOD bias.
* \param biased_lambda per-quad lambda.
* \param lod_in per-fragment lod_bias or explicit_lod.
* \param lod returns the per-fragment lod.
*/
static INLINE void
compute_lod(const struct pipe_sampler_state *sampler,
enum tgsi_sampler_control control,
const float biased_lambda,
const float lod_in[TGSI_QUAD_SIZE],
float lod[TGSI_QUAD_SIZE])
{
float min_lod = sampler->min_lod;
float max_lod = sampler->max_lod;
uint i;
 
switch (control) {
case tgsi_sampler_lod_none:
case tgsi_sampler_lod_zero:
/* XXX FIXME */
case tgsi_sampler_derivs_explicit:
lod[0] = lod[1] = lod[2] = lod[3] = CLAMP(biased_lambda, min_lod, max_lod);
break;
case tgsi_sampler_lod_bias:
for (i = 0; i < TGSI_QUAD_SIZE; i++) {
lod[i] = biased_lambda + lod_in[i];
lod[i] = CLAMP(lod[i], min_lod, max_lod);
}
break;
case tgsi_sampler_lod_explicit:
for (i = 0; i < TGSI_QUAD_SIZE; i++) {
lod[i] = CLAMP(lod_in[i], min_lod, max_lod);
}
break;
default:
assert(0);
lod[0] = lod[1] = lod[2] = lod[3] = 0.0f;
}
}
 
 
/* Calculate level of detail for every fragment.
* \param lod_in per-fragment lod_bias or explicit_lod.
* \param lod results per-fragment lod.
*/
static INLINE void
compute_lambda_lod(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
const float s[TGSI_QUAD_SIZE],
const float t[TGSI_QUAD_SIZE],
const float p[TGSI_QUAD_SIZE],
const float lod_in[TGSI_QUAD_SIZE],
enum tgsi_sampler_control control,
float lod[TGSI_QUAD_SIZE])
{
const struct pipe_sampler_state *sampler = &sp_samp->base;
float lod_bias = sampler->lod_bias;
float min_lod = sampler->min_lod;
float max_lod = sampler->max_lod;
float lambda;
uint i;
 
switch (control) {
case tgsi_sampler_lod_none:
/* XXX FIXME */
case tgsi_sampler_derivs_explicit:
lambda = sp_sview->compute_lambda(sp_sview, s, t, p) + lod_bias;
lod[0] = lod[1] = lod[2] = lod[3] = CLAMP(lambda, min_lod, max_lod);
break;
case tgsi_sampler_lod_bias:
lambda = sp_sview->compute_lambda(sp_sview, s, t, p) + lod_bias;
for (i = 0; i < TGSI_QUAD_SIZE; i++) {
lod[i] = lambda + lod_in[i];
lod[i] = CLAMP(lod[i], min_lod, max_lod);
}
break;
case tgsi_sampler_lod_explicit:
for (i = 0; i < TGSI_QUAD_SIZE; i++) {
lod[i] = CLAMP(lod_in[i], min_lod, max_lod);
}
break;
case tgsi_sampler_lod_zero:
/* this is all static state in the sampler really need clamp here? */
lod[0] = lod[1] = lod[2] = lod[3] = CLAMP(lod_bias, min_lod, max_lod);
break;
default:
assert(0);
lod[0] = lod[1] = lod[2] = lod[3] = 0.0f;
}
}
 
 
static void
mip_filter_linear(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
img_filter_func min_filter,
img_filter_func mag_filter,
const float s[TGSI_QUAD_SIZE],
const float t[TGSI_QUAD_SIZE],
const float p[TGSI_QUAD_SIZE],
const float c0[TGSI_QUAD_SIZE],
const float lod_in[TGSI_QUAD_SIZE],
enum tgsi_sampler_control control,
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
{
const struct pipe_resource *texture = sp_sview->base.texture;
int j;
float lod[TGSI_QUAD_SIZE];
 
compute_lambda_lod(sp_sview, sp_samp, s, t, p, lod_in, control, lod);
 
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int level0 = sp_sview->base.u.tex.first_level + (int)lod[j];
 
if (lod[j] < 0.0)
mag_filter(sp_sview, sp_samp, s[j], t[j], p[j],
sp_sview->base.u.tex.first_level,
sp_sview->faces[j], &rgba[0][j]);
 
else if (level0 >= texture->last_level)
min_filter(sp_sview, sp_samp, s[j], t[j], p[j], texture->last_level,
sp_sview->faces[j], &rgba[0][j]);
 
else {
float levelBlend = frac(lod[j]);
float rgbax[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
int c;
 
min_filter(sp_sview, sp_samp, s[j], t[j], p[j], level0,
sp_sview->faces[j], &rgbax[0][0]);
min_filter(sp_sview, sp_samp, s[j], t[j], p[j], level0+1,
sp_sview->faces[j], &rgbax[0][1]);
 
for (c = 0; c < 4; c++) {
rgba[c][j] = lerp(levelBlend, rgbax[c][0], rgbax[c][1]);
}
}
}
 
if (DEBUG_TEX) {
print_sample_4(__FUNCTION__, rgba);
}
}
 
 
/**
* Compute nearest mipmap level from texcoords.
* Then sample the texture level for four elements of a quad.
* \param c0 the LOD bias factors, or absolute LODs (depending on control)
*/
static void
mip_filter_nearest(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
img_filter_func min_filter,
img_filter_func mag_filter,
const float s[TGSI_QUAD_SIZE],
const float t[TGSI_QUAD_SIZE],
const float p[TGSI_QUAD_SIZE],
const float c0[TGSI_QUAD_SIZE],
const float lod_in[TGSI_QUAD_SIZE],
enum tgsi_sampler_control control,
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
{
const struct pipe_resource *texture = sp_sview->base.texture;
float lod[TGSI_QUAD_SIZE];
int j;
 
compute_lambda_lod(sp_sview, sp_samp, s, t, p, lod_in, control, lod);
 
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (lod[j] < 0.0)
mag_filter(sp_sview, sp_samp, s[j], t[j], p[j],
sp_sview->base.u.tex.first_level,
sp_sview->faces[j], &rgba[0][j]);
else {
float level = sp_sview->base.u.tex.first_level + (int)(lod[j] + 0.5F) ;
level = MIN2(level, (int)texture->last_level);
min_filter(sp_sview, sp_samp, s[j], t[j], p[j],
level, sp_sview->faces[j], &rgba[0][j]);
}
}
 
if (DEBUG_TEX) {
print_sample_4(__FUNCTION__, rgba);
}
}
 
 
static void
mip_filter_none(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
img_filter_func min_filter,
img_filter_func mag_filter,
const float s[TGSI_QUAD_SIZE],
const float t[TGSI_QUAD_SIZE],
const float p[TGSI_QUAD_SIZE],
const float c0[TGSI_QUAD_SIZE],
const float lod_in[TGSI_QUAD_SIZE],
enum tgsi_sampler_control control,
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
{
float lod[TGSI_QUAD_SIZE];
int j;
 
compute_lambda_lod(sp_sview, sp_samp, s, t, p, lod_in, control, lod);
 
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
if (lod[j] < 0.0) {
mag_filter(sp_sview, sp_samp, s[j], t[j], p[j],
sp_sview->base.u.tex.first_level,
sp_sview->faces[j], &rgba[0][j]);
}
else {
min_filter(sp_sview, sp_samp, s[j], t[j], p[j],
sp_sview->base.u.tex.first_level,
sp_sview->faces[j], &rgba[0][j]);
}
}
}
 
 
static void
mip_filter_none_no_filter_select(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
img_filter_func min_filter,
img_filter_func mag_filter,
const float s[TGSI_QUAD_SIZE],
const float t[TGSI_QUAD_SIZE],
const float p[TGSI_QUAD_SIZE],
const float c0[TGSI_QUAD_SIZE],
const float lod_in[TGSI_QUAD_SIZE],
enum tgsi_sampler_control control,
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
{
int j;
 
for (j = 0; j < TGSI_QUAD_SIZE; j++)
mag_filter(sp_sview, sp_samp, s[j], t[j], p[j],
sp_sview->base.u.tex.first_level,
sp_sview->faces[j], &rgba[0][j]);
}
 
 
/* For anisotropic filtering */
#define WEIGHT_LUT_SIZE 1024
 
static float *weightLut = NULL;
 
/**
* Creates the look-up table used to speed-up EWA sampling
*/
static void
create_filter_table(void)
{
unsigned i;
if (!weightLut) {
weightLut = (float *) MALLOC(WEIGHT_LUT_SIZE * sizeof(float));
 
for (i = 0; i < WEIGHT_LUT_SIZE; ++i) {
float alpha = 2;
float r2 = (float) i / (float) (WEIGHT_LUT_SIZE - 1);
float weight = (float) exp(-alpha * r2);
weightLut[i] = weight;
}
}
}
 
 
/**
* Elliptical weighted average (EWA) filter for producing high quality
* anisotropic filtered results.
* Based on the Higher Quality Elliptical Weighted Average Filter
* published by Paul S. Heckbert in his Master's Thesis
* "Fundamentals of Texture Mapping and Image Warping" (1989)
*/
static void
img_filter_2d_ewa(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
img_filter_func min_filter,
img_filter_func mag_filter,
const float s[TGSI_QUAD_SIZE],
const float t[TGSI_QUAD_SIZE],
const float p[TGSI_QUAD_SIZE],
unsigned level,
const float dudx, const float dvdx,
const float dudy, const float dvdy,
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
{
const struct pipe_resource *texture = sp_sview->base.texture;
 
// ??? Won't the image filters blow up if level is negative?
unsigned level0 = level > 0 ? level : 0;
float scaling = 1.0f / (1 << level0);
int width = u_minify(texture->width0, level0);
int height = u_minify(texture->height0, level0);
 
float ux = dudx * scaling;
float vx = dvdx * scaling;
float uy = dudy * scaling;
float vy = dvdy * scaling;
 
/* compute ellipse coefficients to bound the region:
* A*x*x + B*x*y + C*y*y = F.
*/
float A = vx*vx+vy*vy+1;
float B = -2*(ux*vx+uy*vy);
float C = ux*ux+uy*uy+1;
float F = A*C-B*B/4.0f;
 
/* check if it is an ellipse */
/* ASSERT(F > 0.0); */
 
/* Compute the ellipse's (u,v) bounding box in texture space */
float d = -B*B+4.0f*C*A;
float box_u = 2.0f / d * sqrt(d*C*F); /* box_u -> half of bbox with */
float box_v = 2.0f / d * sqrt(A*d*F); /* box_v -> half of bbox height */
 
float rgba_temp[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
float s_buffer[TGSI_QUAD_SIZE];
float t_buffer[TGSI_QUAD_SIZE];
float weight_buffer[TGSI_QUAD_SIZE];
unsigned buffer_next;
int j;
float den; /* = 0.0F; */
float ddq;
float U; /* = u0 - tex_u; */
int v;
 
/* Scale ellipse formula to directly index the Filter Lookup Table.
* i.e. scale so that F = WEIGHT_LUT_SIZE-1
*/
double formScale = (double) (WEIGHT_LUT_SIZE - 1) / F;
A *= formScale;
B *= formScale;
C *= formScale;
/* F *= formScale; */ /* no need to scale F as we don't use it below here */
 
/* For each quad, the du and dx values are the same and so the ellipse is
* also the same. Note that texel/image access can only be performed using
* a quad, i.e. it is not possible to get the pixel value for a single
* tex coord. In order to have a better performance, the access is buffered
* using the s_buffer/t_buffer and weight_buffer. Only when the buffer is
* full, then the pixel values are read from the image.
*/
ddq = 2 * A;
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
/* Heckbert MS thesis, p. 59; scan over the bounding box of the ellipse
* and incrementally update the value of Ax^2+Bxy*Cy^2; when this
* value, q, is less than F, we're inside the ellipse
*/
float tex_u = -0.5F + s[j] * texture->width0 * scaling;
float tex_v = -0.5F + t[j] * texture->height0 * scaling;
 
int u0 = (int) floorf(tex_u - box_u);
int u1 = (int) ceilf(tex_u + box_u);
int v0 = (int) floorf(tex_v - box_v);
int v1 = (int) ceilf(tex_v + box_v);
 
float num[4] = {0.0F, 0.0F, 0.0F, 0.0F};
buffer_next = 0;
den = 0;
U = u0 - tex_u;
for (v = v0; v <= v1; ++v) {
float V = v - tex_v;
float dq = A * (2 * U + 1) + B * V;
float q = (C * V + B * U) * V + A * U * U;
 
int u;
for (u = u0; u <= u1; ++u) {
/* Note that the ellipse has been pre-scaled so F =
* WEIGHT_LUT_SIZE - 1
*/
if (q < WEIGHT_LUT_SIZE) {
/* as a LUT is used, q must never be negative;
* should not happen, though
*/
const int qClamped = q >= 0.0F ? q : 0;
float weight = weightLut[qClamped];
 
weight_buffer[buffer_next] = weight;
s_buffer[buffer_next] = u / ((float) width);
t_buffer[buffer_next] = v / ((float) height);
buffer_next++;
if (buffer_next == TGSI_QUAD_SIZE) {
/* 4 texel coords are in the buffer -> read it now */
unsigned jj;
/* it is assumed that samp->min_img_filter is set to
* img_filter_2d_nearest or one of the
* accelerated img_filter_2d_nearest_XXX functions.
*/
for (jj = 0; jj < buffer_next; jj++) {
min_filter(sp_sview, sp_samp, s_buffer[jj], t_buffer[jj], p[jj],
level, sp_sview->faces[j], &rgba_temp[0][jj]);
num[0] += weight_buffer[jj] * rgba_temp[0][jj];
num[1] += weight_buffer[jj] * rgba_temp[1][jj];
num[2] += weight_buffer[jj] * rgba_temp[2][jj];
num[3] += weight_buffer[jj] * rgba_temp[3][jj];
}
 
buffer_next = 0;
}
 
den += weight;
}
q += dq;
dq += ddq;
}
}
 
/* if the tex coord buffer contains unread values, we will read
* them now.
*/
if (buffer_next > 0) {
unsigned jj;
/* it is assumed that samp->min_img_filter is set to
* img_filter_2d_nearest or one of the
* accelerated img_filter_2d_nearest_XXX functions.
*/
for (jj = 0; jj < buffer_next; jj++) {
min_filter(sp_sview, sp_samp, s_buffer[jj], t_buffer[jj], p[jj],
level, sp_sview->faces[j], &rgba_temp[0][jj]);
num[0] += weight_buffer[jj] * rgba_temp[0][jj];
num[1] += weight_buffer[jj] * rgba_temp[1][jj];
num[2] += weight_buffer[jj] * rgba_temp[2][jj];
num[3] += weight_buffer[jj] * rgba_temp[3][jj];
}
}
 
if (den <= 0.0F) {
/* Reaching this place would mean that no pixels intersected
* the ellipse. This should never happen because the filter
* we use always intersects at least one pixel.
*/
 
/*rgba[0]=0;
rgba[1]=0;
rgba[2]=0;
rgba[3]=0;*/
/* not enough pixels in resampling, resort to direct interpolation */
min_filter(sp_sview, sp_samp, s[j], t[j], p[j], level,
sp_sview->faces[j], &rgba_temp[0][j]);
den = 1;
num[0] = rgba_temp[0][j];
num[1] = rgba_temp[1][j];
num[2] = rgba_temp[2][j];
num[3] = rgba_temp[3][j];
}
 
rgba[0][j] = num[0] / den;
rgba[1][j] = num[1] / den;
rgba[2][j] = num[2] / den;
rgba[3][j] = num[3] / den;
}
}
 
 
/**
* Sample 2D texture using an anisotropic filter.
*/
static void
mip_filter_linear_aniso(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
img_filter_func min_filter,
img_filter_func mag_filter,
const float s[TGSI_QUAD_SIZE],
const float t[TGSI_QUAD_SIZE],
const float p[TGSI_QUAD_SIZE],
const float c0[TGSI_QUAD_SIZE],
const float lod_in[TGSI_QUAD_SIZE],
enum tgsi_sampler_control control,
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
{
const struct pipe_resource *texture = sp_sview->base.texture;
int level0;
float lambda;
float lod[TGSI_QUAD_SIZE];
 
float s_to_u = u_minify(texture->width0, sp_sview->base.u.tex.first_level);
float t_to_v = u_minify(texture->height0, sp_sview->base.u.tex.first_level);
float dudx = (s[QUAD_BOTTOM_RIGHT] - s[QUAD_BOTTOM_LEFT]) * s_to_u;
float dudy = (s[QUAD_TOP_LEFT] - s[QUAD_BOTTOM_LEFT]) * s_to_u;
float dvdx = (t[QUAD_BOTTOM_RIGHT] - t[QUAD_BOTTOM_LEFT]) * t_to_v;
float dvdy = (t[QUAD_TOP_LEFT] - t[QUAD_BOTTOM_LEFT]) * t_to_v;
if (control == tgsi_sampler_lod_bias ||
control == tgsi_sampler_lod_none ||
/* XXX FIXME */
control == tgsi_sampler_derivs_explicit) {
/* note: instead of working with Px and Py, we will use the
* squared length instead, to avoid sqrt.
*/
float Px2 = dudx * dudx + dvdx * dvdx;
float Py2 = dudy * dudy + dvdy * dvdy;
 
float Pmax2;
float Pmin2;
float e;
const float maxEccentricity = sp_samp->base.max_anisotropy * sp_samp->base.max_anisotropy;
if (Px2 < Py2) {
Pmax2 = Py2;
Pmin2 = Px2;
}
else {
Pmax2 = Px2;
Pmin2 = Py2;
}
/* if the eccentricity of the ellipse is too big, scale up the shorter
* of the two vectors to limit the maximum amount of work per pixel
*/
e = Pmax2 / Pmin2;
if (e > maxEccentricity) {
/* float s=e / maxEccentricity;
minor[0] *= s;
minor[1] *= s;
Pmin2 *= s; */
Pmin2 = Pmax2 / maxEccentricity;
}
/* note: we need to have Pmin=sqrt(Pmin2) here, but we can avoid
* this since 0.5*log(x) = log(sqrt(x))
*/
lambda = 0.5F * util_fast_log2(Pmin2) + sp_samp->base.lod_bias;
compute_lod(&sp_samp->base, control, lambda, lod_in, lod);
}
else {
assert(control == tgsi_sampler_lod_explicit ||
control == tgsi_sampler_lod_zero);
compute_lod(&sp_samp->base, control, sp_samp->base.lod_bias, lod_in, lod);
}
/* XXX: Take into account all lod values.
*/
lambda = lod[0];
level0 = sp_sview->base.u.tex.first_level + (int)lambda;
 
/* If the ellipse covers the whole image, we can
* simply return the average of the whole image.
*/
if (level0 >= (int) texture->last_level) {
int j;
for (j = 0; j < TGSI_QUAD_SIZE; j++)
min_filter(sp_sview, sp_samp, s[j], t[j], p[j], texture->last_level,
sp_sview->faces[j], &rgba[0][j]);
}
else {
/* don't bother interpolating between multiple LODs; it doesn't
* seem to be worth the extra running time.
*/
img_filter_2d_ewa(sp_sview, sp_samp, min_filter, mag_filter,
s, t, p, level0,
dudx, dvdx, dudy, dvdy, rgba);
}
 
if (DEBUG_TEX) {
print_sample_4(__FUNCTION__, rgba);
}
}
 
 
/**
* Specialized version of mip_filter_linear with hard-wired calls to
* 2d lambda calculation and 2d_linear_repeat_POT img filters.
*/
static void
mip_filter_linear_2d_linear_repeat_POT(
struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
img_filter_func min_filter,
img_filter_func mag_filter,
const float s[TGSI_QUAD_SIZE],
const float t[TGSI_QUAD_SIZE],
const float p[TGSI_QUAD_SIZE],
const float c0[TGSI_QUAD_SIZE],
const float lod_in[TGSI_QUAD_SIZE],
enum tgsi_sampler_control control,
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
{
const struct pipe_resource *texture = sp_sview->base.texture;
int j;
float lod[TGSI_QUAD_SIZE];
 
compute_lambda_lod(sp_sview, sp_samp, s, t, p, lod_in, control, lod);
 
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int level0 = sp_sview->base.u.tex.first_level + (int)lod[j];
 
/* Catches both negative and large values of level0:
*/
if ((unsigned)level0 >= texture->last_level) {
if (level0 < 0)
img_filter_2d_linear_repeat_POT(sp_sview, sp_samp, s[j], t[j], p[j],
sp_sview->base.u.tex.first_level,
sp_sview->faces[j], &rgba[0][j]);
else
img_filter_2d_linear_repeat_POT(sp_sview, sp_samp, s[j], t[j], p[j],
sp_sview->base.texture->last_level,
sp_sview->faces[j], &rgba[0][j]);
 
}
else {
float levelBlend = frac(lod[j]);
float rgbax[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
int c;
 
img_filter_2d_linear_repeat_POT(sp_sview, sp_samp, s[j], t[j], p[j], level0,
sp_sview->faces[j], &rgbax[0][0]);
img_filter_2d_linear_repeat_POT(sp_sview, sp_samp, s[j], t[j], p[j], level0+1,
sp_sview->faces[j], &rgbax[0][1]);
 
for (c = 0; c < TGSI_NUM_CHANNELS; c++)
rgba[c][j] = lerp(levelBlend, rgbax[c][0], rgbax[c][1]);
}
}
 
if (DEBUG_TEX) {
print_sample_4(__FUNCTION__, rgba);
}
}
 
 
/**
* Do shadow/depth comparisons.
*/
static void
sample_compare(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
const float s[TGSI_QUAD_SIZE],
const float t[TGSI_QUAD_SIZE],
const float p[TGSI_QUAD_SIZE],
const float c0[TGSI_QUAD_SIZE],
const float c1[TGSI_QUAD_SIZE],
enum tgsi_sampler_control control,
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
{
const struct pipe_sampler_state *sampler = &sp_samp->base;
int j, k0, k1, k2, k3;
float val;
float pc0, pc1, pc2, pc3;
 
/**
* Compare texcoord 'p' (aka R) against texture value 'rgba[0]'
* for 2D Array texture we need to use the 'c0' (aka Q).
* When we sampled the depth texture, the depth value was put into all
* RGBA channels. We look at the red channel here.
*/
 
if (sp_sview->base.texture->target == PIPE_TEXTURE_2D_ARRAY ||
sp_sview->base.texture->target == PIPE_TEXTURE_CUBE) {
pc0 = CLAMP(c0[0], 0.0F, 1.0F);
pc1 = CLAMP(c0[1], 0.0F, 1.0F);
pc2 = CLAMP(c0[2], 0.0F, 1.0F);
pc3 = CLAMP(c0[3], 0.0F, 1.0F);
} else if (sp_sview->base.texture->target == PIPE_TEXTURE_CUBE_ARRAY) {
pc0 = CLAMP(c1[0], 0.0F, 1.0F);
pc1 = CLAMP(c1[1], 0.0F, 1.0F);
pc2 = CLAMP(c1[2], 0.0F, 1.0F);
pc3 = CLAMP(c1[3], 0.0F, 1.0F);
} else {
pc0 = CLAMP(p[0], 0.0F, 1.0F);
pc1 = CLAMP(p[1], 0.0F, 1.0F);
pc2 = CLAMP(p[2], 0.0F, 1.0F);
pc3 = CLAMP(p[3], 0.0F, 1.0F);
}
/* compare four texcoords vs. four texture samples */
switch (sampler->compare_func) {
case PIPE_FUNC_LESS:
k0 = pc0 < rgba[0][0];
k1 = pc1 < rgba[0][1];
k2 = pc2 < rgba[0][2];
k3 = pc3 < rgba[0][3];
break;
case PIPE_FUNC_LEQUAL:
k0 = pc0 <= rgba[0][0];
k1 = pc1 <= rgba[0][1];
k2 = pc2 <= rgba[0][2];
k3 = pc3 <= rgba[0][3];
break;
case PIPE_FUNC_GREATER:
k0 = pc0 > rgba[0][0];
k1 = pc1 > rgba[0][1];
k2 = pc2 > rgba[0][2];
k3 = pc3 > rgba[0][3];
break;
case PIPE_FUNC_GEQUAL:
k0 = pc0 >= rgba[0][0];
k1 = pc1 >= rgba[0][1];
k2 = pc2 >= rgba[0][2];
k3 = pc3 >= rgba[0][3];
break;
case PIPE_FUNC_EQUAL:
k0 = pc0 == rgba[0][0];
k1 = pc1 == rgba[0][1];
k2 = pc2 == rgba[0][2];
k3 = pc3 == rgba[0][3];
break;
case PIPE_FUNC_NOTEQUAL:
k0 = pc0 != rgba[0][0];
k1 = pc1 != rgba[0][1];
k2 = pc2 != rgba[0][2];
k3 = pc3 != rgba[0][3];
break;
case PIPE_FUNC_ALWAYS:
k0 = k1 = k2 = k3 = 1;
break;
case PIPE_FUNC_NEVER:
k0 = k1 = k2 = k3 = 0;
break;
default:
k0 = k1 = k2 = k3 = 0;
assert(0);
break;
}
 
if (sampler->mag_img_filter == PIPE_TEX_FILTER_LINEAR) {
/* convert four pass/fail values to an intensity in [0,1] */
/*
* XXX this doesn't actually make much sense.
* We just average the result of four _pixels_ and output the same
* value for all of the four pixels of the quad.
* This really needs to work on the _samples_ i.e. inside the img filter.
*/
val = 0.25F * (k0 + k1 + k2 + k3);
 
/* XXX returning result for default GL_DEPTH_TEXTURE_MODE = GL_LUMINANCE */
for (j = 0; j < 4; j++) {
rgba[0][j] = rgba[1][j] = rgba[2][j] = val;
rgba[3][j] = 1.0F;
}
} else {
for (j = 0; j < 4; j++) {
rgba[0][j] = k0;
rgba[1][j] = k1;
rgba[2][j] = k2;
rgba[3][j] = 1.0F;
}
}
}
 
 
static void
do_swizzling(const struct pipe_sampler_view *sview,
float in[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE],
float out[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
{
int j;
const unsigned swizzle_r = sview->swizzle_r;
const unsigned swizzle_g = sview->swizzle_g;
const unsigned swizzle_b = sview->swizzle_b;
const unsigned swizzle_a = sview->swizzle_a;
 
switch (swizzle_r) {
case PIPE_SWIZZLE_ZERO:
for (j = 0; j < 4; j++)
out[0][j] = 0.0f;
break;
case PIPE_SWIZZLE_ONE:
for (j = 0; j < 4; j++)
out[0][j] = 1.0f;
break;
default:
assert(swizzle_r < 4);
for (j = 0; j < 4; j++)
out[0][j] = in[swizzle_r][j];
}
 
switch (swizzle_g) {
case PIPE_SWIZZLE_ZERO:
for (j = 0; j < 4; j++)
out[1][j] = 0.0f;
break;
case PIPE_SWIZZLE_ONE:
for (j = 0; j < 4; j++)
out[1][j] = 1.0f;
break;
default:
assert(swizzle_g < 4);
for (j = 0; j < 4; j++)
out[1][j] = in[swizzle_g][j];
}
 
switch (swizzle_b) {
case PIPE_SWIZZLE_ZERO:
for (j = 0; j < 4; j++)
out[2][j] = 0.0f;
break;
case PIPE_SWIZZLE_ONE:
for (j = 0; j < 4; j++)
out[2][j] = 1.0f;
break;
default:
assert(swizzle_b < 4);
for (j = 0; j < 4; j++)
out[2][j] = in[swizzle_b][j];
}
 
switch (swizzle_a) {
case PIPE_SWIZZLE_ZERO:
for (j = 0; j < 4; j++)
out[3][j] = 0.0f;
break;
case PIPE_SWIZZLE_ONE:
for (j = 0; j < 4; j++)
out[3][j] = 1.0f;
break;
default:
assert(swizzle_a < 4);
for (j = 0; j < 4; j++)
out[3][j] = in[swizzle_a][j];
}
}
 
 
static wrap_nearest_func
get_nearest_unorm_wrap(unsigned mode)
{
switch (mode) {
case PIPE_TEX_WRAP_CLAMP:
return wrap_nearest_unorm_clamp;
case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
return wrap_nearest_unorm_clamp_to_edge;
case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
return wrap_nearest_unorm_clamp_to_border;
default:
assert(0);
return wrap_nearest_unorm_clamp;
}
}
 
 
static wrap_nearest_func
get_nearest_wrap(unsigned mode)
{
switch (mode) {
case PIPE_TEX_WRAP_REPEAT:
return wrap_nearest_repeat;
case PIPE_TEX_WRAP_CLAMP:
return wrap_nearest_clamp;
case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
return wrap_nearest_clamp_to_edge;
case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
return wrap_nearest_clamp_to_border;
case PIPE_TEX_WRAP_MIRROR_REPEAT:
return wrap_nearest_mirror_repeat;
case PIPE_TEX_WRAP_MIRROR_CLAMP:
return wrap_nearest_mirror_clamp;
case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
return wrap_nearest_mirror_clamp_to_edge;
case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
return wrap_nearest_mirror_clamp_to_border;
default:
assert(0);
return wrap_nearest_repeat;
}
}
 
 
static wrap_linear_func
get_linear_unorm_wrap(unsigned mode)
{
switch (mode) {
case PIPE_TEX_WRAP_CLAMP:
return wrap_linear_unorm_clamp;
case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
return wrap_linear_unorm_clamp_to_edge;
case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
return wrap_linear_unorm_clamp_to_border;
default:
assert(0);
return wrap_linear_unorm_clamp;
}
}
 
 
static wrap_linear_func
get_linear_wrap(unsigned mode)
{
switch (mode) {
case PIPE_TEX_WRAP_REPEAT:
return wrap_linear_repeat;
case PIPE_TEX_WRAP_CLAMP:
return wrap_linear_clamp;
case PIPE_TEX_WRAP_CLAMP_TO_EDGE:
return wrap_linear_clamp_to_edge;
case PIPE_TEX_WRAP_CLAMP_TO_BORDER:
return wrap_linear_clamp_to_border;
case PIPE_TEX_WRAP_MIRROR_REPEAT:
return wrap_linear_mirror_repeat;
case PIPE_TEX_WRAP_MIRROR_CLAMP:
return wrap_linear_mirror_clamp;
case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE:
return wrap_linear_mirror_clamp_to_edge;
case PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER:
return wrap_linear_mirror_clamp_to_border;
default:
assert(0);
return wrap_linear_repeat;
}
}
 
 
/**
* Is swizzling needed for the given state key?
*/
static INLINE bool
any_swizzle(const struct pipe_sampler_view *view)
{
return (view->swizzle_r != PIPE_SWIZZLE_RED ||
view->swizzle_g != PIPE_SWIZZLE_GREEN ||
view->swizzle_b != PIPE_SWIZZLE_BLUE ||
view->swizzle_a != PIPE_SWIZZLE_ALPHA);
}
 
 
static img_filter_func
get_img_filter(const struct sp_sampler_view *sp_sview,
const struct pipe_sampler_state *sampler,
unsigned filter)
{
switch (sp_sview->base.texture->target) {
case PIPE_BUFFER:
case PIPE_TEXTURE_1D:
if (filter == PIPE_TEX_FILTER_NEAREST)
return img_filter_1d_nearest;
else
return img_filter_1d_linear;
break;
case PIPE_TEXTURE_1D_ARRAY:
if (filter == PIPE_TEX_FILTER_NEAREST)
return img_filter_1d_array_nearest;
else
return img_filter_1d_array_linear;
break;
case PIPE_TEXTURE_2D:
case PIPE_TEXTURE_RECT:
/* Try for fast path:
*/
if (sp_sview->pot2d &&
sampler->wrap_s == sampler->wrap_t &&
sampler->normalized_coords)
{
switch (sampler->wrap_s) {
case PIPE_TEX_WRAP_REPEAT:
switch (filter) {
case PIPE_TEX_FILTER_NEAREST:
return img_filter_2d_nearest_repeat_POT;
case PIPE_TEX_FILTER_LINEAR:
return img_filter_2d_linear_repeat_POT;
default:
break;
}
break;
case PIPE_TEX_WRAP_CLAMP:
switch (filter) {
case PIPE_TEX_FILTER_NEAREST:
return img_filter_2d_nearest_clamp_POT;
default:
break;
}
}
}
/* Otherwise use default versions:
*/
if (filter == PIPE_TEX_FILTER_NEAREST)
return img_filter_2d_nearest;
else
return img_filter_2d_linear;
break;
case PIPE_TEXTURE_2D_ARRAY:
if (filter == PIPE_TEX_FILTER_NEAREST)
return img_filter_2d_array_nearest;
else
return img_filter_2d_array_linear;
break;
case PIPE_TEXTURE_CUBE:
if (filter == PIPE_TEX_FILTER_NEAREST)
return img_filter_cube_nearest;
else
return img_filter_cube_linear;
break;
case PIPE_TEXTURE_CUBE_ARRAY:
if (filter == PIPE_TEX_FILTER_NEAREST)
return img_filter_cube_array_nearest;
else
return img_filter_cube_array_linear;
break;
case PIPE_TEXTURE_3D:
if (filter == PIPE_TEX_FILTER_NEAREST)
return img_filter_3d_nearest;
else
return img_filter_3d_linear;
break;
default:
assert(0);
return img_filter_1d_nearest;
}
}
 
 
static void
sample_mip(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
const float s[TGSI_QUAD_SIZE],
const float t[TGSI_QUAD_SIZE],
const float p[TGSI_QUAD_SIZE],
const float c0[TGSI_QUAD_SIZE],
const float lod[TGSI_QUAD_SIZE],
enum tgsi_sampler_control control,
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
{
mip_filter_func mip_filter;
img_filter_func min_img_filter = NULL;
img_filter_func mag_img_filter = NULL;
 
if (sp_sview->pot2d & sp_samp->min_mag_equal_repeat_linear) {
mip_filter = mip_filter_linear_2d_linear_repeat_POT;
}
else {
mip_filter = sp_samp->mip_filter;
min_img_filter = get_img_filter(sp_sview, &sp_samp->base, sp_samp->min_img_filter);
if (sp_samp->min_mag_equal) {
mag_img_filter = min_img_filter;
}
else {
mag_img_filter = get_img_filter(sp_sview, &sp_samp->base, sp_samp->base.mag_img_filter);
}
}
 
mip_filter(sp_sview, sp_samp, min_img_filter, mag_img_filter,
s, t, p, c0, lod, control, rgba);
 
if (sp_samp->base.compare_mode != PIPE_TEX_COMPARE_NONE) {
sample_compare(sp_sview, sp_samp, s, t, p, c0, lod, control, rgba);
}
 
if (sp_sview->need_swizzle) {
float rgba_temp[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
memcpy(rgba_temp, rgba, sizeof(rgba_temp));
do_swizzling(&sp_sview->base, rgba_temp, rgba);
}
 
}
 
 
/**
* Use 3D texcoords to choose a cube face, then sample the 2D cube faces.
* Put face info into the sampler faces[] array.
*/
static void
sample_cube(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
const float s[TGSI_QUAD_SIZE],
const float t[TGSI_QUAD_SIZE],
const float p[TGSI_QUAD_SIZE],
const float c0[TGSI_QUAD_SIZE],
const float c1[TGSI_QUAD_SIZE],
enum tgsi_sampler_control control,
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
{
unsigned j;
float ssss[4], tttt[4];
 
/* Not actually used, but the intermediate steps that do the
* dereferencing don't know it.
*/
static float pppp[4] = { 0, 0, 0, 0 };
 
pppp[0] = c0[0];
pppp[1] = c0[1];
pppp[2] = c0[2];
pppp[3] = c0[3];
/*
major axis
direction target sc tc ma
---------- ------------------------------- --- --- ---
+rx TEXTURE_CUBE_MAP_POSITIVE_X_EXT -rz -ry rx
-rx TEXTURE_CUBE_MAP_NEGATIVE_X_EXT +rz -ry rx
+ry TEXTURE_CUBE_MAP_POSITIVE_Y_EXT +rx +rz ry
-ry TEXTURE_CUBE_MAP_NEGATIVE_Y_EXT +rx -rz ry
+rz TEXTURE_CUBE_MAP_POSITIVE_Z_EXT +rx -ry rz
-rz TEXTURE_CUBE_MAP_NEGATIVE_Z_EXT -rx -ry rz
*/
 
/* Choose the cube face and compute new s/t coords for the 2D face.
*
* Use the same cube face for all four pixels in the quad.
*
* This isn't ideal, but if we want to use a different cube face
* per pixel in the quad, we'd have to also compute the per-face
* LOD here too. That's because the four post-face-selection
* texcoords are no longer related to each other (they're
* per-face!) so we can't use subtraction to compute the partial
* deriviates to compute the LOD. Doing so (near cube edges
* anyway) gives us pretty much random values.
*/
{
/* use the average of the four pixel's texcoords to choose the face */
const float rx = 0.25F * (s[0] + s[1] + s[2] + s[3]);
const float ry = 0.25F * (t[0] + t[1] + t[2] + t[3]);
const float rz = 0.25F * (p[0] + p[1] + p[2] + p[3]);
const float arx = fabsf(rx), ary = fabsf(ry), arz = fabsf(rz);
 
if (arx >= ary && arx >= arz) {
float sign = (rx >= 0.0F) ? 1.0F : -1.0F;
uint face = (rx >= 0.0F) ? PIPE_TEX_FACE_POS_X : PIPE_TEX_FACE_NEG_X;
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
const float ima = -0.5F / fabsf(s[j]);
ssss[j] = sign * p[j] * ima + 0.5F;
tttt[j] = t[j] * ima + 0.5F;
sp_sview->faces[j] = face;
}
}
else if (ary >= arx && ary >= arz) {
float sign = (ry >= 0.0F) ? 1.0F : -1.0F;
uint face = (ry >= 0.0F) ? PIPE_TEX_FACE_POS_Y : PIPE_TEX_FACE_NEG_Y;
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
const float ima = -0.5F / fabsf(t[j]);
ssss[j] = -s[j] * ima + 0.5F;
tttt[j] = sign * -p[j] * ima + 0.5F;
sp_sview->faces[j] = face;
}
}
else {
float sign = (rz >= 0.0F) ? 1.0F : -1.0F;
uint face = (rz >= 0.0F) ? PIPE_TEX_FACE_POS_Z : PIPE_TEX_FACE_NEG_Z;
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
const float ima = -0.5F / fabsf(p[j]);
ssss[j] = sign * -s[j] * ima + 0.5F;
tttt[j] = t[j] * ima + 0.5F;
sp_sview->faces[j] = face;
}
}
}
 
sample_mip(sp_sview, sp_samp, ssss, tttt, pppp, c0, c1, control, rgba);
}
 
 
static void
sp_get_dims(struct sp_sampler_view *sp_sview, int level,
int dims[4])
{
const struct pipe_sampler_view *view = &sp_sview->base;
const struct pipe_resource *texture = view->texture;
 
/* undefined according to EXT_gpu_program */
level += view->u.tex.first_level;
if (level > view->u.tex.last_level)
return;
 
dims[0] = u_minify(texture->width0, level);
 
switch(texture->target) {
case PIPE_TEXTURE_1D_ARRAY:
dims[1] = view->u.tex.last_layer - view->u.tex.first_layer + 1;
/* fallthrough */
case PIPE_TEXTURE_1D:
return;
case PIPE_TEXTURE_2D_ARRAY:
dims[2] = view->u.tex.last_layer - view->u.tex.first_layer + 1;
/* fallthrough */
case PIPE_TEXTURE_2D:
case PIPE_TEXTURE_CUBE:
case PIPE_TEXTURE_RECT:
dims[1] = u_minify(texture->height0, level);
return;
case PIPE_TEXTURE_3D:
dims[1] = u_minify(texture->height0, level);
dims[2] = u_minify(texture->depth0, level);
return;
case PIPE_TEXTURE_CUBE_ARRAY:
dims[1] = u_minify(texture->height0, level);
dims[2] = (view->u.tex.last_layer - view->u.tex.first_layer + 1) / 6;
break;
case PIPE_BUFFER:
dims[0] /= util_format_get_blocksize(view->format);
return;
default:
assert(!"unexpected texture target in sp_get_dims()");
return;
}
}
 
/**
* This function is only used for getting unfiltered texels via the
* TXF opcode. The GL spec says that out-of-bounds texel fetches
* produce undefined results. Instead of crashing, lets just clamp
* coords to the texture image size.
*/
static void
sp_get_texels(struct sp_sampler_view *sp_sview,
const int v_i[TGSI_QUAD_SIZE],
const int v_j[TGSI_QUAD_SIZE],
const int v_k[TGSI_QUAD_SIZE],
const int lod[TGSI_QUAD_SIZE],
const int8_t offset[3],
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
{
union tex_tile_address addr;
const struct pipe_resource *texture = sp_sview->base.texture;
int j, c;
const float *tx;
int width, height, depth;
 
addr.value = 0;
/* TODO write a better test for LOD */
addr.bits.level = lod[0];
 
width = u_minify(texture->width0, addr.bits.level);
height = u_minify(texture->height0, addr.bits.level);
depth = u_minify(texture->depth0, addr.bits.level);
 
switch(texture->target) {
case PIPE_BUFFER:
case PIPE_TEXTURE_1D:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int x = CLAMP(v_i[j] + offset[0], 0, width - 1);
tx = get_texel_2d_no_border(sp_sview, addr, x, 0);
for (c = 0; c < 4; c++) {
rgba[c][j] = tx[c];
}
}
break;
case PIPE_TEXTURE_1D_ARRAY:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int x = CLAMP(v_i[j] + offset[0], 0, width - 1);
int y = CLAMP(v_j[j], sp_sview->base.u.tex.first_layer, sp_sview->base.u.tex.last_layer);
tx = get_texel_2d_no_border(sp_sview, addr, x, y);
for (c = 0; c < 4; c++) {
rgba[c][j] = tx[c];
}
}
break;
case PIPE_TEXTURE_2D:
case PIPE_TEXTURE_RECT:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int x = CLAMP(v_i[j] + offset[0], 0, width - 1);
int y = CLAMP(v_j[j] + offset[1], 0, height - 1);
tx = get_texel_2d_no_border(sp_sview, addr, x, y);
for (c = 0; c < 4; c++) {
rgba[c][j] = tx[c];
}
}
break;
case PIPE_TEXTURE_2D_ARRAY:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int x = CLAMP(v_i[j] + offset[0], 0, width - 1);
int y = CLAMP(v_j[j] + offset[1], 0, height - 1);
int layer = CLAMP(v_k[j], sp_sview->base.u.tex.first_layer, sp_sview->base.u.tex.last_layer);
tx = get_texel_3d_no_border(sp_sview, addr, x, y, layer);
for (c = 0; c < 4; c++) {
rgba[c][j] = tx[c];
}
}
break;
case PIPE_TEXTURE_3D:
for (j = 0; j < TGSI_QUAD_SIZE; j++) {
int x = CLAMP(v_i[j] + offset[0], 0, width - 1);
int y = CLAMP(v_j[j] + offset[1], 0, height - 1);
int z = CLAMP(v_k[j] + offset[2], 0, depth - 1);
tx = get_texel_3d_no_border(sp_sview, addr, x, y, z);
for (c = 0; c < 4; c++) {
rgba[c][j] = tx[c];
}
}
break;
case PIPE_TEXTURE_CUBE: /* TXF can't work on CUBE according to spec */
default:
assert(!"Unknown or CUBE texture type in TXF processing\n");
break;
}
 
if (sp_sview->need_swizzle) {
float rgba_temp[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE];
memcpy(rgba_temp, rgba, sizeof(rgba_temp));
do_swizzling(&sp_sview->base, rgba_temp, rgba);
}
}
 
 
void *
softpipe_create_sampler_state(struct pipe_context *pipe,
const struct pipe_sampler_state *sampler)
{
struct sp_sampler *samp = CALLOC_STRUCT(sp_sampler);
 
samp->base = *sampler;
 
/* Note that (for instance) linear_texcoord_s and
* nearest_texcoord_s may be active at the same time, if the
* sampler min_img_filter differs from its mag_img_filter.
*/
if (sampler->normalized_coords) {
samp->linear_texcoord_s = get_linear_wrap( sampler->wrap_s );
samp->linear_texcoord_t = get_linear_wrap( sampler->wrap_t );
samp->linear_texcoord_p = get_linear_wrap( sampler->wrap_r );
 
samp->nearest_texcoord_s = get_nearest_wrap( sampler->wrap_s );
samp->nearest_texcoord_t = get_nearest_wrap( sampler->wrap_t );
samp->nearest_texcoord_p = get_nearest_wrap( sampler->wrap_r );
}
else {
samp->linear_texcoord_s = get_linear_unorm_wrap( sampler->wrap_s );
samp->linear_texcoord_t = get_linear_unorm_wrap( sampler->wrap_t );
samp->linear_texcoord_p = get_linear_unorm_wrap( sampler->wrap_r );
 
samp->nearest_texcoord_s = get_nearest_unorm_wrap( sampler->wrap_s );
samp->nearest_texcoord_t = get_nearest_unorm_wrap( sampler->wrap_t );
samp->nearest_texcoord_p = get_nearest_unorm_wrap( sampler->wrap_r );
}
 
samp->min_img_filter = sampler->min_img_filter;
 
switch (sampler->min_mip_filter) {
case PIPE_TEX_MIPFILTER_NONE:
if (sampler->min_img_filter == sampler->mag_img_filter)
samp->mip_filter = mip_filter_none_no_filter_select;
else
samp->mip_filter = mip_filter_none;
break;
 
case PIPE_TEX_MIPFILTER_NEAREST:
samp->mip_filter = mip_filter_nearest;
break;
 
case PIPE_TEX_MIPFILTER_LINEAR:
if (sampler->min_img_filter == sampler->mag_img_filter &&
sampler->normalized_coords &&
sampler->wrap_s == PIPE_TEX_WRAP_REPEAT &&
sampler->wrap_t == PIPE_TEX_WRAP_REPEAT &&
sampler->min_img_filter == PIPE_TEX_FILTER_LINEAR &&
sampler->max_anisotropy <= 1) {
samp->min_mag_equal_repeat_linear = TRUE;
}
samp->mip_filter = mip_filter_linear;
 
/* Anisotropic filtering extension. */
if (sampler->max_anisotropy > 1) {
samp->mip_filter = mip_filter_linear_aniso;
 
/* Override min_img_filter:
* min_img_filter needs to be set to NEAREST since we need to access
* each texture pixel as it is and weight it later; using linear
* filters will have incorrect results.
* By setting the filter to NEAREST here, we can avoid calling the
* generic img_filter_2d_nearest in the anisotropic filter function,
* making it possible to use one of the accelerated implementations
*/
samp->min_img_filter = PIPE_TEX_FILTER_NEAREST;
 
/* on first access create the lookup table containing the filter weights. */
if (!weightLut) {
create_filter_table();
}
}
break;
}
if (samp->min_img_filter == sampler->mag_img_filter) {
samp->min_mag_equal = TRUE;
}
 
return (void *)samp;
}
 
 
compute_lambda_func
softpipe_get_lambda_func(const struct pipe_sampler_view *view, unsigned shader)
{
if (shader != PIPE_SHADER_FRAGMENT)
return compute_lambda_vert;
 
switch (view->texture->target) {
case PIPE_BUFFER:
case PIPE_TEXTURE_1D:
case PIPE_TEXTURE_1D_ARRAY:
return compute_lambda_1d;
case PIPE_TEXTURE_2D:
case PIPE_TEXTURE_2D_ARRAY:
case PIPE_TEXTURE_RECT:
case PIPE_TEXTURE_CUBE:
case PIPE_TEXTURE_CUBE_ARRAY:
return compute_lambda_2d;
case PIPE_TEXTURE_3D:
return compute_lambda_3d;
default:
assert(0);
return compute_lambda_1d;
}
}
 
 
struct pipe_sampler_view *
softpipe_create_sampler_view(struct pipe_context *pipe,
struct pipe_resource *resource,
const struct pipe_sampler_view *templ)
{
struct sp_sampler_view *sview = CALLOC_STRUCT(sp_sampler_view);
struct softpipe_resource *spr = (struct softpipe_resource *)resource;
 
if (sview) {
struct pipe_sampler_view *view = &sview->base;
*view = *templ;
view->reference.count = 1;
view->texture = NULL;
pipe_resource_reference(&view->texture, resource);
view->context = pipe;
 
if (any_swizzle(view)) {
sview->need_swizzle = TRUE;
}
 
if (resource->target == PIPE_TEXTURE_CUBE ||
resource->target == PIPE_TEXTURE_CUBE_ARRAY)
sview->get_samples = sample_cube;
else {
sview->get_samples = sample_mip;
}
sview->pot2d = spr->pot &&
(resource->target == PIPE_TEXTURE_2D ||
resource->target == PIPE_TEXTURE_RECT);
 
sview->xpot = util_logbase2( resource->width0 );
sview->ypot = util_logbase2( resource->height0 );
}
 
return (struct pipe_sampler_view *) sview;
}
 
 
static void
sp_tgsi_get_dims(struct tgsi_sampler *tgsi_sampler,
const unsigned sview_index,
int level, int dims[4])
{
struct sp_tgsi_sampler *sp_samp = (struct sp_tgsi_sampler *)tgsi_sampler;
 
assert(sview_index < PIPE_MAX_SHADER_SAMPLER_VIEWS);
/* TODO should have defined behavior if no texture is bound. */
sp_get_dims(&sp_samp->sp_sview[sview_index], level, dims);
}
 
 
static void
sp_tgsi_get_samples(struct tgsi_sampler *tgsi_sampler,
const unsigned sview_index,
const unsigned sampler_index,
const float s[TGSI_QUAD_SIZE],
const float t[TGSI_QUAD_SIZE],
const float p[TGSI_QUAD_SIZE],
const float c0[TGSI_QUAD_SIZE],
const float lod[TGSI_QUAD_SIZE],
float derivs[3][2][TGSI_QUAD_SIZE],
const int8_t offset[3],
enum tgsi_sampler_control control,
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
{
struct sp_tgsi_sampler *sp_samp = (struct sp_tgsi_sampler *)tgsi_sampler;
 
assert(sview_index < PIPE_MAX_SHADER_SAMPLER_VIEWS);
assert(sampler_index < PIPE_MAX_SAMPLERS);
assert(sp_samp->sp_sampler[sampler_index]);
/* FIXME should have defined behavior if no texture is bound. */
assert(sp_samp->sp_sview[sview_index].get_samples);
sp_samp->sp_sview[sview_index].get_samples(&sp_samp->sp_sview[sview_index],
sp_samp->sp_sampler[sampler_index],
s, t, p, c0, lod, control, rgba);
}
 
 
static void
sp_tgsi_get_texel(struct tgsi_sampler *tgsi_sampler,
const unsigned sview_index,
const int i[TGSI_QUAD_SIZE],
const int j[TGSI_QUAD_SIZE], const int k[TGSI_QUAD_SIZE],
const int lod[TGSI_QUAD_SIZE], const int8_t offset[3],
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE])
{
struct sp_tgsi_sampler *sp_samp = (struct sp_tgsi_sampler *)tgsi_sampler;
 
assert(sview_index < PIPE_MAX_SHADER_SAMPLER_VIEWS);
/* FIXME should have defined behavior if no texture is bound. */
assert(sp_samp->sp_sview[sview_index].base.texture);
sp_get_texels(&sp_samp->sp_sview[sview_index], i, j, k, lod, offset, rgba);
}
 
 
struct sp_tgsi_sampler *
sp_create_tgsi_sampler(void)
{
struct sp_tgsi_sampler *samp = CALLOC_STRUCT(sp_tgsi_sampler);
if (!samp)
return NULL;
 
samp->base.get_dims = sp_tgsi_get_dims;
samp->base.get_samples = sp_tgsi_get_samples;
samp->base.get_texel = sp_tgsi_get_texel;
 
return samp;
}
 
/drivers/video/Gallium/drivers/softpipe/sp_tex_sample.h
0,0 → 1,167
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
* Copyright 2010 VMware, Inc. 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.
*
**************************************************************************/
 
#ifndef SP_TEX_SAMPLE_H
#define SP_TEX_SAMPLE_H
 
 
#include "tgsi/tgsi_exec.h"
 
 
struct sp_sampler_view;
struct sp_sampler;
 
typedef void (*wrap_nearest_func)(float s,
unsigned size,
int *icoord);
 
typedef void (*wrap_linear_func)(float s,
unsigned size,
int *icoord0,
int *icoord1,
float *w);
 
typedef float (*compute_lambda_func)(const struct sp_sampler_view *sp_sview,
const float s[TGSI_QUAD_SIZE],
const float t[TGSI_QUAD_SIZE],
const float p[TGSI_QUAD_SIZE]);
 
typedef void (*img_filter_func)(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
float s,
float t,
float p,
unsigned level,
unsigned face_id,
float *rgba);
 
typedef void (*mip_filter_func)(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
img_filter_func min_filter,
img_filter_func mag_filter,
const float s[TGSI_QUAD_SIZE],
const float t[TGSI_QUAD_SIZE],
const float p[TGSI_QUAD_SIZE],
const float c0[TGSI_QUAD_SIZE],
const float lod[TGSI_QUAD_SIZE],
enum tgsi_sampler_control control,
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]);
 
 
typedef void (*filter_func)(struct sp_sampler_view *sp_sview,
struct sp_sampler *sp_samp,
const float s[TGSI_QUAD_SIZE],
const float t[TGSI_QUAD_SIZE],
const float p[TGSI_QUAD_SIZE],
const float c0[TGSI_QUAD_SIZE],
const float lod[TGSI_QUAD_SIZE],
enum tgsi_sampler_control control,
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]);
 
 
typedef void (*fetch_func)(struct sp_sampler_view *sp_sview,
const int i[TGSI_QUAD_SIZE],
const int j[TGSI_QUAD_SIZE], const int k[TGSI_QUAD_SIZE],
const int lod[TGSI_QUAD_SIZE], const int8_t offset[3],
float rgba[TGSI_NUM_CHANNELS][TGSI_QUAD_SIZE]);
 
 
struct sp_sampler_view
{
struct pipe_sampler_view base;
 
/* For sp_get_samples_2d_linear_POT:
*/
unsigned xpot;
unsigned ypot;
 
boolean need_swizzle;
boolean pot2d;
 
filter_func get_samples;
 
/* this is just abusing the sampler_view object as local storage */
unsigned faces[TGSI_QUAD_SIZE];
 
/* these are different per shader type */
struct softpipe_tex_tile_cache *cache;
compute_lambda_func compute_lambda;
 
};
 
 
struct sp_sampler {
struct pipe_sampler_state base;
 
boolean min_mag_equal_repeat_linear;
boolean min_mag_equal;
unsigned min_img_filter;
 
wrap_nearest_func nearest_texcoord_s;
wrap_nearest_func nearest_texcoord_t;
wrap_nearest_func nearest_texcoord_p;
 
wrap_linear_func linear_texcoord_s;
wrap_linear_func linear_texcoord_t;
wrap_linear_func linear_texcoord_p;
 
mip_filter_func mip_filter;
};
 
 
/**
* Subclass of tgsi_sampler
*/
struct sp_tgsi_sampler
{
struct tgsi_sampler base; /**< base class */
struct sp_sampler *sp_sampler[PIPE_MAX_SAMPLERS];
struct sp_sampler_view sp_sview[PIPE_MAX_SHADER_SAMPLER_VIEWS];
 
};
 
compute_lambda_func
softpipe_get_lambda_func(const struct pipe_sampler_view *view, unsigned shader);
 
 
void *
softpipe_create_sampler_state(struct pipe_context *pipe,
const struct pipe_sampler_state *sampler);
 
 
struct pipe_sampler_view *
softpipe_create_sampler_view(struct pipe_context *pipe,
struct pipe_resource *resource,
const struct pipe_sampler_view *templ);
 
 
struct sp_tgsi_sampler *
sp_create_tgsi_sampler(void);
 
 
#endif /* SP_TEX_SAMPLE_H */
/drivers/video/Gallium/drivers/softpipe/sp_tex_tile_cache.c
0,0 → 1,296
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/**
* Texture tile caching.
*
* Author:
* Brian Paul
*/
 
#include "util/u_inlines.h"
#include "util/u_memory.h"
#include "util/u_tile.h"
#include "util/u_format.h"
#include "util/u_math.h"
#include "sp_context.h"
#include "sp_texture.h"
#include "sp_tex_tile_cache.h"
 
 
struct softpipe_tex_tile_cache *
sp_create_tex_tile_cache( struct pipe_context *pipe )
{
struct softpipe_tex_tile_cache *tc;
uint pos;
 
/* make sure max texture size works */
assert((TEX_TILE_SIZE << TEX_ADDR_BITS) >= (1 << (SP_MAX_TEXTURE_2D_LEVELS-1)));
 
tc = CALLOC_STRUCT( softpipe_tex_tile_cache );
if (tc) {
tc->pipe = pipe;
for (pos = 0; pos < Elements(tc->entries); pos++) {
tc->entries[pos].addr.bits.invalid = 1;
}
tc->last_tile = &tc->entries[0]; /* any tile */
}
return tc;
}
 
 
void
sp_destroy_tex_tile_cache(struct softpipe_tex_tile_cache *tc)
{
if (tc) {
uint pos;
 
for (pos = 0; pos < Elements(tc->entries); pos++) {
/*assert(tc->entries[pos].x < 0);*/
}
if (tc->transfer) {
tc->pipe->transfer_unmap(tc->pipe, tc->transfer);
}
if (tc->tex_trans) {
tc->pipe->transfer_unmap(tc->pipe, tc->tex_trans);
}
 
FREE( tc );
}
}
 
 
/**
* Invalidate all cached tiles for the cached texture.
* Should be called when the texture is modified.
*/
void
sp_tex_tile_cache_validate_texture(struct softpipe_tex_tile_cache *tc)
{
unsigned i;
 
assert(tc);
assert(tc->texture);
 
for (i = 0; i < Elements(tc->entries); i++) {
tc->entries[i].addr.bits.invalid = 1;
}
}
 
static boolean
sp_tex_tile_is_compat_view(struct softpipe_tex_tile_cache *tc,
struct pipe_sampler_view *view)
{
if (!view)
return FALSE;
return (tc->texture == view->texture &&
tc->format == view->format &&
tc->swizzle_r == view->swizzle_r &&
tc->swizzle_g == view->swizzle_g &&
tc->swizzle_b == view->swizzle_b &&
tc->swizzle_a == view->swizzle_a);
}
 
/**
* Specify the sampler view to cache.
*/
void
sp_tex_tile_cache_set_sampler_view(struct softpipe_tex_tile_cache *tc,
struct pipe_sampler_view *view)
{
struct pipe_resource *texture = view ? view->texture : NULL;
uint i;
 
assert(!tc->transfer);
 
if (!sp_tex_tile_is_compat_view(tc, view)) {
pipe_resource_reference(&tc->texture, texture);
 
if (tc->tex_trans_map) {
tc->pipe->transfer_unmap(tc->pipe, tc->tex_trans);
tc->tex_trans = NULL;
tc->tex_trans_map = NULL;
}
 
if (view) {
tc->swizzle_r = view->swizzle_r;
tc->swizzle_g = view->swizzle_g;
tc->swizzle_b = view->swizzle_b;
tc->swizzle_a = view->swizzle_a;
tc->format = view->format;
}
 
/* mark as entries as invalid/empty */
/* XXX we should try to avoid this when the teximage hasn't changed */
for (i = 0; i < Elements(tc->entries); i++) {
tc->entries[i].addr.bits.invalid = 1;
}
 
tc->tex_face = -1; /* any invalid value here */
}
}
 
 
 
 
/**
* Flush the tile cache: write all dirty tiles back to the transfer.
* any tiles "flagged" as cleared will be "really" cleared.
*/
void
sp_flush_tex_tile_cache(struct softpipe_tex_tile_cache *tc)
{
int pos;
 
if (tc->texture) {
/* caching a texture, mark all entries as empty */
for (pos = 0; pos < Elements(tc->entries); pos++) {
tc->entries[pos].addr.bits.invalid = 1;
}
tc->tex_face = -1;
}
 
}
 
 
/**
* Given the texture face, level, zslice, x and y values, compute
* the cache entry position/index where we'd hope to find the
* cached texture tile.
* This is basically a direct-map cache.
* XXX There's probably lots of ways in which we can improve this.
*/
static INLINE uint
tex_cache_pos( union tex_tile_address addr )
{
uint entry = (addr.bits.x +
addr.bits.y * 9 +
addr.bits.z * 3 +
addr.bits.face +
addr.bits.level * 7);
 
return entry % NUM_TEX_TILE_ENTRIES;
}
 
/**
* Similar to sp_get_cached_tile() but for textures.
* Tiles are read-only and indexed with more params.
*/
const struct softpipe_tex_cached_tile *
sp_find_cached_tile_tex(struct softpipe_tex_tile_cache *tc,
union tex_tile_address addr )
{
struct softpipe_tex_cached_tile *tile;
boolean zs = util_format_is_depth_or_stencil(tc->format);
 
tile = tc->entries + tex_cache_pos( addr );
 
if (addr.value != tile->addr.value) {
 
/* cache miss. Most misses are because we've invalidated the
* texture cache previously -- most commonly on binding a new
* texture. Currently we effectively flush the cache on texture
* bind.
*/
#if 0
_debug_printf("miss at %u: x=%d y=%d z=%d face=%d level=%d\n"
" tile %u: x=%d y=%d z=%d face=%d level=%d\n",
pos, x/TILE_SIZE, y/TILE_SIZE, z, face, level,
pos, tile->addr.bits.x, tile->addr.bits.y, tile->z, tile->face, tile->level);
#endif
 
/* check if we need to get a new transfer */
if (!tc->tex_trans ||
tc->tex_face != addr.bits.face ||
tc->tex_level != addr.bits.level ||
tc->tex_z != addr.bits.z) {
/* get new transfer (view into texture) */
unsigned width, height, layer;
 
if (tc->tex_trans_map) {
tc->pipe->transfer_unmap(tc->pipe, tc->tex_trans);
tc->tex_trans = NULL;
tc->tex_trans_map = NULL;
}
 
width = u_minify(tc->texture->width0, addr.bits.level);
if (tc->texture->target == PIPE_TEXTURE_1D_ARRAY) {
height = tc->texture->array_size;
layer = 0;
}
else {
height = u_minify(tc->texture->height0, addr.bits.level);
layer = addr.bits.face + addr.bits.z;
}
 
tc->tex_trans_map =
pipe_transfer_map(tc->pipe, tc->texture,
addr.bits.level,
layer,
PIPE_TRANSFER_READ | PIPE_TRANSFER_UNSYNCHRONIZED,
0, 0, width, height, &tc->tex_trans);
 
tc->tex_face = addr.bits.face;
tc->tex_level = addr.bits.level;
tc->tex_z = addr.bits.z;
}
 
/* Get tile from the transfer (view into texture), explicitly passing
* the image format.
*/
if (!zs && util_format_is_pure_uint(tc->format)) {
pipe_get_tile_ui_format(tc->tex_trans, tc->tex_trans_map,
addr.bits.x * TEX_TILE_SIZE,
addr.bits.y * TEX_TILE_SIZE,
TEX_TILE_SIZE,
TEX_TILE_SIZE,
tc->format,
(unsigned *) tile->data.colorui);
} else if (!zs && util_format_is_pure_sint(tc->format)) {
pipe_get_tile_i_format(tc->tex_trans, tc->tex_trans_map,
addr.bits.x * TEX_TILE_SIZE,
addr.bits.y * TEX_TILE_SIZE,
TEX_TILE_SIZE,
TEX_TILE_SIZE,
tc->format,
(int *) tile->data.colori);
} else {
pipe_get_tile_rgba_format(tc->tex_trans, tc->tex_trans_map,
addr.bits.x * TEX_TILE_SIZE,
addr.bits.y * TEX_TILE_SIZE,
TEX_TILE_SIZE,
TEX_TILE_SIZE,
tc->format,
(float *) tile->data.color);
}
tile->addr = addr;
}
 
tc->last_tile = tile;
return tile;
}
/drivers/video/Gallium/drivers/softpipe/sp_tex_tile_cache.h
0,0 → 1,164
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
#ifndef SP_TEX_TILE_CACHE_H
#define SP_TEX_TILE_CACHE_H
 
 
#include "pipe/p_compiler.h"
#include "sp_limits.h"
 
 
struct softpipe_context;
struct softpipe_tex_tile_cache;
 
 
/**
* Cache tile size (width and height). This needs to be a power of two.
*/
#define TEX_TILE_SIZE_LOG2 5
#define TEX_TILE_SIZE (1 << TEX_TILE_SIZE_LOG2)
 
 
#define TEX_ADDR_BITS (SP_MAX_TEXTURE_2D_LEVELS - 1 - TEX_TILE_SIZE_LOG2)
#define TEX_Z_BITS (SP_MAX_TEXTURE_2D_LEVELS - 1)
 
/**
* Texture tile address as a union for fast compares.
*/
union tex_tile_address {
struct {
unsigned x:TEX_ADDR_BITS; /* 16K / TILE_SIZE */
unsigned y:TEX_ADDR_BITS; /* 16K / TILE_SIZE */
unsigned z:TEX_Z_BITS; /* 16K -- z not tiled */
unsigned face:3;
unsigned level:4;
unsigned invalid:1;
} bits;
uint64_t value;
};
 
 
struct softpipe_tex_cached_tile
{
union tex_tile_address addr;
union {
float color[TEX_TILE_SIZE][TEX_TILE_SIZE][4];
unsigned int colorui[TEX_TILE_SIZE][TEX_TILE_SIZE][4];
int colori[TEX_TILE_SIZE][TEX_TILE_SIZE][4];
} data;
};
 
/*
* The number of cache entries.
* Should not be decreased to lower than 16, and even that
* seems too low to avoid cache thrashing in some cases (because
* the cache is direct mapped, see tex_cache_pos() function).
*/
#define NUM_TEX_TILE_ENTRIES 16
 
struct softpipe_tex_tile_cache
{
struct pipe_context *pipe;
struct pipe_transfer *transfer;
void *transfer_map;
 
struct pipe_resource *texture; /**< if caching a texture */
unsigned timestamp;
 
struct softpipe_tex_cached_tile entries[NUM_TEX_TILE_ENTRIES];
 
struct pipe_transfer *tex_trans;
void *tex_trans_map;
int tex_face, tex_level, tex_z;
 
unsigned swizzle_r;
unsigned swizzle_g;
unsigned swizzle_b;
unsigned swizzle_a;
enum pipe_format format;
 
struct softpipe_tex_cached_tile *last_tile; /**< most recently retrieved tile */
};
 
 
extern struct softpipe_tex_tile_cache *
sp_create_tex_tile_cache( struct pipe_context *pipe );
 
extern void
sp_destroy_tex_tile_cache(struct softpipe_tex_tile_cache *tc);
 
extern void
sp_tex_tile_cache_set_sampler_view(struct softpipe_tex_tile_cache *tc,
struct pipe_sampler_view *view);
 
void
sp_tex_tile_cache_validate_texture(struct softpipe_tex_tile_cache *tc);
 
extern void
sp_flush_tex_tile_cache(struct softpipe_tex_tile_cache *tc);
 
 
 
extern const struct softpipe_tex_cached_tile *
sp_find_cached_tile_tex(struct softpipe_tex_tile_cache *tc,
union tex_tile_address addr );
 
static INLINE union tex_tile_address
tex_tile_address( unsigned x,
unsigned y,
unsigned z,
unsigned face,
unsigned level )
{
union tex_tile_address addr;
 
addr.value = 0;
addr.bits.x = x / TEX_TILE_SIZE;
addr.bits.y = y / TEX_TILE_SIZE;
addr.bits.z = z;
addr.bits.face = face;
addr.bits.level = level;
 
return addr;
}
 
/* Quickly retrieve tile if it matches last lookup.
*/
static INLINE const struct softpipe_tex_cached_tile *
sp_get_cached_tile_tex(struct softpipe_tex_tile_cache *tc,
union tex_tile_address addr )
{
if (tc->last_tile->addr.value == addr.value)
return tc->last_tile;
 
return sp_find_cached_tile_tex( tc, addr );
}
 
 
#endif /* SP_TEX_TILE_CACHE_H */
 
/drivers/video/Gallium/drivers/softpipe/sp_texture.c
0,0 → 1,526
/**************************************************************************
*
* Copyright 2006 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.
*
**************************************************************************/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
* Michel Dänzer <michel@tungstengraphics.com>
*/
 
#include "pipe/p_defines.h"
#include "util/u_inlines.h"
 
#include "util/u_format.h"
#include "util/u_math.h"
#include "util/u_memory.h"
#include "util/u_transfer.h"
 
#include "sp_context.h"
#include "sp_flush.h"
#include "sp_texture.h"
#include "sp_screen.h"
 
#include "state_tracker/sw_winsys.h"
 
 
/**
* Conventional allocation path for non-display textures:
* Use a simple, maximally packed layout.
*/
static boolean
softpipe_resource_layout(struct pipe_screen *screen,
struct softpipe_resource *spr,
boolean allocate)
{
struct pipe_resource *pt = &spr->base;
unsigned level;
unsigned width = pt->width0;
unsigned height = pt->height0;
unsigned depth = pt->depth0;
unsigned buffer_size = 0;
 
for (level = 0; level <= pt->last_level; level++) {
unsigned slices;
 
if (pt->target == PIPE_TEXTURE_CUBE)
slices = 6;
else if (pt->target == PIPE_TEXTURE_3D)
slices = depth;
else
slices = pt->array_size;
 
spr->stride[level] = util_format_get_stride(pt->format, width);
 
spr->level_offset[level] = buffer_size;
 
buffer_size += (util_format_get_nblocksy(pt->format, height) *
slices * spr->stride[level]);
 
width = u_minify(width, 1);
height = u_minify(height, 1);
depth = u_minify(depth, 1);
}
 
if (buffer_size > SP_MAX_TEXTURE_SIZE)
return FALSE;
 
if (allocate) {
spr->data = align_malloc(buffer_size, 16);
return spr->data != NULL;
}
else {
return TRUE;
}
}
 
 
/**
* Check the size of the texture specified by 'res'.
* \return TRUE if OK, FALSE if too large.
*/
static boolean
softpipe_can_create_resource(struct pipe_screen *screen,
const struct pipe_resource *res)
{
struct softpipe_resource spr;
memset(&spr, 0, sizeof(spr));
spr.base = *res;
return softpipe_resource_layout(screen, &spr, FALSE);
}
 
 
/**
* Texture layout for simple color buffers.
*/
static boolean
softpipe_displaytarget_layout(struct pipe_screen *screen,
struct softpipe_resource *spr)
{
struct sw_winsys *winsys = softpipe_screen(screen)->winsys;
 
/* Round up the surface size to a multiple of the tile size?
*/
spr->dt = winsys->displaytarget_create(winsys,
spr->base.bind,
spr->base.format,
spr->base.width0,
spr->base.height0,
16,
&spr->stride[0] );
 
return spr->dt != NULL;
}
 
 
/**
* Create new pipe_resource given the template information.
*/
static struct pipe_resource *
softpipe_resource_create(struct pipe_screen *screen,
const struct pipe_resource *templat)
{
struct softpipe_resource *spr = CALLOC_STRUCT(softpipe_resource);
if (!spr)
return NULL;
 
assert(templat->format != PIPE_FORMAT_NONE);
 
spr->base = *templat;
pipe_reference_init(&spr->base.reference, 1);
spr->base.screen = screen;
 
spr->pot = (util_is_power_of_two(templat->width0) &&
util_is_power_of_two(templat->height0) &&
util_is_power_of_two(templat->depth0));
 
if (spr->base.bind & (PIPE_BIND_DISPLAY_TARGET |
PIPE_BIND_SCANOUT |
PIPE_BIND_SHARED)) {
if (!softpipe_displaytarget_layout(screen, spr))
goto fail;
}
else {
if (!softpipe_resource_layout(screen, spr, TRUE))
goto fail;
}
return &spr->base;
 
fail:
FREE(spr);
return NULL;
}
 
 
static void
softpipe_resource_destroy(struct pipe_screen *pscreen,
struct pipe_resource *pt)
{
struct softpipe_screen *screen = softpipe_screen(pscreen);
struct softpipe_resource *spr = softpipe_resource(pt);
 
if (spr->dt) {
/* display target */
struct sw_winsys *winsys = screen->winsys;
winsys->displaytarget_destroy(winsys, spr->dt);
}
else if (!spr->userBuffer) {
/* regular texture */
align_free(spr->data);
}
 
FREE(spr);
}
 
 
static struct pipe_resource *
softpipe_resource_from_handle(struct pipe_screen *screen,
const struct pipe_resource *templat,
struct winsys_handle *whandle)
{
struct sw_winsys *winsys = softpipe_screen(screen)->winsys;
struct softpipe_resource *spr = CALLOC_STRUCT(softpipe_resource);
if (!spr)
return NULL;
 
spr->base = *templat;
pipe_reference_init(&spr->base.reference, 1);
spr->base.screen = screen;
 
spr->pot = (util_is_power_of_two(templat->width0) &&
util_is_power_of_two(templat->height0) &&
util_is_power_of_two(templat->depth0));
 
spr->dt = winsys->displaytarget_from_handle(winsys,
templat,
whandle,
&spr->stride[0]);
if (!spr->dt)
goto fail;
 
return &spr->base;
 
fail:
FREE(spr);
return NULL;
}
 
 
static boolean
softpipe_resource_get_handle(struct pipe_screen *screen,
struct pipe_resource *pt,
struct winsys_handle *whandle)
{
struct sw_winsys *winsys = softpipe_screen(screen)->winsys;
struct softpipe_resource *spr = softpipe_resource(pt);
 
assert(spr->dt);
if (!spr->dt)
return FALSE;
 
return winsys->displaytarget_get_handle(winsys, spr->dt, whandle);
}
 
 
/**
* Helper function to compute offset (in bytes) for a particular
* texture level/face/slice from the start of the buffer.
*/
static unsigned
sp_get_tex_image_offset(const struct softpipe_resource *spr,
unsigned level, unsigned layer)
{
const unsigned hgt = u_minify(spr->base.height0, level);
const unsigned nblocksy = util_format_get_nblocksy(spr->base.format, hgt);
unsigned offset = spr->level_offset[level];
 
if (spr->base.target == PIPE_TEXTURE_CUBE ||
spr->base.target == PIPE_TEXTURE_CUBE_ARRAY ||
spr->base.target == PIPE_TEXTURE_3D ||
spr->base.target == PIPE_TEXTURE_2D_ARRAY) {
offset += layer * nblocksy * spr->stride[level];
}
else if (spr->base.target == PIPE_TEXTURE_1D_ARRAY) {
offset += layer * spr->stride[level];
}
else {
assert(layer == 0);
}
 
return offset;
}
 
 
/**
* Get a pipe_surface "view" into a texture resource.
*/
static struct pipe_surface *
softpipe_create_surface(struct pipe_context *pipe,
struct pipe_resource *pt,
const struct pipe_surface *surf_tmpl)
{
struct pipe_surface *ps;
 
ps = CALLOC_STRUCT(pipe_surface);
if (ps) {
pipe_reference_init(&ps->reference, 1);
pipe_resource_reference(&ps->texture, pt);
ps->context = pipe;
ps->format = surf_tmpl->format;
if (pt->target != PIPE_BUFFER) {
assert(surf_tmpl->u.tex.level <= pt->last_level);
ps->width = u_minify(pt->width0, surf_tmpl->u.tex.level);
ps->height = u_minify(pt->height0, surf_tmpl->u.tex.level);
ps->u.tex.level = surf_tmpl->u.tex.level;
ps->u.tex.first_layer = surf_tmpl->u.tex.first_layer;
ps->u.tex.last_layer = surf_tmpl->u.tex.last_layer;
if (ps->u.tex.first_layer != ps->u.tex.last_layer) {
debug_printf("creating surface with multiple layers, rendering to first layer only\n");
}
}
else {
/* setting width as number of elements should get us correct renderbuffer width */
ps->width = surf_tmpl->u.buf.last_element - surf_tmpl->u.buf.first_element + 1;
ps->height = pt->height0;
ps->u.buf.first_element = surf_tmpl->u.buf.first_element;
ps->u.buf.last_element = surf_tmpl->u.buf.last_element;
assert(ps->u.buf.first_element <= ps->u.buf.last_element);
assert(ps->u.buf.last_element < ps->width);
}
}
return ps;
}
 
 
/**
* Free a pipe_surface which was created with softpipe_create_surface().
*/
static void
softpipe_surface_destroy(struct pipe_context *pipe,
struct pipe_surface *surf)
{
/* Effectively do the texture_update work here - if texture images
* needed post-processing to put them into hardware layout, this is
* where it would happen. For softpipe, nothing to do.
*/
assert(surf->texture);
pipe_resource_reference(&surf->texture, NULL);
FREE(surf);
}
 
 
/**
* Geta pipe_transfer object which is used for moving data in/out of
* a resource object.
* \param pipe rendering context
* \param resource the resource to transfer in/out of
* \param level which mipmap level
* \param usage bitmask of PIPE_TRANSFER_x flags
* \param box the 1D/2D/3D region of interest
*/
static void *
softpipe_transfer_map(struct pipe_context *pipe,
struct pipe_resource *resource,
unsigned level,
unsigned usage,
const struct pipe_box *box,
struct pipe_transfer **transfer)
{
struct sw_winsys *winsys = softpipe_screen(pipe->screen)->winsys;
struct softpipe_resource *spr = softpipe_resource(resource);
struct softpipe_transfer *spt;
struct pipe_transfer *pt;
enum pipe_format format = resource->format;
const unsigned hgt = u_minify(spr->base.height0, level);
const unsigned nblocksy = util_format_get_nblocksy(format, hgt);
uint8_t *map;
 
assert(resource);
assert(level <= resource->last_level);
 
/* make sure the requested region is in the image bounds */
assert(box->x + box->width <= u_minify(resource->width0, level));
if (resource->target == PIPE_TEXTURE_1D_ARRAY) {
assert(box->y + box->height <= resource->array_size);
}
else {
assert(box->y + box->height <= u_minify(resource->height0, level));
if (resource->target == PIPE_TEXTURE_2D_ARRAY) {
assert(box->z + box->depth <= resource->array_size);
}
else if (resource->target == PIPE_TEXTURE_CUBE) {
assert(box->z < 6);
}
else if (resource->target == PIPE_TEXTURE_CUBE_ARRAY) {
assert(box->z <= resource->array_size);
}
else {
assert(box->z + box->depth <= (u_minify(resource->depth0, level)));
}
}
 
/*
* Transfers, like other pipe operations, must happen in order, so flush the
* context if necessary.
*/
if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) {
boolean read_only = !(usage & PIPE_TRANSFER_WRITE);
boolean do_not_block = !!(usage & PIPE_TRANSFER_DONTBLOCK);
if (!softpipe_flush_resource(pipe, resource,
level, box->depth > 1 ? -1 : box->z,
0, /* flush_flags */
read_only,
TRUE, /* cpu_access */
do_not_block)) {
/*
* It would have blocked, but state tracker requested no to.
*/
assert(do_not_block);
return NULL;
}
}
 
spt = CALLOC_STRUCT(softpipe_transfer);
if (!spt)
return NULL;
 
pt = &spt->base;
 
pipe_resource_reference(&pt->resource, resource);
pt->level = level;
pt->usage = usage;
pt->box = *box;
pt->stride = spr->stride[level];
pt->layer_stride = pt->stride * nblocksy;
 
spt->offset = sp_get_tex_image_offset(spr, level, box->z);
 
spt->offset +=
box->y / util_format_get_blockheight(format) * spt->base.stride +
box->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format);
 
/* resources backed by display target treated specially:
*/
if (spr->dt) {
map = winsys->displaytarget_map(winsys, spr->dt, usage);
}
else {
map = spr->data;
}
 
if (map == NULL) {
pipe_resource_reference(&pt->resource, NULL);
FREE(spt);
return NULL;
}
 
*transfer = pt;
return map + spt->offset;
}
 
 
/**
* Unmap memory mapping for given pipe_transfer object.
*/
static void
softpipe_transfer_unmap(struct pipe_context *pipe,
struct pipe_transfer *transfer)
{
struct softpipe_resource *spr;
 
assert(transfer->resource);
spr = softpipe_resource(transfer->resource);
 
if (spr->dt) {
/* display target */
struct sw_winsys *winsys = softpipe_screen(pipe->screen)->winsys;
winsys->displaytarget_unmap(winsys, spr->dt);
}
 
if (transfer->usage & PIPE_TRANSFER_WRITE) {
/* Mark the texture as dirty to expire the tile caches. */
spr->timestamp++;
}
 
pipe_resource_reference(&transfer->resource, NULL);
FREE(transfer);
}
 
/**
* Create buffer which wraps user-space data.
*/
struct pipe_resource *
softpipe_user_buffer_create(struct pipe_screen *screen,
void *ptr,
unsigned bytes,
unsigned bind_flags)
{
struct softpipe_resource *spr;
 
spr = CALLOC_STRUCT(softpipe_resource);
if (!spr)
return NULL;
 
pipe_reference_init(&spr->base.reference, 1);
spr->base.screen = screen;
spr->base.format = PIPE_FORMAT_R8_UNORM; /* ?? */
spr->base.bind = bind_flags;
spr->base.usage = PIPE_USAGE_IMMUTABLE;
spr->base.flags = 0;
spr->base.width0 = bytes;
spr->base.height0 = 1;
spr->base.depth0 = 1;
spr->base.array_size = 1;
spr->userBuffer = TRUE;
spr->data = ptr;
 
return &spr->base;
}
 
 
void
softpipe_init_texture_funcs(struct pipe_context *pipe)
{
pipe->transfer_map = softpipe_transfer_map;
pipe->transfer_unmap = softpipe_transfer_unmap;
 
pipe->transfer_flush_region = u_default_transfer_flush_region;
pipe->transfer_inline_write = u_default_transfer_inline_write;
 
pipe->create_surface = softpipe_create_surface;
pipe->surface_destroy = softpipe_surface_destroy;
}
 
 
void
softpipe_init_screen_texture_funcs(struct pipe_screen *screen)
{
screen->resource_create = softpipe_resource_create;
screen->resource_destroy = softpipe_resource_destroy;
screen->resource_from_handle = softpipe_resource_from_handle;
screen->resource_get_handle = softpipe_resource_get_handle;
screen->can_create_resource = softpipe_can_create_resource;
}
/drivers/video/Gallium/drivers/softpipe/sp_texture.h
0,0 → 1,103
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
#ifndef SP_TEXTURE_H
#define SP_TEXTURE_H
 
 
#include "pipe/p_state.h"
#include "sp_limits.h"
 
 
struct pipe_context;
struct pipe_screen;
struct softpipe_context;
 
 
/**
* Subclass of pipe_resource.
*/
struct softpipe_resource
{
struct pipe_resource base;
 
unsigned long level_offset[SP_MAX_TEXTURE_2D_LEVELS];
unsigned stride[SP_MAX_TEXTURE_2D_LEVELS];
 
/**
* Display target, only valid for PIPE_TEXTURE_2D with the
* PIPE_BIND_DISPLAY_TARGET usage.
*/
struct sw_displaytarget *dt;
 
/**
* Malloc'ed data for regular buffers and textures, or a mapping to dt above.
*/
void *data;
 
/* True if texture images are power-of-two in all dimensions:
*/
boolean pot;
boolean userBuffer;
 
unsigned timestamp;
};
 
 
/**
* Subclass of pipe_transfer.
*/
struct softpipe_transfer
{
struct pipe_transfer base;
 
unsigned long offset;
};
 
 
/** cast wrappers */
static INLINE struct softpipe_resource *
softpipe_resource(struct pipe_resource *pt)
{
return (struct softpipe_resource *) pt;
}
 
static INLINE struct softpipe_transfer *
softpipe_transfer(struct pipe_transfer *pt)
{
return (struct softpipe_transfer *) pt;
}
 
 
extern void
softpipe_init_screen_texture_funcs(struct pipe_screen *screen);
 
extern void
softpipe_init_texture_funcs(struct pipe_context *pipe);
 
 
#endif /* SP_TEXTURE */
/drivers/video/Gallium/drivers/softpipe/sp_tile_cache.c
0,0 → 1,615
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
/**
* Render target tile caching.
*
* Author:
* Brian Paul
*/
 
#include "util/u_inlines.h"
#include "util/u_format.h"
#include "util/u_memory.h"
#include "util/u_tile.h"
#include "sp_tile_cache.h"
 
static struct softpipe_cached_tile *
sp_alloc_tile(struct softpipe_tile_cache *tc);
 
 
/**
* Return the position in the cache for the tile that contains win pos (x,y).
* We currently use a direct mapped cache so this is like a hack key.
* At some point we should investige something more sophisticated, like
* a LRU replacement policy.
*/
#define CACHE_POS(x, y) \
(((x) + (y) * 5) % NUM_ENTRIES)
 
 
 
/**
* Is the tile at (x,y) in cleared state?
*/
static INLINE uint
is_clear_flag_set(const uint *bitvec, union tile_address addr)
{
int pos, bit;
pos = addr.bits.y * (MAX_WIDTH / TILE_SIZE) + addr.bits.x;
assert(pos / 32 < (MAX_WIDTH / TILE_SIZE) * (MAX_HEIGHT / TILE_SIZE) / 32);
bit = bitvec[pos / 32] & (1 << (pos & 31));
return bit;
}
 
/**
* Mark the tile at (x,y) as not cleared.
*/
static INLINE void
clear_clear_flag(uint *bitvec, union tile_address addr)
{
int pos;
pos = addr.bits.y * (MAX_WIDTH / TILE_SIZE) + addr.bits.x;
assert(pos / 32 < (MAX_WIDTH / TILE_SIZE) * (MAX_HEIGHT / TILE_SIZE) / 32);
bitvec[pos / 32] &= ~(1 << (pos & 31));
}
 
struct softpipe_tile_cache *
sp_create_tile_cache( struct pipe_context *pipe )
{
struct softpipe_tile_cache *tc;
uint pos;
int maxLevels, maxTexSize;
 
/* sanity checking: max sure MAX_WIDTH/HEIGHT >= largest texture image */
maxLevels = pipe->screen->get_param(pipe->screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS);
maxTexSize = 1 << (maxLevels - 1);
assert(MAX_WIDTH >= maxTexSize);
 
assert(sizeof(union tile_address) == 4);
 
assert((TILE_SIZE << TILE_ADDR_BITS) >= MAX_WIDTH);
 
tc = CALLOC_STRUCT( softpipe_tile_cache );
if (tc) {
tc->pipe = pipe;
for (pos = 0; pos < Elements(tc->tile_addrs); pos++) {
tc->tile_addrs[pos].bits.invalid = 1;
}
tc->last_tile_addr.bits.invalid = 1;
 
/* this allocation allows us to guarantee that allocation
* failures are never fatal later
*/
tc->tile = MALLOC_STRUCT( softpipe_cached_tile );
if (!tc->tile)
{
FREE(tc);
return NULL;
}
 
/* XXX this code prevents valgrind warnings about use of uninitialized
* memory in programs that don't clear the surface before rendering.
* However, it breaks clearing in other situations (such as in
* progs/tests/drawbuffers, see bug 24402).
*/
#if 0
/* set flags to indicate all the tiles are cleared */
memset(tc->clear_flags, 255, sizeof(tc->clear_flags));
#endif
}
return tc;
}
 
 
void
sp_destroy_tile_cache(struct softpipe_tile_cache *tc)
{
if (tc) {
uint pos;
 
for (pos = 0; pos < Elements(tc->entries); pos++) {
/*assert(tc->entries[pos].x < 0);*/
FREE( tc->entries[pos] );
}
FREE( tc->tile );
 
if (tc->transfer) {
tc->pipe->transfer_unmap(tc->pipe, tc->transfer);
}
 
FREE( tc );
}
}
 
 
/**
* Specify the surface to cache.
*/
void
sp_tile_cache_set_surface(struct softpipe_tile_cache *tc,
struct pipe_surface *ps)
{
struct pipe_context *pipe = tc->pipe;
 
if (tc->transfer_map) {
if (ps == tc->surface)
return;
 
pipe->transfer_unmap(pipe, tc->transfer);
tc->transfer = NULL;
tc->transfer_map = NULL;
}
 
tc->surface = ps;
 
if (ps) {
if (ps->texture->target != PIPE_BUFFER) {
tc->transfer_map = pipe_transfer_map(pipe, ps->texture,
ps->u.tex.level, ps->u.tex.first_layer,
PIPE_TRANSFER_READ_WRITE |
PIPE_TRANSFER_UNSYNCHRONIZED,
0, 0, ps->width, ps->height,
&tc->transfer);
}
else {
/* can't render to buffers */
assert(0);
}
 
tc->depth_stencil = util_format_is_depth_or_stencil(ps->format);
}
}
 
 
/**
* Return the transfer being cached.
*/
struct pipe_surface *
sp_tile_cache_get_surface(struct softpipe_tile_cache *tc)
{
return tc->surface;
}
 
 
/**
* Set pixels in a tile to the given clear color/value, float.
*/
static void
clear_tile_rgba(struct softpipe_cached_tile *tile,
enum pipe_format format,
const union pipe_color_union *clear_value)
{
if (clear_value->f[0] == 0.0 &&
clear_value->f[1] == 0.0 &&
clear_value->f[2] == 0.0 &&
clear_value->f[3] == 0.0) {
memset(tile->data.color, 0, sizeof(tile->data.color));
}
else {
uint i, j;
 
if (util_format_is_pure_uint(format)) {
for (i = 0; i < TILE_SIZE; i++) {
for (j = 0; j < TILE_SIZE; j++) {
tile->data.colorui128[i][j][0] = clear_value->ui[0];
tile->data.colorui128[i][j][1] = clear_value->ui[1];
tile->data.colorui128[i][j][2] = clear_value->ui[2];
tile->data.colorui128[i][j][3] = clear_value->ui[3];
}
}
} else if (util_format_is_pure_sint(format)) {
for (i = 0; i < TILE_SIZE; i++) {
for (j = 0; j < TILE_SIZE; j++) {
tile->data.colori128[i][j][0] = clear_value->i[0];
tile->data.colori128[i][j][1] = clear_value->i[1];
tile->data.colori128[i][j][2] = clear_value->i[2];
tile->data.colori128[i][j][3] = clear_value->i[3];
}
}
} else {
for (i = 0; i < TILE_SIZE; i++) {
for (j = 0; j < TILE_SIZE; j++) {
tile->data.color[i][j][0] = clear_value->f[0];
tile->data.color[i][j][1] = clear_value->f[1];
tile->data.color[i][j][2] = clear_value->f[2];
tile->data.color[i][j][3] = clear_value->f[3];
}
}
}
}
}
 
 
/**
* Set a tile to a solid value/color.
*/
static void
clear_tile(struct softpipe_cached_tile *tile,
enum pipe_format format,
uint64_t clear_value)
{
uint i, j;
 
switch (util_format_get_blocksize(format)) {
case 1:
memset(tile->data.any, (int) clear_value, TILE_SIZE * TILE_SIZE);
break;
case 2:
if (clear_value == 0) {
memset(tile->data.any, 0, 2 * TILE_SIZE * TILE_SIZE);
}
else {
for (i = 0; i < TILE_SIZE; i++) {
for (j = 0; j < TILE_SIZE; j++) {
tile->data.depth16[i][j] = (ushort) clear_value;
}
}
}
break;
case 4:
if (clear_value == 0) {
memset(tile->data.any, 0, 4 * TILE_SIZE * TILE_SIZE);
}
else {
for (i = 0; i < TILE_SIZE; i++) {
for (j = 0; j < TILE_SIZE; j++) {
tile->data.depth32[i][j] = (uint) clear_value;
}
}
}
break;
case 8:
if (clear_value == 0) {
memset(tile->data.any, 0, 8 * TILE_SIZE * TILE_SIZE);
}
else {
for (i = 0; i < TILE_SIZE; i++) {
for (j = 0; j < TILE_SIZE; j++) {
tile->data.depth64[i][j] = clear_value;
}
}
}
break;
default:
assert(0);
}
}
 
 
/**
* Actually clear the tiles which were flagged as being in a clear state.
*/
static void
sp_tile_cache_flush_clear(struct softpipe_tile_cache *tc)
{
struct pipe_transfer *pt = tc->transfer;
const uint w = tc->transfer->box.width;
const uint h = tc->transfer->box.height;
uint x, y;
uint numCleared = 0;
 
assert(pt->resource);
if (!tc->tile)
tc->tile = sp_alloc_tile(tc);
 
/* clear the scratch tile to the clear value */
if (tc->depth_stencil) {
clear_tile(tc->tile, pt->resource->format, tc->clear_val);
} else {
clear_tile_rgba(tc->tile, pt->resource->format, &tc->clear_color);
}
 
/* push the tile to all positions marked as clear */
for (y = 0; y < h; y += TILE_SIZE) {
for (x = 0; x < w; x += TILE_SIZE) {
union tile_address addr = tile_address(x, y);
 
if (is_clear_flag_set(tc->clear_flags, addr)) {
/* write the scratch tile to the surface */
if (tc->depth_stencil) {
pipe_put_tile_raw(pt, tc->transfer_map,
x, y, TILE_SIZE, TILE_SIZE,
tc->tile->data.any, 0/*STRIDE*/);
}
else {
if (util_format_is_pure_uint(tc->surface->format)) {
pipe_put_tile_ui_format(pt, tc->transfer_map,
x, y, TILE_SIZE, TILE_SIZE,
pt->resource->format,
(unsigned *) tc->tile->data.colorui128);
} else if (util_format_is_pure_sint(tc->surface->format)) {
pipe_put_tile_i_format(pt, tc->transfer_map,
x, y, TILE_SIZE, TILE_SIZE,
pt->resource->format,
(int *) tc->tile->data.colori128);
} else {
pipe_put_tile_rgba(pt, tc->transfer_map,
x, y, TILE_SIZE, TILE_SIZE,
(float *) tc->tile->data.color);
}
}
numCleared++;
}
}
}
 
/* reset all clear flags to zero */
memset(tc->clear_flags, 0, sizeof(tc->clear_flags));
 
#if 0
debug_printf("num cleared: %u\n", numCleared);
#endif
}
 
static void
sp_flush_tile(struct softpipe_tile_cache* tc, unsigned pos)
{
if (!tc->tile_addrs[pos].bits.invalid) {
if (tc->depth_stencil) {
pipe_put_tile_raw(tc->transfer, tc->transfer_map,
tc->tile_addrs[pos].bits.x * TILE_SIZE,
tc->tile_addrs[pos].bits.y * TILE_SIZE,
TILE_SIZE, TILE_SIZE,
tc->entries[pos]->data.depth32, 0/*STRIDE*/);
}
else {
if (util_format_is_pure_uint(tc->surface->format)) {
pipe_put_tile_ui_format(tc->transfer, tc->transfer_map,
tc->tile_addrs[pos].bits.x * TILE_SIZE,
tc->tile_addrs[pos].bits.y * TILE_SIZE,
TILE_SIZE, TILE_SIZE,
tc->surface->format,
(unsigned *) tc->entries[pos]->data.colorui128);
} else if (util_format_is_pure_sint(tc->surface->format)) {
pipe_put_tile_i_format(tc->transfer, tc->transfer_map,
tc->tile_addrs[pos].bits.x * TILE_SIZE,
tc->tile_addrs[pos].bits.y * TILE_SIZE,
TILE_SIZE, TILE_SIZE,
tc->surface->format,
(int *) tc->entries[pos]->data.colori128);
} else {
pipe_put_tile_rgba_format(tc->transfer, tc->transfer_map,
tc->tile_addrs[pos].bits.x * TILE_SIZE,
tc->tile_addrs[pos].bits.y * TILE_SIZE,
TILE_SIZE, TILE_SIZE,
tc->surface->format,
(float *) tc->entries[pos]->data.color);
}
}
tc->tile_addrs[pos].bits.invalid = 1; /* mark as empty */
}
}
 
/**
* Flush the tile cache: write all dirty tiles back to the transfer.
* any tiles "flagged" as cleared will be "really" cleared.
*/
void
sp_flush_tile_cache(struct softpipe_tile_cache *tc)
{
struct pipe_transfer *pt = tc->transfer;
int inuse = 0, pos;
 
if (pt) {
/* caching a drawing transfer */
for (pos = 0; pos < Elements(tc->entries); pos++) {
struct softpipe_cached_tile *tile = tc->entries[pos];
if (!tile)
{
assert(tc->tile_addrs[pos].bits.invalid);
continue;
}
 
sp_flush_tile(tc, pos);
++inuse;
}
 
sp_tile_cache_flush_clear(tc);
 
 
tc->last_tile_addr.bits.invalid = 1;
}
 
#if 0
debug_printf("flushed tiles in use: %d\n", inuse);
#endif
}
 
static struct softpipe_cached_tile *
sp_alloc_tile(struct softpipe_tile_cache *tc)
{
struct softpipe_cached_tile * tile = MALLOC_STRUCT(softpipe_cached_tile);
if (!tile)
{
/* in this case, steal an existing tile */
if (!tc->tile)
{
unsigned pos;
for (pos = 0; pos < Elements(tc->entries); ++pos) {
if (!tc->entries[pos])
continue;
 
sp_flush_tile(tc, pos);
tc->tile = tc->entries[pos];
tc->entries[pos] = NULL;
break;
}
 
/* this should never happen */
if (!tc->tile)
abort();
}
 
tile = tc->tile;
tc->tile = NULL;
 
tc->last_tile_addr.bits.invalid = 1;
}
return tile;
}
 
/**
* Get a tile from the cache.
* \param x, y position of tile, in pixels
*/
struct softpipe_cached_tile *
sp_find_cached_tile(struct softpipe_tile_cache *tc,
union tile_address addr )
{
struct pipe_transfer *pt = tc->transfer;
/* cache pos/entry: */
const int pos = CACHE_POS(addr.bits.x,
addr.bits.y);
struct softpipe_cached_tile *tile = tc->entries[pos];
 
if (!tile) {
tile = sp_alloc_tile(tc);
tc->entries[pos] = tile;
}
 
if (addr.value != tc->tile_addrs[pos].value) {
 
assert(pt->resource);
if (tc->tile_addrs[pos].bits.invalid == 0) {
/* put dirty tile back in framebuffer */
if (tc->depth_stencil) {
pipe_put_tile_raw(pt, tc->transfer_map,
tc->tile_addrs[pos].bits.x * TILE_SIZE,
tc->tile_addrs[pos].bits.y * TILE_SIZE,
TILE_SIZE, TILE_SIZE,
tile->data.depth32, 0/*STRIDE*/);
}
else {
if (util_format_is_pure_uint(tc->surface->format)) {
pipe_put_tile_ui_format(pt, tc->transfer_map,
tc->tile_addrs[pos].bits.x * TILE_SIZE,
tc->tile_addrs[pos].bits.y * TILE_SIZE,
TILE_SIZE, TILE_SIZE,
tc->surface->format,
(unsigned *) tile->data.colorui128);
} else if (util_format_is_pure_sint(tc->surface->format)) {
pipe_put_tile_i_format(pt, tc->transfer_map,
tc->tile_addrs[pos].bits.x * TILE_SIZE,
tc->tile_addrs[pos].bits.y * TILE_SIZE,
TILE_SIZE, TILE_SIZE,
tc->surface->format,
(int *) tile->data.colori128);
} else {
pipe_put_tile_rgba_format(pt, tc->transfer_map,
tc->tile_addrs[pos].bits.x * TILE_SIZE,
tc->tile_addrs[pos].bits.y * TILE_SIZE,
TILE_SIZE, TILE_SIZE,
tc->surface->format,
(float *) tile->data.color);
}
}
}
 
tc->tile_addrs[pos] = addr;
 
if (is_clear_flag_set(tc->clear_flags, addr)) {
/* don't get tile from framebuffer, just clear it */
if (tc->depth_stencil) {
clear_tile(tile, pt->resource->format, tc->clear_val);
}
else {
clear_tile_rgba(tile, pt->resource->format, &tc->clear_color);
}
clear_clear_flag(tc->clear_flags, addr);
}
else {
/* get new tile data from transfer */
if (tc->depth_stencil) {
pipe_get_tile_raw(pt, tc->transfer_map,
tc->tile_addrs[pos].bits.x * TILE_SIZE,
tc->tile_addrs[pos].bits.y * TILE_SIZE,
TILE_SIZE, TILE_SIZE,
tile->data.depth32, 0/*STRIDE*/);
}
else {
if (util_format_is_pure_uint(tc->surface->format)) {
pipe_get_tile_ui_format(pt, tc->transfer_map,
tc->tile_addrs[pos].bits.x * TILE_SIZE,
tc->tile_addrs[pos].bits.y * TILE_SIZE,
TILE_SIZE, TILE_SIZE,
tc->surface->format,
(unsigned *) tile->data.colorui128);
} else if (util_format_is_pure_sint(tc->surface->format)) {
pipe_get_tile_i_format(pt, tc->transfer_map,
tc->tile_addrs[pos].bits.x * TILE_SIZE,
tc->tile_addrs[pos].bits.y * TILE_SIZE,
TILE_SIZE, TILE_SIZE,
tc->surface->format,
(int *) tile->data.colori128);
} else {
pipe_get_tile_rgba_format(pt, tc->transfer_map,
tc->tile_addrs[pos].bits.x * TILE_SIZE,
tc->tile_addrs[pos].bits.y * TILE_SIZE,
TILE_SIZE, TILE_SIZE,
tc->surface->format,
(float *) tile->data.color);
}
}
}
}
 
tc->last_tile = tile;
tc->last_tile_addr = addr;
return tile;
}
 
 
 
 
 
/**
* When a whole surface is being cleared to a value we can avoid
* fetching tiles above.
* Save the color and set a 'clearflag' for each tile of the screen.
*/
void
sp_tile_cache_clear(struct softpipe_tile_cache *tc,
const union pipe_color_union *color,
uint64_t clearValue)
{
uint pos;
 
tc->clear_color = *color;
 
tc->clear_val = clearValue;
 
/* set flags to indicate all the tiles are cleared */
memset(tc->clear_flags, 255, sizeof(tc->clear_flags));
 
for (pos = 0; pos < Elements(tc->tile_addrs); pos++) {
tc->tile_addrs[pos].bits.invalid = 1;
}
tc->last_tile_addr.bits.invalid = 1;
}
/drivers/video/Gallium/drivers/softpipe/sp_tile_cache.h
0,0 → 1,159
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
#ifndef SP_TILE_CACHE_H
#define SP_TILE_CACHE_H
 
 
#include "pipe/p_compiler.h"
#include "sp_texture.h"
 
 
struct softpipe_tile_cache;
 
 
/**
* Cache tile size (width and height). This needs to be a power of two.
*/
#define TILE_SIZE_LOG2 6
#define TILE_SIZE (1 << TILE_SIZE_LOG2)
 
 
#define TILE_ADDR_BITS (SP_MAX_TEXTURE_2D_LEVELS - 1 - TILE_SIZE_LOG2)
 
 
/**
* Surface tile address as a union for fast compares.
*/
union tile_address {
struct {
unsigned x:TILE_ADDR_BITS; /* 16K / TILE_SIZE */
unsigned y:TILE_ADDR_BITS; /* 16K / TILE_SIZE */
unsigned invalid:1;
unsigned pad:15;
} bits;
unsigned value;
};
 
 
struct softpipe_cached_tile
{
union {
float color[TILE_SIZE][TILE_SIZE][4];
uint color32[TILE_SIZE][TILE_SIZE];
uint depth32[TILE_SIZE][TILE_SIZE];
ushort depth16[TILE_SIZE][TILE_SIZE];
ubyte stencil8[TILE_SIZE][TILE_SIZE];
uint colorui128[TILE_SIZE][TILE_SIZE][4];
int colori128[TILE_SIZE][TILE_SIZE][4];
uint64_t depth64[TILE_SIZE][TILE_SIZE];
ubyte any[1];
} data;
};
 
#define NUM_ENTRIES 50
 
 
struct softpipe_tile_cache
{
struct pipe_context *pipe;
struct pipe_surface *surface; /**< the surface we're caching */
struct pipe_transfer *transfer;
void *transfer_map;
 
union tile_address tile_addrs[NUM_ENTRIES];
struct softpipe_cached_tile *entries[NUM_ENTRIES];
uint clear_flags[(MAX_WIDTH / TILE_SIZE) * (MAX_HEIGHT / TILE_SIZE) / 32];
union pipe_color_union clear_color; /**< for color bufs */
uint64_t clear_val; /**< for z+stencil */
boolean depth_stencil; /**< Is the surface a depth/stencil format? */
 
struct softpipe_cached_tile *tile; /**< scratch tile for clears */
 
union tile_address last_tile_addr;
struct softpipe_cached_tile *last_tile; /**< most recently retrieved tile */
};
 
 
extern struct softpipe_tile_cache *
sp_create_tile_cache( struct pipe_context *pipe );
 
extern void
sp_destroy_tile_cache(struct softpipe_tile_cache *tc);
 
extern void
sp_tile_cache_set_surface(struct softpipe_tile_cache *tc,
struct pipe_surface *sps);
 
extern struct pipe_surface *
sp_tile_cache_get_surface(struct softpipe_tile_cache *tc);
 
extern void
sp_flush_tile_cache(struct softpipe_tile_cache *tc);
 
extern void
sp_tile_cache_clear(struct softpipe_tile_cache *tc,
const union pipe_color_union *color,
uint64_t clearValue);
 
extern struct softpipe_cached_tile *
sp_find_cached_tile(struct softpipe_tile_cache *tc,
union tile_address addr );
 
 
static INLINE union tile_address
tile_address( unsigned x,
unsigned y )
{
union tile_address addr;
 
addr.value = 0;
addr.bits.x = x / TILE_SIZE;
addr.bits.y = y / TILE_SIZE;
return addr;
}
 
/* Quickly retrieve tile if it matches last lookup.
*/
static INLINE struct softpipe_cached_tile *
sp_get_cached_tile(struct softpipe_tile_cache *tc,
int x, int y )
{
union tile_address addr = tile_address( x, y );
 
if (tc->last_tile_addr.value == addr.value)
return tc->last_tile;
 
return sp_find_cached_tile( tc, addr );
}
 
 
 
 
#endif /* SP_TILE_CACHE_H */
 
/drivers/video/Gallium/include/c99_compat.h
0,0 → 1,145
/**************************************************************************
*
* Copyright 2007-2013 VMware, Inc.
* 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 VMWARE 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.
*
**************************************************************************/
 
#ifndef _C99_COMPAT_H_
#define _C99_COMPAT_H_
 
 
/*
* MSVC hacks.
*/
#if defined(_MSC_VER)
/*
* Visual Studio 2012 will complain if we define the `inline` keyword, but
* actually it only supports the keyword on C++.
*
* To avoid this the _ALLOW_KEYWORD_MACROS must be set.
*/
# if (_MSC_VER >= 1700) && !defined(_ALLOW_KEYWORD_MACROS)
# define _ALLOW_KEYWORD_MACROS
# endif
 
/*
* XXX: MSVC has a `__restrict` keyword, but it also has a
* `__declspec(restrict)` modifier, so it is impossible to define a
* `restrict` macro without interfering with the latter. Furthermore the
* MSVC standard library uses __declspec(restrict) under the _CRTRESTRICT
* macro. For now resolve this issue by redefining _CRTRESTRICT, but going
* forward we should probably should stop using restrict, especially
* considering that our code does not obbey strict aliasing rules any way.
*/
# include <crtdefs.h>
# undef _CRTRESTRICT
# define _CRTRESTRICT
#endif
 
 
/*
* C99 inline keyword
*/
#ifndef inline
# ifdef __cplusplus
/* C++ supports inline keyword */
# elif defined(__GNUC__)
# define inline __inline__
# elif defined(_MSC_VER)
# define inline __inline
# elif defined(__ICL)
# define inline __inline
# elif defined(__INTEL_COMPILER)
/* Intel compiler supports inline keyword */
# elif defined(__WATCOMC__) && (__WATCOMC__ >= 1100)
# define inline __inline
# elif defined(__SUNPRO_C) && defined(__C99FEATURES__)
/* C99 supports inline keyword */
# elif (__STDC_VERSION__ >= 199901L)
/* C99 supports inline keyword */
# else
# define inline
# endif
#endif
 
 
/*
* C99 restrict keyword
*
* See also:
* - http://cellperformance.beyond3d.com/articles/2006/05/demystifying-the-restrict-keyword.html
*/
#ifndef restrict
# if (__STDC_VERSION__ >= 199901L)
/* C99 */
# elif defined(__SUNPRO_C) && defined(__C99FEATURES__)
/* C99 */
# elif defined(__GNUC__)
# define restrict __restrict__
# elif defined(_MSC_VER)
# define restrict __restrict
# else
# define restrict /* */
# endif
#endif
 
 
/*
* C99 __func__ macro
*/
#ifndef __func__
# if (__STDC_VERSION__ >= 199901L)
/* C99 */
# elif defined(__SUNPRO_C) && defined(__C99FEATURES__)
/* C99 */
# elif defined(__GNUC__)
# if __GNUC__ >= 2
# define __func__ __FUNCTION__
# else
# define __func__ "<unknown>"
# endif
# elif defined(_MSC_VER)
# if _MSC_VER >= 1300
# define __func__ __FUNCTION__
# else
# define __func__ "<unknown>"
# endif
# else
# define __func__ "<unknown>"
# endif
#endif
 
 
/* Simple test case for debugging */
#if 0
static inline const char *
test_c99_compat_h(const void * restrict a,
const void * restrict b)
{
return __func__;
}
#endif
 
 
#endif /* _C99_COMPAT_H_ */
/drivers/video/Gallium/include/pipe/p_compiler.h
0,0 → 1,267
/**************************************************************************
*
* Copyright 2007-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.
*
**************************************************************************/
 
#ifndef P_COMPILER_H
#define P_COMPILER_H
 
 
#include "c99_compat.h" /* inline, __func__, etc. */
 
#include "p_config.h"
 
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include <stdarg.h>
#include <limits.h>
 
 
#if defined(_WIN32) && !defined(__WIN32__)
#define __WIN32__
#endif
 
#if defined(_MSC_VER)
 
/* Avoid 'expression is always true' warning */
#pragma warning(disable: 4296)
 
#endif /* _MSC_VER */
 
 
/*
* Alternative stdint.h and stdbool.h headers are supplied in include/c99 for
* systems that lack it.
*/
#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS 1
#endif
#include <stdint.h>
#include <stdbool.h>
 
 
#ifdef __cplusplus
extern "C" {
#endif
 
 
#if !defined(__HAIKU__) && !defined(__USE_MISC)
#if !defined(PIPE_OS_ANDROID)
typedef unsigned int uint;
#endif
typedef unsigned short ushort;
#endif
typedef unsigned char ubyte;
 
typedef unsigned char boolean;
#ifndef TRUE
#define TRUE true
#endif
#ifndef FALSE
#define FALSE false
#endif
 
#ifndef va_copy
#ifdef __va_copy
#define va_copy(dest, src) __va_copy((dest), (src))
#else
#define va_copy(dest, src) (dest) = (src)
#endif
#endif
 
/* XXX: Use standard `inline` keyword instead */
#ifndef INLINE
# define INLINE inline
#endif
 
/* Forced function inlining */
#ifndef ALWAYS_INLINE
# ifdef __GNUC__
# define ALWAYS_INLINE inline __attribute__((always_inline))
# elif defined(_MSC_VER)
# define ALWAYS_INLINE __forceinline
# else
# define ALWAYS_INLINE INLINE
# endif
#endif
 
 
/* Function visibility */
#ifndef PUBLIC
# if defined(__GNUC__) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590))
# define PUBLIC __attribute__((visibility("default")))
# elif defined(_MSC_VER)
# define PUBLIC __declspec(dllexport)
# else
# define PUBLIC
# endif
#endif
 
 
/* XXX: Use standard `__func__` instead */
#ifndef __FUNCTION__
# define __FUNCTION__ __func__
#endif
 
 
/* This should match linux gcc cdecl semantics everywhere, so that we
* just codegen one calling convention on all platforms.
*/
#ifdef _MSC_VER
#define PIPE_CDECL __cdecl
#else
#define PIPE_CDECL
#endif
 
 
 
#if defined(__GNUC__)
#define PIPE_DEPRECATED __attribute__((__deprecated__))
#else
#define PIPE_DEPRECATED
#endif
 
 
 
/* Macros for data alignment. */
#if defined(__GNUC__) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)) || defined(__SUNPRO_CC)
 
/* See http://gcc.gnu.org/onlinedocs/gcc-4.4.2/gcc/Type-Attributes.html */
#define PIPE_ALIGN_TYPE(_alignment, _type) _type __attribute__((aligned(_alignment)))
 
/* See http://gcc.gnu.org/onlinedocs/gcc-4.4.2/gcc/Variable-Attributes.html */
#define PIPE_ALIGN_VAR(_alignment) __attribute__((aligned(_alignment)))
 
#if (__GNUC__ > 4 || (__GNUC__ == 4 &&__GNUC_MINOR__>1)) && !defined(PIPE_ARCH_X86_64)
#define PIPE_ALIGN_STACK __attribute__((force_align_arg_pointer))
#else
#define PIPE_ALIGN_STACK
#endif
 
#elif defined(_MSC_VER)
 
/* See http://msdn.microsoft.com/en-us/library/83ythb65.aspx */
#define PIPE_ALIGN_TYPE(_alignment, _type) __declspec(align(_alignment)) _type
#define PIPE_ALIGN_VAR(_alignment) __declspec(align(_alignment))
 
#define PIPE_ALIGN_STACK
 
#elif defined(SWIG)
 
#define PIPE_ALIGN_TYPE(_alignment, _type) _type
#define PIPE_ALIGN_VAR(_alignment)
 
#define PIPE_ALIGN_STACK
 
#else
 
#error "Unsupported compiler"
 
#endif
 
 
#if defined(__GNUC__)
 
#define PIPE_READ_WRITE_BARRIER() __asm__("":::"memory")
 
#elif defined(_MSC_VER)
 
void _ReadWriteBarrier(void);
#pragma intrinsic(_ReadWriteBarrier)
#define PIPE_READ_WRITE_BARRIER() _ReadWriteBarrier()
 
#elif defined(__SUNPRO_C) || defined(__SUNPRO_CC)
 
#define PIPE_READ_WRITE_BARRIER() __machine_rw_barrier()
 
#else
 
#warning "Unsupported compiler"
#define PIPE_READ_WRITE_BARRIER() /* */
 
#endif
 
 
/* You should use these macros to mark if blocks where the if condition
* is either likely to be true, or unlikely to be true.
*
* This will inform human readers of this fact, and will also inform
* the compiler, who will in turn inform the CPU.
*
* CPUs often start executing code inside the if or the else blocks
* without knowing whether the condition is true or not, and will have
* to throw the work away if they find out later they executed the
* wrong part of the if.
*
* If these macros are used, the CPU is more likely to correctly predict
* the right path, and will avoid speculatively executing the wrong branch,
* thus not throwing away work, resulting in better performance.
*
* In light of this, it is also a good idea to mark as "likely" a path
* which is not necessarily always more likely, but that will benefit much
* more from performance improvements since it is already much faster than
* the other path, or viceversa with "unlikely".
*
* Example usage:
* if(unlikely(do_we_need_a_software_fallback()))
* do_software_fallback();
* else
* render_with_gpu();
*
* The macros follow the Linux kernel convention, and more examples can
* be found there.
*
* Note that profile guided optimization can offer better results, but
* needs an appropriate coverage suite and does not inform human readers.
*/
#ifndef likely
# if defined(__GNUC__)
# define likely(x) __builtin_expect(!!(x), 1)
# define unlikely(x) __builtin_expect(!!(x), 0)
# else
# define likely(x) (x)
# define unlikely(x) (x)
# endif
#endif
 
 
/**
* Static (compile-time) assertion.
* Basically, use COND to dimension an array. If COND is false/zero the
* array size will be -1 and we'll get a compilation error.
*/
#define STATIC_ASSERT(COND) \
do { \
(void) sizeof(char [1 - 2*!(COND)]); \
} while (0)
 
 
#if defined(__cplusplus)
}
#endif
 
 
#endif /* P_COMPILER_H */
/drivers/video/Gallium/include/pipe/p_config.h
0,0 → 1,248
/**************************************************************************
*
* 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
* Gallium configuration defines.
*
* This header file sets several defines based on the compiler, processor
* architecture, and operating system being used. These defines should be used
* throughout the code to facilitate porting to new platforms. It is likely that
* this file is auto-generated by an autoconf-like tool at some point, as some
* things cannot be determined by pre-defined environment alone.
*
* See also:
* - http://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html
* - echo | gcc -dM -E - | sort
* - http://msdn.microsoft.com/en-us/library/b0084kay.aspx
*
* @author José Fonseca <jrfonseca@tungstengraphics.com>
*/
 
#ifndef P_CONFIG_H_
#define P_CONFIG_H_
 
#include <limits.h>
/*
* Compiler
*/
 
#if defined(__GNUC__)
#define PIPE_CC_GCC
#define PIPE_CC_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
#endif
 
/*
* Meaning of _MSC_VER value:
* - 1400: Visual C++ 2005
* - 1310: Visual C++ .NET 2003
* - 1300: Visual C++ .NET 2002
*
* __MSC__ seems to be an old macro -- it is not pre-defined on recent MSVC
* versions.
*/
#if defined(_MSC_VER) || defined(__MSC__)
#define PIPE_CC_MSVC
#endif
 
#if defined(__ICL)
#define PIPE_CC_ICL
#endif
 
#if defined(__SUNPRO_C) || defined(__SUNPRO_CC)
#define PIPE_CC_SUNPRO
#endif
 
 
/*
* Processor architecture
*/
 
#if defined(__i386__) /* gcc */ || defined(_M_IX86) /* msvc */ || defined(_X86_) || defined(__386__) || defined(i386) || defined(__i386) /* Sun cc */
#define PIPE_ARCH_X86
#endif
 
#if defined(__x86_64__) /* gcc */ || defined(_M_X64) /* msvc */ || defined(_M_AMD64) /* msvc */ || defined(__x86_64) /* Sun cc */
#define PIPE_ARCH_X86_64
#endif
 
#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
#if defined(PIPE_CC_GCC) && !defined(__SSE2__)
/* #warning SSE2 support requires -msse -msse2 compiler options */
#else
#define PIPE_ARCH_SSE
#endif
#if defined(PIPE_CC_GCC) && !defined(__SSSE3__)
/* #warning SSE3 support requires -msse3 compiler options */
#else
#define PIPE_ARCH_SSSE3
#endif
#endif
 
#if defined(__ppc__) || defined(__ppc64__) || defined(__PPC__)
#define PIPE_ARCH_PPC
#if defined(__ppc64__) || defined(__PPC64__)
#define PIPE_ARCH_PPC_64
#endif
#endif
 
#if defined(__s390x__)
#define PIPE_ARCH_S390
#endif
 
 
/*
* Endian detection.
*/
 
#ifdef __GLIBC__
#include <endian.h>
 
#if __BYTE_ORDER == __LITTLE_ENDIAN
# define PIPE_ARCH_LITTLE_ENDIAN
#elif __BYTE_ORDER == __BIG_ENDIAN
# define PIPE_ARCH_BIG_ENDIAN
#endif
 
#elif defined(__APPLE__)
#include <machine/endian.h>
 
#if __DARWIN_BYTE_ORDER == __DARWIN_LITTLE_ENDIAN
# define PIPE_ARCH_LITTLE_ENDIAN
#elif __DARWIN_BYTE_ORDER == __DARWIN_BIG_ENDIAN
# define PIPE_ARCH_BIG_ENDIAN
#endif
 
#elif defined(__sun)
#include <sys/isa_defs.h>
 
#if defined(_LITTLE_ENDIAN)
# define PIPE_ARCH_LITTLE_ENDIAN
#elif defined(_BIG_ENDIAN)
# define PIPE_ARCH_BIG_ENDIAN
#endif
 
#else
 
#if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
#define PIPE_ARCH_LITTLE_ENDIAN
#elif defined(PIPE_ARCH_PPC) || defined(PIPE_ARCH_PPC_64) || defined(PIPE_ARCH_S390)
#define PIPE_ARCH_BIG_ENDIAN
#endif
 
#endif
 
#if !defined(PIPE_ARCH_LITTLE_ENDIAN) && !defined(PIPE_ARCH_BIG_ENDIAN)
#error Unknown Endianness
#endif
 
/*
* Auto-detect the operating system family.
*
* See subsystem below for a more fine-grained distinction.
*/
 
#if defined(__linux__)
#define PIPE_OS_LINUX
#define PIPE_OS_UNIX
#endif
 
/*
* Android defines __linux__ so PIPE_OS_LINUX and PIPE_OS_UNIX will also be
* defined.
*/
#if defined(ANDROID)
#define PIPE_OS_ANDROID
#endif
 
#if defined(__FreeBSD__)
#define PIPE_OS_FREEBSD
#define PIPE_OS_BSD
#define PIPE_OS_UNIX
#endif
 
#if defined(__OpenBSD__)
#define PIPE_OS_OPENBSD
#define PIPE_OS_BSD
#define PIPE_OS_UNIX
#endif
 
#if defined(__NetBSD__)
#define PIPE_OS_NETBSD
#define PIPE_OS_BSD
#define PIPE_OS_UNIX
#endif
 
#if defined(__GNU__)
#define PIPE_OS_HURD
#define PIPE_OS_UNIX
#endif
 
#if defined(__sun)
#define PIPE_OS_SOLARIS
#define PIPE_OS_UNIX
#endif
 
#if defined(__APPLE__)
#define PIPE_OS_APPLE
#define PIPE_OS_UNIX
#endif
 
#if defined(_WIN32) || defined(WIN32)
#define PIPE_OS_WINDOWS
#endif
 
#if defined(__HAIKU__)
#define PIPE_OS_HAIKU
#define PIPE_OS_UNIX
#endif
 
#if defined(__CYGWIN__)
#define PIPE_OS_CYGWIN
#define PIPE_OS_UNIX
#endif
 
/*
* Try to auto-detect the subsystem.
*
* NOTE: There is no way to auto-detect most of these.
*/
 
#if defined(PIPE_OS_LINUX) || defined(PIPE_OS_BSD) || defined(PIPE_OS_SOLARIS)
#define PIPE_SUBSYSTEM_DRI
#endif /* PIPE_OS_LINUX || PIPE_OS_BSD || PIPE_OS_SOLARIS */
 
#if defined(PIPE_OS_WINDOWS)
#if defined(PIPE_SUBSYSTEM_WINDOWS_USER)
/* Windows User-space Library */
#else
#define PIPE_SUBSYSTEM_WINDOWS_USER
#endif
#endif /* PIPE_OS_WINDOWS */
 
 
#endif /* P_CONFIG_H_ */
/drivers/video/Gallium/include/pipe/p_context.h
0,0 → 1,551
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
#ifndef PIPE_CONTEXT_H
#define PIPE_CONTEXT_H
 
#include "p_compiler.h"
#include "p_format.h"
#include "p_video_enums.h"
#include "p_defines.h"
 
#ifdef __cplusplus
extern "C" {
#endif
 
 
struct pipe_blend_color;
struct pipe_blend_state;
struct pipe_blit_info;
struct pipe_box;
struct pipe_clip_state;
struct pipe_constant_buffer;
struct pipe_depth_stencil_alpha_state;
struct pipe_draw_info;
struct pipe_fence_handle;
struct pipe_framebuffer_state;
struct pipe_index_buffer;
struct pipe_query;
struct pipe_poly_stipple;
struct pipe_rasterizer_state;
struct pipe_resolve_info;
struct pipe_resource;
struct pipe_sampler_state;
struct pipe_sampler_view;
struct pipe_scissor_state;
struct pipe_shader_state;
struct pipe_stencil_ref;
struct pipe_stream_output_target;
struct pipe_surface;
struct pipe_transfer;
struct pipe_vertex_buffer;
struct pipe_vertex_element;
struct pipe_video_buffer;
struct pipe_video_decoder;
struct pipe_viewport_state;
struct pipe_compute_state;
union pipe_color_union;
union pipe_query_result;
 
/**
* Gallium rendering context. Basically:
* - state setting functions
* - VBO drawing functions
* - surface functions
*/
struct pipe_context {
struct pipe_screen *screen;
 
void *priv; /**< context private data (for DRI for example) */
void *draw; /**< private, for draw module (temporary?) */
 
void (*destroy)( struct pipe_context * );
 
/**
* VBO drawing
*/
/*@{*/
void (*draw_vbo)( struct pipe_context *pipe,
const struct pipe_draw_info *info );
/*@}*/
 
/**
* Predicate subsequent rendering on occlusion query result
* \param query the query predicate, or NULL if no predicate
* \param condition whether to skip on FALSE or TRUE query results
* \param mode one of PIPE_RENDER_COND_x
*/
void (*render_condition)( struct pipe_context *pipe,
struct pipe_query *query,
boolean condition,
uint mode );
 
/**
* Query objects
*/
/*@{*/
struct pipe_query *(*create_query)( struct pipe_context *pipe,
unsigned query_type );
 
void (*destroy_query)(struct pipe_context *pipe,
struct pipe_query *q);
 
void (*begin_query)(struct pipe_context *pipe, struct pipe_query *q);
void (*end_query)(struct pipe_context *pipe, struct pipe_query *q);
 
/**
* Get results of a query.
* \param wait if true, this query will block until the result is ready
* \return TRUE if results are ready, FALSE otherwise
*/
boolean (*get_query_result)(struct pipe_context *pipe,
struct pipe_query *q,
boolean wait,
union pipe_query_result *result);
/*@}*/
 
/**
* State functions (create/bind/destroy state objects)
*/
/*@{*/
void * (*create_blend_state)(struct pipe_context *,
const struct pipe_blend_state *);
void (*bind_blend_state)(struct pipe_context *, void *);
void (*delete_blend_state)(struct pipe_context *, void *);
 
void * (*create_sampler_state)(struct pipe_context *,
const struct pipe_sampler_state *);
void (*bind_fragment_sampler_states)(struct pipe_context *,
unsigned num_samplers,
void **samplers);
void (*bind_vertex_sampler_states)(struct pipe_context *,
unsigned num_samplers,
void **samplers);
void (*bind_geometry_sampler_states)(struct pipe_context *,
unsigned num_samplers,
void **samplers);
void (*bind_compute_sampler_states)(struct pipe_context *,
unsigned start_slot,
unsigned num_samplers,
void **samplers);
void (*delete_sampler_state)(struct pipe_context *, void *);
 
void * (*create_rasterizer_state)(struct pipe_context *,
const struct pipe_rasterizer_state *);
void (*bind_rasterizer_state)(struct pipe_context *, void *);
void (*delete_rasterizer_state)(struct pipe_context *, void *);
 
void * (*create_depth_stencil_alpha_state)(struct pipe_context *,
const struct pipe_depth_stencil_alpha_state *);
void (*bind_depth_stencil_alpha_state)(struct pipe_context *, void *);
void (*delete_depth_stencil_alpha_state)(struct pipe_context *, void *);
 
void * (*create_fs_state)(struct pipe_context *,
const struct pipe_shader_state *);
void (*bind_fs_state)(struct pipe_context *, void *);
void (*delete_fs_state)(struct pipe_context *, void *);
 
void * (*create_vs_state)(struct pipe_context *,
const struct pipe_shader_state *);
void (*bind_vs_state)(struct pipe_context *, void *);
void (*delete_vs_state)(struct pipe_context *, void *);
 
void * (*create_gs_state)(struct pipe_context *,
const struct pipe_shader_state *);
void (*bind_gs_state)(struct pipe_context *, void *);
void (*delete_gs_state)(struct pipe_context *, void *);
 
void * (*create_vertex_elements_state)(struct pipe_context *,
unsigned num_elements,
const struct pipe_vertex_element *);
void (*bind_vertex_elements_state)(struct pipe_context *, void *);
void (*delete_vertex_elements_state)(struct pipe_context *, void *);
 
/*@}*/
 
/**
* Parameter-like state (or properties)
*/
/*@{*/
void (*set_blend_color)( struct pipe_context *,
const struct pipe_blend_color * );
 
void (*set_stencil_ref)( struct pipe_context *,
const struct pipe_stencil_ref * );
 
void (*set_sample_mask)( struct pipe_context *,
unsigned sample_mask );
 
void (*set_clip_state)( struct pipe_context *,
const struct pipe_clip_state * );
 
void (*set_constant_buffer)( struct pipe_context *,
uint shader, uint index,
struct pipe_constant_buffer *buf );
 
void (*set_framebuffer_state)( struct pipe_context *,
const struct pipe_framebuffer_state * );
 
void (*set_polygon_stipple)( struct pipe_context *,
const struct pipe_poly_stipple * );
 
void (*set_scissor_states)( struct pipe_context *,
unsigned start_slot,
unsigned num_scissors,
const struct pipe_scissor_state * );
 
void (*set_viewport_states)( struct pipe_context *,
unsigned start_slot,
unsigned num_viewports,
const struct pipe_viewport_state *);
 
void (*set_fragment_sampler_views)(struct pipe_context *,
unsigned num_views,
struct pipe_sampler_view **);
 
void (*set_vertex_sampler_views)(struct pipe_context *,
unsigned num_views,
struct pipe_sampler_view **);
 
void (*set_geometry_sampler_views)(struct pipe_context *,
unsigned num_views,
struct pipe_sampler_view **);
 
void (*set_compute_sampler_views)(struct pipe_context *,
unsigned start_slot, unsigned num_views,
struct pipe_sampler_view **);
 
/**
* Bind an array of shader resources that will be used by the
* graphics pipeline. Any resources that were previously bound to
* the specified range will be unbound after this call.
*
* \param start first resource to bind.
* \param count number of consecutive resources to bind.
* \param resources array of pointers to the resources to bind, it
* should contain at least \a count elements
* unless it's NULL, in which case no new
* resources will be bound.
*/
void (*set_shader_resources)(struct pipe_context *,
unsigned start, unsigned count,
struct pipe_surface **resources);
 
void (*set_vertex_buffers)( struct pipe_context *,
unsigned start_slot,
unsigned num_buffers,
const struct pipe_vertex_buffer * );
 
void (*set_index_buffer)( struct pipe_context *pipe,
const struct pipe_index_buffer * );
 
/*@}*/
 
/**
* Stream output functions.
*/
/*@{*/
 
struct pipe_stream_output_target *(*create_stream_output_target)(
struct pipe_context *,
struct pipe_resource *,
unsigned buffer_offset,
unsigned buffer_size);
 
void (*stream_output_target_destroy)(struct pipe_context *,
struct pipe_stream_output_target *);
 
void (*set_stream_output_targets)(struct pipe_context *,
unsigned num_targets,
struct pipe_stream_output_target **targets,
unsigned append_bitmask);
 
/*@}*/
 
 
/**
* Resource functions for blit-like functionality
*
* If a driver supports multisampling, blit must implement color resolve.
*/
/*@{*/
 
/**
* Copy a block of pixels from one resource to another.
* The resource must be of the same format.
* Resources with nr_samples > 1 are not allowed.
*/
void (*resource_copy_region)(struct pipe_context *pipe,
struct pipe_resource *dst,
unsigned dst_level,
unsigned dstx, unsigned dsty, unsigned dstz,
struct pipe_resource *src,
unsigned src_level,
const struct pipe_box *src_box);
 
/* Optimal hardware path for blitting pixels.
* Scaling, format conversion, up- and downsampling (resolve) are allowed.
*/
void (*blit)(struct pipe_context *pipe,
const struct pipe_blit_info *info);
 
/*@}*/
 
/**
* Clear the specified set of currently bound buffers to specified values.
* The entire buffers are cleared (no scissor, no colormask, etc).
*
* \param buffers bitfield of PIPE_CLEAR_* values.
* \param color pointer to a union of fiu array for each of r, g, b, a.
* \param depth depth clear value in [0,1].
* \param stencil stencil clear value
*/
void (*clear)(struct pipe_context *pipe,
unsigned buffers,
const union pipe_color_union *color,
double depth,
unsigned stencil);
 
/**
* Clear a color rendertarget surface.
* \param color pointer to an union of fiu array for each of r, g, b, a.
*/
void (*clear_render_target)(struct pipe_context *pipe,
struct pipe_surface *dst,
const union pipe_color_union *color,
unsigned dstx, unsigned dsty,
unsigned width, unsigned height);
 
/**
* Clear a depth-stencil surface.
* \param clear_flags bitfield of PIPE_CLEAR_DEPTH/STENCIL values.
* \param depth depth clear value in [0,1].
* \param stencil stencil clear value
*/
void (*clear_depth_stencil)(struct pipe_context *pipe,
struct pipe_surface *dst,
unsigned clear_flags,
double depth,
unsigned stencil,
unsigned dstx, unsigned dsty,
unsigned width, unsigned height);
 
/** Flush draw commands
*
* \param flags bitfield of enum pipe_flush_flags values.
*/
void (*flush)(struct pipe_context *pipe,
struct pipe_fence_handle **fence,
unsigned flags);
 
/**
* Create a view on a texture to be used by a shader stage.
*/
struct pipe_sampler_view * (*create_sampler_view)(struct pipe_context *ctx,
struct pipe_resource *texture,
const struct pipe_sampler_view *templat);
 
void (*sampler_view_destroy)(struct pipe_context *ctx,
struct pipe_sampler_view *view);
 
 
/**
* Get a surface which is a "view" into a resource, used by
* render target / depth stencil stages.
*/
struct pipe_surface *(*create_surface)(struct pipe_context *ctx,
struct pipe_resource *resource,
const struct pipe_surface *templat);
 
void (*surface_destroy)(struct pipe_context *ctx,
struct pipe_surface *);
 
/**
* Map a resource.
*
* Transfers are (by default) context-private and allow uploads to be
* interleaved with rendering.
*
* out_transfer will contain the transfer object that must be passed
* to all the other transfer functions. It also contains useful
* information (like texture strides).
*/
void *(*transfer_map)(struct pipe_context *,
struct pipe_resource *resource,
unsigned level,
unsigned usage, /* a combination of PIPE_TRANSFER_x */
const struct pipe_box *,
struct pipe_transfer **out_transfer);
 
/* If transfer was created with WRITE|FLUSH_EXPLICIT, only the
* regions specified with this call are guaranteed to be written to
* the resource.
*/
void (*transfer_flush_region)( struct pipe_context *,
struct pipe_transfer *transfer,
const struct pipe_box *);
 
void (*transfer_unmap)(struct pipe_context *,
struct pipe_transfer *transfer);
 
/* One-shot transfer operation with data supplied in a user
* pointer. XXX: strides??
*/
void (*transfer_inline_write)( struct pipe_context *,
struct pipe_resource *,
unsigned level,
unsigned usage, /* a combination of PIPE_TRANSFER_x */
const struct pipe_box *,
const void *data,
unsigned stride,
unsigned layer_stride);
 
/**
* Flush any pending framebuffer writes and invalidate texture caches.
*/
void (*texture_barrier)(struct pipe_context *);
/**
* Creates a video decoder for a specific video codec/profile
*/
struct pipe_video_decoder *(*create_video_decoder)( struct pipe_context *context,
enum pipe_video_profile profile,
enum pipe_video_entrypoint entrypoint,
enum pipe_video_chroma_format chroma_format,
unsigned width, unsigned height, unsigned max_references,
bool expect_chunked_decode);
 
/**
* Creates a video buffer as decoding target
*/
struct pipe_video_buffer *(*create_video_buffer)( struct pipe_context *context,
const struct pipe_video_buffer *templat );
 
/**
* Compute kernel execution
*/
/*@{*/
/**
* Define the compute program and parameters to be used by
* pipe_context::launch_grid.
*/
void *(*create_compute_state)(struct pipe_context *context,
const struct pipe_compute_state *);
void (*bind_compute_state)(struct pipe_context *, void *);
void (*delete_compute_state)(struct pipe_context *, void *);
 
/**
* Bind an array of shader resources that will be used by the
* compute program. Any resources that were previously bound to
* the specified range will be unbound after this call.
*
* \param start first resource to bind.
* \param count number of consecutive resources to bind.
* \param resources array of pointers to the resources to bind, it
* should contain at least \a count elements
* unless it's NULL, in which case no new
* resources will be bound.
*/
void (*set_compute_resources)(struct pipe_context *,
unsigned start, unsigned count,
struct pipe_surface **resources);
 
/**
* Bind an array of buffers to be mapped into the address space of
* the GLOBAL resource. Any buffers that were previously bound
* between [first, first + count - 1] are unbound after this call.
*
* \param first first buffer to map.
* \param count number of consecutive buffers to map.
* \param resources array of pointers to the buffers to map, it
* should contain at least \a count elements
* unless it's NULL, in which case no new
* resources will be bound.
* \param handles array of pointers to the memory locations that
* will be filled with the respective base
* addresses each buffer will be mapped to. It
* should contain at least \a count elements,
* unless \a resources is NULL in which case \a
* handles should be NULL as well.
*
* Note that the driver isn't required to make any guarantees about
* the contents of the \a handles array being valid anytime except
* during the subsequent calls to pipe_context::launch_grid. This
* means that the only sensible location handles[i] may point to is
* somewhere within the INPUT buffer itself. This is so to
* accommodate implementations that lack virtual memory but
* nevertheless migrate buffers on the fly, leading to resource
* base addresses that change on each kernel invocation or are
* unknown to the pipe driver.
*/
void (*set_global_binding)(struct pipe_context *context,
unsigned first, unsigned count,
struct pipe_resource **resources,
uint32_t **handles);
 
/**
* Launch the compute kernel starting from instruction \a pc of the
* currently bound compute program.
*
* \a grid_layout and \a block_layout are arrays of size \a
* PIPE_COMPUTE_CAP_GRID_DIMENSION that determine the layout of the
* grid (in block units) and working block (in thread units) to be
* used, respectively.
*
* \a pc For drivers that use PIPE_SHADER_IR_LLVM as their prefered IR,
* this value will be the index of the kernel in the opencl.kernels
* metadata list.
*
* \a input will be used to initialize the INPUT resource, and it
* should point to a buffer of at least
* pipe_compute_state::req_input_mem bytes.
*/
void (*launch_grid)(struct pipe_context *context,
const uint *block_layout, const uint *grid_layout,
uint32_t pc, const void *input);
/*@}*/
 
/**
* Get sample position for an individual sample point.
*
* \param sample_count - total number of samples
* \param sample_index - sample to get the position values for
* \param out_value - return value of 2 floats for x and y position for
* requested sample.
*/
void (*get_sample_position)(struct pipe_context *context,
unsigned sample_count,
unsigned sample_index,
float *out_value);
};
 
 
#ifdef __cplusplus
}
#endif
 
#endif /* PIPE_CONTEXT_H */
/drivers/video/Gallium/include/pipe/p_defines.h
0,0 → 1,675
/**************************************************************************
*
* Copyright 2007 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.
*
**************************************************************************/
 
#ifndef PIPE_DEFINES_H
#define PIPE_DEFINES_H
 
#include "p_compiler.h"
 
#ifdef __cplusplus
extern "C" {
#endif
 
/**
* Gallium error codes.
*
* - A zero value always means success.
* - A negative value always means failure.
* - The meaning of a positive value is function dependent.
*/
enum pipe_error {
PIPE_OK = 0,
PIPE_ERROR = -1, /**< Generic error */
PIPE_ERROR_BAD_INPUT = -2,
PIPE_ERROR_OUT_OF_MEMORY = -3,
PIPE_ERROR_RETRY = -4
/* TODO */
};
 
 
#define PIPE_BLENDFACTOR_ONE 0x1
#define PIPE_BLENDFACTOR_SRC_COLOR 0x2
#define PIPE_BLENDFACTOR_SRC_ALPHA 0x3
#define PIPE_BLENDFACTOR_DST_ALPHA 0x4
#define PIPE_BLENDFACTOR_DST_COLOR 0x5
#define PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE 0x6
#define PIPE_BLENDFACTOR_CONST_COLOR 0x7
#define PIPE_BLENDFACTOR_CONST_ALPHA 0x8
#define PIPE_BLENDFACTOR_SRC1_COLOR 0x9
#define PIPE_BLENDFACTOR_SRC1_ALPHA 0x0A
#define PIPE_BLENDFACTOR_ZERO 0x11
#define PIPE_BLENDFACTOR_INV_SRC_COLOR 0x12
#define PIPE_BLENDFACTOR_INV_SRC_ALPHA 0x13
#define PIPE_BLENDFACTOR_INV_DST_ALPHA 0x14
#define PIPE_BLENDFACTOR_INV_DST_COLOR 0x15
#define PIPE_BLENDFACTOR_INV_CONST_COLOR 0x17
#define PIPE_BLENDFACTOR_INV_CONST_ALPHA 0x18
#define PIPE_BLENDFACTOR_INV_SRC1_COLOR 0x19
#define PIPE_BLENDFACTOR_INV_SRC1_ALPHA 0x1A
 
#define PIPE_BLEND_ADD 0
#define PIPE_BLEND_SUBTRACT 1
#define PIPE_BLEND_REVERSE_SUBTRACT 2
#define PIPE_BLEND_MIN 3
#define PIPE_BLEND_MAX 4
 
#define PIPE_LOGICOP_CLEAR 0
#define PIPE_LOGICOP_NOR 1
#define PIPE_LOGICOP_AND_INVERTED 2
#define PIPE_LOGICOP_COPY_INVERTED 3
#define PIPE_LOGICOP_AND_REVERSE 4
#define PIPE_LOGICOP_INVERT 5
#define PIPE_LOGICOP_XOR 6
#define PIPE_LOGICOP_NAND 7
#define PIPE_LOGICOP_AND 8
#define PIPE_LOGICOP_EQUIV 9
#define PIPE_LOGICOP_NOOP 10
#define PIPE_LOGICOP_OR_INVERTED 11
#define PIPE_LOGICOP_COPY 12
#define PIPE_LOGICOP_OR_REVERSE 13
#define PIPE_LOGICOP_OR 14
#define PIPE_LOGICOP_SET 15
 
#define PIPE_MASK_R 0x1
#define PIPE_MASK_G 0x2
#define PIPE_MASK_B 0x4
#define PIPE_MASK_A 0x8
#define PIPE_MASK_RGBA 0xf
#define PIPE_MASK_Z 0x10
#define PIPE_MASK_S 0x20
#define PIPE_MASK_ZS 0x30
#define PIPE_MASK_RGBAZS (PIPE_MASK_RGBA|PIPE_MASK_ZS)
 
 
/**
* Inequality functions. Used for depth test, stencil compare, alpha
* test, shadow compare, etc.
*/
#define PIPE_FUNC_NEVER 0
#define PIPE_FUNC_LESS 1
#define PIPE_FUNC_EQUAL 2
#define PIPE_FUNC_LEQUAL 3
#define PIPE_FUNC_GREATER 4
#define PIPE_FUNC_NOTEQUAL 5
#define PIPE_FUNC_GEQUAL 6
#define PIPE_FUNC_ALWAYS 7
 
/** Polygon fill mode */
#define PIPE_POLYGON_MODE_FILL 0
#define PIPE_POLYGON_MODE_LINE 1
#define PIPE_POLYGON_MODE_POINT 2
 
/** Polygon face specification, eg for culling */
#define PIPE_FACE_NONE 0
#define PIPE_FACE_FRONT 1
#define PIPE_FACE_BACK 2
#define PIPE_FACE_FRONT_AND_BACK (PIPE_FACE_FRONT | PIPE_FACE_BACK)
 
/** Stencil ops */
#define PIPE_STENCIL_OP_KEEP 0
#define PIPE_STENCIL_OP_ZERO 1
#define PIPE_STENCIL_OP_REPLACE 2
#define PIPE_STENCIL_OP_INCR 3
#define PIPE_STENCIL_OP_DECR 4
#define PIPE_STENCIL_OP_INCR_WRAP 5
#define PIPE_STENCIL_OP_DECR_WRAP 6
#define PIPE_STENCIL_OP_INVERT 7
 
/** Texture types.
* See the documentation for info on PIPE_TEXTURE_RECT vs PIPE_TEXTURE_2D */
enum pipe_texture_target {
PIPE_BUFFER = 0,
PIPE_TEXTURE_1D = 1,
PIPE_TEXTURE_2D = 2,
PIPE_TEXTURE_3D = 3,
PIPE_TEXTURE_CUBE = 4,
PIPE_TEXTURE_RECT = 5,
PIPE_TEXTURE_1D_ARRAY = 6,
PIPE_TEXTURE_2D_ARRAY = 7,
PIPE_TEXTURE_CUBE_ARRAY = 8,
PIPE_MAX_TEXTURE_TYPES
};
 
#define PIPE_TEX_FACE_POS_X 0
#define PIPE_TEX_FACE_NEG_X 1
#define PIPE_TEX_FACE_POS_Y 2
#define PIPE_TEX_FACE_NEG_Y 3
#define PIPE_TEX_FACE_POS_Z 4
#define PIPE_TEX_FACE_NEG_Z 5
#define PIPE_TEX_FACE_MAX 6
 
#define PIPE_TEX_WRAP_REPEAT 0
#define PIPE_TEX_WRAP_CLAMP 1
#define PIPE_TEX_WRAP_CLAMP_TO_EDGE 2
#define PIPE_TEX_WRAP_CLAMP_TO_BORDER 3
#define PIPE_TEX_WRAP_MIRROR_REPEAT 4
#define PIPE_TEX_WRAP_MIRROR_CLAMP 5
#define PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE 6
#define PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER 7
 
/* Between mipmaps, ie mipfilter
*/
#define PIPE_TEX_MIPFILTER_NEAREST 0
#define PIPE_TEX_MIPFILTER_LINEAR 1
#define PIPE_TEX_MIPFILTER_NONE 2
 
/* Within a mipmap, ie min/mag filter
*/
#define PIPE_TEX_FILTER_NEAREST 0
#define PIPE_TEX_FILTER_LINEAR 1
 
#define PIPE_TEX_COMPARE_NONE 0
#define PIPE_TEX_COMPARE_R_TO_TEXTURE 1
 
/**
* Clear buffer bits
*/
/** All color buffers currently bound */
#define PIPE_CLEAR_COLOR (1 << 0)
#define PIPE_CLEAR_DEPTH (1 << 1)
#define PIPE_CLEAR_STENCIL (1 << 2)
/** Depth/stencil combined */
#define PIPE_CLEAR_DEPTHSTENCIL (PIPE_CLEAR_DEPTH | PIPE_CLEAR_STENCIL)
 
/**
* Transfer object usage flags
*/
enum pipe_transfer_usage {
/**
* Resource contents read back (or accessed directly) at transfer
* create time.
*/
PIPE_TRANSFER_READ = (1 << 0),
/**
* Resource contents will be written back at transfer_unmap
* time (or modified as a result of being accessed directly).
*/
PIPE_TRANSFER_WRITE = (1 << 1),
 
/**
* Read/modify/write
*/
PIPE_TRANSFER_READ_WRITE = PIPE_TRANSFER_READ | PIPE_TRANSFER_WRITE,
 
/**
* The transfer should map the texture storage directly. The driver may
* return NULL if that isn't possible, and the state tracker needs to cope
* with that and use an alternative path without this flag.
*
* E.g. the state tracker could have a simpler path which maps textures and
* does read/modify/write cycles on them directly, and a more complicated
* path which uses minimal read and write transfers.
*/
PIPE_TRANSFER_MAP_DIRECTLY = (1 << 2),
 
/**
* Discards the memory within the mapped region.
*
* It should not be used with PIPE_TRANSFER_READ.
*
* See also:
* - OpenGL's ARB_map_buffer_range extension, MAP_INVALIDATE_RANGE_BIT flag.
*/
PIPE_TRANSFER_DISCARD_RANGE = (1 << 8),
 
/**
* Fail if the resource cannot be mapped immediately.
*
* See also:
* - Direct3D's D3DLOCK_DONOTWAIT flag.
* - Mesa3D's MESA_MAP_NOWAIT_BIT flag.
* - WDDM's D3DDDICB_LOCKFLAGS.DonotWait flag.
*/
PIPE_TRANSFER_DONTBLOCK = (1 << 9),
 
/**
* Do not attempt to synchronize pending operations on the resource when mapping.
*
* It should not be used with PIPE_TRANSFER_READ.
*
* See also:
* - OpenGL's ARB_map_buffer_range extension, MAP_UNSYNCHRONIZED_BIT flag.
* - Direct3D's D3DLOCK_NOOVERWRITE flag.
* - WDDM's D3DDDICB_LOCKFLAGS.IgnoreSync flag.
*/
PIPE_TRANSFER_UNSYNCHRONIZED = (1 << 10),
 
/**
* Written ranges will be notified later with
* pipe_context::transfer_flush_region.
*
* It should not be used with PIPE_TRANSFER_READ.
*
* See also:
* - pipe_context::transfer_flush_region
* - OpenGL's ARB_map_buffer_range extension, MAP_FLUSH_EXPLICIT_BIT flag.
*/
PIPE_TRANSFER_FLUSH_EXPLICIT = (1 << 11),
 
/**
* Discards all memory backing the resource.
*
* It should not be used with PIPE_TRANSFER_READ.
*
* This is equivalent to:
* - OpenGL's ARB_map_buffer_range extension, MAP_INVALIDATE_BUFFER_BIT
* - BufferData(NULL) on a GL buffer
* - Direct3D's D3DLOCK_DISCARD flag.
* - WDDM's D3DDDICB_LOCKFLAGS.Discard flag.
* - D3D10 DDI's D3D10_DDI_MAP_WRITE_DISCARD flag
* - D3D10's D3D10_MAP_WRITE_DISCARD flag.
*/
PIPE_TRANSFER_DISCARD_WHOLE_RESOURCE = (1 << 12)
 
};
 
/**
* Flags for the flush function.
*/
enum pipe_flush_flags {
PIPE_FLUSH_END_OF_FRAME = (1 << 0)
};
 
/*
* Resource binding flags -- state tracker must specify in advance all
* the ways a resource might be used.
*/
#define PIPE_BIND_DEPTH_STENCIL (1 << 0) /* create_surface */
#define PIPE_BIND_RENDER_TARGET (1 << 1) /* create_surface */
#define PIPE_BIND_BLENDABLE (1 << 2) /* create_surface */
#define PIPE_BIND_SAMPLER_VIEW (1 << 3) /* create_sampler_view */
#define PIPE_BIND_VERTEX_BUFFER (1 << 4) /* set_vertex_buffers */
#define PIPE_BIND_INDEX_BUFFER (1 << 5) /* draw_elements */
#define PIPE_BIND_CONSTANT_BUFFER (1 << 6) /* set_constant_buffer */
#define PIPE_BIND_DISPLAY_TARGET (1 << 8) /* flush_front_buffer */
#define PIPE_BIND_TRANSFER_WRITE (1 << 9) /* transfer_map */
#define PIPE_BIND_TRANSFER_READ (1 << 10) /* transfer_map */
#define PIPE_BIND_STREAM_OUTPUT (1 << 11) /* set_stream_output_buffers */
#define PIPE_BIND_CURSOR (1 << 16) /* mouse cursor */
#define PIPE_BIND_CUSTOM (1 << 17) /* state-tracker/winsys usages */
#define PIPE_BIND_GLOBAL (1 << 18) /* set_global_binding */
#define PIPE_BIND_SHADER_RESOURCE (1 << 19) /* set_shader_resources */
#define PIPE_BIND_COMPUTE_RESOURCE (1 << 20) /* set_compute_resources */
 
/* The first two flags above were previously part of the amorphous
* TEXTURE_USAGE, most of which are now descriptions of the ways a
* particular texture can be bound to the gallium pipeline. The two flags
* below do not fit within that and probably need to be migrated to some
* other place.
*
* It seems like scanout is used by the Xorg state tracker to ask for
* a texture suitable for actual scanout (hence the name), which
* implies extra layout constraints on some hardware. It may also
* have some special meaning regarding mouse cursor images.
*
* The shared flag is quite underspecified, but certainly isn't a
* binding flag - it seems more like a message to the winsys to create
* a shareable allocation.
*/
#define PIPE_BIND_SCANOUT (1 << 14) /* */
#define PIPE_BIND_SHARED (1 << 15) /* get_texture_handle ??? */
 
 
/* Flags for the driver about resource behaviour:
*/
#define PIPE_RESOURCE_FLAG_GEN_MIPS (1 << 0) /* Driver performs autogen mips */
#define PIPE_RESOURCE_FLAG_DRV_PRIV (1 << 16) /* driver/winsys private */
#define PIPE_RESOURCE_FLAG_ST_PRIV (1 << 24) /* state-tracker/winsys private */
 
/* Hint about the expected lifecycle of a resource.
*/
#define PIPE_USAGE_DEFAULT 0 /* many uploads, draws intermixed */
#define PIPE_USAGE_DYNAMIC 1 /* many uploads, draws intermixed */
#define PIPE_USAGE_STATIC 2 /* same as immutable?? */
#define PIPE_USAGE_IMMUTABLE 3 /* no change after first upload */
#define PIPE_USAGE_STREAM 4 /* upload, draw, upload, draw */
#define PIPE_USAGE_STAGING 5 /* supports data transfers from the GPU to the CPU */
 
 
/**
* Shaders
*/
#define PIPE_SHADER_VERTEX 0
#define PIPE_SHADER_FRAGMENT 1
#define PIPE_SHADER_GEOMETRY 2
#define PIPE_SHADER_COMPUTE 3
#define PIPE_SHADER_TYPES 4
 
 
/**
* Primitive types:
*/
#define PIPE_PRIM_POINTS 0
#define PIPE_PRIM_LINES 1
#define PIPE_PRIM_LINE_LOOP 2
#define PIPE_PRIM_LINE_STRIP 3
#define PIPE_PRIM_TRIANGLES 4
#define PIPE_PRIM_TRIANGLE_STRIP 5
#define PIPE_PRIM_TRIANGLE_FAN 6
#define PIPE_PRIM_QUADS 7
#define PIPE_PRIM_QUAD_STRIP 8
#define PIPE_PRIM_POLYGON 9
#define PIPE_PRIM_LINES_ADJACENCY 10
#define PIPE_PRIM_LINE_STRIP_ADJACENCY 11
#define PIPE_PRIM_TRIANGLES_ADJACENCY 12
#define PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY 13
#define PIPE_PRIM_MAX 14
 
 
/**
* Query object types
*/
#define PIPE_QUERY_OCCLUSION_COUNTER 0
#define PIPE_QUERY_OCCLUSION_PREDICATE 1
#define PIPE_QUERY_TIMESTAMP 2
#define PIPE_QUERY_TIMESTAMP_DISJOINT 3
#define PIPE_QUERY_TIME_ELAPSED 4
#define PIPE_QUERY_PRIMITIVES_GENERATED 5
#define PIPE_QUERY_PRIMITIVES_EMITTED 6
#define PIPE_QUERY_SO_STATISTICS 7
#define PIPE_QUERY_SO_OVERFLOW_PREDICATE 8
#define PIPE_QUERY_GPU_FINISHED 9
#define PIPE_QUERY_PIPELINE_STATISTICS 10
#define PIPE_QUERY_TYPES 11
 
/* start of driver queries,
* see pipe_screen::get_driver_query_info */
#define PIPE_QUERY_DRIVER_SPECIFIC 256
 
 
/**
* Conditional rendering modes
*/
#define PIPE_RENDER_COND_WAIT 0
#define PIPE_RENDER_COND_NO_WAIT 1
#define PIPE_RENDER_COND_BY_REGION_WAIT 2
#define PIPE_RENDER_COND_BY_REGION_NO_WAIT 3
 
 
/**
* Point sprite coord modes
*/
#define PIPE_SPRITE_COORD_UPPER_LEFT 0
#define PIPE_SPRITE_COORD_LOWER_LEFT 1
 
 
/**
* Texture swizzles
*/
#define PIPE_SWIZZLE_RED 0
#define PIPE_SWIZZLE_GREEN 1
#define PIPE_SWIZZLE_BLUE 2
#define PIPE_SWIZZLE_ALPHA 3
#define PIPE_SWIZZLE_ZERO 4
#define PIPE_SWIZZLE_ONE 5
 
 
#define PIPE_TIMEOUT_INFINITE 0xffffffffffffffffull
 
/**
* Implementation capabilities/limits which are queried through
* pipe_screen::get_param()
*/
enum pipe_cap {
PIPE_CAP_NPOT_TEXTURES = 1,
PIPE_CAP_TWO_SIDED_STENCIL = 2,
PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS = 4,
PIPE_CAP_ANISOTROPIC_FILTER = 5,
PIPE_CAP_POINT_SPRITE = 6,
PIPE_CAP_MAX_RENDER_TARGETS = 7,
PIPE_CAP_OCCLUSION_QUERY = 8,
PIPE_CAP_QUERY_TIME_ELAPSED = 9,
PIPE_CAP_TEXTURE_SHADOW_MAP = 10,
PIPE_CAP_TEXTURE_SWIZZLE = 11,
PIPE_CAP_MAX_TEXTURE_2D_LEVELS = 12,
PIPE_CAP_MAX_TEXTURE_3D_LEVELS = 13,
PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS = 14,
PIPE_CAP_TEXTURE_MIRROR_CLAMP = 25,
PIPE_CAP_BLEND_EQUATION_SEPARATE = 28,
PIPE_CAP_SM3 = 29, /*< Shader Model, supported */
PIPE_CAP_MAX_STREAM_OUTPUT_BUFFERS = 30,
PIPE_CAP_PRIMITIVE_RESTART = 31,
/** Maximum texture image units accessible from vertex and fragment shaders
* combined */
PIPE_CAP_MAX_COMBINED_SAMPLERS = 32,
/** blend enables and write masks per rendertarget */
PIPE_CAP_INDEP_BLEND_ENABLE = 33,
/** different blend funcs per rendertarget */
PIPE_CAP_INDEP_BLEND_FUNC = 34,
PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS = 36,
PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT = 37,
PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT = 38,
PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER = 39,
PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER = 40,
PIPE_CAP_DEPTH_CLIP_DISABLE = 41,
PIPE_CAP_SHADER_STENCIL_EXPORT = 42,
PIPE_CAP_TGSI_INSTANCEID = 43,
PIPE_CAP_VERTEX_ELEMENT_INSTANCE_DIVISOR = 44,
PIPE_CAP_FRAGMENT_COLOR_CLAMPED = 45,
PIPE_CAP_MIXED_COLORBUFFER_FORMATS = 46,
PIPE_CAP_SEAMLESS_CUBE_MAP = 47,
PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE = 48,
PIPE_CAP_SCALED_RESOLVE = 49,
PIPE_CAP_MIN_TEXEL_OFFSET = 50,
PIPE_CAP_MAX_TEXEL_OFFSET = 51,
PIPE_CAP_CONDITIONAL_RENDER = 52,
PIPE_CAP_TEXTURE_BARRIER = 53,
PIPE_CAP_MAX_STREAM_OUTPUT_SEPARATE_COMPONENTS = 55,
PIPE_CAP_MAX_STREAM_OUTPUT_INTERLEAVED_COMPONENTS = 56,
PIPE_CAP_STREAM_OUTPUT_PAUSE_RESUME = 57,
PIPE_CAP_TGSI_CAN_COMPACT_CONSTANTS = 59, /* temporary */
PIPE_CAP_VERTEX_COLOR_UNCLAMPED = 60,
PIPE_CAP_VERTEX_COLOR_CLAMPED = 61,
PIPE_CAP_GLSL_FEATURE_LEVEL = 62,
PIPE_CAP_QUADS_FOLLOW_PROVOKING_VERTEX_CONVENTION = 63,
PIPE_CAP_USER_VERTEX_BUFFERS = 64,
PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY = 65,
PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY = 66,
PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY = 67,
PIPE_CAP_COMPUTE = 68,
PIPE_CAP_USER_INDEX_BUFFERS = 69,
PIPE_CAP_USER_CONSTANT_BUFFERS = 70,
PIPE_CAP_CONSTANT_BUFFER_OFFSET_ALIGNMENT = 71,
PIPE_CAP_START_INSTANCE = 72,
PIPE_CAP_QUERY_TIMESTAMP = 73,
PIPE_CAP_TEXTURE_MULTISAMPLE = 74,
PIPE_CAP_MIN_MAP_BUFFER_ALIGNMENT = 75,
PIPE_CAP_CUBE_MAP_ARRAY = 76,
PIPE_CAP_TEXTURE_BUFFER_OBJECTS = 77,
PIPE_CAP_TEXTURE_BUFFER_OFFSET_ALIGNMENT = 78,
PIPE_CAP_TGSI_TEXCOORD = 79,
PIPE_CAP_PREFER_BLIT_BASED_TEXTURE_TRANSFER = 80,
PIPE_CAP_QUERY_PIPELINE_STATISTICS = 81,
PIPE_CAP_TEXTURE_BORDER_COLOR_QUIRK = 82,
PIPE_CAP_MAX_TEXTURE_BUFFER_SIZE = 83,
PIPE_CAP_MAX_VIEWPORTS = 84
};
 
#define PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_NV50 (1 << 0)
#define PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_R600 (1 << 1)
 
 
/**
* Implementation limits which are queried through
* pipe_screen::get_paramf()
*/
enum pipe_capf
{
PIPE_CAPF_MAX_LINE_WIDTH = 15,
PIPE_CAPF_MAX_LINE_WIDTH_AA = 16,
PIPE_CAPF_MAX_POINT_WIDTH = 17,
PIPE_CAPF_MAX_POINT_WIDTH_AA = 18,
PIPE_CAPF_MAX_TEXTURE_ANISOTROPY = 19,
PIPE_CAPF_MAX_TEXTURE_LOD_BIAS = 20,
PIPE_CAPF_GUARD_BAND_LEFT = 21,
PIPE_CAPF_GUARD_BAND_TOP = 22,
PIPE_CAPF_GUARD_BAND_RIGHT = 23,
PIPE_CAPF_GUARD_BAND_BOTTOM = 24
};
 
/* Shader caps not specific to any single stage */
enum pipe_shader_cap
{
PIPE_SHADER_CAP_MAX_INSTRUCTIONS = 0, /* if 0, it means the stage is unsupported */
PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS = 1,
PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS = 2,
PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS = 3,
PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH = 4,
PIPE_SHADER_CAP_MAX_INPUTS = 5,
PIPE_SHADER_CAP_MAX_CONSTS = 6,
PIPE_SHADER_CAP_MAX_CONST_BUFFERS = 7,
PIPE_SHADER_CAP_MAX_TEMPS = 8,
PIPE_SHADER_CAP_MAX_ADDRS = 9,
PIPE_SHADER_CAP_MAX_PREDS = 10,
/* boolean caps */
PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED = 11,
PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR = 12,
PIPE_SHADER_CAP_INDIRECT_OUTPUT_ADDR = 13,
PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR = 14,
PIPE_SHADER_CAP_INDIRECT_CONST_ADDR = 15,
PIPE_SHADER_CAP_SUBROUTINES = 16, /* BGNSUB, ENDSUB, CAL, RET */
PIPE_SHADER_CAP_INTEGERS = 17,
PIPE_SHADER_CAP_MAX_TEXTURE_SAMPLERS = 18,
PIPE_SHADER_CAP_PREFERRED_IR = 19,
PIPE_SHADER_CAP_TGSI_SQRT_SUPPORTED = 20
};
 
/**
* Shader intermediate representation.
*/
enum pipe_shader_ir
{
PIPE_SHADER_IR_TGSI,
PIPE_SHADER_IR_LLVM
};
 
/**
* Compute-specific implementation capability. They can be queried
* using pipe_screen::get_compute_param.
*/
enum pipe_compute_cap
{
PIPE_COMPUTE_CAP_IR_TARGET,
PIPE_COMPUTE_CAP_GRID_DIMENSION,
PIPE_COMPUTE_CAP_MAX_GRID_SIZE,
PIPE_COMPUTE_CAP_MAX_BLOCK_SIZE,
PIPE_COMPUTE_CAP_MAX_THREADS_PER_BLOCK,
PIPE_COMPUTE_CAP_MAX_GLOBAL_SIZE,
PIPE_COMPUTE_CAP_MAX_LOCAL_SIZE,
PIPE_COMPUTE_CAP_MAX_PRIVATE_SIZE,
PIPE_COMPUTE_CAP_MAX_INPUT_SIZE,
PIPE_COMPUTE_CAP_MAX_MEM_ALLOC_SIZE
};
 
/**
* Composite query types
*/
 
/**
* Query result for PIPE_QUERY_SO_STATISTICS.
*/
struct pipe_query_data_so_statistics
{
uint64_t num_primitives_written;
uint64_t primitives_storage_needed;
};
 
/**
* Query result for PIPE_QUERY_TIMESTAMP_DISJOINT.
*/
struct pipe_query_data_timestamp_disjoint
{
uint64_t frequency;
boolean disjoint;
};
 
/**
* Query result for PIPE_QUERY_PIPELINE_STATISTICS.
*/
struct pipe_query_data_pipeline_statistics
{
uint64_t ia_vertices; /**< Num vertices read by the vertex fetcher. */
uint64_t ia_primitives; /**< Num primitives read by the vertex fetcher. */
uint64_t vs_invocations; /**< Num vertex shader invocations. */
uint64_t gs_invocations; /**< Num geometry shader invocations. */
uint64_t gs_primitives; /**< Num primitives output by a geometry shader. */
uint64_t c_invocations; /**< Num primitives sent to the rasterizer. */
uint64_t c_primitives; /**< Num primitives that were rendered. */
uint64_t ps_invocations; /**< Num pixel shader invocations. */
uint64_t hs_invocations; /**< Num hull shader invocations. */
uint64_t ds_invocations; /**< Num domain shader invocations. */
uint64_t cs_invocations; /**< Num compute shader invocations. */
};
 
/**
* Query result (returned by pipe_context::get_query_result).
*/
union pipe_query_result
{
/* PIPE_QUERY_OCCLUSION_PREDICATE */
/* PIPE_QUERY_SO_OVERFLOW_PREDICATE */
/* PIPE_QUERY_GPU_FINISHED */
boolean b;
 
/* PIPE_QUERY_OCCLUSION_COUNTER */
/* PIPE_QUERY_TIMESTAMP */
/* PIPE_QUERY_TIME_ELAPSED */
/* PIPE_QUERY_PRIMITIVES_GENERATED */
/* PIPE_QUERY_PRIMITIVES_EMITTED */
uint64_t u64;
 
/* PIPE_QUERY_SO_STATISTICS */
struct pipe_query_data_so_statistics so_statistics;
 
/* PIPE_QUERY_TIMESTAMP_DISJOINT */
struct pipe_query_data_timestamp_disjoint timestamp_disjoint;
 
/* PIPE_QUERY_PIPELINE_STATISTICS */
struct pipe_query_data_pipeline_statistics pipeline_statistics;
};
 
union pipe_color_union
{
float f[4];
int i[4];
unsigned int ui[4];
};
 
struct pipe_driver_query_info
{
const char *name;
unsigned query_type; /* PIPE_QUERY_DRIVER_SPECIFIC + i */
uint64_t max_value; /* max value that can be returned */
boolean uses_byte_units; /* whether the result is in bytes */
};
 
#ifdef __cplusplus
}
#endif
 
#endif
/drivers/video/Gallium/include/pipe/p_format.h
0,0 → 1,379
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* Copyright (c) 2008 VMware, Inc.
* 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.
*
**************************************************************************/
 
#ifndef PIPE_FORMAT_H
#define PIPE_FORMAT_H
 
#ifdef __cplusplus
extern "C" {
#endif
 
#include "p_config.h"
 
enum pipe_type {
PIPE_TYPE_UNORM = 0,
PIPE_TYPE_SNORM,
PIPE_TYPE_SINT,
PIPE_TYPE_UINT,
PIPE_TYPE_FLOAT,
PIPE_TYPE_COUNT
};
 
/**
* Texture/surface image formats (preliminary)
*/
 
/* KW: Added lots of surface formats to support vertex element layout
* definitions, and eventually render-to-vertex-buffer.
*/
 
enum pipe_format {
PIPE_FORMAT_NONE = 0,
PIPE_FORMAT_B8G8R8A8_UNORM = 1,
PIPE_FORMAT_B8G8R8X8_UNORM = 2,
PIPE_FORMAT_A8R8G8B8_UNORM = 3,
PIPE_FORMAT_X8R8G8B8_UNORM = 4,
PIPE_FORMAT_B5G5R5A1_UNORM = 5,
PIPE_FORMAT_B4G4R4A4_UNORM = 6,
PIPE_FORMAT_B5G6R5_UNORM = 7,
PIPE_FORMAT_R10G10B10A2_UNORM = 8,
PIPE_FORMAT_L8_UNORM = 9, /**< ubyte luminance */
PIPE_FORMAT_A8_UNORM = 10, /**< ubyte alpha */
PIPE_FORMAT_I8_UNORM = 11, /**< ubyte intensity */
PIPE_FORMAT_L8A8_UNORM = 12, /**< ubyte alpha, luminance */
PIPE_FORMAT_L16_UNORM = 13, /**< ushort luminance */
PIPE_FORMAT_UYVY = 14,
PIPE_FORMAT_YUYV = 15,
PIPE_FORMAT_Z16_UNORM = 16,
PIPE_FORMAT_Z32_UNORM = 17,
PIPE_FORMAT_Z32_FLOAT = 18,
PIPE_FORMAT_Z24_UNORM_S8_UINT = 19,
PIPE_FORMAT_S8_UINT_Z24_UNORM = 20,
PIPE_FORMAT_Z24X8_UNORM = 21,
PIPE_FORMAT_X8Z24_UNORM = 22,
PIPE_FORMAT_S8_UINT = 23, /**< ubyte stencil */
PIPE_FORMAT_R64_FLOAT = 24,
PIPE_FORMAT_R64G64_FLOAT = 25,
PIPE_FORMAT_R64G64B64_FLOAT = 26,
PIPE_FORMAT_R64G64B64A64_FLOAT = 27,
PIPE_FORMAT_R32_FLOAT = 28,
PIPE_FORMAT_R32G32_FLOAT = 29,
PIPE_FORMAT_R32G32B32_FLOAT = 30,
PIPE_FORMAT_R32G32B32A32_FLOAT = 31,
PIPE_FORMAT_R32_UNORM = 32,
PIPE_FORMAT_R32G32_UNORM = 33,
PIPE_FORMAT_R32G32B32_UNORM = 34,
PIPE_FORMAT_R32G32B32A32_UNORM = 35,
PIPE_FORMAT_R32_USCALED = 36,
PIPE_FORMAT_R32G32_USCALED = 37,
PIPE_FORMAT_R32G32B32_USCALED = 38,
PIPE_FORMAT_R32G32B32A32_USCALED = 39,
PIPE_FORMAT_R32_SNORM = 40,
PIPE_FORMAT_R32G32_SNORM = 41,
PIPE_FORMAT_R32G32B32_SNORM = 42,
PIPE_FORMAT_R32G32B32A32_SNORM = 43,
PIPE_FORMAT_R32_SSCALED = 44,
PIPE_FORMAT_R32G32_SSCALED = 45,
PIPE_FORMAT_R32G32B32_SSCALED = 46,
PIPE_FORMAT_R32G32B32A32_SSCALED = 47,
PIPE_FORMAT_R16_UNORM = 48,
PIPE_FORMAT_R16G16_UNORM = 49,
PIPE_FORMAT_R16G16B16_UNORM = 50,
PIPE_FORMAT_R16G16B16A16_UNORM = 51,
PIPE_FORMAT_R16_USCALED = 52,
PIPE_FORMAT_R16G16_USCALED = 53,
PIPE_FORMAT_R16G16B16_USCALED = 54,
PIPE_FORMAT_R16G16B16A16_USCALED = 55,
PIPE_FORMAT_R16_SNORM = 56,
PIPE_FORMAT_R16G16_SNORM = 57,
PIPE_FORMAT_R16G16B16_SNORM = 58,
PIPE_FORMAT_R16G16B16A16_SNORM = 59,
PIPE_FORMAT_R16_SSCALED = 60,
PIPE_FORMAT_R16G16_SSCALED = 61,
PIPE_FORMAT_R16G16B16_SSCALED = 62,
PIPE_FORMAT_R16G16B16A16_SSCALED = 63,
PIPE_FORMAT_R8_UNORM = 64,
PIPE_FORMAT_R8G8_UNORM = 65,
PIPE_FORMAT_R8G8B8_UNORM = 66,
PIPE_FORMAT_R8G8B8A8_UNORM = 67,
PIPE_FORMAT_X8B8G8R8_UNORM = 68,
PIPE_FORMAT_R8_USCALED = 69,
PIPE_FORMAT_R8G8_USCALED = 70,
PIPE_FORMAT_R8G8B8_USCALED = 71,
PIPE_FORMAT_R8G8B8A8_USCALED = 72,
PIPE_FORMAT_R8_SNORM = 74,
PIPE_FORMAT_R8G8_SNORM = 75,
PIPE_FORMAT_R8G8B8_SNORM = 76,
PIPE_FORMAT_R8G8B8A8_SNORM = 77,
PIPE_FORMAT_R8_SSCALED = 82,
PIPE_FORMAT_R8G8_SSCALED = 83,
PIPE_FORMAT_R8G8B8_SSCALED = 84,
PIPE_FORMAT_R8G8B8A8_SSCALED = 85,
PIPE_FORMAT_R32_FIXED = 87,
PIPE_FORMAT_R32G32_FIXED = 88,
PIPE_FORMAT_R32G32B32_FIXED = 89,
PIPE_FORMAT_R32G32B32A32_FIXED = 90,
PIPE_FORMAT_R16_FLOAT = 91,
PIPE_FORMAT_R16G16_FLOAT = 92,
PIPE_FORMAT_R16G16B16_FLOAT = 93,
PIPE_FORMAT_R16G16B16A16_FLOAT = 94,
 
/* sRGB formats */
PIPE_FORMAT_L8_SRGB = 95,
PIPE_FORMAT_L8A8_SRGB = 96,
PIPE_FORMAT_R8G8B8_SRGB = 97,
PIPE_FORMAT_A8B8G8R8_SRGB = 98,
PIPE_FORMAT_X8B8G8R8_SRGB = 99,
PIPE_FORMAT_B8G8R8A8_SRGB = 100,
PIPE_FORMAT_B8G8R8X8_SRGB = 101,
PIPE_FORMAT_A8R8G8B8_SRGB = 102,
PIPE_FORMAT_X8R8G8B8_SRGB = 103,
PIPE_FORMAT_R8G8B8A8_SRGB = 104,
 
/* compressed formats */
PIPE_FORMAT_DXT1_RGB = 105,
PIPE_FORMAT_DXT1_RGBA = 106,
PIPE_FORMAT_DXT3_RGBA = 107,
PIPE_FORMAT_DXT5_RGBA = 108,
 
/* sRGB, compressed */
PIPE_FORMAT_DXT1_SRGB = 109,
PIPE_FORMAT_DXT1_SRGBA = 110,
PIPE_FORMAT_DXT3_SRGBA = 111,
PIPE_FORMAT_DXT5_SRGBA = 112,
 
/* rgtc compressed */
PIPE_FORMAT_RGTC1_UNORM = 113,
PIPE_FORMAT_RGTC1_SNORM = 114,
PIPE_FORMAT_RGTC2_UNORM = 115,
PIPE_FORMAT_RGTC2_SNORM = 116,
 
PIPE_FORMAT_R8G8_B8G8_UNORM = 117,
PIPE_FORMAT_G8R8_G8B8_UNORM = 118,
 
/* mixed formats */
PIPE_FORMAT_R8SG8SB8UX8U_NORM = 119,
PIPE_FORMAT_R5SG5SB6U_NORM = 120,
 
/* TODO: re-order these */
PIPE_FORMAT_A8B8G8R8_UNORM = 121,
PIPE_FORMAT_B5G5R5X1_UNORM = 122,
PIPE_FORMAT_R10G10B10A2_USCALED = 123,
PIPE_FORMAT_R11G11B10_FLOAT = 124,
PIPE_FORMAT_R9G9B9E5_FLOAT = 125,
PIPE_FORMAT_Z32_FLOAT_S8X24_UINT = 126,
PIPE_FORMAT_R1_UNORM = 127,
PIPE_FORMAT_R10G10B10X2_USCALED = 128,
PIPE_FORMAT_R10G10B10X2_SNORM = 129,
PIPE_FORMAT_L4A4_UNORM = 130,
PIPE_FORMAT_B10G10R10A2_UNORM = 131,
PIPE_FORMAT_R10SG10SB10SA2U_NORM = 132,
PIPE_FORMAT_R8G8Bx_SNORM = 133,
PIPE_FORMAT_R8G8B8X8_UNORM = 134,
PIPE_FORMAT_B4G4R4X4_UNORM = 135,
 
/* some stencil samplers formats */
PIPE_FORMAT_X24S8_UINT = 136,
PIPE_FORMAT_S8X24_UINT = 137,
PIPE_FORMAT_X32_S8X24_UINT = 138,
 
PIPE_FORMAT_B2G3R3_UNORM = 139,
PIPE_FORMAT_L16A16_UNORM = 140,
PIPE_FORMAT_A16_UNORM = 141,
PIPE_FORMAT_I16_UNORM = 142,
 
PIPE_FORMAT_LATC1_UNORM = 143,
PIPE_FORMAT_LATC1_SNORM = 144,
PIPE_FORMAT_LATC2_UNORM = 145,
PIPE_FORMAT_LATC2_SNORM = 146,
 
PIPE_FORMAT_A8_SNORM = 147,
PIPE_FORMAT_L8_SNORM = 148,
PIPE_FORMAT_L8A8_SNORM = 149,
PIPE_FORMAT_I8_SNORM = 150,
PIPE_FORMAT_A16_SNORM = 151,
PIPE_FORMAT_L16_SNORM = 152,
PIPE_FORMAT_L16A16_SNORM = 153,
PIPE_FORMAT_I16_SNORM = 154,
 
PIPE_FORMAT_A16_FLOAT = 155,
PIPE_FORMAT_L16_FLOAT = 156,
PIPE_FORMAT_L16A16_FLOAT = 157,
PIPE_FORMAT_I16_FLOAT = 158,
PIPE_FORMAT_A32_FLOAT = 159,
PIPE_FORMAT_L32_FLOAT = 160,
PIPE_FORMAT_L32A32_FLOAT = 161,
PIPE_FORMAT_I32_FLOAT = 162,
 
PIPE_FORMAT_YV12 = 163,
PIPE_FORMAT_YV16 = 164,
PIPE_FORMAT_IYUV = 165, /**< aka I420 */
PIPE_FORMAT_NV12 = 166,
PIPE_FORMAT_NV21 = 167,
 
PIPE_FORMAT_R4A4_UNORM = 168,
PIPE_FORMAT_A4R4_UNORM = 169,
PIPE_FORMAT_R8A8_UNORM = 170,
PIPE_FORMAT_A8R8_UNORM = 171,
 
PIPE_FORMAT_R10G10B10A2_SSCALED = 172,
PIPE_FORMAT_R10G10B10A2_SNORM = 173,
 
PIPE_FORMAT_B10G10R10A2_USCALED = 174,
PIPE_FORMAT_B10G10R10A2_SSCALED = 175,
PIPE_FORMAT_B10G10R10A2_SNORM = 176,
 
PIPE_FORMAT_R8_UINT = 177,
PIPE_FORMAT_R8G8_UINT = 178,
PIPE_FORMAT_R8G8B8_UINT = 179,
PIPE_FORMAT_R8G8B8A8_UINT = 180,
 
PIPE_FORMAT_R8_SINT = 181,
PIPE_FORMAT_R8G8_SINT = 182,
PIPE_FORMAT_R8G8B8_SINT = 183,
PIPE_FORMAT_R8G8B8A8_SINT = 184,
 
PIPE_FORMAT_R16_UINT = 185,
PIPE_FORMAT_R16G16_UINT = 186,
PIPE_FORMAT_R16G16B16_UINT = 187,
PIPE_FORMAT_R16G16B16A16_UINT = 188,
 
PIPE_FORMAT_R16_SINT = 189,
PIPE_FORMAT_R16G16_SINT = 190,
PIPE_FORMAT_R16G16B16_SINT = 191,
PIPE_FORMAT_R16G16B16A16_SINT = 192,
 
PIPE_FORMAT_R32_UINT = 193,
PIPE_FORMAT_R32G32_UINT = 194,
PIPE_FORMAT_R32G32B32_UINT = 195,
PIPE_FORMAT_R32G32B32A32_UINT = 196,
 
PIPE_FORMAT_R32_SINT = 197,
PIPE_FORMAT_R32G32_SINT = 198,
PIPE_FORMAT_R32G32B32_SINT = 199,
PIPE_FORMAT_R32G32B32A32_SINT = 200,
 
PIPE_FORMAT_A8_UINT = 201,
PIPE_FORMAT_I8_UINT = 202,
PIPE_FORMAT_L8_UINT = 203,
PIPE_FORMAT_L8A8_UINT = 204,
 
PIPE_FORMAT_A8_SINT = 205,
PIPE_FORMAT_I8_SINT = 206,
PIPE_FORMAT_L8_SINT = 207,
PIPE_FORMAT_L8A8_SINT = 208,
 
PIPE_FORMAT_A16_UINT = 209,
PIPE_FORMAT_I16_UINT = 210,
PIPE_FORMAT_L16_UINT = 211,
PIPE_FORMAT_L16A16_UINT = 212,
 
PIPE_FORMAT_A16_SINT = 213,
PIPE_FORMAT_I16_SINT = 214,
PIPE_FORMAT_L16_SINT = 215,
PIPE_FORMAT_L16A16_SINT = 216,
 
PIPE_FORMAT_A32_UINT = 217,
PIPE_FORMAT_I32_UINT = 218,
PIPE_FORMAT_L32_UINT = 219,
PIPE_FORMAT_L32A32_UINT = 220,
 
PIPE_FORMAT_A32_SINT = 221,
PIPE_FORMAT_I32_SINT = 222,
PIPE_FORMAT_L32_SINT = 223,
PIPE_FORMAT_L32A32_SINT = 224,
 
PIPE_FORMAT_B10G10R10A2_UINT = 225,
 
PIPE_FORMAT_ETC1_RGB8 = 226,
 
PIPE_FORMAT_R8G8_R8B8_UNORM = 227,
PIPE_FORMAT_G8R8_B8R8_UNORM = 228,
 
PIPE_FORMAT_R8G8B8X8_SNORM = 229,
PIPE_FORMAT_R8G8B8X8_SRGB = 230,
PIPE_FORMAT_R8G8B8X8_UINT = 231,
PIPE_FORMAT_R8G8B8X8_SINT = 232,
PIPE_FORMAT_B10G10R10X2_UNORM = 233,
PIPE_FORMAT_R16G16B16X16_UNORM = 234,
PIPE_FORMAT_R16G16B16X16_SNORM = 235,
PIPE_FORMAT_R16G16B16X16_FLOAT = 236,
PIPE_FORMAT_R16G16B16X16_UINT = 237,
PIPE_FORMAT_R16G16B16X16_SINT = 238,
PIPE_FORMAT_R32G32B32X32_FLOAT = 239,
PIPE_FORMAT_R32G32B32X32_UINT = 240,
PIPE_FORMAT_R32G32B32X32_SINT = 241,
 
PIPE_FORMAT_R8A8_SNORM = 242,
PIPE_FORMAT_R16A16_UNORM = 243,
PIPE_FORMAT_R16A16_SNORM = 244,
PIPE_FORMAT_R16A16_FLOAT = 245,
PIPE_FORMAT_R32A32_FLOAT = 246,
PIPE_FORMAT_R8A8_UINT = 247,
PIPE_FORMAT_R8A8_SINT = 248,
PIPE_FORMAT_R16A16_UINT = 249,
PIPE_FORMAT_R16A16_SINT = 250,
PIPE_FORMAT_R32A32_UINT = 251,
PIPE_FORMAT_R32A32_SINT = 252,
 
PIPE_FORMAT_COUNT
};
 
#if defined(PIPE_ARCH_LITTLE_ENDIAN)
#define PIPE_FORMAT_RGBA8888_UNORM PIPE_FORMAT_R8G8B8A8_UNORM
#define PIPE_FORMAT_RGBX8888_UNORM PIPE_FORMAT_R8G8B8X8_UNORM
#define PIPE_FORMAT_BGRA8888_UNORM PIPE_FORMAT_B8G8R8A8_UNORM
#define PIPE_FORMAT_BGRX8888_UNORM PIPE_FORMAT_B8G8R8X8_UNORM
#define PIPE_FORMAT_ARGB8888_UNORM PIPE_FORMAT_A8R8G8B8_UNORM
#define PIPE_FORMAT_XRGB8888_UNORM PIPE_FORMAT_X8R8G8B8_UNORM
#define PIPE_FORMAT_ABGR8888_UNORM PIPE_FORMAT_A8B8G8R8_UNORM
#define PIPE_FORMAT_XBGR8888_UNORM PIPE_FORMAT_X8B8G8R8_UNORM
#elif defined(PIPE_ARCH_BIG_ENDIAN)
#define PIPE_FORMAT_ABGR8888_UNORM PIPE_FORMAT_R8G8B8A8_UNORM
#define PIPE_FORMAT_XBGR8888_UNORM PIPE_FORMAT_R8G8B8X8_UNORM
#define PIPE_FORMAT_XRGB8888_UNORM PIPE_FORMAT_B8G8R8X8_UNORM
#define PIPE_FORMAT_ARGB8888_UNORM PIPE_FORMAT_B8G8R8A8_UNORM
#define PIPE_FORMAT_XRGB8888_UNORM PIPE_FORMAT_B8G8R8X8_UNORM
#define PIPE_FORMAT_BGRA8888_UNORM PIPE_FORMAT_A8R8G8B8_UNORM
#define PIPE_FORMAT_BGRX8888_UNORM PIPE_FORMAT_X8R8G8B8_UNORM
#define PIPE_FORMAT_RGBA8888_UNORM PIPE_FORMAT_A8B8G8R8_UNORM
#define PIPE_FORMAT_RGBX8888_UNORM PIPE_FORMAT_X8B8G8R8_UNORM
#endif
 
enum pipe_video_chroma_format
{
PIPE_VIDEO_CHROMA_FORMAT_420,
PIPE_VIDEO_CHROMA_FORMAT_422,
PIPE_VIDEO_CHROMA_FORMAT_444
};
 
#ifdef __cplusplus
}
#endif
 
#endif
/drivers/video/Gallium/include/pipe/p_screen.h
0,0 → 1,227
/**************************************************************************
*
* Copyright 2007 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
*
* Screen, Adapter or GPU
*
* These are driver functions/facilities that are context independent.
*/
 
 
#ifndef P_SCREEN_H
#define P_SCREEN_H
 
 
#include "pipe/p_compiler.h"
#include "pipe/p_format.h"
#include "pipe/p_defines.h"
#include "pipe/p_video_enums.h"
 
 
 
#ifdef __cplusplus
extern "C" {
#endif
 
 
/** Opaque types */
struct winsys_handle;
struct pipe_fence_handle;
struct pipe_resource;
struct pipe_surface;
struct pipe_transfer;
 
 
/**
* Gallium screen/adapter context. Basically everything
* hardware-specific that doesn't actually require a rendering
* context.
*/
struct pipe_screen {
void (*destroy)( struct pipe_screen * );
 
const char *(*get_name)( struct pipe_screen * );
 
const char *(*get_vendor)( struct pipe_screen * );
 
/**
* Query an integer-valued capability/parameter/limit
* \param param one of PIPE_CAP_x
*/
int (*get_param)( struct pipe_screen *, enum pipe_cap param );
 
/**
* Query a float-valued capability/parameter/limit
* \param param one of PIPE_CAP_x
*/
float (*get_paramf)( struct pipe_screen *, enum pipe_capf param );
 
/**
* Query a per-shader-stage integer-valued capability/parameter/limit
* \param param one of PIPE_CAP_x
*/
int (*get_shader_param)( struct pipe_screen *, unsigned shader, enum pipe_shader_cap param );
 
/**
* Query an integer-valued capability/parameter/limit for a codec/profile
* \param param one of PIPE_VIDEO_CAP_x
*/
int (*get_video_param)( struct pipe_screen *,
enum pipe_video_profile profile,
enum pipe_video_cap param );
 
/**
* Query a compute-specific capability/parameter/limit.
* \param param one of PIPE_COMPUTE_CAP_x
* \param ret pointer to a preallocated buffer that will be
* initialized to the parameter value, or NULL.
* \return size in bytes of the parameter value that would be
* returned.
*/
int (*get_compute_param)(struct pipe_screen *,
enum pipe_compute_cap param,
void *ret);
 
/**
* Query a timestamp in nanoseconds. The returned value should match
* PIPE_QUERY_TIMESTAMP. This function returns immediately and doesn't
* wait for rendering to complete (which cannot be achieved with queries).
*/
uint64_t (*get_timestamp)(struct pipe_screen *);
 
struct pipe_context * (*context_create)( struct pipe_screen *,
void *priv );
 
/**
* Check if the given pipe_format is supported as a texture or
* drawing surface.
* \param bindings bitmask of PIPE_BIND_*
*/
boolean (*is_format_supported)( struct pipe_screen *,
enum pipe_format format,
enum pipe_texture_target target,
unsigned sample_count,
unsigned bindings );
 
/**
* Check if the given pipe_format is supported as output for this codec/profile.
* \param profile profile to check, may also be PIPE_VIDEO_PROFILE_UNKNOWN
*/
boolean (*is_video_format_supported)( struct pipe_screen *,
enum pipe_format format,
enum pipe_video_profile profile );
 
/**
* Check if we can actually create the given resource (test the dimension,
* overall size, etc). Used to implement proxy textures.
* \return TRUE if size is OK, FALSE if too large.
*/
boolean (*can_create_resource)(struct pipe_screen *screen,
const struct pipe_resource *templat);
/**
* Create a new texture object, using the given template info.
*/
struct pipe_resource * (*resource_create)(struct pipe_screen *,
const struct pipe_resource *templat);
 
/**
* Create a texture from a winsys_handle. The handle is often created in
* another process by first creating a pipe texture and then calling
* resource_get_handle.
*/
struct pipe_resource * (*resource_from_handle)(struct pipe_screen *,
const struct pipe_resource *templat,
struct winsys_handle *handle);
 
/**
* Get a winsys_handle from a texture. Some platforms/winsys requires
* that the texture is created with a special usage flag like
* DISPLAYTARGET or PRIMARY.
*/
boolean (*resource_get_handle)(struct pipe_screen *,
struct pipe_resource *tex,
struct winsys_handle *handle);
 
 
void (*resource_destroy)(struct pipe_screen *,
struct pipe_resource *pt);
 
 
/**
* Do any special operations to ensure frontbuffer contents are
* displayed, eg copy fake frontbuffer.
* \param winsys_drawable_handle an opaque handle that the calling context
* gets out-of-band
*/
void (*flush_frontbuffer)( struct pipe_screen *screen,
struct pipe_resource *resource,
unsigned level, unsigned layer,
void *winsys_drawable_handle );
 
 
 
/** Set ptr = fence, with reference counting */
void (*fence_reference)( struct pipe_screen *screen,
struct pipe_fence_handle **ptr,
struct pipe_fence_handle *fence );
 
/**
* Checks whether the fence has been signalled.
*/
boolean (*fence_signalled)( struct pipe_screen *screen,
struct pipe_fence_handle *fence );
 
/**
* Wait for the fence to finish.
* \param timeout in nanoseconds (may be PIPE_TIMEOUT_INFINITE).
*/
boolean (*fence_finish)( struct pipe_screen *screen,
struct pipe_fence_handle *fence,
uint64_t timeout );
 
/**
* Returns a driver-specific query.
*
* If \p info is NULL, the number of available queries is returned.
* Otherwise, the driver query at the specified \p index is returned
* in \p info. The function returns non-zero on success.
*/
int (*get_driver_query_info)(struct pipe_screen *screen,
unsigned index,
struct pipe_driver_query_info *info);
 
};
 
 
#ifdef __cplusplus
}
#endif
 
#endif /* P_SCREEN_H */
/drivers/video/Gallium/include/pipe/p_shader_tokens.h
0,0 → 1,641
/**************************************************************************
*
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* Copyright 2009-2010 VMware, Inc.
* 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.
*
**************************************************************************/
 
#ifndef P_SHADER_TOKENS_H
#define P_SHADER_TOKENS_H
 
#ifdef __cplusplus
extern "C" {
#endif
 
 
struct tgsi_header
{
unsigned HeaderSize : 8;
unsigned BodySize : 24;
};
 
#define TGSI_PROCESSOR_FRAGMENT 0
#define TGSI_PROCESSOR_VERTEX 1
#define TGSI_PROCESSOR_GEOMETRY 2
#define TGSI_PROCESSOR_COMPUTE 3
 
struct tgsi_processor
{
unsigned Processor : 4; /* TGSI_PROCESSOR_ */
unsigned Padding : 28;
};
 
#define TGSI_TOKEN_TYPE_DECLARATION 0
#define TGSI_TOKEN_TYPE_IMMEDIATE 1
#define TGSI_TOKEN_TYPE_INSTRUCTION 2
#define TGSI_TOKEN_TYPE_PROPERTY 3
 
struct tgsi_token
{
unsigned Type : 4; /**< TGSI_TOKEN_TYPE_x */
unsigned NrTokens : 8; /**< UINT */
unsigned Padding : 20;
};
 
enum tgsi_file_type {
TGSI_FILE_NULL =0,
TGSI_FILE_CONSTANT =1,
TGSI_FILE_INPUT =2,
TGSI_FILE_OUTPUT =3,
TGSI_FILE_TEMPORARY =4,
TGSI_FILE_SAMPLER =5,
TGSI_FILE_ADDRESS =6,
TGSI_FILE_IMMEDIATE =7,
TGSI_FILE_PREDICATE =8,
TGSI_FILE_SYSTEM_VALUE =9,
TGSI_FILE_RESOURCE =10,
TGSI_FILE_SAMPLER_VIEW =11,
TGSI_FILE_COUNT /**< how many TGSI_FILE_ types */
};
 
 
#define TGSI_WRITEMASK_NONE 0x00
#define TGSI_WRITEMASK_X 0x01
#define TGSI_WRITEMASK_Y 0x02
#define TGSI_WRITEMASK_XY 0x03
#define TGSI_WRITEMASK_Z 0x04
#define TGSI_WRITEMASK_XZ 0x05
#define TGSI_WRITEMASK_YZ 0x06
#define TGSI_WRITEMASK_XYZ 0x07
#define TGSI_WRITEMASK_W 0x08
#define TGSI_WRITEMASK_XW 0x09
#define TGSI_WRITEMASK_YW 0x0A
#define TGSI_WRITEMASK_XYW 0x0B
#define TGSI_WRITEMASK_ZW 0x0C
#define TGSI_WRITEMASK_XZW 0x0D
#define TGSI_WRITEMASK_YZW 0x0E
#define TGSI_WRITEMASK_XYZW 0x0F
 
#define TGSI_INTERPOLATE_CONSTANT 0
#define TGSI_INTERPOLATE_LINEAR 1
#define TGSI_INTERPOLATE_PERSPECTIVE 2
#define TGSI_INTERPOLATE_COLOR 3 /* special color case for smooth/flat */
#define TGSI_INTERPOLATE_COUNT 4
 
#define TGSI_CYLINDRICAL_WRAP_X (1 << 0)
#define TGSI_CYLINDRICAL_WRAP_Y (1 << 1)
#define TGSI_CYLINDRICAL_WRAP_Z (1 << 2)
#define TGSI_CYLINDRICAL_WRAP_W (1 << 3)
 
struct tgsi_declaration
{
unsigned Type : 4; /**< TGSI_TOKEN_TYPE_DECLARATION */
unsigned NrTokens : 8; /**< UINT */
unsigned File : 4; /**< one of TGSI_FILE_x */
unsigned UsageMask : 4; /**< bitmask of TGSI_WRITEMASK_x flags */
unsigned Dimension : 1; /**< any extra dimension info? */
unsigned Semantic : 1; /**< BOOL, any semantic info? */
unsigned Interpolate : 1; /**< any interpolation info? */
unsigned Invariant : 1; /**< invariant optimization? */
unsigned Local : 1; /**< optimize as subroutine local variable? */
unsigned Array : 1; /**< extra array info? */
unsigned Padding : 6;
};
 
struct tgsi_declaration_range
{
unsigned First : 16; /**< UINT */
unsigned Last : 16; /**< UINT */
};
 
struct tgsi_declaration_dimension
{
unsigned Index2D:16; /**< UINT */
unsigned Padding:16;
};
 
struct tgsi_declaration_interp
{
unsigned Interpolate : 4; /**< one of TGSI_INTERPOLATE_x */
unsigned Centroid : 1; /**< centroid sampling? */
unsigned CylindricalWrap:4; /**< TGSI_CYLINDRICAL_WRAP_x flags */
unsigned Padding : 23;
};
 
#define TGSI_SEMANTIC_POSITION 0
#define TGSI_SEMANTIC_COLOR 1
#define TGSI_SEMANTIC_BCOLOR 2 /**< back-face color */
#define TGSI_SEMANTIC_FOG 3
#define TGSI_SEMANTIC_PSIZE 4
#define TGSI_SEMANTIC_GENERIC 5
#define TGSI_SEMANTIC_NORMAL 6
#define TGSI_SEMANTIC_FACE 7
#define TGSI_SEMANTIC_EDGEFLAG 8
#define TGSI_SEMANTIC_PRIMID 9
#define TGSI_SEMANTIC_INSTANCEID 10
#define TGSI_SEMANTIC_VERTEXID 11
#define TGSI_SEMANTIC_STENCIL 12
#define TGSI_SEMANTIC_CLIPDIST 13
#define TGSI_SEMANTIC_CLIPVERTEX 14
#define TGSI_SEMANTIC_GRID_SIZE 15 /**< grid size in blocks */
#define TGSI_SEMANTIC_BLOCK_ID 16 /**< id of the current block */
#define TGSI_SEMANTIC_BLOCK_SIZE 17 /**< block size in threads */
#define TGSI_SEMANTIC_THREAD_ID 18 /**< block-relative id of the current thread */
#define TGSI_SEMANTIC_TEXCOORD 19 /**< texture or sprite coordinates */
#define TGSI_SEMANTIC_PCOORD 20 /**< point sprite coordinate */
#define TGSI_SEMANTIC_VIEWPORT_INDEX 21 /**< viewport index */
#define TGSI_SEMANTIC_LAYER 22 /**< layer (rendertarget index) */
#define TGSI_SEMANTIC_CULLDIST 23
#define TGSI_SEMANTIC_COUNT 24 /**< number of semantic values */
 
struct tgsi_declaration_semantic
{
unsigned Name : 8; /**< one of TGSI_SEMANTIC_x */
unsigned Index : 16; /**< UINT */
unsigned Padding : 8;
};
 
struct tgsi_declaration_resource {
unsigned Resource : 8; /**< one of TGSI_TEXTURE_ */
unsigned Raw : 1;
unsigned Writable : 1;
unsigned Padding : 22;
};
 
struct tgsi_declaration_sampler_view {
unsigned Resource : 8; /**< one of TGSI_TEXTURE_ */
unsigned ReturnTypeX : 6; /**< one of enum pipe_type */
unsigned ReturnTypeY : 6; /**< one of enum pipe_type */
unsigned ReturnTypeZ : 6; /**< one of enum pipe_type */
unsigned ReturnTypeW : 6; /**< one of enum pipe_type */
};
 
struct tgsi_declaration_array {
unsigned ArrayID : 10;
unsigned Padding : 22;
};
 
/*
* Special resources that don't need to be declared. They map to the
* GLOBAL/LOCAL/PRIVATE/INPUT compute memory spaces.
*/
#define TGSI_RESOURCE_GLOBAL 0x7fff
#define TGSI_RESOURCE_LOCAL 0x7ffe
#define TGSI_RESOURCE_PRIVATE 0x7ffd
#define TGSI_RESOURCE_INPUT 0x7ffc
 
#define TGSI_IMM_FLOAT32 0
#define TGSI_IMM_UINT32 1
#define TGSI_IMM_INT32 2
 
struct tgsi_immediate
{
unsigned Type : 4; /**< TGSI_TOKEN_TYPE_IMMEDIATE */
unsigned NrTokens : 14; /**< UINT */
unsigned DataType : 4; /**< one of TGSI_IMM_x */
unsigned Padding : 10;
};
 
union tgsi_immediate_data
{
float Float;
unsigned Uint;
int Int;
};
 
#define TGSI_PROPERTY_GS_INPUT_PRIM 0
#define TGSI_PROPERTY_GS_OUTPUT_PRIM 1
#define TGSI_PROPERTY_GS_MAX_OUTPUT_VERTICES 2
#define TGSI_PROPERTY_FS_COORD_ORIGIN 3
#define TGSI_PROPERTY_FS_COORD_PIXEL_CENTER 4
#define TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS 5
#define TGSI_PROPERTY_FS_DEPTH_LAYOUT 6
#define TGSI_PROPERTY_VS_PROHIBIT_UCPS 7
#define TGSI_PROPERTY_COUNT 8
 
struct tgsi_property {
unsigned Type : 4; /**< TGSI_TOKEN_TYPE_PROPERTY */
unsigned NrTokens : 8; /**< UINT */
unsigned PropertyName : 8; /**< one of TGSI_PROPERTY */
unsigned Padding : 12;
};
 
#define TGSI_FS_COORD_ORIGIN_UPPER_LEFT 0
#define TGSI_FS_COORD_ORIGIN_LOWER_LEFT 1
 
#define TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER 0
#define TGSI_FS_COORD_PIXEL_CENTER_INTEGER 1
 
#define TGSI_FS_DEPTH_LAYOUT_NONE 0
#define TGSI_FS_DEPTH_LAYOUT_ANY 1
#define TGSI_FS_DEPTH_LAYOUT_GREATER 2
#define TGSI_FS_DEPTH_LAYOUT_LESS 3
#define TGSI_FS_DEPTH_LAYOUT_UNCHANGED 4
 
 
struct tgsi_property_data {
unsigned Data;
};
 
/* TGSI opcodes.
*
* For more information on semantics of opcodes and
* which APIs are known to use which opcodes, see
* gallium/docs/source/tgsi.rst
*/
#define TGSI_OPCODE_ARL 0
#define TGSI_OPCODE_MOV 1
#define TGSI_OPCODE_LIT 2
#define TGSI_OPCODE_RCP 3
#define TGSI_OPCODE_RSQ 4
#define TGSI_OPCODE_EXP 5
#define TGSI_OPCODE_LOG 6
#define TGSI_OPCODE_MUL 7
#define TGSI_OPCODE_ADD 8
#define TGSI_OPCODE_DP3 9
#define TGSI_OPCODE_DP4 10
#define TGSI_OPCODE_DST 11
#define TGSI_OPCODE_MIN 12
#define TGSI_OPCODE_MAX 13
#define TGSI_OPCODE_SLT 14
#define TGSI_OPCODE_SGE 15
#define TGSI_OPCODE_MAD 16
#define TGSI_OPCODE_SUB 17
#define TGSI_OPCODE_LRP 18
#define TGSI_OPCODE_CND 19
#define TGSI_OPCODE_SQRT 20
#define TGSI_OPCODE_DP2A 21
/* gap */
#define TGSI_OPCODE_FRC 24
#define TGSI_OPCODE_CLAMP 25
#define TGSI_OPCODE_FLR 26
#define TGSI_OPCODE_ROUND 27
#define TGSI_OPCODE_EX2 28
#define TGSI_OPCODE_LG2 29
#define TGSI_OPCODE_POW 30
#define TGSI_OPCODE_XPD 31
/* gap */
#define TGSI_OPCODE_ABS 33
#define TGSI_OPCODE_RCC 34
#define TGSI_OPCODE_DPH 35
#define TGSI_OPCODE_COS 36
#define TGSI_OPCODE_DDX 37
#define TGSI_OPCODE_DDY 38
#define TGSI_OPCODE_KILP 39 /* predicated kill */
#define TGSI_OPCODE_PK2H 40
#define TGSI_OPCODE_PK2US 41
#define TGSI_OPCODE_PK4B 42
#define TGSI_OPCODE_PK4UB 43
#define TGSI_OPCODE_RFL 44
#define TGSI_OPCODE_SEQ 45
#define TGSI_OPCODE_SFL 46
#define TGSI_OPCODE_SGT 47
#define TGSI_OPCODE_SIN 48
#define TGSI_OPCODE_SLE 49
#define TGSI_OPCODE_SNE 50
#define TGSI_OPCODE_STR 51
#define TGSI_OPCODE_TEX 52
#define TGSI_OPCODE_TXD 53
#define TGSI_OPCODE_TXP 54
#define TGSI_OPCODE_UP2H 55
#define TGSI_OPCODE_UP2US 56
#define TGSI_OPCODE_UP4B 57
#define TGSI_OPCODE_UP4UB 58
#define TGSI_OPCODE_X2D 59
#define TGSI_OPCODE_ARA 60
#define TGSI_OPCODE_ARR 61
#define TGSI_OPCODE_BRA 62
#define TGSI_OPCODE_CAL 63
#define TGSI_OPCODE_RET 64
#define TGSI_OPCODE_SSG 65 /* SGN */
#define TGSI_OPCODE_CMP 66
#define TGSI_OPCODE_SCS 67
#define TGSI_OPCODE_TXB 68
#define TGSI_OPCODE_NRM 69
#define TGSI_OPCODE_DIV 70
#define TGSI_OPCODE_DP2 71
#define TGSI_OPCODE_TXL 72
#define TGSI_OPCODE_BRK 73
#define TGSI_OPCODE_IF 74
#define TGSI_OPCODE_UIF 75
#define TGSI_OPCODE_ELSE 77
#define TGSI_OPCODE_ENDIF 78
/* gap */
#define TGSI_OPCODE_PUSHA 81
#define TGSI_OPCODE_POPA 82
#define TGSI_OPCODE_CEIL 83
#define TGSI_OPCODE_I2F 84
#define TGSI_OPCODE_NOT 85
#define TGSI_OPCODE_TRUNC 86
#define TGSI_OPCODE_SHL 87
/* gap */
#define TGSI_OPCODE_AND 89
#define TGSI_OPCODE_OR 90
#define TGSI_OPCODE_MOD 91
#define TGSI_OPCODE_XOR 92
#define TGSI_OPCODE_SAD 93
#define TGSI_OPCODE_TXF 94
#define TGSI_OPCODE_TXQ 95
#define TGSI_OPCODE_CONT 96
#define TGSI_OPCODE_EMIT 97
#define TGSI_OPCODE_ENDPRIM 98
#define TGSI_OPCODE_BGNLOOP 99
#define TGSI_OPCODE_BGNSUB 100
#define TGSI_OPCODE_ENDLOOP 101
#define TGSI_OPCODE_ENDSUB 102
#define TGSI_OPCODE_TXQ_LZ 103 /* TXQ for mipmap level 0 */
/* gap */
#define TGSI_OPCODE_NOP 107
/* gap */
#define TGSI_OPCODE_NRM4 112
#define TGSI_OPCODE_CALLNZ 113
/* gap */
#define TGSI_OPCODE_BREAKC 115
#define TGSI_OPCODE_KIL 116 /* conditional kill */
#define TGSI_OPCODE_END 117 /* aka HALT */
/* gap */
#define TGSI_OPCODE_F2I 119
#define TGSI_OPCODE_IDIV 120
#define TGSI_OPCODE_IMAX 121
#define TGSI_OPCODE_IMIN 122
#define TGSI_OPCODE_INEG 123
#define TGSI_OPCODE_ISGE 124
#define TGSI_OPCODE_ISHR 125
#define TGSI_OPCODE_ISLT 126
#define TGSI_OPCODE_F2U 127
#define TGSI_OPCODE_U2F 128
#define TGSI_OPCODE_UADD 129
#define TGSI_OPCODE_UDIV 130
#define TGSI_OPCODE_UMAD 131
#define TGSI_OPCODE_UMAX 132
#define TGSI_OPCODE_UMIN 133
#define TGSI_OPCODE_UMOD 134
#define TGSI_OPCODE_UMUL 135
#define TGSI_OPCODE_USEQ 136
#define TGSI_OPCODE_USGE 137
#define TGSI_OPCODE_USHR 138
#define TGSI_OPCODE_USLT 139
#define TGSI_OPCODE_USNE 140
#define TGSI_OPCODE_SWITCH 141
#define TGSI_OPCODE_CASE 142
#define TGSI_OPCODE_DEFAULT 143
#define TGSI_OPCODE_ENDSWITCH 144
 
/* resource related opcodes */
#define TGSI_OPCODE_SAMPLE 145
#define TGSI_OPCODE_SAMPLE_I 146
#define TGSI_OPCODE_SAMPLE_I_MS 147
#define TGSI_OPCODE_SAMPLE_B 148
#define TGSI_OPCODE_SAMPLE_C 149
#define TGSI_OPCODE_SAMPLE_C_LZ 150
#define TGSI_OPCODE_SAMPLE_D 151
#define TGSI_OPCODE_SAMPLE_L 152
#define TGSI_OPCODE_GATHER4 153
#define TGSI_OPCODE_SVIEWINFO 154
#define TGSI_OPCODE_SAMPLE_POS 155
#define TGSI_OPCODE_SAMPLE_INFO 156
 
#define TGSI_OPCODE_UARL 157
#define TGSI_OPCODE_UCMP 158
#define TGSI_OPCODE_IABS 159
#define TGSI_OPCODE_ISSG 160
 
#define TGSI_OPCODE_LOAD 161
#define TGSI_OPCODE_STORE 162
 
#define TGSI_OPCODE_MFENCE 163
#define TGSI_OPCODE_LFENCE 164
#define TGSI_OPCODE_SFENCE 165
#define TGSI_OPCODE_BARRIER 166
 
#define TGSI_OPCODE_ATOMUADD 167
#define TGSI_OPCODE_ATOMXCHG 168
#define TGSI_OPCODE_ATOMCAS 169
#define TGSI_OPCODE_ATOMAND 170
#define TGSI_OPCODE_ATOMOR 171
#define TGSI_OPCODE_ATOMXOR 172
#define TGSI_OPCODE_ATOMUMIN 173
#define TGSI_OPCODE_ATOMUMAX 174
#define TGSI_OPCODE_ATOMIMIN 175
#define TGSI_OPCODE_ATOMIMAX 176
 
/* to be used for shadow cube map compares */
#define TGSI_OPCODE_TEX2 177
#define TGSI_OPCODE_TXB2 178
#define TGSI_OPCODE_TXL2 179
 
#define TGSI_OPCODE_LAST 180
 
#define TGSI_SAT_NONE 0 /* do not saturate */
#define TGSI_SAT_ZERO_ONE 1 /* clamp to [0,1] */
#define TGSI_SAT_MINUS_PLUS_ONE 2 /* clamp to [-1,1] */
 
/**
* Opcode is the operation code to execute. A given operation defines the
* semantics how the source registers (if any) are interpreted and what is
* written to the destination registers (if any) as a result of execution.
*
* NumDstRegs and NumSrcRegs is the number of destination and source registers,
* respectively. For a given operation code, those numbers are fixed and are
* present here only for convenience.
*
* If Predicate is TRUE, tgsi_instruction_predicate token immediately follows.
*
* Saturate controls how are final results in destination registers modified.
*/
 
struct tgsi_instruction
{
unsigned Type : 4; /* TGSI_TOKEN_TYPE_INSTRUCTION */
unsigned NrTokens : 8; /* UINT */
unsigned Opcode : 8; /* TGSI_OPCODE_ */
unsigned Saturate : 2; /* TGSI_SAT_ */
unsigned NumDstRegs : 2; /* UINT */
unsigned NumSrcRegs : 4; /* UINT */
unsigned Predicate : 1; /* BOOL */
unsigned Label : 1;
unsigned Texture : 1;
unsigned Padding : 1;
};
 
/*
* If tgsi_instruction::Label is TRUE, tgsi_instruction_label follows.
*
* If tgsi_instruction::Texture is TRUE, tgsi_instruction_texture follows.
* if texture instruction has a number of offsets,
* then tgsi_instruction::Texture::NumOffset of tgsi_texture_offset follow.
*
* Then, tgsi_instruction::NumDstRegs of tgsi_dst_register follow.
*
* Then, tgsi_instruction::NumSrcRegs of tgsi_src_register follow.
*
* tgsi_instruction::NrTokens contains the total number of words that make the
* instruction, including the instruction word.
*/
 
#define TGSI_SWIZZLE_X 0
#define TGSI_SWIZZLE_Y 1
#define TGSI_SWIZZLE_Z 2
#define TGSI_SWIZZLE_W 3
 
struct tgsi_instruction_label
{
unsigned Label : 24; /* UINT */
unsigned Padding : 8;
};
 
#define TGSI_TEXTURE_BUFFER 0
#define TGSI_TEXTURE_1D 1
#define TGSI_TEXTURE_2D 2
#define TGSI_TEXTURE_3D 3
#define TGSI_TEXTURE_CUBE 4
#define TGSI_TEXTURE_RECT 5
#define TGSI_TEXTURE_SHADOW1D 6
#define TGSI_TEXTURE_SHADOW2D 7
#define TGSI_TEXTURE_SHADOWRECT 8
#define TGSI_TEXTURE_1D_ARRAY 9
#define TGSI_TEXTURE_2D_ARRAY 10
#define TGSI_TEXTURE_SHADOW1D_ARRAY 11
#define TGSI_TEXTURE_SHADOW2D_ARRAY 12
#define TGSI_TEXTURE_SHADOWCUBE 13
#define TGSI_TEXTURE_2D_MSAA 14
#define TGSI_TEXTURE_2D_ARRAY_MSAA 15
#define TGSI_TEXTURE_CUBE_ARRAY 16
#define TGSI_TEXTURE_SHADOWCUBE_ARRAY 17
#define TGSI_TEXTURE_UNKNOWN 18
#define TGSI_TEXTURE_COUNT 19
 
struct tgsi_instruction_texture
{
unsigned Texture : 8; /* TGSI_TEXTURE_ */
unsigned NumOffsets : 4;
unsigned Padding : 20;
};
 
/* for texture offsets in GLSL and DirectX.
* Generally these always come from TGSI_FILE_IMMEDIATE,
* however DX11 appears to have the capability to do
* non-constant texture offsets.
*/
struct tgsi_texture_offset
{
int Index : 16;
unsigned File : 4; /**< one of TGSI_FILE_x */
unsigned SwizzleX : 2; /* TGSI_SWIZZLE_x */
unsigned SwizzleY : 2; /* TGSI_SWIZZLE_x */
unsigned SwizzleZ : 2; /* TGSI_SWIZZLE_x */
unsigned Padding : 6;
};
 
/*
* For SM3, the following constraint applies.
* - Swizzle is either set to identity or replicate.
*/
struct tgsi_instruction_predicate
{
int Index : 16; /* SINT */
unsigned SwizzleX : 2; /* TGSI_SWIZZLE_x */
unsigned SwizzleY : 2; /* TGSI_SWIZZLE_x */
unsigned SwizzleZ : 2; /* TGSI_SWIZZLE_x */
unsigned SwizzleW : 2; /* TGSI_SWIZZLE_x */
unsigned Negate : 1; /* BOOL */
unsigned Padding : 7;
};
 
/**
* File specifies the register array to access.
*
* Index specifies the element number of a register in the register file.
*
* If Indirect is TRUE, Index should be offset by the X component of the indirect
* register that follows. The register can be now fetched into local storage
* for further processing.
*
* If Negate is TRUE, all components of the fetched register are negated.
*
* The fetched register components are swizzled according to SwizzleX, SwizzleY,
* SwizzleZ and SwizzleW.
*
*/
 
struct tgsi_src_register
{
unsigned File : 4; /* TGSI_FILE_ */
unsigned Indirect : 1; /* BOOL */
unsigned Dimension : 1; /* BOOL */
int Index : 16; /* SINT */
unsigned SwizzleX : 2; /* TGSI_SWIZZLE_ */
unsigned SwizzleY : 2; /* TGSI_SWIZZLE_ */
unsigned SwizzleZ : 2; /* TGSI_SWIZZLE_ */
unsigned SwizzleW : 2; /* TGSI_SWIZZLE_ */
unsigned Absolute : 1; /* BOOL */
unsigned Negate : 1; /* BOOL */
};
 
/**
* If tgsi_src_register::Indirect is TRUE, tgsi_ind_register follows.
*
* File, Index and Swizzle are handled the same as in tgsi_src_register.
*
* If ArrayID is zero the whole register file might be is indirectly addressed,
* if not only the Declaration with this ArrayID is accessed by this operand.
*
*/
 
struct tgsi_ind_register
{
unsigned File : 4; /* TGSI_FILE_ */
int Index : 16; /* SINT */
unsigned Swizzle : 2; /* TGSI_SWIZZLE_ */
unsigned ArrayID : 10; /* UINT */
};
 
/**
* If tgsi_src_register::Dimension is TRUE, tgsi_dimension follows.
*/
 
struct tgsi_dimension
{
unsigned Indirect : 1; /* BOOL */
unsigned Dimension : 1; /* BOOL */
unsigned Padding : 14;
int Index : 16; /* SINT */
};
 
struct tgsi_dst_register
{
unsigned File : 4; /* TGSI_FILE_ */
unsigned WriteMask : 4; /* TGSI_WRITEMASK_ */
unsigned Indirect : 1; /* BOOL */
unsigned Dimension : 1; /* BOOL */
int Index : 16; /* SINT */
unsigned Padding : 6;
};
 
 
#ifdef __cplusplus
}
#endif
 
#endif /* P_SHADER_TOKENS_H */
/drivers/video/Gallium/include/pipe/p_state.h
0,0 → 1,614
/**************************************************************************
*
* Copyright 2007 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
*
* Abstract graphics pipe state objects.
*
* Basic notes:
* 1. Want compact representations, so we use bitfields.
* 2. Put bitfields before other (GLfloat) fields.
*/
 
 
#ifndef PIPE_STATE_H
#define PIPE_STATE_H
 
#include "p_compiler.h"
#include "p_defines.h"
#include "p_format.h"
 
 
#ifdef __cplusplus
extern "C" {
#endif
 
 
/**
* Implementation limits
*/
#define PIPE_MAX_ATTRIBS 32
#define PIPE_MAX_CLIP_PLANES 8
#define PIPE_MAX_COLOR_BUFS 8
#define PIPE_MAX_CONSTANT_BUFFERS 32
#define PIPE_MAX_SAMPLERS 16
#define PIPE_MAX_SHADER_INPUTS 32
#define PIPE_MAX_SHADER_OUTPUTS 48 /* 32 GENERICs + POS, PSIZE, FOG, etc. */
#define PIPE_MAX_SHADER_SAMPLER_VIEWS 32
#define PIPE_MAX_SHADER_RESOURCES 32
#define PIPE_MAX_TEXTURE_LEVELS 16
#define PIPE_MAX_SO_BUFFERS 4
#define PIPE_MAX_SO_OUTPUTS 64
#define PIPE_MAX_VIEWPORTS 16
#define PIPE_MAX_CLIP_OR_CULL_DISTANCE_COUNT 8
#define PIPE_MAX_CLIP_OR_CULL_DISTANCE_ELEMENT_COUNT 2
 
 
struct pipe_reference
{
int32_t count; /* atomic */
};
 
 
 
/**
* Primitive (point/line/tri) rasterization info
*/
struct pipe_rasterizer_state
{
unsigned flatshade:1;
unsigned light_twoside:1;
unsigned clamp_vertex_color:1;
unsigned clamp_fragment_color:1;
unsigned front_ccw:1;
unsigned cull_face:2; /**< PIPE_FACE_x */
unsigned fill_front:2; /**< PIPE_POLYGON_MODE_x */
unsigned fill_back:2; /**< PIPE_POLYGON_MODE_x */
unsigned offset_point:1;
unsigned offset_line:1;
unsigned offset_tri:1;
unsigned scissor:1;
unsigned poly_smooth:1;
unsigned poly_stipple_enable:1;
unsigned point_smooth:1;
unsigned sprite_coord_mode:1; /**< PIPE_SPRITE_COORD_ */
unsigned point_quad_rasterization:1; /** points rasterized as quads or points */
unsigned point_size_per_vertex:1; /**< size computed in vertex shader */
unsigned multisample:1; /* XXX maybe more ms state in future */
unsigned line_smooth:1;
unsigned line_stipple_enable:1;
unsigned line_last_pixel:1;
 
/**
* Use the first vertex of a primitive as the provoking vertex for
* flat shading.
*/
unsigned flatshade_first:1;
 
unsigned half_pixel_center:1;
unsigned bottom_edge_rule:1;
 
/**
* When true, rasterization is disabled and no pixels are written.
* This only makes sense with the Stream Out functionality.
*/
unsigned rasterizer_discard:1;
 
/**
* When false, depth clipping is disabled and the depth value will be
* clamped later at the per-pixel level before depth testing.
* This depends on PIPE_CAP_DEPTH_CLIP_DISABLE.
*/
unsigned depth_clip:1;
 
/**
* When true clip space in the z axis goes from [0..1] (D3D). When false
* [-1, 1] (GL).
*/
unsigned clip_halfz:1;
 
/**
* Enable bits for clipping half-spaces.
* This applies to both user clip planes and shader clip distances.
* Note that if the bound shader exports any clip distances, these
* replace all user clip planes, and clip half-spaces enabled here
* but not written by the shader count as disabled.
*/
unsigned clip_plane_enable:PIPE_MAX_CLIP_PLANES;
 
unsigned line_stipple_factor:8; /**< [1..256] actually */
unsigned line_stipple_pattern:16;
 
uint32_t sprite_coord_enable; /* referring to 32 TEXCOORD/GENERIC inputs */
 
float line_width;
float point_size; /**< used when no per-vertex size */
float offset_units;
float offset_scale;
float offset_clamp;
};
 
 
struct pipe_poly_stipple
{
unsigned stipple[32];
};
 
 
struct pipe_viewport_state
{
float scale[4];
float translate[4];
};
 
 
struct pipe_scissor_state
{
unsigned minx:16;
unsigned miny:16;
unsigned maxx:16;
unsigned maxy:16;
};
 
 
struct pipe_clip_state
{
float ucp[PIPE_MAX_CLIP_PLANES][4];
};
 
 
/**
* Stream output for vertex transform feedback.
*/
struct pipe_stream_output_info
{
unsigned num_outputs;
/** stride for an entire vertex for each buffer in dwords */
unsigned stride[PIPE_MAX_SO_BUFFERS];
 
/**
* Array of stream outputs, in the order they are to be written in.
* Selected components are tightly packed into the output buffer.
*/
struct {
unsigned register_index:8; /**< 0 to PIPE_MAX_SHADER_OUTPUTS */
unsigned start_component:2; /** 0 to 3 */
unsigned num_components:3; /** 1 to 4 */
unsigned output_buffer:3; /**< 0 to PIPE_MAX_SO_BUFFERS */
unsigned dst_offset:16; /**< offset into the buffer in dwords */
} output[PIPE_MAX_SO_OUTPUTS];
};
 
 
struct pipe_shader_state
{
const struct tgsi_token *tokens;
struct pipe_stream_output_info stream_output;
};
 
 
struct pipe_depth_state
{
unsigned enabled:1; /**< depth test enabled? */
unsigned writemask:1; /**< allow depth buffer writes? */
unsigned func:3; /**< depth test func (PIPE_FUNC_x) */
};
 
 
struct pipe_stencil_state
{
unsigned enabled:1; /**< stencil[0]: stencil enabled, stencil[1]: two-side enabled */
unsigned func:3; /**< PIPE_FUNC_x */
unsigned fail_op:3; /**< PIPE_STENCIL_OP_x */
unsigned zpass_op:3; /**< PIPE_STENCIL_OP_x */
unsigned zfail_op:3; /**< PIPE_STENCIL_OP_x */
unsigned valuemask:8;
unsigned writemask:8;
};
 
 
struct pipe_alpha_state
{
unsigned enabled:1;
unsigned func:3; /**< PIPE_FUNC_x */
float ref_value; /**< reference value */
};
 
 
struct pipe_depth_stencil_alpha_state
{
struct pipe_depth_state depth;
struct pipe_stencil_state stencil[2]; /**< [0] = front, [1] = back */
struct pipe_alpha_state alpha;
};
 
 
struct pipe_rt_blend_state
{
unsigned blend_enable:1;
 
unsigned rgb_func:3; /**< PIPE_BLEND_x */
unsigned rgb_src_factor:5; /**< PIPE_BLENDFACTOR_x */
unsigned rgb_dst_factor:5; /**< PIPE_BLENDFACTOR_x */
 
unsigned alpha_func:3; /**< PIPE_BLEND_x */
unsigned alpha_src_factor:5; /**< PIPE_BLENDFACTOR_x */
unsigned alpha_dst_factor:5; /**< PIPE_BLENDFACTOR_x */
 
unsigned colormask:4; /**< bitmask of PIPE_MASK_R/G/B/A */
};
 
struct pipe_blend_state
{
unsigned independent_blend_enable:1;
unsigned logicop_enable:1;
unsigned logicop_func:4; /**< PIPE_LOGICOP_x */
unsigned dither:1;
unsigned alpha_to_coverage:1;
unsigned alpha_to_one:1;
struct pipe_rt_blend_state rt[PIPE_MAX_COLOR_BUFS];
};
 
 
struct pipe_blend_color
{
float color[4];
};
 
struct pipe_stencil_ref
{
ubyte ref_value[2];
};
 
struct pipe_framebuffer_state
{
unsigned width, height;
 
/** multiple color buffers for multiple render targets */
unsigned nr_cbufs;
struct pipe_surface *cbufs[PIPE_MAX_COLOR_BUFS];
 
struct pipe_surface *zsbuf; /**< Z/stencil buffer */
};
 
 
/**
* Texture sampler state.
*/
struct pipe_sampler_state
{
unsigned wrap_s:3; /**< PIPE_TEX_WRAP_x */
unsigned wrap_t:3; /**< PIPE_TEX_WRAP_x */
unsigned wrap_r:3; /**< PIPE_TEX_WRAP_x */
unsigned min_img_filter:2; /**< PIPE_TEX_FILTER_x */
unsigned min_mip_filter:2; /**< PIPE_TEX_MIPFILTER_x */
unsigned mag_img_filter:2; /**< PIPE_TEX_FILTER_x */
unsigned compare_mode:1; /**< PIPE_TEX_COMPARE_x */
unsigned compare_func:3; /**< PIPE_FUNC_x */
unsigned normalized_coords:1; /**< Are coords normalized to [0,1]? */
unsigned max_anisotropy:6;
unsigned seamless_cube_map:1;
float lod_bias; /**< LOD/lambda bias */
float min_lod, max_lod; /**< LOD clamp range, after bias */
union pipe_color_union border_color;
};
 
 
/**
* A view into a texture that can be bound to a color render target /
* depth stencil attachment point.
*/
struct pipe_surface
{
struct pipe_reference reference;
struct pipe_resource *texture; /**< resource into which this is a view */
struct pipe_context *context; /**< context this surface belongs to */
enum pipe_format format;
 
/* XXX width/height should be removed */
unsigned width; /**< logical width in pixels */
unsigned height; /**< logical height in pixels */
 
unsigned writable:1; /**< writable shader resource */
 
union {
struct {
unsigned level;
unsigned first_layer:16;
unsigned last_layer:16;
} tex;
struct {
unsigned first_element;
unsigned last_element;
} buf;
} u;
};
 
 
/**
* A view into a texture that can be bound to a shader stage.
*/
struct pipe_sampler_view
{
struct pipe_reference reference;
enum pipe_format format; /**< typed PIPE_FORMAT_x */
struct pipe_resource *texture; /**< texture into which this is a view */
struct pipe_context *context; /**< context this view belongs to */
union {
struct {
unsigned first_layer:16; /**< first layer to use for array textures */
unsigned last_layer:16; /**< last layer to use for array textures */
unsigned first_level:8; /**< first mipmap level to use */
unsigned last_level:8; /**< last mipmap level to use */
} tex;
struct {
unsigned first_element;
unsigned last_element;
} buf;
} u;
unsigned swizzle_r:3; /**< PIPE_SWIZZLE_x for red component */
unsigned swizzle_g:3; /**< PIPE_SWIZZLE_x for green component */
unsigned swizzle_b:3; /**< PIPE_SWIZZLE_x for blue component */
unsigned swizzle_a:3; /**< PIPE_SWIZZLE_x for alpha component */
};
 
 
/**
* Subregion of 1D/2D/3D image resource.
*/
struct pipe_box
{
int x;
int y;
int z;
int width;
int height;
int depth;
};
 
 
/**
* A memory object/resource such as a vertex buffer or texture.
*/
struct pipe_resource
{
struct pipe_reference reference;
struct pipe_screen *screen; /**< screen that this texture belongs to */
enum pipe_texture_target target; /**< PIPE_TEXTURE_x */
enum pipe_format format; /**< PIPE_FORMAT_x */
 
unsigned width0;
unsigned height0;
unsigned depth0;
unsigned array_size;
 
unsigned last_level:8; /**< Index of last mipmap level present/defined */
unsigned nr_samples:8; /**< for multisampled surfaces, nr of samples */
unsigned usage:8; /**< PIPE_USAGE_x (not a bitmask) */
 
unsigned bind; /**< bitmask of PIPE_BIND_x */
unsigned flags; /**< bitmask of PIPE_RESOURCE_FLAG_x */
};
 
 
/**
* Transfer object. For data transfer to/from a resource.
*/
struct pipe_transfer
{
struct pipe_resource *resource; /**< resource to transfer to/from */
unsigned level; /**< texture mipmap level */
enum pipe_transfer_usage usage;
struct pipe_box box; /**< region of the resource to access */
unsigned stride; /**< row stride in bytes */
unsigned layer_stride; /**< image/layer stride in bytes */
};
 
 
 
/**
* A vertex buffer. Typically, all the vertex data/attributes for
* drawing something will be in one buffer. But it's also possible, for
* example, to put colors in one buffer and texcoords in another.
*/
struct pipe_vertex_buffer
{
unsigned stride; /**< stride to same attrib in next vertex, in bytes */
unsigned buffer_offset; /**< offset to start of data in buffer, in bytes */
struct pipe_resource *buffer; /**< the actual buffer */
const void *user_buffer; /**< pointer to a user buffer if buffer == NULL */
};
 
 
/**
* A constant buffer. A subrange of an existing buffer can be set
* as a constant buffer.
*/
struct pipe_constant_buffer {
struct pipe_resource *buffer; /**< the actual buffer */
unsigned buffer_offset; /**< offset to start of data in buffer, in bytes */
unsigned buffer_size; /**< how much data can be read in shader */
const void *user_buffer; /**< pointer to a user buffer if buffer == NULL */
};
 
 
/**
* A stream output target. The structure specifies the range vertices can
* be written to.
*
* In addition to that, the structure should internally maintain the offset
* into the buffer, which should be incremented everytime something is written
* (appended) to it. The internal offset is buffer_offset + how many bytes
* have been written. The internal offset can be stored on the device
* and the CPU actually doesn't have to query it.
*
* Note that the buffer_size variable is actually specifying the available
* space in the buffer, not the size of the attached buffer.
* In other words in majority of cases buffer_size would simply be
* 'buffer->width0 - buffer_offset', so buffer_size refers to the size
* of the buffer left, after accounting for buffer offset, for stream output
* to write to.
*
* Use PIPE_QUERY_SO_STATISTICS to know how many primitives have
* actually been written.
*/
struct pipe_stream_output_target
{
struct pipe_reference reference;
struct pipe_resource *buffer; /**< the output buffer */
struct pipe_context *context; /**< context this SO target belongs to */
 
unsigned buffer_offset; /**< offset where data should be written, in bytes */
unsigned buffer_size; /**< how much data is allowed to be written */
};
 
 
/**
* Information to describe a vertex attribute (position, color, etc)
*/
struct pipe_vertex_element
{
/** Offset of this attribute, in bytes, from the start of the vertex */
unsigned src_offset;
 
/** Instance data rate divisor. 0 means this is per-vertex data,
* n means per-instance data used for n consecutive instances (n > 0).
*/
unsigned instance_divisor;
 
/** Which vertex_buffer (as given to pipe->set_vertex_buffer()) does
* this attribute live in?
*/
unsigned vertex_buffer_index;
enum pipe_format src_format;
};
 
 
/**
* An index buffer. When an index buffer is bound, all indices to vertices
* will be looked up in the buffer.
*/
struct pipe_index_buffer
{
unsigned index_size; /**< size of an index, in bytes */
unsigned offset; /**< offset to start of data in buffer, in bytes */
struct pipe_resource *buffer; /**< the actual buffer */
const void *user_buffer; /**< pointer to a user buffer if buffer == NULL */
};
 
 
/**
* Information to describe a draw_vbo call.
*/
struct pipe_draw_info
{
boolean indexed; /**< use index buffer */
 
unsigned mode; /**< the mode of the primitive */
unsigned start; /**< the index of the first vertex */
unsigned count; /**< number of vertices */
 
unsigned start_instance; /**< first instance id */
unsigned instance_count; /**< number of instances */
 
/**
* For indexed drawing, these fields apply after index lookup.
*/
int index_bias; /**< a bias to be added to each index */
unsigned min_index; /**< the min index */
unsigned max_index; /**< the max index */
 
/**
* Primitive restart enable/index (only applies to indexed drawing)
*/
boolean primitive_restart;
unsigned restart_index;
 
/**
* Stream output target. If not NULL, it's used to provide the 'count'
* parameter based on the number vertices captured by the stream output
* stage. (or generally, based on the number of bytes captured)
*
* Only 'mode', 'start_instance', and 'instance_count' are taken into
* account, all the other variables from pipe_draw_info are ignored.
*
* 'start' is implicitly 0 and 'count' is set as discussed above.
* The draw command is non-indexed.
*
* Note that this only provides the count. The vertex buffers must
* be set via set_vertex_buffers manually.
*/
struct pipe_stream_output_target *count_from_stream_output;
};
 
 
/**
* Information to describe a blit call.
*/
struct pipe_blit_info
{
struct {
struct pipe_resource *resource;
unsigned level;
struct pipe_box box; /**< negative width, height only legal for src */
/* For pipe_surface-like format casting: */
enum pipe_format format; /**< must be supported for sampling (src)
or rendering (dst), ZS is always supported */
} dst, src;
 
unsigned mask; /**< bitmask of PIPE_MASK_R/G/B/A/Z/S */
unsigned filter; /**< PIPE_TEX_FILTER_* */
 
boolean scissor_enable;
struct pipe_scissor_state scissor;
};
 
 
/**
* Structure used as a header for serialized LLVM programs.
*/
struct pipe_llvm_program_header
{
uint32_t num_bytes; /**< Number of bytes in the LLVM bytecode program. */
};
 
struct pipe_compute_state
{
const void *prog; /**< Compute program to be executed. */
unsigned req_local_mem; /**< Required size of the LOCAL resource. */
unsigned req_private_mem; /**< Required size of the PRIVATE resource. */
unsigned req_input_mem; /**< Required size of the INPUT resource. */
};
 
#ifdef __cplusplus
}
#endif
#endif
/drivers/video/Gallium/include/pipe/p_video_decoder.h
0,0 → 1,155
/**************************************************************************
*
* Copyright 2009 Younes Manton.
* 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.
*
**************************************************************************/
 
#ifndef PIPE_VIDEO_CONTEXT_H
#define PIPE_VIDEO_CONTEXT_H
 
#ifdef __cplusplus
extern "C" {
#endif
 
#include "pipe/p_video_state.h"
 
struct pipe_screen;
struct pipe_surface;
struct pipe_macroblock;
struct pipe_picture_desc;
struct pipe_fence_handle;
 
/**
* Gallium video decoder for a specific codec/profile
*/
struct pipe_video_decoder
{
struct pipe_context *context;
 
enum pipe_video_profile profile;
enum pipe_video_entrypoint entrypoint;
enum pipe_video_chroma_format chroma_format;
unsigned width;
unsigned height;
unsigned max_references;
 
/**
* destroy this video decoder
*/
void (*destroy)(struct pipe_video_decoder *decoder);
 
/**
* start decoding of a new frame
*/
void (*begin_frame)(struct pipe_video_decoder *decoder,
struct pipe_video_buffer *target,
struct pipe_picture_desc *picture);
 
/**
* decode a macroblock
*/
void (*decode_macroblock)(struct pipe_video_decoder *decoder,
struct pipe_video_buffer *target,
struct pipe_picture_desc *picture,
const struct pipe_macroblock *macroblocks,
unsigned num_macroblocks);
 
/**
* decode a bitstream
*/
void (*decode_bitstream)(struct pipe_video_decoder *decoder,
struct pipe_video_buffer *target,
struct pipe_picture_desc *picture,
unsigned num_buffers,
const void * const *buffers,
const unsigned *sizes);
 
/**
* end decoding of the current frame
*/
void (*end_frame)(struct pipe_video_decoder *decoder,
struct pipe_video_buffer *target,
struct pipe_picture_desc *picture);
 
/**
* flush any outstanding command buffers to the hardware
* should be called before a video_buffer is acessed by the state tracker again
*/
void (*flush)(struct pipe_video_decoder *decoder);
};
 
/**
* output for decoding / input for displaying
*/
struct pipe_video_buffer
{
struct pipe_context *context;
 
enum pipe_format buffer_format;
enum pipe_video_chroma_format chroma_format;
unsigned width;
unsigned height;
bool interlaced;
 
/**
* destroy this video buffer
*/
void (*destroy)(struct pipe_video_buffer *buffer);
 
/**
* get a individual sampler view for each plane
*/
struct pipe_sampler_view **(*get_sampler_view_planes)(struct pipe_video_buffer *buffer);
 
/**
* get a individual sampler view for each component
*/
struct pipe_sampler_view **(*get_sampler_view_components)(struct pipe_video_buffer *buffer);
 
/**
* get a individual surfaces for each plane
*/
struct pipe_surface **(*get_surfaces)(struct pipe_video_buffer *buffer);
 
/*
* auxiliary associated data
*/
void *associated_data;
 
/*
* decoder where the associated data came from
*/
struct pipe_video_decoder *decoder;
 
/*
* destroy the associated data
*/
void (*destroy_associated_data)(void *associated_data);
};
 
#ifdef __cplusplus
}
#endif
 
#endif /* PIPE_VIDEO_CONTEXT_H */
/drivers/video/Gallium/include/pipe/p_video_enums.h
0,0 → 1,78
/**************************************************************************
*
* Copyright 2009 Younes Manton.
* 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.
*
**************************************************************************/
 
#ifndef PIPE_VIDEO_ENUMS_H
#define PIPE_VIDEO_ENUMS_H
 
enum pipe_video_profile
{
PIPE_VIDEO_PROFILE_UNKNOWN,
PIPE_VIDEO_PROFILE_MPEG1,
PIPE_VIDEO_PROFILE_MPEG2_SIMPLE,
PIPE_VIDEO_PROFILE_MPEG2_MAIN,
PIPE_VIDEO_PROFILE_MPEG4_SIMPLE,
PIPE_VIDEO_PROFILE_MPEG4_ADVANCED_SIMPLE,
PIPE_VIDEO_PROFILE_VC1_SIMPLE,
PIPE_VIDEO_PROFILE_VC1_MAIN,
PIPE_VIDEO_PROFILE_VC1_ADVANCED,
PIPE_VIDEO_PROFILE_MPEG4_AVC_BASELINE,
PIPE_VIDEO_PROFILE_MPEG4_AVC_MAIN,
PIPE_VIDEO_PROFILE_MPEG4_AVC_HIGH
};
 
/* Video caps, can be different for each codec/profile */
enum pipe_video_cap
{
PIPE_VIDEO_CAP_SUPPORTED = 0,
PIPE_VIDEO_CAP_NPOT_TEXTURES = 1,
PIPE_VIDEO_CAP_MAX_WIDTH = 2,
PIPE_VIDEO_CAP_MAX_HEIGHT = 3,
PIPE_VIDEO_CAP_PREFERED_FORMAT = 4,
PIPE_VIDEO_CAP_PREFERS_INTERLACED = 5,
PIPE_VIDEO_CAP_SUPPORTS_PROGRESSIVE = 6,
PIPE_VIDEO_CAP_SUPPORTS_INTERLACED = 7
};
 
enum pipe_video_codec
{
PIPE_VIDEO_CODEC_UNKNOWN = 0,
PIPE_VIDEO_CODEC_MPEG12, /**< MPEG1, MPEG2 */
PIPE_VIDEO_CODEC_MPEG4, /**< DIVX, XVID */
PIPE_VIDEO_CODEC_VC1, /**< WMV */
PIPE_VIDEO_CODEC_MPEG4_AVC /**< H.264 */
};
 
enum pipe_video_entrypoint
{
PIPE_VIDEO_ENTRYPOINT_UNKNOWN,
PIPE_VIDEO_ENTRYPOINT_BITSTREAM,
PIPE_VIDEO_ENTRYPOINT_IDCT,
PIPE_VIDEO_ENTRYPOINT_MC
};
 
 
#endif /* PIPE_VIDEO_ENUMS_H */
/drivers/video/Gallium/include/pipe/p_video_state.h
0,0 → 1,292
/**************************************************************************
*
* Copyright 2009 Younes Manton.
* 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.
*
**************************************************************************/
 
#ifndef PIPE_VIDEO_STATE_H
#define PIPE_VIDEO_STATE_H
 
#include "pipe/p_defines.h"
#include "pipe/p_format.h"
#include "pipe/p_state.h"
#include "pipe/p_screen.h"
#include "util/u_inlines.h"
 
#ifdef __cplusplus
extern "C" {
#endif
 
/*
* see table 6-12 in the spec
*/
enum pipe_mpeg12_picture_coding_type
{
PIPE_MPEG12_PICTURE_CODING_TYPE_I = 0x01,
PIPE_MPEG12_PICTURE_CODING_TYPE_P = 0x02,
PIPE_MPEG12_PICTURE_CODING_TYPE_B = 0x03,
PIPE_MPEG12_PICTURE_CODING_TYPE_D = 0x04
};
 
/*
* see table 6-14 in the spec
*/
enum pipe_mpeg12_picture_structure
{
PIPE_MPEG12_PICTURE_STRUCTURE_RESERVED = 0x00,
PIPE_MPEG12_PICTURE_STRUCTURE_FIELD_TOP = 0x01,
PIPE_MPEG12_PICTURE_STRUCTURE_FIELD_BOTTOM = 0x02,
PIPE_MPEG12_PICTURE_STRUCTURE_FRAME = 0x03
};
 
/*
* flags for macroblock_type, see section 6.3.17.1 in the spec
*/
enum pipe_mpeg12_macroblock_type
{
PIPE_MPEG12_MB_TYPE_QUANT = 0x01,
PIPE_MPEG12_MB_TYPE_MOTION_FORWARD = 0x02,
PIPE_MPEG12_MB_TYPE_MOTION_BACKWARD = 0x04,
PIPE_MPEG12_MB_TYPE_PATTERN = 0x08,
PIPE_MPEG12_MB_TYPE_INTRA = 0x10
};
 
/*
* flags for motion_type, see table 6-17 and 6-18 in the spec
*/
enum pipe_mpeg12_motion_type
{
PIPE_MPEG12_MO_TYPE_RESERVED = 0x00,
PIPE_MPEG12_MO_TYPE_FIELD = 0x01,
PIPE_MPEG12_MO_TYPE_FRAME = 0x02,
PIPE_MPEG12_MO_TYPE_16x8 = 0x02,
PIPE_MPEG12_MO_TYPE_DUAL_PRIME = 0x03
};
 
/*
* see section 6.3.17.1 and table 6-19 in the spec
*/
enum pipe_mpeg12_dct_type
{
PIPE_MPEG12_DCT_TYPE_FRAME = 0,
PIPE_MPEG12_DCT_TYPE_FIELD = 1
};
 
enum pipe_mpeg12_field_select
{
PIPE_MPEG12_FS_FIRST_FORWARD = 0x01,
PIPE_MPEG12_FS_FIRST_BACKWARD = 0x02,
PIPE_MPEG12_FS_SECOND_FORWARD = 0x04,
PIPE_MPEG12_FS_SECOND_BACKWARD = 0x08
};
 
struct pipe_picture_desc
{
enum pipe_video_profile profile;
};
 
struct pipe_quant_matrix
{
enum pipe_video_codec codec;
};
 
struct pipe_macroblock
{
enum pipe_video_codec codec;
};
 
struct pipe_mpeg12_picture_desc
{
struct pipe_picture_desc base;
 
unsigned picture_coding_type;
unsigned picture_structure;
unsigned frame_pred_frame_dct;
unsigned q_scale_type;
unsigned alternate_scan;
unsigned intra_vlc_format;
unsigned concealment_motion_vectors;
unsigned intra_dc_precision;
unsigned f_code[2][2];
unsigned top_field_first;
unsigned full_pel_forward_vector;
unsigned full_pel_backward_vector;
unsigned num_slices;
 
const uint8_t *intra_matrix;
const uint8_t *non_intra_matrix;
 
struct pipe_video_buffer *ref[2];
};
 
struct pipe_mpeg12_macroblock
{
struct pipe_macroblock base;
 
/* see section 6.3.17 in the spec */
unsigned short x, y;
 
/* see section 6.3.17.1 in the spec */
unsigned char macroblock_type;
 
union {
struct {
/* see table 6-17 in the spec */
unsigned int frame_motion_type:2;
 
/* see table 6-18 in the spec */
unsigned int field_motion_type:2;
 
/* see table 6-19 in the spec */
unsigned int dct_type:1;
} bits;
unsigned int value;
} macroblock_modes;
 
/* see section 6.3.17.2 in the spec */
unsigned char motion_vertical_field_select;
 
/* see Table 7-7 in the spec */
short PMV[2][2][2];
 
/* see figure 6.10-12 in the spec */
unsigned short coded_block_pattern;
 
/* see figure 6.10-12 in the spec */
short *blocks;
 
/* Number of skipped macroblocks after this macroblock */
unsigned short num_skipped_macroblocks;
};
 
struct pipe_mpeg4_picture_desc
{
struct pipe_picture_desc base;
 
int32_t trd[2];
int32_t trb[2];
uint16_t vop_time_increment_resolution;
uint8_t vop_coding_type;
uint8_t vop_fcode_forward;
uint8_t vop_fcode_backward;
uint8_t resync_marker_disable;
uint8_t interlaced;
uint8_t quant_type;
uint8_t quarter_sample;
uint8_t short_video_header;
uint8_t rounding_control;
uint8_t alternate_vertical_scan_flag;
uint8_t top_field_first;
 
const uint8_t *intra_matrix;
const uint8_t *non_intra_matrix;
 
struct pipe_video_buffer *ref[2];
};
 
struct pipe_vc1_picture_desc
{
struct pipe_picture_desc base;
 
uint32_t slice_count;
uint8_t picture_type;
uint8_t frame_coding_mode;
uint8_t postprocflag;
uint8_t pulldown;
uint8_t interlace;
uint8_t tfcntrflag;
uint8_t finterpflag;
uint8_t psf;
uint8_t dquant;
uint8_t panscan_flag;
uint8_t refdist_flag;
uint8_t quantizer;
uint8_t extended_mv;
uint8_t extended_dmv;
uint8_t overlap;
uint8_t vstransform;
uint8_t loopfilter;
uint8_t fastuvmc;
uint8_t range_mapy_flag;
uint8_t range_mapy;
uint8_t range_mapuv_flag;
uint8_t range_mapuv;
uint8_t multires;
uint8_t syncmarker;
uint8_t rangered;
uint8_t maxbframes;
uint8_t deblockEnable;
uint8_t pquant;
 
struct pipe_video_buffer *ref[2];
};
 
struct pipe_h264_picture_desc
{
struct pipe_picture_desc base;
 
uint32_t slice_count;
int32_t field_order_cnt[2];
bool is_reference;
uint32_t frame_num;
uint8_t field_pic_flag;
uint8_t bottom_field_flag;
uint8_t num_ref_frames;
uint8_t mb_adaptive_frame_field_flag;
uint8_t constrained_intra_pred_flag;
uint8_t weighted_pred_flag;
uint8_t weighted_bipred_idc;
uint8_t frame_mbs_only_flag;
uint8_t transform_8x8_mode_flag;
int8_t chroma_qp_index_offset;
int8_t second_chroma_qp_index_offset;
int8_t pic_init_qp_minus26;
uint8_t num_ref_idx_l0_active_minus1;
uint8_t num_ref_idx_l1_active_minus1;
uint8_t log2_max_frame_num_minus4;
uint8_t pic_order_cnt_type;
uint8_t log2_max_pic_order_cnt_lsb_minus4;
uint8_t delta_pic_order_always_zero_flag;
uint8_t direct_8x8_inference_flag;
uint8_t entropy_coding_mode_flag;
uint8_t pic_order_present_flag;
uint8_t deblocking_filter_control_present_flag;
uint8_t redundant_pic_cnt_present_flag;
uint8_t scaling_lists_4x4[6][16];
uint8_t scaling_lists_8x8[2][64];
 
bool is_long_term[16];
bool top_is_reference[16];
bool bottom_is_reference[16];
uint32_t field_order_cnt_list[16][2];
uint32_t frame_num_list[16];
 
struct pipe_video_buffer *ref[16];
};
 
#ifdef __cplusplus
}
#endif
 
#endif /* PIPE_VIDEO_STATE_H */
/drivers/video/Gallium/include/state_tracker/drisw_api.h
0,0 → 1,23
#ifndef _DRISW_API_H_
#define _DRISW_API_H_
 
#include "pipe/p_compiler.h"
 
struct pipe_screen;
struct dri_drawable;
 
/**
* This callback struct is intended for the winsys to call the loader.
*/
struct drisw_loader_funcs
{
void (*put_image) (struct dri_drawable *dri_drawable,
void *data, unsigned width, unsigned height);
};
 
/**
* Implemented by the drisw target.
*/
struct pipe_screen * drisw_create_screen(struct drisw_loader_funcs *lf);
 
#endif
/drivers/video/Gallium/include/state_tracker/drm_driver.h
0,0 → 1,115
 
#ifndef _DRM_DRIVER_H_
#define _DRM_DRIVER_H_
 
#include "pipe/p_compiler.h"
 
struct pipe_screen;
struct pipe_context;
struct pipe_resource;
 
#define DRM_API_HANDLE_TYPE_SHARED 0
#define DRM_API_HANDLE_TYPE_KMS 1
 
/**
* For use with pipe_screen::{texture_from_handle|texture_get_handle}.
*/
struct winsys_handle
{
/**
* Unused for texture_from_handle, always
* DRM_API_HANDLE_TYPE_SHARED. Input to texture_get_handle,
* use TEXTURE_USAGE to select handle for kms or ipc.
*/
unsigned type;
/**
* Input to texture_from_handle.
* Output for texture_get_handle.
*/
unsigned handle;
/**
* Input to texture_from_handle.
* Output for texture_get_handle.
*/
unsigned stride;
};
 
 
 
/**
* Configuration queries.
*/
enum drm_conf {
/* How many frames to allow before throttling. Or -1 to indicate any number */
DRM_CONF_THROTTLE, /* DRM_CONF_INT. */
DRM_CONF_MAX
};
 
/**
* Type of configuration answer
*/
enum drm_conf_type {
DRM_CONF_INT,
DRM_CONF_BOOL,
DRM_CONF_FLOAT,
DRM_CONF_POINTER
};
 
/**
* Return value from the configuration function.
*/
struct drm_conf_ret {
enum drm_conf_type type;
union {
int val_int;
bool val_bool;
float val_float;
void *val_pointer;
} val;
};
 
struct drm_driver_descriptor
{
/**
* Identifying sufix/prefix of the binary, used by egl.
*/
const char *name;
 
/**
* Kernel driver name, as accepted by drmOpenByName.
*/
const char *driver_name;
 
/**
* Create a pipe srcreen.
*
* This function does any wrapping of the screen.
* For example wrapping trace or rbug debugging drivers around it.
*/
struct pipe_screen* (*create_screen)(int drm_fd);
 
 
/**
* Return a configuration value.
*
* If this function is NULL, or if it returns NULL
* the state tracker- or state
* tracker manager should provide a reasonable default value.
*/
const struct drm_conf_ret *(*configuration) (enum drm_conf conf);
};
 
extern struct drm_driver_descriptor driver_descriptor;
 
/**
* Instantiate a drm_driver_descriptor struct.
*/
#define DRM_DRIVER_DESCRIPTOR(name_str, driver_name_str, func, conf) \
struct drm_driver_descriptor driver_descriptor = { \
.name = name_str, \
.driver_name = driver_name_str, \
.create_screen = func, \
.configuration = (conf), \
};
 
#endif
/drivers/video/Gallium/include/state_tracker/graw.h
0,0 → 1,96
/**************************************************************************
*
* Copyright 2010 VMware, Inc.
* 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 VMWARE 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.
*
**************************************************************************/
 
#ifndef GALLIUM_RAW_H
#define GALLIUM_RAW_H
 
/* This is an API for exercising gallium functionality in a
* platform-neutral fashion. Whatever platform integration is
* necessary to implement this interface is orchestrated by the
* individual target building this entity.
*
* For instance, the graw-xlib target includes code to implent these
* interfaces on top of the X window system.
*
* Programs using this interface may additionally benefit from some of
* the utilities currently in the libgallium.a library, especially
* those for parsing text representations of TGSI shaders.
*/
 
#include "pipe/p_compiler.h"
#include "pipe/p_format.h"
 
struct pipe_context;
struct pipe_screen;
struct pipe_surface;
 
/* Returns a handle to be used with flush_frontbuffer()/present().
*
* Query format support with screen::is_format_supported and usage
* XXX.
*/
PUBLIC struct pipe_screen *graw_create_window_and_screen( int x,
int y,
unsigned width,
unsigned height,
enum pipe_format format,
void **handle);
 
PUBLIC void graw_set_display_func( void (*func)( void ) );
PUBLIC void graw_main_loop( void );
 
PUBLIC void *graw_parse_geometry_shader( struct pipe_context *pipe,
const char *text );
 
PUBLIC void *graw_parse_vertex_shader( struct pipe_context *pipe,
const char *text );
 
PUBLIC void *graw_parse_fragment_shader( struct pipe_context *pipe,
const char *text );
 
/* Parse a single command-line option, if any. Options include:
*
* -o <filename>
*
* If an option has been successfully parsed, argi is updated
* to point just after the option and return TRUE.
*/
PUBLIC boolean graw_parse_args(int *argi, int argc, char *argv[]);
 
/* Saves surface contents to a file.
*
* If filename is NULL, the filename provided with the `-o' option
* is used. If the option has not been specified, the surface
* will not be saved.
*
* Returns TRUE if the surface has been saved.
*/
PUBLIC boolean graw_save_surface_to_file(struct pipe_context *pipe,
struct pipe_surface *surface,
const char *filename);
 
#endif
/drivers/video/Gallium/include/state_tracker/st_api.h
0,0 → 1,524
/**********************************************************
* Copyright 2010 VMware, Inc. 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, sublicense, 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 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
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* 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.
*
**********************************************************/
 
 
#ifndef _ST_API_H_
#define _ST_API_H_
 
#include "pipe/p_compiler.h"
#include "pipe/p_format.h"
 
/**
* \file API for communication between state trackers and state tracker
* managers.
*
* While both are state tackers, we use the term state tracker for rendering
* APIs such as OpenGL or OpenVG, and state tracker manager for window system
* APIs such as EGL or GLX in this file.
*
* This file defines an API to be implemented by both state trackers and state
* tracker managers.
*/
 
/**
* The supported rendering API of a state tracker.
*/
enum st_api_type {
ST_API_OPENGL,
ST_API_OPENVG,
 
ST_API_COUNT
};
 
/**
* The profile of a context.
*/
enum st_profile_type
{
ST_PROFILE_DEFAULT, /**< OpenGL compatibility profile */
ST_PROFILE_OPENGL_CORE, /**< OpenGL 3.2+ core profile */
ST_PROFILE_OPENGL_ES1, /**< OpenGL ES 1.x */
ST_PROFILE_OPENGL_ES2 /**< OpenGL ES 2.0 */
};
 
/* for profile_mask in st_api */
#define ST_PROFILE_DEFAULT_MASK (1 << ST_PROFILE_DEFAULT)
#define ST_PROFILE_OPENGL_CORE_MASK (1 << ST_PROFILE_OPENGL_CORE)
#define ST_PROFILE_OPENGL_ES1_MASK (1 << ST_PROFILE_OPENGL_ES1)
#define ST_PROFILE_OPENGL_ES2_MASK (1 << ST_PROFILE_OPENGL_ES2)
 
/**
* Optional API/state tracker features.
*/
enum st_api_feature
{
ST_API_FEATURE_MS_VISUALS /**< support for multisample visuals */
};
 
/* for feature_mask in st_api */
#define ST_API_FEATURE_MS_VISUALS_MASK (1 << ST_API_FEATURE_MS_VISUALS)
 
/**
* New context flags for GL 3.0 and beyond.
*
* Profile information (core vs. compatibilty for OpenGL 3.2+) is communicated
* through the \c st_profile_type, not through flags.
*/
#define ST_CONTEXT_FLAG_DEBUG (1 << 0)
#define ST_CONTEXT_FLAG_FORWARD_COMPATIBLE (1 << 1)
#define ST_CONTEXT_FLAG_ROBUST_ACCESS (1 << 2)
 
/**
* Reasons that context creation might fail.
*/
enum st_context_error {
ST_CONTEXT_SUCCESS = 0,
ST_CONTEXT_ERROR_NO_MEMORY,
ST_CONTEXT_ERROR_BAD_API,
ST_CONTEXT_ERROR_BAD_VERSION,
ST_CONTEXT_ERROR_BAD_FLAG,
ST_CONTEXT_ERROR_UNKNOWN_ATTRIBUTE,
ST_CONTEXT_ERROR_UNKNOWN_FLAG
};
 
/**
* Used in st_context_iface->teximage.
*/
enum st_texture_type {
ST_TEXTURE_1D,
ST_TEXTURE_2D,
ST_TEXTURE_3D,
ST_TEXTURE_RECT
};
 
/**
* Available attachments of framebuffer.
*/
enum st_attachment_type {
ST_ATTACHMENT_FRONT_LEFT,
ST_ATTACHMENT_BACK_LEFT,
ST_ATTACHMENT_FRONT_RIGHT,
ST_ATTACHMENT_BACK_RIGHT,
ST_ATTACHMENT_DEPTH_STENCIL,
ST_ATTACHMENT_ACCUM,
ST_ATTACHMENT_SAMPLE,
 
ST_ATTACHMENT_COUNT,
ST_ATTACHMENT_INVALID = -1
};
 
/* for buffer_mask in st_visual */
#define ST_ATTACHMENT_FRONT_LEFT_MASK (1 << ST_ATTACHMENT_FRONT_LEFT)
#define ST_ATTACHMENT_BACK_LEFT_MASK (1 << ST_ATTACHMENT_BACK_LEFT)
#define ST_ATTACHMENT_FRONT_RIGHT_MASK (1 << ST_ATTACHMENT_FRONT_RIGHT)
#define ST_ATTACHMENT_BACK_RIGHT_MASK (1 << ST_ATTACHMENT_BACK_RIGHT)
#define ST_ATTACHMENT_DEPTH_STENCIL_MASK (1 << ST_ATTACHMENT_DEPTH_STENCIL)
#define ST_ATTACHMENT_ACCUM_MASK (1 << ST_ATTACHMENT_ACCUM)
#define ST_ATTACHMENT_SAMPLE_MASK (1 << ST_ATTACHMENT_SAMPLE)
 
/**
* Enumerations of state tracker context resources.
*/
enum st_context_resource_type {
ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_2D,
ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_3D,
ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_POSITIVE_X,
ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_NEGATIVE_X,
ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_POSITIVE_Y,
ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_POSITIVE_Z,
ST_CONTEXT_RESOURCE_OPENGL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
ST_CONTEXT_RESOURCE_OPENGL_RENDERBUFFER,
ST_CONTEXT_RESOURCE_OPENVG_PARENT_IMAGE
};
 
/**
* Flush flags.
*/
#define ST_FLUSH_FRONT (1 << 0)
#define ST_FLUSH_END_OF_FRAME (1 << 1)
 
/**
* Value to st_manager->get_param function.
*/
enum st_manager_param {
/**
* The dri state tracker on old libGL's doesn't do the right thing
* with regards to invalidating the framebuffers.
*
* For the mesa state tracker that means that it needs to invalidate
* the framebuffer in glViewport itself.
*/
ST_MANAGER_BROKEN_INVALIDATE
};
 
/**
* The return type of st_api->get_proc_address.
*/
typedef void (*st_proc_t)(void);
 
struct pipe_context;
struct pipe_resource;
struct pipe_fence_handle;
 
/**
* Used in st_context_iface->get_resource_for_egl_image.
*/
struct st_context_resource
{
/* these fields are filled in by the caller */
enum st_context_resource_type type;
void *resource;
 
/* this is owned by the caller */
struct pipe_resource *texture;
};
 
/**
* Used in st_manager_iface->get_egl_image.
*/
struct st_egl_image
{
/* this is owned by the caller */
struct pipe_resource *texture;
 
unsigned level;
unsigned layer;
};
 
/**
* Represent the visual of a framebuffer.
*/
struct st_visual
{
/**
* Available buffers. Tested with ST_FRAMEBUFFER_*_MASK.
*/
unsigned buffer_mask;
 
/**
* Buffer formats. The formats are always set even when the buffer is
* not available.
*/
enum pipe_format color_format;
enum pipe_format depth_stencil_format;
enum pipe_format accum_format;
int samples;
 
/**
* Desired render buffer.
*/
enum st_attachment_type render_buffer;
};
 
 
/**
* Configuration options from driconf
*/
struct st_config_options
{
boolean force_glsl_extensions_warn;
boolean disable_glsl_line_continuations;
};
 
/**
* Represent the attributes of a context.
*/
struct st_context_attribs
{
/**
* The profile and minimal version to support.
*
* The valid profiles and versions are rendering API dependent. The latest
* version satisfying the request should be returned.
*/
enum st_profile_type profile;
int major, minor;
 
/** Mask of ST_CONTEXT_FLAG_x bits */
unsigned flags;
 
/**
* The visual of the framebuffers the context will be bound to.
*/
struct st_visual visual;
 
/**
* Configuration options.
*/
struct st_config_options options;
};
 
struct st_context_iface;
 
/**
* Represent a windowing system drawable.
*
* The framebuffer is implemented by the state tracker manager and
* used by the state trackers.
*
* Instead of the winsys poking into the API context to figure
* out what buffers that might be needed in the future by the API
* context, it calls into the framebuffer to get the textures.
*
* This structure along with the notify_invalid_framebuffer
* allows framebuffers to be shared between different threads
* but at the same make the API context free from thread
* synchronization primitves, with the exception of a small
* atomic flag used for notification of framebuffer dirty status.
*
* The thread synchronization is put inside the framebuffer
* and only called once the framebuffer has become dirty.
*/
struct st_framebuffer_iface
{
/**
* Atomic stamp which changes when framebuffers need to be updated.
*/
int32_t stamp;
 
/**
* Available for the state tracker manager to use.
*/
void *st_manager_private;
 
/**
* The visual of a framebuffer.
*/
const struct st_visual *visual;
 
/**
* Flush the front buffer.
*
* On some window systems, changes to the front buffers are not immediately
* visible. They need to be flushed.
*
* @att is one of the front buffer attachments.
*/
boolean (*flush_front)(struct st_context_iface *stctx,
struct st_framebuffer_iface *stfbi,
enum st_attachment_type statt);
 
/**
* The state tracker asks for the textures it needs.
*
* It should try to only ask for attachments that it currently renders
* to, thus allowing the winsys to delay the allocation of textures not
* needed. For example front buffer attachments are not needed if you
* only do back buffer rendering.
*
* The implementor of this function needs to also ensure
* thread safty as this call might be done from multiple threads.
*
* The returned textures are owned by the caller. They should be
* unreferenced when no longer used. If this function is called multiple
* times with different sets of attachments, those buffers not included in
* the last call might be destroyed. This behavior might change in the
* future.
*/
boolean (*validate)(struct st_framebuffer_iface *stfbi,
const enum st_attachment_type *statts,
unsigned count,
struct pipe_resource **out);
};
 
/**
* Represent a rendering context.
*
* This entity is created from st_api and used by the state tracker manager.
*/
struct st_context_iface
{
/**
* Available for the state tracker and the manager to use.
*/
void *st_context_private;
void *st_manager_private;
 
/**
* The CSO context associated with this context in case we need to draw
* something before swap buffers.
*/
struct cso_context *cso_context;
 
/**
* The gallium context.
*/
struct pipe_context *pipe;
 
/**
* Destroy the context.
*/
void (*destroy)(struct st_context_iface *stctxi);
 
/**
* Flush all drawing from context to the pipe also flushes the pipe.
*/
void (*flush)(struct st_context_iface *stctxi, unsigned flags,
struct pipe_fence_handle **fence);
 
/**
* Replace the texture image of a texture object at the specified level.
*
* This function is optional.
*/
boolean (*teximage)(struct st_context_iface *stctxi,
enum st_texture_type target,
int level, enum pipe_format internal_format,
struct pipe_resource *tex, boolean mipmap);
 
/**
* Used to implement glXCopyContext.
*/
void (*copy)(struct st_context_iface *stctxi,
struct st_context_iface *stsrci, unsigned mask);
 
/**
* Used to implement wglShareLists.
*/
boolean (*share)(struct st_context_iface *stctxi,
struct st_context_iface *stsrci);
 
/**
* Look up and return the info of a resource for EGLImage.
*
* This function is optional.
*/
boolean (*get_resource_for_egl_image)(struct st_context_iface *stctxi,
struct st_context_resource *stres);
};
 
 
/**
* Represent a state tracker manager.
*
* This interface is implemented by the state tracker manager. It corresponds
* to a "display" in the window system.
*/
struct st_manager
{
struct pipe_screen *screen;
 
/**
* Look up and return the info of an EGLImage.
*
* This is used to implement for example EGLImageTargetTexture2DOES.
* The GLeglImageOES agrument of that call is passed directly to this
* function call and the information needed to access this is returned
* in the given struct out.
*
* @smapi: manager owning the caller context
* @stctx: caller context
* @egl_image: EGLImage that caller recived
* @out: return struct filled out with access information.
*
* This function is optional.
*/
boolean (*get_egl_image)(struct st_manager *smapi,
void *egl_image,
struct st_egl_image *out);
 
/**
* Query an manager param.
*/
int (*get_param)(struct st_manager *smapi,
enum st_manager_param param);
};
 
/**
* Represent a rendering API such as OpenGL or OpenVG.
*
* Implemented by the state tracker and used by the state tracker manager.
*/
struct st_api
{
/**
* The name of the rendering API. This is informative.
*/
const char *name;
 
/**
* The supported rendering API.
*/
enum st_api_type api;
 
/**
* The supported profiles. Tested with ST_PROFILE_*_MASK.
*/
unsigned profile_mask;
 
/**
* The supported optional features. Tested with ST_FEATURE_*_MASK.
*/
unsigned feature_mask;
 
/**
* Destroy the API.
*/
void (*destroy)(struct st_api *stapi);
 
/**
* Return an API entry point.
*
* For GL this is the same as _glapi_get_proc_address.
*/
st_proc_t (*get_proc_address)(struct st_api *stapi, const char *procname);
 
/**
* Create a rendering context.
*/
struct st_context_iface *(*create_context)(struct st_api *stapi,
struct st_manager *smapi,
const struct st_context_attribs *attribs,
enum st_context_error *error,
struct st_context_iface *stsharei);
 
/**
* Bind the context to the calling thread with draw and read as drawables.
*
* The framebuffers might be NULL, or might have different visuals than the
* context does.
*/
boolean (*make_current)(struct st_api *stapi,
struct st_context_iface *stctxi,
struct st_framebuffer_iface *stdrawi,
struct st_framebuffer_iface *streadi);
 
/**
* Get the currently bound context in the calling thread.
*/
struct st_context_iface *(*get_current)(struct st_api *stapi);
};
 
/**
* Return true if the visual has the specified buffers.
*/
static INLINE boolean
st_visual_have_buffers(const struct st_visual *visual, unsigned mask)
{
return ((visual->buffer_mask & mask) == mask);
}
 
#endif /* _ST_API_H_ */
/drivers/video/Gallium/include/state_tracker/sw_winsys.h
0,0 → 1,145
/**************************************************************************
*
* Copyright 2007-2009 VMware, Inc.
* 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
* Software rasterizer winsys.
*/
 
 
#ifndef SW_WINSYS_H
#define SW_WINSYS_H
 
 
#include "pipe/p_compiler.h" /* for boolean */
#include "pipe/p_format.h"
 
 
#ifdef __cplusplus
extern "C" {
#endif
 
 
struct winsys_handle;
struct pipe_screen;
struct pipe_context;
struct pipe_resource;
 
 
/**
* Opaque pointer.
*/
struct sw_displaytarget;
 
 
/**
* This is the interface that sw expects any window system
* hosting it to implement.
*
* sw is for the most part a self sufficient driver. The only thing it
* does not know is how to display a surface.
*/
struct sw_winsys
{
void
(*destroy)( struct sw_winsys *ws );
 
boolean
(*is_displaytarget_format_supported)( struct sw_winsys *ws,
unsigned tex_usage,
enum pipe_format format );
/**
* Allocate storage for a render target.
*
* Often surfaces which are meant to be blitted to the front screen (i.e.,
* display targets) must be allocated with special characteristics, memory
* pools, or obtained directly from the windowing system.
*
* This callback is invoked by the pipe_screen when creating a texture marked
* with the PIPE_BIND_DISPLAY_TARGET flag to get the underlying
* storage.
*/
struct sw_displaytarget *
(*displaytarget_create)( struct sw_winsys *ws,
unsigned tex_usage,
enum pipe_format format,
unsigned width, unsigned height,
unsigned alignment,
unsigned *stride );
 
/**
* Used to implement texture_from_handle.
*/
struct sw_displaytarget *
(*displaytarget_from_handle)( struct sw_winsys *ws,
const struct pipe_resource *templat,
struct winsys_handle *whandle,
unsigned *stride );
 
/**
* Used to implement texture_get_handle.
*/
boolean
(*displaytarget_get_handle)( struct sw_winsys *ws,
struct sw_displaytarget *dt,
struct winsys_handle *whandle );
 
/**
* \param flags bitmask of PIPE_TRANSFER_x flags
*/
void *
(*displaytarget_map)( struct sw_winsys *ws,
struct sw_displaytarget *dt,
unsigned flags );
 
void
(*displaytarget_unmap)( struct sw_winsys *ws,
struct sw_displaytarget *dt );
 
/**
* @sa pipe_screen:flush_frontbuffer.
*
* This call will likely become asynchronous eventually.
*/
void
(*displaytarget_display)( struct sw_winsys *ws,
struct sw_displaytarget *dt,
void *context_private );
 
void
(*displaytarget_destroy)( struct sw_winsys *ws,
struct sw_displaytarget *dt );
};
 
 
 
#ifdef __cplusplus
}
#endif
 
#endif /* SW_WINSYS_H */
/drivers/video/Gallium/include/state_tracker/xlib_sw_winsys.h
0,0 → 1,29
#ifndef XLIB_SW_WINSYS_H
#define XLIB_SW_WINSYS_H
 
#include "state_tracker/sw_winsys.h"
#include <X11/Xlib.h>
 
 
struct pipe_screen;
struct pipe_resource;
 
/* This is what the xlib software winsys expects to find in the
* "private" field of flush_frontbuffers().
*
* Xlib-based state trackers somehow need to know this.
*/
struct xlib_drawable {
Visual *visual;
int depth;
Drawable drawable;
};
 
 
/* This is the public interface to the ws/xlib module. Why isn't it
* being defined in that directory?
*/
struct sw_winsys *xlib_create_sw_winsys( Display *display );
 
 
#endif
/drivers/video/Gallium/targets/graw_kos/graw_kos.c
0,0 → 1,110
/**************************************************************************
*
* Copyright 2010 VMware, Inc.
* 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 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
* THE COPYRIGHT HOLDERS, AUTHORS 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.
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
*
**************************************************************************/
 
#include "sw/kos_sw_winsys.h"
#include "pipe/p_screen.h"
#include "state_tracker/graw.h"
#include "target-helpers/inline_debug_helper.h"
#include "target-helpers/inline_sw_helper.h"
#include <kos32sys.h>
//#include <windows.h>
 
/*
static LRESULT CALLBACK
window_proc(HWND hWnd,
UINT uMsg,
WPARAM wParam,
LPARAM lParam)
{
switch (uMsg) {
case WM_DESTROY:
PostQuitMessage(0);
break;
 
default:
return DefWindowProc(hWnd, uMsg, wParam, lParam);
}
 
return 0;
}
*/
 
static struct {
void (* draw)(void);
} graw;
 
struct pipe_screen *
graw_create_window_and_screen(int x,
int y,
unsigned width,
unsigned height,
enum pipe_format format,
void **handle)
{
struct sw_winsys *winsys = NULL;
struct pipe_screen *screen = NULL;
 
if (format != PIPE_FORMAT_B8G8R8X8_UNORM)
goto fail;
 
winsys = kos_create_sw_winsys();
if (winsys == NULL)
goto fail;
 
screen = sw_screen_create(winsys);
if (screen == NULL)
goto fail;
 
return (screen);
 
fail:
if (screen)
screen->destroy(screen);
 
return NULL;
}
 
void
graw_set_display_func(void (* draw)(void))
{
graw.draw = draw;
}
 
void
graw_main_loop(void)
{
for (;;) {
if (graw.draw) {
graw.draw();
}
 
delay(1);
}
}
/drivers/video/Gallium/targets/graw_kos/graw_util.c
0,0 → 1,97
 
#include "pipe/p_compiler.h"
#include "pipe/p_context.h"
#include "pipe/p_shader_tokens.h"
#include "pipe/p_state.h"
#include "tgsi/tgsi_text.h"
#include "util/u_debug.h"
#include "util/u_memory.h"
#include "state_tracker/graw.h"
 
#if 0
/* Helper functions. These are the same for all graw implementations.
*/
PUBLIC void *
graw_parse_geometry_shader(struct pipe_context *pipe,
const char *text)
{
struct tgsi_token tokens[1024];
struct pipe_shader_state state;
 
if (!tgsi_text_translate(text, tokens, Elements(tokens)))
return NULL;
 
memset(&state, 0, sizeof state);
state.tokens = tokens;
return pipe->create_gs_state(pipe, &state);
}
 
PUBLIC void *
graw_parse_vertex_shader(struct pipe_context *pipe,
const char *text)
{
struct tgsi_token tokens[1024];
struct pipe_shader_state state;
 
if (!tgsi_text_translate(text, tokens, Elements(tokens)))
return NULL;
 
memset(&state, 0, sizeof state);
state.tokens = tokens;
return pipe->create_vs_state(pipe, &state);
}
 
PUBLIC void *
graw_parse_fragment_shader(struct pipe_context *pipe,
const char *text)
{
struct tgsi_token tokens[1024];
struct pipe_shader_state state;
 
if (!tgsi_text_translate(text, tokens, Elements(tokens)))
return NULL;
 
memset(&state, 0, sizeof state);
state.tokens = tokens;
return pipe->create_fs_state(pipe, &state);
}
#endif
 
static char out_filename[256] = "";
 
PUBLIC boolean
graw_parse_args(int *argi,
int argc,
char *argv[])
{
if (strcmp(argv[*argi], "-o") == 0) {
if (*argi + 1 >= argc) {
return FALSE;
}
 
strncpy(out_filename, argv[*argi + 1], sizeof(out_filename) - 1);
out_filename[sizeof(out_filename) - 1] = '\0';
*argi += 2;
return TRUE;
}
 
return FALSE;
}
 
PUBLIC boolean
graw_save_surface_to_file(struct pipe_context *pipe,
struct pipe_surface *surface,
const char *filename)
{
if (!filename || !*filename) {
filename = out_filename;
if (!filename || !*filename) {
return FALSE;
}
}
 
/* XXX: Make that working in release builds.
*/
// debug_dump_surface_bmp(pipe, filename, surface);
return TRUE;
}
/drivers/video/Gallium/winsys/sw/kos_sw_winsys.c
0,0 → 1,232
/**************************************************************************
*
* Copyright 2009 VMware, Inc.
* 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 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
* THE COPYRIGHT HOLDERS, AUTHORS 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.
*
* The above copyright notice and this permission notice (including the
* next paragraph) shall be included in all copies or substantial portions
* of the Software.
*
*
**************************************************************************/
 
/**
* @file
* GDI software rasterizer support.
*
* @author Jose Fonseca <jfonseca@vmware.com>
*/
 
#include "pipe/p_format.h"
#include "pipe/p_context.h"
#include "util/u_inlines.h"
#include "util/u_format.h"
#include "util/u_math.h"
#include "util/u_memory.h"
#include "state_tracker/sw_winsys.h"
#include <kos32sys.h>
#include "kos_sw_winsys.h"
 
 
struct kos_sw_displaytarget
{
enum pipe_format format;
unsigned width;
unsigned height;
unsigned stride;
 
unsigned size;
 
void *data;
 
// BITMAPINFO bmi;
};
 
 
/** Cast wrapper */
static INLINE struct kos_sw_displaytarget *
kos_sw_displaytarget( struct sw_displaytarget *buf )
{
return (struct kos_sw_displaytarget *)buf;
}
 
 
static boolean
kos_sw_is_displaytarget_format_supported( struct sw_winsys *ws,
unsigned tex_usage,
enum pipe_format format )
{
switch(format) {
case PIPE_FORMAT_B8G8R8X8_UNORM:
case PIPE_FORMAT_B8G8R8A8_UNORM:
return TRUE;
 
/* TODO: Support other formats possible with BMPs, as described in
* http://msdn.microsoft.com/en-us/library/dd183376(VS.85).aspx */
 
default:
return FALSE;
}
}
 
 
static void *
kos_sw_displaytarget_map(struct sw_winsys *ws,
struct sw_displaytarget *dt,
unsigned flags )
{
struct kos_sw_displaytarget *gdt = kos_sw_displaytarget(dt);
 
return gdt->data;
}
 
 
static void
kos_sw_displaytarget_unmap(struct sw_winsys *ws,
struct sw_displaytarget *dt )
{
 
}
 
 
static void
kos_sw_displaytarget_destroy(struct sw_winsys *winsys,
struct sw_displaytarget *dt)
{
struct kos_sw_displaytarget *gdt = kos_sw_displaytarget(dt);
 
user_free(gdt->data);
FREE(gdt);
}
 
 
static struct sw_displaytarget *
kos_sw_displaytarget_create(struct sw_winsys *winsys,
unsigned tex_usage,
enum pipe_format format,
unsigned width, unsigned height,
unsigned alignment,
unsigned *stride)
{
struct kos_sw_displaytarget *gdt;
unsigned cpp;
unsigned bpp;
 
gdt = CALLOC_STRUCT(kos_sw_displaytarget);
if(!gdt)
goto no_gdt;
 
gdt->format = format;
gdt->width = width;
gdt->height = height;
 
bpp = util_format_get_blocksizebits(format);
cpp = util_format_get_blocksize(format);
 
gdt->stride = align(width * cpp, alignment);
gdt->size = gdt->stride * height;
 
gdt->data = user_alloc(gdt->size);
if(!gdt->data)
goto no_data;
 
*stride = gdt->stride;
return (struct sw_displaytarget *)gdt;
 
no_data:
FREE(gdt);
no_gdt:
return NULL;
}
 
 
static struct sw_displaytarget *
kos_sw_displaytarget_from_handle(struct sw_winsys *winsys,
const struct pipe_resource *templet,
struct winsys_handle *whandle,
unsigned *stride)
{
assert(0);
return NULL;
}
 
 
static boolean
kos_sw_displaytarget_get_handle(struct sw_winsys *winsys,
struct sw_displaytarget *dt,
struct winsys_handle *whandle)
{
assert(0);
return FALSE;
}
 
 
void
kos_sw_display( struct sw_winsys *winsys,
struct sw_displaytarget *dt)
{
struct kos_sw_displaytarget *gdt = kos_sw_displaytarget(dt);
 
// StretchDIBits(hDC,
// 0, 0, gdt->width, gdt->height,
// 0, 0, gdt->width, gdt->height,
// gdt->data, &gdt->bmi, 0, SRCCOPY);
}
 
static void
kos_sw_displaytarget_display(struct sw_winsys *winsys,
struct sw_displaytarget *dt,
void *context_private)
{
/* nasty:
*/
// HDC hDC = (HDC)context_private;
 
kos_sw_display(winsys, dt);
}
 
 
static void
kos_sw_destroy(struct sw_winsys *winsys)
{
FREE(winsys);
}
 
struct sw_winsys *
kos_create_sw_winsys(void)
{
static struct sw_winsys *winsys;
 
winsys = CALLOC_STRUCT(sw_winsys);
if(!winsys)
return NULL;
 
winsys->destroy = kos_sw_destroy;
winsys->is_displaytarget_format_supported = kos_sw_is_displaytarget_format_supported;
winsys->displaytarget_create = kos_sw_displaytarget_create;
winsys->displaytarget_from_handle = kos_sw_displaytarget_from_handle;
winsys->displaytarget_get_handle = kos_sw_displaytarget_get_handle;
winsys->displaytarget_map = kos_sw_displaytarget_map;
winsys->displaytarget_unmap = kos_sw_displaytarget_unmap;
winsys->displaytarget_display = kos_sw_displaytarget_display;
winsys->displaytarget_destroy = kos_sw_displaytarget_destroy;
 
return winsys;
}
 
/drivers/video/Gallium/winsys/sw/kos_sw_winsys.h
0,0 → 1,13
#ifndef KOS_SW_WINSYS_H
#define KOS_SW_WINSYS_H
 
 
#include "pipe/p_compiler.h"
#include "state_tracker/sw_winsys.h"
 
void kos_sw_display( struct sw_winsys *winsys,
struct sw_displaytarget *dt);
 
struct sw_winsys *kos_create_sw_winsys(void);
 
#endif