diff options
Diffstat (limited to 'src/mesa/state_tracker/st_cb_rasterpos.c')
-rw-r--r-- | src/mesa/state_tracker/st_cb_rasterpos.c | 350 |
1 files changed, 350 insertions, 0 deletions
diff --git a/src/mesa/state_tracker/st_cb_rasterpos.c b/src/mesa/state_tracker/st_cb_rasterpos.c new file mode 100644 index 00000000000..5040c21e51c --- /dev/null +++ b/src/mesa/state_tracker/st_cb_rasterpos.c @@ -0,0 +1,350 @@ +/************************************************************************** + * + * 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/macros.h" + +#include "st_context.h" +#include "st_atom.h" +#include "st_draw.h" +#include "st_program.h" +#include "st_cb_rasterpos.h" +#include "st_draw.h" +#include "st_format.h" +#include "pipe/p_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_winsys.h" +#include "pipe/tgsi/exec/tgsi_attribs.h" +#include "shader/prog_instruction.h" +#include "vf/vf.h" + + + +static void +setup_vertex_attribs(GLcontext *ctx) +{ + struct pipe_context *pipe = ctx->st->pipe; + const uint inputAttrs = ctx->st->state.vs.inputs_read; + uint attr; + + /* all attributes come from the default attribute buffer */ + { + struct pipe_vertex_buffer vbuffer; + vbuffer.buffer = ctx->st->default_attrib_buffer; + vbuffer.buffer_offset = 0; + vbuffer.pitch = 0; /* must be zero! */ + vbuffer.max_index = 1; + pipe->set_vertex_buffer(pipe, 0, &vbuffer); + } + + for (attr = 0; attr < 16; attr++) { + struct pipe_vertex_element velement; + + if (inputAttrs & (1 << attr)) { + velement.src_offset = attr * 4 * sizeof(GLfloat); + velement.vertex_buffer_index = 0; + velement.dst_offset = 0; + velement.src_format = PIPE_FORMAT_R32G32B32A32_FLOAT; + pipe->set_vertex_element(pipe, attr, &velement); + } + } +} + + +static void +setup_feedback(GLcontext *ctx) +{ + struct pipe_context *pipe = ctx->st->pipe; + const uint outputAttrs = ctx->st->state.vs.outputs_written; + struct pipe_feedback_state feedback; + uint i; + + memset(&feedback, 0, sizeof(feedback)); + feedback.enabled = 1; + feedback.interleaved = 1; + feedback.discard = 1; + feedback.num_attribs = 0; + + for (i = 0; i < TGSI_ATTRIB_VAR0; i++) { + if ((1 << i) & outputAttrs) { + feedback.attrib[feedback.num_attribs] = i; + feedback.size[feedback.num_attribs] = 4; + feedback.num_attribs++; + } + } + + pipe->set_feedback_state(pipe, &feedback); +} + + + + + +/** + * Clip a point against the view volume. + * + * \param v vertex vector describing the point to clip. + * + * \return zero if outside view volume, or one if inside. + */ +static GLuint +viewclip_point( const GLfloat v[] ) +{ + if ( v[0] > v[3] || v[0] < -v[3] + || v[1] > v[3] || v[1] < -v[3] + || v[2] > v[3] || v[2] < -v[3] ) { + return 0; + } + else { + return 1; + } +} + + +/** + * Clip a point against the far/near Z clipping planes. + * + * \param v vertex vector describing the point to clip. + * + * \return zero if outside view volume, or one if inside. + */ +static GLuint +viewclip_point_z( const GLfloat v[] ) +{ + if (v[2] > v[3] || v[2] < -v[3] ) { + return 0; + } + else { + return 1; + } +} + + +/** + * Clip a point against the user clipping planes. + * + * \param ctx GL context. + * \param v vertex vector describing the point to clip. + * + * \return zero if the point was clipped, or one otherwise. + */ +static GLuint +userclip_point( GLcontext *ctx, const GLfloat v[] ) +{ + GLuint p; + + for (p = 0; p < ctx->Const.MaxClipPlanes; p++) { + if (ctx->Transform.ClipPlanesEnabled & (1 << p)) { + GLfloat dot = v[0] * ctx->Transform._ClipUserPlane[p][0] + + v[1] * ctx->Transform._ClipUserPlane[p][1] + + v[2] * ctx->Transform._ClipUserPlane[p][2] + + v[3] * ctx->Transform._ClipUserPlane[p][3]; + if (dot < 0.0F) { + return 0; + } + } + } + + return 1; +} + + +/** + * Update the current raster position. + * Do clip testing, etc. here. + */ +static void +update_rasterpos(GLcontext *ctx, + const float clipPos[4], + const float color0[4], + const float color1[4], + const float *tex) +{ + uint i; + float d, ndc[3]; + + /* clip to view volume */ + if (ctx->Transform.RasterPositionUnclipped) { + /* GL_IBM_rasterpos_clip: only clip against Z */ + if (viewclip_point_z(clipPos) == 0) { + ctx->Current.RasterPosValid = GL_FALSE; + return; + } + } + else if (viewclip_point(clipPos) == 0) { + /* Normal OpenGL behaviour */ + ctx->Current.RasterPosValid = GL_FALSE; + return; + } + + /* clip to user clipping planes */ + if (ctx->Transform.ClipPlanesEnabled && !userclip_point(ctx, clipPos)) { + ctx->Current.RasterPosValid = GL_FALSE; + return; + } + + + /* + * update current raster position + */ + /* ndc = clip / W */ + d = (clipPos[3] == 0.0F) ? 1.0F : 1.0F / clipPos[3]; + ndc[0] = clipPos[0] * d; + ndc[1] = clipPos[1] * d; + ndc[2] = clipPos[2] * d; + /* wincoord = viewport_mapping(ndc) */ + ctx->Current.RasterPos[0] = (ndc[0] * ctx->Viewport._WindowMap.m[MAT_SX] + + ctx->Viewport._WindowMap.m[MAT_TX]); + ctx->Current.RasterPos[1] = (ndc[1] * ctx->Viewport._WindowMap.m[MAT_SY] + + ctx->Viewport._WindowMap.m[MAT_TY]); + ctx->Current.RasterPos[2] = (ndc[2] * ctx->Viewport._WindowMap.m[MAT_SZ] + + ctx->Viewport._WindowMap.m[MAT_TZ]) + / ctx->DrawBuffer->_DepthMaxF; + ctx->Current.RasterPos[3] = clipPos[3]; + + /* compute raster distance */ + if (ctx->Fog.FogCoordinateSource == GL_FOG_COORDINATE_EXT) + ctx->Current.RasterDistance = ctx->Current.Attrib[VERT_ATTRIB_FOG][0]; + else { +#if 0 + /* XXX we don't have an eye coord! */ + ctx->Current.RasterDistance = + SQRTF( eye[0]*eye[0] + eye[1]*eye[1] + eye[2]*eye[2] ); +#endif + } + + /* colors and texcoords */ + COPY_4FV(ctx->Current.RasterColor, color0); + COPY_4FV(ctx->Current.RasterSecondaryColor, color1); + for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) { + COPY_4FV(ctx->Current.RasterTexCoords + i, tex + i *4); + } + + ctx->Current.RasterPosValid = GL_TRUE; +} + + + +static void +st_RasterPos(GLcontext *ctx, const GLfloat v[4]) +{ + struct pipe_context *pipe = ctx->st->pipe; + float *buf_map; + struct pipe_feedback_buffer fb_buf; + + st_validate_state(ctx->st); + + /* setup vertex buffers */ + setup_vertex_attribs(ctx); + + /* + * Load the default attribute buffer with current attribs. + */ + { + struct pipe_buffer_handle *buf = ctx->st->default_attrib_buffer; + const unsigned size = sizeof(ctx->Current.Attrib); + const void *data = ctx->Current.Attrib; + /* colors, texcoords, etc */ + pipe->winsys->buffer_data(pipe->winsys, buf, size, data); + /* position */ + pipe->winsys->buffer_subdata(pipe->winsys, buf, + 0, /* offset */ + 4 * sizeof(float), /* size */ + v); /* data */ + } + + + /* setup feedback state */ + setup_feedback(ctx); + + /* setup vertex feedback buffer */ + { + fb_buf.size = 8 * 4 * sizeof(float); + fb_buf.buffer = pipe->winsys->buffer_create(pipe->winsys, 0); + fb_buf.start_offset = 0; + pipe->winsys->buffer_data(pipe->winsys, fb_buf.buffer, + fb_buf.size, + NULL); /* data */ + pipe->set_feedback_buffer(pipe, 0, &fb_buf); + } + + + /* draw a point */ + pipe->draw_arrays(pipe, GL_POINTS, 0, 1); + + /* get feedback */ + buf_map = (float *) pipe->winsys->buffer_map(pipe->winsys, fb_buf.buffer, + PIPE_BUFFER_FLAG_READ); + + /* extract values and update rasterpos state */ + { + const uint outputAttrs = ctx->st->state.vs.outputs_written; + const float *pos, *color0, *color1, *tex0; + float *buf = buf_map; + + assert(outputAttrs & (1 << TGSI_ATTRIB_POS)); + pos = buf; + buf += 4; + + if (outputAttrs & (1 << TGSI_ATTRIB_COLOR0)) { + color0 = buf; + buf += 4; + } + else { + color0 = ctx->Current.Attrib[VERT_ATTRIB_COLOR0]; + } + + if (outputAttrs & (1 << TGSI_ATTRIB_COLOR1)) { + color1 = buf; + buf += 4; + } + else { + color1 = ctx->Current.Attrib[VERT_ATTRIB_COLOR1]; + } + + update_rasterpos(ctx, pos, color0, color1, tex0); + } + + + /* free vertex feedback buffer */ + pipe->winsys->buffer_unmap(pipe->winsys, fb_buf.buffer); + pipe->winsys->buffer_unreference(pipe->winsys, &fb_buf.buffer); + + /* restore pipe state */ + pipe->set_feedback_state(pipe, &ctx->st->state.feedback); +} + + +void st_init_rasterpos_functions(struct dd_function_table *functions) +{ + functions->RasterPos = st_RasterPos; +} |