sct.c

Go to the documentation of this file.
00001 /**************************************************************************
00002  * 
00003  * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
00004  * All Rights Reserved.
00005  * 
00006  * Permission is hereby granted, free of charge, to any person obtaining a
00007  * copy of this software and associated documentation files (the
00008  * "Software"), to deal in the Software without restriction, including
00009  * without limitation the rights to use, copy, modify, merge, publish,
00010  * distribute, sub license, and/or sell copies of the Software, and to
00011  * permit persons to whom the Software is furnished to do so, subject to
00012  * the following conditions:
00013  * 
00014  * The above copyright notice and this permission notice (including the
00015  * next paragraph) shall be included in all copies or substantial portions
00016  * of the Software.
00017  * 
00018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00019  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00020  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
00021  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
00022  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
00023  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
00024  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00025  * 
00026  **************************************************************************/
00027 
00028 
00029 #include "util/u_memory.h"
00030 #include "pipe/p_state.h"
00031 #include "pipe/p_inlines.h"
00032 #include "sct.h"
00033 
00034 
00035 struct texture_list
00036 {
00037    struct pipe_texture *texture;
00038    struct texture_list *next;
00039 };
00040 
00041 
00042 
00043 #define MAX_SURFACES  ((PIPE_MAX_COLOR_BUFS) + 1)
00044 
00045 struct sct_context
00046 {
00047    const struct pipe_context *context;
00048 
00050    struct pipe_surface *surfaces[MAX_SURFACES];
00051 
00053    struct pipe_texture *textures[PIPE_MAX_SAMPLERS];
00054 
00056    struct texture_list *textures_used;
00057 
00058    boolean needs_flush;
00059 
00060    struct sct_context *next;
00061 };
00062 
00063 
00064 
00065 struct sct_surface
00066 {
00067    const struct pipe_surface *surface;
00068 
00070    struct sct_context_list *contexts;
00071 
00072    struct sct_surface *next;
00073 };
00074 
00075 
00076 
00080 static struct sct_surface *
00081 find_surface_info(struct surface_context_tracker *sct,
00082                   const struct pipe_surface *surface)
00083 {
00084    struct sct_surface *si;
00085    for (si = sct->surfaces; si; si = si->next)
00086       if (si->surface == surface)
00087          return si;
00088    return NULL;
00089 }
00090 
00091 
00095 static struct sct_surface *
00096 find_create_surface_info(struct surface_context_tracker *sct,
00097                          const struct pipe_surface *surface)
00098 {
00099    struct sct_surface *si = find_surface_info(sct, surface);
00100    if (si)
00101       return si;
00102 
00103    /* alloc new */
00104    si = CALLOC_STRUCT(sct_surface);
00105    if (si) {
00106       si->surface = surface;
00107 
00108       /* insert at head */
00109       si->next = sct->surfaces;
00110       sct->surfaces = si;
00111    }
00112 
00113    return si;
00114 }
00115 
00116 
00120 static struct sct_context *
00121 find_context_info(struct surface_context_tracker *sct,
00122                   const struct pipe_context *context)
00123 {
00124    struct sct_context *ci;
00125    for (ci = sct->contexts; ci; ci = ci->next)
00126       if (ci->context == context)
00127          return ci;
00128    return NULL;
00129 }
00130 
00131 
00135 static struct sct_context *
00136 find_create_context_info(struct surface_context_tracker *sct,
00137                          const struct pipe_context *context)
00138 {
00139    struct sct_context *ci = find_context_info(sct, context);
00140    if (ci)
00141       return ci;
00142 
00143    /* alloc new */
00144    ci = CALLOC_STRUCT(sct_context);
00145    if (ci) {
00146       ci->context = context;
00147 
00148       /* insert at head */
00149       ci->next = sct->contexts;
00150       sct->contexts = ci;
00151    }
00152 
00153    return ci;
00154 }
00155 
00156 
00160 static boolean
00161 find_surface_context(const struct sct_surface *si,
00162                      const struct pipe_context *context)
00163 {
00164    const struct sct_context_list *cl;
00165    for (cl = si->contexts; cl; cl = cl->next) {
00166       if (cl->context == context) {
00167          return TRUE;
00168       }
00169    }
00170    return FALSE;
00171 }
00172 
00173 
00177 static void
00178 add_context_to_surface(struct sct_surface *si,
00179                        const struct pipe_context *context)
00180 {
00181    struct sct_context_list *cl = CALLOC_STRUCT(sct_context_list);
00182    if (cl) {
00183       cl->context = context;
00184       /* insert at head of list of contexts */
00185       cl->next = si->contexts;
00186       si->contexts = cl;
00187    }
00188 }
00189 
00190 
00194 static void
00195 remove_context_from_surface(struct sct_surface *si,
00196                             const struct pipe_context *context)
00197 {
00198    struct sct_context_list *prev = NULL, *curr, *next;
00199 
00200    for (curr = si->contexts; curr; curr = next) {
00201       if (curr->context == context) {
00202          /* remove */
00203          if (prev)
00204             prev->next = curr->next;
00205          else
00206             si->contexts = curr->next;
00207          next = curr->next;
00208          FREE(curr);
00209       }
00210       else {
00211          prev = curr;
00212          next = curr->next;
00213       }
00214    }
00215 }
00216 
00217 
00221 static void
00222 unbind_context_surface(struct surface_context_tracker *sct,
00223                        struct pipe_context *context,
00224                        struct pipe_surface *surface)
00225 {
00226    struct sct_surface *si = find_surface_info(sct, surface);
00227    if (si) {
00228       remove_context_from_surface(si, context);
00229    }
00230 }
00231 
00232 
00237 void
00238 sct_bind_surfaces(struct surface_context_tracker *sct,
00239                   struct pipe_context *context,
00240                   uint num_surf,
00241                   struct pipe_surface **surfaces)
00242 {
00243    struct sct_context *ci = find_create_context_info(sct, context);
00244    uint i;
00245 
00246    if (!ci) {
00247       return; /* out of memory */
00248    }
00249 
00250    /* unbind currently bound surfaces */
00251    for (i = 0; i < MAX_SURFACES; i++) {
00252       if (ci->surfaces[i]) {
00253          unbind_context_surface(sct, context, ci->surfaces[i]);
00254       }
00255    }
00256 
00257    /* bind new surfaces */
00258    for (i = 0; i < num_surf; i++) {
00259       struct sct_surface *si = find_create_surface_info(sct, surfaces[i]);
00260       if (!find_surface_context(si, context)) {
00261          add_context_to_surface(si, context);
00262       }
00263    }
00264 }
00265 
00266 
00270 const struct sct_context_list *
00271 sct_get_surface_contexts(struct surface_context_tracker *sct,
00272                          const struct pipe_surface *surface)
00273 {
00274    const struct sct_surface *si = find_surface_info(sct, surface);
00275    return si->contexts;
00276 }
00277 
00278 
00279 
00280 static boolean
00281 find_texture(const struct sct_context *ci,
00282              const struct pipe_texture *texture)
00283 {
00284    const struct texture_list *tl;
00285 
00286    for (tl = ci->textures_used; tl; tl = tl->next) {
00287       if (tl->texture == texture) {
00288          return TRUE;
00289       }
00290    }
00291    return FALSE;
00292 }
00293 
00294 
00298 static void
00299 add_texture_used(struct sct_context *ci,
00300                  struct pipe_texture *texture)
00301 {
00302    if (!find_texture(ci, texture)) {
00303       /* add to list */
00304       struct texture_list *tl = CALLOC_STRUCT(texture_list);
00305       if (tl) {
00306          pipe_texture_reference(&tl->texture, texture);
00307          /* insert at head */
00308          tl->next = ci->textures_used;
00309          ci->textures_used = tl;
00310       }
00311    }
00312 }
00313 
00314 
00318 void
00319 sct_bind_texture(struct surface_context_tracker *sct,
00320                  struct pipe_context *context,
00321                  uint unit,
00322                  struct pipe_texture *tex)
00323 {
00324    struct sct_context *ci = find_context_info(sct, context);
00325 
00326    if (ci->textures[unit] != tex) {
00327       /* put texture on the 'used' list */
00328       add_texture_used(ci, tex);
00329       /* bind new */
00330       pipe_texture_reference(&ci->textures[unit], tex);
00331    }
00332 }
00333 
00334 
00339 boolean
00340 sct_is_texture_used(struct surface_context_tracker *sct,
00341                     const struct pipe_context *context,
00342                     const struct pipe_texture *texture)
00343 {
00344    const struct sct_context *ci = find_context_info(sct, context);
00345    return find_texture(ci, texture);
00346 }
00347 
00348 
00354 void
00355 sct_update_texture(struct pipe_texture *tex)
00356 {
00357 
00358 }
00359 
00360 
00365 void
00366 sct_flush_textures(struct surface_context_tracker *sct,
00367                    struct pipe_context *context)
00368 {
00369    struct sct_context *ci = find_context_info(sct, context);
00370    struct texture_list *tl, *next;
00371    uint i;
00372 
00373    for (tl = ci->textures_used; tl; tl = next) {
00374       next = tl->next;
00375       pipe_texture_release(&tl->texture);
00376       FREE(tl);
00377    }
00378    ci->textures_used = NULL;
00379 
00380    /* put the currently bound textures on the 'used' list */
00381    for (i = 0; i < PIPE_MAX_SAMPLERS; i++) {
00382       add_texture_used(ci, ci->textures[i]);
00383    }
00384 }
00385 
00386 
00387 
00388 void
00389 sct_destroy_context(struct surface_context_tracker *sct,
00390                     struct pipe_context *context)
00391 {
00392    /* XXX should we require an unbinding first? */
00393    {
00394       struct sct_surface *si;
00395       for (si = sct->surfaces; si; si = si->next) {
00396          remove_context_from_surface(si, context);
00397       }
00398    }
00399 
00400    /* remove context from context_info list */
00401    {
00402       struct sct_context *ci, *next, *prev = NULL;
00403       for (ci = sct->contexts; ci; ci = next) {
00404          next = ci->next;
00405          if (ci->context == context) {
00406             if (prev)
00407                prev->next = ci->next;
00408             else
00409                sct->contexts = ci->next;
00410             FREE(ci);
00411          }
00412          else {
00413             prev = ci;
00414          }
00415       }
00416    }
00417 
00418 }
00419 
00420 
00421 void
00422 sct_destroy_surface(struct surface_context_tracker *sct,
00423                     struct pipe_surface *surface)
00424 {
00425    if (1) {
00426       /* debug/sanity: no context should be bound to surface */
00427       struct sct_context *ci;
00428       uint i;
00429       for (ci = sct->contexts; ci; ci = ci->next) {
00430          for (i = 0; i < MAX_SURFACES; i++) {
00431             assert(ci->surfaces[i] != surface);
00432          }
00433       }
00434    }
00435 
00436    /* remove surface from sct_surface list */
00437    {
00438       struct sct_surface *si, *next, *prev = NULL;
00439       for (si = sct->surfaces; si; si = next) {
00440          next = si->next;
00441          if (si->surface == surface) {
00442             /* unlink */
00443             if (prev)
00444                prev->next = si->next;
00445             else
00446                sct->surfaces = si->next;
00447             FREE(si);
00448          }
00449          else {
00450             prev = si;
00451          }
00452       }
00453    }
00454 }

Generated on Tue Sep 29 06:25:14 2009 for Gallium3D by  doxygen 1.5.4