/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( |
®->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 '};' |
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 '}' |
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 '}' |
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 '}' |
def is_format_hand_written(format): |
return format.layout in ('s3tc', 'rgtc', 'etc', 'subsampled', 'other') or format.colorspace == ZS |
def generate(formats): |
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"' |
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 '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 '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 '};' |
def main(): |
print '/* This file is autogenerated by u_format_srgb.py. Do not edit directly. */' |
# This will print the copyright message on the top of this file |
print CopyRight.strip() |
print '#include "u_format_srgb.h"' |
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. */' |
# This will print the copyright message on the top of this file |
print CopyRight.strip() |
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"' |
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 "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 " 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 "}" |
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 |