1/**************************************************************************
2 *
3 * Copyright 2007 VMware, Inc.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27/*
28 * Authors:
29 *   Keith Whitwell <keithw@vmware.com>
30 */
31
32#include "util/u_memory.h"
33#include "i915_context.h"
34#include "i915_reg.h"
35#include "i915_state.h"
36#include "i915_state_inlines.h"
37
38/* Convinience function to check immediate state.
39 */
40
41static inline void
42set_immediate(struct i915_context *i915, unsigned offset, const unsigned state)
43{
44   if (i915->current.immediate[offset] == state)
45      return;
46
47   i915->current.immediate[offset] = state;
48   i915->immediate_dirty |= 1 << offset;
49   i915->hardware_dirty |= I915_HW_IMMEDIATE;
50}
51
52/***********************************************************************
53 * S0,S1: Vertex buffer state.
54 */
55static void
56upload_S0S1(struct i915_context *i915)
57{
58   unsigned LIS0, LIS1;
59
60   /* I915_NEW_VBO
61    */
62   LIS0 = i915->vbo_offset;
63
64   /* Need to force this */
65   if (i915->dirty & I915_NEW_VBO) {
66      i915->immediate_dirty |= 1 << I915_IMMEDIATE_S0;
67      i915->hardware_dirty |= I915_HW_IMMEDIATE;
68   }
69
70   /* I915_NEW_VERTEX_SIZE
71    */
72   {
73      unsigned vertex_size = i915->current.vertex_info.size;
74
75      LIS1 = ((vertex_size << 24) | (vertex_size << 16));
76   }
77
78   set_immediate(i915, I915_IMMEDIATE_S0, LIS0);
79   set_immediate(i915, I915_IMMEDIATE_S1, LIS1);
80}
81
82const struct i915_tracked_state i915_upload_S0S1 = {
83   "imm S0 S1", upload_S0S1, I915_NEW_VBO | I915_NEW_VERTEX_FORMAT};
84
85/***********************************************************************
86 * S4: Vertex format, rasterization state
87 */
88static void
89upload_S2S4(struct i915_context *i915)
90{
91   unsigned LIS2, LIS4;
92
93   /* I915_NEW_VERTEX_FORMAT
94    */
95   {
96      LIS2 = i915->current.vertex_info.hwfmt[1];
97      LIS4 = i915->current.vertex_info.hwfmt[0];
98      assert(LIS4); /* should never be zero? */
99   }
100
101   LIS4 |= i915->rasterizer->LIS4;
102
103   set_immediate(i915, I915_IMMEDIATE_S2, LIS2);
104   set_immediate(i915, I915_IMMEDIATE_S4, LIS4);
105}
106
107const struct i915_tracked_state i915_upload_S2S4 = {
108   "imm S2 S4", upload_S2S4, I915_NEW_RASTERIZER | I915_NEW_VERTEX_FORMAT};
109
110/***********************************************************************
111 */
112static void
113upload_S5(struct i915_context *i915)
114{
115   unsigned LIS5 = 0;
116   bool stencil_ccw = i915_stencil_ccw(i915);
117
118   /* I915_NEW_DEPTH_STENCIL
119    */
120   if (stencil_ccw)
121      LIS5 |= i915->depth_stencil->stencil_LIS5_ccw;
122   else
123      LIS5 |= i915->depth_stencil->stencil_LIS5_cw;
124   /* hope it's safe to set stencil ref value even if stencil test is disabled?
125    */
126   LIS5 |= i915->stencil_ref.ref_value[stencil_ccw] << S5_STENCIL_REF_SHIFT;
127
128   /* I915_NEW_BLEND
129    */
130   LIS5 |= i915->blend->LIS5;
131
132#if 0
133   /* I915_NEW_RASTERIZER
134    */
135   if (i915->rasterizer->LIS7) {
136      LIS5 |= S5_GLOBAL_DEPTH_OFFSET_ENABLE;
137   }
138#endif
139
140   set_immediate(i915, I915_IMMEDIATE_S5, LIS5);
141}
142
143const struct i915_tracked_state i915_upload_S5 = {
144   "imm S5", upload_S5,
145   I915_NEW_DEPTH_STENCIL | I915_NEW_BLEND | I915_NEW_RASTERIZER};
146
147/***********************************************************************
148 */
149static void
150upload_S6(struct i915_context *i915)
151{
152   unsigned LIS6 = 0;
153
154   /* I915_NEW_FRAMEBUFFER
155    */
156   if (i915->framebuffer.cbufs[0])
157      LIS6 |= S6_COLOR_WRITE_ENABLE;
158
159   /* I915_NEW_BLEND
160    */
161   if (i915->blend) {
162      struct i915_surface *cbuf = i915_surface(i915->framebuffer.cbufs[0]);
163      if (cbuf && cbuf->alpha_in_g)
164         LIS6 |= i915->blend->LIS6_alpha_in_g;
165      else if (cbuf && cbuf->alpha_is_x)
166         LIS6 |= i915->blend->LIS6_alpha_is_x;
167      else
168         LIS6 |= i915->blend->LIS6;
169   }
170
171   /* I915_NEW_DEPTH
172    */
173   if (i915->depth_stencil)
174      LIS6 |= i915->depth_stencil->depth_LIS6;
175
176   if (i915->rasterizer)
177      LIS6 |= i915->rasterizer->LIS6;
178
179   set_immediate(i915, I915_IMMEDIATE_S6, LIS6);
180}
181
182const struct i915_tracked_state i915_upload_S6 = {
183   "imm S6", upload_S6,
184   I915_NEW_BLEND | I915_NEW_DEPTH_STENCIL | I915_NEW_FRAMEBUFFER |
185      I915_NEW_RASTERIZER};
186
187/***********************************************************************
188 */
189static void
190upload_S7(struct i915_context *i915)
191{
192#if 0
193   unsigned LIS7;
194
195   /* I915_NEW_RASTERIZER
196    */
197   LIS7 = i915->rasterizer->LIS7;
198
199   set_immediate(i915, I915_IMMEDIATE_S7, LIS7);
200#endif
201}
202
203const struct i915_tracked_state i915_upload_S7 = {"imm S7", upload_S7,
204                                                  I915_NEW_RASTERIZER};
205
206/***********************************************************************
207 */
208static const struct i915_tracked_state *atoms[] = {
209   &i915_upload_S0S1, &i915_upload_S2S4, &i915_upload_S5, &i915_upload_S6,
210   &i915_upload_S7};
211
212static void
213update_immediate(struct i915_context *i915)
214{
215   int i;
216
217   for (i = 0; i < ARRAY_SIZE(atoms); i++)
218      if (i915->dirty & atoms[i]->dirty)
219         atoms[i]->update(i915);
220}
221
222struct i915_tracked_state i915_hw_immediate = {
223   "immediate", update_immediate,
224   ~0 /* all state atoms, because we do internal checking */
225};
226