00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
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
00104 si = CALLOC_STRUCT(sct_surface);
00105 if (si) {
00106 si->surface = surface;
00107
00108
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
00144 ci = CALLOC_STRUCT(sct_context);
00145 if (ci) {
00146 ci->context = context;
00147
00148
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
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
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;
00248 }
00249
00250
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
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
00304 struct texture_list *tl = CALLOC_STRUCT(texture_list);
00305 if (tl) {
00306 pipe_texture_reference(&tl->texture, texture);
00307
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
00328 add_texture_used(ci, tex);
00329
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
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
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
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
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
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
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 }