mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-27 23:30:10 +01:00
gallium: new surface/context tracker (sct) module
Will be used for tracking the surfaces and textures which are bound/used by contexts.
This commit is contained in:
parent
5b82d551b7
commit
d5692cb349
6 changed files with 659 additions and 1 deletions
|
|
@ -68,7 +68,7 @@ PROGRAM_DIRS = demos redbook samples glsl xdemos
|
|||
|
||||
|
||||
# Gallium directories and
|
||||
GALLIUM_AUXILIARY_DIRS = draw cso_cache pipebuffer tgsi rtasm util
|
||||
GALLIUM_AUXILIARY_DIRS = draw cso_cache pipebuffer tgsi rtasm util sct
|
||||
GALLIUM_AUXILIARIES = $(foreach DIR,$(GALLIUM_AUXILIARY_DIRS),$(TOP)/src/gallium/auxiliary/$(DIR)/lib$(DIR).a)
|
||||
GALLIUM_DRIVER_DIRS = softpipe i915simple i965simple failover
|
||||
GALLIUM_DRIVERS = $(foreach DIR,$(GALLIUM_DRIVER_DIRS),$(TOP)/src/gallium/drivers/$(DIR)/lib$(DIR).a)
|
||||
|
|
|
|||
12
src/gallium/auxiliary/sct/Makefile
Normal file
12
src/gallium/auxiliary/sct/Makefile
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
TOP = ../../../..
|
||||
include $(TOP)/configs/current
|
||||
|
||||
LIBNAME = sct
|
||||
|
||||
C_SOURCES = \
|
||||
sct.c
|
||||
|
||||
include ../../Makefile.template
|
||||
|
||||
symlinks:
|
||||
|
||||
9
src/gallium/auxiliary/sct/SConscript
Normal file
9
src/gallium/auxiliary/sct/SConscript
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
Import('*')
|
||||
|
||||
sct = env.ConvenienceLibrary(
|
||||
target = 'sct',
|
||||
source = [
|
||||
'sct.c'
|
||||
])
|
||||
|
||||
auxiliaries.insert(0, sct)
|
||||
453
src/gallium/auxiliary/sct/sct.c
Normal file
453
src/gallium/auxiliary/sct/sct.c
Normal file
|
|
@ -0,0 +1,453 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
|
||||
#include "pipe/p_util.h"
|
||||
#include "pipe/p_state.h"
|
||||
#include "pipe/p_inlines.h"
|
||||
#include "sct.h"
|
||||
|
||||
|
||||
struct texture_list
|
||||
{
|
||||
struct pipe_texture *texture;
|
||||
struct texture_list *next;
|
||||
};
|
||||
|
||||
|
||||
|
||||
#define MAX_SURFACES ((PIPE_MAX_COLOR_BUFS) + 1)
|
||||
|
||||
struct sct_context
|
||||
{
|
||||
const struct pipe_context *context;
|
||||
|
||||
/** surfaces the context is drawing into */
|
||||
struct pipe_surface *surfaces[MAX_SURFACES];
|
||||
|
||||
/** currently bound textures */
|
||||
struct pipe_texture *textures[PIPE_MAX_SAMPLERS];
|
||||
|
||||
/** previously bound textures, used but not flushed */
|
||||
struct texture_list *textures_used;
|
||||
|
||||
boolean needs_flush;
|
||||
|
||||
struct sct_context *next;
|
||||
};
|
||||
|
||||
|
||||
|
||||
struct sct_surface
|
||||
{
|
||||
const struct pipe_surface *surface;
|
||||
|
||||
/** list of contexts drawing to this surface */
|
||||
struct sct_context_list *contexts;
|
||||
|
||||
struct sct_surface *next;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Find the surface_info for the given pipe_surface
|
||||
*/
|
||||
static struct sct_surface *
|
||||
find_surface_info(struct surface_context_tracker *sct,
|
||||
const struct pipe_surface *surface)
|
||||
{
|
||||
struct sct_surface *si;
|
||||
for (si = sct->surfaces; si; si = si->next)
|
||||
if (si->surface == surface)
|
||||
return si;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* As above, but create new surface_info if surface is new.
|
||||
*/
|
||||
static struct sct_surface *
|
||||
find_create_surface_info(struct surface_context_tracker *sct,
|
||||
const struct pipe_surface *surface)
|
||||
{
|
||||
struct sct_surface *si = find_surface_info(sct, surface);
|
||||
if (si)
|
||||
return si;
|
||||
|
||||
/* alloc new */
|
||||
si = CALLOC_STRUCT(sct_surface);
|
||||
if (si) {
|
||||
si->surface = surface;
|
||||
|
||||
/* insert at head */
|
||||
si->next = sct->surfaces;
|
||||
sct->surfaces = si;
|
||||
}
|
||||
|
||||
return si;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find a context_info for the given context.
|
||||
*/
|
||||
static struct sct_context *
|
||||
find_context_info(struct surface_context_tracker *sct,
|
||||
const struct pipe_context *context)
|
||||
{
|
||||
struct sct_context *ci;
|
||||
for (ci = sct->contexts; ci; ci = ci->next)
|
||||
if (ci->context == context)
|
||||
return ci;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* As above, but create new context_info if context is new.
|
||||
*/
|
||||
static struct sct_context *
|
||||
find_create_context_info(struct surface_context_tracker *sct,
|
||||
const struct pipe_context *context)
|
||||
{
|
||||
struct sct_context *ci = find_context_info(sct, context);
|
||||
if (ci)
|
||||
return ci;
|
||||
|
||||
/* alloc new */
|
||||
ci = CALLOC_STRUCT(sct_context);
|
||||
if (ci) {
|
||||
ci->context = context;
|
||||
|
||||
/* insert at head */
|
||||
ci->next = sct->contexts;
|
||||
sct->contexts = ci;
|
||||
}
|
||||
|
||||
return ci;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Is the context already bound to the surface?
|
||||
*/
|
||||
static boolean
|
||||
find_surface_context(const struct sct_surface *si,
|
||||
const struct pipe_context *context)
|
||||
{
|
||||
const struct sct_context_list *cl;
|
||||
for (cl = si->contexts; cl; cl = cl->next) {
|
||||
if (cl->context == context) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a context to the list of contexts associated with a surface.
|
||||
*/
|
||||
static void
|
||||
add_context_to_surface(struct sct_surface *si,
|
||||
const struct pipe_context *context)
|
||||
{
|
||||
struct sct_context_list *cl = CALLOC_STRUCT(sct_context_list);
|
||||
if (cl) {
|
||||
cl->context = context;
|
||||
/* insert at head of list of contexts */
|
||||
cl->next = si->contexts;
|
||||
si->contexts = cl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove a context from the list of contexts associated with a surface.
|
||||
*/
|
||||
static void
|
||||
remove_context_from_surface(struct sct_surface *si,
|
||||
const struct pipe_context *context)
|
||||
{
|
||||
struct sct_context_list *prev = NULL, *curr, *next;
|
||||
|
||||
for (curr = si->contexts; curr; curr = next) {
|
||||
if (curr->context == context) {
|
||||
/* remove */
|
||||
if (prev)
|
||||
prev->next = curr->next;
|
||||
else
|
||||
si->contexts = curr->next;
|
||||
next = curr->next;
|
||||
FREE(curr);
|
||||
}
|
||||
else {
|
||||
prev = curr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Unbind context from surface.
|
||||
*/
|
||||
static void
|
||||
unbind_context_surface(struct surface_context_tracker *sct,
|
||||
struct pipe_context *context,
|
||||
struct pipe_surface *surface)
|
||||
{
|
||||
struct sct_surface *si = find_surface_info(sct, surface);
|
||||
if (si) {
|
||||
remove_context_from_surface(si, context);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Bind context to a set of surfaces (color + Z).
|
||||
* Like MakeCurrent().
|
||||
*/
|
||||
void
|
||||
sct_bind_surfaces(struct surface_context_tracker *sct,
|
||||
struct pipe_context *context,
|
||||
uint num_surf,
|
||||
struct pipe_surface **surfaces)
|
||||
{
|
||||
struct sct_context *ci = find_create_context_info(sct, context);
|
||||
uint i;
|
||||
|
||||
if (!ci) {
|
||||
return; /* out of memory */
|
||||
}
|
||||
|
||||
/* unbind currently bound surfaces */
|
||||
for (i = 0; i < MAX_SURFACES; i++) {
|
||||
if (ci->surfaces[i]) {
|
||||
unbind_context_surface(sct, context, ci->surfaces[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* bind new surfaces */
|
||||
for (i = 0; i < num_surf; i++) {
|
||||
struct sct_surface *si = find_create_surface_info(sct, surfaces[i]);
|
||||
if (!find_surface_context(si, context)) {
|
||||
add_context_to_surface(si, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return list of contexts bound to a surface.
|
||||
*/
|
||||
const struct sct_context_list *
|
||||
sct_get_surface_contexts(struct surface_context_tracker *sct,
|
||||
const struct pipe_surface *surface)
|
||||
{
|
||||
const struct sct_surface *si = find_surface_info(sct, surface);
|
||||
return si->contexts;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static boolean
|
||||
find_texture(const struct sct_context *ci,
|
||||
const struct pipe_texture *texture)
|
||||
{
|
||||
const struct texture_list *tl;
|
||||
|
||||
for (tl = ci->textures_used; tl; tl = tl->next) {
|
||||
if (tl->texture == texture) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add the given texture to the context's list of used textures.
|
||||
*/
|
||||
static void
|
||||
add_texture_used(struct sct_context *ci,
|
||||
struct pipe_texture *texture)
|
||||
{
|
||||
if (!find_texture(ci, texture)) {
|
||||
/* add to list */
|
||||
struct texture_list *tl = CALLOC_STRUCT(texture_list);
|
||||
if (tl) {
|
||||
pipe_texture_reference(&tl->texture, texture);
|
||||
/* insert at head */
|
||||
tl->next = ci->textures_used;
|
||||
ci->textures_used = tl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Bind a texture to a rendering context.
|
||||
*/
|
||||
void
|
||||
sct_bind_texture(struct surface_context_tracker *sct,
|
||||
struct pipe_context *context,
|
||||
uint unit,
|
||||
struct pipe_texture *tex)
|
||||
{
|
||||
struct sct_context *ci = find_context_info(sct, context);
|
||||
|
||||
if (ci->textures[unit] != tex) {
|
||||
/* put texture on the 'used' list */
|
||||
add_texture_used(ci, tex);
|
||||
/* bind new */
|
||||
pipe_texture_reference(&ci->textures[unit], tex);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if the given texture has been used by the rendering context
|
||||
* since the last call to sct_flush_textures().
|
||||
*/
|
||||
boolean
|
||||
sct_is_texture_used(struct surface_context_tracker *sct,
|
||||
const struct pipe_context *context,
|
||||
const struct pipe_texture *texture)
|
||||
{
|
||||
const struct sct_context *ci = find_context_info(sct, context);
|
||||
return find_texture(ci, texture);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* To be called when the image contents of a texture are changed, such
|
||||
* as for gl[Copy]TexSubImage().
|
||||
* XXX this may not be needed
|
||||
*/
|
||||
void
|
||||
sct_update_texture(struct pipe_texture *tex)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* When a scene is flushed/rendered we can release the list of
|
||||
* used textures.
|
||||
*/
|
||||
void
|
||||
sct_flush_textures(struct surface_context_tracker *sct,
|
||||
struct pipe_context *context)
|
||||
{
|
||||
struct sct_context *ci = find_context_info(sct, context);
|
||||
struct texture_list *tl, *next;
|
||||
uint i;
|
||||
|
||||
for (tl = ci->textures_used; tl; tl = next) {
|
||||
next = tl->next;
|
||||
pipe_texture_release(&tl->texture);
|
||||
FREE(tl);
|
||||
}
|
||||
ci->textures_used = NULL;
|
||||
|
||||
/* put the currently bound textures on the 'used' list */
|
||||
for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
|
||||
add_texture_used(ci, ci->textures[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void
|
||||
sct_destroy_context(struct surface_context_tracker *sct,
|
||||
struct pipe_context *context)
|
||||
{
|
||||
/* XXX should we require an unbinding first? */
|
||||
{
|
||||
struct sct_surface *si;
|
||||
for (si = sct->surfaces; si; si = si->next) {
|
||||
remove_context_from_surface(si, context);
|
||||
}
|
||||
}
|
||||
|
||||
/* remove context from context_info list */
|
||||
{
|
||||
struct sct_context *ci, *next, *prev = NULL;
|
||||
for (ci = sct->contexts; ci; ci = next) {
|
||||
next = ci->next;
|
||||
if (ci->context == context) {
|
||||
if (prev)
|
||||
prev->next = ci->next;
|
||||
else
|
||||
sct->contexts = ci->next;
|
||||
FREE(ci);
|
||||
}
|
||||
else {
|
||||
prev = ci;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
sct_destroy_surface(struct surface_context_tracker *sct,
|
||||
struct pipe_surface *surface)
|
||||
{
|
||||
if (1) {
|
||||
/* debug/sanity: no context should be bound to surface */
|
||||
struct sct_context *ci;
|
||||
uint i;
|
||||
for (ci = sct->contexts; ci; ci = ci->next) {
|
||||
for (i = 0; i < MAX_SURFACES; i++) {
|
||||
assert(ci->surfaces[i] != surface);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* remove surface from sct_surface list */
|
||||
{
|
||||
struct sct_surface *si, *next, *prev = NULL;
|
||||
for (si = sct->surfaces; si; si = next) {
|
||||
next = si->next;
|
||||
if (si->surface == surface) {
|
||||
/* unlink */
|
||||
if (prev)
|
||||
prev->next = si->next;
|
||||
else
|
||||
sct->surfaces = si->next;
|
||||
FREE(si);
|
||||
}
|
||||
else {
|
||||
prev = si;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
123
src/gallium/auxiliary/sct/sct.h
Normal file
123
src/gallium/auxiliary/sct/sct.h
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
/**************************************************************************
|
||||
*
|
||||
* Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
|
||||
* All Rights Reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sub license, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial portions
|
||||
* of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||||
* IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
|
||||
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||||
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*
|
||||
**************************************************************************/
|
||||
|
||||
/**
|
||||
* Surface/Context Tracking
|
||||
*
|
||||
* For some drivers, we need to monitor the binding between contexts and
|
||||
* surfaces/textures.
|
||||
* This code may evolve quite a bit...
|
||||
*/
|
||||
|
||||
|
||||
#ifndef SCT_H
|
||||
#define SCT_H
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
struct pipe_context;
|
||||
struct pipe_surface;
|
||||
|
||||
struct sct_context;
|
||||
struct sct_surface;
|
||||
|
||||
|
||||
/**
|
||||
* Per-device info, basically
|
||||
*/
|
||||
struct surface_context_tracker
|
||||
{
|
||||
struct sct_context *contexts;
|
||||
struct sct_surface *surfaces;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Simple linked list of contexts
|
||||
*/
|
||||
struct sct_context_list
|
||||
{
|
||||
const struct pipe_context *context;
|
||||
struct sct_context_list *next;
|
||||
};
|
||||
|
||||
|
||||
|
||||
extern void
|
||||
sct_bind_surfaces(struct surface_context_tracker *sct,
|
||||
struct pipe_context *context,
|
||||
uint num_surf,
|
||||
struct pipe_surface **surfaces);
|
||||
|
||||
|
||||
extern void
|
||||
sct_bind_texture(struct surface_context_tracker *sct,
|
||||
struct pipe_context *context,
|
||||
uint unit,
|
||||
struct pipe_texture *texture);
|
||||
|
||||
|
||||
extern void
|
||||
sct_update_texture(struct pipe_texture *tex);
|
||||
|
||||
|
||||
extern boolean
|
||||
sct_is_texture_used(struct surface_context_tracker *sct,
|
||||
const struct pipe_context *context,
|
||||
const struct pipe_texture *texture);
|
||||
|
||||
extern void
|
||||
sct_flush_textures(struct surface_context_tracker *sct,
|
||||
struct pipe_context *context);
|
||||
|
||||
|
||||
extern const struct sct_context_list *
|
||||
sct_get_surface_contexts(struct surface_context_tracker *sct,
|
||||
const struct pipe_surface *surf);
|
||||
|
||||
|
||||
extern void
|
||||
sct_destroy_context(struct surface_context_tracker *sct,
|
||||
struct pipe_context *context);
|
||||
|
||||
|
||||
extern void
|
||||
sct_destroy_surface(struct surface_context_tracker *sct,
|
||||
struct pipe_surface *surface);
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SCT_H */
|
||||
61
src/gallium/auxiliary/sct/usage.c
Normal file
61
src/gallium/auxiliary/sct/usage.c
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
/* surface / context tracking */
|
||||
|
||||
|
||||
/*
|
||||
|
||||
context A:
|
||||
render to texture T
|
||||
|
||||
context B:
|
||||
texture from T
|
||||
|
||||
-----------------------
|
||||
|
||||
flush surface:
|
||||
which contexts are bound to the surface?
|
||||
|
||||
-----------------------
|
||||
|
||||
glTexSubImage():
|
||||
which contexts need to be flushed?
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
|
||||
in MakeCurrent():
|
||||
|
||||
call sct_bind_surfaces(context, list of surfaces) to update the
|
||||
dependencies between context and surfaces
|
||||
|
||||
|
||||
in SurfaceFlush(), or whatever it is in D3D:
|
||||
|
||||
call sct_get_surface_contexts(surface) to get a list of contexts
|
||||
which are currently bound to the surface.
|
||||
|
||||
|
||||
|
||||
in BindTexture():
|
||||
|
||||
call sct_bind_texture(context, texture) to indicate that the texture
|
||||
is used in the scene.
|
||||
|
||||
|
||||
in glTexSubImage() or RenderToTexture():
|
||||
|
||||
call sct_is_texture_used(context, texture) to determine if the texture
|
||||
has been used in the scene, but the scene's not flushed. If TRUE is
|
||||
returned it means the scene has to be rendered/flushed before the contents
|
||||
of the texture can be changed.
|
||||
|
||||
|
||||
in psb_scene_flush/terminate():
|
||||
|
||||
call sct_flush_textures(context) to tell the SCT that the textures which
|
||||
were used in the scene can be released.
|
||||
|
||||
|
||||
|
||||
*/
|
||||
Loading…
Add table
Reference in a new issue