[comp.windows.x] More questions about phoney cursor behavior -- apollo this time

kek@DINORAH.WUSTL.EDU (04/05/89)

(Bob Scheifler replied to RUSTY)
>The Sun ddx simply allocates read-only entries out of the default colormap
>(and I don't think it ever frees them).  Yanking an arbitrary number of colors
>away from the user is unfriendly.  Always allocating out of the default map
>is incorrect for windows that use other colormaps.  There is no guarantee that
>the allocation will succeed (the server is technically permitted to fail in
>this operation, but it isn't very desirable to do so).

Config:  Apollo DM 3000, XR3 fixes 1-8, std make World using TCP only.

We have noticed many time how frail the cursor is on sample server for
apollo.  The X looses its white outline immediately and occasionally
picks up what looks like fuzz after some unknown number of operations.
Even more aggravating is that the cursor does some kind of XORing of
the pixels over which it passes.  This is most obviously seen if we
mouse over to the colorchart client which is a 16x16 grid of all of
the (256) pixel values to give visual confirmation to the way we think
the colormap is being used.  Here, it is seen that the X cursor always
takes on the odd value which is equal to or one greater than the
pixels it is overwriting.  The effect is pretty spectacular when it
appears that the cursor passes _over_ some structures but _under_
others depending whether numeric value of that color is even or odd
(today).  Real frustration comes when you try to move the cursor in a
region which is large compared to the cursor and whose pixel value is
odd.  Here the cursor has no contrast (without its outline) and so, is
not seen. It really makes pointing difficult.

has anyone else seen/fixed this?  

BTW The beta server from Apollo does _not_ exhibit this difficulty but
we haven't switched over to that until we have ironed out window
manager issues (dm vs uwm).

bowbeer@apollo.COM (Joe Bowbeer) (04/15/89)

Ken,
This is a copy of the bug report I'm sending to xbugs.
The patch and code included should solve your problems.
I'm giving this wide distribution because I think it's
a particularly irritating problem and affects a lot of
folks.

VERSION:
	X11 release 3

CLIENT MACHINE:
	Apollo

CLIENT OPERATING SYSTEM:
	sr10.1 (and to a lesser extent on sr9.7)

DISPLAY:
	all color displays

SYNOPSIS:
	intermittent problems drawing into pixmaps

DESCRIPTION:
        Sometimes pixmaps are rendered currectly. This visual effects
        are incorrect cursor patterns, incorrect tiles, etc.

FIX:
        There are actually two problems here having to do with the
        the pixmap implementation.

        One problem is that the current bitmap cache (LastGPRBitmap) is not
        updated after calling gpr_$deallocate_bitmap. If the current bitmap
        is the one being deallocated and then another bitmap is created and
        used, its id will most likely be identical to the old bitmap, but
        because of the cache alias the gpr_$set_bitmap call will be elided.

        This problem is fixed by updating the bitmap cache after calling
        gpr_$deallocate_bitmap. See server/ddx/apollo/apclr_curs.c patch below.

        The second problem is caused by a subtle bug in sr10.1 gprlib. While
        a patch is available this month (call 1-800-2APOLLO), the rewritten
        pixmap routines (below) avoid this bug and are also faster and more
        space efficient to boot. Note that the new apcDestroyPixmap routine
        also contains the deallocate fix.

--------------------------------------------------------------------------------

[ Patch for server/ddx/apollo/apclr_curs.c ]

$ diff -c -b apclr_curs.c.orig apclr_curs.c
*** apclr_curs.c.orig	Wed Jan 18 17:20:31 1989
--- apclr_curs.c	Thu Apr 13 23:52:32 1989
***************
*** 261,266 ****
--- 261,268 ----
      return (TRUE);
  }
  
+ extern gpr_$bitmap_desc_t LastGPRBitmap;        /* peek inside apc_$set_bitmap */
+ 
  /*
   * apClrUnrealizeCursor -- DDX interface (screen)
   *      Given a cursor record and the cursor-private record for a
***************
*** 275,280 ****
--- 277,284 ----
      status_$t           st;
  
      gpr_$deallocate_bitmap( pPrivC->pRealizedData, st );
+     if ((gpr_$bitmap_desc_t)pPrivC->pRealizedData == LastGPRBitmap)
+         gpr_$inq_bitmap( LastGPRBitmap, st );           /* update cache */
  
      return (TRUE);
  }

--------------------------------------------------------------------------------

[ Rewritten server/ddx/apollo/apc/apcpixmap.c ]

