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