void FBOBJECT::Init(GLSTATEMANAGER & glstate, std::vector <FBTEXTURE*> newtextures, std::ostream & error_output, bool force_multisample_off)
{
	OPENGL_UTILITY::CheckForOpenGLErrors("FBO init start", error_output);

	const bool verbose = false;

	if (inited)
	{
		if (verbose) error_output << "INFO: deinitializing existing FBO" << std::endl;

		DeInit();

		OPENGL_UTILITY::CheckForOpenGLErrors("FBO deinit", error_output);
	}

	textures = newtextures;

	inited = true;

	assert(!textures.empty());

	// run some sanity checks and find out which textures are for the color attachment and
	// which are for the depth attachment
	std::vector <FBTEXTURE*> color_textures;
	std::vector <FBTEXTURE*> depth_textures;

	for (std::vector <FBTEXTURE*>::iterator i = textures.begin(); i != textures.end(); i++)
	{
		if ((*i)->texture_format == FBTEXTURE::DEPTH24)
			depth_textures.push_back(*i);
		else
			color_textures.push_back(*i);

		//assert(!(*i)->attached || (force_multisample_off && (*i)->renderbuffer_multisample != 0));
		(*i)->attached = true;
	}

	if (verbose) error_output << "INFO: color textures: " << color_textures.size() << ", depth textures: " << depth_textures.size() << std::endl;

	//need at least some textures
	assert(color_textures.size() + depth_textures.size() >= 1);

	//can't have more than one depth attachment
	assert(depth_textures.size() < 2);

	//can't have more than 4 color textures
	assert(color_textures.size() < 5);

	for (std::vector <FBTEXTURE*>::iterator i = color_textures.begin(); i != color_textures.end(); i++)
	{
		if ((*i)->texture_target == FBTEXTURE::CUBEMAP)
		{
			if (verbose) error_output << "INFO: found cubemap" << std::endl;

			//can't have MRT with cubemaps
			assert(color_textures.size() == 1);

			//can't have multisample with cubemaps
			assert((*i)->multisample == 0);

			//can't have depth texture with cubemaps
			assert(depth_textures.empty());
		}
	}

	//find what multisample value to use
	int multisample = 0;
	if (!color_textures.empty())
	{
		multisample = -1;
		for (std::vector <FBTEXTURE*>::iterator i = textures.begin(); i != textures.end(); i++)
		{
			if (multisample == -1)
				multisample = (*i)->multisample;

			//all must have the same multisample
			assert(multisample == (*i)->multisample);
		}
	}

	if (verbose) error_output << "INFO: multisample " << multisample << " found, " << force_multisample_off << std::endl;

	if (force_multisample_off)
		multisample = 0;

	//either we have no multisample
	//or multisample and no depth texture
	assert((multisample == 0) || ((multisample > 0) && depth_textures.empty()));

	//ensure consistent sizes
	width = -1;
	height = -1;
	for (std::vector <FBTEXTURE*>::iterator i = textures.begin(); i != textures.end(); i++)
	{
		if (width == -1)
			width = (*i)->sizew;
		if (height == -1)
			height = (*i)->sizeh;
		assert(width == (*i)->sizew);
		assert(height == (*i)->sizeh);
	}

	if (verbose) error_output << "INFO: width " << width << ", height " << height << std::endl;

	//initialize framebuffer object (FBO)
	assert(GLEW_ARB_framebuffer_object);
	glGenFramebuffers(1, &framebuffer_object);

	if (verbose) error_output << "INFO: generated FBO " << framebuffer_object << std::endl;

	OPENGL_UTILITY::CheckForOpenGLErrors("FBO generation", error_output);

	//bind the framebuffer
	glstate.BindFramebuffer(framebuffer_object);

	OPENGL_UTILITY::CheckForOpenGLErrors("FBO binding", error_output);

	//initialize renderbuffer object that's used for our depth buffer if we're not using
	//a depth texture
	if (depth_textures.empty())
	{
		glGenRenderbuffers(1, &renderbuffer_depth);
		glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer_depth);

		if (verbose) error_output << "INFO: generating depth renderbuffer" << std::endl;

		OPENGL_UTILITY::CheckForOpenGLErrors("FBO renderbuffer generation", error_output);

		if (multisample > 0)
		{
			// need a separate multisample depth buffer
			glRenderbufferStorageMultisample(GL_RENDERBUFFER, multisample, GL_DEPTH_COMPONENT, width, height);

			if (verbose) error_output << "INFO: using multisampling for depth renderbuffer" << std::endl;
		}
		else
			glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);

		OPENGL_UTILITY::CheckForOpenGLErrors("FBO renderbuffer initialization", error_output);

		//attach the render buffer to the FBO
		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, renderbuffer_depth);

		if (verbose) error_output << "INFO: depth renderbuffer attached to FBO" << std::endl;

		OPENGL_UTILITY::CheckForOpenGLErrors("FBO renderbuffer attachment", error_output);
	}

	GLenum buffers[4] = {GL_NONE, GL_NONE, GL_NONE, GL_NONE};
	{
		int count = 0;
		for (std::vector <FBTEXTURE*>::iterator i = color_textures.begin(); i != color_textures.end(); i++,count++)
		{
			buffers[count] = GL_COLOR_ATTACHMENT0+count;
		}
	}

	glDrawBuffers(4, buffers);
	glReadBuffer(buffers[0]);

	if (verbose) error_output << "INFO: set draw buffers: " << buffers[0] << ", " << buffers[1] << ", " << buffers[2] << ", " << buffers[3] << std::endl;
	if (verbose) error_output << "INFO: set read buffer: " << buffers[0] << std::endl;

	OPENGL_UTILITY::CheckForOpenGLErrors("FBO buffer mask set", error_output);

	//add separate multisample color buffers for each color texture
	if (multisample > 0)
	{
		int count = 0;
		for (std::vector <FBTEXTURE*>::iterator i = color_textures.begin(); i != color_textures.end(); i++,count++)
		{
			// need a separate multisample color buffer
			glGenRenderbuffers(1, &(*i)->renderbuffer_multisample);
			glBindRenderbuffer(GL_RENDERBUFFER, (*i)->renderbuffer_multisample);
			glRenderbufferStorageMultisample(GL_RENDERBUFFER, multisample, (*i)->texture_format, width, height);
			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0+count, GL_RENDERBUFFER, (*i)->renderbuffer_multisample);

			if (verbose) error_output << "INFO: generating separate multisample color buffer " << count << std::endl;

			OPENGL_UTILITY::CheckForOpenGLErrors("FBO multisample color renderbuffer", error_output);
		}
	}

	//attach any color textures to the FBO
	{
		int count = 0;
		for (std::vector <FBTEXTURE*>::iterator i = color_textures.begin(); i != color_textures.end(); i++,count++)
		{
			int texture_attachment = GL_COLOR_ATTACHMENT0+count;
			if (multisample == 0)
			{
				if ((*i)->texture_target == FBTEXTURE::CUBEMAP)
				{
					// if we're using a cubemap, arbitrarily pick one of the faces to activate so we can check that the FBO is complete
					glFramebufferTexture2D(GL_FRAMEBUFFER, texture_attachment, GL_TEXTURE_CUBE_MAP_POSITIVE_X, (*i)->fbtexture, 0);

					if (verbose) error_output << "INFO: attaching arbitrary cubemap face to color attachment " << count << std::endl;
				}
				else
				{
					glFramebufferTexture2D(GL_FRAMEBUFFER, texture_attachment, (*i)->texture_target, (*i)->fbtexture, 0);

					if (verbose) error_output << "INFO: attaching texture to color attachment " << count << std::endl;
				}
				(*i)->texture_attachment = texture_attachment;
			}
		}
	}

	//attach the depth texture to the FBO, if there is one
	{
		int count = 0;
		for (std::vector <FBTEXTURE*>::iterator i = depth_textures.begin(); i != depth_textures.end(); i++,count++)
		{
			if (multisample == 0)
			{
				if ((*i)->texture_target == FBTEXTURE::CUBEMAP)
				{
					// if we're using a cubemap, arbitrarily pick one of the faces to activate so we can check that the FBO is complete
					glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_CUBE_MAP_POSITIVE_X, (*i)->fbtexture, 0);

					if (verbose) error_output << "INFO: attaching cubemap depth texture" << std::endl;
				}
				else
				{
					glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, (*i)->texture_target, (*i)->fbtexture, 0);

					if (verbose) error_output << "INFO: attaching depth texture" << std::endl;
				}
			}
		}
	}

	OPENGL_UTILITY::CheckForOpenGLErrors("FBO attachment", error_output);

	bool status_ok = CheckStatus(error_output);
	if (!status_ok)
	{
		error_output << "Error initializing FBO:" << std::endl;
		int count = 0;
		for (std::vector <FBTEXTURE*>::iterator i = textures.begin(); i != textures.end(); i++)
		{
			error_output << "\t" << count << ". " << TargetToString((*i)->texture_target) << ": " << FormatToString((*i)->texture_format) << std::endl;
			count++;
		}
	}
	assert(status_ok);

	glstate.BindFramebuffer(0);

	OPENGL_UTILITY::CheckForOpenGLErrors("FBO unbinding", error_output);

	// if multisampling is on, create another framebuffer object for the single sample version of these textures
	if (multisample > 0)
	{
		if (verbose) error_output << "INFO: creating secondary single sample framebuffer object" << std::endl;

		assert(multisample_dest_singlesample_framebuffer_object.empty());
		multisample_dest_singlesample_framebuffer_object.push_back(FBOBJECT());
		multisample_dest_singlesample_framebuffer_object.back().Init(glstate, newtextures, error_output, true);
	}
}
// prime chain type and length value
std::string GetPrimeChainName(unsigned int nChainType, unsigned int nChainLength)
{
	return (nChainType==PRIME_CHAIN_CUNNINGHAM1)? "1CC" : ((nChainType==PRIME_CHAIN_CUNNINGHAM2)? "2CC" : "TWN") + TargetToString(nChainLength);
}
Exemple #3
0
void FrameBufferObject::Init(
	GraphicsState & glstate,
	const std::vector <FrameBufferTexture*> & newtextures,
	std::ostream & error_output,
	bool force_multisample_off)
{
	CheckForOpenGLErrors("FBO init start", error_output);

	const bool verbose = false;

	if (inited)
	{
		if (verbose) error_output << "INFO: deinitializing existing FBO" << std::endl;

		DeInit();

		CheckForOpenGLErrors("FBO deinit", error_output);
	}
	inited = true;

	// need at least some textures
	assert(!newtextures.empty());
	textures = newtextures;

	width = -1;
	height = -1;
	std::vector <FrameBufferTexture*> color_textures;
	FrameBufferTexture * depth_texture = 0;
	for (std::vector <FrameBufferTexture*>::const_iterator i = textures.begin(); i != textures.end(); i++)
	{
		// ensure consistent sizes
		if (width == -1)
			width = (*i)->GetW();
		if (height == -1)
			height = (*i)->GetH();
		assert(width == int((*i)->GetW()));
		assert(height == int((*i)->GetH()));

		// separate textures by type
		if ((*i)->GetFormat() == FrameBufferTexture::DEPTH24)
		{
			// can't have more than one depth attachment
			assert(!depth_texture);
			depth_texture = *i;
		}
		else
		{
			color_textures.push_back(*i);
		}
	}
	if (verbose) error_output << "INFO: width " << width << ", height " << height << std::endl;
	if (verbose) error_output << "INFO: color textures: " << color_textures.size() << std::endl;
	if (verbose && depth_texture) error_output << "INFO: depth texture: 1" << std::endl;

	// can't have more than 4 color attachments
	assert(color_textures.size() < 5);

	// check for cubemaps
	for (std::vector <FrameBufferTexture*>::const_iterator i = color_textures.begin(); i != color_textures.end(); i++)
	{
		if ((*i)->GetTarget() == FrameBufferTexture::CUBEMAP)
		{
			if (verbose) error_output << "INFO: found cubemap" << std::endl;

			// can't have MRT with cubemaps
			assert(color_textures.size() == 1);

			// can't have multisample with cubemaps
			assert((*i)->GetMultiSample() == 0);

			// can't have depth texture with cubemaps
			assert(!depth_texture);
		}
	}

	// find what multisample value to use
	int multisample = 0;
	if (!color_textures.empty())
	{
		multisample = -1;
		for (std::vector <FrameBufferTexture*>::const_iterator i = textures.begin(); i != textures.end(); i++)
		{
			if (multisample == -1)
				multisample = (*i)->GetMultiSample();

			// all must have the same multisample
			assert(multisample == (*i)->GetMultiSample());
		}
	}

	if (verbose) error_output << "INFO: multisample " << multisample << " found, " << force_multisample_off << std::endl;

	if (force_multisample_off)
		multisample = 0;

	// either we have no multisample or multisample and no depth texture
	assert((multisample == 0) || ((multisample > 0) && depth_texture));

	// initialize framebuffer object
	glGenFramebuffers(1, &framebuffer_object);

	if (verbose) error_output << "INFO: generated FBO " << framebuffer_object << std::endl;

	CheckForOpenGLErrors("FBO generation", error_output);

	// bind framebuffer
	glstate.BindFramebuffer(GL_FRAMEBUFFER, framebuffer_object);

	CheckForOpenGLErrors("FBO binding", error_output);

	if (!depth_texture)
	{
		// create depth render buffer if we're not using a depth texture
		glGenRenderbuffers(1, &depth_renderbuffer);
		glBindRenderbuffer(GL_RENDERBUFFER, depth_renderbuffer);

		if (verbose) error_output << "INFO: generating depth renderbuffer" << std::endl;

		CheckForOpenGLErrors("FBO renderbuffer generation", error_output);

		if (multisample > 0)
		{
			glRenderbufferStorageMultisample(GL_RENDERBUFFER, multisample, GL_DEPTH_COMPONENT, width, height);

			if (verbose) error_output << "INFO: using multisampling for depth renderbuffer" << std::endl;
		}
		else
		{
			glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, width, height);
		}

		CheckForOpenGLErrors("FBO renderbuffer initialization", error_output);

		// attach depth render buffer to the FBO
		glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth_renderbuffer);

		if (verbose) error_output << "INFO: depth renderbuffer attached to FBO" << std::endl;

		CheckForOpenGLErrors("FBO renderbuffer attachment", error_output);
	}

	if (multisample > 0)
	{
		// create/attach separate multisample color buffers for each color texture
		multisample_renderbuffers.resize(color_textures.size(), 0);
		for (size_t i = 0; i < color_textures.size(); i++)
		{
			glGenRenderbuffers(1, &multisample_renderbuffers[i]);
			glBindRenderbuffer(GL_RENDERBUFFER, multisample_renderbuffers[i]);
			glRenderbufferStorageMultisample(GL_RENDERBUFFER, multisample, color_textures[i]->GetFormat(), width, height);

			glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_RENDERBUFFER, multisample_renderbuffers[i]);

			if (verbose) error_output << "INFO: generating separate multisample color buffer " << i << std::endl;

			CheckForOpenGLErrors("FBO multisample color renderbuffer", error_output);
		}
	}
	else
	{
		// attach color textures to frame buffer object
		int count = 0;
		for (std::vector <FrameBufferTexture*>::iterator i = color_textures.begin(); i != color_textures.end(); i++, count++)
		{
			int attachment = GL_COLOR_ATTACHMENT0 + count;
			if ((*i)->GetTarget() == FrameBufferTexture::CUBEMAP)
			{
				// if we're using a cubemap, arbitrarily pick one of the faces to activate so we can check that the FBO is complete
				glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_CUBE_MAP_POSITIVE_X, (*i)->GetId(), 0);

				if (verbose) error_output << "INFO: attaching arbitrary cubemap face to color attachment " << count << std::endl;
			}
			else
			{
				glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, (*i)->GetTarget(), (*i)->GetId(), 0);

				if (verbose) error_output << "INFO: attaching texture to color attachment " << count << std::endl;
			}
			(*i)->SetAttachment(attachment);

			CheckForOpenGLErrors("FBO attachment", error_output);
		}

		if (depth_texture)
		{
			// attach depth texture to frame buffer object
			glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, depth_texture->GetTarget(), depth_texture->GetId(), 0);
			depth_texture->SetAttachment(GL_DEPTH_ATTACHMENT);

			if (verbose) error_output << "INFO: attaching depth texture" << std::endl;
			CheckForOpenGLErrors("FBO attachment", error_output);
		}
	}

	GLenum buffers[4] = {GL_NONE, GL_NONE, GL_NONE, GL_NONE};
	{
		int count = 0;
		for (std::vector <FrameBufferTexture*>::const_iterator i = color_textures.begin(); i != color_textures.end(); i++, count++)
		{
			buffers[count] = GL_COLOR_ATTACHMENT0 + count;
		}

		glDrawBuffers(count, buffers);
		glReadBuffer(buffers[0]);

		CheckForOpenGLErrors("FBO buffer mask set", error_output);
	}

	if (verbose) error_output << "INFO: set draw buffers: " << buffers[0] << ", " << buffers[1] << ", " << buffers[2] << ", " << buffers[3] << std::endl;
	if (verbose) error_output << "INFO: set read buffer: " << buffers[0] << std::endl;

	if (!CheckStatus(error_output))
	{
		error_output << "Error initializing FBO:" << std::endl;
		int count = 0;
		for (std::vector <FrameBufferTexture*>::const_iterator i = textures.begin(); i != textures.end(); i++)
		{
			error_output << "\t" << count << ". " << TargetToString(FrameBufferTexture::Target((*i)->GetTarget()));
			error_output << ": " << FormatToString((*i)->GetFormat()) << std::endl;
			count++;
		}
		assert(0);
	}

	// explicitely unbind framebuffer object
	glstate.BindFramebuffer(GL_FRAMEBUFFER, 0);

	CheckForOpenGLErrors("FBO unbinding", error_output);

	// if multisampling is on, create another framebuffer object for the single sample version of these textures
	if (multisample > 0)
	{
		if (verbose) error_output << "INFO: creating secondary single sample framebuffer object" << std::endl;

		assert(!singlesample_framebuffer_object);
		singlesample_framebuffer_object = new FrameBufferObject();
		singlesample_framebuffer_object->Init(glstate, newtextures, error_output, true);
	}
}
// Test probable prime chain for: nOrigin
// Return value:
//   true - Probable prime chain found (one of nChainLength meeting target)
//   false - prime chain too short (none of nChainLength meeting target)
static bool ProbablePrimeChainTestFast(const mpz_class& mpzPrimeChainOrigin, CPrimalityTestParams& testParams, uint sievenumber, bool use_gpu_fermat_test)
{
    const unsigned int nBits = testParams.nBits;
	const unsigned int nBits_masked = nBits&TARGET_LENGTH_MASK;
    unsigned int& nChainLengthCunningham1 = testParams.nChainLengthCunningham1;
    unsigned int& nChainLengthCunningham2 = testParams.nChainLengthCunningham2;
    unsigned int& nChainLengthBiTwin = testParams.nChainLengthBiTwin;
    const bool fFermatTest = testParams.fFermatTest;
    mpz_class& mpzOriginMinusOne = testParams.mpzOriginMinusOne;
    mpz_class& mpzOriginPlusOne = testParams.mpzOriginPlusOne;
    nChainLengthCunningham1 = 0;
    nChainLengthCunningham2 = 0;
    nChainLengthBiTwin = 0;
	
    // Test for Cunningham Chain of first kind
	if (sievenumber&1)
	{
		mpzOriginMinusOne = mpzPrimeChainOrigin - 1;
		ProbableCunninghamChainTestFast(mpzOriginMinusOne, true, fFermatTest, nChainLengthCunningham1, testParams, use_gpu_fermat_test);
		if ((nChainLengthCunningham1&TARGET_FRACTIONAL_MASK) == 0)
			nChainLengthCunningham1 |= TARGET_FRACTIONAL_MASK;
	}
    // Test for Cunningham Chain of second kind
	if (sievenumber&2)
	{
		mpzOriginPlusOne = mpzPrimeChainOrigin + 1;
		ProbableCunninghamChainTestFast(mpzOriginPlusOne, false, fFermatTest, nChainLengthCunningham2, testParams, use_gpu_fermat_test);
		if ((nChainLengthCunningham2&TARGET_FRACTIONAL_MASK) == 0)
			nChainLengthCunningham2 |= TARGET_FRACTIONAL_MASK;
	}
	// Figure out BiTwin Chain length
    // BiTwin Chain allows a single prime at the end for odd length chain
    nChainLengthBiTwin =
        (TargetGetLength(nChainLengthCunningham1) > TargetGetLength(nChainLengthCunningham2))?
            (nChainLengthCunningham2 + TargetFromInt(TargetGetLength(nChainLengthCunningham2)+1)) :
            (nChainLengthCunningham1 + TargetFromInt(TargetGetLength(nChainLengthCunningham1)));
			
	uint c1 = TargetGetLength(nChainLengthCunningham1);
	uint c2 = TargetGetLength(nChainLengthCunningham2);
	uint tw = TargetGetLength(nChainLengthBiTwin);
	
	if (c1 >= 6)
	{
		cout << "C1 " << nChainLengthCunningham1 << " --> " << TargetToString(nChainLengthCunningham1) << " found!" << endl;
	}
	if (c2 >= 6)
	{
		cout << "C2 " << nChainLengthCunningham2 << " --> " << TargetToString(nChainLengthCunningham2) << " found!" << endl;
	}
	if (tw >= 6)
	{
		cout << "TW " << nChainLengthBiTwin << " --> " << TargetToString(nChainLengthBiTwin) << " found!" << endl;
	}
	
	++chainspersec[c1];
	++chainspersec[c2];
	++chainspersec[tw];
	++totalpersec;
	
    return (nChainLengthCunningham1 >= nBits || nChainLengthCunningham2 >= nBits || nChainLengthBiTwin >= nBits);
}