gdi和dx比较研究
gdi设备获取的源头, 同样是通过底层驱动来进行实现
PGRAPHICS_DEVICE
NTAPI
EngpRegisterGraphicsDevice(
PUNICODE_STRING pustrDeviceName,
PUNICODE_STRING pustrDiplayDrivers,
PUNICODE_STRING pustrDescription,
PDEVMODEW pdmDefault)
{
PGRAPHICS_DEVICE pGraphicsDevice;
PDEVICE_OBJECT pDeviceObject;
PFILE_OBJECT pFileObject;
NTSTATUS Status;
PWSTR pwsz;
ULONG i, cj, cModes = 0;
BOOL bEnable = TRUE;
PDEVMODEINFO pdminfo;
PDEVMODEW pdm, pdmEnd;
PLDEVOBJ pldev;
DPRINT("EngpRegisterGraphicsDevice(%wZ)\n", pustrDeviceName);
/* Allocate a GRAPHICS_DEVICE structure */
pGraphicsDevice = ExAllocatePoolWithTag(PagedPool,
sizeof(GRAPHICS_DEVICE),
GDITAG_GDEVICE);
if (!pGraphicsDevice)
{
DPRINT1("ExAllocatePoolWithTag failed\n");
return NULL;
}
/* Try to open the driver */
// 找到gdi设备获取的初始源头了,就是这里
Status = IoGetDeviceObjectPointer(pustrDeviceName,
FILE_READ_DATA | FILE_WRITE_DATA,
&pFileObject,
&pDeviceObject);
if (!NT_SUCCESS(Status))
{
DPRINT1("Could not open driver %wZ, 0x%lx\n", pustrDeviceName, Status);
ExFreePoolWithTag(pGraphicsDevice, GDITAG_GDEVICE);
return NULL;
}
/* Enable the device */
EngFileWrite(pFileObject, &bEnable, sizeof(BOOL), &cj);
/* Copy the device and file object pointers */
pGraphicsDevice->DeviceObject = pDeviceObject;
pGraphicsDevice->FileObject = pFileObject;
/* Copy device name */
wcsncpy(pGraphicsDevice->szNtDeviceName,
pustrDeviceName->Buffer,
sizeof(pGraphicsDevice->szNtDeviceName) / sizeof(WCHAR));
/* Create a win device name (FIXME: virtual devices!) */
swprintf(pGraphicsDevice->szWinDeviceName, L"\\\\.\\VIDEO%d", (CHAR)giDevNum);
/* Allocate a buffer for the strings */
cj = pustrDiplayDrivers->Length + pustrDescription->Length + sizeof(WCHAR);
pwsz = ExAllocatePoolWithTag(PagedPool, cj, GDITAG_DRVSUP);
if (!pwsz)
{
DPRINT1("Could not allocate string buffer\n");
ASSERT(FALSE); // FIXME
}
/* Copy display driver names */
pGraphicsDevice->pDiplayDrivers = pwsz;
RtlCopyMemory(pGraphicsDevice->pDiplayDrivers,
pustrDiplayDrivers->Buffer,
pustrDiplayDrivers->Length);
/* Copy description */
pGraphicsDevice->pwszDescription = pwsz + pustrDiplayDrivers->Length / sizeof(WCHAR);
RtlCopyMemory(pGraphicsDevice->pwszDescription,
pustrDescription->Buffer,
pustrDescription->Length + sizeof(WCHAR));
/* Initialize the pdevmodeInfo list and default index */
pGraphicsDevice->pdevmodeInfo = NULL;
pGraphicsDevice->iDefaultMode = 0;
pGraphicsDevice->iCurrentMode = 0;
// FIXME: initialize state flags
pGraphicsDevice->StateFlags = 0;
/* Loop through the driver names
* This is a REG_MULTI_SZ string */
for (; *pwsz; pwsz += wcslen(pwsz) + 1)
{
DPRINT("trying driver: %ls\n", pwsz);
/* Try to load the display driver */
pldev = EngLoadImageEx(pwsz, LDEV_DEVICE_DISPLAY);
if (!pldev)
{
DPRINT1("Could not load driver: '%ls'\n", pwsz);
continue;
}
/* Get the mode list from the driver */
pdminfo = LDEVOBJ_pdmiGetModes(pldev, pDeviceObject);
if (!pdminfo)
{
DPRINT1("Could not get mode list for '%ls'\n", pwsz);
continue;
}
/* Attach the mode info to the device */
pdminfo->pdmiNext = pGraphicsDevice->pdevmodeInfo;
pGraphicsDevice->pdevmodeInfo = pdminfo;
/* Count DEVMODEs */
pdmEnd = (DEVMODEW*)((PCHAR)pdminfo->adevmode + pdminfo->cbdevmode);
for (pdm = pdminfo->adevmode;
pdm + 1 <= pdmEnd;
pdm = (DEVMODEW*)((PCHAR)pdm + pdm->dmSize + pdm->dmDriverExtra))
{
cModes++;
}
// FIXME: release the driver again until it's used?
}
if (!pGraphicsDevice->pdevmodeInfo || cModes == 0)
{
DPRINT1("No devmodes\n");
ExFreePool(pGraphicsDevice);
return NULL;
}
/* Allocate an index buffer */
pGraphicsDevice->cDevModes = cModes;
pGraphicsDevice->pDevModeList = ExAllocatePoolWithTag(PagedPool,
cModes * sizeof(DEVMODEENTRY),
GDITAG_GDEVICE);
if (!pGraphicsDevice->pDevModeList)
{
DPRINT1("No devmode list\n");
ExFreePool(pGraphicsDevice);
return NULL;
}
/* Loop through all DEVMODEINFOs */
for (pdminfo = pGraphicsDevice->pdevmodeInfo, i = 0;
pdminfo;
pdminfo = pdminfo->pdmiNext)
{
/* Calculate End of the DEVMODEs */
pdmEnd = (DEVMODEW*)((PCHAR)pdminfo->adevmode + pdminfo->cbdevmode);
/* Loop through the DEVMODEs */
for (pdm = pdminfo->adevmode;
pdm + 1 <= pdmEnd;
pdm = (PDEVMODEW)((PCHAR)pdm + pdm->dmSize + pdm->dmDriverExtra))
{
/* Compare with the default entry */
if (pdm->dmBitsPerPel == pdmDefault->dmBitsPerPel &&
pdm->dmPelsWidth == pdmDefault->dmPelsWidth &&
pdm->dmPelsHeight == pdmDefault->dmPelsHeight &&
pdm->dmDisplayFrequency == pdmDefault->dmDisplayFrequency)
{
pGraphicsDevice->iDefaultMode = i;
pGraphicsDevice->iCurrentMode = i;
DPRINT("Found default entry: %ld '%ls'\n", i, pdm->dmDeviceName);
}
/* Initialize the entry */
pGraphicsDevice->pDevModeList[i].dwFlags = 0;
pGraphicsDevice->pDevModeList[i].pdm = pdm;
i++;
}
}
/* Lock loader */
EngAcquireSemaphore(ghsemGraphicsDeviceList);
/* Insert the device into the global list */
pGraphicsDevice->pNextGraphicsDevice = gpGraphicsDeviceLast;
gpGraphicsDeviceLast = pGraphicsDevice;
if (!gpGraphicsDeviceFirst)
gpGraphicsDeviceFirst = pGraphicsDevice;
/* Increment device number */
giDevNum++;
/* Unlock loader */
EngReleaseSemaphore(ghsemGraphicsDeviceList);
DPRINT("Prepared %ld modes for %ls\n", cModes, pGraphicsDevice->pwszDescription);
return pGraphicsDevice;
}
static BOOL IsDirectDrawSupported()
dx9里面的这个功能原来是直接调用 dc里面的信息来返回啊,哈哈
gdi和dx其实使用的是同一个显示驱动, 只不过由于gdi是专门为桌面系统而进行封装的, 对象游戏使用来说显然效率、易用性方面还大大不足, 于是根据用途不同就分成了gdi和dx的区别