Blame src/blitter/ntapi_blt_alloc.c

dd89bb
/********************************************************/
dd89bb
/*  ntapi: Native API core library                      */
dde53a
/*  Copyright (C) 2013--2017  Z. Gilboa                 */
dd89bb
/*  Released under GPLv2 and GPLv3; see COPYING.NTAPI.  */
dd89bb
/********************************************************/
dd89bb
dd89bb
#include <ntapi/nt_status.h>
dd89bb
#include <ntapi/nt_blitter.h>
dd89bb
#include <ntapi/nt_sync.h>
dd89bb
#include <ntapi/ntapi.h>
dd89bb
#include <ntapi/nt_atomic.h>
dd89bb
#include "ntapi_blitter.h"
dd89bb
#include "ntapi_impl.h"
dd89bb
dd89bb
static int __blt_popcount(uintptr_t mask)
dd89bb
{
dd89bb
	/* todo: check cpuid, use at_popcount */
d8a833
	uintptr_t i;
d8a833
	int       ret;
dd89bb
dd89bb
	for (i=0,ret=0; i<8*sizeof(uintptr_t); i++)
dd89bb
		if (mask & ((uintptr_t)1<
dd89bb
			ret++;
dd89bb
dd89bb
	return ret;
dd89bb
}
dd89bb
dd89bb
dd89bb
int32_t __fastcall __ntapi_blt_alloc(
dd89bb
	__out	nt_blitter **		blitter,
dd89bb
	__in	nt_blitter_params *	params)
dd89bb
{
dd89bb
	int32_t		status;
dd89bb
	nt_blitter *	blt_ctx;
dd89bb
	size_t		blt_ctx_size;
dd89bb
	size_t		params_size;
dd89bb
	size_t		ptrs,i;
dd89bb
dd89bb
	/* alignment */
7e3ebd
	if (params->block_count % sizeof(uintptr_t))
7e3ebd
		return NT_STATUS_INVALID_PARAMETER;
7e3ebd
7e3ebd
	else if (!params->region && (params->block_size % sizeof(uintptr_t)))
dd89bb
		return NT_STATUS_INVALID_PARAMETER;
dd89bb
dd89bb
	/* blt control block allocation */
dd89bb
	ptrs		= params->block_count / (8 * sizeof(uintptr_t));
dd89bb
	blt_ctx		= (nt_blitter *)0;
dd89bb
	blt_ctx_size	= (size_t)&((nt_blitter *)0)->bits;
dd89bb
dd89bb
	/* user-provided bitmap? */
dd89bb
	if (!params->bitmap)
dd89bb
		blt_ctx_size += ptrs * sizeof(uintptr_t);
dd89bb
dd89bb
	/* alloc */
dd89bb
	status = __ntapi->zw_allocate_virtual_memory(
dd89bb
		NT_CURRENT_PROCESS_HANDLE,
dd89bb
		(void **)&blt_ctx,
dd89bb
		0,
dd89bb
		&blt_ctx_size,
dd89bb
		NT_MEM_COMMIT,
dd89bb
		NT_PAGE_READWRITE);
dd89bb
dd89bb
	if (status) return (status);
dd89bb
dd89bb
	/* init control block */
dd89bb
	__ntapi->tt_aligned_block_memset(
dd89bb
		blt_ctx,
dd89bb
		0,(size_t)&((nt_blitter *)0)->bits);
dd89bb
dd89bb
	blt_ctx->addr	= blt_ctx;
dd89bb
	blt_ctx->size	= blt_ctx_size;
dd89bb
	blt_ctx->ptrs	= ptrs;
dd89bb
dd89bb
	/* init bitmap */
dd89bb
	blt_ctx->bitmap = params->bitmap
dd89bb
		? (uintptr_t *)params->bitmap
dd89bb
		: blt_ctx->bits;
dd89bb
dd89bb
	if (!(params->flags & NT_BLITTER_PRESERVE_BITS))
dd89bb
		__ntapi->tt_aligned_block_memset(
bbb5d0
			blt_ctx->bitmap,(-1),
dd89bb
			ptrs * sizeof(uintptr_t));
dd89bb
dd89bb
	/* info structure */
dd89bb
	blt_ctx->info.info_size   = sizeof(nt_blitter_info);
dd89bb
	blt_ctx->info.block_count = params->block_count;
dd89bb
	blt_ctx->info.block_size  = params->block_size;
dd89bb
dd89bb
	if (params->flags & NT_BLITTER_ENABLE_BLOCK_ARRAY)
dd89bb
		/* allocate in place */
dd89bb
		blt_ctx->info.region_size = params->block_count * params->block_size;
dd89bb
	else
dd89bb
		/* use pointer array */
dd89bb
		blt_ctx->info.region_size = params->block_count * sizeof(uintptr_t);
dd89bb
dd89bb
	/* allocate region */
dd89bb
	if (params->region)
dd89bb
		blt_ctx->info.region_addr = params->region;
dd89bb
	else
dd89bb
		status = __ntapi->zw_allocate_virtual_memory(
dd89bb
			NT_CURRENT_PROCESS_HANDLE,
dd89bb
			&blt_ctx->info.region_addr,
dd89bb
			0,
dd89bb
			&blt_ctx->info.region_size,
dd89bb
			NT_MEM_COMMIT,
dd89bb
			NT_PAGE_READWRITE);
dd89bb
dd89bb
	if (status) {
dd89bb
		__ntapi->blt_free(blt_ctx);
dd89bb
		return status;
dd89bb
	}
dd89bb
dd89bb
	if (params->flags & NT_BLITTER_PRESERVE_BITS)
dd89bb
		for (i=0,blt_ctx->info.blocks_avail=0; i
dd89bb
			blt_ctx->info.blocks_avail += __blt_popcount(blt_ctx->bitmap[i]);
dd89bb
	else
dd89bb
		blt_ctx->info.blocks_avail = params->block_count;
dd89bb
dd89bb
	if (params->flags & NT_BLITTER_ENABLE_BLOCK_ARRAY)
dd89bb
		blt_ctx->info.blocks_cached = params->block_count;
dd89bb
dd89bb
	/* init block array */
dd89bb
	if (!params->region)
dd89bb
		__ntapi->tt_aligned_block_memset(
dd89bb
			blt_ctx->info.region_addr,
dd89bb
			0,blt_ctx->info.region_size);
dd89bb
dd89bb
	/* copy params */
dd89bb
	if (params->params_size < sizeof(nt_blitter_params))
dd89bb
		params_size = params->params_size;
dd89bb
	else
dd89bb
		params_size = sizeof(nt_blitter_params);
dd89bb
dd89bb
	__ntapi->tt_aligned_block_memcpy(
dd89bb
		(uintptr_t *)&blt_ctx->params,
dd89bb
		(uintptr_t *)params,
dd89bb
		params_size);
dd89bb
dd89bb
	/* update params */
dd89bb
	blt_ctx->params.lock_tries = params->lock_tries
dd89bb
				? params->lock_tries
dd89bb
				: __NT_BLITTER_DEFAULT_LOCK_TRIES;
dd89bb
dd89bb
	blt_ctx->params.round_trips = params->round_trips
dd89bb
				? params->round_trips
dd89bb
				: __NT_BLITTER_DEFAULT_ROUND_TRIPS;
dd89bb
dd89bb
	*blitter = blt_ctx;
dd89bb
dd89bb
	return NT_STATUS_SUCCESS;
dd89bb
}