Exemplo n.º 1
0
/**
 * @brief Finds space for a map of the given size in the atlas.
 * @details This methods searches for a space to store a region of the given
 *   size in the atlas. tile_width and tile_height should be already in tile
 *   space. They can be converted using ShadowAtlas::get_required_tiles.
 *
 *   If no region is found, or an invalid size is passed, an integer vector with
 *   all components set to -1 is returned.
 *
 *    If a region is found, an integer vector with the given layout is returned:
 *     x: x- Start of the region
 *     y: y- Start of the region
 *     z: width of the region
 *     w: height of the region
 *
 *   The layout is in tile space, and can get converted to uv space using
 *   ShadowAtlas::region_to_uv.
 *
 * @param tile_width Width of the region in tile space
 * @param tile_height Height of the region in tile space
 *
 * @return Region, see description, or -1 when no region is found.
 */
LVecBase4i ShadowAtlas::find_and_reserve_region(size_t tile_width, size_t tile_height) {

    // Check for empty region
    if (tile_width < 1 || tile_height < 1) {
        shadowatlas_cat.error() << "Called find_and_reserve_region with null-region!" << endl;
        return LVecBase4i(-1);
    }

    // Check for region bigger than the shadow atlas
    if (tile_width > _num_tiles || tile_height > _num_tiles) {
        shadowatlas_cat.error() << "Requested region exceeds shadow atlas size!" << endl;
        return LVecBase4i(-1);
    }

    // Iterate over every possible region and check if its still free
    for (size_t x = 0; x <= _num_tiles - tile_width; ++x) {
        for (size_t y = 0; y <= _num_tiles - tile_height; ++y) {
            if (region_is_free(x, y, tile_width, tile_height)) {
                // Found free region, now reserve it
                reserve_region(x, y, tile_width, tile_height);
                return LVecBase4i(x, y, tile_width, tile_height);
            }
        }
    }

    // When we reached this part, we couldn't find a free region, so the atlas
    // seems to be full.
    shadowatlas_cat.error() << "Failed to find a free region of size " << tile_width
                            << " x " << tile_height << "!"  << endl;
    return LVecBase4i(-1);
}
Exemplo n.º 2
0
/*
 * This function is called from mem_init() to reserve the pages needed for
 * ST-RAM management.
 */
void __init atari_stram_reserve_pages(unsigned long start_mem)
{
#ifdef CONFIG_STRAM_SWAP
	/* if max_swap_size is negative (i.e. no stram_swap= option given),
	 * determine at run time whether to use ST-RAM swapping */
	if (max_swap_size < 0)
		/* Use swapping if ST-RAM doesn't make up more than MAX_STRAM_FRACTION
		 * of total memory. In that case, the max. size is set to 16 MB,
		 * because ST-RAM can never be bigger than that.
		 * Also, never use swapping on a Hades, there's no separate ST-RAM in
		 * that machine. */
		max_swap_size =
			(!MACH_IS_HADES &&
			 (N_PAGES(stram_end-stram_start)*MAX_STRAM_FRACTION_DENOM <=
			  max_mapnr*MAX_STRAM_FRACTION_NOM)) ? 16*1024*1024 : 0;
	DPRINTK( "atari_stram_reserve_pages: max_swap_size = %d\n", max_swap_size );
#endif

	/* always reserve first page of ST-RAM, the first 2 kB are
	 * supervisor-only! */
	set_bit( PG_reserved, &mem_map[MAP_NR(stram_start)].flags );

#ifdef CONFIG_STRAM_SWAP
	if (!max_swap_size) {
	  fallback:
#endif
		DPRINTK( "atari_stram_reserve_pages: swapping disabled\n" );
		if (!kernel_in_stram) {
			/* Reserve all pages that have been marked by pre-mem_init
			 * stram_alloc() (e.g. for the screen memory). */
			reserve_region( rsvd_stram_beg, rsvd_stram_end );
			DPRINTK( "atari_stram_reserve_pages: reseverved %08lx-%08lx\n",
					 rsvd_stram_beg, rsvd_stram_end );
		}
		/* else (kernel in ST-RAM): nothing to do, ST-RAM buffers are
		 * kernel data */
#ifdef CONFIG_STRAM_SWAP
	}
	else {
		unsigned long swap_data;
		BLOCK *p;

		/* determine first page to use as swap:
		 * if the kernel is in TT-RAM, this is the first page of (usable)
		 * ST-RAM; else if there were already some allocations (probable...),
		 * use the lowest address of these (the list is sorted by address!);
		 * otherwise just use the end of kernel data (= start_mem) */
		swap_start = !kernel_in_stram ? stram_start + PAGE_SIZE :
					 alloc_list ? alloc_list->start :
					 start_mem;
		/* decrement by one page, rest of kernel assumes that first swap page
		 * is always reserved and maybe doesn't handle SWP_ENTRY == 0
		 * correctly */
		swap_start -= PAGE_SIZE;
		swap_end = stram_end;
		if (swap_end-swap_start > max_swap_size)
			swap_end =  swap_start + max_swap_size;
		DPRINTK( "atari_stram_reserve_pages: swapping enabled; "
				 "swap=%08lx-%08lx\n", swap_start, swap_end );
		
		/* reserve some amount of memory for maintainance of
		 * swapping itself: 1 page for the lockmap, and one page
		 * for each 2048 (PAGE_SIZE/2) swap pages. (2 bytes for
		 * each page) */
		swap_data = start_mem;
		start_mem += (((SWAP_NR(swap_end) + PAGE_SIZE/2 - 1)
			       >> (PAGE_SHIFT-1)) + 1) << PAGE_SHIFT;
		/* correct swap_start if necessary */
		if (swap_start == swap_data)
			swap_start = start_mem;
		
		if (!swap_init( start_mem, swap_data )) {
			printk( KERN_ERR "ST-RAM swap space initialization failed\n" );
			max_swap_size = 0;
			goto fallback;
		}
		/* reserve region for swapping meta-data */
		reserve_region( swap_data, start_mem );
		/* reserve swapping area itself */
		reserve_region( swap_start+PAGE_SIZE, swap_end );

		/* Formerly static areas have been included in the swap area. */
		for( p = alloc_list; p; p = p->next ) {
			if (p->flags & BLOCK_STATIC)
				p->flags = (p->flags & ~BLOCK_STATIC) | BLOCK_INSWAP;
		}

		/*
		 * If the whole ST-RAM is used for swapping, there are no allocatable
		 * dma pages left. But unfortunately, some shared parts of the kernel
		 * (particularily the SCSI mid-level) call __get_dma_pages()
		 * unconditionally :-( These calls then fail, and scsi.c even doesn't
		 * check for NULL return values and just crashes. The quick fix for
		 * this (instead of doing much clean up work in the SCSI code) is to
		 * pretend all pages are DMA-able by setting mach_max_dma_address to
		 * ULONG_MAX. This doesn't change any functionality so far, since
		 * get_dma_pages() shouldn't be used on Atari anyway anymore (better
		 * use atari_stram_alloc()), and the Atari SCSI drivers don't need DMA
		 * memory. But unfortunately there's now no kind of warning (even not
		 * a NULL return value) if you use get_dma_pages() nevertheless :-(
		 * You just will get non-DMA-able memory...
		 */
		mach_max_dma_address = 0xffffffff;

		/*
		 * Ok, num_physpages needs not be really exact, but it's better to
		 * subtract the pages set aside for swapping.
		 */
		num_physpages -= SWAP_NR(swap_end)-1;
	}
#endif
	
	mem_init_done = 1;
}