[comp.windows.x] Colormaps for StaticColor visuals

mtoy@xman.sgi.COM (Michael Toy -- The S.G.I. XMAN) (11/04/87)

I'm close to the light at the end of the tunnel on this one.

Mission:  Create a colormap filled in with the correct hardware values
on a StaticColor display.  (I actually have a PsedoColor display, but I want
X to use a particluar already set up colormap with nice ramps in it)

PortingLayer doc suggests checking the BeingCreated bit in the ddx 
CreateColormap routine and if it is set, calling AllocColor for
each pixel.

This doesn't work.  AllocColors calss Find<mumble> which just returns if
your visualtype is StaticColor.

What mostly works for ms is filling a xColorItem structure and calling
StoreColors in a loop.  Most things work ok unless I ask for colors up
in the high parts of the colormap, then I get core dumps.

So how about it Xperts?  Am I on the right track?  Anybody else out there
been down this road?  Don't tell me about cfb/sun supprt through the
STATIC_COLOR #define, that stuff seems to be a dinosaurish implementation
of a TrueColor visual.
--
Michael Toy, secret identity: the XMAN at Silicon Graphics
Someday: mtoy@xman.sgi.com		For now: {ames,decwrl,sun}!sgi!mtoy

carver@3d.DEC.COM (The danger on the rocks has surely passed, still I remain tied to the mast) (11/04/87)

  We needed to do the same thing in our server---in fact we needed to
  construct several static colormaps with device dependent color values---
  and the method we use (as your mail discussed) is as follows:

	mid = FakeClientID(0);
	CreateColormap(mid,pScr,pVisTrue24,&pCmap,AllocAll,0); *
	StoreColors(pCmap,256,defs)

  * The last argument to CreateColormap is the client index, we use 0 to
    indicate that the server is the creator.

  So far as we know this works properly in our environments: VAX/ULTRIX and
  VAX/VMS.  You may be having some sort of portability problem in 
  dix/colormap.c.

	--david carver

todd@GRANITE.DEC.COM (Todd Newman) (11/05/87)

This is in reply to Michael Toy's mail.  (It would be nice if the return
address given is one I can actually use instead of one that will work
"Someday.")

I'm having trouble believing what you've said.  You said:

    PortingLayer doc suggests checking the BeingCreated bit in the ddx 
    CreateColormap routine and if it is set, calling AllocColor for
    each pixel.

    This doesn't work.  AllocColors calss Find<mumble> which just returns if
    your visualtype is StaticColor.

It's hard for me to believe that FindColor just returns.  You've actually
run this and had it fail?  I'm puzzled because I double-checked the source
code and can't see why it should.
AllocColor will diddle with its concept of the class so that if the server is
creating the colormap, and the BeingCreated flag is set, the class becomes
Dynamic.

That means that it will ALWAYS call FindColor when you're creating a colormap.

Three points about FindColor:
Firstly, FindColor never checks whether the colormap is static or not.
There simply isn't such a test.

Secondly, all you have to do is AllocColor with *pPix (the 5th argument)
set to 0.  When it calls FindColor, FindColor will start looking at the
0th map entry and keep searching till it finds an empty one.  That is 
going to be the next free one.  Just keep making the same call to AllocColor
and it should return successive pixels into which you load your ramping
color values.

Finally, if you think about it right, you'll see that that's how the
qvCreateColormap code works.  The monochrome colormap is static.  And I
call it twice and get back two different pixels.

I know it seems a lot to ask, but please trace through the FindColor
and see why it's giving up.  I just can't believe it's because the
class is static.
	/tdn

paulsh@shark.tek.COM (11/10/87)

> I'm close to the light at the end of the tunnel on this one.
> 
> Mission:  Create a colormap filled in with the correct hardware values
> on a StaticColor display.  (I actually have a PsedoColor display, but I want
> X to use a particluar already set up colormap with nice ramps in it)
> 
> PortingLayer doc suggests checking the BeingCreated bit in the ddx 
> CreateColormap routine and if it is set, calling AllocColor for
> each pixel.
> 
> This doesn't work.  AllocColors calss Find<mumble> which just returns if
> your visualtype is StaticColor.
> 
> What mostly works for ms is filling a xColorItem structure and calling
> StoreColors in a loop.  Most things work ok unless I ask for colors up
> in the high parts of the colormap, then I get core dumps.
> 
> So how about it Xperts?  Am I on the right track?  Anybody else out there
> been down this road?  Don't tell me about cfb/sun supprt through the
> STATIC_COLOR #define, that stuff seems to be a dinosaurish implementation
> of a TrueColor visual.
> --
> Michael Toy, secret identity: the XMAN at Silicon Graphics
> Someday: mtoy@xman.sgi.com        For now: {ames,decwrl,sun}!sgi!mtoy

