/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, ®ion); |
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 |