3a8a35954dbaf1d9b51b03ea3a0cd09950604674
[reactos.git] / reactos / win32ss / gdi / ntgdi / dclife.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS kernel
4 * PURPOSE: Functions for creation and destruction of DCs
5 * FILE: subsystem/win32/win32k/objects/dclife.c
6 * PROGRAMER: Timo Kreuzer (timo.kreuzer@rectos.org)
7 */
8
9 #include <win32k.h>
10
11 #define NDEBUG
12 #include <debug.h>
13
14 // FIXME: Windows uses 0x0012009f
15 #define DIRTY_DEFAULT DIRTY_CHARSET|DIRTY_BACKGROUND|DIRTY_TEXT|DIRTY_LINE|DIRTY_FILL
16
17 PSURFACE psurfDefaultBitmap = NULL;
18 PBRUSH pbrDefaultBrush = NULL;
19
20 static const MATRIX gmxWorldToDeviceDefault =
21 {
22 FLOATOBJ_16, FLOATOBJ_0,
23 FLOATOBJ_0, FLOATOBJ_16,
24 FLOATOBJ_0, FLOATOBJ_0,
25 0, 0, 0x4b
26 };
27
28 static const MATRIX gmxDeviceToWorldDefault =
29 {
30 FLOATOBJ_1_16, FLOATOBJ_0,
31 FLOATOBJ_0, FLOATOBJ_1_16,
32 FLOATOBJ_0, FLOATOBJ_0,
33 0, 0, 0x53
34 };
35
36 static const MATRIX gmxWorldToPageDefault =
37 {
38 FLOATOBJ_1, FLOATOBJ_0,
39 FLOATOBJ_0, FLOATOBJ_1,
40 FLOATOBJ_0, FLOATOBJ_0,
41 0, 0, 0x63
42 };
43
44 // HACK!! Fix XFORMOBJ then use 1:16 / 16:1
45 #define gmxWorldToDeviceDefault gmxWorldToPageDefault
46 #define gmxDeviceToWorldDefault gmxWorldToPageDefault
47
48 /** Internal functions ********************************************************/
49
50 INIT_FUNCTION
51 NTSTATUS
52 NTAPI
53 InitDcImpl()
54 {
55 psurfDefaultBitmap = SURFACE_ShareLockSurface(StockObjects[DEFAULT_BITMAP]);
56 if (!psurfDefaultBitmap)
57 return STATUS_UNSUCCESSFUL;
58
59 pbrDefaultBrush = BRUSH_ShareLockBrush(StockObjects[BLACK_BRUSH]);
60 if (!pbrDefaultBrush)
61 return STATUS_UNSUCCESSFUL;
62
63 return STATUS_SUCCESS;
64 }
65
66
67 PDC
68 NTAPI
69 DC_AllocDcWithHandle()
70 {
71 PDC pdc;
72
73 pdc = (PDC)GDIOBJ_AllocateObject(GDIObjType_DC_TYPE,
74 sizeof(DC),
75 BASEFLAG_LOOKASIDE);
76 if (!pdc)
77 {
78 DPRINT1("Could not allocate a DC.\n");
79 return NULL;
80 }
81
82 if (!GDIOBJ_hInsertObject(&pdc->BaseObject, GDI_OBJ_HMGR_POWNED))
83 {
84 DPRINT1("Could not insert DC into handle table.\n");
85 GDIOBJ_vFreeObject(&pdc->BaseObject);
86 return NULL;
87 }
88
89 pdc->pdcattr = &pdc->dcattr;
90
91 return pdc;
92 }
93
94
95 void
96 DC_InitHack(PDC pdc)
97 {
98 HRGN hVisRgn;
99
100 TextIntRealizeFont(pdc->pdcattr->hlfntNew,NULL);
101 pdc->pdcattr->iCS_CP = ftGdiGetTextCharsetInfo(pdc,NULL,0);
102
103 /* This should never fail */
104 ASSERT(pdc->dclevel.ppal);
105
106 /* Select regions */
107 pdc->rosdc.hClipRgn = NULL;
108 pdc->rosdc.hGCClipRgn = NULL;
109
110 hVisRgn = IntSysCreateRectRgn(0, 0, 1, 1);
111 ASSERT(hVisRgn);
112 GdiSelectVisRgn(pdc->BaseObject.hHmgr, hVisRgn);
113 GreDeleteObject(hVisRgn);
114 }
115
116 VOID
117 NTAPI
118 DC_vInitDc(
119 PDC pdc,
120 DCTYPE dctype,
121 PPDEVOBJ ppdev)
122 {
123 /* Setup some basic fields */
124 pdc->dctype = dctype;
125 pdc->ppdev = ppdev;
126 pdc->dhpdev = ppdev->dhpdev;
127 pdc->hsem = ppdev->hsemDevLock;
128 pdc->flGraphicsCaps = ppdev->devinfo.flGraphicsCaps;
129 pdc->flGraphicsCaps2 = ppdev->devinfo.flGraphicsCaps2;
130 pdc->fs = DC_DIRTY_RAO;
131
132 /* Setup dc attribute */
133 pdc->pdcattr = &pdc->dcattr;
134 pdc->dcattr.pvLDC = NULL;
135 pdc->dcattr.ulDirty_ = DIRTY_DEFAULT;
136 if (ppdev == gppdevPrimary)
137 pdc->dcattr.ulDirty_ |= DC_PRIMARY_DISPLAY;
138
139 /* Setup the DC size */
140 if (dctype == DCTYPE_MEMORY)
141 {
142 /* Memory DCs have a 1 x 1 bitmap by default */
143 pdc->dclevel.sizl.cx = 1;
144 pdc->dclevel.sizl.cy = 1;
145 }
146 else
147 {
148 /* Other DC's are as big as the related PDEV */
149 pdc->dclevel.sizl.cx = ppdev->gdiinfo.ulHorzRes;
150 pdc->dclevel.sizl.cy = ppdev->gdiinfo.ulVertRes;
151 }
152
153 /* Setup Window rect based on DC size */
154 pdc->erclWindow.left = 0;
155 pdc->erclWindow.top = 0;
156 pdc->erclWindow.right = pdc->dclevel.sizl.cx;
157 pdc->erclWindow.bottom = pdc->dclevel.sizl.cy;
158
159 if (dctype == DCTYPE_DIRECT)
160 {
161 /* Direct DCs get the surface from the PDEV */
162 pdc->dclevel.pSurface = PDEVOBJ_pSurface(ppdev);
163
164 pdc->erclBounds.left = 0x7fffffff;
165 pdc->erclBounds.top = 0x7fffffff;
166 pdc->erclBounds.right = 0x80000000;
167 pdc->erclBounds.bottom = 0x80000000;
168 pdc->erclBoundsApp.left = 0xffffffff;
169 pdc->erclBoundsApp.top = 0xfffffffc;
170 pdc->erclBoundsApp.right = 0x00007ffc; // FIXME
171 pdc->erclBoundsApp.bottom = 0x00000333; // FIXME
172 pdc->erclClip = pdc->erclBounds;
173 // pdc->co
174
175 pdc->fs |= DC_SYNCHRONIZEACCESS | DC_ACCUM_APP | DC_PERMANANT | DC_DISPLAY;
176 }
177 else
178 {
179 /* Non-direct DCs don't have a surface by default */
180 pdc->dclevel.pSurface = NULL;
181
182 pdc->erclBounds.left = 0;
183 pdc->erclBounds.top = 0;
184 pdc->erclBounds.right = 0;
185 pdc->erclBounds.bottom = 0;
186 pdc->erclBoundsApp = pdc->erclBounds;
187 pdc->erclClip = pdc->erclWindow;
188 //pdc->co = NULL
189 }
190
191 //pdc->dcattr.VisRectRegion:
192
193 /* Setup coordinate transformation data */
194 pdc->dclevel.mxWorldToDevice = gmxWorldToDeviceDefault;
195 pdc->dclevel.mxDeviceToWorld = gmxDeviceToWorldDefault;
196 pdc->dclevel.mxWorldToPage = gmxWorldToPageDefault;
197 pdc->dclevel.efM11PtoD = gef16;
198 pdc->dclevel.efM22PtoD = gef16;
199 pdc->dclevel.efDxPtoD = gef0;
200 pdc->dclevel.efDyPtoD = gef0;
201 pdc->dclevel.efM11_TWIPS = gef0;
202 pdc->dclevel.efM22_TWIPS = gef0;
203 pdc->dclevel.efPr11 = gef0;
204 pdc->dclevel.efPr22 = gef0;
205 pdc->dcattr.mxWorldToDevice = pdc->dclevel.mxWorldToDevice;
206 pdc->dcattr.mxDeviceToWorld = pdc->dclevel.mxDeviceToWorld;
207 pdc->dcattr.mxWorldToPage = pdc->dclevel.mxWorldToPage;
208 pdc->dcattr.efM11PtoD = pdc->dclevel.efM11PtoD;
209 pdc->dcattr.efM22PtoD = pdc->dclevel.efM22PtoD;
210 pdc->dcattr.efDxPtoD = pdc->dclevel.efDxPtoD;
211 pdc->dcattr.efDyPtoD = pdc->dclevel.efDyPtoD;
212 pdc->dcattr.iMapMode = MM_TEXT;
213 pdc->dcattr.dwLayout = 0;
214 pdc->dcattr.flXform = PAGE_TO_DEVICE_SCALE_IDENTITY |
215 PAGE_TO_DEVICE_IDENTITY |
216 WORLD_TO_PAGE_IDENTITY;
217
218 /* Setup more coordinates */
219 pdc->ptlDCOrig.x = 0;
220 pdc->ptlDCOrig.y = 0;
221 pdc->dcattr.lWindowOrgx = 0;
222 pdc->dcattr.ptlWindowOrg.x = 0;
223 pdc->dcattr.ptlWindowOrg.y = 0;
224 pdc->dcattr.szlWindowExt.cx = 1;
225 pdc->dcattr.szlWindowExt.cy = 1;
226 pdc->dcattr.ptlViewportOrg.x = 0;
227 pdc->dcattr.ptlViewportOrg.y = 0;
228 pdc->dcattr.szlViewportExt.cx = 1;
229 pdc->dcattr.szlViewportExt.cy = 1;
230 pdc->dcattr.szlVirtualDevicePixel.cx = ppdev->gdiinfo.ulHorzRes;
231 pdc->dcattr.szlVirtualDevicePixel.cy = ppdev->gdiinfo.ulVertRes;
232 pdc->dcattr.szlVirtualDeviceMm.cx = ppdev->gdiinfo.ulHorzSize;
233 pdc->dcattr.szlVirtualDeviceMm.cy = ppdev->gdiinfo.ulVertSize;
234 pdc->dcattr.szlVirtualDeviceSize.cx = 0;
235 pdc->dcattr.szlVirtualDeviceSize.cy = 0;
236
237 /* Setup regions */
238 pdc->prgnAPI = NULL;
239 pdc->prgnRao = NULL;
240 /* Allocate a Vis region */
241 pdc->prgnVis = IntSysCreateRectpRgn(0, 0, pdc->dclevel.sizl.cx, pdc->dclevel.sizl.cy);
242 ASSERT(pdc->prgnVis);
243
244 /* Setup palette */
245 pdc->dclevel.hpal = StockObjects[DEFAULT_PALETTE];
246 pdc->dclevel.ppal = PALETTE_ShareLockPalette(pdc->dclevel.hpal);
247
248 /* Setup path */
249 pdc->dclevel.hPath = NULL;
250 pdc->dclevel.flPath = 0;
251 // pdc->dclevel.lapath:
252
253 /* Setup colors */
254 pdc->dcattr.crBackgroundClr = RGB(0xff, 0xff, 0xff);
255 pdc->dcattr.ulBackgroundClr = RGB(0xff, 0xff, 0xff);
256 pdc->dcattr.crForegroundClr = RGB(0, 0, 0);
257 pdc->dcattr.ulForegroundClr = RGB(0, 0, 0);
258 pdc->dcattr.crBrushClr = RGB(0xff, 0xff, 0xff);
259 pdc->dcattr.ulBrushClr = RGB(0xff, 0xff, 0xff);
260 pdc->dcattr.crPenClr = RGB(0, 0, 0);
261 pdc->dcattr.ulPenClr = RGB(0, 0, 0);
262
263 /* Select the default fill and line brush */
264 pdc->dcattr.hbrush = StockObjects[WHITE_BRUSH];
265 pdc->dcattr.hpen = StockObjects[BLACK_PEN];
266 pdc->dclevel.pbrFill = BRUSH_ShareLockBrush(pdc->pdcattr->hbrush);
267 pdc->dclevel.pbrLine = PEN_ShareLockPen(pdc->pdcattr->hpen);
268 pdc->dclevel.ptlBrushOrigin.x = 0;
269 pdc->dclevel.ptlBrushOrigin.y = 0;
270 pdc->dcattr.ptlBrushOrigin = pdc->dclevel.ptlBrushOrigin;
271
272 /* Initialize EBRUSHOBJs */
273 EBRUSHOBJ_vInitFromDC(&pdc->eboFill, pdc->dclevel.pbrFill, pdc);
274 EBRUSHOBJ_vInitFromDC(&pdc->eboLine, pdc->dclevel.pbrLine, pdc);
275 EBRUSHOBJ_vInitFromDC(&pdc->eboText, pbrDefaultBrush, pdc);
276 EBRUSHOBJ_vInitFromDC(&pdc->eboBackground, pbrDefaultBrush, pdc);
277
278 /* Setup fill data */
279 pdc->dcattr.jROP2 = R2_COPYPEN;
280 pdc->dcattr.jBkMode = 2;
281 pdc->dcattr.lBkMode = 2;
282 pdc->dcattr.jFillMode = ALTERNATE;
283 pdc->dcattr.lFillMode = 1;
284 pdc->dcattr.jStretchBltMode = 1;
285 pdc->dcattr.lStretchBltMode = 1;
286 pdc->ptlFillOrigin.x = 0;
287 pdc->ptlFillOrigin.y = 0;
288
289 /* Setup drawing position */
290 pdc->dcattr.ptlCurrent.x = 0;
291 pdc->dcattr.ptlCurrent.y = 0;
292 pdc->dcattr.ptfxCurrent.x = 0;
293 pdc->dcattr.ptfxCurrent.y = 0;
294
295 /* Setup ICM data */
296 pdc->dclevel.lIcmMode = 0;
297 pdc->dcattr.lIcmMode = 0;
298 pdc->dcattr.hcmXform = NULL;
299 pdc->dcattr.flIcmFlags = 0;
300 pdc->dcattr.IcmBrushColor = CLR_INVALID;
301 pdc->dcattr.IcmPenColor = CLR_INVALID;
302 pdc->dcattr.pvLIcm = NULL;
303 pdc->dcattr.hColorSpace = NULL; // FIXME: 0189001f
304 pdc->dclevel.pColorSpace = NULL; // FIXME
305 pdc->pClrxFormLnk = NULL;
306 // pdc->dclevel.ca =
307
308 /* Setup font data */
309 pdc->hlfntCur = NULL; // FIXME: 2f0a0cf8
310 pdc->pPFFList = NULL;
311 pdc->flSimulationFlags = 0;
312 pdc->lEscapement = 0;
313 pdc->prfnt = NULL;
314 pdc->dcattr.flFontMapper = 0;
315 pdc->dcattr.flTextAlign = 0;
316 pdc->dcattr.lTextAlign = 0;
317 pdc->dcattr.lTextExtra = 0;
318 pdc->dcattr.lRelAbs = 1;
319 pdc->dcattr.lBreakExtra = 0;
320 pdc->dcattr.cBreak = 0;
321 pdc->dcattr.hlfntNew = StockObjects[SYSTEM_FONT];
322 pdc->dclevel.plfnt = LFONT_ShareLockFont(pdc->dcattr.hlfntNew);
323
324 /* Other stuff */
325 pdc->hdcNext = NULL;
326 pdc->hdcPrev = NULL;
327 pdc->ipfdDevMax = 0x0000ffff;
328 pdc->ulCopyCount = -1;
329 pdc->ptlDoBanding.x = 0;
330 pdc->ptlDoBanding.y = 0;
331 pdc->dclevel.lSaveDepth = 1;
332 pdc->dclevel.hdcSave = NULL;
333 pdc->dcattr.iGraphicsMode = GM_COMPATIBLE;
334 pdc->dcattr.iCS_CP = 0;
335 pdc->pSurfInfo = NULL;
336
337 if (defaultDCstate == NULL)
338 {
339 defaultDCstate = ExAllocatePoolWithTag(PagedPool, sizeof(DC), TAG_DC);
340 ASSERT(defaultDCstate);
341 RtlZeroMemory(defaultDCstate, sizeof(DC));
342 defaultDCstate->pdcattr = &defaultDCstate->dcattr;
343 DC_vCopyState(pdc, defaultDCstate, TRUE);
344 }
345 }
346
347 VOID
348 NTAPI
349 DC_vCleanup(PVOID ObjectBody)
350 {
351 PDC pdc = (PDC)ObjectBody;
352
353 /* Free DC_ATTR */
354 DC_vFreeDcAttr(pdc);
355
356 /* Delete saved DCs */
357 DC_vRestoreDC(pdc, 1);
358
359 /* Deselect dc objects */
360 DC_vSelectSurface(pdc, NULL);
361 DC_vSelectFillBrush(pdc, NULL);
362 DC_vSelectLineBrush(pdc, NULL);
363 DC_vSelectPalette(pdc, NULL);
364
365 /* Cleanup the dc brushes */
366 EBRUSHOBJ_vCleanup(&pdc->eboFill);
367 EBRUSHOBJ_vCleanup(&pdc->eboLine);
368 EBRUSHOBJ_vCleanup(&pdc->eboText);
369 EBRUSHOBJ_vCleanup(&pdc->eboBackground);
370
371 /* Release font */
372 LFONT_ShareUnlockFont(pdc->dclevel.plfnt);
373
374 /* Free regions */
375 if (pdc->rosdc.hClipRgn && GreIsHandleValid(pdc->rosdc.hClipRgn))
376 GreDeleteObject(pdc->rosdc.hClipRgn);
377 if (pdc->prgnVis)
378 {
379 REGION_Delete(pdc->prgnVis);
380 }
381 if (pdc->rosdc.hGCClipRgn && GreIsHandleValid(pdc->rosdc.hGCClipRgn))
382 {
383 GreDeleteObject(pdc->rosdc.hGCClipRgn);
384 }
385 if (NULL != pdc->rosdc.CombinedClip)
386 IntEngDeleteClipRegion(pdc->rosdc.CombinedClip);
387
388 PATH_Delete(pdc->dclevel.hPath);
389
390 if(pdc->dclevel.pSurface)
391 SURFACE_ShareUnlockSurface(pdc->dclevel.pSurface);
392
393 PDEVOBJ_vRelease(pdc->ppdev) ;
394 }
395
396 VOID
397 NTAPI
398 DC_vSetOwner(PDC pdc, ULONG ulOwner)
399 {
400
401 if (pdc->rosdc.hClipRgn)
402 {
403 IntGdiSetRegionOwner(pdc->rosdc.hClipRgn, ulOwner);
404 }
405
406 if (pdc->rosdc.hGCClipRgn)
407 {
408 IntGdiSetRegionOwner(pdc->rosdc.hGCClipRgn, ulOwner);
409 }
410
411 if (pdc->dclevel.hPath)
412 {
413 GreSetObjectOwner(pdc->dclevel.hPath, ulOwner);
414 }
415
416 /* Dereference current brush and pen */
417 BRUSH_ShareUnlockBrush(pdc->dclevel.pbrFill);
418 BRUSH_ShareUnlockBrush(pdc->dclevel.pbrLine);
419
420 /* Select the default fill and line brush */
421 pdc->dcattr.hbrush = StockObjects[WHITE_BRUSH];
422 pdc->dcattr.hpen = StockObjects[BLACK_PEN];
423 pdc->dclevel.pbrFill = BRUSH_ShareLockBrush(pdc->pdcattr->hbrush);
424 pdc->dclevel.pbrLine = PEN_ShareLockPen(pdc->pdcattr->hpen);
425
426 /* Mark them as dirty */
427 pdc->pdcattr->ulDirty_ |= DIRTY_FILL|DIRTY_LINE;
428
429 /* Allocate or free DC attribute */
430 if (ulOwner == GDI_OBJ_HMGR_PUBLIC || ulOwner == GDI_OBJ_HMGR_NONE)
431 {
432 if (pdc->pdcattr != &pdc->dcattr)
433 DC_vFreeDcAttr(pdc);
434 }
435 else if (ulOwner == GDI_OBJ_HMGR_POWNED)
436 {
437 if (pdc->pdcattr == &pdc->dcattr)
438 DC_bAllocDcAttr(pdc);
439 }
440
441 /* Set the DC's ownership */
442 GDIOBJ_vSetObjectOwner(&pdc->BaseObject, ulOwner);
443 }
444
445 BOOL
446 NTAPI
447 GreSetDCOwner(HDC hdc, ULONG ulOwner)
448 {
449 PDC pdc;
450
451 pdc = DC_LockDc(hdc);
452 if (!pdc)
453 {
454 DPRINT1("GreSetDCOwner: Could not lock DC\n");
455 return FALSE;
456 }
457
458 /* Call the internal DC function */
459 DC_vSetOwner(pdc, ulOwner);
460
461 DC_UnlockDc(pdc);
462 return TRUE;
463 }
464
465 static
466 void
467 DC_vUpdateDC(PDC pdc)
468 {
469 HRGN hVisRgn ;
470 PPDEVOBJ ppdev = pdc->ppdev ;
471
472 pdc->dhpdev = ppdev->dhpdev;
473
474 SURFACE_ShareUnlockSurface(pdc->dclevel.pSurface);
475 pdc->dclevel.pSurface = PDEVOBJ_pSurface(ppdev);
476
477 PDEVOBJ_sizl(pdc->ppdev, &pdc->dclevel.sizl);
478 hVisRgn = NtGdiCreateRectRgn(0, 0, pdc->dclevel.sizl.cx, pdc->dclevel.sizl.cy);
479 ASSERT(hVisRgn);
480 GdiSelectVisRgn(pdc->BaseObject.hHmgr, hVisRgn);
481 GreDeleteObject(hVisRgn);
482
483 pdc->flGraphicsCaps = ppdev->devinfo.flGraphicsCaps;
484 pdc->flGraphicsCaps2 = ppdev->devinfo.flGraphicsCaps2;
485
486 /* Mark EBRUSHOBJs as dirty */
487 pdc->pdcattr->ulDirty_ |= DIRTY_DEFAULT ;
488 }
489
490 /* Prepare a blit for up to 2 DCs */
491 /* rc1 and rc2 are the rectangles where we want to draw or
492 * from where we take pixels. */
493 VOID
494 FASTCALL
495 DC_vPrepareDCsForBlit(PDC pdc1,
496 RECT rc1,
497 PDC pdc2,
498 RECT rc2)
499 {
500 PDC pdcFirst, pdcSecond;
501 PRECT prcFirst, prcSecond;
502
503 /* Update brushes */
504 if (pdc1->pdcattr->ulDirty_ & (DIRTY_FILL | DC_BRUSH_DIRTY))
505 DC_vUpdateFillBrush(pdc1);
506 if (pdc1->pdcattr->ulDirty_ & (DIRTY_LINE | DC_PEN_DIRTY))
507 DC_vUpdateLineBrush(pdc1);
508 if(pdc1->pdcattr->ulDirty_ & DIRTY_TEXT)
509 DC_vUpdateTextBrush(pdc1);
510
511 /* Lock them in good order */
512 if(pdc2)
513 {
514 if((ULONG_PTR)pdc1->ppdev->hsemDevLock >= (ULONG_PTR)pdc2->ppdev->hsemDevLock)
515 {
516 pdcFirst = pdc1;
517 prcFirst = &rc1;
518 pdcSecond = pdc2;
519 prcSecond = &rc2;
520 }
521 else
522 {
523 pdcFirst = pdc2;
524 prcFirst = &rc2;
525 pdcSecond = pdc1;
526 prcSecond = &rc1;
527 }
528 }
529 else
530 {
531 pdcFirst = pdc1 ;
532 prcFirst = &rc1;
533 pdcSecond = NULL;
534 prcSecond = NULL;
535 }
536
537 if(pdcFirst && pdcFirst->dctype == DCTYPE_DIRECT)
538 {
539 EngAcquireSemaphore(pdcFirst->ppdev->hsemDevLock);
540 MouseSafetyOnDrawStart(pdcFirst->ppdev,
541 prcFirst->left,
542 prcFirst->top,
543 prcFirst->right,
544 prcFirst->bottom) ;
545 /* Update surface if needed */
546 if(pdcFirst->ppdev->pSurface != pdcFirst->dclevel.pSurface)
547 {
548 DC_vUpdateDC(pdcFirst);
549 }
550 }
551 if(pdcSecond && pdcSecond->dctype == DCTYPE_DIRECT)
552 {
553 EngAcquireSemaphore(pdcSecond->ppdev->hsemDevLock);
554 MouseSafetyOnDrawStart(pdcSecond->ppdev,
555 prcSecond->left,
556 prcSecond->top,
557 prcSecond->right,
558 prcSecond->bottom) ;
559 /* Update surface if needed */
560 if(pdcSecond->ppdev->pSurface != pdcSecond->dclevel.pSurface)
561 {
562 DC_vUpdateDC(pdcSecond);
563 }
564 }
565 }
566
567 /* Finishes a blit for one or two DCs */
568 VOID
569 FASTCALL
570 DC_vFinishBlit(PDC pdc1, PDC pdc2)
571 {
572 if(pdc1->dctype == DCTYPE_DIRECT)
573 {
574 MouseSafetyOnDrawEnd(pdc1->ppdev);
575 EngReleaseSemaphore(pdc1->ppdev->hsemDevLock);
576 }
577
578 if(pdc2)
579 {
580 if(pdc2->dctype == DCTYPE_DIRECT)
581 {
582 MouseSafetyOnDrawEnd(pdc2->ppdev);
583 EngReleaseSemaphore(pdc2->ppdev->hsemDevLock);
584 }
585 }
586 }
587
588 HDC
589 NTAPI
590 GreOpenDCW(
591 PUNICODE_STRING pustrDevice,
592 DEVMODEW *pdmInit,
593 PUNICODE_STRING pustrLogAddr,
594 ULONG iType,
595 BOOL bDisplay,
596 HANDLE hspool,
597 VOID *pDriverInfo2,
598 VOID *pUMdhpdev)
599 {
600 PPDEVOBJ ppdev;
601 PDC pdc;
602 HDC hdc;
603
604 DPRINT("GreOpenDCW(%S, iType=%lu)\n",
605 pustrDevice ? pustrDevice->Buffer : NULL, iType);
606
607 /* Get a PDEVOBJ for the device */
608 ppdev = EngpGetPDEV(pustrDevice);
609 if (!ppdev)
610 {
611 DPRINT1("Didn't find a suitable PDEV\n");
612 return NULL;
613 }
614
615 DPRINT("GreOpenDCW - ppdev = %p\n", ppdev);
616
617 pdc = DC_AllocDcWithHandle();
618 if (!pdc)
619 {
620 DPRINT1("Could not Allocate a DC\n");
621 PDEVOBJ_vRelease(ppdev);
622 return NULL;
623 }
624 hdc = pdc->BaseObject.hHmgr;
625
626 /* Lock ppdev and initialize the new DC */
627 DC_vInitDc(pdc, iType, ppdev);
628 /* FIXME: HACK! */
629 DC_InitHack(pdc);
630
631 DC_bAllocDcAttr(pdc);
632
633 DC_UnlockDc(pdc);
634
635 DPRINT("Returning hdc = %p\n", hdc);
636
637 return hdc;
638 }
639
640 HDC
641 APIENTRY
642 NtGdiOpenDCW(
643 PUNICODE_STRING pustrDevice,
644 DEVMODEW *pdmInit,
645 PUNICODE_STRING pustrLogAddr,
646 ULONG iType,
647 BOOL bDisplay,
648 HANDLE hspool,
649 VOID *pDriverInfo2,
650 VOID *pUMdhpdev)
651 {
652 UNICODE_STRING ustrDevice;
653 WCHAR awcDevice[CCHDEVICENAME];
654 DEVMODEW dmInit;
655 PVOID dhpdev;
656 HDC hdc;
657
658 /* Only if a devicename is given, we need any data */
659 if (pustrDevice)
660 {
661 /* Initialize destination string */
662 RtlInitEmptyUnicodeString(&ustrDevice, awcDevice, sizeof(awcDevice));
663
664 _SEH2_TRY
665 {
666 /* Probe the UNICODE_STRING and the buffer */
667 ProbeForRead(pustrDevice, sizeof(UNICODE_STRING), 1);
668 ProbeForRead(pustrDevice->Buffer, pustrDevice->Length, 1);
669
670 /* Copy the string */
671 RtlCopyUnicodeString(&ustrDevice, pustrDevice);
672
673 if (pdmInit)
674 {
675 /* FIXME: could be larger */
676 ProbeForRead(pdmInit, sizeof(DEVMODEW), 1);
677 RtlCopyMemory(&dmInit, pdmInit, sizeof(DEVMODEW));
678 }
679
680 if (pUMdhpdev)
681 {
682 ProbeForWrite(pUMdhpdev, sizeof(HANDLE), 1);
683 }
684 }
685 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
686 {
687 SetLastNtError(_SEH2_GetExceptionCode());
688 _SEH2_YIELD(return NULL);
689 }
690 _SEH2_END
691 }
692 else
693 {
694 pdmInit = NULL;
695 pUMdhpdev = NULL;
696 }
697
698 /* FIXME: HACK! */
699 if (pustrDevice)
700 {
701 UNICODE_STRING ustrDISPLAY = RTL_CONSTANT_STRING(L"DISPLAY");
702 if (RtlEqualUnicodeString(&ustrDevice, &ustrDISPLAY, TRUE))
703 {
704 pustrDevice = NULL;
705 }
706 }
707
708 /* Call the internal function */
709 hdc = GreOpenDCW(pustrDevice ? &ustrDevice : NULL,
710 pdmInit ? &dmInit : NULL,
711 NULL, // FIXME: pwszLogAddress
712 iType,
713 bDisplay,
714 hspool,
715 NULL, // FIXME: pDriverInfo2
716 pUMdhpdev ? &dhpdev : NULL);
717
718 /* If we got a HDC and a UM dhpdev is requested,... */
719 if (hdc && pUMdhpdev)
720 {
721 /* Copy dhpdev to caller (FIXME: use dhpdev?) */
722 _SEH2_TRY
723 {
724 /* Pointer was already probed */
725 *(HANDLE*)pUMdhpdev = dhpdev;
726 }
727 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
728 {
729 /* Ignore error */
730 (void)0;
731 }
732 _SEH2_END
733 }
734
735 return hdc;
736 }
737
738
739 HDC
740 APIENTRY
741 NtGdiCreateCompatibleDC(HDC hdc)
742 {
743 HDC hdcNew;
744 PPDEVOBJ ppdev;
745 PDC pdc, pdcNew;
746
747 DPRINT("NtGdiCreateCompatibleDC(0x%p)\n", hdc);
748
749 /* Did the caller provide a DC? */
750 if (hdc)
751 {
752 /* Yes, try to lock it */
753 pdc = DC_LockDc(hdc);
754 if (!pdc)
755 {
756 DPRINT1("Could not lock source DC %p\n", hdc);
757 return NULL;
758 }
759
760 /* Get the pdev from the DC */
761 ppdev = pdc->ppdev;
762 InterlockedIncrement(&ppdev->cPdevRefs);
763
764 /* Unlock the source DC */
765 DC_UnlockDc(pdc);
766 }
767 else
768 {
769 /* No DC given, get default device */
770 ppdev = EngpGetPDEV(NULL);
771 }
772
773 if (!ppdev)
774 {
775 DPRINT1("Didn't find a suitable PDEV\n");
776 return NULL;
777 }
778
779 /* Allocate a new DC */
780 pdcNew = DC_AllocDcWithHandle();
781 if (!pdcNew)
782 {
783 DPRINT1("Could not allocate a new DC\n");
784 PDEVOBJ_vRelease(ppdev);
785 return NULL;
786 }
787 hdcNew = pdcNew->BaseObject.hHmgr;
788
789 /* Lock ppdev and initialize the new DC */
790 DC_vInitDc(pdcNew, DCTYPE_MEMORY, ppdev);
791 /* FIXME: HACK! */
792 DC_InitHack(pdcNew);
793
794 /* Allocate a dc attribute */
795 DC_bAllocDcAttr(pdcNew);
796
797 DC_UnlockDc(pdcNew);
798
799 DPRINT("Leave NtGdiCreateCompatibleDC hdcNew = %p\n", hdcNew);
800
801 return hdcNew;
802 }
803
804 BOOL
805 FASTCALL
806 IntGdiDeleteDC(HDC hDC, BOOL Force)
807 {
808 PDC DCToDelete = DC_LockDc(hDC);
809
810 if (DCToDelete == NULL)
811 {
812 EngSetLastError(ERROR_INVALID_HANDLE);
813 return FALSE;
814 }
815
816 if (!Force)
817 {
818 /* Windows permits NtGdiDeleteObjectApp to delete a permanent DC
819 * For some reason, it's still a valid handle, pointing to some kernel data.
820 * Not sure if this is a bug, a feature, some cache stuff... Who knows?
821 * See NtGdiDeleteObjectApp test for details */
822 if (DCToDelete->fs & DC_FLAG_PERMANENT)
823 {
824 DC_UnlockDc(DCToDelete);
825 if(UserReleaseDC(NULL, hDC, FALSE))
826 {
827 /* ReactOS feature: Call UserReleaseDC
828 * I don't think Windows does it.
829 * Still, complain, no one should ever call DeleteDC
830 * on a window DC */
831 DPRINT1("No, you naughty application!\n");
832 return TRUE;
833 }
834 else
835 {
836 /* This is not a window owned DC.
837 * Force its deletion */
838 return IntGdiDeleteDC(hDC, TRUE);
839 }
840 }
841 }
842
843 DC_UnlockDc(DCToDelete);
844
845 if (GreIsHandleValid(hDC))
846 {
847 if (!GreDeleteObject(hDC))
848 {
849 DPRINT1("DC_FreeDC failed\n");
850 }
851 }
852 else
853 {
854 DPRINT1("Attempted to Delete 0x%p currently being destroyed!!!\n", hDC);
855 }
856
857 return TRUE;
858 }
859
860 BOOL
861 APIENTRY
862 NtGdiDeleteObjectApp(HANDLE hobj)
863 {
864 /* Complete all pending operations */
865 NtGdiFlushUserBatch(); // FIXME: We shouldn't need this
866
867 if (GDI_HANDLE_IS_STOCKOBJ(hobj)) return TRUE;
868
869 if (GreGetObjectOwner(hobj) != GDI_OBJ_HMGR_POWNED)
870 {
871 EngSetLastError(ERROR_INVALID_HANDLE);
872 return FALSE;
873 }
874
875 if (GDI_HANDLE_GET_TYPE(hobj) != GDI_OBJECT_TYPE_DC)
876 return GreDeleteObject(hobj);
877
878 // FIXME: Everything should be callback based
879 return IntGdiDeleteDC(hobj, FALSE);
880 }
881
882 BOOL
883 FASTCALL
884 MakeInfoDC(PDC pdc, BOOL bSet)
885 {
886 PSURFACE pSurface;
887 SIZEL sizl;
888
889 /* Can not be a display DC. */
890 if (pdc->fs & DC_FLAG_DISPLAY) return FALSE;
891 if (bSet)
892 {
893 if (pdc->fs & DC_FLAG_TEMPINFODC || pdc->dctype == DC_TYPE_DIRECT)
894 return FALSE;
895
896 pSurface = pdc->dclevel.pSurface;
897 pdc->fs |= DC_FLAG_TEMPINFODC;
898 pdc->pSurfInfo = pSurface;
899 pdc->dctype = DC_TYPE_INFO;
900 pdc->dclevel.pSurface = NULL;
901
902 PDEVOBJ_sizl(pdc->ppdev, &sizl);
903
904 if ( sizl.cx == pdc->dclevel.sizl.cx &&
905 sizl.cy == pdc->dclevel.sizl.cy )
906 return TRUE;
907
908 pdc->dclevel.sizl.cx = sizl.cx;
909 pdc->dclevel.sizl.cy = sizl.cy;
910 }
911 else
912 {
913 if (!(pdc->fs & DC_FLAG_TEMPINFODC) || pdc->dctype != DC_TYPE_INFO)
914 return FALSE;
915
916 pSurface = pdc->pSurfInfo;
917 pdc->fs &= ~DC_FLAG_TEMPINFODC;
918 pdc->dclevel.pSurface = pSurface;
919 pdc->dctype = DC_TYPE_DIRECT;
920 pdc->pSurfInfo = NULL;
921
922 if ( !pSurface ||
923 (pSurface->SurfObj.sizlBitmap.cx == pdc->dclevel.sizl.cx &&
924 pSurface->SurfObj.sizlBitmap.cy == pdc->dclevel.sizl.cy) )
925 return TRUE;
926
927 pdc->dclevel.sizl.cx = pSurface->SurfObj.sizlBitmap.cx;
928 pdc->dclevel.sizl.cy = pSurface->SurfObj.sizlBitmap.cy;
929 }
930 return IntSetDefaultRegion(pdc);
931 }
932
933 /*
934 * @implemented
935 */
936 BOOL
937 APIENTRY
938 NtGdiMakeInfoDC(
939 IN HDC hdc,
940 IN BOOL bSet)
941 {
942 BOOL Ret;
943 PDC pdc = DC_LockDc(hdc);
944 if (pdc)
945 {
946 Ret = MakeInfoDC(pdc, bSet);
947 DC_UnlockDc(pdc);
948 return Ret;
949 }
950 return FALSE;
951 }
952
953
954 HDC FASTCALL
955 IntGdiCreateDC(
956 PUNICODE_STRING Driver,
957 PUNICODE_STRING pustrDevice,
958 PVOID pUMdhpdev,
959 CONST PDEVMODEW pdmInit,
960 BOOL CreateAsIC)
961 {
962 HDC hdc;
963
964 hdc = GreOpenDCW(pustrDevice,
965 pdmInit,
966 NULL,
967 CreateAsIC ? DCTYPE_INFO :
968 (Driver ? DC_TYPE_DIRECT : DC_TYPE_DIRECT),
969 TRUE,
970 NULL,
971 NULL,
972 pUMdhpdev);
973
974 return hdc;
975 }
976
977 HDC FASTCALL
978 IntGdiCreateDisplayDC(HDEV hDev, ULONG DcType, BOOL EmptyDC)
979 {
980 HDC hDC;
981 UNIMPLEMENTED;
982 ASSERT(FALSE);
983
984 if (DcType == DC_TYPE_MEMORY)
985 hDC = NtGdiCreateCompatibleDC(NULL); // OH~ Yuck! I think I taste vomit in my mouth!
986 else
987 hDC = IntGdiCreateDC(NULL, NULL, NULL, NULL, (DcType == DC_TYPE_INFO));
988
989 return hDC;
990 }
991