I have done exactly what Michael is attempting.
I have successfully used AllocColor() from within my
ddx pScreen->CreateColormap routine.

If you will be implementing server colormap routines,
tuck this information away for later use.

I'll give only accurate answers and carefully state my assumptions.
(No wild guesses this time.)

First from the Mission statement I am assuming that Michael is creating a 
colormap using a visual of class StaticColor.  The goal is
to then:
     1. Create the StaticColor colormap by calling dix CreateColormap()
     2. Initialize the color entries using AllocColor() from within
        ddx pScreen->CreateColormap that is called by dix CreateColormap().
        StoreColors() could also be used for server owned maps, see below.
     3. Install the colormap (at some point).

First to clarify some confusion.

> PortingLayer doc suggests checking the BeingCreated bit in the ddx 
> CreateColormap routine and if it is set, calling AllocColor for
> each pixel.
> 
> This doesn't work.  AllocColors calss Find<mumble> which just returns if
> your visualtype is StaticColor.

No not quite.  Let's look at the documentation closely.
"Definition of the Porting Layer for the X V11 Sample Server".
page 26
          5.2.7.2  Initializing a Colormap
          
          When a client requests a new colormap and  when  the  server
          creates  the  default colormap, the procedure CreateColormap
          in the DIX  layer  is  invoked.   That  procedure  allocates
          memory  for  the  colormap  and  related storage such as the
*         lists of which client owns which pixels. It then sets a bit,
*         BeingCreated,  in  the  flags  field  of the ColormapRec and
*         calls the DDX layer's CreateColormap routine.  This is  your
*         chance  to  initialize  the  colormap.   If  the colormap is
          static, which you can tell by looking at  the  class  field,
          you  will  want  to  fill  in  each  color cell to match the
*         hardwares notion of the color for that pixel.  If the color-
*         map  is  the  default  for the screen, which you can tell by
*         looking at the flags field, you will want to allocate Black-
          Pixel  and  WhitePixel  to  match  the values you set in the
          pScreen structure.  (Of course, you picked those  values  to
          begin with.)
          
          There are two ways to fill in the  colormap.   The  simplest
          way is to use AllocColor.
          ...
          ...
          If for some reason AllocColor doesn't do what you want,  you
          can  do  your own bookkeeping and call StoreColors yourself.
          This is much more difficult and shouldn't be  necessary  for
          most devices.
          

Therefore the above documentation does NOT suggest checking the
BeingCreated bit and then calling AllocColor() if it is set.
It simply says to check the class and if it is static, then
call AllocColor().  The BeingCreated bit is not intended to be
checked by pScreen->Colormap since it will always be set prior to
calling this routine.  The role of the BeingCreated bit is to inform
dix routines, AllocColor() and FindColor(), that they have been 
called specifically from pScreen->CreateColormap and that they 
should do something special in that case, like store rgb values
in static colormap entries.

The bit the above documentation is referring to check is the IsDefault
bit in the flags element.  This allows pScreen->Colormap to do anything
special to the screen default colormap, like allocate its whitePixel and
blackPixel.  (I actually recommend doing this later and forcing those
values to agree with the colormap and not vise versa, but I'll save that
discussion for another time.  No guesses, just facts right now.)

One problem right now is that the IsDefault bit is never set.
It should, I believe, be set in dix/colormap.c CreateColormap() to
agree with the above documentation.  I am submitting a bug report which
suggests the following addition to CreateColormap().

    AddResource(mid, RT_COLORMAP, pmap, FreeColormap, RC_CORE);
    pmap->mid = mid;
    pmap->flags = 0;     /* start out with all flags clear */
+   if( mid == pScreen->defColormap )
+   { 
+       pmap->flags |= IsDefault; 
+   }
    pmap->pScreen = pScreen;
    pmap->pVisual = pVisual;
    pmap->class = class;

If this becomes a blessed fix, then you will be able to check for
    if( pmap->flags & IsDefault)
