Ejemplo n.º 1
0
/**
 * exaOffscreenFree frees an allocation.
 *
 * @param pScreen current screen
 * @param area offscreen area to free
 *
 * exaOffscreenFree frees an allocation created by exaOffscreenAlloc.  Note that
 * the save callback of the area is not called, and it is up to the driver to
 * do any cleanup necessary as a result.
 *
 * @return pointer to the newly freed area. This behavior should not be relied
 * on.
 */
ExaOffscreenArea *
exaOffscreenFree (ScreenPtr pScreen, ExaOffscreenArea *area)
{
    ExaScreenPriv(pScreen);
    ExaOffscreenArea	*next = area->next;
    ExaOffscreenArea	*prev;

    DBG_OFFSCREEN (("Free 0x%x -> 0x%x (0x%x)\n", area->size,
		    area->base_offset, area->offset));
    ExaOffscreenValidate (pScreen);

    area->state = ExaOffscreenAvail;
    area->save = NULL;
    area->score = 0;
    /*
     * Find previous area
     */
    if (area == pExaScr->info->offScreenAreas)
	prev = NULL;
    else
	for (prev = pExaScr->info->offScreenAreas; prev; prev = prev->next)
	    if (prev->next == area)
		break;

    /* link with next area if free */
    if (next && next->state == ExaOffscreenAvail)
	ExaOffscreenMerge (area);

    /* link with prev area if free */
    if (prev && prev->state == ExaOffscreenAvail)
    {
	area = prev;
	ExaOffscreenMerge (area);
    }

    ExaOffscreenValidate (pScreen);
    DBG_OFFSCREEN(("\tdone freeing\n"));
    return area;
}
Ejemplo n.º 2
0
KdOffscreenArea *
KdOffscreenFree (ScreenPtr pScreen, KdOffscreenArea *area)
{
    KdScreenPriv(pScreen);
    KdOffscreenArea	*next = area->next;
    KdOffscreenArea	*prev;
    
    DBG_OFFSCREEN (("Free 0x%x -> 0x%x\n", area->size, area->offset));
    KdOffscreenValidate (pScreen);

    area->state = KdOffscreenAvail;
    area->save = 0;
    area->offset = area->save_offset;
    area->score = 0;

    /*
     * Find previous area
     */
    if (area == pScreenPriv->off_screen_areas)
	prev = 0;
    else
	for (prev = pScreenPriv->off_screen_areas; prev; prev = prev->next)
	    if (prev->next == area)
		break;
    
    /* link with next area if free */
    if (next && next->state == KdOffscreenAvail)
	KdOffscreenMerge (area);
    
    /* link with prev area if free */
    if (prev && prev->state == KdOffscreenAvail)
    {
	area = prev;
	KdOffscreenMerge (area);
    }

    KdOffscreenValidate (pScreen);
    return area;
}
Ejemplo n.º 3
0
KdOffscreenArea *
KdOffscreenAlloc (ScreenPtr pScreen, int size, int align,
		  Bool locked,
		  KdOffscreenSaveProc save,
		  pointer privData)
{
    KdOffscreenArea *area, *begin, *best;
    KdScreenPriv (pScreen);
    int tmp, real_size = 0, best_score;

    KdOffscreenValidate (pScreen);
    if (!align)
	align = 1;

    if (!size)
    {
	DBG_OFFSCREEN (("Alloc 0x%x -> EMPTY\n", size));
	return NULL;
    }

    /* throw out requests that cannot fit */
    if (size > (pScreenPriv->screen->memory_size - pScreenPriv->screen->off_screen_base))
    {
	DBG_OFFSCREEN (("Alloc 0x%x -> TOBIG\n", size));
	return NULL;
    }
    
    /* Try to find a free space that'll fit. */
    for (area = pScreenPriv->off_screen_areas; area; area = area->next)
    {
	/* skip allocated areas */
	if (area->state != KdOffscreenAvail)
	    continue;

	/* adjust size to match alignment requirement */
	real_size = size;
	tmp = area->offset % align;
	if (tmp)
	    real_size += (align - tmp);
	
	/* does it fit? */
	if (real_size <= area->size)
	    break;
    }
    
    if (!area)
    {
	/* 
	 * Kick out existing users to make space.
	 *
	 * First, locate a region which can hold the desired object.
	 */
	
	/* prev points at the first object to boot */
	best = NULL;
	best_score = MAXINT;
	for (begin = pScreenPriv->off_screen_areas; begin != NULL;
	     begin = begin->next)
	{
	    int avail, score;
	    KdOffscreenArea *scan;

	    if (begin->state == KdOffscreenLocked)
		continue;

	    /* adjust size to match alignment requirement */
	    real_size = size;
	    tmp = begin->offset % align;
	    if (tmp)
		real_size += (align - tmp);
	    
	    avail = 0;
	    score = 0;
	    /* now see if we can make room here, and how "costly" it'll be. */
	    for (scan = begin; scan != NULL; scan = scan->next)
	    {
		if (scan->state == KdOffscreenLocked) {
		    /* Can't make room here, start after this locked area. */
		    begin = scan->next;
		    break;
		}
		/* Score should only be non-zero for KdOffscreenRemovable */
		score += scan->score;
		avail += scan->size;
		if (avail >= real_size)
		    break;
	    }
	    /* Is it the best option we've found so far? */
	    if (avail >= real_size && score < best_score) {
		best = begin;
		best_score = score;
	    }
	}
	area = best;
	if (!area)
	{
	    DBG_OFFSCREEN (("Alloc 0x%x -> NOSPACE\n", size));
	    /* Could not allocate memory */
	    KdOffscreenValidate (pScreen);
	    return NULL;
	}

	/* adjust size to match alignment requirement */
	real_size = size;
	tmp = begin->offset % align;
	if (tmp)
	    real_size += (align - tmp);

	/*
	 * Kick out first area if in use
	 */
	if (area->state != KdOffscreenAvail)
	    area = KdOffscreenKickOut (pScreen, area);
	/*
	 * Now get the system to merge the other needed areas together
	 */
	while (area->size < real_size)
	{
	    assert (area->next && area->next->state == KdOffscreenRemovable);
	    (void) KdOffscreenKickOut (pScreen, area->next);
	}
    }
    
    /* save extra space in new area */
    if (real_size < area->size)
    {
	KdOffscreenArea   *new_area = xalloc (sizeof (KdOffscreenArea));
	if (!new_area)
	    return NULL;
	new_area->offset = area->offset + real_size;
	new_area->size = area->size - real_size;
	new_area->state = KdOffscreenAvail;
	new_area->save = 0;
	new_area->score = 0;
	new_area->next = area->next;
	area->next = new_area;
	area->size = real_size;
    }
    /*
     * Mark this area as in use
     */
    if (locked)
	area->state = KdOffscreenLocked;
    else
	area->state = KdOffscreenRemovable;
    area->privData = privData;
    area->save = save;
    area->score = 0;

    area->save_offset = area->offset;
    {
	int tmp = area->offset % align;
	if (tmp)
	    area->offset += (align - tmp);
    }

    KdOffscreenValidate (pScreen);
    
    DBG_OFFSCREEN (("Alloc 0x%x -> 0x%x\n", size, area->offset));
    return area;
}