Changeset 67531 in vbox for trunk/src/VBox/Main
- Timestamp:
- Jun 21, 2017 9:17:51 AM (8 years ago)
- svn:sync-xref-src-repo-rev:
- 116271
- Location:
- trunk/src/VBox/Main
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/include/DisplayImpl.h
r66400 r67531 34 34 #include "DisplaySourceBitmapWrap.h" 35 35 36 #define NEW_RESIZE37 36 38 37 class Console; … … 158 157 159 158 // public methods only for internal purposes 160 #ifndef NEW_RESIZE161 int i_handleDisplayResize(unsigned uScreenId, uint32_t bpp, void *pvVRAM, uint32_t cbLine,162 uint32_t w, uint32_t h, uint16_t flags);163 #else164 159 int i_handleDisplayResize(unsigned uScreenId, uint32_t bpp, void *pvVRAM, 165 160 uint32_t cbLine, uint32_t w, uint32_t h, uint16_t flags, 166 161 int32_t xOrigin, int32_t yOrigin, bool fVGAResize); 167 #endif168 162 void i_handleDisplayUpdate(unsigned uScreenId, int x, int y, int w, int h); 169 163 void i_handleUpdateVMMDevSupportsGraphics(bool fSupportsGraphics); … … 310 304 BitmapFormat_T aBitmapFormat, 311 305 ULONG *pcbOut); 312 #ifdef NEW_RESIZE313 306 int processVBVAResize(PCVBVAINFOVIEW pView, PCVBVAINFOSCREEN pScreen, void *pvVRAM, bool fResetInputMapping); 314 #endif315 307 316 308 #ifdef VBOX_WITH_CRHGSMI -
trunk/src/VBox/Main/src-client/DisplayImpl.cpp
r67474 r67531 889 889 } 890 890 891 #ifndef NEW_RESIZE892 /**893 * Handles display resize event.894 *895 * @param uScreenId Screen ID896 * @param bpp New bits per pixel.897 * @param pvVRAM VRAM pointer.898 * @param cbLine New bytes per line.899 * @param w New display width.900 * @param h New display height.901 * @param flags Flags of the new video mode.902 *903 * @thread EMT904 */905 int Display::i_handleDisplayResize(unsigned uScreenId, uint32_t bpp, void *pvVRAM,906 uint32_t cbLine, uint32_t w, uint32_t h, uint16_t flags)907 #else908 891 /** 909 892 * Handles display resize event. … … 923 906 uint32_t cbLine, uint32_t w, uint32_t h, uint16_t flags, 924 907 int32_t xOrigin, int32_t yOrigin, bool fVGAResize) 925 #endif926 908 { 927 909 LogRel(("Display::handleDisplayResize: uScreenId=%d pvVRAM=%p w=%d h=%d bpp=%d cbLine=0x%X flags=0x%X\n", uScreenId, 928 910 pvVRAM, w, h, bpp, cbLine, flags)); 929 930 #ifndef NEW_RESIZE931 if (uScreenId >= mcMonitors)932 return VINF_SUCCESS;933 934 DISPLAYFBINFO *pFBInfo = &maFramebuffers[uScreenId];935 936 /* Reset the update mode. */937 pFBInfo->updateImage.pSourceBitmap.setNull();938 pFBInfo->updateImage.pu8Address = NULL;939 pFBInfo->updateImage.cbLine = 0;940 941 if (uScreenId == VBOX_VIDEO_PRIMARY_SCREEN)942 {943 pFBInfo->w = w;944 pFBInfo->h = h;945 946 pFBInfo->u16BitsPerPixel = (uint16_t)bpp;947 pFBInfo->pu8FramebufferVRAM = (uint8_t *)pvVRAM;948 pFBInfo->u32LineSize = cbLine;949 pFBInfo->flags = flags;950 }951 952 /* Guest screen image will be invalid during resize, make sure that it is not updated. */953 if (uScreenId == VBOX_VIDEO_PRIMARY_SCREEN)954 {955 if (mpDrv)956 {957 mpDrv->pUpPort->pfnSetRenderVRAM(mpDrv->pUpPort, false);958 959 mpDrv->IConnector.pbData = NULL;960 mpDrv->IConnector.cbScanline = 0;961 mpDrv->IConnector.cBits = 32; /* DevVGA does not work with cBits == 0. */962 mpDrv->IConnector.cx = 0;963 mpDrv->IConnector.cy = 0;964 }965 }966 967 maFramebuffers[uScreenId].pSourceBitmap.setNull();968 969 if (!maFramebuffers[uScreenId].pFramebuffer.isNull())970 {971 HRESULT hr = maFramebuffers[uScreenId].pFramebuffer->NotifyChange(uScreenId, 0, 0, w, h); /** @todo origin */972 LogFunc(("NotifyChange hr %08X\n", hr));973 NOREF(hr);974 }975 976 bool fUpdateImage = RT_BOOL(pFBInfo->u32Caps & FramebufferCapabilities_UpdateImage);977 if (fUpdateImage && !pFBInfo->pFramebuffer.isNull())978 {979 ComPtr<IDisplaySourceBitmap> pSourceBitmap;980 HRESULT hr = QuerySourceBitmap(uScreenId, pSourceBitmap.asOutParam());981 if (SUCCEEDED(hr))982 {983 BYTE *pAddress = NULL;984 ULONG ulWidth = 0;985 ULONG ulHeight = 0;986 ULONG ulBitsPerPixel = 0;987 ULONG ulBytesPerLine = 0;988 BitmapFormat_T bitmapFormat = BitmapFormat_Opaque;989 990 hr = pSourceBitmap->QueryBitmapInfo(&pAddress,991 &ulWidth,992 &ulHeight,993 &ulBitsPerPixel,994 &ulBytesPerLine,995 &bitmapFormat);996 if (SUCCEEDED(hr))997 {998 pFBInfo->updateImage.pSourceBitmap = pSourceBitmap;999 pFBInfo->updateImage.pu8Address = pAddress;1000 pFBInfo->updateImage.cbLine = ulBytesPerLine;1001 }1002 }1003 }1004 1005 /* Inform the VRDP server about the change of display parameters. */1006 LogRelFlowFunc(("Calling VRDP\n"));1007 mParent->i_consoleVRDPServer()->SendResize();1008 1009 /* And re-send the seamless rectangles if necessary. */1010 if (mfSeamlessEnabled)1011 i_handleSetVisibleRegion(mcRectVisibleRegion, mpRectVisibleRegion);1012 1013 #ifdef VBOX_WITH_VIDEOREC1014 videoCaptureScreenChanged(uScreenId);1015 #endif1016 1017 #else /* NEW_RESIZE */1018 911 1019 912 /* Caller must not hold the object lock. */ … … 1157 1050 #endif 1158 1051 1159 #endif /* NEW_RESIZE */1160 1161 1052 LogRelFlowFunc(("[%d]: default format %d\n", uScreenId, pFBInfo->fDefaultFormat)); 1162 1053 … … 1219 1110 return; */ 1220 1111 1221 #ifndef NEW_RESIZE1222 i_checkCoordBounds(&x, &y, &w, &h, maFramebuffers[uScreenId].w,1223 maFramebuffers[uScreenId].h);1224 1225 IFramebuffer *pFramebuffer = maFramebuffers[uScreenId].pFramebuffer;1226 if (pFramebuffer != NULL)1227 {1228 if (w != 0 && h != 0)1229 {1230 bool fUpdateImage = RT_BOOL(maFramebuffers[uScreenId].u32Caps & FramebufferCapabilities_UpdateImage);1231 if (RT_LIKELY(!fUpdateImage))1232 {1233 pFramebuffer->NotifyUpdate(x, y, w, h);1234 }1235 else1236 {1237 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);1238 1239 DISPLAYFBINFO *pFBInfo = &maFramebuffers[uScreenId];1240 1241 if (!pFBInfo->updateImage.pSourceBitmap.isNull())1242 {1243 Assert(pFBInfo->updateImage.pu8Address);1244 1245 size_t cbData = w * h * 4;1246 com::SafeArray<BYTE> image(cbData);1247 1248 uint8_t *pu8Dst = image.raw();1249 const uint8_t *pu8Src = pFBInfo->updateImage.pu8Address + pFBInfo->updateImage.cbLine * y + x * 4;1250 1251 int i;1252 for (i = y; i < y + h; ++i)1253 {1254 memcpy(pu8Dst, pu8Src, w * 4);1255 pu8Dst += w * 4;1256 pu8Src += pFBInfo->updateImage.cbLine;1257 }1258 1259 pFramebuffer->NotifyUpdateImage(x, y, w, h, ComSafeArrayAsInParam(image));1260 }1261 }1262 }1263 }1264 #else /* NEW_RESIZE */1265 1112 DISPLAYFBINFO *pFBInfo = &maFramebuffers[uScreenId]; 1266 1113 AutoReadLock alockr(this COMMA_LOCKVAL_SRC_POS); … … 1365 1212 } 1366 1213 } 1367 #endif /* NEW_RESIZE */1368 1214 1369 1215 #ifndef VBOX_WITH_HGSMI … … 1852 1698 if (!pFBInfo->fDisabled) 1853 1699 { 1854 #ifndef NEW_RESIZE1855 i_handleDisplayResize(uScreenId, 32,1856 pFBInfo->pu8FramebufferVRAM,1857 pFBInfo->u32LineSize,1858 pFBInfo->w,1859 pFBInfo->h,1860 pFBInfo->flags);1861 #else1862 1700 i_handleDisplayResize(uScreenId, 32, 1863 1701 pFBInfo->pu8FramebufferVRAM, … … 1869 1707 pFBInfo->yOrigin, 1870 1708 false); 1871 #endif1872 1709 } 1873 1710 } … … 1943 1780 if (mpDrv) 1944 1781 { 1945 #ifndef NEW_RESIZE1946 /* Setup the new framebuffer. */1947 i_handleDisplayResize(aScreenId, pFBInfo->u16BitsPerPixel,1948 pFBInfo->pu8FramebufferVRAM,1949 pFBInfo->u32LineSize,1950 pFBInfo->w,1951 pFBInfo->h,1952 pFBInfo->flags);1953 #else1954 1782 /* Inform the framebuffer about the actual screen size. */ 1955 1783 HRESULT hr = aFramebuffer->NotifyChange(aScreenId, 0, 0, pFBInfo->w, pFBInfo->h); /** @todo origin */ … … 1959 1787 if (mfSeamlessEnabled) 1960 1788 i_handleSetVisibleRegion(mcRectVisibleRegion, mpRectVisibleRegion); 1961 #endif1962 1789 } 1963 1790 … … 3146 2973 if (pFBInfo->pSourceBitmap.isNull()) 3147 2974 { 3148 #ifndef NEW_RESIZE3149 2975 /* Create a new object. */ 3150 2976 ComObjPtr<DisplaySourceBitmap> obj; … … 3155 2981 if (SUCCEEDED(hr)) 3156 2982 { 3157 bool fDefaultFormat = !obj->i_usesVRAM(); 2983 pFBInfo->pSourceBitmap = obj; 2984 pFBInfo->fDefaultFormat = !obj->i_usesVRAM(); 3158 2985 3159 2986 if (aScreenId == VBOX_VIDEO_PRIMARY_SCREEN) … … 3167 2994 BitmapFormat_T bitmapFormat = BitmapFormat_Opaque; 3168 2995 3169 obj->QueryBitmapInfo(&pAddress,3170 &ulWidth,3171 &ulHeight,3172 &ulBitsPerPixel,3173 &ulBytesPerLine,3174 &bitmapFormat);3175 3176 mpDrv->IConnector.pbData = pAddress;3177 mpDrv->IConnector.cbScanline = ulBytesPerLine;3178 mpDrv->IConnector.cBits = ulBitsPerPixel;3179 mpDrv->IConnector.cx = ulWidth;3180 mpDrv->IConnector.cy = ulHeight;3181 3182 fSetRenderVRAM = fDefaultFormat;3183 }3184 3185 /* Make sure that the bitmap contains the latest image. */3186 fInvalidate = fDefaultFormat;3187 3188 pFBInfo->pSourceBitmap = obj;3189 pFBInfo->fDefaultFormat = fDefaultFormat;3190 }3191 #else /* NEW_RESIZE */3192 /* Create a new object. */3193 ComObjPtr<DisplaySourceBitmap> obj;3194 hr = obj.createObject();3195 if (SUCCEEDED(hr))3196 hr = obj->init(this, aScreenId, pFBInfo);3197 3198 if (SUCCEEDED(hr))3199 {3200 pFBInfo->pSourceBitmap = obj;3201 pFBInfo->fDefaultFormat = !obj->i_usesVRAM();3202 3203 if (aScreenId == VBOX_VIDEO_PRIMARY_SCREEN)3204 {3205 /* Start buffer updates. */3206 BYTE *pAddress = NULL;3207 ULONG ulWidth = 0;3208 ULONG ulHeight = 0;3209 ULONG ulBitsPerPixel = 0;3210 ULONG ulBytesPerLine = 0;3211 BitmapFormat_T bitmapFormat = BitmapFormat_Opaque;3212 3213 2996 pFBInfo->pSourceBitmap->QueryBitmapInfo(&pAddress, 3214 2997 &ulWidth, … … 3230 3013 fInvalidate = pFBInfo->fDefaultFormat; 3231 3014 } 3232 #endif /* NEW_RESIZE */3233 3015 } 3234 3016 … … 3426 3208 } 3427 3209 3428 #ifndef NEW_RESIZE3429 int rc = pThis->i_handleDisplayResize(VBOX_VIDEO_PRIMARY_SCREEN, bpp, pvVRAM, cbLine, cx, cy, VBVA_SCREEN_F_ACTIVE);3430 #else3431 3210 int rc = pThis->i_handleDisplayResize(VBOX_VIDEO_PRIMARY_SCREEN, bpp, pvVRAM, cbLine, cx, cy, 0, 0, 0, true); 3432 #endif3433 3211 3434 3212 /* Restore the flag. */ … … 4212 3990 * The guest can't use VBVA anymore, so only only the VGA device output works. 4213 3991 */ 4214 #ifdef NEW_RESIZE4215 3992 pFBInfo->flags = 0; 4216 #endif4217 3993 if (pFBInfo->fDisabled) 4218 3994 { … … 4430 4206 Display *pThis = pDrv->pDisplay; 4431 4207 4432 #ifndef NEW_RESIZE 4433 DISPLAYFBINFO *pFBInfo = &pThis->maFramebuffers[pScreen->u32ViewIndex]; 4208 return pThis->processVBVAResize(pView, pScreen, pvVRAM, fResetInputMapping); 4209 } 4210 4211 int Display::processVBVAResize(PCVBVAINFOVIEW pView, PCVBVAINFOSCREEN pScreen, void *pvVRAM, bool fResetInputMapping) 4212 { 4213 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 4214 4215 DISPLAYFBINFO *pFBInfo = &maFramebuffers[pScreen->u32ViewIndex]; 4434 4216 4435 4217 if (pScreen->u16Flags & VBVA_SCREEN_F_DISABLED) 4436 4218 { 4437 pThis->i_notifyCroglResize(pView, pScreen, pvVRAM);4438 4439 pFBInfo->fDisabled = true;4440 pFBInfo->flags = pScreen->u16Flags;4441 4442 4219 /* Ask the framebuffer to resize using a default format. The framebuffer will be black. 4443 4220 * So if the frontend does not support GuestMonitorChangedEventType_Disabled event, … … 4445 4222 uint32_t u32Width = pFBInfo->w ? pFBInfo->w : 640; 4446 4223 uint32_t u32Height = pFBInfo->h ? pFBInfo->h : 480; 4447 pThis->i_handleDisplayResize(pScreen->u32ViewIndex, 0, (uint8_t *)NULL, 0, 4448 u32Width, u32Height, pScreen->u16Flags); 4449 4450 fireGuestMonitorChangedEvent(pThis->mParent->i_getEventSource(), 4451 GuestMonitorChangedEventType_Disabled, 4452 pScreen->u32ViewIndex, 4453 0, 0, 0, 0); 4224 int32_t xOrigin = pFBInfo->xOrigin; 4225 int32_t yOrigin = pFBInfo->yOrigin; 4226 4227 alock.release(); 4228 4229 i_notifyCroglResize(pView, pScreen, pvVRAM); 4230 4231 i_handleDisplayResize(pScreen->u32ViewIndex, 0, (uint8_t *)NULL, 0, 4232 u32Width, u32Height, pScreen->u16Flags, xOrigin, yOrigin, false); 4233 4454 4234 return VINF_SUCCESS; 4455 4235 } … … 4477 4257 } 4478 4258 4479 /* If display was disabled or there is no framebuffer, a resize will be required,4480 * because the framebuffer was/will be changed.4481 */4482 bool fResize = pFBInfo->fDisabled || pFBInfo->pFramebuffer.isNull();4483 4484 if (pFBInfo->fVBVAForceResize)4485 {4486 /* VBVA was just enabled. Do the resize. */4487 fResize = true;4488 pFBInfo->fVBVAForceResize = false;4489 }4490 4491 /* If the screen if blanked, then do a resize request to make sure that the framebuffer4492 * switches to the default format.4493 */4494 fResize = fResize || RT_BOOL((pScreen->u16Flags ^ pFBInfo->flags) & VBVA_SCREEN_F_BLANK);4495 4496 /* Check if this is a real resize or a notification about the screen origin.4497 * The guest uses this VBVAResize call for both.4498 */4499 fResize = fResize4500 || pFBInfo->u16BitsPerPixel != pScreen->u16BitsPerPixel4501 || pFBInfo->pu8FramebufferVRAM != (uint8_t *)pvVRAM + pScreen->u32StartOffset4502 || pFBInfo->u32LineSize != pScreen->u32LineSize4503 || pFBInfo->w != pScreen->u32Width4504 || pFBInfo->h != pScreen->u32Height;4505 4506 bool fNewOrigin = pFBInfo->xOrigin != pScreen->i32OriginX4507 || pFBInfo->yOrigin != pScreen->i32OriginY;4508 4509 if (fNewOrigin || fResize)4510 pThis->i_notifyCroglResize(pView, pScreen, pvVRAM);4511 4512 if (pFBInfo->fDisabled)4513 {4514 pFBInfo->fDisabled = false;4515 fireGuestMonitorChangedEvent(pThis->mParent->i_getEventSource(),4516 GuestMonitorChangedEventType_Enabled,4517 pScreen->u32ViewIndex,4518 pScreen->i32OriginX, pScreen->i32OriginY,4519 pScreen->u32Width, pScreen->u32Height);4520 /* Continue to update pFBInfo. */4521 }4522 4523 pFBInfo->u32Offset = pView->u32ViewOffset; /* Not used in HGSMI. */4524 pFBInfo->u32MaxFramebufferSize = pView->u32MaxScreenSize; /* Not used in HGSMI. */4525 pFBInfo->u32InformationSize = 0; /* Not used in HGSMI. */4526 4527 pFBInfo->xOrigin = pScreen->i32OriginX;4528 pFBInfo->yOrigin = pScreen->i32OriginY;4529 4530 pFBInfo->w = pScreen->u32Width;4531 pFBInfo->h = pScreen->u32Height;4532 4533 pFBInfo->u16BitsPerPixel = pScreen->u16BitsPerPixel;4534 pFBInfo->pu8FramebufferVRAM = (uint8_t *)pvVRAM + pScreen->u32StartOffset;4535 pFBInfo->u32LineSize = pScreen->u32LineSize;4536 4537 pFBInfo->flags = pScreen->u16Flags;4538 4539 if (fResetInputMapping)4540 {4541 pThis->xInputMappingOrigin = 0;4542 pThis->yInputMappingOrigin = 0;4543 pThis->cxInputMapping = 0;4544 pThis->cyInputMapping = 0;4545 }4546 4547 if (fNewOrigin)4548 {4549 fireGuestMonitorChangedEvent(pThis->mParent->i_getEventSource(),4550 GuestMonitorChangedEventType_NewOrigin,4551 pScreen->u32ViewIndex,4552 pScreen->i32OriginX, pScreen->i32OriginY,4553 0, 0);4554 }4555 4556 if (!fResize)4557 {4558 /* No parameters of the framebuffer have actually changed. */4559 if (fNewOrigin)4560 {4561 /* VRDP server still need this notification. */4562 LogRelFlowFunc(("Calling VRDP\n"));4563 pThis->mParent->i_consoleVRDPServer()->SendResize();4564 }4565 return VINF_SUCCESS;4566 }4567 4568 /* Do a regular resize. */4569 return pThis->i_handleDisplayResize(pScreen->u32ViewIndex, pScreen->u16BitsPerPixel,4570 (uint8_t *)pvVRAM + pScreen->u32StartOffset,4571 pScreen->u32LineSize, pScreen->u32Width, pScreen->u32Height, pScreen->u16Flags);4572 #else /* NEW_RESIZE */4573 return pThis->processVBVAResize(pView, pScreen, pvVRAM, fResetInputMapping);4574 #endif /* NEW_RESIZE */4575 }4576 4577 #ifdef NEW_RESIZE4578 int Display::processVBVAResize(PCVBVAINFOVIEW pView, PCVBVAINFOSCREEN pScreen, void *pvVRAM, bool fResetInputMapping)4579 {4580 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);4581 4582 DISPLAYFBINFO *pFBInfo = &maFramebuffers[pScreen->u32ViewIndex];4583 4584 if (pScreen->u16Flags & VBVA_SCREEN_F_DISABLED)4585 {4586 /* Ask the framebuffer to resize using a default format. The framebuffer will be black.4587 * So if the frontend does not support GuestMonitorChangedEventType_Disabled event,4588 * the VM window will be black. */4589 uint32_t u32Width = pFBInfo->w ? pFBInfo->w : 640;4590 uint32_t u32Height = pFBInfo->h ? pFBInfo->h : 480;4591 int32_t xOrigin = pFBInfo->xOrigin;4592 int32_t yOrigin = pFBInfo->yOrigin;4593 4594 alock.release();4595 4596 i_notifyCroglResize(pView, pScreen, pvVRAM);4597 4598 i_handleDisplayResize(pScreen->u32ViewIndex, 0, (uint8_t *)NULL, 0,4599 u32Width, u32Height, pScreen->u16Flags, xOrigin, yOrigin, false);4600 4601 return VINF_SUCCESS;4602 }4603 4604 VBVAINFOSCREEN screenInfo;4605 RT_ZERO(screenInfo);4606 4607 if (pScreen->u16Flags & VBVA_SCREEN_F_BLANK2)4608 {4609 /* Init a local VBVAINFOSCREEN structure, which will be used instead of4610 * the original pScreen. Set VBVA_SCREEN_F_BLANK, which will force4611 * the code below to choose the "blanking" branches.4612 */4613 screenInfo.u32ViewIndex = pScreen->u32ViewIndex;4614 screenInfo.i32OriginX = pFBInfo->xOrigin;4615 screenInfo.i32OriginY = pFBInfo->yOrigin;4616 screenInfo.u32StartOffset = 0; /* Irrelevant */4617 screenInfo.u32LineSize = pFBInfo->u32LineSize;4618 screenInfo.u32Width = pFBInfo->w;4619 screenInfo.u32Height = pFBInfo->h;4620 screenInfo.u16BitsPerPixel = pFBInfo->u16BitsPerPixel;4621 screenInfo.u16Flags = pScreen->u16Flags | VBVA_SCREEN_F_BLANK;4622 4623 pScreen = &screenInfo;4624 }4625 4626 4259 if (fResetInputMapping) 4627 4260 { … … 4642 4275 pScreen->i32OriginX, pScreen->i32OriginY, false); 4643 4276 } 4644 #endif /* NEW_RESIZE */4645 4277 4646 4278 DECLCALLBACK(int) Display::i_displayVBVAMousePointerShape(PPDMIDISPLAYCONNECTOR pInterface, bool fVisible, bool fAlpha, -
trunk/src/VBox/Main/src-client/DisplayImplLegacy.cpp
r66396 r67531 957 957 } 958 958 959 #ifndef NEW_RESIZE960 i_handleDisplayResize(uScreenId, pScreen->bitsPerPixel,961 (uint8_t *)pvVRAM + pFBInfo->u32Offset,962 pScreen->u32LineSize,963 pScreen->u16Width, pScreen->u16Height,964 VBVA_SCREEN_F_ACTIVE);965 #else966 959 i_handleDisplayResize(uScreenId, pScreen->bitsPerPixel, 967 960 (uint8_t *)pvVRAM + pFBInfo->u32Offset, … … 970 963 VBVA_SCREEN_F_ACTIVE, 971 964 pScreen->xOrigin, pScreen->yOrigin, false); 972 #endif973 965 } 974 966 }
Note:
See TracChangeset
for help on using the changeset viewer.