VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/Display/vbva.c@ 33530

Last change on this file since 33530 was 33002, checked in by vboxsync, 14 years ago

VBoxDisp: properly clip reported VBVA rectangles.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 14.3 KB
Line 
1/** @file
2 *
3 * VirtualBox Windows NT/2000/XP guest video driver
4 *
5 * VBVA dirty rectangles calculations.
6 *
7 * Copyright (C) 2006-2007 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#include "driver.h"
19
20#ifdef VBOX_VBVA_ADJUST_RECT
21static ULONG vbvaConvertPixel ( /*from*/ BYTE *pu8PixelFrom, int cbPixelFrom,
22 /*to*/ int cbPixelTo)
23{
24 BYTE r, g, b;
25 ULONG ulConvertedPixel = 0;
26
27 switch (cbPixelFrom)
28 {
29 case 4:
30 {
31 switch (cbPixelTo)
32 {
33 case 3:
34 {
35 memcpy (&ulConvertedPixel, pu8PixelFrom, 3);
36 } break;
37
38 case 2:
39 {
40 ulConvertedPixel = *(ULONG *)pu8PixelFrom;
41
42 r = (BYTE)(ulConvertedPixel >> 16);
43 g = (BYTE)(ulConvertedPixel >> 8);
44 b = (BYTE)(ulConvertedPixel);
45
46 ulConvertedPixel = ((r >> 3) << 11) + ((g >> 2) << 5) + (b >> 3);
47 } break;
48 }
49 } break;
50
51 case 3:
52 {
53 switch (cbPixelTo)
54 {
55 case 2:
56 {
57 memcpy (&ulConvertedPixel, pu8PixelFrom, 3);
58
59 r = (BYTE)(ulConvertedPixel >> 16);
60 g = (BYTE)(ulConvertedPixel >> 8);
61 b = (BYTE)(ulConvertedPixel);
62
63 ulConvertedPixel = ((r >> 3) << 11) + ((g >> 2) << 5) + (b >> 3);
64 } break;
65 }
66 } break;
67 }
68
69 return ulConvertedPixel;
70}
71
72BOOL vbvaFindChangedRect (SURFOBJ *psoDest, SURFOBJ *psoSrc, RECTL *prclDest, POINTL *pptlSrc)
73{
74 int x, y;
75 int fTopNonEqualFound;
76 int yTopmost;
77 int yBottommost;
78 int cbPixelSrc;
79 int cbPixelDest;
80 RECTL rclDest;
81 RECTL rclSrc;
82 BYTE *pu8Src;
83 BYTE *pu8Dest;
84
85 if (!prclDest || !pptlSrc)
86 {
87 return TRUE;
88 }
89
90 DISPDBG((1, "vbvaFindChangedRect: dest %d,%d %dx%d from %d,%d\n",
91 prclDest->left, prclDest->top, prclDest->right - prclDest->left, prclDest->bottom - prclDest->top,
92 pptlSrc->x, pptlSrc->y
93 ));
94
95 switch (psoDest->iBitmapFormat)
96 {
97 case BMF_16BPP: cbPixelDest = 2; break;
98 case BMF_24BPP: cbPixelDest = 3; break;
99 case BMF_32BPP: cbPixelDest = 4; break;
100 default: cbPixelDest = 0;
101 }
102
103 switch (psoSrc->iBitmapFormat)
104 {
105 case BMF_16BPP: cbPixelSrc = 2; break;
106 case BMF_24BPP: cbPixelSrc = 3; break;
107 case BMF_32BPP: cbPixelSrc = 4; break;
108 default: cbPixelSrc = 0;
109 }
110
111 if (cbPixelDest == 0 || cbPixelSrc == 0)
112 {
113 DISPDBG((1, "vbvaFindChangedRect: unsupported pixel format src %d dst %d\n", psoDest->iBitmapFormat, psoSrc->iBitmapFormat));
114 return TRUE;
115 }
116
117 rclDest = *prclDest;
118
119 vrdpAdjustRect (psoDest, &rclDest);
120
121 pptlSrc->x += rclDest.left - prclDest->left;
122 pptlSrc->y += rclDest.top - prclDest->top;
123
124 *prclDest = rclDest;
125
126 if ( rclDest.right == rclDest.left
127 || rclDest.bottom == rclDest.top)
128 {
129 DISPDBG((1, "vbvaFindChangedRect: empty dest rect: %d-%d, %d-%d\n", rclDest.left, rclDest.right, rclDest.top, rclDest.bottom));
130 return FALSE;
131 }
132
133 rclSrc.left = pptlSrc->x;
134 rclSrc.top = pptlSrc->y;
135 rclSrc.right = pptlSrc->x + (rclDest.right - rclDest.left);
136 rclSrc.bottom = pptlSrc->y + (rclDest.bottom - rclDest.top);
137 vrdpAdjustRect (psoSrc, &rclSrc);
138
139 if ( rclSrc.right == rclSrc.left
140 || rclSrc.bottom == rclSrc.top)
141 {
142 prclDest->right = prclDest->left;
143 prclDest->bottom = prclDest->top;
144
145 DISPDBG((1, "vbvaFindChangedRect: empty src rect: %d-%d, %d-%d\n", rclSrc.left, rclSrc.right, rclSrc.top, rclSrc.bottom));
146 return FALSE;
147 }
148
149 VBVA_ASSERT(pptlSrc->x == rclSrc.left);
150 VBVA_ASSERT(pptlSrc->y == rclSrc.top);
151
152 /*
153 * Compare the content of the screen surface (psoDest) with the source surface (psoSrc).
154 * Update the prclDest with the rectangle that will be actually changed after
155 * copying the source bits to the screen.
156 */
157 pu8Src = (BYTE *)psoSrc->pvScan0 + psoSrc->lDelta * pptlSrc->y + cbPixelSrc * pptlSrc->x;
158 pu8Dest = (BYTE *)psoDest->pvScan0 + psoDest->lDelta * prclDest->top + cbPixelDest * prclDest->left;
159
160 /* Use the rclDest as the bounding rectangle for the changed area. */
161 rclDest.left = prclDest->right; /* +inf */
162 rclDest.right = prclDest->left; /* -inf */
163 rclDest.top = prclDest->bottom; /* +inf */
164 rclDest.bottom = prclDest->top; /* -inf */
165
166 fTopNonEqualFound = 0;
167 yTopmost = prclDest->top; /* inclusive */
168 yBottommost = prclDest->top - 1; /* inclusive */
169
170 for (y = prclDest->top; y < prclDest->bottom; y++)
171 {
172 int fLeftNonEqualFound = 0;
173
174 /* Init to an empty line. */
175 int xLeftmost = prclDest->left; /* inclusive */
176 int xRightmost = prclDest->left - 1; /* inclusive */
177
178 BYTE *pu8SrcLine = pu8Src;
179 BYTE *pu8DestLine = pu8Dest;
180
181 for (x = prclDest->left; x < prclDest->right; x++)
182 {
183 int fEqualPixels;
184
185 if (cbPixelSrc == cbPixelDest)
186 {
187 fEqualPixels = (memcmp (pu8SrcLine, pu8DestLine, cbPixelDest) == 0);
188 }
189 else
190 {
191 /* Convert larger pixel to the smaller pixel format. */
192 ULONG ulConvertedPixel;
193 if (cbPixelSrc > cbPixelDest)
194 {
195 /* Convert the source pixel to the destination pixel format. */
196 ulConvertedPixel = vbvaConvertPixel ( /*from*/ pu8SrcLine, cbPixelSrc,
197 /*to*/ cbPixelDest);
198 fEqualPixels = (memcmp (&ulConvertedPixel, pu8DestLine, cbPixelDest) == 0);
199 }
200 else
201 {
202 /* Convert the destination pixel to the source pixel format. */
203 ulConvertedPixel = vbvaConvertPixel ( /*from*/ pu8DestLine, cbPixelDest,
204 /*to*/ cbPixelSrc);
205 fEqualPixels = (memcmp (&ulConvertedPixel, pu8SrcLine, cbPixelSrc) == 0);
206 }
207 }
208
209 if (fEqualPixels)
210 {
211 /* Equal pixels. */
212 if (!fLeftNonEqualFound)
213 {
214 xLeftmost = x;
215 }
216 }
217 else
218 {
219 fLeftNonEqualFound = 1;
220 xRightmost = x;
221 }
222
223 pu8SrcLine += cbPixelSrc;
224 pu8DestLine += cbPixelDest;
225 }
226
227 /* min */
228 if (rclDest.left > xLeftmost)
229 {
230 rclDest.left = xLeftmost;
231 }
232
233 /* max */
234 if (rclDest.right < xRightmost)
235 {
236 rclDest.right = xRightmost;
237 }
238
239 if (xLeftmost > xRightmost) /* xRightmost is inclusive, so '>', not '>='. */
240 {
241 /* Empty line. */
242 if (!fTopNonEqualFound)
243 {
244 yTopmost = y;
245 }
246 }
247 else
248 {
249 fTopNonEqualFound = 1;
250 yBottommost = y;
251 }
252
253 pu8Src += psoSrc->lDelta;
254 pu8Dest += psoDest->lDelta;
255 }
256
257 /* min */
258 if (rclDest.top > yTopmost)
259 {
260 rclDest.top = yTopmost;
261 }
262
263 /* max */
264 if (rclDest.bottom < yBottommost)
265 {
266 rclDest.bottom = yBottommost;
267 }
268
269 /* rclDest was calculated with right-bottom inclusive.
270 * The following checks and the caller require exclusive coords.
271 */
272 rclDest.right++;
273 rclDest.bottom++;
274
275 DISPDBG((1, "vbvaFindChangedRect: new dest %d,%d %dx%d from %d,%d\n",
276 rclDest.left, rclDest.top, rclDest.right - rclDest.left, rclDest.bottom - rclDest.top,
277 pptlSrc->x, pptlSrc->y
278 ));
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 DISPDBG((1, "vbvaFindChangedRect: empty\n"));
286 prclDest->right = prclDest->left;
287 prclDest->bottom = prclDest->top;
288 return FALSE;
289 }
290
291 DISPDBG((1, "vbvaFindChangedRect: not empty\n"));
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
302void vboxReportDirtyRect (PPDEV ppdev, RECTL *pRectOrig)
303{
304 if (ppdev)
305 {
306 VBVACMDHDR hdr;
307 RECTL rect;
308
309 /* Ensure correct order. */
310 if (pRectOrig->left <= pRectOrig->right)
311 {
312 rect.left = pRectOrig->left;
313 rect.right = pRectOrig->right;
314 }
315 else
316 {
317 rect.left = pRectOrig->right;
318 rect.right = pRectOrig->left;
319 }
320
321 if (pRectOrig->top <= pRectOrig->bottom)
322 {
323 rect.top = pRectOrig->top;
324 rect.bottom = pRectOrig->bottom;
325 }
326 else
327 {
328 rect.top = pRectOrig->bottom;
329 rect.bottom = pRectOrig->top;
330 }
331
332 /* Clip the rectangle. */
333 rect.left = RT_CLAMP(rect.left, 0, (LONG)ppdev->cxScreen);
334 rect.top = RT_CLAMP(rect.top, 0, (LONG)ppdev->cyScreen);
335 rect.right = RT_CLAMP(rect.right, 0, (LONG)ppdev->cxScreen);
336 rect.bottom = RT_CLAMP(rect.bottom, 0, (LONG)ppdev->cyScreen);
337
338 /* If the rectangle is empty, still report it. */
339 if (rect.right < rect.left)
340 {
341 rect.right = rect.left;
342 }
343 if (rect.bottom < rect.top)
344 {
345 rect.bottom = rect.top;
346 }
347
348 hdr.x = (int16_t)(rect.left + ppdev->ptlDevOrg.x);
349 hdr.y = (int16_t)(rect.top + ppdev->ptlDevOrg.y);
350 hdr.w = (uint16_t)(rect.right - rect.left);
351 hdr.h = (uint16_t)(rect.bottom - rect.top);
352
353 vboxWrite (ppdev, &hdr, sizeof(hdr));
354 }
355
356 return;
357}
358
359void vbvaReportDirtyRect (PPDEV ppdev, RECTL *prcl)
360{
361 if (prcl)
362 {
363 DISPDBG((1, "DISP VBVA dirty rect: left %d, top: %d, width: %d, height: %d\n",
364 prcl->left, prcl->top, prcl->right - prcl->left, prcl->bottom - prcl->top));
365
366 vboxReportDirtyRect(ppdev, prcl);
367 }
368}
369
370void vbvaReportDirtyPath (PPDEV ppdev, PATHOBJ *ppo)
371{
372 RECTFX rcfxBounds;
373 RECTL rclBounds;
374
375 PATHOBJ_vGetBounds(ppo, &rcfxBounds);
376
377 rclBounds.left = FXTOLFLOOR(rcfxBounds.xLeft);
378 rclBounds.right = FXTOLCEILING(rcfxBounds.xRight);
379 rclBounds.top = FXTOLFLOOR(rcfxBounds.yTop);
380 rclBounds.bottom = FXTOLCEILING(rcfxBounds.yBottom);
381
382 vbvaReportDirtyRect (ppdev, &rclBounds);
383}
384
385__inline void vbvaReportDirtyClip (PPDEV ppdev, CLIPOBJ *pco, RECTL *prcl)
386{
387 if (prcl)
388 {
389 vbvaReportDirtyRect (ppdev, prcl);
390 }
391 else if (pco)
392 {
393 vbvaReportDirtyRect (ppdev, &pco->rclBounds);
394 }
395}
396
397
398void vbvaBitBlt (
399 SURFOBJ *psoTrg,
400 SURFOBJ *psoSrc,
401 SURFOBJ *psoMask,
402 CLIPOBJ *pco,
403 XLATEOBJ *pxlo,
404 RECTL *prclTrg,
405 POINTL *pptlSrc,
406 POINTL *pptlMask,
407 BRUSHOBJ *pbo,
408 POINTL *pptlBrush,
409 ROP4 rop4)
410{
411 PPDEV ppdev = (PPDEV)psoTrg->dhpdev;
412
413 vbvaReportDirtyClip (ppdev, pco, prclTrg);
414}
415
416void vbvaTextOut(
417 SURFOBJ *pso,
418 STROBJ *pstro,
419 FONTOBJ *pfo,
420 CLIPOBJ *pco,
421 RECTL *prclExtra, // Obsolete, always NULL
422 RECTL *prclOpaque,
423 BRUSHOBJ *pboFore,
424 BRUSHOBJ *pboOpaque,
425 POINTL *pptlOrg,
426 MIX mix
427 )
428{
429 PPDEV ppdev = (PPDEV)pso->dhpdev;
430
431 vbvaReportDirtyClip (ppdev, pco, prclOpaque? prclOpaque: &pstro->rclBkGround);
432}
433
434void vbvaLineTo(
435 SURFOBJ *pso,
436 CLIPOBJ *pco,
437 BRUSHOBJ *pbo,
438 LONG x1,
439 LONG y1,
440 LONG x2,
441 LONG y2,
442 RECTL *prclBounds,
443 MIX mix
444 )
445{
446 PPDEV ppdev = (PPDEV)pso->dhpdev;
447
448 vbvaReportDirtyClip (ppdev, pco, prclBounds);
449}
450
451void vbvaStretchBlt(
452 SURFOBJ *psoDest,
453 SURFOBJ *psoSrc,
454 SURFOBJ *psoMask,
455 CLIPOBJ *pco,
456 XLATEOBJ *pxlo,
457 COLORADJUSTMENT *pca,
458 POINTL *pptlHTOrg,
459 RECTL *prclDest,
460 RECTL *prclSrc,
461 POINTL *pptlMask,
462 ULONG iMode
463 )
464{
465 PPDEV ppdev = (PPDEV)psoDest->dhpdev;
466
467 vbvaReportDirtyClip (ppdev, pco, prclDest);
468}
469
470void vbvaCopyBits(
471 SURFOBJ *psoDest,
472 SURFOBJ *psoSrc,
473 CLIPOBJ *pco,
474 XLATEOBJ *pxlo,
475 RECTL *prclDest,
476 POINTL *pptlSrc
477 )
478{
479 PPDEV ppdev = (PPDEV)psoDest->dhpdev;
480
481 vbvaReportDirtyClip (ppdev, pco, prclDest);
482}
483
484void vbvaPaint(
485 SURFOBJ *pso,
486 CLIPOBJ *pco,
487 BRUSHOBJ *pbo,
488 POINTL *pptlBrushOrg,
489 MIX mix
490 )
491{
492 PPDEV ppdev = (PPDEV)pso->dhpdev;
493
494 vbvaReportDirtyClip (ppdev, pco, NULL);
495}
496
497void vbvaFillPath(
498 SURFOBJ *pso,
499 PATHOBJ *ppo,
500 CLIPOBJ *pco,
501 BRUSHOBJ *pbo,
502 POINTL *pptlBrushOrg,
503 MIX mix,
504 FLONG flOptions
505 )
506{
507 PPDEV ppdev = (PPDEV)pso->dhpdev;
508
509 vbvaReportDirtyPath (ppdev, ppo);
510}
511
512void vbvaStrokePath(
513 SURFOBJ *pso,
514 PATHOBJ *ppo,
515 CLIPOBJ *pco,
516 XFORMOBJ *pxo,
517 BRUSHOBJ *pbo,
518 POINTL *pptlBrushOrg,
519 LINEATTRS *plineattrs,
520 MIX mix
521 )
522{
523 PPDEV ppdev = (PPDEV)pso->dhpdev;
524
525 vbvaReportDirtyPath (ppdev, ppo);
526}
527
528void vbvaStrokeAndFillPath(
529 SURFOBJ *pso,
530 PATHOBJ *ppo,
531 CLIPOBJ *pco,
532 XFORMOBJ *pxo,
533 BRUSHOBJ *pboStroke,
534 LINEATTRS *plineattrs,
535 BRUSHOBJ *pboFill,
536 POINTL *pptlBrushOrg,
537 MIX mixFill,
538 FLONG flOptions
539 )
540{
541 PPDEV ppdev = (PPDEV)pso->dhpdev;
542
543 vbvaReportDirtyPath (ppdev, ppo);
544}
545
546void vbvaSaveScreenBits(
547 SURFOBJ *pso,
548 ULONG iMode,
549 ULONG_PTR ident,
550 RECTL *prcl
551 )
552{
553 PPDEV ppdev = (PPDEV)pso->dhpdev;
554
555 VBVA_ASSERT(iMode == SS_RESTORE || iMode == SS_SAVE);
556
557 vbvaReportDirtyRect (ppdev, prcl);
558}
559
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette