1 /**************************************************************************
3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
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:
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
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.
26 **************************************************************************/
29 #include "util/u_memory.h"
30 #include "pipe/p_state.h"
31 #include "pipe/p_inlines.h"
37 struct pipe_texture
*texture
;
38 struct texture_list
*next
;
43 #define MAX_SURFACES ((PIPE_MAX_COLOR_BUFS) + 1)
47 const struct pipe_context
*context
;
49 /** surfaces the context is drawing into */
50 struct pipe_surface
*surfaces
[MAX_SURFACES
];
52 /** currently bound textures */
53 struct pipe_texture
*textures
[PIPE_MAX_SAMPLERS
];
55 /** previously bound textures, used but not flushed */
56 struct texture_list
*textures_used
;
60 struct sct_context
*next
;
67 const struct pipe_surface
*surface
;
69 /** list of contexts drawing to this surface */
70 struct sct_context_list
*contexts
;
72 struct sct_surface
*next
;
78 * Find the surface_info for the given pipe_surface
80 static struct sct_surface
*
81 find_surface_info(struct surface_context_tracker
*sct
,
82 const struct pipe_surface
*surface
)
84 struct sct_surface
*si
;
85 for (si
= sct
->surfaces
; si
; si
= si
->next
)
86 if (si
->surface
== surface
)
93 * As above, but create new surface_info if surface is new.
95 static struct sct_surface
*
96 find_create_surface_info(struct surface_context_tracker
*sct
,
97 const struct pipe_surface
*surface
)
99 struct sct_surface
*si
= find_surface_info(sct
, surface
);
104 si
= CALLOC_STRUCT(sct_surface
);
106 si
->surface
= surface
;
109 si
->next
= sct
->surfaces
;
118 * Find a context_info for the given context.
120 static struct sct_context
*
121 find_context_info(struct surface_context_tracker
*sct
,
122 const struct pipe_context
*context
)
124 struct sct_context
*ci
;
125 for (ci
= sct
->contexts
; ci
; ci
= ci
->next
)
126 if (ci
->context
== context
)
133 * As above, but create new context_info if context is new.
135 static struct sct_context
*
136 find_create_context_info(struct surface_context_tracker
*sct
,
137 const struct pipe_context
*context
)
139 struct sct_context
*ci
= find_context_info(sct
, context
);
144 ci
= CALLOC_STRUCT(sct_context
);
146 ci
->context
= context
;
149 ci
->next
= sct
->contexts
;
158 * Is the context already bound to the surface?
161 find_surface_context(const struct sct_surface
*si
,
162 const struct pipe_context
*context
)
164 const struct sct_context_list
*cl
;
165 for (cl
= si
->contexts
; cl
; cl
= cl
->next
) {
166 if (cl
->context
== context
) {
175 * Add a context to the list of contexts associated with a surface.
178 add_context_to_surface(struct sct_surface
*si
,
179 const struct pipe_context
*context
)
181 struct sct_context_list
*cl
= CALLOC_STRUCT(sct_context_list
);
183 cl
->context
= context
;
184 /* insert at head of list of contexts */
185 cl
->next
= si
->contexts
;
192 * Remove a context from the list of contexts associated with a surface.
195 remove_context_from_surface(struct sct_surface
*si
,
196 const struct pipe_context
*context
)
198 struct sct_context_list
*prev
= NULL
, *curr
, *next
;
200 for (curr
= si
->contexts
; curr
; curr
= next
) {
201 if (curr
->context
== context
) {
204 prev
->next
= curr
->next
;
206 si
->contexts
= curr
->next
;
219 * Unbind context from surface.
222 unbind_context_surface(struct surface_context_tracker
*sct
,
223 struct pipe_context
*context
,
224 struct pipe_surface
*surface
)
226 struct sct_surface
*si
= find_surface_info(sct
, surface
);
228 remove_context_from_surface(si
, context
);
234 * Bind context to a set of surfaces (color + Z).
235 * Like MakeCurrent().
238 sct_bind_surfaces(struct surface_context_tracker
*sct
,
239 struct pipe_context
*context
,
241 struct pipe_surface
**surfaces
)
243 struct sct_context
*ci
= find_create_context_info(sct
, context
);
247 return; /* out of memory */
250 /* unbind currently bound surfaces */
251 for (i
= 0; i
< MAX_SURFACES
; i
++) {
252 if (ci
->surfaces
[i
]) {
253 unbind_context_surface(sct
, context
, ci
->surfaces
[i
]);
257 /* bind new surfaces */
258 for (i
= 0; i
< num_surf
; i
++) {
259 struct sct_surface
*si
= find_create_surface_info(sct
, surfaces
[i
]);
260 if (!find_surface_context(si
, context
)) {
261 add_context_to_surface(si
, context
);
268 * Return list of contexts bound to a surface.
270 const struct sct_context_list
*
271 sct_get_surface_contexts(struct surface_context_tracker
*sct
,
272 const struct pipe_surface
*surface
)
274 const struct sct_surface
*si
= find_surface_info(sct
, surface
);
281 find_texture(const struct sct_context
*ci
,
282 const struct pipe_texture
*texture
)
284 const struct texture_list
*tl
;
286 for (tl
= ci
->textures_used
; tl
; tl
= tl
->next
) {
287 if (tl
->texture
== texture
) {
296 * Add the given texture to the context's list of used textures.
299 add_texture_used(struct sct_context
*ci
,
300 struct pipe_texture
*texture
)
302 if (!find_texture(ci
, texture
)) {
304 struct texture_list
*tl
= CALLOC_STRUCT(texture_list
);
306 pipe_texture_reference(&tl
->texture
, texture
);
308 tl
->next
= ci
->textures_used
;
309 ci
->textures_used
= tl
;
316 * Bind a texture to a rendering context.
319 sct_bind_texture(struct surface_context_tracker
*sct
,
320 struct pipe_context
*context
,
322 struct pipe_texture
*tex
)
324 struct sct_context
*ci
= find_context_info(sct
, context
);
326 if (ci
->textures
[unit
] != tex
) {
327 /* put texture on the 'used' list */
328 add_texture_used(ci
, tex
);
330 pipe_texture_reference(&ci
->textures
[unit
], tex
);
336 * Check if the given texture has been used by the rendering context
337 * since the last call to sct_flush_textures().
340 sct_is_texture_used(struct surface_context_tracker
*sct
,
341 const struct pipe_context
*context
,
342 const struct pipe_texture
*texture
)
344 const struct sct_context
*ci
= find_context_info(sct
, context
);
345 return find_texture(ci
, texture
);
350 * To be called when the image contents of a texture are changed, such
351 * as for gl[Copy]TexSubImage().
352 * XXX this may not be needed
355 sct_update_texture(struct pipe_texture
*tex
)
362 * When a scene is flushed/rendered we can release the list of
366 sct_flush_textures(struct surface_context_tracker
*sct
,
367 struct pipe_context
*context
)
369 struct sct_context
*ci
= find_context_info(sct
, context
);
370 struct texture_list
*tl
, *next
;
373 for (tl
= ci
->textures_used
; tl
; tl
= next
) {
375 pipe_texture_release(&tl
->texture
);
378 ci
->textures_used
= NULL
;
380 /* put the currently bound textures on the 'used' list */
381 for (i
= 0; i
< PIPE_MAX_SAMPLERS
; i
++) {
382 add_texture_used(ci
, ci
->textures
[i
]);
389 sct_destroy_context(struct surface_context_tracker
*sct
,
390 struct pipe_context
*context
)
392 /* XXX should we require an unbinding first? */
394 struct sct_surface
*si
;
395 for (si
= sct
->surfaces
; si
; si
= si
->next
) {
396 remove_context_from_surface(si
, context
);
400 /* remove context from context_info list */
402 struct sct_context
*ci
, *next
, *prev
= NULL
;
403 for (ci
= sct
->contexts
; ci
; ci
= next
) {
405 if (ci
->context
== context
) {
407 prev
->next
= ci
->next
;
409 sct
->contexts
= ci
->next
;
422 sct_destroy_surface(struct surface_context_tracker
*sct
,
423 struct pipe_surface
*surface
)
426 /* debug/sanity: no context should be bound to surface */
427 struct sct_context
*ci
;
429 for (ci
= sct
->contexts
; ci
; ci
= ci
->next
) {
430 for (i
= 0; i
< MAX_SURFACES
; i
++) {
431 assert(ci
->surfaces
[i
] != surface
);
436 /* remove surface from sct_surface list */
438 struct sct_surface
*si
, *next
, *prev
= NULL
;
439 for (si
= sct
->surfaces
; si
; si
= next
) {
441 if (si
->surface
== surface
) {
444 prev
->next
= si
->next
;
446 sct
->surfaces
= si
->next
;