Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / gallium / auxiliary / cso_cache / cso_context.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  /**
29   * @file
30   * 
31   * Wrap the cso cache & hash mechanisms in a simplified
32   * pipe-driver-specific interface.
33   *
34   * @author Zack Rusin <zack@tungstengraphics.com>
35   * @author Keith Whitwell <keith@tungstengraphics.com>
36   */
37
38 #include "pipe/p_state.h"
39 #include "util/u_framebuffer.h"
40 #include "util/u_inlines.h"
41 #include "util/u_math.h"
42 #include "util/u_memory.h"
43 #include "tgsi/tgsi_parse.h"
44
45 #include "cso_cache/cso_context.h"
46 #include "cso_cache/cso_cache.h"
47 #include "cso_cache/cso_hash.h"
48 #include "cso_context.h"
49
50
51 /**
52  * Info related to samplers and sampler views.
53  * We have one of these for fragment samplers and another for vertex samplers.
54  */
55 struct sampler_info
56 {
57    struct {
58       void *samplers[PIPE_MAX_SAMPLERS];
59       unsigned nr_samplers;
60    } hw;
61
62    void *samplers[PIPE_MAX_SAMPLERS];
63    unsigned nr_samplers;
64
65    void *samplers_saved[PIPE_MAX_SAMPLERS];
66    unsigned nr_samplers_saved;
67
68    struct pipe_sampler_view *views[PIPE_MAX_SAMPLERS];
69    unsigned nr_views;
70
71    struct pipe_sampler_view *views_saved[PIPE_MAX_SAMPLERS];
72    unsigned nr_views_saved;
73 };
74
75
76
77 struct cso_context {
78    struct pipe_context *pipe;
79    struct cso_cache *cache;
80
81    struct sampler_info fragment_samplers;
82    struct sampler_info vertex_samplers;
83
84    uint nr_vertex_buffers;
85    struct pipe_vertex_buffer vertex_buffers[PIPE_MAX_ATTRIBS];
86
87    uint nr_vertex_buffers_saved;
88    struct pipe_vertex_buffer vertex_buffers_saved[PIPE_MAX_ATTRIBS];
89
90    /** Current and saved state.
91     * The saved state is used as a 1-deep stack.
92     */
93    void *blend, *blend_saved;
94    void *depth_stencil, *depth_stencil_saved;
95    void *rasterizer, *rasterizer_saved;
96    void *fragment_shader, *fragment_shader_saved, *geometry_shader;
97    void *vertex_shader, *vertex_shader_saved, *geometry_shader_saved;
98    void *velements, *velements_saved;
99
100    struct pipe_clip_state clip;
101    struct pipe_clip_state clip_saved;
102
103    struct pipe_framebuffer_state fb, fb_saved;
104    struct pipe_viewport_state vp, vp_saved;
105    struct pipe_blend_color blend_color;
106    unsigned sample_mask;
107    struct pipe_stencil_ref stencil_ref, stencil_ref_saved;
108 };
109
110
111 static boolean delete_blend_state(struct cso_context *ctx, void *state)
112 {
113    struct cso_blend *cso = (struct cso_blend *)state;
114
115    if (ctx->blend == cso->data)
116       return FALSE;
117
118    if (cso->delete_state)
119       cso->delete_state(cso->context, cso->data);
120    FREE(state);
121    return TRUE;
122 }
123
124 static boolean delete_depth_stencil_state(struct cso_context *ctx, void *state)
125 {
126    struct cso_depth_stencil_alpha *cso = (struct cso_depth_stencil_alpha *)state;
127
128    if (ctx->depth_stencil == cso->data)
129       return FALSE;
130
131    if (cso->delete_state)
132       cso->delete_state(cso->context, cso->data);
133    FREE(state);
134
135    return TRUE;
136 }
137
138 static boolean delete_sampler_state(struct cso_context *ctx, void *state)
139 {
140    struct cso_sampler *cso = (struct cso_sampler *)state;
141    if (cso->delete_state)
142       cso->delete_state(cso->context, cso->data);
143    FREE(state);
144    return TRUE;
145 }
146
147 static boolean delete_rasterizer_state(struct cso_context *ctx, void *state)
148 {
149    struct cso_rasterizer *cso = (struct cso_rasterizer *)state;
150
151    if (ctx->rasterizer == cso->data)
152       return FALSE;
153    if (cso->delete_state)
154       cso->delete_state(cso->context, cso->data);
155    FREE(state);
156    return TRUE;
157 }
158
159 static boolean delete_fs_state(struct cso_context *ctx, void *state)
160 {
161    struct cso_fragment_shader *cso = (struct cso_fragment_shader *)state;
162    if (ctx->fragment_shader == cso->data)
163       return FALSE;
164    if (cso->delete_state)
165       cso->delete_state(cso->context, cso->data);
166    FREE(state);
167    return TRUE;
168 }
169
170 static boolean delete_vs_state(struct cso_context *ctx, void *state)
171 {
172    struct cso_vertex_shader *cso = (struct cso_vertex_shader *)state;
173    if (ctx->vertex_shader == cso->data)
174       return TRUE;
175    if (cso->delete_state)
176       cso->delete_state(cso->context, cso->data);
177    FREE(state);
178    return FALSE;
179 }
180
181 static boolean delete_vertex_elements(struct cso_context *ctx,
182                                       void *state)
183 {
184    struct cso_velements *cso = (struct cso_velements *)state;
185
186    if (ctx->velements == cso->data)
187       return FALSE;
188
189    if (cso->delete_state)
190       cso->delete_state(cso->context, cso->data);
191    FREE(state);
192    return TRUE;
193 }
194
195
196 static INLINE boolean delete_cso(struct cso_context *ctx,
197                                  void *state, enum cso_cache_type type)
198 {
199    switch (type) {
200    case CSO_BLEND:
201       return delete_blend_state(ctx, state);
202       break;
203    case CSO_SAMPLER:
204       return delete_sampler_state(ctx, state);
205       break;
206    case CSO_DEPTH_STENCIL_ALPHA:
207       return delete_depth_stencil_state(ctx, state);
208       break;
209    case CSO_RASTERIZER:
210       return delete_rasterizer_state(ctx, state);
211       break;
212    case CSO_FRAGMENT_SHADER:
213       return delete_fs_state(ctx, state);
214       break;
215    case CSO_VERTEX_SHADER:
216       return delete_vs_state(ctx, state);
217       break;
218    case CSO_VELEMENTS:
219       return delete_vertex_elements(ctx, state);
220       break;
221    default:
222       assert(0);
223       FREE(state);
224    }
225    return FALSE;
226 }
227
228 static INLINE void sanitize_hash(struct cso_hash *hash, enum cso_cache_type type,
229                                  int max_size, void *user_data)
230 {
231    struct cso_context *ctx = (struct cso_context *)user_data;
232    /* if we're approach the maximum size, remove fourth of the entries
233     * otherwise every subsequent call will go through the same */
234    int hash_size = cso_hash_size(hash);
235    int max_entries = (max_size > hash_size) ? max_size : hash_size;
236    int to_remove =  (max_size < max_entries) * max_entries/4;
237    struct cso_hash_iter iter = cso_hash_first_node(hash);
238    if (hash_size > max_size)
239       to_remove += hash_size - max_size;
240    while (to_remove) {
241       /*remove elements until we're good */
242       /*fixme: currently we pick the nodes to remove at random*/
243       void *cso = cso_hash_iter_data(iter);
244       if (delete_cso(ctx, cso, type)) {
245          iter = cso_hash_erase(hash, iter);
246          --to_remove;
247       } else
248          iter = cso_hash_iter_next(iter);
249    }
250 }
251
252
253 struct cso_context *cso_create_context( struct pipe_context *pipe )
254 {
255    struct cso_context *ctx = CALLOC_STRUCT(cso_context);
256    if (ctx == NULL)
257       goto out;
258
259    assert(PIPE_MAX_SAMPLERS == PIPE_MAX_VERTEX_SAMPLERS);
260
261    ctx->cache = cso_cache_create();
262    if (ctx->cache == NULL)
263       goto out;
264    cso_cache_set_sanitize_callback(ctx->cache,
265                                    sanitize_hash,
266                                    ctx);
267
268    ctx->pipe = pipe;
269
270    /* Enable for testing: */
271    if (0) cso_set_maximum_cache_size( ctx->cache, 4 );
272
273    return ctx;
274
275 out:
276    cso_destroy_context( ctx );      
277    return NULL;
278 }
279
280
281 /**
282  * Prior to context destruction, this function unbinds all state objects.
283  */
284 void cso_release_all( struct cso_context *ctx )
285 {
286    unsigned i;
287    struct sampler_info *info;
288
289    if (ctx->pipe) {
290       ctx->pipe->bind_blend_state( ctx->pipe, NULL );
291       ctx->pipe->bind_rasterizer_state( ctx->pipe, NULL );
292       ctx->pipe->bind_fragment_sampler_states( ctx->pipe, 0, NULL );
293       if (ctx->pipe->bind_vertex_sampler_states)
294          ctx->pipe->bind_vertex_sampler_states(ctx->pipe, 0, NULL);
295       ctx->pipe->bind_depth_stencil_alpha_state( ctx->pipe, NULL );
296       ctx->pipe->bind_fs_state( ctx->pipe, NULL );
297       ctx->pipe->bind_vs_state( ctx->pipe, NULL );
298       ctx->pipe->bind_vertex_elements_state( ctx->pipe, NULL );
299       ctx->pipe->set_fragment_sampler_views(ctx->pipe, 0, NULL);
300       if (ctx->pipe->set_vertex_sampler_views)
301          ctx->pipe->set_vertex_sampler_views(ctx->pipe, 0, NULL);
302    }
303
304    /* free fragment samplers, views */
305    info = &ctx->fragment_samplers;   
306    for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
307       pipe_sampler_view_reference(&info->views[i], NULL);
308       pipe_sampler_view_reference(&info->views_saved[i], NULL);
309    }
310
311    /* free vertex samplers, views */
312    info = &ctx->vertex_samplers;   
313    for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
314       pipe_sampler_view_reference(&info->views[i], NULL);
315       pipe_sampler_view_reference(&info->views_saved[i], NULL);
316    }
317
318    util_unreference_framebuffer_state(&ctx->fb);
319    util_unreference_framebuffer_state(&ctx->fb_saved);
320
321    util_copy_vertex_buffers(ctx->vertex_buffers,
322                             &ctx->nr_vertex_buffers,
323                             NULL, 0);
324    util_copy_vertex_buffers(ctx->vertex_buffers_saved,
325                             &ctx->nr_vertex_buffers_saved,
326                             NULL, 0);
327
328    if (ctx->cache) {
329       cso_cache_delete( ctx->cache );
330       ctx->cache = NULL;
331    }
332 }
333
334
335 /**
336  * Free the CSO context.  NOTE: the state tracker should have previously called
337  * cso_release_all().
338  */
339 void cso_destroy_context( struct cso_context *ctx )
340 {
341    if (ctx) {
342       FREE( ctx );
343    }
344 }
345
346
347 /* Those function will either find the state of the given template
348  * in the cache or they will create a new state from the given
349  * template, insert it in the cache and return it.
350  */
351
352 /*
353  * If the driver returns 0 from the create method then they will assign
354  * the data member of the cso to be the template itself.
355  */
356
357 enum pipe_error cso_set_blend(struct cso_context *ctx,
358                               const struct pipe_blend_state *templ)
359 {
360    unsigned key_size, hash_key;
361    struct cso_hash_iter iter;
362    void *handle;
363
364    key_size = templ->independent_blend_enable ? sizeof(struct pipe_blend_state) :
365               (char *)&(templ->rt[1]) - (char *)templ;
366    hash_key = cso_construct_key((void*)templ, key_size);
367    iter = cso_find_state_template(ctx->cache, hash_key, CSO_BLEND, (void*)templ, key_size);
368
369    if (cso_hash_iter_is_null(iter)) {
370       struct cso_blend *cso = MALLOC(sizeof(struct cso_blend));
371       if (!cso)
372          return PIPE_ERROR_OUT_OF_MEMORY;
373
374       memset(&cso->state, 0, sizeof cso->state);
375       memcpy(&cso->state, templ, key_size);
376       cso->data = ctx->pipe->create_blend_state(ctx->pipe, &cso->state);
377       cso->delete_state = (cso_state_callback)ctx->pipe->delete_blend_state;
378       cso->context = ctx->pipe;
379
380       iter = cso_insert_state(ctx->cache, hash_key, CSO_BLEND, cso);
381       if (cso_hash_iter_is_null(iter)) {
382          FREE(cso);
383          return PIPE_ERROR_OUT_OF_MEMORY;
384       }
385
386       handle = cso->data;
387    }
388    else {
389       handle = ((struct cso_blend *)cso_hash_iter_data(iter))->data;
390    }
391
392    if (ctx->blend != handle) {
393       ctx->blend = handle;
394       ctx->pipe->bind_blend_state(ctx->pipe, handle);
395    }
396    return PIPE_OK;
397 }
398
399 void cso_save_blend(struct cso_context *ctx)
400 {
401    assert(!ctx->blend_saved);
402    ctx->blend_saved = ctx->blend;
403 }
404
405 void cso_restore_blend(struct cso_context *ctx)
406 {
407    if (ctx->blend != ctx->blend_saved) {
408       ctx->blend = ctx->blend_saved;
409       ctx->pipe->bind_blend_state(ctx->pipe, ctx->blend_saved);
410    }
411    ctx->blend_saved = NULL;
412 }
413
414
415
416 enum pipe_error cso_set_depth_stencil_alpha(struct cso_context *ctx,
417                                             const struct pipe_depth_stencil_alpha_state *templ)
418 {
419    unsigned key_size = sizeof(struct pipe_depth_stencil_alpha_state);
420    unsigned hash_key = cso_construct_key((void*)templ, key_size);
421    struct cso_hash_iter iter = cso_find_state_template(ctx->cache,
422                                                        hash_key, 
423                                                        CSO_DEPTH_STENCIL_ALPHA,
424                                                        (void*)templ, key_size);
425    void *handle;
426
427    if (cso_hash_iter_is_null(iter)) {
428       struct cso_depth_stencil_alpha *cso = MALLOC(sizeof(struct cso_depth_stencil_alpha));
429       if (!cso)
430          return PIPE_ERROR_OUT_OF_MEMORY;
431
432       memcpy(&cso->state, templ, sizeof(*templ));
433       cso->data = ctx->pipe->create_depth_stencil_alpha_state(ctx->pipe, &cso->state);
434       cso->delete_state = (cso_state_callback)ctx->pipe->delete_depth_stencil_alpha_state;
435       cso->context = ctx->pipe;
436
437       iter = cso_insert_state(ctx->cache, hash_key, CSO_DEPTH_STENCIL_ALPHA, cso);
438       if (cso_hash_iter_is_null(iter)) {
439          FREE(cso);
440          return PIPE_ERROR_OUT_OF_MEMORY;
441       }
442
443       handle = cso->data;
444    }
445    else {
446       handle = ((struct cso_depth_stencil_alpha *)cso_hash_iter_data(iter))->data;
447    }
448
449    if (ctx->depth_stencil != handle) {
450       ctx->depth_stencil = handle;
451       ctx->pipe->bind_depth_stencil_alpha_state(ctx->pipe, handle);
452    }
453    return PIPE_OK;
454 }
455
456 void cso_save_depth_stencil_alpha(struct cso_context *ctx)
457 {
458    assert(!ctx->depth_stencil_saved);
459    ctx->depth_stencil_saved = ctx->depth_stencil;
460 }
461
462 void cso_restore_depth_stencil_alpha(struct cso_context *ctx)
463 {
464    if (ctx->depth_stencil != ctx->depth_stencil_saved) {
465       ctx->depth_stencil = ctx->depth_stencil_saved;
466       ctx->pipe->bind_depth_stencil_alpha_state(ctx->pipe, ctx->depth_stencil_saved);
467    }
468    ctx->depth_stencil_saved = NULL;
469 }
470
471
472
473 enum pipe_error cso_set_rasterizer(struct cso_context *ctx,
474                                    const struct pipe_rasterizer_state *templ)
475 {
476    unsigned key_size = sizeof(struct pipe_rasterizer_state);
477    unsigned hash_key = cso_construct_key((void*)templ, key_size);
478    struct cso_hash_iter iter = cso_find_state_template(ctx->cache,
479                                                        hash_key, CSO_RASTERIZER,
480                                                        (void*)templ, key_size);
481    void *handle = NULL;
482
483    if (cso_hash_iter_is_null(iter)) {
484       struct cso_rasterizer *cso = MALLOC(sizeof(struct cso_rasterizer));
485       if (!cso)
486          return PIPE_ERROR_OUT_OF_MEMORY;
487
488       memcpy(&cso->state, templ, sizeof(*templ));
489       cso->data = ctx->pipe->create_rasterizer_state(ctx->pipe, &cso->state);
490       cso->delete_state = (cso_state_callback)ctx->pipe->delete_rasterizer_state;
491       cso->context = ctx->pipe;
492
493       iter = cso_insert_state(ctx->cache, hash_key, CSO_RASTERIZER, cso);
494       if (cso_hash_iter_is_null(iter)) {
495          FREE(cso);
496          return PIPE_ERROR_OUT_OF_MEMORY;
497       }
498
499       handle = cso->data;
500    }
501    else {
502       handle = ((struct cso_rasterizer *)cso_hash_iter_data(iter))->data;
503    }
504
505    if (ctx->rasterizer != handle) {
506       ctx->rasterizer = handle;
507       ctx->pipe->bind_rasterizer_state(ctx->pipe, handle);
508    }
509    return PIPE_OK;
510 }
511
512 void cso_save_rasterizer(struct cso_context *ctx)
513 {
514    assert(!ctx->rasterizer_saved);
515    ctx->rasterizer_saved = ctx->rasterizer;
516 }
517
518 void cso_restore_rasterizer(struct cso_context *ctx)
519 {
520    if (ctx->rasterizer != ctx->rasterizer_saved) {
521       ctx->rasterizer = ctx->rasterizer_saved;
522       ctx->pipe->bind_rasterizer_state(ctx->pipe, ctx->rasterizer_saved);
523    }
524    ctx->rasterizer_saved = NULL;
525 }
526
527
528
529 enum pipe_error cso_set_fragment_shader_handle(struct cso_context *ctx,
530                                                void *handle )
531 {
532    if (ctx->fragment_shader != handle) {
533       ctx->fragment_shader = handle;
534       ctx->pipe->bind_fs_state(ctx->pipe, handle);
535    }
536    return PIPE_OK;
537 }
538
539 void cso_delete_fragment_shader(struct cso_context *ctx, void *handle )
540 {
541    if (handle == ctx->fragment_shader) {
542       /* unbind before deleting */
543       ctx->pipe->bind_fs_state(ctx->pipe, NULL);
544       ctx->fragment_shader = NULL;
545    }
546    ctx->pipe->delete_fs_state(ctx->pipe, handle);
547 }
548
549 /* Not really working:
550  */
551 #if 0
552 enum pipe_error cso_set_fragment_shader(struct cso_context *ctx,
553                                         const struct pipe_shader_state *templ)
554 {
555    const struct tgsi_token *tokens = templ->tokens;
556    unsigned num_tokens = tgsi_num_tokens(tokens);
557    size_t tokens_size = num_tokens*sizeof(struct tgsi_token);
558    unsigned hash_key = cso_construct_key((void*)tokens, tokens_size);
559    struct cso_hash_iter iter = cso_find_state_template(ctx->cache,
560                                                        hash_key, 
561                                                        CSO_FRAGMENT_SHADER,
562                                                        (void*)tokens,
563                                                        sizeof(*templ)); /* XXX correct? tokens_size? */
564    void *handle = NULL;
565
566    if (cso_hash_iter_is_null(iter)) {
567       struct cso_fragment_shader *cso = MALLOC(sizeof(struct cso_fragment_shader) + tokens_size);
568       struct tgsi_token *cso_tokens = (struct tgsi_token *)((char *)cso + sizeof(*cso));
569
570       if (!cso)
571          return PIPE_ERROR_OUT_OF_MEMORY;
572
573       memcpy(cso_tokens, tokens, tokens_size);
574       cso->state.tokens = cso_tokens;
575       cso->data = ctx->pipe->create_fs_state(ctx->pipe, &cso->state);
576       cso->delete_state = (cso_state_callback)ctx->pipe->delete_fs_state;
577       cso->context = ctx->pipe;
578
579       iter = cso_insert_state(ctx->cache, hash_key, CSO_FRAGMENT_SHADER, cso);
580       if (cso_hash_iter_is_null(iter)) {
581          FREE(cso);
582          return PIPE_ERROR_OUT_OF_MEMORY;
583       }
584
585       handle = cso->data;
586    }
587    else {
588       handle = ((struct cso_fragment_shader *)cso_hash_iter_data(iter))->data;
589    }
590
591    return cso_set_fragment_shader_handle( ctx, handle );
592 }
593 #endif
594
595 void cso_save_fragment_shader(struct cso_context *ctx)
596 {
597    assert(!ctx->fragment_shader_saved);
598    ctx->fragment_shader_saved = ctx->fragment_shader;
599 }
600
601 void cso_restore_fragment_shader(struct cso_context *ctx)
602 {
603    if (ctx->fragment_shader_saved != ctx->fragment_shader) {
604       ctx->pipe->bind_fs_state(ctx->pipe, ctx->fragment_shader_saved);
605       ctx->fragment_shader = ctx->fragment_shader_saved;
606    }
607    ctx->fragment_shader_saved = NULL;
608 }
609
610
611 enum pipe_error cso_set_vertex_shader_handle(struct cso_context *ctx,
612                                              void *handle )
613 {
614    if (ctx->vertex_shader != handle) {
615       ctx->vertex_shader = handle;
616       ctx->pipe->bind_vs_state(ctx->pipe, handle);
617    }
618    return PIPE_OK;
619 }
620
621 void cso_delete_vertex_shader(struct cso_context *ctx, void *handle )
622 {
623    if (handle == ctx->vertex_shader) {
624       /* unbind before deleting */
625       ctx->pipe->bind_vs_state(ctx->pipe, NULL);
626       ctx->vertex_shader = NULL;
627    }
628    ctx->pipe->delete_vs_state(ctx->pipe, handle);
629 }
630
631
632 /* Not really working:
633  */
634 #if 0
635 enum pipe_error cso_set_vertex_shader(struct cso_context *ctx,
636                                       const struct pipe_shader_state *templ)
637 {
638    unsigned hash_key = cso_construct_key((void*)templ,
639                                          sizeof(struct pipe_shader_state));
640    struct cso_hash_iter iter = cso_find_state_template(ctx->cache,
641                                                        hash_key, CSO_VERTEX_SHADER,
642                                                        (void*)templ,
643                                                        sizeof(*templ));
644    void *handle = NULL;
645
646    if (cso_hash_iter_is_null(iter)) {
647       struct cso_vertex_shader *cso = MALLOC(sizeof(struct cso_vertex_shader));
648
649       if (!cso)
650          return PIPE_ERROR_OUT_OF_MEMORY;
651
652       memcpy(cso->state, templ, sizeof(*templ));
653       cso->data = ctx->pipe->create_vs_state(ctx->pipe, &cso->state);
654       cso->delete_state = (cso_state_callback)ctx->pipe->delete_vs_state;
655       cso->context = ctx->pipe;
656
657       iter = cso_insert_state(ctx->cache, hash_key, CSO_VERTEX_SHADER, cso);
658       if (cso_hash_iter_is_null(iter)) {
659          FREE(cso);
660          return PIPE_ERROR_OUT_OF_MEMORY;
661       }
662
663       handle = cso->data;
664    }
665    else {
666       handle = ((struct cso_vertex_shader *)cso_hash_iter_data(iter))->data;
667    }
668
669    return cso_set_vertex_shader_handle( ctx, handle );
670 }
671 #endif
672
673
674
675 void cso_save_vertex_shader(struct cso_context *ctx)
676 {
677    assert(!ctx->vertex_shader_saved);
678    ctx->vertex_shader_saved = ctx->vertex_shader;
679 }
680
681 void cso_restore_vertex_shader(struct cso_context *ctx)
682 {
683    if (ctx->vertex_shader_saved != ctx->vertex_shader) {
684       ctx->pipe->bind_vs_state(ctx->pipe, ctx->vertex_shader_saved);
685       ctx->vertex_shader = ctx->vertex_shader_saved;
686    }
687    ctx->vertex_shader_saved = NULL;
688 }
689
690
691 enum pipe_error cso_set_framebuffer(struct cso_context *ctx,
692                                     const struct pipe_framebuffer_state *fb)
693 {
694    if (memcmp(&ctx->fb, fb, sizeof(*fb)) != 0) {
695       util_copy_framebuffer_state(&ctx->fb, fb);
696       ctx->pipe->set_framebuffer_state(ctx->pipe, fb);
697    }
698    return PIPE_OK;
699 }
700
701 void cso_save_framebuffer(struct cso_context *ctx)
702 {
703    util_copy_framebuffer_state(&ctx->fb_saved, &ctx->fb);
704 }
705
706 void cso_restore_framebuffer(struct cso_context *ctx)
707 {
708    if (memcmp(&ctx->fb, &ctx->fb_saved, sizeof(ctx->fb))) {
709       util_copy_framebuffer_state(&ctx->fb, &ctx->fb_saved);
710       ctx->pipe->set_framebuffer_state(ctx->pipe, &ctx->fb);
711       util_unreference_framebuffer_state(&ctx->fb_saved);
712    }
713 }
714
715
716 enum pipe_error cso_set_viewport(struct cso_context *ctx,
717                                  const struct pipe_viewport_state *vp)
718 {
719    if (memcmp(&ctx->vp, vp, sizeof(*vp))) {
720       ctx->vp = *vp;
721       ctx->pipe->set_viewport_state(ctx->pipe, vp);
722    }
723    return PIPE_OK;
724 }
725
726 void cso_save_viewport(struct cso_context *ctx)
727 {
728    ctx->vp_saved = ctx->vp;
729 }
730
731
732 void cso_restore_viewport(struct cso_context *ctx)
733 {
734    if (memcmp(&ctx->vp, &ctx->vp_saved, sizeof(ctx->vp))) {
735       ctx->vp = ctx->vp_saved;
736       ctx->pipe->set_viewport_state(ctx->pipe, &ctx->vp);
737    }
738 }
739
740
741 enum pipe_error cso_set_blend_color(struct cso_context *ctx,
742                                     const struct pipe_blend_color *bc)
743 {
744    if (memcmp(&ctx->blend_color, bc, sizeof(ctx->blend_color))) {
745       ctx->blend_color = *bc;
746       ctx->pipe->set_blend_color(ctx->pipe, bc);
747    }
748    return PIPE_OK;
749 }
750
751 enum pipe_error cso_set_sample_mask(struct cso_context *ctx,
752                                     unsigned sample_mask)
753 {
754    if (ctx->sample_mask != sample_mask) {
755       ctx->sample_mask = sample_mask;
756       ctx->pipe->set_sample_mask(ctx->pipe, sample_mask);
757    }
758    return PIPE_OK;
759 }
760
761 enum pipe_error cso_set_stencil_ref(struct cso_context *ctx,
762                                     const struct pipe_stencil_ref *sr)
763 {
764    if (memcmp(&ctx->stencil_ref, sr, sizeof(ctx->stencil_ref))) {
765       ctx->stencil_ref = *sr;
766       ctx->pipe->set_stencil_ref(ctx->pipe, sr);
767    }
768    return PIPE_OK;
769 }
770
771 void cso_save_stencil_ref(struct cso_context *ctx)
772 {
773    ctx->stencil_ref_saved = ctx->stencil_ref;
774 }
775
776
777 void cso_restore_stencil_ref(struct cso_context *ctx)
778 {
779    if (memcmp(&ctx->stencil_ref, &ctx->stencil_ref_saved, sizeof(ctx->stencil_ref))) {
780       ctx->stencil_ref = ctx->stencil_ref_saved;
781       ctx->pipe->set_stencil_ref(ctx->pipe, &ctx->stencil_ref);
782    }
783 }
784
785 enum pipe_error cso_set_geometry_shader_handle(struct cso_context *ctx,
786                                                void *handle)
787 {
788    if (ctx->geometry_shader != handle) {
789       ctx->geometry_shader = handle;
790       ctx->pipe->bind_gs_state(ctx->pipe, handle);
791    }
792    return PIPE_OK;
793 }
794
795 void cso_delete_geometry_shader(struct cso_context *ctx, void *handle)
796 {
797     if (handle == ctx->geometry_shader) {
798       /* unbind before deleting */
799       ctx->pipe->bind_gs_state(ctx->pipe, NULL);
800       ctx->geometry_shader = NULL;
801    }
802    ctx->pipe->delete_gs_state(ctx->pipe, handle);
803 }
804
805 void cso_save_geometry_shader(struct cso_context *ctx)
806 {
807    assert(!ctx->geometry_shader_saved);
808    ctx->geometry_shader_saved = ctx->geometry_shader;
809 }
810
811 void cso_restore_geometry_shader(struct cso_context *ctx)
812 {
813    if (ctx->geometry_shader_saved != ctx->geometry_shader) {
814       ctx->pipe->bind_gs_state(ctx->pipe, ctx->geometry_shader_saved);
815       ctx->geometry_shader = ctx->geometry_shader_saved;
816    }
817    ctx->geometry_shader_saved = NULL;
818 }
819
820 /* clip state */
821
822 static INLINE void
823 clip_state_cpy(struct pipe_clip_state *dst,
824                const struct pipe_clip_state *src)
825 {
826    dst->depth_clamp = src->depth_clamp;
827    dst->nr = src->nr;
828    if (src->nr) {
829       memcpy(dst->ucp, src->ucp, src->nr * sizeof(src->ucp[0]));
830    }
831 }
832
833 static INLINE int
834 clip_state_cmp(const struct pipe_clip_state *a,
835                const struct pipe_clip_state *b)
836 {
837    if (a->depth_clamp != b->depth_clamp) {
838       return 1;
839    }
840    if (a->nr != b->nr) {
841       return 1;
842    }
843    if (a->nr) {
844       return memcmp(a->ucp, b->ucp, a->nr * sizeof(a->ucp[0]));
845    }
846    return 0;
847 }
848
849 void
850 cso_set_clip(struct cso_context *ctx,
851              const struct pipe_clip_state *clip)
852 {
853    if (clip_state_cmp(&ctx->clip, clip)) {
854       clip_state_cpy(&ctx->clip, clip);
855       ctx->pipe->set_clip_state(ctx->pipe, clip);
856    }
857 }
858
859 void
860 cso_save_clip(struct cso_context *ctx)
861 {
862    clip_state_cpy(&ctx->clip_saved, &ctx->clip);
863 }
864
865 void
866 cso_restore_clip(struct cso_context *ctx)
867 {
868    if (clip_state_cmp(&ctx->clip, &ctx->clip_saved)) {
869       clip_state_cpy(&ctx->clip, &ctx->clip_saved);
870       ctx->pipe->set_clip_state(ctx->pipe, &ctx->clip_saved);
871    }
872 }
873
874 enum pipe_error cso_set_vertex_elements(struct cso_context *ctx,
875                                         unsigned count,
876                                         const struct pipe_vertex_element *states)
877 {
878    unsigned key_size, hash_key;
879    struct cso_hash_iter iter;
880    void *handle;
881    struct cso_velems_state velems_state;
882
883    /* need to include the count into the stored state data too.
884       Otherwise first few count pipe_vertex_elements could be identical even if count
885       is different, and there's no guarantee the hash would be different in that
886       case neither */
887    key_size = sizeof(struct pipe_vertex_element) * count + sizeof(unsigned);
888    velems_state.count = count;
889    memcpy(velems_state.velems, states, sizeof(struct pipe_vertex_element) * count);
890    hash_key = cso_construct_key((void*)&velems_state, key_size);
891    iter = cso_find_state_template(ctx->cache, hash_key, CSO_VELEMENTS, (void*)&velems_state, key_size);
892
893    if (cso_hash_iter_is_null(iter)) {
894       struct cso_velements *cso = MALLOC(sizeof(struct cso_velements));
895       if (!cso)
896          return PIPE_ERROR_OUT_OF_MEMORY;
897
898       memcpy(&cso->state, &velems_state, key_size);
899       cso->data = ctx->pipe->create_vertex_elements_state(ctx->pipe, count, &cso->state.velems[0]);
900       cso->delete_state = (cso_state_callback)ctx->pipe->delete_vertex_elements_state;
901       cso->context = ctx->pipe;
902
903       iter = cso_insert_state(ctx->cache, hash_key, CSO_VELEMENTS, cso);
904       if (cso_hash_iter_is_null(iter)) {
905          FREE(cso);
906          return PIPE_ERROR_OUT_OF_MEMORY;
907       }
908
909       handle = cso->data;
910    }
911    else {
912       handle = ((struct cso_velements *)cso_hash_iter_data(iter))->data;
913    }
914
915    if (ctx->velements != handle) {
916       ctx->velements = handle;
917       ctx->pipe->bind_vertex_elements_state(ctx->pipe, handle);
918    }
919    return PIPE_OK;
920 }
921
922 void cso_save_vertex_elements(struct cso_context *ctx)
923 {
924    assert(!ctx->velements_saved);
925    ctx->velements_saved = ctx->velements;
926 }
927
928 void cso_restore_vertex_elements(struct cso_context *ctx)
929 {
930    if (ctx->velements != ctx->velements_saved) {
931       ctx->velements = ctx->velements_saved;
932       ctx->pipe->bind_vertex_elements_state(ctx->pipe, ctx->velements_saved);
933    }
934    ctx->velements_saved = NULL;
935 }
936
937 /* vertex buffers */
938
939 void cso_set_vertex_buffers(struct cso_context *ctx,
940                             unsigned count,
941                             const struct pipe_vertex_buffer *buffers)
942 {
943    if (count != ctx->nr_vertex_buffers ||
944        memcmp(buffers, ctx->vertex_buffers,
945               sizeof(struct pipe_vertex_buffer) * count) != 0) {
946       util_copy_vertex_buffers(ctx->vertex_buffers, &ctx->nr_vertex_buffers,
947                                buffers, count);
948       ctx->pipe->set_vertex_buffers(ctx->pipe, count, buffers);
949    }
950 }
951
952 void cso_save_vertex_buffers(struct cso_context *ctx)
953 {
954    util_copy_vertex_buffers(ctx->vertex_buffers_saved,
955                             &ctx->nr_vertex_buffers_saved,
956                             ctx->vertex_buffers,
957                             ctx->nr_vertex_buffers);
958 }
959
960 void cso_restore_vertex_buffers(struct cso_context *ctx)
961 {
962    util_copy_vertex_buffers(ctx->vertex_buffers,
963                             &ctx->nr_vertex_buffers,
964                             ctx->vertex_buffers_saved,
965                             ctx->nr_vertex_buffers_saved);
966    ctx->pipe->set_vertex_buffers(ctx->pipe, ctx->nr_vertex_buffers,
967                                  ctx->vertex_buffers);
968 }
969
970
971 /**************** fragment/vertex sampler view state *************************/
972
973 static enum pipe_error
974 single_sampler(struct cso_context *ctx,
975                struct sampler_info *info,
976                unsigned idx,
977                const struct pipe_sampler_state *templ)
978 {
979    void *handle = NULL;
980
981    if (templ != NULL) {
982       unsigned key_size = sizeof(struct pipe_sampler_state);
983       unsigned hash_key = cso_construct_key((void*)templ, key_size);
984       struct cso_hash_iter iter =
985          cso_find_state_template(ctx->cache,
986                                  hash_key, CSO_SAMPLER,
987                                  (void *) templ, key_size);
988
989       if (cso_hash_iter_is_null(iter)) {
990          struct cso_sampler *cso = MALLOC(sizeof(struct cso_sampler));
991          if (!cso)
992             return PIPE_ERROR_OUT_OF_MEMORY;
993
994          memcpy(&cso->state, templ, sizeof(*templ));
995          cso->data = ctx->pipe->create_sampler_state(ctx->pipe, &cso->state);
996          cso->delete_state = (cso_state_callback)ctx->pipe->delete_sampler_state;
997          cso->context = ctx->pipe;
998
999          iter = cso_insert_state(ctx->cache, hash_key, CSO_SAMPLER, cso);
1000          if (cso_hash_iter_is_null(iter)) {
1001             FREE(cso);
1002             return PIPE_ERROR_OUT_OF_MEMORY;
1003          }
1004
1005          handle = cso->data;
1006       }
1007       else {
1008          handle = ((struct cso_sampler *)cso_hash_iter_data(iter))->data;
1009       }
1010    }
1011
1012    info->samplers[idx] = handle;
1013
1014    return PIPE_OK;
1015 }
1016
1017 enum pipe_error
1018 cso_single_sampler(struct cso_context *ctx,
1019                    unsigned idx,
1020                    const struct pipe_sampler_state *templ)
1021 {
1022    return single_sampler(ctx, &ctx->fragment_samplers, idx, templ);
1023 }
1024
1025 enum pipe_error
1026 cso_single_vertex_sampler(struct cso_context *ctx,
1027                           unsigned idx,
1028                           const struct pipe_sampler_state *templ)
1029 {
1030    return single_sampler(ctx, &ctx->vertex_samplers, idx, templ);
1031 }
1032
1033
1034
1035 static void
1036 single_sampler_done(struct cso_context *ctx,
1037                     struct sampler_info *info)
1038 {
1039    unsigned i;
1040
1041    /* find highest non-null sampler */
1042    for (i = PIPE_MAX_SAMPLERS; i > 0; i--) {
1043       if (info->samplers[i - 1] != NULL)
1044          break;
1045    }
1046
1047    info->nr_samplers = i;
1048
1049    if (info->hw.nr_samplers != info->nr_samplers ||
1050        memcmp(info->hw.samplers,
1051               info->samplers,
1052               info->nr_samplers * sizeof(void *)) != 0) 
1053    {
1054       memcpy(info->hw.samplers,
1055              info->samplers,
1056              info->nr_samplers * sizeof(void *));
1057       info->hw.nr_samplers = info->nr_samplers;
1058
1059       if (info == &ctx->fragment_samplers) {
1060          ctx->pipe->bind_fragment_sampler_states(ctx->pipe,
1061                                                  info->nr_samplers,
1062                                                  info->samplers);
1063       }
1064       else if (info == &ctx->vertex_samplers) {
1065          ctx->pipe->bind_vertex_sampler_states(ctx->pipe,
1066                                                info->nr_samplers,
1067                                                info->samplers);
1068       }
1069       else {
1070          assert(0);
1071       }
1072    }
1073 }
1074
1075 void
1076 cso_single_sampler_done( struct cso_context *ctx )
1077 {
1078    single_sampler_done(ctx, &ctx->fragment_samplers);
1079 }
1080
1081 void
1082 cso_single_vertex_sampler_done(struct cso_context *ctx)
1083 {
1084    single_sampler_done(ctx, &ctx->vertex_samplers);
1085 }
1086
1087
1088 /*
1089  * If the function encouters any errors it will return the
1090  * last one. Done to always try to set as many samplers
1091  * as possible.
1092  */
1093 static enum pipe_error
1094 set_samplers(struct cso_context *ctx,
1095              struct sampler_info *info,
1096              unsigned nr,
1097              const struct pipe_sampler_state **templates)
1098 {
1099    unsigned i;
1100    enum pipe_error temp, error = PIPE_OK;
1101
1102    /* TODO: fastpath
1103     */
1104
1105    for (i = 0; i < nr; i++) {
1106       temp = single_sampler(ctx, info, i, templates[i]);
1107       if (temp != PIPE_OK)
1108          error = temp;
1109    }
1110
1111    for ( ; i < info->nr_samplers; i++) {
1112       temp = single_sampler(ctx, info, i, NULL);
1113       if (temp != PIPE_OK)
1114          error = temp;
1115    }
1116
1117    single_sampler_done(ctx, info);
1118
1119    return error;
1120 }
1121
1122 enum pipe_error
1123 cso_set_samplers(struct cso_context *ctx,
1124                  unsigned nr,
1125                  const struct pipe_sampler_state **templates)
1126 {
1127    return set_samplers(ctx, &ctx->fragment_samplers, nr, templates);
1128 }
1129
1130 enum pipe_error
1131 cso_set_vertex_samplers(struct cso_context *ctx,
1132                         unsigned nr,
1133                         const struct pipe_sampler_state **templates)
1134 {
1135    return set_samplers(ctx, &ctx->vertex_samplers, nr, templates);
1136 }
1137
1138
1139
1140 static void
1141 save_samplers(struct cso_context *ctx, struct sampler_info *info)
1142 {
1143    info->nr_samplers_saved = info->nr_samplers;
1144    memcpy(info->samplers_saved, info->samplers, sizeof(info->samplers));
1145 }
1146
1147 void
1148 cso_save_samplers(struct cso_context *ctx)
1149 {
1150    save_samplers(ctx, &ctx->fragment_samplers);
1151 }
1152
1153 void
1154 cso_save_vertex_samplers(struct cso_context *ctx)
1155 {
1156    save_samplers(ctx, &ctx->vertex_samplers);
1157 }
1158
1159
1160
1161 static void
1162 restore_samplers(struct cso_context *ctx, struct sampler_info *info)
1163 {
1164    info->nr_samplers = info->nr_samplers_saved;
1165    memcpy(info->samplers, info->samplers_saved, sizeof(info->samplers));
1166    single_sampler_done(ctx, info);
1167 }
1168
1169 void
1170 cso_restore_samplers(struct cso_context *ctx)
1171 {
1172    restore_samplers(ctx, &ctx->fragment_samplers);
1173 }
1174
1175 void
1176 cso_restore_vertex_samplers(struct cso_context *ctx)
1177 {
1178    restore_samplers(ctx, &ctx->vertex_samplers);
1179 }
1180
1181
1182
1183 static void
1184 set_sampler_views(struct cso_context *ctx,
1185                   struct sampler_info *info,
1186                   void (*set_views)(struct pipe_context *,
1187                                     unsigned num_views,
1188                                     struct pipe_sampler_view **),
1189                   uint count,
1190                   struct pipe_sampler_view **views)
1191 {
1192    uint i;
1193
1194    /* reference new views */
1195    for (i = 0; i < count; i++) {
1196       pipe_sampler_view_reference(&info->views[i], views[i]);
1197    }
1198    /* unref extra old views, if any */
1199    for (; i < info->nr_views; i++) {
1200       pipe_sampler_view_reference(&info->views[i], NULL);
1201    }
1202
1203    info->nr_views = count;
1204
1205    /* bind the new sampler views */
1206    set_views(ctx->pipe, count, info->views);
1207 }
1208
1209 void
1210 cso_set_fragment_sampler_views(struct cso_context *ctx,
1211                                uint count,
1212                                struct pipe_sampler_view **views)
1213 {
1214    set_sampler_views(ctx, &ctx->fragment_samplers,
1215                      ctx->pipe->set_fragment_sampler_views,
1216                      count, views);
1217 }
1218
1219 void
1220 cso_set_vertex_sampler_views(struct cso_context *ctx,
1221                              uint count,
1222                              struct pipe_sampler_view **views)
1223 {
1224    set_sampler_views(ctx, &ctx->vertex_samplers,
1225                      ctx->pipe->set_vertex_sampler_views,
1226                      count, views);
1227 }
1228
1229
1230
1231 static void
1232 save_sampler_views(struct cso_context *ctx,
1233                    struct sampler_info *info)
1234 {
1235    uint i;
1236
1237    info->nr_views_saved = info->nr_views;
1238
1239    for (i = 0; i < info->nr_views; i++) {
1240       assert(!info->views_saved[i]);
1241       pipe_sampler_view_reference(&info->views_saved[i], info->views[i]);
1242    }
1243 }
1244
1245 void
1246 cso_save_fragment_sampler_views(struct cso_context *ctx)
1247 {
1248    save_sampler_views(ctx, &ctx->fragment_samplers);
1249 }
1250
1251 void
1252 cso_save_vertex_sampler_views(struct cso_context *ctx)
1253 {
1254    save_sampler_views(ctx, &ctx->vertex_samplers);
1255 }
1256
1257
1258 static void
1259 restore_sampler_views(struct cso_context *ctx,
1260                       struct sampler_info *info,
1261                       void (*set_views)(struct pipe_context *,
1262                                         unsigned num_views,
1263                                         struct pipe_sampler_view **))
1264 {
1265    uint i;
1266
1267    for (i = 0; i < info->nr_views_saved; i++) {
1268       pipe_sampler_view_reference(&info->views[i], info->views_saved[i]);
1269       pipe_sampler_view_reference(&info->views_saved[i], NULL);
1270    }
1271    for (; i < info->nr_views; i++) {
1272       pipe_sampler_view_reference(&info->views[i], NULL);
1273    }
1274
1275    /* bind the old/saved sampler views */
1276    set_views(ctx->pipe, info->nr_views_saved, info->views);
1277
1278    info->nr_views = info->nr_views_saved;
1279    info->nr_views_saved = 0;
1280 }
1281
1282 void
1283 cso_restore_fragment_sampler_views(struct cso_context *ctx)
1284 {
1285    restore_sampler_views(ctx, &ctx->fragment_samplers,
1286                          ctx->pipe->set_fragment_sampler_views);
1287 }
1288
1289 void
1290 cso_restore_vertex_sampler_views(struct cso_context *ctx)
1291 {
1292    restore_sampler_views(ctx, &ctx->vertex_samplers,
1293                          ctx->pipe->set_vertex_sampler_views);
1294 }