Merge branch 'mesa_7_7_branch'
[mesa.git] / src / gallium / drivers / i965 / brw_wm_surface_state.c
1 /*
2 Copyright (C) Intel Corp. 2006. All Rights Reserved.
3 Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
4 develop this 3D driver.
5
6 Permission is hereby granted, free of charge, to any person obtaining
7 a 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, sublicense, 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
16 portions of the Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
22 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
26 **********************************************************************/
27 /*
28 * Authors:
29 * Keith Whitwell <keith@tungstengraphics.com>
30 */
31
32 #include "pipe/p_format.h"
33
34 #include "brw_batchbuffer.h"
35 #include "brw_context.h"
36 #include "brw_state.h"
37 #include "brw_defines.h"
38 #include "brw_screen.h"
39
40
41
42
43 static enum pipe_error
44 brw_update_texture_surface( struct brw_context *brw,
45 struct brw_texture *tex,
46 struct brw_winsys_buffer **bo_out)
47 {
48 struct brw_winsys_reloc reloc[1];
49 enum pipe_error ret;
50
51 /* Emit relocation to surface contents */
52 make_reloc(&reloc[0],
53 BRW_USAGE_SAMPLER,
54 0,
55 offsetof(struct brw_surface_state, ss1),
56 tex->bo);
57
58 if (brw_search_cache(&brw->surface_cache,
59 BRW_SS_SURFACE,
60 &tex->ss, sizeof tex->ss,
61 reloc, Elements(reloc),
62 NULL,
63 bo_out))
64 return PIPE_OK;
65
66 ret = brw_upload_cache(&brw->surface_cache, BRW_SS_SURFACE,
67 &tex->ss, sizeof tex->ss,
68 reloc, Elements(reloc),
69 &tex->ss, sizeof tex->ss,
70 NULL, NULL,
71 bo_out);
72 if (ret)
73 return ret;
74
75 return PIPE_OK;
76 }
77
78
79
80
81
82
83
84
85 /**
86 * Sets up a surface state structure to point at the given region.
87 * While it is only used for the front/back buffer currently, it should be
88 * usable for further buffers when doing ARB_draw_buffer support.
89 */
90 static enum pipe_error
91 brw_update_render_surface(struct brw_context *brw,
92 struct brw_surface *surface,
93 struct brw_winsys_buffer **bo_out)
94 {
95 struct brw_surf_ss0 blend_ss0 = brw->curr.blend->ss0;
96 struct brw_surface_state ss;
97 struct brw_winsys_reloc reloc[1];
98 enum pipe_error ret;
99
100 /* XXX: we will only be rendering to this surface:
101 */
102 make_reloc(&reloc[0],
103 BRW_USAGE_RENDER_TARGET,
104 0,
105 offsetof(struct brw_surface_state, ss1),
106 surface->bo);
107
108 /* Surfaces are potentially shared between contexts, so can't
109 * scribble the in-place ss0 value in the surface.
110 */
111 memcpy(&ss, &surface->ss, sizeof ss);
112
113 ss.ss0.color_blend = blend_ss0.color_blend;
114 ss.ss0.writedisable_blue = blend_ss0.writedisable_blue;
115 ss.ss0.writedisable_green = blend_ss0.writedisable_green;
116 ss.ss0.writedisable_red = blend_ss0.writedisable_red;
117 ss.ss0.writedisable_alpha = blend_ss0.writedisable_alpha;
118
119 if (brw_search_cache(&brw->surface_cache,
120 BRW_SS_SURFACE,
121 &ss, sizeof(ss),
122 reloc, Elements(reloc),
123 NULL,
124 bo_out))
125 return PIPE_OK;
126
127 ret = brw_upload_cache(&brw->surface_cache,
128 BRW_SS_SURFACE,
129 &ss, sizeof ss,
130 reloc, Elements(reloc),
131 &ss, sizeof ss,
132 NULL, NULL,
133 bo_out);
134 if (ret)
135 return ret;
136
137 return PIPE_OK;
138 }
139
140
141 /**
142 * Constructs the binding table for the WM surface state, which maps unit
143 * numbers to surface state objects.
144 */
145 static enum pipe_error
146 brw_wm_get_binding_table(struct brw_context *brw,
147 struct brw_winsys_buffer **bo_out )
148 {
149 enum pipe_error ret;
150 struct brw_winsys_reloc reloc[BRW_WM_MAX_SURF];
151 uint32_t data[BRW_WM_MAX_SURF];
152 GLuint nr_relocs = 0;
153 GLuint data_size = brw->wm.nr_surfaces * sizeof data[0];
154 int i;
155
156 assert(brw->wm.nr_surfaces <= BRW_WM_MAX_SURF);
157 assert(brw->wm.nr_surfaces > 0);
158
159 /* Emit binding table relocations to surface state
160 */
161 for (i = 0; i < brw->wm.nr_surfaces; i++) {
162 if (brw->wm.surf_bo[i]) {
163 make_reloc(&reloc[nr_relocs++],
164 BRW_USAGE_STATE,
165 0,
166 i * sizeof(GLuint),
167 brw->wm.surf_bo[i]);
168 }
169 }
170
171 /* Note there is no key for this search beyond the values in the
172 * relocation array:
173 */
174 if (brw_search_cache(&brw->surface_cache, BRW_SS_SURF_BIND,
175 NULL, 0,
176 reloc, nr_relocs,
177 NULL,
178 bo_out))
179 return PIPE_OK;
180
181 /* Upload zero data, will all be overwitten with relocation
182 * offsets:
183 */
184 for (i = 0; i < brw->wm.nr_surfaces; i++)
185 data[i] = 0;
186
187 ret = brw_upload_cache( &brw->surface_cache, BRW_SS_SURF_BIND,
188 NULL, 0,
189 reloc, nr_relocs,
190 data, data_size,
191 NULL, NULL,
192 bo_out);
193 if (ret)
194 return ret;
195
196 return PIPE_OK;
197 }
198
199 static enum pipe_error prepare_wm_surfaces(struct brw_context *brw )
200 {
201 enum pipe_error ret;
202 int nr_surfaces = 0;
203 GLuint i;
204
205 /* PIPE_NEW_COLOR_BUFFERS | PIPE_NEW_BLEND
206 *
207 * Update surfaces for drawing buffers. Mixes in colormask and
208 * blend state.
209 *
210 * XXX: no color buffer case
211 */
212 for (i = 0; i < brw->curr.fb.nr_cbufs; i++) {
213 ret = brw_update_render_surface(brw,
214 brw_surface(brw->curr.fb.cbufs[i]),
215 &brw->wm.surf_bo[BTI_COLOR_BUF(i)]);
216 if (ret)
217 return ret;
218
219 nr_surfaces = BTI_COLOR_BUF(i) + 1;
220 }
221
222
223
224 /* PIPE_NEW_FRAGMENT_CONSTANTS
225 */
226 #if 0
227 if (brw->curr.fragment_constants) {
228 ret = brw_update_fragment_constant_surface(
229 brw,
230 brw->curr.fragment_constants,
231 &brw->wm.surf_bo[BTI_FRAGMENT_CONSTANTS]);
232
233 if (ret)
234 return ret;
235
236 nr_surfaces = BTI_FRAGMENT_CONSTANTS + 1;
237 }
238 else {
239 bo_reference(&brw->wm.surf_bo[SURF_FRAG_CONSTANTS], NULL);
240 }
241 #endif
242
243
244 /* PIPE_NEW_TEXTURE
245 */
246 for (i = 0; i < brw->curr.num_textures; i++) {
247 ret = brw_update_texture_surface(brw,
248 brw_texture(brw->curr.texture[i]),
249 &brw->wm.surf_bo[BTI_TEXTURE(i)]);
250 if (ret)
251 return ret;
252
253 nr_surfaces = BTI_TEXTURE(i) + 1;
254 }
255
256 /* Clear any inactive entries:
257 */
258 for (i = brw->curr.fb.nr_cbufs; i < BRW_MAX_DRAW_BUFFERS; i++)
259 bo_reference(&brw->wm.surf_bo[BTI_COLOR_BUF(i)], NULL);
260
261 if (!brw->curr.fragment_constants)
262 bo_reference(&brw->wm.surf_bo[BTI_FRAGMENT_CONSTANTS], NULL);
263
264 /* XXX: no pipe_max_textures define?? */
265 for (i = brw->curr.num_textures; i < PIPE_MAX_SAMPLERS; i++)
266 bo_reference(&brw->wm.surf_bo[BTI_TEXTURE(i)], NULL);
267
268 if (brw->wm.nr_surfaces != nr_surfaces) {
269 brw->wm.nr_surfaces = nr_surfaces;
270 brw->state.dirty.brw |= BRW_NEW_NR_WM_SURFACES;
271 }
272
273 ret = brw_wm_get_binding_table(brw, &brw->wm.bind_bo);
274 if (ret)
275 return ret;
276
277 return PIPE_OK;
278 }
279
280 const struct brw_tracked_state brw_wm_surfaces = {
281 .dirty = {
282 .mesa = (PIPE_NEW_COLOR_BUFFERS |
283 PIPE_NEW_BOUND_TEXTURES |
284 PIPE_NEW_FRAGMENT_CONSTANTS |
285 PIPE_NEW_BLEND),
286 .brw = (BRW_NEW_CONTEXT |
287 BRW_NEW_WM_SURFACES),
288 .cache = 0
289 },
290 .prepare = prepare_wm_surfaces,
291 };
292
293
294