1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS kernel 4 * PURPOSE: Support for meta devices 5 * FILE: win32ss/gdi/eng/mdevobj.c 6 * PROGRAMER: Hervé Poussineau 7 */ 8 9 #include <win32k.h> 10 #define NDEBUG 11 #include <debug.h> 12 DBG_DEFAULT_CHANNEL(EngMDev); 13 14 PMDEVOBJ gpmdev = NULL; /* FIXME: should be stored in gpDispInfo->pmdev */ 15 16 VOID 17 MDEVOBJ_vEnable( 18 _Inout_ PMDEVOBJ pmdev) 19 { 20 ULONG i; 21 22 for (i = 0; i < pmdev->cDev; i++) 23 { 24 PDEVOBJ_vEnableDisplay(pmdev->dev[i].ppdev); 25 } 26 } 27 28 BOOL 29 MDEVOBJ_bDisable( 30 _Inout_ PMDEVOBJ pmdev) 31 { 32 BOOL bSuccess = TRUE; 33 ULONG i, j; 34 35 for (i = 0; i < pmdev->cDev; i++) 36 { 37 if (!PDEVOBJ_bDisableDisplay(pmdev->dev[i].ppdev)) 38 { 39 bSuccess = FALSE; 40 break; 41 } 42 } 43 44 if (!bSuccess) 45 { 46 /* Failed to disable all PDEVs. Reenable those we have disabled */ 47 for (j = 0; j < i; j++) 48 { 49 PDEVOBJ_vEnableDisplay(pmdev->dev[i].ppdev); 50 } 51 } 52 53 return bSuccess; 54 } 55 56 PMDEVOBJ 57 MDEVOBJ_Create( 58 _In_opt_ PUNICODE_STRING pustrDeviceName, 59 _In_opt_ PDEVMODEW pdm) 60 { 61 PMDEVOBJ pmdev = NULL; 62 PPDEVOBJ ppdev; 63 PGRAPHICS_DEVICE pGraphicsDevice; 64 DEVMODEW dmDefault; 65 PDEVMODEW localPdm; 66 ULONG iDevNum = 0; 67 ULONG dwAccelerationLevel = 0; 68 69 TRACE("MDEVOBJ_Create('%wZ' '%dx%dx%d (%d Hz)')\n", 70 pustrDeviceName, 71 pdm ? pdm->dmPelsWidth : 0, 72 pdm ? pdm->dmPelsHeight : 0, 73 pdm ? pdm->dmBitsPerPel : 0, 74 pdm ? pdm->dmDisplayFrequency : 0); 75 76 pmdev = ExAllocatePoolZero(PagedPool, sizeof(MDEVOBJ) + sizeof(MDEVDISPLAY), GDITAG_MDEV); 77 if (!pmdev) 78 { 79 ERR("Failed to allocate memory for MDEV\n"); 80 return NULL; 81 } 82 83 pmdev->cDev = 0; 84 85 while (TRUE) 86 { 87 /* Get the right graphics devices: either the specified one, or all of them (one after one) */ 88 if (pustrDeviceName) 89 pGraphicsDevice = (iDevNum == 0) ? EngpFindGraphicsDevice(pustrDeviceName, 0) : NULL; 90 else 91 pGraphicsDevice = EngpFindGraphicsDevice(NULL, iDevNum); 92 iDevNum++; 93 94 if (!pGraphicsDevice) 95 { 96 TRACE("Done enumeration of graphic devices (DeviceName '%wZ' iDevNum %d)\n", pustrDeviceName, iDevNum); 97 break; 98 } 99 100 if (!pdm) 101 { 102 /* No settings requested. Provide nothing and LDEVOBJ_bProbeAndCaptureDevmode 103 * will read default settings from registry */ 104 RtlZeroMemory(&dmDefault, sizeof(dmDefault)); 105 dmDefault.dmSize = sizeof(dmDefault); 106 } 107 108 dwAccelerationLevel = EngpGetDisplayDriverAccelerationLevel(pGraphicsDevice); 109 110 /* Get or create a PDEV for these settings */ 111 if (LDEVOBJ_bProbeAndCaptureDevmode(pGraphicsDevice, pdm ? pdm : &dmDefault, &localPdm, !pdm)) 112 { 113 ppdev = PDEVOBJ_Create(pGraphicsDevice, localPdm, dwAccelerationLevel, LDEV_DEVICE_DISPLAY); 114 } 115 else 116 { 117 ppdev = NULL; 118 } 119 120 if (ppdev) 121 { 122 /* Great. We have a found a matching PDEV. Store it in MDEV */ 123 if (pmdev->cDev >= 1) 124 { 125 /* We have to reallocate MDEV to add space for the new display */ 126 PMDEVOBJ pmdevBigger = ExAllocatePoolZero(PagedPool, sizeof(MDEVOBJ) + (pmdev->cDev + 1) * sizeof(MDEVDISPLAY), GDITAG_MDEV); 127 if (!pmdevBigger) 128 { 129 WARN("Failed to allocate memory for MDEV. Skipping display '%S'\n", pGraphicsDevice->szWinDeviceName); 130 continue; 131 } 132 else 133 { 134 /* Copy existing data */ 135 RtlCopyMemory(pmdevBigger, pmdev, sizeof(MDEVOBJ) + pmdev->cDev * sizeof(MDEVDISPLAY)); 136 ExFreePoolWithTag(pmdev, GDITAG_MDEV); 137 pmdev = pmdevBigger; 138 } 139 } 140 141 TRACE("Adding '%S' to MDEV %p\n", pGraphicsDevice->szWinDeviceName, pmdev); 142 PDEVOBJ_vReference(ppdev); 143 pmdev->dev[pmdev->cDev].ppdev = ppdev; 144 pmdev->cDev++; 145 } 146 else 147 { 148 WARN("Failed to add '%S' to MDEV %p\n", pGraphicsDevice->szWinDeviceName, pmdev); 149 } 150 } 151 152 if (pmdev->cDev == 0) 153 { 154 TRACE("Failed to add any device to MDEV. Returning NULL\n"); 155 MDEVOBJ_vDestroy(pmdev); 156 return NULL; 157 } 158 159 TRACE("Returning new MDEV %p with %d devices\n", pmdev, pmdev->cDev); 160 return pmdev; 161 } 162 163 VOID 164 MDEVOBJ_vDestroy( 165 _Inout_ PMDEVOBJ pmdev) 166 { 167 ULONG i; 168 169 for (i = 0; i < pmdev->cDev; i++) 170 { 171 PDEVOBJ_vRelease(pmdev->dev[i].ppdev); 172 } 173 174 if (pmdev->cDev > 1) 175 PDEVOBJ_vRelease(pmdev->ppdevGlobal); 176 177 ExFreePoolWithTag(pmdev, GDITAG_MDEV); 178 } 179