Ejemplo n.º 1
0
void BaseRenderOSystem::drawSurface(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, TransformStruct &transform) { 

	if (_disableDirtyRects) {
		RenderTicket *ticket = new RenderTicket(owner, surf, srcRect, dstRect, transform);
		ticket->_wantsDraw = true;
		_renderQueue.push_back(ticket);
		drawFromSurface(ticket);
		return;
	}

	// Skip rects that are completely outside the screen:
	if ((dstRect->left < 0 && dstRect->right < 0) || (dstRect->top < 0 && dstRect->bottom < 0)) {
		return;
	}

	if (owner) { // Fade-tickets are owner-less
		RenderTicket compare(owner, nullptr, srcRect, dstRect, transform);
		RenderQueueIterator it = _lastFrameIter;
		++it;
		// Avoid calling end() and operator* every time, when potentially going through
		// LOTS of tickets.
		RenderQueueIterator endIterator = _renderQueue.end();
		RenderTicket *compareTicket = nullptr;
		for (; it != endIterator; ++it) {
			compareTicket = *it;
			if (*(compareTicket) == compare && compareTicket->_isValid) {
				if (_disableDirtyRects) {
					drawFromSurface(compareTicket);
				} else {
					drawFromQueuedTicket(it);
				}
				return;
			}
		}
	}
	RenderTicket *ticket = new RenderTicket(owner, surf, srcRect, dstRect, transform);
	if (!_disableDirtyRects) {
		drawFromTicket(ticket);
	} else {
		ticket->_wantsDraw = true;
		_renderQueue.push_back(ticket);
		drawFromSurface(ticket);
	}
}
Ejemplo n.º 2
0
void BaseRenderOSystem::drawTickets() {
	RenderQueueIterator it = _renderQueue.begin();
	// Clean out the old tickets
	// Note: We draw invalid tickets too, otherwise we wouldn't be honouring
	// the draw request they obviously made BEFORE becoming invalid, either way
	// we have a copy of their data, so their invalidness won't affect us.
	uint32 decrement = 0;
	while (it != _renderQueue.end()) {
		if ((*it)->_wantsDraw == false) {
			RenderTicket *ticket = *it;
			addDirtyRect((*it)->_dstRect);
			it = _renderQueue.erase(it);
			delete ticket;
			decrement++;
		} else {
			(*it)->_drawNum -= decrement;
			++it;
		}
	}
	if (!_dirtyRect || _dirtyRect->width() == 0 || _dirtyRect->height() == 0) {
		it = _renderQueue.begin();
		while (it != _renderQueue.end()) {
			RenderTicket *ticket = *it;
			ticket->_wantsDraw = false;
			++it;
		}
		return;
	}
	// The color-mods are stored in the RenderTickets on add, since we set that state again during
	// draw, we need to keep track of what it was prior to draw.
	uint32 oldColorMod = _colorMod;

	// Apply the clear-color to the dirty rect.
	_renderSurface->fillRect(*_dirtyRect, _clearColor);
	_drawNum = 1;
	for (it = _renderQueue.begin(); it != _renderQueue.end(); ++it) {
		RenderTicket *ticket = *it;
		assert(ticket->_drawNum == _drawNum);
		++_drawNum;
		if (ticket->_dstRect.intersects(*_dirtyRect)) {
			// dstClip is the area we want redrawn.
			Common::Rect dstClip(ticket->_dstRect);
			// reduce it to the dirty rect
			dstClip.clip(*_dirtyRect);
			// we need to keep track of the position to redraw the dirty rect
			Common::Rect pos(dstClip);
			int16 offsetX = ticket->_dstRect.left;
			int16 offsetY = ticket->_dstRect.top;
			// convert from screen-coords to surface-coords.
			dstClip.translate(-offsetX, -offsetY);

			_colorMod = ticket->_transform._rgbaMod; 
			drawFromSurface(ticket, &pos, &dstClip);
			_needsFlip = true;
		}
		// Some tickets want redraw but don't actually clip the dirty area (typically the ones that shouldnt become clear-color)
		ticket->_wantsDraw = false;
	}
	g_system->copyRectToScreen((byte *)_renderSurface->getBasePtr(_dirtyRect->left, _dirtyRect->top), _renderSurface->pitch, _dirtyRect->left, _dirtyRect->top, _dirtyRect->width(), _dirtyRect->height());

	// Revert the colorMod-state.
	_colorMod = oldColorMod;

	it = _renderQueue.begin();
	// Clean out the old tickets
	decrement = 0;
	while (it != _renderQueue.end()) {
		if ((*it)->_isValid == false) {
			RenderTicket *ticket = *it;
			addDirtyRect((*it)->_dstRect);
			it = _renderQueue.erase(it);
			delete ticket;
			decrement++;
		} else {
			(*it)->_drawNum -= decrement;
			++it;
		}
	}

}
Ejemplo n.º 3
0
void BaseRenderOSystem::drawSurface(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, TransformStruct &transform) { 

	if (_tempDisableDirtyRects || _disableDirtyRects) {
		RenderTicket *ticket = new RenderTicket(owner, surf, srcRect, dstRect, transform);
		ticket->_transform._rgbaMod = _colorMod;
		ticket->_wantsDraw = true;
		_renderQueue.push_back(ticket);
		_previousTicket = ticket;
		drawFromSurface(ticket);
		return;
	}

	// Start searching from the beginning for the first and second items (since it's empty the first time around
	// then keep incrementing the start-position, to avoid comparing against already used tickets.
	if (_drawNum == 0 || _drawNum == 1) {
		_lastAddedTicket = _renderQueue.begin();
	}

	// Skip rects that are completely outside the screen:
	if ((dstRect->left < 0 && dstRect->right < 0) || (dstRect->top < 0 && dstRect->bottom < 0)) {
		return;
	}

	if (owner) { // Fade-tickets are owner-less
		RenderTicket compare(owner, nullptr, srcRect, dstRect, transform);
		compare._batchNum = _batchNum;
		if (_spriteBatch) {
			_batchNum++;
		}
		RenderQueueIterator it;
		// Avoid calling end() and operator* every time, when potentially going through
		// LOTS of tickets.
		RenderQueueIterator endIterator = _renderQueue.end();
		RenderTicket *compareTicket = nullptr;
		for (it = _lastAddedTicket; it != endIterator; ++it) {
			compareTicket = *it;
			if (*(compareTicket) == compare && compareTicket->_isValid) {
				compareTicket->_transform._rgbaMod = transform._rgbaMod; 
				if (_disableDirtyRects) {
					drawFromSurface(compareTicket);
				} else {
					drawFromTicket(compareTicket);
					_previousTicket = compareTicket;
				}
				if (_renderQueue.size() > DIRTY_RECT_LIMIT) {
					drawTickets();
					_tempDisableDirtyRects = 3;
				}
				return;
			}
		}
	}
	RenderTicket *ticket = new RenderTicket(owner, surf, srcRect, dstRect, transform);
	if (!_disableDirtyRects) {
		drawFromTicket(ticket);
		_previousTicket = ticket;
	} else {
		ticket->_wantsDraw = true;
		_renderQueue.push_back(ticket);
		_previousTicket = ticket;
		drawFromSurface(ticket);
	}
}
Ejemplo n.º 4
0
void BaseRenderOSystem::drawTickets() {
	RenderQueueIterator it = _renderQueue.begin();
	// Clean out the old tickets
	// Note: We draw invalid tickets too, otherwise we wouldn't be honoring
	// the draw request they obviously made BEFORE becoming invalid, either way
	// we have a copy of their data, so their invalidness won't affect us.
	while (it != _renderQueue.end()) {
		if ((*it)->_wantsDraw == false) {
			RenderTicket *ticket = *it;
			addDirtyRect((*it)->_dstRect);
			it = _renderQueue.erase(it);
			delete ticket;
		} else {
			++it;
		}
	}
	if (!_dirtyRect || _dirtyRect->width() == 0 || _dirtyRect->height() == 0) {
		it = _renderQueue.begin();
		while (it != _renderQueue.end()) {
			RenderTicket *ticket = *it;
			ticket->_wantsDraw = false;
			++it;
		}
		return;
	}

	it = _renderQueue.begin();
	_lastFrameIter = _renderQueue.end();
	// A special case: If the screen has one giant OPAQUE rect to be drawn, then we skip filling
	// the background color. Typical use-case: Fullscreen FMVs.
	// Caveat: The FPS-counter will invalidate this.
	if (it != _lastFrameIter && _renderQueue.front() == _renderQueue.back() && (*it)->_transform._alphaDisable == true) {
		// If our single opaque rect fills the dirty rect, we can skip filling.
		if (*_dirtyRect != (*it)->_dstRect) {
			// Apply the clear-color to the dirty rect.
			_renderSurface->fillRect(*_dirtyRect, _clearColor);
		}
		// Otherwise Do NOT fill.
	} else {
		// Apply the clear-color to the dirty rect.
		_renderSurface->fillRect(*_dirtyRect, _clearColor);
	}
	for (; it != _renderQueue.end(); ++it) {
		RenderTicket *ticket = *it;
		if (ticket->_dstRect.intersects(*_dirtyRect)) {
			// dstClip is the area we want redrawn.
			Common::Rect dstClip(ticket->_dstRect);
			// reduce it to the dirty rect
			dstClip.clip(*_dirtyRect);
			// we need to keep track of the position to redraw the dirty rect
			Common::Rect pos(dstClip);
			int16 offsetX = ticket->_dstRect.left;
			int16 offsetY = ticket->_dstRect.top;
			// convert from screen-coords to surface-coords.
			dstClip.translate(-offsetX, -offsetY);

			drawFromSurface(ticket, &pos, &dstClip);
			_needsFlip = true;
		}
		// Some tickets want redraw but don't actually clip the dirty area (typically the ones that shouldnt become clear-color)
		ticket->_wantsDraw = false;
	}
	g_system->copyRectToScreen((byte *)_renderSurface->getBasePtr(_dirtyRect->left, _dirtyRect->top), _renderSurface->pitch, _dirtyRect->left, _dirtyRect->top, _dirtyRect->width(), _dirtyRect->height());

	it = _renderQueue.begin();
	// Clean out the old tickets
	while (it != _renderQueue.end()) {
		if ((*it)->_isValid == false) {
			RenderTicket *ticket = *it;
			addDirtyRect((*it)->_dstRect);
			it = _renderQueue.erase(it);
			delete ticket;
		} else {
			++it;
		}
	}

}