[comp.windows.news] retained canvases - application writers please read

msc@ramoth.SGI.COM (Mark Callow) (01/11/89)

Almost every NeWS application that I have seen that uses retained canvases
fails to respond correctly to /Damaged events.  The most common problem is
that the program paints into an unmapped retained canvas then maps the
canvas.  The program expects mapping to cause its bits to be transferred
to the screen from the retained buffer.

However to quote the NeWS manual Section 2.2, Page 14

	"All programs have to cope with damage and must be able to
	reconstruct the damaged part" ... "retained canvases are
	purely a performance enhancement".

and from Section 11.3, Page 120

	"For color displays the cost of retaining canvases is often
	prohibitive".

And to quote from "The NeWS Book" (not yet published)

	"Retained canvases are purely a performance enhancement.  A
	server may choose to stop supporting retained canvases at any
	time, such as when running out of memory.  Programs must
	always be ready to cope with damage."

The Silicon Graphics 4Sight (NeWS) server, when running in RGB mode
(the default mode on most of our systems) chooses not to support
retained canvases.  This is because of the memory cost of 24-bit deep
pixels especially given our fast rendering speed.

Therefore there may not be a retained buffer so the program had better be
able to respond to damage when it maps a "retained" canvas.  Those that
don't will not work on a large class of machines running NeWS.

Application writers please take note.
--
	-Mark

mwp@murtoa (Michael Paddon) (01/11/89)

From article <24631@sgi.SGI.COM>, by msc@ramoth.SGI.COM (Mark Callow):
> 
> However to quote the NeWS manual Section 2.2, Page 14
> 
> 	"All programs have to cope with damage and must be able to
> 	reconstruct the damaged part" ... "retained canvases are
> 	purely a performance enhancement".

Sometimes it is extremely useful to have a canvas that you
*know* is retained. This, in fact, can be achieved under NeWS.

To quote the NeWS 1.1 "READ THIS FIRST" document, Page 8

	"One exception to this rule (that the NeWS server may ignore
	retained hints) is that the NeWS server must honor the
	/Retained setting of parent-less canvases"

I presume that a parent-less canvas is one with a null value in
its /Parent entry, although this is not explicitly stated. Note
that any canvas may be made parent-less at any time.

The major drawback of using parent-less canvases is that the
functions of the window hieracrchy are not available (ie. child
canvases moving with parent; child canvases clipped by parent).
It's not at all clear why Sun defined this one special case for
retained canvases. It would be much more useful to make the
/Retained entry tri-valued (yes, no and maybe) so that if you
*really* want offscreen bitmaps you don't have to write bizarre
code.

========================================================
| Michael Paddon (mwp@munnari.oz.au)                   |
| Department of Computer Science, Melbourne University |
========================================================

andy@ecrcvax.UUCP (Andrew Dwelly) (01/12/89)

In article <24631@sgi.SGI.COM> msc@ramoth.SGI.COM (Mark Callow) writes:

>Almost every NeWS application that I have seen that uses retained canvases
>fails to respond correctly to /Damaged events.  The most common problem is
>that the program paints into an unmapped retained canvas then maps the
>canvas.  The program expects mapping to cause its bits to be transferred
>to the screen from the retained buffer.
>
> [Quotes from the 1.1 manual supporting, deleted]

Mark is absolutely correct, but as a writer of (research) applications I 
feel that this is one of the aspects of NeWS that I like the least. Making
the application keep track of where everything is, in order to be able
to redraw it, obviously makes life considerably more complex. Since in
my case, the creations are merely prototypes, and keeping them understandable
is a requirement, I (Oh Heresy!!) usually just ignore this and make everything
retained.

-- I did once try an experiment though. I wrote a program (unfortunately
unavailable now) which associated an array with a canvas. I had several
routines to draw items on the canvas, and each time they were called, they
carefully stored the details in the array. A separate process used this
array to recreate damaged portions of the canvas. The most important routine
was /Clear which cleared the canvas, and the array, otherwise redrawing
an picture that had been changed a lot, produced a sort of complete history
of the canvas.

