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 "pipe/p_util.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
;
218 * Unbind context from surface.
221 unbind_context_surface(struct surface_context_tracker
*sct
,
222 struct pipe_context
*context
,
223 struct pipe_surface
*surface
)
225 struct sct_surface
*si
= find_surface_info(sct
, surface
);
227 remove_context_from_surface(si
, context
);
233 * Bind context to a set of surfaces (color + Z).
234 * Like MakeCurrent().
237 sct_bind_surfaces(struct surface_context_tracker
*sct
,
238 struct pipe_context
*context
,
240 struct pipe_surface
**surfaces
)
242 struct sct_context
*ci
= find_create_context_info(sct
, context
);
246 return; /* out of memory */
249 /* unbind currently bound surfaces */
250 for (i
= 0; i
< MAX_SURFACES
; i
++) {
251 if (ci
->surfaces
[i
]) {
252 unbind_context_surface(sct
, context
, ci
->surfaces
[i
]);
256 /* bind new surfaces */
257 for (i
= 0; i
< num_surf
; i
++) {
258 struct sct_surface
*si
= find_create_surface_info(sct
, surfaces
[i
]);
259 if (!find_surface_context(si
, context
)) {
260 add_context_to_surface(si
, context
);
267 * Return list of contexts bound to a surface.
269 const struct sct_context_list
*
270 sct_get_surface_contexts(struct surface_context_tracker
*sct
,
271 const struct pipe_surface
*surface
)
273 const struct sct_surface
*si
= find_surface_info(sct
, surface
);
280 find_texture(const struct sct_context
*ci
,
281 const struct pipe_texture
*texture
)
283 const struct texture_list
*tl
;
285 for (tl
= ci
->textures_used
; tl
; tl
= tl
->next
) {
286 if (tl
->texture
== texture
) {
295 * Add the given texture to the context's list of used textures.
298 add_texture_used(struct sct_context
*ci
,
299 struct pipe_texture
*texture
)
301 if (!find_texture(ci
, texture
)) {
303 struct texture_list
*tl
= CALLOC_STRUCT(texture_list
);
305 pipe_texture_reference(&tl
->texture
, texture
);
307 tl
->next
= ci
->textures_used
;
308 ci
->textures_used
= tl
;
315 * Bind a texture to a rendering context.
318 sct_bind_texture(struct surface_context_tracker
*sct
,
319 struct pipe_context
*context
,
321 struct pipe_texture
*tex
)
323 struct sct_context
*ci
= find_context_info(sct
, context
);
325 if (ci
->textures
[unit
] != tex
) {
326 /* put texture on the 'used' list */
327 add_texture_used(ci
, tex
);
329 pipe_texture_reference(&ci
->textures
[unit
], tex
);
335 * Check if the given texture has been used by the rendering context
336 * since the last call to sct_flush_textures().
339 sct_is_texture_used(struct surface_context_tracker
*sct
,
340 const struct pipe_context
*context
,
341 const struct pipe_texture
*texture
)
343 const struct sct_context
*ci
= find_context_info(sct
, context
);
344 return find_texture(ci
, texture
);
349 * To be called when the image contents of a texture are changed, such
350 * as for gl[Copy]TexSubImage().
351 * XXX this may not be needed
354 sct_update_texture(struct pipe_texture
*tex
)
361 * When a scene is flushed/rendered we can release the list of
365 sct_flush_textures(struct surface_context_tracker
*sct
,
366 struct pipe_context
*context
)
368 struct sct_context
*ci
= find_context_info(sct
, context
);
369 struct texture_list
*tl
, *next
;
372 for (tl
= ci
->textures_used
; tl
; tl
= next
) {
374 pipe_texture_release(&tl
->texture
);
377 ci
->textures_used
= NULL
;
379 /* put the currently bound textures on the 'used' list */
380 for (i
= 0; i
< PIPE_MAX_SAMPLERS
; i
++) {
381 add_texture_used(ci
, ci
->textures
[i
]);
388 sct_destroy_context(struct surface_context_tracker
*sct
,
389 struct pipe_context
*context
)
391 /* XXX should we require an unbinding first? */
393 struct sct_surface
*si
;
394 for (si
= sct
->surfaces
; si
; si
= si
->next
) {
395 remove_context_from_surface(si
, context
);
399 /* remove context from context_info list */
401 struct sct_context
*ci
, *next
, *prev
= NULL
;
402 for (ci
= sct
->contexts
; ci
; ci
= next
) {
404 if (ci
->context
== context
) {
406 prev
->next
= ci
->next
;
408 sct
->contexts
= ci
->next
;
421 sct_destroy_surface(struct surface_context_tracker
*sct
,
422 struct pipe_surface
*surface
)
425 /* debug/sanity: no context should be bound to surface */
426 struct sct_context
*ci
;
428 for (ci
= sct
->contexts
; ci
; ci
= ci
->next
) {
429 for (i
= 0; i
< MAX_SURFACES
; i
++) {
430 assert(ci
->surfaces
[i
] != surface
);
435 /* remove surface from sct_surface list */
437 struct sct_surface
*si
, *next
, *prev
= NULL
;
438 for (si
= sct
->surfaces
; si
; si
= next
) {
440 if (si
->surface
== surface
) {
443 prev
->next
= si
->next
;
445 sct
->surfaces
= si
->next
;