Subversion Repositories Kolibri OS

Compare Revisions

No changes between revisions

Regard whitespace Rev 1900 → Rev 1901

/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_atom.c
0,0 → 1,200
/**************************************************************************
*
* 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 "main/glheader.h"
#include "main/context.h"
 
#include "pipe/p_defines.h"
#include "st_context.h"
#include "st_atom.h"
#include "st_cb_bitmap.h"
#include "st_program.h"
#include "st_manager.h"
 
 
/**
* This is used to initialize st->atoms[].
*/
static const struct st_tracked_state *atoms[] =
{
&st_update_depth_stencil_alpha,
&st_update_clip,
 
&st_finalize_textures,
&st_update_fp,
&st_update_gp,
&st_update_vp,
 
&st_update_rasterizer,
&st_update_polygon_stipple,
&st_update_viewport,
&st_update_scissor,
&st_update_blend,
&st_update_sampler,
&st_update_texture,
&st_update_framebuffer,
&st_update_msaa,
&st_update_vs_constants,
&st_update_gs_constants,
&st_update_fs_constants,
&st_update_pixel_transfer
};
 
 
void st_init_atoms( struct st_context *st )
{
/* no-op */
}
 
 
void st_destroy_atoms( struct st_context *st )
{
/* no-op */
}
 
 
/***********************************************************************
*/
 
static GLboolean check_state( const struct st_state_flags *a,
const struct st_state_flags *b )
{
return ((a->mesa & b->mesa) ||
(a->st & b->st));
}
 
static void accumulate_state( struct st_state_flags *a,
const struct st_state_flags *b )
{
a->mesa |= b->mesa;
a->st |= b->st;
}
 
 
static void xor_states( struct st_state_flags *result,
const struct st_state_flags *a,
const struct st_state_flags *b )
{
result->mesa = a->mesa ^ b->mesa;
result->st = a->st ^ b->st;
}
 
 
/* Too complex to figure out, just check every time:
*/
static void check_program_state( struct st_context *st )
{
struct gl_context *ctx = st->ctx;
 
if (ctx->VertexProgram._Current != &st->vp->Base)
st->dirty.st |= ST_NEW_VERTEX_PROGRAM;
 
if (ctx->FragmentProgram._Current != &st->fp->Base)
st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM;
 
if (ctx->GeometryProgram._Current != &st->gp->Base)
st->dirty.st |= ST_NEW_GEOMETRY_PROGRAM;
}
 
 
/***********************************************************************
* Update all derived state:
*/
 
void st_validate_state( struct st_context *st )
{
struct st_state_flags *state = &st->dirty;
GLuint i;
 
/* The bitmap cache is immune to pixel unpack changes.
* Note that GLUT makes several calls to glPixelStore for each
* bitmap char it draws so this is an important check.
*/
if (state->mesa & ~_NEW_PACKUNPACK)
st_flush_bitmap_cache(st);
 
check_program_state( st );
 
st_manager_validate_framebuffers(st);
 
if (state->st == 0)
return;
 
/*printf("%s %x/%x\n", __FUNCTION__, state->mesa, state->st);*/
 
if (1) {
/* Debug version which enforces various sanity checks on the
* state flags which are generated and checked to help ensure
* state atoms are ordered correctly in the list.
*/
struct st_state_flags examined, prev;
memset(&examined, 0, sizeof(examined));
prev = *state;
 
for (i = 0; i < Elements(atoms); i++) {
const struct st_tracked_state *atom = atoms[i];
struct st_state_flags generated;
/*printf("atom %s %x/%x\n", atom->name, atom->dirty.mesa, atom->dirty.st);*/
 
if (!(atom->dirty.mesa || atom->dirty.st) ||
!atom->update) {
printf("malformed atom %s\n", atom->name);
assert(0);
}
 
if (check_state(state, &atom->dirty)) {
atoms[i]->update( st );
/*printf("after: %x\n", atom->dirty.mesa);*/
}
 
accumulate_state(&examined, &atom->dirty);
 
/* generated = (prev ^ state)
* if (examined & generated)
* fail;
*/
xor_states(&generated, &prev, state);
assert(!check_state(&examined, &generated));
prev = *state;
}
/*printf("\n");*/
 
}
else {
for (i = 0; i < Elements(atoms); i++) {
if (check_state(state, &atoms[i]->dirty))
atoms[i]->update( st );
}
}
 
memset(state, 0, sizeof(*state));
}
 
 
 
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_atom.h
0,0 → 1,72
/**************************************************************************
*
* 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.
*
**************************************************************************/
 
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
#ifndef ST_ATOM_H
#define ST_ATOM_H
 
#include "main/glheader.h"
 
struct st_context;
struct st_tracked_state;
 
void st_init_atoms( struct st_context *st );
void st_destroy_atoms( struct st_context *st );
 
 
void st_validate_state( struct st_context *st );
 
 
extern const struct st_tracked_state st_update_framebuffer;
extern const struct st_tracked_state st_update_clip;
extern const struct st_tracked_state st_update_depth_stencil_alpha;
extern const struct st_tracked_state st_update_fp;
extern const struct st_tracked_state st_update_gp;
extern const struct st_tracked_state st_update_vp;
extern const struct st_tracked_state st_update_rasterizer;
extern const struct st_tracked_state st_update_polygon_stipple;
extern const struct st_tracked_state st_update_viewport;
extern const struct st_tracked_state st_update_scissor;
extern const struct st_tracked_state st_update_blend;
extern const struct st_tracked_state st_update_msaa;
extern const struct st_tracked_state st_update_sampler;
extern const struct st_tracked_state st_update_texture;
extern const struct st_tracked_state st_finalize_textures;
extern const struct st_tracked_state st_update_fs_constants;
extern const struct st_tracked_state st_update_gs_constants;
extern const struct st_tracked_state st_update_vs_constants;
extern const struct st_tracked_state st_update_pixel_transfer;
 
 
GLuint st_compare_func_to_pipe(GLenum func);
 
#endif
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_atom_blend.c
0,0 → 1,286
/**************************************************************************
*
* 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 "st_context.h"
#include "st_atom.h"
 
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "cso_cache/cso_context.h"
 
#include "main/macros.h"
 
/**
* Convert GLenum blend tokens to pipe tokens.
* Both blend factors and blend funcs are accepted.
*/
static GLuint
translate_blend(GLenum blend)
{
switch (blend) {
/* blend functions */
case GL_FUNC_ADD:
return PIPE_BLEND_ADD;
case GL_FUNC_SUBTRACT:
return PIPE_BLEND_SUBTRACT;
case GL_FUNC_REVERSE_SUBTRACT:
return PIPE_BLEND_REVERSE_SUBTRACT;
case GL_MIN:
return PIPE_BLEND_MIN;
case GL_MAX:
return PIPE_BLEND_MAX;
 
/* blend factors */
case GL_ONE:
return PIPE_BLENDFACTOR_ONE;
case GL_SRC_COLOR:
return PIPE_BLENDFACTOR_SRC_COLOR;
case GL_SRC_ALPHA:
return PIPE_BLENDFACTOR_SRC_ALPHA;
case GL_DST_ALPHA:
return PIPE_BLENDFACTOR_DST_ALPHA;
case GL_DST_COLOR:
return PIPE_BLENDFACTOR_DST_COLOR;
case GL_SRC_ALPHA_SATURATE:
return PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE;
case GL_CONSTANT_COLOR:
return PIPE_BLENDFACTOR_CONST_COLOR;
case GL_CONSTANT_ALPHA:
return PIPE_BLENDFACTOR_CONST_ALPHA;
/*
return PIPE_BLENDFACTOR_SRC1_COLOR;
return PIPE_BLENDFACTOR_SRC1_ALPHA;
*/
case GL_ZERO:
return PIPE_BLENDFACTOR_ZERO;
case GL_ONE_MINUS_SRC_COLOR:
return PIPE_BLENDFACTOR_INV_SRC_COLOR;
case GL_ONE_MINUS_SRC_ALPHA:
return PIPE_BLENDFACTOR_INV_SRC_ALPHA;
case GL_ONE_MINUS_DST_COLOR:
return PIPE_BLENDFACTOR_INV_DST_COLOR;
case GL_ONE_MINUS_DST_ALPHA:
return PIPE_BLENDFACTOR_INV_DST_ALPHA;
case GL_ONE_MINUS_CONSTANT_COLOR:
return PIPE_BLENDFACTOR_INV_CONST_COLOR;
case GL_ONE_MINUS_CONSTANT_ALPHA:
return PIPE_BLENDFACTOR_INV_CONST_ALPHA;
/*
return PIPE_BLENDFACTOR_INV_SRC1_COLOR;
return PIPE_BLENDFACTOR_INV_SRC1_ALPHA;
*/
default:
assert("invalid GL token in translate_blend()" == NULL);
return 0;
}
}
 
 
/**
* Convert GLenum logicop tokens to pipe tokens.
*/
static GLuint
translate_logicop(GLenum logicop)
{
switch (logicop) {
case GL_CLEAR:
return PIPE_LOGICOP_CLEAR;
case GL_NOR:
return PIPE_LOGICOP_NOR;
case GL_AND_INVERTED:
return PIPE_LOGICOP_AND_INVERTED;
case GL_COPY_INVERTED:
return PIPE_LOGICOP_COPY_INVERTED;
case GL_AND_REVERSE:
return PIPE_LOGICOP_AND_REVERSE;
case GL_INVERT:
return PIPE_LOGICOP_INVERT;
case GL_XOR:
return PIPE_LOGICOP_XOR;
case GL_NAND:
return PIPE_LOGICOP_NAND;
case GL_AND:
return PIPE_LOGICOP_AND;
case GL_EQUIV:
return PIPE_LOGICOP_EQUIV;
case GL_NOOP:
return PIPE_LOGICOP_NOOP;
case GL_OR_INVERTED:
return PIPE_LOGICOP_OR_INVERTED;
case GL_COPY:
return PIPE_LOGICOP_COPY;
case GL_OR_REVERSE:
return PIPE_LOGICOP_OR_REVERSE;
case GL_OR:
return PIPE_LOGICOP_OR;
case GL_SET:
return PIPE_LOGICOP_SET;
default:
assert("invalid GL token in translate_logicop()" == NULL);
return 0;
}
}
 
/**
* Figure out if colormasks are different per rt.
*/
static GLboolean
colormask_per_rt(struct gl_context *ctx)
{
/* a bit suboptimal have to compare lots of values */
unsigned i;
for (i = 1; i < ctx->Const.MaxDrawBuffers; i++) {
if (memcmp(ctx->Color.ColorMask[0], ctx->Color.ColorMask[i], 4)) {
return GL_TRUE;
}
}
return GL_FALSE;
}
 
/**
* Figure out if blend enables are different per rt.
*/
static GLboolean
blend_per_rt(struct gl_context *ctx)
{
if (ctx->Color.BlendEnabled &&
(ctx->Color.BlendEnabled != ((1 << ctx->Const.MaxDrawBuffers) - 1))) {
return GL_TRUE;
}
return GL_FALSE;
}
 
static void
update_blend( struct st_context *st )
{
struct pipe_blend_state *blend = &st->state.blend;
unsigned num_state = 1;
unsigned i;
 
memset(blend, 0, sizeof(*blend));
 
if (blend_per_rt(st->ctx) || colormask_per_rt(st->ctx)) {
num_state = st->ctx->Const.MaxDrawBuffers;
blend->independent_blend_enable = 1;
}
/* Note it is impossible to correctly deal with EXT_blend_logic_op and
EXT_draw_buffers2/EXT_blend_equation_separate at the same time.
These combinations would require support for per-rt logicop enables
and separate alpha/rgb logicop/blend support respectively. Neither
possible in gallium nor most hardware. Assume these combinations
don't happen. */
if (st->ctx->Color.ColorLogicOpEnabled ||
(st->ctx->Color.BlendEnabled &&
st->ctx->Color.BlendEquationRGB == GL_LOGIC_OP)) {
/* logicop enabled */
blend->logicop_enable = 1;
blend->logicop_func = translate_logicop(st->ctx->Color.LogicOp);
}
else if (st->ctx->Color.BlendEnabled) {
/* blending enabled */
for (i = 0; i < num_state; i++) {
 
blend->rt[i].blend_enable = (st->ctx->Color.BlendEnabled >> i) & 0x1;
 
blend->rt[i].rgb_func = translate_blend(st->ctx->Color.BlendEquationRGB);
if (st->ctx->Color.BlendEquationRGB == GL_MIN ||
st->ctx->Color.BlendEquationRGB == GL_MAX) {
/* Min/max are special */
blend->rt[i].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
blend->rt[i].rgb_dst_factor = PIPE_BLENDFACTOR_ONE;
}
else {
blend->rt[i].rgb_src_factor = translate_blend(st->ctx->Color.BlendSrcRGB);
blend->rt[i].rgb_dst_factor = translate_blend(st->ctx->Color.BlendDstRGB);
}
 
blend->rt[i].alpha_func = translate_blend(st->ctx->Color.BlendEquationA);
if (st->ctx->Color.BlendEquationA == GL_MIN ||
st->ctx->Color.BlendEquationA == GL_MAX) {
/* Min/max are special */
blend->rt[i].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
blend->rt[i].alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
}
else {
blend->rt[i].alpha_src_factor = translate_blend(st->ctx->Color.BlendSrcA);
blend->rt[i].alpha_dst_factor = translate_blend(st->ctx->Color.BlendDstA);
}
}
}
else {
/* no blending / logicop */
}
 
/* Colormask - maybe reverse these bits? */
for (i = 0; i < num_state; i++) {
if (st->ctx->Color.ColorMask[i][0])
blend->rt[i].colormask |= PIPE_MASK_R;
if (st->ctx->Color.ColorMask[i][1])
blend->rt[i].colormask |= PIPE_MASK_G;
if (st->ctx->Color.ColorMask[i][2])
blend->rt[i].colormask |= PIPE_MASK_B;
if (st->ctx->Color.ColorMask[i][3])
blend->rt[i].colormask |= PIPE_MASK_A;
}
 
if (st->ctx->Color.DitherFlag)
blend->dither = 1;
 
if (st->ctx->Multisample.Enabled) {
/* unlike in gallium/d3d10 these operations are only performed
if msaa is enabled */
if (st->ctx->Multisample.SampleAlphaToCoverage)
blend->alpha_to_coverage = 1;
if (st->ctx->Multisample.SampleAlphaToOne)
blend->alpha_to_one = 1;
}
 
cso_set_blend(st->cso_context, blend);
 
{
struct pipe_blend_color bc;
COPY_4FV(bc.color, st->ctx->Color.BlendColor);
cso_set_blend_color(st->cso_context, &bc);
}
}
 
 
const struct st_tracked_state st_update_blend = {
"st_update_blend", /* name */
{ /* dirty */
(_NEW_COLOR | _NEW_MULTISAMPLE), /* XXX _NEW_BLEND someday? */ /* mesa */
0, /* st */
},
update_blend, /* update */
};
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_atom_clip.c
0,0 → 1,75
/**************************************************************************
*
* 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 "st_context.h"
#include "pipe/p_context.h"
#include "st_atom.h"
 
#include "cso_cache/cso_context.h"
 
 
/* Second state atom for user clip planes:
*/
static void update_clip( struct st_context *st )
{
struct pipe_clip_state clip;
GLuint i;
 
memset(&clip, 0, sizeof(clip));
 
for (i = 0; i < PIPE_MAX_CLIP_PLANES; i++) {
if (st->ctx->Transform.ClipPlanesEnabled & (1 << i)) {
memcpy(clip.ucp[clip.nr],
st->ctx->Transform._ClipUserPlane[i],
sizeof(clip.ucp[0]));
clip.nr++;
}
}
 
clip.depth_clamp = st->ctx->Transform.DepthClamp != GL_FALSE;
if (memcmp(&clip, &st->state.clip, sizeof(clip)) != 0) {
st->state.clip = clip;
cso_set_clip(st->cso_context, &clip);
}
}
 
 
const struct st_tracked_state st_update_clip = {
"st_update_clip", /* name */
{ /* dirty */
(_NEW_TRANSFORM), /* mesa */
0, /* st */
},
update_clip /* update */
};
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_atom_constbuf.c
0,0 → 1,171
/**************************************************************************
*
* 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 "main/imports.h"
#include "program/prog_parameter.h"
#include "program/prog_print.h"
 
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "util/u_inlines.h"
 
#include "st_debug.h"
#include "st_context.h"
#include "st_atom.h"
#include "st_atom_constbuf.h"
#include "st_program.h"
 
 
/**
* Pass the given program parameters to the graphics pipe as a
* constant buffer.
* \param shader_type either PIPE_SHADER_VERTEX or PIPE_SHADER_FRAGMENT
*/
void st_upload_constants( struct st_context *st,
struct gl_program_parameter_list *params,
unsigned shader_type)
{
struct pipe_context *pipe = st->pipe;
struct pipe_resource **cbuf = &st->state.constants[shader_type];
 
assert(shader_type == PIPE_SHADER_VERTEX ||
shader_type == PIPE_SHADER_FRAGMENT ||
shader_type == PIPE_SHADER_GEOMETRY);
 
/* update constants */
if (params && params->NumParameters) {
const uint paramBytes = params->NumParameters * sizeof(GLfloat) * 4;
 
/* Update the constants which come from fixed-function state, such as
* transformation matrices, fog factors, etc. The rest of the values in
* the parameters list are explicitly set by the user with glUniform,
* glProgramParameter(), etc.
*/
_mesa_load_state_parameters(st->ctx, params);
 
/* We always need to get a new buffer, to keep the drivers simple and
* avoid gratuitous rendering synchronization.
*/
pipe_resource_reference(cbuf, NULL );
*cbuf = pipe_buffer_create(pipe->screen,
PIPE_BIND_CONSTANT_BUFFER,
paramBytes );
 
if (ST_DEBUG & DEBUG_CONSTANTS) {
debug_printf("%s(shader=%d, numParams=%d, stateFlags=0x%x)\n",
__FUNCTION__, shader_type, params->NumParameters,
params->StateFlags);
_mesa_print_parameter_list(params);
}
 
/* load Mesa constants into the constant buffer */
pipe_buffer_write(st->pipe, *cbuf,
0, paramBytes,
params->ParameterValues);
 
st->pipe->set_constant_buffer(st->pipe, shader_type, 0, *cbuf);
}
else if (*cbuf) {
st->constants.tracked_state[shader_type].dirty.mesa = 0x0;
 
pipe_resource_reference(cbuf, NULL);
st->pipe->set_constant_buffer(st->pipe, shader_type, 0, NULL);
}
}
 
 
/**
* Vertex shader:
*/
static void update_vs_constants(struct st_context *st )
{
struct st_vertex_program *vp = st->vp;
struct gl_program_parameter_list *params = vp->Base.Base.Parameters;
 
st_upload_constants( st, params, PIPE_SHADER_VERTEX );
}
 
 
const struct st_tracked_state st_update_vs_constants = {
"st_update_vs_constants", /* name */
{ /* dirty */
(_NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS), /* mesa */
ST_NEW_VERTEX_PROGRAM, /* st */
},
update_vs_constants /* update */
};
 
 
 
/**
* Fragment shader:
*/
static void update_fs_constants(struct st_context *st )
{
struct st_fragment_program *fp = st->fp;
struct gl_program_parameter_list *params = fp->Base.Base.Parameters;
 
st_upload_constants( st, params, PIPE_SHADER_FRAGMENT );
}
 
 
const struct st_tracked_state st_update_fs_constants = {
"st_update_fs_constants", /* name */
{ /* dirty */
(_NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS), /* mesa */
ST_NEW_FRAGMENT_PROGRAM, /* st */
},
update_fs_constants /* update */
};
 
/* Geometry shader:
*/
static void update_gs_constants(struct st_context *st )
{
struct st_geometry_program *gp = st->gp;
struct gl_program_parameter_list *params;
 
if (gp) {
params = gp->Base.Base.Parameters;
st_upload_constants( st, params, PIPE_SHADER_GEOMETRY );
}
}
 
const struct st_tracked_state st_update_gs_constants = {
"st_update_gs_constants", /* name */
{ /* dirty */
(_NEW_PROGRAM | _NEW_PROGRAM_CONSTANTS), /* mesa */
ST_NEW_GEOMETRY_PROGRAM, /* st */
},
update_gs_constants /* update */
};
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_atom_constbuf.h
0,0 → 1,41
/**************************************************************************
*
* 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 ST_ATOM_CONSTBUF_H
#define ST_ATOM_CONSTBUF_H
 
struct gl_program_parameter_list;
struct st_context;
 
 
void st_upload_constants( struct st_context *st,
struct gl_program_parameter_list *params,
unsigned id);
 
 
#endif /* ST_ATOM_CONSTBUF_H */
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_atom_depth.c
0,0 → 1,160
/**************************************************************************
*
* 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
* Zack Rusin
*/
 
#include <assert.h>
 
#include "st_context.h"
#include "st_atom.h"
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "cso_cache/cso_context.h"
 
 
/**
* Convert an OpenGL compare mode to a pipe tokens.
*/
GLuint
st_compare_func_to_pipe(GLenum func)
{
/* Same values, just biased */
assert(PIPE_FUNC_NEVER == GL_NEVER - GL_NEVER);
assert(PIPE_FUNC_LESS == GL_LESS - GL_NEVER);
assert(PIPE_FUNC_EQUAL == GL_EQUAL - GL_NEVER);
assert(PIPE_FUNC_LEQUAL == GL_LEQUAL - GL_NEVER);
assert(PIPE_FUNC_GREATER == GL_GREATER - GL_NEVER);
assert(PIPE_FUNC_NOTEQUAL == GL_NOTEQUAL - GL_NEVER);
assert(PIPE_FUNC_GEQUAL == GL_GEQUAL - GL_NEVER);
assert(PIPE_FUNC_ALWAYS == GL_ALWAYS - GL_NEVER);
assert(func >= GL_NEVER);
assert(func <= GL_ALWAYS);
return func - GL_NEVER;
}
 
 
/**
* Convert GLenum stencil op tokens to pipe tokens.
*/
static GLuint
gl_stencil_op_to_pipe(GLenum func)
{
switch (func) {
case GL_KEEP:
return PIPE_STENCIL_OP_KEEP;
case GL_ZERO:
return PIPE_STENCIL_OP_ZERO;
case GL_REPLACE:
return PIPE_STENCIL_OP_REPLACE;
case GL_INCR:
return PIPE_STENCIL_OP_INCR;
case GL_DECR:
return PIPE_STENCIL_OP_DECR;
case GL_INCR_WRAP:
return PIPE_STENCIL_OP_INCR_WRAP;
case GL_DECR_WRAP:
return PIPE_STENCIL_OP_DECR_WRAP;
case GL_INVERT:
return PIPE_STENCIL_OP_INVERT;
default:
assert("invalid GL token in gl_stencil_op_to_pipe()" == NULL);
return 0;
}
}
 
static void
update_depth_stencil_alpha(struct st_context *st)
{
struct pipe_depth_stencil_alpha_state *dsa = &st->state.depth_stencil;
struct pipe_stencil_ref sr;
struct gl_context *ctx = st->ctx;
 
memset(dsa, 0, sizeof(*dsa));
memset(&sr, 0, sizeof(sr));
 
if (ctx->Depth.Test && ctx->DrawBuffer->Visual.depthBits > 0) {
dsa->depth.enabled = 1;
dsa->depth.writemask = ctx->Depth.Mask;
dsa->depth.func = st_compare_func_to_pipe(ctx->Depth.Func);
}
 
if (ctx->Stencil.Enabled && ctx->DrawBuffer->Visual.stencilBits > 0) {
dsa->stencil[0].enabled = 1;
dsa->stencil[0].func = st_compare_func_to_pipe(ctx->Stencil.Function[0]);
dsa->stencil[0].fail_op = gl_stencil_op_to_pipe(ctx->Stencil.FailFunc[0]);
dsa->stencil[0].zfail_op = gl_stencil_op_to_pipe(ctx->Stencil.ZFailFunc[0]);
dsa->stencil[0].zpass_op = gl_stencil_op_to_pipe(ctx->Stencil.ZPassFunc[0]);
dsa->stencil[0].valuemask = ctx->Stencil.ValueMask[0] & 0xff;
dsa->stencil[0].writemask = ctx->Stencil.WriteMask[0] & 0xff;
sr.ref_value[0] = ctx->Stencil.Ref[0] & 0xff;
 
if (ctx->Stencil._TestTwoSide) {
const GLuint back = ctx->Stencil._BackFace;
dsa->stencil[1].enabled = 1;
dsa->stencil[1].func = st_compare_func_to_pipe(ctx->Stencil.Function[back]);
dsa->stencil[1].fail_op = gl_stencil_op_to_pipe(ctx->Stencil.FailFunc[back]);
dsa->stencil[1].zfail_op = gl_stencil_op_to_pipe(ctx->Stencil.ZFailFunc[back]);
dsa->stencil[1].zpass_op = gl_stencil_op_to_pipe(ctx->Stencil.ZPassFunc[back]);
dsa->stencil[1].valuemask = ctx->Stencil.ValueMask[back] & 0xff;
dsa->stencil[1].writemask = ctx->Stencil.WriteMask[back] & 0xff;
sr.ref_value[1] = ctx->Stencil.Ref[back] & 0xff;
}
else {
/* This should be unnecessary. Drivers must not expect this to
* contain valid data, except the enabled bit
*/
dsa->stencil[1] = dsa->stencil[0];
dsa->stencil[1].enabled = 0;
sr.ref_value[1] = sr.ref_value[0];
}
}
 
if (ctx->Color.AlphaEnabled) {
dsa->alpha.enabled = 1;
dsa->alpha.func = st_compare_func_to_pipe(ctx->Color.AlphaFunc);
dsa->alpha.ref_value = ctx->Color.AlphaRef;
}
 
cso_set_depth_stencil_alpha(st->cso_context, dsa);
cso_set_stencil_ref(st->cso_context, &sr);
}
 
 
const struct st_tracked_state st_update_depth_stencil_alpha = {
"st_update_depth_stencil", /* name */
{ /* dirty */
(_NEW_DEPTH|_NEW_STENCIL|_NEW_COLOR), /* mesa */
0, /* st */
},
update_depth_stencil_alpha /* update */
};
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_atom_framebuffer.c
0,0 → 1,180
/**************************************************************************
*
* 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 "st_context.h"
#include "st_atom.h"
#include "st_cb_fbo.h"
#include "st_texture.h"
#include "pipe/p_context.h"
#include "cso_cache/cso_context.h"
#include "util/u_math.h"
#include "util/u_inlines.h"
 
 
 
/**
* When doing GL render to texture, we have to be sure that finalize_texture()
* didn't yank out the pipe_resource that we earlier created a surface for.
* Check for that here and create a new surface if needed.
*/
static void
update_renderbuffer_surface(struct st_context *st,
struct st_renderbuffer *strb)
{
struct pipe_context *pipe = st->pipe;
struct pipe_resource *resource = strb->rtt->pt;
int rtt_width = strb->Base.Width;
int rtt_height = strb->Base.Height;
 
if (!strb->surface ||
strb->surface->texture != resource ||
strb->surface->width != rtt_width ||
strb->surface->height != rtt_height) {
GLuint level;
/* find matching mipmap level size */
for (level = 0; level <= resource->last_level; level++) {
if (u_minify(resource->width0, level) == rtt_width &&
u_minify(resource->height0, level) == rtt_height) {
struct pipe_surface surf_tmpl;
memset(&surf_tmpl, 0, sizeof(surf_tmpl));
surf_tmpl.format = resource->format;
surf_tmpl.usage = PIPE_BIND_RENDER_TARGET;
surf_tmpl.u.tex.level = level;
surf_tmpl.u.tex.first_layer = strb->rtt_face + strb->rtt_slice;
surf_tmpl.u.tex.last_layer = strb->rtt_face + strb->rtt_slice;
 
pipe_surface_reference(&strb->surface, NULL);
 
strb->surface = pipe->create_surface(pipe,
resource,
&surf_tmpl);
#if 0
printf("-- alloc new surface %d x %d into tex %p\n",
strb->surface->width, strb->surface->height,
texture);
#endif
break;
}
}
}
}
 
 
/**
* Update framebuffer state (color, depth, stencil, etc. buffers)
*/
static void
update_framebuffer_state( struct st_context *st )
{
struct pipe_framebuffer_state *framebuffer = &st->state.framebuffer;
struct gl_framebuffer *fb = st->ctx->DrawBuffer;
struct st_renderbuffer *strb;
GLuint i;
 
framebuffer->width = fb->Width;
framebuffer->height = fb->Height;
 
/*printf("------ fb size %d x %d\n", fb->Width, fb->Height);*/
 
/* Examine Mesa's ctx->DrawBuffer->_ColorDrawBuffers state
* to determine which surfaces to draw to
*/
framebuffer->nr_cbufs = 0;
for (i = 0; i < fb->_NumColorDrawBuffers; i++) {
strb = st_renderbuffer(fb->_ColorDrawBuffers[i]);
 
if (strb) {
/*printf("--------- framebuffer surface rtt %p\n", strb->rtt);*/
if (strb->rtt) {
/* rendering to a GL texture, may have to update surface */
update_renderbuffer_surface(st, strb);
}
 
if (strb->surface) {
pipe_surface_reference(&framebuffer->cbufs[framebuffer->nr_cbufs],
strb->surface);
framebuffer->nr_cbufs++;
}
strb->defined = GL_TRUE; /* we'll be drawing something */
}
}
for (i = framebuffer->nr_cbufs; i < PIPE_MAX_COLOR_BUFS; i++) {
pipe_surface_reference(&framebuffer->cbufs[i], NULL);
}
 
/*
* Depth/Stencil renderbuffer/surface.
*/
strb = st_renderbuffer(fb->Attachment[BUFFER_DEPTH].Renderbuffer);
if (strb) {
strb = st_renderbuffer(strb->Base.Wrapped);
if (strb->rtt) {
/* rendering to a GL texture, may have to update surface */
update_renderbuffer_surface(st, strb);
}
pipe_surface_reference(&framebuffer->zsbuf, strb->surface);
}
else {
strb = st_renderbuffer(fb->Attachment[BUFFER_STENCIL].Renderbuffer);
if (strb) {
strb = st_renderbuffer(strb->Base.Wrapped);
assert(strb->surface);
pipe_surface_reference(&framebuffer->zsbuf, strb->surface);
}
else
pipe_surface_reference(&framebuffer->zsbuf, NULL);
}
 
#ifdef DEBUG
/* Make sure the resource binding flags were set properly */
for (i = 0; i < framebuffer->nr_cbufs; i++) {
assert(framebuffer->cbufs[i]->texture->bind & PIPE_BIND_RENDER_TARGET);
}
if (framebuffer->zsbuf) {
assert(framebuffer->zsbuf->texture->bind & PIPE_BIND_DEPTH_STENCIL);
}
#endif
 
cso_set_framebuffer(st->cso_context, framebuffer);
}
 
 
const struct st_tracked_state st_update_framebuffer = {
"st_update_framebuffer", /* name */
{ /* dirty */
_NEW_BUFFERS, /* mesa */
ST_NEW_FRAMEBUFFER, /* st */
},
update_framebuffer_state /* update */
};
 
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_atom_msaa.c
0,0 → 1,83
/**************************************************************************
*
* 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.
*
**************************************************************************/
 
 
#include "st_context.h"
#include "pipe/p_context.h"
#include "st_atom.h"
 
#include "cso_cache/cso_context.h"
 
 
/* Second state atom for user clip planes:
*/
static void update_sample_mask( struct st_context *st )
{
unsigned sample_mask = 0xffffffff;
unsigned sample_count = 1;
struct pipe_framebuffer_state *framebuffer = &st->state.framebuffer;
 
/* dependency here on bound surface (or rather, sample count) is worrying */
if (framebuffer->zsbuf)
sample_count = framebuffer->zsbuf->texture->nr_samples;
else if (framebuffer->cbufs[0])
sample_count = framebuffer->cbufs[0]->texture->nr_samples;
 
if (st->ctx->Multisample.Enabled && sample_count > 1) {
/* unlike in gallium/d3d10 the mask is only active if msaa is enabled */
if (st->ctx->Multisample.SampleCoverage) {
unsigned nr_bits;
nr_bits = st->ctx->Multisample.SampleCoverageValue * (float)sample_count;
/* there's lot of ways how to do this. We just use first few bits,
since we have no knowledge of sample positions here. When
app-supplied mask though is used too might need to be smarter.
Also, there's a interface restriction here in theory it is
encouraged this mask not be the same at each pixel. */
sample_mask = (1 << nr_bits) - 1;
if (st->ctx->Multisample.SampleCoverageInvert)
sample_mask = ~sample_mask;
}
/* TODO merge with app-supplied sample mask */
}
 
/* mask off unused bits or don't care? */
 
if (sample_mask != st->state.sample_mask) {
st->state.sample_mask = sample_mask;
cso_set_sample_mask(st->cso_context, sample_mask);
}
}
 
 
const struct st_tracked_state st_update_msaa = {
"st_update_msaa", /* name */
{ /* dirty */
(_NEW_MULTISAMPLE | _NEW_BUFFERS), /* mesa */
ST_NEW_FRAMEBUFFER, /* st */
},
update_sample_mask /* update */
};
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_atom_pixeltransfer.c
0,0 → 1,354
/**************************************************************************
*
* 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.
*
**************************************************************************/
 
/*
* Generate fragment programs to implement pixel transfer ops, such as
* scale/bias, colortable, convolution...
*
* Authors:
* Brian Paul
*/
 
#include "main/imports.h"
#include "main/image.h"
#include "main/macros.h"
#include "program/program.h"
#include "program/prog_cache.h"
#include "program/prog_instruction.h"
#include "program/prog_parameter.h"
#include "program/prog_print.h"
 
#include "st_context.h"
#include "st_format.h"
#include "st_texture.h"
 
#include "pipe/p_screen.h"
#include "pipe/p_context.h"
#include "util/u_inlines.h"
#include "util/u_pack_color.h"
 
 
struct state_key
{
GLuint scaleAndBias:1;
GLuint pixelMaps:1;
 
#if 0
GLfloat Maps[3][256][4];
int NumMaps;
GLint NumStages;
pipeline_stage Stages[STAGE_MAX];
GLboolean StagesUsed[STAGE_MAX];
GLfloat Scale1[4], Bias1[4];
GLfloat Scale2[4], Bias2[4];
#endif
};
 
static void
make_state_key(struct gl_context *ctx, struct state_key *key)
{
memset(key, 0, sizeof(*key));
 
if (ctx->Pixel.RedBias != 0.0 || ctx->Pixel.RedScale != 1.0 ||
ctx->Pixel.GreenBias != 0.0 || ctx->Pixel.GreenScale != 1.0 ||
ctx->Pixel.BlueBias != 0.0 || ctx->Pixel.BlueScale != 1.0 ||
ctx->Pixel.AlphaBias != 0.0 || ctx->Pixel.AlphaScale != 1.0) {
key->scaleAndBias = 1;
}
 
key->pixelMaps = ctx->Pixel.MapColorFlag;
}
 
 
static struct pipe_resource *
create_color_map_texture(struct gl_context *ctx)
{
struct st_context *st = st_context(ctx);
struct pipe_context *pipe = st->pipe;
struct pipe_resource *pt;
enum pipe_format format;
const uint texSize = 256; /* simple, and usually perfect */
 
/* find an RGBA texture format */
format = st_choose_format(pipe->screen, GL_RGBA,
PIPE_TEXTURE_2D, 0, PIPE_BIND_SAMPLER_VIEW);
 
/* create texture for color map/table */
pt = st_texture_create(st, PIPE_TEXTURE_2D, format, 0,
texSize, texSize, 1, PIPE_BIND_SAMPLER_VIEW);
return pt;
}
 
 
/**
* Update the pixelmap texture with the contents of the R/G/B/A pixel maps.
*/
static void
load_color_map_texture(struct gl_context *ctx, struct pipe_resource *pt)
{
struct st_context *st = st_context(ctx);
struct pipe_context *pipe = st->pipe;
struct pipe_transfer *transfer;
const GLuint rSize = ctx->PixelMaps.RtoR.Size;
const GLuint gSize = ctx->PixelMaps.GtoG.Size;
const GLuint bSize = ctx->PixelMaps.BtoB.Size;
const GLuint aSize = ctx->PixelMaps.AtoA.Size;
const uint texSize = pt->width0;
uint *dest;
uint i, j;
 
transfer = pipe_get_transfer(st_context(ctx)->pipe,
pt, 0, 0, PIPE_TRANSFER_WRITE,
0, 0, texSize, texSize);
dest = (uint *) pipe_transfer_map(pipe, transfer);
 
/* Pack four 1D maps into a 2D texture:
* R map is placed horizontally, indexed by S, in channel 0
* G map is placed vertically, indexed by T, in channel 1
* B map is placed horizontally, indexed by S, in channel 2
* A map is placed vertically, indexed by T, in channel 3
*/
for (i = 0; i < texSize; i++) {
for (j = 0; j < texSize; j++) {
union util_color uc;
int k = (i * texSize + j);
ubyte r = ctx->PixelMaps.RtoR.Map8[j * rSize / texSize];
ubyte g = ctx->PixelMaps.GtoG.Map8[i * gSize / texSize];
ubyte b = ctx->PixelMaps.BtoB.Map8[j * bSize / texSize];
ubyte a = ctx->PixelMaps.AtoA.Map8[i * aSize / texSize];
util_pack_color_ub(r, g, b, a, pt->format, &uc);
*(dest + k) = uc.ui;
}
}
 
pipe_transfer_unmap(pipe, transfer);
pipe->transfer_destroy(pipe, transfer);
}
 
 
 
#define MAX_INST 100
 
/**
* Returns a fragment program which implements the current pixel transfer ops.
*/
static struct gl_fragment_program *
get_pixel_transfer_program(struct gl_context *ctx, const struct state_key *key)
{
struct st_context *st = st_context(ctx);
struct prog_instruction inst[MAX_INST];
struct gl_program_parameter_list *params;
struct gl_fragment_program *fp;
GLuint ic = 0;
const GLuint colorTemp = 0;
 
fp = (struct gl_fragment_program *)
ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
if (!fp)
return NULL;
 
params = _mesa_new_parameter_list();
 
/*
* Get initial pixel color from the texture.
* TEX colorTemp, fragment.texcoord[0], texture[0], 2D;
*/
_mesa_init_instructions(inst + ic, 1);
inst[ic].Opcode = OPCODE_TEX;
inst[ic].DstReg.File = PROGRAM_TEMPORARY;
inst[ic].DstReg.Index = colorTemp;
inst[ic].SrcReg[0].File = PROGRAM_INPUT;
inst[ic].SrcReg[0].Index = FRAG_ATTRIB_TEX0;
inst[ic].TexSrcUnit = 0;
inst[ic].TexSrcTarget = TEXTURE_2D_INDEX;
ic++;
fp->Base.InputsRead = (1 << FRAG_ATTRIB_TEX0);
fp->Base.OutputsWritten = (1 << FRAG_RESULT_COLOR);
fp->Base.SamplersUsed = 0x1; /* sampler 0 (bit 0) is used */
 
if (key->scaleAndBias) {
static const gl_state_index scale_state[STATE_LENGTH] =
{ STATE_INTERNAL, STATE_PT_SCALE, 0, 0, 0 };
static const gl_state_index bias_state[STATE_LENGTH] =
{ STATE_INTERNAL, STATE_PT_BIAS, 0, 0, 0 };
GLfloat scale[4], bias[4];
GLint scale_p, bias_p;
 
scale[0] = ctx->Pixel.RedScale;
scale[1] = ctx->Pixel.GreenScale;
scale[2] = ctx->Pixel.BlueScale;
scale[3] = ctx->Pixel.AlphaScale;
bias[0] = ctx->Pixel.RedBias;
bias[1] = ctx->Pixel.GreenBias;
bias[2] = ctx->Pixel.BlueBias;
bias[3] = ctx->Pixel.AlphaBias;
 
scale_p = _mesa_add_state_reference(params, scale_state);
bias_p = _mesa_add_state_reference(params, bias_state);
 
/* MAD colorTemp, colorTemp, scale, bias; */
_mesa_init_instructions(inst + ic, 1);
inst[ic].Opcode = OPCODE_MAD;
inst[ic].DstReg.File = PROGRAM_TEMPORARY;
inst[ic].DstReg.Index = colorTemp;
inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
inst[ic].SrcReg[0].Index = colorTemp;
inst[ic].SrcReg[1].File = PROGRAM_STATE_VAR;
inst[ic].SrcReg[1].Index = scale_p;
inst[ic].SrcReg[2].File = PROGRAM_STATE_VAR;
inst[ic].SrcReg[2].Index = bias_p;
ic++;
}
 
if (key->pixelMaps) {
const GLuint temp = 1;
 
/* create the colormap/texture now if not already done */
if (!st->pixel_xfer.pixelmap_texture) {
st->pixel_xfer.pixelmap_texture = create_color_map_texture(ctx);
st->pixel_xfer.pixelmap_sampler_view =
st_create_texture_sampler_view(st->pipe,
st->pixel_xfer.pixelmap_texture);
}
 
/* with a little effort, we can do four pixel map look-ups with
* two TEX instructions:
*/
 
/* TEX temp.rg, colorTemp.rgba, texture[1], 2D; */
_mesa_init_instructions(inst + ic, 1);
inst[ic].Opcode = OPCODE_TEX;
inst[ic].DstReg.File = PROGRAM_TEMPORARY;
inst[ic].DstReg.Index = temp;
inst[ic].DstReg.WriteMask = WRITEMASK_XY; /* write R,G */
inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
inst[ic].SrcReg[0].Index = colorTemp;
inst[ic].TexSrcUnit = 1;
inst[ic].TexSrcTarget = TEXTURE_2D_INDEX;
ic++;
 
/* TEX temp.ba, colorTemp.baba, texture[1], 2D; */
_mesa_init_instructions(inst + ic, 1);
inst[ic].Opcode = OPCODE_TEX;
inst[ic].DstReg.File = PROGRAM_TEMPORARY;
inst[ic].DstReg.Index = temp;
inst[ic].DstReg.WriteMask = WRITEMASK_ZW; /* write B,A */
inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
inst[ic].SrcReg[0].Index = colorTemp;
inst[ic].SrcReg[0].Swizzle = MAKE_SWIZZLE4(SWIZZLE_Z, SWIZZLE_W,
SWIZZLE_Z, SWIZZLE_W);
inst[ic].TexSrcUnit = 1;
inst[ic].TexSrcTarget = TEXTURE_2D_INDEX;
ic++;
 
/* MOV colorTemp, temp; */
_mesa_init_instructions(inst + ic, 1);
inst[ic].Opcode = OPCODE_MOV;
inst[ic].DstReg.File = PROGRAM_TEMPORARY;
inst[ic].DstReg.Index = colorTemp;
inst[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
inst[ic].SrcReg[0].Index = temp;
ic++;
 
fp->Base.SamplersUsed |= (1 << 1); /* sampler 1 is used */
}
 
/* Modify last instruction's dst reg to write to result.color */
{
struct prog_instruction *last = &inst[ic - 1];
last->DstReg.File = PROGRAM_OUTPUT;
last->DstReg.Index = FRAG_RESULT_COLOR;
}
 
/* END; */
_mesa_init_instructions(inst + ic, 1);
inst[ic].Opcode = OPCODE_END;
ic++;
 
assert(ic <= MAX_INST);
 
 
fp->Base.Instructions = _mesa_alloc_instructions(ic);
if (!fp->Base.Instructions) {
_mesa_error(ctx, GL_OUT_OF_MEMORY,
"generating pixel transfer program");
return NULL;
}
 
_mesa_copy_instructions(fp->Base.Instructions, inst, ic);
fp->Base.NumInstructions = ic;
fp->Base.Parameters = params;
 
#if 0
printf("========= pixel transfer prog\n");
_mesa_print_program(&fp->Base);
_mesa_print_parameter_list(fp->Base.Parameters);
#endif
 
return fp;
}
 
 
 
/**
* Update st->pixel_xfer.program in response to new pixel-transfer state.
*/
static void
update_pixel_transfer(struct st_context *st)
{
struct gl_context *ctx = st->ctx;
struct state_key key;
struct gl_fragment_program *fp;
 
make_state_key(st->ctx, &key);
 
fp = (struct gl_fragment_program *)
_mesa_search_program_cache(st->pixel_xfer.cache, &key, sizeof(key));
if (!fp) {
fp = get_pixel_transfer_program(st->ctx, &key);
_mesa_program_cache_insert(st->ctx, st->pixel_xfer.cache,
&key, sizeof(key), &fp->Base);
}
 
if (ctx->Pixel.MapColorFlag) {
load_color_map_texture(ctx, st->pixel_xfer.pixelmap_texture);
}
st->pixel_xfer.pixelmap_enabled = ctx->Pixel.MapColorFlag;
 
st->pixel_xfer.program = (struct st_fragment_program *) fp;
}
 
 
 
const struct st_tracked_state st_update_pixel_transfer = {
"st_update_pixel_transfer", /* name */
{ /* dirty */
_NEW_PIXEL, /* mesa */
0, /* st */
},
update_pixel_transfer /* update */
};
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_atom_rasterizer.c
0,0 → 1,272
/**************************************************************************
*
* 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 "main/macros.h"
#include "st_context.h"
#include "st_atom.h"
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "cso_cache/cso_context.h"
 
 
static GLuint translate_fill( GLenum mode )
{
switch (mode) {
case GL_POINT:
return PIPE_POLYGON_MODE_POINT;
case GL_LINE:
return PIPE_POLYGON_MODE_LINE;
case GL_FILL:
return PIPE_POLYGON_MODE_FILL;
default:
assert(0);
return 0;
}
}
 
 
 
static void update_raster_state( struct st_context *st )
{
struct gl_context *ctx = st->ctx;
struct pipe_rasterizer_state *raster = &st->state.rasterizer;
const struct gl_vertex_program *vertProg = ctx->VertexProgram._Current;
const struct gl_fragment_program *fragProg = ctx->FragmentProgram._Current;
uint i;
 
memset(raster, 0, sizeof(*raster));
 
/* _NEW_POLYGON, _NEW_BUFFERS
*/
{
raster->front_ccw = (ctx->Polygon.FrontFace == GL_CCW);
 
/* XXX
* I think the intention here is that user-created framebuffer objects
* use Y=0=TOP layout instead of OpenGL's normal Y=0=bottom layout.
* Flipping Y changes CW to CCW and vice-versa.
* But this is an implementation/driver-specific artifact - remove...
*/
if (ctx->DrawBuffer && ctx->DrawBuffer->Name != 0)
raster->front_ccw ^= 1;
}
 
/* _NEW_LIGHT
*/
if (ctx->Light.ShadeModel == GL_FLAT)
raster->flatshade = 1;
 
if (ctx->Light.ProvokingVertex == GL_FIRST_VERTEX_CONVENTION_EXT)
raster->flatshade_first = 1;
 
/* _NEW_LIGHT | _NEW_PROGRAM
*
* Back-face colors can come from traditional lighting (when
* GL_LIGHT_MODEL_TWO_SIDE is set) or from vertex programs/shaders (when
* GL_VERTEX_PROGRAM_TWO_SIDE is set). Note the logic here.
*/
if (ctx->VertexProgram._Current) {
if (ctx->VertexProgram._Enabled ||
(ctx->Shader.CurrentVertexProgram &&
ctx->Shader.CurrentVertexProgram->LinkStatus)) {
/* user-defined vertex program or shader */
raster->light_twoside = ctx->VertexProgram.TwoSideEnabled;
}
else {
/* TNL-generated program */
raster->light_twoside = ctx->Light.Enabled && ctx->Light.Model.TwoSide;
}
}
else if (ctx->Light.Enabled && ctx->Light.Model.TwoSide) {
raster->light_twoside = 1;
}
 
/* _NEW_POLYGON
*/
if (ctx->Polygon.CullFlag) {
switch (ctx->Polygon.CullFaceMode) {
case GL_FRONT:
raster->cull_face = PIPE_FACE_FRONT;
break;
case GL_BACK:
raster->cull_face = PIPE_FACE_BACK;
break;
case GL_FRONT_AND_BACK:
raster->cull_face = PIPE_FACE_FRONT_AND_BACK;
break;
}
}
else {
raster->cull_face = PIPE_FACE_NONE;
}
 
/* _NEW_POLYGON
*/
{
raster->fill_front = translate_fill( ctx->Polygon.FrontMode );
raster->fill_back = translate_fill( ctx->Polygon.BackMode );
 
/* Simplify when culling is active:
*/
if (raster->cull_face & PIPE_FACE_FRONT) {
raster->fill_front = raster->fill_back;
}
if (raster->cull_face & PIPE_FACE_BACK) {
raster->fill_back = raster->fill_front;
}
}
 
/* _NEW_POLYGON
*/
if (ctx->Polygon.OffsetUnits != 0.0 ||
ctx->Polygon.OffsetFactor != 0.0) {
raster->offset_point = ctx->Polygon.OffsetPoint;
raster->offset_line = ctx->Polygon.OffsetLine;
raster->offset_tri = ctx->Polygon.OffsetFill;
}
 
if (ctx->Polygon.OffsetPoint ||
ctx->Polygon.OffsetLine ||
ctx->Polygon.OffsetFill) {
raster->offset_units = ctx->Polygon.OffsetUnits;
raster->offset_scale = ctx->Polygon.OffsetFactor;
}
 
if (ctx->Polygon.SmoothFlag)
raster->poly_smooth = 1;
 
if (ctx->Polygon.StippleFlag)
raster->poly_stipple_enable = 1;
 
/* _NEW_POINT
*/
raster->point_size = ctx->Point.Size;
 
if (!ctx->Point.PointSprite && ctx->Point.SmoothFlag)
raster->point_smooth = 1;
 
/* _NEW_POINT | _NEW_PROGRAM
*/
if (ctx->Point.PointSprite) {
/* origin */
if ((ctx->Point.SpriteOrigin == GL_UPPER_LEFT) ^
(st_fb_orientation(ctx->DrawBuffer) == Y_0_BOTTOM))
raster->sprite_coord_mode = PIPE_SPRITE_COORD_UPPER_LEFT;
else
raster->sprite_coord_mode = PIPE_SPRITE_COORD_LOWER_LEFT;
 
/* Coord replacement flags. If bit 'k' is set that means
* that we need to replace GENERIC[k] attrib with an automatically
* computed texture coord.
*/
for (i = 0; i < MAX_TEXTURE_COORD_UNITS; i++) {
if (ctx->Point.CoordReplace[i]) {
raster->sprite_coord_enable |= 1 << i;
}
}
if (fragProg->Base.InputsRead & FRAG_BIT_PNTC) {
raster->sprite_coord_enable |=
1 << (FRAG_ATTRIB_PNTC - FRAG_ATTRIB_TEX0);
}
 
raster->point_quad_rasterization = 1;
}
 
/* ST_NEW_VERTEX_PROGRAM
*/
if (vertProg) {
if (vertProg->Base.Id == 0) {
if (vertProg->Base.OutputsWritten & BITFIELD64_BIT(VERT_RESULT_PSIZ)) {
/* generated program which emits point size */
raster->point_size_per_vertex = TRUE;
}
}
else if (ctx->VertexProgram.PointSizeEnabled) {
/* user-defined program and GL_VERTEX_PROGRAM_POINT_SIZE set */
raster->point_size_per_vertex = ctx->VertexProgram.PointSizeEnabled;
}
}
if (!raster->point_size_per_vertex) {
/* clamp size now */
raster->point_size = CLAMP(ctx->Point.Size,
ctx->Point.MinSize,
ctx->Point.MaxSize);
}
 
/* _NEW_LINE
*/
raster->line_smooth = ctx->Line.SmoothFlag;
if (ctx->Line.SmoothFlag) {
raster->line_width = CLAMP(ctx->Line.Width,
ctx->Const.MinLineWidthAA,
ctx->Const.MaxLineWidthAA);
}
else {
raster->line_width = CLAMP(ctx->Line.Width,
ctx->Const.MinLineWidth,
ctx->Const.MaxLineWidth);
}
 
raster->line_stipple_enable = ctx->Line.StippleFlag;
raster->line_stipple_pattern = ctx->Line.StipplePattern;
/* GL stipple factor is in [1,256], remap to [0, 255] here */
raster->line_stipple_factor = ctx->Line.StippleFactor - 1;
 
/* _NEW_MULTISAMPLE */
if (ctx->Multisample._Enabled || st->force_msaa)
raster->multisample = 1;
 
/* _NEW_SCISSOR */
if (ctx->Scissor.Enabled)
raster->scissor = 1;
 
raster->gl_rasterization_rules = 1;
 
cso_set_rasterizer(st->cso_context, raster);
}
 
const struct st_tracked_state st_update_rasterizer = {
"st_update_rasterizer", /* name */
{
(_NEW_BUFFERS |
_NEW_LIGHT |
_NEW_LINE |
_NEW_MULTISAMPLE |
_NEW_POINT |
_NEW_POLYGON |
_NEW_PROGRAM |
_NEW_SCISSOR), /* mesa state dependencies*/
ST_NEW_VERTEX_PROGRAM, /* state tracker dependencies */
},
update_raster_state /* update function */
};
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_atom_sampler.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>
* Brian Paul
*/
 
#include "main/macros.h"
 
#include "st_context.h"
#include "st_cb_texture.h"
#include "st_format.h"
#include "st_atom.h"
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
 
#include "cso_cache/cso_context.h"
 
 
/**
* Convert GLenum texcoord wrap tokens to pipe tokens.
*/
static GLuint
gl_wrap_xlate(GLenum wrap)
{
switch (wrap) {
case GL_REPEAT:
return PIPE_TEX_WRAP_REPEAT;
case GL_CLAMP:
return PIPE_TEX_WRAP_CLAMP;
case GL_CLAMP_TO_EDGE:
return PIPE_TEX_WRAP_CLAMP_TO_EDGE;
case GL_CLAMP_TO_BORDER:
return PIPE_TEX_WRAP_CLAMP_TO_BORDER;
case GL_MIRRORED_REPEAT:
return PIPE_TEX_WRAP_MIRROR_REPEAT;
case GL_MIRROR_CLAMP_EXT:
return PIPE_TEX_WRAP_MIRROR_CLAMP;
case GL_MIRROR_CLAMP_TO_EDGE_EXT:
return PIPE_TEX_WRAP_MIRROR_CLAMP_TO_EDGE;
case GL_MIRROR_CLAMP_TO_BORDER_EXT:
return PIPE_TEX_WRAP_MIRROR_CLAMP_TO_BORDER;
default:
assert(0);
return 0;
}
}
 
 
static GLuint
gl_filter_to_mip_filter(GLenum filter)
{
switch (filter) {
case GL_NEAREST:
case GL_LINEAR:
return PIPE_TEX_MIPFILTER_NONE;
 
case GL_NEAREST_MIPMAP_NEAREST:
case GL_LINEAR_MIPMAP_NEAREST:
return PIPE_TEX_MIPFILTER_NEAREST;
 
case GL_NEAREST_MIPMAP_LINEAR:
case GL_LINEAR_MIPMAP_LINEAR:
return PIPE_TEX_MIPFILTER_LINEAR;
 
default:
assert(0);
return PIPE_TEX_MIPFILTER_NONE;
}
}
 
 
static GLuint
gl_filter_to_img_filter(GLenum filter)
{
switch (filter) {
case GL_NEAREST:
case GL_NEAREST_MIPMAP_NEAREST:
case GL_NEAREST_MIPMAP_LINEAR:
return PIPE_TEX_FILTER_NEAREST;
 
case GL_LINEAR:
case GL_LINEAR_MIPMAP_NEAREST:
case GL_LINEAR_MIPMAP_LINEAR:
return PIPE_TEX_FILTER_LINEAR;
 
default:
assert(0);
return PIPE_TEX_FILTER_NEAREST;
}
}
 
 
static void
update_samplers(struct st_context *st)
{
struct gl_vertex_program *vprog = st->ctx->VertexProgram._Current;
struct gl_fragment_program *fprog = st->ctx->FragmentProgram._Current;
const GLbitfield samplersUsed = (vprog->Base.SamplersUsed |
fprog->Base.SamplersUsed);
GLuint su;
 
st->state.num_samplers = 0;
 
/* loop over sampler units (aka tex image units) */
for (su = 0; su < st->ctx->Const.MaxTextureImageUnits; su++) {
struct pipe_sampler_state *sampler = st->state.samplers + su;
 
memset(sampler, 0, sizeof(*sampler));
 
if (samplersUsed & (1 << su)) {
struct gl_texture_object *texobj;
struct gl_texture_image *teximg;
GLuint texUnit;
 
if (fprog->Base.SamplersUsed & (1 << su))
texUnit = fprog->Base.SamplerUnits[su];
else
texUnit = vprog->Base.SamplerUnits[su];
 
texobj = st->ctx->Texture.Unit[texUnit]._Current;
if (!texobj) {
texobj = st_get_default_texture(st);
}
 
teximg = texobj->Image[0][texobj->BaseLevel];
 
sampler->wrap_s = gl_wrap_xlate(texobj->WrapS);
sampler->wrap_t = gl_wrap_xlate(texobj->WrapT);
sampler->wrap_r = gl_wrap_xlate(texobj->WrapR);
 
sampler->min_img_filter = gl_filter_to_img_filter(texobj->MinFilter);
sampler->min_mip_filter = gl_filter_to_mip_filter(texobj->MinFilter);
sampler->mag_img_filter = gl_filter_to_img_filter(texobj->MagFilter);
 
if (texobj->Target != GL_TEXTURE_RECTANGLE_ARB)
sampler->normalized_coords = 1;
 
sampler->lod_bias = st->ctx->Texture.Unit[su].LodBias;
 
sampler->min_lod = texobj->BaseLevel + texobj->MinLod;
if (sampler->min_lod < texobj->BaseLevel)
sampler->min_lod = texobj->BaseLevel;
 
sampler->max_lod = MIN2((GLfloat) texobj->MaxLevel,
(texobj->MaxLod + texobj->BaseLevel));
if (sampler->max_lod < sampler->min_lod) {
/* The GL spec doesn't seem to specify what to do in this case.
* Swap the values.
*/
float tmp = sampler->max_lod;
sampler->max_lod = sampler->min_lod;
sampler->min_lod = tmp;
assert(sampler->min_lod <= sampler->max_lod);
}
 
st_translate_color(texobj->BorderColor.f,
teximg ? teximg->_BaseFormat : GL_RGBA,
sampler->border_color);
 
sampler->max_anisotropy = (texobj->MaxAnisotropy == 1.0 ? 0 : (GLuint)texobj->MaxAnisotropy);
 
/* only care about ARB_shadow, not SGI shadow */
if (texobj->CompareMode == GL_COMPARE_R_TO_TEXTURE) {
sampler->compare_mode = PIPE_TEX_COMPARE_R_TO_TEXTURE;
sampler->compare_func
= st_compare_func_to_pipe(texobj->CompareFunc);
}
 
st->state.num_samplers = su + 1;
 
/*printf("%s su=%u non-null\n", __FUNCTION__, su);*/
cso_single_sampler(st->cso_context, su, sampler);
if (su < st->ctx->Const.MaxVertexTextureImageUnits) {
cso_single_vertex_sampler(st->cso_context, su, sampler);
}
}
else {
/*printf("%s su=%u null\n", __FUNCTION__, su);*/
cso_single_sampler(st->cso_context, su, NULL);
if (su < st->ctx->Const.MaxVertexTextureImageUnits) {
cso_single_vertex_sampler(st->cso_context, su, NULL);
}
}
}
 
cso_single_sampler_done(st->cso_context);
if (st->ctx->Const.MaxVertexTextureImageUnits > 0) {
cso_single_vertex_sampler_done(st->cso_context);
}
}
 
 
const struct st_tracked_state st_update_sampler = {
"st_update_sampler", /* name */
{ /* dirty */
_NEW_TEXTURE, /* mesa */
0, /* st */
},
update_samplers /* update */
};
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_atom_scissor.c
0,0 → 1,100
/**************************************************************************
*
* 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 "main/macros.h"
#include "st_context.h"
#include "pipe/p_context.h"
#include "st_atom.h"
 
 
/**
* Scissor depends on the scissor box, and the framebuffer dimensions.
*/
static void
update_scissor( struct st_context *st )
{
struct pipe_scissor_state scissor;
const struct gl_framebuffer *fb = st->ctx->DrawBuffer;
GLint miny, maxy;
 
scissor.minx = 0;
scissor.miny = 0;
scissor.maxx = fb->Width;
scissor.maxy = fb->Height;
 
if (st->ctx->Scissor.Enabled) {
/* need to be careful here with xmax or ymax < 0 */
GLint xmax = MAX2(0, st->ctx->Scissor.X + st->ctx->Scissor.Width);
GLint ymax = MAX2(0, st->ctx->Scissor.Y + st->ctx->Scissor.Height);
 
if (st->ctx->Scissor.X > (GLint)scissor.minx)
scissor.minx = st->ctx->Scissor.X;
if (st->ctx->Scissor.Y > (GLint)scissor.miny)
scissor.miny = st->ctx->Scissor.Y;
 
if (xmax < (GLint) scissor.maxx)
scissor.maxx = xmax;
if (ymax < (GLint) scissor.maxy)
scissor.maxy = ymax;
 
/* check for null space */
if (scissor.minx >= scissor.maxx || scissor.miny >= scissor.maxy)
scissor.minx = scissor.miny = scissor.maxx = scissor.maxy = 0;
}
 
/* Now invert Y if needed.
* Gallium drivers use the convention Y=0=top for surfaces.
*/
if (st_fb_orientation(fb) == Y_0_TOP) {
miny = fb->Height - scissor.maxy;
maxy = fb->Height - scissor.miny;
scissor.miny = miny;
scissor.maxy = maxy;
}
 
if (memcmp(&scissor, &st->state.scissor, sizeof(scissor)) != 0) {
/* state has changed */
st->state.scissor = scissor; /* struct copy */
st->pipe->set_scissor_state(st->pipe, &scissor); /* activate */
}
}
 
 
const struct st_tracked_state st_update_scissor = {
"st_update_scissor", /* name */
{ /* dirty */
(_NEW_SCISSOR | _NEW_BUFFERS), /* mesa */
0, /* st */
},
update_scissor /* update */
};
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_atom_shader.c
0,0 → 1,265
/**************************************************************************
*
* 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.
*
**************************************************************************/
 
/**
* State validation for vertex/fragment shaders.
* Note that we have to delay most vertex/fragment shader translation
* until rendering time since the linkage between the vertex outputs and
* fragment inputs can vary depending on the pairing of shaders.
*
* Authors:
* Brian Paul
*/
 
#include "main/imports.h"
#include "main/mtypes.h"
#include "program/program.h"
 
#include "pipe/p_context.h"
 
#include "util/u_simple_shaders.h"
 
#include "cso_cache/cso_context.h"
 
#include "st_context.h"
#include "st_atom.h"
#include "st_program.h"
 
 
 
/**
* Translate fragment program if needed.
*/
static void
translate_fp(struct st_context *st,
struct st_fragment_program *stfp)
{
if (!stfp->tgsi.tokens) {
assert(stfp->Base.Base.NumInstructions > 0);
 
st_translate_fragment_program(st, stfp);
}
}
 
/*
* Translate geometry program if needed.
*/
static void
translate_gp(struct st_context *st,
struct st_geometry_program *stgp)
{
if (!stgp->tgsi.tokens) {
assert(stgp->Base.Base.NumInstructions > 1);
 
st_translate_geometry_program(st, stgp);
}
}
 
/**
* Find a translated vertex program that corresponds to stvp and
* has outputs matched to stfp's inputs.
* This performs vertex and fragment translation (to TGSI) when needed.
*/
static struct st_vp_varient *
find_translated_vp(struct st_context *st,
struct st_vertex_program *stvp )
{
struct st_vp_varient *vpv;
struct st_vp_varient_key key;
 
/* Nothing in our key yet. This will change:
*/
memset(&key, 0, sizeof key);
 
/* When this is true, we will add an extra input to the vertex
* shader translation (for edgeflags), an extra output with
* edgeflag semantics, and extend the vertex shader to pass through
* the input to the output. We'll need to use similar logic to set
* up the extra vertex_element input for edgeflags.
* _NEW_POLYGON, ST_NEW_EDGEFLAGS_DATA
*/
key.passthrough_edgeflags = (st->vertdata_edgeflags && (
st->ctx->Polygon.FrontMode != GL_FILL ||
st->ctx->Polygon.BackMode != GL_FILL));
 
 
/* Do we need to throw away old translations after a change in the
* GL program string?
*/
if (stvp->serialNo != stvp->lastSerialNo) {
/* These may have changed if the program string changed.
*/
st_prepare_vertex_program( st, stvp );
 
/* We are now up-to-date:
*/
stvp->lastSerialNo = stvp->serialNo;
}
/* See if we've got a translated vertex program whose outputs match
* the fragment program's inputs.
*/
for (vpv = stvp->varients; vpv; vpv = vpv->next) {
if (memcmp(&vpv->key, &key, sizeof key) == 0) {
break;
}
}
 
/* No? Perform new translation here. */
if (!vpv) {
vpv = st_translate_vertex_program(st, stvp, &key);
if (!vpv)
return NULL;
vpv->next = stvp->varients;
stvp->varients = vpv;
}
 
return vpv;
}
 
 
/**
* Return pointer to a pass-through fragment shader.
* This shader is used when a texture is missing/incomplete.
*/
static void *
get_passthrough_fs(struct st_context *st)
{
if (!st->passthrough_fs) {
st->passthrough_fs =
util_make_fragment_passthrough_shader(st->pipe);
}
 
return st->passthrough_fs;
}
 
 
/**
* Update fragment program state/atom. This involves translating the
* Mesa fragment program into a gallium fragment program and binding it.
*/
static void
update_fp( struct st_context *st )
{
struct st_fragment_program *stfp;
 
assert(st->ctx->FragmentProgram._Current);
stfp = st_fragment_program(st->ctx->FragmentProgram._Current);
assert(stfp->Base.Base.Target == GL_FRAGMENT_PROGRAM_ARB);
 
translate_fp(st, stfp);
 
st_reference_fragprog(st, &st->fp, stfp);
 
if (st->missing_textures) {
/* use a pass-through frag shader that uses no textures */
void *fs = get_passthrough_fs(st);
cso_set_fragment_shader_handle(st->cso_context, fs);
}
else {
cso_set_fragment_shader_handle(st->cso_context, stfp->driver_shader);
}
}
 
 
const struct st_tracked_state st_update_fp = {
"st_update_fp", /* name */
{ /* dirty */
0, /* mesa */
ST_NEW_FRAGMENT_PROGRAM /* st */
},
update_fp /* update */
};
 
 
 
/**
* Update vertex program state/atom. This involves translating the
* Mesa vertex program into a gallium fragment program and binding it.
*/
static void
update_vp( struct st_context *st )
{
struct st_vertex_program *stvp;
 
/* find active shader and params -- Should be covered by
* ST_NEW_VERTEX_PROGRAM
*/
assert(st->ctx->VertexProgram._Current);
stvp = st_vertex_program(st->ctx->VertexProgram._Current);
assert(stvp->Base.Base.Target == GL_VERTEX_PROGRAM_ARB);
 
st->vp_varient = find_translated_vp(st, stvp);
 
st_reference_vertprog(st, &st->vp, stvp);
 
cso_set_vertex_shader_handle(st->cso_context,
st->vp_varient->driver_shader);
 
st->vertex_result_to_slot = stvp->result_to_output;
}
 
 
const struct st_tracked_state st_update_vp = {
"st_update_vp", /* name */
{ /* dirty */
_NEW_POLYGON, /* mesa */
ST_NEW_VERTEX_PROGRAM | ST_NEW_EDGEFLAGS_DATA /* st */
},
update_vp /* update */
};
 
static void
update_gp( struct st_context *st )
{
 
struct st_geometry_program *stgp;
 
if (!st->ctx->GeometryProgram._Current) {
cso_set_geometry_shader_handle(st->cso_context, NULL);
return;
}
 
stgp = st_geometry_program(st->ctx->GeometryProgram._Current);
assert(stgp->Base.Base.Target == MESA_GEOMETRY_PROGRAM);
 
translate_gp(st, stgp);
 
st_reference_geomprog(st, &st->gp, stgp);
 
cso_set_geometry_shader_handle(st->cso_context, stgp->driver_shader);
}
 
const struct st_tracked_state st_update_gp = {
"st_update_gp", /* name */
{ /* dirty */
0, /* mesa */
ST_NEW_GEOMETRY_PROGRAM /* st */
},
update_gp /* update */
};
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_atom_shader.h
0,0 → 1,41
/**************************************************************************
*
* 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 ST_ATOM_SHADER_H
#define ST_ATOM_SHADER_H
 
 
struct st_context;
struct translated_vertex_program;
 
extern void
st_free_translated_vertex_programs(struct st_context *st,
struct translated_vertex_program *xvp);
 
 
#endif /* ST_ATOM_SHADER_H */
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_atom_stipple.c
0,0 → 1,93
/**************************************************************************
*
* 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 stipple state
*
* Authors:
* Brian Paul
*/
 
#include <assert.h>
 
#include "st_context.h"
#include "st_atom.h"
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
 
 
/**
* OpenGL's polygon stipple is indexed with window coordinates in which
* the origin (0,0) is the lower-left corner of the window.
* With Gallium, the origin is the upper-left corner of the window.
* To convert GL's polygon stipple to what gallium expects we need to
* invert the pattern vertically and rotate the stipple rows according
* to the window height.
*/
static void
invert_stipple(GLuint dest[32], const GLuint src[32], GLuint winHeight)
{
GLuint i;
 
for (i = 0; i < 32; i++) {
dest[i] = src[(winHeight - 1 - i) & 0x1f];
}
}
 
 
 
static void
update_stipple( struct st_context *st )
{
const GLuint sz = sizeof(st->state.poly_stipple);
assert(sz == sizeof(st->ctx->PolygonStipple));
 
if (memcmp(st->state.poly_stipple, st->ctx->PolygonStipple, sz)) {
/* state has changed */
struct pipe_poly_stipple newStipple;
 
memcpy(st->state.poly_stipple, st->ctx->PolygonStipple, sz);
 
invert_stipple(newStipple.stipple, st->ctx->PolygonStipple,
st->ctx->DrawBuffer->Height);
 
st->pipe->set_polygon_stipple(st->pipe, &newStipple);
}
}
 
 
/** Update the stipple when the pattern or window height changes */
const struct st_tracked_state st_update_polygon_stipple = {
"st_update_polygon_stipple", /* name */
{ /* dirty */
(_NEW_POLYGONSTIPPLE |
_NEW_BUFFERS), /* mesa */
0, /* st */
},
update_stipple /* update */
};
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_atom_texture.c
0,0 → 1,308
/**************************************************************************
*
* 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 "main/macros.h"
#include "program/prog_instruction.h"
 
#include "st_context.h"
#include "st_atom.h"
#include "st_texture.h"
#include "st_format.h"
#include "st_cb_texture.h"
#include "pipe/p_context.h"
#include "util/u_format.h"
#include "util/u_inlines.h"
#include "cso_cache/cso_context.h"
 
/**
* Combine depth texture mode with "swizzle" so that depth mode swizzling
* takes place before texture swizzling, and return the resulting swizzle.
* If the format is not a depth format, return "swizzle" unchanged.
*
* \param format PIPE_FORMAT_*.
* \param swizzle Texture swizzle, a bitmask computed using MAKE_SWIZZLE4.
* \param depthmode One of GL_LUMINANCE, GL_INTENSITY, GL_ALPHA, GL_RED.
*/
static GLuint apply_depthmode(enum pipe_format format,
GLuint swizzle, GLenum depthmode)
{
const struct util_format_description *desc =
util_format_description(format);
unsigned char swiz[4];
unsigned i;
 
if (desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS ||
desc->swizzle[0] == UTIL_FORMAT_SWIZZLE_NONE) {
/* Not a depth format. */
return swizzle;
}
 
for (i = 0; i < 4; i++)
swiz[i] = GET_SWZ(swizzle, i);
 
switch (depthmode) {
case GL_LUMINANCE:
/* Rewrite reads from W to ONE, and reads from XYZ to XXX. */
for (i = 0; i < 4; i++)
if (swiz[i] == SWIZZLE_W)
swiz[i] = SWIZZLE_ONE;
else if (swiz[i] < SWIZZLE_W)
swiz[i] = SWIZZLE_X;
break;
 
case GL_INTENSITY:
/* Rewrite reads from XYZW to XXXX. */
for (i = 0; i < 4; i++)
if (swiz[i] <= SWIZZLE_W)
swiz[i] = SWIZZLE_X;
break;
 
case GL_ALPHA:
/* Rewrite reads from W to X, and reads from XYZ to 000. */
for (i = 0; i < 4; i++)
if (swiz[i] == SWIZZLE_W)
swiz[i] = SWIZZLE_X;
else if (swiz[i] < SWIZZLE_W)
swiz[i] = SWIZZLE_ZERO;
break;
case GL_RED:
/* Rewrite reads W to 1, XYZ to X00 */
for (i = 0; i < 4; i++)
if (swiz[i] == SWIZZLE_W)
swiz[i] = SWIZZLE_ONE;
else if (swiz[i] == SWIZZLE_Y || swiz[i] == SWIZZLE_Z)
swiz[i] = SWIZZLE_ZERO;
break;
}
 
return MAKE_SWIZZLE4(swiz[0], swiz[1], swiz[2], swiz[3]);
}
 
/**
* Return TRUE if the swizzling described by "swizzle" and
* "depthmode" (for depth textures only) is different from the swizzling
* set in the given sampler view.
*
* \param sv A sampler view.
* \param swizzle Texture swizzle, a bitmask computed using MAKE_SWIZZLE4.
* \param depthmode One of GL_LUMINANCE, GL_INTENSITY, GL_ALPHA.
*/
static boolean check_sampler_swizzle(struct pipe_sampler_view *sv,
GLuint swizzle, GLenum depthmode)
{
swizzle = apply_depthmode(sv->texture->format, swizzle, depthmode);
 
if ((sv->swizzle_r != GET_SWZ(swizzle, 0)) ||
(sv->swizzle_g != GET_SWZ(swizzle, 1)) ||
(sv->swizzle_b != GET_SWZ(swizzle, 2)) ||
(sv->swizzle_a != GET_SWZ(swizzle, 3)))
return true;
return false;
}
 
static INLINE struct pipe_sampler_view *
st_create_texture_sampler_view_from_stobj(struct pipe_context *pipe,
struct st_texture_object *stObj,
enum pipe_format format)
{
struct pipe_sampler_view templ;
GLuint swizzle = apply_depthmode(stObj->pt->format,
stObj->base._Swizzle,
stObj->base.DepthMode);
 
u_sampler_view_default_template(&templ,
stObj->pt,
format);
 
if (swizzle != SWIZZLE_NOOP) {
templ.swizzle_r = GET_SWZ(swizzle, 0);
templ.swizzle_g = GET_SWZ(swizzle, 1);
templ.swizzle_b = GET_SWZ(swizzle, 2);
templ.swizzle_a = GET_SWZ(swizzle, 3);
}
 
return pipe->create_sampler_view(pipe, stObj->pt, &templ);
}
 
 
static INLINE struct pipe_sampler_view *
st_get_texture_sampler_view_from_stobj(struct st_texture_object *stObj,
struct pipe_context *pipe,
enum pipe_format format)
 
{
if (!stObj || !stObj->pt) {
return NULL;
}
 
if (!stObj->sampler_view) {
stObj->sampler_view = st_create_texture_sampler_view_from_stobj(pipe, stObj, format);
}
 
return stObj->sampler_view;
}
 
static void
update_textures(struct st_context *st)
{
struct pipe_context *pipe = st->pipe;
struct gl_vertex_program *vprog = st->ctx->VertexProgram._Current;
struct gl_fragment_program *fprog = st->ctx->FragmentProgram._Current;
const GLbitfield samplersUsed = (vprog->Base.SamplersUsed |
fprog->Base.SamplersUsed);
GLuint su;
 
st->state.num_textures = 0;
 
/* loop over sampler units (aka tex image units) */
for (su = 0; su < st->ctx->Const.MaxTextureImageUnits; su++) {
struct pipe_sampler_view *sampler_view = NULL;
enum pipe_format st_view_format;
if (samplersUsed & (1 << su)) {
struct gl_texture_object *texObj;
struct st_texture_object *stObj;
GLboolean retval;
GLuint texUnit;
 
if (fprog->Base.SamplersUsed & (1 << su))
texUnit = fprog->Base.SamplerUnits[su];
else
texUnit = vprog->Base.SamplerUnits[su];
 
texObj = st->ctx->Texture.Unit[texUnit]._Current;
 
if (!texObj) {
texObj = st_get_default_texture(st);
}
stObj = st_texture_object(texObj);
 
retval = st_finalize_texture(st->ctx, st->pipe, texObj);
if (!retval) {
/* out of mem */
continue;
}
 
st_view_format = stObj->pt->format;
{
struct st_texture_image *firstImage;
enum pipe_format firstImageFormat;
firstImage = st_texture_image(stObj->base.Image[0][stObj->base.BaseLevel]);
 
firstImageFormat = st_mesa_format_to_pipe_format(firstImage->base.TexFormat);
if (firstImageFormat != stObj->pt->format)
st_view_format = firstImageFormat;
 
}
st->state.num_textures = su + 1;
 
/* if sampler view has changed dereference it */
if (stObj->sampler_view)
if (check_sampler_swizzle(stObj->sampler_view,
stObj->base._Swizzle,
stObj->base.DepthMode) ||
(st_view_format != stObj->sampler_view->format))
pipe_sampler_view_reference(&stObj->sampler_view, NULL);
 
sampler_view = st_get_texture_sampler_view_from_stobj(stObj, pipe, st_view_format);
}
pipe_sampler_view_reference(&st->state.sampler_views[su], sampler_view);
}
 
cso_set_fragment_sampler_views(st->cso_context,
st->state.num_textures,
st->state.sampler_views);
if (st->ctx->Const.MaxVertexTextureImageUnits > 0) {
cso_set_vertex_sampler_views(st->cso_context,
MIN2(st->state.num_textures,
st->ctx->Const.MaxVertexTextureImageUnits),
st->state.sampler_views);
}
}
 
 
const struct st_tracked_state st_update_texture = {
"st_update_texture", /* name */
{ /* dirty */
_NEW_TEXTURE, /* mesa */
ST_NEW_FRAGMENT_PROGRAM, /* st */
},
update_textures /* update */
};
 
 
 
 
static void
finalize_textures(struct st_context *st)
{
struct gl_fragment_program *fprog = st->ctx->FragmentProgram._Current;
const GLboolean prev_missing_textures = st->missing_textures;
GLuint su;
 
st->missing_textures = GL_FALSE;
 
for (su = 0; su < st->ctx->Const.MaxTextureCoordUnits; su++) {
if (fprog->Base.SamplersUsed & (1 << su)) {
const GLuint texUnit = fprog->Base.SamplerUnits[su];
struct gl_texture_object *texObj
= st->ctx->Texture.Unit[texUnit]._Current;
 
if (texObj) {
GLboolean retval;
 
retval = st_finalize_texture(st->ctx, st->pipe, texObj);
if (!retval) {
/* out of mem */
st->missing_textures = GL_TRUE;
continue;
}
}
}
}
 
if (prev_missing_textures != st->missing_textures)
st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM;
}
 
 
 
const struct st_tracked_state st_finalize_textures = {
"st_finalize_textures", /* name */
{ /* dirty */
_NEW_TEXTURE, /* mesa */
0, /* st */
},
finalize_textures /* update */
};
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_atom_viewport.c
0,0 → 1,90
/**************************************************************************
*
* 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 "main/context.h"
#include "st_context.h"
#include "st_atom.h"
#include "pipe/p_context.h"
#include "cso_cache/cso_context.h"
 
/**
* Update the viewport transformation matrix. Depends on:
* - viewport pos/size
* - depthrange
* - window pos/size or FBO size
*/
static void
update_viewport( struct st_context *st )
{
struct gl_context *ctx = st->ctx;
GLfloat yScale, yBias;
 
/* _NEW_BUFFERS
*/
if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
yScale = -1;
yBias = (GLfloat)ctx->DrawBuffer->Height;
}
else {
yScale = 1.0;
yBias = 0.0;
}
 
/* _NEW_VIEWPORT
*/
{
GLfloat x = (GLfloat)ctx->Viewport.X;
GLfloat y = (GLfloat)ctx->Viewport.Y;
GLfloat z = ctx->Viewport.Near;
GLfloat half_width = (GLfloat)ctx->Viewport.Width * 0.5f;
GLfloat half_height = (GLfloat)ctx->Viewport.Height * 0.5f;
GLfloat half_depth = (GLfloat)(ctx->Viewport.Far - ctx->Viewport.Near) * 0.5f;
st->state.viewport.scale[0] = half_width;
st->state.viewport.scale[1] = half_height * yScale;
st->state.viewport.scale[2] = half_depth;
st->state.viewport.scale[3] = 1.0;
 
st->state.viewport.translate[0] = half_width + x;
st->state.viewport.translate[1] = (half_height + y) * yScale + yBias;
st->state.viewport.translate[2] = half_depth + z;
st->state.viewport.translate[3] = 0.0;
 
cso_set_viewport(st->cso_context, &st->state.viewport);
}
}
 
 
const struct st_tracked_state st_update_viewport = {
"st_update_viewport", /* name */
{ /* dirty */
_NEW_BUFFERS | _NEW_VIEWPORT, /* mesa */
0, /* st */
},
update_viewport /* update */
};
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_cache.h
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.
*
**************************************************************************/
 
/*
* Authors:
* Zack Rusin <zack@tungstengraphics.com>
*/
 
#ifndef ST_CACHE_H
#define ST_CACHE_H
 
struct pipe_blend_state;
struct pipe_depth_stencil_alpha_state;
struct pipe_rasterizer_state;
struct pipe_sampler_state;
struct pipe_shader_state;
struct st_context;
 
 
const struct cso_blend *
st_cached_blend_state(struct st_context *st,
const struct pipe_blend_state *blend);
 
const struct cso_sampler *
st_cached_sampler_state(struct st_context *st,
const struct pipe_sampler_state *sampler);
 
const struct cso_depth_stencil_alpha *
st_cached_depth_stencil_alpha_state(struct st_context *st,
const struct pipe_depth_stencil_alpha_state *depth_stencil);
 
const struct cso_rasterizer *
st_cached_rasterizer_state(struct st_context *st,
const struct pipe_rasterizer_state *raster);
 
const struct cso_fragment_shader *
st_cached_fs_state(struct st_context *st,
const struct pipe_shader_state *templ);
 
 
const struct cso_vertex_shader *
st_cached_vs_state(struct st_context *st,
const struct pipe_shader_state *templ);
 
#endif
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_cb_accum.c
0,0 → 1,339
/**************************************************************************
*
* 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 "main/imports.h"
#include "main/image.h"
#include "main/macros.h"
 
#include "st_debug.h"
#include "st_context.h"
#include "st_cb_accum.h"
#include "st_cb_fbo.h"
#include "st_texture.h"
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "util/u_inlines.h"
#include "util/u_tile.h"
 
 
#if FEATURE_accum
 
/**
* For hardware that supports deep color buffers, we could accelerate
* most/all the accum operations with blending/texturing.
* For now, just use the get/put_tile() functions and do things in software.
*/
 
 
void
st_clear_accum_buffer(struct gl_context *ctx, struct gl_renderbuffer *rb)
{
struct st_renderbuffer *acc_strb = st_renderbuffer(rb);
const GLint xpos = ctx->DrawBuffer->_Xmin;
const GLint ypos = ctx->DrawBuffer->_Ymin;
const GLint width = ctx->DrawBuffer->_Xmax - xpos;
const GLint height = ctx->DrawBuffer->_Ymax - ypos;
size_t stride = acc_strb->stride;
GLubyte *data = acc_strb->data;
 
if(!data)
return;
switch (acc_strb->format) {
case PIPE_FORMAT_R16G16B16A16_SNORM:
{
GLshort r = FLOAT_TO_SHORT(ctx->Accum.ClearColor[0]);
GLshort g = FLOAT_TO_SHORT(ctx->Accum.ClearColor[1]);
GLshort b = FLOAT_TO_SHORT(ctx->Accum.ClearColor[2]);
GLshort a = FLOAT_TO_SHORT(ctx->Accum.ClearColor[3]);
int i, j;
for (i = 0; i < height; i++) {
GLshort *dst = (GLshort *) (data + (ypos + i) * stride + xpos * 8);
for (j = 0; j < width; j++) {
dst[0] = r;
dst[1] = g;
dst[2] = b;
dst[3] = a;
dst += 4;
}
}
}
break;
default:
_mesa_problem(ctx, "unexpected format in st_clear_accum_buffer()");
}
}
 
 
/** For ADD/MULT */
static void
accum_mad(struct gl_context *ctx, GLfloat scale, GLfloat bias,
GLint xpos, GLint ypos, GLint width, GLint height,
struct st_renderbuffer *acc_strb)
{
size_t stride = acc_strb->stride;
GLubyte *data = acc_strb->data;
 
switch (acc_strb->format) {
case PIPE_FORMAT_R16G16B16A16_SNORM:
{
int i, j;
for (i = 0; i < height; i++) {
GLshort *acc = (GLshort *) (data + (ypos + i) * stride + xpos * 8);
for (j = 0; j < width * 4; j++) {
float val = SHORT_TO_FLOAT(*acc) * scale + bias;
*acc++ = FLOAT_TO_SHORT(val);
}
}
}
break;
default:
_mesa_problem(NULL, "unexpected format in st_clear_accum_buffer()");
}
}
 
 
static void
accum_accum(struct st_context *st, GLfloat value,
GLint xpos, GLint ypos, GLint width, GLint height,
struct st_renderbuffer *acc_strb,
struct st_renderbuffer *color_strb)
{
struct pipe_context *pipe = st->pipe;
struct pipe_transfer *color_trans;
size_t stride = acc_strb->stride;
GLubyte *data = acc_strb->data;
GLfloat *buf;
 
if (ST_DEBUG & DEBUG_FALLBACK)
debug_printf("%s: fallback processing\n", __FUNCTION__);
 
color_trans = pipe_get_transfer(st->pipe,
color_strb->texture,
0, 0,
PIPE_TRANSFER_READ, xpos, ypos,
width, height);
 
buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
 
pipe_get_tile_rgba(pipe, color_trans, 0, 0, width, height, buf);
 
switch (acc_strb->format) {
case PIPE_FORMAT_R16G16B16A16_SNORM:
{
const GLfloat *color = buf;
int i, j;
for (i = 0; i < height; i++) {
GLshort *acc = (GLshort *) (data + (ypos + i) * stride + xpos * 8);
for (j = 0; j < width * 4; j++) {
float val = *color++ * value;
*acc++ += FLOAT_TO_SHORT(val);
}
}
}
break;
default:
_mesa_problem(NULL, "unexpected format in st_clear_accum_buffer()");
}
 
free(buf);
pipe->transfer_destroy(pipe, color_trans);
}
 
 
static void
accum_load(struct st_context *st, GLfloat value,
GLint xpos, GLint ypos, GLint width, GLint height,
struct st_renderbuffer *acc_strb,
struct st_renderbuffer *color_strb)
{
struct pipe_context *pipe = st->pipe;
struct pipe_transfer *color_trans;
size_t stride = acc_strb->stride;
GLubyte *data = acc_strb->data;
GLfloat *buf;
 
 
if (ST_DEBUG & DEBUG_FALLBACK)
debug_printf("%s: fallback processing\n", __FUNCTION__);
 
color_trans = pipe_get_transfer(st->pipe, color_strb->texture,
0, 0,
PIPE_TRANSFER_READ, xpos, ypos,
width, height);
 
buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
 
pipe_get_tile_rgba(pipe, color_trans, 0, 0, width, height, buf);
 
switch (acc_strb->format) {
case PIPE_FORMAT_R16G16B16A16_SNORM:
{
const GLfloat *color = buf;
int i, j;
for (i = 0; i < height; i++) {
GLshort *acc = (GLshort *) (data + (ypos + i) * stride + xpos * 8);
for (j = 0; j < width * 4; j++) {
float val = *color++ * value;
*acc++ = FLOAT_TO_SHORT(val);
}
}
}
break;
default:
_mesa_problem(NULL, "unexpected format in st_clear_accum_buffer()");
}
 
free(buf);
pipe->transfer_destroy(pipe, color_trans);
}
 
 
static void
accum_return(struct gl_context *ctx, GLfloat value,
GLint xpos, GLint ypos, GLint width, GLint height,
struct st_renderbuffer *acc_strb,
struct st_renderbuffer *color_strb)
{
struct pipe_context *pipe = st_context(ctx)->pipe;
const GLubyte *colormask = ctx->Color.ColorMask[0];
enum pipe_transfer_usage usage;
struct pipe_transfer *color_trans;
size_t stride = acc_strb->stride;
const GLubyte *data = acc_strb->data;
GLfloat *buf;
 
if (ST_DEBUG & DEBUG_FALLBACK)
debug_printf("%s: fallback processing\n", __FUNCTION__);
 
buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
 
if (!colormask[0] || !colormask[1] || !colormask[2] || !colormask[3])
usage = PIPE_TRANSFER_READ_WRITE;
else
usage = PIPE_TRANSFER_WRITE;
 
color_trans = pipe_get_transfer(st_context(ctx)->pipe,
color_strb->texture, 0, 0,
usage,
xpos, ypos,
width, height);
 
if (usage & PIPE_TRANSFER_READ)
pipe_get_tile_rgba(pipe, color_trans, 0, 0, width, height, buf);
 
switch (acc_strb->format) {
case PIPE_FORMAT_R16G16B16A16_SNORM:
{
GLfloat *color = buf;
int i, j, ch;
for (i = 0; i < height; i++) {
const GLshort *acc = (const GLshort *) (data + (ypos + i) * stride + xpos * 8);
for (j = 0; j < width; j++) {
for (ch = 0; ch < 4; ch++) {
if (colormask[ch]) {
GLfloat val = SHORT_TO_FLOAT(*acc * value);
*color = CLAMP(val, 0.0f, 1.0f);
}
else {
/* No change */
}
++acc;
++color;
}
}
}
}
break;
default:
_mesa_problem(NULL, "unexpected format in st_clear_accum_buffer()");
}
 
pipe_put_tile_rgba(pipe, color_trans, 0, 0, width, height, buf);
 
free(buf);
pipe->transfer_destroy(pipe, color_trans);
}
 
 
static void
st_Accum(struct gl_context *ctx, GLenum op, GLfloat value)
{
struct st_context *st = st_context(ctx);
struct st_renderbuffer *acc_strb
= st_renderbuffer(ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer);
struct st_renderbuffer *color_strb
= st_renderbuffer(ctx->ReadBuffer->_ColorReadBuffer);
 
const GLint xpos = ctx->DrawBuffer->_Xmin;
const GLint ypos = ctx->DrawBuffer->_Ymin;
const GLint width = ctx->DrawBuffer->_Xmax - xpos;
const GLint height = ctx->DrawBuffer->_Ymax - ypos;
 
if(!acc_strb->data)
return;
switch (op) {
case GL_ADD:
if (value != 0.0F) {
accum_mad(ctx, 1.0, value, xpos, ypos, width, height, acc_strb);
}
break;
case GL_MULT:
if (value != 1.0F) {
accum_mad(ctx, value, 0.0, xpos, ypos, width, height, acc_strb);
}
break;
case GL_ACCUM:
if (value != 0.0F) {
accum_accum(st, value, xpos, ypos, width, height, acc_strb, color_strb);
}
break;
case GL_LOAD:
accum_load(st, value, xpos, ypos, width, height, acc_strb, color_strb);
break;
case GL_RETURN:
accum_return(ctx, value, xpos, ypos, width, height, acc_strb, color_strb);
break;
default:
assert(0);
}
}
 
 
 
void st_init_accum_functions(struct dd_function_table *functions)
{
functions->Accum = st_Accum;
}
 
#endif /* FEATURE_accum */
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_cb_accum.h
0,0 → 1,59
/**************************************************************************
*
* 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 ST_CB_ACCUM_H
#define ST_CB_ACCUM_H
 
 
#include "main/mtypes.h"
 
#if FEATURE_accum
 
extern void
st_clear_accum_buffer(struct gl_context *ctx, struct gl_renderbuffer *rb);
 
extern void st_init_accum_functions(struct dd_function_table *functions);
 
#else
 
#include "main/compiler.h"
 
static INLINE void
st_clear_accum_buffer(struct gl_context *ctx, struct gl_renderbuffer *rb)
{
ASSERT_NO_FEATURE();
}
 
static INLINE void
st_init_accum_functions(struct dd_function_table *functions)
{
}
 
#endif /* FEATURE_accum */
 
#endif /* ST_CB_ACCUM_H */
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_cb_bitmap.c
0,0 → 1,871
/**************************************************************************
*
* 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 "main/imports.h"
#include "main/image.h"
#include "main/bufferobj.h"
#include "main/macros.h"
#include "program/program.h"
#include "program/prog_print.h"
 
#include "st_context.h"
#include "st_atom.h"
#include "st_atom_constbuf.h"
#include "st_program.h"
#include "st_cb_bitmap.h"
#include "st_texture.h"
 
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "pipe/p_shader_tokens.h"
#include "util/u_inlines.h"
#include "util/u_draw_quad.h"
#include "util/u_simple_shaders.h"
#include "program/prog_instruction.h"
#include "cso_cache/cso_context.h"
 
 
#if FEATURE_drawpix
 
/**
* glBitmaps are drawn as textured quads. The user's bitmap pattern
* is stored in a texture image. An alpha8 texture format is used.
* The fragment shader samples a bit (texel) from the texture, then
* discards the fragment if the bit is off.
*
* Note that we actually store the inverse image of the bitmap to
* simplify the fragment program. An "on" bit gets stored as texel=0x0
* and an "off" bit is stored as texel=0xff. Then we kill the
* fragment if the negated texel value is less than zero.
*/
 
 
/**
* The bitmap cache attempts to accumulate multiple glBitmap calls in a
* buffer which is then rendered en mass upon a flush, state change, etc.
* A wide, short buffer is used to target the common case of a series
* of glBitmap calls being used to draw text.
*/
static GLboolean UseBitmapCache = GL_TRUE;
 
 
#define BITMAP_CACHE_WIDTH 512
#define BITMAP_CACHE_HEIGHT 32
 
struct bitmap_cache
{
/** Window pos to render the cached image */
GLint xpos, ypos;
/** Bounds of region used in window coords */
GLint xmin, ymin, xmax, ymax;
 
GLfloat color[4];
 
/** Bitmap's Z position */
GLfloat zpos;
 
struct pipe_resource *texture;
struct pipe_transfer *trans;
 
GLboolean empty;
 
/** An I8 texture image: */
ubyte *buffer;
};
 
 
/** Epsilon for Z comparisons */
#define Z_EPSILON 1e-06
 
 
/**
* Make fragment program for glBitmap:
* Sample the texture and kill the fragment if the bit is 0.
* This program will be combined with the user's fragment program.
*/
static struct st_fragment_program *
make_bitmap_fragment_program(struct gl_context *ctx, GLuint samplerIndex)
{
struct st_context *st = st_context(ctx);
struct st_fragment_program *stfp;
struct gl_program *p;
GLuint ic = 0;
 
p = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
if (!p)
return NULL;
 
p->NumInstructions = 3;
 
p->Instructions = _mesa_alloc_instructions(p->NumInstructions);
if (!p->Instructions) {
ctx->Driver.DeleteProgram(ctx, p);
return NULL;
}
_mesa_init_instructions(p->Instructions, p->NumInstructions);
 
/* TEX tmp0, fragment.texcoord[0], texture[0], 2D; */
p->Instructions[ic].Opcode = OPCODE_TEX;
p->Instructions[ic].DstReg.File = PROGRAM_TEMPORARY;
p->Instructions[ic].DstReg.Index = 0;
p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_TEX0;
p->Instructions[ic].TexSrcUnit = samplerIndex;
p->Instructions[ic].TexSrcTarget = TEXTURE_2D_INDEX;
ic++;
 
/* KIL if -tmp0 < 0 # texel=0 -> keep / texel=0 -> discard */
p->Instructions[ic].Opcode = OPCODE_KIL;
p->Instructions[ic].SrcReg[0].File = PROGRAM_TEMPORARY;
 
if (st->bitmap.tex_format == PIPE_FORMAT_L8_UNORM)
p->Instructions[ic].SrcReg[0].Swizzle = SWIZZLE_XXXX;
 
p->Instructions[ic].SrcReg[0].Index = 0;
p->Instructions[ic].SrcReg[0].Negate = NEGATE_XYZW;
ic++;
 
/* END; */
p->Instructions[ic++].Opcode = OPCODE_END;
 
assert(ic == p->NumInstructions);
 
p->InputsRead = FRAG_BIT_TEX0;
p->OutputsWritten = 0x0;
p->SamplersUsed = (1 << samplerIndex);
 
stfp = (struct st_fragment_program *) p;
stfp->Base.UsesKill = GL_TRUE;
 
return stfp;
}
 
 
static int
find_free_bit(uint bitfield)
{
int i;
for (i = 0; i < 32; i++) {
if ((bitfield & (1 << i)) == 0) {
return i;
}
}
return -1;
}
 
 
/**
* Combine basic bitmap fragment program with the user-defined program.
*/
static struct st_fragment_program *
combined_bitmap_fragment_program(struct gl_context *ctx)
{
struct st_context *st = st_context(ctx);
struct st_fragment_program *stfp = st->fp;
 
if (!stfp->bitmap_program) {
/*
* Generate new program which is the user-defined program prefixed
* with the bitmap sampler/kill instructions.
*/
struct st_fragment_program *bitmap_prog;
uint sampler;
 
sampler = find_free_bit(st->fp->Base.Base.SamplersUsed);
bitmap_prog = make_bitmap_fragment_program(ctx, sampler);
 
stfp->bitmap_program = (struct st_fragment_program *)
_mesa_combine_programs(ctx,
&bitmap_prog->Base.Base, &stfp->Base.Base);
stfp->bitmap_program->bitmap_sampler = sampler;
 
/* done with this after combining */
st_reference_fragprog(st, &bitmap_prog, NULL);
 
#if 0
{
struct gl_program *p = &stfp->bitmap_program->Base.Base;
printf("Combined bitmap program:\n");
_mesa_print_program(p);
printf("InputsRead: 0x%x\n", p->InputsRead);
printf("OutputsWritten: 0x%x\n", p->OutputsWritten);
_mesa_print_parameter_list(p->Parameters);
}
#endif
 
/* translate to TGSI tokens */
st_translate_fragment_program(st, stfp->bitmap_program);
}
 
return stfp->bitmap_program;
}
 
 
/**
* Copy user-provide bitmap bits into texture buffer, expanding
* bits into texels.
* "On" bits will set texels to 0x0.
* "Off" bits will not modify texels.
* Note that the image is actually going to be upside down in
* the texture. We deal with that with texcoords.
*/
static void
unpack_bitmap(struct st_context *st,
GLint px, GLint py, GLsizei width, GLsizei height,
const struct gl_pixelstore_attrib *unpack,
const GLubyte *bitmap,
ubyte *destBuffer, uint destStride)
{
destBuffer += py * destStride + px;
 
_mesa_expand_bitmap(width, height, unpack, bitmap,
destBuffer, destStride, 0x0);
}
 
 
/**
* Create a texture which represents a bitmap image.
*/
static struct pipe_resource *
make_bitmap_texture(struct gl_context *ctx, GLsizei width, GLsizei height,
const struct gl_pixelstore_attrib *unpack,
const GLubyte *bitmap)
{
struct st_context *st = st_context(ctx);
struct pipe_context *pipe = st->pipe;
struct pipe_transfer *transfer;
ubyte *dest;
struct pipe_resource *pt;
 
/* PBO source... */
bitmap = _mesa_map_pbo_source(ctx, unpack, bitmap);
if (!bitmap) {
return NULL;
}
 
/**
* Create texture to hold bitmap pattern.
*/
pt = st_texture_create(st, st->internal_target, st->bitmap.tex_format,
0, width, height, 1,
PIPE_BIND_SAMPLER_VIEW);
if (!pt) {
_mesa_unmap_pbo_source(ctx, unpack);
return NULL;
}
 
transfer = pipe_get_transfer(st->pipe, pt, 0, 0,
PIPE_TRANSFER_WRITE,
0, 0, width, height);
 
dest = pipe_transfer_map(pipe, transfer);
 
/* Put image into texture transfer */
memset(dest, 0xff, height * transfer->stride);
unpack_bitmap(st, 0, 0, width, height, unpack, bitmap,
dest, transfer->stride);
 
_mesa_unmap_pbo_source(ctx, unpack);
 
/* Release transfer */
pipe_transfer_unmap(pipe, transfer);
pipe->transfer_destroy(pipe, transfer);
 
return pt;
}
 
static GLuint
setup_bitmap_vertex_data(struct st_context *st, bool normalized,
int x, int y, int width, int height,
float z, const float color[4])
{
struct pipe_context *pipe = st->pipe;
const struct gl_framebuffer *fb = st->ctx->DrawBuffer;
const GLfloat fb_width = (GLfloat)fb->Width;
const GLfloat fb_height = (GLfloat)fb->Height;
const GLfloat x0 = (GLfloat)x;
const GLfloat x1 = (GLfloat)(x + width);
const GLfloat y0 = (GLfloat)y;
const GLfloat y1 = (GLfloat)(y + height);
GLfloat sLeft = (GLfloat)0.0, sRight = (GLfloat)1.0;
GLfloat tTop = (GLfloat)0.0, tBot = (GLfloat)1.0 - tTop;
const GLfloat clip_x0 = (GLfloat)(x0 / fb_width * 2.0 - 1.0);
const GLfloat clip_y0 = (GLfloat)(y0 / fb_height * 2.0 - 1.0);
const GLfloat clip_x1 = (GLfloat)(x1 / fb_width * 2.0 - 1.0);
const GLfloat clip_y1 = (GLfloat)(y1 / fb_height * 2.0 - 1.0);
const GLuint max_slots = 1; /* 4096 / sizeof(st->bitmap.vertices); */
GLuint i;
 
if(!normalized)
{
sRight = width;
tBot = height;
}
 
/* XXX: Need to improve buffer_write to allow NO_WAIT (as well as
* no_flush) updates to buffers where we know there is no conflict
* with previous data. Currently using max_slots > 1 will cause
* synchronous rendering if the driver flushes its command buffers
* between one bitmap and the next. Our flush hook below isn't
* sufficient to catch this as the driver doesn't tell us when it
* flushes its own command buffers. Until this gets fixed, pay the
* price of allocating a new buffer for each bitmap cache-flush to
* avoid synchronous rendering.
*/
if (st->bitmap.vbuf_slot >= max_slots) {
pipe_resource_reference(&st->bitmap.vbuf, NULL);
st->bitmap.vbuf_slot = 0;
}
 
if (!st->bitmap.vbuf) {
st->bitmap.vbuf = pipe_buffer_create(pipe->screen,
PIPE_BIND_VERTEX_BUFFER,
max_slots * sizeof(st->bitmap.vertices));
}
 
/* Positions are in clip coords since we need to do clipping in case
* the bitmap quad goes beyond the window bounds.
*/
st->bitmap.vertices[0][0][0] = clip_x0;
st->bitmap.vertices[0][0][1] = clip_y0;
st->bitmap.vertices[0][2][0] = sLeft;
st->bitmap.vertices[0][2][1] = tTop;
 
st->bitmap.vertices[1][0][0] = clip_x1;
st->bitmap.vertices[1][0][1] = clip_y0;
st->bitmap.vertices[1][2][0] = sRight;
st->bitmap.vertices[1][2][1] = tTop;
st->bitmap.vertices[2][0][0] = clip_x1;
st->bitmap.vertices[2][0][1] = clip_y1;
st->bitmap.vertices[2][2][0] = sRight;
st->bitmap.vertices[2][2][1] = tBot;
st->bitmap.vertices[3][0][0] = clip_x0;
st->bitmap.vertices[3][0][1] = clip_y1;
st->bitmap.vertices[3][2][0] = sLeft;
st->bitmap.vertices[3][2][1] = tBot;
/* same for all verts: */
for (i = 0; i < 4; i++) {
st->bitmap.vertices[i][0][2] = z;
st->bitmap.vertices[i][0][3] = 1.0;
st->bitmap.vertices[i][1][0] = color[0];
st->bitmap.vertices[i][1][1] = color[1];
st->bitmap.vertices[i][1][2] = color[2];
st->bitmap.vertices[i][1][3] = color[3];
st->bitmap.vertices[i][2][2] = 0.0; /*R*/
st->bitmap.vertices[i][2][3] = 1.0; /*Q*/
}
 
/* put vertex data into vbuf */
pipe_buffer_write_nooverlap(st->pipe,
st->bitmap.vbuf,
st->bitmap.vbuf_slot * sizeof st->bitmap.vertices,
sizeof st->bitmap.vertices,
st->bitmap.vertices);
 
return st->bitmap.vbuf_slot++ * sizeof st->bitmap.vertices;
}
 
 
 
/**
* Render a glBitmap by drawing a textured quad
*/
static void
draw_bitmap_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
GLsizei width, GLsizei height,
struct pipe_sampler_view *sv,
const GLfloat *color)
{
struct st_context *st = st_context(ctx);
struct pipe_context *pipe = st->pipe;
struct cso_context *cso = st->cso_context;
struct st_fragment_program *stfp;
GLuint maxSize;
GLuint offset;
 
stfp = combined_bitmap_fragment_program(ctx);
 
/* As an optimization, Mesa's fragment programs will sometimes get the
* primary color from a statevar/constant rather than a varying variable.
* when that's the case, we need to ensure that we use the 'color'
* parameter and not the current attribute color (which may have changed
* through glRasterPos and state validation.
* So, we force the proper color here. Not elegant, but it works.
*/
{
GLfloat colorSave[4];
COPY_4V(colorSave, ctx->Current.Attrib[VERT_ATTRIB_COLOR0]);
COPY_4V(ctx->Current.Attrib[VERT_ATTRIB_COLOR0], color);
st_upload_constants(st, stfp->Base.Base.Parameters, PIPE_SHADER_FRAGMENT);
COPY_4V(ctx->Current.Attrib[VERT_ATTRIB_COLOR0], colorSave);
}
 
 
/* limit checks */
/* XXX if the bitmap is larger than the max texture size, break
* it up into chunks.
*/
maxSize = 1 << (pipe->screen->get_param(pipe->screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1);
assert(width <= (GLsizei)maxSize);
assert(height <= (GLsizei)maxSize);
 
cso_save_rasterizer(cso);
cso_save_samplers(cso);
cso_save_fragment_sampler_views(cso);
cso_save_viewport(cso);
cso_save_fragment_shader(cso);
cso_save_vertex_shader(cso);
cso_save_vertex_elements(cso);
 
/* rasterizer state: just scissor */
st->bitmap.rasterizer.scissor = ctx->Scissor.Enabled;
cso_set_rasterizer(cso, &st->bitmap.rasterizer);
 
/* fragment shader state: TEX lookup program */
cso_set_fragment_shader_handle(cso, stfp->driver_shader);
 
/* vertex shader state: position + texcoord pass-through */
cso_set_vertex_shader_handle(cso, st->bitmap.vs);
 
/* user samplers, plus our bitmap sampler */
{
struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
uint num = MAX2(stfp->bitmap_sampler + 1, st->state.num_samplers);
uint i;
for (i = 0; i < st->state.num_samplers; i++) {
samplers[i] = &st->state.samplers[i];
}
samplers[stfp->bitmap_sampler] = &st->bitmap.samplers[sv->texture->target != PIPE_TEXTURE_RECT];
cso_set_samplers(cso, num, (const struct pipe_sampler_state **) samplers);
}
 
/* user textures, plus the bitmap texture */
{
struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS];
uint num = MAX2(stfp->bitmap_sampler + 1, st->state.num_textures);
memcpy(sampler_views, st->state.sampler_views, sizeof(sampler_views));
sampler_views[stfp->bitmap_sampler] = sv;
cso_set_fragment_sampler_views(cso, num, sampler_views);
}
 
/* viewport state: viewport matching window dims */
{
const struct gl_framebuffer *fb = st->ctx->DrawBuffer;
const GLboolean invert = (st_fb_orientation(fb) == Y_0_TOP);
const GLfloat width = (GLfloat)fb->Width;
const GLfloat height = (GLfloat)fb->Height;
struct pipe_viewport_state vp;
vp.scale[0] = 0.5f * width;
vp.scale[1] = height * (invert ? -0.5f : 0.5f);
vp.scale[2] = 0.5f;
vp.scale[3] = 1.0f;
vp.translate[0] = 0.5f * width;
vp.translate[1] = 0.5f * height;
vp.translate[2] = 0.5f;
vp.translate[3] = 0.0f;
cso_set_viewport(cso, &vp);
}
 
cso_set_vertex_elements(cso, 3, st->velems_util_draw);
 
/* convert Z from [0,1] to [-1,-1] to match viewport Z scale/bias */
z = z * 2.0 - 1.0;
 
/* draw textured quad */
offset = setup_bitmap_vertex_data(st, sv->texture->target != PIPE_TEXTURE_RECT, x, y, width, height, z, color);
 
util_draw_vertex_buffer(pipe, st->bitmap.vbuf, offset,
PIPE_PRIM_TRIANGLE_FAN,
4, /* verts */
3); /* attribs/vert */
 
 
/* restore state */
cso_restore_rasterizer(cso);
cso_restore_samplers(cso);
cso_restore_fragment_sampler_views(cso);
cso_restore_viewport(cso);
cso_restore_fragment_shader(cso);
cso_restore_vertex_shader(cso);
cso_restore_vertex_elements(cso);
}
 
 
static void
reset_cache(struct st_context *st)
{
struct pipe_context *pipe = st->pipe;
struct bitmap_cache *cache = st->bitmap.cache;
 
/*memset(cache->buffer, 0xff, sizeof(cache->buffer));*/
cache->empty = GL_TRUE;
 
cache->xmin = 1000000;
cache->xmax = -1000000;
cache->ymin = 1000000;
cache->ymax = -1000000;
 
if (cache->trans) {
pipe->transfer_destroy(pipe, cache->trans);
cache->trans = NULL;
}
 
assert(!cache->texture);
 
/* allocate a new texture */
cache->texture = st_texture_create(st, PIPE_TEXTURE_2D,
st->bitmap.tex_format, 0,
BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT,
1,
PIPE_BIND_SAMPLER_VIEW);
}
 
 
/** Print bitmap image to stdout (debug) */
static void
print_cache(const struct bitmap_cache *cache)
{
int i, j, k;
 
for (i = 0; i < BITMAP_CACHE_HEIGHT; i++) {
k = BITMAP_CACHE_WIDTH * (BITMAP_CACHE_HEIGHT - i - 1);
for (j = 0; j < BITMAP_CACHE_WIDTH; j++) {
if (cache->buffer[k])
printf("X");
else
printf(" ");
k++;
}
printf("\n");
}
}
 
 
static void
create_cache_trans(struct st_context *st)
{
struct pipe_context *pipe = st->pipe;
struct bitmap_cache *cache = st->bitmap.cache;
 
if (cache->trans)
return;
 
/* Map the texture transfer.
* Subsequent glBitmap calls will write into the texture image.
*/
cache->trans = pipe_get_transfer(st->pipe, cache->texture, 0, 0,
PIPE_TRANSFER_WRITE, 0, 0,
BITMAP_CACHE_WIDTH,
BITMAP_CACHE_HEIGHT);
cache->buffer = pipe_transfer_map(pipe, cache->trans);
 
/* init image to all 0xff */
memset(cache->buffer, 0xff, cache->trans->stride * BITMAP_CACHE_HEIGHT);
}
 
 
/**
* If there's anything in the bitmap cache, draw/flush it now.
*/
void
st_flush_bitmap_cache(struct st_context *st)
{
if (!st->bitmap.cache->empty) {
struct bitmap_cache *cache = st->bitmap.cache;
 
if (st->ctx->DrawBuffer) {
struct pipe_context *pipe = st->pipe;
struct pipe_sampler_view *sv;
 
assert(cache->xmin <= cache->xmax);
/* printf("flush size %d x %d at %d, %d\n",
cache->xmax - cache->xmin,
cache->ymax - cache->ymin,
cache->xpos, cache->ypos);
*/
 
/* The texture transfer has been mapped until now.
* So unmap and release the texture transfer before drawing.
*/
if (cache->trans) {
if (0)
print_cache(cache);
pipe_transfer_unmap(pipe, cache->trans);
cache->buffer = NULL;
 
pipe->transfer_destroy(pipe, cache->trans);
cache->trans = NULL;
}
 
sv = st_create_texture_sampler_view(st->pipe, cache->texture);
if (sv) {
draw_bitmap_quad(st->ctx,
cache->xpos,
cache->ypos,
cache->zpos,
BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT,
sv,
cache->color);
 
pipe_sampler_view_reference(&sv, NULL);
}
}
 
/* release/free the texture */
pipe_resource_reference(&cache->texture, NULL);
 
reset_cache(st);
}
}
 
/* Flush bitmap cache and release vertex buffer.
*/
void
st_flush_bitmap( struct st_context *st )
{
st_flush_bitmap_cache(st);
 
/* Release vertex buffer to avoid synchronous rendering if we were
* to map it in the next frame.
*/
pipe_resource_reference(&st->bitmap.vbuf, NULL);
st->bitmap.vbuf_slot = 0;
}
 
 
/**
* Try to accumulate this glBitmap call in the bitmap cache.
* \return GL_TRUE for success, GL_FALSE if bitmap is too large, etc.
*/
static GLboolean
accum_bitmap(struct st_context *st,
GLint x, GLint y, GLsizei width, GLsizei height,
const struct gl_pixelstore_attrib *unpack,
const GLubyte *bitmap )
{
struct bitmap_cache *cache = st->bitmap.cache;
int px = -999, py = -999;
const GLfloat z = st->ctx->Current.RasterPos[2];
 
if (width > BITMAP_CACHE_WIDTH ||
height > BITMAP_CACHE_HEIGHT)
return GL_FALSE; /* too big to cache */
 
if (!cache->empty) {
px = x - cache->xpos; /* pos in buffer */
py = y - cache->ypos;
if (px < 0 || px + width > BITMAP_CACHE_WIDTH ||
py < 0 || py + height > BITMAP_CACHE_HEIGHT ||
!TEST_EQ_4V(st->ctx->Current.RasterColor, cache->color) ||
((fabs(z - cache->zpos) > Z_EPSILON))) {
/* This bitmap would extend beyond cache bounds, or the bitmap
* color is changing
* so flush and continue.
*/
st_flush_bitmap_cache(st);
}
}
 
if (cache->empty) {
/* Initialize. Center bitmap vertically in the buffer. */
px = 0;
py = (BITMAP_CACHE_HEIGHT - height) / 2;
cache->xpos = x;
cache->ypos = y - py;
cache->zpos = z;
cache->empty = GL_FALSE;
COPY_4FV(cache->color, st->ctx->Current.RasterColor);
}
 
assert(px != -999);
assert(py != -999);
 
if (x < cache->xmin)
cache->xmin = x;
if (y < cache->ymin)
cache->ymin = y;
if (x + width > cache->xmax)
cache->xmax = x + width;
if (y + height > cache->ymax)
cache->ymax = y + height;
 
/* create the transfer if needed */
create_cache_trans(st);
 
unpack_bitmap(st, px, py, width, height, unpack, bitmap,
cache->buffer, BITMAP_CACHE_WIDTH);
 
return GL_TRUE; /* accumulated */
}
 
 
 
/**
* Called via ctx->Driver.Bitmap()
*/
static void
st_Bitmap(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
const struct gl_pixelstore_attrib *unpack, const GLubyte *bitmap )
{
struct st_context *st = st_context(ctx);
struct pipe_resource *pt;
 
if (width == 0 || height == 0)
return;
 
st_validate_state(st);
 
if (!st->bitmap.vs) {
/* create pass-through vertex shader now */
const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
TGSI_SEMANTIC_COLOR,
TGSI_SEMANTIC_GENERIC };
const uint semantic_indexes[] = { 0, 0, 0 };
st->bitmap.vs = util_make_vertex_passthrough_shader(st->pipe, 3,
semantic_names,
semantic_indexes);
}
 
if (UseBitmapCache && accum_bitmap(st, x, y, width, height, unpack, bitmap))
return;
 
pt = make_bitmap_texture(ctx, width, height, unpack, bitmap);
if (pt) {
struct pipe_sampler_view *sv = st_create_texture_sampler_view(st->pipe, pt);
 
assert(pt->target == PIPE_TEXTURE_2D || pt->target == PIPE_TEXTURE_RECT);
 
if (sv) {
draw_bitmap_quad(ctx, x, y, ctx->Current.RasterPos[2],
width, height, sv,
st->ctx->Current.RasterColor);
 
pipe_sampler_view_reference(&sv, NULL);
}
 
/* release/free the texture */
pipe_resource_reference(&pt, NULL);
}
}
 
 
/** Per-context init */
void
st_init_bitmap_functions(struct dd_function_table *functions)
{
functions->Bitmap = st_Bitmap;
}
 
 
/** Per-context init */
void
st_init_bitmap(struct st_context *st)
{
struct pipe_sampler_state *sampler = &st->bitmap.samplers[0];
struct pipe_context *pipe = st->pipe;
struct pipe_screen *screen = pipe->screen;
 
/* init sampler state once */
memset(sampler, 0, sizeof(*sampler));
sampler->wrap_s = PIPE_TEX_WRAP_CLAMP;
sampler->wrap_t = PIPE_TEX_WRAP_CLAMP;
sampler->wrap_r = PIPE_TEX_WRAP_CLAMP;
sampler->min_img_filter = PIPE_TEX_FILTER_NEAREST;
sampler->min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
sampler->mag_img_filter = PIPE_TEX_FILTER_NEAREST;
st->bitmap.samplers[1] = *sampler;
st->bitmap.samplers[1].normalized_coords = 1;
 
/* init baseline rasterizer state once */
memset(&st->bitmap.rasterizer, 0, sizeof(st->bitmap.rasterizer));
st->bitmap.rasterizer.gl_rasterization_rules = 1;
 
/* find a usable texture format */
if (screen->is_format_supported(screen, PIPE_FORMAT_I8_UNORM, PIPE_TEXTURE_2D, 0,
PIPE_BIND_SAMPLER_VIEW, 0)) {
st->bitmap.tex_format = PIPE_FORMAT_I8_UNORM;
}
else if (screen->is_format_supported(screen, PIPE_FORMAT_A8_UNORM, PIPE_TEXTURE_2D, 0,
PIPE_BIND_SAMPLER_VIEW, 0)) {
st->bitmap.tex_format = PIPE_FORMAT_A8_UNORM;
}
else if (screen->is_format_supported(screen, PIPE_FORMAT_L8_UNORM, PIPE_TEXTURE_2D, 0,
PIPE_BIND_SAMPLER_VIEW, 0)) {
st->bitmap.tex_format = PIPE_FORMAT_L8_UNORM;
}
else {
/* XXX support more formats */
assert(0);
}
 
/* alloc bitmap cache object */
st->bitmap.cache = ST_CALLOC_STRUCT(bitmap_cache);
 
reset_cache(st);
}
 
 
/** Per-context tear-down */
void
st_destroy_bitmap(struct st_context *st)
{
struct pipe_context *pipe = st->pipe;
struct bitmap_cache *cache = st->bitmap.cache;
 
 
 
if (st->bitmap.vs) {
cso_delete_vertex_shader(st->cso_context, st->bitmap.vs);
st->bitmap.vs = NULL;
}
 
if (st->bitmap.vbuf) {
pipe_resource_reference(&st->bitmap.vbuf, NULL);
st->bitmap.vbuf = NULL;
}
 
if (cache) {
if (cache->trans) {
pipe_transfer_unmap(pipe, cache->trans);
pipe->transfer_destroy(pipe, cache->trans);
}
pipe_resource_reference(&st->bitmap.cache->texture, NULL);
free(st->bitmap.cache);
st->bitmap.cache = NULL;
}
}
 
#endif /* FEATURE_drawpix */
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_cb_bitmap.h
0,0 → 1,87
/**************************************************************************
*
* 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 ST_CB_BITMAP_H
#define ST_CB_BITMAP_H
 
 
#include "main/compiler.h"
 
struct dd_function_table;
struct st_context;
 
#if FEATURE_drawpix
 
extern void
st_init_bitmap_functions(struct dd_function_table *functions);
 
extern void
st_init_bitmap(struct st_context *st);
 
extern void
st_destroy_bitmap(struct st_context *st);
 
extern void
st_flush_bitmap_cache(struct st_context *st);
 
/* Flush bitmap cache and release vertex buffer. Needed at end of
* frame to avoid synchronous rendering.
*/
extern void
st_flush_bitmap(struct st_context *st);
 
#else
 
static INLINE void
st_init_bitmap_functions(struct dd_function_table *functions)
{
}
 
static INLINE void
st_init_bitmap(struct st_context *st)
{
}
 
static INLINE void
st_destroy_bitmap(struct st_context *st)
{
}
 
static INLINE void
st_flush_bitmap_cache(struct st_context *st)
{
}
 
static INLINE void
st_flush_bitmap(struct st_context *st)
{
}
 
#endif /* FEATURE_drawpix */
 
#endif /* ST_CB_BITMAP_H */
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_cb_blit.c
0,0 → 1,208
/**************************************************************************
*
* 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 "main/imports.h"
#include "main/image.h"
#include "main/macros.h"
 
#include "st_context.h"
#include "st_texture.h"
#include "st_cb_blit.h"
#include "st_cb_fbo.h"
 
#include "util/u_blit.h"
#include "util/u_inlines.h"
 
 
void
st_init_blit(struct st_context *st)
{
st->blit = util_create_blit(st->pipe, st->cso_context);
}
 
 
void
st_destroy_blit(struct st_context *st)
{
util_destroy_blit(st->blit);
st->blit = NULL;
}
 
 
#if FEATURE_EXT_framebuffer_blit
 
static void
st_BlitFramebuffer(struct gl_context *ctx,
GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
GLbitfield mask, GLenum filter)
{
const GLbitfield depthStencil = (GL_DEPTH_BUFFER_BIT |
GL_STENCIL_BUFFER_BIT);
struct st_context *st = st_context(ctx);
const uint pFilter = ((filter == GL_NEAREST)
? PIPE_TEX_MIPFILTER_NEAREST
: PIPE_TEX_MIPFILTER_LINEAR);
struct gl_framebuffer *readFB = ctx->ReadBuffer;
struct gl_framebuffer *drawFB = ctx->DrawBuffer;
 
if (!_mesa_clip_blit(ctx, &srcX0, &srcY0, &srcX1, &srcY1,
&dstX0, &dstY0, &dstX1, &dstY1)) {
return; /* nothing to draw/blit */
}
 
if (st_fb_orientation(drawFB) == Y_0_TOP) {
/* invert Y for dest */
dstY0 = drawFB->Height - dstY0;
dstY1 = drawFB->Height - dstY1;
}
 
if (st_fb_orientation(readFB) == Y_0_TOP) {
/* invert Y for src */
srcY0 = readFB->Height - srcY0;
srcY1 = readFB->Height - srcY1;
}
 
if (srcY0 > srcY1 && dstY0 > dstY1) {
/* Both src and dst are upside down. Swap Y to make it
* right-side up to increase odds of using a fast path.
* Recall that all Gallium raster coords have Y=0=top.
*/
GLint tmp;
tmp = srcY0;
srcY0 = srcY1;
srcY1 = tmp;
tmp = dstY0;
dstY0 = dstY1;
dstY1 = tmp;
}
 
if (mask & GL_COLOR_BUFFER_BIT) {
struct gl_renderbuffer_attachment *srcAtt =
&readFB->Attachment[readFB->_ColorReadBufferIndex];
 
if(srcAtt->Type == GL_TEXTURE) {
struct st_texture_object *srcObj =
st_texture_object(srcAtt->Texture);
struct st_renderbuffer *dstRb =
st_renderbuffer(drawFB->_ColorDrawBuffers[0]);
struct pipe_surface *dstSurf = dstRb->surface;
 
if (!srcObj->pt)
return;
 
util_blit_pixels(st->blit, srcObj->pt, srcAtt->TextureLevel,
srcX0, srcY0, srcX1, srcY1,
srcAtt->Zoffset + srcAtt->CubeMapFace,
dstSurf, dstX0, dstY0, dstX1, dstY1,
0.0, pFilter);
}
else {
struct st_renderbuffer *srcRb =
st_renderbuffer(readFB->_ColorReadBuffer);
struct st_renderbuffer *dstRb =
st_renderbuffer(drawFB->_ColorDrawBuffers[0]);
struct pipe_surface *srcSurf = srcRb->surface;
struct pipe_surface *dstSurf = dstRb->surface;
 
util_blit_pixels(st->blit,
srcRb->texture, srcSurf->u.tex.level,
srcX0, srcY0, srcX1, srcY1,
srcSurf->u.tex.first_layer,
dstSurf, dstX0, dstY0, dstX1, dstY1,
0.0, pFilter);
}
}
 
if (mask & depthStencil) {
/* depth and/or stencil blit */
 
/* get src/dst depth surfaces */
struct gl_renderbuffer_attachment *srcDepth =
&readFB->Attachment[BUFFER_DEPTH];
struct gl_renderbuffer_attachment *dstDepth =
&drawFB->Attachment[BUFFER_DEPTH];
struct gl_renderbuffer_attachment *srcStencil =
&readFB->Attachment[BUFFER_STENCIL];
struct gl_renderbuffer_attachment *dstStencil =
&drawFB->Attachment[BUFFER_STENCIL];
 
struct st_renderbuffer *srcDepthRb =
st_renderbuffer(readFB->Attachment[BUFFER_DEPTH].Renderbuffer);
struct st_renderbuffer *dstDepthRb =
st_renderbuffer(drawFB->Attachment[BUFFER_DEPTH].Renderbuffer);
struct pipe_surface *dstDepthSurf =
dstDepthRb ? dstDepthRb->surface : NULL;
 
if ((mask & depthStencil) == depthStencil &&
st_is_depth_stencil_combined(srcDepth, srcStencil) &&
st_is_depth_stencil_combined(dstDepth, dstStencil)) {
 
/* Blitting depth and stencil values between combined
* depth/stencil buffers. This is the ideal case for such buffers.
*/
util_blit_pixels(st->blit,
srcDepthRb->texture,
srcDepthRb->surface->u.tex.level,
srcX0, srcY0, srcX1, srcY1,
srcDepthRb->surface->u.tex.first_layer,
dstDepthSurf, dstX0, dstY0, dstX1, dstY1,
0.0, pFilter);
}
else {
/* blitting depth and stencil separately */
 
if (mask & GL_DEPTH_BUFFER_BIT) {
util_blit_pixels(st->blit, srcDepthRb->texture,
srcDepthRb->surface->u.tex.level,
srcX0, srcY0, srcX1, srcY1,
srcDepthRb->surface->u.tex.first_layer,
dstDepthSurf, dstX0, dstY0, dstX1, dstY1,
0.0, pFilter);
}
 
if (mask & GL_STENCIL_BUFFER_BIT) {
/* blit stencil only */
_mesa_problem(ctx, "st_BlitFramebuffer(STENCIL) not completed");
}
}
}
}
 
 
void
st_init_blit_functions(struct dd_function_table *functions)
{
functions->BlitFramebuffer = st_BlitFramebuffer;
}
 
#endif /* FEATURE_EXT_framebuffer_blit */
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_cb_blit.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 ST_CB_BLIT_H
#define ST_CB_BLIT_H
 
 
#include "main/compiler.h"
 
struct dd_function_table;
struct st_context;
 
 
extern void
st_init_blit(struct st_context *st);
 
extern void
st_destroy_blit(struct st_context *st);
 
#if FEATURE_EXT_framebuffer_blit
 
extern void
st_init_blit_functions(struct dd_function_table *functions);
 
#else
 
static INLINE void
st_init_blit_functions(struct dd_function_table *functions)
{
}
 
#endif /* FEATURE_EXT_framebuffer_blit */
 
#endif /* ST_CB_BLIT_H */
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_cb_bufferobjects.c
0,0 → 1,447
/**************************************************************************
*
* 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 pixel buffer objects and vertex/element buffer objects.
*/
 
 
#include "main/imports.h"
#include "main/mtypes.h"
#include "main/arrayobj.h"
#include "main/bufferobj.h"
 
#include "st_context.h"
#include "st_cb_bufferobjects.h"
 
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "util/u_inlines.h"
 
 
/**
* There is some duplication between mesa's bufferobjects and our
* bufmgr buffers. Both have an integer handle and a hashtable to
* lookup an opaque structure. It would be nice if the handles and
* internal structure where somehow shared.
*/
static struct gl_buffer_object *
st_bufferobj_alloc(struct gl_context *ctx, GLuint name, GLenum target)
{
struct st_buffer_object *st_obj = ST_CALLOC_STRUCT(st_buffer_object);
 
if (!st_obj)
return NULL;
 
_mesa_initialize_buffer_object(&st_obj->Base, name, target);
 
return &st_obj->Base;
}
 
 
 
/**
* Deallocate/free a vertex/pixel buffer object.
* Called via glDeleteBuffersARB().
*/
static void
st_bufferobj_free(struct gl_context *ctx, struct gl_buffer_object *obj)
{
struct st_buffer_object *st_obj = st_buffer_object(obj);
 
assert(obj->RefCount == 0);
assert(st_obj->transfer == NULL);
 
if (st_obj->buffer)
pipe_resource_reference(&st_obj->buffer, NULL);
 
free(st_obj);
}
 
 
 
/**
* Replace data in a subrange of buffer object. If the data range
* specified by size + offset extends beyond the end of the buffer or
* if data is NULL, no copy is performed.
* Called via glBufferSubDataARB().
*/
static void
st_bufferobj_subdata(struct gl_context *ctx,
GLenum target,
GLintptrARB offset,
GLsizeiptrARB size,
const GLvoid * data, struct gl_buffer_object *obj)
{
struct st_buffer_object *st_obj = st_buffer_object(obj);
 
/* we may be called from VBO code, so double-check params here */
ASSERT(offset >= 0);
ASSERT(size >= 0);
ASSERT(offset + size <= obj->Size);
 
if (!size)
return;
 
/*
* According to ARB_vertex_buffer_object specification, if data is null,
* then the contents of the buffer object's data store is undefined. We just
* ignore, and leave it unchanged.
*/
if (!data)
return;
 
/* Now that transfers are per-context, we don't have to figure out
* flushing here. Usually drivers won't need to flush in this case
* even if the buffer is currently referenced by hardware - they
* just queue the upload as dma rather than mapping the underlying
* buffer directly.
*/
pipe_buffer_write(st_context(ctx)->pipe,
st_obj->buffer,
offset, size, data);
}
 
 
/**
* Called via glGetBufferSubDataARB().
*/
static void
st_bufferobj_get_subdata(struct gl_context *ctx,
GLenum target,
GLintptrARB offset,
GLsizeiptrARB size,
GLvoid * data, struct gl_buffer_object *obj)
{
struct st_buffer_object *st_obj = st_buffer_object(obj);
 
/* we may be called from VBO code, so double-check params here */
ASSERT(offset >= 0);
ASSERT(size >= 0);
ASSERT(offset + size <= obj->Size);
 
if (!size)
return;
 
pipe_buffer_read(st_context(ctx)->pipe, st_obj->buffer,
offset, size, data);
}
 
 
/**
* Allocate space for and store data in a buffer object. Any data that was
* previously stored in the buffer object is lost. If data is NULL,
* memory will be allocated, but no copy will occur.
* Called via ctx->Driver.BufferData().
* \return GL_TRUE for success, GL_FALSE if out of memory
*/
static GLboolean
st_bufferobj_data(struct gl_context *ctx,
GLenum target,
GLsizeiptrARB size,
const GLvoid * data,
GLenum usage,
struct gl_buffer_object *obj)
{
struct st_context *st = st_context(ctx);
struct pipe_context *pipe = st->pipe;
struct st_buffer_object *st_obj = st_buffer_object(obj);
unsigned buffer_usage;
 
st_obj->Base.Size = size;
st_obj->Base.Usage = usage;
switch(target) {
case GL_PIXEL_PACK_BUFFER_ARB:
case GL_PIXEL_UNPACK_BUFFER_ARB:
buffer_usage = PIPE_BIND_RENDER_TARGET;
break;
case GL_ARRAY_BUFFER_ARB:
buffer_usage = PIPE_BIND_VERTEX_BUFFER;
break;
case GL_ELEMENT_ARRAY_BUFFER_ARB:
buffer_usage = PIPE_BIND_INDEX_BUFFER;
break;
default:
buffer_usage = 0;
}
 
pipe_resource_reference( &st_obj->buffer, NULL );
 
if (size != 0) {
st_obj->buffer = pipe_buffer_create(pipe->screen, buffer_usage, size);
 
if (!st_obj->buffer) {
return GL_FALSE;
}
 
if (data)
pipe_buffer_write(st_context(ctx)->pipe, st_obj->buffer, 0,
size, data);
return GL_TRUE;
}
 
return GL_TRUE;
}
 
 
/**
* Dummy data whose's pointer is used for zero size buffers or ranges.
*/
static long st_bufferobj_zero_length = 0;
 
 
 
/**
* Called via glMapBufferARB().
*/
static void *
st_bufferobj_map(struct gl_context *ctx, GLenum target, GLenum access,
struct gl_buffer_object *obj)
{
struct st_buffer_object *st_obj = st_buffer_object(obj);
uint flags;
 
switch (access) {
case GL_WRITE_ONLY:
flags = PIPE_TRANSFER_WRITE;
break;
case GL_READ_ONLY:
flags = PIPE_TRANSFER_READ;
break;
case GL_READ_WRITE:
default:
flags = PIPE_TRANSFER_READ_WRITE;
break;
}
 
/* Handle zero-size buffers here rather than in drivers */
if (obj->Size == 0) {
obj->Pointer = &st_bufferobj_zero_length;
}
else {
obj->Pointer = pipe_buffer_map(st_context(ctx)->pipe,
st_obj->buffer,
flags,
&st_obj->transfer);
}
 
if (obj->Pointer) {
obj->Offset = 0;
obj->Length = obj->Size;
}
return obj->Pointer;
}
 
 
/**
* Called via glMapBufferRange().
*/
static void *
st_bufferobj_map_range(struct gl_context *ctx, GLenum target,
GLintptr offset, GLsizeiptr length, GLbitfield access,
struct gl_buffer_object *obj)
{
struct pipe_context *pipe = st_context(ctx)->pipe;
struct st_buffer_object *st_obj = st_buffer_object(obj);
enum pipe_transfer_usage flags = 0x0;
 
if (access & GL_MAP_WRITE_BIT)
flags |= PIPE_TRANSFER_WRITE;
 
if (access & GL_MAP_READ_BIT)
flags |= PIPE_TRANSFER_READ;
 
if (access & GL_MAP_FLUSH_EXPLICIT_BIT)
flags |= PIPE_TRANSFER_FLUSH_EXPLICIT;
 
if (access & GL_MAP_INVALIDATE_RANGE_BIT)
flags |= PIPE_TRANSFER_DISCARD;
 
if (access & GL_MAP_INVALIDATE_BUFFER_BIT)
flags |= PIPE_TRANSFER_DISCARD;
if (access & GL_MAP_UNSYNCHRONIZED_BIT)
flags |= PIPE_TRANSFER_UNSYNCHRONIZED;
 
/* ... other flags ...
*/
 
if (access & MESA_MAP_NOWAIT_BIT)
flags |= PIPE_TRANSFER_DONTBLOCK;
 
assert(offset >= 0);
assert(length >= 0);
assert(offset < obj->Size);
assert(offset + length <= obj->Size);
 
/*
* We go out of way here to hide the degenerate yet valid case of zero
* length range from the pipe driver.
*/
if (!length) {
obj->Pointer = &st_bufferobj_zero_length;
}
else {
obj->Pointer = pipe_buffer_map_range(pipe,
st_obj->buffer,
offset, length,
flags,
&st_obj->transfer);
if (obj->Pointer) {
obj->Pointer = (ubyte *) obj->Pointer + offset;
}
}
if (obj->Pointer) {
obj->Offset = offset;
obj->Length = length;
obj->AccessFlags = access;
}
 
return obj->Pointer;
}
 
 
static void
st_bufferobj_flush_mapped_range(struct gl_context *ctx, GLenum target,
GLintptr offset, GLsizeiptr length,
struct gl_buffer_object *obj)
{
struct pipe_context *pipe = st_context(ctx)->pipe;
struct st_buffer_object *st_obj = st_buffer_object(obj);
 
/* Subrange is relative to mapped range */
assert(offset >= 0);
assert(length >= 0);
assert(offset + length <= obj->Length);
assert(obj->Pointer);
if (!length)
return;
 
pipe_buffer_flush_mapped_range(pipe, st_obj->transfer,
obj->Offset + offset, length);
}
 
 
/**
* Called via glUnmapBufferARB().
*/
static GLboolean
st_bufferobj_unmap(struct gl_context *ctx, GLenum target, struct gl_buffer_object *obj)
{
struct pipe_context *pipe = st_context(ctx)->pipe;
struct st_buffer_object *st_obj = st_buffer_object(obj);
 
if (obj->Length)
pipe_buffer_unmap(pipe, st_obj->buffer, st_obj->transfer);
 
st_obj->transfer = NULL;
obj->Pointer = NULL;
obj->Offset = 0;
obj->Length = 0;
return GL_TRUE;
}
 
 
/**
* Called via glCopyBufferSubData().
*/
static void
st_copy_buffer_subdata(struct gl_context *ctx,
struct gl_buffer_object *src,
struct gl_buffer_object *dst,
GLintptr readOffset, GLintptr writeOffset,
GLsizeiptr size)
{
struct pipe_context *pipe = st_context(ctx)->pipe;
struct st_buffer_object *srcObj = st_buffer_object(src);
struct st_buffer_object *dstObj = st_buffer_object(dst);
struct pipe_transfer *src_transfer;
struct pipe_transfer *dst_transfer;
ubyte *srcPtr, *dstPtr;
 
if(!size)
return;
 
/* buffer should not already be mapped */
assert(!src->Pointer);
assert(!dst->Pointer);
 
srcPtr = (ubyte *) pipe_buffer_map_range(pipe,
srcObj->buffer,
readOffset, size,
PIPE_TRANSFER_READ,
&src_transfer);
 
dstPtr = (ubyte *) pipe_buffer_map_range(pipe,
dstObj->buffer,
writeOffset, size,
PIPE_TRANSFER_WRITE,
&dst_transfer);
 
if (srcPtr && dstPtr)
memcpy(dstPtr + writeOffset, srcPtr + readOffset, size);
 
pipe_buffer_unmap(pipe, srcObj->buffer, src_transfer);
pipe_buffer_unmap(pipe, dstObj->buffer, dst_transfer);
}
 
 
/* TODO: if buffer wasn't created with appropriate usage flags, need
* to recreate it now and copy contents -- or possibly create a
* gallium entrypoint to extend the usage flags and let the driver
* decide if a copy is necessary.
*/
void
st_bufferobj_validate_usage(struct st_context *st,
struct st_buffer_object *obj,
unsigned usage)
{
}
 
 
void
st_init_bufferobject_functions(struct dd_function_table *functions)
{
functions->NewBufferObject = st_bufferobj_alloc;
functions->DeleteBuffer = st_bufferobj_free;
functions->BufferData = st_bufferobj_data;
functions->BufferSubData = st_bufferobj_subdata;
functions->GetBufferSubData = st_bufferobj_get_subdata;
functions->MapBuffer = st_bufferobj_map;
functions->MapBufferRange = st_bufferobj_map_range;
functions->FlushMappedBufferRange = st_bufferobj_flush_mapped_range;
functions->UnmapBuffer = st_bufferobj_unmap;
functions->CopyBufferSubData = st_copy_buffer_subdata;
 
/* For GL_APPLE_vertex_array_object */
functions->NewArrayObject = _mesa_new_array_object;
functions->DeleteArrayObject = _mesa_delete_array_object;
}
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_cb_bufferobjects.h
0,0 → 1,68
/**************************************************************************
*
* Copyright 2005 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 ST_CB_BUFFEROBJECTS_H
#define ST_CB_BUFFEROBJECTS_H
 
#include "main/compiler.h"
#include "main/mtypes.h"
 
struct dd_function_table;
struct pipe_resource;
struct st_context;
 
/**
* State_tracker vertex/pixel buffer object, derived from Mesa's
* gl_buffer_object.
*/
struct st_buffer_object
{
struct gl_buffer_object Base;
struct pipe_resource *buffer; /* GPU storage */
struct pipe_transfer *transfer; /* In-progress map information */
};
 
 
/** cast wrapper */
static INLINE struct st_buffer_object *
st_buffer_object(struct gl_buffer_object *obj)
{
return (struct st_buffer_object *) obj;
}
 
 
extern void
st_bufferobj_validate_usage(struct st_context *st,
struct st_buffer_object *obj,
unsigned usage);
 
 
extern void
st_init_bufferobject_functions(struct dd_function_table *functions);
 
 
#endif
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_cb_clear.c
0,0 → 1,571
/**************************************************************************
*
* 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.
*
**************************************************************************/
 
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
* Brian Paul
* Michel Dänzer
*/
 
#include "main/glheader.h"
#include "main/formats.h"
#include "main/macros.h"
#include "program/prog_instruction.h"
#include "st_context.h"
#include "st_atom.h"
#include "st_cb_accum.h"
#include "st_cb_clear.h"
#include "st_cb_fbo.h"
#include "st_format.h"
#include "st_program.h"
 
#include "pipe/p_context.h"
#include "pipe/p_shader_tokens.h"
#include "pipe/p_state.h"
#include "pipe/p_defines.h"
#include "util/u_format.h"
#include "util/u_inlines.h"
#include "util/u_simple_shaders.h"
#include "util/u_draw_quad.h"
 
#include "cso_cache/cso_context.h"
 
 
/**
* Do per-context initialization for glClear.
*/
void
st_init_clear(struct st_context *st)
{
struct pipe_context *pipe = st->pipe;
struct pipe_screen *pscreen = st->pipe->screen;
 
memset(&st->clear, 0, sizeof(st->clear));
 
st->clear.raster.gl_rasterization_rules = 1;
st->clear.enable_ds_separate = pscreen->get_param(pscreen, PIPE_CAP_DEPTHSTENCIL_CLEAR_SEPARATE);
 
/* fragment shader state: color pass-through program */
st->clear.fs = util_make_fragment_passthrough_shader(pipe);
 
/* vertex shader state: color/position pass-through */
{
const uint semantic_names[] = { TGSI_SEMANTIC_POSITION,
TGSI_SEMANTIC_COLOR };
const uint semantic_indexes[] = { 0, 0 };
st->clear.vs = util_make_vertex_passthrough_shader(pipe, 2,
semantic_names,
semantic_indexes);
}
}
 
 
/**
* Free per-context state for glClear.
*/
void
st_destroy_clear(struct st_context *st)
{
if (st->clear.fs) {
cso_delete_fragment_shader(st->cso_context, st->clear.fs);
st->clear.fs = NULL;
}
if (st->clear.vs) {
cso_delete_vertex_shader(st->cso_context, st->clear.vs);
st->clear.vs = NULL;
}
if (st->clear.vbuf) {
pipe_resource_reference(&st->clear.vbuf, NULL);
st->clear.vbuf = NULL;
}
}
 
 
/**
* Draw a screen-aligned quadrilateral.
* Coords are clip coords with y=0=bottom.
*/
static void
draw_quad(struct st_context *st,
float x0, float y0, float x1, float y1, GLfloat z,
const GLfloat color[4])
{
struct pipe_context *pipe = st->pipe;
 
/* XXX: Need to improve buffer_write to allow NO_WAIT (as well as
* no_flush) updates to buffers where we know there is no conflict
* with previous data. Currently using max_slots > 1 will cause
* synchronous rendering if the driver flushes its command buffers
* between one bitmap and the next. Our flush hook below isn't
* sufficient to catch this as the driver doesn't tell us when it
* flushes its own command buffers. Until this gets fixed, pay the
* price of allocating a new buffer for each bitmap cache-flush to
* avoid synchronous rendering.
*/
const GLuint max_slots = 1; /* 1024 / sizeof(st->clear.vertices); */
GLuint i;
 
if (st->clear.vbuf_slot >= max_slots) {
pipe_resource_reference(&st->clear.vbuf, NULL);
st->clear.vbuf_slot = 0;
}
 
if (!st->clear.vbuf) {
st->clear.vbuf = pipe_buffer_create(pipe->screen,
PIPE_BIND_VERTEX_BUFFER,
max_slots * sizeof(st->clear.vertices));
}
 
/* positions */
st->clear.vertices[0][0][0] = x0;
st->clear.vertices[0][0][1] = y0;
 
st->clear.vertices[1][0][0] = x1;
st->clear.vertices[1][0][1] = y0;
 
st->clear.vertices[2][0][0] = x1;
st->clear.vertices[2][0][1] = y1;
 
st->clear.vertices[3][0][0] = x0;
st->clear.vertices[3][0][1] = y1;
 
/* same for all verts: */
for (i = 0; i < 4; i++) {
st->clear.vertices[i][0][2] = z;
st->clear.vertices[i][0][3] = 1.0;
st->clear.vertices[i][1][0] = color[0];
st->clear.vertices[i][1][1] = color[1];
st->clear.vertices[i][1][2] = color[2];
st->clear.vertices[i][1][3] = color[3];
}
 
/* put vertex data into vbuf */
pipe_buffer_write_nooverlap(st->pipe, st->clear.vbuf,
st->clear.vbuf_slot
* sizeof(st->clear.vertices),
sizeof(st->clear.vertices),
st->clear.vertices);
 
/* draw */
util_draw_vertex_buffer(pipe,
st->clear.vbuf,
st->clear.vbuf_slot * sizeof(st->clear.vertices),
PIPE_PRIM_TRIANGLE_FAN,
4, /* verts */
2); /* attribs/vert */
 
/* Increment slot */
st->clear.vbuf_slot++;
}
 
 
 
/**
* Do glClear by drawing a quadrilateral.
* The vertices of the quad will be computed from the
* ctx->DrawBuffer->_X/Ymin/max fields.
*/
static void
clear_with_quad(struct gl_context *ctx,
GLboolean color, GLboolean depth, GLboolean stencil)
{
struct st_context *st = st_context(ctx);
const struct gl_framebuffer *fb = ctx->DrawBuffer;
const GLfloat fb_width = (GLfloat) fb->Width;
const GLfloat fb_height = (GLfloat) fb->Height;
const GLfloat x0 = (GLfloat) ctx->DrawBuffer->_Xmin / fb_width * 2.0f - 1.0f;
const GLfloat x1 = (GLfloat) ctx->DrawBuffer->_Xmax / fb_width * 2.0f - 1.0f;
const GLfloat y0 = (GLfloat) ctx->DrawBuffer->_Ymin / fb_height * 2.0f - 1.0f;
const GLfloat y1 = (GLfloat) ctx->DrawBuffer->_Ymax / fb_height * 2.0f - 1.0f;
float clearColor[4];
 
/*
printf("%s %s%s%s %f,%f %f,%f\n", __FUNCTION__,
color ? "color, " : "",
depth ? "depth, " : "",
stencil ? "stencil" : "",
x0, y0,
x1, y1);
*/
 
cso_save_blend(st->cso_context);
cso_save_stencil_ref(st->cso_context);
cso_save_depth_stencil_alpha(st->cso_context);
cso_save_rasterizer(st->cso_context);
cso_save_viewport(st->cso_context);
cso_save_clip(st->cso_context);
cso_save_fragment_shader(st->cso_context);
cso_save_vertex_shader(st->cso_context);
cso_save_vertex_elements(st->cso_context);
 
/* blend state: RGBA masking */
{
struct pipe_blend_state blend;
memset(&blend, 0, sizeof(blend));
blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
if (color) {
if (ctx->Color.ColorMask[0][0])
blend.rt[0].colormask |= PIPE_MASK_R;
if (ctx->Color.ColorMask[0][1])
blend.rt[0].colormask |= PIPE_MASK_G;
if (ctx->Color.ColorMask[0][2])
blend.rt[0].colormask |= PIPE_MASK_B;
if (ctx->Color.ColorMask[0][3])
blend.rt[0].colormask |= PIPE_MASK_A;
if (st->ctx->Color.DitherFlag)
blend.dither = 1;
}
cso_set_blend(st->cso_context, &blend);
}
 
/* depth_stencil state: always pass/set to ref value */
{
struct pipe_depth_stencil_alpha_state depth_stencil;
memset(&depth_stencil, 0, sizeof(depth_stencil));
if (depth) {
depth_stencil.depth.enabled = 1;
depth_stencil.depth.writemask = 1;
depth_stencil.depth.func = PIPE_FUNC_ALWAYS;
}
 
if (stencil) {
struct pipe_stencil_ref stencil_ref;
memset(&stencil_ref, 0, sizeof(stencil_ref));
depth_stencil.stencil[0].enabled = 1;
depth_stencil.stencil[0].func = PIPE_FUNC_ALWAYS;
depth_stencil.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
depth_stencil.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
depth_stencil.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
depth_stencil.stencil[0].valuemask = 0xff;
depth_stencil.stencil[0].writemask = ctx->Stencil.WriteMask[0] & 0xff;
stencil_ref.ref_value[0] = ctx->Stencil.Clear;
cso_set_stencil_ref(st->cso_context, &stencil_ref);
}
 
cso_set_depth_stencil_alpha(st->cso_context, &depth_stencil);
}
 
cso_set_vertex_elements(st->cso_context, 2, st->velems_util_draw);
 
cso_set_rasterizer(st->cso_context, &st->clear.raster);
 
/* viewport state: viewport matching window dims */
{
const GLboolean invert = (st_fb_orientation(fb) == Y_0_TOP);
struct pipe_viewport_state vp;
vp.scale[0] = 0.5f * fb_width;
vp.scale[1] = fb_height * (invert ? -0.5f : 0.5f);
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(st->cso_context, &vp);
}
 
cso_set_clip(st->cso_context, &st->clear.clip);
cso_set_fragment_shader_handle(st->cso_context, st->clear.fs);
cso_set_vertex_shader_handle(st->cso_context, st->clear.vs);
 
st_translate_color(ctx->Color.ClearColor,
ctx->DrawBuffer->_ColorDrawBuffers[0]->_BaseFormat,
clearColor);
 
/* draw quad matching scissor rect */
draw_quad(st, x0, y0, x1, y1, (GLfloat) ctx->Depth.Clear, clearColor);
 
/* Restore pipe state */
cso_restore_blend(st->cso_context);
cso_restore_stencil_ref(st->cso_context);
cso_restore_depth_stencil_alpha(st->cso_context);
cso_restore_rasterizer(st->cso_context);
cso_restore_viewport(st->cso_context);
cso_restore_clip(st->cso_context);
cso_restore_fragment_shader(st->cso_context);
cso_restore_vertex_shader(st->cso_context);
cso_restore_vertex_elements(st->cso_context);
}
 
 
/**
* Determine if we need to clear the depth buffer by drawing a quad.
*/
static INLINE GLboolean
check_clear_color_with_quad(struct gl_context *ctx, struct gl_renderbuffer *rb)
{
if (ctx->Scissor.Enabled &&
(ctx->Scissor.X != 0 ||
ctx->Scissor.Y != 0 ||
ctx->Scissor.Width < rb->Width ||
ctx->Scissor.Height < rb->Height))
return GL_TRUE;
 
if (!ctx->Color.ColorMask[0][0] ||
!ctx->Color.ColorMask[0][1] ||
!ctx->Color.ColorMask[0][2] ||
!ctx->Color.ColorMask[0][3])
return GL_TRUE;
 
return GL_FALSE;
}
 
 
/**
* Determine if we need to clear the combiend depth/stencil buffer by
* drawing a quad.
*/
static INLINE GLboolean
check_clear_depth_stencil_with_quad(struct gl_context *ctx, struct gl_renderbuffer *rb)
{
const GLuint stencilMax = 0xff;
GLboolean maskStencil
= (ctx->Stencil.WriteMask[0] & stencilMax) != stencilMax;
 
assert(rb->Format == MESA_FORMAT_S8 ||
rb->Format == MESA_FORMAT_Z24_S8 ||
rb->Format == MESA_FORMAT_S8_Z24);
 
if (ctx->Scissor.Enabled &&
(ctx->Scissor.X != 0 ||
ctx->Scissor.Y != 0 ||
ctx->Scissor.Width < rb->Width ||
ctx->Scissor.Height < rb->Height))
return GL_TRUE;
 
if (maskStencil)
return GL_TRUE;
 
return GL_FALSE;
}
 
 
/**
* Determine if we need to clear the depth buffer by drawing a quad.
*/
static INLINE GLboolean
check_clear_depth_with_quad(struct gl_context *ctx, struct gl_renderbuffer *rb,
boolean ds_separate)
{
const struct st_renderbuffer *strb = st_renderbuffer(rb);
const GLboolean isDS = util_format_is_depth_and_stencil(strb->surface->format);
 
if (ctx->Scissor.Enabled &&
(ctx->Scissor.X != 0 ||
ctx->Scissor.Y != 0 ||
ctx->Scissor.Width < rb->Width ||
ctx->Scissor.Height < rb->Height))
return GL_TRUE;
 
if (!ds_separate && isDS && ctx->DrawBuffer->Visual.stencilBits > 0)
return GL_TRUE;
 
return GL_FALSE;
}
 
 
/**
* Determine if we need to clear the stencil buffer by drawing a quad.
*/
static INLINE GLboolean
check_clear_stencil_with_quad(struct gl_context *ctx, struct gl_renderbuffer *rb,
boolean ds_separate)
{
const struct st_renderbuffer *strb = st_renderbuffer(rb);
const GLboolean isDS = util_format_is_depth_and_stencil(strb->surface->format);
const GLuint stencilMax = 0xff;
const GLboolean maskStencil
= (ctx->Stencil.WriteMask[0] & stencilMax) != stencilMax;
 
assert(rb->Format == MESA_FORMAT_S8 ||
rb->Format == MESA_FORMAT_Z24_S8 ||
rb->Format == MESA_FORMAT_S8_Z24);
 
if (maskStencil)
return GL_TRUE;
 
if (ctx->Scissor.Enabled &&
(ctx->Scissor.X != 0 ||
ctx->Scissor.Y != 0 ||
ctx->Scissor.Width < rb->Width ||
ctx->Scissor.Height < rb->Height))
return GL_TRUE;
 
/* This is correct, but it is necessary to look at the depth clear
* value held in the surface when it comes time to issue the clear,
* rather than taking depth and stencil clear values from the
* current state.
*/
if (!ds_separate && isDS && ctx->DrawBuffer->Visual.depthBits > 0)
return GL_TRUE;
 
return GL_FALSE;
}
 
 
 
/**
* Called when we need to flush.
*/
void
st_flush_clear(struct st_context *st)
{
/* Release vertex buffer to avoid synchronous rendering if we were
* to map it in the next frame.
*/
pipe_resource_reference(&st->clear.vbuf, NULL);
st->clear.vbuf_slot = 0;
}
 
 
/**
* Called via ctx->Driver.Clear()
*/
static void
st_Clear(struct gl_context *ctx, GLbitfield mask)
{
static const GLbitfield BUFFER_BITS_DS
= (BUFFER_BIT_DEPTH | BUFFER_BIT_STENCIL);
struct st_context *st = st_context(ctx);
struct gl_renderbuffer *depthRb
= ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer;
struct gl_renderbuffer *stencilRb
= ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer;
GLbitfield quad_buffers = 0x0;
GLbitfield clear_buffers = 0x0;
GLuint i;
 
/* This makes sure the pipe has the latest scissor, etc values */
st_validate_state( st );
 
if (mask & BUFFER_BITS_COLOR) {
for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) {
GLuint b = ctx->DrawBuffer->_ColorDrawBufferIndexes[i];
 
if (mask & (1 << b)) {
struct gl_renderbuffer *rb
= ctx->DrawBuffer->Attachment[b].Renderbuffer;
struct st_renderbuffer *strb = st_renderbuffer(rb);
 
if (!strb || !strb->surface)
continue;
 
if (check_clear_color_with_quad( ctx, rb ))
quad_buffers |= PIPE_CLEAR_COLOR;
else
clear_buffers |= PIPE_CLEAR_COLOR;
}
}
}
 
if ((mask & BUFFER_BITS_DS) == BUFFER_BITS_DS && depthRb == stencilRb) {
/* clearing combined depth + stencil */
struct st_renderbuffer *strb = st_renderbuffer(depthRb);
 
if (strb->surface) {
if (check_clear_depth_stencil_with_quad(ctx, depthRb))
quad_buffers |= PIPE_CLEAR_DEPTHSTENCIL;
else
clear_buffers |= PIPE_CLEAR_DEPTHSTENCIL;
}
}
else {
/* separate depth/stencil clears */
/* I don't think truly separate buffers are actually possible in gallium or hw? */
if (mask & BUFFER_BIT_DEPTH) {
struct st_renderbuffer *strb = st_renderbuffer(depthRb);
 
if (strb->surface) {
if (check_clear_depth_with_quad(ctx, depthRb,
st->clear.enable_ds_separate))
quad_buffers |= PIPE_CLEAR_DEPTH;
else
clear_buffers |= PIPE_CLEAR_DEPTH;
}
}
if (mask & BUFFER_BIT_STENCIL) {
struct st_renderbuffer *strb = st_renderbuffer(stencilRb);
 
if (strb->surface) {
if (check_clear_stencil_with_quad(ctx, stencilRb,
st->clear.enable_ds_separate))
quad_buffers |= PIPE_CLEAR_STENCIL;
else
clear_buffers |= PIPE_CLEAR_STENCIL;
}
}
}
 
/*
* If we're going to use clear_with_quad() for any reason, use it for
* everything possible.
*/
if (quad_buffers) {
quad_buffers |= clear_buffers;
clear_with_quad(ctx,
quad_buffers & PIPE_CLEAR_COLOR,
quad_buffers & PIPE_CLEAR_DEPTH,
quad_buffers & PIPE_CLEAR_STENCIL);
} else if (clear_buffers) {
/* driver cannot know it can clear everything if the buffer
* is a combined depth/stencil buffer but this wasn't actually
* required from the visual. Hence fix this up to avoid potential
* read-modify-write in the driver.
*/
float clearColor[4];
 
if ((clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) &&
((clear_buffers & PIPE_CLEAR_DEPTHSTENCIL) != PIPE_CLEAR_DEPTHSTENCIL) &&
(depthRb == stencilRb) &&
(ctx->DrawBuffer->Visual.depthBits == 0 ||
ctx->DrawBuffer->Visual.stencilBits == 0))
clear_buffers |= PIPE_CLEAR_DEPTHSTENCIL;
 
st_translate_color(ctx->Color.ClearColor,
ctx->DrawBuffer->_ColorDrawBuffers[0]->_BaseFormat,
clearColor);
 
st->pipe->clear(st->pipe, clear_buffers, ctx->Color.ClearColor,
ctx->Depth.Clear, ctx->Stencil.Clear);
}
if (mask & BUFFER_BIT_ACCUM)
st_clear_accum_buffer(ctx,
ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer);
}
 
 
void
st_init_clear_functions(struct dd_function_table *functions)
{
functions->Clear = st_Clear;
}
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_cb_clear.h
0,0 → 1,52
/**************************************************************************
*
* 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 ST_CB_CLEAR_H
#define ST_CB_CLEAR_H
 
 
struct dd_function_table;
struct st_context;
 
extern void
st_init_clear(struct st_context *st);
 
 
extern void
st_destroy_clear(struct st_context *st);
 
extern void
st_flush_clear(struct st_context *st);
 
 
extern void
st_init_clear_functions(struct dd_function_table *functions);
 
 
#endif /* ST_CB_CLEAR_H */
 
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_cb_condrender.c
0,0 → 1,96
/**************************************************************************
*
* 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 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.
*
**************************************************************************/
 
 
/**
* glBegin/EndCondtionalRender functions
*
* \author Brian Paul
*/
 
 
#include "main/imports.h"
#include "main/context.h"
 
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "st_context.h"
#include "st_cb_queryobj.h"
#include "st_cb_condrender.h"
 
 
/**
* Called via ctx->Driver.BeginConditionalRender()
*/
static void
st_BeginConditionalRender(struct gl_context *ctx, struct gl_query_object *q,
GLenum mode)
{
struct st_query_object *stq = st_query_object(q);
struct pipe_context *pipe = st_context(ctx)->pipe;
uint m;
 
switch (mode) {
case GL_QUERY_WAIT:
m = PIPE_RENDER_COND_WAIT;
break;
case GL_QUERY_NO_WAIT:
m = PIPE_RENDER_COND_NO_WAIT;
break;
case GL_QUERY_BY_REGION_WAIT:
m = PIPE_RENDER_COND_BY_REGION_WAIT;
break;
case GL_QUERY_BY_REGION_NO_WAIT:
m = PIPE_RENDER_COND_BY_REGION_NO_WAIT;
break;
default:
assert(0 && "bad mode in st_BeginConditionalRender");
m = PIPE_RENDER_COND_WAIT;
}
 
pipe->render_condition(pipe, stq->pq, m);
}
 
 
/**
* Called via ctx->Driver.BeginConditionalRender()
*/
static void
st_EndConditionalRender(struct gl_context *ctx, struct gl_query_object *q)
{
struct pipe_context *pipe = st_context(ctx)->pipe;
(void) q;
pipe->render_condition(pipe, NULL, 0);
}
 
 
 
void st_init_cond_render_functions(struct dd_function_table *functions)
{
functions->BeginConditionalRender = st_BeginConditionalRender;
functions->EndConditionalRender = st_EndConditionalRender;
}
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_cb_condrender.h
0,0 → 1,37
/**************************************************************************
*
* 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 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 ST_CB_CONDRENDER_H
#define ST_CB_CONDRENDER_H
 
 
struct dd_function_table;
 
extern void st_init_cond_render_functions(struct dd_function_table *functions);
 
 
#endif
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_cb_drawpixels.c
0,0 → 1,1308
/**************************************************************************
*
* 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 "main/imports.h"
#include "main/image.h"
#include "main/bufferobj.h"
#include "main/macros.h"
#include "main/pack.h"
#include "main/texformat.h"
#include "main/texstore.h"
#include "program/program.h"
#include "program/prog_print.h"
#include "program/prog_instruction.h"
 
#include "st_atom.h"
#include "st_atom_constbuf.h"
#include "st_cb_drawpixels.h"
#include "st_cb_readpixels.h"
#include "st_cb_fbo.h"
#include "st_context.h"
#include "st_debug.h"
#include "st_format.h"
#include "st_program.h"
#include "st_texture.h"
 
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "tgsi/tgsi_ureg.h"
#include "util/u_draw_quad.h"
#include "util/u_format.h"
#include "util/u_inlines.h"
#include "util/u_math.h"
#include "util/u_tile.h"
#include "cso_cache/cso_context.h"
 
 
#if FEATURE_drawpix
 
/**
* Check if the given program is:
* 0: MOVE result.color, fragment.color;
* 1: END;
*/
static GLboolean
is_passthrough_program(const struct gl_fragment_program *prog)
{
if (prog->Base.NumInstructions == 2) {
const struct prog_instruction *inst = prog->Base.Instructions;
if (inst[0].Opcode == OPCODE_MOV &&
inst[1].Opcode == OPCODE_END &&
inst[0].DstReg.File == PROGRAM_OUTPUT &&
inst[0].DstReg.Index == FRAG_RESULT_COLOR &&
inst[0].DstReg.WriteMask == WRITEMASK_XYZW &&
inst[0].SrcReg[0].File == PROGRAM_INPUT &&
inst[0].SrcReg[0].Index == FRAG_ATTRIB_COL0 &&
inst[0].SrcReg[0].Swizzle == SWIZZLE_XYZW) {
return GL_TRUE;
}
}
return GL_FALSE;
}
 
 
 
/**
* Make fragment shader for glDraw/CopyPixels. This shader is made
* by combining the pixel transfer shader with the user-defined shader.
* \return pointer to Gallium driver fragment shader
*/
static void *
combined_drawpix_fragment_program(struct gl_context *ctx)
{
struct st_context *st = st_context(ctx);
struct st_fragment_program *stfp;
 
if (st->pixel_xfer.program->serialNo == st->pixel_xfer.xfer_prog_sn
&& st->fp->serialNo == st->pixel_xfer.user_prog_sn) {
/* the pixel tranfer program has not changed and the user-defined
* program has not changed, so re-use the combined program.
*/
stfp = st->pixel_xfer.combined_prog;
}
else {
/* Concatenate the pixel transfer program with the current user-
* defined program.
*/
if (is_passthrough_program(&st->fp->Base)) {
stfp = (struct st_fragment_program *)
_mesa_clone_fragment_program(ctx, &st->pixel_xfer.program->Base);
}
else {
#if 0
printf("Base program:\n");
_mesa_print_program(&st->fp->Base.Base);
printf("DrawPix program:\n");
_mesa_print_program(&st->pixel_xfer.program->Base.Base);
#endif
stfp = (struct st_fragment_program *)
_mesa_combine_programs(ctx,
&st->pixel_xfer.program->Base.Base,
&st->fp->Base.Base);
}
 
#if 0
{
struct gl_program *p = &stfp->Base.Base;
printf("Combined DrawPixels program:\n");
_mesa_print_program(p);
printf("InputsRead: 0x%x\n", p->InputsRead);
printf("OutputsWritten: 0x%x\n", p->OutputsWritten);
_mesa_print_parameter_list(p->Parameters);
}
#endif
 
/* translate to TGSI tokens */
st_translate_fragment_program(st, stfp);
 
/* save new program, update serial numbers */
st->pixel_xfer.xfer_prog_sn = st->pixel_xfer.program->serialNo;
st->pixel_xfer.user_prog_sn = st->fp->serialNo;
st->pixel_xfer.combined_prog_sn = stfp->serialNo;
/* can't reference new program directly, already have a reference on it */
st_reference_fragprog(st, &st->pixel_xfer.combined_prog, NULL);
st->pixel_xfer.combined_prog = stfp;
}
 
/* Ideally we'd have updated the pipe constants during the normal
* st/atom mechanism. But we can't since this is specific to glDrawPixels.
*/
st_upload_constants(st, stfp->Base.Base.Parameters, PIPE_SHADER_FRAGMENT);
 
return stfp->driver_shader;
}
 
 
/**
* Create fragment shader that does a TEX() instruction to get a Z and/or
* stencil value value, then writes to FRAG_RESULT_DEPTH/FRAG_RESULT_STENCIL.
* Used for glDrawPixels(GL_DEPTH_COMPONENT / GL_STENCIL_INDEX).
* Pass fragment color through as-is.
* \return pointer to the Gallium driver fragment shader
*/
static void *
make_fragment_shader_z_stencil(struct st_context *st, GLboolean write_depth,
GLboolean write_stencil)
{
struct gl_context *ctx = st->ctx;
struct gl_program *p;
struct st_fragment_program *stp;
GLuint ic = 0;
const GLuint shaderIndex = write_depth * 2 + write_stencil;
 
assert(shaderIndex < Elements(st->drawpix.shaders));
 
if (st->drawpix.shaders[shaderIndex]) {
/* already have the proper shader */
return st->drawpix.shaders[shaderIndex]->driver_shader;
}
 
/*
* Create shader now
*/
p = ctx->Driver.NewProgram(ctx, GL_FRAGMENT_PROGRAM_ARB, 0);
if (!p)
return NULL;
 
p->NumInstructions = write_depth ? 2 : 1;
p->NumInstructions += write_stencil ? 1 : 0;
 
p->Instructions = _mesa_alloc_instructions(p->NumInstructions);
if (!p->Instructions) {
ctx->Driver.DeleteProgram(ctx, p);
return NULL;
}
_mesa_init_instructions(p->Instructions, p->NumInstructions);
 
if (write_depth) {
/* TEX result.depth, fragment.texcoord[0], texture[0], 2D; */
p->Instructions[ic].Opcode = OPCODE_TEX;
p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT;
p->Instructions[ic].DstReg.Index = FRAG_RESULT_DEPTH;
p->Instructions[ic].DstReg.WriteMask = WRITEMASK_Z;
p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_TEX0;
p->Instructions[ic].TexSrcUnit = 0;
p->Instructions[ic].TexSrcTarget = TEXTURE_2D_INDEX;
ic++;
}
 
if (write_stencil) {
/* TEX result.stencil, fragment.texcoord[0], texture[0], 2D; */
p->Instructions[ic].Opcode = OPCODE_TEX;
p->Instructions[ic].DstReg.File = PROGRAM_OUTPUT;
p->Instructions[ic].DstReg.Index = FRAG_RESULT_STENCIL;
p->Instructions[ic].DstReg.WriteMask = WRITEMASK_Y;
p->Instructions[ic].SrcReg[0].File = PROGRAM_INPUT;
p->Instructions[ic].SrcReg[0].Index = FRAG_ATTRIB_TEX0;
p->Instructions[ic].TexSrcUnit = 1;
p->Instructions[ic].TexSrcTarget = TEXTURE_2D_INDEX;
ic++;
}
 
/* END; */
p->Instructions[ic++].Opcode = OPCODE_END;
 
assert(ic == p->NumInstructions);
 
p->InputsRead = FRAG_BIT_TEX0 | FRAG_BIT_COL0;
p->OutputsWritten = 0;
if (write_depth)
p->OutputsWritten |= (1 << FRAG_RESULT_DEPTH);
if (write_stencil)
p->OutputsWritten |= (1 << FRAG_RESULT_STENCIL);
 
p->SamplersUsed = 0x1; /* sampler 0 (bit 0) is used */
if (write_stencil)
p->SamplersUsed |= 1 << 1;
 
stp = st_fragment_program((struct gl_fragment_program *) p);
 
/* save the new shader */
st->drawpix.shaders[shaderIndex] = stp;
 
st_translate_fragment_program(st, stp);
 
return stp->driver_shader;
}
 
 
 
/**
* Create a simple vertex shader that just passes through the
* vertex position and texcoord (and optionally, color).
*/
static void *
make_passthrough_vertex_shader(struct st_context *st,
GLboolean passColor)
{
if (!st->drawpix.vert_shaders[passColor]) {
struct ureg_program *ureg = ureg_create( TGSI_PROCESSOR_VERTEX );
 
if (ureg == NULL)
return NULL;
 
/* MOV result.pos, vertex.pos; */
ureg_MOV(ureg,
ureg_DECL_output( ureg, TGSI_SEMANTIC_POSITION, 0 ),
ureg_DECL_vs_input( ureg, 0 ));
/* MOV result.texcoord0, vertex.attr[1]; */
ureg_MOV(ureg,
ureg_DECL_output( ureg, TGSI_SEMANTIC_GENERIC, 0 ),
ureg_DECL_vs_input( ureg, 1 ));
if (passColor) {
/* MOV result.color0, vertex.attr[2]; */
ureg_MOV(ureg,
ureg_DECL_output( ureg, TGSI_SEMANTIC_COLOR, 0 ),
ureg_DECL_vs_input( ureg, 2 ));
}
 
ureg_END( ureg );
st->drawpix.vert_shaders[passColor] =
ureg_create_shader_and_destroy( ureg, st->pipe );
}
 
return st->drawpix.vert_shaders[passColor];
}
 
 
/**
* Return a texture base format for drawing/copying an image
* of the given format.
*/
static GLenum
base_format(GLenum format)
{
switch (format) {
case GL_DEPTH_COMPONENT:
return GL_DEPTH_COMPONENT;
case GL_DEPTH_STENCIL:
return GL_DEPTH_STENCIL;
case GL_STENCIL_INDEX:
return GL_STENCIL_INDEX;
default:
return GL_RGBA;
}
}
 
 
/**
* Return a texture internalFormat for drawing/copying an image
* of the given format and type.
*/
static GLenum
internal_format(GLenum format, GLenum type)
{
switch (format) {
case GL_DEPTH_COMPONENT:
return GL_DEPTH_COMPONENT;
case GL_DEPTH_STENCIL:
return GL_DEPTH_STENCIL;
case GL_STENCIL_INDEX:
return GL_STENCIL_INDEX;
default:
if (_mesa_is_integer_format(format)) {
switch (type) {
case GL_BYTE:
return GL_RGBA8I;
case GL_UNSIGNED_BYTE:
return GL_RGBA8UI;
case GL_SHORT:
return GL_RGBA16I;
case GL_UNSIGNED_SHORT:
return GL_RGBA16UI;
case GL_INT:
return GL_RGBA32I;
case GL_UNSIGNED_INT:
return GL_RGBA32UI;
default:
assert(0 && "Unexpected type in internal_format()");
return GL_RGBA_INTEGER;
}
}
else {
return GL_RGBA;
}
}
}
 
 
/**
* Create a temporary texture to hold an image of the given size.
* If width, height are not POT and the driver only handles POT textures,
* allocate the next larger size of texture that is POT.
*/
static struct pipe_resource *
alloc_texture(struct st_context *st, GLsizei width, GLsizei height,
enum pipe_format texFormat)
{
struct pipe_resource *pt;
 
pt = st_texture_create(st, st->internal_target, texFormat, 0,
width, height, 1, PIPE_BIND_SAMPLER_VIEW);
 
return pt;
}
 
 
/**
* Make texture containing an image for glDrawPixels image.
* If 'pixels' is NULL, leave the texture image data undefined.
*/
static struct pipe_resource *
make_texture(struct st_context *st,
GLsizei width, GLsizei height, GLenum format, GLenum type,
const struct gl_pixelstore_attrib *unpack,
const GLvoid *pixels)
{
struct gl_context *ctx = st->ctx;
struct pipe_context *pipe = st->pipe;
gl_format mformat;
struct pipe_resource *pt;
enum pipe_format pipeFormat;
GLuint cpp;
GLenum baseFormat, intFormat;
 
baseFormat = base_format(format);
intFormat = internal_format(format, type);
 
mformat = st_ChooseTextureFormat_renderable(ctx, intFormat,
format, type, GL_FALSE);
assert(mformat);
 
pipeFormat = st_mesa_format_to_pipe_format(mformat);
assert(pipeFormat);
cpp = util_format_get_blocksize(pipeFormat);
 
pixels = _mesa_map_pbo_source(ctx, unpack, pixels);
if (!pixels)
return NULL;
 
/* alloc temporary texture */
pt = alloc_texture(st, width, height, pipeFormat);
if (!pt) {
_mesa_unmap_pbo_source(ctx, unpack);
return NULL;
}
 
{
struct pipe_transfer *transfer;
static const GLuint dstImageOffsets = 0;
GLboolean success;
GLubyte *dest;
const GLbitfield imageTransferStateSave = ctx->_ImageTransferState;
 
/* we'll do pixel transfer in a fragment shader */
ctx->_ImageTransferState = 0x0;
 
transfer = pipe_get_transfer(st->pipe, pt, 0, 0,
PIPE_TRANSFER_WRITE, 0, 0,
width, height);
 
/* map texture transfer */
dest = pipe_transfer_map(pipe, transfer);
 
 
/* Put image into texture transfer.
* Note that the image is actually going to be upside down in
* the texture. We deal with that with texcoords.
*/
success = _mesa_texstore(ctx, 2, /* dims */
baseFormat, /* baseInternalFormat */
mformat, /* gl_format */
dest, /* dest */
0, 0, 0, /* dstX/Y/Zoffset */
transfer->stride, /* dstRowStride, bytes */
&dstImageOffsets, /* dstImageOffsets */
width, height, 1, /* size */
format, type, /* src format/type */
pixels, /* data source */
unpack);
 
/* unmap */
pipe_transfer_unmap(pipe, transfer);
pipe->transfer_destroy(pipe, transfer);
 
assert(success);
 
/* restore */
ctx->_ImageTransferState = imageTransferStateSave;
}
 
_mesa_unmap_pbo_source(ctx, unpack);
 
return pt;
}
 
 
/**
* Draw quad with texcoords and optional color.
* Coords are gallium window coords with y=0=top.
* \param color may be null
* \param invertTex if true, flip texcoords vertically
*/
static void
draw_quad(struct gl_context *ctx, GLfloat x0, GLfloat y0, GLfloat z,
GLfloat x1, GLfloat y1, const GLfloat *color,
GLboolean invertTex, GLfloat maxXcoord, GLfloat maxYcoord)
{
struct st_context *st = st_context(ctx);
struct pipe_context *pipe = st->pipe;
GLfloat verts[4][3][4]; /* four verts, three attribs, XYZW */
 
/* setup vertex data */
{
const struct gl_framebuffer *fb = st->ctx->DrawBuffer;
const GLfloat fb_width = (GLfloat) fb->Width;
const GLfloat fb_height = (GLfloat) fb->Height;
const GLfloat clip_x0 = x0 / fb_width * 2.0f - 1.0f;
const GLfloat clip_y0 = y0 / fb_height * 2.0f - 1.0f;
const GLfloat clip_x1 = x1 / fb_width * 2.0f - 1.0f;
const GLfloat clip_y1 = y1 / fb_height * 2.0f - 1.0f;
const GLfloat sLeft = 0.0f, sRight = maxXcoord;
const GLfloat tTop = invertTex ? maxYcoord : 0.0f;
const GLfloat tBot = invertTex ? 0.0f : maxYcoord;
GLuint i;
 
/* upper-left */
verts[0][0][0] = clip_x0; /* v[0].attr[0].x */
verts[0][0][1] = clip_y0; /* v[0].attr[0].y */
 
/* upper-right */
verts[1][0][0] = clip_x1;
verts[1][0][1] = clip_y0;
 
/* lower-right */
verts[2][0][0] = clip_x1;
verts[2][0][1] = clip_y1;
 
/* lower-left */
verts[3][0][0] = clip_x0;
verts[3][0][1] = clip_y1;
 
verts[0][1][0] = sLeft; /* v[0].attr[1].S */
verts[0][1][1] = tTop; /* v[0].attr[1].T */
verts[1][1][0] = sRight;
verts[1][1][1] = tTop;
verts[2][1][0] = sRight;
verts[2][1][1] = tBot;
verts[3][1][0] = sLeft;
verts[3][1][1] = tBot;
 
/* same for all verts: */
if (color) {
for (i = 0; i < 4; i++) {
verts[i][0][2] = z; /* v[i].attr[0].z */
verts[i][0][3] = 1.0f; /* v[i].attr[0].w */
verts[i][2][0] = color[0]; /* v[i].attr[2].r */
verts[i][2][1] = color[1]; /* v[i].attr[2].g */
verts[i][2][2] = color[2]; /* v[i].attr[2].b */
verts[i][2][3] = color[3]; /* v[i].attr[2].a */
verts[i][1][2] = 0.0f; /* v[i].attr[1].R */
verts[i][1][3] = 1.0f; /* v[i].attr[1].Q */
}
}
else {
for (i = 0; i < 4; i++) {
verts[i][0][2] = z; /*Z*/
verts[i][0][3] = 1.0f; /*W*/
verts[i][1][2] = 0.0f; /*R*/
verts[i][1][3] = 1.0f; /*Q*/
}
}
}
 
{
struct pipe_resource *buf;
 
/* allocate/load buffer object with vertex data */
buf = pipe_buffer_create(pipe->screen,
PIPE_BIND_VERTEX_BUFFER,
sizeof(verts));
pipe_buffer_write(st->pipe, buf, 0, sizeof(verts), verts);
 
util_draw_vertex_buffer(pipe, buf, 0,
PIPE_PRIM_QUADS,
4, /* verts */
3); /* attribs/vert */
pipe_resource_reference(&buf, NULL);
}
}
 
 
 
static void
draw_textured_quad(struct gl_context *ctx, GLint x, GLint y, GLfloat z,
GLsizei width, GLsizei height,
GLfloat zoomX, GLfloat zoomY,
struct pipe_sampler_view **sv,
int num_sampler_view,
void *driver_vp,
void *driver_fp,
const GLfloat *color,
GLboolean invertTex,
GLboolean write_depth, GLboolean write_stencil)
{
struct st_context *st = st_context(ctx);
struct pipe_context *pipe = st->pipe;
struct cso_context *cso = st->cso_context;
GLfloat x0, y0, x1, y1;
GLsizei maxSize;
boolean normalized = sv[0]->texture->target != PIPE_TEXTURE_RECT;
 
/* limit checks */
/* XXX if DrawPixels image is larger than max texture size, break
* it up into chunks.
*/
maxSize = 1 << (pipe->screen->get_param(pipe->screen,
PIPE_CAP_MAX_TEXTURE_2D_LEVELS) - 1);
assert(width <= maxSize);
assert(height <= maxSize);
 
cso_save_rasterizer(cso);
cso_save_viewport(cso);
cso_save_samplers(cso);
cso_save_fragment_sampler_views(cso);
cso_save_fragment_shader(cso);
cso_save_vertex_shader(cso);
cso_save_vertex_elements(cso);
if (write_stencil) {
cso_save_depth_stencil_alpha(cso);
cso_save_blend(cso);
}
 
/* rasterizer state: just scissor */
{
struct pipe_rasterizer_state rasterizer;
memset(&rasterizer, 0, sizeof(rasterizer));
rasterizer.gl_rasterization_rules = 1;
rasterizer.scissor = ctx->Scissor.Enabled;
cso_set_rasterizer(cso, &rasterizer);
}
 
if (write_stencil) {
/* Stencil writing bypasses the normal fragment pipeline to
* disable color writing and set stencil test to always pass.
*/
struct pipe_depth_stencil_alpha_state dsa;
struct pipe_blend_state blend;
 
/* depth/stencil */
memset(&dsa, 0, sizeof(dsa));
dsa.stencil[0].enabled = 1;
dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
dsa.stencil[0].writemask = ctx->Stencil.WriteMask[0] & 0xff;
dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
if (write_depth) {
/* writing depth+stencil: depth test always passes */
dsa.depth.enabled = 1;
dsa.depth.writemask = ctx->Depth.Mask;
dsa.depth.func = PIPE_FUNC_ALWAYS;
}
cso_set_depth_stencil_alpha(cso, &dsa);
 
/* blend (colormask) */
memset(&blend, 0, sizeof(blend));
cso_set_blend(cso, &blend);
}
 
/* fragment shader state: TEX lookup program */
cso_set_fragment_shader_handle(cso, driver_fp);
 
/* vertex shader state: position + texcoord pass-through */
cso_set_vertex_shader_handle(cso, driver_vp);
 
 
/* texture sampling state: */
{
struct pipe_sampler_state sampler;
memset(&sampler, 0, sizeof(sampler));
sampler.wrap_s = PIPE_TEX_WRAP_CLAMP;
sampler.wrap_t = PIPE_TEX_WRAP_CLAMP;
sampler.wrap_r = PIPE_TEX_WRAP_CLAMP;
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.normalized_coords = normalized;
 
cso_single_sampler(cso, 0, &sampler);
if (num_sampler_view > 1) {
cso_single_sampler(cso, 1, &sampler);
}
cso_single_sampler_done(cso);
}
 
/* viewport state: viewport matching window dims */
{
const float w = (float) ctx->DrawBuffer->Width;
const float h = (float) ctx->DrawBuffer->Height;
struct pipe_viewport_state vp;
vp.scale[0] = 0.5f * w;
vp.scale[1] = -0.5f * h;
vp.scale[2] = 0.5f;
vp.scale[3] = 1.0f;
vp.translate[0] = 0.5f * w;
vp.translate[1] = 0.5f * h;
vp.translate[2] = 0.5f;
vp.translate[3] = 0.0f;
cso_set_viewport(cso, &vp);
}
 
cso_set_vertex_elements(cso, 3, st->velems_util_draw);
 
/* texture state: */
cso_set_fragment_sampler_views(cso, num_sampler_view, sv);
 
/* Compute Gallium window coords (y=0=top) with pixel zoom.
* Recall that these coords are transformed by the current
* vertex shader and viewport transformation.
*/
if (st_fb_orientation(ctx->DrawBuffer) == Y_0_BOTTOM) {
y = ctx->DrawBuffer->Height - (int) (y + height * ctx->Pixel.ZoomY);
invertTex = !invertTex;
}
 
x0 = (GLfloat) x;
x1 = x + width * ctx->Pixel.ZoomX;
y0 = (GLfloat) y;
y1 = y + height * ctx->Pixel.ZoomY;
 
/* convert Z from [0,1] to [-1,-1] to match viewport Z scale/bias */
z = z * 2.0 - 1.0;
 
draw_quad(ctx, x0, y0, z, x1, y1, color, invertTex,
normalized ? ((GLfloat) width / sv[0]->texture->width0) : (GLfloat)width,
normalized ? ((GLfloat) height / sv[0]->texture->height0) : (GLfloat)height);
 
/* restore state */
cso_restore_rasterizer(cso);
cso_restore_viewport(cso);
cso_restore_samplers(cso);
cso_restore_fragment_sampler_views(cso);
cso_restore_fragment_shader(cso);
cso_restore_vertex_shader(cso);
cso_restore_vertex_elements(cso);
if (write_stencil) {
cso_restore_depth_stencil_alpha(cso);
cso_restore_blend(cso);
}
}
 
 
/**
* Software fallback to do glDrawPixels(GL_STENCIL_INDEX) when we
* can't use a fragment shader to write stencil values.
*/
static void
draw_stencil_pixels(struct gl_context *ctx, GLint x, GLint y,
GLsizei width, GLsizei height, GLenum format, GLenum type,
const struct gl_pixelstore_attrib *unpack,
const GLvoid *pixels)
{
struct st_context *st = st_context(ctx);
struct pipe_context *pipe = st->pipe;
struct st_renderbuffer *strb;
enum pipe_transfer_usage usage;
struct pipe_transfer *pt;
const GLboolean zoom = ctx->Pixel.ZoomX != 1.0 || ctx->Pixel.ZoomY != 1.0;
GLint skipPixels;
ubyte *stmap;
struct gl_pixelstore_attrib clippedUnpack = *unpack;
 
if (!zoom) {
if (!_mesa_clip_drawpixels(ctx, &x, &y, &width, &height,
&clippedUnpack)) {
/* totally clipped */
return;
}
}
 
strb = st_renderbuffer(ctx->DrawBuffer->
Attachment[BUFFER_STENCIL].Renderbuffer);
 
if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
y = ctx->DrawBuffer->Height - y - height;
}
 
if(format != GL_DEPTH_STENCIL &&
util_format_get_component_bits(strb->format,
UTIL_FORMAT_COLORSPACE_ZS, 0) != 0)
usage = PIPE_TRANSFER_READ_WRITE;
else
usage = PIPE_TRANSFER_WRITE;
 
pt = pipe_get_transfer(st_context(ctx)->pipe, strb->texture, 0, 0,
usage, x, y,
width, height);
 
stmap = pipe_transfer_map(pipe, pt);
 
pixels = _mesa_map_pbo_source(ctx, &clippedUnpack, pixels);
assert(pixels);
 
/* if width > MAX_WIDTH, have to process image in chunks */
skipPixels = 0;
while (skipPixels < width) {
const GLint spanX = skipPixels;
const GLint spanWidth = MIN2(width - skipPixels, MAX_WIDTH);
GLint row;
for (row = 0; row < height; row++) {
GLubyte sValues[MAX_WIDTH];
GLuint zValues[MAX_WIDTH];
GLenum destType = GL_UNSIGNED_BYTE;
const GLvoid *source = _mesa_image_address2d(&clippedUnpack, pixels,
width, height,
format, type,
row, skipPixels);
_mesa_unpack_stencil_span(ctx, spanWidth, destType, sValues,
type, source, &clippedUnpack,
ctx->_ImageTransferState);
 
if (format == GL_DEPTH_STENCIL) {
_mesa_unpack_depth_span(ctx, spanWidth, GL_UNSIGNED_INT, zValues,
(1 << 24) - 1, type, source,
&clippedUnpack);
}
 
if (zoom) {
_mesa_problem(ctx, "Gallium glDrawPixels(GL_STENCIL) with "
"zoom not complete");
}
 
{
GLint spanY;
 
if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
spanY = height - row - 1;
}
else {
spanY = row;
}
 
/* now pack the stencil (and Z) values in the dest format */
switch (pt->resource->format) {
case PIPE_FORMAT_S8_USCALED:
{
ubyte *dest = stmap + spanY * pt->stride + spanX;
assert(usage == PIPE_TRANSFER_WRITE);
memcpy(dest, sValues, spanWidth);
}
break;
case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
if (format == GL_DEPTH_STENCIL) {
uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4);
GLint k;
assert(usage == PIPE_TRANSFER_WRITE);
for (k = 0; k < spanWidth; k++) {
dest[k] = zValues[k] | (sValues[k] << 24);
}
}
else {
uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4);
GLint k;
assert(usage == PIPE_TRANSFER_READ_WRITE);
for (k = 0; k < spanWidth; k++) {
dest[k] = (dest[k] & 0xffffff) | (sValues[k] << 24);
}
}
break;
case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
if (format == GL_DEPTH_STENCIL) {
uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4);
GLint k;
assert(usage == PIPE_TRANSFER_WRITE);
for (k = 0; k < spanWidth; k++) {
dest[k] = (zValues[k] << 8) | (sValues[k] & 0xff);
}
}
else {
uint *dest = (uint *) (stmap + spanY * pt->stride + spanX*4);
GLint k;
assert(usage == PIPE_TRANSFER_READ_WRITE);
for (k = 0; k < spanWidth; k++) {
dest[k] = (dest[k] & 0xffffff00) | (sValues[k] & 0xff);
}
}
break;
default:
assert(0);
}
}
}
skipPixels += spanWidth;
}
 
_mesa_unmap_pbo_source(ctx, &clippedUnpack);
 
/* unmap the stencil buffer */
pipe_transfer_unmap(pipe, pt);
pipe->transfer_destroy(pipe, pt);
}
 
 
/**
* Called via ctx->Driver.DrawPixels()
*/
static void
st_DrawPixels(struct gl_context *ctx, GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *unpack, const GLvoid *pixels)
{
void *driver_vp, *driver_fp;
struct st_context *st = st_context(ctx);
const GLfloat *color;
struct pipe_context *pipe = st->pipe;
GLboolean write_stencil = GL_FALSE, write_depth = GL_FALSE;
struct pipe_sampler_view *sv[2];
int num_sampler_view = 1;
enum pipe_format stencil_format = PIPE_FORMAT_NONE;
 
if (format == GL_DEPTH_STENCIL)
write_stencil = write_depth = GL_TRUE;
else if (format == GL_STENCIL_INDEX)
write_stencil = GL_TRUE;
else if (format == GL_DEPTH_COMPONENT)
write_depth = GL_TRUE;
 
if (write_stencil) {
enum pipe_format tex_format;
/* can we write to stencil if not fallback */
if (!pipe->screen->get_param(pipe->screen, PIPE_CAP_SHADER_STENCIL_EXPORT))
goto stencil_fallback;
tex_format = st_choose_format(st->pipe->screen, base_format(format),
PIPE_TEXTURE_2D,
0, PIPE_BIND_SAMPLER_VIEW);
if (tex_format == PIPE_FORMAT_Z24_UNORM_S8_USCALED)
stencil_format = PIPE_FORMAT_X24S8_USCALED;
else if (tex_format == PIPE_FORMAT_S8_USCALED_Z24_UNORM)
stencil_format = PIPE_FORMAT_S8X24_USCALED;
else
stencil_format = PIPE_FORMAT_S8_USCALED;
if (stencil_format == PIPE_FORMAT_NONE)
goto stencil_fallback;
}
 
/* Mesa state should be up to date by now */
assert(ctx->NewState == 0x0);
 
st_validate_state(st);
 
if (write_depth || write_stencil) {
driver_fp = make_fragment_shader_z_stencil(st, write_depth, write_stencil);
driver_vp = make_passthrough_vertex_shader(st, GL_TRUE);
color = ctx->Current.RasterColor;
}
else {
driver_fp = combined_drawpix_fragment_program(ctx);
driver_vp = make_passthrough_vertex_shader(st, GL_FALSE);
color = NULL;
if (st->pixel_xfer.pixelmap_enabled) {
sv[1] = st->pixel_xfer.pixelmap_sampler_view;
num_sampler_view++;
}
}
 
/* draw with textured quad */
{
struct pipe_resource *pt
= make_texture(st, width, height, format, type, unpack, pixels);
if (pt) {
sv[0] = st_create_texture_sampler_view(st->pipe, pt);
 
if (sv[0]) {
if (write_stencil) {
sv[1] = st_create_texture_sampler_view_format(st->pipe, pt,
stencil_format);
num_sampler_view++;
}
 
draw_textured_quad(ctx, x, y, ctx->Current.RasterPos[2],
width, height,
ctx->Pixel.ZoomX, ctx->Pixel.ZoomY,
sv,
num_sampler_view,
driver_vp,
driver_fp,
color, GL_FALSE, write_depth, write_stencil);
pipe_sampler_view_reference(&sv[0], NULL);
if (num_sampler_view > 1)
pipe_sampler_view_reference(&sv[1], NULL);
}
pipe_resource_reference(&pt, NULL);
}
}
return;
 
stencil_fallback:
draw_stencil_pixels(ctx, x, y, width, height, format, type,
unpack, pixels);
}
 
 
 
/**
* Software fallback for glCopyPixels(GL_STENCIL).
*/
static void
copy_stencil_pixels(struct gl_context *ctx, GLint srcx, GLint srcy,
GLsizei width, GLsizei height,
GLint dstx, GLint dsty)
{
struct st_renderbuffer *rbDraw;
struct pipe_context *pipe = st_context(ctx)->pipe;
enum pipe_transfer_usage usage;
struct pipe_transfer *ptDraw;
ubyte *drawMap;
ubyte *buffer;
int i;
 
buffer = malloc(width * height * sizeof(ubyte));
if (!buffer) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glCopyPixels(stencil)");
return;
}
 
/* Get the dest renderbuffer. If there's a wrapper, use the
* underlying renderbuffer.
*/
rbDraw = st_renderbuffer(ctx->DrawBuffer->_StencilBuffer);
if (rbDraw->Base.Wrapped)
rbDraw = st_renderbuffer(rbDraw->Base.Wrapped);
 
/* this will do stencil pixel transfer ops */
st_read_stencil_pixels(ctx, srcx, srcy, width, height,
GL_STENCIL_INDEX, GL_UNSIGNED_BYTE,
&ctx->DefaultPacking, buffer);
 
if (0) {
/* debug code: dump stencil values */
GLint row, col;
for (row = 0; row < height; row++) {
printf("%3d: ", row);
for (col = 0; col < width; col++) {
printf("%02x ", buffer[col + row * width]);
}
printf("\n");
}
}
 
if (util_format_get_component_bits(rbDraw->format,
UTIL_FORMAT_COLORSPACE_ZS, 0) != 0)
usage = PIPE_TRANSFER_READ_WRITE;
else
usage = PIPE_TRANSFER_WRITE;
 
if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
dsty = rbDraw->Base.Height - dsty - height;
}
 
ptDraw = pipe_get_transfer(st_context(ctx)->pipe,
rbDraw->texture, 0, 0,
usage, dstx, dsty,
width, height);
 
assert(util_format_get_blockwidth(ptDraw->resource->format) == 1);
assert(util_format_get_blockheight(ptDraw->resource->format) == 1);
 
/* map the stencil buffer */
drawMap = pipe_transfer_map(pipe, ptDraw);
 
/* draw */
/* XXX PixelZoom not handled yet */
for (i = 0; i < height; i++) {
ubyte *dst;
const ubyte *src;
int y;
 
y = i;
 
if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
y = height - y - 1;
}
 
dst = drawMap + y * ptDraw->stride;
src = buffer + i * width;
 
switch (ptDraw->resource->format) {
case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
{
uint *dst4 = (uint *) dst;
int j;
assert(usage == PIPE_TRANSFER_READ_WRITE);
for (j = 0; j < width; j++) {
*dst4 = (*dst4 & 0xffffff) | (src[j] << 24);
dst4++;
}
}
break;
case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
{
uint *dst4 = (uint *) dst;
int j;
assert(usage == PIPE_TRANSFER_READ_WRITE);
for (j = 0; j < width; j++) {
*dst4 = (*dst4 & 0xffffff00) | (src[j] & 0xff);
dst4++;
}
}
break;
case PIPE_FORMAT_S8_USCALED:
assert(usage == PIPE_TRANSFER_WRITE);
memcpy(dst, src, width);
break;
default:
assert(0);
}
}
 
free(buffer);
 
/* unmap the stencil buffer */
pipe_transfer_unmap(pipe, ptDraw);
pipe->transfer_destroy(pipe, ptDraw);
}
 
 
static void
st_CopyPixels(struct gl_context *ctx, GLint srcx, GLint srcy,
GLsizei width, GLsizei height,
GLint dstx, GLint dsty, GLenum type)
{
struct st_context *st = st_context(ctx);
struct pipe_context *pipe = st->pipe;
struct pipe_screen *screen = pipe->screen;
struct st_renderbuffer *rbRead;
void *driver_vp, *driver_fp;
struct pipe_resource *pt;
struct pipe_sampler_view *sv[2];
int num_sampler_view = 1;
GLfloat *color;
enum pipe_format srcFormat, texFormat;
GLboolean invertTex = GL_FALSE;
GLint readX, readY, readW, readH;
GLuint sample_count;
struct gl_pixelstore_attrib pack = ctx->DefaultPacking;
 
st_validate_state(st);
 
if (type == GL_STENCIL) {
/* can't use texturing to do stencil */
copy_stencil_pixels(ctx, srcx, srcy, width, height, dstx, dsty);
return;
}
 
if (type == GL_COLOR) {
rbRead = st_get_color_read_renderbuffer(ctx);
color = NULL;
driver_fp = combined_drawpix_fragment_program(ctx);
driver_vp = make_passthrough_vertex_shader(st, GL_FALSE);
if (st->pixel_xfer.pixelmap_enabled) {
sv[1] = st->pixel_xfer.pixelmap_sampler_view;
num_sampler_view++;
}
}
else {
assert(type == GL_DEPTH);
rbRead = st_renderbuffer(ctx->ReadBuffer->_DepthBuffer);
color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
driver_fp = make_fragment_shader_z_stencil(st, GL_TRUE, GL_FALSE);
driver_vp = make_passthrough_vertex_shader(st, GL_TRUE);
}
 
if (rbRead->Base.Wrapped)
rbRead = st_renderbuffer(rbRead->Base.Wrapped);
 
sample_count = rbRead->texture->nr_samples;
/* I believe this would be legal, presumably would need to do a resolve
for color, and for depth/stencil spec says to just use one of the
depth/stencil samples per pixel? Need some transfer clarifications. */
assert(sample_count < 2);
 
srcFormat = rbRead->texture->format;
 
if (screen->is_format_supported(screen, srcFormat, st->internal_target,
sample_count,
PIPE_BIND_SAMPLER_VIEW, 0)) {
texFormat = srcFormat;
}
else {
/* srcFormat can't be used as a texture format */
if (type == GL_DEPTH) {
texFormat = st_choose_format(screen, GL_DEPTH_COMPONENT,
st->internal_target, sample_count,
PIPE_BIND_DEPTH_STENCIL);
assert(texFormat != PIPE_FORMAT_NONE);
}
else {
/* default color format */
texFormat = st_choose_format(screen, GL_RGBA, st->internal_target,
sample_count, PIPE_BIND_SAMPLER_VIEW);
assert(texFormat != PIPE_FORMAT_NONE);
}
}
 
/* Invert src region if needed */
if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
srcy = ctx->ReadBuffer->Height - srcy - height;
invertTex = !invertTex;
}
 
/* Clip the read region against the src buffer bounds.
* We'll still allocate a temporary buffer/texture for the original
* src region size but we'll only read the region which is on-screen.
* This may mean that we draw garbage pixels into the dest region, but
* that's expected.
*/
readX = srcx;
readY = srcy;
readW = width;
readH = height;
_mesa_clip_readpixels(ctx, &readX, &readY, &readW, &readH, &pack);
readW = MAX2(0, readW);
readH = MAX2(0, readH);
 
/* alloc temporary texture */
pt = alloc_texture(st, width, height, texFormat);
if (!pt)
return;
 
sv[0] = st_create_texture_sampler_view(st->pipe, pt);
if (!sv[0]) {
pipe_resource_reference(&pt, NULL);
return;
}
 
/* Make temporary texture which is a copy of the src region.
*/
if (srcFormat == texFormat) {
struct pipe_box src_box;
u_box_2d(readX, readY, readW, readH, &src_box);
/* copy source framebuffer surface into mipmap/texture */
pipe->resource_copy_region(pipe,
pt, /* dest tex */
0,
pack.SkipPixels, pack.SkipRows, 0, /* dest pos */
rbRead->texture, /* src tex */
0,
&src_box);
 
}
else {
/* CPU-based fallback/conversion */
struct pipe_transfer *ptRead =
pipe_get_transfer(st->pipe, rbRead->texture,
0, 0, /* level, layer */
PIPE_TRANSFER_READ,
readX, readY, readW, readH);
struct pipe_transfer *ptTex;
enum pipe_transfer_usage transfer_usage;
 
if (ST_DEBUG & DEBUG_FALLBACK)
debug_printf("%s: fallback processing\n", __FUNCTION__);
 
if (type == GL_DEPTH && util_format_is_depth_and_stencil(pt->format))
transfer_usage = PIPE_TRANSFER_READ_WRITE;
else
transfer_usage = PIPE_TRANSFER_WRITE;
 
ptTex = pipe_get_transfer(st->pipe, pt, 0, 0, transfer_usage,
0, 0, width, height);
 
/* copy image from ptRead surface to ptTex surface */
if (type == GL_COLOR) {
/* alternate path using get/put_tile() */
GLfloat *buf = (GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
pipe_get_tile_rgba(pipe, ptRead, 0, 0, readW, readH, buf);
pipe_put_tile_rgba(pipe, ptTex, pack.SkipPixels, pack.SkipRows,
readW, readH, buf);
free(buf);
}
else {
/* GL_DEPTH */
GLuint *buf = (GLuint *) malloc(width * height * sizeof(GLuint));
pipe_get_tile_z(pipe, ptRead, 0, 0, readW, readH, buf);
pipe_put_tile_z(pipe, ptTex, pack.SkipPixels, pack.SkipRows,
readW, readH, buf);
free(buf);
}
 
pipe->transfer_destroy(pipe, ptRead);
pipe->transfer_destroy(pipe, ptTex);
}
 
/* OK, the texture 'pt' contains the src image/pixels. Now draw a
* textured quad with that texture.
*/
draw_textured_quad(ctx, dstx, dsty, ctx->Current.RasterPos[2],
width, height, ctx->Pixel.ZoomX, ctx->Pixel.ZoomY,
sv,
num_sampler_view,
driver_vp,
driver_fp,
color, invertTex, GL_FALSE, GL_FALSE);
 
pipe_resource_reference(&pt, NULL);
pipe_sampler_view_reference(&sv[0], NULL);
}
 
 
 
void st_init_drawpixels_functions(struct dd_function_table *functions)
{
functions->DrawPixels = st_DrawPixels;
functions->CopyPixels = st_CopyPixels;
}
 
 
void
st_destroy_drawpix(struct st_context *st)
{
GLuint i;
 
for (i = 0; i < Elements(st->drawpix.shaders); i++) {
if (st->drawpix.shaders[i])
st_reference_fragprog(st, &st->drawpix.shaders[i], NULL);
}
 
st_reference_fragprog(st, &st->pixel_xfer.combined_prog, NULL);
if (st->drawpix.vert_shaders[0])
ureg_free_tokens(st->drawpix.vert_shaders[0]);
if (st->drawpix.vert_shaders[1])
ureg_free_tokens(st->drawpix.vert_shaders[1]);
}
 
#endif /* FEATURE_drawpix */
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_cb_drawpixels.h
0,0 → 1,59
/**************************************************************************
*
* 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 ST_CB_DRAWPIXELS_H
#define ST_CB_DRAWPIXELS_H
 
 
#include "main/compiler.h"
 
struct dd_function_table;
struct st_context;
 
#if FEATURE_drawpix
 
extern void st_init_drawpixels_functions(struct dd_function_table *functions);
 
extern void
st_destroy_drawpix(struct st_context *st);
 
#else
 
static INLINE void
st_init_drawpixels_functions(struct dd_function_table *functions)
{
}
 
static INLINE void
st_destroy_drawpix(struct st_context *st)
{
}
 
#endif /* FEATURE_drawpix */
 
#endif /* ST_CB_DRAWPIXELS_H */
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_cb_drawtex.c
0,0 → 1,303
/**************************************************************************
*
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
**************************************************************************/
 
 
/**
* Implementation of glDrawTex() for GL_OES_draw_tex
*/
 
 
 
#include "main/imports.h"
#include "main/image.h"
#include "main/macros.h"
#include "program/program.h"
#include "program/prog_print.h"
 
#include "st_context.h"
#include "st_atom.h"
#include "st_cb_drawtex.h"
 
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "util/u_inlines.h"
#include "pipe/p_shader_tokens.h"
#include "util/u_draw_quad.h"
#include "util/u_simple_shaders.h"
 
#include "cso_cache/cso_context.h"
 
 
#if FEATURE_OES_draw_texture
 
 
struct cached_shader
{
void *handle;
 
uint num_attribs;
uint semantic_names[2 + MAX_TEXTURE_UNITS];
uint semantic_indexes[2 + MAX_TEXTURE_UNITS];
};
 
#define MAX_SHADERS (2 * MAX_TEXTURE_UNITS)
 
/**
* Simple linear list cache.
* Most of the time there'll only be one cached shader.
*/
static struct cached_shader CachedShaders[MAX_SHADERS];
static GLuint NumCachedShaders = 0;
 
 
static void *
lookup_shader(struct pipe_context *pipe,
uint num_attribs,
const uint *semantic_names,
const uint *semantic_indexes)
{
GLuint i, j;
 
/* look for existing shader with same attributes */
for (i = 0; i < NumCachedShaders; i++) {
if (CachedShaders[i].num_attribs == num_attribs) {
GLboolean match = GL_TRUE;
for (j = 0; j < num_attribs; j++) {
if (semantic_names[j] != CachedShaders[i].semantic_names[j] ||
semantic_indexes[j] != CachedShaders[i].semantic_indexes[j]) {
match = GL_FALSE;
break;
}
}
if (match)
return CachedShaders[i].handle;
}
}
 
/* not found - create new one now */
if (NumCachedShaders >= MAX_SHADERS) {
return NULL;
}
 
CachedShaders[i].num_attribs = num_attribs;
for (j = 0; j < num_attribs; j++) {
CachedShaders[i].semantic_names[j] = semantic_names[j];
CachedShaders[i].semantic_indexes[j] = semantic_indexes[j];
}
 
CachedShaders[i].handle =
util_make_vertex_passthrough_shader(pipe,
num_attribs,
semantic_names,
semantic_indexes);
NumCachedShaders++;
 
return CachedShaders[i].handle;
}
 
static void
st_DrawTex(struct gl_context *ctx, GLfloat x, GLfloat y, GLfloat z,
GLfloat width, GLfloat height)
{
struct st_context *st = ctx->st;
struct pipe_context *pipe = st->pipe;
struct cso_context *cso = ctx->st->cso_context;
struct pipe_resource *vbuffer;
struct pipe_transfer *vbuffer_transfer;
GLuint i, numTexCoords, numAttribs;
GLboolean emitColor;
uint semantic_names[2 + MAX_TEXTURE_UNITS];
uint semantic_indexes[2 + MAX_TEXTURE_UNITS];
struct pipe_vertex_element velements[2 + MAX_TEXTURE_UNITS];
GLbitfield inputs = VERT_BIT_POS;
 
st_validate_state(st);
 
/* determine if we need vertex color */
if (ctx->FragmentProgram._Current->Base.InputsRead & FRAG_BIT_COL0)
emitColor = GL_TRUE;
else
emitColor = GL_FALSE;
 
/* determine how many enabled sets of texcoords */
numTexCoords = 0;
for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
if (ctx->Texture.Unit[i]._ReallyEnabled & TEXTURE_2D_BIT) {
inputs |= VERT_BIT_TEX(i);
numTexCoords++;
}
}
 
/* total number of attributes per vertex */
numAttribs = 1 + emitColor + numTexCoords;
 
 
/* create the vertex buffer */
vbuffer = pipe_buffer_create(pipe->screen, PIPE_BIND_VERTEX_BUFFER,
numAttribs * 4 * 4 * sizeof(GLfloat));
 
/* load vertex buffer */
{
#define SET_ATTRIB(VERT, ATTR, X, Y, Z, W) \
do { \
GLuint k = (((VERT) * numAttribs + (ATTR)) * 4); \
assert(k < 4 * 4 * numAttribs); \
vbuf[k + 0] = X; \
vbuf[k + 1] = Y; \
vbuf[k + 2] = Z; \
vbuf[k + 3] = W; \
} while (0)
 
const GLfloat x0 = x, y0 = y, x1 = x + width, y1 = y + height;
GLfloat *vbuf = (GLfloat *) pipe_buffer_map(pipe, vbuffer,
PIPE_TRANSFER_WRITE,
&vbuffer_transfer);
GLuint attr;
z = CLAMP(z, 0.0f, 1.0f);
 
/* positions (in clip coords) */
{
const struct gl_framebuffer *fb = st->ctx->DrawBuffer;
const GLfloat fb_width = (GLfloat)fb->Width;
const GLfloat fb_height = (GLfloat)fb->Height;
 
const GLfloat clip_x0 = (GLfloat)(x0 / fb_width * 2.0 - 1.0);
const GLfloat clip_y0 = (GLfloat)(y0 / fb_height * 2.0 - 1.0);
const GLfloat clip_x1 = (GLfloat)(x1 / fb_width * 2.0 - 1.0);
const GLfloat clip_y1 = (GLfloat)(y1 / fb_height * 2.0 - 1.0);
 
SET_ATTRIB(0, 0, clip_x0, clip_y0, z, 1.0f); /* lower left */
SET_ATTRIB(1, 0, clip_x1, clip_y0, z, 1.0f); /* lower right */
SET_ATTRIB(2, 0, clip_x1, clip_y1, z, 1.0f); /* upper right */
SET_ATTRIB(3, 0, clip_x0, clip_y1, z, 1.0f); /* upper left */
 
semantic_names[0] = TGSI_SEMANTIC_POSITION;
semantic_indexes[0] = 0;
}
 
/* colors */
if (emitColor) {
const GLfloat *c = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
SET_ATTRIB(0, 1, c[0], c[1], c[2], c[3]);
SET_ATTRIB(1, 1, c[0], c[1], c[2], c[3]);
SET_ATTRIB(2, 1, c[0], c[1], c[2], c[3]);
SET_ATTRIB(3, 1, c[0], c[1], c[2], c[3]);
semantic_names[1] = TGSI_SEMANTIC_COLOR;
semantic_indexes[1] = 0;
attr = 2;
}
else {
attr = 1;
}
 
/* texcoords */
for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
if (ctx->Texture.Unit[i]._ReallyEnabled & TEXTURE_2D_BIT) {
struct gl_texture_object *obj = ctx->Texture.Unit[i]._Current;
struct gl_texture_image *img = obj->Image[0][obj->BaseLevel];
const GLfloat wt = (GLfloat) img->Width;
const GLfloat ht = (GLfloat) img->Height;
const GLfloat s0 = obj->CropRect[0] / wt;
const GLfloat t0 = obj->CropRect[1] / ht;
const GLfloat s1 = (obj->CropRect[0] + obj->CropRect[2]) / wt;
const GLfloat t1 = (obj->CropRect[1] + obj->CropRect[3]) / ht;
 
/*printf("crop texcoords: %g, %g .. %g, %g\n", s0, t0, s1, t1);*/
SET_ATTRIB(0, attr, s0, t0, 0.0f, 1.0f); /* lower left */
SET_ATTRIB(1, attr, s1, t0, 0.0f, 1.0f); /* lower right */
SET_ATTRIB(2, attr, s1, t1, 0.0f, 1.0f); /* upper right */
SET_ATTRIB(3, attr, s0, t1, 0.0f, 1.0f); /* upper left */
 
semantic_names[attr] = TGSI_SEMANTIC_GENERIC;
semantic_indexes[attr] = 0;
 
attr++;
}
}
 
pipe_buffer_unmap(pipe, vbuffer, vbuffer_transfer);
 
#undef SET_ATTRIB
}
 
 
cso_save_viewport(cso);
cso_save_vertex_shader(cso);
cso_save_vertex_elements(cso);
 
{
void *vs = lookup_shader(pipe, numAttribs,
semantic_names, semantic_indexes);
cso_set_vertex_shader_handle(cso, vs);
}
 
for (i = 0; i < numAttribs; i++) {
velements[i].src_offset = i * 4 * sizeof(float);
velements[i].instance_divisor = 0;
velements[i].vertex_buffer_index = 0;
velements[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
}
cso_set_vertex_elements(cso, numAttribs, velements);
 
/* viewport state: viewport matching window dims */
{
const struct gl_framebuffer *fb = st->ctx->DrawBuffer;
const GLboolean invert = (st_fb_orientation(fb) == Y_0_TOP);
const GLfloat width = (GLfloat)fb->Width;
const GLfloat height = (GLfloat)fb->Height;
struct pipe_viewport_state vp;
vp.scale[0] = 0.5f * width;
vp.scale[1] = height * (invert ? -0.5f : 0.5f);
vp.scale[2] = 1.0f;
vp.scale[3] = 1.0f;
vp.translate[0] = 0.5f * width;
vp.translate[1] = 0.5f * height;
vp.translate[2] = 0.0f;
vp.translate[3] = 0.0f;
cso_set_viewport(cso, &vp);
}
 
 
util_draw_vertex_buffer(pipe, vbuffer,
0, /* offset */
PIPE_PRIM_TRIANGLE_FAN,
4, /* verts */
numAttribs); /* attribs/vert */
 
 
pipe_resource_reference(&vbuffer, NULL);
 
/* restore state */
cso_restore_viewport(cso);
cso_restore_vertex_shader(cso);
cso_restore_vertex_elements(cso);
}
 
 
void
st_init_drawtex_functions(struct dd_function_table *functions)
{
functions->DrawTex = st_DrawTex;
}
 
 
/**
* Free any cached shaders
*/
void
st_destroy_drawtex(struct st_context *st)
{
GLuint i;
for (i = 0; i < NumCachedShaders; i++) {
cso_delete_vertex_shader(st->cso_context, CachedShaders[i].handle);
}
NumCachedShaders = 0;
}
 
 
#endif /* FEATURE_OES_draw_texture */
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_cb_drawtex.h
0,0 → 1,40
/**************************************************************************
*
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
* All Rights Reserved.
*
**************************************************************************/
 
 
#ifndef ST_CB_DRAWTEX_H
#define ST_CB_DRAWTEX_H
 
 
#include "main/compiler.h"
 
struct dd_function_table;
struct st_context;
 
#if FEATURE_OES_draw_texture
 
extern void
st_init_drawtex_functions(struct dd_function_table *functions);
 
extern void
st_destroy_drawtex(struct st_context *st);
 
#else
 
static INLINE void
st_init_drawtex_functions(struct dd_function_table *functions)
{
}
 
static INLINE void
st_destroy_drawtex(struct st_context *st)
{
}
 
#endif /* FEATURE_OES_draw_texture */
 
#endif /* ST_CB_DRAWTEX_H */
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_cb_eglimage.c
0,0 → 1,169
/*
* Mesa 3-D graphics library
* Version: 7.9
*
* 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:
* Chia-I Wu <olv@lunarg.com>
*/
 
#include "main/texobj.h"
#include "main/texfetch.h"
#include "main/teximage.h"
#include "util/u_inlines.h"
#include "util/u_format.h"
#include "st_cb_eglimage.h"
#include "st_cb_fbo.h"
#include "st_context.h"
#include "st_texture.h"
#include "st_format.h"
#include "st_manager.h"
 
#if FEATURE_OES_EGL_image
 
/**
* Return the base format just like _mesa_base_fbo_format does.
*/
static GLenum
st_pipe_format_to_base_format(enum pipe_format format)
{
GLenum base_format;
 
if (util_format_is_depth_or_stencil(format)) {
if (util_format_is_depth_and_stencil(format)) {
base_format = GL_DEPTH_STENCIL;
}
else {
if (format == PIPE_FORMAT_S8_USCALED)
base_format = GL_STENCIL_INDEX;
else
base_format = GL_DEPTH_COMPONENT;
}
}
else {
/* is this enough? */
if (util_format_has_alpha(format))
base_format = GL_RGBA;
else
base_format = GL_RGB;
}
 
return base_format;
}
 
static void
st_egl_image_target_renderbuffer_storage(struct gl_context *ctx,
struct gl_renderbuffer *rb,
GLeglImageOES image_handle)
{
struct st_context *st = st_context(ctx);
struct st_renderbuffer *strb = st_renderbuffer(rb);
struct pipe_surface *ps;
unsigned usage;
 
usage = PIPE_BIND_RENDER_TARGET;
ps = st_manager_get_egl_image_surface(st, (void *) image_handle, usage);
if (ps) {
strb->Base.Width = ps->width;
strb->Base.Height = ps->height;
strb->Base.Format = st_pipe_format_to_mesa_format(ps->format);
strb->Base.DataType = st_format_datatype(ps->format);
strb->Base._BaseFormat = st_pipe_format_to_base_format(ps->format);
strb->Base.InternalFormat = strb->Base._BaseFormat;
 
pipe_surface_reference(&strb->surface, ps);
pipe_resource_reference(&strb->texture, ps->texture);
 
pipe_surface_reference(&ps, NULL);
}
}
 
static void
st_bind_surface(struct gl_context *ctx, GLenum target,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage,
struct pipe_surface *ps)
{
struct st_texture_object *stObj;
struct st_texture_image *stImage;
GLenum internalFormat;
gl_format texFormat;
 
/* map pipe format to base format */
if (util_format_get_component_bits(ps->format, UTIL_FORMAT_COLORSPACE_RGB, 3) > 0)
internalFormat = GL_RGBA;
else
internalFormat = GL_RGB;
 
stObj = st_texture_object(texObj);
stImage = st_texture_image(texImage);
 
/* switch to surface based */
if (!stObj->surface_based) {
_mesa_clear_texture_object(ctx, texObj);
stObj->surface_based = GL_TRUE;
}
 
texFormat = st_pipe_format_to_mesa_format(ps->format);
 
_mesa_init_teximage_fields(ctx, target, texImage,
ps->width, ps->height, 1, 0, internalFormat,
texFormat);
 
/* FIXME create a non-default sampler view from the pipe_surface? */
pipe_resource_reference(&stObj->pt, ps->texture);
pipe_sampler_view_reference(&stObj->sampler_view, NULL);
pipe_resource_reference(&stImage->pt, stObj->pt);
 
stObj->width0 = ps->width;
stObj->height0 = ps->height;
stObj->depth0 = 1;
 
_mesa_dirty_texobj(ctx, texObj, GL_TRUE);
}
 
static void
st_egl_image_target_texture_2d(struct gl_context *ctx, GLenum target,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage,
GLeglImageOES image_handle)
{
struct st_context *st = st_context(ctx);
struct pipe_surface *ps;
unsigned usage;
 
usage = PIPE_BIND_SAMPLER_VIEW;
ps = st_manager_get_egl_image_surface(st, (void *) image_handle, usage);
if (ps) {
st_bind_surface(ctx, target, texObj, texImage, ps);
pipe_surface_reference(&ps, NULL);
}
}
 
void
st_init_eglimage_functions(struct dd_function_table *functions)
{
functions->EGLImageTargetTexture2D = st_egl_image_target_texture_2d;
functions->EGLImageTargetRenderbufferStorage = st_egl_image_target_renderbuffer_storage;
}
 
#endif /* FEATURE_OES_EGL_image */
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_cb_eglimage.h
0,0 → 1,50
/*
* Mesa 3-D graphics library
* Version: 7.9
*
* 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:
* Chia-I Wu <olv@lunarg.com>
*/
 
#ifndef ST_CB_EGLIMAGE_H
#define ST_CB_EGLIMAGE_H
 
#include "main/compiler.h"
 
struct dd_function_table;
 
#if FEATURE_OES_EGL_image
 
extern void
st_init_eglimage_functions(struct dd_function_table *functions);
 
#else
 
static INLINE void
st_init_eglimage_functions(struct dd_function_table *functions)
{
}
 
#endif
 
#endif /* ST_CB_EGLIMAGE_H */
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_cb_fbo.c
0,0 → 1,619
/**************************************************************************
*
* 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.
*
**************************************************************************/
 
 
/**
* Framebuffer/renderbuffer functions.
*
* \author Brian Paul
*/
 
 
#include "main/imports.h"
#include "main/context.h"
#include "main/fbobject.h"
#include "main/framebuffer.h"
#include "main/macros.h"
#include "main/renderbuffer.h"
 
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "pipe/p_screen.h"
#include "st_context.h"
#include "st_cb_fbo.h"
#include "st_cb_flush.h"
#include "st_format.h"
#include "st_texture.h"
#include "st_manager.h"
 
#include "util/u_format.h"
#include "util/u_inlines.h"
#include "util/u_surface.h"
 
 
/**
* gl_renderbuffer::AllocStorage()
* This is called to allocate the original drawing surface, and
* during window resize.
*/
static GLboolean
st_renderbuffer_alloc_storage(struct gl_context * ctx, struct gl_renderbuffer *rb,
GLenum internalFormat,
GLuint width, GLuint height)
{
struct st_context *st = st_context(ctx);
struct pipe_context *pipe = st->pipe;
struct pipe_screen *screen = st->pipe->screen;
struct st_renderbuffer *strb = st_renderbuffer(rb);
enum pipe_format format;
struct pipe_surface surf_tmpl;
 
if (strb->format != PIPE_FORMAT_NONE)
format = strb->format;
else
format = st_choose_renderbuffer_format(screen, internalFormat, rb->NumSamples);
/* init renderbuffer fields */
strb->Base.Width = width;
strb->Base.Height = height;
strb->Base.Format = st_pipe_format_to_mesa_format(format);
strb->Base._BaseFormat = _mesa_base_fbo_format(ctx, internalFormat);
strb->Base.DataType = st_format_datatype(format);
 
strb->defined = GL_FALSE; /* undefined contents now */
 
if (strb->software) {
size_t size;
free(strb->data);
 
assert(strb->format != PIPE_FORMAT_NONE);
strb->stride = util_format_get_stride(strb->format, width);
size = util_format_get_2d_size(strb->format, strb->stride, height);
strb->data = malloc(size);
return strb->data != NULL;
}
else {
struct pipe_resource template;
/* Free the old surface and texture
*/
pipe_surface_reference( &strb->surface, NULL );
pipe_resource_reference( &strb->texture, NULL );
pipe_sampler_view_reference(&strb->sampler_view, NULL);
 
/* Setup new texture template.
*/
memset(&template, 0, sizeof(template));
template.target = st->internal_target;
template.format = format;
template.width0 = width;
template.height0 = height;
template.depth0 = 1;
template.array_size = 1;
template.last_level = 0;
template.nr_samples = rb->NumSamples;
if (util_format_is_depth_or_stencil(format)) {
template.bind = PIPE_BIND_DEPTH_STENCIL;
}
else {
template.bind = (PIPE_BIND_DISPLAY_TARGET |
PIPE_BIND_RENDER_TARGET);
}
 
strb->texture = screen->resource_create(screen, &template);
 
if (!strb->texture)
return FALSE;
 
memset(&surf_tmpl, 0, sizeof(surf_tmpl));
u_surface_default_template(&surf_tmpl, strb->texture, template.bind);
strb->surface = pipe->create_surface(pipe,
strb->texture,
&surf_tmpl);
if (strb->surface) {
assert(strb->surface->texture);
assert(strb->surface->format);
assert(strb->surface->width == width);
assert(strb->surface->height == height);
}
 
return strb->surface != NULL;
}
}
 
 
/**
* gl_renderbuffer::Delete()
*/
static void
st_renderbuffer_delete(struct gl_renderbuffer *rb)
{
struct st_renderbuffer *strb = st_renderbuffer(rb);
ASSERT(strb);
pipe_surface_reference(&strb->surface, NULL);
pipe_resource_reference(&strb->texture, NULL);
pipe_sampler_view_reference(&strb->sampler_view, NULL);
free(strb->data);
free(strb);
}
 
 
/**
* gl_renderbuffer::GetPointer()
*/
static void *
null_get_pointer(struct gl_context * ctx, struct gl_renderbuffer *rb,
GLint x, GLint y)
{
/* By returning NULL we force all software rendering to go through
* the span routines.
*/
#if 0
assert(0); /* Should never get called with softpipe */
#endif
return NULL;
}
 
 
/**
* Called via ctx->Driver.NewFramebuffer()
*/
static struct gl_framebuffer *
st_new_framebuffer(struct gl_context *ctx, GLuint name)
{
/* XXX not sure we need to subclass gl_framebuffer for pipe */
return _mesa_new_framebuffer(ctx, name);
}
 
 
/**
* Called via ctx->Driver.NewRenderbuffer()
*/
static struct gl_renderbuffer *
st_new_renderbuffer(struct gl_context *ctx, GLuint name)
{
struct st_renderbuffer *strb = ST_CALLOC_STRUCT(st_renderbuffer);
if (strb) {
_mesa_init_renderbuffer(&strb->Base, name);
strb->Base.Delete = st_renderbuffer_delete;
strb->Base.AllocStorage = st_renderbuffer_alloc_storage;
strb->Base.GetPointer = null_get_pointer;
strb->format = PIPE_FORMAT_NONE;
return &strb->Base;
}
return NULL;
}
 
 
/**
* Allocate a renderbuffer for a an on-screen window (not a user-created
* renderbuffer). The window system code determines the format.
*/
struct gl_renderbuffer *
st_new_renderbuffer_fb(enum pipe_format format, int samples, boolean sw)
{
struct st_renderbuffer *strb;
 
strb = ST_CALLOC_STRUCT(st_renderbuffer);
if (!strb) {
_mesa_error(NULL, GL_OUT_OF_MEMORY, "creating renderbuffer");
return NULL;
}
 
_mesa_init_renderbuffer(&strb->Base, 0);
strb->Base.ClassID = 0x4242; /* just a unique value */
strb->Base.NumSamples = samples;
strb->Base.Format = st_pipe_format_to_mesa_format(format);
strb->Base._BaseFormat = _mesa_get_format_base_format(strb->Base.Format);
strb->Base.DataType = st_format_datatype(format);
strb->format = format;
strb->software = sw;
switch (format) {
case PIPE_FORMAT_R8G8B8A8_UNORM:
case PIPE_FORMAT_B8G8R8A8_UNORM:
case PIPE_FORMAT_A8R8G8B8_UNORM:
case PIPE_FORMAT_R8G8B8X8_UNORM:
case PIPE_FORMAT_B8G8R8X8_UNORM:
case PIPE_FORMAT_X8R8G8B8_UNORM:
case PIPE_FORMAT_B5G5R5A1_UNORM:
case PIPE_FORMAT_B4G4R4A4_UNORM:
case PIPE_FORMAT_B5G6R5_UNORM:
strb->Base.InternalFormat = GL_RGBA;
break;
case PIPE_FORMAT_Z16_UNORM:
strb->Base.InternalFormat = GL_DEPTH_COMPONENT16;
break;
case PIPE_FORMAT_Z32_UNORM:
strb->Base.InternalFormat = GL_DEPTH_COMPONENT32;
break;
case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
case PIPE_FORMAT_Z24X8_UNORM:
case PIPE_FORMAT_X8Z24_UNORM:
strb->Base.InternalFormat = GL_DEPTH24_STENCIL8_EXT;
break;
case PIPE_FORMAT_S8_USCALED:
strb->Base.InternalFormat = GL_STENCIL_INDEX8_EXT;
break;
case PIPE_FORMAT_R16G16B16A16_SNORM:
strb->Base.InternalFormat = GL_RGBA16;
break;
case PIPE_FORMAT_R8_UNORM:
strb->Base.InternalFormat = GL_R8;
break;
case PIPE_FORMAT_R8G8_UNORM:
strb->Base.InternalFormat = GL_RG8;
break;
case PIPE_FORMAT_R16_UNORM:
strb->Base.InternalFormat = GL_R16;
break;
case PIPE_FORMAT_R16G16_UNORM:
strb->Base.InternalFormat = GL_RG16;
break;
default:
_mesa_problem(NULL,
"Unexpected format in st_new_renderbuffer_fb");
free(strb);
return NULL;
}
 
/* st-specific methods */
strb->Base.Delete = st_renderbuffer_delete;
strb->Base.AllocStorage = st_renderbuffer_alloc_storage;
strb->Base.GetPointer = null_get_pointer;
 
/* surface is allocated in st_renderbuffer_alloc_storage() */
strb->surface = NULL;
 
return &strb->Base;
}
 
 
 
 
/**
* Called via ctx->Driver.BindFramebufferEXT().
*/
static void
st_bind_framebuffer(struct gl_context *ctx, GLenum target,
struct gl_framebuffer *fb, struct gl_framebuffer *fbread)
{
 
}
 
/**
* Called by ctx->Driver.FramebufferRenderbuffer
*/
static void
st_framebuffer_renderbuffer(struct gl_context *ctx,
struct gl_framebuffer *fb,
GLenum attachment,
struct gl_renderbuffer *rb)
{
/* XXX no need for derivation? */
_mesa_framebuffer_renderbuffer(ctx, fb, attachment, rb);
}
 
 
/**
* Called by ctx->Driver.RenderTexture
*/
static void
st_render_texture(struct gl_context *ctx,
struct gl_framebuffer *fb,
struct gl_renderbuffer_attachment *att)
{
struct st_context *st = st_context(ctx);
struct pipe_context *pipe = st->pipe;
struct st_renderbuffer *strb;
struct gl_renderbuffer *rb;
struct pipe_resource *pt = st_get_texobj_resource(att->Texture);
struct st_texture_object *stObj;
const struct gl_texture_image *texImage;
struct pipe_surface surf_tmpl;
 
/* When would this fail? Perhaps assert? */
if (!pt)
return;
 
/* get pointer to texture image we're rendeing to */
texImage = att->Texture->Image[att->CubeMapFace][att->TextureLevel];
 
/* create new renderbuffer which wraps the texture image */
rb = st_new_renderbuffer(ctx, 0);
if (!rb) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glFramebufferTexture()");
return;
}
 
_mesa_reference_renderbuffer(&att->Renderbuffer, rb);
assert(rb->RefCount == 1);
rb->AllocStorage = NULL; /* should not get called */
strb = st_renderbuffer(rb);
 
assert(strb->Base.RefCount > 0);
 
/* get the texture for the texture object */
stObj = st_texture_object(att->Texture);
 
/* point renderbuffer at texobject */
strb->rtt = stObj;
strb->rtt_level = att->TextureLevel;
strb->rtt_face = att->CubeMapFace;
strb->rtt_slice = att->Zoffset;
 
rb->Width = texImage->Width2;
rb->Height = texImage->Height2;
rb->_BaseFormat = texImage->_BaseFormat;
/*printf("***** render to texture level %d: %d x %d\n", att->TextureLevel, rb->Width, rb->Height);*/
 
/*printf("***** pipe texture %d x %d\n", pt->width0, pt->height0);*/
 
pipe_resource_reference( &strb->texture, pt );
 
pipe_surface_reference(&strb->surface, NULL);
 
pipe_sampler_view_reference(&strb->sampler_view,
st_get_texture_sampler_view(stObj, pipe));
 
assert(strb->rtt_level <= strb->texture->last_level);
 
/* new surface for rendering into the texture */
memset(&surf_tmpl, 0, sizeof(surf_tmpl));
surf_tmpl.format = strb->texture->format;
surf_tmpl.usage = PIPE_BIND_RENDER_TARGET;
surf_tmpl.u.tex.level = strb->rtt_level;
surf_tmpl.u.tex.first_layer = strb->rtt_face + strb->rtt_slice;
surf_tmpl.u.tex.last_layer = strb->rtt_face + strb->rtt_slice;
strb->surface = pipe->create_surface(pipe,
strb->texture,
&surf_tmpl);
 
strb->format = pt->format;
 
strb->Base.Format = st_pipe_format_to_mesa_format(pt->format);
strb->Base.DataType = st_format_datatype(pt->format);
 
/*
printf("RENDER TO TEXTURE obj=%p pt=%p surf=%p %d x %d\n",
att->Texture, pt, strb->surface, rb->Width, rb->Height);
*/
 
/* Invalidate buffer state so that the pipe's framebuffer state
* gets updated.
* That's where the new renderbuffer (which we just created) gets
* passed to the pipe as a (color/depth) render target.
*/
st_invalidate_state(ctx, _NEW_BUFFERS);
}
 
 
/**
* Called via ctx->Driver.FinishRenderTexture.
*/
static void
st_finish_render_texture(struct gl_context *ctx,
struct gl_renderbuffer_attachment *att)
{
struct st_context *st = st_context(ctx);
struct st_renderbuffer *strb = st_renderbuffer(att->Renderbuffer);
 
if (!strb)
return;
 
st_flush(st, PIPE_FLUSH_RENDER_CACHE, NULL);
 
strb->rtt = NULL;
 
/*
printf("FINISH RENDER TO TEXTURE surf=%p\n", strb->surface);
*/
 
/* restore previous framebuffer state */
st_invalidate_state(ctx, _NEW_BUFFERS);
}
 
 
/**
* Validate a renderbuffer attachment for a particular set of bindings.
*/
static GLboolean
st_validate_attachment(struct pipe_screen *screen,
const struct gl_renderbuffer_attachment *att,
unsigned bindings)
{
const struct st_texture_object *stObj = st_texture_object(att->Texture);
 
/* Only validate texture attachments for now, since
* st_renderbuffer_alloc_storage makes sure that
* the format is supported.
*/
if (att->Type != GL_TEXTURE)
return GL_TRUE;
 
if (!stObj)
return GL_FALSE;
 
return screen->is_format_supported(screen, stObj->pt->format,
PIPE_TEXTURE_2D,
stObj->pt->nr_samples, bindings, 0);
}
 
 
/**
* Check if two renderbuffer attachments name a combined depth/stencil
* renderbuffer.
*/
GLboolean
st_is_depth_stencil_combined(const struct gl_renderbuffer_attachment *depth,
const struct gl_renderbuffer_attachment *stencil)
{
assert(depth && stencil);
 
if (depth->Type == stencil->Type) {
if (depth->Type == GL_RENDERBUFFER_EXT &&
depth->Renderbuffer == stencil->Renderbuffer)
return GL_TRUE;
 
if (depth->Type == GL_TEXTURE &&
depth->Texture == stencil->Texture)
return GL_TRUE;
}
 
return GL_FALSE;
}
 
/**
* Check that the framebuffer configuration is valid in terms of what
* the driver can support.
*
* For Gallium we only supports combined Z+stencil, not separate buffers.
*/
static void
st_validate_framebuffer(struct gl_context *ctx, struct gl_framebuffer *fb)
{
struct st_context *st = st_context(ctx);
struct pipe_screen *screen = st->pipe->screen;
const struct gl_renderbuffer_attachment *depth =
&fb->Attachment[BUFFER_DEPTH];
const struct gl_renderbuffer_attachment *stencil =
&fb->Attachment[BUFFER_STENCIL];
GLuint i;
 
if (depth->Type && stencil->Type && depth->Type != stencil->Type) {
fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
return;
}
if (depth->Type == GL_RENDERBUFFER_EXT &&
stencil->Type == GL_RENDERBUFFER_EXT &&
depth->Renderbuffer != stencil->Renderbuffer) {
fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
return;
}
if (depth->Type == GL_TEXTURE &&
stencil->Type == GL_TEXTURE &&
depth->Texture != stencil->Texture) {
fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
return;
}
 
if (!st_validate_attachment(screen,
depth,
PIPE_BIND_DEPTH_STENCIL)) {
fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
return;
}
if (!st_validate_attachment(screen,
stencil,
PIPE_BIND_DEPTH_STENCIL)) {
fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
return;
}
for (i = 0; i < ctx->Const.MaxColorAttachments; i++) {
if (!st_validate_attachment(screen,
&fb->Attachment[BUFFER_COLOR0 + i],
PIPE_BIND_RENDER_TARGET)) {
fb->_Status = GL_FRAMEBUFFER_UNSUPPORTED_EXT;
return;
}
}
}
 
 
/**
* Called via glDrawBuffer.
*/
static void
st_DrawBuffers(struct gl_context *ctx, GLsizei count, const GLenum *buffers)
{
struct st_context *st = st_context(ctx);
struct gl_framebuffer *fb = ctx->DrawBuffer;
GLuint i;
 
(void) count;
(void) buffers;
 
/* add the renderbuffers on demand */
for (i = 0; i < fb->_NumColorDrawBuffers; i++) {
gl_buffer_index idx = fb->_ColorDrawBufferIndexes[i];
st_manager_add_color_renderbuffer(st, fb, idx);
}
}
 
 
/**
* Called via glReadBuffer.
*/
static void
st_ReadBuffer(struct gl_context *ctx, GLenum buffer)
{
struct st_context *st = st_context(ctx);
struct gl_framebuffer *fb = ctx->ReadBuffer;
 
(void) buffer;
 
/* add the renderbuffer on demand */
st_manager_add_color_renderbuffer(st, fb, fb->_ColorReadBufferIndex);
}
 
 
void st_init_fbo_functions(struct dd_function_table *functions)
{
#if FEATURE_EXT_framebuffer_object
functions->NewFramebuffer = st_new_framebuffer;
functions->NewRenderbuffer = st_new_renderbuffer;
functions->BindFramebuffer = st_bind_framebuffer;
functions->FramebufferRenderbuffer = st_framebuffer_renderbuffer;
functions->RenderTexture = st_render_texture;
functions->FinishRenderTexture = st_finish_render_texture;
functions->ValidateFramebuffer = st_validate_framebuffer;
#endif
/* no longer needed by core Mesa, drivers handle resizes...
functions->ResizeBuffers = st_resize_buffers;
*/
 
functions->DrawBuffers = st_DrawBuffers;
functions->ReadBuffer = st_ReadBuffer;
}
 
/* XXX unused ? */
struct pipe_sampler_view *
st_get_renderbuffer_sampler_view(struct st_renderbuffer *rb,
struct pipe_context *pipe)
{
if (!rb->sampler_view) {
rb->sampler_view = st_create_texture_sampler_view(pipe, rb->texture);
}
 
return rb->sampler_view;
}
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_cb_fbo.h
0,0 → 1,96
/**************************************************************************
*
* 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 ST_CB_FBO_H
#define ST_CB_FBO_H
 
#include "main/compiler.h"
#include "main/glheader.h"
#include "main/mtypes.h"
 
#include "pipe/p_compiler.h"
#include "pipe/p_format.h"
 
struct dd_function_table;
struct pipe_context;
 
/**
* Derived renderbuffer class. Just need to add a pointer to the
* pipe surface.
*/
struct st_renderbuffer
{
struct gl_renderbuffer Base;
struct pipe_resource *texture;
struct pipe_surface *surface; /* temporary view into texture */
struct pipe_sampler_view *sampler_view;
enum pipe_format format; /** preferred format, or PIPE_FORMAT_NONE */
GLboolean defined; /**< defined contents? */
 
/**
* Used only when hardware accumulation buffers are not supported.
*/
boolean software;
size_t stride;
void *data;
struct st_texture_object *rtt; /**< GL render to texture's texture */
int rtt_level, rtt_face, rtt_slice;
 
/** Render to texture state */
struct pipe_resource *texture_save;
struct pipe_surface *surface_save;
struct pipe_sampler_view *sampler_view_save;
};
 
 
static INLINE struct st_renderbuffer *
st_renderbuffer(struct gl_renderbuffer *rb)
{
return (struct st_renderbuffer *) rb;
}
 
 
extern struct gl_renderbuffer *
st_new_renderbuffer_fb(enum pipe_format format, int samples, boolean sw);
 
extern void
st_init_fbo_functions(struct dd_function_table *functions);
 
/* XXX unused ? */
extern struct pipe_sampler_view *
st_get_renderbuffer_sampler_view(struct st_renderbuffer *rb,
struct pipe_context *pipe);
 
 
extern GLboolean
st_is_depth_stencil_combined(const struct gl_renderbuffer_attachment *depth,
const struct gl_renderbuffer_attachment *stencil);
 
 
#endif /* ST_CB_FBO_H */
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_cb_feedback.c
0,0 → 1,308
/**************************************************************************
*
* 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.
*
**************************************************************************/
 
/**
* GL_SELECT and GL_FEEDBACK render modes.
* Basically, we use a private instance of the 'draw' module for doing
* selection/feedback. It would be nice to use the transform_feedback
* hardware feature, but it's defined as happening pre-clip and we want
* post-clipped primitives. Also, there's concerns about the efficiency
* of using the hardware for this anyway.
*
* Authors:
* Brian Paul
*/
 
#include "main/imports.h"
#include "main/context.h"
#include "main/feedback.h"
 
#include "vbo/vbo.h"
 
#include "st_context.h"
#include "st_draw.h"
#include "st_cb_feedback.h"
 
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
 
#include "draw/draw_context.h"
#include "draw/draw_pipe.h"
 
 
#if FEATURE_feedback
 
/**
* This is actually used for both feedback and selection.
*/
struct feedback_stage
{
struct draw_stage stage; /**< Base class */
struct gl_context *ctx; /**< Rendering context */
GLboolean reset_stipple_counter;
};
 
 
/**********************************************************************
* GL Feedback functions
**********************************************************************/
 
static INLINE struct feedback_stage *
feedback_stage( struct draw_stage *stage )
{
return (struct feedback_stage *)stage;
}
 
 
static void
feedback_vertex(struct gl_context *ctx, const struct draw_context *draw,
const struct vertex_header *v)
{
const struct st_context *st = st_context(ctx);
GLfloat win[4];
const GLfloat *color, *texcoord;
GLuint slot;
 
/* Recall that Y=0=Top of window for Gallium wincoords */
win[0] = v->data[0][0];
win[1] = ctx->DrawBuffer->Height - v->data[0][1];
win[2] = v->data[0][2];
win[3] = 1.0F / v->data[0][3];
 
/* XXX
* When we compute vertex layout, save info about position of the
* color and texcoord attribs to use here.
*/
 
slot = st->vertex_result_to_slot[VERT_RESULT_COL0];
if (slot != ~0U)
color = v->data[slot];
else
color = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
 
slot = st->vertex_result_to_slot[VERT_RESULT_TEX0];
if (slot != ~0U)
texcoord = v->data[slot];
else
texcoord = ctx->Current.Attrib[VERT_ATTRIB_TEX0];
 
_mesa_feedback_vertex(ctx, win, color, texcoord);
}
 
 
static void
feedback_tri( struct draw_stage *stage, struct prim_header *prim )
{
struct feedback_stage *fs = feedback_stage(stage);
struct draw_context *draw = stage->draw;
_mesa_feedback_token(fs->ctx, (GLfloat) GL_POLYGON_TOKEN);
_mesa_feedback_token(fs->ctx, (GLfloat) 3); /* three vertices */
feedback_vertex(fs->ctx, draw, prim->v[0]);
feedback_vertex(fs->ctx, draw, prim->v[1]);
feedback_vertex(fs->ctx, draw, prim->v[2]);
}
 
 
static void
feedback_line( struct draw_stage *stage, struct prim_header *prim )
{
struct feedback_stage *fs = feedback_stage(stage);
struct draw_context *draw = stage->draw;
if (fs->reset_stipple_counter) {
_mesa_feedback_token(fs->ctx, (GLfloat) GL_LINE_RESET_TOKEN);
fs->reset_stipple_counter = GL_FALSE;
}
else {
_mesa_feedback_token(fs->ctx, (GLfloat) GL_LINE_TOKEN);
}
feedback_vertex(fs->ctx, draw, prim->v[0]);
feedback_vertex(fs->ctx, draw, prim->v[1]);
}
 
 
static void
feedback_point( struct draw_stage *stage, struct prim_header *prim )
{
struct feedback_stage *fs = feedback_stage(stage);
struct draw_context *draw = stage->draw;
_mesa_feedback_token(fs->ctx, (GLfloat) GL_POINT_TOKEN);
feedback_vertex(fs->ctx, draw, prim->v[0]);
}
 
 
static void
feedback_flush( struct draw_stage *stage, unsigned flags )
{
/* no-op */
}
 
 
static void
feedback_reset_stipple_counter( struct draw_stage *stage )
{
struct feedback_stage *fs = feedback_stage(stage);
fs->reset_stipple_counter = GL_TRUE;
}
 
 
static void
feedback_destroy( struct draw_stage *stage )
{
/* no-op */
}
 
/**
* Create GL feedback drawing stage.
*/
static struct draw_stage *
draw_glfeedback_stage(struct gl_context *ctx, struct draw_context *draw)
{
struct feedback_stage *fs = ST_CALLOC_STRUCT(feedback_stage);
 
fs->stage.draw = draw;
fs->stage.next = NULL;
fs->stage.point = feedback_point;
fs->stage.line = feedback_line;
fs->stage.tri = feedback_tri;
fs->stage.flush = feedback_flush;
fs->stage.reset_stipple_counter = feedback_reset_stipple_counter;
fs->stage.destroy = feedback_destroy;
fs->ctx = ctx;
 
return &fs->stage;
}
 
 
 
/**********************************************************************
* GL Selection functions
**********************************************************************/
 
static void
select_tri( struct draw_stage *stage, struct prim_header *prim )
{
struct feedback_stage *fs = feedback_stage(stage);
_mesa_update_hitflag( fs->ctx, prim->v[0]->data[0][2] );
_mesa_update_hitflag( fs->ctx, prim->v[1]->data[0][2] );
_mesa_update_hitflag( fs->ctx, prim->v[2]->data[0][2] );
}
 
static void
select_line( struct draw_stage *stage, struct prim_header *prim )
{
struct feedback_stage *fs = feedback_stage(stage);
_mesa_update_hitflag( fs->ctx, prim->v[0]->data[0][2] );
_mesa_update_hitflag( fs->ctx, prim->v[1]->data[0][2] );
}
 
 
static void
select_point( struct draw_stage *stage, struct prim_header *prim )
{
struct feedback_stage *fs = feedback_stage(stage);
_mesa_update_hitflag( fs->ctx, prim->v[0]->data[0][2] );
}
 
 
static void
select_flush( struct draw_stage *stage, unsigned flags )
{
/* no-op */
}
 
 
static void
select_reset_stipple_counter( struct draw_stage *stage )
{
/* no-op */
}
 
static void
select_destroy( struct draw_stage *stage )
{
/* no-op */
}
 
 
/**
* Create GL selection mode drawing stage.
*/
static struct draw_stage *
draw_glselect_stage(struct gl_context *ctx, struct draw_context *draw)
{
struct feedback_stage *fs = ST_CALLOC_STRUCT(feedback_stage);
 
fs->stage.draw = draw;
fs->stage.next = NULL;
fs->stage.point = select_point;
fs->stage.line = select_line;
fs->stage.tri = select_tri;
fs->stage.flush = select_flush;
fs->stage.reset_stipple_counter = select_reset_stipple_counter;
fs->stage.destroy = select_destroy;
fs->ctx = ctx;
 
return &fs->stage;
}
 
 
static void
st_RenderMode(struct gl_context *ctx, GLenum newMode )
{
struct st_context *st = st_context(ctx);
struct draw_context *draw = st->draw;
 
if (newMode == GL_RENDER) {
/* restore normal VBO draw function */
vbo_set_draw_func(ctx, st_draw_vbo);
}
else if (newMode == GL_SELECT) {
if (!st->selection_stage)
st->selection_stage = draw_glselect_stage(ctx, draw);
draw_set_rasterize_stage(draw, st->selection_stage);
/* Plug in new vbo draw function */
vbo_set_draw_func(ctx, st_feedback_draw_vbo);
}
else {
if (!st->feedback_stage)
st->feedback_stage = draw_glfeedback_stage(ctx, draw);
draw_set_rasterize_stage(draw, st->feedback_stage);
/* Plug in new vbo draw function */
vbo_set_draw_func(ctx, st_feedback_draw_vbo);
/* need to generate/use a vertex program that emits pos/color/tex */
st->dirty.st |= ST_NEW_VERTEX_PROGRAM;
}
}
 
 
 
void st_init_feedback_functions(struct dd_function_table *functions)
{
functions->RenderMode = st_RenderMode;
}
 
#endif /* FEATURE_feedback */
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_cb_feedback.h
0,0 → 1,51
/**************************************************************************
*
* 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 ST_CB_FEEDBACK_H
#define ST_CB_FEEDBACK_H
 
 
#include "main/compiler.h"
 
struct dd_function_table;
 
#if FEATURE_feedback
 
extern void
st_init_feedback_functions(struct dd_function_table *functions);
 
#else
 
static INLINE void
st_init_feedback_functions(struct dd_function_table *functions)
{
}
 
#endif /* FEATURE_feedback */
 
#endif /* ST_CB_FEEDBACK_H */
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_cb_flush.c
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.
*
**************************************************************************/
 
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
* Brian Paul
*/
 
#include "main/glheader.h"
#include "main/macros.h"
#include "main/context.h"
#include "st_context.h"
#include "st_cb_bitmap.h"
#include "st_cb_flush.h"
#include "st_cb_clear.h"
#include "st_cb_fbo.h"
#include "st_manager.h"
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "pipe/p_screen.h"
#include "util/u_gen_mipmap.h"
#include "util/u_blit.h"
 
 
/** Check if we have a front color buffer and if it's been drawn to. */
static INLINE GLboolean
is_front_buffer_dirty(struct st_context *st)
{
struct gl_framebuffer *fb = st->ctx->DrawBuffer;
struct st_renderbuffer *strb
= st_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
return strb && strb->defined;
}
 
 
/**
* Tell the screen to display the front color buffer on-screen.
*/
static void
display_front_buffer(struct st_context *st)
{
struct gl_framebuffer *fb = st->ctx->DrawBuffer;
struct st_renderbuffer *strb
= st_renderbuffer(fb->Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
 
if (strb) {
/* Hook for copying "fake" frontbuffer if necessary:
*/
st_manager_flush_frontbuffer(st);
}
}
 
 
void st_flush( struct st_context *st, uint pipeFlushFlags,
struct pipe_fence_handle **fence )
{
FLUSH_CURRENT(st->ctx, 0);
 
/* Release any vertex buffers that might potentially be accessed in
* successive frames:
*/
st_flush_bitmap(st);
st_flush_clear(st);
util_blit_flush(st->blit);
util_gen_mipmap_flush(st->gen_mipmap);
 
st->pipe->flush( st->pipe, pipeFlushFlags, fence );
}
 
 
/**
* Flush, and wait for completion.
*/
void st_finish( struct st_context *st )
{
struct pipe_fence_handle *fence = NULL;
 
st_flush(st, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, &fence);
 
if(fence) {
st->pipe->screen->fence_finish(st->pipe->screen, fence, 0);
st->pipe->screen->fence_reference(st->pipe->screen, &fence, NULL);
}
}
 
 
 
/**
* Called via ctx->Driver.Flush()
*/
static void st_glFlush(struct gl_context *ctx)
{
struct st_context *st = st_context(ctx);
 
/* Don't call st_finish() here. It is not the state tracker's
* responsibilty to inject sleeps in the hope of avoiding buffer
* synchronization issues. Calling finish() here will just hide
* problems that need to be fixed elsewhere.
*/
st_flush(st, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, NULL);
 
if (is_front_buffer_dirty(st)) {
display_front_buffer(st);
}
}
 
 
/**
* Called via ctx->Driver.Finish()
*/
static void st_glFinish(struct gl_context *ctx)
{
struct st_context *st = st_context(ctx);
 
st_finish(st);
 
if (is_front_buffer_dirty(st)) {
display_front_buffer(st);
}
}
 
 
void st_init_flush_functions(struct dd_function_table *functions)
{
functions->Flush = st_glFlush;
functions->Finish = st_glFinish;
 
/* Windows opengl32.dll calls glFinish prior to every swapbuffers.
* This is unnecessary and degrades performance. Luckily we have some
* scope to work around this, as the externally-visible behaviour of
* Finish() is identical to Flush() in all cases - no differences in
* rendering or ReadPixels are visible if we opt not to wait here.
*
* Only set this up on windows to avoid suprise elsewhere.
*/
#ifdef PIPE_OS_WINDOWS
functions->Finish = st_glFlush;
#endif
}
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_cb_flush.h
0,0 → 1,51
/**************************************************************************
*
* 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 ST_CB_FLUSH_H
#define ST_CB_FLUSH_H
 
 
#include "pipe/p_compiler.h"
 
struct dd_function_table;
struct pipe_fence_handle;
struct st_context;
 
extern void
st_init_flush_functions(struct dd_function_table *functions);
 
extern void
st_flush(struct st_context *st, uint pipeFlushFlags,
struct pipe_fence_handle **fence);
 
extern void
st_finish(struct st_context *st);
 
 
#endif /* ST_CB_FLUSH_H */
 
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_cb_program.c
0,0 → 1,273
/**************************************************************************
*
* 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.
*
**************************************************************************/
 
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
#include "main/glheader.h"
#include "main/macros.h"
#include "main/enums.h"
#include "main/shaderapi.h"
#include "program/prog_instruction.h"
#include "program/program.h"
 
#include "cso_cache/cso_context.h"
#include "draw/draw_context.h"
 
#include "st_context.h"
#include "st_program.h"
#include "st_mesa_to_tgsi.h"
#include "st_cb_program.h"
 
 
static GLuint SerialNo = 1;
 
 
/**
* Called via ctx->Driver.BindProgram() to bind an ARB vertex or
* fragment program.
*/
static void st_bind_program( struct gl_context *ctx,
GLenum target,
struct gl_program *prog )
{
struct st_context *st = st_context(ctx);
 
switch (target) {
case GL_VERTEX_PROGRAM_ARB:
st->dirty.st |= ST_NEW_VERTEX_PROGRAM;
break;
case GL_FRAGMENT_PROGRAM_ARB:
st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM;
break;
case MESA_GEOMETRY_PROGRAM:
st->dirty.st |= ST_NEW_GEOMETRY_PROGRAM;
break;
}
}
 
 
/**
* Called via ctx->Driver.UseProgram() to bind a linked GLSL program
* (vertex shader + fragment shader).
*/
static void st_use_program( struct gl_context *ctx, struct gl_shader_program *shProg)
{
struct st_context *st = st_context(ctx);
 
st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM;
st->dirty.st |= ST_NEW_VERTEX_PROGRAM;
st->dirty.st |= ST_NEW_GEOMETRY_PROGRAM;
}
 
 
 
/**
* Called via ctx->Driver.NewProgram() to allocate a new vertex or
* fragment program.
*/
static struct gl_program *st_new_program( struct gl_context *ctx,
GLenum target,
GLuint id )
{
switch (target) {
case GL_VERTEX_PROGRAM_ARB: {
struct st_vertex_program *prog = ST_CALLOC_STRUCT(st_vertex_program);
 
prog->serialNo = SerialNo++;
 
return _mesa_init_vertex_program( ctx,
&prog->Base,
target,
id );
}
 
case GL_FRAGMENT_PROGRAM_ARB:
case GL_FRAGMENT_PROGRAM_NV: {
struct st_fragment_program *prog = ST_CALLOC_STRUCT(st_fragment_program);
 
prog->serialNo = SerialNo++;
 
return _mesa_init_fragment_program( ctx,
&prog->Base,
target,
id );
}
 
case MESA_GEOMETRY_PROGRAM: {
struct st_geometry_program *prog = ST_CALLOC_STRUCT(st_geometry_program);
 
prog->serialNo = SerialNo++;
 
return _mesa_init_geometry_program( ctx,
&prog->Base,
target,
id );
}
 
default:
assert(0);
return NULL;
}
}
 
 
void
st_delete_program(struct gl_context *ctx, struct gl_program *prog)
{
struct st_context *st = st_context(ctx);
 
switch( prog->Target ) {
case GL_VERTEX_PROGRAM_ARB:
{
struct st_vertex_program *stvp = (struct st_vertex_program *) prog;
st_vp_release_varients( st, stvp );
}
break;
case MESA_GEOMETRY_PROGRAM:
{
struct st_geometry_program *stgp = (struct st_geometry_program *) prog;
 
if (stgp->driver_shader) {
cso_delete_geometry_shader(st->cso_context, stgp->driver_shader);
stgp->driver_shader = NULL;
}
 
if (stgp->tgsi.tokens) {
st_free_tokens((void *) stgp->tgsi.tokens);
stgp->tgsi.tokens = NULL;
}
}
break;
case GL_FRAGMENT_PROGRAM_ARB:
{
struct st_fragment_program *stfp = (struct st_fragment_program *) prog;
 
if (stfp->driver_shader) {
cso_delete_fragment_shader(st->cso_context, stfp->driver_shader);
stfp->driver_shader = NULL;
}
if (stfp->tgsi.tokens) {
st_free_tokens(stfp->tgsi.tokens);
stfp->tgsi.tokens = NULL;
}
 
if (stfp->bitmap_program) {
struct gl_program *prg = &stfp->bitmap_program->Base.Base;
_mesa_reference_program(ctx, &prg, NULL);
stfp->bitmap_program = NULL;
}
}
break;
default:
assert(0); /* problem */
}
 
/* delete base class */
_mesa_delete_program( ctx, prog );
}
 
 
static GLboolean st_is_program_native( struct gl_context *ctx,
GLenum target,
struct gl_program *prog )
{
return GL_TRUE;
}
 
 
static GLboolean st_program_string_notify( struct gl_context *ctx,
GLenum target,
struct gl_program *prog )
{
struct st_context *st = st_context(ctx);
 
if (target == GL_FRAGMENT_PROGRAM_ARB) {
struct st_fragment_program *stfp = (struct st_fragment_program *) prog;
 
stfp->serialNo++;
 
if (stfp->driver_shader) {
cso_delete_fragment_shader(st->cso_context, stfp->driver_shader);
stfp->driver_shader = NULL;
}
 
if (stfp->tgsi.tokens) {
st_free_tokens(stfp->tgsi.tokens);
stfp->tgsi.tokens = NULL;
}
 
if (st->fp == stfp)
st->dirty.st |= ST_NEW_FRAGMENT_PROGRAM;
}
else if (target == MESA_GEOMETRY_PROGRAM) {
struct st_geometry_program *stgp = (struct st_geometry_program *) prog;
 
stgp->serialNo++;
 
if (stgp->driver_shader) {
cso_delete_geometry_shader(st->cso_context, stgp->driver_shader);
stgp->driver_shader = NULL;
}
 
if (stgp->tgsi.tokens) {
st_free_tokens((void *) stgp->tgsi.tokens);
stgp->tgsi.tokens = NULL;
}
 
if (st->gp == stgp)
st->dirty.st |= ST_NEW_GEOMETRY_PROGRAM;
}
else if (target == GL_VERTEX_PROGRAM_ARB) {
struct st_vertex_program *stvp = (struct st_vertex_program *) prog;
 
stvp->serialNo++;
 
st_vp_release_varients( st, stvp );
 
if (st->vp == stvp)
st->dirty.st |= ST_NEW_VERTEX_PROGRAM;
}
 
/* XXX check if program is legal, within limits */
return GL_TRUE;
}
 
 
 
void st_init_program_functions(struct dd_function_table *functions)
{
functions->BindProgram = st_bind_program;
functions->UseProgram = st_use_program;
functions->NewProgram = st_new_program;
functions->DeleteProgram = st_delete_program;
functions->IsProgramNative = st_is_program_native;
functions->ProgramStringNotify = st_program_string_notify;
}
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_cb_program.h
0,0 → 1,43
/**************************************************************************
*
* 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 ST_CB_PROGRAM_H
#define ST_CB_PROGRAM_H
 
 
#include "main/mtypes.h"
 
struct dd_function_table;
 
extern void
st_init_program_functions(struct dd_function_table *functions);
 
extern void
st_delete_program(struct gl_context *ctx, struct gl_program *prog);
 
 
#endif
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_cb_queryobj.c
0,0 → 1,176
/**************************************************************************
*
* 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.
*
**************************************************************************/
 
 
/**
* glBegin/EndQuery interface to pipe
*
* \author Brian Paul
*/
 
 
#include "main/imports.h"
#include "main/context.h"
 
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "st_context.h"
#include "st_cb_queryobj.h"
 
 
#if FEATURE_queryobj
 
static struct gl_query_object *
st_NewQueryObject(struct gl_context *ctx, GLuint id)
{
struct st_query_object *stq = ST_CALLOC_STRUCT(st_query_object);
if (stq) {
stq->base.Id = id;
stq->base.Ready = GL_TRUE;
stq->pq = NULL;
stq->type = PIPE_QUERY_TYPES; /* an invalid value */
return &stq->base;
}
return NULL;
}
 
 
 
static void
st_DeleteQuery(struct gl_context *ctx, struct gl_query_object *q)
{
struct pipe_context *pipe = st_context(ctx)->pipe;
struct st_query_object *stq = st_query_object(q);
 
if (stq->pq) {
pipe->destroy_query(pipe, stq->pq);
stq->pq = NULL;
}
 
free(stq);
}
 
 
static void
st_BeginQuery(struct gl_context *ctx, struct gl_query_object *q)
{
struct pipe_context *pipe = st_context(ctx)->pipe;
struct st_query_object *stq = st_query_object(q);
unsigned type;
 
/* convert GL query type to Gallium query type */
switch (q->Target) {
case GL_SAMPLES_PASSED_ARB:
type = PIPE_QUERY_OCCLUSION_COUNTER;
break;
case GL_PRIMITIVES_GENERATED:
type = PIPE_QUERY_PRIMITIVES_GENERATED;
break;
case GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN:
type = PIPE_QUERY_PRIMITIVES_EMITTED;
break;
case GL_TIME_ELAPSED_EXT:
type = PIPE_QUERY_TIME_ELAPSED;
break;
default:
assert(0 && "unexpected query target in st_BeginQuery()");
return;
}
 
if (stq->pq && stq->type != type) {
/* free old query of different type */
pipe->destroy_query(pipe, stq->pq);
stq->pq = NULL;
stq->type = PIPE_QUERY_TYPES; /* an invalid value */
}
 
if (!stq->pq) {
stq->pq = pipe->create_query(pipe, type);
stq->type = type;
}
 
assert(stq->type == type);
 
pipe->begin_query(pipe, stq->pq);
}
 
 
static void
st_EndQuery(struct gl_context *ctx, struct gl_query_object *q)
{
struct pipe_context *pipe = st_context(ctx)->pipe;
struct st_query_object *stq = st_query_object(q);
 
pipe->end_query(pipe, stq->pq);
}
 
 
static void
st_WaitQuery(struct gl_context *ctx, struct gl_query_object *q)
{
struct pipe_context *pipe = st_context(ctx)->pipe;
struct st_query_object *stq = st_query_object(q);
 
/* this function should only be called if we don't have a ready result */
assert(!stq->base.Ready);
 
while (!stq->base.Ready &&
!pipe->get_query_result(pipe,
stq->pq,
TRUE,
&q->Result))
{
/* nothing */
}
q->Ready = GL_TRUE;
}
 
 
static void
st_CheckQuery(struct gl_context *ctx, struct gl_query_object *q)
{
struct pipe_context *pipe = st_context(ctx)->pipe;
struct st_query_object *stq = st_query_object(q);
assert(!q->Ready); /* we should not get called if Ready is TRUE */
q->Ready = pipe->get_query_result(pipe, stq->pq, FALSE, &q->Result);
}
 
 
 
 
void st_init_query_functions(struct dd_function_table *functions)
{
functions->NewQueryObject = st_NewQueryObject;
functions->DeleteQuery = st_DeleteQuery;
functions->BeginQuery = st_BeginQuery;
functions->EndQuery = st_EndQuery;
functions->WaitQuery = st_WaitQuery;
functions->CheckQuery = st_CheckQuery;
}
 
#endif /* FEATURE_queryobj */
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_cb_queryobj.h
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.
*
**************************************************************************/
 
#ifndef ST_CB_QUERYOBJ_H
#define ST_CB_QUERYOBJ_H
 
 
#include "main/mtypes.h"
 
/**
* Subclass of gl_query_object
*/
struct st_query_object
{
struct gl_query_object base;
struct pipe_query *pq;
unsigned type; /**< PIPE_QUERY_x */
};
 
 
/**
* Cast wrapper
*/
static INLINE struct st_query_object *
st_query_object(struct gl_query_object *q)
{
return (struct st_query_object *) q;
}
 
 
#if FEATURE_queryobj
 
extern void
st_init_query_functions(struct dd_function_table *functions);
 
#else
 
static INLINE void
st_init_query_functions(struct dd_function_table *functions)
{
}
 
#endif /* FEATURE_queryobj */
 
#endif
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_cb_rasterpos.c
0,0 → 1,271
/**************************************************************************
*
* 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.
*
**************************************************************************/
 
/**
* glRasterPos implementation. Basically render a GL_POINT with our
* private draw module. Plug in a special "rasterpos" stage at the end
* of the 'draw' pipeline to capture the results and update the current
* raster pos attributes.
*
* Authors:
* Brian Paul
*/
 
 
#include "main/imports.h"
#include "main/macros.h"
#include "main/feedback.h"
 
#include "st_context.h"
#include "st_atom.h"
#include "st_draw.h"
#include "st_cb_rasterpos.h"
#include "draw/draw_context.h"
#include "draw/draw_pipe.h"
#include "vbo/vbo.h"
 
 
#if FEATURE_rastpos
 
/**
* Our special drawing pipeline stage (replaces rasterization).
*/
struct rastpos_stage
{
struct draw_stage stage; /**< Base class */
struct gl_context *ctx; /**< Rendering context */
 
/* vertex attrib info we can setup once and re-use */
struct gl_client_array array[VERT_ATTRIB_MAX];
const struct gl_client_array *arrays[VERT_ATTRIB_MAX];
struct _mesa_prim prim;
};
 
 
static INLINE struct rastpos_stage *
rastpos_stage( struct draw_stage *stage )
{
return (struct rastpos_stage *) stage;
}
 
static void
rastpos_flush( struct draw_stage *stage, unsigned flags )
{
/* no-op */
}
 
static void
rastpos_reset_stipple_counter( struct draw_stage *stage )
{
/* no-op */
}
 
static void
rastpos_tri( struct draw_stage *stage, struct prim_header *prim )
{
/* should never get here */
assert(0);
}
 
static void
rastpos_line( struct draw_stage *stage, struct prim_header *prim )
{
/* should never get here */
assert(0);
}
 
static void
rastpos_destroy(struct draw_stage *stage)
{
free(stage);
}
 
 
/**
* Update a raster pos attribute from the vertex result if it's present,
* else copy the current attrib.
*/
static void
update_attrib(struct gl_context *ctx, const GLuint *outputMapping,
const struct vertex_header *vert,
GLfloat *dest,
GLuint result, GLuint defaultAttrib)
{
const GLfloat *src;
const GLuint k = outputMapping[result];
if (k != ~0U)
src = vert->data[k];
else
src = ctx->Current.Attrib[defaultAttrib];
COPY_4V(dest, src);
}
 
 
/**
* Normally, this function would render a GL_POINT.
*/
static void
rastpos_point(struct draw_stage *stage, struct prim_header *prim)
{
struct rastpos_stage *rs = rastpos_stage(stage);
struct gl_context *ctx = rs->ctx;
struct st_context *st = st_context(ctx);
const GLfloat height = (GLfloat) ctx->DrawBuffer->Height;
const GLuint *outputMapping = st->vertex_result_to_slot;
const GLfloat *pos;
GLuint i;
 
/* if we get here, we didn't get clipped */
ctx->Current.RasterPosValid = GL_TRUE;
 
/* update raster pos */
pos = prim->v[0]->data[0];
ctx->Current.RasterPos[0] = pos[0];
if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP)
ctx->Current.RasterPos[1] = height - pos[1]; /* invert Y */
else
ctx->Current.RasterPos[1] = pos[1];
ctx->Current.RasterPos[2] = pos[2];
ctx->Current.RasterPos[3] = pos[3];
 
/* update other raster attribs */
update_attrib(ctx, outputMapping, prim->v[0],
ctx->Current.RasterColor,
VERT_RESULT_COL0, VERT_ATTRIB_COLOR0);
 
update_attrib(ctx, outputMapping, prim->v[0],
ctx->Current.RasterSecondaryColor,
VERT_RESULT_COL1, VERT_ATTRIB_COLOR1);
 
for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
update_attrib(ctx, outputMapping, prim->v[0],
ctx->Current.RasterTexCoords[i],
VERT_RESULT_TEX0 + i, VERT_ATTRIB_TEX0 + i);
}
 
if (ctx->RenderMode == GL_SELECT) {
_mesa_update_hitflag( ctx, ctx->Current.RasterPos[2] );
}
}
 
 
/**
* Create rasterpos "drawing" stage.
*/
static struct rastpos_stage *
new_draw_rastpos_stage(struct gl_context *ctx, struct draw_context *draw)
{
struct rastpos_stage *rs = ST_CALLOC_STRUCT(rastpos_stage);
GLuint i;
 
rs->stage.draw = draw;
rs->stage.next = NULL;
rs->stage.point = rastpos_point;
rs->stage.line = rastpos_line;
rs->stage.tri = rastpos_tri;
rs->stage.flush = rastpos_flush;
rs->stage.destroy = rastpos_destroy;
rs->stage.reset_stipple_counter = rastpos_reset_stipple_counter;
rs->stage.destroy = rastpos_destroy;
rs->ctx = ctx;
 
for (i = 0; i < Elements(rs->array); i++) {
rs->array[i].Size = 4;
rs->array[i].Type = GL_FLOAT;
rs->array[i].Format = GL_RGBA;
rs->array[i].Stride = 0;
rs->array[i].StrideB = 0;
rs->array[i].Ptr = (GLubyte *) ctx->Current.Attrib[i];
rs->array[i].Enabled = GL_TRUE;
rs->array[i].Normalized = GL_TRUE;
rs->array[i].BufferObj = NULL;
rs->arrays[i] = &rs->array[i];
}
 
rs->prim.mode = GL_POINTS;
rs->prim.indexed = 0;
rs->prim.begin = 1;
rs->prim.end = 1;
rs->prim.weak = 0;
rs->prim.start = 0;
rs->prim.count = 1;
 
return rs;
}
 
 
static void
st_RasterPos(struct gl_context *ctx, const GLfloat v[4])
{
struct st_context *st = st_context(ctx);
struct draw_context *draw = st->draw;
struct rastpos_stage *rs;
 
if (st->rastpos_stage) {
/* get rastpos stage info */
rs = rastpos_stage(st->rastpos_stage);
}
else {
/* create rastpos draw stage */
rs = new_draw_rastpos_stage(ctx, draw);
st->rastpos_stage = &rs->stage;
}
 
/* plug our rastpos stage into the draw module */
draw_set_rasterize_stage(st->draw, st->rastpos_stage);
 
/* make sure everything's up to date */
st_validate_state(st);
 
/* This will get set only if rastpos_point(), above, gets called */
ctx->Current.RasterPosValid = GL_FALSE;
 
/* All vertex attribs but position were previously initialized above.
* Just plug in position pointer now.
*/
rs->array[0].Ptr = (GLubyte *) v;
 
/* draw the point */
st_feedback_draw_vbo(ctx, rs->arrays, &rs->prim, 1, NULL, GL_TRUE, 0, 1);
 
/* restore draw's rasterization stage depending on rendermode */
if (ctx->RenderMode == GL_FEEDBACK) {
draw_set_rasterize_stage(draw, st->feedback_stage);
}
else if (ctx->RenderMode == GL_SELECT) {
draw_set_rasterize_stage(draw, st->selection_stage);
}
}
 
 
 
void st_init_rasterpos_functions(struct dd_function_table *functions)
{
functions->RasterPos = st_RasterPos;
}
 
#endif /* FEATURE_rastpos */
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_cb_rasterpos.h
0,0 → 1,49
/**************************************************************************
*
* 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 ST_CB_RASTERPOS_H
#define ST_CB_RASTERPOS_H
 
 
#include "main/compiler.h"
 
struct dd_function_table;
 
#if FEATURE_rastpos
 
extern void st_init_rasterpos_functions(struct dd_function_table *functions);
 
#else
 
static INLINE void
st_init_rasterpos_functions(struct dd_function_table *functions)
{
}
 
#endif /* FEATURE_rastpos */
 
#endif /* ST_CB_RASTERPOS_H */
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_cb_readpixels.c
0,0 → 1,554
/**************************************************************************
*
* 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.
*
**************************************************************************/
 
 
/**
* glReadPixels interface to pipe
*
* \author Brian Paul
*/
 
 
#include "main/imports.h"
#include "main/bufferobj.h"
#include "main/context.h"
#include "main/image.h"
#include "main/pack.h"
 
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "util/u_inlines.h"
#include "util/u_tile.h"
 
#include "st_debug.h"
#include "st_context.h"
#include "st_atom.h"
#include "st_cb_bitmap.h"
#include "st_cb_readpixels.h"
#include "st_cb_fbo.h"
 
/**
* Special case for reading stencil buffer.
* For color/depth we use get_tile(). For stencil, map the stencil buffer.
*/
void
st_read_stencil_pixels(struct gl_context *ctx, GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *packing,
GLvoid *pixels)
{
struct gl_framebuffer *fb = ctx->ReadBuffer;
struct pipe_context *pipe = st_context(ctx)->pipe;
struct st_renderbuffer *strb = st_renderbuffer(fb->_StencilBuffer);
struct pipe_transfer *pt;
ubyte *stmap;
GLint j;
 
if (strb->Base.Wrapped) {
strb = st_renderbuffer(strb->Base.Wrapped);
}
 
if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
y = ctx->DrawBuffer->Height - y - height;
}
 
/* Create a read transfer from the renderbuffer's texture */
 
pt = pipe_get_transfer(pipe, strb->texture,
0, 0,
PIPE_TRANSFER_READ,
x, y, width, height);
 
/* map the stencil buffer */
stmap = pipe_transfer_map(pipe, pt);
 
/* width should never be > MAX_WIDTH since we did clipping earlier */
ASSERT(width <= MAX_WIDTH);
 
/* process image row by row */
for (j = 0; j < height; j++) {
GLvoid *dest;
GLstencil sValues[MAX_WIDTH];
GLfloat zValues[MAX_WIDTH];
GLint srcY;
 
if (st_fb_orientation(ctx->DrawBuffer) == Y_0_TOP) {
srcY = height - j - 1;
}
else {
srcY = j;
}
 
/* get stencil (and Z) values */
switch (pt->resource->format) {
case PIPE_FORMAT_S8_USCALED:
{
const ubyte *src = stmap + srcY * pt->stride;
memcpy(sValues, src, width);
}
break;
case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
if (format == GL_DEPTH_STENCIL) {
const uint *src = (uint *) (stmap + srcY * pt->stride);
const GLfloat scale = 1.0f / (0xffffff);
GLint k;
for (k = 0; k < width; k++) {
sValues[k] = src[k] >> 24;
zValues[k] = (src[k] & 0xffffff) * scale;
}
}
else {
const uint *src = (uint *) (stmap + srcY * pt->stride);
GLint k;
for (k = 0; k < width; k++) {
sValues[k] = src[k] >> 24;
}
}
break;
case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
if (format == GL_DEPTH_STENCIL) {
const uint *src = (uint *) (stmap + srcY * pt->stride);
const GLfloat scale = 1.0f / (0xffffff);
GLint k;
for (k = 0; k < width; k++) {
sValues[k] = src[k] & 0xff;
zValues[k] = (src[k] >> 8) * scale;
}
}
else {
const uint *src = (uint *) (stmap + srcY * pt->stride);
GLint k;
for (k = 0; k < width; k++) {
sValues[k] = src[k] & 0xff;
}
}
break;
default:
assert(0);
}
 
/* store */
dest = _mesa_image_address2d(packing, pixels, width, height,
format, type, j, 0);
if (format == GL_DEPTH_STENCIL) {
_mesa_pack_depth_stencil_span(ctx, width, dest,
zValues, sValues, packing);
}
else {
_mesa_pack_stencil_span(ctx, width, type, dest, sValues, packing);
}
}
 
/* unmap the stencil buffer */
pipe_transfer_unmap(pipe, pt);
pipe->transfer_destroy(pipe, pt);
}
 
 
/**
* Return renderbuffer to use for reading color pixels for glRead/CopyPixel
* commands.
*/
struct st_renderbuffer *
st_get_color_read_renderbuffer(struct gl_context *ctx)
{
struct gl_framebuffer *fb = ctx->ReadBuffer;
struct st_renderbuffer *strb =
st_renderbuffer(fb->_ColorReadBuffer);
 
return strb;
}
 
 
/**
* Try to do glReadPixels in a fast manner for common cases.
* \return GL_TRUE for success, GL_FALSE for failure
*/
static GLboolean
st_fast_readpixels(struct gl_context *ctx, struct st_renderbuffer *strb,
GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *pack,
GLvoid *dest)
{
enum combination {
A8R8G8B8_UNORM_TO_RGBA_UBYTE,
A8R8G8B8_UNORM_TO_RGB_UBYTE,
A8R8G8B8_UNORM_TO_BGRA_UINT
} combo;
 
if (ctx->_ImageTransferState)
return GL_FALSE;
 
if (strb->format == PIPE_FORMAT_B8G8R8A8_UNORM &&
format == GL_RGBA && type == GL_UNSIGNED_BYTE) {
combo = A8R8G8B8_UNORM_TO_RGBA_UBYTE;
}
else if (strb->format == PIPE_FORMAT_B8G8R8A8_UNORM &&
format == GL_RGB && type == GL_UNSIGNED_BYTE) {
combo = A8R8G8B8_UNORM_TO_RGB_UBYTE;
}
else if (strb->format == PIPE_FORMAT_B8G8R8A8_UNORM &&
format == GL_BGRA && type == GL_UNSIGNED_INT_8_8_8_8_REV) {
combo = A8R8G8B8_UNORM_TO_BGRA_UINT;
}
else {
return GL_FALSE;
}
 
/*printf("st_fast_readpixels combo %d\n", (GLint) combo);*/
 
{
struct pipe_context *pipe = st_context(ctx)->pipe;
struct pipe_transfer *trans;
const GLubyte *map;
GLubyte *dst;
GLint row, col, dy, dstStride;
 
if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
/* convert GL Y to Gallium Y */
y = strb->texture->height0 - y - height;
}
 
trans = pipe_get_transfer(pipe, strb->texture,
0, 0,
PIPE_TRANSFER_READ,
x, y, width, height);
if (!trans) {
return GL_FALSE;
}
 
map = pipe_transfer_map(pipe, trans);
if (!map) {
pipe->transfer_destroy(pipe, trans);
return GL_FALSE;
}
 
/* We always write to the user/dest buffer from low addr to high addr
* but the read order depends on renderbuffer orientation
*/
if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
/* read source rows from bottom to top */
y = height - 1;
dy = -1;
}
else {
/* read source rows from top to bottom */
y = 0;
dy = 1;
}
 
dst = _mesa_image_address2d(pack, dest, width, height,
format, type, 0, 0);
dstStride = _mesa_image_row_stride(pack, width, format, type);
 
switch (combo) {
case A8R8G8B8_UNORM_TO_RGBA_UBYTE:
for (row = 0; row < height; row++) {
const GLubyte *src = map + y * trans->stride;
for (col = 0; col < width; col++) {
GLuint pixel = ((GLuint *) src)[col];
dst[col*4+0] = (pixel >> 16) & 0xff;
dst[col*4+1] = (pixel >> 8) & 0xff;
dst[col*4+2] = (pixel >> 0) & 0xff;
dst[col*4+3] = (pixel >> 24) & 0xff;
}
dst += dstStride;
y += dy;
}
break;
case A8R8G8B8_UNORM_TO_RGB_UBYTE:
for (row = 0; row < height; row++) {
const GLubyte *src = map + y * trans->stride;
for (col = 0; col < width; col++) {
GLuint pixel = ((GLuint *) src)[col];
dst[col*3+0] = (pixel >> 16) & 0xff;
dst[col*3+1] = (pixel >> 8) & 0xff;
dst[col*3+2] = (pixel >> 0) & 0xff;
}
dst += dstStride;
y += dy;
}
break;
case A8R8G8B8_UNORM_TO_BGRA_UINT:
for (row = 0; row < height; row++) {
const GLubyte *src = map + y * trans->stride;
memcpy(dst, src, 4 * width);
dst += dstStride;
y += dy;
}
break;
default:
; /* nothing */
}
 
pipe_transfer_unmap(pipe, trans);
pipe->transfer_destroy(pipe, trans);
}
 
return GL_TRUE;
}
 
 
/**
* Do glReadPixels by getting rows from the framebuffer transfer with
* get_tile(). Convert to requested format/type with Mesa image routines.
* Image transfer ops are done in software too.
*/
static void
st_readpixels(struct gl_context *ctx, GLint x, GLint y, GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *pack,
GLvoid *dest)
{
struct st_context *st = st_context(ctx);
struct pipe_context *pipe = st->pipe;
GLfloat (*temp)[4];
const GLbitfield transferOps = ctx->_ImageTransferState;
GLsizei i, j;
GLint yStep, dfStride;
GLfloat *df;
struct st_renderbuffer *strb;
struct gl_pixelstore_attrib clippedPacking = *pack;
struct pipe_transfer *trans;
 
assert(ctx->ReadBuffer->Width > 0);
 
st_validate_state(st);
 
/* Do all needed clipping here, so that we can forget about it later */
if (!_mesa_clip_readpixels(ctx, &x, &y, &width, &height, &clippedPacking)) {
/* The ReadPixels transfer is totally outside the window bounds */
return;
}
 
st_flush_bitmap_cache(st);
 
dest = _mesa_map_pbo_dest(ctx, &clippedPacking, dest);
if (!dest)
return;
 
if (format == GL_STENCIL_INDEX ||
format == GL_DEPTH_STENCIL) {
st_read_stencil_pixels(ctx, x, y, width, height,
format, type, pack, dest);
return;
}
else if (format == GL_DEPTH_COMPONENT) {
strb = st_renderbuffer(ctx->ReadBuffer->_DepthBuffer);
if (strb->Base.Wrapped) {
strb = st_renderbuffer(strb->Base.Wrapped);
}
}
else {
/* Read color buffer */
strb = st_get_color_read_renderbuffer(ctx);
}
 
if (!strb)
return;
 
/* try a fast-path readpixels before anything else */
if (st_fast_readpixels(ctx, strb, x, y, width, height,
format, type, pack, dest)) {
/* success! */
_mesa_unmap_pbo_dest(ctx, &clippedPacking);
return;
}
 
/* allocate temp pixel row buffer */
temp = (GLfloat (*)[4]) malloc(4 * width * sizeof(GLfloat));
if (!temp) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glReadPixels");
return;
}
 
if (format == GL_RGBA && type == GL_FLOAT) {
/* write tile(row) directly into user's buffer */
df = (GLfloat *) _mesa_image_address2d(&clippedPacking, dest, width,
height, format, type, 0, 0);
dfStride = width * 4;
}
else {
/* write tile(row) into temp row buffer */
df = (GLfloat *) temp;
dfStride = 0;
}
 
if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
/* convert GL Y to Gallium Y */
y = strb->Base.Height - y - height;
}
 
/* Create a read transfer from the renderbuffer's texture */
trans = pipe_get_transfer(pipe, strb->texture,
0, 0,
PIPE_TRANSFER_READ,
x, y, width, height);
 
/* determine bottom-to-top vs. top-to-bottom order */
if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
y = height - 1;
yStep = -1;
}
else {
y = 0;
yStep = 1;
}
 
if (ST_DEBUG & DEBUG_FALLBACK)
debug_printf("%s: fallback processing\n", __FUNCTION__);
 
/*
* Copy pixels from pipe_transfer to user memory
*/
{
/* dest of first pixel in client memory */
GLubyte *dst = _mesa_image_address2d(&clippedPacking, dest, width,
height, format, type, 0, 0);
/* dest row stride */
const GLint dstStride = _mesa_image_row_stride(&clippedPacking, width,
format, type);
 
if (trans->resource->format == PIPE_FORMAT_Z24_UNORM_S8_USCALED ||
trans->resource->format == PIPE_FORMAT_Z24X8_UNORM) {
if (format == GL_DEPTH_COMPONENT) {
for (i = 0; i < height; i++) {
GLuint ztemp[MAX_WIDTH];
GLfloat zfloat[MAX_WIDTH];
const double scale = 1.0 / ((1 << 24) - 1);
pipe_get_tile_raw(pipe, trans, 0, y, width, 1, ztemp, 0);
y += yStep;
for (j = 0; j < width; j++) {
zfloat[j] = (float) (scale * (ztemp[j] & 0xffffff));
}
_mesa_pack_depth_span(ctx, width, dst, type,
zfloat, &clippedPacking);
dst += dstStride;
}
}
else {
/* XXX: unreachable code -- should be before st_read_stencil_pixels */
assert(format == GL_DEPTH_STENCIL_EXT);
for (i = 0; i < height; i++) {
GLuint *zshort = (GLuint *)dst;
pipe_get_tile_raw(pipe, trans, 0, y, width, 1, dst, 0);
y += yStep;
/* Reverse into 24/8 */
for (j = 0; j < width; j++) {
zshort[j] = (zshort[j] << 8) | (zshort[j] >> 24);
}
dst += dstStride;
}
}
}
else if (trans->resource->format == PIPE_FORMAT_S8_USCALED_Z24_UNORM ||
trans->resource->format == PIPE_FORMAT_X8Z24_UNORM) {
if (format == GL_DEPTH_COMPONENT) {
for (i = 0; i < height; i++) {
GLuint ztemp[MAX_WIDTH];
GLfloat zfloat[MAX_WIDTH];
const double scale = 1.0 / ((1 << 24) - 1);
pipe_get_tile_raw(pipe, trans, 0, y, width, 1, ztemp, 0);
y += yStep;
for (j = 0; j < width; j++) {
zfloat[j] = (float) (scale * ((ztemp[j] >> 8) & 0xffffff));
}
_mesa_pack_depth_span(ctx, width, dst, type,
zfloat, &clippedPacking);
dst += dstStride;
}
}
else {
/* XXX: unreachable code -- should be before st_read_stencil_pixels */
assert(format == GL_DEPTH_STENCIL_EXT);
for (i = 0; i < height; i++) {
pipe_get_tile_raw(pipe, trans, 0, y, width, 1, dst, 0);
y += yStep;
dst += dstStride;
}
}
}
else if (trans->resource->format == PIPE_FORMAT_Z16_UNORM) {
for (i = 0; i < height; i++) {
GLushort ztemp[MAX_WIDTH];
GLfloat zfloat[MAX_WIDTH];
const double scale = 1.0 / 0xffff;
pipe_get_tile_raw(pipe, trans, 0, y, width, 1, ztemp, 0);
y += yStep;
for (j = 0; j < width; j++) {
zfloat[j] = (float) (scale * ztemp[j]);
}
_mesa_pack_depth_span(ctx, width, dst, type,
zfloat, &clippedPacking);
dst += dstStride;
}
}
else if (trans->resource->format == PIPE_FORMAT_Z32_UNORM) {
for (i = 0; i < height; i++) {
GLuint ztemp[MAX_WIDTH];
GLfloat zfloat[MAX_WIDTH];
const double scale = 1.0 / 0xffffffff;
pipe_get_tile_raw(pipe, trans, 0, y, width, 1, ztemp, 0);
y += yStep;
for (j = 0; j < width; j++) {
zfloat[j] = (float) (scale * ztemp[j]);
}
_mesa_pack_depth_span(ctx, width, dst, type,
zfloat, &clippedPacking);
dst += dstStride;
}
}
else {
/* RGBA format */
/* Do a row at a time to flip image data vertically */
for (i = 0; i < height; i++) {
pipe_get_tile_rgba(pipe, trans, 0, y, width, 1, df);
y += yStep;
df += dfStride;
if (!dfStride) {
_mesa_pack_rgba_span_float(ctx, width, temp, format, type, dst,
&clippedPacking, transferOps);
dst += dstStride;
}
}
}
}
 
free(temp);
 
pipe->transfer_destroy(pipe, trans);
 
_mesa_unmap_pbo_dest(ctx, &clippedPacking);
}
 
 
void st_init_readpixels_functions(struct dd_function_table *functions)
{
functions->ReadPixels = st_readpixels;
}
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_cb_readpixels.h
0,0 → 1,50
/**************************************************************************
*
* 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 ST_CB_READPIXELS_H
#define ST_CB_READPIXELS_H
 
#include "main/mtypes.h"
 
struct dd_function_table;
 
extern struct st_renderbuffer *
st_get_color_read_renderbuffer(struct gl_context *ctx);
 
extern void
st_read_stencil_pixels(struct gl_context *ctx, GLint x, GLint y,
GLsizei width, GLsizei height,
GLenum format, GLenum type,
const struct gl_pixelstore_attrib *packing,
GLvoid *pixels);
 
extern void
st_init_readpixels_functions(struct dd_function_table *functions);
 
 
#endif /* ST_CB_READPIXELS_H */
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_cb_strings.c
0,0 → 1,73
/**************************************************************************
*
* 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 "main/glheader.h"
#include "main/macros.h"
#include "pipe/p_context.h"
#include "pipe/p_screen.h"
#include "util/u_string.h"
#include "st_context.h"
#include "st_cb_strings.h"
 
#define ST_VERSION_STRING "0.4"
 
static const GLubyte *
st_get_string(struct gl_context * ctx, GLenum name)
{
struct st_context *st = st_context(ctx);
struct pipe_screen *screen = st->pipe->screen;
 
switch (name) {
case GL_VENDOR: {
const char *vendor = screen->get_vendor( screen );
util_snprintf(st->vendor, sizeof(st->vendor), "%s", vendor);
return (GLubyte *) st->vendor;
}
 
case GL_RENDERER:
util_snprintf(st->renderer, sizeof(st->renderer), "Gallium %s on %s",
ST_VERSION_STRING,
screen->get_name( screen ));
 
return (GLubyte *) st->renderer;
 
default:
return NULL;
}
}
 
 
void st_init_string_functions(struct dd_function_table *functions)
{
functions->GetString = st_get_string;
}
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_cb_strings.h
0,0 → 1,40
/**************************************************************************
*
* 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 ST_CB_STRINGS_H
#define ST_CB_STRINGS_H
 
 
struct dd_function_table;
 
extern void
st_init_string_functions(struct dd_function_table *functions);
 
 
#endif /* ST_CB_CLEAR_H */
 
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_cb_texture.c
0,0 → 1,2018
/**************************************************************************
*
* 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 "main/mfeatures.h"
#include "main/bufferobj.h"
#include "main/enums.h"
#include "main/fbobject.h"
#include "main/formats.h"
#include "main/image.h"
#include "main/imports.h"
#include "main/macros.h"
#include "main/mipmap.h"
#include "main/pack.h"
#include "main/pixeltransfer.h"
#include "main/texcompress.h"
#include "main/texfetch.h"
#include "main/texgetimage.h"
#include "main/teximage.h"
#include "main/texobj.h"
#include "main/texstore.h"
 
#include "state_tracker/st_debug.h"
#include "state_tracker/st_context.h"
#include "state_tracker/st_cb_fbo.h"
#include "state_tracker/st_cb_flush.h"
#include "state_tracker/st_cb_texture.h"
#include "state_tracker/st_format.h"
#include "state_tracker/st_texture.h"
#include "state_tracker/st_gen_mipmap.h"
#include "state_tracker/st_atom.h"
 
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "util/u_inlines.h"
#include "pipe/p_shader_tokens.h"
#include "util/u_tile.h"
#include "util/u_blit.h"
#include "util/u_format.h"
#include "util/u_surface.h"
#include "util/u_sampler.h"
#include "util/u_math.h"
#include "util/u_box.h"
 
#define DBG if (0) printf
 
 
static enum pipe_texture_target
gl_target_to_pipe(GLenum target)
{
switch (target) {
case GL_TEXTURE_1D:
return PIPE_TEXTURE_1D;
 
case GL_TEXTURE_2D:
return PIPE_TEXTURE_2D;
 
case GL_TEXTURE_RECTANGLE_NV:
return PIPE_TEXTURE_RECT;
 
case GL_TEXTURE_3D:
return PIPE_TEXTURE_3D;
 
case GL_TEXTURE_CUBE_MAP_ARB:
return PIPE_TEXTURE_CUBE;
 
default:
assert(0);
return 0;
}
}
 
 
/** called via ctx->Driver.NewTextureImage() */
static struct gl_texture_image *
st_NewTextureImage(struct gl_context * ctx)
{
DBG("%s\n", __FUNCTION__);
(void) ctx;
return (struct gl_texture_image *) ST_CALLOC_STRUCT(st_texture_image);
}
 
 
/** called via ctx->Driver.NewTextureObject() */
static struct gl_texture_object *
st_NewTextureObject(struct gl_context * ctx, GLuint name, GLenum target)
{
struct st_texture_object *obj = ST_CALLOC_STRUCT(st_texture_object);
 
DBG("%s\n", __FUNCTION__);
_mesa_initialize_texture_object(&obj->base, name, target);
 
return &obj->base;
}
 
/** called via ctx->Driver.DeleteTextureObject() */
static void
st_DeleteTextureObject(struct gl_context *ctx,
struct gl_texture_object *texObj)
{
struct st_context *st = st_context(ctx);
struct st_texture_object *stObj = st_texture_object(texObj);
if (stObj->pt)
pipe_resource_reference(&stObj->pt, NULL);
if (stObj->sampler_view) {
if (stObj->sampler_view->context != st->pipe) {
/* Take "ownership" of this texture sampler view by setting
* its context pointer to this context. This avoids potential
* crashes when the texture object is shared among contexts
* and the original/owner context has already been destroyed.
*/
stObj->sampler_view->context = st->pipe;
}
pipe_sampler_view_reference(&stObj->sampler_view, NULL);
}
_mesa_delete_texture_object(ctx, texObj);
}
 
 
/** called via ctx->Driver.FreeTexImageData() */
static void
st_FreeTextureImageData(struct gl_context * ctx, struct gl_texture_image *texImage)
{
struct st_texture_image *stImage = st_texture_image(texImage);
 
DBG("%s\n", __FUNCTION__);
 
if (stImage->pt) {
pipe_resource_reference(&stImage->pt, NULL);
}
 
if (texImage->Data) {
_mesa_align_free(texImage->Data);
texImage->Data = NULL;
}
}
 
 
/**
* From linux kernel i386 header files, copes with odd sizes better
* than COPY_DWORDS would:
* XXX Put this in src/mesa/main/imports.h ???
*/
#if defined(PIPE_CC_GCC) && defined(PIPE_ARCH_X86)
static INLINE void *
__memcpy(void *to, const void *from, size_t n)
{
int d0, d1, d2;
__asm__ __volatile__("rep ; movsl\n\t"
"testb $2,%b4\n\t"
"je 1f\n\t"
"movsw\n"
"1:\ttestb $1,%b4\n\t"
"je 2f\n\t"
"movsb\n" "2:":"=&c"(d0), "=&D"(d1), "=&S"(d2)
:"0"(n / 4), "q"(n), "1"((long) to), "2"((long) from)
:"memory");
return (to);
}
#else
#define __memcpy(a,b,c) memcpy(a,b,c)
#endif
 
 
/**
* The system memcpy (at least on ubuntu 5.10) has problems copying
* to agp (writecombined) memory from a source which isn't 64-byte
* aligned - there is a 4x performance falloff.
*
* The x86 __memcpy is immune to this but is slightly slower
* (10%-ish) than the system memcpy.
*
* The sse_memcpy seems to have a slight cliff at 64/32 bytes, but
* isn't much faster than x86_memcpy for agp copies.
*
* TODO: switch dynamically.
*/
static void *
do_memcpy(void *dest, const void *src, size_t n)
{
if ((((unsigned long) src) & 63) || (((unsigned long) dest) & 63)) {
return __memcpy(dest, src, n);
}
else
return memcpy(dest, src, n);
}
 
 
/**
* Return default texture resource binding bitmask for the given format.
*/
static GLuint
default_bindings(struct st_context *st, enum pipe_format format)
{
struct pipe_screen *screen = st->pipe->screen;
const unsigned target = PIPE_TEXTURE_2D;
const unsigned geom = 0x0;
unsigned bindings;
 
if (util_format_is_depth_or_stencil(format))
bindings = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_DEPTH_STENCIL;
else
bindings = PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_RENDER_TARGET;
 
if (screen->is_format_supported(screen, format, target, 0, bindings, geom))
return bindings;
else
return PIPE_BIND_SAMPLER_VIEW;
}
 
 
/** Return number of image dimensions (1, 2 or 3) for a texture target. */
static GLuint
get_texture_dims(GLenum target)
{
switch (target) {
case GL_TEXTURE_1D:
case GL_TEXTURE_1D_ARRAY_EXT:
return 1;
case GL_TEXTURE_2D:
case GL_TEXTURE_CUBE_MAP_ARB:
case GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB:
case GL_TEXTURE_RECTANGLE_NV:
case GL_TEXTURE_2D_ARRAY_EXT:
return 2;
case GL_TEXTURE_3D:
return 3;
default:
assert(0 && "invalid texture target in get_texture_dims()");
return 1;
}
}
 
 
/**
* Try to allocate a pipe_resource object for the given st_texture_object.
*
* We use the given st_texture_image as a clue to determine the size of the
* mipmap image at level=0.
*
* \return GL_TRUE for success, GL_FALSE if out of memory.
*/
static GLboolean
guess_and_alloc_texture(struct st_context *st,
struct st_texture_object *stObj,
const struct st_texture_image *stImage)
{
const GLuint dims = get_texture_dims(stObj->base.Target);
GLuint level, lastLevel, width, height, depth;
GLuint bindings;
enum pipe_format fmt;
 
DBG("%s\n", __FUNCTION__);
 
assert(!stObj->pt);
 
level = stImage->level;
width = stImage->base.Width2; /* size w/out border */
height = stImage->base.Height2;
depth = stImage->base.Depth2;
 
assert(width > 0);
assert(height > 0);
assert(depth > 0);
 
/* Depending on the image's size, we can't always make a guess here.
*/
if (level > 0) {
if ( (dims >= 1 && width == 1) ||
(dims >= 2 && height == 1) ||
(dims >= 3 && depth == 1) ) {
/* we can't determine the image size at level=0 */
stObj->width0 = stObj->height0 = stObj->depth0 = 0;
/* this is not an out of memory error */
return GL_TRUE;
}
}
 
/* grow the image size until we hit level = 0 */
while (level > 0) {
if (width != 1)
width <<= 1;
if (height != 1)
height <<= 1;
if (depth != 1)
depth <<= 1;
level--;
}
 
assert(level == 0);
 
/* At this point, (width x height x depth) is the expected size of
* the level=0 mipmap image.
*/
 
/* Guess a reasonable value for lastLevel. With OpenGL we have no
* idea how many mipmap levels will be in a texture until we start
* to render with it. Make an educated guess here but be prepared
* to re-allocating a texture buffer with space for more (or fewer)
* mipmap levels later.
*/
if ((stObj->base.MinFilter == GL_NEAREST ||
stObj->base.MinFilter == GL_LINEAR ||
stImage->base._BaseFormat == GL_DEPTH_COMPONENT ||
stImage->base._BaseFormat == GL_DEPTH_STENCIL_EXT) &&
!stObj->base.GenerateMipmap &&
stImage->level == 0) {
/* only alloc space for a single mipmap level */
lastLevel = 0;
}
else {
/* alloc space for a full mipmap */
GLuint l2width = util_logbase2(width);
GLuint l2height = util_logbase2(height);
GLuint l2depth = util_logbase2(depth);
lastLevel = MAX2(MAX2(l2width, l2height), l2depth);
}
 
/* Save the level=0 dimensions */
stObj->width0 = width;
stObj->height0 = height;
stObj->depth0 = depth;
 
fmt = st_mesa_format_to_pipe_format(stImage->base.TexFormat);
 
bindings = default_bindings(st, fmt);
 
stObj->pt = st_texture_create(st,
gl_target_to_pipe(stObj->base.Target),
fmt,
lastLevel,
width,
height,
depth,
bindings);
 
DBG("%s returning %d\n", __FUNCTION__, (stObj->pt != NULL));
 
return stObj->pt != NULL;
}
 
 
/**
* Adjust pixel unpack params and image dimensions to strip off the
* texture border.
* Gallium doesn't support texture borders. They've seldem been used
* and seldom been implemented correctly anyway.
* \param unpackNew returns the new pixel unpack parameters
*/
static void
strip_texture_border(GLint border,
GLint *width, GLint *height, GLint *depth,
const struct gl_pixelstore_attrib *unpack,
struct gl_pixelstore_attrib *unpackNew)
{
assert(border > 0); /* sanity check */
 
*unpackNew = *unpack;
 
if (unpackNew->RowLength == 0)
unpackNew->RowLength = *width;
 
if (depth && unpackNew->ImageHeight == 0)
unpackNew->ImageHeight = *height;
 
unpackNew->SkipPixels += border;
if (height)
unpackNew->SkipRows += border;
if (depth)
unpackNew->SkipImages += border;
 
assert(*width >= 3);
*width = *width - 2 * border;
if (height && *height >= 3)
*height = *height - 2 * border;
if (depth && *depth >= 3)
*depth = *depth - 2 * border;
}
 
 
/**
* Try to do texture compression via rendering. If the Gallium driver
* can render into a compressed surface this will allow us to do texture
* compression.
* \return GL_TRUE for success, GL_FALSE for failure
*/
static GLboolean
compress_with_blit(struct gl_context * ctx,
GLenum target, GLint level,
GLint xoffset, GLint yoffset, GLint zoffset,
GLint width, GLint height, GLint depth,
GLenum format, GLenum type, const void *pixels,
const struct gl_pixelstore_attrib *unpack,
struct gl_texture_image *texImage)
{
const GLuint dstImageOffsets[1] = {0};
struct st_texture_image *stImage = st_texture_image(texImage);
struct st_context *st = st_context(ctx);
struct pipe_context *pipe = st->pipe;
struct pipe_screen *screen = pipe->screen;
gl_format mesa_format;
struct pipe_resource templ;
struct pipe_resource *src_tex;
struct pipe_sampler_view view_templ;
struct pipe_sampler_view *src_view;
struct pipe_surface *dst_surface, surf_tmpl;
struct pipe_transfer *tex_xfer;
void *map;
 
if (!stImage->pt) {
/* XXX: Can this happen? Should we assert? */
return GL_FALSE;
}
 
/* get destination surface (in the compressed texture) */
memset(&surf_tmpl, 0, sizeof(surf_tmpl));
surf_tmpl.format = stImage->pt->format;
surf_tmpl.usage = PIPE_BIND_RENDER_TARGET;
surf_tmpl.u.tex.level = stImage->level;
surf_tmpl.u.tex.first_layer = stImage->face;
surf_tmpl.u.tex.last_layer = stImage->face;
dst_surface = pipe->create_surface(pipe, stImage->pt, &surf_tmpl);
if (!dst_surface) {
/* can't render into this format (or other problem) */
return GL_FALSE;
}
 
/* Choose format for the temporary RGBA texture image.
*/
mesa_format = st_ChooseTextureFormat(ctx, GL_RGBA, format, type);
assert(mesa_format);
if (!mesa_format)
return GL_FALSE;
 
/* Create the temporary source texture
*/
memset(&templ, 0, sizeof(templ));
templ.target = st->internal_target;
templ.format = st_mesa_format_to_pipe_format(mesa_format);
templ.width0 = width;
templ.height0 = height;
templ.depth0 = 1;
templ.array_size = 1;
templ.last_level = 0;
templ.usage = PIPE_USAGE_DEFAULT;
templ.bind = PIPE_BIND_SAMPLER_VIEW;
src_tex = screen->resource_create(screen, &templ);
 
if (!src_tex)
return GL_FALSE;
 
/* Put user's tex data into the temporary texture
*/
tex_xfer = pipe_get_transfer(st_context(ctx)->pipe, src_tex,
0, 0, /* layer, level are zero */
PIPE_TRANSFER_WRITE,
0, 0, width, height); /* x, y, w, h */
map = pipe_transfer_map(pipe, tex_xfer);
 
_mesa_texstore(ctx, 2, GL_RGBA, mesa_format,
map, /* dest ptr */
0, 0, 0, /* dest x/y/z offset */
tex_xfer->stride, /* dest row stride (bytes) */
dstImageOffsets, /* image offsets (for 3D only) */
width, height, 1, /* size */
format, type, /* source format/type */
pixels, /* source data */
unpack); /* source data packing */
 
pipe_transfer_unmap(pipe, tex_xfer);
pipe->transfer_destroy(pipe, tex_xfer);
 
/* Create temporary sampler view */
u_sampler_view_default_template(&view_templ,
src_tex,
src_tex->format);
src_view = pipe->create_sampler_view(pipe, src_tex, &view_templ);
 
 
/* copy / compress image */
util_blit_pixels_tex(st->blit,
src_view, /* sampler view (src) */
0, 0, /* src x0, y0 */
width, height, /* src x1, y1 */
dst_surface, /* pipe_surface (dst) */
xoffset, yoffset, /* dst x0, y0 */
xoffset + width, /* dst x1 */
yoffset + height, /* dst y1 */
0.0, /* z */
PIPE_TEX_MIPFILTER_NEAREST);
 
pipe_surface_reference(&dst_surface, NULL);
pipe_resource_reference(&src_tex, NULL);
pipe_sampler_view_reference(&src_view, NULL);
 
return GL_TRUE;
}
 
 
/**
* Do glTexImage1/2/3D().
*/
static void
st_TexImage(struct gl_context * ctx,
GLint dims,
GLenum target, GLint level,
GLint internalFormat,
GLint width, GLint height, GLint depth,
GLint border,
GLenum format, GLenum type, const void *pixels,
const struct gl_pixelstore_attrib *unpack,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage,
GLsizei imageSize, GLboolean compressed_src)
{
struct st_context *st = st_context(ctx);
struct pipe_screen *screen = st->pipe->screen;
struct st_texture_object *stObj = st_texture_object(texObj);
struct st_texture_image *stImage = st_texture_image(texImage);
GLuint dstRowStride = 0;
struct gl_pixelstore_attrib unpackNB;
enum pipe_transfer_usage transfer_usage = 0;
 
DBG("%s target %s level %d %dx%dx%d border %d\n", __FUNCTION__,
_mesa_lookup_enum_by_nr(target), level, width, height, depth, border);
 
/* switch to "normal" */
if (stObj->surface_based) {
gl_format texFormat;
 
_mesa_clear_texture_object(ctx, texObj);
pipe_resource_reference(&stObj->pt, NULL);
 
/* oops, need to init this image again */
texFormat = _mesa_choose_texture_format(ctx, texObj, target, level,
internalFormat, format, type);
 
_mesa_init_teximage_fields(ctx, target, texImage,
width, height, depth, border,
internalFormat, texFormat);
 
stObj->surface_based = GL_FALSE;
}
 
/* gallium does not support texture borders, strip it off */
if (border) {
strip_texture_border(border, &width, &height, &depth, unpack, &unpackNB);
unpack = &unpackNB;
texImage->Width = width;
texImage->Height = height;
texImage->Depth = depth;
texImage->Border = 0;
border = 0;
}
else {
assert(texImage->Width == width);
assert(texImage->Height == height);
assert(texImage->Depth == depth);
}
 
stImage->face = _mesa_tex_target_to_face(target);
stImage->level = level;
 
_mesa_set_fetch_functions(texImage, dims);
 
/* Release the reference to a potentially orphaned buffer.
* Release any old malloced memory.
*/
if (stImage->pt) {
pipe_resource_reference(&stImage->pt, NULL);
assert(!texImage->Data);
}
else if (texImage->Data) {
_mesa_align_free(texImage->Data);
}
 
/*
* See if the new image is somehow incompatible with the existing
* mipmap. If so, free the old mipmap.
*/
if (stObj->pt) {
if (level > (GLint) stObj->pt->last_level ||
!st_texture_match_image(stObj->pt, &stImage->base,
stImage->face, stImage->level)) {
DBG("release it\n");
pipe_resource_reference(&stObj->pt, NULL);
assert(!stObj->pt);
pipe_sampler_view_reference(&stObj->sampler_view, NULL);
}
}
 
if (width == 0 || height == 0 || depth == 0) {
/* stop after freeing old image */
return;
}
 
if (!stObj->pt) {
if (!guess_and_alloc_texture(st, stObj, stImage)) {
/* Probably out of memory.
* Try flushing any pending rendering, then retry.
*/
st_finish(st);
if (!guess_and_alloc_texture(st, stObj, stImage)) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
return;
}
}
}
 
assert(!stImage->pt);
 
/* Check if this texture image can live inside the texture object's buffer.
* If so, store the image there. Otherwise the image will temporarily live
* in its own buffer.
*/
if (stObj->pt &&
st_texture_match_image(stObj->pt, &stImage->base,
stImage->face, stImage->level)) {
 
pipe_resource_reference(&stImage->pt, stObj->pt);
assert(stImage->pt);
}
 
if (!stImage->pt)
DBG("XXX: Image did not fit into texture - storing in local memory!\n");
 
/* Pixel data may come from regular user memory or a PBO. For the later,
* do bounds checking and map the PBO to read pixels data from it.
*
* XXX we should try to use a GPU-accelerated path to copy the image data
* from the PBO to the texture.
*/
if (compressed_src) {
pixels = _mesa_validate_pbo_compressed_teximage(ctx, imageSize, pixels,
unpack,
"glCompressedTexImage");
}
else {
pixels = _mesa_validate_pbo_teximage(ctx, dims, width, height, 1,
format, type,
pixels, unpack, "glTexImage");
}
 
/* See if we can do texture compression with a blit/render.
*/
if (!compressed_src &&
!ctx->Mesa_DXTn &&
_mesa_is_format_compressed(texImage->TexFormat) &&
screen->is_format_supported(screen,
stImage->pt->format,
stImage->pt->target, 0,
PIPE_BIND_RENDER_TARGET, 0)) {
if (!pixels)
goto done;
 
if (compress_with_blit(ctx, target, level, 0, 0, 0, width, height, depth,
format, type, pixels, unpack, texImage)) {
goto done;
}
}
 
/*
* Prepare to store the texture data. Either map the gallium texture buffer
* memory or malloc space for it.
*/
if (stImage->pt) {
/* Store the image in the gallium texture memory buffer */
if (format == GL_DEPTH_COMPONENT &&
util_format_is_depth_and_stencil(stImage->pt->format))
transfer_usage = PIPE_TRANSFER_READ_WRITE;
else
transfer_usage = PIPE_TRANSFER_WRITE;
 
texImage->Data = st_texture_image_map(st, stImage, 0,
transfer_usage, 0, 0, width, height);
if(stImage->transfer)
dstRowStride = stImage->transfer->stride;
}
else {
/* Allocate regular memory and store the image there temporarily. */
GLuint imageSize = _mesa_format_image_size(texImage->TexFormat,
width, height, depth);
dstRowStride = _mesa_format_row_stride(texImage->TexFormat, width);
 
texImage->Data = _mesa_align_malloc(imageSize, 16);
}
 
if (!texImage->Data) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
return;
}
 
if (!pixels) {
/* We've allocated texture memory, but have no pixel data - all done. */
goto done;
}
 
DBG("Upload image %dx%dx%d row_len %x pitch %x\n",
width, height, depth, width, dstRowStride);
 
/* Copy user texture image into the texture buffer.
*/
if (compressed_src) {
const GLuint srcRowStride =
_mesa_format_row_stride(texImage->TexFormat, width);
if (dstRowStride == srcRowStride) {
memcpy(texImage->Data, pixels, imageSize);
}
else {
char *dst = texImage->Data;
const char *src = pixels;
GLuint i, bw, bh, lines;
_mesa_get_format_block_size(texImage->TexFormat, &bw, &bh);
lines = (height + bh - 1) / bh;
 
for (i = 0; i < lines; ++i) {
memcpy(dst, src, srcRowStride);
dst += dstRowStride;
src += srcRowStride;
}
}
}
else {
const GLuint srcImageStride =
_mesa_image_image_stride(unpack, width, height, format, type);
GLint i;
const GLubyte *src = (const GLubyte *) pixels;
 
for (i = 0; i < depth; i++) {
if (!_mesa_texstore(ctx, dims,
texImage->_BaseFormat,
texImage->TexFormat,
texImage->Data,
0, 0, 0, /* dstX/Y/Zoffset */
dstRowStride,
texImage->ImageOffsets,
width, height, 1,
format, type, src, unpack)) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
}
 
if (stImage->pt && i + 1 < depth) {
/* unmap this slice */
st_texture_image_unmap(st, stImage);
/* map next slice of 3D texture */
texImage->Data = st_texture_image_map(st, stImage, i + 1,
transfer_usage, 0, 0,
width, height);
src += srcImageStride;
}
}
}
 
done:
_mesa_unmap_teximage_pbo(ctx, unpack);
 
if (stImage->pt && texImage->Data) {
st_texture_image_unmap(st, stImage);
texImage->Data = NULL;
}
}
 
 
static void
st_TexImage3D(struct gl_context * ctx,
GLenum target, GLint level,
GLint internalFormat,
GLint width, GLint height, GLint depth,
GLint border,
GLenum format, GLenum type, const void *pixels,
const struct gl_pixelstore_attrib *unpack,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
st_TexImage(ctx, 3, target, level, internalFormat, width, height, depth,
border, format, type, pixels, unpack, texObj, texImage,
0, GL_FALSE);
}
 
 
static void
st_TexImage2D(struct gl_context * ctx,
GLenum target, GLint level,
GLint internalFormat,
GLint width, GLint height, GLint border,
GLenum format, GLenum type, const void *pixels,
const struct gl_pixelstore_attrib *unpack,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
st_TexImage(ctx, 2, target, level, internalFormat, width, height, 1, border,
format, type, pixels, unpack, texObj, texImage, 0, GL_FALSE);
}
 
 
static void
st_TexImage1D(struct gl_context * ctx,
GLenum target, GLint level,
GLint internalFormat,
GLint width, GLint border,
GLenum format, GLenum type, const void *pixels,
const struct gl_pixelstore_attrib *unpack,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
st_TexImage(ctx, 1, target, level, internalFormat, width, 1, 1, border,
format, type, pixels, unpack, texObj, texImage, 0, GL_FALSE);
}
 
 
static void
st_CompressedTexImage2D(struct gl_context *ctx, GLenum target, GLint level,
GLint internalFormat,
GLint width, GLint height, GLint border,
GLsizei imageSize, const GLvoid *data,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
st_TexImage(ctx, 2, target, level, internalFormat, width, height, 1, border,
0, 0, data, &ctx->Unpack, texObj, texImage, imageSize, GL_TRUE);
}
 
 
 
/**
* glGetTexImage() helper: decompress a compressed texture by rendering
* a textured quad. Store the results in the user's buffer.
*/
static void
decompress_with_blit(struct gl_context * ctx, GLenum target, GLint level,
GLenum format, GLenum type, GLvoid *pixels,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
struct st_context *st = st_context(ctx);
struct pipe_context *pipe = st->pipe;
struct st_texture_image *stImage = st_texture_image(texImage);
struct st_texture_object *stObj = st_texture_object(texObj);
struct pipe_sampler_view *src_view =
st_get_texture_sampler_view(stObj, pipe);
const GLuint width = texImage->Width;
const GLuint height = texImage->Height;
struct pipe_surface *dst_surface;
struct pipe_resource *dst_texture;
struct pipe_transfer *tex_xfer;
unsigned bind = (PIPE_BIND_RENDER_TARGET | /* util_blit may choose to render */
PIPE_BIND_TRANSFER_READ);
 
/* create temp / dest surface */
if (!util_create_rgba_surface(pipe, width, height, bind,
&dst_texture, &dst_surface)) {
_mesa_problem(ctx, "util_create_rgba_surface() failed "
"in decompress_with_blit()");
return;
}
 
/* blit/render/decompress */
util_blit_pixels_tex(st->blit,
src_view, /* pipe_resource (src) */
0, 0, /* src x0, y0 */
width, height, /* src x1, y1 */
dst_surface, /* pipe_surface (dst) */
0, 0, /* dst x0, y0 */
width, height, /* dst x1, y1 */
0.0, /* z */
PIPE_TEX_MIPFILTER_NEAREST);
 
/* map the dst_surface so we can read from it */
tex_xfer = pipe_get_transfer(st_context(ctx)->pipe,
dst_texture, 0, 0,
PIPE_TRANSFER_READ,
0, 0, width, height);
 
pixels = _mesa_map_pbo_dest(ctx, &ctx->Pack, pixels);
 
/* copy/pack data into user buffer */
if (st_equal_formats(stImage->pt->format, format, type)) {
/* memcpy */
const uint bytesPerRow = width * util_format_get_blocksize(stImage->pt->format);
ubyte *map = pipe_transfer_map(pipe, tex_xfer);
GLuint row;
for (row = 0; row < height; row++) {
GLvoid *dest = _mesa_image_address2d(&ctx->Pack, pixels, width,
height, format, type, row, 0);
memcpy(dest, map, bytesPerRow);
map += tex_xfer->stride;
}
pipe_transfer_unmap(pipe, tex_xfer);
}
else {
/* format translation via floats */
GLuint row;
for (row = 0; row < height; row++) {
const GLbitfield transferOps = 0x0; /* bypassed for glGetTexImage() */
GLfloat rgba[4 * MAX_WIDTH];
GLvoid *dest = _mesa_image_address2d(&ctx->Pack, pixels, width,
height, format, type, row, 0);
 
if (ST_DEBUG & DEBUG_FALLBACK)
debug_printf("%s: fallback format translation\n", __FUNCTION__);
 
/* get float[4] rgba row from surface */
pipe_get_tile_rgba(pipe, tex_xfer, 0, row, width, 1, rgba);
 
_mesa_pack_rgba_span_float(ctx, width, (GLfloat (*)[4]) rgba, format,
type, dest, &ctx->Pack, transferOps);
}
}
 
_mesa_unmap_pbo_dest(ctx, &ctx->Pack);
 
pipe->transfer_destroy(pipe, tex_xfer);
 
/* destroy the temp / dest surface */
util_destroy_rgba_surface(dst_texture, dst_surface);
}
 
 
 
/**
* Need to map texture image into memory before copying image data,
* then unmap it.
*/
static void
st_get_tex_image(struct gl_context * ctx, GLenum target, GLint level,
GLenum format, GLenum type, GLvoid * pixels,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage, GLboolean compressed_dst)
{
struct st_context *st = st_context(ctx);
struct st_texture_image *stImage = st_texture_image(texImage);
const GLuint dstImageStride =
_mesa_image_image_stride(&ctx->Pack, texImage->Width, texImage->Height,
format, type);
GLuint depth, i;
GLubyte *dest;
 
if (stImage->pt &&
util_format_is_s3tc(stImage->pt->format) &&
!compressed_dst) {
/* Need to decompress the texture.
* We'll do this by rendering a textured quad.
* Note that we only expect RGBA formats (no Z/depth formats).
*/
decompress_with_blit(ctx, target, level, format, type, pixels,
texObj, texImage);
return;
}
 
/* Map */
if (stImage->pt) {
/* Image is stored in hardware format in a buffer managed by the
* kernel. Need to explicitly map and unmap it.
*/
texImage->Data = st_texture_image_map(st, stImage, 0,
PIPE_TRANSFER_READ, 0, 0,
stImage->base.Width,
stImage->base.Height);
/* compute stride in texels from stride in bytes */
texImage->RowStride = stImage->transfer->stride
* util_format_get_blockwidth(stImage->pt->format)
/ util_format_get_blocksize(stImage->pt->format);
}
else {
/* Otherwise, the image should actually be stored in
* texImage->Data. This is pretty confusing for
* everybody, I'd much prefer to separate the two functions of
* texImage->Data - storage for texture images in main memory
* and access (ie mappings) of images. In other words, we'd
* create a new texImage->Map field and leave Data simply for
* storage.
*/
assert(texImage->Data);
}
 
depth = texImage->Depth;
texImage->Depth = 1;
 
dest = (GLubyte *) pixels;
 
_mesa_set_fetch_functions(texImage, get_texture_dims(target));
 
for (i = 0; i < depth; i++) {
if (compressed_dst) {
_mesa_get_compressed_teximage(ctx, target, level, dest,
texObj, texImage);
}
else {
_mesa_get_teximage(ctx, target, level, format, type, dest,
texObj, texImage);
}
 
if (stImage->pt && i + 1 < depth) {
/* unmap this slice */
st_texture_image_unmap(st, stImage);
/* map next slice of 3D texture */
texImage->Data = st_texture_image_map(st, stImage, i + 1,
PIPE_TRANSFER_READ, 0, 0,
stImage->base.Width,
stImage->base.Height);
dest += dstImageStride;
}
}
 
texImage->Depth = depth;
 
/* Unmap */
if (stImage->pt) {
st_texture_image_unmap(st, stImage);
texImage->Data = NULL;
}
}
 
 
static void
st_GetTexImage(struct gl_context * ctx, GLenum target, GLint level,
GLenum format, GLenum type, GLvoid * pixels,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
st_get_tex_image(ctx, target, level, format, type, pixels, texObj, texImage,
GL_FALSE);
}
 
 
static void
st_GetCompressedTexImage(struct gl_context *ctx, GLenum target, GLint level,
GLvoid *pixels,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
st_get_tex_image(ctx, target, level, 0, 0, pixels, texObj, texImage,
GL_TRUE);
}
 
 
 
static void
st_TexSubimage(struct gl_context *ctx, GLint dims, GLenum target, GLint level,
GLint xoffset, GLint yoffset, GLint zoffset,
GLint width, GLint height, GLint depth,
GLenum format, GLenum type, const void *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
struct st_context *st = st_context(ctx);
struct pipe_screen *screen = st->pipe->screen;
struct st_texture_image *stImage = st_texture_image(texImage);
GLuint dstRowStride;
const GLuint srcImageStride =
_mesa_image_image_stride(packing, width, height, format, type);
GLint i;
const GLubyte *src;
/* init to silence warning only: */
enum pipe_transfer_usage transfer_usage = PIPE_TRANSFER_WRITE;
 
DBG("%s target %s level %d offset %d,%d %dx%d\n", __FUNCTION__,
_mesa_lookup_enum_by_nr(target),
level, xoffset, yoffset, width, height);
 
pixels =
_mesa_validate_pbo_teximage(ctx, dims, width, height, depth, format,
type, pixels, packing, "glTexSubImage2D");
if (!pixels)
return;
 
/* See if we can do texture compression with a blit/render.
*/
if (!ctx->Mesa_DXTn &&
_mesa_is_format_compressed(texImage->TexFormat) &&
screen->is_format_supported(screen,
stImage->pt->format,
stImage->pt->target, 0,
PIPE_BIND_RENDER_TARGET, 0)) {
if (compress_with_blit(ctx, target, level,
xoffset, yoffset, zoffset,
width, height, depth,
format, type, pixels, packing, texImage)) {
goto done;
}
}
 
/* Map buffer if necessary. Need to lock to prevent other contexts
* from uploading the buffer under us.
*/
if (stImage->pt) {
if (format == GL_DEPTH_COMPONENT &&
util_format_is_depth_and_stencil(stImage->pt->format))
transfer_usage = PIPE_TRANSFER_READ_WRITE;
else
transfer_usage = PIPE_TRANSFER_WRITE;
 
texImage->Data = st_texture_image_map(st, stImage, zoffset,
transfer_usage,
xoffset, yoffset,
width, height);
}
 
if (!texImage->Data) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage");
goto done;
}
 
src = (const GLubyte *) pixels;
dstRowStride = stImage->transfer->stride;
 
for (i = 0; i < depth; i++) {
if (!_mesa_texstore(ctx, dims, texImage->_BaseFormat,
texImage->TexFormat,
texImage->Data,
0, 0, 0,
dstRowStride,
texImage->ImageOffsets,
width, height, 1,
format, type, src, packing)) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage");
}
 
if (stImage->pt && i + 1 < depth) {
/* unmap this slice */
st_texture_image_unmap(st, stImage);
/* map next slice of 3D texture */
texImage->Data = st_texture_image_map(st, stImage,
zoffset + i + 1,
transfer_usage,
xoffset, yoffset,
width, height);
src += srcImageStride;
}
}
 
done:
_mesa_unmap_teximage_pbo(ctx, packing);
 
if (stImage->pt && texImage->Data) {
st_texture_image_unmap(st, stImage);
texImage->Data = NULL;
}
}
 
 
 
static void
st_TexSubImage3D(struct gl_context *ctx, GLenum target, GLint level,
GLint xoffset, GLint yoffset, GLint zoffset,
GLsizei width, GLsizei height, GLsizei depth,
GLenum format, GLenum type, const GLvoid *pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
st_TexSubimage(ctx, 3, target, level, xoffset, yoffset, zoffset,
width, height, depth, format, type,
pixels, packing, texObj, texImage);
}
 
 
static void
st_TexSubImage2D(struct gl_context *ctx, GLenum target, GLint level,
GLint xoffset, GLint yoffset,
GLsizei width, GLsizei height,
GLenum format, GLenum type, const GLvoid * pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
st_TexSubimage(ctx, 2, target, level, xoffset, yoffset, 0,
width, height, 1, format, type,
pixels, packing, texObj, texImage);
}
 
 
static void
st_TexSubImage1D(struct gl_context *ctx, GLenum target, GLint level,
GLint xoffset, GLsizei width, GLenum format, GLenum type,
const GLvoid * pixels,
const struct gl_pixelstore_attrib *packing,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
st_TexSubimage(ctx, 1, target, level, xoffset, 0, 0, width, 1, 1,
format, type, pixels, packing, texObj, texImage);
}
 
 
static void
st_CompressedTexSubImage1D(struct gl_context *ctx, GLenum target, GLint level,
GLint xoffset, GLsizei width,
GLenum format,
GLsizei imageSize, const GLvoid *data,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
assert(0);
}
 
 
static void
st_CompressedTexSubImage2D(struct gl_context *ctx, GLenum target, GLint level,
GLint xoffset, GLint yoffset,
GLsizei width, GLint height,
GLenum format,
GLsizei imageSize, const GLvoid *data,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
struct st_context *st = st_context(ctx);
struct st_texture_image *stImage = st_texture_image(texImage);
int srcBlockStride;
int dstBlockStride;
int y;
enum pipe_format pformat;
 
if (stImage->pt) {
pformat = stImage->pt->format;
 
texImage->Data = st_texture_image_map(st, stImage, 0,
PIPE_TRANSFER_WRITE,
xoffset, yoffset,
width, height);
srcBlockStride = util_format_get_stride(pformat, width);
dstBlockStride = stImage->transfer->stride;
} else {
assert(stImage->pt);
/* TODO find good values for block and strides */
/* TODO also adjust texImage->data for yoffset/xoffset */
return;
}
 
if (!texImage->Data) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glCompressedTexSubImage");
return;
}
 
assert(xoffset % util_format_get_blockwidth(pformat) == 0);
assert(yoffset % util_format_get_blockheight(pformat) == 0);
 
for (y = 0; y < height; y += util_format_get_blockheight(pformat)) {
/* don't need to adjust for xoffset and yoffset as st_texture_image_map does that */
const char *src = (const char*)data + srcBlockStride * util_format_get_nblocksy(pformat, y);
char *dst = (char*)texImage->Data + dstBlockStride * util_format_get_nblocksy(pformat, y);
memcpy(dst, src, util_format_get_stride(pformat, width));
}
 
if (stImage->pt) {
st_texture_image_unmap(st, stImage);
texImage->Data = NULL;
}
}
 
 
static void
st_CompressedTexSubImage3D(struct gl_context *ctx, GLenum target, GLint level,
GLint xoffset, GLint yoffset, GLint zoffset,
GLsizei width, GLint height, GLint depth,
GLenum format,
GLsizei imageSize, const GLvoid *data,
struct gl_texture_object *texObj,
struct gl_texture_image *texImage)
{
assert(0);
}
 
 
 
/**
* Do a CopyTexSubImage operation using a read transfer from the source,
* a write transfer to the destination and get_tile()/put_tile() to access
* the pixels/texels.
*
* Note: srcY=0=TOP of renderbuffer
*/
static void
fallback_copy_texsubimage(struct gl_context *ctx, GLenum target, GLint level,
struct st_renderbuffer *strb,
struct st_texture_image *stImage,
GLenum baseFormat,
GLint destX, GLint destY, GLint destZ,
GLint srcX, GLint srcY,
GLsizei width, GLsizei height)
{
struct st_context *st = st_context(ctx);
struct pipe_context *pipe = st->pipe;
struct pipe_transfer *src_trans;
GLvoid *texDest;
enum pipe_transfer_usage transfer_usage;
 
if (ST_DEBUG & DEBUG_FALLBACK)
debug_printf("%s: fallback processing\n", __FUNCTION__);
 
assert(width <= MAX_WIDTH);
 
if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
srcY = strb->Base.Height - srcY - height;
}
 
src_trans = pipe_get_transfer(st_context(ctx)->pipe,
strb->texture,
0, 0,
PIPE_TRANSFER_READ,
srcX, srcY,
width, height);
 
if ((baseFormat == GL_DEPTH_COMPONENT ||
baseFormat == GL_DEPTH_STENCIL) &&
util_format_is_depth_and_stencil(stImage->pt->format))
transfer_usage = PIPE_TRANSFER_READ_WRITE;
else
transfer_usage = PIPE_TRANSFER_WRITE;
 
/* XXX this used to ignore destZ param */
texDest = st_texture_image_map(st, stImage, destZ, transfer_usage,
destX, destY, width, height);
 
if (baseFormat == GL_DEPTH_COMPONENT ||
baseFormat == GL_DEPTH_STENCIL) {
const GLboolean scaleOrBias = (ctx->Pixel.DepthScale != 1.0F ||
ctx->Pixel.DepthBias != 0.0F);
GLint row, yStep;
 
/* determine bottom-to-top vs. top-to-bottom order for src buffer */
if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
srcY = height - 1;
yStep = -1;
}
else {
srcY = 0;
yStep = 1;
}
 
/* To avoid a large temp memory allocation, do copy row by row */
for (row = 0; row < height; row++, srcY += yStep) {
uint data[MAX_WIDTH];
pipe_get_tile_z(pipe, src_trans, 0, srcY, width, 1, data);
if (scaleOrBias) {
_mesa_scale_and_bias_depth_uint(ctx, width, data);
}
pipe_put_tile_z(pipe, stImage->transfer, 0, row, width, 1, data);
}
}
else {
/* RGBA format */
GLfloat *tempSrc =
(GLfloat *) malloc(width * height * 4 * sizeof(GLfloat));
 
if (tempSrc && texDest) {
const GLint dims = 2;
const GLint dstRowStride = stImage->transfer->stride;
struct gl_texture_image *texImage = &stImage->base;
struct gl_pixelstore_attrib unpack = ctx->DefaultPacking;
 
if (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP) {
unpack.Invert = GL_TRUE;
}
 
/* get float/RGBA image from framebuffer */
/* XXX this usually involves a lot of int/float conversion.
* try to avoid that someday.
*/
pipe_get_tile_rgba(pipe, src_trans, 0, 0, width, height, tempSrc);
 
/* Store into texture memory.
* Note that this does some special things such as pixel transfer
* ops and format conversion. In particular, if the dest tex format
* is actually RGBA but the user created the texture as GL_RGB we
* need to fill-in/override the alpha channel with 1.0.
*/
_mesa_texstore(ctx, dims,
texImage->_BaseFormat,
texImage->TexFormat,
texDest,
0, 0, 0,
dstRowStride,
texImage->ImageOffsets,
width, height, 1,
GL_RGBA, GL_FLOAT, tempSrc, /* src */
&unpack);
}
else {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexSubImage");
}
 
if (tempSrc)
free(tempSrc);
}
 
st_texture_image_unmap(st, stImage);
pipe->transfer_destroy(pipe, src_trans);
}
 
 
 
/**
* If the format of the src renderbuffer and the format of the dest
* texture are compatible (in terms of blitting), return a TGSI writemask
* to be used during the blit.
* If the src/dest are incompatible, return 0.
*/
static unsigned
compatible_src_dst_formats(struct gl_context *ctx,
const struct gl_renderbuffer *src,
const struct gl_texture_image *dst)
{
/* Get logical base formats for the src and dest.
* That is, use the user-requested formats and not the actual, device-
* chosen formats.
* For example, the user may have requested an A8 texture but the
* driver may actually be using an RGBA texture format. When we
* copy/blit to that texture, we only want to copy the Alpha channel
* and not the RGB channels.
*
* Similarly, when the src FBO was created an RGB format may have been
* requested but the driver actually chose an RGBA format. In that case,
* we don't want to copy the undefined Alpha channel to the dest texture
* (it should be 1.0).
*/
const GLenum srcFormat = _mesa_base_fbo_format(ctx, src->InternalFormat);
const GLenum dstFormat = _mesa_base_tex_format(ctx, dst->InternalFormat);
 
/**
* XXX when we have red-only and red/green renderbuffers we'll need
* to add more cases here (or implement a general-purpose routine that
* queries the existance of the R,G,B,A channels in the src and dest).
*/
if (srcFormat == dstFormat) {
/* This is the same as matching_base_formats, which should
* always pass, as it did previously.
*/
return TGSI_WRITEMASK_XYZW;
}
else if (srcFormat == GL_RGB && dstFormat == GL_RGBA) {
/* Make sure that A in the dest is 1. The actual src format
* may be RGBA and have undefined A values.
*/
return TGSI_WRITEMASK_XYZ;
}
else if (srcFormat == GL_RGBA && dstFormat == GL_RGB) {
/* Make sure that A in the dest is 1. The actual dst format
* may be RGBA and will need A=1 to provide proper alpha values
* when sampled later.
*/
return TGSI_WRITEMASK_XYZ;
}
else {
if (ST_DEBUG & DEBUG_FALLBACK)
debug_printf("%s failed for src %s, dst %s\n",
__FUNCTION__,
_mesa_lookup_enum_by_nr(srcFormat),
_mesa_lookup_enum_by_nr(dstFormat));
 
/* Otherwise fail.
*/
return 0;
}
}
 
 
 
/**
* Do a CopyTex[Sub]Image1/2/3D() using a hardware (blit) path if possible.
* Note that the region to copy has already been clipped so we know we
* won't read from outside the source renderbuffer's bounds.
*
* Note: srcY=0=Bottom of renderbuffer (GL convention)
*/
static void
st_copy_texsubimage(struct gl_context *ctx,
GLenum target, GLint level,
GLint destX, GLint destY, GLint destZ,
GLint srcX, GLint srcY,
GLsizei width, GLsizei height)
{
struct gl_texture_unit *texUnit =
&ctx->Texture.Unit[ctx->Texture.CurrentUnit];
struct gl_texture_object *texObj =
_mesa_select_tex_object(ctx, texUnit, target);
struct gl_texture_image *texImage =
_mesa_select_tex_image(ctx, texObj, target, level);
struct st_texture_image *stImage = st_texture_image(texImage);
const GLenum texBaseFormat = texImage->_BaseFormat;
struct gl_framebuffer *fb = ctx->ReadBuffer;
struct st_renderbuffer *strb;
struct st_context *st = st_context(ctx);
struct pipe_context *pipe = st->pipe;
struct pipe_screen *screen = pipe->screen;
enum pipe_format dest_format, src_format;
GLboolean use_fallback = GL_TRUE;
GLboolean matching_base_formats;
GLuint format_writemask, sample_count;
struct pipe_surface *dest_surface = NULL;
GLboolean do_flip = (st_fb_orientation(ctx->ReadBuffer) == Y_0_TOP);
 
/* make sure finalize_textures has been called?
*/
if (0) st_validate_state(st);
 
/* determine if copying depth or color data */
if (texBaseFormat == GL_DEPTH_COMPONENT ||
texBaseFormat == GL_DEPTH_STENCIL) {
strb = st_renderbuffer(fb->_DepthBuffer);
if (strb->Base.Wrapped) {
strb = st_renderbuffer(strb->Base.Wrapped);
}
}
else {
/* texBaseFormat == GL_RGB, GL_RGBA, GL_ALPHA, etc */
strb = st_renderbuffer(fb->_ColorReadBuffer);
}
 
if (!strb || !strb->surface || !stImage->pt) {
debug_printf("%s: null strb or stImage\n", __FUNCTION__);
return;
}
 
sample_count = strb->surface->texture->nr_samples;
/* I believe this would be legal, presumably would need to do a resolve
for color, and for depth/stencil spec says to just use one of the
depth/stencil samples per pixel? Need some transfer clarifications. */
assert(sample_count < 2);
 
if (srcX < 0) {
width -= -srcX;
destX += -srcX;
srcX = 0;
}
 
if (srcY < 0) {
height -= -srcY;
destY += -srcY;
srcY = 0;
}
 
if (destX < 0) {
width -= -destX;
srcX += -destX;
destX = 0;
}
 
if (destY < 0) {
height -= -destY;
srcY += -destY;
destY = 0;
}
 
if (width < 0 || height < 0)
return;
 
 
assert(strb);
assert(strb->surface);
assert(stImage->pt);
 
src_format = strb->surface->format;
dest_format = stImage->pt->format;
 
/*
* Determine if the src framebuffer and dest texture have the same
* base format. We need this to detect a case such as the framebuffer
* being GL_RGBA but the texture being GL_RGB. If the actual hardware
* texture format stores RGBA we need to set A=1 (overriding the
* framebuffer's alpha values). We can't do that with the blit or
* textured-quad paths.
*/
matching_base_formats =
(_mesa_get_format_base_format(strb->Base.Format) ==
_mesa_get_format_base_format(texImage->TexFormat));
format_writemask = compatible_src_dst_formats(ctx, &strb->Base, texImage);
 
if (ctx->_ImageTransferState == 0x0) {
 
if (matching_base_formats &&
src_format == dest_format &&
!do_flip)
{
/* use surface_copy() / blit */
struct pipe_box src_box;
u_box_2d_zslice(srcX, srcY, strb->surface->u.tex.first_layer,
width, height, &src_box);
 
/* for resource_copy_region(), y=0=top, always */
pipe->resource_copy_region(pipe,
/* dest */
stImage->pt,
stImage->level,
destX, destY, destZ + stImage->face,
/* src */
strb->texture,
strb->surface->u.tex.level,
&src_box);
use_fallback = GL_FALSE;
}
else if (format_writemask &&
texBaseFormat != GL_DEPTH_COMPONENT &&
texBaseFormat != GL_DEPTH_STENCIL &&
screen->is_format_supported(screen, src_format,
PIPE_TEXTURE_2D, sample_count,
PIPE_BIND_SAMPLER_VIEW,
0) &&
screen->is_format_supported(screen, dest_format,
PIPE_TEXTURE_2D, 0,
PIPE_BIND_RENDER_TARGET,
0)) {
/* draw textured quad to do the copy */
GLint srcY0, srcY1;
struct pipe_surface surf_tmpl;
memset(&surf_tmpl, 0, sizeof(surf_tmpl));
surf_tmpl.format = stImage->pt->format;
surf_tmpl.usage = PIPE_BIND_RENDER_TARGET;
surf_tmpl.u.tex.level = stImage->level;
surf_tmpl.u.tex.first_layer = stImage->face + destZ;
surf_tmpl.u.tex.last_layer = stImage->face + destZ;
 
dest_surface = pipe->create_surface(pipe, stImage->pt,
&surf_tmpl);
 
if (do_flip) {
srcY1 = strb->Base.Height - srcY - height;
srcY0 = srcY1 + height;
}
else {
srcY0 = srcY;
srcY1 = srcY0 + height;
}
 
util_blit_pixels_writemask(st->blit,
strb->texture,
strb->surface->u.tex.level,
srcX, srcY0,
srcX + width, srcY1,
strb->surface->u.tex.first_layer,
dest_surface,
destX, destY,
destX + width, destY + height,
0.0, PIPE_TEX_MIPFILTER_NEAREST,
format_writemask);
use_fallback = GL_FALSE;
}
 
if (dest_surface)
pipe_surface_reference(&dest_surface, NULL);
}
 
if (use_fallback) {
/* software fallback */
fallback_copy_texsubimage(ctx, target, level,
strb, stImage, texBaseFormat,
destX, destY, destZ,
srcX, srcY, width, height);
}
}
 
 
 
static void
st_CopyTexImage1D(struct gl_context * ctx, GLenum target, GLint level,
GLenum internalFormat,
GLint x, GLint y, GLsizei width, GLint border)
{
struct gl_texture_unit *texUnit =
&ctx->Texture.Unit[ctx->Texture.CurrentUnit];
struct gl_texture_object *texObj =
_mesa_select_tex_object(ctx, texUnit, target);
struct gl_texture_image *texImage =
_mesa_select_tex_image(ctx, texObj, target, level);
 
/* Setup or redefine the texture object, texture and texture
* image. Don't populate yet.
*/
ctx->Driver.TexImage1D(ctx, target, level, internalFormat,
width, border,
GL_RGBA, CHAN_TYPE, NULL,
&ctx->DefaultPacking, texObj, texImage);
 
st_copy_texsubimage(ctx, target, level,
0, 0, 0, /* destX,Y,Z */
x, y, width, 1); /* src X, Y, size */
}
 
 
static void
st_CopyTexImage2D(struct gl_context * ctx, GLenum target, GLint level,
GLenum internalFormat,
GLint x, GLint y, GLsizei width, GLsizei height,
GLint border)
{
struct gl_texture_unit *texUnit =
&ctx->Texture.Unit[ctx->Texture.CurrentUnit];
struct gl_texture_object *texObj =
_mesa_select_tex_object(ctx, texUnit, target);
struct gl_texture_image *texImage =
_mesa_select_tex_image(ctx, texObj, target, level);
 
/* Setup or redefine the texture object, texture and texture
* image. Don't populate yet.
*/
ctx->Driver.TexImage2D(ctx, target, level, internalFormat,
width, height, border,
GL_RGBA, CHAN_TYPE, NULL,
&ctx->DefaultPacking, texObj, texImage);
 
st_copy_texsubimage(ctx, target, level,
0, 0, 0, /* destX,Y,Z */
x, y, width, height); /* src X, Y, size */
}
 
 
static void
st_CopyTexSubImage1D(struct gl_context * ctx, GLenum target, GLint level,
GLint xoffset, GLint x, GLint y, GLsizei width)
{
const GLint yoffset = 0, zoffset = 0;
const GLsizei height = 1;
st_copy_texsubimage(ctx, target, level,
xoffset, yoffset, zoffset, /* destX,Y,Z */
x, y, width, height); /* src X, Y, size */
}
 
 
static void
st_CopyTexSubImage2D(struct gl_context * ctx, GLenum target, GLint level,
GLint xoffset, GLint yoffset,
GLint x, GLint y, GLsizei width, GLsizei height)
{
const GLint zoffset = 0;
st_copy_texsubimage(ctx, target, level,
xoffset, yoffset, zoffset, /* destX,Y,Z */
x, y, width, height); /* src X, Y, size */
}
 
 
static void
st_CopyTexSubImage3D(struct gl_context * ctx, GLenum target, GLint level,
GLint xoffset, GLint yoffset, GLint zoffset,
GLint x, GLint y, GLsizei width, GLsizei height)
{
st_copy_texsubimage(ctx, target, level,
xoffset, yoffset, zoffset, /* destX,Y,Z */
x, y, width, height); /* src X, Y, size */
}
 
 
/**
* Copy image data from stImage into the texture object 'stObj' at level
* 'dstLevel'.
*/
static void
copy_image_data_to_texture(struct st_context *st,
struct st_texture_object *stObj,
GLuint dstLevel,
struct st_texture_image *stImage)
{
/* debug checks */
{
const struct gl_texture_image *dstImage =
stObj->base.Image[stImage->face][stImage->level];
assert(dstImage);
assert(dstImage->Width == stImage->base.Width);
assert(dstImage->Height == stImage->base.Height);
assert(dstImage->Depth == stImage->base.Depth);
}
 
if (stImage->pt) {
/* Copy potentially with the blitter:
*/
st_texture_image_copy(st->pipe,
stObj->pt, dstLevel, /* dest texture, level */
stImage->pt, stImage->level, /* src texture, level */
stImage->face);
 
pipe_resource_reference(&stImage->pt, NULL);
}
else if (stImage->base.Data) {
st_texture_image_data(st,
stObj->pt,
stImage->face,
dstLevel,
stImage->base.Data,
stImage->base.RowStride *
util_format_get_blocksize(stObj->pt->format),
stImage->base.RowStride *
stImage->base.Height *
util_format_get_blocksize(stObj->pt->format));
_mesa_align_free(stImage->base.Data);
stImage->base.Data = NULL;
}
 
pipe_resource_reference(&stImage->pt, stObj->pt);
}
 
 
/**
* Called during state validation. When this function is finished,
* the texture object should be ready for rendering.
* \return GL_TRUE for success, GL_FALSE for failure (out of mem)
*/
GLboolean
st_finalize_texture(struct gl_context *ctx,
struct pipe_context *pipe,
struct gl_texture_object *tObj)
{
struct st_context *st = st_context(ctx);
struct st_texture_object *stObj = st_texture_object(tObj);
const GLuint nr_faces = (stObj->base.Target == GL_TEXTURE_CUBE_MAP) ? 6 : 1;
GLuint face;
struct st_texture_image *firstImage;
enum pipe_format firstImageFormat;
 
if (stObj->base._Complete) {
/* The texture is complete and we know exactly how many mipmap levels
* are present/needed. This is conditional because we may be called
* from the st_generate_mipmap() function when the texture object is
* incomplete. In that case, we'll have set stObj->lastLevel before
* we get here.
*/
if (stObj->base.MinFilter == GL_LINEAR ||
stObj->base.MinFilter == GL_NEAREST)
stObj->lastLevel = stObj->base.BaseLevel;
else
stObj->lastLevel = stObj->base._MaxLevel;
}
 
firstImage = st_texture_image(stObj->base.Image[0][stObj->base.BaseLevel]);
assert(firstImage);
 
/* If both firstImage and stObj point to a texture which can contain
* all active images, favour firstImage. Note that because of the
* completeness requirement, we know that the image dimensions
* will match.
*/
if (firstImage->pt &&
firstImage->pt != stObj->pt &&
(!stObj->pt || firstImage->pt->last_level >= stObj->pt->last_level)) {
pipe_resource_reference(&stObj->pt, firstImage->pt);
pipe_sampler_view_reference(&stObj->sampler_view, NULL);
}
 
/* Find gallium format for the Mesa texture */
firstImageFormat = st_mesa_format_to_pipe_format(firstImage->base.TexFormat);
 
/* If we already have a gallium texture, check that it matches the texture
* object's format, target, size, num_levels, etc.
*/
if (stObj->pt) {
if (stObj->pt->target != gl_target_to_pipe(stObj->base.Target) ||
!st_sampler_compat_formats(stObj->pt->format, firstImageFormat) ||
stObj->pt->last_level < stObj->lastLevel ||
stObj->pt->width0 != stObj->width0 ||
stObj->pt->height0 != stObj->height0 ||
stObj->pt->depth0 != stObj->depth0)
{
/* The gallium texture does not match the Mesa texture so delete the
* gallium texture now. We'll make a new one below.
*/
pipe_resource_reference(&stObj->pt, NULL);
pipe_sampler_view_reference(&stObj->sampler_view, NULL);
st->dirty.st |= ST_NEW_FRAMEBUFFER;
}
}
 
/* May need to create a new gallium texture:
*/
if (!stObj->pt) {
GLuint bindings = default_bindings(st, firstImageFormat);
 
stObj->pt = st_texture_create(st,
gl_target_to_pipe(stObj->base.Target),
firstImageFormat,
stObj->lastLevel,
stObj->width0,
stObj->height0,
stObj->depth0,
bindings);
 
if (!stObj->pt) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "glTexImage");
return GL_FALSE;
}
}
 
/* Pull in any images not in the object's texture:
*/
for (face = 0; face < nr_faces; face++) {
GLuint level;
for (level = stObj->base.BaseLevel; level <= stObj->lastLevel; level++) {
struct st_texture_image *stImage =
st_texture_image(stObj->base.Image[face][level]);
 
/* Need to import images in main memory or held in other textures.
*/
if (stImage && stObj->pt != stImage->pt) {
copy_image_data_to_texture(st, stObj, level, stImage);
}
}
}
 
return GL_TRUE;
}
 
 
/**
* Returns pointer to a default/dummy texture.
* This is typically used when the current shader has tex/sample instructions
* but the user has not provided a (any) texture(s).
*/
struct gl_texture_object *
st_get_default_texture(struct st_context *st)
{
if (!st->default_texture) {
static const GLenum target = GL_TEXTURE_2D;
GLubyte pixels[16][16][4];
struct gl_texture_object *texObj;
struct gl_texture_image *texImg;
GLuint i, j;
 
/* The ARB_fragment_program spec says (0,0,0,1) should be returned
* when attempting to sample incomplete textures.
*/
for (i = 0; i < 16; i++) {
for (j = 0; j < 16; j++) {
pixels[i][j][0] = 0;
pixels[i][j][1] = 0;
pixels[i][j][2] = 0;
pixels[i][j][3] = 255;
}
}
 
texObj = st->ctx->Driver.NewTextureObject(st->ctx, 0, target);
 
texImg = _mesa_get_tex_image(st->ctx, texObj, target, 0);
 
_mesa_init_teximage_fields(st->ctx, target, texImg,
16, 16, 1, 0, /* w, h, d, border */
GL_RGBA, MESA_FORMAT_RGBA8888);
 
st_TexImage(st->ctx, 2, target,
0, GL_RGBA, /* level, intformat */
16, 16, 1, 0, /* w, h, d, border */
GL_RGBA, GL_UNSIGNED_BYTE, pixels,
&st->ctx->DefaultPacking,
texObj, texImg,
0, 0);
 
texObj->MinFilter = GL_NEAREST;
texObj->MagFilter = GL_NEAREST;
texObj->_Complete = GL_TRUE;
 
st->default_texture = texObj;
}
return st->default_texture;
}
 
 
void
st_init_texture_functions(struct dd_function_table *functions)
{
functions->ChooseTextureFormat = st_ChooseTextureFormat;
functions->TexImage1D = st_TexImage1D;
functions->TexImage2D = st_TexImage2D;
functions->TexImage3D = st_TexImage3D;
functions->TexSubImage1D = st_TexSubImage1D;
functions->TexSubImage2D = st_TexSubImage2D;
functions->TexSubImage3D = st_TexSubImage3D;
functions->CompressedTexSubImage1D = st_CompressedTexSubImage1D;
functions->CompressedTexSubImage2D = st_CompressedTexSubImage2D;
functions->CompressedTexSubImage3D = st_CompressedTexSubImage3D;
functions->CopyTexImage1D = st_CopyTexImage1D;
functions->CopyTexImage2D = st_CopyTexImage2D;
functions->CopyTexSubImage1D = st_CopyTexSubImage1D;
functions->CopyTexSubImage2D = st_CopyTexSubImage2D;
functions->CopyTexSubImage3D = st_CopyTexSubImage3D;
functions->GenerateMipmap = st_generate_mipmap;
 
functions->GetTexImage = st_GetTexImage;
 
/* compressed texture functions */
functions->CompressedTexImage2D = st_CompressedTexImage2D;
functions->GetCompressedTexImage = st_GetCompressedTexImage;
 
functions->NewTextureObject = st_NewTextureObject;
functions->NewTextureImage = st_NewTextureImage;
functions->DeleteTexture = st_DeleteTextureObject;
functions->FreeTexImageData = st_FreeTextureImageData;
 
functions->TextureMemCpy = do_memcpy;
 
/* XXX Temporary until we can query pipe's texture sizes */
functions->TestProxyTexImage = _mesa_test_proxy_teximage;
}
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_cb_texture.h
0,0 → 1,54
/**************************************************************************
*
* 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 ST_CB_TEXTURE_H
#define ST_CB_TEXTURE_H
 
 
#include "main/glheader.h"
#include "main/mtypes.h"
 
struct dd_function_table;
struct pipe_context;
struct st_context;
 
extern GLboolean
st_finalize_texture(struct gl_context *ctx,
struct pipe_context *pipe,
struct gl_texture_object *tObj);
 
 
extern struct gl_texture_object *
st_get_default_texture(struct st_context *st);
 
 
extern void
st_init_texture_functions(struct dd_function_table *functions);
 
 
#endif /* ST_CB_TEXTURE_H */
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_cb_viewport.c
0,0 → 1,71
/**************************************************************************
*
* 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 "main/glheader.h"
#include "st_context.h"
#include "st_cb_viewport.h"
 
#include "pipe/p_state.h"
#include "pipe/p_defines.h"
#include "util/u_atomic.h"
 
/**
* Cast wrapper to convert a struct gl_framebuffer to an st_framebuffer.
* Return NULL if the struct gl_framebuffer is a user-created framebuffer.
* We'll only return non-null for window system framebuffers.
* Note that this function may fail.
*/
static INLINE struct st_framebuffer *
st_ws_framebuffer(struct gl_framebuffer *fb)
{
/* FBO cannot be casted. See st_new_framebuffer */
return (struct st_framebuffer *) ((fb && !fb->Name) ? fb : NULL);
}
 
static void st_viewport(struct gl_context * ctx, GLint x, GLint y,
GLsizei width, GLsizei height)
{
struct st_context *st = ctx->st;
struct st_framebuffer *stdraw;
struct st_framebuffer *stread;
 
if (!st->invalidate_on_gl_viewport)
return;
 
stdraw = st_ws_framebuffer(st->ctx->DrawBuffer);
stread = st_ws_framebuffer(st->ctx->ReadBuffer);
 
if (stdraw)
p_atomic_set(&stdraw->revalidate, TRUE);
if (stread && stread != stdraw)
p_atomic_set(&stread->revalidate, TRUE);
}
 
void st_init_viewport_functions(struct dd_function_table *functions)
{
functions->Viewport = st_viewport;
}
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_cb_viewport.h
0,0 → 1,36
/**************************************************************************
*
* 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 ST_CB_VIEWPORT_H
#define ST_CB_VIEWPORT_H
 
struct dd_function_table;
 
extern void
st_init_viewport_functions(struct dd_function_table *functions);
 
#endif /* ST_CB_VIEW_PORT_H */
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_cb_xformfb.c
0,0 → 1,133
/**************************************************************************
*
* 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.
*
**************************************************************************/
 
 
/**
* Transform feedback functions.
*
* \author Brian Paul
*/
 
 
#include "main/imports.h"
#include "main/context.h"
#include "main/transformfeedback.h"
 
#include "st_cb_xformfb.h"
 
 
#if FEATURE_EXT_transform_feedback
 
#if 0
static struct gl_transform_feedback_object *
st_new_transform_feedback(struct gl_context *ctx, GLuint name)
{
struct gl_transform_feedback_object *obj;
obj = CALLOC_STRUCT(gl_transform_feedback_object);
if (obj) {
obj->Name = name;
obj->RefCount = 1;
}
return obj;
}
#endif
 
#if 0
static void
st_delete_transform_feedback(struct gl_context *ctx,
struct gl_transform_feedback_object *obj)
{
GLuint i;
 
for (i = 0; i < Elements(obj->Buffers); i++) {
_mesa_reference_buffer_object(ctx, &obj->Buffers[i], NULL);
}
 
free(obj);
}
#endif
 
 
static void
st_begin_transform_feedback(struct gl_context *ctx, GLenum mode,
struct gl_transform_feedback_object *obj)
{
/* to-do */
}
 
 
static void
st_end_transform_feedback(struct gl_context *ctx,
struct gl_transform_feedback_object *obj)
{
/* to-do */
}
 
 
static void
st_pause_transform_feedback(struct gl_context *ctx,
struct gl_transform_feedback_object *obj)
{
/* to-do */
}
 
 
static void
st_resume_transform_feedback(struct gl_context *ctx,
struct gl_transform_feedback_object *obj)
{
/* to-do */
}
 
 
static void
st_draw_transform_feedback(struct gl_context *ctx, GLenum mode,
struct gl_transform_feedback_object *obj)
{
/* XXX to do */
/*
* Get number of vertices in obj's feedback buffer.
* Call ctx->Exec.DrawArrays(mode, 0, count);
*/
}
 
 
void
st_init_xformfb_functions(struct dd_function_table *functions)
{
/* let core Mesa plug in its functions */
_mesa_init_transform_feedback_functions(functions);
 
/* then override a few: */
functions->BeginTransformFeedback = st_begin_transform_feedback;
functions->EndTransformFeedback = st_end_transform_feedback;
functions->PauseTransformFeedback = st_pause_transform_feedback;
functions->ResumeTransformFeedback = st_resume_transform_feedback;
functions->DrawTransformFeedback = st_draw_transform_feedback;
}
 
#endif /* FEATURE_EXT_transform_feedback */
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_cb_xformfb.h
0,0 → 1,50
/**************************************************************************
*
* 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 ST_CB_XFORMFB_H
#define ST_CB_XFORMFB_H
 
 
#include "main/compiler.h"
 
struct dd_function_table;
 
#if FEATURE_EXT_transform_feedback
 
extern void
st_init_xformfb_functions(struct dd_function_table *functions);
 
#else
 
static INLINE void
st_init_xformfb_functions(struct dd_function_table *functions)
{
}
 
#endif /* FEATURE_EXT_transform_feedback */
 
#endif /* ST_CB_XFORMFB_H */
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_context.c
0,0 → 1,297
/**************************************************************************
*
* 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 "main/imports.h"
#include "main/context.h"
#include "main/shaderobj.h"
#include "program/prog_cache.h"
#include "vbo/vbo.h"
#include "glapi/glapi.h"
#include "st_context.h"
#include "st_debug.h"
#include "st_cb_accum.h"
#include "st_cb_bitmap.h"
#include "st_cb_blit.h"
#include "st_cb_bufferobjects.h"
#include "st_cb_clear.h"
#include "st_cb_condrender.h"
#include "st_cb_drawpixels.h"
#include "st_cb_rasterpos.h"
#include "st_cb_drawtex.h"
#include "st_cb_eglimage.h"
#include "st_cb_fbo.h"
#include "st_cb_feedback.h"
#include "st_cb_program.h"
#include "st_cb_queryobj.h"
#include "st_cb_readpixels.h"
#include "st_cb_texture.h"
#include "st_cb_xformfb.h"
#include "st_cb_flush.h"
#include "st_cb_strings.h"
#include "st_cb_viewport.h"
#include "st_atom.h"
#include "st_draw.h"
#include "st_extensions.h"
#include "st_gen_mipmap.h"
#include "st_program.h"
#include "pipe/p_context.h"
#include "util/u_inlines.h"
#include "cso_cache/cso_context.h"
 
 
DEBUG_GET_ONCE_BOOL_OPTION(mesa_mvp_dp4, "MESA_MVP_DP4", FALSE)
 
 
/**
* Called via ctx->Driver.UpdateState()
*/
void st_invalidate_state(struct gl_context * ctx, GLuint new_state)
{
struct st_context *st = st_context(ctx);
 
st->dirty.mesa |= new_state;
st->dirty.st |= ST_NEW_MESA;
 
/* This is the only core Mesa module we depend upon.
* No longer use swrast, swsetup, tnl.
*/
_vbo_InvalidateState(ctx, new_state);
}
 
 
/**
* Check for multisample env var override.
*/
int
st_get_msaa(void)
{
const char *msaa = _mesa_getenv("__GL_FSAA_MODE");
if (msaa)
return atoi(msaa);
return 0;
}
 
 
static struct st_context *
st_create_context_priv( struct gl_context *ctx, struct pipe_context *pipe )
{
uint i;
struct st_context *st = ST_CALLOC_STRUCT( st_context );
ctx->st = st;
 
st->ctx = ctx;
st->pipe = pipe;
 
/* XXX: this is one-off, per-screen init: */
st_debug_init();
/* state tracker needs the VBO module */
_vbo_CreateContext(ctx);
 
st->dirty.mesa = ~0;
st->dirty.st = ~0;
 
st->cso_context = cso_create_context(pipe);
 
st_init_atoms( st );
st_init_bitmap(st);
st_init_clear(st);
st_init_draw( st );
st_init_generate_mipmap(st);
st_init_blit(st);
 
if(pipe->screen->get_param(pipe->screen, PIPE_CAP_NPOT_TEXTURES))
st->internal_target = PIPE_TEXTURE_2D;
else
st->internal_target = PIPE_TEXTURE_RECT;
 
for (i = 0; i < PIPE_MAX_SAMPLERS; i++)
st->state.sampler_list[i] = &st->state.samplers[i];
 
for (i = 0; i < 3; i++) {
memset(&st->velems_util_draw[i], 0, sizeof(struct pipe_vertex_element));
st->velems_util_draw[i].src_offset = i * 4 * sizeof(float);
st->velems_util_draw[i].instance_divisor = 0;
st->velems_util_draw[i].vertex_buffer_index = 0;
st->velems_util_draw[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
}
 
/* we want all vertex data to be placed in buffer objects */
vbo_use_buffer_objects(ctx);
 
/* Need these flags:
*/
st->ctx->FragmentProgram._MaintainTexEnvProgram = GL_TRUE;
 
st->ctx->VertexProgram._MaintainTnlProgram = GL_TRUE;
 
st->pixel_xfer.cache = _mesa_new_program_cache();
 
st->force_msaa = st_get_msaa();
 
/* GL limits and extensions */
st_init_limits(st);
st_init_extensions(st);
 
return st;
}
 
 
struct st_context *st_create_context(gl_api api, struct pipe_context *pipe,
const struct gl_config *visual,
struct st_context *share)
{
struct gl_context *ctx;
struct gl_context *shareCtx = share ? share->ctx : NULL;
struct dd_function_table funcs;
 
/* Sanity checks */
assert(MESA_SHADER_VERTEX == PIPE_SHADER_VERTEX);
assert(MESA_SHADER_FRAGMENT == PIPE_SHADER_FRAGMENT);
assert(MESA_SHADER_GEOMETRY == PIPE_SHADER_GEOMETRY);
 
memset(&funcs, 0, sizeof(funcs));
st_init_driver_functions(&funcs);
 
ctx = _mesa_create_context_for_api(api, visual, shareCtx, &funcs, NULL);
 
/* XXX: need a capability bit in gallium to query if the pipe
* driver prefers DP4 or MUL/MAD for vertex transformation.
*/
if (debug_get_option_mesa_mvp_dp4())
_mesa_set_mvp_with_dp4( ctx, GL_TRUE );
 
return st_create_context_priv(ctx, pipe);
}
 
 
static void st_destroy_context_priv( struct st_context *st )
{
uint i;
 
st_destroy_atoms( st );
st_destroy_draw( st );
st_destroy_generate_mipmap(st);
st_destroy_blit(st);
st_destroy_clear(st);
st_destroy_bitmap(st);
st_destroy_drawpix(st);
st_destroy_drawtex(st);
 
for (i = 0; i < Elements(st->state.sampler_views); i++) {
pipe_sampler_view_reference(&st->state.sampler_views[i], NULL);
}
 
for (i = 0; i < Elements(st->state.constants); i++) {
if (st->state.constants[i]) {
pipe_resource_reference(&st->state.constants[i], NULL);
}
}
 
if (st->default_texture) {
st->ctx->Driver.DeleteTexture(st->ctx, st->default_texture);
st->default_texture = NULL;
}
 
free( st );
}
 
void st_destroy_context( struct st_context *st )
{
struct pipe_context *pipe = st->pipe;
struct cso_context *cso = st->cso_context;
struct gl_context *ctx = st->ctx;
GLuint i;
 
/* need to unbind and destroy CSO objects before anything else */
cso_release_all(st->cso_context);
 
st_reference_fragprog(st, &st->fp, NULL);
st_reference_vertprog(st, &st->vp, NULL);
 
/* release framebuffer surfaces */
for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
pipe_surface_reference(&st->state.framebuffer.cbufs[i], NULL);
}
pipe_surface_reference(&st->state.framebuffer.zsbuf, NULL);
 
pipe->set_index_buffer(pipe, NULL);
 
for (i = 0; i < PIPE_SHADER_TYPES; i++) {
pipe->set_constant_buffer(pipe, i, 0, NULL);
pipe_resource_reference(&st->state.constants[i], NULL);
}
 
_mesa_delete_program_cache(st->ctx, st->pixel_xfer.cache);
 
_vbo_DestroyContext(st->ctx);
 
_mesa_free_context_data(ctx);
 
st_destroy_context_priv(st);
 
cso_destroy_context(cso);
 
pipe->destroy( pipe );
 
free(ctx);
}
 
 
void st_init_driver_functions(struct dd_function_table *functions)
{
_mesa_init_shader_object_functions(functions);
 
st_init_accum_functions(functions);
st_init_blit_functions(functions);
st_init_bufferobject_functions(functions);
st_init_clear_functions(functions);
st_init_bitmap_functions(functions);
st_init_drawpixels_functions(functions);
st_init_rasterpos_functions(functions);
 
st_init_drawtex_functions(functions);
 
st_init_eglimage_functions(functions);
 
st_init_fbo_functions(functions);
st_init_feedback_functions(functions);
st_init_program_functions(functions);
st_init_query_functions(functions);
st_init_cond_render_functions(functions);
st_init_readpixels_functions(functions);
st_init_texture_functions(functions);
st_init_flush_functions(functions);
st_init_string_functions(functions);
st_init_viewport_functions(functions);
 
st_init_xformfb_functions(functions);
 
functions->UpdateState = st_invalidate_state;
}
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_context.h
0,0 → 1,270
//struct dd_function_table;
/**************************************************************************
*
* 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.
*
**************************************************************************/
 
#ifndef ST_CONTEXT_H
#define ST_CONTEXT_H
 
#include "main/mtypes.h"
#include "pipe/p_state.h"
#include "state_tracker/st_api.h"
 
struct bitmap_cache;
struct blit_state;
struct dd_function_table;
struct draw_context;
struct draw_stage;
struct gen_mipmap_state;
struct st_context;
struct st_fragment_program;
 
 
#define ST_NEW_MESA 0x1 /* Mesa state has changed */
#define ST_NEW_FRAGMENT_PROGRAM 0x2
#define ST_NEW_VERTEX_PROGRAM 0x4
#define ST_NEW_FRAMEBUFFER 0x8
#define ST_NEW_EDGEFLAGS_DATA 0x10
#define ST_NEW_GEOMETRY_PROGRAM 0x20
 
 
struct st_state_flags {
GLuint mesa;
GLuint st;
};
 
struct st_tracked_state {
const char *name;
struct st_state_flags dirty;
void (*update)( struct st_context *st );
};
 
 
 
struct st_context
{
struct st_context_iface iface;
 
struct gl_context *ctx;
 
struct pipe_context *pipe;
 
struct draw_context *draw; /**< For selection/feedback/rastpos only */
struct draw_stage *feedback_stage; /**< For GL_FEEDBACK rendermode */
struct draw_stage *selection_stage; /**< For GL_SELECT rendermode */
struct draw_stage *rastpos_stage; /**< For glRasterPos */
 
 
/* On old libGL's for linux we need to invalidate the drawables
* on glViewpport calls, this is set via a option.
*/
boolean invalidate_on_gl_viewport;
 
/* Some state is contained in constant objects.
* Other state is just parameter values.
*/
struct {
struct pipe_blend_state blend;
struct pipe_depth_stencil_alpha_state depth_stencil;
struct pipe_rasterizer_state rasterizer;
struct pipe_sampler_state samplers[PIPE_MAX_SAMPLERS];
struct pipe_sampler_state *sampler_list[PIPE_MAX_SAMPLERS];
struct pipe_clip_state clip;
struct pipe_resource *constants[PIPE_SHADER_TYPES];
struct pipe_framebuffer_state framebuffer;
struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS];
struct pipe_scissor_state scissor;
struct pipe_viewport_state viewport;
unsigned sample_mask;
 
GLuint num_samplers;
GLuint num_textures;
 
GLuint poly_stipple[32]; /**< In OpenGL's bottom-to-top order */
} state;
 
struct {
struct st_tracked_state tracked_state[PIPE_SHADER_TYPES];
} constants;
 
/* XXX unused: */
struct {
struct gl_fragment_program *fragment_program;
} cb;
 
char vendor[100];
char renderer[100];
 
struct st_state_flags dirty;
 
GLboolean missing_textures;
GLboolean vertdata_edgeflags;
 
/** Mapping from VERT_RESULT_x to post-transformed vertex slot */
const GLuint *vertex_result_to_slot;
 
struct st_vertex_program *vp; /**< Currently bound vertex program */
struct st_fragment_program *fp; /**< Currently bound fragment program */
struct st_geometry_program *gp; /**< Currently bound geometry program */
 
struct st_vp_varient *vp_varient;
 
struct gl_texture_object *default_texture;
 
struct {
struct gl_program_cache *cache;
struct st_fragment_program *program; /**< cur pixel transfer prog */
GLuint xfer_prog_sn; /**< pixel xfer program serial no. */
GLuint user_prog_sn; /**< user fragment program serial no. */
struct st_fragment_program *combined_prog;
GLuint combined_prog_sn;
struct pipe_resource *pixelmap_texture;
struct pipe_sampler_view *pixelmap_sampler_view;
boolean pixelmap_enabled; /**< use the pixelmap texture? */
} pixel_xfer;
 
/** for glBitmap */
struct {
struct pipe_rasterizer_state rasterizer;
struct pipe_sampler_state samplers[2];
enum pipe_format tex_format;
void *vs;
float vertices[4][3][4]; /**< vertex pos + color + texcoord */
struct pipe_resource *vbuf;
unsigned vbuf_slot; /* next free slot in vbuf */
struct bitmap_cache *cache;
} bitmap;
 
/** for glDraw/CopyPixels */
struct {
struct st_fragment_program *shaders[4];
void *vert_shaders[2]; /**< ureg shaders */
} drawpix;
 
/** for glClear */
struct {
struct pipe_rasterizer_state raster;
struct pipe_viewport_state viewport;
struct pipe_clip_state clip;
void *vs;
void *fs;
float vertices[4][2][4]; /**< vertex pos + color */
struct pipe_resource *vbuf;
unsigned vbuf_slot;
boolean enable_ds_separate;
} clear;
 
/** used for anything using util_draw_vertex_buffer */
struct pipe_vertex_element velems_util_draw[3];
 
void *passthrough_fs; /**< simple pass-through frag shader */
 
enum pipe_texture_target internal_target;
struct gen_mipmap_state *gen_mipmap;
struct blit_state *blit;
 
struct cso_context *cso_context;
 
int force_msaa;
void *winsys_drawable_handle;
};
 
 
/* Need this so that we can implement Mesa callbacks in this module.
*/
static INLINE struct st_context *st_context(struct gl_context *ctx)
{
return ctx->st;
}
 
 
/**
* Wrapper for struct gl_framebuffer.
* This is an opaque type to the outside world.
*/
struct st_framebuffer
{
struct gl_framebuffer Base;
void *Private;
 
struct st_framebuffer_iface *iface;
enum st_attachment_type statts[ST_ATTACHMENT_COUNT];
unsigned num_statts;
int32_t revalidate;
};
 
 
extern void st_init_driver_functions(struct dd_function_table *functions);
 
void st_invalidate_state(struct gl_context * ctx, GLuint new_state);
 
 
 
#define Y_0_TOP 1
#define Y_0_BOTTOM 2
 
static INLINE GLuint
st_fb_orientation(const struct gl_framebuffer *fb)
{
if (fb && fb->Name == 0) {
/* Drawing into a window (on-screen buffer).
*
* Negate Y scale to flip image vertically.
* The NDC Y coords prior to viewport transformation are in the range
* [y=-1=bottom, y=1=top]
* Hardware window coords are in the range [y=0=top, y=H-1=bottom] where
* H is the window height.
* Use the viewport transformation to invert Y.
*/
return Y_0_TOP;
}
else {
/* Drawing into user-created FBO (very likely a texture).
*
* For textures, T=0=Bottom, so by extension Y=0=Bottom for rendering.
*/
return Y_0_BOTTOM;
}
}
 
 
/** clear-alloc a struct-sized object, with casting */
#define ST_CALLOC_STRUCT(T) (struct T *) calloc(1, sizeof(struct T))
 
 
extern int
st_get_msaa(void);
 
extern struct st_context *
st_create_context(gl_api api, struct pipe_context *pipe,
const struct gl_config *visual,
struct st_context *share);
 
extern void
st_destroy_context(struct st_context *st);
 
 
#endif
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_debug.c
0,0 → 1,102
/**************************************************************************
*
* 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 "main/context.h"
#include "program/prog_print.h"
 
#include "pipe/p_state.h"
#include "pipe/p_shader_tokens.h"
#include "tgsi/tgsi_dump.h"
 
#include "cso_cache/cso_cache.h"
 
#include "st_context.h"
#include "st_debug.h"
#include "st_program.h"
 
 
 
#ifdef DEBUG
int ST_DEBUG = 0;
 
static const struct debug_named_value st_debug_flags[] = {
{ "mesa", DEBUG_MESA, NULL },
{ "tgsi", DEBUG_TGSI, NULL },
{ "constants",DEBUG_CONSTANTS, NULL },
{ "pipe", DEBUG_PIPE, NULL },
{ "tex", DEBUG_TEX, NULL },
{ "fallback", DEBUG_FALLBACK, NULL },
{ "screen", DEBUG_SCREEN, NULL },
{ "query", DEBUG_QUERY, NULL },
DEBUG_NAMED_VALUE_END
};
 
DEBUG_GET_ONCE_FLAGS_OPTION(st_debug, "ST_DEBUG", st_debug_flags, 0)
#endif
 
 
void
st_debug_init(void)
{
#ifdef DEBUG
ST_DEBUG = debug_get_option_st_debug();
#endif
}
 
 
 
/**
* Print current state. May be called from inside gdb to see currently
* bound vertex/fragment shaders and associated constants.
*/
void
st_print_current(void)
{
GET_CURRENT_CONTEXT(ctx);
struct st_context *st = st_context(ctx);
 
#if 0
int i;
 
printf("Vertex Transform Inputs:\n");
for (i = 0; i < st->vp->state.num_inputs; i++) {
printf(" Slot %d: VERT_ATTRIB_%d\n", i, st->vp->index_to_input[i]);
}
#endif
 
if (st->vp->varients)
tgsi_dump( st->vp->varients[0].tgsi.tokens, 0 );
if (st->vp->Base.Base.Parameters)
_mesa_print_parameter_list(st->vp->Base.Base.Parameters);
 
tgsi_dump( st->fp->tgsi.tokens, 0 );
if (st->fp->Base.Base.Parameters)
_mesa_print_parameter_list(st->fp->Base.Base.Parameters);
}
 
 
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_debug.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.
*
**************************************************************************/
 
 
#ifndef ST_DEBUG_H
#define ST_DEBUG_H
 
#include "pipe/p_compiler.h"
#include "util/u_debug.h"
 
extern void
st_print_current(void);
 
 
#define DEBUG_MESA 0x1
#define DEBUG_TGSI 0x2
#define DEBUG_CONSTANTS 0x4
#define DEBUG_PIPE 0x8
#define DEBUG_TEX 0x10
#define DEBUG_FALLBACK 0x20
#define DEBUG_QUERY 0x40
#define DEBUG_SCREEN 0x80
 
#ifdef DEBUG
extern int ST_DEBUG;
#define DBSTR(x) x
#else
#define ST_DEBUG 0
#define DBSTR(x) ""
#endif
 
void st_debug_init( void );
 
static INLINE void
ST_DBG( unsigned flag, const char *fmt, ... )
{
if (ST_DEBUG & flag)
{
va_list args;
 
va_start( args, fmt );
debug_vprintf( fmt, args );
va_end( args );
}
}
 
 
#endif /* ST_DEBUG_H */
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_draw.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.
*
**************************************************************************/
 
/*
* This file implements the st_draw_vbo() function which is called from
* Mesa's VBO module. All point/line/triangle rendering is done through
* this function whether the user called glBegin/End, glDrawArrays,
* glDrawElements, glEvalMesh, or glCalList, etc.
*
* We basically convert the VBO's vertex attribute/array information into
* Gallium vertex state, bind the vertex buffer objects and call
* pipe->draw_elements(), pipe->draw_range_elements() or pipe->draw_arrays().
*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
 
#include "main/imports.h"
#include "main/image.h"
#include "main/macros.h"
#include "program/prog_uniform.h"
 
#include "vbo/vbo.h"
 
#include "st_context.h"
#include "st_atom.h"
#include "st_cb_bufferobjects.h"
#include "st_draw.h"
#include "st_program.h"
 
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "util/u_inlines.h"
#include "util/u_format.h"
#include "util/u_prim.h"
#include "util/u_draw_quad.h"
#include "draw/draw_context.h"
#include "cso_cache/cso_context.h"
 
 
static GLuint double_types[4] = {
PIPE_FORMAT_R64_FLOAT,
PIPE_FORMAT_R64G64_FLOAT,
PIPE_FORMAT_R64G64B64_FLOAT,
PIPE_FORMAT_R64G64B64A64_FLOAT
};
 
static GLuint float_types[4] = {
PIPE_FORMAT_R32_FLOAT,
PIPE_FORMAT_R32G32_FLOAT,
PIPE_FORMAT_R32G32B32_FLOAT,
PIPE_FORMAT_R32G32B32A32_FLOAT
};
 
static GLuint half_float_types[4] = {
PIPE_FORMAT_R16_FLOAT,
PIPE_FORMAT_R16G16_FLOAT,
PIPE_FORMAT_R16G16B16_FLOAT,
PIPE_FORMAT_R16G16B16A16_FLOAT
};
 
static GLuint uint_types_norm[4] = {
PIPE_FORMAT_R32_UNORM,
PIPE_FORMAT_R32G32_UNORM,
PIPE_FORMAT_R32G32B32_UNORM,
PIPE_FORMAT_R32G32B32A32_UNORM
};
 
static GLuint uint_types_scale[4] = {
PIPE_FORMAT_R32_USCALED,
PIPE_FORMAT_R32G32_USCALED,
PIPE_FORMAT_R32G32B32_USCALED,
PIPE_FORMAT_R32G32B32A32_USCALED
};
 
static GLuint int_types_norm[4] = {
PIPE_FORMAT_R32_SNORM,
PIPE_FORMAT_R32G32_SNORM,
PIPE_FORMAT_R32G32B32_SNORM,
PIPE_FORMAT_R32G32B32A32_SNORM
};
 
static GLuint int_types_scale[4] = {
PIPE_FORMAT_R32_SSCALED,
PIPE_FORMAT_R32G32_SSCALED,
PIPE_FORMAT_R32G32B32_SSCALED,
PIPE_FORMAT_R32G32B32A32_SSCALED
};
 
static GLuint ushort_types_norm[4] = {
PIPE_FORMAT_R16_UNORM,
PIPE_FORMAT_R16G16_UNORM,
PIPE_FORMAT_R16G16B16_UNORM,
PIPE_FORMAT_R16G16B16A16_UNORM
};
 
static GLuint ushort_types_scale[4] = {
PIPE_FORMAT_R16_USCALED,
PIPE_FORMAT_R16G16_USCALED,
PIPE_FORMAT_R16G16B16_USCALED,
PIPE_FORMAT_R16G16B16A16_USCALED
};
 
static GLuint short_types_norm[4] = {
PIPE_FORMAT_R16_SNORM,
PIPE_FORMAT_R16G16_SNORM,
PIPE_FORMAT_R16G16B16_SNORM,
PIPE_FORMAT_R16G16B16A16_SNORM
};
 
static GLuint short_types_scale[4] = {
PIPE_FORMAT_R16_SSCALED,
PIPE_FORMAT_R16G16_SSCALED,
PIPE_FORMAT_R16G16B16_SSCALED,
PIPE_FORMAT_R16G16B16A16_SSCALED
};
 
static GLuint ubyte_types_norm[4] = {
PIPE_FORMAT_R8_UNORM,
PIPE_FORMAT_R8G8_UNORM,
PIPE_FORMAT_R8G8B8_UNORM,
PIPE_FORMAT_R8G8B8A8_UNORM
};
 
static GLuint ubyte_types_scale[4] = {
PIPE_FORMAT_R8_USCALED,
PIPE_FORMAT_R8G8_USCALED,
PIPE_FORMAT_R8G8B8_USCALED,
PIPE_FORMAT_R8G8B8A8_USCALED
};
 
static GLuint byte_types_norm[4] = {
PIPE_FORMAT_R8_SNORM,
PIPE_FORMAT_R8G8_SNORM,
PIPE_FORMAT_R8G8B8_SNORM,
PIPE_FORMAT_R8G8B8A8_SNORM
};
 
static GLuint byte_types_scale[4] = {
PIPE_FORMAT_R8_SSCALED,
PIPE_FORMAT_R8G8_SSCALED,
PIPE_FORMAT_R8G8B8_SSCALED,
PIPE_FORMAT_R8G8B8A8_SSCALED
};
 
static GLuint fixed_types[4] = {
PIPE_FORMAT_R32_FIXED,
PIPE_FORMAT_R32G32_FIXED,
PIPE_FORMAT_R32G32B32_FIXED,
PIPE_FORMAT_R32G32B32A32_FIXED
};
 
 
 
/**
* Return a PIPE_FORMAT_x for the given GL datatype and size.
*/
GLuint
st_pipe_vertex_format(GLenum type, GLuint size, GLenum format,
GLboolean normalized)
{
assert((type >= GL_BYTE && type <= GL_DOUBLE) ||
type == GL_FIXED || type == GL_HALF_FLOAT);
assert(size >= 1);
assert(size <= 4);
assert(format == GL_RGBA || format == GL_BGRA);
 
if (format == GL_BGRA) {
/* this is an odd-ball case */
assert(type == GL_UNSIGNED_BYTE);
assert(normalized);
return PIPE_FORMAT_B8G8R8A8_UNORM;
}
 
if (normalized) {
switch (type) {
case GL_DOUBLE: return double_types[size-1];
case GL_FLOAT: return float_types[size-1];
case GL_HALF_FLOAT: return half_float_types[size-1];
case GL_INT: return int_types_norm[size-1];
case GL_SHORT: return short_types_norm[size-1];
case GL_BYTE: return byte_types_norm[size-1];
case GL_UNSIGNED_INT: return uint_types_norm[size-1];
case GL_UNSIGNED_SHORT: return ushort_types_norm[size-1];
case GL_UNSIGNED_BYTE: return ubyte_types_norm[size-1];
case GL_FIXED: return fixed_types[size-1];
default: assert(0); return 0;
}
}
else {
switch (type) {
case GL_DOUBLE: return double_types[size-1];
case GL_FLOAT: return float_types[size-1];
case GL_HALF_FLOAT: return half_float_types[size-1];
case GL_INT: return int_types_scale[size-1];
case GL_SHORT: return short_types_scale[size-1];
case GL_BYTE: return byte_types_scale[size-1];
case GL_UNSIGNED_INT: return uint_types_scale[size-1];
case GL_UNSIGNED_SHORT: return ushort_types_scale[size-1];
case GL_UNSIGNED_BYTE: return ubyte_types_scale[size-1];
case GL_FIXED: return fixed_types[size-1];
default: assert(0); return 0;
}
}
return 0; /* silence compiler warning */
}
 
 
 
 
 
/**
* Examine the active arrays to determine if we have interleaved
* vertex arrays all living in one VBO, or all living in user space.
* \param userSpace returns whether the arrays are in user space.
*/
static GLboolean
is_interleaved_arrays(const struct st_vertex_program *vp,
const struct st_vp_varient *vpv,
const struct gl_client_array **arrays,
GLboolean *userSpace)
{
GLuint attr;
const struct gl_buffer_object *firstBufObj = NULL;
GLint firstStride = -1;
GLuint num_client_arrays = 0;
const GLubyte *client_addr = NULL;
 
for (attr = 0; attr < vpv->num_inputs; attr++) {
const GLuint mesaAttr = vp->index_to_input[attr];
const struct gl_buffer_object *bufObj = arrays[mesaAttr]->BufferObj;
const GLsizei stride = arrays[mesaAttr]->StrideB; /* in bytes */
 
if (firstStride < 0) {
firstStride = stride;
}
else if (firstStride != stride) {
return GL_FALSE;
}
if (!bufObj || !bufObj->Name) {
num_client_arrays++;
/* Try to detect if the client-space arrays are
* "close" to each other.
*/
if (!client_addr) {
client_addr = arrays[mesaAttr]->Ptr;
}
else if (abs(arrays[mesaAttr]->Ptr - client_addr) > firstStride) {
/* arrays start too far apart */
return GL_FALSE;
}
}
else if (!firstBufObj) {
firstBufObj = bufObj;
}
else if (bufObj != firstBufObj) {
return GL_FALSE;
}
}
 
*userSpace = (num_client_arrays == vpv->num_inputs);
/* debug_printf("user space: %s (%d arrays, %d inputs)\n",
(int)*userSpace ? "Yes" : "No", num_client_arrays, vp->num_inputs); */
 
return GL_TRUE;
}
 
 
/**
* Compute the memory range occupied by the arrays.
*/
static void
get_arrays_bounds(const struct st_vertex_program *vp,
const struct st_vp_varient *vpv,
const struct gl_client_array **arrays,
GLuint max_index,
const GLubyte **low, const GLubyte **high)
{
const GLubyte *low_addr = NULL;
const GLubyte *high_addr = NULL;
GLuint attr;
 
/* debug_printf("get_arrays_bounds: Handling %u attrs\n", vpv->num_inputs); */
 
for (attr = 0; attr < vpv->num_inputs; attr++) {
const GLuint mesaAttr = vp->index_to_input[attr];
const GLint stride = arrays[mesaAttr]->StrideB;
const GLubyte *start = arrays[mesaAttr]->Ptr;
const unsigned sz = (arrays[mesaAttr]->Size *
_mesa_sizeof_type(arrays[mesaAttr]->Type));
const GLubyte *end = start + (max_index * stride) + sz;
 
/* debug_printf("attr %u: stride %d size %u start %p end %p\n",
attr, stride, sz, start, end); */
 
if (attr == 0) {
low_addr = start;
high_addr = end;
}
else {
low_addr = MIN2(low_addr, start);
high_addr = MAX2(high_addr, end);
}
}
 
*low = low_addr;
*high = high_addr;
}
 
 
/**
* Set up for drawing interleaved arrays that all live in one VBO
* or all live in user space.
* \param vbuffer returns vertex buffer info
* \param velements returns vertex element info
*/
static void
setup_interleaved_attribs(struct gl_context *ctx,
const struct st_vertex_program *vp,
const struct st_vp_varient *vpv,
const struct gl_client_array **arrays,
GLuint max_index,
GLboolean userSpace,
struct pipe_vertex_buffer *vbuffer,
struct pipe_vertex_element velements[])
{
struct st_context *st = st_context(ctx);
struct pipe_context *pipe = st->pipe;
GLuint attr;
const GLubyte *offset0 = NULL;
 
for (attr = 0; attr < vpv->num_inputs; attr++) {
const GLuint mesaAttr = vp->index_to_input[attr];
struct gl_buffer_object *bufobj = arrays[mesaAttr]->BufferObj;
struct st_buffer_object *stobj = st_buffer_object(bufobj);
GLsizei stride = arrays[mesaAttr]->StrideB;
 
/*printf("stobj %u = %p\n", attr, (void*)stobj);*/
 
if (attr == 0) {
const GLubyte *low, *high;
 
get_arrays_bounds(vp, vpv, arrays, max_index, &low, &high);
/* debug_printf("buffer range: %p %p range %d max index %u\n",
low, high, high - low, max_index); */
 
offset0 = low;
if (userSpace) {
vbuffer->buffer =
pipe_user_buffer_create(pipe->screen, (void *) low, high - low,
PIPE_BIND_VERTEX_BUFFER);
vbuffer->buffer_offset = 0;
}
else {
vbuffer->buffer = NULL;
pipe_resource_reference(&vbuffer->buffer, stobj->buffer);
vbuffer->buffer_offset = pointer_to_offset(low);
}
vbuffer->stride = stride; /* in bytes */
vbuffer->max_index = max_index;
}
 
velements[attr].src_offset =
(unsigned) (arrays[mesaAttr]->Ptr - offset0);
velements[attr].instance_divisor = 0;
velements[attr].vertex_buffer_index = 0;
velements[attr].src_format =
st_pipe_vertex_format(arrays[mesaAttr]->Type,
arrays[mesaAttr]->Size,
arrays[mesaAttr]->Format,
arrays[mesaAttr]->Normalized);
assert(velements[attr].src_format);
}
}
 
 
/**
* Set up a separate pipe_vertex_buffer and pipe_vertex_element for each
* vertex attribute.
* \param vbuffer returns vertex buffer info
* \param velements returns vertex element info
*/
static void
setup_non_interleaved_attribs(struct gl_context *ctx,
const struct st_vertex_program *vp,
const struct st_vp_varient *vpv,
const struct gl_client_array **arrays,
GLuint max_index,
GLboolean *userSpace,
struct pipe_vertex_buffer vbuffer[],
struct pipe_vertex_element velements[])
{
struct st_context *st = st_context(ctx);
struct pipe_context *pipe = st->pipe;
GLuint attr;
 
for (attr = 0; attr < vpv->num_inputs; attr++) {
const GLuint mesaAttr = vp->index_to_input[attr];
struct gl_buffer_object *bufobj = arrays[mesaAttr]->BufferObj;
GLsizei stride = arrays[mesaAttr]->StrideB;
 
*userSpace = GL_FALSE;
 
if (bufobj && bufobj->Name) {
/* Attribute data is in a VBO.
* Recall that for VBOs, the gl_client_array->Ptr field is
* really an offset from the start of the VBO, not a pointer.
*/
struct st_buffer_object *stobj = st_buffer_object(bufobj);
assert(stobj->buffer);
/*printf("stobj %u = %p\n", attr, (void*) stobj);*/
 
vbuffer[attr].buffer = NULL;
pipe_resource_reference(&vbuffer[attr].buffer, stobj->buffer);
vbuffer[attr].buffer_offset = pointer_to_offset(arrays[mesaAttr]->Ptr);
velements[attr].src_offset = 0;
}
else {
/* attribute data is in user-space memory, not a VBO */
uint bytes;
/*printf("user-space array %d stride %d\n", attr, stride);*/
*userSpace = GL_TRUE;
 
/* wrap user data */
if (arrays[mesaAttr]->Ptr) {
/* user's vertex array */
if (arrays[mesaAttr]->StrideB) {
bytes = arrays[mesaAttr]->StrideB * (max_index + 1);
}
else {
bytes = arrays[mesaAttr]->Size
* _mesa_sizeof_type(arrays[mesaAttr]->Type);
}
vbuffer[attr].buffer =
pipe_user_buffer_create(pipe->screen,
(void *) arrays[mesaAttr]->Ptr, bytes,
PIPE_BIND_VERTEX_BUFFER);
}
else {
/* no array, use ctx->Current.Attrib[] value */
bytes = sizeof(ctx->Current.Attrib[0]);
vbuffer[attr].buffer =
pipe_user_buffer_create(pipe->screen,
(void *) ctx->Current.Attrib[mesaAttr],
bytes,
PIPE_BIND_VERTEX_BUFFER);
stride = 0;
}
 
vbuffer[attr].buffer_offset = 0;
velements[attr].src_offset = 0;
}
 
assert(velements[attr].src_offset <= 2048); /* 11-bit field */
 
/* common-case setup */
vbuffer[attr].stride = stride; /* in bytes */
vbuffer[attr].max_index = max_index;
velements[attr].instance_divisor = 0;
velements[attr].vertex_buffer_index = attr;
velements[attr].src_format
= st_pipe_vertex_format(arrays[mesaAttr]->Type,
arrays[mesaAttr]->Size,
arrays[mesaAttr]->Format,
arrays[mesaAttr]->Normalized);
assert(velements[attr].src_format);
}
}
 
 
static void
setup_index_buffer(struct gl_context *ctx,
const struct _mesa_index_buffer *ib,
struct pipe_index_buffer *ibuffer)
{
struct st_context *st = st_context(ctx);
struct pipe_context *pipe = st->pipe;
 
memset(ibuffer, 0, sizeof(*ibuffer));
if (ib) {
struct gl_buffer_object *bufobj = ib->obj;
 
switch (ib->type) {
case GL_UNSIGNED_INT:
ibuffer->index_size = 4;
break;
case GL_UNSIGNED_SHORT:
ibuffer->index_size = 2;
break;
case GL_UNSIGNED_BYTE:
ibuffer->index_size = 1;
break;
default:
assert(0);
return;
}
 
/* get/create the index buffer object */
if (bufobj && bufobj->Name) {
/* elements/indexes are in a real VBO */
struct st_buffer_object *stobj = st_buffer_object(bufobj);
pipe_resource_reference(&ibuffer->buffer, stobj->buffer);
ibuffer->offset = pointer_to_offset(ib->ptr);
}
else {
/* element/indicies are in user space memory */
ibuffer->buffer =
pipe_user_buffer_create(pipe->screen, (void *) ib->ptr,
ib->count * ibuffer->index_size,
PIPE_BIND_INDEX_BUFFER);
}
}
}
 
/**
* Prior to drawing, check that any uniforms referenced by the
* current shader have been set. If a uniform has not been set,
* issue a warning.
*/
static void
check_uniforms(struct gl_context *ctx)
{
struct gl_shader_program *shProg[3] = {
ctx->Shader.CurrentVertexProgram,
ctx->Shader.CurrentGeometryProgram,
ctx->Shader.CurrentFragmentProgram,
};
unsigned j;
 
for (j = 0; j < 3; j++) {
unsigned i;
 
if (shProg[j] == NULL || !shProg[j]->LinkStatus)
continue;
 
for (i = 0; i < shProg[j]->Uniforms->NumUniforms; i++) {
const struct gl_uniform *u = &shProg[j]->Uniforms->Uniforms[i];
if (!u->Initialized) {
_mesa_warning(ctx,
"Using shader with uninitialized uniform: %s",
u->Name);
}
}
}
}
 
 
/**
* Translate OpenGL primtive type (GL_POINTS, GL_TRIANGLE_STRIP, etc) to
* the corresponding Gallium type.
*/
static unsigned
translate_prim(const struct gl_context *ctx, unsigned prim)
{
/* GL prims should match Gallium prims, spot-check a few */
assert(GL_POINTS == PIPE_PRIM_POINTS);
assert(GL_QUADS == PIPE_PRIM_QUADS);
assert(GL_TRIANGLE_STRIP_ADJACENCY == PIPE_PRIM_TRIANGLE_STRIP_ADJACENCY);
 
/* Avoid quadstrips if it's easy to do so:
* Note: it's imporant to do the correct trimming if we change the prim type!
* We do that wherever this function is called.
*/
if (prim == GL_QUAD_STRIP &&
ctx->Light.ShadeModel != GL_FLAT &&
ctx->Polygon.FrontMode == GL_FILL &&
ctx->Polygon.BackMode == GL_FILL)
prim = GL_TRIANGLE_STRIP;
 
return prim;
}
 
 
 
/**
* This function gets plugged into the VBO module and is called when
* we have something to render.
* Basically, translate the information into the format expected by gallium.
*/
void
st_draw_vbo(struct gl_context *ctx,
const struct gl_client_array **arrays,
const struct _mesa_prim *prims,
GLuint nr_prims,
const struct _mesa_index_buffer *ib,
GLboolean index_bounds_valid,
GLuint min_index,
GLuint max_index)
{
struct st_context *st = st_context(ctx);
struct pipe_context *pipe = st->pipe;
const struct st_vertex_program *vp;
const struct st_vp_varient *vpv;
struct pipe_vertex_buffer vbuffer[PIPE_MAX_SHADER_INPUTS];
GLuint attr;
struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS];
unsigned num_vbuffers, num_velements;
struct pipe_index_buffer ibuffer;
GLboolean userSpace = GL_FALSE;
GLboolean vertDataEdgeFlags;
struct pipe_draw_info info;
unsigned i;
 
/* Mesa core state should have been validated already */
assert(ctx->NewState == 0x0);
 
/* Gallium probably doesn't want this in some cases. */
if (!index_bounds_valid)
if (!vbo_all_varyings_in_vbos(arrays))
vbo_get_minmax_index(ctx, prims, ib, &min_index, &max_index);
 
/* sanity check for pointer arithmetic below */
assert(sizeof(arrays[0]->Ptr[0]) == 1);
 
vertDataEdgeFlags = arrays[VERT_ATTRIB_EDGEFLAG]->BufferObj &&
arrays[VERT_ATTRIB_EDGEFLAG]->BufferObj->Name;
if (vertDataEdgeFlags != st->vertdata_edgeflags) {
st->vertdata_edgeflags = vertDataEdgeFlags;
st->dirty.st |= ST_NEW_EDGEFLAGS_DATA;
}
 
st_validate_state(st);
 
/* must get these after state validation! */
vp = st->vp;
vpv = st->vp_varient;
 
#if 0
if (MESA_VERBOSE & VERBOSE_GLSL) {
check_uniforms(ctx);
}
#else
(void) check_uniforms;
#endif
 
memset(velements, 0, sizeof(struct pipe_vertex_element) * vpv->num_inputs);
/*
* Setup the vbuffer[] and velements[] arrays.
*/
if (is_interleaved_arrays(vp, vpv, arrays, &userSpace)) {
/*printf("Draw interleaved\n");*/
setup_interleaved_attribs(ctx, vp, vpv, arrays, max_index, userSpace,
vbuffer, velements);
num_vbuffers = 1;
num_velements = vpv->num_inputs;
if (num_velements == 0)
num_vbuffers = 0;
}
else {
/*printf("Draw non-interleaved\n");*/
setup_non_interleaved_attribs(ctx, vp, vpv, arrays, max_index,
&userSpace, vbuffer, velements);
num_vbuffers = vpv->num_inputs;
num_velements = vpv->num_inputs;
}
 
#if 0
{
GLuint i;
for (i = 0; i < num_vbuffers; i++) {
printf("buffers[%d].stride = %u\n", i, vbuffer[i].stride);
printf("buffers[%d].max_index = %u\n", i, vbuffer[i].max_index);
printf("buffers[%d].buffer_offset = %u\n", i, vbuffer[i].buffer_offset);
printf("buffers[%d].buffer = %p\n", i, (void*) vbuffer[i].buffer);
}
for (i = 0; i < num_velements; i++) {
printf("vlements[%d].vbuffer_index = %u\n", i, velements[i].vertex_buffer_index);
printf("vlements[%d].src_offset = %u\n", i, velements[i].src_offset);
printf("vlements[%d].format = %s\n", i, util_format_name(velements[i].src_format));
}
}
#endif
 
pipe->set_vertex_buffers(pipe, num_vbuffers, vbuffer);
cso_set_vertex_elements(st->cso_context, num_velements, velements);
 
setup_index_buffer(ctx, ib, &ibuffer);
pipe->set_index_buffer(pipe, &ibuffer);
 
util_draw_init_info(&info);
if (ib) {
info.indexed = TRUE;
if (min_index != ~0 && max_index != ~0) {
info.min_index = min_index;
info.max_index = max_index;
}
}
 
info.primitive_restart = st->ctx->Array.PrimitiveRestart;
info.restart_index = st->ctx->Array.RestartIndex;
 
/* do actual drawing */
for (i = 0; i < nr_prims; i++) {
info.mode = translate_prim( ctx, prims[i].mode );
info.start = prims[i].start;
info.count = prims[i].count;
info.instance_count = prims[i].num_instances;
info.index_bias = prims[i].basevertex;
if (!ib) {
info.min_index = info.start;
info.max_index = info.start + info.count - 1;
}
 
if (u_trim_pipe_prim(info.mode, &info.count))
pipe->draw_vbo(pipe, &info);
}
 
pipe_resource_reference(&ibuffer.buffer, NULL);
 
/* unreference buffers (frees wrapped user-space buffer objects) */
for (attr = 0; attr < num_vbuffers; attr++) {
pipe_resource_reference(&vbuffer[attr].buffer, NULL);
assert(!vbuffer[attr].buffer);
}
 
if (userSpace)
{
pipe->set_vertex_buffers(pipe, 0, NULL);
}
}
 
 
void st_init_draw( struct st_context *st )
{
struct gl_context *ctx = st->ctx;
 
vbo_set_draw_func(ctx, st_draw_vbo);
 
#if FEATURE_feedback || FEATURE_rastpos
st->draw = draw_create(st->pipe); /* for selection/feedback */
 
/* Disable draw options that might convert points/lines to tris, etc.
* as that would foul-up feedback/selection mode.
*/
draw_wide_line_threshold(st->draw, 1000.0f);
draw_wide_point_threshold(st->draw, 1000.0f);
draw_enable_line_stipple(st->draw, FALSE);
draw_enable_point_sprites(st->draw, FALSE);
#endif
}
 
 
void st_destroy_draw( struct st_context *st )
{
#if FEATURE_feedback || FEATURE_rastpos
draw_destroy(st->draw);
#endif
}
 
 
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_draw.h
0,0 → 1,90
/**************************************************************************
*
* Copyright 2004 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 ST_DRAW_H
#define ST_DRAW_H
 
#include "main/compiler.h"
#include "main/glheader.h"
#include "main/mtypes.h"
 
struct _mesa_index_buffer;
struct _mesa_prim;
struct st_context;
 
void st_init_draw( struct st_context *st );
 
void st_destroy_draw( struct st_context *st );
 
extern void
st_draw_vbo(struct gl_context *ctx,
const struct gl_client_array **arrays,
const struct _mesa_prim *prims,
GLuint nr_prims,
const struct _mesa_index_buffer *ib,
GLboolean index_bounds_valid,
GLuint min_index,
GLuint max_index);
 
extern void
st_feedback_draw_vbo(struct gl_context *ctx,
const struct gl_client_array **arrays,
const struct _mesa_prim *prims,
GLuint nr_prims,
const struct _mesa_index_buffer *ib,
GLboolean index_bounds_valid,
GLuint min_index,
GLuint max_index);
 
/* Internal function:
*/
extern GLuint
st_pipe_vertex_format(GLenum type, GLuint size, GLenum format,
GLboolean normalized);
 
 
/**
* When drawing with VBOs, the addresses specified with
* glVertex/Color/TexCoordPointer() are really offsets into the VBO, not real
* addresses. At some point we need to convert those pointers to offsets.
* This function is basically a cast wrapper to avoid warnings when building
* in 64-bit mode.
*/
static INLINE unsigned
pointer_to_offset(const void *ptr)
{
return (unsigned) (((unsigned long) ptr) & 0xffffffffUL);
}
 
 
#endif
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_draw_feedback.c
0,0 → 1,288
/**************************************************************************
*
* 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 "main/imports.h"
#include "main/image.h"
#include "main/macros.h"
 
#include "vbo/vbo.h"
 
#include "st_context.h"
#include "st_atom.h"
#include "st_cb_bufferobjects.h"
#include "st_draw.h"
#include "st_program.h"
 
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "util/u_inlines.h"
 
#include "draw/draw_private.h"
#include "draw/draw_context.h"
 
 
#if FEATURE_feedback || FEATURE_rastpos
 
/**
* Set the (private) draw module's post-transformed vertex format when in
* GL_SELECT or GL_FEEDBACK mode or for glRasterPos.
*/
static void
set_feedback_vertex_format(struct gl_context *ctx)
{
#if 0
struct st_context *st = st_context(ctx);
struct vertex_info vinfo;
GLuint i;
 
memset(&vinfo, 0, sizeof(vinfo));
 
if (ctx->RenderMode == GL_SELECT) {
assert(ctx->RenderMode == GL_SELECT);
vinfo.num_attribs = 1;
vinfo.format[0] = FORMAT_4F;
vinfo.interp_mode[0] = INTERP_LINEAR;
}
else {
/* GL_FEEDBACK, or glRasterPos */
/* emit all attribs (pos, color, texcoord) as GLfloat[4] */
vinfo.num_attribs = st->state.vs->cso->state.num_outputs;
for (i = 0; i < vinfo.num_attribs; i++) {
vinfo.format[i] = FORMAT_4F;
vinfo.interp_mode[i] = INTERP_LINEAR;
}
}
 
draw_set_vertex_info(st->draw, &vinfo);
#endif
}
 
 
/**
* Called by VBO to draw arrays when in selection or feedback mode and
* to implement glRasterPos.
* This is very much like the normal draw_vbo() function above.
* Look at code refactoring some day.
* Might move this into the failover module some day.
*/
void
st_feedback_draw_vbo(struct gl_context *ctx,
const struct gl_client_array **arrays,
const struct _mesa_prim *prims,
GLuint nr_prims,
const struct _mesa_index_buffer *ib,
GLboolean index_bounds_valid,
GLuint min_index,
GLuint max_index)
{
struct st_context *st = st_context(ctx);
struct pipe_context *pipe = st->pipe;
struct draw_context *draw = st->draw;
const struct st_vertex_program *vp;
const struct pipe_shader_state *vs;
struct pipe_vertex_buffer vbuffers[PIPE_MAX_SHADER_INPUTS];
struct pipe_vertex_element velements[PIPE_MAX_ATTRIBS];
struct pipe_index_buffer ibuffer;
struct pipe_transfer *vb_transfer[PIPE_MAX_ATTRIBS];
struct pipe_transfer *ib_transfer = NULL;
struct pipe_transfer *cb_transfer;
GLuint attr, i;
ubyte *mapped_constants;
const void *mapped_indices = NULL;
 
assert(draw);
 
st_validate_state(st);
 
if (!index_bounds_valid)
vbo_get_minmax_index(ctx, prims, ib, &min_index, &max_index);
 
/* must get these after state validation! */
vp = st->vp;
vs = &st->vp_varient->tgsi;
 
if (!st->vp_varient->draw_shader) {
st->vp_varient->draw_shader = draw_create_vertex_shader(draw, vs);
}
 
/*
* Set up the draw module's state.
*
* We'd like to do this less frequently, but the normal state-update
* code sends state updates to the pipe, not to our private draw module.
*/
assert(draw);
draw_set_viewport_state(draw, &st->state.viewport);
draw_set_clip_state(draw, &st->state.clip);
draw_set_rasterizer_state(draw, &st->state.rasterizer, NULL);
draw_bind_vertex_shader(draw, st->vp_varient->draw_shader);
set_feedback_vertex_format(ctx);
 
/* loop over TGSI shader inputs to determine vertex buffer
* and attribute info
*/
for (attr = 0; attr < vp->num_inputs; attr++) {
const GLuint mesaAttr = vp->index_to_input[attr];
struct gl_buffer_object *bufobj = arrays[mesaAttr]->BufferObj;
void *map;
 
if (bufobj && bufobj->Name) {
/* Attribute data is in a VBO.
* Recall that for VBOs, the gl_client_array->Ptr field is
* really an offset from the start of the VBO, not a pointer.
*/
struct st_buffer_object *stobj = st_buffer_object(bufobj);
assert(stobj->buffer);
 
vbuffers[attr].buffer = NULL;
pipe_resource_reference(&vbuffers[attr].buffer, stobj->buffer);
vbuffers[attr].buffer_offset = pointer_to_offset(arrays[0]->Ptr);
velements[attr].src_offset = arrays[mesaAttr]->Ptr - arrays[0]->Ptr;
}
else {
/* attribute data is in user-space memory, not a VBO */
uint bytes = (arrays[mesaAttr]->Size
* _mesa_sizeof_type(arrays[mesaAttr]->Type)
* (max_index + 1));
 
/* wrap user data */
vbuffers[attr].buffer
= pipe_user_buffer_create(pipe->screen, (void *) arrays[mesaAttr]->Ptr,
bytes,
PIPE_BIND_VERTEX_BUFFER);
vbuffers[attr].buffer_offset = 0;
velements[attr].src_offset = 0;
}
 
/* common-case setup */
vbuffers[attr].stride = arrays[mesaAttr]->StrideB; /* in bytes */
vbuffers[attr].max_index = max_index;
velements[attr].instance_divisor = 0;
velements[attr].vertex_buffer_index = attr;
velements[attr].src_format =
st_pipe_vertex_format(arrays[mesaAttr]->Type,
arrays[mesaAttr]->Size,
arrays[mesaAttr]->Format,
arrays[mesaAttr]->Normalized);
assert(velements[attr].src_format);
 
/* tell draw about this attribute */
#if 0
draw_set_vertex_buffer(draw, attr, &vbuffer[attr]);
#endif
 
/* map the attrib buffer */
map = pipe_buffer_map(pipe, vbuffers[attr].buffer,
PIPE_TRANSFER_READ,
&vb_transfer[attr]);
draw_set_mapped_vertex_buffer(draw, attr, map);
}
 
draw_set_vertex_buffers(draw, vp->num_inputs, vbuffers);
draw_set_vertex_elements(draw, vp->num_inputs, velements);
 
memset(&ibuffer, 0, sizeof(ibuffer));
if (ib) {
struct gl_buffer_object *bufobj = ib->obj;
 
switch (ib->type) {
case GL_UNSIGNED_INT:
ibuffer.index_size = 4;
break;
case GL_UNSIGNED_SHORT:
ibuffer.index_size = 2;
break;
case GL_UNSIGNED_BYTE:
ibuffer.index_size = 1;
break;
default:
assert(0);
return;
}
 
if (bufobj && bufobj->Name) {
struct st_buffer_object *stobj = st_buffer_object(bufobj);
 
pipe_resource_reference(&ibuffer.buffer, stobj->buffer);
ibuffer.offset = pointer_to_offset(ib->ptr);
 
mapped_indices = pipe_buffer_map(pipe, stobj->buffer,
PIPE_TRANSFER_READ, &ib_transfer);
}
else {
/* skip setting ibuffer.buffer as the draw module does not use it */
mapped_indices = ib->ptr;
}
 
draw_set_index_buffer(draw, &ibuffer);
draw_set_mapped_index_buffer(draw, mapped_indices);
}
 
/* map constant buffers */
mapped_constants = pipe_buffer_map(pipe,
st->state.constants[PIPE_SHADER_VERTEX],
PIPE_TRANSFER_READ,
&cb_transfer);
draw_set_mapped_constant_buffer(st->draw, PIPE_SHADER_VERTEX, 0,
mapped_constants,
st->state.constants[PIPE_SHADER_VERTEX]->width0);
 
 
/* draw here */
for (i = 0; i < nr_prims; i++) {
draw_arrays(draw, prims[i].mode, prims[i].start, prims[i].count);
}
 
 
/* unmap constant buffers */
pipe_buffer_unmap(pipe, st->state.constants[PIPE_SHADER_VERTEX],
cb_transfer);
 
/*
* unmap vertex/index buffers
*/
for (i = 0; i < PIPE_MAX_ATTRIBS; i++) {
if (draw->pt.vertex_buffer[i].buffer) {
pipe_buffer_unmap(pipe, draw->pt.vertex_buffer[i].buffer,
vb_transfer[i]);
pipe_resource_reference(&draw->pt.vertex_buffer[i].buffer, NULL);
draw_set_mapped_vertex_buffer(draw, i, NULL);
}
}
 
if (ib) {
draw_set_mapped_index_buffer(draw, NULL);
draw_set_index_buffer(draw, NULL);
 
if (ib_transfer)
pipe_buffer_unmap(pipe, ibuffer.buffer, ib_transfer);
pipe_resource_reference(&ibuffer.buffer, NULL);
}
}
 
#endif /* FEATURE_feedback || FEATURE_rastpos */
 
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_extensions.c
0,0 → 1,461
/**************************************************************************
*
* 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.
*
**************************************************************************/
 
#include "main/imports.h"
#include "main/context.h"
#include "main/macros.h"
 
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "pipe/p_screen.h"
 
#include "st_context.h"
#include "st_extensions.h"
 
 
static int _min(int a, int b)
{
return (a < b) ? a : b;
}
 
static float _maxf(float a, float b)
{
return (a > b) ? a : b;
}
 
static int _clamp(int a, int min, int max)
{
if (a < min)
return min;
else if (a > max)
return max;
else
return a;
}
 
 
/**
* Query driver to get implementation limits.
* Note that we have to limit/clamp against Mesa's internal limits too.
*/
void st_init_limits(struct st_context *st)
{
struct pipe_screen *screen = st->pipe->screen;
struct gl_constants *c = &st->ctx->Const;
gl_shader_type sh;
 
c->MaxTextureLevels
= _min(screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_2D_LEVELS),
MAX_TEXTURE_LEVELS);
 
c->Max3DTextureLevels
= _min(screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_3D_LEVELS),
MAX_3D_TEXTURE_LEVELS);
 
c->MaxCubeTextureLevels
= _min(screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_CUBE_LEVELS),
MAX_CUBE_TEXTURE_LEVELS);
 
c->MaxTextureRectSize
= _min(1 << (c->MaxTextureLevels - 1), MAX_TEXTURE_RECT_SIZE);
 
c->MaxTextureImageUnits
= _min(screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS),
MAX_TEXTURE_IMAGE_UNITS);
 
c->MaxVertexTextureImageUnits
= _min(screen->get_param(screen, PIPE_CAP_MAX_VERTEX_TEXTURE_UNITS),
MAX_VERTEX_TEXTURE_IMAGE_UNITS);
 
c->MaxCombinedTextureImageUnits
= _min(screen->get_param(screen, PIPE_CAP_MAX_COMBINED_SAMPLERS),
MAX_COMBINED_TEXTURE_IMAGE_UNITS);
 
c->MaxTextureCoordUnits
= _min(c->MaxTextureImageUnits, MAX_TEXTURE_COORD_UNITS);
 
c->MaxTextureUnits = _min(c->MaxTextureImageUnits, c->MaxTextureCoordUnits);
 
c->MaxDrawBuffers
= _clamp(screen->get_param(screen, PIPE_CAP_MAX_RENDER_TARGETS),
1, MAX_DRAW_BUFFERS);
 
c->MaxLineWidth
= _maxf(1.0f, screen->get_paramf(screen, PIPE_CAP_MAX_LINE_WIDTH));
c->MaxLineWidthAA
= _maxf(1.0f, screen->get_paramf(screen, PIPE_CAP_MAX_LINE_WIDTH_AA));
 
c->MaxPointSize
= _maxf(1.0f, screen->get_paramf(screen, PIPE_CAP_MAX_POINT_WIDTH));
c->MaxPointSizeAA
= _maxf(1.0f, screen->get_paramf(screen, PIPE_CAP_MAX_POINT_WIDTH_AA));
/* called after _mesa_create_context/_mesa_init_point, fix default user
* settable max point size up
*/
st->ctx->Point.MaxSize = MAX2(c->MaxPointSize, c->MaxPointSizeAA);
/* these are not queryable. Note that GL basically mandates a 1.0 minimum
* for non-aa sizes, but we can go down to 0.0 for aa points.
*/
c->MinPointSize = 1.0f;
c->MinPointSizeAA = 0.0f;
 
c->MaxTextureMaxAnisotropy
= _maxf(2.0f, screen->get_paramf(screen, PIPE_CAP_MAX_TEXTURE_ANISOTROPY));
 
c->MaxTextureLodBias
= screen->get_paramf(screen, PIPE_CAP_MAX_TEXTURE_LOD_BIAS);
 
c->MaxDrawBuffers
= CLAMP(screen->get_param(screen, PIPE_CAP_MAX_RENDER_TARGETS),
1, MAX_DRAW_BUFFERS);
 
/* Quads always follow GL provoking rules. */
c->QuadsFollowProvokingVertexConvention = GL_FALSE;
 
for (sh = 0; sh < MESA_SHADER_TYPES; ++sh) {
struct gl_shader_compiler_options *options =
&st->ctx->ShaderCompilerOptions[sh];
struct gl_program_constants *pc;
 
switch (sh) {
case PIPE_SHADER_FRAGMENT:
pc = &c->FragmentProgram;
break;
case PIPE_SHADER_VERTEX:
pc = &c->VertexProgram;
break;
case PIPE_SHADER_GEOMETRY:
pc = &c->GeometryProgram;
break;
default:
assert(0);
continue;
}
 
pc->MaxNativeInstructions = screen->get_shader_param(screen, sh, PIPE_SHADER_CAP_MAX_INSTRUCTIONS);
pc->MaxNativeAluInstructions = screen->get_shader_param(screen, sh, PIPE_SHADER_CAP_MAX_ALU_INSTRUCTIONS);
pc->MaxNativeTexInstructions = screen->get_shader_param(screen, sh, PIPE_SHADER_CAP_MAX_TEX_INSTRUCTIONS);
pc->MaxNativeTexIndirections = screen->get_shader_param(screen, sh, PIPE_SHADER_CAP_MAX_TEX_INDIRECTIONS);
pc->MaxNativeAttribs = screen->get_shader_param(screen, sh, PIPE_SHADER_CAP_MAX_INPUTS);
pc->MaxNativeTemps = screen->get_shader_param(screen, sh, PIPE_SHADER_CAP_MAX_TEMPS);
pc->MaxNativeAddressRegs = screen->get_shader_param(screen, sh, PIPE_SHADER_CAP_MAX_ADDRS);
pc->MaxNativeParameters = screen->get_shader_param(screen, sh, PIPE_SHADER_CAP_MAX_CONSTS);
pc->MaxUniformComponents = 4 * MIN2(pc->MaxNativeParameters, MAX_UNIFORMS);
 
options->EmitNoNoise = TRUE;
 
/* TODO: make these more fine-grained if anyone needs it */
options->EmitNoIfs = !screen->get_shader_param(screen, sh, PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH);
options->EmitNoLoops = !screen->get_shader_param(screen, sh, PIPE_SHADER_CAP_MAX_CONTROL_FLOW_DEPTH);
options->EmitNoFunctions = !screen->get_shader_param(screen, sh, PIPE_SHADER_CAP_SUBROUTINES);
options->EmitNoMainReturn = !screen->get_shader_param(screen, sh, PIPE_SHADER_CAP_SUBROUTINES);
 
options->EmitNoCont = !screen->get_shader_param(screen, sh, PIPE_SHADER_CAP_TGSI_CONT_SUPPORTED);
 
options->EmitNoIndirectInput = !screen->get_shader_param(screen, sh,
PIPE_SHADER_CAP_INDIRECT_INPUT_ADDR);
options->EmitNoIndirectOutput = !screen->get_shader_param(screen, sh,
PIPE_SHADER_CAP_INDIRECT_OUTPUT_ADDR);
options->EmitNoIndirectTemp = !screen->get_shader_param(screen, sh,
PIPE_SHADER_CAP_INDIRECT_TEMP_ADDR);
options->EmitNoIndirectUniform = !screen->get_shader_param(screen, sh,
PIPE_SHADER_CAP_INDIRECT_CONST_ADDR);
 
if(options->EmitNoLoops)
options->MaxUnrollIterations = MIN2(screen->get_shader_param(screen, sh, PIPE_SHADER_CAP_MAX_INSTRUCTIONS), 65536);
}
 
/* PIPE_CAP_MAX_FS_INPUTS specifies the number of COLORn + GENERICn inputs
* and is set in MaxNativeAttribs. It's always 2 colors + N generic
* attributes. The GLSL compiler never uses COLORn for varyings, so we
* subtract the 2 colors to get the maximum number of varyings (generic
* attributes) supported by a driver. */
c->MaxVarying = screen->get_shader_param(screen, PIPE_SHADER_FRAGMENT, PIPE_SHADER_CAP_MAX_INPUTS) - 2;
c->MaxVarying = MIN2(c->MaxVarying, MAX_VARYING);
 
/* XXX we'll need a better query here someday */
if (screen->get_param(screen, PIPE_CAP_GLSL)) {
c->GLSLVersion = 120;
}
}
 
 
/**
* Use pipe_screen::get_param() to query PIPE_CAP_ values to determine
* which GL extensions are supported.
* Quite a few extensions are always supported because they are standard
* features or can be built on top of other gallium features.
* Some fine tuning may still be needed.
*/
void st_init_extensions(struct st_context *st)
{
struct pipe_screen *screen = st->pipe->screen;
struct gl_context *ctx = st->ctx;
 
/*
* Extensions that are supported by all Gallium drivers:
*/
ctx->Extensions.ARB_copy_buffer = GL_TRUE;
ctx->Extensions.ARB_draw_elements_base_vertex = GL_TRUE;
ctx->Extensions.ARB_fragment_coord_conventions = GL_TRUE;
ctx->Extensions.ARB_fragment_program = GL_TRUE;
ctx->Extensions.ARB_map_buffer_range = GL_TRUE;
ctx->Extensions.ARB_multisample = GL_TRUE;
ctx->Extensions.ARB_texture_border_clamp = GL_TRUE; /* XXX temp */
ctx->Extensions.ARB_texture_compression = GL_TRUE;
ctx->Extensions.ARB_texture_cube_map = GL_TRUE;
ctx->Extensions.ARB_texture_env_combine = GL_TRUE;
ctx->Extensions.ARB_texture_env_crossbar = GL_TRUE;
ctx->Extensions.ARB_texture_env_dot3 = GL_TRUE;
ctx->Extensions.ARB_vertex_array_object = GL_TRUE;
ctx->Extensions.ARB_vertex_buffer_object = GL_TRUE;
ctx->Extensions.ARB_vertex_program = GL_TRUE;
ctx->Extensions.ARB_window_pos = GL_TRUE;
 
ctx->Extensions.EXT_blend_color = GL_TRUE;
ctx->Extensions.EXT_blend_func_separate = GL_TRUE;
ctx->Extensions.EXT_blend_logic_op = GL_TRUE;
ctx->Extensions.EXT_blend_minmax = GL_TRUE;
ctx->Extensions.EXT_blend_subtract = GL_TRUE;
ctx->Extensions.EXT_framebuffer_blit = GL_TRUE;
ctx->Extensions.EXT_framebuffer_object = GL_TRUE;
ctx->Extensions.EXT_framebuffer_multisample = GL_TRUE;
ctx->Extensions.EXT_fog_coord = GL_TRUE;
ctx->Extensions.EXT_gpu_program_parameters = GL_TRUE;
ctx->Extensions.EXT_multi_draw_arrays = GL_TRUE;
ctx->Extensions.EXT_pixel_buffer_object = GL_TRUE;
ctx->Extensions.EXT_point_parameters = GL_TRUE;
ctx->Extensions.EXT_provoking_vertex = GL_TRUE;
ctx->Extensions.EXT_secondary_color = GL_TRUE;
ctx->Extensions.EXT_stencil_wrap = GL_TRUE;
ctx->Extensions.EXT_texture_env_add = GL_TRUE;
ctx->Extensions.EXT_texture_env_combine = GL_TRUE;
ctx->Extensions.EXT_texture_env_dot3 = GL_TRUE;
ctx->Extensions.EXT_texture_lod_bias = GL_TRUE;
ctx->Extensions.EXT_vertex_array_bgra = GL_TRUE;
 
ctx->Extensions.APPLE_vertex_array_object = GL_TRUE;
 
ctx->Extensions.ATI_texture_env_combine3 = GL_TRUE;
 
ctx->Extensions.MESA_pack_invert = GL_TRUE;
 
ctx->Extensions.NV_blend_square = GL_TRUE;
ctx->Extensions.NV_texgen_reflection = GL_TRUE;
ctx->Extensions.NV_texture_env_combine4 = GL_TRUE;
ctx->Extensions.NV_texture_rectangle = GL_TRUE;
#if 0
/* possibly could support the following two */
ctx->Extensions.NV_vertex_program = GL_TRUE;
ctx->Extensions.NV_vertex_program1_1 = GL_TRUE;
#endif
 
#if FEATURE_OES_EGL_image
ctx->Extensions.OES_EGL_image = GL_TRUE;
#endif
#if FEATURE_OES_draw_texture
ctx->Extensions.OES_draw_texture = GL_TRUE;
#endif
 
ctx->Extensions.SGIS_generate_mipmap = GL_TRUE;
 
/*
* Extensions that depend on the driver/hardware:
*/
if (screen->get_param(screen, PIPE_CAP_MAX_RENDER_TARGETS) > 0) {
ctx->Extensions.ARB_draw_buffers = GL_TRUE;
}
 
if (screen->get_param(screen, PIPE_CAP_TEXTURE_SWIZZLE) > 0) {
ctx->Extensions.EXT_texture_swizzle = GL_TRUE;
}
 
if (screen->get_param(screen, PIPE_CAP_GLSL)) {
ctx->Extensions.ARB_fragment_shader = GL_TRUE;
ctx->Extensions.ARB_vertex_shader = GL_TRUE;
ctx->Extensions.ARB_shader_objects = GL_TRUE;
ctx->Extensions.ARB_shading_language_100 = GL_TRUE;
ctx->Extensions.ARB_explicit_attrib_location = GL_TRUE;
ctx->Extensions.EXT_separate_shader_objects = GL_TRUE;
}
 
if (screen->get_param(screen, PIPE_CAP_TEXTURE_MIRROR_REPEAT) > 0) {
ctx->Extensions.ARB_texture_mirrored_repeat = GL_TRUE;
}
 
if (screen->get_param(screen, PIPE_CAP_BLEND_EQUATION_SEPARATE)) {
ctx->Extensions.EXT_blend_equation_separate = GL_TRUE;
}
 
if (screen->get_param(screen, PIPE_CAP_TEXTURE_MIRROR_CLAMP) > 0) {
ctx->Extensions.EXT_texture_mirror_clamp = GL_TRUE;
ctx->Extensions.ATI_texture_mirror_once = GL_TRUE;
}
 
if (screen->get_param(screen, PIPE_CAP_NPOT_TEXTURES)) {
ctx->Extensions.ARB_texture_non_power_of_two = GL_TRUE;
}
 
if (screen->get_param(screen, PIPE_CAP_MAX_TEXTURE_IMAGE_UNITS) > 1) {
ctx->Extensions.ARB_multitexture = GL_TRUE;
}
 
if (screen->get_param(screen, PIPE_CAP_TWO_SIDED_STENCIL)) {
ctx->Extensions.ATI_separate_stencil = GL_TRUE;
ctx->Extensions.EXT_stencil_two_side = GL_TRUE;
}
 
if (screen->get_param(screen, PIPE_CAP_ANISOTROPIC_FILTER)) {
ctx->Extensions.EXT_texture_filter_anisotropic = GL_TRUE;
}
 
if (screen->get_param(screen, PIPE_CAP_POINT_SPRITE)) {
ctx->Extensions.ARB_point_sprite = GL_TRUE;
/* GL_NV_point_sprite is not supported by gallium because we don't
* support the GL_POINT_SPRITE_R_MODE_NV option.
*/
}
 
if (screen->get_param(screen, PIPE_CAP_OCCLUSION_QUERY)) {
ctx->Extensions.ARB_occlusion_query = GL_TRUE;
}
if (screen->get_param(screen, PIPE_CAP_TIMER_QUERY)) {
ctx->Extensions.EXT_timer_query = GL_TRUE;
}
 
if (screen->get_param(screen, PIPE_CAP_TEXTURE_SHADOW_MAP)) {
ctx->Extensions.ARB_depth_texture = GL_TRUE;
ctx->Extensions.ARB_fragment_program_shadow = GL_TRUE;
ctx->Extensions.ARB_shadow = GL_TRUE;
ctx->Extensions.EXT_shadow_funcs = GL_TRUE;
/*ctx->Extensions.ARB_shadow_ambient = GL_TRUE;*/
}
 
/* GL_EXT_packed_depth_stencil requires both the ability to render to
* a depth/stencil buffer and texture from depth/stencil source.
*/
if (screen->is_format_supported(screen, PIPE_FORMAT_S8_USCALED_Z24_UNORM,
PIPE_TEXTURE_2D, 0,
PIPE_BIND_DEPTH_STENCIL, 0) &&
screen->is_format_supported(screen, PIPE_FORMAT_S8_USCALED_Z24_UNORM,
PIPE_TEXTURE_2D, 0,
PIPE_BIND_SAMPLER_VIEW, 0)) {
ctx->Extensions.EXT_packed_depth_stencil = GL_TRUE;
}
else if (screen->is_format_supported(screen, PIPE_FORMAT_Z24_UNORM_S8_USCALED,
PIPE_TEXTURE_2D, 0,
PIPE_BIND_DEPTH_STENCIL, 0) &&
screen->is_format_supported(screen, PIPE_FORMAT_Z24_UNORM_S8_USCALED,
PIPE_TEXTURE_2D, 0,
PIPE_BIND_SAMPLER_VIEW, 0)) {
ctx->Extensions.EXT_packed_depth_stencil = GL_TRUE;
}
 
/* sRGB support */
if (screen->is_format_supported(screen, PIPE_FORMAT_A8B8G8R8_SRGB,
PIPE_TEXTURE_2D, 0,
PIPE_BIND_SAMPLER_VIEW, 0) ||
screen->is_format_supported(screen, PIPE_FORMAT_B8G8R8A8_SRGB,
PIPE_TEXTURE_2D, 0,
PIPE_BIND_SAMPLER_VIEW, 0)) {
ctx->Extensions.EXT_texture_sRGB = GL_TRUE;
}
 
if (screen->is_format_supported(screen, PIPE_FORMAT_R8G8_UNORM,
PIPE_TEXTURE_2D, 0,
PIPE_BIND_SAMPLER_VIEW, 0)) {
ctx->Extensions.ARB_texture_rg = GL_TRUE;
}
 
/* s3tc support */
if (screen->is_format_supported(screen, PIPE_FORMAT_DXT5_RGBA,
PIPE_TEXTURE_2D, 0,
PIPE_BIND_SAMPLER_VIEW, 0) &&
(ctx->Mesa_DXTn ||
screen->is_format_supported(screen, PIPE_FORMAT_DXT5_RGBA,
PIPE_TEXTURE_2D, 0,
PIPE_BIND_RENDER_TARGET, 0))) {
ctx->Extensions.EXT_texture_compression_s3tc = GL_TRUE;
ctx->Extensions.S3_s3tc = GL_TRUE;
}
 
/* ycbcr support */
if (screen->is_format_supported(screen, PIPE_FORMAT_UYVY,
PIPE_TEXTURE_2D, 0,
PIPE_BIND_SAMPLER_VIEW, 0) ||
screen->is_format_supported(screen, PIPE_FORMAT_YUYV,
PIPE_TEXTURE_2D, 0,
PIPE_BIND_SAMPLER_VIEW, 0)) {
ctx->Extensions.MESA_ycbcr_texture = GL_TRUE;
}
 
/* GL_ARB_framebuffer_object */
if (ctx->Extensions.EXT_packed_depth_stencil) {
/* we support always support GL_EXT_framebuffer_blit */
ctx->Extensions.ARB_framebuffer_object = GL_TRUE;
}
 
if (st->pipe->render_condition) {
ctx->Extensions.NV_conditional_render = GL_TRUE;
}
 
if (screen->get_param(screen, PIPE_CAP_INDEP_BLEND_ENABLE)) {
ctx->Extensions.EXT_draw_buffers2 = GL_TRUE;
}
 
/* GL_ARB_half_float_vertex */
if (screen->is_format_supported(screen, PIPE_FORMAT_R16G16B16A16_FLOAT,
PIPE_BUFFER, 0,
PIPE_BIND_VERTEX_BUFFER, 0)) {
ctx->Extensions.ARB_half_float_vertex = GL_TRUE;
}
 
#if 0 /* not yet */
if (screen->get_param(screen, PIPE_CAP_INDEP_BLEND_FUNC)) {
ctx->Extensions.ARB_draw_buffers_blend = GL_TRUE;
}
#endif
 
if (screen->get_shader_param(screen, PIPE_SHADER_GEOMETRY, PIPE_SHADER_CAP_MAX_INSTRUCTIONS) > 0) {
#if 0 /* XXX re-enable when GLSL compiler again supports geometry shaders */
ctx->Extensions.ARB_geometry_shader4 = GL_TRUE;
#endif
}
 
if (screen->get_param(screen, PIPE_CAP_PRIMITIVE_RESTART)) {
ctx->Extensions.NV_primitive_restart = GL_TRUE;
}
 
if (screen->get_param(screen, PIPE_CAP_DEPTH_CLAMP)) {
ctx->Extensions.ARB_depth_clamp = GL_TRUE;
}
 
if (screen->get_param(screen, PIPE_CAP_SHADER_STENCIL_EXPORT)) {
ctx->Extensions.ARB_shader_stencil_export = GL_TRUE;
}
}
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_extensions.h
0,0 → 1,40
/**************************************************************************
*
* 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 ST_EXTENSIONS_H
#define ST_EXTENSIONS_H
 
 
struct st_context;
 
extern void st_init_limits(struct st_context *st);
 
extern void st_init_extensions(struct st_context *st);
 
 
#endif /* ST_EXTENSIONS_H */
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_format.c
0,0 → 1,1061
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* Copyright (c) 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.
*
**************************************************************************/
 
 
/**
* Mesa / Gallium format conversion and format selection code.
* \author Brian Paul
*/
 
#include "main/imports.h"
#include "main/context.h"
#include "main/texstore.h"
#include "main/image.h"
#include "main/macros.h"
 
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "pipe/p_screen.h"
#include "util/u_format.h"
#include "st_context.h"
#include "st_format.h"
 
 
static GLuint
format_max_bits(enum pipe_format format)
{
GLuint size = util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, 0);
 
size = MAX2(size, util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, 1));
size = MAX2(size, util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, 2));
size = MAX2(size, util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_RGB, 3));
size = MAX2(size, util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_ZS, 0));
size = MAX2(size, util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_ZS, 1));
return size;
}
 
 
/**
* Return basic GL datatype for the given gallium format.
*/
GLenum
st_format_datatype(enum pipe_format format)
{
const struct util_format_description *desc;
 
desc = util_format_description(format);
assert(desc);
 
if (desc->layout == UTIL_FORMAT_LAYOUT_PLAIN) {
if (format == PIPE_FORMAT_B5G5R5A1_UNORM ||
format == PIPE_FORMAT_B5G6R5_UNORM) {
return GL_UNSIGNED_SHORT;
}
else if (format == PIPE_FORMAT_Z24_UNORM_S8_USCALED ||
format == PIPE_FORMAT_S8_USCALED_Z24_UNORM ||
format == PIPE_FORMAT_Z24X8_UNORM ||
format == PIPE_FORMAT_X8Z24_UNORM) {
return GL_UNSIGNED_INT_24_8;
}
else {
const GLuint size = format_max_bits(format);
if (size == 8) {
if (desc->channel[0].type == UTIL_FORMAT_TYPE_UNSIGNED)
return GL_UNSIGNED_BYTE;
else
return GL_BYTE;
}
else if (size == 16) {
if (desc->channel[0].type == UTIL_FORMAT_TYPE_UNSIGNED)
return GL_UNSIGNED_SHORT;
else
return GL_SHORT;
}
else {
assert( size <= 32 );
if (desc->channel[0].type == UTIL_FORMAT_TYPE_UNSIGNED)
return GL_UNSIGNED_INT;
else
return GL_INT;
}
}
}
else if (format == PIPE_FORMAT_UYVY) {
return GL_UNSIGNED_SHORT;
}
else if (format == PIPE_FORMAT_YUYV) {
return GL_UNSIGNED_SHORT;
}
else {
/* probably a compressed format, unsupported anyway */
return GL_NONE;
}
}
 
 
/**
* Translate Mesa format to Gallium format.
*/
enum pipe_format
st_mesa_format_to_pipe_format(gl_format mesaFormat)
{
switch (mesaFormat) {
case MESA_FORMAT_RGBA8888:
return PIPE_FORMAT_A8B8G8R8_UNORM;
case MESA_FORMAT_RGBA8888_REV:
return PIPE_FORMAT_R8G8B8A8_UNORM;
case MESA_FORMAT_ARGB8888:
return PIPE_FORMAT_B8G8R8A8_UNORM;
case MESA_FORMAT_ARGB8888_REV:
return PIPE_FORMAT_A8R8G8B8_UNORM;
case MESA_FORMAT_XRGB8888:
return PIPE_FORMAT_B8G8R8X8_UNORM;
case MESA_FORMAT_XRGB8888_REV:
return PIPE_FORMAT_X8R8G8B8_UNORM;
case MESA_FORMAT_ARGB1555:
return PIPE_FORMAT_B5G5R5A1_UNORM;
case MESA_FORMAT_ARGB4444:
return PIPE_FORMAT_B4G4R4A4_UNORM;
case MESA_FORMAT_RGB565:
return PIPE_FORMAT_B5G6R5_UNORM;
case MESA_FORMAT_AL88:
return PIPE_FORMAT_L8A8_UNORM;
case MESA_FORMAT_A8:
return PIPE_FORMAT_A8_UNORM;
case MESA_FORMAT_L8:
return PIPE_FORMAT_L8_UNORM;
case MESA_FORMAT_I8:
return PIPE_FORMAT_I8_UNORM;
case MESA_FORMAT_Z16:
return PIPE_FORMAT_Z16_UNORM;
case MESA_FORMAT_Z32:
return PIPE_FORMAT_Z32_UNORM;
case MESA_FORMAT_Z24_S8:
return PIPE_FORMAT_S8_USCALED_Z24_UNORM;
case MESA_FORMAT_S8_Z24:
return PIPE_FORMAT_Z24_UNORM_S8_USCALED;
case MESA_FORMAT_Z24_X8:
return PIPE_FORMAT_X8Z24_UNORM;
case MESA_FORMAT_X8_Z24:
return PIPE_FORMAT_Z24X8_UNORM;
case MESA_FORMAT_S8:
return PIPE_FORMAT_S8_USCALED;
case MESA_FORMAT_YCBCR:
return PIPE_FORMAT_UYVY;
#if FEATURE_texture_s3tc
case MESA_FORMAT_RGB_DXT1:
return PIPE_FORMAT_DXT1_RGB;
case MESA_FORMAT_RGBA_DXT1:
return PIPE_FORMAT_DXT1_RGBA;
case MESA_FORMAT_RGBA_DXT3:
return PIPE_FORMAT_DXT3_RGBA;
case MESA_FORMAT_RGBA_DXT5:
return PIPE_FORMAT_DXT5_RGBA;
#if FEATURE_EXT_texture_sRGB
case MESA_FORMAT_SRGB_DXT1:
return PIPE_FORMAT_DXT1_SRGB;
case MESA_FORMAT_SRGBA_DXT1:
return PIPE_FORMAT_DXT1_SRGBA;
case MESA_FORMAT_SRGBA_DXT3:
return PIPE_FORMAT_DXT3_SRGBA;
case MESA_FORMAT_SRGBA_DXT5:
return PIPE_FORMAT_DXT5_SRGBA;
#endif
#endif
#if FEATURE_EXT_texture_sRGB
case MESA_FORMAT_SLA8:
return PIPE_FORMAT_L8A8_SRGB;
case MESA_FORMAT_SL8:
return PIPE_FORMAT_L8_SRGB;
case MESA_FORMAT_SRGB8:
return PIPE_FORMAT_R8G8B8_SRGB;
case MESA_FORMAT_SRGBA8:
return PIPE_FORMAT_A8B8G8R8_SRGB;
case MESA_FORMAT_SARGB8:
return PIPE_FORMAT_B8G8R8A8_SRGB;
#endif
case MESA_FORMAT_R8:
return PIPE_FORMAT_R8_UNORM;
case MESA_FORMAT_R16:
return PIPE_FORMAT_R16_UNORM;
case MESA_FORMAT_RG88:
return PIPE_FORMAT_R8G8_UNORM;
case MESA_FORMAT_RG1616:
return PIPE_FORMAT_R16G16_UNORM;
case MESA_FORMAT_RGBA_16:
return PIPE_FORMAT_R16G16B16A16_UNORM;
 
/* signed int formats */
case MESA_FORMAT_RGBA_INT8:
return PIPE_FORMAT_R8G8B8A8_SSCALED;
case MESA_FORMAT_RGBA_INT16:
return PIPE_FORMAT_R16G16B16A16_SSCALED;
case MESA_FORMAT_RGBA_INT32:
return PIPE_FORMAT_R32G32B32A32_SSCALED;
 
/* unsigned int formats */
case MESA_FORMAT_RGBA_UINT8:
return PIPE_FORMAT_R8G8B8A8_USCALED;
case MESA_FORMAT_RGBA_UINT16:
return PIPE_FORMAT_R16G16B16A16_USCALED;
case MESA_FORMAT_RGBA_UINT32:
return PIPE_FORMAT_R32G32B32A32_USCALED;
 
default:
assert(0);
return PIPE_FORMAT_NONE;
}
}
 
 
/**
* Translate Gallium format to Mesa format.
*/
gl_format
st_pipe_format_to_mesa_format(enum pipe_format format)
{
switch (format) {
case PIPE_FORMAT_A8B8G8R8_UNORM:
return MESA_FORMAT_RGBA8888;
case PIPE_FORMAT_R8G8B8A8_UNORM:
return MESA_FORMAT_RGBA8888_REV;
case PIPE_FORMAT_B8G8R8A8_UNORM:
return MESA_FORMAT_ARGB8888;
case PIPE_FORMAT_A8R8G8B8_UNORM:
return MESA_FORMAT_ARGB8888_REV;
case PIPE_FORMAT_B8G8R8X8_UNORM:
return MESA_FORMAT_XRGB8888;
case PIPE_FORMAT_X8R8G8B8_UNORM:
return MESA_FORMAT_XRGB8888_REV;
case PIPE_FORMAT_B5G5R5A1_UNORM:
return MESA_FORMAT_ARGB1555;
case PIPE_FORMAT_B4G4R4A4_UNORM:
return MESA_FORMAT_ARGB4444;
case PIPE_FORMAT_B5G6R5_UNORM:
return MESA_FORMAT_RGB565;
case PIPE_FORMAT_L8A8_UNORM:
return MESA_FORMAT_AL88;
case PIPE_FORMAT_A8_UNORM:
return MESA_FORMAT_A8;
case PIPE_FORMAT_L8_UNORM:
return MESA_FORMAT_L8;
case PIPE_FORMAT_I8_UNORM:
return MESA_FORMAT_I8;
case PIPE_FORMAT_S8_USCALED:
return MESA_FORMAT_S8;
 
case PIPE_FORMAT_R16G16B16A16_UNORM:
return MESA_FORMAT_RGBA_16;
case PIPE_FORMAT_R16G16B16A16_SNORM:
return MESA_FORMAT_SIGNED_RGBA_16;
 
case PIPE_FORMAT_Z16_UNORM:
return MESA_FORMAT_Z16;
case PIPE_FORMAT_Z32_UNORM:
return MESA_FORMAT_Z32;
case PIPE_FORMAT_S8_USCALED_Z24_UNORM:
return MESA_FORMAT_Z24_S8;
case PIPE_FORMAT_X8Z24_UNORM:
return MESA_FORMAT_Z24_X8;
case PIPE_FORMAT_Z24X8_UNORM:
return MESA_FORMAT_X8_Z24;
case PIPE_FORMAT_Z24_UNORM_S8_USCALED:
return MESA_FORMAT_S8_Z24;
 
case PIPE_FORMAT_UYVY:
return MESA_FORMAT_YCBCR;
case PIPE_FORMAT_YUYV:
return MESA_FORMAT_YCBCR_REV;
 
#if FEATURE_texture_s3tc
case PIPE_FORMAT_DXT1_RGB:
return MESA_FORMAT_RGB_DXT1;
case PIPE_FORMAT_DXT1_RGBA:
return MESA_FORMAT_RGBA_DXT1;
case PIPE_FORMAT_DXT3_RGBA:
return MESA_FORMAT_RGBA_DXT3;
case PIPE_FORMAT_DXT5_RGBA:
return MESA_FORMAT_RGBA_DXT5;
#if FEATURE_EXT_texture_sRGB
case PIPE_FORMAT_DXT1_SRGB:
return MESA_FORMAT_SRGB_DXT1;
case PIPE_FORMAT_DXT1_SRGBA:
return MESA_FORMAT_SRGBA_DXT1;
case PIPE_FORMAT_DXT3_SRGBA:
return MESA_FORMAT_SRGBA_DXT3;
case PIPE_FORMAT_DXT5_SRGBA:
return MESA_FORMAT_SRGBA_DXT5;
#endif
#endif
 
#if FEATURE_EXT_texture_sRGB
case PIPE_FORMAT_L8A8_SRGB:
return MESA_FORMAT_SLA8;
case PIPE_FORMAT_L8_SRGB:
return MESA_FORMAT_SL8;
case PIPE_FORMAT_R8G8B8_SRGB:
return MESA_FORMAT_SRGB8;
case PIPE_FORMAT_A8B8G8R8_SRGB:
return MESA_FORMAT_SRGBA8;
case PIPE_FORMAT_B8G8R8A8_SRGB:
return MESA_FORMAT_SARGB8;
#endif
 
case PIPE_FORMAT_R8_UNORM:
return MESA_FORMAT_R8;
case PIPE_FORMAT_R16_UNORM:
return MESA_FORMAT_R16;
case PIPE_FORMAT_R8G8_UNORM:
return MESA_FORMAT_RG88;
case PIPE_FORMAT_R16G16_UNORM:
return MESA_FORMAT_RG1616;
 
/* signed int formats */
case PIPE_FORMAT_R8G8B8A8_SSCALED:
return MESA_FORMAT_RGBA_INT8;
case PIPE_FORMAT_R16G16B16A16_SSCALED:
return MESA_FORMAT_RGBA_INT16;
case PIPE_FORMAT_R32G32B32A32_SSCALED:
return MESA_FORMAT_RGBA_INT32;
 
/* unsigned int formats */
case PIPE_FORMAT_R8G8B8A8_USCALED:
return MESA_FORMAT_RGBA_UINT8;
case PIPE_FORMAT_R16G16B16A16_USCALED:
return MESA_FORMAT_RGBA_UINT16;
case PIPE_FORMAT_R32G32B32A32_USCALED:
return MESA_FORMAT_RGBA_UINT32;
 
default:
assert(0);
return MESA_FORMAT_NONE;
}
}
 
 
/**
* Return first supported format from the given list.
*/
static enum pipe_format
find_supported_format(struct pipe_screen *screen,
const enum pipe_format formats[],
uint num_formats,
enum pipe_texture_target target,
unsigned sample_count,
unsigned tex_usage,
unsigned geom_flags)
{
uint i;
for (i = 0; i < num_formats; i++) {
if (screen->is_format_supported(screen, formats[i], target,
sample_count, tex_usage, geom_flags)) {
return formats[i];
}
}
return PIPE_FORMAT_NONE;
}
 
 
/**
* Find an RGBA format supported by the context/winsys.
*/
static enum pipe_format
default_rgba_format(struct pipe_screen *screen,
enum pipe_texture_target target,
unsigned sample_count,
unsigned tex_usage,
unsigned geom_flags)
{
static const enum pipe_format colorFormats[] = {
PIPE_FORMAT_B8G8R8A8_UNORM,
PIPE_FORMAT_A8R8G8B8_UNORM,
PIPE_FORMAT_A8B8G8R8_UNORM,
PIPE_FORMAT_B5G6R5_UNORM
};
return find_supported_format(screen, colorFormats, Elements(colorFormats),
target, sample_count, tex_usage, geom_flags);
}
 
 
/**
* Find an RGB format supported by the context/winsys.
*/
static enum pipe_format
default_rgb_format(struct pipe_screen *screen,
enum pipe_texture_target target,
unsigned sample_count,
unsigned tex_usage,
unsigned geom_flags)
{
static const enum pipe_format colorFormats[] = {
PIPE_FORMAT_B8G8R8X8_UNORM,
PIPE_FORMAT_X8R8G8B8_UNORM,
PIPE_FORMAT_X8B8G8R8_UNORM,
PIPE_FORMAT_B8G8R8A8_UNORM,
PIPE_FORMAT_A8R8G8B8_UNORM,
PIPE_FORMAT_A8B8G8R8_UNORM,
PIPE_FORMAT_B5G6R5_UNORM
};
return find_supported_format(screen, colorFormats, Elements(colorFormats),
target, sample_count, tex_usage, geom_flags);
}
 
/**
* Find an sRGBA format supported by the context/winsys.
*/
static enum pipe_format
default_srgba_format(struct pipe_screen *screen,
enum pipe_texture_target target,
unsigned sample_count,
unsigned tex_usage,
unsigned geom_flags)
{
static const enum pipe_format colorFormats[] = {
PIPE_FORMAT_B8G8R8A8_SRGB,
PIPE_FORMAT_A8R8G8B8_SRGB,
PIPE_FORMAT_A8B8G8R8_SRGB,
};
return find_supported_format(screen, colorFormats, Elements(colorFormats),
target, sample_count, tex_usage, geom_flags);
}
 
 
/**
* Given an OpenGL internalFormat value for a texture or surface, return
* the best matching PIPE_FORMAT_x, or PIPE_FORMAT_NONE if there's no match.
* This is called during glTexImage2D, for example.
*
* The bindings parameter typically has PIPE_BIND_SAMPLER_VIEW set, plus
* either PIPE_BINDING_RENDER_TARGET or PIPE_BINDING_DEPTH_STENCIL if
* we want render-to-texture ability.
*
* \param internalFormat the user value passed to glTexImage2D
* \param target one of PIPE_TEXTURE_x
* \param bindings bitmask of PIPE_BIND_x flags.
*/
enum pipe_format
st_choose_format(struct pipe_screen *screen, GLenum internalFormat,
enum pipe_texture_target target, unsigned sample_count,
unsigned bindings)
{
unsigned geom_flags = 0; /* we don't care about POT vs. NPOT here, yet */
 
switch (internalFormat) {
case 4:
case GL_RGBA:
case GL_RGBA8:
case GL_RGB10_A2:
return default_rgba_format( screen, target, sample_count, bindings,
geom_flags );
 
case 3:
case GL_RGB:
return default_rgb_format( screen, target, sample_count, bindings,
geom_flags );
case GL_RGBA12:
case GL_RGBA16:
if (screen->is_format_supported( screen, PIPE_FORMAT_R16G16B16A16_UNORM,
target, sample_count, bindings,
geom_flags ))
return PIPE_FORMAT_R16G16B16A16_UNORM;
return default_rgba_format( screen, target, sample_count, bindings,
geom_flags );
 
case GL_RGBA4:
case GL_RGBA2:
if (screen->is_format_supported( screen, PIPE_FORMAT_B4G4R4A4_UNORM,
target, sample_count, bindings,
geom_flags ))
return PIPE_FORMAT_B4G4R4A4_UNORM;
return default_rgba_format( screen, target, sample_count, bindings,
geom_flags );
 
case GL_RGB5_A1:
if (screen->is_format_supported( screen, PIPE_FORMAT_B5G5R5A1_UNORM,
target, sample_count, bindings,
geom_flags ))
return PIPE_FORMAT_B5G5R5A1_UNORM;
return default_rgba_format( screen, target, sample_count, bindings,
geom_flags );
 
case GL_RGB8:
case GL_RGB10:
case GL_RGB12:
case GL_RGB16:
return default_rgb_format( screen, target, sample_count, bindings,
geom_flags );
 
case GL_RGB5:
case GL_RGB4:
case GL_R3_G3_B2:
if (screen->is_format_supported( screen, PIPE_FORMAT_B5G6R5_UNORM,
target, sample_count, bindings,
geom_flags ))
return PIPE_FORMAT_B5G6R5_UNORM;
if (screen->is_format_supported( screen, PIPE_FORMAT_B5G5R5A1_UNORM,
target, sample_count, bindings,
geom_flags ))
return PIPE_FORMAT_B5G5R5A1_UNORM;
return default_rgba_format( screen, target, sample_count, bindings,
geom_flags );
 
case GL_ALPHA:
case GL_ALPHA4:
case GL_ALPHA8:
case GL_ALPHA12:
case GL_ALPHA16:
case GL_COMPRESSED_ALPHA:
if (screen->is_format_supported( screen, PIPE_FORMAT_A8_UNORM, target,
sample_count, bindings, geom_flags ))
return PIPE_FORMAT_A8_UNORM;
return default_rgba_format( screen, target, sample_count, bindings,
geom_flags );
 
case 1:
case GL_LUMINANCE:
case GL_LUMINANCE4:
case GL_LUMINANCE8:
case GL_LUMINANCE12:
case GL_LUMINANCE16:
case GL_COMPRESSED_LUMINANCE:
if (screen->is_format_supported( screen, PIPE_FORMAT_L8_UNORM, target,
sample_count, bindings, geom_flags ))
return PIPE_FORMAT_L8_UNORM;
return default_rgba_format( screen, target, sample_count, bindings,
geom_flags );
 
case 2:
case GL_LUMINANCE_ALPHA:
case GL_LUMINANCE4_ALPHA4:
case GL_LUMINANCE6_ALPHA2:
case GL_LUMINANCE8_ALPHA8:
case GL_LUMINANCE12_ALPHA4:
case GL_LUMINANCE12_ALPHA12:
case GL_LUMINANCE16_ALPHA16:
case GL_COMPRESSED_LUMINANCE_ALPHA:
if (screen->is_format_supported( screen, PIPE_FORMAT_L8A8_UNORM, target,
sample_count, bindings, geom_flags ))
return PIPE_FORMAT_L8A8_UNORM;
return default_rgba_format( screen, target, sample_count, bindings,
geom_flags );
 
case GL_INTENSITY:
case GL_INTENSITY4:
case GL_INTENSITY8:
case GL_INTENSITY12:
case GL_INTENSITY16:
case GL_COMPRESSED_INTENSITY:
if (screen->is_format_supported( screen, PIPE_FORMAT_I8_UNORM, target,
sample_count, bindings, geom_flags ))
return PIPE_FORMAT_I8_UNORM;
return default_rgba_format( screen, target, sample_count, bindings,
geom_flags );
 
case GL_YCBCR_MESA:
if (screen->is_format_supported(screen, PIPE_FORMAT_UYVY, target,
sample_count, bindings, geom_flags)) {
return PIPE_FORMAT_UYVY;
}
if (screen->is_format_supported(screen, PIPE_FORMAT_YUYV, target,
sample_count, bindings, geom_flags)) {
return PIPE_FORMAT_YUYV;
}
return PIPE_FORMAT_NONE;
 
case GL_COMPRESSED_RED:
case GL_COMPRESSED_RG:
case GL_COMPRESSED_RGB:
/* can only sample from compressed formats */
if (bindings & ~PIPE_BIND_SAMPLER_VIEW)
return PIPE_FORMAT_NONE;
else if (screen->is_format_supported(screen, PIPE_FORMAT_DXT1_RGB,
target, sample_count, bindings,
geom_flags))
return PIPE_FORMAT_DXT1_RGB;
else
return default_rgb_format(screen, target, sample_count, bindings,
geom_flags);
 
case GL_COMPRESSED_RGBA:
/* can only sample from compressed formats */
if (bindings & ~PIPE_BIND_SAMPLER_VIEW)
return PIPE_FORMAT_NONE;
else if (screen->is_format_supported(screen, PIPE_FORMAT_DXT3_RGBA,
target, sample_count, bindings,
geom_flags))
return PIPE_FORMAT_DXT3_RGBA;
else
return default_rgba_format(screen, target, sample_count, bindings,
geom_flags);
 
case GL_RGB_S3TC:
case GL_RGB4_S3TC:
case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
if (screen->is_format_supported(screen, PIPE_FORMAT_DXT1_RGB,
target, sample_count, bindings,
geom_flags))
return PIPE_FORMAT_DXT1_RGB;
else
return PIPE_FORMAT_NONE;
 
case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
if (screen->is_format_supported(screen, PIPE_FORMAT_DXT1_RGBA,
target, sample_count, bindings,
geom_flags))
return PIPE_FORMAT_DXT1_RGBA;
else
return PIPE_FORMAT_NONE;
 
case GL_RGBA_S3TC:
case GL_RGBA4_S3TC:
case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
if (screen->is_format_supported(screen, PIPE_FORMAT_DXT3_RGBA,
target, sample_count, bindings,
geom_flags))
return PIPE_FORMAT_DXT3_RGBA;
else
return PIPE_FORMAT_NONE;
 
case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
if (screen->is_format_supported(screen, PIPE_FORMAT_DXT5_RGBA,
target, sample_count, bindings,
geom_flags))
return PIPE_FORMAT_DXT5_RGBA;
else
return PIPE_FORMAT_NONE;
 
#if 0
case GL_COMPRESSED_RGB_FXT1_3DFX:
return PIPE_FORMAT_RGB_FXT1;
case GL_COMPRESSED_RGBA_FXT1_3DFX:
return PIPE_FORMAT_RGB_FXT1;
#endif
 
case GL_DEPTH_COMPONENT16:
if (screen->is_format_supported(screen, PIPE_FORMAT_Z16_UNORM, target,
sample_count, bindings, geom_flags))
return PIPE_FORMAT_Z16_UNORM;
/* fall-through */
case GL_DEPTH_COMPONENT24:
if (screen->is_format_supported(screen, PIPE_FORMAT_Z24_UNORM_S8_USCALED,
target, sample_count, bindings, geom_flags))
return PIPE_FORMAT_Z24_UNORM_S8_USCALED;
if (screen->is_format_supported(screen, PIPE_FORMAT_S8_USCALED_Z24_UNORM,
target, sample_count, bindings, geom_flags))
return PIPE_FORMAT_S8_USCALED_Z24_UNORM;
/* fall-through */
case GL_DEPTH_COMPONENT32:
if (screen->is_format_supported(screen, PIPE_FORMAT_Z32_UNORM, target,
sample_count, bindings, geom_flags))
return PIPE_FORMAT_Z32_UNORM;
/* fall-through */
case GL_DEPTH_COMPONENT:
{
static const enum pipe_format formats[] = {
PIPE_FORMAT_Z16_UNORM,
PIPE_FORMAT_Z32_UNORM,
PIPE_FORMAT_Z24_UNORM_S8_USCALED,
PIPE_FORMAT_S8_USCALED_Z24_UNORM
};
return find_supported_format(screen, formats, Elements(formats),
target, sample_count, bindings, geom_flags);
}
 
case GL_STENCIL_INDEX:
case GL_STENCIL_INDEX1_EXT:
case GL_STENCIL_INDEX4_EXT:
case GL_STENCIL_INDEX8_EXT:
case GL_STENCIL_INDEX16_EXT:
{
static const enum pipe_format formats[] = {
PIPE_FORMAT_S8_USCALED,
PIPE_FORMAT_Z24_UNORM_S8_USCALED,
PIPE_FORMAT_S8_USCALED_Z24_UNORM
};
return find_supported_format(screen, formats, Elements(formats),
target, sample_count, bindings, geom_flags);
}
 
case GL_DEPTH_STENCIL_EXT:
case GL_DEPTH24_STENCIL8_EXT:
{
static const enum pipe_format formats[] = {
PIPE_FORMAT_Z24_UNORM_S8_USCALED,
PIPE_FORMAT_S8_USCALED_Z24_UNORM
};
return find_supported_format(screen, formats, Elements(formats),
target, sample_count, bindings, geom_flags);
}
 
case GL_SRGB_EXT:
case GL_SRGB8_EXT:
case GL_COMPRESSED_SRGB_EXT:
case GL_COMPRESSED_SRGB_ALPHA_EXT:
case GL_SRGB_ALPHA_EXT:
case GL_SRGB8_ALPHA8_EXT:
return default_srgba_format( screen, target, sample_count, bindings,
geom_flags );
case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT:
return PIPE_FORMAT_DXT1_SRGB;
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
return PIPE_FORMAT_DXT1_SRGBA;
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT:
return PIPE_FORMAT_DXT3_SRGBA;
case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
return PIPE_FORMAT_DXT5_SRGBA;
 
case GL_SLUMINANCE_ALPHA_EXT:
case GL_SLUMINANCE8_ALPHA8_EXT:
case GL_COMPRESSED_SLUMINANCE_EXT:
case GL_COMPRESSED_SLUMINANCE_ALPHA_EXT:
if (screen->is_format_supported(screen, PIPE_FORMAT_L8A8_SRGB, target,
sample_count, bindings, geom_flags))
return PIPE_FORMAT_L8A8_SRGB;
return default_srgba_format( screen, target, sample_count, bindings,
geom_flags );
 
case GL_SLUMINANCE_EXT:
case GL_SLUMINANCE8_EXT:
if (screen->is_format_supported(screen, PIPE_FORMAT_L8_SRGB, target,
sample_count, bindings, geom_flags))
return PIPE_FORMAT_L8_SRGB;
return default_srgba_format( screen, target, sample_count, bindings,
geom_flags );
 
case GL_RED:
case GL_R8:
if (screen->is_format_supported(screen, PIPE_FORMAT_R8_UNORM, target,
sample_count, bindings, geom_flags))
return PIPE_FORMAT_R8_UNORM;
return PIPE_FORMAT_NONE;
case GL_RG:
case GL_RG8:
if (screen->is_format_supported(screen, PIPE_FORMAT_R8G8_UNORM, target,
sample_count, bindings, geom_flags))
return PIPE_FORMAT_R8G8_UNORM;
return PIPE_FORMAT_NONE;
 
case GL_R16:
if (screen->is_format_supported(screen, PIPE_FORMAT_R16_UNORM, target,
sample_count, bindings, geom_flags))
return PIPE_FORMAT_R16_UNORM;
return PIPE_FORMAT_NONE;
 
case GL_RG16:
if (screen->is_format_supported(screen, PIPE_FORMAT_R16G16_UNORM, target,
sample_count, bindings, geom_flags))
return PIPE_FORMAT_R16G16_UNORM;
return PIPE_FORMAT_NONE;
 
case GL_COMPRESSED_RED_RGTC1:
if (screen->is_format_supported(screen, PIPE_FORMAT_RGTC1_UNORM, target,
sample_count, bindings, geom_flags))
return PIPE_FORMAT_RGTC1_UNORM;
return PIPE_FORMAT_NONE;
 
case GL_COMPRESSED_SIGNED_RED_RGTC1:
if (screen->is_format_supported(screen, PIPE_FORMAT_RGTC1_SNORM, target,
sample_count, bindings, geom_flags))
return PIPE_FORMAT_RGTC1_SNORM;
return PIPE_FORMAT_NONE;
 
case GL_COMPRESSED_RG_RGTC2:
if (screen->is_format_supported(screen, PIPE_FORMAT_RGTC2_UNORM, target,
sample_count, bindings, geom_flags))
return PIPE_FORMAT_RGTC2_UNORM;
return PIPE_FORMAT_NONE;
 
case GL_COMPRESSED_SIGNED_RG_RGTC2:
if (screen->is_format_supported(screen, PIPE_FORMAT_RGTC2_SNORM, target,
sample_count, bindings, geom_flags))
return PIPE_FORMAT_RGTC2_SNORM;
return PIPE_FORMAT_NONE;
 
/* signed/unsigned integer formats.
* XXX Mesa only has formats for RGBA signed/unsigned integer formats.
* If/when new formats are added this code should be updated.
*/
case GL_RED_INTEGER_EXT:
case GL_GREEN_INTEGER_EXT:
case GL_BLUE_INTEGER_EXT:
case GL_ALPHA_INTEGER_EXT:
case GL_RGB_INTEGER_EXT:
case GL_RGBA_INTEGER_EXT:
case GL_BGR_INTEGER_EXT:
case GL_BGRA_INTEGER_EXT:
case GL_LUMINANCE_INTEGER_EXT:
case GL_LUMINANCE_ALPHA_INTEGER_EXT:
/* fall-through */
case GL_RGBA8I_EXT:
case GL_RGB8I_EXT:
case GL_ALPHA8I_EXT:
case GL_INTENSITY8I_EXT:
case GL_LUMINANCE8I_EXT:
case GL_LUMINANCE_ALPHA8I_EXT:
if (screen->is_format_supported(screen, PIPE_FORMAT_R8G8B8A8_SSCALED,
target,
sample_count, bindings, geom_flags))
return PIPE_FORMAT_R8G8B8A8_SSCALED;
return PIPE_FORMAT_NONE;
case GL_RGBA16I_EXT:
case GL_RGB16I_EXT:
case GL_ALPHA16I_EXT:
case GL_INTENSITY16I_EXT:
case GL_LUMINANCE16I_EXT:
case GL_LUMINANCE_ALPHA16I_EXT:
if (screen->is_format_supported(screen, PIPE_FORMAT_R16G16B16A16_SSCALED,
target,
sample_count, bindings, geom_flags))
return PIPE_FORMAT_R16G16B16A16_SSCALED;
return PIPE_FORMAT_NONE;
case GL_RGBA32I_EXT:
case GL_RGB32I_EXT:
case GL_ALPHA32I_EXT:
case GL_INTENSITY32I_EXT:
case GL_LUMINANCE32I_EXT:
case GL_LUMINANCE_ALPHA32I_EXT:
/* xxx */
if (screen->is_format_supported(screen, PIPE_FORMAT_R32G32B32A32_SSCALED,
target,
sample_count, bindings, geom_flags))
return PIPE_FORMAT_R32G32B32A32_SSCALED;
return PIPE_FORMAT_NONE;
 
case GL_RGBA8UI_EXT:
case GL_RGB8UI_EXT:
case GL_ALPHA8UI_EXT:
case GL_INTENSITY8UI_EXT:
case GL_LUMINANCE8UI_EXT:
case GL_LUMINANCE_ALPHA8UI_EXT:
if (screen->is_format_supported(screen, PIPE_FORMAT_R8G8B8A8_USCALED,
target,
sample_count, bindings, geom_flags))
return PIPE_FORMAT_R8G8B8A8_USCALED;
return PIPE_FORMAT_NONE;
 
case GL_RGBA16UI_EXT:
case GL_RGB16UI_EXT:
case GL_ALPHA16UI_EXT:
case GL_INTENSITY16UI_EXT:
case GL_LUMINANCE16UI_EXT:
case GL_LUMINANCE_ALPHA16UI_EXT:
if (screen->is_format_supported(screen, PIPE_FORMAT_R16G16B16A16_USCALED,
target,
sample_count, bindings, geom_flags))
return PIPE_FORMAT_R16G16B16A16_USCALED;
return PIPE_FORMAT_NONE;
 
case GL_RGBA32UI_EXT:
case GL_RGB32UI_EXT:
case GL_ALPHA32UI_EXT:
case GL_INTENSITY32UI_EXT:
case GL_LUMINANCE32UI_EXT:
case GL_LUMINANCE_ALPHA32UI_EXT:
if (screen->is_format_supported(screen, PIPE_FORMAT_R32G32B32A32_USCALED,
target,
sample_count, bindings, geom_flags))
return PIPE_FORMAT_R32G32B32A32_USCALED;
return PIPE_FORMAT_NONE;
 
default:
return PIPE_FORMAT_NONE;
}
}
 
 
/**
* Called by FBO code to choose a PIPE_FORMAT_ for drawing surfaces.
*/
enum pipe_format
st_choose_renderbuffer_format(struct pipe_screen *screen,
GLenum internalFormat, unsigned sample_count)
{
uint usage;
if (_mesa_is_depth_or_stencil_format(internalFormat))
usage = PIPE_BIND_DEPTH_STENCIL;
else
usage = PIPE_BIND_RENDER_TARGET;
return st_choose_format(screen, internalFormat, PIPE_TEXTURE_2D,
sample_count, usage);
}
 
 
/**
* Called via ctx->Driver.chooseTextureFormat().
*/
gl_format
st_ChooseTextureFormat_renderable(struct gl_context *ctx, GLint internalFormat,
GLenum format, GLenum type, GLboolean renderable)
{
struct pipe_screen *screen = st_context(ctx)->pipe->screen;
enum pipe_format pFormat;
uint bindings;
 
(void) format;
(void) type;
 
/* GL textures may wind up being render targets, but we don't know
* that in advance. Specify potential render target flags now.
*/
bindings = PIPE_BIND_SAMPLER_VIEW;
if (renderable == GL_TRUE) {
if (_mesa_is_depth_format(internalFormat) ||
_mesa_is_depth_or_stencil_format(internalFormat))
bindings |= PIPE_BIND_DEPTH_STENCIL;
else
bindings |= PIPE_BIND_RENDER_TARGET;
}
 
pFormat = st_choose_format(screen, internalFormat,
PIPE_TEXTURE_2D, 0, bindings);
 
if (pFormat == PIPE_FORMAT_NONE) {
/* try choosing format again, this time without render target bindings */
pFormat = st_choose_format(screen, internalFormat,
PIPE_TEXTURE_2D, 0, PIPE_BIND_SAMPLER_VIEW);
}
 
if (pFormat == PIPE_FORMAT_NONE) {
/* no luck at all */
return MESA_FORMAT_NONE;
}
 
return st_pipe_format_to_mesa_format(pFormat);
}
 
gl_format
st_ChooseTextureFormat(struct gl_context *ctx, GLint internalFormat,
GLenum format, GLenum type)
{
return st_ChooseTextureFormat_renderable(ctx, internalFormat,
format, type, GL_TRUE);
}
 
/**
* Test if a gallium format is equivalent to a GL format/type.
*/
GLboolean
st_equal_formats(enum pipe_format pFormat, GLenum format, GLenum type)
{
switch (pFormat) {
case PIPE_FORMAT_A8B8G8R8_UNORM:
return format == GL_RGBA && type == GL_UNSIGNED_BYTE;
case PIPE_FORMAT_A8R8G8B8_UNORM:
return format == GL_BGRA && type == GL_UNSIGNED_BYTE;
case PIPE_FORMAT_B5G6R5_UNORM:
return format == GL_RGB && type == GL_UNSIGNED_SHORT_5_6_5;
/* XXX more combos... */
default:
return GL_FALSE;
}
}
 
GLboolean
st_sampler_compat_formats(enum pipe_format format1, enum pipe_format format2)
{
if (format1 == format2)
return GL_TRUE;
 
if (format1 == PIPE_FORMAT_B8G8R8A8_UNORM &&
format2 == PIPE_FORMAT_B8G8R8X8_UNORM)
return GL_TRUE;
 
if (format1 == PIPE_FORMAT_B8G8R8X8_UNORM &&
format2 == PIPE_FORMAT_B8G8R8A8_UNORM)
return GL_TRUE;
 
if (format1 == PIPE_FORMAT_A8B8G8R8_UNORM &&
format2 == PIPE_FORMAT_X8B8G8R8_UNORM)
return GL_TRUE;
 
if (format1 == PIPE_FORMAT_X8B8G8R8_UNORM &&
format2 == PIPE_FORMAT_A8B8G8R8_UNORM)
return GL_TRUE;
 
if (format1 == PIPE_FORMAT_A8R8G8B8_UNORM &&
format2 == PIPE_FORMAT_X8R8G8B8_UNORM)
return GL_TRUE;
 
if (format1 == PIPE_FORMAT_X8R8G8B8_UNORM &&
format2 == PIPE_FORMAT_A8R8G8B8_UNORM)
return GL_TRUE;
 
return GL_FALSE;
}
 
 
 
/**
* This is used for translating texture border color and the clear
* color. For example, the clear color is interpreted according to
* the renderbuffer's base format. For example, if clearing a
* GL_LUMINANCE buffer, ClearColor[0] = luminance and ClearColor[1] =
* alpha. Similarly for texture border colors.
*/
void
st_translate_color(const GLfloat colorIn[4], GLenum baseFormat,
GLfloat colorOut[4])
{
switch (baseFormat) {
case GL_RED:
colorOut[0] = colorIn[0];
colorOut[1] = 0.0F;
colorOut[2] = 0.0F;
colorOut[3] = 1.0F;
break;
case GL_RG:
colorOut[0] = colorIn[0];
colorOut[1] = colorIn[1];
colorOut[2] = 0.0F;
colorOut[3] = 1.0F;
break;
case GL_RGB:
colorOut[0] = colorIn[0];
colorOut[1] = colorIn[1];
colorOut[2] = colorIn[2];
colorOut[3] = 1.0F;
break;
case GL_ALPHA:
colorOut[0] = colorOut[1] = colorOut[2] = 0.0;
colorOut[3] = colorIn[3];
break;
case GL_LUMINANCE:
colorOut[0] = colorOut[1] = colorOut[2] = colorIn[0];
colorOut[3] = 1.0;
break;
case GL_LUMINANCE_ALPHA:
colorOut[0] = colorOut[1] = colorOut[2] = colorIn[0];
colorOut[3] = colorIn[3];
break;
case GL_INTENSITY:
colorOut[0] = colorOut[1] = colorOut[2] = colorOut[3] = colorIn[0];
break;
default:
COPY_4V(colorOut, colorIn);
}
}
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_format.h
0,0 → 1,85
/**************************************************************************
*
* Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
* Copyright (c) 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 ST_FORMAT_H
#define ST_FORMAT_H
 
#include "main/formats.h"
#include "main/mtypes.h"
 
#include "pipe/p_defines.h"
#include "pipe/p_format.h"
 
struct pipe_screen;
 
extern GLenum
st_format_datatype(enum pipe_format format);
 
 
extern enum pipe_format
st_mesa_format_to_pipe_format(gl_format mesaFormat);
 
extern gl_format
st_pipe_format_to_mesa_format(enum pipe_format pipeFormat);
 
 
extern enum pipe_format
st_choose_format(struct pipe_screen *screen, GLenum internalFormat,
enum pipe_texture_target target, unsigned sample_count,
unsigned tex_usage);
 
extern enum pipe_format
st_choose_renderbuffer_format(struct pipe_screen *screen,
GLenum internalFormat, unsigned sample_count);
 
 
gl_format
st_ChooseTextureFormat_renderable(struct gl_context *ctx, GLint internalFormat,
GLenum format, GLenum type, GLboolean renderable);
 
extern gl_format
st_ChooseTextureFormat(struct gl_context * ctx, GLint internalFormat,
GLenum format, GLenum type);
 
 
extern GLboolean
st_equal_formats(enum pipe_format pFormat, GLenum format, GLenum type);
 
/* can we use a sampler view to translate these formats
only used to make TFP so far */
extern GLboolean
st_sampler_compat_formats(enum pipe_format format1, enum pipe_format format2);
 
 
extern void
st_translate_color(const GLfloat colorIn[4], GLenum baseFormat,
GLfloat colorOut[4]);
 
 
#endif /* ST_FORMAT_H */
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_gen_mipmap.c
0,0 → 1,423
/**************************************************************************
*
* 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 "main/imports.h"
#include "main/mipmap.h"
#include "main/teximage.h"
 
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "util/u_inlines.h"
#include "util/u_format.h"
#include "util/u_gen_mipmap.h"
 
#include "st_debug.h"
#include "st_context.h"
#include "st_texture.h"
#include "st_gen_mipmap.h"
#include "st_cb_texture.h"
 
 
/**
* one-time init for generate mipmap
* XXX Note: there may be other times we need no-op/simple state like this.
* In that case, some code refactoring would be good.
*/
void
st_init_generate_mipmap(struct st_context *st)
{
st->gen_mipmap = util_create_gen_mipmap(st->pipe, st->cso_context);
}
 
 
void
st_destroy_generate_mipmap(struct st_context *st)
{
util_destroy_gen_mipmap(st->gen_mipmap);
st->gen_mipmap = NULL;
}
 
 
/**
* Generate mipmap levels using hardware rendering.
* \return TRUE if successful, FALSE if not possible
*/
static boolean
st_render_mipmap(struct st_context *st,
GLenum target,
struct st_texture_object *stObj,
uint baseLevel, uint lastLevel)
{
struct pipe_context *pipe = st->pipe;
struct pipe_screen *screen = pipe->screen;
struct pipe_sampler_view *psv = st_get_texture_sampler_view(stObj, pipe);
const uint face = _mesa_tex_target_to_face(target);
 
assert(psv->texture == stObj->pt);
#if 0
assert(target != GL_TEXTURE_3D); /* implemented but untested */
#endif
 
/* check if we can render in the texture's format */
/* XXX should probably kill this and always use util_gen_mipmap
since this implements a sw fallback as well */
if (!screen->is_format_supported(screen, psv->format, psv->texture->target,
0, PIPE_BIND_RENDER_TARGET, 0)) {
return FALSE;
}
 
util_gen_mipmap(st->gen_mipmap, psv, face, baseLevel, lastLevel,
PIPE_TEX_FILTER_LINEAR);
 
return TRUE;
}
 
 
/**
* Helper function to decompress an image. The result is a 32-bpp RGBA
* image with stride==width.
*/
static void
decompress_image(enum pipe_format format,
const uint8_t *src, uint8_t *dst,
unsigned width, unsigned height)
{
const struct util_format_description *desc = util_format_description(format);
const uint bw = util_format_get_blockwidth(format);
const uint bh = util_format_get_blockheight(format);
const uint dst_stride = 4 * MAX2(width, bw);
const uint src_stride = util_format_get_stride(format, width);
 
desc->unpack_rgba_8unorm(dst, dst_stride, src, src_stride, width, height);
 
if (width < bw || height < bh) {
/* We're decompressing an image smaller than the compression
* block size. We don't want garbage pixel values in the region
* outside (width x height) so replicate pixels from the (width
* x height) region to fill out the (bw x bh) block size.
*/
uint x, y;
for (y = 0; y < bh; y++) {
for (x = 0; x < bw; x++) {
if (x >= width || y >= height) {
uint p = (y * bw + x) * 4;
dst[p + 0] = dst[0];
dst[p + 1] = dst[1];
dst[p + 2] = dst[2];
dst[p + 3] = dst[3];
}
}
}
}
}
 
 
/**
* Helper function to compress an image. The source is a 32-bpp RGBA image
* with stride==width.
*/
static void
compress_image(enum pipe_format format,
const uint8_t *src, uint8_t *dst,
unsigned width, unsigned height)
{
const struct util_format_description *desc = util_format_description(format);
const uint dst_stride = util_format_get_stride(format, width);
const uint src_stride = 4 * width;
 
desc->pack_rgba_8unorm(dst, dst_stride, src, src_stride, width, height);
}
 
 
/**
* Software fallback for generate mipmap levels.
*/
static void
fallback_generate_mipmap(struct gl_context *ctx, GLenum target,
struct gl_texture_object *texObj)
{
struct pipe_context *pipe = st_context(ctx)->pipe;
struct pipe_resource *pt = st_get_texobj_resource(texObj);
const uint baseLevel = texObj->BaseLevel;
const uint lastLevel = pt->last_level;
const uint face = _mesa_tex_target_to_face(target);
uint dstLevel;
GLenum datatype;
GLuint comps;
GLboolean compressed;
 
if (ST_DEBUG & DEBUG_FALLBACK)
debug_printf("%s: fallback processing\n", __FUNCTION__);
 
assert(target != GL_TEXTURE_3D); /* not done yet */
 
compressed =
_mesa_is_format_compressed(texObj->Image[face][baseLevel]->TexFormat);
 
if (compressed) {
datatype = GL_UNSIGNED_BYTE;
comps = 4;
}
else {
_mesa_format_to_type_and_comps(texObj->Image[face][baseLevel]->TexFormat,
&datatype, &comps);
assert(comps > 0 && "bad texture format in fallback_generate_mipmap()");
}
 
for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
const uint srcLevel = dstLevel - 1;
const uint srcWidth = u_minify(pt->width0, srcLevel);
const uint srcHeight = u_minify(pt->height0, srcLevel);
const uint srcDepth = u_minify(pt->depth0, srcLevel);
const uint dstWidth = u_minify(pt->width0, dstLevel);
const uint dstHeight = u_minify(pt->height0, dstLevel);
const uint dstDepth = u_minify(pt->depth0, dstLevel);
struct pipe_transfer *srcTrans, *dstTrans;
const ubyte *srcData;
ubyte *dstData;
int srcStride, dstStride;
 
srcTrans = pipe_get_transfer(st_context(ctx)->pipe, pt, srcLevel,
face,
PIPE_TRANSFER_READ, 0, 0,
srcWidth, srcHeight);
 
dstTrans = pipe_get_transfer(st_context(ctx)->pipe, pt, dstLevel,
face,
PIPE_TRANSFER_WRITE, 0, 0,
dstWidth, dstHeight);
 
srcData = (ubyte *) pipe_transfer_map(pipe, srcTrans);
dstData = (ubyte *) pipe_transfer_map(pipe, dstTrans);
 
srcStride = srcTrans->stride / util_format_get_blocksize(srcTrans->resource->format);
dstStride = dstTrans->stride / util_format_get_blocksize(dstTrans->resource->format);
 
/* this cannot work correctly for 3d since it does
not respect layerStride. */
if (compressed) {
const enum pipe_format format = pt->format;
const uint bw = util_format_get_blockwidth(format);
const uint bh = util_format_get_blockheight(format);
const uint srcWidth2 = align(srcWidth, bw);
const uint srcHeight2 = align(srcHeight, bh);
const uint dstWidth2 = align(dstWidth, bw);
const uint dstHeight2 = align(dstHeight, bh);
uint8_t *srcTemp, *dstTemp;
 
assert(comps == 4);
 
srcTemp = malloc(srcWidth2 * srcHeight2 * comps + 000);
dstTemp = malloc(dstWidth2 * dstHeight2 * comps + 000);
 
/* decompress the src image: srcData -> srcTemp */
decompress_image(format, srcData, srcTemp, srcWidth, srcHeight);
 
_mesa_generate_mipmap_level(target, datatype, comps,
0 /*border*/,
srcWidth2, srcHeight2, srcDepth,
srcTemp,
srcWidth2, /* stride in texels */
dstWidth2, dstHeight2, dstDepth,
dstTemp,
dstWidth2); /* stride in texels */
 
/* compress the new image: dstTemp -> dstData */
compress_image(format, dstTemp, dstData, dstWidth, dstHeight);
 
free(srcTemp);
free(dstTemp);
}
else {
_mesa_generate_mipmap_level(target, datatype, comps,
0 /*border*/,
srcWidth, srcHeight, srcDepth,
srcData,
srcStride, /* stride in texels */
dstWidth, dstHeight, dstDepth,
dstData,
dstStride); /* stride in texels */
}
 
pipe_transfer_unmap(pipe, srcTrans);
pipe_transfer_unmap(pipe, dstTrans);
 
pipe->transfer_destroy(pipe, srcTrans);
pipe->transfer_destroy(pipe, dstTrans);
}
}
 
 
/**
* Compute the expected number of mipmap levels in the texture given
* the width/height/depth of the base image and the GL_TEXTURE_BASE_LEVEL/
* GL_TEXTURE_MAX_LEVEL settings. This will tell us how many mipmap
* levels should be generated.
*/
static GLuint
compute_num_levels(struct gl_context *ctx,
struct gl_texture_object *texObj,
GLenum target)
{
if (target == GL_TEXTURE_RECTANGLE_ARB) {
return 1;
}
else {
const struct gl_texture_image *baseImage =
_mesa_get_tex_image(ctx, texObj, target, texObj->BaseLevel);
GLuint size, numLevels;
 
size = MAX2(baseImage->Width2, baseImage->Height2);
size = MAX2(size, baseImage->Depth2);
 
numLevels = texObj->BaseLevel;
 
while (size > 0) {
numLevels++;
size >>= 1;
}
 
numLevels = MIN2(numLevels, texObj->MaxLevel + 1);
 
assert(numLevels >= 1);
 
return numLevels;
}
}
 
 
/**
* Called via ctx->Driver.GenerateMipmap().
*/
void
st_generate_mipmap(struct gl_context *ctx, GLenum target,
struct gl_texture_object *texObj)
{
struct st_context *st = st_context(ctx);
struct st_texture_object *stObj = st_texture_object(texObj);
struct pipe_resource *pt = st_get_texobj_resource(texObj);
const uint baseLevel = texObj->BaseLevel;
uint lastLevel;
uint dstLevel;
 
if (!pt)
return;
 
/* not sure if this ultimately actually should work,
but we're not supporting multisampled textures yet. */
assert(pt->nr_samples < 2);
 
/* find expected last mipmap level to generate*/
lastLevel = compute_num_levels(ctx, texObj, target) - 1;
 
if (lastLevel == 0)
return;
 
if (pt->last_level < lastLevel) {
/* The current gallium texture doesn't have space for all the
* mipmap levels we need to generate. So allocate a new texture.
*/
struct pipe_resource *oldTex = stObj->pt;
 
/* create new texture with space for more levels */
stObj->pt = st_texture_create(st,
oldTex->target,
oldTex->format,
lastLevel,
oldTex->width0,
oldTex->height0,
oldTex->depth0,
oldTex->bind);
 
/* The texture isn't in a "complete" state yet so set the expected
* lastLevel here, since it won't get done in st_finalize_texture().
*/
stObj->lastLevel = lastLevel;
 
/* This will copy the old texture's base image into the new texture
* which we just allocated.
*/
st_finalize_texture(ctx, st->pipe, texObj);
 
/* release the old tex (will likely be freed too) */
pipe_resource_reference(&oldTex, NULL);
pipe_sampler_view_reference(&stObj->sampler_view, NULL);
 
pt = stObj->pt;
}
else {
/* Make sure that the base texture image data is present in the
* texture buffer.
*/
st_finalize_texture(ctx, st->pipe, texObj);
}
 
assert(pt->last_level >= lastLevel);
 
/* Try to generate the mipmap by rendering/texturing. If that fails,
* use the software fallback.
*/
if (!st_render_mipmap(st, target, stObj, baseLevel, lastLevel)) {
/* since the util code actually also has a fallback, should
probably make it never fail and kill this */
fallback_generate_mipmap(ctx, target, texObj);
}
 
/* Fill in the Mesa gl_texture_image fields */
for (dstLevel = baseLevel + 1; dstLevel <= lastLevel; dstLevel++) {
const uint srcLevel = dstLevel - 1;
const struct gl_texture_image *srcImage
= _mesa_get_tex_image(ctx, texObj, target, srcLevel);
struct gl_texture_image *dstImage;
struct st_texture_image *stImage;
uint dstWidth = u_minify(pt->width0, dstLevel);
uint dstHeight = u_minify(pt->height0, dstLevel);
uint dstDepth = u_minify(pt->depth0, dstLevel);
uint border = srcImage->Border;
 
dstImage = _mesa_get_tex_image(ctx, texObj, target, dstLevel);
if (!dstImage) {
_mesa_error(ctx, GL_OUT_OF_MEMORY, "generating mipmaps");
return;
}
 
/* Free old image data */
if (dstImage->Data)
ctx->Driver.FreeTexImageData(ctx, dstImage);
 
/* initialize new image */
_mesa_init_teximage_fields(ctx, target, dstImage, dstWidth, dstHeight,
dstDepth, border, srcImage->InternalFormat,
srcImage->TexFormat);
 
stImage = st_texture_image(dstImage);
stImage->level = dstLevel;
 
pipe_resource_reference(&stImage->pt, pt);
}
}
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_gen_mipmap.h
0,0 → 1,50
/**************************************************************************
*
* 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 ST_GEN_MIPMAP_H
#define ST_GEN_MIPMAP_H
 
 
#include "main/mtypes.h"
 
struct st_context;
 
extern void
st_init_generate_mipmap(struct st_context *st);
 
 
extern void
st_destroy_generate_mipmap(struct st_context *st);
 
 
extern void
st_generate_mipmap(struct gl_context *ctx, GLenum target,
struct gl_texture_object *texObj);
 
 
#endif /* ST_GEN_MIPMAP_H */
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_gl_api.h
0,0 → 1,7
 
#ifndef ST_GL_API_H
#define ST_GL_API_H
 
struct st_api *st_gl_api_create(void);
 
#endif
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_manager.c
0,0 → 1,924
/*
* Mesa 3-D graphics library
* Version: 7.9
*
* 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:
* Chia-I Wu <olv@lunarg.com>
*/
 
#include "state_tracker/st_gl_api.h"
 
#include "pipe/p_context.h"
#include "pipe/p_screen.h"
#include "util/u_format.h"
#include "util/u_pointer.h"
#include "util/u_inlines.h"
#include "util/u_atomic.h"
#include "util/u_surface.h"
 
#include "main/mtypes.h"
#include "main/context.h"
#include "main/texobj.h"
#include "main/teximage.h"
#include "main/texstate.h"
#include "main/framebuffer.h"
#include "main/fbobject.h"
#include "main/renderbuffer.h"
#include "main/version.h"
#include "st_texture.h"
 
#include "st_context.h"
#include "st_format.h"
#include "st_cb_fbo.h"
#include "st_cb_flush.h"
#include "st_manager.h"
 
/**
* Cast wrapper to convert a struct gl_framebuffer to an st_framebuffer.
* Return NULL if the struct gl_framebuffer is a user-created framebuffer.
* We'll only return non-null for window system framebuffers.
* Note that this function may fail.
*/
static INLINE struct st_framebuffer *
st_ws_framebuffer(struct gl_framebuffer *fb)
{
/* FBO cannot be casted. See st_new_framebuffer */
return (struct st_framebuffer *) ((fb && !fb->Name) ? fb : NULL);
}
 
/**
* Map an attachment to a buffer index.
*/
static INLINE gl_buffer_index
attachment_to_buffer_index(enum st_attachment_type statt)
{
gl_buffer_index index;
 
switch (statt) {
case ST_ATTACHMENT_FRONT_LEFT:
index = BUFFER_FRONT_LEFT;
break;
case ST_ATTACHMENT_BACK_LEFT:
index = BUFFER_BACK_LEFT;
break;
case ST_ATTACHMENT_FRONT_RIGHT:
index = BUFFER_FRONT_RIGHT;
break;
case ST_ATTACHMENT_BACK_RIGHT:
index = BUFFER_BACK_RIGHT;
break;
case ST_ATTACHMENT_DEPTH_STENCIL:
index = BUFFER_DEPTH;
break;
case ST_ATTACHMENT_ACCUM:
index = BUFFER_ACCUM;
break;
case ST_ATTACHMENT_SAMPLE:
default:
index = BUFFER_COUNT;
break;
}
 
return index;
}
 
/**
* Map a buffer index to an attachment.
*/
static INLINE enum st_attachment_type
buffer_index_to_attachment(gl_buffer_index index)
{
enum st_attachment_type statt;
 
switch (index) {
case BUFFER_FRONT_LEFT:
statt = ST_ATTACHMENT_FRONT_LEFT;
break;
case BUFFER_BACK_LEFT:
statt = ST_ATTACHMENT_BACK_LEFT;
break;
case BUFFER_FRONT_RIGHT:
statt = ST_ATTACHMENT_FRONT_RIGHT;
break;
case BUFFER_BACK_RIGHT:
statt = ST_ATTACHMENT_BACK_RIGHT;
break;
case BUFFER_DEPTH:
statt = ST_ATTACHMENT_DEPTH_STENCIL;
break;
case BUFFER_ACCUM:
statt = ST_ATTACHMENT_ACCUM;
break;
default:
statt = ST_ATTACHMENT_INVALID;
break;
}
 
return statt;
}
 
/**
* Validate a framebuffer to make sure up-to-date pipe_textures are used.
*/
static void
st_framebuffer_validate(struct st_framebuffer *stfb, struct st_context *st)
{
struct pipe_context *pipe = st->pipe;
struct pipe_resource *textures[ST_ATTACHMENT_COUNT];
uint width, height;
unsigned i;
boolean changed = FALSE;
 
if (!p_atomic_read(&stfb->revalidate))
return;
 
/* validate the fb */
if (!stfb->iface->validate(stfb->iface, stfb->statts, stfb->num_statts, textures))
return;
 
width = stfb->Base.Width;
height = stfb->Base.Height;
 
for (i = 0; i < stfb->num_statts; i++) {
struct st_renderbuffer *strb;
struct pipe_surface *ps, surf_tmpl;
gl_buffer_index idx;
 
if (!textures[i])
continue;
 
idx = attachment_to_buffer_index(stfb->statts[i]);
if (idx >= BUFFER_COUNT) {
pipe_resource_reference(&textures[i], NULL);
continue;
}
 
strb = st_renderbuffer(stfb->Base.Attachment[idx].Renderbuffer);
assert(strb);
if (strb->texture == textures[i]) {
pipe_resource_reference(&textures[i], NULL);
continue;
}
 
memset(&surf_tmpl, 0, sizeof(surf_tmpl));
u_surface_default_template(&surf_tmpl, textures[i],
PIPE_BIND_RENDER_TARGET);
ps = pipe->create_surface(pipe, textures[i], &surf_tmpl);
if (ps) {
pipe_surface_reference(&strb->surface, ps);
pipe_resource_reference(&strb->texture, ps->texture);
/* ownership transfered */
pipe_surface_reference(&ps, NULL);
 
changed = TRUE;
 
strb->Base.Width = strb->surface->width;
strb->Base.Height = strb->surface->height;
 
width = strb->Base.Width;
height = strb->Base.Height;
}
 
pipe_resource_reference(&textures[i], NULL);
}
 
if (changed) {
st->dirty.st |= ST_NEW_FRAMEBUFFER;
_mesa_resize_framebuffer(st->ctx, &stfb->Base, width, height);
 
assert(stfb->Base.Width == width);
assert(stfb->Base.Height == height);
}
 
p_atomic_set(&stfb->revalidate, FALSE);
}
 
/**
* Update the attachments to validate by looping the existing renderbuffers.
*/
static void
st_framebuffer_update_attachments(struct st_framebuffer *stfb)
{
gl_buffer_index idx;
 
stfb->num_statts = 0;
for (idx = 0; idx < BUFFER_COUNT; idx++) {
struct st_renderbuffer *strb;
enum st_attachment_type statt;
 
strb = st_renderbuffer(stfb->Base.Attachment[idx].Renderbuffer);
if (!strb || strb->software)
continue;
 
statt = buffer_index_to_attachment(idx);
if (statt != ST_ATTACHMENT_INVALID &&
st_visual_have_buffers(stfb->iface->visual, 1 << statt))
stfb->statts[stfb->num_statts++] = statt;
}
 
p_atomic_set(&stfb->revalidate, TRUE);
}
 
/**
* Add a renderbuffer to the framebuffer.
*/
static boolean
st_framebuffer_add_renderbuffer(struct st_framebuffer *stfb,
gl_buffer_index idx)
{
struct gl_renderbuffer *rb;
enum pipe_format format;
int samples;
boolean sw;
 
if (!stfb->iface)
return FALSE;
 
/* do not distinguish depth/stencil buffers */
if (idx == BUFFER_STENCIL)
idx = BUFFER_DEPTH;
 
switch (idx) {
case BUFFER_DEPTH:
format = stfb->iface->visual->depth_stencil_format;
sw = FALSE;
break;
case BUFFER_ACCUM:
format = stfb->iface->visual->accum_format;
sw = TRUE;
break;
default:
format = stfb->iface->visual->color_format;
sw = FALSE;
break;
}
 
if (format == PIPE_FORMAT_NONE)
return FALSE;
 
samples = stfb->iface->visual->samples;
if (!samples)
samples = st_get_msaa();
 
rb = st_new_renderbuffer_fb(format, samples, sw);
if (!rb)
return FALSE;
 
if (idx != BUFFER_DEPTH) {
_mesa_add_renderbuffer(&stfb->Base, idx, rb);
}
else {
if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_ZS, 0))
_mesa_add_renderbuffer(&stfb->Base, BUFFER_DEPTH, rb);
if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_ZS, 1))
_mesa_add_renderbuffer(&stfb->Base, BUFFER_STENCIL, rb);
}
 
return TRUE;
}
 
/**
* Intialize a struct gl_config from a visual.
*/
static void
st_visual_to_context_mode(const struct st_visual *visual,
struct gl_config *mode)
{
memset(mode, 0, sizeof(*mode));
 
if (st_visual_have_buffers(visual, ST_ATTACHMENT_BACK_LEFT_MASK))
mode->doubleBufferMode = GL_TRUE;
if (st_visual_have_buffers(visual,
ST_ATTACHMENT_FRONT_RIGHT_MASK | ST_ATTACHMENT_BACK_RIGHT_MASK))
mode->stereoMode = GL_TRUE;
 
if (visual->color_format != PIPE_FORMAT_NONE) {
mode->rgbMode = GL_TRUE;
 
mode->redBits =
util_format_get_component_bits(visual->color_format,
UTIL_FORMAT_COLORSPACE_RGB, 0);
mode->greenBits =
util_format_get_component_bits(visual->color_format,
UTIL_FORMAT_COLORSPACE_RGB, 1);
mode->blueBits =
util_format_get_component_bits(visual->color_format,
UTIL_FORMAT_COLORSPACE_RGB, 2);
mode->alphaBits =
util_format_get_component_bits(visual->color_format,
UTIL_FORMAT_COLORSPACE_RGB, 3);
 
mode->rgbBits = mode->redBits +
mode->greenBits + mode->blueBits + mode->alphaBits;
}
 
if (visual->depth_stencil_format != PIPE_FORMAT_NONE) {
mode->depthBits =
util_format_get_component_bits(visual->depth_stencil_format,
UTIL_FORMAT_COLORSPACE_ZS, 0);
mode->stencilBits =
util_format_get_component_bits(visual->depth_stencil_format,
UTIL_FORMAT_COLORSPACE_ZS, 1);
 
mode->haveDepthBuffer = mode->depthBits > 0;
mode->haveStencilBuffer = mode->stencilBits > 0;
}
 
if (visual->accum_format != PIPE_FORMAT_NONE) {
mode->haveAccumBuffer = GL_TRUE;
 
mode->accumRedBits =
util_format_get_component_bits(visual->accum_format,
UTIL_FORMAT_COLORSPACE_RGB, 0);
mode->accumGreenBits =
util_format_get_component_bits(visual->accum_format,
UTIL_FORMAT_COLORSPACE_RGB, 1);
mode->accumBlueBits =
util_format_get_component_bits(visual->accum_format,
UTIL_FORMAT_COLORSPACE_RGB, 2);
mode->accumAlphaBits =
util_format_get_component_bits(visual->accum_format,
UTIL_FORMAT_COLORSPACE_RGB, 3);
}
 
if (visual->samples) {
mode->sampleBuffers = 1;
mode->samples = visual->samples;
}
}
 
/**
* Determine the default draw or read buffer from a visual.
*/
static void
st_visual_to_default_buffer(const struct st_visual *visual,
GLenum *buffer, GLint *index)
{
enum st_attachment_type statt;
GLenum buf;
gl_buffer_index idx;
 
statt = visual->render_buffer;
/* do nothing if an invalid render buffer is specified */
if (statt == ST_ATTACHMENT_INVALID ||
!st_visual_have_buffers(visual, 1 << statt))
return;
 
switch (statt) {
case ST_ATTACHMENT_FRONT_LEFT:
buf = GL_FRONT_LEFT;
idx = BUFFER_FRONT_LEFT;
break;
case ST_ATTACHMENT_BACK_LEFT:
buf = GL_BACK_LEFT;
idx = BUFFER_BACK_LEFT;
break;
case ST_ATTACHMENT_FRONT_RIGHT:
buf = GL_FRONT_RIGHT;
idx = BUFFER_FRONT_RIGHT;
break;
case ST_ATTACHMENT_BACK_RIGHT:
buf = GL_BACK_RIGHT;
idx = BUFFER_BACK_RIGHT;
break;
default:
buf = GL_NONE;
idx = BUFFER_COUNT;
break;
}
 
if (buf != GL_NONE) {
if (buffer)
*buffer = buf;
if (index)
*index = idx;
}
}
 
/**
* Create a framebuffer from a manager interface.
*/
static struct st_framebuffer *
st_framebuffer_create(struct st_framebuffer_iface *stfbi)
{
struct st_framebuffer *stfb;
struct gl_config mode;
gl_buffer_index idx;
 
stfb = CALLOC_STRUCT(st_framebuffer);
if (!stfb)
return NULL;
 
/* for FBO-only context */
if (!stfbi) {
struct gl_framebuffer *base = _mesa_get_incomplete_framebuffer();
 
stfb->Base = *base;
 
return stfb;
}
 
st_visual_to_context_mode(stfbi->visual, &mode);
_mesa_initialize_window_framebuffer(&stfb->Base, &mode);
 
/* modify the draw/read buffers of the fb */
st_visual_to_default_buffer(stfbi->visual, &stfb->Base.ColorDrawBuffer[0],
&stfb->Base._ColorDrawBufferIndexes[0]);
st_visual_to_default_buffer(stfbi->visual, &stfb->Base.ColorReadBuffer,
&stfb->Base._ColorReadBufferIndex);
 
stfb->iface = stfbi;
 
/* add the color buffer */
idx = stfb->Base._ColorDrawBufferIndexes[0];
if (!st_framebuffer_add_renderbuffer(stfb, idx)) {
FREE(stfb);
return NULL;
}
 
st_framebuffer_add_renderbuffer(stfb, BUFFER_DEPTH);
st_framebuffer_add_renderbuffer(stfb, BUFFER_ACCUM);
 
st_framebuffer_update_attachments(stfb);
 
stfb->Base.Initialized = GL_TRUE;
 
return stfb;
}
 
/**
* Reference a framebuffer.
*/
static void
st_framebuffer_reference(struct st_framebuffer **ptr,
struct st_framebuffer *stfb)
{
struct gl_framebuffer *fb = &stfb->Base;
_mesa_reference_framebuffer((struct gl_framebuffer **) ptr, fb);
}
 
static void
st_context_notify_invalid_framebuffer(struct st_context_iface *stctxi,
struct st_framebuffer_iface *stfbi)
{
struct st_context *st = (struct st_context *) stctxi;
struct st_framebuffer *stfb;
 
/* either draw or read winsys fb */
stfb = st_ws_framebuffer(st->ctx->WinSysDrawBuffer);
if (!stfb || stfb->iface != stfbi)
stfb = st_ws_framebuffer(st->ctx->WinSysReadBuffer);
 
if (stfb && stfb->iface == stfbi) {
p_atomic_set(&stfb->revalidate, TRUE);
}
else {
/* This function is probably getting called when we've detected a
* change in a window's size but the currently bound context is
* not bound to that window.
* If the st_framebuffer_iface structure had a pointer to the
* corresponding st_framebuffer we'd be able to handle this.
*/
}
}
 
static void
st_context_flush(struct st_context_iface *stctxi, unsigned flags,
struct pipe_fence_handle **fence)
{
struct st_context *st = (struct st_context *) stctxi;
st_flush(st, flags, fence);
if (flags & PIPE_FLUSH_RENDER_CACHE)
st_manager_flush_frontbuffer(st);
}
 
static boolean
st_context_teximage(struct st_context_iface *stctxi, enum st_texture_type target,
int level, enum pipe_format internal_format,
struct pipe_resource *tex, boolean mipmap)
{
struct st_context *st = (struct st_context *) stctxi;
struct gl_context *ctx = st->ctx;
struct gl_texture_unit *texUnit = _mesa_get_current_tex_unit(ctx);
struct gl_texture_object *texObj;
struct gl_texture_image *texImage;
struct st_texture_object *stObj;
struct st_texture_image *stImage;
GLenum internalFormat;
GLuint width, height, depth;
 
switch (target) {
case ST_TEXTURE_1D:
target = GL_TEXTURE_1D;
break;
case ST_TEXTURE_2D:
target = GL_TEXTURE_2D;
break;
case ST_TEXTURE_3D:
target = GL_TEXTURE_3D;
break;
case ST_TEXTURE_RECT:
target = GL_TEXTURE_RECTANGLE_ARB;
break;
default:
return FALSE;
break;
}
 
texObj = _mesa_select_tex_object(ctx, texUnit, target);
_mesa_lock_texture(ctx, texObj);
 
stObj = st_texture_object(texObj);
/* switch to surface based */
if (!stObj->surface_based) {
_mesa_clear_texture_object(ctx, texObj);
stObj->surface_based = GL_TRUE;
}
 
texImage = _mesa_get_tex_image(ctx, texObj, target, level);
stImage = st_texture_image(texImage);
if (tex) {
gl_format texFormat;
 
/*
* XXX When internal_format and tex->format differ, st_finalize_texture
* needs to allocate a new texture with internal_format and copy the
* texture here into the new one. It will result in surface_copy being
* called on surfaces whose formats differ.
*
* To avoid that, internal_format is (wrongly) ignored here. A sane fix
* is to use a sampler view.
*/
if (!st_sampler_compat_formats(tex->format, internal_format))
internal_format = tex->format;
if (util_format_get_component_bits(internal_format,
UTIL_FORMAT_COLORSPACE_RGB, 3) > 0)
internalFormat = GL_RGBA;
else
internalFormat = GL_RGB;
 
texFormat = st_ChooseTextureFormat(ctx, internalFormat,
GL_RGBA, GL_UNSIGNED_BYTE);
 
_mesa_init_teximage_fields(ctx, target, texImage,
tex->width0, tex->height0, 1, 0,
internalFormat, texFormat);
 
width = tex->width0;
height = tex->height0;
depth = tex->depth0;
 
/* grow the image size until we hit level = 0 */
while (level > 0) {
if (width != 1)
width <<= 1;
if (height != 1)
height <<= 1;
if (depth != 1)
depth <<= 1;
level--;
}
}
else {
_mesa_clear_texture_image(ctx, texImage);
width = height = depth = 0;
}
 
pipe_resource_reference(&stImage->pt, tex);
stObj->width0 = width;
stObj->height0 = height;
stObj->depth0 = depth;
 
_mesa_dirty_texobj(ctx, texObj, GL_TRUE);
_mesa_unlock_texture(ctx, texObj);
return TRUE;
}
 
static void
st_context_copy(struct st_context_iface *stctxi,
struct st_context_iface *stsrci, unsigned mask)
{
struct st_context *st = (struct st_context *) stctxi;
struct st_context *src = (struct st_context *) stsrci;
 
_mesa_copy_context(src->ctx, st->ctx, mask);
}
 
static boolean
st_context_share(struct st_context_iface *stctxi,
struct st_context_iface *stsrci)
{
struct st_context *st = (struct st_context *) stctxi;
struct st_context *src = (struct st_context *) stsrci;
 
return _mesa_share_state(st->ctx, src->ctx);
}
 
static void
st_context_destroy(struct st_context_iface *stctxi)
{
struct st_context *st = (struct st_context *) stctxi;
st_destroy_context(st);
}
 
static struct st_context_iface *
st_api_create_context(struct st_api *stapi, struct st_manager *smapi,
const struct st_context_attribs *attribs,
struct st_context_iface *shared_stctxi)
{
struct st_context *shared_ctx = (struct st_context *) shared_stctxi;
struct st_context *st;
struct pipe_context *pipe;
struct gl_config mode;
gl_api api;
 
if (!(stapi->profile_mask & (1 << attribs->profile)))
return NULL;
 
switch (attribs->profile) {
case ST_PROFILE_DEFAULT:
api = API_OPENGL;
break;
case ST_PROFILE_OPENGL_ES1:
api = API_OPENGLES;
break;
case ST_PROFILE_OPENGL_ES2:
api = API_OPENGLES2;
break;
case ST_PROFILE_OPENGL_CORE:
default:
return NULL;
break;
}
 
pipe = smapi->screen->context_create(smapi->screen, NULL);
if (!pipe)
return NULL;
 
st_visual_to_context_mode(&attribs->visual, &mode);
st = st_create_context(api, pipe, &mode, shared_ctx);
if (!st) {
pipe->destroy(pipe);
return NULL;
}
 
/* need to perform version check */
if (attribs->major > 1 || attribs->minor > 0) {
_mesa_compute_version(st->ctx);
 
if (st->ctx->VersionMajor < attribs->major ||
st->ctx->VersionMajor < attribs->minor) {
st_destroy_context(st);
return NULL;
}
}
 
st->invalidate_on_gl_viewport =
smapi->get_param(smapi, ST_MANAGER_BROKEN_INVALIDATE);
 
st->iface.destroy = st_context_destroy;
st->iface.notify_invalid_framebuffer =
st_context_notify_invalid_framebuffer;
st->iface.flush = st_context_flush;
st->iface.teximage = st_context_teximage;
st->iface.copy = st_context_copy;
st->iface.share = st_context_share;
st->iface.st_context_private = (void *) smapi;
 
return &st->iface;
}
 
static boolean
st_api_make_current(struct st_api *stapi, struct st_context_iface *stctxi,
struct st_framebuffer_iface *stdrawi,
struct st_framebuffer_iface *streadi)
{
struct st_context *st = (struct st_context *) stctxi;
struct st_framebuffer *stdraw, *stread, *stfb;
boolean ret;
 
_glapi_check_multithread();
 
if (st) {
/* reuse/create the draw fb */
stfb = st_ws_framebuffer(st->ctx->WinSysDrawBuffer);
if (stfb && stfb->iface == stdrawi) {
stdraw = NULL;
st_framebuffer_reference(&stdraw, stfb);
}
else {
stdraw = st_framebuffer_create(stdrawi);
}
 
/* reuse/create the read fb */
stfb = st_ws_framebuffer(st->ctx->WinSysReadBuffer);
if (!stfb || stfb->iface != streadi)
stfb = stdraw;
if (stfb && stfb->iface == streadi) {
stread = NULL;
st_framebuffer_reference(&stread, stfb);
}
else {
stread = st_framebuffer_create(streadi);
}
 
if (stdraw && stread) {
st_framebuffer_validate(stdraw, st);
if (stread != stdraw)
st_framebuffer_validate(stread, st);
 
/* modify the draw/read buffers of the context */
if (stdraw->iface) {
st_visual_to_default_buffer(stdraw->iface->visual,
&st->ctx->Color.DrawBuffer[0], NULL);
}
if (stread->iface) {
st_visual_to_default_buffer(stread->iface->visual,
&st->ctx->Pixel.ReadBuffer, NULL);
}
 
ret = _mesa_make_current(st->ctx, &stdraw->Base, &stread->Base);
}
else {
ret = FALSE;
}
 
st_framebuffer_reference(&stdraw, NULL);
st_framebuffer_reference(&stread, NULL);
}
else {
ret = _mesa_make_current(NULL, NULL, NULL);
}
 
return ret;
}
 
static struct st_context_iface *
st_api_get_current(struct st_api *stapi)
{
GET_CURRENT_CONTEXT(ctx);
struct st_context *st = (ctx) ? ctx->st : NULL;
 
return (st) ? &st->iface : NULL;
}
 
static st_proc_t
st_api_get_proc_address(struct st_api *stapi, const char *procname)
{
return (st_proc_t) _glapi_get_proc_address(procname);
}
 
static void
st_api_destroy(struct st_api *stapi)
{
}
 
/**
* Flush the front buffer if the current context renders to the front buffer.
*/
void
st_manager_flush_frontbuffer(struct st_context *st)
{
struct st_framebuffer *stfb = st_ws_framebuffer(st->ctx->DrawBuffer);
struct st_renderbuffer *strb = NULL;
 
if (stfb)
strb = st_renderbuffer(stfb->Base.Attachment[BUFFER_FRONT_LEFT].Renderbuffer);
if (!strb)
return;
 
/* never a dummy fb */
assert(stfb->iface);
stfb->iface->flush_front(stfb->iface, ST_ATTACHMENT_FRONT_LEFT);
}
 
/**
* Return the surface of an EGLImage.
* FIXME: I think this should operate on resources, not surfaces
*/
struct pipe_surface *
st_manager_get_egl_image_surface(struct st_context *st,
void *eglimg, unsigned usage)
{
struct st_manager *smapi =
(struct st_manager *) st->iface.st_context_private;
struct st_egl_image stimg;
struct pipe_surface *ps, surf_tmpl;
 
if (!smapi || !smapi->get_egl_image)
return NULL;
 
memset(&stimg, 0, sizeof(stimg));
if (!smapi->get_egl_image(smapi, eglimg, &stimg))
return NULL;
 
memset(&surf_tmpl, 0, sizeof(surf_tmpl));
surf_tmpl.format = stimg.texture->format;
surf_tmpl.usage = usage;
surf_tmpl.u.tex.level = stimg.level;
surf_tmpl.u.tex.first_layer = stimg.layer;
surf_tmpl.u.tex.last_layer = stimg.layer;
ps = st->pipe->create_surface(st->pipe, stimg.texture, &surf_tmpl);
pipe_resource_reference(&stimg.texture, NULL);
 
return ps;
}
 
/**
* Re-validate the framebuffers.
*/
void
st_manager_validate_framebuffers(struct st_context *st)
{
struct st_framebuffer *stdraw = st_ws_framebuffer(st->ctx->DrawBuffer);
struct st_framebuffer *stread = st_ws_framebuffer(st->ctx->ReadBuffer);
 
if (stdraw)
st_framebuffer_validate(stdraw, st);
if (stread && stread != stdraw)
st_framebuffer_validate(stread, st);
}
 
/**
* Add a color renderbuffer on demand.
*/
boolean
st_manager_add_color_renderbuffer(struct st_context *st, struct gl_framebuffer *fb,
gl_buffer_index idx)
{
struct st_framebuffer *stfb = st_ws_framebuffer(fb);
 
/* FBO */
if (!stfb)
return FALSE;
 
if (stfb->Base.Attachment[idx].Renderbuffer)
return TRUE;
 
switch (idx) {
case BUFFER_FRONT_LEFT:
case BUFFER_BACK_LEFT:
case BUFFER_FRONT_RIGHT:
case BUFFER_BACK_RIGHT:
break;
default:
return FALSE;
break;
}
 
if (!st_framebuffer_add_renderbuffer(stfb, idx))
return FALSE;
 
st_framebuffer_update_attachments(stfb);
st_invalidate_state(st->ctx, _NEW_BUFFERS);
 
return TRUE;
}
 
static const struct st_api st_gl_api = {
"Mesa " MESA_VERSION_STRING,
ST_API_OPENGL,
#if FEATURE_GL
ST_PROFILE_DEFAULT_MASK |
#endif
#if FEATURE_ES1
ST_PROFILE_OPENGL_ES1_MASK |
#endif
#if FEATURE_ES2
ST_PROFILE_OPENGL_ES2_MASK |
#endif
0,
st_api_destroy,
st_api_get_proc_address,
st_api_create_context,
st_api_make_current,
st_api_get_current,
};
 
struct st_api *
st_gl_api_create(void)
{
return (struct st_api *) &st_gl_api;
}
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_manager.h
0,0 → 1,52
/*
* Mesa 3-D graphics library
* Version: 7.9
*
* 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:
* Chia-I Wu <olv@lunarg.com>
*/
 
#ifndef ST_MANAGER_H
#define ST_MANAGER_H
 
#include "main/mtypes.h"
 
#include "pipe/p_compiler.h"
 
struct st_context;
 
struct pipe_surface *
st_manager_get_egl_image_surface(struct st_context *st,
void *eglimg, unsigned usage);
 
void
st_manager_flush_frontbuffer(struct st_context *st);
 
void
st_manager_validate_framebuffers(struct st_context *st);
 
boolean
st_manager_add_color_renderbuffer(struct st_context *st, struct gl_framebuffer *fb,
gl_buffer_index idx);
 
#endif /* ST_MANAGER_H */
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_mesa_to_tgsi.c
0,0 → 1,1208
/**************************************************************************
*
* 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.
*
**************************************************************************/
 
/*
* \author
* Michal Krol,
* Keith Whitwell
*/
 
#include "pipe/p_compiler.h"
#include "pipe/p_context.h"
#include "pipe/p_screen.h"
#include "pipe/p_shader_tokens.h"
#include "pipe/p_state.h"
#include "tgsi/tgsi_ureg.h"
#include "st_mesa_to_tgsi.h"
#include "st_context.h"
#include "program/prog_instruction.h"
#include "program/prog_parameter.h"
#include "util/u_debug.h"
#include "util/u_math.h"
#include "util/u_memory.h"
 
 
#define PROGRAM_ANY_CONST ((1 << PROGRAM_LOCAL_PARAM) | \
(1 << PROGRAM_ENV_PARAM) | \
(1 << PROGRAM_STATE_VAR) | \
(1 << PROGRAM_NAMED_PARAM) | \
(1 << PROGRAM_CONSTANT) | \
(1 << PROGRAM_UNIFORM))
 
 
struct label {
unsigned branch_target;
unsigned token;
};
 
 
/**
* Intermediate state used during shader translation.
*/
struct st_translate {
struct ureg_program *ureg;
 
struct ureg_dst temps[MAX_PROGRAM_TEMPS];
struct ureg_src *constants;
struct ureg_dst outputs[PIPE_MAX_SHADER_OUTPUTS];
struct ureg_src inputs[PIPE_MAX_SHADER_INPUTS];
struct ureg_dst address[1];
struct ureg_src samplers[PIPE_MAX_SAMPLERS];
 
/* Extra info for handling point size clamping in vertex shader */
struct ureg_dst pointSizeResult; /**< Actual point size output register */
struct ureg_src pointSizeConst; /**< Point size range constant register */
GLint pointSizeOutIndex; /**< Temp point size output register */
GLboolean prevInstWrotePointSize;
 
const GLuint *inputMapping;
const GLuint *outputMapping;
 
/* For every instruction that contains a label (eg CALL), keep
* details so that we can go back afterwards and emit the correct
* tgsi instruction number for each label.
*/
struct label *labels;
unsigned labels_size;
unsigned labels_count;
 
/* Keep a record of the tgsi instruction number that each mesa
* instruction starts at, will be used to fix up labels after
* translation.
*/
unsigned *insn;
unsigned insn_size;
unsigned insn_count;
 
unsigned procType; /**< TGSI_PROCESSOR_VERTEX/FRAGMENT */
 
boolean error;
};
 
 
/**
* Make note of a branch to a label in the TGSI code.
* After we've emitted all instructions, we'll go over the list
* of labels built here and patch the TGSI code with the actual
* location of each label.
*/
static unsigned *get_label( struct st_translate *t,
unsigned branch_target )
{
unsigned i;
 
if (t->labels_count + 1 >= t->labels_size) {
unsigned old_size = t->labels_size;
t->labels_size = 1 << (util_logbase2(t->labels_size) + 1);
t->labels = REALLOC( t->labels,
old_size * sizeof t->labels[0],
t->labels_size * sizeof t->labels[0] );
if (t->labels == NULL) {
static unsigned dummy;
t->error = TRUE;
return &dummy;
}
}
 
i = t->labels_count++;
t->labels[i].branch_target = branch_target;
return &t->labels[i].token;
}
 
 
/**
* Called prior to emitting the TGSI code for each Mesa instruction.
* Allocate additional space for instructions if needed.
* Update the insn[] array so the next Mesa instruction points to
* the next TGSI instruction.
*/
static void set_insn_start( struct st_translate *t,
unsigned start )
{
if (t->insn_count + 1 >= t->insn_size) {
unsigned old_size = t->insn_size;
t->insn_size = 1 << (util_logbase2(t->insn_size) + 1);
t->insn = REALLOC( t->insn,
old_size * sizeof t->insn[0],
t->insn_size * sizeof t->insn[0] );
if (t->insn == NULL) {
t->error = TRUE;
return;
}
}
 
t->insn[t->insn_count++] = start;
}
 
 
/**
* Map a Mesa dst register to a TGSI ureg_dst register.
*/
static struct ureg_dst
dst_register( struct st_translate *t,
gl_register_file file,
GLuint index )
{
switch( file ) {
case PROGRAM_UNDEFINED:
return ureg_dst_undef();
 
case PROGRAM_TEMPORARY:
if (ureg_dst_is_undef(t->temps[index]))
t->temps[index] = ureg_DECL_temporary( t->ureg );
 
return t->temps[index];
 
case PROGRAM_OUTPUT:
if (t->procType == TGSI_PROCESSOR_VERTEX && index == VERT_RESULT_PSIZ)
t->prevInstWrotePointSize = GL_TRUE;
 
if (t->procType == TGSI_PROCESSOR_VERTEX)
assert(index < VERT_RESULT_MAX);
else if (t->procType == TGSI_PROCESSOR_FRAGMENT)
assert(index < FRAG_RESULT_MAX);
else
assert(index < GEOM_RESULT_MAX);
 
assert(t->outputMapping[index] < Elements(t->outputs));
 
return t->outputs[t->outputMapping[index]];
 
case PROGRAM_ADDRESS:
return t->address[index];
 
default:
debug_assert( 0 );
return ureg_dst_undef();
}
}
 
 
/**
* Map a Mesa src register to a TGSI ureg_src register.
*/
static struct ureg_src
src_register( struct st_translate *t,
gl_register_file file,
GLint index )
{
switch( file ) {
case PROGRAM_UNDEFINED:
return ureg_src_undef();
 
case PROGRAM_TEMPORARY:
assert(index >= 0);
if (ureg_dst_is_undef(t->temps[index]))
t->temps[index] = ureg_DECL_temporary( t->ureg );
assert(index < Elements(t->temps));
return ureg_src(t->temps[index]);
 
case PROGRAM_NAMED_PARAM:
case PROGRAM_ENV_PARAM:
case PROGRAM_LOCAL_PARAM:
case PROGRAM_UNIFORM:
assert(index >= 0);
return t->constants[index];
case PROGRAM_STATE_VAR:
case PROGRAM_CONSTANT: /* ie, immediate */
if (index < 0)
return ureg_DECL_constant( t->ureg, 0 );
else
return t->constants[index];
 
case PROGRAM_INPUT:
assert(t->inputMapping[index] < Elements(t->inputs));
return t->inputs[t->inputMapping[index]];
 
case PROGRAM_OUTPUT:
assert(t->outputMapping[index] < Elements(t->outputs));
return ureg_src(t->outputs[t->outputMapping[index]]); /* not needed? */
 
case PROGRAM_ADDRESS:
return ureg_src(t->address[index]);
 
default:
debug_assert( 0 );
return ureg_src_undef();
}
}
 
 
/**
* Map mesa texture target to TGSI texture target.
*/
static unsigned
translate_texture_target( GLuint textarget,
GLboolean shadow )
{
if (shadow) {
switch( textarget ) {
case TEXTURE_1D_INDEX: return TGSI_TEXTURE_SHADOW1D;
case TEXTURE_2D_INDEX: return TGSI_TEXTURE_SHADOW2D;
case TEXTURE_RECT_INDEX: return TGSI_TEXTURE_SHADOWRECT;
default: break;
}
}
 
switch( textarget ) {
case TEXTURE_1D_INDEX: return TGSI_TEXTURE_1D;
case TEXTURE_2D_INDEX: return TGSI_TEXTURE_2D;
case TEXTURE_3D_INDEX: return TGSI_TEXTURE_3D;
case TEXTURE_CUBE_INDEX: return TGSI_TEXTURE_CUBE;
case TEXTURE_RECT_INDEX: return TGSI_TEXTURE_RECT;
default:
debug_assert( 0 );
return TGSI_TEXTURE_1D;
}
}
 
 
/**
* Create a TGSI ureg_dst register from a Mesa dest register.
*/
static struct ureg_dst
translate_dst( struct st_translate *t,
const struct prog_dst_register *DstReg,
boolean saturate )
{
struct ureg_dst dst = dst_register( t,
DstReg->File,
DstReg->Index );
 
dst = ureg_writemask( dst,
DstReg->WriteMask );
if (saturate)
dst = ureg_saturate( dst );
 
if (DstReg->RelAddr)
dst = ureg_dst_indirect( dst, ureg_src(t->address[0]) );
 
return dst;
}
 
 
/**
* Create a TGSI ureg_src register from a Mesa src register.
*/
static struct ureg_src
translate_src( struct st_translate *t,
const struct prog_src_register *SrcReg )
{
struct ureg_src src = src_register( t, SrcReg->File, SrcReg->Index );
 
if (t->procType == TGSI_PROCESSOR_GEOMETRY && SrcReg->HasIndex2) {
src = src_register( t, SrcReg->File, SrcReg->Index2 );
if (SrcReg->RelAddr2)
src = ureg_src_dimension_indirect( src, ureg_src(t->address[0]),
SrcReg->Index);
else
src = ureg_src_dimension( src, SrcReg->Index);
}
 
src = ureg_swizzle( src,
GET_SWZ( SrcReg->Swizzle, 0 ) & 0x3,
GET_SWZ( SrcReg->Swizzle, 1 ) & 0x3,
GET_SWZ( SrcReg->Swizzle, 2 ) & 0x3,
GET_SWZ( SrcReg->Swizzle, 3 ) & 0x3);
 
if (SrcReg->Negate == NEGATE_XYZW)
src = ureg_negate(src);
 
if (SrcReg->Abs)
src = ureg_abs(src);
 
if (SrcReg->RelAddr) {
src = ureg_src_indirect( src, ureg_src(t->address[0]));
if (SrcReg->File != PROGRAM_INPUT &&
SrcReg->File != PROGRAM_OUTPUT) {
/* If SrcReg->Index was negative, it was set to zero in
* src_register(). Reassign it now. But don't do this
* for input/output regs since they get remapped while
* const buffers don't.
*/
src.Index = SrcReg->Index;
}
}
 
return src;
}
 
 
static struct ureg_src swizzle_4v( struct ureg_src src,
const unsigned *swz )
{
return ureg_swizzle( src, swz[0], swz[1], swz[2], swz[3] );
}
 
 
/**
* Translate a SWZ instruction into a MOV, MUL or MAD instruction. EG:
*
* SWZ dst, src.x-y10
*
* becomes:
*
* MAD dst {1,-1,0,0}, src.xyxx, {0,0,1,0}
*/
static void emit_swz( struct st_translate *t,
struct ureg_dst dst,
const struct prog_src_register *SrcReg )
{
struct ureg_program *ureg = t->ureg;
struct ureg_src src = src_register( t, SrcReg->File, SrcReg->Index );
 
unsigned negate_mask = SrcReg->Negate;
 
unsigned one_mask = ((GET_SWZ(SrcReg->Swizzle, 0) == SWIZZLE_ONE) << 0 |
(GET_SWZ(SrcReg->Swizzle, 1) == SWIZZLE_ONE) << 1 |
(GET_SWZ(SrcReg->Swizzle, 2) == SWIZZLE_ONE) << 2 |
(GET_SWZ(SrcReg->Swizzle, 3) == SWIZZLE_ONE) << 3);
 
unsigned zero_mask = ((GET_SWZ(SrcReg->Swizzle, 0) == SWIZZLE_ZERO) << 0 |
(GET_SWZ(SrcReg->Swizzle, 1) == SWIZZLE_ZERO) << 1 |
(GET_SWZ(SrcReg->Swizzle, 2) == SWIZZLE_ZERO) << 2 |
(GET_SWZ(SrcReg->Swizzle, 3) == SWIZZLE_ZERO) << 3);
 
unsigned negative_one_mask = one_mask & negate_mask;
unsigned positive_one_mask = one_mask & ~negate_mask;
struct ureg_src imm;
unsigned i;
unsigned mul_swizzle[4] = {0,0,0,0};
unsigned add_swizzle[4] = {0,0,0,0};
unsigned src_swizzle[4] = {0,0,0,0};
boolean need_add = FALSE;
boolean need_mul = FALSE;
 
if (dst.WriteMask == 0)
return;
 
/* Is this just a MOV?
*/
if (zero_mask == 0 &&
one_mask == 0 &&
(negate_mask == 0 || negate_mask == TGSI_WRITEMASK_XYZW))
{
ureg_MOV( ureg, dst, translate_src( t, SrcReg ));
return;
}
 
#define IMM_ZERO 0
#define IMM_ONE 1
#define IMM_NEG_ONE 2
 
imm = ureg_imm3f( ureg, 0, 1, -1 );
 
for (i = 0; i < 4; i++) {
unsigned bit = 1 << i;
 
if (dst.WriteMask & bit) {
if (positive_one_mask & bit) {
mul_swizzle[i] = IMM_ZERO;
add_swizzle[i] = IMM_ONE;
need_add = TRUE;
}
else if (negative_one_mask & bit) {
mul_swizzle[i] = IMM_ZERO;
add_swizzle[i] = IMM_NEG_ONE;
need_add = TRUE;
}
else if (zero_mask & bit) {
mul_swizzle[i] = IMM_ZERO;
add_swizzle[i] = IMM_ZERO;
need_add = TRUE;
}
else {
add_swizzle[i] = IMM_ZERO;
src_swizzle[i] = GET_SWZ(SrcReg->Swizzle, i);
need_mul = TRUE;
if (negate_mask & bit) {
mul_swizzle[i] = IMM_NEG_ONE;
}
else {
mul_swizzle[i] = IMM_ONE;
}
}
}
}
 
if (need_mul && need_add) {
ureg_MAD( ureg,
dst,
swizzle_4v( src, src_swizzle ),
swizzle_4v( imm, mul_swizzle ),
swizzle_4v( imm, add_swizzle ) );
}
else if (need_mul) {
ureg_MUL( ureg,
dst,
swizzle_4v( src, src_swizzle ),
swizzle_4v( imm, mul_swizzle ) );
}
else if (need_add) {
ureg_MOV( ureg,
dst,
swizzle_4v( imm, add_swizzle ) );
}
else {
debug_assert(0);
}
 
#undef IMM_ZERO
#undef IMM_ONE
#undef IMM_NEG_ONE
}
 
 
/**
* Negate the value of DDY to match GL semantics where (0,0) is the
* lower-left corner of the window.
* Note that the GL_ARB_fragment_coord_conventions extension will
* effect this someday.
*/
static void emit_ddy( struct st_translate *t,
struct ureg_dst dst,
const struct prog_src_register *SrcReg )
{
struct ureg_program *ureg = t->ureg;
struct ureg_src src = translate_src( t, SrcReg );
src = ureg_negate( src );
ureg_DDY( ureg, dst, src );
}
 
 
 
static unsigned
translate_opcode( unsigned op )
{
switch( op ) {
case OPCODE_ARL:
return TGSI_OPCODE_ARL;
case OPCODE_ABS:
return TGSI_OPCODE_ABS;
case OPCODE_ADD:
return TGSI_OPCODE_ADD;
case OPCODE_BGNLOOP:
return TGSI_OPCODE_BGNLOOP;
case OPCODE_BGNSUB:
return TGSI_OPCODE_BGNSUB;
case OPCODE_BRA:
return TGSI_OPCODE_BRA;
case OPCODE_BRK:
return TGSI_OPCODE_BRK;
case OPCODE_CAL:
return TGSI_OPCODE_CAL;
case OPCODE_CMP:
return TGSI_OPCODE_CMP;
case OPCODE_CONT:
return TGSI_OPCODE_CONT;
case OPCODE_COS:
return TGSI_OPCODE_COS;
case OPCODE_DDX:
return TGSI_OPCODE_DDX;
case OPCODE_DDY:
return TGSI_OPCODE_DDY;
case OPCODE_DP2:
return TGSI_OPCODE_DP2;
case OPCODE_DP2A:
return TGSI_OPCODE_DP2A;
case OPCODE_DP3:
return TGSI_OPCODE_DP3;
case OPCODE_DP4:
return TGSI_OPCODE_DP4;
case OPCODE_DPH:
return TGSI_OPCODE_DPH;
case OPCODE_DST:
return TGSI_OPCODE_DST;
case OPCODE_ELSE:
return TGSI_OPCODE_ELSE;
case OPCODE_EMIT_VERTEX:
return TGSI_OPCODE_EMIT;
case OPCODE_END_PRIMITIVE:
return TGSI_OPCODE_ENDPRIM;
case OPCODE_ENDIF:
return TGSI_OPCODE_ENDIF;
case OPCODE_ENDLOOP:
return TGSI_OPCODE_ENDLOOP;
case OPCODE_ENDSUB:
return TGSI_OPCODE_ENDSUB;
case OPCODE_EX2:
return TGSI_OPCODE_EX2;
case OPCODE_EXP:
return TGSI_OPCODE_EXP;
case OPCODE_FLR:
return TGSI_OPCODE_FLR;
case OPCODE_FRC:
return TGSI_OPCODE_FRC;
case OPCODE_IF:
return TGSI_OPCODE_IF;
case OPCODE_TRUNC:
return TGSI_OPCODE_TRUNC;
case OPCODE_KIL:
return TGSI_OPCODE_KIL;
case OPCODE_KIL_NV:
return TGSI_OPCODE_KILP;
case OPCODE_LG2:
return TGSI_OPCODE_LG2;
case OPCODE_LOG:
return TGSI_OPCODE_LOG;
case OPCODE_LIT:
return TGSI_OPCODE_LIT;
case OPCODE_LRP:
return TGSI_OPCODE_LRP;
case OPCODE_MAD:
return TGSI_OPCODE_MAD;
case OPCODE_MAX:
return TGSI_OPCODE_MAX;
case OPCODE_MIN:
return TGSI_OPCODE_MIN;
case OPCODE_MOV:
return TGSI_OPCODE_MOV;
case OPCODE_MUL:
return TGSI_OPCODE_MUL;
case OPCODE_NOP:
return TGSI_OPCODE_NOP;
case OPCODE_NRM3:
return TGSI_OPCODE_NRM;
case OPCODE_NRM4:
return TGSI_OPCODE_NRM4;
case OPCODE_POW:
return TGSI_OPCODE_POW;
case OPCODE_RCP:
return TGSI_OPCODE_RCP;
case OPCODE_RET:
return TGSI_OPCODE_RET;
case OPCODE_RSQ:
return TGSI_OPCODE_RSQ;
case OPCODE_SCS:
return TGSI_OPCODE_SCS;
case OPCODE_SEQ:
return TGSI_OPCODE_SEQ;
case OPCODE_SGE:
return TGSI_OPCODE_SGE;
case OPCODE_SGT:
return TGSI_OPCODE_SGT;
case OPCODE_SIN:
return TGSI_OPCODE_SIN;
case OPCODE_SLE:
return TGSI_OPCODE_SLE;
case OPCODE_SLT:
return TGSI_OPCODE_SLT;
case OPCODE_SNE:
return TGSI_OPCODE_SNE;
case OPCODE_SSG:
return TGSI_OPCODE_SSG;
case OPCODE_SUB:
return TGSI_OPCODE_SUB;
case OPCODE_TEX:
return TGSI_OPCODE_TEX;
case OPCODE_TXB:
return TGSI_OPCODE_TXB;
case OPCODE_TXD:
return TGSI_OPCODE_TXD;
case OPCODE_TXL:
return TGSI_OPCODE_TXL;
case OPCODE_TXP:
return TGSI_OPCODE_TXP;
case OPCODE_XPD:
return TGSI_OPCODE_XPD;
case OPCODE_END:
return TGSI_OPCODE_END;
default:
debug_assert( 0 );
return TGSI_OPCODE_NOP;
}
}
 
 
static void
compile_instruction(
struct st_translate *t,
const struct prog_instruction *inst )
{
struct ureg_program *ureg = t->ureg;
GLuint i;
struct ureg_dst dst[1];
struct ureg_src src[4];
unsigned num_dst;
unsigned num_src;
 
num_dst = _mesa_num_inst_dst_regs( inst->Opcode );
num_src = _mesa_num_inst_src_regs( inst->Opcode );
 
if (num_dst)
dst[0] = translate_dst( t,
&inst->DstReg,
inst->SaturateMode );
 
for (i = 0; i < num_src; i++)
src[i] = translate_src( t, &inst->SrcReg[i] );
 
switch( inst->Opcode ) {
case OPCODE_SWZ:
emit_swz( t, dst[0], &inst->SrcReg[0] );
return;
 
case OPCODE_BGNLOOP:
case OPCODE_CAL:
case OPCODE_ELSE:
case OPCODE_ENDLOOP:
case OPCODE_IF:
debug_assert(num_dst == 0);
ureg_label_insn( ureg,
translate_opcode( inst->Opcode ),
src, num_src,
get_label( t, inst->BranchTarget ));
return;
 
case OPCODE_TEX:
case OPCODE_TXB:
case OPCODE_TXD:
case OPCODE_TXL:
case OPCODE_TXP:
src[num_src++] = t->samplers[inst->TexSrcUnit];
ureg_tex_insn( ureg,
translate_opcode( inst->Opcode ),
dst, num_dst,
translate_texture_target( inst->TexSrcTarget,
inst->TexShadow ),
src, num_src );
return;
 
case OPCODE_SCS:
dst[0] = ureg_writemask(dst[0], TGSI_WRITEMASK_XY );
ureg_insn( ureg,
translate_opcode( inst->Opcode ),
dst, num_dst,
src, num_src );
break;
 
case OPCODE_XPD:
dst[0] = ureg_writemask(dst[0], TGSI_WRITEMASK_XYZ );
ureg_insn( ureg,
translate_opcode( inst->Opcode ),
dst, num_dst,
src, num_src );
break;
 
case OPCODE_NOISE1:
case OPCODE_NOISE2:
case OPCODE_NOISE3:
case OPCODE_NOISE4:
/* At some point, a motivated person could add a better
* implementation of noise. Currently not even the nvidia
* binary drivers do anything more than this. In any case, the
* place to do this is in the GL state tracker, not the poor
* driver.
*/
ureg_MOV( ureg, dst[0], ureg_imm1f(ureg, 0.5) );
break;
case OPCODE_DDY:
emit_ddy( t, dst[0], &inst->SrcReg[0] );
break;
 
default:
ureg_insn( ureg,
translate_opcode( inst->Opcode ),
dst, num_dst,
src, num_src );
break;
}
}
 
 
/**
* Emit the TGSI instructions to adjust the WPOS pixel center convention
* Basically, add (adjX, adjY) to the fragment position.
*/
static void
emit_adjusted_wpos( struct st_translate *t,
const struct gl_program *program,
GLfloat adjX, GLfloat adjY)
{
struct ureg_program *ureg = t->ureg;
struct ureg_dst wpos_temp = ureg_DECL_temporary(ureg);
struct ureg_src wpos_input = t->inputs[t->inputMapping[FRAG_ATTRIB_WPOS]];
 
/* Note that we bias X and Y and pass Z and W through unchanged.
* The shader might also use gl_FragCoord.w and .z.
*/
ureg_ADD(ureg, wpos_temp, wpos_input,
ureg_imm4f(ureg, adjX, adjY, 0.0f, 0.0f));
 
t->inputs[t->inputMapping[FRAG_ATTRIB_WPOS]] = ureg_src(wpos_temp);
}
 
 
/**
* Emit the TGSI instructions for inverting the WPOS y coordinate.
* This code is unavoidable because it also depends on whether
* a FBO is bound (STATE_FB_WPOS_Y_TRANSFORM).
*/
static void
emit_wpos_inversion( struct st_translate *t,
const struct gl_program *program,
boolean invert)
{
struct ureg_program *ureg = t->ureg;
 
/* Fragment program uses fragment position input.
* Need to replace instances of INPUT[WPOS] with temp T
* where T = INPUT[WPOS] by y is inverted.
*/
static const gl_state_index wposTransformState[STATE_LENGTH]
= { STATE_INTERNAL, STATE_FB_WPOS_Y_TRANSFORM, 0, 0, 0 };
/* XXX: note we are modifying the incoming shader here! Need to
* do this before emitting the constant decls below, or this
* will be missed:
*/
unsigned wposTransConst = _mesa_add_state_reference(program->Parameters,
wposTransformState);
 
struct ureg_src wpostrans = ureg_DECL_constant( ureg, wposTransConst );
struct ureg_dst wpos_temp;
struct ureg_src wpos_input = t->inputs[t->inputMapping[FRAG_ATTRIB_WPOS]];
 
/* MOV wpos_temp, input[wpos]
*/
if (wpos_input.File == TGSI_FILE_TEMPORARY)
wpos_temp = ureg_dst(wpos_input);
else {
wpos_temp = ureg_DECL_temporary( ureg );
ureg_MOV( ureg, wpos_temp, wpos_input );
}
 
if (invert) {
/* MAD wpos_temp.y, wpos_input, wpostrans.xxxx, wpostrans.yyyy
*/
ureg_MAD( ureg,
ureg_writemask(wpos_temp, TGSI_WRITEMASK_Y ),
wpos_input,
ureg_scalar(wpostrans, 0),
ureg_scalar(wpostrans, 1));
} else {
/* MAD wpos_temp.y, wpos_input, wpostrans.zzzz, wpostrans.wwww
*/
ureg_MAD( ureg,
ureg_writemask(wpos_temp, TGSI_WRITEMASK_Y ),
wpos_input,
ureg_scalar(wpostrans, 2),
ureg_scalar(wpostrans, 3));
}
 
/* Use wpos_temp as position input from here on:
*/
t->inputs[t->inputMapping[FRAG_ATTRIB_WPOS]] = ureg_src(wpos_temp);
}
 
 
/**
* Emit fragment position/ooordinate code.
*/
static void
emit_wpos(struct st_context *st,
struct st_translate *t,
const struct gl_program *program,
struct ureg_program *ureg)
{
const struct gl_fragment_program *fp =
(const struct gl_fragment_program *) program;
struct pipe_screen *pscreen = st->pipe->screen;
boolean invert = FALSE;
 
if (fp->OriginUpperLeft) {
if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT)) {
}
else if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT)) {
ureg_property_fs_coord_origin(ureg, TGSI_FS_COORD_ORIGIN_LOWER_LEFT);
invert = TRUE;
}
else
assert(0);
}
else {
if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT))
ureg_property_fs_coord_origin(ureg, TGSI_FS_COORD_ORIGIN_LOWER_LEFT);
else if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_ORIGIN_UPPER_LEFT))
invert = TRUE;
else
assert(0);
}
if (fp->PixelCenterInteger) {
if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER))
ureg_property_fs_coord_pixel_center(ureg, TGSI_FS_COORD_PIXEL_CENTER_INTEGER);
else if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER))
emit_adjusted_wpos(t, program, 0.5f, invert ? 0.5f : -0.5f);
else
assert(0);
}
else {
if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_HALF_INTEGER)) {
}
else if (pscreen->get_param(pscreen, PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER)) {
ureg_property_fs_coord_pixel_center(ureg, TGSI_FS_COORD_PIXEL_CENTER_INTEGER);
emit_adjusted_wpos(t, program, 0.5f, invert ? -0.5f : 0.5f);
}
else
assert(0);
}
 
/* we invert after adjustment so that we avoid the MOV to temporary,
* and reuse the adjustment ADD instead */
emit_wpos_inversion(t, program, invert);
}
 
 
/**
* OpenGL's fragment gl_FrontFace input is 1 for front-facing, 0 for back.
* TGSI uses +1 for front, -1 for back.
* This function converts the TGSI value to the GL value. Simply clamping/
* saturating the value to [0,1] does the job.
*/
static void
emit_face_var( struct st_translate *t,
const struct gl_program *program )
{
struct ureg_program *ureg = t->ureg;
struct ureg_dst face_temp = ureg_DECL_temporary( ureg );
struct ureg_src face_input = t->inputs[t->inputMapping[FRAG_ATTRIB_FACE]];
 
/* MOV_SAT face_temp, input[face]
*/
face_temp = ureg_saturate( face_temp );
ureg_MOV( ureg, face_temp, face_input );
 
/* Use face_temp as face input from here on:
*/
t->inputs[t->inputMapping[FRAG_ATTRIB_FACE]] = ureg_src(face_temp);
}
 
 
static void
emit_edgeflags( struct st_translate *t,
const struct gl_program *program )
{
struct ureg_program *ureg = t->ureg;
struct ureg_dst edge_dst = t->outputs[t->outputMapping[VERT_RESULT_EDGE]];
struct ureg_src edge_src = t->inputs[t->inputMapping[VERT_ATTRIB_EDGEFLAG]];
 
ureg_MOV( ureg, edge_dst, edge_src );
}
 
 
/**
* Translate Mesa program to TGSI format.
* \param program the program to translate
* \param numInputs number of input registers used
* \param inputMapping maps Mesa fragment program inputs to TGSI generic
* input indexes
* \param inputSemanticName the TGSI_SEMANTIC flag for each input
* \param inputSemanticIndex the semantic index (ex: which texcoord) for
* each input
* \param interpMode the TGSI_INTERPOLATE_LINEAR/PERSP mode for each input
* \param numOutputs number of output registers used
* \param outputMapping maps Mesa fragment program outputs to TGSI
* generic outputs
* \param outputSemanticName the TGSI_SEMANTIC flag for each output
* \param outputSemanticIndex the semantic index (ex: which texcoord) for
* each output
*
* \return PIPE_OK or PIPE_ERROR_OUT_OF_MEMORY
*/
enum pipe_error
st_translate_mesa_program(
struct gl_context *ctx,
uint procType,
struct ureg_program *ureg,
const struct gl_program *program,
GLuint numInputs,
const GLuint inputMapping[],
const ubyte inputSemanticName[],
const ubyte inputSemanticIndex[],
const GLuint interpMode[],
GLuint numOutputs,
const GLuint outputMapping[],
const ubyte outputSemanticName[],
const ubyte outputSemanticIndex[],
boolean passthrough_edgeflags )
{
struct st_translate translate, *t;
unsigned i;
enum pipe_error ret = PIPE_OK;
 
assert(numInputs <= Elements(t->inputs));
assert(numOutputs <= Elements(t->outputs));
 
t = &translate;
memset(t, 0, sizeof *t);
 
t->procType = procType;
t->inputMapping = inputMapping;
t->outputMapping = outputMapping;
t->ureg = ureg;
t->pointSizeOutIndex = -1;
t->prevInstWrotePointSize = GL_FALSE;
 
/*_mesa_print_program(program);*/
 
/*
* Declare input attributes.
*/
if (procType == TGSI_PROCESSOR_FRAGMENT) {
for (i = 0; i < numInputs; i++) {
if (program->InputFlags[0] & PROG_PARAM_BIT_CYL_WRAP) {
t->inputs[i] = ureg_DECL_fs_input_cyl(ureg,
inputSemanticName[i],
inputSemanticIndex[i],
interpMode[i],
TGSI_CYLINDRICAL_WRAP_X);
}
else {
t->inputs[i] = ureg_DECL_fs_input(ureg,
inputSemanticName[i],
inputSemanticIndex[i],
interpMode[i]);
}
}
 
if (program->InputsRead & FRAG_BIT_WPOS) {
/* Must do this after setting up t->inputs, and before
* emitting constant references, below:
*/
emit_wpos(st_context(ctx), t, program, ureg);
}
 
if (program->InputsRead & FRAG_BIT_FACE) {
emit_face_var( t, program );
}
 
/*
* Declare output attributes.
*/
for (i = 0; i < numOutputs; i++) {
switch (outputSemanticName[i]) {
case TGSI_SEMANTIC_POSITION:
t->outputs[i] = ureg_DECL_output( ureg,
TGSI_SEMANTIC_POSITION, /* Z / Depth */
outputSemanticIndex[i] );
 
t->outputs[i] = ureg_writemask( t->outputs[i],
TGSI_WRITEMASK_Z );
break;
case TGSI_SEMANTIC_STENCIL:
t->outputs[i] = ureg_DECL_output( ureg,
TGSI_SEMANTIC_STENCIL, /* Stencil */
outputSemanticIndex[i] );
t->outputs[i] = ureg_writemask( t->outputs[i],
TGSI_WRITEMASK_Y );
break;
case TGSI_SEMANTIC_COLOR:
t->outputs[i] = ureg_DECL_output( ureg,
TGSI_SEMANTIC_COLOR,
outputSemanticIndex[i] );
break;
default:
debug_assert(0);
return 0;
}
}
}
else if (procType == TGSI_PROCESSOR_GEOMETRY) {
for (i = 0; i < numInputs; i++) {
t->inputs[i] = ureg_DECL_gs_input(ureg,
i,
inputSemanticName[i],
inputSemanticIndex[i]);
}
 
for (i = 0; i < numOutputs; i++) {
t->outputs[i] = ureg_DECL_output( ureg,
outputSemanticName[i],
outputSemanticIndex[i] );
}
}
else {
assert(procType == TGSI_PROCESSOR_VERTEX);
 
for (i = 0; i < numInputs; i++) {
t->inputs[i] = ureg_DECL_vs_input(ureg, i);
}
 
for (i = 0; i < numOutputs; i++) {
t->outputs[i] = ureg_DECL_output( ureg,
outputSemanticName[i],
outputSemanticIndex[i] );
if ((outputSemanticName[i] == TGSI_SEMANTIC_PSIZE) && program->Id) {
/* Writing to the point size result register requires special
* handling to implement clamping.
*/
static const gl_state_index pointSizeClampState[STATE_LENGTH]
= { STATE_INTERNAL, STATE_POINT_SIZE_IMPL_CLAMP, 0, 0, 0 };
/* XXX: note we are modifying the incoming shader here! Need to
* do this before emitting the constant decls below, or this
* will be missed:
*/
unsigned pointSizeClampConst =
_mesa_add_state_reference(program->Parameters,
pointSizeClampState);
struct ureg_dst psizregtemp = ureg_DECL_temporary( ureg );
t->pointSizeConst = ureg_DECL_constant( ureg, pointSizeClampConst );
t->pointSizeResult = t->outputs[i];
t->pointSizeOutIndex = i;
t->outputs[i] = psizregtemp;
}
}
if (passthrough_edgeflags)
emit_edgeflags( t, program );
}
 
/* Declare address register.
*/
if (program->NumAddressRegs > 0) {
debug_assert( program->NumAddressRegs == 1 );
t->address[0] = ureg_DECL_address( ureg );
}
 
if (program->IndirectRegisterFiles & (1 << PROGRAM_TEMPORARY)) {
/* If temps are accessed with indirect addressing, declare temporaries
* in sequential order. Else, we declare them on demand elsewhere.
*/
for (i = 0; i < program->NumTemporaries; i++) {
/* XXX use TGSI_FILE_TEMPORARY_ARRAY when it's supported by ureg */
t->temps[i] = ureg_DECL_temporary( t->ureg );
}
}
 
/* Emit constants and immediates. Mesa uses a single index space
* for these, so we put all the translated regs in t->constants.
*/
if (program->Parameters) {
t->constants = CALLOC( program->Parameters->NumParameters,
sizeof t->constants[0] );
if (t->constants == NULL) {
ret = PIPE_ERROR_OUT_OF_MEMORY;
goto out;
}
 
for (i = 0; i < program->Parameters->NumParameters; i++) {
switch (program->Parameters->Parameters[i].Type) {
case PROGRAM_ENV_PARAM:
case PROGRAM_LOCAL_PARAM:
case PROGRAM_STATE_VAR:
case PROGRAM_NAMED_PARAM:
case PROGRAM_UNIFORM:
t->constants[i] = ureg_DECL_constant( ureg, i );
break;
 
/* Emit immediates only when there's no indirect addressing of
* the const buffer.
* FIXME: Be smarter and recognize param arrays:
* indirect addressing is only valid within the referenced
* array.
*/
case PROGRAM_CONSTANT:
if (program->IndirectRegisterFiles & PROGRAM_ANY_CONST)
t->constants[i] = ureg_DECL_constant( ureg, i );
else
t->constants[i] =
ureg_DECL_immediate( ureg,
program->Parameters->ParameterValues[i],
4 );
break;
default:
break;
}
}
}
 
/* texture samplers */
for (i = 0; i < ctx->Const.MaxTextureImageUnits; i++) {
if (program->SamplersUsed & (1 << i)) {
t->samplers[i] = ureg_DECL_sampler( ureg, i );
}
}
 
/* Emit each instruction in turn:
*/
for (i = 0; i < program->NumInstructions; i++) {
set_insn_start( t, ureg_get_instruction_number( ureg ));
compile_instruction( t, &program->Instructions[i] );
 
if (t->prevInstWrotePointSize && program->Id) {
/* The previous instruction wrote to the (fake) vertex point size
* result register. Now we need to clamp that value to the min/max
* point size range, putting the result into the real point size
* register.
* Note that we can't do this easily at the end of program due to
* possible early return.
*/
set_insn_start( t, ureg_get_instruction_number( ureg ));
ureg_MAX( t->ureg,
ureg_writemask(t->outputs[t->pointSizeOutIndex], WRITEMASK_X),
ureg_src(t->outputs[t->pointSizeOutIndex]),
ureg_swizzle(t->pointSizeConst, 1,1,1,1));
ureg_MIN( t->ureg, ureg_writemask(t->pointSizeResult, WRITEMASK_X),
ureg_src(t->outputs[t->pointSizeOutIndex]),
ureg_swizzle(t->pointSizeConst, 2,2,2,2));
}
t->prevInstWrotePointSize = GL_FALSE;
}
 
/* Fix up all emitted labels:
*/
for (i = 0; i < t->labels_count; i++) {
ureg_fixup_label( ureg,
t->labels[i].token,
t->insn[t->labels[i].branch_target] );
}
 
out:
FREE(t->insn);
FREE(t->labels);
FREE(t->constants);
 
if (t->error) {
debug_printf("%s: translate error flag set\n", __FUNCTION__);
}
 
return ret;
}
 
 
/**
* Tokens cannot be free with free otherwise the builtin gallium
* malloc debugging will get confused.
*/
void
st_free_tokens(const struct tgsi_token *tokens)
{
FREE((void *)tokens);
}
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_mesa_to_tgsi.h
0,0 → 1,71
/**************************************************************************
*
* 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 ST_MESA_TO_TGSI_H
#define ST_MESA_TO_TGSI_H
 
#include "main/mtypes.h"
 
#include "pipe/p_compiler.h"
 
struct ureg_program;
 
#if defined __cplusplus
extern "C" {
#endif
 
struct tgsi_token;
struct gl_program;
 
enum pipe_error
st_translate_mesa_program(
struct gl_context *ctx,
uint procType,
struct ureg_program *ureg,
const struct gl_program *program,
GLuint numInputs,
const GLuint inputMapping[],
const ubyte inputSemanticName[],
const ubyte inputSemanticIndex[],
const GLuint interpMode[],
GLuint numOutputs,
const GLuint outputMapping[],
const ubyte outputSemanticName[],
const ubyte outputSemanticIndex[],
boolean passthrough_edgeflags );
 
void
st_free_tokens(const struct tgsi_token *tokens);
 
 
#if defined __cplusplus
} /* extern "C" */
#endif
 
#endif /* ST_MESA_TO_TGSI_H */
 
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_program.c
0,0 → 1,761
/**************************************************************************
*
* 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 "main/imports.h"
#include "main/mtypes.h"
#include "program/prog_print.h"
#include "program/programopt.h"
 
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "pipe/p_shader_tokens.h"
#include "draw/draw_context.h"
#include "tgsi/tgsi_dump.h"
#include "tgsi/tgsi_ureg.h"
 
#include "st_debug.h"
#include "st_context.h"
#include "st_program.h"
#include "st_mesa_to_tgsi.h"
#include "cso_cache/cso_context.h"
 
 
 
/**
* Clean out any old compilations:
*/
void
st_vp_release_varients( struct st_context *st,
struct st_vertex_program *stvp )
{
struct st_vp_varient *vpv;
 
for (vpv = stvp->varients; vpv; ) {
struct st_vp_varient *next = vpv->next;
 
if (vpv->driver_shader)
cso_delete_vertex_shader(st->cso_context, vpv->driver_shader);
#if FEATURE_feedback || FEATURE_rastpos
if (vpv->draw_shader)
draw_delete_vertex_shader( st->draw, vpv->draw_shader );
#endif
if (vpv->tgsi.tokens)
st_free_tokens(vpv->tgsi.tokens);
FREE( vpv );
 
vpv = next;
}
 
stvp->varients = NULL;
}
 
 
 
 
/**
* Translate a Mesa vertex shader into a TGSI shader.
* \param outputMapping to map vertex program output registers (VERT_RESULT_x)
* to TGSI output slots
* \param tokensOut destination for TGSI tokens
* \return pointer to cached pipe_shader object.
*/
void
st_prepare_vertex_program(struct st_context *st,
struct st_vertex_program *stvp)
{
GLuint attr;
 
stvp->num_inputs = 0;
stvp->num_outputs = 0;
 
if (stvp->Base.IsPositionInvariant)
_mesa_insert_mvp_code(st->ctx, &stvp->Base);
 
assert(stvp->Base.Base.NumInstructions > 1);
 
/*
* Determine number of inputs, the mappings between VERT_ATTRIB_x
* and TGSI generic input indexes, plus input attrib semantic info.
*/
for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) {
if (stvp->Base.Base.InputsRead & (1 << attr)) {
stvp->input_to_index[attr] = stvp->num_inputs;
stvp->index_to_input[stvp->num_inputs] = attr;
stvp->num_inputs++;
}
}
/* bit of a hack, presetup potentially unused edgeflag input */
stvp->input_to_index[VERT_ATTRIB_EDGEFLAG] = stvp->num_inputs;
stvp->index_to_input[stvp->num_inputs] = VERT_ATTRIB_EDGEFLAG;
 
/* Compute mapping of vertex program outputs to slots.
*/
for (attr = 0; attr < VERT_RESULT_MAX; attr++) {
if ((stvp->Base.Base.OutputsWritten & BITFIELD64_BIT(attr)) == 0) {
stvp->result_to_output[attr] = ~0;
}
else {
unsigned slot = stvp->num_outputs++;
 
stvp->result_to_output[attr] = slot;
 
switch (attr) {
case VERT_RESULT_HPOS:
stvp->output_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
stvp->output_semantic_index[slot] = 0;
break;
case VERT_RESULT_COL0:
stvp->output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
stvp->output_semantic_index[slot] = 0;
break;
case VERT_RESULT_COL1:
stvp->output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
stvp->output_semantic_index[slot] = 1;
break;
case VERT_RESULT_BFC0:
stvp->output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
stvp->output_semantic_index[slot] = 0;
break;
case VERT_RESULT_BFC1:
stvp->output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
stvp->output_semantic_index[slot] = 1;
break;
case VERT_RESULT_FOGC:
stvp->output_semantic_name[slot] = TGSI_SEMANTIC_FOG;
stvp->output_semantic_index[slot] = 0;
break;
case VERT_RESULT_PSIZ:
stvp->output_semantic_name[slot] = TGSI_SEMANTIC_PSIZE;
stvp->output_semantic_index[slot] = 0;
break;
case VERT_RESULT_EDGE:
assert(0);
break;
 
case VERT_RESULT_TEX0:
case VERT_RESULT_TEX1:
case VERT_RESULT_TEX2:
case VERT_RESULT_TEX3:
case VERT_RESULT_TEX4:
case VERT_RESULT_TEX5:
case VERT_RESULT_TEX6:
case VERT_RESULT_TEX7:
stvp->output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
stvp->output_semantic_index[slot] = attr - VERT_RESULT_TEX0;
break;
 
case VERT_RESULT_VAR0:
default:
assert(attr < VERT_RESULT_MAX);
stvp->output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
stvp->output_semantic_index[slot] = (FRAG_ATTRIB_VAR0 -
FRAG_ATTRIB_TEX0 +
attr -
VERT_RESULT_VAR0);
break;
}
}
}
/* similar hack to above, presetup potentially unused edgeflag output */
stvp->result_to_output[VERT_RESULT_EDGE] = stvp->num_outputs;
stvp->output_semantic_name[stvp->num_outputs] = TGSI_SEMANTIC_EDGEFLAG;
stvp->output_semantic_index[stvp->num_outputs] = 0;
}
 
 
struct st_vp_varient *
st_translate_vertex_program(struct st_context *st,
struct st_vertex_program *stvp,
const struct st_vp_varient_key *key)
{
struct st_vp_varient *vpv = CALLOC_STRUCT(st_vp_varient);
struct pipe_context *pipe = st->pipe;
struct ureg_program *ureg;
enum pipe_error error;
unsigned num_outputs;
 
_mesa_remove_output_reads(&stvp->Base.Base, PROGRAM_OUTPUT);
_mesa_remove_output_reads(&stvp->Base.Base, PROGRAM_VARYING);
 
ureg = ureg_create( TGSI_PROCESSOR_VERTEX );
if (ureg == NULL) {
FREE(vpv);
return NULL;
}
 
vpv->key = *key;
 
vpv->num_inputs = stvp->num_inputs;
num_outputs = stvp->num_outputs;
if (key->passthrough_edgeflags) {
vpv->num_inputs++;
num_outputs++;
}
 
if (ST_DEBUG & DEBUG_MESA) {
_mesa_print_program(&stvp->Base.Base);
_mesa_print_program_parameters(st->ctx, &stvp->Base.Base);
debug_printf("\n");
}
 
error =
st_translate_mesa_program(st->ctx,
TGSI_PROCESSOR_VERTEX,
ureg,
&stvp->Base.Base,
/* inputs */
vpv->num_inputs,
stvp->input_to_index,
NULL, /* input semantic name */
NULL, /* input semantic index */
NULL,
/* outputs */
num_outputs,
stvp->result_to_output,
stvp->output_semantic_name,
stvp->output_semantic_index,
key->passthrough_edgeflags );
 
if (error)
goto fail;
 
vpv->tgsi.tokens = ureg_get_tokens( ureg, NULL );
if (!vpv->tgsi.tokens)
goto fail;
 
ureg_destroy( ureg );
 
vpv->driver_shader = pipe->create_vs_state(pipe, &vpv->tgsi);
 
if (ST_DEBUG & DEBUG_TGSI) {
tgsi_dump( vpv->tgsi.tokens, 0 );
debug_printf("\n");
}
 
return vpv;
 
fail:
debug_printf("%s: failed to translate Mesa program:\n", __FUNCTION__);
_mesa_print_program(&stvp->Base.Base);
debug_assert(0);
 
ureg_destroy( ureg );
return NULL;
}
 
 
 
/**
* Translate a Mesa fragment shader into a TGSI shader.
* \return pointer to cached pipe_shader object.
*/
void
st_translate_fragment_program(struct st_context *st,
struct st_fragment_program *stfp )
{
struct pipe_context *pipe = st->pipe;
GLuint outputMapping[FRAG_RESULT_MAX];
GLuint inputMapping[FRAG_ATTRIB_MAX];
GLuint interpMode[PIPE_MAX_SHADER_INPUTS]; /* XXX size? */
GLuint attr;
enum pipe_error error;
const GLbitfield inputsRead = stfp->Base.Base.InputsRead;
struct ureg_program *ureg;
 
ubyte input_semantic_name[PIPE_MAX_SHADER_INPUTS];
ubyte input_semantic_index[PIPE_MAX_SHADER_INPUTS];
uint fs_num_inputs = 0;
 
ubyte fs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS];
ubyte fs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS];
uint fs_num_outputs = 0;
 
_mesa_remove_output_reads(&stfp->Base.Base, PROGRAM_OUTPUT);
 
/*
* Convert Mesa program inputs to TGSI input register semantics.
*/
for (attr = 0; attr < FRAG_ATTRIB_MAX; attr++) {
if (inputsRead & (1 << attr)) {
const GLuint slot = fs_num_inputs++;
 
inputMapping[attr] = slot;
 
switch (attr) {
case FRAG_ATTRIB_WPOS:
input_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
input_semantic_index[slot] = 0;
interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
break;
case FRAG_ATTRIB_COL0:
input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
input_semantic_index[slot] = 0;
interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
break;
case FRAG_ATTRIB_COL1:
input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
input_semantic_index[slot] = 1;
interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
break;
case FRAG_ATTRIB_FOGC:
input_semantic_name[slot] = TGSI_SEMANTIC_FOG;
input_semantic_index[slot] = 0;
interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
break;
case FRAG_ATTRIB_FACE:
input_semantic_name[slot] = TGSI_SEMANTIC_FACE;
input_semantic_index[slot] = 0;
interpMode[slot] = TGSI_INTERPOLATE_CONSTANT;
break;
/* In most cases, there is nothing special about these
* inputs, so adopt a convention to use the generic
* semantic name and the mesa FRAG_ATTRIB_ number as the
* index.
*
* All that is required is that the vertex shader labels
* its own outputs similarly, and that the vertex shader
* generates at least every output required by the
* fragment shader plus fixed-function hardware (such as
* BFC).
*
* There is no requirement that semantic indexes start at
* zero or be restricted to a particular range -- nobody
* should be building tables based on semantic index.
*/
case FRAG_ATTRIB_PNTC:
case FRAG_ATTRIB_TEX0:
case FRAG_ATTRIB_TEX1:
case FRAG_ATTRIB_TEX2:
case FRAG_ATTRIB_TEX3:
case FRAG_ATTRIB_TEX4:
case FRAG_ATTRIB_TEX5:
case FRAG_ATTRIB_TEX6:
case FRAG_ATTRIB_TEX7:
case FRAG_ATTRIB_VAR0:
default:
/* Actually, let's try and zero-base this just for
* readability of the generated TGSI.
*/
assert(attr >= FRAG_ATTRIB_TEX0);
input_semantic_index[slot] = (attr - FRAG_ATTRIB_TEX0);
input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
if (attr == FRAG_ATTRIB_PNTC)
interpMode[slot] = TGSI_INTERPOLATE_LINEAR;
else
interpMode[slot] = TGSI_INTERPOLATE_PERSPECTIVE;
break;
}
}
else {
inputMapping[attr] = -1;
}
}
 
/*
* Semantics and mapping for outputs
*/
{
uint numColors = 0;
GLbitfield64 outputsWritten = stfp->Base.Base.OutputsWritten;
 
/* if z is written, emit that first */
if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH)) {
fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_POSITION;
fs_output_semantic_index[fs_num_outputs] = 0;
outputMapping[FRAG_RESULT_DEPTH] = fs_num_outputs;
fs_num_outputs++;
outputsWritten &= ~(1 << FRAG_RESULT_DEPTH);
}
 
if (outputsWritten & BITFIELD64_BIT(FRAG_RESULT_STENCIL)) {
fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_STENCIL;
fs_output_semantic_index[fs_num_outputs] = 0;
outputMapping[FRAG_RESULT_STENCIL] = fs_num_outputs;
fs_num_outputs++;
outputsWritten &= ~(1 << FRAG_RESULT_STENCIL);
}
 
/* handle remaning outputs (color) */
for (attr = 0; attr < FRAG_RESULT_MAX; attr++) {
if (outputsWritten & BITFIELD64_BIT(attr)) {
switch (attr) {
case FRAG_RESULT_DEPTH:
case FRAG_RESULT_STENCIL:
/* handled above */
assert(0);
break;
default:
assert(attr == FRAG_RESULT_COLOR ||
(FRAG_RESULT_DATA0 <= attr && attr < FRAG_RESULT_MAX));
fs_output_semantic_name[fs_num_outputs] = TGSI_SEMANTIC_COLOR;
fs_output_semantic_index[fs_num_outputs] = numColors;
outputMapping[attr] = fs_num_outputs;
numColors++;
break;
}
 
fs_num_outputs++;
}
}
}
 
ureg = ureg_create( TGSI_PROCESSOR_FRAGMENT );
if (ureg == NULL)
return;
 
if (ST_DEBUG & DEBUG_MESA) {
_mesa_print_program(&stfp->Base.Base);
_mesa_print_program_parameters(st->ctx, &stfp->Base.Base);
debug_printf("\n");
}
 
error =
st_translate_mesa_program(st->ctx,
TGSI_PROCESSOR_FRAGMENT,
ureg,
&stfp->Base.Base,
/* inputs */
fs_num_inputs,
inputMapping,
input_semantic_name,
input_semantic_index,
interpMode,
/* outputs */
fs_num_outputs,
outputMapping,
fs_output_semantic_name,
fs_output_semantic_index, FALSE );
 
stfp->tgsi.tokens = ureg_get_tokens( ureg, NULL );
ureg_destroy( ureg );
stfp->driver_shader = pipe->create_fs_state(pipe, &stfp->tgsi);
 
if (ST_DEBUG & DEBUG_TGSI) {
tgsi_dump( stfp->tgsi.tokens, 0/*TGSI_DUMP_VERBOSE*/ );
debug_printf("\n");
}
}
 
void
st_translate_geometry_program(struct st_context *st,
struct st_geometry_program *stgp)
{
GLuint inputMapping[GEOM_ATTRIB_MAX];
GLuint outputMapping[GEOM_RESULT_MAX];
struct pipe_context *pipe = st->pipe;
enum pipe_error error;
GLuint attr;
const GLbitfield inputsRead = stgp->Base.Base.InputsRead;
GLuint vslot = 0;
GLuint num_generic = 0;
 
uint gs_num_inputs = 0;
uint gs_builtin_inputs = 0;
uint gs_array_offset = 0;
 
ubyte gs_output_semantic_name[PIPE_MAX_SHADER_OUTPUTS];
ubyte gs_output_semantic_index[PIPE_MAX_SHADER_OUTPUTS];
uint gs_num_outputs = 0;
 
GLint i;
GLuint maxSlot = 0;
struct ureg_program *ureg;
 
_mesa_remove_output_reads(&stgp->Base.Base, PROGRAM_OUTPUT);
_mesa_remove_output_reads(&stgp->Base.Base, PROGRAM_VARYING);
 
ureg = ureg_create( TGSI_PROCESSOR_GEOMETRY );
if (ureg == NULL) {
return;
}
 
/* which vertex output goes to the first geometry input */
vslot = 0;
 
memset(inputMapping, 0, sizeof(inputMapping));
memset(outputMapping, 0, sizeof(outputMapping));
 
/*
* Convert Mesa program inputs to TGSI input register semantics.
*/
for (attr = 0; attr < GEOM_ATTRIB_MAX; attr++) {
if (inputsRead & (1 << attr)) {
const GLuint slot = gs_num_inputs;
 
gs_num_inputs++;
 
inputMapping[attr] = slot;
 
stgp->input_map[slot + gs_array_offset] = vslot - gs_builtin_inputs;
stgp->input_to_index[attr] = vslot;
stgp->index_to_input[vslot] = attr;
++vslot;
 
if (attr != GEOM_ATTRIB_PRIMITIVE_ID) {
gs_array_offset += 2;
} else
++gs_builtin_inputs;
 
#if 1
debug_printf("input map at %d = %d\n",
slot + gs_array_offset, stgp->input_map[slot + gs_array_offset]);
#endif
 
switch (attr) {
case GEOM_ATTRIB_PRIMITIVE_ID:
stgp->input_semantic_name[slot] = TGSI_SEMANTIC_PRIMID;
stgp->input_semantic_index[slot] = 0;
break;
case GEOM_ATTRIB_POSITION:
stgp->input_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
stgp->input_semantic_index[slot] = 0;
break;
case GEOM_ATTRIB_COLOR0:
stgp->input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
stgp->input_semantic_index[slot] = 0;
break;
case GEOM_ATTRIB_COLOR1:
stgp->input_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
stgp->input_semantic_index[slot] = 1;
break;
case GEOM_ATTRIB_FOG_FRAG_COORD:
stgp->input_semantic_name[slot] = TGSI_SEMANTIC_FOG;
stgp->input_semantic_index[slot] = 0;
break;
case GEOM_ATTRIB_TEX_COORD:
stgp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
stgp->input_semantic_index[slot] = num_generic++;
break;
case GEOM_ATTRIB_VAR0:
/* fall-through */
default:
stgp->input_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
stgp->input_semantic_index[slot] = num_generic++;
}
}
}
 
/* initialize output semantics to defaults */
for (i = 0; i < PIPE_MAX_SHADER_OUTPUTS; i++) {
gs_output_semantic_name[i] = TGSI_SEMANTIC_GENERIC;
gs_output_semantic_index[i] = 0;
}
 
num_generic = 0;
/*
* Determine number of outputs, the (default) output register
* mapping and the semantic information for each output.
*/
for (attr = 0; attr < GEOM_RESULT_MAX; attr++) {
if (stgp->Base.Base.OutputsWritten & (1 << attr)) {
GLuint slot;
 
slot = gs_num_outputs;
gs_num_outputs++;
outputMapping[attr] = slot;
 
switch (attr) {
case GEOM_RESULT_POS:
assert(slot == 0);
gs_output_semantic_name[slot] = TGSI_SEMANTIC_POSITION;
gs_output_semantic_index[slot] = 0;
break;
case GEOM_RESULT_COL0:
gs_output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
gs_output_semantic_index[slot] = 0;
break;
case GEOM_RESULT_COL1:
gs_output_semantic_name[slot] = TGSI_SEMANTIC_COLOR;
gs_output_semantic_index[slot] = 1;
break;
case GEOM_RESULT_SCOL0:
gs_output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
gs_output_semantic_index[slot] = 0;
break;
case GEOM_RESULT_SCOL1:
gs_output_semantic_name[slot] = TGSI_SEMANTIC_BCOLOR;
gs_output_semantic_index[slot] = 1;
break;
case GEOM_RESULT_FOGC:
gs_output_semantic_name[slot] = TGSI_SEMANTIC_FOG;
gs_output_semantic_index[slot] = 0;
break;
case GEOM_RESULT_PSIZ:
gs_output_semantic_name[slot] = TGSI_SEMANTIC_PSIZE;
gs_output_semantic_index[slot] = 0;
break;
case GEOM_RESULT_TEX0:
case GEOM_RESULT_TEX1:
case GEOM_RESULT_TEX2:
case GEOM_RESULT_TEX3:
case GEOM_RESULT_TEX4:
case GEOM_RESULT_TEX5:
case GEOM_RESULT_TEX6:
case GEOM_RESULT_TEX7:
/* fall-through */
case GEOM_RESULT_VAR0:
/* fall-through */
default:
assert(slot < Elements(gs_output_semantic_name));
/* use default semantic info */
gs_output_semantic_name[slot] = TGSI_SEMANTIC_GENERIC;
gs_output_semantic_index[slot] = num_generic++;
}
}
}
 
assert(gs_output_semantic_name[0] == TGSI_SEMANTIC_POSITION);
 
/* find max output slot referenced to compute gs_num_outputs */
for (attr = 0; attr < GEOM_RESULT_MAX; attr++) {
if (outputMapping[attr] != ~0 && outputMapping[attr] > maxSlot)
maxSlot = outputMapping[attr];
}
gs_num_outputs = maxSlot + 1;
 
#if 0 /* debug */
{
GLuint i;
printf("outputMapping? %d\n", outputMapping ? 1 : 0);
if (outputMapping) {
printf("attr -> slot\n");
for (i = 0; i < 16; i++) {
printf(" %2d %3d\n", i, outputMapping[i]);
}
}
printf("slot sem_name sem_index\n");
for (i = 0; i < gs_num_outputs; i++) {
printf(" %2d %d %d\n",
i,
gs_output_semantic_name[i],
gs_output_semantic_index[i]);
}
}
#endif
 
/* free old shader state, if any */
if (stgp->tgsi.tokens) {
st_free_tokens(stgp->tgsi.tokens);
stgp->tgsi.tokens = NULL;
}
if (stgp->driver_shader) {
cso_delete_geometry_shader(st->cso_context, stgp->driver_shader);
stgp->driver_shader = NULL;
}
 
ureg_property_gs_input_prim(ureg, stgp->Base.InputType);
ureg_property_gs_output_prim(ureg, stgp->Base.OutputType);
ureg_property_gs_max_vertices(ureg, stgp->Base.VerticesOut);
 
error = st_translate_mesa_program(st->ctx,
TGSI_PROCESSOR_GEOMETRY,
ureg,
&stgp->Base.Base,
/* inputs */
gs_num_inputs,
inputMapping,
stgp->input_semantic_name,
stgp->input_semantic_index,
NULL,
/* outputs */
gs_num_outputs,
outputMapping,
gs_output_semantic_name,
gs_output_semantic_index,
FALSE);
 
 
stgp->num_inputs = gs_num_inputs;
stgp->tgsi.tokens = ureg_get_tokens( ureg, NULL );
ureg_destroy( ureg );
stgp->driver_shader = pipe->create_gs_state(pipe, &stgp->tgsi);
 
if ((ST_DEBUG & DEBUG_TGSI) && (ST_DEBUG & DEBUG_MESA)) {
_mesa_print_program(&stgp->Base.Base);
debug_printf("\n");
}
 
if (ST_DEBUG & DEBUG_TGSI) {
tgsi_dump(stgp->tgsi.tokens, 0);
debug_printf("\n");
}
}
 
/**
* Debug- print current shader text
*/
void
st_print_shaders(struct gl_context *ctx)
{
struct gl_shader_program *shProg[3] = {
ctx->Shader.CurrentVertexProgram,
ctx->Shader.CurrentGeometryProgram,
ctx->Shader.CurrentFragmentProgram,
};
unsigned j;
 
for (j = 0; j < 3; j++) {
unsigned i;
 
if (shProg[j] == NULL)
continue;
 
for (i = 0; i < shProg[j]->NumShaders; i++) {
struct gl_shader *sh;
 
switch (shProg[j]->Shaders[i]->Type) {
case GL_VERTEX_SHADER:
sh = (i != 0) ? NULL : shProg[j]->Shaders[i];
break;
case GL_GEOMETRY_SHADER_ARB:
sh = (i != 1) ? NULL : shProg[j]->Shaders[i];
break;
case GL_FRAGMENT_SHADER:
sh = (i != 2) ? NULL : shProg[j]->Shaders[i];
break;
default:
assert(0);
sh = NULL;
break;
}
 
if (sh != NULL) {
printf("GLSL shader %u of %u:\n", i, shProg[j]->NumShaders);
printf("%s\n", sh->Source);
}
}
}
}
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_program.h
0,0 → 1,229
/**************************************************************************
*
* 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.
*
**************************************************************************/
 
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
 
#ifndef ST_PROGRAM_H
#define ST_PROGRAM_H
 
#include "main/mtypes.h"
#include "program/program.h"
#include "pipe/p_state.h"
#include "st_context.h"
 
 
/**
* Derived from Mesa gl_fragment_program:
*/
struct st_fragment_program
{
struct gl_fragment_program Base;
GLuint serialNo;
 
struct pipe_shader_state tgsi;
void *driver_shader;
 
/** Program prefixed with glBitmap prologue */
struct st_fragment_program *bitmap_program;
uint bitmap_sampler;
};
 
 
 
struct st_vp_varient_key
{
boolean passthrough_edgeflags;
};
 
 
/**
* This represents a vertex program, especially translated to match
* the inputs of a particular fragment shader.
*/
struct st_vp_varient
{
/* Parameters which generated this translated version of a vertex
* shader:
*/
struct st_vp_varient_key key;
 
/**
* TGSI tokens (to later generate a 'draw' module shader for
* selection/feedback/rasterpos)
*/
struct pipe_shader_state tgsi;
 
/** Driver's compiled shader */
void *driver_shader;
 
/** For using our private draw module (glRasterPos) */
struct draw_vertex_shader *draw_shader;
 
/** Next in linked list */
struct st_vp_varient *next;
 
/** similar to that in st_vertex_program, but with information about edgeflags too */
GLuint num_inputs;
};
 
 
/**
* Derived from Mesa gl_fragment_program:
*/
struct st_vertex_program
{
struct gl_vertex_program Base; /**< The Mesa vertex program */
GLuint serialNo, lastSerialNo;
 
/** maps a Mesa VERT_ATTRIB_x to a packed TGSI input index */
GLuint input_to_index[VERT_ATTRIB_MAX];
/** maps a TGSI input index back to a Mesa VERT_ATTRIB_x */
GLuint index_to_input[PIPE_MAX_SHADER_INPUTS];
GLuint num_inputs;
 
/** Maps VERT_RESULT_x to slot */
GLuint result_to_output[VERT_RESULT_MAX];
ubyte output_semantic_name[VERT_RESULT_MAX];
ubyte output_semantic_index[VERT_RESULT_MAX];
GLuint num_outputs;
 
/** List of translated varients of this vertex program.
*/
struct st_vp_varient *varients;
};
 
/**
* Derived from Mesa gl_geometry_program:
*/
struct st_geometry_program
{
struct gl_geometry_program Base; /**< The Mesa geometry program */
GLuint serialNo;
 
/** map GP input back to VP output */
GLuint input_map[PIPE_MAX_SHADER_INPUTS];
 
/** maps a Mesa GEOM_ATTRIB_x to a packed TGSI input index */
GLuint input_to_index[GEOM_ATTRIB_MAX];
/** maps a TGSI input index back to a Mesa GEOM_ATTRIB_x */
GLuint index_to_input[PIPE_MAX_SHADER_INPUTS];
 
GLuint num_inputs;
 
GLuint input_to_slot[GEOM_ATTRIB_MAX]; /**< Maps GEOM_ATTRIB_x to slot */
GLuint num_input_slots;
 
ubyte input_semantic_name[PIPE_MAX_SHADER_INPUTS];
ubyte input_semantic_index[PIPE_MAX_SHADER_INPUTS];
 
struct pipe_shader_state tgsi;
void *driver_shader;
};
 
static INLINE struct st_fragment_program *
st_fragment_program( struct gl_fragment_program *fp )
{
return (struct st_fragment_program *)fp;
}
 
 
static INLINE struct st_vertex_program *
st_vertex_program( struct gl_vertex_program *vp )
{
return (struct st_vertex_program *)vp;
}
 
static INLINE struct st_geometry_program *
st_geometry_program( struct gl_geometry_program *vp )
{
return (struct st_geometry_program *)vp;
}
 
static INLINE void
st_reference_vertprog(struct st_context *st,
struct st_vertex_program **ptr,
struct st_vertex_program *prog)
{
_mesa_reference_program(st->ctx,
(struct gl_program **) ptr,
(struct gl_program *) prog);
}
 
static INLINE void
st_reference_geomprog(struct st_context *st,
struct st_geometry_program **ptr,
struct st_geometry_program *prog)
{
_mesa_reference_program(st->ctx,
(struct gl_program **) ptr,
(struct gl_program *) prog);
}
 
static INLINE void
st_reference_fragprog(struct st_context *st,
struct st_fragment_program **ptr,
struct st_fragment_program *prog)
{
_mesa_reference_program(st->ctx,
(struct gl_program **) ptr,
(struct gl_program *) prog);
}
 
 
extern void
st_translate_fragment_program(struct st_context *st,
struct st_fragment_program *fp);
 
extern void
st_translate_geometry_program(struct st_context *st,
struct st_geometry_program *stgp);
 
/* Called after program string change, discard all previous
* compilation results.
*/
extern void
st_prepare_vertex_program(struct st_context *st,
struct st_vertex_program *stvp);
 
extern struct st_vp_varient *
st_translate_vertex_program(struct st_context *st,
struct st_vertex_program *stvp,
const struct st_vp_varient_key *key);
 
void
st_vp_release_varients( struct st_context *st,
struct st_vertex_program *stvp );
 
extern void
st_print_shaders(struct gl_context *ctx);
 
 
#endif
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_texture.c
0,0 → 1,316
/**************************************************************************
*
* 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 <stdio.h>
 
#include "st_context.h"
#include "st_format.h"
#include "st_texture.h"
#include "st_cb_fbo.h"
#include "main/enums.h"
 
#include "pipe/p_state.h"
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
#include "util/u_inlines.h"
#include "util/u_format.h"
#include "util/u_rect.h"
#include "util/u_math.h"
 
 
#define DBG if(0) printf
 
 
/**
* Allocate a new pipe_resource object
* width0, height0, depth0 are the dimensions of the level 0 image
* (the highest resolution). last_level indicates how many mipmap levels
* to allocate storage for. For non-mipmapped textures, this will be zero.
*/
struct pipe_resource *
st_texture_create(struct st_context *st,
enum pipe_texture_target target,
enum pipe_format format,
GLuint last_level,
GLuint width0,
GLuint height0,
GLuint depth0,
GLuint bind )
{
struct pipe_resource pt, *newtex;
struct pipe_screen *screen = st->pipe->screen;
 
assert(target < PIPE_MAX_TEXTURE_TYPES);
assert(width0 > 0);
assert(height0 > 0);
assert(depth0 > 0);
 
DBG("%s target %s format %s last_level %d\n", __FUNCTION__,
_mesa_lookup_enum_by_nr(target),
_mesa_lookup_enum_by_nr(format), last_level);
 
assert(format);
assert(screen->is_format_supported(screen, format, target, 0,
PIPE_BIND_SAMPLER_VIEW, 0));
 
memset(&pt, 0, sizeof(pt));
pt.target = target;
pt.format = format;
pt.last_level = last_level;
pt.width0 = width0;
pt.height0 = height0;
pt.depth0 = depth0;
pt.array_size = (target == PIPE_TEXTURE_CUBE ? 6 : 1);
pt.usage = PIPE_USAGE_DEFAULT;
pt.bind = bind;
pt.flags = 0;
 
newtex = screen->resource_create(screen, &pt);
 
assert(!newtex || pipe_is_referenced(&newtex->reference));
 
return newtex;
}
 
 
/**
* Check if a texture image can be pulled into a unified mipmap texture.
*/
GLboolean
st_texture_match_image(const struct pipe_resource *pt,
const struct gl_texture_image *image,
GLuint face, GLuint level)
{
/* Images with borders are never pulled into mipmap textures.
*/
if (image->Border)
return GL_FALSE;
 
/* Check if this image's format matches the established texture's format.
*/
if (st_mesa_format_to_pipe_format(image->TexFormat) != pt->format)
return GL_FALSE;
 
/* Test if this image's size matches what's expected in the
* established texture.
*/
if (image->Width != u_minify(pt->width0, level) ||
image->Height != u_minify(pt->height0, level) ||
image->Depth != u_minify(pt->depth0, level))
return GL_FALSE;
 
return GL_TRUE;
}
 
 
/**
* Map a texture image and return the address for a particular 2D face/slice/
* layer. The stImage indicates the cube face and mipmap level. The slice
* of the 3D texture is passed in 'zoffset'.
* \param usage one of the PIPE_TRANSFER_x values
* \param x, y, w, h the region of interest of the 2D image.
* \return address of mapping or NULL if any error
*/
GLubyte *
st_texture_image_map(struct st_context *st, struct st_texture_image *stImage,
GLuint zoffset, enum pipe_transfer_usage usage,
GLuint x, GLuint y, GLuint w, GLuint h)
{
struct pipe_context *pipe = st->pipe;
struct pipe_resource *pt = stImage->pt;
 
DBG("%s \n", __FUNCTION__);
 
stImage->transfer = pipe_get_transfer(st->pipe, pt, stImage->level,
stImage->face + zoffset,
usage, x, y, w, h);
 
if (stImage->transfer)
return pipe_transfer_map(pipe, stImage->transfer);
else
return NULL;
}
 
 
void
st_texture_image_unmap(struct st_context *st,
struct st_texture_image *stImage)
{
struct pipe_context *pipe = st->pipe;
 
DBG("%s\n", __FUNCTION__);
 
pipe_transfer_unmap(pipe, stImage->transfer);
 
pipe->transfer_destroy(pipe, stImage->transfer);
}
 
 
 
/**
* Upload data to a rectangular sub-region. Lots of choices how to do this:
*
* - memcpy by span to current destination
* - upload data as new buffer and blit
*
* Currently always memcpy.
*/
static void
st_surface_data(struct pipe_context *pipe,
struct pipe_transfer *dst,
unsigned dstx, unsigned dsty,
const void *src, unsigned src_stride,
unsigned srcx, unsigned srcy, unsigned width, unsigned height)
{
void *map = pipe_transfer_map(pipe, dst);
 
assert(dst->resource);
util_copy_rect(map,
dst->resource->format,
dst->stride,
dstx, dsty,
width, height,
src, src_stride,
srcx, srcy);
 
pipe_transfer_unmap(pipe, dst);
}
 
 
/* Upload data for a particular image.
*/
void
st_texture_image_data(struct st_context *st,
struct pipe_resource *dst,
GLuint face,
GLuint level,
void *src,
GLuint src_row_stride, GLuint src_image_stride)
{
struct pipe_context *pipe = st->pipe;
GLuint depth = u_minify(dst->depth0, level);
GLuint i;
const GLubyte *srcUB = src;
struct pipe_transfer *dst_transfer;
 
DBG("%s\n", __FUNCTION__);
 
for (i = 0; i < depth; i++) {
dst_transfer = pipe_get_transfer(st->pipe, dst, level, face + i,
PIPE_TRANSFER_WRITE, 0, 0,
u_minify(dst->width0, level),
u_minify(dst->height0, level));
 
st_surface_data(pipe, dst_transfer,
0, 0, /* dstx, dsty */
srcUB,
src_row_stride,
0, 0, /* source x, y */
u_minify(dst->width0, level),
u_minify(dst->height0, level)); /* width, height */
 
pipe->transfer_destroy(pipe, dst_transfer);
 
srcUB += src_image_stride;
}
}
 
 
/**
* For debug only: get/print center pixel in the src resource.
*/
static void
print_center_pixel(struct pipe_context *pipe, struct pipe_resource *src)
{
struct pipe_transfer *xfer;
struct pipe_box region;
ubyte *map;
 
region.x = src->width0 / 2;
region.y = src->height0 / 2;
region.z = 0;
region.width = 1;
region.height = 1;
region.depth = 1;
 
xfer = pipe->get_transfer(pipe, src, 0, PIPE_TRANSFER_READ, &region);
map = pipe->transfer_map(pipe, xfer);
 
printf("center pixel: %d %d %d %d\n", map[0], map[1], map[2], map[3]);
 
pipe->transfer_unmap(pipe, xfer);
pipe->transfer_destroy(pipe, xfer);
}
 
 
/**
* Copy the image at level=0 in 'src' to the 'dst' resource at 'dstLevel'.
* This is used to copy mipmap images from one texture buffer to another.
* This typically happens when our initial guess at the total texture size
* is incorrect (see the guess_and_alloc_texture() function).
*/
void
st_texture_image_copy(struct pipe_context *pipe,
struct pipe_resource *dst, GLuint dstLevel,
struct pipe_resource *src, GLuint srcLevel,
GLuint face)
{
GLuint width = u_minify(dst->width0, dstLevel);
GLuint height = u_minify(dst->height0, dstLevel);
GLuint depth = u_minify(dst->depth0, dstLevel);
struct pipe_box src_box;
GLuint i;
 
assert(u_minify(src->width0, srcLevel) == width);
assert(u_minify(src->height0, srcLevel) == height);
assert(u_minify(src->depth0, srcLevel) == depth);
 
src_box.x = 0;
src_box.y = 0;
src_box.width = width;
src_box.height = height;
src_box.depth = 1;
/* Loop over 3D image slices */
/* could (and probably should) use "true" 3d box here -
but drivers can't quite handle it yet */
for (i = face; i < face + depth; i++) {
src_box.z = i;
 
if (0) {
print_center_pixel(pipe, src);
}
 
pipe->resource_copy_region(pipe,
dst,
dstLevel,
0, 0, i,/* destX, Y, Z */
src,
srcLevel,
&src_box);
}
}
 
/programs/develop/libraries/Mesa/src/mesa/state_tracker/st_texture.h
0,0 → 1,225
/**************************************************************************
*
* 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 ST_TEXTURE_H
#define ST_TEXTURE_H
 
 
#include "pipe/p_context.h"
#include "util/u_sampler.h"
 
#include "main/mtypes.h"
 
 
struct pipe_resource;
 
 
/**
* Subclass of gl_texure_image.
*/
struct st_texture_image
{
struct gl_texture_image base;
 
/* These aren't stored in gl_texture_image
*/
GLuint level;
GLuint face;
 
/* If stImage->pt != NULL, image data is stored here.
* Else if stImage->base.Data != NULL, image is stored there.
* Else there is no image data.
*/
struct pipe_resource *pt;
 
struct pipe_transfer *transfer;
};
 
 
/**
* Subclass of gl_texure_object.
*/
struct st_texture_object
{
struct gl_texture_object base; /* The "parent" object */
 
/* The texture must include at levels [0..lastLevel] once validated:
*/
GLuint lastLevel;
 
/** The size of the level=0 mipmap image */
GLuint width0, height0, depth0;
 
/* On validation any active images held in main memory or in other
* textures will be copied to this texture and the old storage freed.
*/
struct pipe_resource *pt;
 
/* Default sampler view attached to this texture object. Created lazily
* on first binding.
*/
struct pipe_sampler_view *sampler_view;
 
/* True if there is/was a surface bound to this texture object. It helps
* track whether the texture object is surface based or not.
*/
GLboolean surface_based;
};
 
 
static INLINE struct st_texture_image *
st_texture_image(struct gl_texture_image *img)
{
return (struct st_texture_image *) img;
}
 
static INLINE struct st_texture_object *
st_texture_object(struct gl_texture_object *obj)
{
return (struct st_texture_object *) obj;
}
 
 
static INLINE struct pipe_resource *
st_get_texobj_resource(struct gl_texture_object *texObj)
{
struct st_texture_object *stObj = st_texture_object(texObj);
return stObj ? stObj->pt : NULL;
}
 
 
static INLINE struct pipe_resource *
st_get_stobj_resource(struct st_texture_object *stObj)
{
return stObj ? stObj->pt : NULL;
}
 
 
static INLINE struct pipe_sampler_view *
st_create_texture_sampler_view(struct pipe_context *pipe,
struct pipe_resource *texture)
{
struct pipe_sampler_view templ;
 
u_sampler_view_default_template(&templ,
texture,
texture->format);
 
return pipe->create_sampler_view(pipe, texture, &templ);
}
 
 
static INLINE struct pipe_sampler_view *
st_create_texture_sampler_view_format(struct pipe_context *pipe,
struct pipe_resource *texture,
enum pipe_format format)
{
struct pipe_sampler_view templ;
 
u_sampler_view_default_template(&templ,
texture,
format);
 
return pipe->create_sampler_view(pipe, texture, &templ);
}
 
static INLINE struct pipe_sampler_view *
st_get_texture_sampler_view(struct st_texture_object *stObj,
struct pipe_context *pipe)
 
{
if (!stObj || !stObj->pt) {
return NULL;
}
 
if (!stObj->sampler_view) {
stObj->sampler_view = st_create_texture_sampler_view(pipe, stObj->pt);
}
 
return stObj->sampler_view;
}
 
 
extern struct pipe_resource *
st_texture_create(struct st_context *st,
enum pipe_texture_target target,
enum pipe_format format,
GLuint last_level,
GLuint width0,
GLuint height0,
GLuint depth0,
GLuint tex_usage );
 
 
/* Check if an image fits into an existing texture object.
*/
extern GLboolean
st_texture_match_image(const struct pipe_resource *pt,
const struct gl_texture_image *image,
GLuint face, GLuint level);
 
/* Return a pointer to an image within a texture. Return image stride as
* well.
*/
extern GLubyte *
st_texture_image_map(struct st_context *st,
struct st_texture_image *stImage,
GLuint zoffset,
enum pipe_transfer_usage usage,
unsigned x, unsigned y,
unsigned w, unsigned h);
 
extern void
st_texture_image_unmap(struct st_context *st,
struct st_texture_image *stImage);
 
 
/* Return pointers to each 2d slice within an image. Indexed by depth
* value.
*/
extern const GLuint *
st_texture_depth_offsets(struct pipe_resource *pt, GLuint level);
 
 
/* Upload an image into a texture
*/
extern void
st_texture_image_data(struct st_context *st,
struct pipe_resource *dst,
GLuint face, GLuint level, void *src,
GLuint src_row_pitch, GLuint src_image_pitch);
 
 
/* Copy an image between two textures
*/
extern void
st_texture_image_copy(struct pipe_context *pipe,
struct pipe_resource *dst, GLuint dstLevel,
struct pipe_resource *src, GLuint srcLevel,
GLuint face);
 
#endif
/programs/develop/libraries/Mesa/src/mesa/state_tracker/.
Property changes:
Added: tsvn:logminsize
+5
\ No newline at end of property