Eventually I gave up with this approach. NeWS 1.1 appears to have a number of
bugs concerning arrays of length > 255 elements, causing strange effects
with some of the larger drawings. Secondly I found that the redrawn parts
did not match the existing parts quite accurately, often the difference was
only a pixel or so, but the effect was noticable and disturbing.

The final problem was that the whole process was rather slow. In order to
mend some damage, I set the damage path, and re-executed the entire history.
NeWS seems to just blindly execute every command, without even checking
whether a particular command is trivially outside of the clip area. Thus
redrawing a small portion of a complex drawing was as slow as redoing the
entire canvas, - real slooow.

A good idea, defeated by bugs, and my own lack of experience with the system.
There may be something useful here for future versions though. Possibly this
could even be introduced as a new sort of canvas (virtually-retained ?) at
the implementation level. Rather than storing the results of PS execution
on a bitmap, it just stores the commands for re-execution later. Lack of
referential transparency in the PS language, probably restricts the number
of commands that can successfully be used with such a canvas.

Comments ?

Andrew Dwelly                 
E.C.R.C.                                       UUCP: mcvax!unido!ecrcvax!andy
ArabellaStrasse 17 			       or    pyramid!ecrcvax!andy
D-8000 Muenchen 81, West Germany 	       UUCP Domain:  andy@ecrcvax.UUCP

[Bump, Crash ......
 Listen; who swears ?
 Christopher Robin has fallen down stairs.]

cjc@ulysses.homer.nj.att.com (Chris Calabrese[mav]) (01/12/89)

In article <1154@murtoa.cs.mu.oz.au>, mwp@murtoa (Michael Paddon) writes:
| [...]
| To quote the NeWS 1.1 "READ THIS FIRST" document, Page 8
| 
| 	"One exception to this rule (that the NeWS server may ignore
| 	retained hints) is that the NeWS server must honor the
| 	/Retained setting of parent-less canvases"
| 
| I presume that a parent-less canvas is one with a null value in
| its /Parent entry, although this is not explicitly stated. Note
| that any canvas may be made parent-less at any time.
| [...]

I just tried changing `framebuffer' to a `null' in one
of my program segments (to draw a window), and got:

Process: 0x81B630   Error: typecheck
Stack: ... /FrameCanvas null
Executing: `newcanvas'
At: {/FrameCanvas ParentCanvas *`newcanvas' 'def' /beye
/beye_m FrameCanvas setstandardcursor FrameCanvas /SaveBehind 'true' 'put'}
In: {*CreateFrameCanvas CreateClientCanvas CreateIconCanvas
CreateFrameControls CreateFrameInterests CreateFrameMenu
CreateIconControls CreateIconInterests CreateIconMenu ShapeIconCanvas}

sjs@spectral.ctt.bellcore.com (Stan Switzer) (01/13/89)

In article <11090@ulysses.homer.nj.att.com> cjc@ulysses.homer.nj.att.com (Chris Calabrese[mav]) writes:
> In article <1154@murtoa.cs.mu.oz.au>, mwp@murtoa (Michael Paddon) writes:
> | [...]
> | To quote the NeWS 1.1 "READ THIS FIRST" document, Page 8
> | 
> | 	"One exception to this rule (that the NeWS server may ignore
> | 	retained hints) is that the NeWS server must honor the
> | 	/Retained setting of parent-less canvases"
> | 
> | I presume that a parent-less canvas is one with a null value in
> | its /Parent entry, although this is not explicitly stated. Note
> | that any canvas may be made parent-less at any time.
> | [...]
> 
> I just tried changing `framebuffer' to a `null' in one
> of my program segments (to draw a window), and got:
> [an error]

