Merge branch '7.8'
[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_screen.h"
38
39
40
41
42 static enum pipe_error
43 brw_update_texture_surface( struct brw_context *brw,
44 struct brw_texture *tex,
45 struct brw_winsys_buffer **bo_out)
46 {
47 struct brw_winsys_reloc reloc[1];
48 enum pipe_error ret;
49
50 /* Emit relocation to surface contents */
51 make_reloc(&reloc[0],
52 BRW_USAGE_SAMPLER,
53 0,
54 offsetof(struct brw_surface_state, ss1),
55 tex->bo);
56
57 if (brw_search_cache(&brw->surface_cache,
58 BRW_SS_SURFACE,
59 &tex->ss, sizeof tex->ss,
60 reloc, Elements(reloc),
61 NULL,
62 bo_out))
63 return PIPE_OK;
64
65 ret = brw_upload_cache(&brw->surface_cache, BRW_SS_SURFACE,
66 &tex->ss, sizeof tex->ss,
67 reloc, Elements(reloc),
68 &tex->ss, sizeof tex->ss,
69 NULL, NULL,
70 bo_out);
71 if (ret)
72 return ret;
73
74 return PIPE_OK;
75 }
76
77
78
79
80
81
82
83
84 /**
85 * Sets up a surface state structure to point at the given region.
86 * While it is only used for the front/back buffer currently, it should be
87 * usable for further buffers when doing ARB_draw_buffer support.
88 */
89 static enum pipe_error
90 brw_update_render_surface(struct brw_context *brw,
91 struct brw_surface *surface,
92 struct brw_winsys_buffer **bo_out)
93 {
94 struct brw_surf_ss0 blend_ss0 = brw->curr.blend->ss0;
95 struct brw_surface_state ss;
96 struct brw_winsys_reloc reloc[1];
97 enum pipe_error ret;
98
99 /* XXX: we will only be rendering to this surface:
100 */
101 make_reloc(&reloc[0],
102 BRW_USAGE_RENDER_TARGET,
103 0,
104 offsetof(struct brw_surface_state, ss1),
105 surface->bo);
106
107 /* Surfaces are potentially shared between contexts, so can't
108 * scribble the in-place ss0 value in the surface.
109 */
110 memcpy(&ss, &surface->ss, sizeof ss);
111
112 ss.ss0.color_blend = blend_ss0.color_blend;
113 ss.ss0.writedisable_blue = blend_ss0.writedisable_blue;
114 ss.ss0.writedisable_green = blend_ss0.writedisable_green;
115 ss.ss0.writedisable_red = blend_ss0.writedisable_red;
116 ss.ss0.writedisable_alpha = blend_ss0.writedisable_alpha;
117
118 if (brw_search_cache(&brw->surface_cache,
119 BRW_SS_SURFACE,
120 &ss, sizeof(ss),
121 reloc, Elements(reloc),
122 NULL,
123 bo_out))
124 return PIPE_OK;
125
126 ret = brw_upload_cache(&brw->surface_cache,
127 BRW_SS_SURFACE,
128 &ss, sizeof ss,
129 reloc, Elements(reloc),
130 &ss, sizeof ss,
131 NULL, NULL,
132 bo_out);
133 if (ret)
134 return ret;
135
136 return PIPE_OK;
137 }
138
139
140 /**
141 * Constructs the binding table for the WM surface state, which maps unit
142 * numbers to surface state objects.
143 */
144 static enum pipe_error
145 brw_wm_get_binding_table(struct brw_context *brw,
146 struct brw_winsys_buffer **bo_out )
147 {
148 enum pipe_error ret;
149 struct brw_winsys_reloc reloc[BRW_WM_MAX_SURF];
150 uint32_t data[BRW_WM_MAX_SURF];
151 GLuint nr_relocs = 0;
152 GLuint data_size = brw->wm.nr_surfaces * sizeof data[0];
153 int i;
154
155 assert(brw->wm.nr_surfaces <= BRW_WM_MAX_SURF);
156 assert(brw->wm.nr_surfaces > 0);
157
158 /* Emit binding table relocations to surface state
159 */
160 for (i = 0; i < brw->wm.nr_surfaces; i++) {
161 if (brw->wm.surf_bo[i]) {
162 make_reloc(&reloc[nr_relocs++],
163 BRW_USAGE_STATE,
164 0,
165 i * sizeof(GLuint),
166 brw->wm.surf_bo[i]);
167 }
168 }
169
170 /* Note there is no key for this search beyond the values in the
171 * relocation array:
172 */
173 if (brw_search_cache(&brw->surface_cache, BRW_SS_SURF_BIND,
174 NULL, 0,
175 reloc, nr_relocs,
176 NULL,
177 bo_out))
178 return PIPE_OK;
179
180 /* Upload zero data, will all be overwitten with relocation
181 * offsets:
182 */
183 for (i = 0; i < brw->wm.nr_surfaces; i++)
184 data[i] = 0;
185
186 ret = brw_upload_cache( &brw->surface_cache, BRW_SS_SURF_BIND,
187 NULL, 0,
188 reloc, nr_relocs,
189 data, data_size,
190 NULL, NULL,
191 bo_out);
192 if (ret)
193 return ret;
194
195 return PIPE_OK;
196 }
197
198 static enum pipe_error prepare_wm_surfaces(struct brw_context *brw )
199 {
200 enum pipe_error ret;
201 int nr_surfaces = 0;
202 GLuint i;
203
204 /* PIPE_NEW_COLOR_BUFFERS | PIPE_NEW_BLEND
205 *
206 * Update surfaces for drawing buffers. Mixes in colormask and
207 * blend state.
208 *
209 * XXX: no color buffer case
210 */
211 for (i = 0; i < brw->curr.fb.nr_cbufs; i++) {
212 ret = brw_update_render_surface(brw,
213 brw_surface(brw->curr.fb.cbufs[i]),
214 &brw->wm.surf_bo[BTI_COLOR_BUF(i)]);
215 if (ret)
216 return ret;
217
218 nr_surfaces = BTI_COLOR_BUF(i) + 1;
219 }
220
221
222
223 /* PIPE_NEW_FRAGMENT_CONSTANTS
224 */
225 #if 0
226 if (brw->curr.fragment_constants) {
227 ret = brw_update_fragment_constant_surface(
228 brw,
229 brw->curr.fragment_constants,
230 &brw->wm.surf_bo[BTI_FRAGMENT_CONSTANTS]);
231
232 if (ret)
233 return ret;
234
235 nr_surfaces = BTI_FRAGMENT_CONSTANTS + 1;
236 }
237 else {
238 bo_reference(&brw->wm.surf_bo[SURF_FRAG_CONSTANTS], NULL);
239 }
240 #endif
241
242
243 /* PIPE_NEW_TEXTURE
244 */
245 for (i = 0; i < brw->curr.num_fragment_sampler_views; i++) {
246 ret = brw_update_texture_surface(brw,
247 brw_texture(brw->curr.fragment_sampler_views[i]->texture),
248 &brw->wm.surf_bo[BTI_TEXTURE(i)]);
249 if (ret)
250 return ret;
251
252 nr_surfaces = BTI_TEXTURE(i) + 1;
253 }
254
255 /* Clear any inactive entries:
256 */
257 for (i = brw->curr.fb.nr_cbufs; i < BRW_MAX_DRAW_BUFFERS; i++)
258 bo_reference(&brw->wm.surf_bo[BTI_COLOR_BUF(i)], NULL);
259
260 if (!brw->curr.fragment_constants)
261 bo_reference(&brw->wm.surf_bo[BTI_FRAGMENT_CONSTANTS], NULL);
262
263 /* XXX: no pipe_max_textures define?? */
264 for (i = brw->curr.num_fragment_sampler_views; i < PIPE_MAX_SAMPLERS; i++)
265 bo_reference(&brw->wm.surf_bo[BTI_TEXTURE(i)], NULL);
266
267 if (brw->wm.nr_surfaces != nr_surfaces) {
268 brw->wm.nr_surfaces = nr_surfaces;
269 brw->state.dirty.brw |= BRW_NEW_NR_WM_SURFACES;
270 }
271
272 ret = brw_wm_get_binding_table(brw, &brw->wm.bind_bo);
273 if (ret)
274 return ret;
275
276 return PIPE_OK;
277 }
278
279 const struct brw_tracked_state brw_wm_surfaces = {
280 .dirty = {
281 .mesa = (PIPE_NEW_COLOR_BUFFERS |
282 PIPE_NEW_BOUND_TEXTURES |
283 PIPE_NEW_FRAGMENT_CONSTANTS |
284 PIPE_NEW_BLEND),
285 .brw = (BRW_NEW_CONTEXT |
286 BRW_NEW_WM_SURFACES),
287 .cache = 0
288 },
289 .prepare = prepare_wm_surfaces,
290 };
291
292
293