#include "i915_context.h"
#include "i915_batch.h"
#include "i915_debug.h"
+#include "i915_fpc.h"
#include "i915_resource.h"
#include "pipe/p_context.h"
#include "pipe/p_defines.h"
+#include "pipe/p_format.h"
+#include "util/u_format.h"
#include "util/u_math.h"
#include "util/u_memory.h"
1 << I915_IMMEDIATE_S5 | 1 << I915_IMMEDIATE_S6) &
i915->immediate_dirty;
- if (i915->immediate_dirty & (1 << I915_IMMEDIATE_S0))
+ if (i915->immediate_dirty & (1 << I915_IMMEDIATE_S0) && i915->vbo)
i915->validation_buffers[i915->num_validation_buffers++] = i915->vbo;
*batch_space = 1 + util_bitcount(dirty);
static void
emit_immediate(struct i915_context *i915)
{
- /* remove unwatned bits and S7 */
+ /* remove unwanted bits and S7 */
unsigned dirty = (1 << I915_IMMEDIATE_S0 | 1 << I915_IMMEDIATE_S1 |
1 << I915_IMMEDIATE_S2 | 1 << I915_IMMEDIATE_S3 |
1 << I915_IMMEDIATE_S3 | 1 << I915_IMMEDIATE_S4 |
}
for (i = 1; i < I915_MAX_IMMEDIATE; i++) {
- if (dirty & (1 << i))
- OUT_BATCH(i915->current.immediate[i]);
+ if (dirty & (1 << i)) {
+ /* Fixup blend function for A8 dst buffers.
+ * When we blend to an A8 buffer, the GPU thinks it's a G8 buffer,
+ * and therefore we need to use the color factor for alphas. */
+ if ((i == I915_IMMEDIATE_S6) &&
+ (i915->current.target_fixup_format == PIPE_FORMAT_A8_UNORM)) {
+ uint32_t imm = i915->current.immediate[i];
+ uint32_t srcRGB = (imm >> S6_CBUF_SRC_BLEND_FACT_SHIFT) & BLENDFACT_MASK;
+ if (srcRGB == BLENDFACT_DST_ALPHA)
+ srcRGB = BLENDFACT_DST_COLR;
+ else if (srcRGB == BLENDFACT_INV_DST_ALPHA)
+ srcRGB = BLENDFACT_INV_DST_COLR;
+ imm &= ~SRC_BLND_FACT(BLENDFACT_MASK);
+ imm |= SRC_BLND_FACT(srcRGB);
+ OUT_BATCH(imm);
+ } else {
+ OUT_BATCH(i915->current.immediate[i]);
+ }
+ }
}
}
static void
validate_static(struct i915_context *i915, unsigned *batch_space)
{
- *batch_space = 2 + 5; /* including DRAW_RECT */
+ *batch_space = 0;
- if (i915->current.cbuf_bo) {
+ if (i915->current.cbuf_bo && (i915->static_dirty & I915_DST_BUF_COLOR)) {
i915->validation_buffers[i915->num_validation_buffers++]
= i915->current.cbuf_bo;
*batch_space += 3;
}
- if (i915->current.depth_bo) {
+ if (i915->current.depth_bo && (i915->static_dirty & I915_DST_BUF_DEPTH)) {
i915->validation_buffers[i915->num_validation_buffers++]
= i915->current.depth_bo;
*batch_space += 3;
}
+
+ if (i915->static_dirty & I915_DST_VARS)
+ *batch_space += 2;
+
+ if (i915->static_dirty & I915_DST_RECT)
+ *batch_space += 5;
}
static void
emit_static(struct i915_context *i915)
{
- if (i915->current.cbuf_bo) {
+ if (i915->current.cbuf_bo && (i915->static_dirty & I915_DST_BUF_COLOR)) {
OUT_BATCH(_3DSTATE_BUF_INFO_CMD);
OUT_BATCH(i915->current.cbuf_flags);
OUT_RELOC(i915->current.cbuf_bo,
/* What happens if no zbuf??
*/
- if (i915->current.depth_bo) {
+ if (i915->current.depth_bo && (i915->static_dirty & I915_DST_BUF_DEPTH)) {
OUT_BATCH(_3DSTATE_BUF_INFO_CMD);
OUT_BATCH(i915->current.depth_flags);
OUT_RELOC(i915->current.depth_bo,
0);
}
- {
+ if (i915->static_dirty & I915_DST_VARS) {
OUT_BATCH(_3DSTATE_DST_BUF_VARS_CMD);
OUT_BATCH(i915->current.dst_buf_vars);
}
if (i915->current.sampler_enable_nr) {
int i;
- OUT_BATCH( _3DSTATE_SAMPLER_STATE |
+ OUT_BATCH( _3DSTATE_SAMPLER_STATE |
(3 * i915->current.sampler_enable_nr) );
OUT_BATCH( i915->current.sampler_enable_flags );
static void
validate_constants(struct i915_context *i915, unsigned *batch_space)
{
- *batch_space = i915->fs->num_constants ?
+ int nr = i915->fs->num_constants ?
2 + 4*i915->fs->num_constants : 0;
+
+ *batch_space = nr;
}
static void
* immediates according to the constant_flags[] array.
*/
const uint nr = i915->fs->num_constants;
+
+ assert(nr < I915_MAX_CONSTANT);
if (nr) {
uint i;
static void
validate_program(struct i915_context *i915, unsigned *batch_space)
{
- *batch_space = i915->fs->program_len;
+ uint additional_size = 0;
+
+ additional_size += i915->current.target_fixup_format ? 3 : 0;
+
+ /* we need more batch space if we want to emulate rgba framebuffers */
+ *batch_space = i915->fs->decl_len + i915->fs->program_len + additional_size;
}
static void
emit_program(struct i915_context *i915)
{
- uint i;
- /* we should always have, at least, a pass-through program */
- assert(i915->fs->program_len > 0);
- for (i = 0; i < i915->fs->program_len; i++) {
- OUT_BATCH(i915->fs->program[i]);
- }
+ uint additional_size = 0;
+ uint i;
+
+ /* count how much additional space we'll need */
+ validate_program(i915, &additional_size);
+ additional_size -= i915->fs->decl_len + i915->fs->program_len;
+
+ /* we should always have, at least, a pass-through program */
+ assert(i915->fs->program_len > 0);
+
+ /* output the declarations */
+ {
+ /* first word has the size, we have to adjust that */
+ uint size = (i915->fs->decl[0]);
+ size += additional_size;
+ OUT_BATCH(size);
+ }
+
+ for (i = 1 ; i < i915->fs->decl_len; i++)
+ OUT_BATCH(i915->fs->decl[i]);
+
+ /* output the program */
+ assert(i915->fs->program_len % 3 == 0);
+ for (i = 0 ; i < i915->fs->program_len; i+=3) {
+ OUT_BATCH(i915->fs->program[i]);
+ OUT_BATCH(i915->fs->program[i+1]);
+ OUT_BATCH(i915->fs->program[i+2]);
+ }
+
+ /* we emit an additional mov with swizzle to fake RGBA framebuffers */
+ if (i915->current.target_fixup_format) {
+ /* mov out_color, out_color.zyxw */
+ OUT_BATCH(A0_MOV |
+ (REG_TYPE_OC << A0_DEST_TYPE_SHIFT) |
+ A0_DEST_CHANNEL_ALL |
+ (REG_TYPE_OC << A0_SRC0_TYPE_SHIFT) |
+ (T_DIFFUSE << A0_SRC0_NR_SHIFT));
+ OUT_BATCH(i915->current.fixup_swizzle);
+ OUT_BATCH(0);
+ }
}
static void
emit_draw_rect(struct i915_context *i915)
{
- OUT_BATCH(_3DSTATE_DRAW_RECT_CMD);
- OUT_BATCH(DRAW_RECT_DIS_DEPTH_OFS);
- OUT_BATCH(i915->current.draw_offset);
- OUT_BATCH(i915->current.draw_size);
- OUT_BATCH(i915->current.draw_offset);
+ if (i915->static_dirty & I915_DST_RECT) {
+ OUT_BATCH(_3DSTATE_DRAW_RECT_CMD);
+ OUT_BATCH(DRAW_RECT_DIS_DEPTH_OFS);
+ OUT_BATCH(i915->current.draw_offset);
+ OUT_BATCH(i915->current.draw_size);
+ OUT_BATCH(i915->current.draw_offset);
+ }
}
static boolean
else
*batch_space = 0;
+#if 0
+static int counter_total = 0;
+#define VALIDATE_ATOM(atom, hw_dirty) \
+ if (i915->hardware_dirty & hw_dirty) { \
+ static int counter_##atom = 0;\
+ validate_##atom(i915, &tmp); \
+ *batch_space += tmp;\
+ counter_##atom += tmp;\
+ counter_total += tmp;\
+ printf("%s: \t%d/%d \t%2.2f\n",#atom, counter_##atom, counter_total, counter_##atom*100.f/counter_total);}
+#else
#define VALIDATE_ATOM(atom, hw_dirty) \
if (i915->hardware_dirty & hw_dirty) { \
validate_##atom(i915, &tmp); \
*batch_space += tmp; }
+#endif
VALIDATE_ATOM(flush, I915_HW_FLUSH);
VALIDATE_ATOM(immediate, I915_HW_IMMEDIATE);
VALIDATE_ATOM(dynamic, I915_HW_DYNAMIC);
unsigned batch_space;
uintptr_t save_ptr;
+ assert(i915->dirty == 0);
+
if (I915_DBG_ON(DBG_ATOMS))
i915_dump_hardware_dirty(i915, __FUNCTION__);
i915->hardware_dirty = 0;
i915->immediate_dirty = 0;
i915->dynamic_dirty = 0;
+ i915->static_dirty = 0;
i915->flush_dirty = 0;
}