970606a3f50a0cd3561e2e14c7fcaab1fa0b8d6e
[profile/ivi/mesa.git] / src / gallium / drivers / failover / fo_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:  Keith Whitwell <keith@tungstengraphics.com>
29  */
30
31 #include "util/u_inlines.h"
32
33 #include "fo_context.h"
34
35
36 /* This looks like a lot of work at the moment - we're keeping a
37  * duplicate copy of the state up-to-date.  
38  *
39  * This can change in two ways:
40  * - With constant state objects we would only need to save a pointer,
41  *     not the whole object.
42  * - By adding a callback in the state tracker to re-emit state.  The
43  *     state tracker knows the current state already and can re-emit it 
44  *     without additional complexity.
45  *
46  * This works as a proof-of-concept, but a final version will have
47  * lower overheads.
48  */
49
50
51
52 static void *
53 failover_create_blend_state( struct pipe_context *pipe,
54                              const struct pipe_blend_state *blend )
55 {
56    struct fo_state *state = malloc(sizeof(struct fo_state));
57    struct failover_context *failover = failover_context(pipe);
58
59    state->sw_state = failover->sw->create_blend_state(failover->sw, blend);
60    state->hw_state = failover->hw->create_blend_state(failover->hw, blend);
61
62    return state;
63 }
64
65 static void
66 failover_bind_blend_state( struct pipe_context *pipe,
67                            void *blend )
68 {
69    struct failover_context *failover = failover_context(pipe);
70    struct fo_state *state = (struct fo_state *)blend;
71    failover->blend = state;
72    failover->dirty |= FO_NEW_BLEND;
73    failover->sw->bind_blend_state( failover->sw, state->sw_state );
74    failover->hw->bind_blend_state( failover->hw, state->hw_state );
75 }
76
77 static void
78 failover_delete_blend_state( struct pipe_context *pipe,
79                              void *blend )
80 {
81    struct fo_state *state = (struct fo_state*)blend;
82    struct failover_context *failover = failover_context(pipe);
83
84    failover->sw->delete_blend_state(failover->sw, state->sw_state);
85    failover->hw->delete_blend_state(failover->hw, state->hw_state);
86    state->sw_state = 0;
87    state->hw_state = 0;
88    free(state);
89 }
90
91 static void
92 failover_set_blend_color( struct pipe_context *pipe,
93                           const struct pipe_blend_color *blend_color )
94 {
95    struct failover_context *failover = failover_context(pipe);
96
97    failover->blend_color = *blend_color;
98    failover->dirty |= FO_NEW_BLEND_COLOR;
99    failover->sw->set_blend_color( failover->sw, blend_color );
100    failover->hw->set_blend_color( failover->hw, blend_color );
101 }
102
103 static void
104 failover_set_stencil_ref( struct pipe_context *pipe,
105                           const struct pipe_stencil_ref *stencil_ref )
106 {
107    struct failover_context *failover = failover_context(pipe);
108
109    failover->stencil_ref = *stencil_ref;
110    failover->dirty |= FO_NEW_STENCIL_REF;
111    failover->sw->set_stencil_ref( failover->sw, stencil_ref );
112    failover->hw->set_stencil_ref( failover->hw, stencil_ref );
113 }
114
115 static void 
116 failover_set_clip_state( struct pipe_context *pipe,
117                          const struct pipe_clip_state *clip )
118 {
119    struct failover_context *failover = failover_context(pipe);
120
121    failover->clip = *clip;
122    failover->dirty |= FO_NEW_CLIP;
123    failover->sw->set_clip_state( failover->sw, clip );
124    failover->hw->set_clip_state( failover->hw, clip );
125 }
126
127
128 static void *
129 failover_create_depth_stencil_state(struct pipe_context *pipe,
130                               const struct pipe_depth_stencil_alpha_state *templ)
131 {
132    struct fo_state *state = malloc(sizeof(struct fo_state));
133    struct failover_context *failover = failover_context(pipe);
134
135    state->sw_state = failover->sw->create_depth_stencil_alpha_state(failover->sw, templ);
136    state->hw_state = failover->hw->create_depth_stencil_alpha_state(failover->hw, templ);
137
138    return state;
139 }
140
141 static void
142 failover_bind_depth_stencil_state(struct pipe_context *pipe,
143                                   void *depth_stencil)
144 {
145    struct failover_context *failover = failover_context(pipe);
146    struct fo_state *state = (struct fo_state *)depth_stencil;
147    failover->depth_stencil = state;
148    failover->dirty |= FO_NEW_DEPTH_STENCIL;
149    failover->sw->bind_depth_stencil_alpha_state(failover->sw, state->sw_state);
150    failover->hw->bind_depth_stencil_alpha_state(failover->hw, state->hw_state);
151 }
152
153 static void
154 failover_delete_depth_stencil_state(struct pipe_context *pipe,
155                                     void *ds)
156 {
157    struct fo_state *state = (struct fo_state*)ds;
158    struct failover_context *failover = failover_context(pipe);
159
160    failover->sw->delete_depth_stencil_alpha_state(failover->sw, state->sw_state);
161    failover->hw->delete_depth_stencil_alpha_state(failover->hw, state->hw_state);
162    state->sw_state = 0;
163    state->hw_state = 0;
164    free(state);
165 }
166
167 static void
168 failover_set_framebuffer_state(struct pipe_context *pipe,
169                                const struct pipe_framebuffer_state *framebuffer)
170 {
171    struct failover_context *failover = failover_context(pipe);
172
173    failover->framebuffer = *framebuffer;
174    failover->dirty |= FO_NEW_FRAMEBUFFER;
175    failover->sw->set_framebuffer_state( failover->sw, framebuffer );
176    failover->hw->set_framebuffer_state( failover->hw, framebuffer );
177 }
178
179
180 static void *
181 failover_create_fs_state(struct pipe_context *pipe,
182                          const struct pipe_shader_state *templ)
183 {
184    struct fo_state *state = malloc(sizeof(struct fo_state));
185    struct failover_context *failover = failover_context(pipe);
186
187    state->sw_state = failover->sw->create_fs_state(failover->sw, templ);
188    state->hw_state = failover->hw->create_fs_state(failover->hw, templ);
189
190    return state;
191 }
192
193 static void
194 failover_bind_fs_state(struct pipe_context *pipe, void *fs)
195 {
196    struct failover_context *failover = failover_context(pipe);
197    struct fo_state *state = (struct fo_state*)fs;
198    failover->fragment_shader = state;
199    failover->dirty |= FO_NEW_FRAGMENT_SHADER;
200    failover->sw->bind_fs_state(failover->sw, state->sw_state);
201    failover->hw->bind_fs_state(failover->hw, state->hw_state);
202 }
203
204 static void
205 failover_delete_fs_state(struct pipe_context *pipe,
206                          void *fs)
207 {
208    struct fo_state *state = (struct fo_state*)fs;
209    struct failover_context *failover = failover_context(pipe);
210
211    failover->sw->delete_fs_state(failover->sw, state->sw_state);
212    failover->hw->delete_fs_state(failover->hw, state->hw_state);
213    state->sw_state = 0;
214    state->hw_state = 0;
215    free(state);
216 }
217
218 static void *
219 failover_create_vs_state(struct pipe_context *pipe,
220                          const struct pipe_shader_state *templ)
221 {
222    struct fo_state *state = malloc(sizeof(struct fo_state));
223    struct failover_context *failover = failover_context(pipe);
224
225    state->sw_state = failover->sw->create_vs_state(failover->sw, templ);
226    state->hw_state = failover->hw->create_vs_state(failover->hw, templ);
227
228    return state;
229 }
230
231 static void
232 failover_bind_vs_state(struct pipe_context *pipe,
233                        void *vs)
234 {
235    struct failover_context *failover = failover_context(pipe);
236
237    struct fo_state *state = (struct fo_state*)vs;
238    failover->vertex_shader = state;
239    failover->dirty |= FO_NEW_VERTEX_SHADER;
240    failover->sw->bind_vs_state(failover->sw, state->sw_state);
241    failover->hw->bind_vs_state(failover->hw, state->hw_state);
242 }
243
244 static void
245 failover_delete_vs_state(struct pipe_context *pipe,
246                          void *vs)
247 {
248    struct fo_state *state = (struct fo_state*)vs;
249    struct failover_context *failover = failover_context(pipe);
250
251    failover->sw->delete_vs_state(failover->sw, state->sw_state);
252    failover->hw->delete_vs_state(failover->hw, state->hw_state);
253    state->sw_state = 0;
254    state->hw_state = 0;
255    free(state);
256 }
257
258 static void 
259 failover_set_polygon_stipple( struct pipe_context *pipe,
260                               const struct pipe_poly_stipple *stipple )
261 {
262    struct failover_context *failover = failover_context(pipe);
263
264    failover->poly_stipple = *stipple;
265    failover->dirty |= FO_NEW_STIPPLE;
266    failover->sw->set_polygon_stipple( failover->sw, stipple );
267    failover->hw->set_polygon_stipple( failover->hw, stipple );
268 }
269
270
271 static void *
272 failover_create_rasterizer_state(struct pipe_context *pipe,
273                                  const struct pipe_rasterizer_state *templ)
274 {
275    struct fo_state *state = malloc(sizeof(struct fo_state));
276    struct failover_context *failover = failover_context(pipe);
277
278    state->sw_state = failover->sw->create_rasterizer_state(failover->sw, templ);
279    state->hw_state = failover->hw->create_rasterizer_state(failover->hw, templ);
280
281    return state;
282 }
283
284 static void
285 failover_bind_rasterizer_state(struct pipe_context *pipe,
286                                void *raster)
287 {
288    struct failover_context *failover = failover_context(pipe);
289
290    struct fo_state *state = (struct fo_state*)raster;
291    failover->rasterizer = state;
292    failover->dirty |= FO_NEW_RASTERIZER;
293    failover->sw->bind_rasterizer_state(failover->sw, state->sw_state);
294    failover->hw->bind_rasterizer_state(failover->hw, state->hw_state);
295 }
296
297 static void
298 failover_delete_rasterizer_state(struct pipe_context *pipe,
299                                  void *raster)
300 {
301    struct fo_state *state = (struct fo_state*)raster;
302    struct failover_context *failover = failover_context(pipe);
303
304    failover->sw->delete_rasterizer_state(failover->sw, state->sw_state);
305    failover->hw->delete_rasterizer_state(failover->hw, state->hw_state);
306    state->sw_state = 0;
307    state->hw_state = 0;
308    free(state);
309 }
310
311
312 static void 
313 failover_set_scissor_state( struct pipe_context *pipe,
314                                  const struct pipe_scissor_state *scissor )
315 {
316    struct failover_context *failover = failover_context(pipe);
317
318    failover->scissor = *scissor;
319    failover->dirty |= FO_NEW_SCISSOR;
320    failover->sw->set_scissor_state( failover->sw, scissor );
321    failover->hw->set_scissor_state( failover->hw, scissor );
322 }
323
324
325 static void *
326 failover_create_sampler_state(struct pipe_context *pipe,
327                               const struct pipe_sampler_state *templ)
328 {
329    struct fo_state *state = malloc(sizeof(struct fo_state));
330    struct failover_context *failover = failover_context(pipe);
331
332    state->sw_state = failover->sw->create_sampler_state(failover->sw, templ);
333    state->hw_state = failover->hw->create_sampler_state(failover->hw, templ);
334
335    return state;
336 }
337
338 static void
339 failover_bind_fragment_sampler_states(struct pipe_context *pipe,
340                                       unsigned num,
341                                       void **sampler)
342 {
343    struct failover_context *failover = failover_context(pipe);
344    struct fo_state *state = (struct fo_state*)sampler;
345    uint i;
346    assert(num <= PIPE_MAX_SAMPLERS);
347    /* Check for no-op */
348    if (num == failover->num_samplers &&
349        !memcmp(failover->sampler, sampler, num * sizeof(void *)))
350       return;
351    for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
352       failover->sw_sampler_state[i] = i < num ? state[i].sw_state : NULL;
353       failover->hw_sampler_state[i] = i < num ? state[i].hw_state : NULL;
354    }
355    failover->dirty |= FO_NEW_SAMPLER;
356    failover->num_samplers = num;
357    failover->sw->bind_fragment_sampler_states(failover->sw, num,
358                                               failover->sw_sampler_state);
359    failover->hw->bind_fragment_sampler_states(failover->hw, num,
360                                               failover->hw_sampler_state);
361 }
362
363 static void
364 failover_bind_vertex_sampler_states(struct pipe_context *pipe,
365                                     unsigned num_samplers,
366                                     void **samplers)
367 {
368    struct failover_context *failover = failover_context(pipe);
369    struct fo_state *state = (struct fo_state*)samplers;
370    uint i;
371
372    assert(num_samplers <= PIPE_MAX_VERTEX_SAMPLERS);
373
374    /* Check for no-op */
375    if (num_samplers == failover->num_vertex_samplers &&
376        !memcmp(failover->vertex_samplers, samplers, num_samplers * sizeof(void *))) {
377       return;
378    }
379    for (i = 0; i < PIPE_MAX_VERTEX_SAMPLERS; i++) {
380       failover->sw_vertex_sampler_state[i] = i < num_samplers ? state[i].sw_state : NULL;
381       failover->hw_vertex_sampler_state[i] = i < num_samplers ? state[i].hw_state : NULL;
382    }
383    failover->dirty |= FO_NEW_SAMPLER;
384    failover->num_vertex_samplers = num_samplers;
385    failover->sw->bind_vertex_sampler_states(failover->sw,
386                                             num_samplers,
387                                             failover->sw_vertex_sampler_state);
388    failover->hw->bind_vertex_sampler_states(failover->hw,
389                                             num_samplers,
390                                             failover->hw_vertex_sampler_state);
391 }
392
393 static void
394 failover_delete_sampler_state(struct pipe_context *pipe, void *sampler)
395 {
396    struct fo_state *state = (struct fo_state*)sampler;
397    struct failover_context *failover = failover_context(pipe);
398
399    failover->sw->delete_sampler_state(failover->sw, state->sw_state);
400    failover->hw->delete_sampler_state(failover->hw, state->hw_state);
401    state->sw_state = 0;
402    state->hw_state = 0;
403    free(state);
404 }
405
406
407 static void
408 failover_set_fragment_sampler_textures(struct pipe_context *pipe,
409                                        unsigned num,
410                                        struct pipe_texture **texture)
411 {
412    struct failover_context *failover = failover_context(pipe);
413    uint i;
414
415    assert(num <= PIPE_MAX_SAMPLERS);
416
417    /* Check for no-op */
418    if (num == failover->num_textures &&
419        !memcmp(failover->texture, texture, num * sizeof(struct pipe_texture *)))
420       return;
421    for (i = 0; i < num; i++)
422       pipe_texture_reference((struct pipe_texture **) &failover->texture[i],
423                              texture[i]);
424    for (i = num; i < failover->num_textures; i++)
425       pipe_texture_reference((struct pipe_texture **) &failover->texture[i],
426                              NULL);
427    failover->dirty |= FO_NEW_TEXTURE;
428    failover->num_textures = num;
429    failover->sw->set_fragment_sampler_textures( failover->sw, num, texture );
430    failover->hw->set_fragment_sampler_textures( failover->hw, num, texture );
431 }
432
433
434 static void
435 failover_set_vertex_sampler_textures(struct pipe_context *pipe,
436                                      unsigned num_textures,
437                                      struct pipe_texture **textures)
438 {
439    struct failover_context *failover = failover_context(pipe);
440    uint i;
441
442    assert(num_textures <= PIPE_MAX_VERTEX_SAMPLERS);
443
444    /* Check for no-op */
445    if (num_textures == failover->num_vertex_textures &&
446        !memcmp(failover->vertex_textures, textures, num_textures * sizeof(struct pipe_texture *))) {
447       return;
448    }
449    for (i = 0; i < num_textures; i++) {
450       pipe_texture_reference((struct pipe_texture **)&failover->vertex_textures[i],
451                              textures[i]);
452    }
453    for (i = num_textures; i < failover->num_vertex_textures; i++) {
454       pipe_texture_reference((struct pipe_texture **)&failover->vertex_textures[i],
455                              NULL);
456    }
457    failover->dirty |= FO_NEW_TEXTURE;
458    failover->num_vertex_textures = num_textures;
459    failover->sw->set_vertex_sampler_textures(failover->sw, num_textures, textures);
460    failover->hw->set_vertex_sampler_textures(failover->hw, num_textures, textures);
461 }
462
463
464 static void 
465 failover_set_viewport_state( struct pipe_context *pipe,
466                              const struct pipe_viewport_state *viewport )
467 {
468    struct failover_context *failover = failover_context(pipe);
469
470    failover->viewport = *viewport; 
471    failover->dirty |= FO_NEW_VIEWPORT;
472    failover->sw->set_viewport_state( failover->sw, viewport );
473    failover->hw->set_viewport_state( failover->hw, viewport );
474 }
475
476
477 static void
478 failover_set_vertex_buffers(struct pipe_context *pipe,
479                             unsigned count,
480                             const struct pipe_vertex_buffer *vertex_buffers)
481 {
482    struct failover_context *failover = failover_context(pipe);
483
484    memcpy(failover->vertex_buffers, vertex_buffers,
485           count * sizeof(vertex_buffers[0]));
486    failover->dirty |= FO_NEW_VERTEX_BUFFER;
487    failover->num_vertex_buffers = count;
488    failover->sw->set_vertex_buffers( failover->sw, count, vertex_buffers );
489    failover->hw->set_vertex_buffers( failover->hw, count, vertex_buffers );
490 }
491
492
493 static void
494 failover_set_vertex_elements(struct pipe_context *pipe,
495                              unsigned count,
496                              const struct pipe_vertex_element *vertex_elements)
497 {
498    struct failover_context *failover = failover_context(pipe);
499
500    memcpy(failover->vertex_elements, vertex_elements,
501           count * sizeof(vertex_elements[0]));
502
503    failover->dirty |= FO_NEW_VERTEX_ELEMENT;
504    failover->num_vertex_elements = count;
505    failover->sw->set_vertex_elements( failover->sw, count, vertex_elements );
506    failover->hw->set_vertex_elements( failover->hw, count, vertex_elements );
507 }
508
509 void
510 failover_set_constant_buffer(struct pipe_context *pipe,
511                              uint shader, uint index,
512                              struct pipe_buffer *buf)
513 {
514    struct failover_context *failover = failover_context(pipe);
515
516    assert(shader < PIPE_SHADER_TYPES);
517    assert(index == 0);
518
519    failover->sw->set_constant_buffer(failover->sw, shader, index, buf);
520    failover->hw->set_constant_buffer(failover->hw, shader, index, buf);
521 }
522
523
524 void
525 failover_init_state_functions( struct failover_context *failover )
526 {
527    failover->pipe.create_blend_state = failover_create_blend_state;
528    failover->pipe.bind_blend_state   = failover_bind_blend_state;
529    failover->pipe.delete_blend_state = failover_delete_blend_state;
530    failover->pipe.create_sampler_state = failover_create_sampler_state;
531    failover->pipe.bind_fragment_sampler_states  = failover_bind_fragment_sampler_states;
532    failover->pipe.bind_vertex_sampler_states  = failover_bind_vertex_sampler_states;
533    failover->pipe.delete_sampler_state = failover_delete_sampler_state;
534    failover->pipe.create_depth_stencil_alpha_state = failover_create_depth_stencil_state;
535    failover->pipe.bind_depth_stencil_alpha_state   = failover_bind_depth_stencil_state;
536    failover->pipe.delete_depth_stencil_alpha_state = failover_delete_depth_stencil_state;
537    failover->pipe.create_rasterizer_state = failover_create_rasterizer_state;
538    failover->pipe.bind_rasterizer_state = failover_bind_rasterizer_state;
539    failover->pipe.delete_rasterizer_state = failover_delete_rasterizer_state;
540    failover->pipe.create_fs_state = failover_create_fs_state;
541    failover->pipe.bind_fs_state   = failover_bind_fs_state;
542    failover->pipe.delete_fs_state = failover_delete_fs_state;
543    failover->pipe.create_vs_state = failover_create_vs_state;
544    failover->pipe.bind_vs_state   = failover_bind_vs_state;
545    failover->pipe.delete_vs_state = failover_delete_vs_state;
546
547    failover->pipe.set_blend_color = failover_set_blend_color;
548    failover->pipe.set_stencil_ref = failover_set_stencil_ref;
549    failover->pipe.set_clip_state = failover_set_clip_state;
550    failover->pipe.set_framebuffer_state = failover_set_framebuffer_state;
551    failover->pipe.set_polygon_stipple = failover_set_polygon_stipple;
552    failover->pipe.set_scissor_state = failover_set_scissor_state;
553    failover->pipe.set_fragment_sampler_textures = failover_set_fragment_sampler_textures;
554    failover->pipe.set_vertex_sampler_textures = failover_set_vertex_sampler_textures;
555    failover->pipe.set_viewport_state = failover_set_viewport_state;
556    failover->pipe.set_vertex_buffers = failover_set_vertex_buffers;
557    failover->pipe.set_vertex_elements = failover_set_vertex_elements;
558    failover->pipe.set_constant_buffer = failover_set_constant_buffer;
559 }