in your ddx pScreen->CreateColormap routine.

A simple workaround is to let pScreen->CreateColormap check
with the test:
    if( pmap->mid == pmap->pScreen->defColormap)
You would only be concerned about this if you want to do something special
to the default colormap during its creation.

Anyway, back to the mission at hand,

> This doesn't work.  AllocColors calss Find<mumble> which just returns if
> your visualtype is StaticColor.

Now it is time to look at the code closely.  If you are calling
AllocColor() from within pScreen->CreateColormap this WILL work PROVIDED
you called CreateColormap with alloc=AllocNone.

As soon as AllocColor() is entered, if the BeingCreated bit is set then
the class is changed to a dynamic one.  Thus your StaticColor class was
changed to PseudoColor class.  What probably tripped FindColor() up was
the possibility (this is a good guess) that you had called

CreateColormap(  ,  ,  ,  ,AllocAll,  )

This is what is done in cfb code for static colormaps.  Notice that
cfb code uses pScreen->CreateColormap = cfbInitialize332Colormap
which does not call AllocColor() (they do it the hard way).
If this was the case, then FindColor would return without Allocating the
color entry values due to the fact that pent->refcnt == AllocPrivate if
alloc==AllocAll.

Here is a coding sequence for static colormaps if you want to use 
AllocNone and AllocColor().
The code may be spread out (called from different routines) 
but the order is important.


    pScreen->CreateColormap = <your ddx>CreateColormap ;
    ...

    mid = (Colormap) FakeClientID(0);
    ...
    if( <this is your default colormap> )
    {
        pScreen->defColormap = mid;
    }
    ...
     CreateColormap(mid,pScreen,pVisStatic,&pColormap,AllocNone,0);
    ...
    <Inside pScreen->CreateColormap(pColormap)>
        for( i=0; i<pColormap->pVisual->ColormapEntries; i++)
        {
            pixel = i;
            ...
            AllocColor(pColormap,pred,pgreen,pblue,&pixel,0);
        }

    ...
    pScreen->InstallColormap(pColormap);


----

If you used the argument AllocAll instead of AllocNone then you have to 
initialize the color entry values using StoreColors() and not AllocColor().
This scenario was given by David Carver in a previous posting.
Note that, as David footnotes, only
the server can create a static colormap using AllocAll.  Thus if you want
to initialize static colormaps being created by clients via their Xlib
call to XCreateColormap, you need to use the scenario above.
This is because StoreColors will not store the entries since the
refcnt would be refcnt==0 in the client case.
Also note that you loose some of the bookkeeping 
advantages when you don't use AllocColor(),
but I don't think it matters since the colormap is static.
Unlike AllocColor(), the call to StoreColors() will work just as nicely
outside pScreen->CreateColormap where the BeingCreated bit is not set.
Thus David's call to StoreColors() can be done inside or outside 
pScreen->CreateColormap().  I however encourage the use of AllocColor()
since the same server code can initialize both server and client static
colormaps.


>>    mid = FakeClientID(0);
>>    CreateColormap(mid,pScr,pVisTrue24,&pCmap,AllocAll,0); *
>>    StoreColors(pCmap,256,defs)
>>
>>  * The last argument to CreateColormap is the client index, we use 0 to
>>    indicate that the server is the creator.
>>
>>    -- david carver

The final glitch posted was:

> What mostly works for ms is filling a xColorItem structure and calling
> StoreColors in a loop.  Most things work ok unless I ask for colors up
> in the high parts of the colormap, then I get core dumps.

I am not sure what is meant by "ask for colors".  Core dumps when 
StoreColors is called or later when large value pixels are used?
If it is later, then the following explanation may help.

Remember if you use StoreColors() and you pass it color defs with pixel
values that are too big, pix > pVisual->ColormapEntries , 
then it will only correctly store to hardware using your 
ddx pScreen->StoreColors routine the acceptable pixel entries and will 
throw out the others and return a value of BadValue.

Thus check the return value of StoreColors() and check the visual you are 
using to be sure that the value of pVisual->ColormapEntries is what you expect
(want it to be).  If it is too small, that may be the problem.

Hope this helps.


Paul Shearer
M.S. 61-277
Tektronix, Inc.
P.O. Box 1000
Wilsonville, OR
     97070-1000

W (503) 685-2137
H (503) 224-3536
tektronix!shark!paulsh