*
**************************************************************************/
-#include "glheader.h"
-#include "macros.h"
-#include "enums.h"
-#include "program.h"
+#include "main/glheader.h"
+#include "main/macros.h"
+#include "main/enums.h"
+#include "vf/vf.h"
+#include "pipe/draw/draw_context.h"
#include "sp_context.h"
-#include "sp_draw.h"
#include "sp_state.h"
-#define EMIT_ATTR( ATTR, FRAG_ATTR, INTERP ) \
-do { \
- slot_to_vf_attr[softpipe->nr_attrs] = ATTR; \
- softpipe->vf_attr_to_slot[ATTR] = softpipe->nr_attrs; \
+
+#define EMIT_ATTR( VF_ATTR, FRAG_ATTR, INTERP ) \
+do { \
+ slot_to_vf_attr[softpipe->nr_attrs] = VF_ATTR; \
+ softpipe->vf_attr_to_slot[VF_ATTR] = softpipe->nr_attrs; \
softpipe->fp_attr_to_slot[FRAG_ATTR] = softpipe->nr_attrs; \
- softpipe->interp[softpipe->nr_attrs] = INTERP; \
- softpipe->nr_attrs++; \
- attr_mask |= (1<<ATTR); \
+ softpipe->interp[softpipe->nr_attrs] = INTERP; \
+ softpipe->nr_attrs++; \
+ attr_mask |= (1 << (VF_ATTR)); \
} while (0)
-static GLuint frag_to_vf[FRAG_ATTRIB_MAX] =
+static const GLuint frag_to_vf[FRAG_ATTRIB_MAX] =
{
VF_ATTRIB_POS,
VF_ATTRIB_COLOR0,
VF_ATTRIB_TEX5,
VF_ATTRIB_TEX6,
VF_ATTRIB_TEX7,
+ VF_ATTRIB_VAR0,
+ VF_ATTRIB_VAR1,
+ VF_ATTRIB_VAR2,
+ VF_ATTRIB_VAR3,
+ VF_ATTRIB_VAR4,
+ VF_ATTRIB_VAR5,
+ VF_ATTRIB_VAR6,
+ VF_ATTRIB_VAR7,
};
-/* Derived from: fs, setup states.
+/**
+ * Determine which post-transform / pre-rasterization vertex attributes
+ * we need.
+ * Derived from: fs, setup states.
*/
static void calculate_vertex_layout( struct softpipe_context *softpipe )
{
- struct gl_fragment_program *fp = softpipe->fs.fp;
- const GLuint inputsRead = fp->Base.InputsRead;
+ const GLbitfield inputsRead = softpipe->fs.inputs_read;
GLuint slot_to_vf_attr[VF_ATTRIB_MAX];
- GLuint attr_mask = 0;
+ GLbitfield attr_mask = 0x0;
GLuint i;
+ /* Need Z if depth test is enabled or the fragment program uses the
+ * fragment position (XYZW).
+ */
+ if (softpipe->depth_test.enabled ||
+ (inputsRead & FRAG_ATTRIB_WPOS))
+ softpipe->need_z = GL_TRUE;
+ else
+ softpipe->need_z = GL_FALSE;
+
+ /* Need W if we do any perspective-corrected interpolation or the
+ * fragment program uses the fragment position.
+ */
+ if (inputsRead & FRAG_ATTRIB_WPOS)
+ softpipe->need_w = GL_TRUE;
+ else
+ softpipe->need_w = GL_FALSE;
+
+
softpipe->nr_attrs = 0;
memset(slot_to_vf_attr, 0, sizeof(slot_to_vf_attr));
- memset(softpipe->fp_attr_to_slot, 0, sizeof(softpipe->vf_attr_to_slot));
- memset(softpipe->vf_attr_to_slot, 0, sizeof(softpipe->fp_attr_to_slot));
+ memset(softpipe->fp_attr_to_slot, 0, sizeof(softpipe->fp_attr_to_slot));
+ memset(softpipe->vf_attr_to_slot, 0, sizeof(softpipe->vf_attr_to_slot));
/* TODO - Figure out if we need to do perspective divide, etc.
*/
* as fixed point or ubyte format.
*/
for (i = 1; i < FRAG_ATTRIB_TEX0; i++) {
- if (inputsRead & (i << i)) {
- EMIT_ATTR(frag_to_vf[i], i, INTERP_LINEAR);
+ if (inputsRead & (1 << i)) {
+ assert(i < sizeof(frag_to_vf) / sizeof(frag_to_vf[0]));
+ if (softpipe->setup.flatshade
+ && (i == FRAG_ATTRIB_COL0 || i == FRAG_ATTRIB_COL1))
+ EMIT_ATTR(frag_to_vf[i], i, INTERP_CONSTANT);
+ else
+ EMIT_ATTR(frag_to_vf[i], i, INTERP_LINEAR);
}
}
for (i = FRAG_ATTRIB_TEX0; i < FRAG_ATTRIB_MAX; i++) {
- if (inputsRead & (i << i)) {
- EMIT_ATTR(frag_to_vf[i], i, INTERP_PERSPECTIVE);
+ if (inputsRead & (1 << i)) {
+ assert(i < sizeof(frag_to_vf) / sizeof(frag_to_vf[0]));
+ EMIT_ATTR(frag_to_vf[i], i, INTERP_PERSPECTIVE);
+ softpipe->need_w = GL_TRUE;
}
}
}
}
+ /* If the attributes have changed, tell the draw module (which in turn
+ * tells the vf module) about the new vertex layout.
+ */
if (attr_mask != softpipe->attr_mask) {
softpipe->attr_mask = attr_mask;
}
+/**
+ * Recompute cliprect from scissor bounds, scissor enable and surface size.
+ */
+static void
+compute_cliprect(struct softpipe_context *sp)
+{
+ GLint surfWidth, surfHeight;
+
+ if (sp->framebuffer.num_cbufs > 0) {
+ surfWidth = sp->framebuffer.cbufs[0]->width;
+ surfHeight = sp->framebuffer.cbufs[0]->height;
+ }
+ else {
+ /* no surface? */
+ surfWidth = sp->scissor.maxx;
+ surfHeight = sp->scissor.maxy;
+ }
+
+ if (sp->setup.scissor) {
+ /* clip to scissor rect */
+ sp->cliprect.minx = MAX2(sp->scissor.minx, 0);
+ sp->cliprect.miny = MAX2(sp->scissor.miny, 0);
+ sp->cliprect.maxx = MIN2(sp->scissor.maxx, surfWidth);
+ sp->cliprect.maxy = MIN2(sp->scissor.maxy, surfHeight);
+ }
+ else {
+ /* clip to surface bounds */
+ sp->cliprect.minx = 0;
+ sp->cliprect.miny = 0;
+ sp->cliprect.maxx = surfWidth;
+ sp->cliprect.maxy = surfHeight;
+ }
+}
+
+
/* Hopefully this will remain quite simple, otherwise need to pull in
* something like the state tracker mechanism.
*/
void softpipe_update_derived( struct softpipe_context *softpipe )
{
- if (softpipe->dirty & (G_NEW_SETUP | G_NEW_FS))
+ if (softpipe->dirty & (SP_NEW_SETUP | SP_NEW_FS))
calculate_vertex_layout( softpipe );
- if (softpipe->dirty & (G_NEW_BLEND | G_NEW_FS))
+ if (softpipe->dirty & (SP_NEW_SCISSOR |
+ SP_NEW_STENCIL |
+ SP_NEW_FRAMEBUFFER))
+ compute_cliprect(softpipe);
+
+ if (softpipe->dirty & (SP_NEW_BLEND |
+ SP_NEW_DEPTH_TEST |
+ SP_NEW_ALPHA_TEST |
+ SP_NEW_FRAMEBUFFER |
+ SP_NEW_STENCIL |
+ SP_NEW_SETUP |
+ SP_NEW_FS))
sp_build_quad_pipeline(softpipe);
softpipe->dirty = 0;