/******************************************************************
Copyright 1989 by Apollo Computer Inc., Chelmsford, Massachusetts.
     
                        All Rights Reserved

Permission to use, duplicate, change, and distribute this software and
its documentation for any purpose and without fee is granted, provided
that the above copyright notice appear in such copy and that this
copyright notice appear in all supporting documentation, and that the
names of Apollo Computer Inc. or MIT not be used in advertising or publicity
pertaining to distribution of the software without written prior permission.
******************************************************************/

#include "apc.h"
#include "Xmd.h"
#include "servermd.h"
#include "pixmapstr.h"

PixmapPtr
apcCreatePixmap (pScreen, width, height, depth, format)
    ScreenPtr	pScreen;
    int		width;
    int		height;
    int		depth;
    int		format;
{
    apDisplayDataPtr            pDisp = &apDisplayData[pScreen->myNum];
    PixmapPtr                   pPixmap;
    apcPrivPMPtr                pPriv;
    unsigned int                linebytes, planebytes, totalbytes;
    gpr_$offset_t               size;
    gpr_$bmf_group_header_t     group_header;
    gpr_$bitmap_desc_t          bitmap;
    status_$t                   status;

    if ( !(pPixmap = (PixmapPtr)Xalloc(sizeof(PixmapRec))) )
        return (PixmapPtr)NULL;
    pPixmap->drawable.type = DRAWABLE_PIXMAP;
    pPixmap->drawable.pScreen = pScreen;
    pPixmap->drawable.depth = depth;
    pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
    pPixmap->width = width;
    pPixmap->height = height;
    pPixmap->devKind = PixmapBytePad(width, depth);
    pPixmap->refcnt = 1;

    if ( !(pPriv = (apcPrivPMPtr)Xalloc(sizeof(apcPrivPM)))) {
	Xfree(pPixmap);
	return (PixmapPtr)NULL;
        }
    pPixmap->devPrivate = (pointer)pPriv;

/*
 * We wish to allocate the pixmap memory ourselves with Xalloc instead of letting
 * GPR do it.  We do not need GPR to zero the pixmap, nor to allocate the pixmap in
 * memory backed by separate filesystem objects ("blocks" of GPR bitmaps).  (This
 * is only to support frame mode, and makes allocation more expensive in time and
 * space.)  We also suspect GPR's complex 2-D allocator results in severe
 * fragmentation of the collection of these objects under some X usage patterns.
 *
 * Here we compute the group header information needed to call gpr_$make_bitmap_from_array,
 * and actually allocate the memory with Xalloc.  We create a planewise GPR bitmap.
 * We round bytes_per_line up to a multiple of 4; bytes_per_sect is just bytes_per_line
 * times height, in order to lay out the planes with no extra intervening space
 * (some of the spans code depends on this).
 */
    linebytes = ((width + 0x1F) & (~0x1F)) >> 3;
    planebytes = linebytes * height;
    totalbytes = planebytes * depth;
    if ( !(pPriv->bitmap_ptr = (int *)Xalloc(totalbytes)) ) {
        Xfree(pPriv);
        Xfree(pPixmap);
        return (PixmapPtr)NULL;
        }
    bzero((char *)pPriv->bitmap_ptr, totalbytes);

    size.x_size = width;
    size.y_size = height;
    group_header.n_sects = depth;
    group_header.pixel_size = 1;
    group_header.allocated_size = 1;
    group_header.bytes_per_line = linebytes;
    group_header.bytes_per_sect = planebytes;
    group_header.storage_offset = (char *)pPriv->bitmap_ptr;
    gpr_$make_bitmap_from_array(size, pDisp->attribute_block, 1,
                                group_header, bitmap, status);

    pPriv->bitmap_desc = bitmap;
    pPriv->width = linebytes >> 1;
    pPriv->size = size;
          
    return pPixmap;
}

extern gpr_$bitmap_desc_t LastGPRBitmap;        /* peek inside apc_$set_bitmap */

Bool
apcDestroyPixmap(pPixmap)
    PixmapPtr pPixmap;
{
    status_$t status;
    gpr_$bitmap_desc_t  bitmap;
    apcPrivPMPtr        pPriv;

/* BOGOSITY ALERT */
    if ((unsigned)pPixmap < 42)
	return TRUE;

    if(--pPixmap->refcnt)
	return TRUE;
    
    bitmap = ((apcPrivPMPtr)(pPixmap->devPrivate))->bitmap_desc;
    gpr_$deallocate_bitmap(bitmap, status);
    if (bitmap == LastGPRBitmap)
        gpr_$inq_bitmap(LastGPRBitmap, status);         /* update cache */

    pPriv = (apcPrivPMPtr)pPixmap->devPrivate;
    Xfree(pPriv->bitmap_ptr);
    Xfree(pPriv);
    Xfree(pPixmap);
    return TRUE;
}

--------------------------------------------------------------------------------