gallium: temporarily disable the memcmp() in cso_set_framebuffer()
[mesa.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 /* Wrap the cso cache & hash mechanisms in a simplified
29 * pipe-driver-specific interface.
30 *
31 * Authors:
32 * Zack Rusin <zack@tungstengraphics.com>
33 * Keith Whitwell <keith@tungstengraphics.com>
34 */
35
36 #include "pipe/p_state.h"
37 #include "pipe/p_util.h"
38
39 #include "cso_cache/cso_context.h"
40 #include "cso_cache/cso_cache.h"
41 #include "cso_cache/cso_hash.h"
42
43 struct cso_context {
44 struct pipe_context *pipe;
45 struct cso_cache *cache;
46
47 struct {
48 void *samplers[PIPE_MAX_SAMPLERS];
49 unsigned nr_samplers;
50 } hw;
51
52 void *samplers[PIPE_MAX_SAMPLERS];
53 unsigned nr_samplers;
54
55 void *samplers_saved[PIPE_MAX_SAMPLERS];
56 unsigned nr_samplers_saved;
57
58 struct pipe_texture *textures[PIPE_MAX_SAMPLERS];
59 uint nr_textures;
60
61 struct pipe_texture *textures_saved[PIPE_MAX_SAMPLERS];
62 uint nr_textures_saved;
63
64 /** Current and saved state.
65 * The saved state is used as a 1-deep stack.
66 */
67 void *blend, *blend_saved;
68 void *depth_stencil, *depth_stencil_saved;
69 void *rasterizer, *rasterizer_saved;
70 void *fragment_shader, *fragment_shader_saved;
71 void *vertex_shader, *vertex_shader_saved;
72
73 struct pipe_framebuffer_state fb, fb_saved;
74 struct pipe_viewport_state vp, vp_saved;
75 struct pipe_blend_color blend_color;
76 };
77
78
79 struct cso_context *cso_create_context( struct pipe_context *pipe )
80 {
81 struct cso_context *ctx = CALLOC_STRUCT(cso_context);
82 if (ctx == NULL)
83 goto out;
84
85 ctx->cache = cso_cache_create();
86 if (ctx->cache == NULL)
87 goto out;
88
89 ctx->pipe = pipe;
90
91 /* Enable for testing: */
92 if (0) cso_set_maximum_cache_size( ctx->cache, 4 );
93
94 return ctx;
95
96 out:
97 cso_destroy_context( ctx );
98 return NULL;
99 }
100
101 static void cso_release_all( struct cso_context *ctx )
102 {
103 if (ctx->pipe) {
104 ctx->pipe->bind_blend_state( ctx->pipe, NULL );
105 ctx->pipe->bind_rasterizer_state( ctx->pipe, NULL );
106 ctx->pipe->bind_sampler_states( ctx->pipe, 0, NULL );
107 ctx->pipe->bind_depth_stencil_alpha_state( ctx->pipe, NULL );
108 ctx->pipe->bind_fs_state( ctx->pipe, NULL );
109 ctx->pipe->bind_vs_state( ctx->pipe, NULL );
110 }
111
112 if (ctx->cache) {
113 cso_cache_delete( ctx->cache );
114 ctx->cache = NULL;
115 }
116 }
117
118
119 void cso_destroy_context( struct cso_context *ctx )
120 {
121 if (ctx)
122 cso_release_all( ctx );
123
124 FREE( ctx );
125 }
126
127
128 /* Those function will either find the state of the given template
129 * in the cache or they will create a new state from the given
130 * template, insert it in the cache and return it.
131 */
132
133 /*
134 * If the driver returns 0 from the create method then they will assign
135 * the data member of the cso to be the template itself.
136 */
137
138 void cso_set_blend(struct cso_context *ctx,
139 const struct pipe_blend_state *templ)
140 {
141 unsigned hash_key = cso_construct_key((void*)templ, sizeof(struct pipe_blend_state));
142 struct cso_hash_iter iter = cso_find_state_template(ctx->cache,
143 hash_key, CSO_BLEND,
144 (void*)templ);
145 void *handle;
146
147 if (cso_hash_iter_is_null(iter)) {
148 struct cso_blend *cso = MALLOC(sizeof(struct cso_blend));
149
150 cso->state = *templ;
151 cso->data = ctx->pipe->create_blend_state(ctx->pipe, &cso->state);
152 cso->delete_state = (cso_state_callback)ctx->pipe->delete_blend_state;
153 cso->context = ctx->pipe;
154
155 iter = cso_insert_state(ctx->cache, hash_key, CSO_BLEND, cso);
156 handle = cso->data;
157 }
158 else {
159 handle = ((struct cso_blend *)cso_hash_iter_data(iter))->data;
160 }
161
162 if (ctx->blend != handle) {
163 ctx->blend = handle;
164 ctx->pipe->bind_blend_state(ctx->pipe, handle);
165 }
166 }
167
168 void cso_save_blend(struct cso_context *ctx)
169 {
170 assert(!ctx->blend_saved);
171 ctx->blend_saved = ctx->blend;
172 }
173
174 void cso_restore_blend(struct cso_context *ctx)
175 {
176 if (ctx->blend != ctx->blend_saved) {
177 ctx->blend = ctx->blend_saved;
178 ctx->pipe->bind_blend_state(ctx->pipe, ctx->blend_saved);
179 }
180 ctx->blend_saved = NULL;
181 }
182
183
184
185 void cso_single_sampler(struct cso_context *ctx,
186 unsigned idx,
187 const struct pipe_sampler_state *templ)
188 {
189 void *handle = NULL;
190
191 if (templ != NULL) {
192 unsigned hash_key = cso_construct_key((void*)templ, sizeof(struct pipe_sampler_state));
193 struct cso_hash_iter iter = cso_find_state_template(ctx->cache,
194 hash_key, CSO_SAMPLER,
195 (void*)templ);
196
197 if (cso_hash_iter_is_null(iter)) {
198 struct cso_sampler *cso = MALLOC(sizeof(struct cso_sampler));
199
200 cso->state = *templ;
201 cso->data = ctx->pipe->create_sampler_state(ctx->pipe, &cso->state);
202 cso->delete_state = (cso_state_callback)ctx->pipe->delete_sampler_state;
203 cso->context = ctx->pipe;
204
205 iter = cso_insert_state(ctx->cache, hash_key, CSO_SAMPLER, cso);
206 handle = cso->data;
207 }
208 else {
209 handle = ((struct cso_sampler *)cso_hash_iter_data(iter))->data;
210 }
211 }
212
213 ctx->samplers[idx] = handle;
214 }
215
216 void cso_single_sampler_done( struct cso_context *ctx )
217 {
218 unsigned i;
219
220 /* find highest non-null sampler */
221 for (i = PIPE_MAX_SAMPLERS; i > 0; i--) {
222 if (ctx->samplers[i - 1] != NULL)
223 break;
224 }
225
226 ctx->nr_samplers = i;
227
228 if (ctx->hw.nr_samplers != ctx->nr_samplers ||
229 memcmp(ctx->hw.samplers,
230 ctx->samplers,
231 ctx->nr_samplers * sizeof(void *)) != 0)
232 {
233 memcpy(ctx->hw.samplers, ctx->samplers, ctx->nr_samplers * sizeof(void *));
234 ctx->hw.nr_samplers = ctx->nr_samplers;
235
236 ctx->pipe->bind_sampler_states(ctx->pipe, ctx->nr_samplers, ctx->samplers);
237 }
238 }
239
240 void cso_set_samplers( struct cso_context *ctx,
241 unsigned nr,
242 const struct pipe_sampler_state **templates )
243 {
244 unsigned i;
245
246 /* TODO: fastpath
247 */
248
249 for (i = 0; i < nr; i++)
250 cso_single_sampler( ctx, i, templates[i] );
251
252 for ( ; i < ctx->nr_samplers; i++)
253 cso_single_sampler( ctx, i, NULL );
254
255 cso_single_sampler_done( ctx );
256 }
257
258 void cso_save_samplers(struct cso_context *ctx)
259 {
260 ctx->nr_samplers_saved = ctx->nr_samplers;
261 memcpy(ctx->samplers_saved, ctx->samplers, sizeof(ctx->samplers));
262 }
263
264 void cso_restore_samplers(struct cso_context *ctx)
265 {
266 cso_set_samplers(ctx, ctx->nr_samplers_saved,
267 (const struct pipe_sampler_state **) ctx->samplers_saved);
268 }
269
270
271 void cso_set_sampler_textures( struct cso_context *ctx,
272 uint count,
273 struct pipe_texture **textures )
274 {
275 uint i;
276
277 ctx->nr_textures = count;
278
279 for (i = 0; i < count; i++)
280 ctx->textures[i] = textures[i];
281 for ( ; i < PIPE_MAX_SAMPLERS; i++)
282 ctx->textures[i] = NULL;
283
284 ctx->pipe->set_sampler_textures(ctx->pipe, count, textures);
285 }
286
287 void cso_save_sampler_textures( struct cso_context *ctx )
288 {
289 ctx->nr_textures_saved = ctx->nr_textures;
290 memcpy(ctx->textures_saved, ctx->textures, sizeof(ctx->textures));
291 }
292
293 void cso_restore_sampler_textures( struct cso_context *ctx )
294 {
295 cso_set_sampler_textures(ctx, ctx->nr_textures_saved, ctx->textures_saved);
296 ctx->nr_textures_saved = 0;
297 }
298
299
300
301
302 void cso_set_depth_stencil_alpha(struct cso_context *ctx,
303 const struct pipe_depth_stencil_alpha_state *templ)
304 {
305 unsigned hash_key = cso_construct_key((void*)templ,
306 sizeof(struct pipe_depth_stencil_alpha_state));
307 struct cso_hash_iter iter = cso_find_state_template(ctx->cache,
308 hash_key,
309 CSO_DEPTH_STENCIL_ALPHA,
310 (void*)templ);
311 void *handle;
312
313 if (cso_hash_iter_is_null(iter)) {
314 struct cso_depth_stencil_alpha *cso = MALLOC(sizeof(struct cso_depth_stencil_alpha));
315
316 cso->state = *templ;
317 cso->data = ctx->pipe->create_depth_stencil_alpha_state(ctx->pipe, &cso->state);
318 cso->delete_state = (cso_state_callback)ctx->pipe->delete_depth_stencil_alpha_state;
319 cso->context = ctx->pipe;
320
321 cso_insert_state(ctx->cache, hash_key, CSO_DEPTH_STENCIL_ALPHA, cso);
322 handle = cso->data;
323 }
324 else {
325 handle = ((struct cso_depth_stencil_alpha *)cso_hash_iter_data(iter))->data;
326 }
327
328 if (ctx->depth_stencil != handle) {
329 ctx->depth_stencil = handle;
330 ctx->pipe->bind_depth_stencil_alpha_state(ctx->pipe, handle);
331 }
332 }
333
334 void cso_save_depth_stencil_alpha(struct cso_context *ctx)
335 {
336 assert(!ctx->depth_stencil_saved);
337 ctx->depth_stencil_saved = ctx->depth_stencil;
338 }
339
340 void cso_restore_depth_stencil_alpha(struct cso_context *ctx)
341 {
342 if (ctx->depth_stencil != ctx->depth_stencil_saved) {
343 ctx->depth_stencil = ctx->depth_stencil_saved;
344 ctx->pipe->bind_depth_stencil_alpha_state(ctx->pipe, ctx->depth_stencil_saved);
345 }
346 ctx->depth_stencil_saved = NULL;
347 }
348
349
350
351 void cso_set_rasterizer(struct cso_context *ctx,
352 const struct pipe_rasterizer_state *templ)
353 {
354 unsigned hash_key = cso_construct_key((void*)templ,
355 sizeof(struct pipe_rasterizer_state));
356 struct cso_hash_iter iter = cso_find_state_template(ctx->cache,
357 hash_key, CSO_RASTERIZER,
358 (void*)templ);
359 void *handle = NULL;
360
361 if (cso_hash_iter_is_null(iter)) {
362 struct cso_rasterizer *cso = MALLOC(sizeof(struct cso_rasterizer));
363
364 cso->state = *templ;
365 cso->data = ctx->pipe->create_rasterizer_state(ctx->pipe, &cso->state);
366 cso->delete_state = (cso_state_callback)ctx->pipe->delete_rasterizer_state;
367 cso->context = ctx->pipe;
368
369 cso_insert_state(ctx->cache, hash_key, CSO_RASTERIZER, cso);
370 handle = cso->data;
371 }
372 else {
373 handle = ((struct cso_rasterizer *)cso_hash_iter_data(iter))->data;
374 }
375
376 if (ctx->rasterizer != handle) {
377 ctx->rasterizer = handle;
378 ctx->pipe->bind_rasterizer_state(ctx->pipe, handle);
379 }
380 }
381
382 void cso_save_rasterizer(struct cso_context *ctx)
383 {
384 assert(!ctx->rasterizer_saved);
385 ctx->rasterizer_saved = ctx->rasterizer;
386 }
387
388 void cso_restore_rasterizer(struct cso_context *ctx)
389 {
390 if (ctx->rasterizer != ctx->rasterizer_saved) {
391 ctx->rasterizer = ctx->rasterizer_saved;
392 ctx->pipe->bind_rasterizer_state(ctx->pipe, ctx->rasterizer_saved);
393 }
394 ctx->rasterizer_saved = NULL;
395 }
396
397
398 void cso_set_fragment_shader(struct cso_context *ctx,
399 const struct pipe_shader_state *templ)
400 {
401 unsigned hash_key = cso_construct_key((void*)templ,
402 sizeof(struct pipe_shader_state));
403 struct cso_hash_iter iter = cso_find_state_template(ctx->cache,
404 hash_key, CSO_FRAGMENT_SHADER,
405 (void*)templ);
406 void *handle = NULL;
407
408 if (cso_hash_iter_is_null(iter)) {
409 struct cso_fragment_shader *cso = MALLOC(sizeof(struct cso_fragment_shader));
410
411 cso->state = *templ;
412 cso->data = ctx->pipe->create_fs_state(ctx->pipe, &cso->state);
413 cso->delete_state = (cso_state_callback)ctx->pipe->delete_fs_state;
414 cso->context = ctx->pipe;
415
416 iter = cso_insert_state(ctx->cache, hash_key, CSO_FRAGMENT_SHADER, cso);
417 handle = cso->data;
418 }
419 else {
420 handle = ((struct cso_fragment_shader *)cso_hash_iter_data(iter))->data;
421 }
422
423 if (ctx->fragment_shader != handle) {
424 ctx->fragment_shader = handle;
425 ctx->pipe->bind_fs_state(ctx->pipe, handle);
426 }
427 }
428
429 void cso_save_fragment_shader(struct cso_context *ctx)
430 {
431 assert(!ctx->fragment_shader_saved);
432 ctx->fragment_shader_saved = ctx->fragment_shader;
433 }
434
435 void cso_restore_fragment_shader(struct cso_context *ctx)
436 {
437 assert(ctx->fragment_shader_saved);
438 if (ctx->fragment_shader_saved != ctx->fragment_shader) {
439 ctx->pipe->bind_fs_state(ctx->pipe, ctx->fragment_shader_saved);
440 ctx->fragment_shader = ctx->fragment_shader_saved;
441 }
442 ctx->fragment_shader_saved = NULL;
443 }
444
445
446
447 void cso_set_vertex_shader(struct cso_context *ctx,
448 const struct pipe_shader_state *templ)
449 {
450 unsigned hash_key = cso_construct_key((void*)templ,
451 sizeof(struct pipe_shader_state));
452 struct cso_hash_iter iter = cso_find_state_template(ctx->cache,
453 hash_key, CSO_VERTEX_SHADER,
454 (void*)templ);
455 void *handle = NULL;
456
457 if (cso_hash_iter_is_null(iter)) {
458 struct cso_vertex_shader *cso = MALLOC(sizeof(struct cso_vertex_shader));
459
460 cso->state = *templ;
461 cso->data = ctx->pipe->create_vs_state(ctx->pipe, &cso->state);
462 cso->delete_state = (cso_state_callback)ctx->pipe->delete_vs_state;
463 cso->context = ctx->pipe;
464
465 iter = cso_insert_state(ctx->cache, hash_key, CSO_VERTEX_SHADER, cso);
466 handle = cso->data;
467 }
468 else {
469 handle = ((struct cso_vertex_shader *)cso_hash_iter_data(iter))->data;
470 }
471
472 if (ctx->vertex_shader != handle) {
473 ctx->vertex_shader = handle;
474 ctx->pipe->bind_vs_state(ctx->pipe, handle);
475 }
476 }
477
478 void cso_save_vertex_shader(struct cso_context *ctx)
479 {
480 assert(!ctx->vertex_shader_saved);
481 ctx->vertex_shader_saved = ctx->vertex_shader;
482 }
483
484 void cso_restore_vertex_shader(struct cso_context *ctx)
485 {
486 assert(ctx->vertex_shader_saved);
487 if (ctx->vertex_shader_saved != ctx->vertex_shader) {
488 ctx->pipe->bind_fs_state(ctx->pipe, ctx->vertex_shader_saved);
489 ctx->vertex_shader = ctx->vertex_shader_saved;
490 }
491 ctx->vertex_shader_saved = NULL;
492 }
493
494
495
496 void cso_set_framebuffer(struct cso_context *ctx,
497 const struct pipe_framebuffer_state *fb)
498 {
499 /* XXX this memcmp() fails to detect buffer size changes */
500 if (1/*memcmp(&ctx->fb, fb, sizeof(*fb))*/) {
501 ctx->fb = *fb;
502 ctx->pipe->set_framebuffer_state(ctx->pipe, fb);
503 }
504 }
505
506 void cso_save_framebuffer(struct cso_context *ctx)
507 {
508 ctx->fb_saved = ctx->fb;
509 }
510
511 void cso_restore_framebuffer(struct cso_context *ctx)
512 {
513 if (memcmp(&ctx->fb, &ctx->fb_saved, sizeof(ctx->fb))) {
514 ctx->fb = ctx->fb_saved;
515 ctx->pipe->set_framebuffer_state(ctx->pipe, &ctx->fb);
516 }
517 }
518
519
520 void cso_set_viewport(struct cso_context *ctx,
521 const struct pipe_viewport_state *vp)
522 {
523 if (memcmp(&ctx->vp, vp, sizeof(*vp))) {
524 ctx->vp = *vp;
525 ctx->pipe->set_viewport_state(ctx->pipe, vp);
526 }
527 }
528
529 void cso_save_viewport(struct cso_context *ctx)
530 {
531 ctx->vp_saved = ctx->vp;
532 }
533
534
535 void cso_restore_viewport(struct cso_context *ctx)
536 {
537 if (memcmp(&ctx->vp, &ctx->vp_saved, sizeof(ctx->vp))) {
538 ctx->vp = ctx->vp_saved;
539 ctx->pipe->set_viewport_state(ctx->pipe, &ctx->vp);
540 }
541 }
542
543
544
545
546 void cso_set_blend_color(struct cso_context *ctx,
547 const struct pipe_blend_color *bc)
548 {
549 if (memcmp(&ctx->blend_color, bc, sizeof(ctx->blend_color))) {
550 ctx->blend_color = *bc;
551 ctx->pipe->set_blend_color(ctx->pipe, bc);
552 }
553 }