Well, there ARE parentless canvases, but as Chris discovered and as I
have just confirmed, you can't create them with "newcanvas" or even
mutate a parented canvas into one.  The only retained, parentless
canvases that I can find are the result of "readcanvas."
Interestingly, these canvases need never actually exist as bitmaps
since they can always be recreated from the original file (my guess is
that this is indeed what happens on SGI 4Sight and possibly even in
the Sun version).

Unfortunately, this means is that there isn't any good way of doing
double-buffered displaying (as in my wbounce demo).  I really don't
need a full 8 to 24 bit deep backing store for this but I do need some
off-screen drawing space.

What I would like to be able to do is to create a retained 1 plane
deep canvas that I can subsequently use for imagemaskcanvas
operations.  Although it seems like there must be a way to do this, I
haveso far been unable to find it.

Alternatively, having some canvas attribute such as /Freeze that could
be toggled to batch complex operations and then display the net result
when unfrozen would be very useful.  A very common scenario for a
graphical tool is to erase some changed area and redraw it
back-to-front.  It is exceedingly annoying to have to watch this
tedious process--especially if it destroys an illusion of continuous
change.

Perhaps someone knows of a supported approach to do double buffering?

Stan Switzer  sjs@ctt.bellcore.com  "If you can't be just, be arbitrary."

sjs@spectral.ctt.bellcore.com (Stan Switzer) (01/13/89)

In article <13402@bellcore.bellcore.com> I write:
> Well, there ARE parentless canvases, but as Chris discovered and as I
> have just confirmed, you can't create them with "newcanvas" or even
> mutate a parented canvas into one.  The only retained, parentless
> canvases that I can find are the result of "readcanvas."

I have looked into this a bit further and it seems that I overlooked
"buildimage" which seems to be able to build a non-parented, retained
canvas of just about any size and depth.

You seem to be able to reparent this canvas and map it (it worked for
me).  Interestingly, though, trying to set the parent back to null
(canvas /Parent null put) both works and doesn't.  It does reset the
parent to null but gives you a "typecheck" error after having done so.
I guess you could use "errored" to get around it if it mattered.

I guess I answered my own question about how I can create a 1 pixel
deep canvas to use with imagemaskcanvas that works regardless of
whether your workstation is color or not.

Now back to the original question.  Is this the exception to the
"retained is only an optimization" rule?

Stan Switzer  sjs@ctt.bellcore.com  "What's this big red button do?"

msc@ramoth.SGI.COM (Mark Callow) (01/13/89)

In article <13402@bellcore.bellcore.com>, sjs@spectral.ctt.bellcore.com (Stan Switzer) writes:
> Well, there ARE parentless canvases, but as Chris discovered and as I
> have just confirmed, you can't create them with "newcanvas" or even
> mutate a parented canvas into one.  The only retained, parentless
> canvases that I can find are the result of "readcanvas."
> Interestingly, these canvases need never actually exist as bitmaps
> since they can always be recreated from the original file (my guess is
> that this is indeed what happens on SGI 4Sight and possibly even in
> the Sun version).
> 
I think you've hit on the reason for the exception noted in the
"READ ME FIRST" document.  I can breath a sigh of relief.  We have it
right.  On both Sun and SGI implementations readcanvas reads the file
into an offscreen pixrect structure.  It then plugs that pixrect into
a canvas data structure as the "retained part" of the canvas.  This
has to be imaged using imagecanvas.  You can't map this kind of canvas.

> What I would like to be able to do is to create a retained 1 plane
> deep canvas that I can subsequently use for imagemaskcanvas
> operations.  Although it seems like there must be a way to do this, I
> haveso far been unable to find it.
> 
I agree that some way to have Retained canvases with different depths from
the display would be nice.  The spin demo is a good example of where you
could use this.  Since the server has code to support 1-bit and 8-bit deep
canvases adding this feature wouldn't be hard.

> Perhaps someone knows of a supported approach to do double buffering?
We'd love an approach to double buffering since we have the hardware to
support it and would be able to use that.  Servers without double buffering
hardware could use the /Retained canvas code to simulate it.

If anyone has any proposals for a double buffering spec, let me know.

--
	-Mark