/**************************************************************************
*
* 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:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#include "i915_state_inlines.h"
#include "i915_context.h"
#include "i915_state.h"
#include "i915_reg.h"
#include "util/u_memory.h"
/* Convinience function to check immediate state.
*/
static INLINE void set_immediate(struct i915_context *i915,
unsigned offset,
const unsigned state)
{
if (i915->current.immediate[offset] == state)
return;
i915->current.immediate[offset] = state;
i915->immediate_dirty |= 1 << offset;
i915->hardware_dirty |= I915_HW_IMMEDIATE;
}
/***********************************************************************
* S0,S1: Vertex buffer state.
*/
static void upload_S0S1(struct i915_context *i915)
{
unsigned LIS0, LIS1;
/* I915_NEW_VBO
*/
LIS0 = i915->vbo_offset;
/* Need to force this */
if (i915->dirty & I915_NEW_VBO) {
i915->immediate_dirty |= 1 << I915_IMMEDIATE_S0;
i915->hardware_dirty |= I915_HW_IMMEDIATE;
}
/* I915_NEW_VERTEX_SIZE
*/
{
unsigned vertex_size = i915->current.vertex_info.size;
LIS1 = ((vertex_size << 24) |
(vertex_size << 16));
}
set_immediate(i915, I915_IMMEDIATE_S0, LIS0);
set_immediate(i915, I915_IMMEDIATE_S1, LIS1);
}
const struct i915_tracked_state i915_upload_S0S1 = {
"imm S0 S1",
upload_S0S1,
I915_NEW_VBO | I915_NEW_VERTEX_FORMAT
};
/***********************************************************************
* S4: Vertex format, rasterization state
*/
static void upload_S2S4(struct i915_context *i915)
{
unsigned LIS2, LIS4;
/* I915_NEW_VERTEX_FORMAT
*/
{
LIS2 = i915->current.vertex_info.hwfmt[1];
LIS4 = i915->current.vertex_info.hwfmt[0];
assert(LIS4); /* should never be zero? */
}
LIS4 |= i915->rasterizer->LIS4;
set_immediate(i915, I915_IMMEDIATE_S2, LIS2);
set_immediate(i915, I915_IMMEDIATE_S4, LIS4);
}
const struct i915_tracked_state i915_upload_S2S4 = {
"imm S2 S4",
upload_S2S4,
I915_NEW_RASTERIZER | I915_NEW_VERTEX_FORMAT
};
/***********************************************************************
*/
static void upload_S5(struct i915_context *i915)
{
unsigned LIS5 = 0;
/* I915_NEW_DEPTH_STENCIL
*/
LIS5 |= i915->depth_stencil->stencil_LIS5;
/* hope it's safe to set stencil ref value even if stencil test is disabled? */
LIS5 |= i915->stencil_ref.ref_value[0] << S5_STENCIL_REF_SHIFT;
/* I915_NEW_BLEND
*/
LIS5 |= i915->blend->LIS5;
#if 0
/* I915_NEW_RASTERIZER
*/
if (i915->rasterizer->LIS7) {
LIS5 |= S5_GLOBAL_DEPTH_OFFSET_ENABLE;
}
#endif
set_immediate(i915, I915_IMMEDIATE_S5, LIS5);
}
const struct i915_tracked_state i915_upload_S5 = {
"imm S5",
upload_S5,
I915_NEW_DEPTH_STENCIL | I915_NEW_BLEND | I915_NEW_RASTERIZER
};
/***********************************************************************
*/
static void upload_S6(struct i915_context *i915)
{
unsigned LIS6 = (2 << S6_TRISTRIP_PV_SHIFT);
/* I915_NEW_FRAMEBUFFER
*/
if (i915->framebuffer.cbufs[0])
LIS6 |= S6_COLOR_WRITE_ENABLE;
/* I915_NEW_BLEND
*/
LIS6 |= i915->blend->LIS6;
/* I915_NEW_DEPTH
*/
LIS6 |= i915->depth_stencil->depth_LIS6;
set_immediate(i915, I915_IMMEDIATE_S6, LIS6);
}
const struct i915_tracked_state i915_upload_S6 = {
"imm S6",
upload_S6,
I915_NEW_BLEND | I915_NEW_DEPTH_STENCIL | I915_NEW_FRAMEBUFFER
};
/***********************************************************************
*/
static void upload_S7(struct i915_context *i915)
{
#if 0
unsigned LIS7;
/* I915_NEW_RASTERIZER
*/
LIS7 = i915->rasterizer->LIS7;
set_immediate(i915, I915_IMMEDIATE_S7, LIS7);
#endif
}
const struct i915_tracked_state i915_upload_S7 = {
"imm S7",
upload_S7,
I915_NEW_RASTERIZER
};
/***********************************************************************
*/
static const struct i915_tracked_state *atoms[] = {
&i915_upload_S0S1,
&i915_upload_S2S4,
&i915_upload_S5,
&i915_upload_S6,
&i915_upload_S7
};
static void update_immediate(struct i915_context *i915)
{
int i;
for (i = 0; i < Elements(atoms); i++)
if (i915->dirty & atoms[i]->dirty)
atoms[i]->update(i915);
}
struct i915_tracked_state i915_hw_immediate = {
"immediate",
update_immediate,
~0 /* all state atoms, becuase we do internal checking */
};