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