Commit the stuff. Lots of changes. I'll write a proper list of changes when it's...
[reactos.git] / subsystems / win32 / win32k / objects / dcstate.c
1 /*
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)
7 */
8
9 #include <w32k.h>
10
11 #define NDEBUG
12 #include <debug.h>
13
14 VOID
15 FASTCALL
16 DC_vCopyState(PDC pdcSrc, PDC pdcDst)
17 {
18 DPRINT("DC_vCopyState(%p, %p)\n", pdcSrc->BaseObject.hHmgr, pdcDst->BaseObject.hHmgr);
19
20 /* Copy full DC attribute */
21 *pdcDst->pdcattr = *pdcSrc->pdcattr;
22
23 /* Get/SetDCState() don't change hVisRgn field ("Undoc. Windows" p.559). */
24 /* The VisRectRegion field needs to be set to a valid state */
25
26 /* Mark some fields as dirty */
27 pdcDst->pdcattr->ulDirty_ |= 0x0012001f;
28
29 /* Copy DC level */
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;
42
43 /* Handle references here correctly */
44 DC_vSelectSurface(pdcDst, pdcSrc->dclevel.pSurface);
45 DC_vSelectFillBrush(pdcDst, pdcSrc->dclevel.pbrFill);
46 DC_vSelectLineBrush(pdcDst, pdcSrc->dclevel.pbrLine);
47 DC_vSelectPalette(pdcDst, pdcSrc->dclevel.ppal);
48
49 // FIXME: handle refs
50 pdcDst->dclevel.plfnt = pdcSrc->dclevel.plfnt;
51
52 /* ROS hacks */
53 if (pdcDst->dctype != DC_TYPE_MEMORY)
54 {
55 pdcDst->rosdc.bitsPerPixel = pdcSrc->rosdc.bitsPerPixel;
56 }
57
58 GdiExtSelectClipRgn(pdcDst, pdcSrc->rosdc.hClipRgn, RGN_COPY);
59
60 }
61
62
63 BOOL FASTCALL
64 IntGdiCleanDC(HDC hDC)
65 {
66 PDC dc;
67 if (!hDC) return FALSE;
68 dc = DC_LockDc(hDC);
69 if (!dc) return FALSE;
70 // Clean the DC
71 if (defaultDCstate) DC_vCopyState(defaultDCstate, dc);
72
73 if (dc->dctype != DC_TYPE_MEMORY)
74 {
75 dc->rosdc.bitsPerPixel = defaultDCstate->rosdc.bitsPerPixel;
76 }
77
78 DC_UnlockDc(dc);
79
80 return TRUE;
81 }
82
83
84 BOOL
85 APIENTRY
86 NtGdiResetDC(
87 IN HDC hdc,
88 IN LPDEVMODEW pdm,
89 OUT PBOOL pbBanding,
90 IN OPTIONAL VOID *pDriverInfo2,
91 OUT VOID *ppUMdhpdev)
92 {
93 UNIMPLEMENTED;
94 return 0;
95 }
96
97
98 VOID
99 NTAPI
100 DC_vRestoreDC(
101 IN PDC pdc,
102 INT iSaveLevel)
103 {
104 PEPROCESS pepCurrentProcess;
105 HDC hdcSave;
106 PDC pdcSave;
107
108 ASSERT(iSaveLevel > 0);
109 DPRINT("DC_vRestoreDC(%p, %ld)\n", pdc->BaseObject.hHmgr, iSaveLevel);
110
111 /* Get current process */
112 pepCurrentProcess = PsGetCurrentProcess();
113
114 /* Loop the save levels */
115 while (pdc->dclevel.lSaveDepth > iSaveLevel)
116 {
117 hdcSave = pdc->dclevel.hdcSave;
118 DPRINT("RestoreDC = %p\n", hdcSave);
119
120 /* Set us as the owner */
121 if (!GDIOBJ_SetOwnership(hdcSave, pepCurrentProcess))
122 {
123 /* Could not get ownership. That's bad! */
124 DPRINT1("Could not get ownership of saved DC (%p) for hdc %p!\n",
125 hdcSave, pdc->BaseObject.hHmgr);
126 return;// FALSE;
127 }
128
129 /* Lock the saved dc */
130 pdcSave = DC_LockDc(hdcSave);
131 if (!pdcSave)
132 {
133 /* WTF? Internal error! */
134 DPRINT1("Could not lock the saved DC (%p) for dc %p!\n",
135 hdcSave, pdc->BaseObject.hHmgr);
136 DC_UnlockDc(pdc);
137 return;// FALSE;
138 }
139
140 /* Remove the saved dc from the queue */
141 pdc->dclevel.hdcSave = pdcSave->dclevel.hdcSave;
142
143 /* Decrement save level */
144 pdc->dclevel.lSaveDepth--;
145
146 /* Is this the state we want? */
147 if (pdc->dclevel.lSaveDepth == iSaveLevel)
148 {
149 /* Copy the state back */
150 DC_vCopyState(pdcSave, pdc);
151
152 // Restore Path by removing it, if the Save flag is set.
153 // BeginPath will takecare of the rest.
154 if (pdc->dclevel.hPath && pdc->dclevel.flPath & DCPATH_SAVE)
155 {
156 PATH_Delete(pdc->dclevel.hPath);
157 pdc->dclevel.hPath = 0;
158 pdc->dclevel.flPath &= ~DCPATH_SAVE;
159 }
160 }
161
162 /* Prevent save dc from being restored */
163 pdcSave->dclevel.lSaveDepth = 1;
164
165 /* Delete the saved dc */
166 GreDeleteObject(hdcSave);
167 }
168
169 DPRINT("Leave DC_vRestoreDC()\n");
170 }
171
172
173
174 BOOL
175 APIENTRY
176 NtGdiRestoreDC(
177 HDC hdc,
178 INT iSaveLevel)
179 {
180 PDC pdc;
181
182 DPRINT("NtGdiRestoreDC(%p, %d)\n", hdc, iSaveLevel);
183
184 /* Lock the original DC */
185 pdc = DC_LockDc(hdc);
186 if (!pdc)
187 {
188 SetLastWin32Error(ERROR_INVALID_HANDLE);
189 return FALSE;
190 }
191
192 ASSERT(pdc->dclevel.lSaveDepth > 0);
193
194 /* Negative values are relative to the stack top */
195 if (iSaveLevel < 0)
196 iSaveLevel = pdc->dclevel.lSaveDepth + iSaveLevel;
197
198 /* Check if we have a valid instance */
199 if (iSaveLevel <= 0 || iSaveLevel >= pdc->dclevel.lSaveDepth)
200 {
201 DPRINT("Illegal save level, requested: %ld, current: %ld\n",
202 iSaveLevel, pdc->dclevel.lSaveDepth);
203 DC_UnlockDc(pdc);
204 SetLastWin32Error(ERROR_INVALID_PARAMETER);
205 return FALSE;
206 }
207
208 /* Call the internal function */
209 DC_vRestoreDC(pdc, iSaveLevel);
210
211 DC_UnlockDc(pdc);
212
213 DPRINT("Leave NtGdiRestoreDC\n");
214 return TRUE;
215 }
216
217
218 INT
219 APIENTRY
220 NtGdiSaveDC(
221 HDC hDC)
222 {
223 HDC hdcSave;
224 PDC pdc, pdcSave;
225 INT lSaveDepth;
226
227 DPRINT("NtGdiSaveDC(%p)\n", hDC);
228
229 /* Lock the original dc */
230 pdc = DC_LockDc(hDC);
231 if (pdc == NULL)
232 {
233 DPRINT("Could not lock DC\n");
234 SetLastWin32Error(ERROR_INVALID_HANDLE);
235 return 0;
236 }
237
238 /* Allocate a new dc */
239 pdcSave = DC_AllocDcWithHandle();
240 if (pdcSave == NULL)
241 {
242 DPRINT("Could not allocate a new DC\n");
243 DC_UnlockDc(pdc);
244 return 0;
245 }
246 hdcSave = pdcSave->BaseObject.hHmgr;
247
248 InterlockedIncrement(&pdc->ppdev->cPdevRefs);
249 DC_vInitDc(pdcSave, DCTYPE_MEMORY, pdc->ppdev);
250
251 /* Make it a kernel handle
252 (FIXME: windows handles this different, see wiki)*/
253 GDIOBJ_SetOwnership(hdcSave, NULL);
254
255 /* Copy the current state */
256 DC_vCopyState(pdc, pdcSave);
257
258 /* Copy path. FIXME: why this way? */
259 pdcSave->dclevel.hPath = pdc->dclevel.hPath;
260 pdcSave->dclevel.flPath = pdc->dclevel.flPath | DCPATH_SAVESTATE;
261 if (pdcSave->dclevel.hPath) pdcSave->dclevel.flPath |= DCPATH_SAVE;
262
263 /* Set new dc as save dc */
264 pdc->dclevel.hdcSave = hdcSave;
265
266 /* Increase save depth, return old value */
267 lSaveDepth = pdc->dclevel.lSaveDepth++;
268
269 /* Cleanup and return */
270 DC_UnlockDc(pdcSave);
271 DC_UnlockDc(pdc);
272
273 DPRINT("Leave NtGdiSaveDC: %ld, hdcSave = %p\n", lSaveDepth, hdcSave);
274 return lSaveDepth;
275 }
276