コード例 #1
0
ファイル: viewport_drawing.cpp プロジェクト: ajaskier/gerbil
void Viewport::continueDrawing(int buffer)
{
	renderbuffer &b = buffers[buffer];
	if (b.dirty)
		return;

	SharedDataLock ctxlock(ctx->mutex);
	SharedDataLock setslock(sets->mutex);

	if ((*sets)->empty() || (*ctx)->wait)
		return;

	setslock.unlock();
	ctxlock.unlock();

	QPainter painter(b.fbo);

	if (drawingState == HIGH_QUALITY)
		painter.setRenderHint(QPainter::Antialiasing);

	painter.save();
	painter.setWorldTransform(modelview);
	drawBins(painter, b.renderTimer, b.renderedLines, b.renderStep,
	         (buffer == 1));
	painter.restore();

	update();
}
コード例 #2
0
ファイル: viewport.cpp プロジェクト: ribalda/gerbil
void Viewport::prepareLines()
{
	if (!ctx) {
		GGDBGM("no ctx" << endl);
		return;
	}
	if (!sets) {
		GGDBGM("no sets" << endl);
		return;
	}

	// lock context and sets
	SharedDataLock ctxlock(ctx->mutex);
	SharedDataLock setslock(sets->mutex);
	(*ctx)->wait.fetch_and_store(0); // set to zero: our data will be usable
	if ((*ctx)->reset.fetch_and_store(0)) // is true if it was 1 before
		reset();

	// first step (cpu only)
	Compute::preparePolylines(**ctx, **sets, shuffleIdx);

	// second step (cpu -> gpu)
	target->makeCurrent();
	Compute::storeVertices(**ctx, **sets, shuffleIdx, vb,
	                       drawMeans->isChecked(), illuminantAppl);

}
コード例 #3
0
ファイル: viewport_drawing.cpp プロジェクト: ajaskier/gerbil
void Viewport::updateBuffers(RenderMode spectrum, RenderMode highlight)
{
	if (!buffers[0].fbo || !buffers[1].fbo)
		return;

	{
		SharedDataLock ctxlock(ctx->mutex);
		SharedDataLock setslock(sets->mutex);
		if ((*sets)->empty() || (*ctx)->wait)
			return;
	}

	// even if we had HQ last time, this time it will be dirty!
	if (drawingState == HIGH_QUALITY_QUICK)
		drawingState = QUICK;

	// array for convenience
	RenderMode mode[2] = { spectrum, highlight };
	QRect rect(0, 0, width, height);

	for (int i = 0; i < 2; ++i) {
		renderbuffer &b = buffers[i];

		if (mode[i] == RM_SKIP)
			continue;

		b.renderTimer.stop();
		b.renderedLines = 0;

		if (!(b.fbo->isValid() && b.blit->isValid())) {
			GerbilApplication::internalError(
			            "Framebuffer not valid in viewport updateBuffers().",
			            false);
			return;
		}

		// does not make much sense here, but seems to help with no/partial update problems
		target->makeCurrent();
		QPainter painter(b.fbo);

		painter.setCompositionMode(QPainter::CompositionMode_Source);
		painter.fillRect(rect, Qt::transparent);
		painter.setCompositionMode(QPainter::CompositionMode_SourceOver);

		if (drawingState == HIGH_QUALITY)
			painter.setRenderHint(QPainter::Antialiasing);

		painter.save();
		painter.setWorldTransform(modelview);
		drawBins(painter, b.renderTimer, b.renderedLines,
		         (mode[i] == RM_FULL) ? std::numeric_limits<int>::max()
		                              : b.renderStep, (i == 1));
		painter.restore();
		b.dirty = false;
	}

	update();
}
コード例 #4
0
ファイル: viewport.cpp プロジェクト: ribalda/gerbil
void Viewport::rebuild()
{
	// guess: we want the lock to carry over both methods..
	SharedDataLock ctxlock(ctx->mutex);
	SharedDataLock setslock(sets->mutex);

	prepareLines(); // will also call reset() if indicated by ctx
	updateBuffers();
}
コード例 #5
0
ファイル: viewport.cpp プロジェクト: ribalda/gerbil
void Viewport::setLimiters(int label)
{
	if (label < 1) {	// not label
		SharedDataLock ctxlock(ctx->mutex);
		limiters.assign((*ctx)->dimensionality,
		                std::make_pair(0, (*ctx)->nbins-1));
		if (label == -1) {	// use hover data
			int b = selection;
			int h = hover;
			limiters[b] = std::make_pair(h, h);
		}
	} else {            // label holds data
		SharedDataLock setslock(sets->mutex);
		if ((int)(*sets)->size() > label && (**sets)[label].totalweight > 0) {
			// use range from this label
			const std::vector<std::pair<int, int> > &b =
			        (**sets)[label].boundary;
			limiters.assign(b.begin(), b.end());
		} else {
			setLimiters(0);
		}
	}
}
コード例 #6
0
ファイル: viewport_drawing.cpp プロジェクト: ajaskier/gerbil
void Viewport::drawBins(QPainter &painter, QTimer &renderTimer,
                        unsigned int &renderedLines, unsigned int renderStep,
                        bool highlight)
{
	SharedDataLock ctxlock(ctx->mutex);
	// TODO: this also locks shuffleIdx implicitely, better do it explicitely?
	SharedDataLock setslock(sets->mutex);

	// Stopwatch watch("drawBins");

	/* initialize painting in GL, vertex buffer */
	target->makeCurrent();
	painter.beginNativePainting();
	glEnable(GL_BLEND);
	glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
	bool success = vb.bind();
	if (!success) {
		GerbilApplication::internalError(
		            "Vertex buffer could not be bound in viewport drawBins().",
		            false);
		painter.endNativePainting();
		return;
	}
	glEnableClientState(GL_VERTEX_ARRAY);
	glVertexPointer(2, GL_FLOAT, 0, 0);
	size_t iD = renderedLines * (*ctx)->dimensionality;

	/* determine drawing range. could be expanded to only draw spec. labels */
	// make sure that viewport draws "unlabeled" data in ignore-label case
	int start = ((showUnlabeled || (*ctx)->ignoreLabels == 1) ? 0 : 1);
	int end = (showLabeled ? (int)(*sets)->size() : 1);

	size_t total = shuffleIdx.size();
	size_t first = renderedLines;
	size_t last = std::min((size_t)(renderedLines + renderStep), total);

	// loop over all elements in vertex index, update element and vector indices
	for (size_t i = first; i < last;
	     ++i, iD += (*ctx)->dimensionality) {
		std::pair<int, BinSet::HashKey> &idx = shuffleIdx[i];

		// filter out according to label
		bool filter = ((idx.first < start || idx.first >= end));
		// do not filter out highlighted label(s)
		if (!(*ctx)->ignoreLabels) {
			filter = filter && !highlightLabels.contains(idx.first);
		}
		if (filter) {
			// increase loop count to achieve renderStep
			if (last < total)
				++last;
			continue;
		}

		BinSet::HashKey &K = idx.second;

		// highlight mode (foreground buffer)
		if (highlight) {

			//test if we are part of the highlight
			bool highlighted = false;
			if (limiterMode) {
				highlighted = true;
				for (size_t i = 0; i < (*ctx)->dimensionality; ++i) {
					unsigned char k = K[i];
					if (k < limiters[i].first || k > limiters[i].second)
						highlighted = false;
				}
			} else if ((unsigned char)K[selection] == hover) {
				highlighted = true;
			}

			// filter out
			if (!highlighted) {
				// increase loop count to achieve renderStep
				if (last < total)
					++last;
				continue;
			}
		}

		// grab binset and bin according to key
		BinSet &s = (**sets)[idx.first];
		std::pair<BinSet::HashMap::const_iterator, BinSet::HashMap::const_iterator> binitp =
		        s.bins.equal_range(K);
		if (s.bins.end() == binitp.first) {
			// FIXME this is an error and should be treated accordingly
			GGDBGM("no bin"<< endl);
			return;
		}
		Bin const &b = s.bins.equal_range(K).first->second;

		// set color
		QColor color = determineColor((drawRGB->isChecked() ? b.rgb : s.label),
		                              b.weight, s.totalweight,
		                              highlight,
		                              highlightLabels.contains(idx.first));
		target->qglColor(color);

		// draw polyline
		glDrawArrays(GL_LINE_STRIP, (GLsizei)iD, (GLint)(*ctx)->dimensionality);
	}
	vb.release();
	painter.endNativePainting();

	// setup succeeding incremental drawing
	renderedLines += (unsigned int)(last - first);
	if (renderedLines < total) {
		if (renderedLines <= renderStep) {
			renderTimer.start(150);
		} else {
			renderTimer.start(0);
		}
	}
}
コード例 #7
0
ファイル: viewport_drawing.cpp プロジェクト: ajaskier/gerbil
bool Viewport::drawScene(QPainter *painter, bool withDynamics)
{
	bool disabled = false;
	{
		/* TODO: disabled member state instead? */
		SharedDataLock ctxlock(ctx->mutex);
		SharedDataLock setslock(sets->mutex);
		if ((*sets)->empty() || (*ctx)->wait)
			disabled = true;
	}

	target->makeCurrent();

	/* draw background */
	QRect rect(0, 0, width, height);
	/* Hack: without dynamics, we typically also want a boring background */
	if (withDynamics)
		painter->fillRect(rect, QColor(15, 7, 15));
	else
		painter->fillRect(rect, Qt::black);
	painter->setRenderHint(QPainter::Antialiasing);

	if (disabled) {
		drawWaitMessage(painter);
		return false;
	}

	painter->save();
	painter->setWorldTransform(modelview);
	drawAxesBg(painter);
	painter->restore();

	/* determine if we draw the highlight part */
	// only draw when active and dynamic content is desired
	bool drawHighlight = active && withDynamics;
	// only draw if not implicitely empty
	drawHighlight = drawHighlight && (hover > -1 || limiterMode);
	// do not draw when in single pixel overlay mode
	drawHighlight = drawHighlight && (!overlayMode);
	// do not draw when in single label mode
	drawHighlight = drawHighlight && (highlightLabels.empty());

	for (int i = 0; i < (drawHighlight ? 2 : 1); ++i) {

		renderbuffer &b = buffers[i];
		if (b.dirty) {
			drawWaitMessage(painter);
			// nothing to draw yet, don't even bother with other buffer,
			disabled = true;
			break;
		}

		// blit first to get from multisample to regular buffer. then draw that
		QGLFramebufferObject::blitFramebuffer(b.blit, rect, b.fbo, rect);
		target->drawTexture(rect, b.blit->texture());
	}

	// only provide selection for view with dynamic components (selected band)
	if (withDynamics)
		drawLegend(painter, selection);
	else
		drawLegend(painter);

	// foreground axes are a dynamic part
	if (withDynamics) {
		painter->save();
		painter->setWorldTransform(modelview);
		drawAxesFg(painter);
		painter->restore();
	}

	if (overlayMode && withDynamics)
		drawOverlay(painter);

	// return success if nothing was omited
	return !disabled;
}