1
/* $Xorg: strip.c,v 1.4 2001/02/09 02:04:23 xorgcvs Exp $ */
2
/* AGE Logic - Oct 15 1995 - Larry Hare */
3
/**** module strip.c ****/
4
/*****************************************************************************
6
Copyright 1993, 1994, 1998 The Open Group
8
Permission to use, copy, modify, distribute, and sell this software and its
9
documentation for any purpose is hereby granted without fee, provided that
10
the above copyright notice appear in all copies and that both that
11
copyright notice and this permission notice appear in supporting
14
The above copyright notice and this permission notice shall be included in
15
all copies or substantial portions of the Software.
17
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
Except as contained in this notice, the name of The Open Group shall not be
25
used in advertising or otherwise to promote the sale, use or other dealings
26
in this Software without prior written authorization from The Open Group.
31
This software is being provided by AGE Logic, Inc. under the
32
following license. By obtaining, using and/or copying this software,
33
you agree that you have read, understood, and will comply with these
36
Permission to use, copy, modify, distribute and sell this
37
software and its documentation for any purpose and without
38
fee or royalty and to grant others any or all rights granted
39
herein is hereby granted, provided that you agree to comply
40
with the following copyright notice and statements, including
41
the disclaimer, and that the same appears on all copies and
42
derivative works of the software and documentation you make.
44
"Copyright 1993, 1994 by AGE Logic, Inc."
46
THIS SOFTWARE IS PROVIDED "AS IS". AGE LOGIC MAKES NO
47
REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. By way of
48
example, but not limitation, AGE LOGIC MAKE NO
49
REPRESENTATIONS OR WARRANTIES OF MERCHANTABILITY OR FITNESS
50
FOR ANY PARTICULAR PURPOSE OR THAT THE SOFTWARE DOES NOT
51
INFRINGE THIRD-PARTY PROPRIETARY RIGHTS. AGE LOGIC
52
SHALL BEAR NO LIABILITY FOR ANY USE OF THIS SOFTWARE. IN NO
53
EVENT SHALL EITHER PARTY BE LIABLE FOR ANY INDIRECT,
54
INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS
55
OF PROFITS, REVENUE, DATA OR USE, INCURRED BY EITHER PARTY OR
56
ANY THIRD PARTY, WHETHER IN AN ACTION IN CONTRACT OR TORT OR
57
BASED ON A WARRANTY, EVEN IF AGE LOGIC LICENSEES
58
HEREUNDER HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH
61
The name of AGE Logic, Inc. may not be used in
62
advertising or publicity pertaining to this software without
63
specific, written prior permission from AGE Logic.
65
Title to this software shall at all times remain with AGE
67
*****************************************************************************
69
strip.c -- DDXIE machine independent data flo manager
71
Robert NC Shelley -- AGE Logic, Inc. April, 1993
73
*****************************************************************************/
74
/* $XFree86: xc/programs/Xserver/XIE/mixie/control/strip.c,v 3.7 2001/12/14 19:58:17 dawes Exp $ */
91
* more X server includes.
94
#include <dixstruct.h>
105
/* routines exported to DIXIE via the photoflo management vector
107
static int import_data(
114
static int export_data(
120
static int query_data(
122
xieTypPhototag **list,
126
/* routines exported to elements via the data manager's vector
128
static CARD8 *make_bytes(
134
static CARD8 *make_lines(
139
static Bool map_data(
147
static CARD8 *get_data(
153
static Bool put_data(floDefPtr flo, peTexPtr pet, bandPtr dbnd);
154
static void free_data(floDefPtr flo, peTexPtr pet, bandPtr dbnd);
155
static Bool pass_strip(
160
static Bool import_strips(
165
static Bool alter_src(floDefPtr flo, peTexPtr pet, stripPtr strip);
166
static void bypass_src(floDefPtr flo, peTexPtr pet, bandPtr dbnd);
167
static void disable_src(floDefPtr flo, peTexPtr pet, bandPtr bnd, Bool purge);
168
static void disable_dst(floDefPtr flo, peTexPtr pet, bandPtr dbnd);
170
/* routines used internal to this module
172
static stripPtr alter_data(floDefPtr flo, peTexPtr pet, bandPtr db);
173
static stripPtr contig_data(
179
static stripPtr make_strip(
186
static stripPtr clone_strip(floDefPtr flo, stripPtr in_strip);
187
static bandMsk put_strip(floDefPtr flo, peTexPtr pet, stripPtr strip);
188
static void forward_strip(floDefPtr flo, peTexPtr pet, stripPtr fwd);
189
static stripPtr free_strip(floDefPtr flo, stripPtr strip);
191
/* DDXIE client data manager entry points
193
static dataVecRec dataManagerVec = {
194
(xieIntProc)import_data,
195
(xieIntProc)export_data,
196
(xieIntProc)query_data
199
/* DDXIE photoflo manager entry points
201
static stripVecRec stripManagerVec = {
216
INT32 STRIPS = 0; /* DEBUG */
217
INT32 BYTES = 0; /* DEBUG */
219
/*------------------------------------------------------------------------
220
-------------------------- Initialize Data Manager -----------------------
221
------------------------------------------------------------------------*/
222
int InitStripManager(floDefPtr flo)
224
/* plug in the DDXIE client data management vector */
225
flo->dataVec = &dataManagerVec;
227
/* plug in the strip manager vector */
228
flo->stripVec = &stripManagerVec;
230
/* init the strip cache */
231
ListInit(&flo->floTex->stripHead);
233
/* choose the best strip size for this flo (a constant value for now) */
234
flo->floTex->stripSize = STANDARD_STRIP_SIZE;
236
/* clear the count of strips passed */
237
flo->floTex->putCnt = 0;
240
} /* end InitStripManager */
243
/*------------------------------------------------------------------------
244
----------- discard parent headers from a whole list of strips -----------
245
----------- and copy data if multiple references are found -----------
246
----------- then transfer them all to their final destination -----------
247
------------------------------------------------------------------------*/
252
stripPtr child, parent;
254
/* NOTE: we might want to consider (re)allocing strip buffers to
255
* strip->length instead of leaving them an strip->bufSiz.
257
for(child = i_head->flink; !ListEnd(child,i_head); child = child->flink) {
258
while ((parent = child->parent) != 0)
259
if(parent->refCnt == 1) { /* discard a cloned header */
260
child->parent = parent->parent;
263
} else { /* copy multiply referenced data */
264
if(!(child->data = (CARD8*)XieMalloc(child->bufSiz)))
266
memcpy((char*)child->data, (char*)parent->data, (int)child->bufSiz);
267
child->parent = NULL; /* de-reference child from parent */
269
BYTES += child->bufSiz; /*DEBUG*/
271
child->format = NULL; /* kill per-strip format pointer */
273
/* transfer the entire list of input strips to the output
275
if(ListEmpty(i_head))
278
i_head->flink->blink = (stripPtr)o_head;
279
i_head->blink->flink = (stripPtr)o_head;
284
} /* end DebriefStrips */
287
/*------------------------------------------------------------------------
288
------------------------- Free a whole list of strips --------------------
289
------------------------------------------------------------------------*/
290
void FreeStrips(stripLstPtr head)
292
while( !ListEmpty(head) ) {
295
RemoveMember(strip, head->flink);
296
free_strip(NULL, strip);
298
} /* end FreeStrips */
301
/*------------------------------------------------------------------------
302
------------------------ Input from PutClientData ------------------------
303
------------------------------------------------------------------------*/
304
static int import_data(
312
peTexPtr pet = ped->peTex;
313
receptorPtr rcp = &pet->receptor[IMPORT];
314
bandPtr bnd = &rcp->band[band];
315
bandMsk msk = 1<<band;
318
if(!((rcp->admit | rcp->bypass) & msk))
319
return(TRUE); /* drop unwanted data */
321
/* make a strip and fill it in the info from the client
322
* (the format info was supplied with the element and technique parameters)
324
if(!(strip = make_strip(flo,bnd->format,bnd->maxGlobal,len,len,FALSE)))
325
AllocError(flo,ped, return(FALSE));
326
strip->final = final;
330
if(rcp->bypass & msk) {
331
put_strip(flo,pet,strip); /* pass it downstream */
333
free_strip(flo,strip); /* nobody wanted it */
335
bnd->maxGlobal = strip->end + 1;
336
bnd->available += len;
338
InsertMember(strip,bnd->stripLst.blink);
339
if ((bnd->final = final) != 0) {
340
if(!(rcp->admit &= ~msk))
342
--flo->floTex->imports;
345
/* fire up the scheduler -- then we're outa here */
346
return( Execute(flo,pet) );
347
} /* end import_data */
350
/*------------------------------------------------------------------------
351
-------------------------- Output for GetClientData ----------------------
352
------------------------------------------------------------------------*/
353
static int export_data(
360
BOOL release = FALSE, final = FALSE;
361
stripLstPtr lst = &ped->outFlo.output[band];
362
stripPtr strip = NULL;
363
CARD32 bytes, want = maxLen;
366
/* if this is multi-byte data, make sure we send/swap complete aggregates
368
if(ped->swapUnits[band] > 1)
369
want &= ~(ped->swapUnits[band]-1);
371
if ((bytes = ListEmpty(lst) ? 0 : min(lst->flink->length, want)) != 0) {
373
data = strip->data + (strip->bitOff>>3);
374
if(strip->length -= bytes) {
375
strip->start += bytes;
376
strip->bitOff += bytes<<3;
378
RemoveMember(strip, strip);
379
final = strip->final;
382
ped->outFlo.ready &= ~(1<<band);
388
flo->floTex->exports--;
390
/* shut down the output band prematurely */
391
ped->outFlo.ready &= ~(1<<band);
392
disable_dst(flo,ped->peTex,&ped->peTex->emitter[band]);
394
/* figure out our current state and send a reply to the client
396
state = ped->outFlo.ready & 1<<band ? xieValExportMore
397
: ped->outFlo.active & 1<<band ? xieValExportEmpty
399
SendClientData(flo,ped,data,bytes,ped->swapUnits[band],state);
401
free_strip(flo,strip);
403
return(bytes ? Execute(flo,NULL) : TRUE);
404
} /* end export_data */
407
/*------------------------------------------------------------------------
408
----------- Query flo elements involved in client data transport ---------
409
------------------------------------------------------------------------*/
410
static int query_data(
412
xieTypPhototag **list,
417
pedLstPtr lst = ListEmpty(&flo->optDAG) ? &flo->defDAG : &flo->optDAG;
420
*pending = *available = 0;
421
if(!(*list = (xieTypPhototag *)XieMalloc(flo->peCnt * sz_xieTypPhototag)))
422
FloAllocError(flo,0,0, return(FALSE));
424
/* find all the import elements that need client data */
425
for(ped = lst->flink; ped; ped = ped->clink)
426
if(ped->flags.putData && ped->peTex->admissionCnt)
427
*list[(*pending)++] = ped->phototag;
429
/* find all the export elements that have client data */
430
exdex = *pending + (*pending & 1);
431
for(ped = lst->blink; ped; ped = ped->clink)
432
if(ped->flags.getData && ped->outFlo.ready)
433
*list[exdex + (*available)++] = ped->phototag;
436
} /* end query_data */
439
/*------------------------------------------------------------------------
440
---- make a strip containing the specified number of contiguous bytes ----
441
------------------------------------------------------------------------*/
442
static CARD8* make_bytes(
449
stripPtr strip = bnd->stripLst.blink;
450
CARD32 limit, size, units;
451
Bool avail = (!ListEmpty(&bnd->stripLst) && bnd->current >= strip->start &&
452
bnd->current + contig <= strip->start + strip->bufSiz);
454
if(purge && !avail && put_data(flo,pet,bnd))
455
return(bnd->data = NULL); /* force element to suspend processing */
458
return(get_data(flo,pet,bnd,contig,FALSE)); /* "current" is available */
461
/* extend the available space in our current strip
463
limit = bnd->current + contig;
464
bnd->available += limit - bnd->maxGlobal;
465
bnd->maxGlobal = limit;
466
strip->end = limit - 1;
467
strip->length = limit - strip->start;
469
/* time to make a fresh strip
471
units = bnd->current + contig - bnd->maxGlobal;
472
size = units + Align(units,flo->floTex->stripSize);
473
if(!(strip = make_strip(flo,bnd->format,bnd->maxGlobal,units,size,TRUE)))
474
AllocError(flo,pet->peDef, return(NULL));
476
bnd->available += strip->length;
477
bnd->maxGlobal = strip->end + 1;
478
InsertMember(strip,bnd->stripLst.blink);
480
/* update our bandRec with the results */
482
bnd->minLocal = max(bnd->minGlobal,strip->start);
483
bnd->maxLocal = strip->end + 1;
484
return(bnd->data = _byte_ptr(bnd));
485
} /* end make_bytes */
488
/*------------------------------------------------------------------------
489
--- Find or make a strip containing the unit specified by bnd->current ---
490
------------------------------------------------------------------------*/
491
static CARD8* make_lines(
497
stripPtr strip = NULL;
501
if(purge && _release_ok(bnd) && put_data(flo,pet,bnd))
502
return(bnd->data = NULL); /* force element to suspend processing */
504
if(_is_global(bnd)) /* we already have it, just go find it */
505
return(get_data(flo,pet,bnd,(CARD32) 1,FALSE));
508
if(bnd->current >= fmt->height)
509
return(NULL); /* trying to go beyond end of image */
511
while(bnd->current >= bnd->maxGlobal) {
513
* re-use src if we're allowed to alter the data
515
if(!bnd->inPlace || !(strip = alter_data(flo,pet,bnd))) {
516
size = flo->floTex->stripSize;
517
units = size / bnd->pitch;
518
if(units == 0) { /* image bigger than standard strip */
521
} else if(bnd->current + units > fmt->height) /* at end of image */
522
units = fmt->height - bnd->current;
523
strip = make_strip(flo,fmt,bnd->maxGlobal,units,size,TRUE);
526
AllocError(flo,pet->peDef, return(NULL));
527
bnd->available += strip->length;
528
bnd->maxGlobal = strip->end + 1;
529
if(bnd->maxGlobal == fmt->height)
530
bnd->final = strip->final = TRUE;
531
InsertMember(strip,bnd->stripLst.blink);
533
/* update our bandRec with the results */
535
bnd->minLocal = max(bnd->minGlobal,strip->start);
536
bnd->maxLocal = strip->end + 1;
537
return(bnd->data = _line_ptr(bnd));
538
} /* end make_lines */
541
/*------------------------------------------------------------------------
542
-------------- load data map with pointers to specified data -------------
543
------------------------------------------------------------------------*/
544
static Bool map_data(
554
CARD8 *next = (CARD8 *)NULL, *last = (CARD8 *)NULL;
555
CARD8 **ptr = bnd->dataMap + map;
558
/* first map the last unit and then the first unit -- if we have to make
559
* strips, or if input strips aren't there, we may as well handle it now
561
if(len && map + len <= bnd->mapSize)
563
last = (CARD8*)GetSrc(flo,pet,bnd,unit+len-1,KEEP);
564
next = (CARD8*)GetSrc(flo,pet,bnd,unit,purge);
566
last = (CARD8*)GetDst(flo,pet,bnd,unit+len-1,KEEP);
567
next = (CARD8*)GetDst(flo,pet,bnd,unit,purge);
570
return(FALSE); /* map too small or can't map first and last unit */
572
/* now walk through the strips and map all the lines (or bytes!)
577
while((*ptr++ = next) != last)
578
if(++line <= strip->end)
581
strip = strip->flink;
588
/*------------------------------------------------------------------------
589
------ Find the strip containing the unit specified by bnd->current ------
590
------------------------------------------------------------------------*/
591
static CARD8* get_data(
598
/* NOTE: get_data assumes that the caller has already verified that the
599
* beginning of the requested data is available in bnd->stripLst.
601
stripPtr strip = bnd->strip ? bnd->strip : bnd->stripLst.flink;
603
/* first get rid of extra baggage if we can
605
if(purge && _release_ok(bnd))
606
free_data(flo,pet,bnd);
608
strip = bnd->strip ? bnd->strip : bnd->stripLst.flink;
609
while(!ListEnd(strip,&bnd->stripLst))
610
if(bnd->current > strip->end)
611
strip = strip->flink; /* try the next strip */
612
else if(bnd->current < strip->start)
613
strip = strip->blink; /* try the previous strip */
614
else if(bnd->current+contig-1 <= strip->end ||
615
(strip = contig_data(flo,pet,bnd,strip,contig)))
616
break; /* we found or assembled it */
618
return(NULL); /* couldn't get enough bytes */
620
/* update our bandRec with the results
623
bnd->minLocal = max(bnd->minGlobal,strip->start);
624
bnd->maxLocal = strip->end + 1;
625
bnd->data = _is_local_contig(bnd,contig) ? _line_ptr(bnd) : NULL;
630
/*------------------------------------------------------------------------
631
------- move strip(s) onto awaiting receptor(s) or an export outFlo ------
632
------------------------------------------------------------------------*/
633
static Bool put_data(
641
/* transfer strips until we run out or reach the one we're working in
643
while(_release_ok(bnd)) {
644
RemoveMember(strip, bnd->stripLst.flink);
645
bnd->available -= strip->length;
646
bnd->minGlobal = strip->end + 1;
648
if(!(pet->emitting & 1<<bnd->band))
649
free_strip(flo,strip); /* output disabled */
652
suspend |= put_strip(flo,pet,strip); /* send it downstream */
654
free_strip(flo,strip); /* nobody wanted it! */
657
if(ListEmpty(&bnd->stripLst)) {
661
disable_dst(flo,pet,bnd);
663
return(suspend != 0);
667
/*------------------------------------------------------------------------
668
---------- free strip(s) from a receptor band or an emitter band ---------
669
------------------------------------------------------------------------*/
670
static void free_data(
675
bandMsk msk = 1<<bnd->band;
677
/* free strips until we run out or reach the one we're working in
679
while(_release_ok(bnd)) {
682
RemoveMember(strip, bnd->stripLst.flink);
683
bnd->available -= strip->length - (bnd->minGlobal - strip->start);
684
bnd->minGlobal = strip->end + 1;
685
if(bnd->isInput && bnd->receptor->forward & msk)
686
forward_strip(flo,pet,strip);
688
free_strip(flo,strip);
690
/* a little bookkeeping to let the scheduler know where we're at
692
bnd->available -= bnd->current - bnd->minGlobal;
693
bnd->minGlobal = bnd->current;
695
CheckSrcReady(bnd,msk);
697
if(bnd->final && bnd->isInput && ListEmpty(&bnd->stripLst)) {
698
bnd->receptor->active &= ~msk;
699
bnd->receptor->attend &= ~msk;
701
if(!(bnd->data = _is_local(bnd) ? _line_ptr(bnd) : NULL))
703
} /* end free_data */
706
/*------------------------------------------------------------------------
707
---- take list of strips passed in (most likely from a photomap), clone --
708
---- the headers, and hang them on the input receptor to make the data --
709
---- accessable by standard macros --
710
------------------------------------------------------------------------*/
711
static Bool import_strips(
717
stripPtr strip = strips->flink, clone = NULL;
718
receptorPtr rcp = pet->receptor;
719
CARD8 msk = 1<<bnd->band;
721
for(strip = strips->flink; !ListEnd(strip,strips); strip = strip->flink) {
723
if(!(clone = clone_strip(flo, strip)))
724
AllocError(flo,pet->peDef, return(FALSE));
726
clone->format = bnd->format; /* this had better be right! */
728
bnd->available += clone->length;
730
InsertMember(clone,bnd->stripLst.blink);
732
bnd->final = clone->final;
733
bnd->maxGlobal = clone->end + 1;
735
if(!(rcp->admit &= ~msk))
739
} /* end import_strips */
742
/*------------------------------------------------------------------------
743
--------- Clone a strip and pass it on to the element's recipients -------
744
------------------------------------------------------------------------*/
745
static Bool pass_strip(
753
if(!(pet->emitting & 1<<bnd->band))
754
return(TRUE); /* output disabled */
756
if(!(clone = clone_strip(flo, strip)))
757
AllocError(flo,pet->peDef, return(FALSE));
759
clone->format = bnd->format; /* this had better be right! */
761
put_strip(flo,pet,clone); /* give to downstream receptors */
763
free_strip(flo,clone); /* nobody wanted it */
765
if ((bnd->final = strip->final) != 0)
766
disable_dst(flo,pet,bnd);
769
} /* end pass_strip */
772
/*------------------------------------------------------------------------
773
------------ see if it's ok to over write the data in a src strip --------
774
------------------------------------------------------------------------*/
775
static Bool alter_src(
782
if(!strip->data || strip->Xowner)
785
/* make sure there are no other users of this strip's data
787
for(chk = strip; chk->parent && chk->refCnt == 1; chk = chk->parent);
788
return(chk->refCnt == 1);
789
} /* end alter_src */
792
/*------------------------------------------------------------------------
793
--------- pass all remaining input for this band straight through --------
794
------------------------------------------------------------------------*/
795
static void bypass_src(
801
bandPtr dbnd = &pet->emitter[sbnd->band];
805
if(sbnd->receptor->active & 1<<sbnd->band) {
807
* if there's lingering data, see that it gets to its destination
809
for(src = (CARD8*)GetCurrentSrc(flo,pet,sbnd),
810
dst = (CARD8*)GetCurrentDst(flo,pet,dbnd);
812
src = (CARD8*)GetNextSrc(flo,pet,sbnd,KEEP),
813
dst = (CARD8*)GetNextDst(flo,pet,dbnd,!src)) {
815
memcpy((char*)dst, (char*)src, (int)dbnd->pitch);
817
/* if there's a partial strip still here, adjust its length
819
if(!ListEmpty(&dbnd->stripLst)) {
820
strip = dbnd->stripLst.blink;
821
if(strip->start < dbnd->current) {
822
strip->end = dbnd->current - 1;
823
strip->length = dbnd->current - strip->start;
824
put_data(flo,pet,dbnd);
827
/* shut down the src band, or the dst band if we're all done
829
if(pet->emitting &= ~(1<<dbnd->band))
830
disable_src(flo,pet,sbnd,FLUSH);
832
disable_dst(flo,pet,dbnd);
834
/* if we're still accepting input, the remainder will bypass this element
836
sbnd->receptor->bypass |= 1<<sbnd->band;
837
} /* end bypass_src */
840
/*------------------------------------------------------------------------
841
---------- disable src band and discard any remaining input data ---------
842
------------------------------------------------------------------------*/
843
static void disable_src(
849
bandMsk msk = 1<<bnd->band;
851
if(bnd->receptor->admit & msk && pet->peDef->flags.putData)
852
--flo->floTex->imports; /* one less import client band */
854
if(bnd->receptor->admit && !(bnd->receptor->admit &= ~msk))
855
--pet->admissionCnt; /* one less receptor needing data */
860
FreeData(flo,pet,bnd,bnd->maxGlobal);
861
} /* end disable_src */
864
/*------------------------------------------------------------------------
865
--- disable dst band -- also disables all src's if no dst bands remain ---
866
------------------------------------------------------------------------*/
867
static void disable_dst(
872
peDefPtr ped = pet->peDef;
873
receptorPtr rcp, rend = &pet->receptor[ped->inCnt];
877
/* if this is the last emitter band to turn off and this isn't an import
878
* client element, we'll step thru all the receptor bands and kill them too
880
if(!(pet->emitting &= ~(1<<dbnd->band)) && !ped->flags.putData)
881
for(rcp = pet->receptor; rcp < rend; ++rcp)
882
for(mask = 1, sbnd = rcp->band; rcp->active; mask <<= 1, ++sbnd)
883
if(rcp->active & mask)
884
disable_src(flo,pet,sbnd,TRUE);
885
if(ped->flags.getData) {
886
ped->outFlo.active &= ~(1<<dbnd->band);
887
if(!(ped->outFlo.ready & 1<<dbnd->band))
888
flo->floTex->exports--;
890
} /* end disable_dst */
891
/*------------------------------------------------------------------------
892
- Get permission for an emitter to write into an existing receptor strip -
893
------------------------------------------------------------------------*/
894
static stripPtr alter_data(
899
bandPtr sb = db->inPlace;
900
stripPtr chk, strip = sb->strip ? sb->strip : sb->stripLst.flink;
902
/* search through the source data for the corresponding line number
904
while(!ListEnd(strip,&sb->stripLst))
905
if(db->current > strip->end)
906
strip = strip->flink;
907
else if(db->current < strip->start)
908
strip = strip->blink;
909
else if(!strip->data || strip->Xowner)
912
/* make sure there are no other users of this strip's data
914
for(chk = strip; chk->parent && chk->refCnt == 1; chk = chk->parent);
917
return(clone_strip(flo,strip)); /* return a clone of the src strip */
920
} /* end alter_data */
923
/*------------------------------------------------------------------------
924
---------- enter with a strip containing at least one byte of data ------
925
---------- {if a new strip must be created (to hold at least ------
926
---------- contig bytes), available data will be copied to it} ------
927
---------- return with a strip containing "contig" contiguous bytes ------
928
------------------------------------------------------------------------*/
929
static stripPtr contig_data(
936
stripPtr o_strip, n_strip;
937
CARD32 limit, start, skip, avail = i_strip->end - bnd->current + 1;
939
if(contig <= i_strip->bufSiz - i_strip->length + avail)
942
/* i_strip too small, make a new one and copy available data into it
944
if(!(o_strip = make_strip(flo, bnd->format, bnd->current, avail,
945
contig + Align(contig, flo->floTex->stripSize),
947
AllocError(flo,pet->peDef, return(NULL));
948
InsertMember(o_strip,i_strip);
949
memcpy((char*)o_strip->data,
950
(char*)&i_strip->data[bnd->current-i_strip->start], (int)avail);
951
if(i_strip->length -= avail)
952
i_strip->end -= avail;
954
RemoveMember(n_strip,i_strip);
955
o_strip->final = n_strip->final;
956
free_strip(flo, n_strip);
959
/* determine how far we can extend our o_strip
961
if(bnd->current + contig <= bnd->maxGlobal)
962
limit = bnd->current + contig; /* limit to data needed */
964
limit = bnd->maxGlobal; /* limit to data available */
966
/* if there are more strips beyond "o_strip", transfer the needed amount of
967
* data into our mega-strip (free any strips that we completely consume)
969
for(start = o_strip->end+1; start < limit; start += avail) {
970
n_strip = o_strip->flink;
971
skip = start - n_strip->start;
972
avail = min(n_strip->length - skip, limit - start);
973
memcpy((char*)&o_strip->data[o_strip->length],
974
(char*)&n_strip->data[skip], (int)avail);
975
o_strip->end += avail;
976
o_strip->length += avail;
977
if(avail+skip == n_strip->length) {
978
RemoveMember(n_strip, n_strip);
979
o_strip->final = n_strip->final;
980
free_strip(flo, n_strip);
984
limit = bnd->current + contig;
985
bnd->available += limit - bnd->maxGlobal;
986
bnd->maxGlobal = limit;
987
o_strip->end = limit - 1;
988
o_strip->length = limit - o_strip->start;
991
} /* end contig_data */
994
/*------------------------------------------------------------------------
995
---------------------------- Make a new strip ----------------------------
996
------------------------------------------------------------------------*/
997
static stripPtr make_strip(
1006
stripLstPtr cache = &flo->floTex->stripHead;
1007
Bool cachable = allocData && bytes == flo->floTex->stripSize;
1009
if(!ListEmpty(cache) && (cachable || !cache->blink->data))
1010
RemoveMember(strip, cachable ? cache->flink : cache->blink);
1011
else if ((strip = (stripPtr) XieMalloc(sizeof(stripRec))) != 0) {
1016
strip->flink = NULL;
1017
strip->parent = NULL;
1018
strip->format = fmt;
1020
strip->Xowner = !allocData;
1021
strip->canonic = IsCanonic(fmt->class);
1022
strip->final = FALSE;
1023
strip->cache = cachable;
1024
strip->start = start;
1025
strip->end = start + units - 1;
1026
strip->length = units;
1028
strip->bufSiz = bytes;
1030
if(allocData && bytes && !strip->data)
1031
if ((strip->data = (CARD8 *) XieCalloc(bytes)) != 0) /* calloc to hush purify */
1032
BYTES += bytes; /*DEBUG*/
1034
strip = free_strip(NULL,strip);
1037
} /* end make_strip */
1040
/*------------------------------------------------------------------------
1041
---- Clone a new modifiable strip wrapper for existing read-only data ----
1042
------------------------------------------------------------------------*/
1043
static stripPtr clone_strip(floDefPtr flo, stripPtr in_strip)
1045
stripLstPtr cache = &flo->floTex->stripHead;
1048
if(ListEmpty(cache) || cache->blink->data) {
1049
out_strip = (stripPtr) XieMalloc(sizeof(stripRec));
1052
RemoveMember(out_strip, cache->blink);
1055
*out_strip = *in_strip;
1056
out_strip->flink = NULL;
1057
out_strip->parent = in_strip;
1058
out_strip->refCnt = 1;
1062
} /* end clone_strip */
1065
/*------------------------------------------------------------------------
1066
---------------- Put strip on each receptor fed by an element ------------
1067
------------------------------------------------------------------------*/
1068
static bandMsk put_strip(floDefPtr flo, peTexPtr pet, stripPtr strip)
1075
CARD8 band = strip->format->band;
1076
bandMsk repmsk, mask = 1<<band, suspend = 0;
1078
if(pet->peDef->flags.export) {
1079
pet->outFlo->ready |= mask;
1081
* give to DIXIE via our outFlo; if we're not first in line, make a clone
1083
if(!(clone = strip->flink ? clone_strip(flo,strip) : strip))
1084
AllocError(flo,pet->peDef, return(suspend));
1085
InsertMember(clone,pet->outFlo->output[band].blink);
1086
++flo->floTex->putCnt;
1089
/* hang this strip on the receptor of each of our interested recipients
1091
for(inf = pet->outFlo->outChain; inf; inf = inf->outChain) {
1092
if(inf->format[band].class != strip->format->class)
1094
dst = inf->ownDef->peTex;
1095
rcp = &dst->receptor[inf->index];
1096
bnd = &rcp->band[band];
1098
if(rcp->bypass & mask) {
1099
suspend |= put_strip(flo,dst,strip); /* just passin' through */
1101
} else if(!(rcp->admit & mask)) {
1102
continue; /* data not wanted here */
1104
if(strip->final && !(rcp->admit &= ~mask))
1105
--dst->admissionCnt; /* all bands complete */
1107
* give the data to the intended receptor band
1109
for(repmsk = mask; repmsk <= rcp->active; ++bnd, repmsk <<= 1) {
1110
if(rcp->active & repmsk) {
1111
bnd->final = strip->final;
1112
bnd->maxGlobal = strip->end + 1;
1113
bnd->available += strip->length;
1114
Schedule(flo,dst,rcp,bnd,repmsk); /* schedule if runnable */
1115
suspend |= dst->scheduled;
1117
* first recipient gets the original, all others get clones
1119
if(!(clone = strip->flink ? clone_strip(flo,strip) : strip))
1120
AllocError(flo,dst->peDef, break);
1121
InsertMember(clone,bnd->stripLst.blink);
1122
++flo->floTex->putCnt;
1124
/* see if we should replicate the data through the other bands
1126
if(!rcp->band[0].replicate) break;
1130
} /* end put_strip */
1133
/*------------------------------------------------------------------------
1134
------------ forward input data downstream (re-buffer if Xowner) --------
1135
------------ primarily used to pass compressed data to a photomap --------
1136
------------------------------------------------------------------------*/
1137
static void forward_strip(floDefPtr flo, peTexPtr pet, stripPtr fwd)
1139
if(!pet->peDef->flags.putData) {
1140
/* non-client data -- just pass it along
1143
put_strip(flo,pet,fwd); /* give to downstream receptors */
1145
free_strip(flo,fwd); /* hmm, nobody wanted it */
1147
/* since this is client data we must copy it before passing it along
1149
stripLstPtr lst = &pet->outFlo->output[fwd->format->band];
1150
stripPtr tmp = ListEmpty(lst) ? NULL : lst->flink;
1151
int maxlen = flo->floTex->stripSize, datlen;
1152
int overlap = tmp ? tmp->end - fwd->start + 1 : 0;
1153
int start = fwd->start + overlap;
1154
int size = fwd->length - overlap;
1155
CARD8 *data = &fwd->data[overlap];
1160
if ((tmp = make_strip(flo, fwd->format, start, 0, maxlen, TRUE)) != 0) {
1161
InsertMember(tmp,lst->flink);
1163
free_strip(flo,fwd);
1164
AllocError(flo,pet->peDef, return);
1167
datlen = min(size, tmp->bufSiz - tmp->length);
1168
memcpy((char*)&tmp->data[tmp->length], (char*)data, (int)datlen);
1169
tmp->length += datlen;
1174
if((!size && fwd->final) || tmp->length == tmp->bufSiz) {
1175
RemoveMember(tmp,lst->flink);
1176
start = tmp->start + tmp->length;
1177
tmp->final = final = fwd->final && !size;
1178
tmp->canonic = fwd->canonic;
1180
put_strip(flo,pet,tmp); /* give to downstream receptors */
1182
free_strip(flo,tmp);
1186
free_strip(flo,fwd);
1188
} /* end forward_strip */
1191
/*------------------------------------------------------------------------
1192
----------------------------- Get rid of a strip -------------------------
1193
------------------------------------------------------------------------*/
1194
static stripPtr free_strip(floDefPtr flo, stripPtr strip)
1198
if(strip && !--strip->refCnt) {
1199
/* since this was the last reference we're going to nuke this strip,
1200
* if this was a clone, free the parent and forget where the data was
1203
free_strip(flo, strip->parent);
1205
} else if(strip->data) {
1206
/* if the data buffer belongs to coreX or is uncachable, nuke it */
1209
else if(!flo || !strip->cache) {
1210
strip->data = (CARD8 *) XieFree(strip->data);
1211
BYTES -= strip->bufSiz; /*DEBUG*/
1215
/* strips with standard data buffers are cached at the front
1216
* strips without data buffers go at the back
1219
strip->parent = NULL;
1220
cache = (strip->data
1221
? (lstPtr)&flo->floTex->stripHead
1222
: (lstPtr) flo->floTex->stripHead.blink);
1223
InsertMember(strip,cache);
1230
} /* end free_strip */
1232
/* end module strip.c */