|
|
dd89bb |
/********************************************************/
|
|
|
dd89bb |
/* ntapi: Native API core library */
|
|
|
4256e2 |
/* Copyright (C) 2013--2016 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 */
|
|
|
dd89bb |
int i,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 */
|
|
|
dd89bb |
if ((params->block_size % sizeof(uintptr_t)) || (params->block_count % 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(
|
|
|
dd89bb |
blt_ctx->bitmap,
|
|
|
dd89bb |
(intptr_t)0xFFFFFFFFFFFFFFFF,
|
|
|
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 |
}
|