1*4e0f2fc0SHervé Poussineau /*
2*4e0f2fc0SHervé Poussineau * PROJECT: ReactOS Win32k subsystem
3*4e0f2fc0SHervé Poussineau * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4*4e0f2fc0SHervé Poussineau * PURPOSE: Pan-Display driver
5*4e0f2fc0SHervé Poussineau * COPYRIGHT: Copyright 2022 Hervé Poussineau <hpoussin@reactos.org>
6*4e0f2fc0SHervé Poussineau */
7*4e0f2fc0SHervé Poussineau
8*4e0f2fc0SHervé Poussineau /* INCLUDES *******************************************************************/
9*4e0f2fc0SHervé Poussineau
10*4e0f2fc0SHervé Poussineau #include <win32k.h>
11*4e0f2fc0SHervé Poussineau #define NDEBUG
12*4e0f2fc0SHervé Poussineau #include <debug.h>
13*4e0f2fc0SHervé Poussineau
14*4e0f2fc0SHervé Poussineau #define TAG_PAN 'DnaP'
15*4e0f2fc0SHervé Poussineau #define GETPFN(name) ((PFN_Drv##name)(pandev->apfn[INDEX_Drv##name]))
16*4e0f2fc0SHervé Poussineau
17*4e0f2fc0SHervé Poussineau static DHPDEV gPan; /* FIXME: remove once PanSynchronize() is called periodically */
18*4e0f2fc0SHervé Poussineau
19*4e0f2fc0SHervé Poussineau typedef struct _PANDEV
20*4e0f2fc0SHervé Poussineau {
21*4e0f2fc0SHervé Poussineau ULONG iBitmapFormat;
22*4e0f2fc0SHervé Poussineau HDEV hdev;
23*4e0f2fc0SHervé Poussineau SIZEL szlDesktop; /* Size of the whole desktop */
24*4e0f2fc0SHervé Poussineau RECTL rclViewport; /* Viewport area */
25*4e0f2fc0SHervé Poussineau HSURF hsurf; /* Global surface */
26*4e0f2fc0SHervé Poussineau HSURF hsurfShadow; /* Our shadow surface, used for drawing */
27*4e0f2fc0SHervé Poussineau SURFOBJ *psoShadow;
28*4e0f2fc0SHervé Poussineau
29*4e0f2fc0SHervé Poussineau /* Underlying PDEVOBJ */
30*4e0f2fc0SHervé Poussineau ULONG flUnderlyingGraphicsCaps;
31*4e0f2fc0SHervé Poussineau SIZEL szlScreen;
32*4e0f2fc0SHervé Poussineau DHPDEV dhpdevScreen;
33*4e0f2fc0SHervé Poussineau BOOL enabledScreen; /* underlying surface enabled */
34*4e0f2fc0SHervé Poussineau SURFOBJ *surfObjScreen;
35*4e0f2fc0SHervé Poussineau PFN apfn[INDEX_LAST]; /* Functions of underlying PDEVOBJ */
36*4e0f2fc0SHervé Poussineau } PANDEV, *PPANDEV;
37*4e0f2fc0SHervé Poussineau
38*4e0f2fc0SHervé Poussineau BOOL
39*4e0f2fc0SHervé Poussineau APIENTRY
PanSynchronize(_In_ DHPDEV dhpdev,_In_ PRECTL prcl)40*4e0f2fc0SHervé Poussineau PanSynchronize(
41*4e0f2fc0SHervé Poussineau _In_ DHPDEV dhpdev,
42*4e0f2fc0SHervé Poussineau _In_ PRECTL prcl)
43*4e0f2fc0SHervé Poussineau {
44*4e0f2fc0SHervé Poussineau PPANDEV pandev = (PPANDEV)dhpdev;
45*4e0f2fc0SHervé Poussineau RECTL rclDest;
46*4e0f2fc0SHervé Poussineau POINTL ptlSrc;
47*4e0f2fc0SHervé Poussineau
48*4e0f2fc0SHervé Poussineau /* FIXME: for now, copy the whole shadow buffer. We might try to optimize that */
49*4e0f2fc0SHervé Poussineau
50*4e0f2fc0SHervé Poussineau ptlSrc.x = pandev->rclViewport.left;
51*4e0f2fc0SHervé Poussineau ptlSrc.y = pandev->rclViewport.top;
52*4e0f2fc0SHervé Poussineau
53*4e0f2fc0SHervé Poussineau rclDest.top = rclDest.left = 0;
54*4e0f2fc0SHervé Poussineau rclDest.bottom = pandev->szlScreen.cy;
55*4e0f2fc0SHervé Poussineau rclDest.right = pandev->szlScreen.cx;
56*4e0f2fc0SHervé Poussineau
57*4e0f2fc0SHervé Poussineau return EngCopyBits(pandev->surfObjScreen, pandev->psoShadow, NULL, NULL, &rclDest, &ptlSrc);
58*4e0f2fc0SHervé Poussineau }
59*4e0f2fc0SHervé Poussineau
60*4e0f2fc0SHervé Poussineau DHPDEV
61*4e0f2fc0SHervé Poussineau APIENTRY
PanEnablePDEV(_In_ PDEVMODEW pdm,_In_ LPWSTR pwszLogAddress,_In_ ULONG cPat,_In_reads_opt_ (cPat)HSURF * phsurfPatterns,_In_ ULONG cjCaps,_Out_writes_bytes_ (cjCaps)PULONG pdevcaps,_In_ ULONG cjDevInfo,_Out_writes_bytes_ (cjDevInfo)PDEVINFO pdi,_In_ HDEV hdev,_In_ LPWSTR pwszDeviceName,_In_ HANDLE hDriver)62*4e0f2fc0SHervé Poussineau PanEnablePDEV(
63*4e0f2fc0SHervé Poussineau _In_ PDEVMODEW pdm,
64*4e0f2fc0SHervé Poussineau _In_ LPWSTR pwszLogAddress,
65*4e0f2fc0SHervé Poussineau _In_ ULONG cPat,
66*4e0f2fc0SHervé Poussineau _In_reads_opt_(cPat) HSURF *phsurfPatterns,
67*4e0f2fc0SHervé Poussineau _In_ ULONG cjCaps,
68*4e0f2fc0SHervé Poussineau _Out_writes_bytes_(cjCaps) PULONG pdevcaps,
69*4e0f2fc0SHervé Poussineau _In_ ULONG cjDevInfo,
70*4e0f2fc0SHervé Poussineau _Out_writes_bytes_(cjDevInfo) PDEVINFO pdi,
71*4e0f2fc0SHervé Poussineau _In_ HDEV hdev,
72*4e0f2fc0SHervé Poussineau _In_ LPWSTR pwszDeviceName,
73*4e0f2fc0SHervé Poussineau _In_ HANDLE hDriver)
74*4e0f2fc0SHervé Poussineau {
75*4e0f2fc0SHervé Poussineau PPANDEV pandev;
76*4e0f2fc0SHervé Poussineau PPDEVOBJ ppdev = (PPDEVOBJ)hdev;
77*4e0f2fc0SHervé Poussineau DEVMODEW underlyingDevmode;
78*4e0f2fc0SHervé Poussineau PGDIINFO pGdiInfo = (PGDIINFO)pdevcaps;
79*4e0f2fc0SHervé Poussineau
80*4e0f2fc0SHervé Poussineau DPRINT("PanEnablePDEV(ppdev %p %dx%dx%d -> %dx%dx%d %d Hz)\n",
81*4e0f2fc0SHervé Poussineau ppdev,
82*4e0f2fc0SHervé Poussineau pdm->dmPelsWidth, pdm->dmPelsHeight, pdm->dmBitsPerPel,
83*4e0f2fc0SHervé Poussineau pdm->dmPanningWidth, pdm->dmPanningHeight, pdm->dmBitsPerPel, pdm->dmDisplayFrequency);
84*4e0f2fc0SHervé Poussineau
85*4e0f2fc0SHervé Poussineau ASSERT(pdm->dmPanningWidth <= pdm->dmPelsWidth && pdm->dmPanningHeight <= pdm->dmPelsHeight);
86*4e0f2fc0SHervé Poussineau
87*4e0f2fc0SHervé Poussineau /* Allocate PANDEV */
88*4e0f2fc0SHervé Poussineau pandev = EngAllocMem(FL_ZERO_MEMORY, sizeof(PANDEV), TAG_PAN);
89*4e0f2fc0SHervé Poussineau if (!pandev)
90*4e0f2fc0SHervé Poussineau {
91*4e0f2fc0SHervé Poussineau DPRINT1("Failed to allocate memory\n");
92*4e0f2fc0SHervé Poussineau return NULL;
93*4e0f2fc0SHervé Poussineau }
94*4e0f2fc0SHervé Poussineau
95*4e0f2fc0SHervé Poussineau /* Copy device pointers to our structure (do not copy ppdev->apfn,
96*4e0f2fc0SHervé Poussineau * as it contains our local pointers!) */
97*4e0f2fc0SHervé Poussineau RtlCopyMemory(pandev->apfn, ppdev->pldev->apfn, sizeof(pandev->apfn));
98*4e0f2fc0SHervé Poussineau
99*4e0f2fc0SHervé Poussineau /* Enable underlying PDEV */
100*4e0f2fc0SHervé Poussineau underlyingDevmode = *pdm;
101*4e0f2fc0SHervé Poussineau underlyingDevmode.dmPelsWidth = pdm->dmPanningWidth;
102*4e0f2fc0SHervé Poussineau underlyingDevmode.dmPelsHeight = pdm->dmPanningHeight;
103*4e0f2fc0SHervé Poussineau pandev->dhpdevScreen = GETPFN(EnablePDEV)(&underlyingDevmode,
104*4e0f2fc0SHervé Poussineau pwszLogAddress,
105*4e0f2fc0SHervé Poussineau cPat,
106*4e0f2fc0SHervé Poussineau phsurfPatterns,
107*4e0f2fc0SHervé Poussineau cjCaps,
108*4e0f2fc0SHervé Poussineau pdevcaps,
109*4e0f2fc0SHervé Poussineau cjDevInfo,
110*4e0f2fc0SHervé Poussineau pdi,
111*4e0f2fc0SHervé Poussineau hdev,
112*4e0f2fc0SHervé Poussineau pwszDeviceName,
113*4e0f2fc0SHervé Poussineau hDriver);
114*4e0f2fc0SHervé Poussineau if (!pandev->dhpdevScreen)
115*4e0f2fc0SHervé Poussineau {
116*4e0f2fc0SHervé Poussineau DPRINT1("Failed to enable underlying PDEV\n");
117*4e0f2fc0SHervé Poussineau EngFreeMem(pandev);
118*4e0f2fc0SHervé Poussineau return NULL;
119*4e0f2fc0SHervé Poussineau }
120*4e0f2fc0SHervé Poussineau
121*4e0f2fc0SHervé Poussineau pandev->iBitmapFormat = pdi->iDitherFormat;
122*4e0f2fc0SHervé Poussineau pandev->szlDesktop.cx = pdm->dmPelsWidth;
123*4e0f2fc0SHervé Poussineau pandev->szlDesktop.cy = pdm->dmPelsHeight;
124*4e0f2fc0SHervé Poussineau pandev->szlScreen.cx = pdm->dmPanningWidth;
125*4e0f2fc0SHervé Poussineau pandev->szlScreen.cy = pdm->dmPanningHeight;
126*4e0f2fc0SHervé Poussineau pandev->flUnderlyingGraphicsCaps = pdi->flGraphicsCaps;
127*4e0f2fc0SHervé Poussineau
128*4e0f2fc0SHervé Poussineau /* Upgrade some capabilities */
129*4e0f2fc0SHervé Poussineau pGdiInfo->ulHorzRes = pdm->dmPelsWidth;
130*4e0f2fc0SHervé Poussineau pGdiInfo->ulVertRes = pdm->dmPelsHeight;
131*4e0f2fc0SHervé Poussineau pdi->flGraphicsCaps |= GCAPS_PANNING;
132*4e0f2fc0SHervé Poussineau pdi->flGraphicsCaps2 = GCAPS2_SYNCFLUSH | GCAPS2_SYNCTIMER;
133*4e0f2fc0SHervé Poussineau
134*4e0f2fc0SHervé Poussineau gPan = (DHPDEV)pandev;
135*4e0f2fc0SHervé Poussineau return (DHPDEV)pandev;
136*4e0f2fc0SHervé Poussineau }
137*4e0f2fc0SHervé Poussineau
138*4e0f2fc0SHervé Poussineau VOID
139*4e0f2fc0SHervé Poussineau APIENTRY
PanCompletePDEV(_In_ DHPDEV dhpdev,_In_ HDEV hdev)140*4e0f2fc0SHervé Poussineau PanCompletePDEV(
141*4e0f2fc0SHervé Poussineau _In_ DHPDEV dhpdev,
142*4e0f2fc0SHervé Poussineau _In_ HDEV hdev)
143*4e0f2fc0SHervé Poussineau {
144*4e0f2fc0SHervé Poussineau PPANDEV pandev = (PPANDEV)dhpdev;
145*4e0f2fc0SHervé Poussineau
146*4e0f2fc0SHervé Poussineau DPRINT("PanCompletePDEV(%p %p)\n", dhpdev, hdev);
147*4e0f2fc0SHervé Poussineau
148*4e0f2fc0SHervé Poussineau pandev->hdev = hdev;
149*4e0f2fc0SHervé Poussineau GETPFN(CompletePDEV)(pandev->dhpdevScreen, hdev);
150*4e0f2fc0SHervé Poussineau }
151*4e0f2fc0SHervé Poussineau
152*4e0f2fc0SHervé Poussineau VOID
153*4e0f2fc0SHervé Poussineau APIENTRY
PanDisablePDEV(_In_ DHPDEV dhpdev)154*4e0f2fc0SHervé Poussineau PanDisablePDEV(
155*4e0f2fc0SHervé Poussineau _In_ DHPDEV dhpdev)
156*4e0f2fc0SHervé Poussineau {
157*4e0f2fc0SHervé Poussineau PPANDEV pandev = (PPANDEV)dhpdev;
158*4e0f2fc0SHervé Poussineau
159*4e0f2fc0SHervé Poussineau DPRINT("PanDisablePDEV(%p)\n", dhpdev);
160*4e0f2fc0SHervé Poussineau
161*4e0f2fc0SHervé Poussineau GETPFN(DisablePDEV)(pandev->dhpdevScreen);
162*4e0f2fc0SHervé Poussineau EngFreeMem(pandev);
163*4e0f2fc0SHervé Poussineau }
164*4e0f2fc0SHervé Poussineau
165*4e0f2fc0SHervé Poussineau VOID
166*4e0f2fc0SHervé Poussineau APIENTRY
PanDisableSurface(_In_ DHPDEV dhpdev)167*4e0f2fc0SHervé Poussineau PanDisableSurface(
168*4e0f2fc0SHervé Poussineau _In_ DHPDEV dhpdev)
169*4e0f2fc0SHervé Poussineau {
170*4e0f2fc0SHervé Poussineau PPANDEV pandev = (PPANDEV)dhpdev;
171*4e0f2fc0SHervé Poussineau
172*4e0f2fc0SHervé Poussineau DPRINT("PanDisableSurface(%p)\n", dhpdev);
173*4e0f2fc0SHervé Poussineau
174*4e0f2fc0SHervé Poussineau /* Note that we must handle a not fully initialized pandev, as this
175*4e0f2fc0SHervé Poussineau * function is also called from PanEnableSurface in case of error. */
176*4e0f2fc0SHervé Poussineau
177*4e0f2fc0SHervé Poussineau if (pandev->psoShadow)
178*4e0f2fc0SHervé Poussineau {
179*4e0f2fc0SHervé Poussineau EngUnlockSurface(pandev->psoShadow);
180*4e0f2fc0SHervé Poussineau pandev->psoShadow = NULL;
181*4e0f2fc0SHervé Poussineau }
182*4e0f2fc0SHervé Poussineau if (pandev->hsurfShadow)
183*4e0f2fc0SHervé Poussineau {
184*4e0f2fc0SHervé Poussineau EngDeleteSurface(pandev->hsurfShadow);
185*4e0f2fc0SHervé Poussineau pandev->hsurfShadow = NULL;
186*4e0f2fc0SHervé Poussineau }
187*4e0f2fc0SHervé Poussineau if (pandev->hsurf)
188*4e0f2fc0SHervé Poussineau {
189*4e0f2fc0SHervé Poussineau EngDeleteSurface(pandev->hsurf);
190*4e0f2fc0SHervé Poussineau pandev->hsurf = NULL;
191*4e0f2fc0SHervé Poussineau }
192*4e0f2fc0SHervé Poussineau if (pandev->surfObjScreen)
193*4e0f2fc0SHervé Poussineau {
194*4e0f2fc0SHervé Poussineau EngUnlockSurface(pandev->surfObjScreen);
195*4e0f2fc0SHervé Poussineau pandev->surfObjScreen = NULL;
196*4e0f2fc0SHervé Poussineau }
197*4e0f2fc0SHervé Poussineau if (pandev->enabledScreen)
198*4e0f2fc0SHervé Poussineau {
199*4e0f2fc0SHervé Poussineau GETPFN(DisableSurface)(pandev->dhpdevScreen);
200*4e0f2fc0SHervé Poussineau pandev->enabledScreen = FALSE;
201*4e0f2fc0SHervé Poussineau }
202*4e0f2fc0SHervé Poussineau }
203*4e0f2fc0SHervé Poussineau
204*4e0f2fc0SHervé Poussineau HSURF
205*4e0f2fc0SHervé Poussineau APIENTRY
PanEnableSurface(_In_ DHPDEV dhpdev)206*4e0f2fc0SHervé Poussineau PanEnableSurface(
207*4e0f2fc0SHervé Poussineau _In_ DHPDEV dhpdev)
208*4e0f2fc0SHervé Poussineau {
209*4e0f2fc0SHervé Poussineau PPANDEV pandev = (PPANDEV)dhpdev;
210*4e0f2fc0SHervé Poussineau HSURF surfScreen;
211*4e0f2fc0SHervé Poussineau
212*4e0f2fc0SHervé Poussineau /* Move viewport to center of screen */
213*4e0f2fc0SHervé Poussineau pandev->rclViewport.left = (pandev->szlDesktop.cx - pandev->szlScreen.cx) / 2;
214*4e0f2fc0SHervé Poussineau pandev->rclViewport.top = (pandev->szlDesktop.cy - pandev->szlScreen.cy) / 2;
215*4e0f2fc0SHervé Poussineau pandev->rclViewport.right = pandev->rclViewport.left + pandev->szlScreen.cx;
216*4e0f2fc0SHervé Poussineau pandev->rclViewport.bottom = pandev->rclViewport.top + pandev->szlScreen.cy;
217*4e0f2fc0SHervé Poussineau
218*4e0f2fc0SHervé Poussineau /* Enable underlying device */
219*4e0f2fc0SHervé Poussineau surfScreen = GETPFN(EnableSurface)(pandev->dhpdevScreen);
220*4e0f2fc0SHervé Poussineau if (!surfScreen)
221*4e0f2fc0SHervé Poussineau {
222*4e0f2fc0SHervé Poussineau DPRINT1("Failed to enable underlying surface\n");
223*4e0f2fc0SHervé Poussineau goto failure;
224*4e0f2fc0SHervé Poussineau }
225*4e0f2fc0SHervé Poussineau pandev->enabledScreen = TRUE;
226*4e0f2fc0SHervé Poussineau
227*4e0f2fc0SHervé Poussineau pandev->surfObjScreen = EngLockSurface(surfScreen);
228*4e0f2fc0SHervé Poussineau if (!pandev->surfObjScreen)
229*4e0f2fc0SHervé Poussineau {
230*4e0f2fc0SHervé Poussineau DPRINT1("Failed to lock underlying surface\n");
231*4e0f2fc0SHervé Poussineau goto failure;
232*4e0f2fc0SHervé Poussineau }
233*4e0f2fc0SHervé Poussineau
234*4e0f2fc0SHervé Poussineau /* Create device surface */
235*4e0f2fc0SHervé Poussineau pandev->hsurf = EngCreateDeviceSurface(NULL, pandev->szlDesktop, pandev->iBitmapFormat);
236*4e0f2fc0SHervé Poussineau if (!pandev->hsurf)
237*4e0f2fc0SHervé Poussineau {
238*4e0f2fc0SHervé Poussineau DPRINT1("EngCreateDeviceSurface() failed\n");
239*4e0f2fc0SHervé Poussineau goto failure;
240*4e0f2fc0SHervé Poussineau }
241*4e0f2fc0SHervé Poussineau
242*4e0f2fc0SHervé Poussineau if (!EngAssociateSurface(pandev->hsurf, pandev->hdev, HOOK_ALPHABLEND |
243*4e0f2fc0SHervé Poussineau HOOK_BITBLT |
244*4e0f2fc0SHervé Poussineau HOOK_COPYBITS |
245*4e0f2fc0SHervé Poussineau HOOK_GRADIENTFILL |
246*4e0f2fc0SHervé Poussineau HOOK_STROKEPATH |
247*4e0f2fc0SHervé Poussineau HOOK_SYNCHRONIZE |
248*4e0f2fc0SHervé Poussineau HOOK_TEXTOUT))
249*4e0f2fc0SHervé Poussineau {
250*4e0f2fc0SHervé Poussineau DPRINT1("EngAssociateSurface() failed\n");
251*4e0f2fc0SHervé Poussineau goto failure;
252*4e0f2fc0SHervé Poussineau }
253*4e0f2fc0SHervé Poussineau
254*4e0f2fc0SHervé Poussineau /* Create shadow surface */
255*4e0f2fc0SHervé Poussineau pandev->hsurfShadow = (HSURF)EngCreateBitmap(pandev->szlDesktop, pandev->szlDesktop.cx, pandev->iBitmapFormat, BMF_TOPDOWN, NULL);
256*4e0f2fc0SHervé Poussineau if (!pandev->hsurfShadow)
257*4e0f2fc0SHervé Poussineau {
258*4e0f2fc0SHervé Poussineau DPRINT1("EngCreateBitmap() failed\n");
259*4e0f2fc0SHervé Poussineau goto failure;
260*4e0f2fc0SHervé Poussineau }
261*4e0f2fc0SHervé Poussineau
262*4e0f2fc0SHervé Poussineau pandev->psoShadow = EngLockSurface(pandev->hsurfShadow);
263*4e0f2fc0SHervé Poussineau if (!pandev->psoShadow)
264*4e0f2fc0SHervé Poussineau {
265*4e0f2fc0SHervé Poussineau DPRINT1("EngLockSurface() failed\n");
266*4e0f2fc0SHervé Poussineau goto failure;
267*4e0f2fc0SHervé Poussineau }
268*4e0f2fc0SHervé Poussineau
269*4e0f2fc0SHervé Poussineau return pandev->hsurf;
270*4e0f2fc0SHervé Poussineau
271*4e0f2fc0SHervé Poussineau failure:
272*4e0f2fc0SHervé Poussineau PanDisableSurface(dhpdev);
273*4e0f2fc0SHervé Poussineau return NULL;
274*4e0f2fc0SHervé Poussineau }
275*4e0f2fc0SHervé Poussineau
276*4e0f2fc0SHervé Poussineau BOOL
277*4e0f2fc0SHervé Poussineau APIENTRY
PanBitBlt(_Inout_ SURFOBJ * psoTrg,_In_opt_ SURFOBJ * psoSrc,_In_opt_ SURFOBJ * psoMask,_In_ CLIPOBJ * pco,_In_opt_ XLATEOBJ * pxlo,_In_ PRECTL prclTrg,_In_opt_ PPOINTL pptlSrc,_In_opt_ PPOINTL pptlMask,_In_opt_ BRUSHOBJ * pbo,_In_opt_ PPOINTL pptlBrush,_In_ ROP4 rop4)278*4e0f2fc0SHervé Poussineau PanBitBlt(
279*4e0f2fc0SHervé Poussineau _Inout_ SURFOBJ *psoTrg,
280*4e0f2fc0SHervé Poussineau _In_opt_ SURFOBJ *psoSrc,
281*4e0f2fc0SHervé Poussineau _In_opt_ SURFOBJ *psoMask,
282*4e0f2fc0SHervé Poussineau _In_ CLIPOBJ *pco,
283*4e0f2fc0SHervé Poussineau _In_opt_ XLATEOBJ *pxlo,
284*4e0f2fc0SHervé Poussineau _In_ PRECTL prclTrg,
285*4e0f2fc0SHervé Poussineau _In_opt_ PPOINTL pptlSrc,
286*4e0f2fc0SHervé Poussineau _In_opt_ PPOINTL pptlMask,
287*4e0f2fc0SHervé Poussineau _In_opt_ BRUSHOBJ *pbo,
288*4e0f2fc0SHervé Poussineau _In_opt_ PPOINTL pptlBrush,
289*4e0f2fc0SHervé Poussineau _In_ ROP4 rop4)
290*4e0f2fc0SHervé Poussineau {
291*4e0f2fc0SHervé Poussineau PPANDEV pandev;
292*4e0f2fc0SHervé Poussineau BOOL res;
293*4e0f2fc0SHervé Poussineau
294*4e0f2fc0SHervé Poussineau if (psoTrg->iType == STYPE_DEVICE)
295*4e0f2fc0SHervé Poussineau {
296*4e0f2fc0SHervé Poussineau pandev = (PPANDEV)psoTrg->dhpdev;
297*4e0f2fc0SHervé Poussineau psoTrg = pandev->psoShadow;
298*4e0f2fc0SHervé Poussineau }
299*4e0f2fc0SHervé Poussineau if (psoSrc && psoSrc->iType == STYPE_DEVICE)
300*4e0f2fc0SHervé Poussineau {
301*4e0f2fc0SHervé Poussineau pandev = (PPANDEV)psoSrc->dhpdev;
302*4e0f2fc0SHervé Poussineau psoSrc = pandev->psoShadow;
303*4e0f2fc0SHervé Poussineau }
304*4e0f2fc0SHervé Poussineau
305*4e0f2fc0SHervé Poussineau res = EngBitBlt(psoTrg, psoSrc, psoMask, pco, pxlo, prclTrg, pptlSrc, pptlMask, pbo, pptlBrush, rop4);
306*4e0f2fc0SHervé Poussineau
307*4e0f2fc0SHervé Poussineau /* FIXME: PanSynchronize must be called periodically, as we have the GCAPS2_SYNCTIMER flag.
308*4e0f2fc0SHervé Poussineau * That's not the case, so call PanSynchronize() manually */
309*4e0f2fc0SHervé Poussineau if (res)
310*4e0f2fc0SHervé Poussineau PanSynchronize(gPan, NULL);
311*4e0f2fc0SHervé Poussineau
312*4e0f2fc0SHervé Poussineau return res;
313*4e0f2fc0SHervé Poussineau }
314*4e0f2fc0SHervé Poussineau
315*4e0f2fc0SHervé Poussineau BOOL
316*4e0f2fc0SHervé Poussineau APIENTRY
PanCopyBits(_Inout_ SURFOBJ * psoDest,_In_opt_ SURFOBJ * psoSrc,_In_ CLIPOBJ * pco,_In_opt_ XLATEOBJ * pxlo,_In_ PRECTL prclDest,_In_opt_ PPOINTL pptlSrc)317*4e0f2fc0SHervé Poussineau PanCopyBits(
318*4e0f2fc0SHervé Poussineau _Inout_ SURFOBJ *psoDest,
319*4e0f2fc0SHervé Poussineau _In_opt_ SURFOBJ *psoSrc,
320*4e0f2fc0SHervé Poussineau _In_ CLIPOBJ *pco,
321*4e0f2fc0SHervé Poussineau _In_opt_ XLATEOBJ *pxlo,
322*4e0f2fc0SHervé Poussineau _In_ PRECTL prclDest,
323*4e0f2fc0SHervé Poussineau _In_opt_ PPOINTL pptlSrc)
324*4e0f2fc0SHervé Poussineau {
325*4e0f2fc0SHervé Poussineau /* Easy. Just call the more general function PanBitBlt */
326*4e0f2fc0SHervé Poussineau return PanBitBlt(psoDest, psoSrc, NULL, pco, pxlo, prclDest, pptlSrc, NULL, NULL, NULL, ROP4_SRCCOPY);
327*4e0f2fc0SHervé Poussineau }
328*4e0f2fc0SHervé Poussineau
329*4e0f2fc0SHervé Poussineau BOOL
330*4e0f2fc0SHervé Poussineau APIENTRY
PanStrokePath(_Inout_ SURFOBJ * pso,_In_ PATHOBJ * ppo,_In_ CLIPOBJ * pco,_In_opt_ XFORMOBJ * pxo,_In_ BRUSHOBJ * pbo,_In_ PPOINTL pptlBrushOrg,_In_ PLINEATTRS plineattrs,_In_ MIX mix)331*4e0f2fc0SHervé Poussineau PanStrokePath(
332*4e0f2fc0SHervé Poussineau _Inout_ SURFOBJ *pso,
333*4e0f2fc0SHervé Poussineau _In_ PATHOBJ *ppo,
334*4e0f2fc0SHervé Poussineau _In_ CLIPOBJ *pco,
335*4e0f2fc0SHervé Poussineau _In_opt_ XFORMOBJ *pxo,
336*4e0f2fc0SHervé Poussineau _In_ BRUSHOBJ *pbo,
337*4e0f2fc0SHervé Poussineau _In_ PPOINTL pptlBrushOrg,
338*4e0f2fc0SHervé Poussineau _In_ PLINEATTRS plineattrs,
339*4e0f2fc0SHervé Poussineau _In_ MIX mix)
340*4e0f2fc0SHervé Poussineau {
341*4e0f2fc0SHervé Poussineau UNIMPLEMENTED;
342*4e0f2fc0SHervé Poussineau ASSERT(FALSE);
343*4e0f2fc0SHervé Poussineau return FALSE;
344*4e0f2fc0SHervé Poussineau }
345*4e0f2fc0SHervé Poussineau
346*4e0f2fc0SHervé Poussineau BOOL
347*4e0f2fc0SHervé Poussineau APIENTRY
PanTextOut(_Inout_ SURFOBJ * pso,_In_ STROBJ * pstro,_In_ FONTOBJ * pfo,_In_ CLIPOBJ * pco,_In_opt_ PRECTL prclExtra,_In_opt_ PRECTL prclOpaque,_In_ BRUSHOBJ * pboFore,_In_ BRUSHOBJ * pboOpaque,_In_ PPOINTL pptlOrg,_In_ MIX mix)348*4e0f2fc0SHervé Poussineau PanTextOut(
349*4e0f2fc0SHervé Poussineau _Inout_ SURFOBJ *pso,
350*4e0f2fc0SHervé Poussineau _In_ STROBJ *pstro,
351*4e0f2fc0SHervé Poussineau _In_ FONTOBJ *pfo,
352*4e0f2fc0SHervé Poussineau _In_ CLIPOBJ *pco,
353*4e0f2fc0SHervé Poussineau _In_opt_ PRECTL prclExtra,
354*4e0f2fc0SHervé Poussineau _In_opt_ PRECTL prclOpaque,
355*4e0f2fc0SHervé Poussineau _In_ BRUSHOBJ *pboFore,
356*4e0f2fc0SHervé Poussineau _In_ BRUSHOBJ *pboOpaque,
357*4e0f2fc0SHervé Poussineau _In_ PPOINTL pptlOrg,
358*4e0f2fc0SHervé Poussineau _In_ MIX mix)
359*4e0f2fc0SHervé Poussineau {
360*4e0f2fc0SHervé Poussineau UNIMPLEMENTED;
361*4e0f2fc0SHervé Poussineau ASSERT(FALSE);
362*4e0f2fc0SHervé Poussineau return FALSE;
363*4e0f2fc0SHervé Poussineau }
364*4e0f2fc0SHervé Poussineau
365*4e0f2fc0SHervé Poussineau VOID
366*4e0f2fc0SHervé Poussineau APIENTRY
PanMovePointer(_Inout_ SURFOBJ * pso,_In_ LONG x,_In_ LONG y,_In_ PRECTL prcl)367*4e0f2fc0SHervé Poussineau PanMovePointer(
368*4e0f2fc0SHervé Poussineau _Inout_ SURFOBJ *pso,
369*4e0f2fc0SHervé Poussineau _In_ LONG x,
370*4e0f2fc0SHervé Poussineau _In_ LONG y,
371*4e0f2fc0SHervé Poussineau _In_ PRECTL prcl)
372*4e0f2fc0SHervé Poussineau {
373*4e0f2fc0SHervé Poussineau PPANDEV pandev = (PPANDEV)pso->dhpdev;
374*4e0f2fc0SHervé Poussineau PFN_DrvMovePointer pfnMovePointer;
375*4e0f2fc0SHervé Poussineau BOOL bChanged = FALSE;
376*4e0f2fc0SHervé Poussineau
377*4e0f2fc0SHervé Poussineau DPRINT("PanMovePointer(%d, %d)\n", x, y);
378*4e0f2fc0SHervé Poussineau
379*4e0f2fc0SHervé Poussineau /* FIXME: MouseSafetyOnDrawStart/MouseSafetyOnDrawEnd like to call us to hide/show the cursor,
380*4e0f2fc0SHervé Poussineau * without real reason (see 5b0f6dcceeae3cf21f2535e2c523c0bf2749ea6b). Ignore those calls */
381*4e0f2fc0SHervé Poussineau if (x < 0 || y >= 0) return;
382*4e0f2fc0SHervé Poussineau
383*4e0f2fc0SHervé Poussineau /* We don't set DrvSetPointerShape, so we must not be called
384*4e0f2fc0SHervé Poussineau * with x < 0 (hide cursor) or y >= 0 (we have GCAPS_PANNING) */
385*4e0f2fc0SHervé Poussineau ASSERT(x >= 0 && y < 0);
386*4e0f2fc0SHervé Poussineau
387*4e0f2fc0SHervé Poussineau /* Call underlying MovePointer function */
388*4e0f2fc0SHervé Poussineau if (pandev->flUnderlyingGraphicsCaps & GCAPS_PANNING)
389*4e0f2fc0SHervé Poussineau {
390*4e0f2fc0SHervé Poussineau pfnMovePointer = GETPFN(MovePointer);
391*4e0f2fc0SHervé Poussineau if (pfnMovePointer)
392*4e0f2fc0SHervé Poussineau pfnMovePointer(pandev->surfObjScreen, x, y, prcl);
393*4e0f2fc0SHervé Poussineau }
394*4e0f2fc0SHervé Poussineau
395*4e0f2fc0SHervé Poussineau y += pso->sizlBitmap.cy;
396*4e0f2fc0SHervé Poussineau
397*4e0f2fc0SHervé Poussineau if (x < pandev->rclViewport.left)
398*4e0f2fc0SHervé Poussineau {
399*4e0f2fc0SHervé Poussineau pandev->rclViewport.left = x;
400*4e0f2fc0SHervé Poussineau pandev->rclViewport.right = x + pandev->szlScreen.cx;
401*4e0f2fc0SHervé Poussineau bChanged = TRUE;
402*4e0f2fc0SHervé Poussineau }
403*4e0f2fc0SHervé Poussineau else if (x >= pandev->rclViewport.right)
404*4e0f2fc0SHervé Poussineau {
405*4e0f2fc0SHervé Poussineau pandev->rclViewport.right = x + 1;
406*4e0f2fc0SHervé Poussineau pandev->rclViewport.left = x - pandev->szlScreen.cx;
407*4e0f2fc0SHervé Poussineau bChanged = TRUE;
408*4e0f2fc0SHervé Poussineau }
409*4e0f2fc0SHervé Poussineau if (y < pandev->rclViewport.top)
410*4e0f2fc0SHervé Poussineau {
411*4e0f2fc0SHervé Poussineau pandev->rclViewport.top = y;
412*4e0f2fc0SHervé Poussineau pandev->rclViewport.bottom = y + pandev->szlScreen.cy;
413*4e0f2fc0SHervé Poussineau bChanged = TRUE;
414*4e0f2fc0SHervé Poussineau }
415*4e0f2fc0SHervé Poussineau else if (y >= pandev->rclViewport.bottom)
416*4e0f2fc0SHervé Poussineau {
417*4e0f2fc0SHervé Poussineau pandev->rclViewport.bottom = y + 1;
418*4e0f2fc0SHervé Poussineau pandev->rclViewport.top = y - pandev->szlScreen.cy;
419*4e0f2fc0SHervé Poussineau bChanged = TRUE;
420*4e0f2fc0SHervé Poussineau }
421*4e0f2fc0SHervé Poussineau
422*4e0f2fc0SHervé Poussineau if (bChanged)
423*4e0f2fc0SHervé Poussineau PanSynchronize(pso->dhpdev, NULL);
424*4e0f2fc0SHervé Poussineau }
425*4e0f2fc0SHervé Poussineau
426*4e0f2fc0SHervé Poussineau BOOL
427*4e0f2fc0SHervé Poussineau APIENTRY
PanAlphaBlend(_Inout_ SURFOBJ * psoDest,_In_ SURFOBJ * psoSrc,_In_ CLIPOBJ * pco,_In_opt_ XLATEOBJ * pxlo,_In_ PRECTL prclDest,_In_ PRECTL prclSrc,_In_ BLENDOBJ * pBlendObj)428*4e0f2fc0SHervé Poussineau PanAlphaBlend(
429*4e0f2fc0SHervé Poussineau _Inout_ SURFOBJ *psoDest,
430*4e0f2fc0SHervé Poussineau _In_ SURFOBJ *psoSrc,
431*4e0f2fc0SHervé Poussineau _In_ CLIPOBJ *pco,
432*4e0f2fc0SHervé Poussineau _In_opt_ XLATEOBJ *pxlo,
433*4e0f2fc0SHervé Poussineau _In_ PRECTL prclDest,
434*4e0f2fc0SHervé Poussineau _In_ PRECTL prclSrc,
435*4e0f2fc0SHervé Poussineau _In_ BLENDOBJ *pBlendObj)
436*4e0f2fc0SHervé Poussineau {
437*4e0f2fc0SHervé Poussineau PPANDEV pandev = (PPANDEV)psoDest->dhpdev;
438*4e0f2fc0SHervé Poussineau BOOL res;
439*4e0f2fc0SHervé Poussineau
440*4e0f2fc0SHervé Poussineau res = EngAlphaBlend(pandev->psoShadow, psoSrc, pco, pxlo, prclDest, prclSrc, pBlendObj);
441*4e0f2fc0SHervé Poussineau
442*4e0f2fc0SHervé Poussineau /* FIXME: PanSynchronize must be called periodically, as we have the GCAPS2_SYNCTIMER flag.
443*4e0f2fc0SHervé Poussineau * That's not the case, so call PanSynchronize() manually */
444*4e0f2fc0SHervé Poussineau if (res)
445*4e0f2fc0SHervé Poussineau PanSynchronize(gPan, NULL);
446*4e0f2fc0SHervé Poussineau
447*4e0f2fc0SHervé Poussineau return res;
448*4e0f2fc0SHervé Poussineau }
449*4e0f2fc0SHervé Poussineau
450*4e0f2fc0SHervé Poussineau BOOL
451*4e0f2fc0SHervé Poussineau APIENTRY
PanGradientFill(_Inout_ SURFOBJ * pso,_In_ CLIPOBJ * pco,_In_opt_ XLATEOBJ * pxlo,_In_ PTRIVERTEX pVertex,_In_ ULONG nVertex,_In_ PVOID pMesh,_In_ ULONG nMesh,_In_ PRECTL prclExtents,_In_ PPOINTL pptlDitherOrg,_In_ ULONG ulMode)452*4e0f2fc0SHervé Poussineau PanGradientFill(
453*4e0f2fc0SHervé Poussineau _Inout_ SURFOBJ *pso,
454*4e0f2fc0SHervé Poussineau _In_ CLIPOBJ *pco,
455*4e0f2fc0SHervé Poussineau _In_opt_ XLATEOBJ *pxlo,
456*4e0f2fc0SHervé Poussineau _In_ PTRIVERTEX pVertex,
457*4e0f2fc0SHervé Poussineau _In_ ULONG nVertex,
458*4e0f2fc0SHervé Poussineau _In_ PVOID pMesh,
459*4e0f2fc0SHervé Poussineau _In_ ULONG nMesh,
460*4e0f2fc0SHervé Poussineau _In_ PRECTL prclExtents,
461*4e0f2fc0SHervé Poussineau _In_ PPOINTL pptlDitherOrg,
462*4e0f2fc0SHervé Poussineau _In_ ULONG ulMode)
463*4e0f2fc0SHervé Poussineau {
464*4e0f2fc0SHervé Poussineau PPANDEV pandev = (PPANDEV)pso->dhpdev;
465*4e0f2fc0SHervé Poussineau BOOL res;
466*4e0f2fc0SHervé Poussineau
467*4e0f2fc0SHervé Poussineau res = EngGradientFill(pandev->psoShadow, pco, pxlo, pVertex, nVertex, pMesh, nMesh, prclExtents, pptlDitherOrg, ulMode);
468*4e0f2fc0SHervé Poussineau
469*4e0f2fc0SHervé Poussineau /* FIXME: PanSynchronize must be called periodically, as we have the GCAPS2_SYNCTIMER flag.
470*4e0f2fc0SHervé Poussineau * That's not the case, so call PanSynchronize() manually */
471*4e0f2fc0SHervé Poussineau if (res)
472*4e0f2fc0SHervé Poussineau PanSynchronize(gPan, NULL);
473*4e0f2fc0SHervé Poussineau
474*4e0f2fc0SHervé Poussineau return res;
475*4e0f2fc0SHervé Poussineau }
476*4e0f2fc0SHervé Poussineau
477*4e0f2fc0SHervé Poussineau DRVFN gPanDispDrvFn[] =
478*4e0f2fc0SHervé Poussineau {
479*4e0f2fc0SHervé Poussineau /* required */
480*4e0f2fc0SHervé Poussineau { INDEX_DrvEnablePDEV, (PFN) PanEnablePDEV },
481*4e0f2fc0SHervé Poussineau { INDEX_DrvCompletePDEV, (PFN) PanCompletePDEV },
482*4e0f2fc0SHervé Poussineau { INDEX_DrvDisablePDEV, (PFN) PanDisablePDEV },
483*4e0f2fc0SHervé Poussineau { INDEX_DrvEnableSurface, (PFN) PanEnableSurface },
484*4e0f2fc0SHervé Poussineau { INDEX_DrvDisableSurface, (PFN) PanDisableSurface },
485*4e0f2fc0SHervé Poussineau
486*4e0f2fc0SHervé Poussineau /* required for device-managed surfaces */
487*4e0f2fc0SHervé Poussineau { INDEX_DrvCopyBits, (PFN) PanCopyBits },
488*4e0f2fc0SHervé Poussineau { INDEX_DrvStrokePath, (PFN) PanStrokePath },
489*4e0f2fc0SHervé Poussineau { INDEX_DrvTextOut, (PFN) PanTextOut },
490*4e0f2fc0SHervé Poussineau
491*4e0f2fc0SHervé Poussineau /* optional, but required for panning functionality */
492*4e0f2fc0SHervé Poussineau { INDEX_DrvSynchronize, (PFN) PanSynchronize },
493*4e0f2fc0SHervé Poussineau { INDEX_DrvMovePointer, (PFN) PanMovePointer },
494*4e0f2fc0SHervé Poussineau
495*4e0f2fc0SHervé Poussineau /* optional */
496*4e0f2fc0SHervé Poussineau { INDEX_DrvBitBlt, (PFN) PanBitBlt },
497*4e0f2fc0SHervé Poussineau { INDEX_DrvAlphaBlend, (PFN) PanAlphaBlend },
498*4e0f2fc0SHervé Poussineau { INDEX_DrvGradientFill, (PFN) PanGradientFill },
499*4e0f2fc0SHervé Poussineau };
500*4e0f2fc0SHervé Poussineau
501*4e0f2fc0SHervé Poussineau ULONG gPanDispDrvCount = RTL_NUMBER_OF(gPanDispDrvFn);
502