VirtualBox

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

Last change on this file since 24646 was 17615, checked in by vboxsync, 16 years ago

Windows guest display driver: experimental StrokeAndFillPath support (currently disabled).

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