Files
mirror-processhacker/2.x/trunk/plugins/ExtendedTools/gpunodes.c
T
wj32 36a4284b8d converted all annotations to SAL 2.0
git-svn-id: svn://svn.code.sf.net/p/processhacker/code@5548 21ef857c-d57f-4fe0-8362-d861dc6d29cd
2013-11-10 06:25:03 +00:00

405 lines
13 KiB
C

/*
* Process Hacker Extended Tools -
* GPU nodes window
*
* Copyright (C) 2011 wj32
*
* This file is part of Process Hacker.
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Process Hacker is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#include "exttools.h"
#include "resource.h"
#include <windowsx.h>
#define UPDATE_MSG (WM_APP + 1)
#define GRAPH_PADDING 5
#define CHECKBOX_PADDING 3
INT_PTR CALLBACK EtpGpuNodesDlgProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
static HWND WindowHandle;
static RECT MinimumSize;
static PH_LAYOUT_MANAGER LayoutManager;
static RECT LayoutMargin;
static HWND *GraphHandle;
static HWND *CheckBoxHandle;
static PPH_GRAPH_STATE GraphState;
static PPH_SYSINFO_PARAMETERS SysInfoParameters;
static PH_CALLBACK_REGISTRATION ProcessesUpdatedCallbackRegistration;
VOID EtShowGpuNodesDialog(
_In_ HWND ParentWindowHandle,
_In_ PPH_SYSINFO_PARAMETERS Parameters
)
{
SysInfoParameters = Parameters;
DialogBox(
PluginInstance->DllBase,
MAKEINTRESOURCE(IDD_GPUNODES),
ParentWindowHandle,
EtpGpuNodesDlgProc
);
}
static VOID ProcessesUpdatedCallback(
_In_opt_ PVOID Parameter,
_In_opt_ PVOID Context
)
{
PostMessage(WindowHandle, UPDATE_MSG, 0, 0);
}
VOID EtpLoadNodeBitMap(
VOID
)
{
ULONG i;
for (i = 0; i < EtGpuTotalNodeCount; i++)
{
Button_SetCheck(
CheckBoxHandle[i],
RtlCheckBit(&EtGpuNodeBitMap, i) ? BST_CHECKED : BST_UNCHECKED
);
}
}
VOID EtpSaveNodeBitMap(
VOID
)
{
RTL_BITMAP newBitMap;
ULONG i;
EtAllocateGpuNodeBitMap(&newBitMap);
for (i = 0; i < EtGpuTotalNodeCount; i++)
{
if (Button_GetCheck(CheckBoxHandle[i]) == BST_CHECKED)
RtlSetBits(&newBitMap, i, 1);
}
if (RtlNumberOfSetBits(&newBitMap) == 0)
RtlSetBits(&newBitMap, 0, 1);
EtUpdateGpuNodeBitMap(&newBitMap);
}
INT_PTR CALLBACK EtpGpuNodesDlgProc(
_In_ HWND hwndDlg,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
)
{
switch (uMsg)
{
case WM_INITDIALOG:
{
ULONG i;
HFONT font;
PPH_STRING nodeString;
RECT labelRect;
RECT tempRect;
WindowHandle = hwndDlg;
PhCenterWindow(hwndDlg, GetParent(hwndDlg));
PhInitializeLayoutManager(&LayoutManager, hwndDlg);
PhAddLayoutItem(&LayoutManager, GetDlgItem(hwndDlg, IDOK), NULL, PH_ANCHOR_RIGHT | PH_ANCHOR_BOTTOM);
LayoutMargin = PhAddLayoutItem(&LayoutManager, GetDlgItem(hwndDlg, IDC_LAYOUT), NULL, PH_ANCHOR_ALL)->Margin;
PhRegisterCallback(&PhProcessesUpdatedEvent, ProcessesUpdatedCallback, NULL, &ProcessesUpdatedCallbackRegistration);
GraphHandle = PhAllocate(sizeof(HWND) * EtGpuTotalNodeCount);
CheckBoxHandle = PhAllocate(sizeof(HWND) * EtGpuTotalNodeCount);
GraphState = PhAllocate(sizeof(PH_GRAPH_STATE) * EtGpuTotalNodeCount);
font = (HFONT)SendMessage(hwndDlg, WM_GETFONT, 0, 0);
for (i = 0; i < EtGpuTotalNodeCount; i++)
{
nodeString = PhFormatString(L"Node %u", i);
GraphHandle[i] = CreateWindow(
PH_GRAPH_CLASSNAME,
NULL,
WS_VISIBLE | WS_CHILD | WS_BORDER,
0,
0,
3,
3,
hwndDlg,
(HMENU)10000 + i,
PluginInstance->DllBase,
NULL
);
Graph_SetTooltip(GraphHandle[i], TRUE);
CheckBoxHandle[i] = CreateWindow(
L"BUTTON",
nodeString->Buffer,
WS_VISIBLE | WS_CHILD | BS_AUTOCHECKBOX,
0,
0,
3,
3,
hwndDlg,
(HMENU)20000 + i,
PluginInstance->DllBase,
NULL
);
SendMessage(CheckBoxHandle[i], WM_SETFONT, (WPARAM)font, FALSE);
PhInitializeGraphState(&GraphState[i]);
PhDereferenceObject(nodeString);
}
// Calculate the minimum size.
MinimumSize.left = 0;
MinimumSize.top = 0;
MinimumSize.right = 45;
MinimumSize.bottom = 170;
MapDialogRect(hwndDlg, &MinimumSize);
MinimumSize.right += (MinimumSize.right + GRAPH_PADDING) * EtGpuTotalNodeCount;
GetWindowRect(GetDlgItem(hwndDlg, IDC_INSTRUCTION), &labelRect);
MapWindowPoints(NULL, hwndDlg, (POINT *)&labelRect, 2);
labelRect.right += GetSystemMetrics(SM_CXFRAME) * 2;
tempRect.left = 0;
tempRect.top = 0;
tempRect.right = 7;
tempRect.bottom = 0;
MapDialogRect(hwndDlg, &tempRect);
labelRect.right += tempRect.right;
if (MinimumSize.right < labelRect.right)
MinimumSize.right = labelRect.right;
SetWindowPos(hwndDlg, NULL, 0, 0, MinimumSize.right, MinimumSize.bottom, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER);
EtpLoadNodeBitMap();
}
break;
case WM_DESTROY:
{
ULONG i;
EtpSaveNodeBitMap();
PhUnregisterCallback(&PhProcessesUpdatedEvent, &ProcessesUpdatedCallbackRegistration);
for (i = 0; i < EtGpuTotalNodeCount; i++)
{
PhDeleteGraphState(&GraphState[i]);
}
PhFree(GraphHandle);
PhFree(CheckBoxHandle);
PhFree(GraphState);
PhDeleteLayoutManager(&LayoutManager);
}
break;
case WM_SIZE:
{
HDWP deferHandle;
RECT clientRect;
RECT checkBoxRect;
ULONG i;
ULONG availableWidth;
ULONG graphWidth;
ULONG x;
PhLayoutManagerLayout(&LayoutManager);
deferHandle = BeginDeferWindowPos(EtGpuTotalNodeCount * 2);
GetClientRect(hwndDlg, &clientRect);
GetClientRect(GetDlgItem(hwndDlg, IDC_EXAMPLE), &checkBoxRect);
availableWidth = clientRect.right - LayoutMargin.left - LayoutMargin.right;
graphWidth = (availableWidth - GRAPH_PADDING * (EtGpuTotalNodeCount - 1)) / EtGpuTotalNodeCount;
x = LayoutMargin.left;
for (i = 0; i < EtGpuTotalNodeCount; i++)
{
if (i == EtGpuTotalNodeCount - 1)
{
graphWidth = clientRect.right - LayoutMargin.right - x;
}
deferHandle = DeferWindowPos(
deferHandle,
GraphHandle[i],
NULL,
x,
LayoutMargin.top,
graphWidth,
clientRect.bottom - LayoutMargin.top - LayoutMargin.bottom - checkBoxRect.bottom - CHECKBOX_PADDING,
SWP_NOACTIVATE | SWP_NOZORDER
);
deferHandle = DeferWindowPos(
deferHandle,
CheckBoxHandle[i],
NULL,
x,
clientRect.bottom - LayoutMargin.bottom - checkBoxRect.bottom,
graphWidth,
checkBoxRect.bottom,
SWP_NOACTIVATE | SWP_NOZORDER
);
x += graphWidth + GRAPH_PADDING;
}
EndDeferWindowPos(deferHandle);
}
break;
case WM_SIZING:
{
PhResizingMinimumSize((PRECT)lParam, wParam, MinimumSize.right, MinimumSize.bottom);
}
break;
case WM_COMMAND:
{
switch (LOWORD(wParam))
{
case IDCANCEL:
case IDOK:
{
EndDialog(hwndDlg, IDOK);
}
break;
}
}
break;
case WM_NOTIFY:
{
NMHDR *header = (NMHDR *)lParam;
ULONG i;
switch (header->code)
{
case GCN_GETDRAWINFO:
{
PPH_GRAPH_GETDRAWINFO getDrawInfo = (PPH_GRAPH_GETDRAWINFO)header;
PPH_GRAPH_DRAW_INFO drawInfo = getDrawInfo->DrawInfo;
drawInfo->Flags = PH_GRAPH_USE_GRID;
SysInfoParameters->ColorSetupFunction(drawInfo, PhGetIntegerSetting(L"ColorCpuKernel"), 0);
for (i = 0; i < EtGpuTotalNodeCount; i++)
{
if (header->hwndFrom == GraphHandle[i])
{
PhGraphStateGetDrawInfo(
&GraphState[i],
getDrawInfo,
EtGpuNodesHistory[i].Count
);
if (!GraphState[i].Valid)
{
PhCopyCircularBuffer_FLOAT(&EtGpuNodesHistory[i], GraphState[i].Data1, drawInfo->LineDataCount);
GraphState[i].Valid = TRUE;
}
break;
}
}
}
break;
case GCN_GETTOOLTIPTEXT:
{
PPH_GRAPH_GETTOOLTIPTEXT getTooltipText = (PPH_GRAPH_GETTOOLTIPTEXT)header;
if (getTooltipText->Index < getTooltipText->TotalCount)
{
for (i = 0; i < EtGpuTotalNodeCount; i++)
{
if (header->hwndFrom == GraphHandle[i])
{
if (GraphState[i].TooltipIndex != getTooltipText->Index)
{
FLOAT gpu;
ULONG adapterIndex;
PPH_STRING adapterDescription;
gpu = PhGetItemCircularBuffer_FLOAT(&EtGpuNodesHistory[i], getTooltipText->Index);
adapterIndex = EtGetGpuAdapterIndexFromNodeIndex(i);
if (adapterIndex != -1)
{
adapterDescription = EtGetGpuAdapterDescription(adapterIndex);
if (adapterDescription && adapterDescription->Length == 0)
PhSwapReference(&adapterDescription, NULL);
if (!adapterDescription)
adapterDescription = PhFormatString(L"Adapter %u", adapterIndex);
}
else
{
adapterDescription = PhCreateString(L"Unknown Adapter");
}
PhSwapReference2(&GraphState[i].TooltipText, PhFormatString(
L"Node %u on %s\n%.2f%%\n%s",
i,
adapterDescription->Buffer,
gpu * 100,
((PPH_STRING)PHA_DEREFERENCE(PhGetStatisticsTimeString(NULL, getTooltipText->Index)))->Buffer
));
PhDereferenceObject(adapterDescription);
}
getTooltipText->Text = GraphState[i].TooltipText->sr;
break;
}
}
}
}
break;
}
}
break;
case UPDATE_MSG:
{
ULONG i;
for (i = 0; i < EtGpuTotalNodeCount; i++)
{
GraphState[i].Valid = FALSE;
GraphState[i].TooltipIndex = -1;
Graph_MoveGrid(GraphHandle[i], 1);
Graph_Draw(GraphHandle[i]);
Graph_UpdateTooltip(GraphHandle[i]);
InvalidateRect(GraphHandle[i], NULL, FALSE);
}
}
break;
}
return FALSE;
}