add memory and resources allocation functions
This commit is contained in:
parent
529445dbb9
commit
947a854992
@ -96,7 +96,7 @@ NTSTATUS QxlDod::CheckHardware()
|
|||||||
}
|
}
|
||||||
|
|
||||||
Status = STATUS_GRAPHICS_DRIVER_MISMATCH;
|
Status = STATUS_GRAPHICS_DRIVER_MISMATCH;
|
||||||
if (Header.VendorID == 0x1B36 &&
|
if (Header.VendorID == REDHAT_PCI_VENDOR_ID &&
|
||||||
Header.DeviceID == 0x0100 &&
|
Header.DeviceID == 0x0100 &&
|
||||||
Header.RevisionID == 4)
|
Header.RevisionID == 4)
|
||||||
{
|
{
|
||||||
@ -2896,11 +2896,11 @@ NTSTATUS QxlDevice::GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo)
|
|||||||
{
|
{
|
||||||
m_ModeNumbers[SuitableModeCount] = CurrentMode;
|
m_ModeNumbers[SuitableModeCount] = CurrentMode;
|
||||||
SetVideoModeInfo(SuitableModeCount, tmpModeInfo);
|
SetVideoModeInfo(SuitableModeCount, tmpModeInfo);
|
||||||
// if (tmpModeInfo->x_res == 1024 &&
|
if (tmpModeInfo->x_res == 1024 &&
|
||||||
// tmpModeInfo->y_res == 768)
|
tmpModeInfo->y_res == 768)
|
||||||
// {
|
{
|
||||||
// m_CurrentMode = (USHORT)SuitableModeCount;
|
m_CurrentMode = (USHORT)SuitableModeCount;
|
||||||
// }
|
}
|
||||||
SuitableModeCount++;
|
SuitableModeCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2911,7 +2911,7 @@ NTSTATUS QxlDevice::GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo)
|
|||||||
Status = STATUS_UNSUCCESSFUL;
|
Status = STATUS_UNSUCCESSFUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_CurrentMode = m_ModeNumbers[0];
|
// m_CurrentMode = m_ModeNumbers[0];
|
||||||
m_ModeCount = SuitableModeCount;
|
m_ModeCount = SuitableModeCount;
|
||||||
DbgPrint(TRACE_LEVEL_ERROR, ("ModeCount filtered %d\n", m_ModeCount));
|
DbgPrint(TRACE_LEVEL_ERROR, ("ModeCount filtered %d\n", m_ModeCount));
|
||||||
for (ULONG idx = 0; idx < m_ModeCount; idx++)
|
for (ULONG idx = 0; idx < m_ModeCount; idx++)
|
||||||
@ -2937,11 +2937,19 @@ NTSTATUS QxlDevice::QueryCurrentMode(PVIDEO_MODE RequestedMode)
|
|||||||
|
|
||||||
NTSTATUS QxlDevice::SetCurrentMode(ULONG Mode)
|
NTSTATUS QxlDevice::SetCurrentMode(ULONG Mode)
|
||||||
{
|
{
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
|
||||||
DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s Mode = %x\n", __FUNCTION__, Mode));
|
DbgPrint(TRACE_LEVEL_INFORMATION, ("---> %s Mode = %x\n", __FUNCTION__, Mode));
|
||||||
UNREFERENCED_PARAMETER(Mode);
|
// UNREFERENCED_PARAMETER(Mode);
|
||||||
|
for (ULONG idx = 0; idx < m_ModeCount; idx++)
|
||||||
|
{
|
||||||
|
if (Mode == m_ModeNumbers[idx])
|
||||||
|
{
|
||||||
|
DestroyPrimarySurface();
|
||||||
|
CreatePrimarySurface(&m_ModeInfo[idx]);
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__));
|
DbgPrint(TRACE_LEVEL_VERBOSE, ("<--- %s\n", __FUNCTION__));
|
||||||
return Status;
|
return STATUS_UNSUCCESSFUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS QxlDevice::GetCurrentMode(ULONG* pMode)
|
NTSTATUS QxlDevice::GetCurrentMode(ULONG* pMode)
|
||||||
@ -3161,6 +3169,45 @@ void QxlDevice::DestroyMemSlots(void)
|
|||||||
m_MemSlots = NULL;
|
m_MemSlots = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QxlDevice::CreatePrimarySurface(PVIDEO_MODE_INFORMATION pModeInfo)
|
||||||
|
{
|
||||||
|
QXLSurfaceCreate *primary_surface_create;
|
||||||
|
primary_surface_create = &m_RamHdr->create_surface;
|
||||||
|
primary_surface_create->format = pModeInfo->BitsPerPlane;
|
||||||
|
primary_surface_create->width = pModeInfo->VisScreenWidth;
|
||||||
|
primary_surface_create->height = pModeInfo->VisScreenHeight;
|
||||||
|
primary_surface_create->stride = pModeInfo->ScreenStride;
|
||||||
|
|
||||||
|
primary_surface_create->mem = PA( m_RamStart, 0);
|
||||||
|
|
||||||
|
primary_surface_create->flags = QXL_SURF_FLAG_KEEP_DATA; //0;
|
||||||
|
primary_surface_create->type = QXL_SURF_TYPE_PRIMARY;
|
||||||
|
WRITE_PORT_UCHAR((PUCHAR)(m_IoBase + QXL_IO_CREATE_PRIMARY), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QxlDevice::DestroyPrimarySurface(void)
|
||||||
|
{
|
||||||
|
WRITE_PORT_UCHAR((PUCHAR)(m_IoBase + QXL_IO_DESTROY_PRIMARY), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
_inline QXLPHYSICAL QxlDevice::PA(PVOID virt, UINT8 slot_id)
|
||||||
|
{
|
||||||
|
MemSlot *pSlot = &m_MemSlots[slot_id];;
|
||||||
|
|
||||||
|
return pSlot->high_bits | ((UINT64)virt - pSlot->start_virt_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
_inline UINT64 QxlDevice::VA(QXLPHYSICAL paddr, UINT8 slot_id)
|
||||||
|
{
|
||||||
|
UINT64 virt;
|
||||||
|
MemSlot *pSlot = &m_MemSlots[slot_id];;
|
||||||
|
|
||||||
|
virt = paddr & m_VaSlotMask;
|
||||||
|
virt += pSlot->start_virt_addr;;
|
||||||
|
|
||||||
|
return virt;
|
||||||
|
}
|
||||||
|
|
||||||
void QxlDevice::SetupHWSlot(UINT8 Idx, MemSlot *pSlot)
|
void QxlDevice::SetupHWSlot(UINT8 Idx, MemSlot *pSlot)
|
||||||
{
|
{
|
||||||
m_RamHdr->mem_slot.mem_start = pSlot->start_phys_addr;
|
m_RamHdr->mem_slot.mem_start = pSlot->start_phys_addr;
|
||||||
@ -3179,6 +3226,8 @@ BOOL QxlDevice::CreateEvents()
|
|||||||
KeInitializeEvent(&m_IoCmdEvent,
|
KeInitializeEvent(&m_IoCmdEvent,
|
||||||
SynchronizationEvent,
|
SynchronizationEvent,
|
||||||
FALSE);
|
FALSE);
|
||||||
|
KeInitializeSpinLock(&m_MemLock);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3218,6 +3267,19 @@ BOOL QxlDevice::CreateMemSlots(void)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QxlDevice::InitDeviceMemoryResources(void)
|
||||||
|
{
|
||||||
|
InitMspace(MSPACE_TYPE_DEVRAM, (m_RamStart + m_RomHdr->surface0_area_size), (size_t)((m_VRamPA.QuadPart + m_RomHdr->surface0_area_size) * PAGE_SIZE));
|
||||||
|
InitMspace(MSPACE_TYPE_VRAM, m_VRamStart, m_VRamSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QxlDevice::InitMspace(UINT32 mspace_type, UINT8 *start, size_t capacity)
|
||||||
|
{
|
||||||
|
m_MSInfo[mspace_type]._mspace = create_mspace_with_base(start, capacity, 0, this);
|
||||||
|
m_MSInfo[mspace_type].mspace_start = start;
|
||||||
|
m_MSInfo[mspace_type].mspace_end = start + capacity;
|
||||||
|
}
|
||||||
|
|
||||||
void QxlDevice::ResetDevice(void)
|
void QxlDevice::ResetDevice(void)
|
||||||
{
|
{
|
||||||
m_RamHdr->int_mask = ~0;
|
m_RamHdr->int_mask = ~0;
|
||||||
@ -3239,14 +3301,467 @@ QxlDevice::ExecutePresentDisplayOnly(
|
|||||||
_In_ D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation,
|
_In_ D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation,
|
||||||
_In_ const CURRENT_BDD_MODE* pModeCur)
|
_In_ const CURRENT_BDD_MODE* pModeCur)
|
||||||
{
|
{
|
||||||
|
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__));
|
DbgPrint(TRACE_LEVEL_VERBOSE, ("---> %s\n", __FUNCTION__));
|
||||||
|
|
||||||
NTSTATUS Status = STATUS_SUCCESS;
|
NTSTATUS Status = STATUS_SUCCESS;
|
||||||
|
|
||||||
|
SIZE_T sizeMoves = NumMoves*sizeof(D3DKMT_MOVE_RECT);
|
||||||
|
SIZE_T sizeRects = NumDirtyRects*sizeof(RECT);
|
||||||
|
SIZE_T size = sizeof(DoPresentMemory) + sizeMoves + sizeRects;
|
||||||
|
|
||||||
|
DoPresentMemory* ctx = reinterpret_cast<DoPresentMemory*>
|
||||||
|
(new (NonPagedPoolNx) BYTE[size]);
|
||||||
|
|
||||||
|
if (!ctx)
|
||||||
|
{
|
||||||
|
return STATUS_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
RtlZeroMemory(ctx,size);
|
||||||
|
|
||||||
|
// const CURRENT_BDD_MODE* pModeCur = &m_CurrentModes[0];
|
||||||
|
ctx->DstAddr = DstAddr;
|
||||||
|
ctx->DstBitPerPixel = DstBitPerPixel;
|
||||||
|
ctx->DstStride = pModeCur->DispInfo.Pitch;
|
||||||
|
ctx->SrcWidth = pModeCur->SrcModeWidth;
|
||||||
|
ctx->SrcHeight = pModeCur->SrcModeHeight;
|
||||||
|
ctx->SrcAddr = NULL;
|
||||||
|
ctx->SrcPitch = SrcPitch;
|
||||||
|
ctx->Rotation = Rotation;
|
||||||
|
ctx->NumMoves = NumMoves;
|
||||||
|
ctx->Moves = Moves;
|
||||||
|
ctx->NumDirtyRects = NumDirtyRects;
|
||||||
|
ctx->DirtyRect = DirtyRect;
|
||||||
|
// ctx->SourceID = m_SourceId;
|
||||||
|
// ctx->hAdapter = m_DevExt;
|
||||||
|
ctx->Mdl = NULL;
|
||||||
|
ctx->DisplaySource = this;
|
||||||
|
|
||||||
|
// Alternate between synch and asynch execution, for demonstrating
|
||||||
|
// that a real hardware implementation can do either
|
||||||
|
|
||||||
|
{
|
||||||
|
// Map Source into kernel space, as Blt will be executed by system worker thread
|
||||||
|
UINT sizeToMap = SrcBytesPerPixel * ctx->SrcWidth * ctx->SrcHeight;
|
||||||
|
|
||||||
|
PMDL mdl = IoAllocateMdl((PVOID)SrcAddr, sizeToMap, FALSE, FALSE, NULL);
|
||||||
|
if(!mdl)
|
||||||
|
{
|
||||||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
}
|
||||||
|
|
||||||
|
KPROCESSOR_MODE AccessMode = static_cast<KPROCESSOR_MODE>(( SrcAddr <=
|
||||||
|
(BYTE* const) MM_USER_PROBE_ADDRESS)?UserMode:KernelMode);
|
||||||
|
__try
|
||||||
|
{
|
||||||
|
// Probe and lock the pages of this buffer in physical memory.
|
||||||
|
// We need only IoReadAccess.
|
||||||
|
MmProbeAndLockPages(mdl, AccessMode, IoReadAccess);
|
||||||
|
}
|
||||||
|
#pragma prefast(suppress: __WARNING_EXCEPTIONEXECUTEHANDLER, "try/except is only able to protect against user-mode errors and these are the only errors we try to catch here");
|
||||||
|
__except(EXCEPTION_EXECUTE_HANDLER)
|
||||||
|
{
|
||||||
|
Status = GetExceptionCode();
|
||||||
|
IoFreeMdl(mdl);
|
||||||
return Status;
|
return Status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Map the physical pages described by the MDL into system space.
|
||||||
|
// Note: double mapping the buffer this way causes lot of system
|
||||||
|
// overhead for large size buffers.
|
||||||
|
ctx->SrcAddr = reinterpret_cast<BYTE*>
|
||||||
|
(MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority ));
|
||||||
|
|
||||||
|
if(!ctx->SrcAddr) {
|
||||||
|
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||||||
|
MmUnlockPages(mdl);
|
||||||
|
IoFreeMdl(mdl);
|
||||||
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save Mdl to unmap and unlock the pages in worker thread
|
||||||
|
ctx->Mdl = mdl;
|
||||||
|
}
|
||||||
|
|
||||||
|
BYTE* rects = reinterpret_cast<BYTE*>(ctx+1);
|
||||||
|
|
||||||
|
// copy moves and update pointer
|
||||||
|
if (Moves)
|
||||||
|
{
|
||||||
|
memcpy(rects,Moves,sizeMoves);
|
||||||
|
ctx->Moves = reinterpret_cast<D3DKMT_MOVE_RECT*>(rects);
|
||||||
|
rects += sizeMoves;
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy dirty rects and update pointer
|
||||||
|
if (DirtyRect)
|
||||||
|
{
|
||||||
|
memcpy(rects,DirtyRect,sizeRects);
|
||||||
|
ctx->DirtyRect = reinterpret_cast<RECT*>(rects);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up destination blt info
|
||||||
|
BLT_INFO DstBltInfo;
|
||||||
|
DstBltInfo.pBits = ctx->DstAddr;
|
||||||
|
DstBltInfo.Pitch = ctx->DstStride;
|
||||||
|
DstBltInfo.BitsPerPel = ctx->DstBitPerPixel;
|
||||||
|
DstBltInfo.Offset.x = 0;
|
||||||
|
DstBltInfo.Offset.y = 0;
|
||||||
|
DstBltInfo.Rotation = ctx->Rotation;
|
||||||
|
DstBltInfo.Width = ctx->SrcWidth;
|
||||||
|
DstBltInfo.Height = ctx->SrcHeight;
|
||||||
|
|
||||||
|
// Set up source blt info
|
||||||
|
BLT_INFO SrcBltInfo;
|
||||||
|
SrcBltInfo.pBits = ctx->SrcAddr;
|
||||||
|
SrcBltInfo.Pitch = ctx->SrcPitch;
|
||||||
|
SrcBltInfo.BitsPerPel = 32;
|
||||||
|
SrcBltInfo.Offset.x = 0;
|
||||||
|
SrcBltInfo.Offset.y = 0;
|
||||||
|
SrcBltInfo.Rotation = D3DKMDT_VPPR_IDENTITY;
|
||||||
|
if (ctx->Rotation == D3DKMDT_VPPR_ROTATE90 ||
|
||||||
|
ctx->Rotation == D3DKMDT_VPPR_ROTATE270)
|
||||||
|
{
|
||||||
|
SrcBltInfo.Width = DstBltInfo.Height;
|
||||||
|
SrcBltInfo.Height = DstBltInfo.Width;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SrcBltInfo.Width = DstBltInfo.Width;
|
||||||
|
SrcBltInfo.Height = DstBltInfo.Height;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Copy all the scroll rects from source image to video frame buffer.
|
||||||
|
for (UINT i = 0; i < ctx->NumMoves; i++)
|
||||||
|
{
|
||||||
|
POINT* pSourcePoint = &ctx->Moves[i].SourcePoint;
|
||||||
|
RECT* pDestRect = &ctx->Moves[i].DestRect;
|
||||||
|
|
||||||
|
DbgPrint(TRACE_LEVEL_FATAL, ("--- %d SourcePoint.x = %d, SourcePoint.y = %d, DestRect.bottom = %d, DestRect.left = %d, DestRect.right = %d, DestRect.top = %d\n",
|
||||||
|
i , pSourcePoint->x, pSourcePoint->y, pDestRect->bottom, pDestRect->left, pDestRect->right, pDestRect->top));
|
||||||
|
|
||||||
|
BltBits(&DstBltInfo,
|
||||||
|
&SrcBltInfo,
|
||||||
|
1, // NumRects
|
||||||
|
&ctx->Moves[i].DestRect);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy all the dirty rects from source image to video frame buffer.
|
||||||
|
for (UINT i = 0; i < ctx->NumDirtyRects; i++)
|
||||||
|
{
|
||||||
|
RECT* pDirtyRect = &ctx->DirtyRect[i];
|
||||||
|
DbgPrint(TRACE_LEVEL_FATAL, ("--- %d pDirtyRect->bottom = %d, pDirtyRect->left = %d, pDirtyRect->right = %d, pDirtyRect->top = %d\n",
|
||||||
|
i, pDirtyRect->bottom, pDirtyRect->left, pDirtyRect->right, pDirtyRect->top));
|
||||||
|
|
||||||
|
BltBits(&DstBltInfo,
|
||||||
|
&SrcBltInfo,
|
||||||
|
1, // NumRects
|
||||||
|
&ctx->DirtyRect[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unmap unmap and unlock the pages.
|
||||||
|
if (ctx->Mdl)
|
||||||
|
{
|
||||||
|
MmUnlockPages(ctx->Mdl);
|
||||||
|
IoFreeMdl(ctx->Mdl);
|
||||||
|
}
|
||||||
|
delete [] reinterpret_cast<BYTE*>(ctx);
|
||||||
|
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
KIRQL
|
||||||
|
AcquireSpinLock(PVOID pSpinLock)
|
||||||
|
{
|
||||||
|
KIRQL IRQL;
|
||||||
|
|
||||||
|
IRQL = KeGetCurrentIrql();
|
||||||
|
|
||||||
|
if (DISPATCH_LEVEL == IRQL)
|
||||||
|
KeAcquireSpinLockAtDpcLevel((KSPIN_LOCK *)pSpinLock);
|
||||||
|
else
|
||||||
|
KeAcquireSpinLock((KSPIN_LOCK *)pSpinLock, &IRQL);
|
||||||
|
|
||||||
|
return IRQL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline
|
||||||
|
VOID
|
||||||
|
ReleaseSpinLock(PVOID pSpinLock, KIRQL IRQL)
|
||||||
|
{
|
||||||
|
if (DISPATCH_LEVEL == IRQL)
|
||||||
|
KeReleaseSpinLockFromDpcLevel((KSPIN_LOCK *)pSpinLock);
|
||||||
|
else
|
||||||
|
KeReleaseSpinLock((KSPIN_LOCK *)pSpinLock, IRQL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QxlDevice::WaitForReleaseRing(void)
|
||||||
|
{
|
||||||
|
int wait;
|
||||||
|
|
||||||
|
DbgPrint(TRACE_LEVEL_VERBOSE, ("%s\n", __FUNCTION__));
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
LARGE_INTEGER timeout;
|
||||||
|
|
||||||
|
if (SPICE_RING_IS_EMPTY(m_ReleaseRing)) {
|
||||||
|
QXL_SLEEP(10);
|
||||||
|
if (!SPICE_RING_IS_EMPTY(m_ReleaseRing)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
WRITE_PORT_UCHAR((PUCHAR)(m_IoBase + QXL_IO_NOTIFY_OOM), 0);
|
||||||
|
}
|
||||||
|
SPICE_RING_CONS_WAIT(m_ReleaseRing, wait);
|
||||||
|
|
||||||
|
if (!wait) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
timeout.QuadPart = -30 * 1000 * 10; //30ms
|
||||||
|
WAIT_FOR_EVENT(m_DisplayEvent, &timeout);
|
||||||
|
|
||||||
|
if (SPICE_RING_IS_EMPTY(m_ReleaseRing)) {
|
||||||
|
WRITE_PORT_UCHAR((PUCHAR)(m_IoBase + QXL_IO_NOTIFY_OOM), 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DbgPrint(TRACE_LEVEL_VERBOSE, ("%s: done\n", __FUNCTION__));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void QxlDevice::FlushReleaseRing()
|
||||||
|
{
|
||||||
|
UINT64 output;
|
||||||
|
int notify;
|
||||||
|
int num_to_release = 50;
|
||||||
|
|
||||||
|
output = free_outputs;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
while (output != 0) {
|
||||||
|
output = ReleaseOutput(output);
|
||||||
|
if (--num_to_release == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (output != 0 ||
|
||||||
|
SPICE_RING_IS_EMPTY(m_ReleaseRing)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
output = *SPICE_RING_CONS_ITEM(m_ReleaseRing);
|
||||||
|
SPICE_RING_POP(m_ReleaseRing, notify);
|
||||||
|
}
|
||||||
|
|
||||||
|
free_outputs = output;
|
||||||
|
}
|
||||||
|
|
||||||
|
UINT64 QxlDevice::ReleaseOutput(UINT64 output_id)
|
||||||
|
{
|
||||||
|
QXLOutput *output = (QXLOutput *)output_id;
|
||||||
|
Resource **now;
|
||||||
|
Resource **end;
|
||||||
|
UINT64 next;
|
||||||
|
|
||||||
|
ASSERT(output_id);
|
||||||
|
DbgPrint(TRACE_LEVEL_VERBOSE, ("%s 0x%x\n", __FUNCTION__, output));
|
||||||
|
// DebugShowOutput(pdev, output);
|
||||||
|
|
||||||
|
for (now = output->resources, end = now + output->num_res; now < end; now++) {
|
||||||
|
RELEASE_RES(*now);
|
||||||
|
}
|
||||||
|
next = *(UINT64*)output->data;
|
||||||
|
FreeMem(MSPACE_TYPE_DEVRAM, output);
|
||||||
|
DbgPrint(TRACE_LEVEL_VERBOSE, ("%s done\n", __FUNCTION__));
|
||||||
|
return next;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *QxlDevice::AllocMem(UINT32 mspace_type, size_t size, BOOL force)
|
||||||
|
{
|
||||||
|
PVOID ptr;
|
||||||
|
KIRQL old_irql;
|
||||||
|
|
||||||
|
ASSERT(m_MSInfo[mspace_type]._mspace);
|
||||||
|
DbgPrint(TRACE_LEVEL_VERBOSE, ("%s: %p(%d) size %u\n", __FUNCTION__,
|
||||||
|
m_MSInfo[mspace_type]._mspace,
|
||||||
|
mspace_footprint(m_MSInfo[mspace_type]._mspace),
|
||||||
|
size));
|
||||||
|
#ifdef DBG
|
||||||
|
mspace_malloc_stats(m_MSInfo[mspace_type]._mspace);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
/* Release lots of queued resources, before allocating, as we
|
||||||
|
want to release early to minimize fragmentation risks. */
|
||||||
|
FlushReleaseRing();
|
||||||
|
|
||||||
|
old_irql = AcquireSpinLock(&m_MemLock);
|
||||||
|
ptr = mspace_malloc(m_MSInfo[mspace_type]._mspace, size);
|
||||||
|
ReleaseSpinLock(&m_MemLock, old_irql);
|
||||||
|
if (ptr) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (free_outputs != 0 ||
|
||||||
|
!SPICE_RING_IS_EMPTY(m_ReleaseRing)) {
|
||||||
|
/* We have more things to free, try that */
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (force) {
|
||||||
|
/* Ask spice to free some stuff */
|
||||||
|
WaitForReleaseRing();
|
||||||
|
} else {
|
||||||
|
/* Fail */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT((!ptr && !force) || (ptr >= m_MSInfo[mspace_type].mspace_start &&
|
||||||
|
ptr < m_MSInfo[mspace_type].mspace_end));
|
||||||
|
DbgPrint(TRACE_LEVEL_VERBOSE, ("%s: done 0x%x\n", __FUNCTION__, ptr));
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QxlDevice::FreeMem(UINT32 mspace_type, void *ptr)
|
||||||
|
{
|
||||||
|
KIRQL old_irql;
|
||||||
|
ASSERT(m_MSInfo[mspace_type]._mspace);
|
||||||
|
#ifdef DBG
|
||||||
|
if (!((UINT8 *)ptr >= m_MSInfo[mspace_type].mspace_start &&
|
||||||
|
(UINT8 *)ptr < m_MSInfo[mspace_type].mspace_end)) {
|
||||||
|
DbgPrint(TRACE_LEVEL_ERROR, ("ASSERT failed @ %s, %p not in [%p, %p) (%d)\n", __FUNCTION__,
|
||||||
|
ptr, m_MSInfo[mspace_type].mspace_start,
|
||||||
|
m_MSInfo[mspace_type].mspace_end, mspace_type));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
old_irql = AcquireSpinLock(&m_MemLock);
|
||||||
|
mspace_free(m_MSInfo[mspace_type]._mspace, ptr);
|
||||||
|
ReleaseSpinLock(&m_MemLock, old_irql);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QXLDrawable *QxlDevice::GetDrawable()
|
||||||
|
{
|
||||||
|
QXLOutput *output;
|
||||||
|
|
||||||
|
output = (QXLOutput *)AllocMem(MSPACE_TYPE_DEVRAM, sizeof(QXLOutput) + sizeof(QXLDrawable), TRUE);
|
||||||
|
output->num_res = 0;
|
||||||
|
RESOURCE_TYPE(output, RESOURCE_TYPE_DRAWABLE);
|
||||||
|
((QXLDrawable *)output->data)->release_info.id = (UINT64)output;
|
||||||
|
DbgPrint(TRACE_LEVEL_VERBOSE, ("%s 0x%x\n", __FUNCTION__, output));
|
||||||
|
return(QXLDrawable *)output->data;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL QxlDevice::SetClip(const RECT *clip, QXLDrawable *drawable)
|
||||||
|
{
|
||||||
|
Resource *rects_res;
|
||||||
|
|
||||||
|
if (clip == NULL) {
|
||||||
|
drawable->clip.type = SPICE_CLIP_TYPE_NONE;
|
||||||
|
DbgPrint(TRACE_LEVEL_ERROR, ("%s QXL_CLIP_TYPE_NONE\n", __FUNCTION__));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
QXLClipRects *rects;
|
||||||
|
rects_res = (Resource *)AllocMem(MSPACE_TYPE_DEVRAM, sizeof(Resource) + sizeof(QXLClipRects) +
|
||||||
|
sizeof(QXLRect), TRUE);
|
||||||
|
rects_res->refs = 1;
|
||||||
|
//FIXME
|
||||||
|
rects_res->free = FreeClipRectsEx;
|
||||||
|
rects_res->ptr = this;
|
||||||
|
rects = (QXLClipRects *)rects_res->res;
|
||||||
|
rects->num_rects = 1;
|
||||||
|
rects->chunk.data_size = sizeof(QXLRect);
|
||||||
|
rects->chunk.prev_chunk = 0;
|
||||||
|
rects->chunk.next_chunk = 0;
|
||||||
|
CopyRect((QXLRect *)rects->chunk.data, clip);
|
||||||
|
|
||||||
|
DrawableAddRes(drawable, rects_res);
|
||||||
|
drawable->clip.type = SPICE_CLIP_TYPE_RECTS;
|
||||||
|
drawable->clip.data = PA(rects_res->res, m_MainMemSlot);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QxlDevice::AddRes(QXLOutput *output, Resource *res)
|
||||||
|
{
|
||||||
|
res->refs++;
|
||||||
|
output->resources[output->num_res++] = res;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QxlDevice::DrawableAddRes(QXLDrawable *drawable, Resource *res)
|
||||||
|
{
|
||||||
|
QXLOutput *output;
|
||||||
|
|
||||||
|
output = (QXLOutput *)((UINT8 *)drawable - sizeof(QXLOutput));
|
||||||
|
AddRes(output, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QxlDevice::FreeClipRectsEx(Resource *res)
|
||||||
|
{
|
||||||
|
QxlDevice* pqxl = (QxlDevice*)res->ptr;
|
||||||
|
pqxl->FreeClipRects(res);
|
||||||
|
}
|
||||||
|
void QxlDevice::FreeClipRects(Resource *res)
|
||||||
|
{
|
||||||
|
QXLPHYSICAL chunk_phys;
|
||||||
|
|
||||||
|
chunk_phys = ((QXLClipRects *)res->res)->chunk.next_chunk;
|
||||||
|
while (chunk_phys) {
|
||||||
|
QXLDataChunk *chunk = (QXLDataChunk *)VA(chunk_phys, m_MainMemSlot);
|
||||||
|
chunk_phys = chunk->next_chunk;
|
||||||
|
FreeMem(MSPACE_TYPE_DEVRAM, chunk);
|
||||||
|
}
|
||||||
|
FreeMem(MSPACE_TYPE_DEVRAM, res);
|
||||||
|
}
|
||||||
|
|
||||||
|
QXLDrawable *QxlDevice::Drawable(UINT8 type, CONST RECT *area, CONST RECT *clip, UINT32 surface_id)
|
||||||
|
{
|
||||||
|
QXLDrawable *drawable;
|
||||||
|
|
||||||
|
ASSERT(area);
|
||||||
|
|
||||||
|
drawable = GetDrawable();
|
||||||
|
drawable->surface_id = surface_id;
|
||||||
|
drawable->type = type;
|
||||||
|
drawable->effect = QXL_EFFECT_BLEND;
|
||||||
|
drawable->self_bitmap = 0;
|
||||||
|
drawable->mm_time = m_RomHdr->mm_clock;
|
||||||
|
drawable->surfaces_dest[0] = -1;
|
||||||
|
drawable->surfaces_dest[1] = - 1;
|
||||||
|
drawable->surfaces_dest[2] = -1;
|
||||||
|
CopyRect(&drawable->bbox, area);
|
||||||
|
|
||||||
|
if (!SetClip(clip, drawable)) {
|
||||||
|
DbgPrint(TRACE_LEVEL_VERBOSE, ("%s: set clip failed\n", __FUNCTION__));
|
||||||
|
ReleaseOutput(drawable->release_info.id);
|
||||||
|
drawable = NULL;
|
||||||
|
}
|
||||||
|
return drawable;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VOID QxlDevice::BltBits (
|
||||||
|
BLT_INFO* pDst,
|
||||||
|
CONST BLT_INFO* pSrc,
|
||||||
|
UINT NumRects,
|
||||||
|
_In_reads_(NumRects) CONST RECT *pRects)
|
||||||
|
{
|
||||||
|
QXLDrawable *drawable;
|
||||||
|
|
||||||
|
if (!(drawable = Drawable(QXL_DRAW_COPY, pRects, NULL, 0))) {
|
||||||
|
DbgPrint(TRACE_LEVEL_ERROR, ("Cannot get Drawable.\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (UINT iRect = 0; iRect < NumRects; iRect++)
|
||||||
|
{
|
||||||
|
CONST RECT* pRect = &pRects[iRect];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
VOID QxlDevice::BlackOutScreen(CURRENT_BDD_MODE* pCurrentBddMod)
|
VOID QxlDevice::BlackOutScreen(CURRENT_BDD_MODE* pCurrentBddMod)
|
||||||
{
|
{
|
||||||
PAGED_CODE();
|
PAGED_CODE();
|
||||||
@ -3293,3 +3808,17 @@ D3DDDIFORMAT PixelFormatFromBPP(UINT BPP)
|
|||||||
default: QXL_LOG_ASSERTION1("A bit per pixel of 0x%I64x is not supported.", BPP); return D3DDDIFMT_UNKNOWN;
|
default: QXL_LOG_ASSERTION1("A bit per pixel of 0x%I64x is not supported.", BPP); return D3DDDIFMT_UNKNOWN;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UINT SpiceFromPixelFormat(D3DDDIFORMAT Format)
|
||||||
|
{
|
||||||
|
switch (Format)
|
||||||
|
{
|
||||||
|
case D3DDDIFMT_UNKNOWN:
|
||||||
|
case D3DDDIFMT_P8: QXL_LOG_ASSERTION1("Bad format type 0x%I64x", Format); return 0;
|
||||||
|
case D3DDDIFMT_R5G6B5: return SPICE_SURFACE_FMT_16_555;
|
||||||
|
case D3DDDIFMT_R8G8B8:
|
||||||
|
case D3DDDIFMT_X8R8G8B8:
|
||||||
|
case D3DDDIFMT_A8R8G8B8: return SPICE_SURFACE_FMT_32_xRGB;
|
||||||
|
default: QXL_LOG_ASSERTION1("Unknown D3DDDIFORMAT 0x%I64x", Format); return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
149
qxldod/QxlDod.h
149
qxldod/QxlDod.h
@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "baseobject.h"
|
#include "baseobject.h"
|
||||||
#include "qxl_dev.h"
|
#include "qxl_dev.h"
|
||||||
|
#include "mspace.h"
|
||||||
|
|
||||||
#define MAX_CHILDREN 1
|
#define MAX_CHILDREN 1
|
||||||
#define MAX_VIEWS 1
|
#define MAX_VIEWS 1
|
||||||
@ -306,6 +307,85 @@ typedef struct _MemSlot {
|
|||||||
QXLPHYSICAL high_bits;
|
QXLPHYSICAL high_bits;
|
||||||
} MemSlot;
|
} MemSlot;
|
||||||
|
|
||||||
|
typedef struct MspaceInfo {
|
||||||
|
mspace _mspace;
|
||||||
|
UINT8 *mspace_start;
|
||||||
|
UINT8 *mspace_end;
|
||||||
|
} MspaceInfo;
|
||||||
|
|
||||||
|
enum {
|
||||||
|
MSPACE_TYPE_DEVRAM,
|
||||||
|
MSPACE_TYPE_VRAM,
|
||||||
|
|
||||||
|
NUM_MSPACES,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define RELEASE_RES(res) if (!--(res)->refs) (res)->free(res);
|
||||||
|
#define GET_RES(res) (++(res)->refs)
|
||||||
|
|
||||||
|
/* Debug helpers - tag each resource with this enum */
|
||||||
|
enum {
|
||||||
|
RESOURCE_TYPE_DRAWABLE = 1,
|
||||||
|
RESOURCE_TYPE_SURFACE,
|
||||||
|
RESOURCE_TYPE_PATH,
|
||||||
|
RESOURCE_TYPE_CLIP_RECTS,
|
||||||
|
RESOURCE_TYPE_QUIC_IMAGE,
|
||||||
|
RESOURCE_TYPE_BITMAP_IMAGE,
|
||||||
|
RESOURCE_TYPE_SURFACE_IMAGE,
|
||||||
|
RESOURCE_TYPE_SRING,
|
||||||
|
RESOURCE_TYPE_CURSOR,
|
||||||
|
RESOURCE_TYPE_BUF,
|
||||||
|
RESOURCE_TYPE_UPDATE,
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef DBG
|
||||||
|
#define RESOURCE_TYPE(res, val) do { res->type = val; } while (0)
|
||||||
|
#else
|
||||||
|
#define RESOURCE_TYPE(res, val)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct Resource Resource;
|
||||||
|
struct Resource {
|
||||||
|
UINT32 refs;
|
||||||
|
void* ptr;
|
||||||
|
#ifdef DBG
|
||||||
|
UINT32 type;
|
||||||
|
#endif
|
||||||
|
void (*free)(Resource *res);
|
||||||
|
UINT8 res[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
#define TIMEOUT_TO_MS ((LONGLONG) 1 * 10 * 1000)
|
||||||
|
|
||||||
|
#define WAIT_FOR_EVENT(event, timeout) do { \
|
||||||
|
NTSTATUS status; \
|
||||||
|
status = KeWaitForSingleObject ( \
|
||||||
|
&event, \
|
||||||
|
Executive, \
|
||||||
|
KernelMode, \
|
||||||
|
FALSE, \
|
||||||
|
timeout); \
|
||||||
|
ASSERT(NT_SUCCESS(status)); \
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
#define QXL_SLEEP(msec) do { \
|
||||||
|
LARGE_INTEGER timeout; \
|
||||||
|
timeout.QuadPart = -msec * TIMEOUT_TO_MS; \
|
||||||
|
KeDelayExecutionThread (KernelMode, FALSE, &timeout);\
|
||||||
|
} while (0);
|
||||||
|
|
||||||
|
|
||||||
|
#define MAX_OUTPUT_RES 6
|
||||||
|
|
||||||
|
typedef struct QXLOutput {
|
||||||
|
UINT32 num_res;
|
||||||
|
#ifdef DBG
|
||||||
|
UINT32 type;
|
||||||
|
#endif
|
||||||
|
Resource *resources[MAX_OUTPUT_RES];
|
||||||
|
UINT8 data[0];
|
||||||
|
} QXLOutput;
|
||||||
|
|
||||||
class QxlDevice :
|
class QxlDevice :
|
||||||
public HwDeviceIntrface
|
public HwDeviceIntrface
|
||||||
{
|
{
|
||||||
@ -332,17 +412,44 @@ public:
|
|||||||
VOID BlackOutScreen(CURRENT_BDD_MODE* pCurrentBddMod);
|
VOID BlackOutScreen(CURRENT_BDD_MODE* pCurrentBddMod);
|
||||||
protected:
|
protected:
|
||||||
NTSTATUS GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo);
|
NTSTATUS GetModeList(DXGK_DISPLAY_INFORMATION* pDispInfo);
|
||||||
|
VOID BltBits (
|
||||||
|
BLT_INFO* pDst,
|
||||||
|
CONST BLT_INFO* pSrc,
|
||||||
|
UINT NumRects,
|
||||||
|
_In_reads_(NumRects) CONST RECT *pRects);
|
||||||
|
QXLDrawable *Drawable(
|
||||||
|
UINT8 type,
|
||||||
|
CONST RECT *area,
|
||||||
|
CONST RECT *clip,
|
||||||
|
UINT32 surface_id);
|
||||||
|
QXLDrawable *GetDrawable();
|
||||||
|
void *AllocMem(UINT32 mspace_type, size_t size, BOOL force);
|
||||||
private:
|
private:
|
||||||
void UnmapMemory(void);
|
void UnmapMemory(void);
|
||||||
BOOL SetVideoModeInfo(UINT Idx, QXLMode* pModeInfo);
|
BOOL SetVideoModeInfo(UINT Idx, QXLMode* pModeInfo);
|
||||||
BOOL InitMemSlots(void);
|
BOOL InitMemSlots(void);
|
||||||
BOOL CreateMemSlots(void);
|
BOOL CreateMemSlots(void);
|
||||||
void DestroyMemSlots(void);
|
void DestroyMemSlots(void);
|
||||||
|
void CreatePrimarySurface(PVIDEO_MODE_INFORMATION pModeInfo);
|
||||||
|
void DestroyPrimarySurface(void);
|
||||||
void ResetDevice(void);
|
void ResetDevice(void);
|
||||||
void SetupHWSlot(UINT8 Idx, MemSlot *pSlot);
|
void SetupHWSlot(UINT8 Idx, MemSlot *pSlot);
|
||||||
UINT8 SetupMemSlot(UINT8 Idx, QXLPHYSICAL start, QXLPHYSICAL end);
|
UINT8 SetupMemSlot(UINT8 Idx, QXLPHYSICAL start, QXLPHYSICAL end);
|
||||||
BOOL CreateEvents();
|
BOOL CreateEvents(void);
|
||||||
BOOL CreateRings();
|
BOOL CreateRings(void);
|
||||||
|
UINT64 VA(QXLPHYSICAL paddr, UINT8 slot_id);
|
||||||
|
QXLPHYSICAL PA(PVOID virt, UINT8 slot_id);
|
||||||
|
void InitDeviceMemoryResources(void);
|
||||||
|
void InitMspace(UINT32 mspace_type, UINT8 *start, size_t capacity);
|
||||||
|
void FlushReleaseRing();
|
||||||
|
void FreeMem(UINT32 mspace_type, void *ptr);
|
||||||
|
UINT64 ReleaseOutput(UINT64 output_id);
|
||||||
|
void WaitForReleaseRing(void);
|
||||||
|
BOOL SetClip(const RECT *clip, QXLDrawable *drawable);
|
||||||
|
void AddRes(QXLOutput *output, Resource *res);
|
||||||
|
void DrawableAddRes(QXLDrawable *drawable, Resource *res);
|
||||||
|
void FreeClipRects(Resource *res);
|
||||||
|
void static FreeClipRectsEx(Resource *res);
|
||||||
private:
|
private:
|
||||||
PUCHAR m_IoBase;
|
PUCHAR m_IoBase;
|
||||||
BOOLEAN m_IoMapped;
|
BOOLEAN m_IoMapped;
|
||||||
@ -378,6 +485,12 @@ private:
|
|||||||
|
|
||||||
PUCHAR m_LogPort;
|
PUCHAR m_LogPort;
|
||||||
PUCHAR m_LogBuf;
|
PUCHAR m_LogBuf;
|
||||||
|
|
||||||
|
KSPIN_LOCK m_MemLock;
|
||||||
|
MspaceInfo m_MSInfo[NUM_MSPACES];
|
||||||
|
|
||||||
|
UINT64 free_outputs;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class QxlDod :
|
class QxlDod :
|
||||||
@ -517,6 +630,37 @@ private:
|
|||||||
|
|
||||||
|
|
||||||
NTSTATUS RegisterHWInfo();
|
NTSTATUS RegisterHWInfo();
|
||||||
|
/*
|
||||||
|
NTSTATUS ExecutePresentDisplayOnly(_In_ BYTE* DstAddr,
|
||||||
|
_In_ UINT DstBitPerPixel,
|
||||||
|
_In_ BYTE* SrcAddr,
|
||||||
|
_In_ UINT SrcBytesPerPixel,
|
||||||
|
_In_ LONG SrcPitch,
|
||||||
|
_In_ ULONG NumMoves,
|
||||||
|
_In_ D3DKMT_MOVE_RECT* pMoves,
|
||||||
|
_In_ ULONG NumDirtyRects,
|
||||||
|
_In_ RECT* pDirtyRect,
|
||||||
|
_In_ D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation);
|
||||||
|
BYTE* GetRowStart(_In_ CONST BLT_INFO* pBltInfo, CONST RECT* pRect);
|
||||||
|
VOID GetPitches(_In_ CONST BLT_INFO* pBltInfo, _Out_ LONG* pPixelPitch, _Out_ LONG* pRowPitch);
|
||||||
|
VOID CopyBitsGeneric(
|
||||||
|
BLT_INFO* pDst,
|
||||||
|
CONST BLT_INFO* pSrc,
|
||||||
|
UINT NumRects,
|
||||||
|
_In_reads_(NumRects) CONST RECT *pRects);
|
||||||
|
|
||||||
|
VOID CopyBits32_32(
|
||||||
|
BLT_INFO* pDst,
|
||||||
|
CONST BLT_INFO* pSrc,
|
||||||
|
UINT NumRects,
|
||||||
|
_In_reads_(NumRects) CONST RECT *pRects);
|
||||||
|
VOID BltBits (
|
||||||
|
BLT_INFO* pDst,
|
||||||
|
CONST BLT_INFO* pSrc,
|
||||||
|
UINT NumRects,
|
||||||
|
_In_reads_(NumRects) CONST RECT *pRects);
|
||||||
|
VOID BlackOutScreen(D3DDDI_VIDEO_PRESENT_SOURCE_ID SourceId);
|
||||||
|
*/
|
||||||
};
|
};
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
@ -532,6 +676,7 @@ UnmapFrameBuffer(
|
|||||||
|
|
||||||
UINT BPPFromPixelFormat(D3DDDIFORMAT Format);
|
UINT BPPFromPixelFormat(D3DDDIFORMAT Format);
|
||||||
D3DDDIFORMAT PixelFormatFromBPP(UINT BPP);
|
D3DDDIFORMAT PixelFormatFromBPP(UINT BPP);
|
||||||
|
UINT SpiceFromPixelFormat(D3DDDIFORMAT Format);
|
||||||
|
|
||||||
VOID CopyBitsGeneric(
|
VOID CopyBitsGeneric(
|
||||||
BLT_INFO* pDst,
|
BLT_INFO* pDst,
|
||||||
|
2437
qxldod/mspace.c
Executable file
2437
qxldod/mspace.c
Executable file
File diff suppressed because it is too large
Load Diff
150
qxldod/mspace.h
Executable file
150
qxldod/mspace.h
Executable file
@ -0,0 +1,150 @@
|
|||||||
|
#ifndef _H_MSPACE
|
||||||
|
#define _H_MSPACE
|
||||||
|
|
||||||
|
#define NO_MALLINFO 1
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
//typedef unsigned long size_t;
|
||||||
|
typedef void (*mspace_abort_t)(void *user_data);
|
||||||
|
typedef void (*mspace_print_t)(void *user_data, char *format, ...);
|
||||||
|
|
||||||
|
void mspace_set_abort_func(mspace_abort_t f);
|
||||||
|
void mspace_set_print_func(mspace_print_t f);
|
||||||
|
|
||||||
|
/*
|
||||||
|
mspace is an opaque type representing an independent
|
||||||
|
region of space that supports mspace_malloc, etc.
|
||||||
|
*/
|
||||||
|
typedef void* mspace;
|
||||||
|
|
||||||
|
/*
|
||||||
|
create_mspace creates and returns a new independent space with the
|
||||||
|
given initial capacity, or, if 0, the default granularity size. It
|
||||||
|
returns null if there is no system memory available to create the
|
||||||
|
space. If argument locked is non-zero, the space uses a separate
|
||||||
|
lock to control access. The capacity of the space will grow
|
||||||
|
dynamically as needed to service mspace_malloc requests. You can
|
||||||
|
control the sizes of incremental increases of this space by
|
||||||
|
compiling with a different DEFAULT_GRANULARITY or dynamically
|
||||||
|
setting with mallopt(M_GRANULARITY, value).
|
||||||
|
*/
|
||||||
|
//mspace create_mspace(size_t capacity, int locked);
|
||||||
|
|
||||||
|
/*
|
||||||
|
destroy_mspace destroys the given space, and attempts to return all
|
||||||
|
of its memory back to the system, returning the total number of
|
||||||
|
bytes freed. After destruction, the results of access to all memory
|
||||||
|
used by the space become undefined.
|
||||||
|
*/
|
||||||
|
//size_t destroy_mspace(mspace msp);
|
||||||
|
|
||||||
|
/*
|
||||||
|
create_mspace_with_base uses the memory supplied as the initial base
|
||||||
|
of a new mspace. Part (less than 128*sizeof(size_t) bytes) of this
|
||||||
|
space is used for bookkeeping, so the capacity must be at least this
|
||||||
|
large. (Otherwise 0 is returned.) When this initial space is
|
||||||
|
exhausted, additional memory will be obtained from the system.
|
||||||
|
Destroying this space will deallocate all additionally allocated
|
||||||
|
space (if possible) but not the initial base.
|
||||||
|
*/
|
||||||
|
mspace create_mspace_with_base(void* base, size_t capacity, int locked, void *user_data);
|
||||||
|
|
||||||
|
/*
|
||||||
|
mspace_malloc behaves as malloc, but operates within
|
||||||
|
the given space.
|
||||||
|
*/
|
||||||
|
void* mspace_malloc(mspace msp, size_t bytes);
|
||||||
|
|
||||||
|
/*
|
||||||
|
mspace_free behaves as free, but operates within
|
||||||
|
the given space.
|
||||||
|
|
||||||
|
If compiled with FOOTERS==1, mspace_free is not actually needed.
|
||||||
|
free may be called instead of mspace_free because freed chunks from
|
||||||
|
any space are handled by their originating spaces.
|
||||||
|
*/
|
||||||
|
void mspace_free(mspace msp, void* mem);
|
||||||
|
|
||||||
|
/*
|
||||||
|
mspace_realloc behaves as realloc, but operates within
|
||||||
|
the given space.
|
||||||
|
|
||||||
|
If compiled with FOOTERS==1, mspace_realloc is not actually
|
||||||
|
needed. realloc may be called instead of mspace_realloc because
|
||||||
|
realloced chunks from any space are handled by their originating
|
||||||
|
spaces.
|
||||||
|
*/
|
||||||
|
void* mspace_realloc(mspace msp, void* mem, size_t newsize);
|
||||||
|
|
||||||
|
/*
|
||||||
|
mspace_calloc behaves as calloc, but operates within
|
||||||
|
the given space.
|
||||||
|
*/
|
||||||
|
void* mspace_calloc(mspace msp, size_t n_elements, size_t elem_size);
|
||||||
|
|
||||||
|
/*
|
||||||
|
mspace_memalign behaves as memalign, but operates within
|
||||||
|
the given space.
|
||||||
|
*/
|
||||||
|
void* mspace_memalign(mspace msp, size_t alignment, size_t bytes);
|
||||||
|
|
||||||
|
/*
|
||||||
|
mspace_independent_calloc behaves as independent_calloc, but
|
||||||
|
operates within the given space.
|
||||||
|
*/
|
||||||
|
//void** mspace_independent_calloc(mspace msp, size_t n_elements,
|
||||||
|
// size_t elem_size, void* chunks[]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
mspace_independent_comalloc behaves as independent_comalloc, but
|
||||||
|
operates within the given space.
|
||||||
|
*/
|
||||||
|
//void** mspace_independent_comalloc(mspace msp, size_t n_elements,
|
||||||
|
// size_t sizes[], void* chunks[]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
mspace_footprint() returns the number of bytes obtained from the
|
||||||
|
system for this space.
|
||||||
|
*/
|
||||||
|
size_t mspace_footprint(mspace msp);
|
||||||
|
|
||||||
|
/*
|
||||||
|
mspace_max_footprint() returns the peak number of bytes obtained from the
|
||||||
|
system for this space.
|
||||||
|
*/
|
||||||
|
size_t mspace_max_footprint(mspace msp);
|
||||||
|
|
||||||
|
|
||||||
|
#if !NO_MALLINFO
|
||||||
|
/*
|
||||||
|
mspace_mallinfo behaves as mallinfo, but reports properties of
|
||||||
|
the given space.
|
||||||
|
*/
|
||||||
|
struct mallinfo mspace_mallinfo(mspace msp);
|
||||||
|
#endif /* NO_MALLINFO */
|
||||||
|
|
||||||
|
/*
|
||||||
|
mspace_malloc_stats behaves as malloc_stats, but reports
|
||||||
|
properties of the given space.
|
||||||
|
*/
|
||||||
|
void mspace_malloc_stats(mspace msp);
|
||||||
|
|
||||||
|
/*
|
||||||
|
mspace_trim behaves as malloc_trim, but
|
||||||
|
operates within the given space.
|
||||||
|
*/
|
||||||
|
//int mspace_trim(mspace msp, size_t pad);
|
||||||
|
|
||||||
|
/*
|
||||||
|
An alias for mallopt.
|
||||||
|
*/
|
||||||
|
int mspace_mallopt(int, int);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}; /* end of extern "C" */
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
#endif
|
@ -156,6 +156,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="BaseObject.cpp" />
|
<ClCompile Include="BaseObject.cpp" />
|
||||||
<ClCompile Include="driver.cpp" />
|
<ClCompile Include="driver.cpp" />
|
||||||
|
<ClCompile Include="mspace.c" />
|
||||||
<ClCompile Include="QxlDod.cpp" />
|
<ClCompile Include="QxlDod.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
Loading…
Reference in New Issue
Block a user