X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fi915%2Fi915_state_emit.c;h=a407020f67a9d329490f48ba8842005c9cfc545b;hb=8147c4a4a58a9328a07fd358b54622de0d01c374;hp=0155cd8351004e9420b926514169667255ed2b6e;hpb=2bf95c519e755146704f4942b1703d47d18bfeaa;p=mesa.git diff --git a/src/gallium/drivers/i915/i915_state_emit.c b/src/gallium/drivers/i915/i915_state_emit.c index 0155cd83510..a407020f67a 100644 --- a/src/gallium/drivers/i915/i915_state_emit.c +++ b/src/gallium/drivers/i915/i915_state_emit.c @@ -1,6 +1,6 @@ /************************************************************************** * - * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. + * Copyright 2003 VMware, Inc. * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a @@ -18,7 +18,7 @@ * 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 + * IN NO EVENT SHALL VMWARE 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. @@ -30,11 +30,14 @@ #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" @@ -107,7 +110,7 @@ static void emit_invariant(struct i915_context *i915) { i915_winsys_batchbuffer_write(i915->batch, invariant_state, - Elements(invariant_state)*sizeof(uint32_t)); + ARRAY_SIZE(invariant_state)*sizeof(uint32_t)); } static void @@ -125,10 +128,74 @@ validate_immediate(struct i915_context *i915, unsigned *batch_space) *batch_space = 1 + util_bitcount(dirty); } +static uint target_fixup(struct pipe_surface *p, int component) +{ + const struct + { + enum pipe_format format; + uint hw_mask[4]; + } fixup_mask[] = { + { PIPE_FORMAT_R8G8B8A8_UNORM, { S5_WRITEDISABLE_BLUE, S5_WRITEDISABLE_GREEN, S5_WRITEDISABLE_RED, S5_WRITEDISABLE_ALPHA}}, + { PIPE_FORMAT_R8G8B8X8_UNORM, { S5_WRITEDISABLE_BLUE, S5_WRITEDISABLE_GREEN, S5_WRITEDISABLE_RED, S5_WRITEDISABLE_ALPHA}}, + { PIPE_FORMAT_L8_UNORM, { S5_WRITEDISABLE_RED | S5_WRITEDISABLE_GREEN | S5_WRITEDISABLE_BLUE, 0, 0, S5_WRITEDISABLE_ALPHA}}, + { PIPE_FORMAT_I8_UNORM, { S5_WRITEDISABLE_RED | S5_WRITEDISABLE_GREEN | S5_WRITEDISABLE_BLUE, 0, 0, S5_WRITEDISABLE_ALPHA}}, + { PIPE_FORMAT_A8_UNORM, { 0, 0, 0, S5_WRITEDISABLE_RED | S5_WRITEDISABLE_GREEN | S5_WRITEDISABLE_BLUE | S5_WRITEDISABLE_ALPHA}}, + { 0, { S5_WRITEDISABLE_RED, S5_WRITEDISABLE_GREEN, S5_WRITEDISABLE_BLUE, S5_WRITEDISABLE_ALPHA}} + }; + int i = sizeof(fixup_mask) / sizeof(*fixup_mask) - 1; + + if (p) + for(i = 0; fixup_mask[i].format != 0; i++) + if (p->format == fixup_mask[i].format) + return fixup_mask[i].hw_mask[component]; + + /* Just return default masks */ + return fixup_mask[i].hw_mask[component]; +} + +static void emit_immediate_s5(struct i915_context *i915, uint imm) +{ + /* Fixup write mask for non-BGRA render targets */ + uint fixup_imm = imm & ~( S5_WRITEDISABLE_RED | S5_WRITEDISABLE_GREEN | + S5_WRITEDISABLE_BLUE | S5_WRITEDISABLE_ALPHA ); + struct pipe_surface *surf = i915->framebuffer.cbufs[0]; + + if (imm & S5_WRITEDISABLE_RED) + fixup_imm |= target_fixup(surf, 0); + if (imm & S5_WRITEDISABLE_GREEN) + fixup_imm |= target_fixup(surf, 1); + if (imm & S5_WRITEDISABLE_BLUE) + fixup_imm |= target_fixup(surf, 2); + if (imm & S5_WRITEDISABLE_ALPHA) + fixup_imm |= target_fixup(surf, 3); + + OUT_BATCH(fixup_imm); +} + +static void emit_immediate_s6(struct i915_context *i915, uint imm) +{ + /* 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. */ + uint srcRGB; + + if (i915->current.target_fixup_format == PIPE_FORMAT_A8_UNORM) { + 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); +} + 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 | @@ -149,8 +216,14 @@ emit_immediate(struct i915_context *i915) } for (i = 1; i < I915_MAX_IMMEDIATE; i++) { - if (dirty & (1 << i)) - OUT_BATCH(i915->current.immediate[i]); + if (dirty & (1 << i)) { + if (i == I915_IMMEDIATE_S5) + emit_immediate_s5(i915, i915->current.immediate[i]); + else if (i == I915_IMMEDIATE_S6) + emit_immediate_s6(i915, i915->current.immediate[i]); + else + OUT_BATCH(i915->current.immediate[i]); + } } } @@ -253,11 +326,13 @@ emit_map(struct i915_context *i915) if (enabled & (1 << unit)) { struct i915_texture *texture = i915_texture(i915->fragment_sampler_views[unit]->texture); struct i915_winsys_buffer *buf = texture->buffer; + unsigned offset = i915->current.texbuffer[unit][2]; + assert(buf); count++; - OUT_RELOC(buf, I915_USAGE_SAMPLER, 0); + OUT_RELOC(buf, I915_USAGE_SAMPLER, offset); OUT_BATCH(i915->current.texbuffer[unit][0]); /* MS3 */ OUT_BATCH(i915->current.texbuffer[unit][1]); /* MS4 */ } @@ -297,8 +372,10 @@ emit_sampler(struct i915_context *i915) 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 @@ -308,6 +385,8 @@ emit_constants(struct i915_context *i915) * immediates according to the constant_flags[] array. */ const uint nr = i915->fs->num_constants; + + assert(nr < I915_MAX_CONSTANT); if (nr) { uint i; @@ -344,18 +423,57 @@ emit_constants(struct i915_context *i915) 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 @@ -377,14 +495,26 @@ i915_validate_state(struct i915_context *i915, unsigned *batch_space) i915->num_validation_buffers = 0; if (i915->hardware_dirty & I915_HW_INVARIANT) - *batch_space = Elements(invariant_state); + *batch_space = ARRAY_SIZE(invariant_state); 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); @@ -419,12 +549,12 @@ i915_emit_hardware_state(struct i915_context *i915 ) i915_dump_hardware_dirty(i915, __FUNCTION__); if (!i915_validate_state(i915, &batch_space)) { - FLUSH_BATCH(NULL); + FLUSH_BATCH(NULL, I915_FLUSH_ASYNC); assert(i915_validate_state(i915, &batch_space)); } if(!BEGIN_BATCH(batch_space)) { - FLUSH_BATCH(NULL); + FLUSH_BATCH(NULL, I915_FLUSH_ASYNC); assert(i915_validate_state(i915, &batch_space)); assert(BEGIN_BATCH(batch_space)); }