2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: Functions for saving and restoring dc states
5 * FILE: subsystem/win32/win32k/objects/dcstate.c
6 * PROGRAMER: Timo Kreuzer (timo.kreuzer@rectos.org)
16 DC_vCopyState(PDC pdcSrc
, PDC pdcDst
, BOOL To
)
18 DPRINT("DC_vCopyState(%p, %p)\n", pdcSrc
->BaseObject
.hHmgr
, pdcDst
->BaseObject
.hHmgr
);
20 /* Copy full DC attribute */
21 *pdcDst
->pdcattr
= *pdcSrc
->pdcattr
;
23 /* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
24 /* The VisRectRegion field needs to be set to a valid state */
26 /* Mark some fields as dirty */
27 pdcDst
->pdcattr
->ulDirty_
|= 0x0012001f; // Note: Use if, To is FALSE....
30 pdcDst
->dclevel
.pColorSpace
= pdcSrc
->dclevel
.pColorSpace
;
31 pdcDst
->dclevel
.lSaveDepth
= pdcSrc
->dclevel
.lSaveDepth
;
32 pdcDst
->dclevel
.hdcSave
= pdcSrc
->dclevel
.hdcSave
;
33 pdcDst
->dclevel
.laPath
= pdcSrc
->dclevel
.laPath
;
34 pdcDst
->dclevel
.ca
= pdcSrc
->dclevel
.ca
;
35 pdcDst
->dclevel
.mxWorldToDevice
= pdcSrc
->dclevel
.mxWorldToDevice
;
36 pdcDst
->dclevel
.mxDeviceToWorld
= pdcSrc
->dclevel
.mxDeviceToWorld
;
37 pdcDst
->dclevel
.mxWorldToPage
= pdcSrc
->dclevel
.mxWorldToPage
;
38 pdcDst
->dclevel
.efM11PtoD
= pdcSrc
->dclevel
.efM11PtoD
;
39 pdcDst
->dclevel
.efM22PtoD
= pdcSrc
->dclevel
.efM22PtoD
;
40 pdcDst
->dclevel
.sizl
= pdcSrc
->dclevel
.sizl
;
41 pdcDst
->dclevel
.hpal
= pdcSrc
->dclevel
.hpal
;
43 /* Handle references here correctly */
44 DC_vSelectFillBrush(pdcDst
, pdcSrc
->dclevel
.pbrFill
);
45 DC_vSelectLineBrush(pdcDst
, pdcSrc
->dclevel
.pbrLine
);
46 DC_vSelectPalette(pdcDst
, pdcSrc
->dclevel
.ppal
);
49 pdcDst
->dclevel
.plfnt
= pdcSrc
->dclevel
.plfnt
;
52 if (pdcDst
->dctype
!= DC_TYPE_MEMORY
)
54 pdcDst
->rosdc
.bitsPerPixel
= pdcSrc
->rosdc
.bitsPerPixel
;
57 /* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
58 if (To
) // Copy "To" SaveDC state.
60 if (pdcSrc
->rosdc
.hClipRgn
)
62 pdcDst
->rosdc
.hClipRgn
= IntSysCreateRectRgn(0, 0, 0, 0);
63 NtGdiCombineRgn(pdcDst
->rosdc
.hClipRgn
, pdcSrc
->rosdc
.hClipRgn
, 0, RGN_COPY
);
65 // FIXME! Handle prgnMeta!
67 else // Copy "!To" RestoreDC state.
68 { /* The VisRectRegion field needs to be set to a valid state */
69 GdiExtSelectClipRgn(pdcDst
, pdcSrc
->rosdc
.hClipRgn
, RGN_COPY
);
75 IntGdiCleanDC(HDC hDC
)
78 if (!hDC
) return FALSE
;
80 if (!dc
) return FALSE
;
82 if (defaultDCstate
) DC_vCopyState(defaultDCstate
, dc
, FALSE
);
84 if (dc
->dctype
!= DC_TYPE_MEMORY
)
86 dc
->rosdc
.bitsPerPixel
= defaultDCstate
->rosdc
.bitsPerPixel
;
101 IN OPTIONAL VOID
*pDriverInfo2
,
102 OUT VOID
*ppUMdhpdev
)
115 PEPROCESS pepCurrentProcess
;
119 ASSERT(iSaveLevel
> 0);
120 DPRINT("DC_vRestoreDC(%p, %ld)\n", pdc
->BaseObject
.hHmgr
, iSaveLevel
);
122 /* Get current process */
123 pepCurrentProcess
= PsGetCurrentProcess();
125 /* Loop the save levels */
126 while (pdc
->dclevel
.lSaveDepth
> iSaveLevel
)
128 hdcSave
= pdc
->dclevel
.hdcSave
;
129 DPRINT("RestoreDC = %p\n", hdcSave
);
131 /* Set us as the owner */
132 if (!GDIOBJ_SetOwnership(hdcSave
, pepCurrentProcess
))
134 /* Could not get ownership. That's bad! */
135 DPRINT1("Could not get ownership of saved DC (%p) for hdc %p!\n",
136 hdcSave
, pdc
->BaseObject
.hHmgr
);
140 /* Lock the saved dc */
141 pdcSave
= DC_LockDc(hdcSave
);
144 /* WTF? Internal error! */
145 DPRINT1("Could not lock the saved DC (%p) for dc %p!\n",
146 hdcSave
, pdc
->BaseObject
.hHmgr
);
150 /* Remove the saved dc from the queue */
151 pdc
->dclevel
.hdcSave
= pdcSave
->dclevel
.hdcSave
;
153 /* Decrement save level */
154 pdc
->dclevel
.lSaveDepth
--;
156 /* Is this the state we want? */
157 if (pdc
->dclevel
.lSaveDepth
== iSaveLevel
)
159 /* Copy the state back */
160 DC_vCopyState(pdcSave
, pdc
, FALSE
);
162 /* Only memory DC's change their surface */
163 if (pdcSave
->dctype
== DCTYPE_MEMORY
)
164 DC_vSelectSurface(pdc
, pdcSave
->dclevel
.pSurface
);
166 // Restore Path by removing it, if the Save flag is set.
167 // BeginPath will takecare of the rest.
168 if (pdc
->dclevel
.hPath
&& pdc
->dclevel
.flPath
& DCPATH_SAVE
)
170 PATH_Delete(pdc
->dclevel
.hPath
);
171 pdc
->dclevel
.hPath
= 0;
172 pdc
->dclevel
.flPath
&= ~DCPATH_SAVE
;
176 /* Prevent save dc from being restored */
177 pdcSave
->dclevel
.lSaveDepth
= 1;
180 DC_UnlockDc(pdcSave
);
181 /* Delete the saved dc */
182 GreDeleteObject(hdcSave
);
185 DPRINT("Leave DC_vRestoreDC()\n");
198 DPRINT("NtGdiRestoreDC(%p, %d)\n", hdc
, iSaveLevel
);
200 /* Lock the original DC */
201 pdc
= DC_LockDc(hdc
);
204 SetLastWin32Error(ERROR_INVALID_HANDLE
);
208 ASSERT(pdc
->dclevel
.lSaveDepth
> 0);
210 /* Negative values are relative to the stack top */
212 iSaveLevel
= pdc
->dclevel
.lSaveDepth
+ iSaveLevel
;
214 /* Check if we have a valid instance */
215 if (iSaveLevel
<= 0 || iSaveLevel
>= pdc
->dclevel
.lSaveDepth
)
217 DPRINT("Illegal save level, requested: %ld, current: %ld\n",
218 iSaveLevel
, pdc
->dclevel
.lSaveDepth
);
220 SetLastWin32Error(ERROR_INVALID_PARAMETER
);
224 /* Call the internal function */
225 DC_vRestoreDC(pdc
, iSaveLevel
);
229 DPRINT("Leave NtGdiRestoreDC\n");
243 DPRINT("NtGdiSaveDC(%p)\n", hDC
);
245 /* Lock the original dc */
246 pdc
= DC_LockDc(hDC
);
249 DPRINT("Could not lock DC\n");
250 SetLastWin32Error(ERROR_INVALID_HANDLE
);
254 /* Allocate a new dc */
255 pdcSave
= DC_AllocDcWithHandle();
258 DPRINT("Could not allocate a new DC\n");
262 hdcSave
= pdcSave
->BaseObject
.hHmgr
;
264 InterlockedIncrement(&pdc
->ppdev
->cPdevRefs
);
265 DC_vInitDc(pdcSave
, DCTYPE_MEMORY
, pdc
->ppdev
);
267 /* Handle references here correctly */
268 // pdcSrc->dclevel.pSurface = NULL;
269 // pdcSrc->dclevel.pbrFill = NULL;
270 // pdcSrc->dclevel.pbrLine = NULL;
271 // pdcSrc->dclevel.ppal = NULL;
273 /* Make it a kernel handle
274 (FIXME: windows handles this different, see wiki)*/
275 GDIOBJ_SetOwnership(hdcSave
, NULL
);
277 /* Copy the current state */
278 DC_vCopyState(pdc
, pdcSave
, TRUE
);
280 /* Only memory DC's change their surface */
281 if (pdc
->dctype
== DCTYPE_MEMORY
)
282 DC_vSelectSurface(pdcSave
, pdc
->dclevel
.pSurface
);
284 /* Copy path. FIXME: why this way? */
285 pdcSave
->dclevel
.hPath
= pdc
->dclevel
.hPath
;
286 pdcSave
->dclevel
.flPath
= pdc
->dclevel
.flPath
| DCPATH_SAVESTATE
;
287 if (pdcSave
->dclevel
.hPath
) pdcSave
->dclevel
.flPath
|= DCPATH_SAVE
;
289 /* Set new dc as save dc */
290 pdc
->dclevel
.hdcSave
= hdcSave
;
292 /* Increase save depth, return old value */
293 lSaveDepth
= pdc
->dclevel
.lSaveDepth
++;
295 /* Cleanup and return */
296 DC_UnlockDc(pdcSave
);
299 DPRINT("Leave NtGdiSaveDC: %ld, hdcSave = %p\n", lSaveDepth
, hdcSave
);