};
+
#define BRW_PACKCOLOR8888(r,g,b,a) ((r<<24) | (g<<16) | (b<<8) | a)
struct brw_instruction_info {
void brw_compute_vue_map(struct brw_vue_map *vue_map,
const struct intel_context *intel, int nr_userclip,
GLbitfield64 outputs_written);
+gl_clip_plane *brw_select_clip_planes(struct gl_context *ctx);
+
/*======================================================================
* Inline conversion functions. These are better-typed than the
const GLuint bufsz = sz * 16 * sizeof(GLfloat);
GLfloat *buf;
GLuint i;
+ gl_clip_plane *clip_planes;
if (sz == 0) {
brw->curbe.last_bufsz = 0;
/* Clip planes: _NEW_TRANSFORM plus _NEW_PROJECTION to get to
* clip-space:
*/
+ clip_planes = brw_select_clip_planes(ctx);
for (j = 0; j < MAX_CLIP_PLANES; j++) {
if (ctx->Transform.ClipPlanesEnabled & (1<<j)) {
- buf[offset + i * 4 + 0] = ctx->Transform._ClipUserPlane[j][0];
- buf[offset + i * 4 + 1] = ctx->Transform._ClipUserPlane[j][1];
- buf[offset + i * 4 + 2] = ctx->Transform._ClipUserPlane[j][2];
- buf[offset + i * 4 + 3] = ctx->Transform._ClipUserPlane[j][3];
+ buf[offset + i * 4 + 0] = clip_planes[j][0];
+ buf[offset + i * 4 + 1] = clip_planes[j][1];
+ buf[offset + i * 4 + 2] = clip_planes[j][2];
+ buf[offset + i * 4 + 3] = clip_planes[j][3];
i++;
}
}
void
vec4_visitor::setup_uniform_clipplane_values()
{
+ gl_clip_plane *clip_planes = brw_select_clip_planes(ctx);
+
int compacted_clipplane_index = 0;
for (int i = 0; i < MAX_CLIP_PLANES; ++i) {
if (ctx->Transform.ClipPlanesEnabled & (1 << i)) {
this->userplane[compacted_clipplane_index] = dst_reg(UNIFORM, this->uniforms);
this->userplane[compacted_clipplane_index].type = BRW_REGISTER_TYPE_F;
for (int j = 0; j < 4; ++j) {
- c->prog_data.param[this->uniforms * 4 + j] = &ctx->Transform._ClipUserPlane[i][j];
+ c->prog_data.param[this->uniforms * 4 + j] = &clip_planes[i][j];
}
++compacted_clipplane_index;
++this->uniforms;
return;
}
+ /* From the GLSL 1.30 spec, section 7.1 (Vertex Shader Special Variables):
+ *
+ * "If a linked set of shaders forming the vertex stage contains no
+ * static write to gl_ClipVertex or gl_ClipDistance, but the
+ * application has requested clipping against user clip planes through
+ * the API, then the coordinate written to gl_Position is used for
+ * comparison against the user clip planes."
+ *
+ * This function is only called if the shader didn't write to
+ * gl_ClipDistance. Accordingly, we use gl_ClipVertex to perform clipping
+ * if the user wrote to it; otherwise we use gl_Position.
+ */
+ gl_vert_result clip_vertex = VERT_RESULT_CLIP_VERTEX;
+ if (!(c->prog_data.outputs_written
+ & BITFIELD64_BIT(VERT_RESULT_CLIP_VERTEX))) {
+ clip_vertex = VERT_RESULT_HPOS;
+ }
+
for (int i = 0; i + offset < c->key.nr_userclip && i < 4; ++i) {
emit(DP4(dst_reg(brw_writemask(reg, 1 << i)),
- src_reg(output_reg[VERT_RESULT_HPOS]),
+ src_reg(output_reg[clip_vertex]),
src_reg(this->userplane[i + offset])));
}
}
/* The hardware doesn't care about the rest of the vertex outputs, so just
* assign them contiguously. Don't reassign outputs that already have a
* slot.
+ *
+ * Also, don't assign a slot for VERT_RESULT_CLIP_VERTEX, since it is
+ * unsupported in pre-GEN6, and in GEN6+ the vertex shader converts it into
+ * clip distances.
*/
for (int i = 0; i < VERT_RESULT_MAX; ++i) {
if ((outputs_written & BITFIELD64_BIT(i)) &&
- vue_map->vert_result_to_slot[i] == -1) {
+ vue_map->vert_result_to_slot[i] == -1 &&
+ i != VERT_RESULT_CLIP_VERTEX) {
assign_vue_slot(vue_map, i);
}
}
}
+
+/**
+ * Decide which set of clip planes should be used when clipping via
+ * gl_Position or gl_ClipVertex.
+ */
+gl_clip_plane *brw_select_clip_planes(struct gl_context *ctx)
+{
+ if (ctx->Shader.CurrentVertexProgram) {
+ /* There is currently a GLSL vertex shader, so clip according to GLSL
+ * rules, which means compare gl_ClipVertex (or gl_Position, if
+ * gl_ClipVertex wasn't assigned) against the eye-coordinate clip planes
+ * that were stored in EyeUserPlane at the time the clip planes were
+ * specified.
+ */
+ return ctx->Transform.EyeUserPlane;
+ } else {
+ /* Either we are using fixed function or an ARB vertex program. In
+ * either case the clip planes are going to be compared against
+ * gl_Position (which is in clip coordinates) so we have to clip using
+ * _ClipUserPlane, which was transformed into clip coordinates by Mesa
+ * core.
+ */
+ return ctx->Transform._ClipUserPlane;
+ }
+}
+
+
static bool
do_vs_prog(struct brw_context *brw,
struct gl_shader_program *prog,
* until we redo the VS backend.
*/
if (!uses_clip_distance) {
+ gl_clip_plane *clip_planes = brw_select_clip_planes(ctx);
for (i = 0; i < MAX_CLIP_PLANES; i++) {
if (ctx->Transform.ClipPlanesEnabled & (1 << i)) {
- memcpy(param, ctx->Transform._ClipUserPlane[i], 4 * sizeof(float));
+ memcpy(param, clip_planes[i], 4 * sizeof(float));
param += 4;
params_uploaded++;
}
};
+/**
+ * Data structure representing a single clip plane (e.g. one of the elements
+ * of the ctx->Transform.EyeUserPlane or ctx->Transform._ClipUserPlane array).
+ */
+typedef GLfloat gl_clip_plane[4];
+
+
/**
* Transformation attribute group (GL_TRANSFORM_BIT).
*/
struct gl_transform_attrib
{
GLenum MatrixMode; /**< Matrix mode */
- GLfloat EyeUserPlane[MAX_CLIP_PLANES][4]; /**< User clip planes */
- GLfloat _ClipUserPlane[MAX_CLIP_PLANES][4]; /**< derived */
+ gl_clip_plane EyeUserPlane[MAX_CLIP_PLANES]; /**< User clip planes */
+ gl_clip_plane _ClipUserPlane[MAX_CLIP_PLANES]; /**< derived */
GLbitfield ClipPlanesEnabled; /**< on/off bitmask */
GLboolean Normalize; /**< Normalize all normals? */
GLboolean RescaleNormals; /**< GL_EXT_rescale_normal */