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