void Win8DeskDuplicationThread::processDirtyRects(size_t dirtyCount, WinD3D11Texture2D *acquiredDesktopImage) { _ASSERT(dirtyCount <= m_dirtyRects.size()); Region changedRegion; Rect rect; Dimension stageDim(&m_targetRect); Rect stageRect = stageDim.getRect(); for (size_t iRect = 0; iRect < dirtyCount; iRect++) { rect.fromWindowsRect(&m_dirtyRects[iRect]); if (!stageRect.isFullyContainRect(&rect)) { rect = rect.intersection(&stageRect); /* Disabled the followed throwing because it realy may happen and better is to see any picture // instead of a black screen. StringStorage errMess; errMess.format(_T("During processDirtyRects has been got a rect (%d, %d, %dx%d) which outside") _T(" from the stage rect (%d, %d, %dx%d)"), rect.left, rect.top, rect.getWidth(), rect.getHeight(), stageRect.left, stageRect.top, stageRect.getWidth(), stageRect.getHeight()); throw Exception(errMess.getString()); */ } m_device.copySubresourceRegion(m_stageTexture2D.getTexture(), rect.left, rect.top, acquiredDesktopImage->getTexture(), &rect, 0, 1); WinDxgiSurface surface(m_stageTexture2D.getTexture()); WinAutoMapDxgiSurface autoMapSurface(&surface, DXGI_MAP_READ); Rect dstRect(rect); // Translate the rect to the frame buffer coordinates. dstRect.move(m_targetRect.left, m_targetRect.top); m_log->debug(_T("Destination dirty rect = %d, %d, %dx%d"), dstRect.left, dstRect.top, dstRect.getWidth(), dstRect.getHeight()); stageDim.width = static_cast<int> (autoMapSurface.getStride() / 4); m_auxiliaryFrameBuffer.setPropertiesWithoutResize(&stageDim, &m_targetFb->getPixelFormat()); m_auxiliaryFrameBuffer.setBuffer(autoMapSurface.getBuffer()); m_targetFb->copyFrom(&dstRect, &m_auxiliaryFrameBuffer, rect.left, rect.top); m_auxiliaryFrameBuffer.setBuffer(0); changedRegion.addRect(&dstRect); } m_duplListener->onFrameBufferUpdate(&changedRegion); }
void ConsolePoller::execute() { Log::info(_T("console poller thread id = %d"), getThreadId()); Rect scanRect; Region region; while (!isTerminating()) { Rect conRect = getConsoleRect(); if (!conRect.isEmpty()) { int pollHeight = m_pollingRect.getHeight(); int pollWidth = m_pollingRect.getWidth(); { AutoLock al(m_frameBufferMutex); Rect offsetFb = m_screenGrabber->getScreenRect(); conRect.move(-offsetFb.left, -offsetFb.top); FrameBuffer *screenFrameBuffer = m_screenGrabber->getScreenBuffer(); if (screenFrameBuffer->isEqualTo(m_backupFrameBuffer)) { m_screenGrabber->grab(&conRect); for (int iRow = conRect.top; iRow < conRect.bottom; iRow += pollHeight) { for (int iCol = conRect.left; iCol < conRect.right; iCol += pollWidth) { scanRect.setRect(iCol, iRow, min(iCol + pollWidth, conRect.right), min(iRow + pollHeight, conRect.bottom)); if (!screenFrameBuffer->cmpFrom(&scanRect, m_backupFrameBuffer, scanRect.left, scanRect.top)) { region.addRect(&scanRect); } } } } } if (!region.isEmpty()) { m_updateKeeper->addChangedRegion(®ion); doUpdate(); } } unsigned int pollInterval = 200; m_intervalWaiter.waitForEvent(pollInterval); } }
void RfbClient::onMouseEvent(UINT16 x, UINT16 y, UINT8 buttonMask) { PixelFormat pfStub; Dimension fbDim; m_desktop->getFrameBufferProperties(&fbDim, &pfStub); Rect vp; bool shareApp; Region sharedRegion; getViewPortInfo(&fbDim, &vp, &shareApp, &sharedRegion); if (!shareApp) { sharedRegion.clear(); sharedRegion.addRect(&vp); } bool pointInside = sharedRegion.isPointInside(x + vp.left, y + vp.top); if (pointInside) { m_updateSender->blockCursorPosSending(); m_desktop->setMouseEvent(x + vp.left, y + vp.top, buttonMask); } }
void FbUpdateNotifier::execute() { // Don't send any event to adapter, while adapter isn't set. { bool adapterIsNull = true; while (!isTerminating() && adapterIsNull) { // Wait event. m_eventUpdate.waitForEvent(); // Check: now adapter is set? AutoLock al(&m_updateLock); if (m_adapter != 0) { adapterIsNull = false; } } } // Send event to adapter, while tread isn't terminated. while (!isTerminating()) { // If flag is set, then thread going to sleep (wait event). bool noUpdates = true; // Move updates to local variable with blocking notifier mutex "m_updateLock". bool isNewSize; bool isCursorChange; Region update; { AutoLock al(&m_updateLock); isNewSize = m_isNewSize; m_isNewSize = false; isCursorChange = m_isCursorChange; m_isCursorChange = false; update = m_update; m_update.clear(); } // Send event "Change properties of frame buffer" to adapter // with blocking frame buffer mutex "m_fbLock". if (isNewSize) { noUpdates = false; m_logWriter->debug(_T("FbUpdateNotifier (event): new size of frame buffer")); try { AutoLock al(m_fbLock); m_adapter->onFrameBufferPropChange(m_frameBuffer); // FIXME: it's bad code. Must work without one next line, but not it. m_adapter->onFrameBufferUpdate(m_frameBuffer, &m_frameBuffer->getDimension().getRect()); } catch (...) { m_logWriter->error(_T("FbUpdateNotifier (event): error in set new size")); } } // Update position on cursor and send frame buffer update event to adapter // with blocking frame buffer mutex "m_fbLock". if (isCursorChange || !update.isEmpty()) { noUpdates = false; AutoLock al(m_fbLock); Rect cursor = m_cursorPainter.showCursor(); update.addRect(&cursor); update.addRect(&m_oldPosition); vector<Rect> updateList; update.getRectVector(&updateList); m_logWriter->detail(_T("FbUpdateNotifier (event): %u updates"), updateList.size()); try { for (vector<Rect>::iterator i = updateList.begin(); i != updateList.end(); i++) { m_adapter->onFrameBufferUpdate(m_frameBuffer, &*i); } } catch (...) { m_logWriter->error(_T("FbUpdateNotifier (event): error in update")); } m_oldPosition = m_cursorPainter.hideCursor(); } // Pause this thread, if there are no updates (cursor, frame buffer). if (noUpdates) { m_eventUpdate.waitForEvent(); } } }