cell: more efficient state emit for textures/samplers
[mesa.git] / src / gallium / drivers / cell / ppu / cell_pipe_state.c
1 /**************************************************************************
2 *
3 * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
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 TUNGSTEN GRAPHICS 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 <keith@tungstengraphics.com>
30 * Brian Paul
31 */
32
33 #include "util/u_memory.h"
34 #include "pipe/p_inlines.h"
35 #include "draw/draw_context.h"
36 #include "cell_context.h"
37 #include "cell_flush.h"
38 #include "cell_state.h"
39 #include "cell_texture.h"
40
41
42
43 static void *
44 cell_create_blend_state(struct pipe_context *pipe,
45 const struct pipe_blend_state *blend)
46 {
47 return mem_dup(blend, sizeof(*blend));
48 }
49
50
51 static void
52 cell_bind_blend_state(struct pipe_context *pipe, void *blend)
53 {
54 struct cell_context *cell = cell_context(pipe);
55
56 draw_flush(cell->draw);
57
58 cell->blend = (struct pipe_blend_state *) blend;
59 cell->dirty |= CELL_NEW_BLEND;
60 }
61
62
63 static void
64 cell_delete_blend_state(struct pipe_context *pipe, void *blend)
65 {
66 FREE(blend);
67 }
68
69
70 static void
71 cell_set_blend_color(struct pipe_context *pipe,
72 const struct pipe_blend_color *blend_color)
73 {
74 struct cell_context *cell = cell_context(pipe);
75
76 draw_flush(cell->draw);
77
78 cell->blend_color = *blend_color;
79
80 cell->dirty |= CELL_NEW_BLEND;
81 }
82
83
84
85
86 static void *
87 cell_create_depth_stencil_alpha_state(struct pipe_context *pipe,
88 const struct pipe_depth_stencil_alpha_state *dsa)
89 {
90 return mem_dup(dsa, sizeof(*dsa));
91 }
92
93
94 static void
95 cell_bind_depth_stencil_alpha_state(struct pipe_context *pipe,
96 void *dsa)
97 {
98 struct cell_context *cell = cell_context(pipe);
99
100 draw_flush(cell->draw);
101
102 cell->depth_stencil = (struct pipe_depth_stencil_alpha_state *) dsa;
103 cell->dirty |= CELL_NEW_DEPTH_STENCIL;
104 }
105
106
107 static void
108 cell_delete_depth_stencil_alpha_state(struct pipe_context *pipe, void *dsa)
109 {
110 FREE(dsa);
111 }
112
113
114 static void
115 cell_set_clip_state(struct pipe_context *pipe,
116 const struct pipe_clip_state *clip)
117 {
118 struct cell_context *cell = cell_context(pipe);
119
120 /* pass the clip state to the draw module */
121 draw_set_clip_state(cell->draw, clip);
122 }
123
124
125
126 /* Called when driver state tracker notices changes to the viewport
127 * matrix:
128 */
129 static void
130 cell_set_viewport_state( struct pipe_context *pipe,
131 const struct pipe_viewport_state *viewport )
132 {
133 struct cell_context *cell = cell_context(pipe);
134
135 cell->viewport = *viewport; /* struct copy */
136 cell->dirty |= CELL_NEW_VIEWPORT;
137
138 /* pass the viewport info to the draw module */
139 draw_set_viewport_state(cell->draw, viewport);
140
141 /* Using tnl/ and vf/ modules is temporary while getting started.
142 * Full pipe will have vertex shader, vertex fetch of its own.
143 */
144 }
145
146
147 static void
148 cell_set_scissor_state( struct pipe_context *pipe,
149 const struct pipe_scissor_state *scissor )
150 {
151 struct cell_context *cell = cell_context(pipe);
152
153 memcpy( &cell->scissor, scissor, sizeof(*scissor) );
154 cell->dirty |= CELL_NEW_SCISSOR;
155 }
156
157
158 static void
159 cell_set_polygon_stipple( struct pipe_context *pipe,
160 const struct pipe_poly_stipple *stipple )
161 {
162 struct cell_context *cell = cell_context(pipe);
163
164 memcpy( &cell->poly_stipple, stipple, sizeof(*stipple) );
165 cell->dirty |= CELL_NEW_STIPPLE;
166 }
167
168
169
170 static void *
171 cell_create_rasterizer_state(struct pipe_context *pipe,
172 const struct pipe_rasterizer_state *rasterizer)
173 {
174 return mem_dup(rasterizer, sizeof(*rasterizer));
175 }
176
177
178 static void
179 cell_bind_rasterizer_state(struct pipe_context *pipe, void *rast)
180 {
181 struct pipe_rasterizer_state *rasterizer =
182 (struct pipe_rasterizer_state *) rast;
183 struct cell_context *cell = cell_context(pipe);
184
185 /* pass-through to draw module */
186 draw_set_rasterizer_state(cell->draw, rasterizer);
187
188 cell->rasterizer = rasterizer;
189
190 cell->dirty |= CELL_NEW_RASTERIZER;
191 }
192
193
194 static void
195 cell_delete_rasterizer_state(struct pipe_context *pipe, void *rasterizer)
196 {
197 FREE(rasterizer);
198 }
199
200
201
202 static void *
203 cell_create_sampler_state(struct pipe_context *pipe,
204 const struct pipe_sampler_state *sampler)
205 {
206 return mem_dup(sampler, sizeof(*sampler));
207 }
208
209
210 static void
211 cell_bind_sampler_states(struct pipe_context *pipe,
212 unsigned num, void **samplers)
213 {
214 struct cell_context *cell = cell_context(pipe);
215 uint i, changed = 0x0;
216
217 assert(num <= CELL_MAX_SAMPLERS);
218
219 draw_flush(cell->draw);
220
221 for (i = 0; i < CELL_MAX_SAMPLERS; i++) {
222 struct pipe_sampler_state *new_samp = i < num ? samplers[i] : NULL;
223 if (cell->sampler[i] != new_samp) {
224 cell->sampler[i] = new_samp;
225 changed |= (1 << i);
226 }
227 }
228
229 if (changed) {
230 cell->dirty |= CELL_NEW_SAMPLER;
231 cell->dirty_samplers |= changed;
232 }
233 }
234
235
236 static void
237 cell_delete_sampler_state(struct pipe_context *pipe,
238 void *sampler)
239 {
240 FREE( sampler );
241 }
242
243
244
245 static void
246 cell_set_sampler_textures(struct pipe_context *pipe,
247 unsigned num, struct pipe_texture **texture)
248 {
249 struct cell_context *cell = cell_context(pipe);
250 uint i, changed = 0x0;
251
252 assert(num <= CELL_MAX_SAMPLERS);
253
254 for (i = 0; i < CELL_MAX_SAMPLERS; i++) {
255 struct pipe_texture *new_tex = i < num ? texture[i] : NULL;
256 if ((struct pipe_texture *) cell->texture[i] != new_tex) {
257 pipe_texture_reference((struct pipe_texture **) &cell->texture[i],
258 new_tex);
259 changed |= (1 << i);
260 }
261 }
262
263 if (changed) {
264 cell->dirty |= CELL_NEW_TEXTURE;
265 cell->dirty_textures |= changed;
266 }
267 }
268
269
270
271 static void
272 cell_set_framebuffer_state(struct pipe_context *pipe,
273 const struct pipe_framebuffer_state *fb)
274 {
275 struct cell_context *cell = cell_context(pipe);
276
277 if (1 /*memcmp(&cell->framebuffer, fb, sizeof(*fb))*/) {
278 struct pipe_surface *csurf = fb->cbufs[0];
279 struct pipe_surface *zsurf = fb->zsbuf;
280 uint i;
281 uint flags = (PIPE_BUFFER_USAGE_GPU_WRITE |
282 PIPE_BUFFER_USAGE_GPU_READ);
283
284 /* unmap old surfaces */
285 for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
286 if (cell->framebuffer.cbufs[i] && cell->cbuf_map[i]) {
287 pipe_surface_unmap(cell->framebuffer.cbufs[i]);
288 cell->cbuf_map[i] = NULL;
289 }
290 }
291
292 if (cell->framebuffer.zsbuf && cell->zsbuf_map) {
293 pipe_surface_unmap(cell->framebuffer.zsbuf);
294 cell->zsbuf_map = NULL;
295 }
296
297 /* Finish any pending rendering to the current surface before
298 * installing a new surface!
299 */
300 cell_flush_int(cell, CELL_FLUSH_WAIT);
301
302 /* update my state
303 * (this is also where old surfaces will finally get freed)
304 */
305 cell->framebuffer.width = fb->width;
306 cell->framebuffer.height = fb->height;
307 cell->framebuffer.num_cbufs = fb->num_cbufs;
308 for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
309 pipe_surface_reference(&cell->framebuffer.cbufs[i], fb->cbufs[i]);
310 }
311 pipe_surface_reference(&cell->framebuffer.zsbuf, fb->zsbuf);
312
313 /* map new surfaces */
314 if (csurf)
315 cell->cbuf_map[0] = pipe_surface_map(csurf, flags);
316
317 if (zsurf)
318 cell->zsbuf_map = pipe_surface_map(zsurf, flags);
319
320 cell->dirty |= CELL_NEW_FRAMEBUFFER;
321 }
322 }
323
324
325
326 void
327 cell_init_state_functions(struct cell_context *cell)
328 {
329 cell->pipe.create_blend_state = cell_create_blend_state;
330 cell->pipe.bind_blend_state = cell_bind_blend_state;
331 cell->pipe.delete_blend_state = cell_delete_blend_state;
332
333 cell->pipe.create_sampler_state = cell_create_sampler_state;
334 cell->pipe.bind_sampler_states = cell_bind_sampler_states;
335 cell->pipe.delete_sampler_state = cell_delete_sampler_state;
336
337 cell->pipe.set_sampler_textures = cell_set_sampler_textures;
338
339 cell->pipe.create_depth_stencil_alpha_state = cell_create_depth_stencil_alpha_state;
340 cell->pipe.bind_depth_stencil_alpha_state = cell_bind_depth_stencil_alpha_state;
341 cell->pipe.delete_depth_stencil_alpha_state = cell_delete_depth_stencil_alpha_state;
342
343 cell->pipe.create_rasterizer_state = cell_create_rasterizer_state;
344 cell->pipe.bind_rasterizer_state = cell_bind_rasterizer_state;
345 cell->pipe.delete_rasterizer_state = cell_delete_rasterizer_state;
346
347 cell->pipe.set_blend_color = cell_set_blend_color;
348 cell->pipe.set_clip_state = cell_set_clip_state;
349
350 cell->pipe.set_framebuffer_state = cell_set_framebuffer_state;
351
352 cell->pipe.set_polygon_stipple = cell_set_polygon_stipple;
353 cell->pipe.set_scissor_state = cell_set_scissor_state;
354 cell->pipe.set_viewport_state = cell_set_viewport_state;
355 }