1 | /* $Id: VBoxDispVBVA.cpp 37423 2011-06-12 18:37:56Z vboxsync $ */
|
---|
2 |
|
---|
3 | /** @file
|
---|
4 | * VBox XPDM Display driver
|
---|
5 | */
|
---|
6 |
|
---|
7 | /*
|
---|
8 | * Copyright (C) 2011 Oracle Corporation
|
---|
9 | *
|
---|
10 | * This file is part of VirtualBox Open Source Edition (OSE), as
|
---|
11 | * available from http://www.virtualbox.org. This file is free software;
|
---|
12 | * you can redistribute it and/or modify it under the terms of the GNU
|
---|
13 | * General Public License (GPL) as published by the Free Software
|
---|
14 | * Foundation, in version 2 as it comes in the "COPYING" file of the
|
---|
15 | * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
|
---|
16 | * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
|
---|
17 | */
|
---|
18 |
|
---|
19 | #include "VBoxDisp.h"
|
---|
20 | #include "VBoxDispMini.h"
|
---|
21 | #include <VBox/HGSMI/HGSMIChSetup.h>
|
---|
22 |
|
---|
23 | #ifdef VBOX_VBVA_ADJUST_RECT
|
---|
24 | static ULONG vbvaConvertPixel(BYTE *pu8PixelFrom, int cbPixelFrom, int cbPixelTo)
|
---|
25 | {
|
---|
26 | BYTE r, g, b;
|
---|
27 | ULONG ulConvertedPixel = 0;
|
---|
28 |
|
---|
29 | switch (cbPixelFrom)
|
---|
30 | {
|
---|
31 | case 4:
|
---|
32 | {
|
---|
33 | switch (cbPixelTo)
|
---|
34 | {
|
---|
35 | case 3:
|
---|
36 | {
|
---|
37 | memcpy (&ulConvertedPixel, pu8PixelFrom, 3);
|
---|
38 | } break;
|
---|
39 |
|
---|
40 | case 2:
|
---|
41 | {
|
---|
42 | ulConvertedPixel = *(ULONG *)pu8PixelFrom;
|
---|
43 |
|
---|
44 | r = (BYTE)(ulConvertedPixel >> 16);
|
---|
45 | g = (BYTE)(ulConvertedPixel >> 8);
|
---|
46 | b = (BYTE)(ulConvertedPixel);
|
---|
47 |
|
---|
48 | ulConvertedPixel = ((r >> 3) << 11) + ((g >> 2) << 5) + (b >> 3);
|
---|
49 | } break;
|
---|
50 | }
|
---|
51 | } break;
|
---|
52 |
|
---|
53 | case 3:
|
---|
54 | {
|
---|
55 | switch (cbPixelTo)
|
---|
56 | {
|
---|
57 | case 2:
|
---|
58 | {
|
---|
59 | memcpy (&ulConvertedPixel, pu8PixelFrom, 3);
|
---|
60 |
|
---|
61 | r = (BYTE)(ulConvertedPixel >> 16);
|
---|
62 | g = (BYTE)(ulConvertedPixel >> 8);
|
---|
63 | b = (BYTE)(ulConvertedPixel);
|
---|
64 |
|
---|
65 | ulConvertedPixel = ((r >> 3) << 11) + ((g >> 2) << 5) + (b >> 3);
|
---|
66 | } break;
|
---|
67 | }
|
---|
68 | } break;
|
---|
69 | }
|
---|
70 |
|
---|
71 | return ulConvertedPixel;
|
---|
72 | }
|
---|
73 |
|
---|
74 | BOOL vbvaFindChangedRect(SURFOBJ *psoDest, SURFOBJ *psoSrc, RECTL *prclDest, POINTL *pptlSrc)
|
---|
75 | {
|
---|
76 | int x, y;
|
---|
77 | int fTopNonEqualFound;
|
---|
78 | int yTopmost;
|
---|
79 | int yBottommost;
|
---|
80 | int cbPixelSrc;
|
---|
81 | int cbPixelDest;
|
---|
82 | RECTL rclDest;
|
---|
83 | RECTL rclSrc;
|
---|
84 | BYTE *pu8Src;
|
---|
85 | BYTE *pu8Dest;
|
---|
86 |
|
---|
87 | if (!prclDest || !pptlSrc)
|
---|
88 | {
|
---|
89 | return TRUE;
|
---|
90 | }
|
---|
91 |
|
---|
92 | LOGF(("dest %d,%d %dx%d from %d,%d",
|
---|
93 | prclDest->left, prclDest->top, prclDest->right - prclDest->left, prclDest->bottom - prclDest->top,
|
---|
94 | pptlSrc->x, pptlSrc->y));
|
---|
95 |
|
---|
96 | switch (psoDest->iBitmapFormat)
|
---|
97 | {
|
---|
98 | case BMF_16BPP: cbPixelDest = 2; break;
|
---|
99 | case BMF_24BPP: cbPixelDest = 3; break;
|
---|
100 | case BMF_32BPP: cbPixelDest = 4; break;
|
---|
101 | default: cbPixelDest = 0;
|
---|
102 | }
|
---|
103 |
|
---|
104 | switch (psoSrc->iBitmapFormat)
|
---|
105 | {
|
---|
106 | case BMF_16BPP: cbPixelSrc = 2; break;
|
---|
107 | case BMF_24BPP: cbPixelSrc = 3; break;
|
---|
108 | case BMF_32BPP: cbPixelSrc = 4; break;
|
---|
109 | default: cbPixelSrc = 0;
|
---|
110 | }
|
---|
111 |
|
---|
112 | if (cbPixelDest == 0 || cbPixelSrc == 0)
|
---|
113 | {
|
---|
114 | WARN(("unsupported pixel format src %d dst %d", psoDest->iBitmapFormat, psoSrc->iBitmapFormat));
|
---|
115 | return TRUE;
|
---|
116 | }
|
---|
117 |
|
---|
118 | rclDest = *prclDest;
|
---|
119 |
|
---|
120 | vrdpAdjustRect(psoDest, &rclDest);
|
---|
121 |
|
---|
122 | pptlSrc->x += rclDest.left - prclDest->left;
|
---|
123 | pptlSrc->y += rclDest.top - prclDest->top;
|
---|
124 |
|
---|
125 | *prclDest = rclDest;
|
---|
126 |
|
---|
127 | if ( rclDest.right == rclDest.left
|
---|
128 | || rclDest.bottom == rclDest.top)
|
---|
129 | {
|
---|
130 | WARN(("empty dest rect: %d-%d, %d-%d", rclDest.left, rclDest.right, rclDest.top, rclDest.bottom));
|
---|
131 | return FALSE;
|
---|
132 | }
|
---|
133 |
|
---|
134 | rclSrc.left = pptlSrc->x;
|
---|
135 | rclSrc.top = pptlSrc->y;
|
---|
136 | rclSrc.right = pptlSrc->x + (rclDest.right - rclDest.left);
|
---|
137 | rclSrc.bottom = pptlSrc->y + (rclDest.bottom - rclDest.top);
|
---|
138 | vrdpAdjustRect (psoSrc, &rclSrc);
|
---|
139 |
|
---|
140 | if ( rclSrc.right == rclSrc.left
|
---|
141 | || rclSrc.bottom == rclSrc.top)
|
---|
142 | {
|
---|
143 | prclDest->right = prclDest->left;
|
---|
144 | prclDest->bottom = prclDest->top;
|
---|
145 |
|
---|
146 | WARN(("empty src rect: %d-%d, %d-%d", rclSrc.left, rclSrc.right, rclSrc.top, rclSrc.bottom));
|
---|
147 | return FALSE;
|
---|
148 | }
|
---|
149 |
|
---|
150 | Assert(pptlSrc->x == rclSrc.left);
|
---|
151 | Assert(pptlSrc->y == rclSrc.top);
|
---|
152 |
|
---|
153 | /*
|
---|
154 | * Compare the content of the screen surface (psoDest) with the source surface (psoSrc).
|
---|
155 | * Update the prclDest with the rectangle that will be actually changed after
|
---|
156 | * copying the source bits to the screen.
|
---|
157 | */
|
---|
158 | pu8Src = (BYTE *)psoSrc->pvScan0 + psoSrc->lDelta * pptlSrc->y + cbPixelSrc * pptlSrc->x;
|
---|
159 | pu8Dest = (BYTE *)psoDest->pvScan0 + psoDest->lDelta * prclDest->top + cbPixelDest * prclDest->left;
|
---|
160 |
|
---|
161 | /* Use the rclDest as the bounding rectangle for the changed area. */
|
---|
162 | rclDest.left = prclDest->right; /* +inf */
|
---|
163 | rclDest.right = prclDest->left; /* -inf */
|
---|
164 | rclDest.top = prclDest->bottom; /* +inf */
|
---|
165 | rclDest.bottom = prclDest->top; /* -inf */
|
---|
166 |
|
---|
167 | fTopNonEqualFound = 0;
|
---|
168 | yTopmost = prclDest->top; /* inclusive */
|
---|
169 | yBottommost = prclDest->top - 1; /* inclusive */
|
---|
170 |
|
---|
171 | for (y = prclDest->top; y < prclDest->bottom; y++)
|
---|
172 | {
|
---|
173 | int fLeftNonEqualFound = 0;
|
---|
174 |
|
---|
175 | /* Init to an empty line. */
|
---|
176 | int xLeftmost = prclDest->left; /* inclusive */
|
---|
177 | int xRightmost = prclDest->left - 1; /* inclusive */
|
---|
178 |
|
---|
179 | BYTE *pu8SrcLine = pu8Src;
|
---|
180 | BYTE *pu8DestLine = pu8Dest;
|
---|
181 |
|
---|
182 | for (x = prclDest->left; x < prclDest->right; x++)
|
---|
183 | {
|
---|
184 | int fEqualPixels;
|
---|
185 |
|
---|
186 | if (cbPixelSrc == cbPixelDest)
|
---|
187 | {
|
---|
188 | fEqualPixels = (memcmp (pu8SrcLine, pu8DestLine, cbPixelDest) == 0);
|
---|
189 | }
|
---|
190 | else
|
---|
191 | {
|
---|
192 | /* Convert larger pixel to the smaller pixel format. */
|
---|
193 | ULONG ulConvertedPixel;
|
---|
194 | if (cbPixelSrc > cbPixelDest)
|
---|
195 | {
|
---|
196 | /* Convert the source pixel to the destination pixel format. */
|
---|
197 | ulConvertedPixel = vbvaConvertPixel ( /*from*/ pu8SrcLine, cbPixelSrc,
|
---|
198 | /*to*/ cbPixelDest);
|
---|
199 | fEqualPixels = (memcmp (&ulConvertedPixel, pu8DestLine, cbPixelDest) == 0);
|
---|
200 | }
|
---|
201 | else
|
---|
202 | {
|
---|
203 | /* Convert the destination pixel to the source pixel format. */
|
---|
204 | ulConvertedPixel = vbvaConvertPixel ( /*from*/ pu8DestLine, cbPixelDest,
|
---|
205 | /*to*/ cbPixelSrc);
|
---|
206 | fEqualPixels = (memcmp (&ulConvertedPixel, pu8SrcLine, cbPixelSrc) == 0);
|
---|
207 | }
|
---|
208 | }
|
---|
209 |
|
---|
210 | if (fEqualPixels)
|
---|
211 | {
|
---|
212 | /* Equal pixels. */
|
---|
213 | if (!fLeftNonEqualFound)
|
---|
214 | {
|
---|
215 | xLeftmost = x;
|
---|
216 | }
|
---|
217 | }
|
---|
218 | else
|
---|
219 | {
|
---|
220 | fLeftNonEqualFound = 1;
|
---|
221 | xRightmost = x;
|
---|
222 | }
|
---|
223 |
|
---|
224 | pu8SrcLine += cbPixelSrc;
|
---|
225 | pu8DestLine += cbPixelDest;
|
---|
226 | }
|
---|
227 |
|
---|
228 | /* min */
|
---|
229 | if (rclDest.left > xLeftmost)
|
---|
230 | {
|
---|
231 | rclDest.left = xLeftmost;
|
---|
232 | }
|
---|
233 |
|
---|
234 | /* max */
|
---|
235 | if (rclDest.right < xRightmost)
|
---|
236 | {
|
---|
237 | rclDest.right = xRightmost;
|
---|
238 | }
|
---|
239 |
|
---|
240 | if (xLeftmost > xRightmost) /* xRightmost is inclusive, so '>', not '>='. */
|
---|
241 | {
|
---|
242 | /* Empty line. */
|
---|
243 | if (!fTopNonEqualFound)
|
---|
244 | {
|
---|
245 | yTopmost = y;
|
---|
246 | }
|
---|
247 | }
|
---|
248 | else
|
---|
249 | {
|
---|
250 | fTopNonEqualFound = 1;
|
---|
251 | yBottommost = y;
|
---|
252 | }
|
---|
253 |
|
---|
254 | pu8Src += psoSrc->lDelta;
|
---|
255 | pu8Dest += psoDest->lDelta;
|
---|
256 | }
|
---|
257 |
|
---|
258 | /* min */
|
---|
259 | if (rclDest.top > yTopmost)
|
---|
260 | {
|
---|
261 | rclDest.top = yTopmost;
|
---|
262 | }
|
---|
263 |
|
---|
264 | /* max */
|
---|
265 | if (rclDest.bottom < yBottommost)
|
---|
266 | {
|
---|
267 | rclDest.bottom = yBottommost;
|
---|
268 | }
|
---|
269 |
|
---|
270 | /* rclDest was calculated with right-bottom inclusive.
|
---|
271 | * The following checks and the caller require exclusive coords.
|
---|
272 | */
|
---|
273 | rclDest.right++;
|
---|
274 | rclDest.bottom++;
|
---|
275 |
|
---|
276 | LOG(("new dest %d,%d %dx%d from %d,%d",
|
---|
277 | rclDest.left, rclDest.top, rclDest.right - rclDest.left, rclDest.bottom - rclDest.top,
|
---|
278 | pptlSrc->x, pptlSrc->y));
|
---|
279 |
|
---|
280 | /* Update the rectangle with the changed area. */
|
---|
281 | if ( rclDest.left >= rclDest.right
|
---|
282 | || rclDest.top >= rclDest.bottom)
|
---|
283 | {
|
---|
284 | /* Empty rect. */
|
---|
285 | LOG(("empty"));
|
---|
286 | prclDest->right = prclDest->left;
|
---|
287 | prclDest->bottom = prclDest->top;
|
---|
288 | return FALSE;
|
---|
289 | }
|
---|
290 |
|
---|
291 | LOG(("not empty"));
|
---|
292 |
|
---|
293 | pptlSrc->x += rclDest.left - prclDest->left;
|
---|
294 | pptlSrc->y += rclDest.top - prclDest->top;
|
---|
295 |
|
---|
296 | *prclDest = rclDest;
|
---|
297 |
|
---|
298 | return TRUE;
|
---|
299 | }
|
---|
300 | #endif /* VBOX_VBVA_ADJUST_RECT */
|
---|
301 |
|
---|
302 | int VBoxDispVBVAInit(PVBOXDISPDEV pDev)
|
---|
303 | {
|
---|
304 | int rc;
|
---|
305 | DWORD dwrc;
|
---|
306 | ULONG cbReturned;
|
---|
307 | QUERYHGSMIRESULT info;
|
---|
308 | HGSMIQUERYCALLBACKS callbacks;
|
---|
309 | HGSMIQUERYCPORTPROCS portProcs;
|
---|
310 | LOGF_ENTER();
|
---|
311 |
|
---|
312 | /* Check if HGSMI is supported and obtain necessary info */
|
---|
313 | rc = VBoxDispMPQueryHGSMIInfo(pDev->hDriver, &info);
|
---|
314 | if (RT_SUCCESS(rc))
|
---|
315 | {
|
---|
316 | rc = VBoxDispMPQueryHGSMICallbacks(pDev->hDriver, &callbacks);
|
---|
317 | if (RT_SUCCESS(rc))
|
---|
318 | {
|
---|
319 | rc = VBoxDispMPHGSMIQueryPortProcs(pDev->hDriver, &portProcs);
|
---|
320 | }
|
---|
321 | }
|
---|
322 | if (RT_SUCCESS(rc))
|
---|
323 | {
|
---|
324 | pDev->hgsmi.bSupported = TRUE;
|
---|
325 |
|
---|
326 | pDev->hgsmi.mp = callbacks;
|
---|
327 | pDev->vpAPI = portProcs;
|
---|
328 | }
|
---|
329 |
|
---|
330 | if (pDev->hgsmi.bSupported)
|
---|
331 | {
|
---|
332 | HGSMIHANDLERENABLE HandlerReg;
|
---|
333 |
|
---|
334 | memset(&HandlerReg, 0, sizeof(HandlerReg));
|
---|
335 | HandlerReg.u8Channel = HGSMI_CH_VBVA;
|
---|
336 | dwrc = EngDeviceIoControl(pDev->hDriver, IOCTL_VIDEO_HGSMI_HANDLER_ENABLE, &HandlerReg, sizeof(HandlerReg),
|
---|
337 | 0, NULL, &cbReturned);
|
---|
338 | VBOX_WARN_WINERR(dwrc);
|
---|
339 |
|
---|
340 | #ifdef VBOX_WITH_VIDEOHWACCEL
|
---|
341 | if (NO_ERROR == dwrc)
|
---|
342 | {
|
---|
343 | VBoxDispVHWAInit(pDev);
|
---|
344 | }
|
---|
345 | #endif
|
---|
346 | }
|
---|
347 |
|
---|
348 | /* Check if we have enough VRAM and update layout info.
|
---|
349 | * 0=Framebuffer(fixed)->DDrawHeap(all left vram)->VBVABuffer(64k..cbFramebuffer)->DisplayInfo(fixed)->=EndOfVRAM
|
---|
350 | */
|
---|
351 | if (pDev->hgsmi.bSupported)
|
---|
352 | {
|
---|
353 | ULONG cbAvailable;
|
---|
354 | VBOXDISPVRAMLAYOUT *vram = &pDev->layout;
|
---|
355 |
|
---|
356 | pDev->iDevice = info.iDevice;
|
---|
357 |
|
---|
358 | vram->cbVRAM = pDev->memInfo.VideoRamLength;
|
---|
359 |
|
---|
360 | vram->offFramebuffer = 0;
|
---|
361 | vram->cbFramebuffer = RT_ALIGN_32(pDev->memInfo.FrameBufferLength, 0x1000);
|
---|
362 | cbAvailable = vram->cbVRAM - vram->cbFramebuffer;
|
---|
363 |
|
---|
364 | if (cbAvailable <= info.u32DisplayInfoSize)
|
---|
365 | {
|
---|
366 | pDev->hgsmi.bSupported = FALSE;
|
---|
367 | }
|
---|
368 | else
|
---|
369 | {
|
---|
370 | vram->offDisplayInfo = vram->cbVRAM - info.u32DisplayInfoSize;
|
---|
371 | vram->cbDisplayInfo = info.u32DisplayInfoSize;
|
---|
372 | cbAvailable -= vram->cbDisplayInfo;
|
---|
373 |
|
---|
374 | for (vram->cbVBVABuffer = vram->cbFramebuffer;
|
---|
375 | vram->cbVBVABuffer >= info.u32MinVBVABufferSize;
|
---|
376 | vram->cbVBVABuffer /= 2)
|
---|
377 | {
|
---|
378 | if (vram->cbVBVABuffer < cbAvailable)
|
---|
379 | {
|
---|
380 | break;
|
---|
381 | }
|
---|
382 | }
|
---|
383 |
|
---|
384 | if (vram->cbVBVABuffer >= cbAvailable)
|
---|
385 | {
|
---|
386 | pDev->hgsmi.bSupported = FALSE;
|
---|
387 | }
|
---|
388 | else
|
---|
389 | {
|
---|
390 | vram->offDDrawHeap = vram->offFramebuffer + vram->cbFramebuffer;
|
---|
391 |
|
---|
392 | cbAvailable -= vram->cbVBVABuffer;
|
---|
393 | vram->cbDDrawHeap = cbAvailable;
|
---|
394 |
|
---|
395 | vram->offVBVABuffer = vram->offDDrawHeap + vram->cbDDrawHeap;
|
---|
396 | }
|
---|
397 | }
|
---|
398 | }
|
---|
399 |
|
---|
400 | /* Setup HGSMI heap in the display information area.
|
---|
401 | * The area has some space reserved for HGSMI event flags in the beginning.
|
---|
402 | */
|
---|
403 | if (pDev->hgsmi.bSupported)
|
---|
404 | {
|
---|
405 | LOG(("offBase=%#x", info.areaDisplay.offBase));
|
---|
406 |
|
---|
407 | rc = HGSMIHeapSetup(&pDev->hgsmi.ctx.heapCtx,
|
---|
408 | (uint8_t *)pDev->memInfo.VideoRamBase+pDev->layout.offDisplayInfo+sizeof(HGSMIHOSTFLAGS),
|
---|
409 | pDev->layout.cbDisplayInfo-sizeof(HGSMIHOSTFLAGS),
|
---|
410 | info.areaDisplay.offBase+pDev->layout.offDisplayInfo+sizeof(HGSMIHOSTFLAGS),
|
---|
411 | false /*fOffsetBased*/);
|
---|
412 |
|
---|
413 | if (RT_SUCCESS(rc))
|
---|
414 | {
|
---|
415 | pDev->hgsmi.ctx.port = info.IOPortGuestCommand;
|
---|
416 | }
|
---|
417 | else
|
---|
418 | {
|
---|
419 | VBOX_WARNRC(rc);
|
---|
420 | pDev->hgsmi.bSupported = FALSE;
|
---|
421 | }
|
---|
422 | }
|
---|
423 |
|
---|
424 | /* If we don't have HGSMI or doesn't have enough VRAM, setup layout without VBVA buffer and display info */
|
---|
425 | if (!pDev->hgsmi.bSupported)
|
---|
426 | {
|
---|
427 | VBOXDISPVRAMLAYOUT *vram = &pDev->layout;
|
---|
428 |
|
---|
429 | pDev->iDevice = 0;
|
---|
430 |
|
---|
431 | /* Setup a layout without both the VBVA buffer and the display information. */
|
---|
432 | vram->cbVRAM = pDev->memInfo.VideoRamLength;
|
---|
433 |
|
---|
434 | vram->offFramebuffer = 0;
|
---|
435 | vram->cbFramebuffer = RT_ALIGN_32(pDev->memInfo.FrameBufferLength, 0x1000);
|
---|
436 |
|
---|
437 | vram->offDDrawHeap = vram->offFramebuffer + vram->cbFramebuffer;
|
---|
438 | vram->cbDDrawHeap = vram->cbVRAM - vram->offDDrawHeap;
|
---|
439 |
|
---|
440 | vram->offVBVABuffer = vram->offDDrawHeap + vram->cbDDrawHeap;
|
---|
441 | vram->cbVBVABuffer = 0;
|
---|
442 |
|
---|
443 | vram->offDisplayInfo = vram->offVBVABuffer + vram->cbVBVABuffer;
|
---|
444 | vram->cbDisplayInfo = 0;
|
---|
445 | }
|
---|
446 |
|
---|
447 | /* Update buffer layout in VBVA context info */
|
---|
448 | VBoxVBVASetupBufferContext(&pDev->vbvaCtx, pDev->layout.offVBVABuffer, pDev->layout.cbVBVABuffer);
|
---|
449 |
|
---|
450 | LOG(("\n"
|
---|
451 | " cbVRAM=%#X\n"
|
---|
452 | " offFramebuffer=%#X cbFramebuffer=%#X\n"
|
---|
453 | " offDDrawHeap=%#X cbDDrawHeap=%#X\n"
|
---|
454 | " offVBVABuffer=%#X cbVBVABuffer=%#X\n"
|
---|
455 | " offDisplayInfo=%#X cbDisplayInfo=%#X\n",
|
---|
456 | pDev->layout.cbVRAM,
|
---|
457 | pDev->layout.offFramebuffer, pDev->layout.cbFramebuffer,
|
---|
458 | pDev->layout.offDDrawHeap, pDev->layout.cbDDrawHeap,
|
---|
459 | pDev->layout.offVBVABuffer, pDev->layout.cbVBVABuffer,
|
---|
460 | pDev->layout.offDisplayInfo, pDev->layout.cbDisplayInfo
|
---|
461 | ));
|
---|
462 |
|
---|
463 | LOGF_LEAVE();
|
---|
464 | return VINF_SUCCESS;
|
---|
465 | }
|
---|
466 |
|
---|
467 | void VBoxDispVBVAHostCommandComplete(PVBOXDISPDEV pDev, VBVAHOSTCMD *pCmd)
|
---|
468 | {
|
---|
469 | pDev->hgsmi.mp.pfnCompletionHandler(pDev->hgsmi.mp.hContext, pCmd);
|
---|
470 | }
|
---|
471 |
|
---|
472 | void vbvaReportDirtyRect(PVBOXDISPDEV pDev, RECTL *pRectOrig)
|
---|
473 | {
|
---|
474 | if (pDev && pRectOrig)
|
---|
475 | {
|
---|
476 |
|
---|
477 | LOG(("dirty rect: left %d, top: %d, width: %d, height: %d",
|
---|
478 | pRectOrig->left, pRectOrig->top,
|
---|
479 | pRectOrig->right - pRectOrig->left, pRectOrig->bottom - pRectOrig->top));
|
---|
480 |
|
---|
481 | VBVACMDHDR hdr;
|
---|
482 | RECTL rect;
|
---|
483 |
|
---|
484 | /* Ensure correct order. */
|
---|
485 | if (pRectOrig->left <= pRectOrig->right)
|
---|
486 | {
|
---|
487 | rect.left = pRectOrig->left;
|
---|
488 | rect.right = pRectOrig->right;
|
---|
489 | }
|
---|
490 | else
|
---|
491 | {
|
---|
492 | rect.left = pRectOrig->right;
|
---|
493 | rect.right = pRectOrig->left;
|
---|
494 | }
|
---|
495 |
|
---|
496 | if (pRectOrig->top <= pRectOrig->bottom)
|
---|
497 | {
|
---|
498 | rect.top = pRectOrig->top;
|
---|
499 | rect.bottom = pRectOrig->bottom;
|
---|
500 | }
|
---|
501 | else
|
---|
502 | {
|
---|
503 | rect.top = pRectOrig->bottom;
|
---|
504 | rect.bottom = pRectOrig->top;
|
---|
505 | }
|
---|
506 |
|
---|
507 | /* Clip the rectangle. */
|
---|
508 | rect.left = RT_CLAMP(rect.left, 0, (LONG)pDev->mode.ulWidth);
|
---|
509 | rect.top = RT_CLAMP(rect.top, 0, (LONG)pDev->mode.ulHeight);
|
---|
510 | rect.right = RT_CLAMP(rect.right, 0, (LONG)pDev->mode.ulWidth);
|
---|
511 | rect.bottom = RT_CLAMP(rect.bottom, 0, (LONG)pDev->mode.ulHeight);
|
---|
512 |
|
---|
513 | /* If the rectangle is empty, still report it. */
|
---|
514 | if (rect.right < rect.left)
|
---|
515 | {
|
---|
516 | rect.right = rect.left;
|
---|
517 | }
|
---|
518 | if (rect.bottom < rect.top)
|
---|
519 | {
|
---|
520 | rect.bottom = rect.top;
|
---|
521 | }
|
---|
522 |
|
---|
523 | hdr.x = (int16_t)(rect.left + pDev->orgDev.x);
|
---|
524 | hdr.y = (int16_t)(rect.top + pDev->orgDev.y);
|
---|
525 | hdr.w = (uint16_t)(rect.right - rect.left);
|
---|
526 | hdr.h = (uint16_t)(rect.bottom - rect.top);
|
---|
527 |
|
---|
528 | VBoxVBVAWrite(&pDev->vbvaCtx, &pDev->hgsmi.ctx, &hdr, sizeof(hdr));
|
---|
529 | }
|
---|
530 | }
|
---|
531 |
|
---|
532 | static void vbvaReportDirtyPath(PVBOXDISPDEV pDev, PATHOBJ *ppo)
|
---|
533 | {
|
---|
534 | RECTFX rcfxBounds;
|
---|
535 | RECTL rclBounds;
|
---|
536 |
|
---|
537 | PATHOBJ_vGetBounds(ppo, &rcfxBounds);
|
---|
538 |
|
---|
539 | rclBounds.left = FXTOLFLOOR(rcfxBounds.xLeft);
|
---|
540 | rclBounds.right = FXTOLCEILING(rcfxBounds.xRight);
|
---|
541 | rclBounds.top = FXTOLFLOOR(rcfxBounds.yTop);
|
---|
542 | rclBounds.bottom = FXTOLCEILING(rcfxBounds.yBottom);
|
---|
543 |
|
---|
544 | vbvaReportDirtyRect(pDev, &rclBounds);
|
---|
545 | }
|
---|
546 |
|
---|
547 | static void vbvaReportDirtyClip(PVBOXDISPDEV pDev, CLIPOBJ *pco, RECTL *prcl)
|
---|
548 | {
|
---|
549 | if (prcl)
|
---|
550 | {
|
---|
551 | vbvaReportDirtyRect(pDev, prcl);
|
---|
552 | }
|
---|
553 | else if (pco)
|
---|
554 | {
|
---|
555 | vbvaReportDirtyRect(pDev, &pco->rclBounds);
|
---|
556 | }
|
---|
557 | }
|
---|
558 |
|
---|
559 | /*
|
---|
560 | * VBVA driver functions.
|
---|
561 | */
|
---|
562 |
|
---|
563 | void vbvaDrvLineTo(SURFOBJ *pso, CLIPOBJ *pco, BRUSHOBJ *pbo,
|
---|
564 | LONG x1, LONG y1, LONG x2, LONG y2, RECTL *prclBounds, MIX mix)
|
---|
565 | {
|
---|
566 | PVBOXDISPDEV pDev = (PVBOXDISPDEV)pso->dhpdev;
|
---|
567 | vbvaReportDirtyClip(pDev, pco, prclBounds);
|
---|
568 | }
|
---|
569 |
|
---|
570 | void vbvaDrvStrokePath(SURFOBJ *pso, PATHOBJ *ppo, CLIPOBJ *pco, XFORMOBJ *pxo,
|
---|
571 | BRUSHOBJ *pbo, POINTL *pptlBrushOrg, LINEATTRS *plineattrs, MIX mix)
|
---|
572 | {
|
---|
573 | PVBOXDISPDEV pDev = (PVBOXDISPDEV)pso->dhpdev;
|
---|
574 | vbvaReportDirtyPath(pDev, ppo);
|
---|
575 | }
|
---|
576 |
|
---|
577 | void vbvaDrvFillPath(SURFOBJ *pso, PATHOBJ *ppo, CLIPOBJ *pco, BRUSHOBJ *pbo, POINTL *pptlBrushOrg,
|
---|
578 | MIX mix, FLONG flOptions)
|
---|
579 | {
|
---|
580 | PVBOXDISPDEV pDev = (PVBOXDISPDEV)pso->dhpdev;
|
---|
581 | vbvaReportDirtyPath(pDev, ppo);
|
---|
582 | }
|
---|
583 |
|
---|
584 | void vbvaDrvPaint(SURFOBJ *pso, CLIPOBJ *pco, BRUSHOBJ *pbo, POINTL *pptlBrushOrg, MIX mix)
|
---|
585 | {
|
---|
586 | PVBOXDISPDEV pDev = (PVBOXDISPDEV)pso->dhpdev;
|
---|
587 | vbvaReportDirtyClip(pDev, pco, NULL);
|
---|
588 | }
|
---|
589 |
|
---|
590 | void vbvaDrvTextOut(SURFOBJ *pso, STROBJ *pstro, FONTOBJ *pfo, CLIPOBJ *pco,
|
---|
591 | RECTL *prclExtra, RECTL *prclOpaque, BRUSHOBJ *pboFore,
|
---|
592 | BRUSHOBJ *pboOpaque, POINTL *pptlOrg, MIX mix)
|
---|
593 | {
|
---|
594 | PVBOXDISPDEV pDev = (PVBOXDISPDEV)pso->dhpdev;
|
---|
595 | vbvaReportDirtyClip(pDev, pco, prclOpaque? prclOpaque: &pstro->rclBkGround);
|
---|
596 | }
|
---|
597 |
|
---|
598 | void vbvaDrvSaveScreenBits(SURFOBJ *pso, ULONG iMode, ULONG_PTR ident, RECTL *prcl)
|
---|
599 | {
|
---|
600 | PVBOXDISPDEV pDev = (PVBOXDISPDEV)pso->dhpdev;
|
---|
601 |
|
---|
602 | Assert(iMode == SS_RESTORE || iMode == SS_SAVE);
|
---|
603 | vbvaReportDirtyRect(pDev, prcl);
|
---|
604 | }
|
---|
605 |
|
---|
606 | void vbvaDrvBitBlt(SURFOBJ *psoTrg, SURFOBJ *psoSrc, SURFOBJ *psoMask, CLIPOBJ *pco, XLATEOBJ *pxlo,
|
---|
607 | RECTL *prclTrg, POINTL *pptlSrc, POINTL *pptlMask, BRUSHOBJ *pbo, POINTL *pptlBrush,
|
---|
608 | ROP4 rop4)
|
---|
609 | {
|
---|
610 | PVBOXDISPDEV pDev = (PVBOXDISPDEV)psoTrg->dhpdev;
|
---|
611 | vbvaReportDirtyClip(pDev, pco, prclTrg);
|
---|
612 | }
|
---|
613 |
|
---|
614 | void vbvaDrvStretchBlt(SURFOBJ *psoDest, SURFOBJ *psoSrc, SURFOBJ *psoMask, CLIPOBJ *pco, XLATEOBJ *pxlo,
|
---|
615 | COLORADJUSTMENT *pca, POINTL *pptlHTOrg, RECTL *prclDest, RECTL *prclSrc,
|
---|
616 | POINTL *pptlMask, ULONG iMode)
|
---|
617 | {
|
---|
618 | PVBOXDISPDEV pDev = (PVBOXDISPDEV)psoDest->dhpdev;
|
---|
619 | vbvaReportDirtyClip(pDev, pco, prclDest);
|
---|
620 | }
|
---|
621 |
|
---|
622 | void vbvaDrvCopyBits(SURFOBJ *psoDest, SURFOBJ *psoSrc, CLIPOBJ *pco, XLATEOBJ *pxlo,
|
---|
623 | RECTL *prclDest, POINTL *pptlSrc)
|
---|
624 | {
|
---|
625 | PVBOXDISPDEV pDev = (PVBOXDISPDEV)psoDest->dhpdev;
|
---|
626 | vbvaReportDirtyClip(pDev, pco, prclDest);
|
---|
627 | }
|
---|