Пример #1
0
CGSH_OpenGL::TEXTURE_INFO CGSH_OpenGL::PrepareTexture(const TEX0& tex0)
{
	TEXTURE_INFO texInfo;

	for(const auto& candidateFramebuffer : m_framebuffers)
	{
		bool canBeUsed = false;
		float offsetX = 0;

		//Case: TEX0 points at the start of a frame buffer with the same width
		if(candidateFramebuffer->m_basePtr == tex0.GetBufPtr() &&
			candidateFramebuffer->m_width == tex0.GetBufWidth() &&
			IsCompatibleFramebufferPSM(candidateFramebuffer->m_psm, tex0.nPsm))
		{
			canBeUsed = true;
		}

		//Another case: TEX0 is pointing to the start of a page within our framebuffer (BGDA does this)
		else if(candidateFramebuffer->m_basePtr <= tex0.GetBufPtr() &&
			candidateFramebuffer->m_psm == tex0.nPsm)
		{
			uint32 framebufferOffset = tex0.GetBufPtr() - candidateFramebuffer->m_basePtr;

			//Bail if offset is not aligned on a page boundary
			if((framebufferOffset & (CGsPixelFormats::PAGESIZE - 1)) != 0) continue;

			auto framebufferPageSize = CGsPixelFormats::GetPsmPageSize(candidateFramebuffer->m_psm);
			uint32 framebufferPageCountX = candidateFramebuffer->m_width / framebufferPageSize.first;
			uint32 framebufferPageIndex = framebufferOffset / CGsPixelFormats::PAGESIZE;

			//Bail if pointed page isn't on the first line
			if(framebufferPageIndex >= framebufferPageCountX) continue;

			canBeUsed = true;
			offsetX = static_cast<float>(framebufferPageIndex * framebufferPageSize.first) / static_cast<float>(candidateFramebuffer->m_width);
		}

		if(canBeUsed)
		{
			CommitFramebufferDirtyPages(candidateFramebuffer, 0, tex0.GetHeight());

			//We have a winner
			glBindTexture(GL_TEXTURE_2D, candidateFramebuffer->m_texture);

			float scaleRatioX = static_cast<float>(tex0.GetWidth()) / static_cast<float>(candidateFramebuffer->m_textureWidth);
			float scaleRatioY = static_cast<float>(tex0.GetHeight()) / static_cast<float>(candidateFramebuffer->m_height);

			//If we're currently in interlaced mode, framebuffer will have twice the height
			bool halfHeight = GetCrtIsInterlaced() && GetCrtIsFrameMode();
			if(halfHeight) scaleRatioY *= 2.0f;

			texInfo.offsetX = offsetX;
			texInfo.scaleRatioX = scaleRatioX;
			texInfo.scaleRatioY = scaleRatioY;

			return texInfo;
		}
	}

	auto texture = TexCache_Search(tex0);
	if(texture)
	{
		glBindTexture(GL_TEXTURE_2D, texture->m_texture);
		auto& cachedArea = texture->m_cachedArea;

		if(cachedArea.HasDirtyPages())
		{
			auto texturePageSize = CGsPixelFormats::GetPsmPageSize(tex0.nPsm);
			auto pageRect = cachedArea.GetPageRect();

			for(unsigned int dirtyPageIndex = 0; dirtyPageIndex < CGsCachedArea::MAX_DIRTYPAGES; dirtyPageIndex++)
			{
				if(!cachedArea.IsPageDirty(dirtyPageIndex)) continue;

				uint32 pageX = dirtyPageIndex % pageRect.first;
				uint32 pageY = dirtyPageIndex / pageRect.first;
				uint32 texX = pageX * texturePageSize.first;
				uint32 texY = pageY * texturePageSize.second;
				uint32 texWidth = texturePageSize.first;
				uint32 texHeight = texturePageSize.second;
				if(texX >= tex0.GetWidth()) continue;
				if(texY >= tex0.GetHeight()) continue;
				//assert(texX < tex0.GetWidth());
				//assert(texY < tex0.GetHeight());
				if((texX + texWidth) > tex0.GetWidth())
				{
					texWidth = tex0.GetWidth() - texX;
				}
				if((texY + texHeight) > tex0.GetHeight())
				{
					texHeight = tex0.GetHeight() - texY;
				}
				((this)->*(m_textureUpdater[tex0.nPsm]))(tex0.GetBufPtr(), tex0.nBufWidth, texX, texY, texWidth, texHeight);
			}

			cachedArea.ClearDirtyPages();
		}
	}
	else
	{
		//Validate texture dimensions to prevent problems
		auto texWidth = tex0.GetWidth();
		auto texHeight = tex0.GetHeight();
		assert(texWidth <= 1024);
		assert(texHeight <= 1024);
		texWidth = std::min<uint32>(texWidth, 1024);
		texHeight = std::min<uint32>(texHeight, 1024);

		GLuint nTexture = 0;
		glGenTextures(1, &nTexture);
		glBindTexture(GL_TEXTURE_2D, nTexture);
		((this)->*(m_textureUploader[tex0.nPsm]))(tex0.GetBufPtr(), tex0.nBufWidth, texWidth, texHeight);
		TexCache_Insert(tex0, nTexture);
	}

	return texInfo;
}
Пример #2
0
void CGSH_Direct3D9::SetRenderingContext(uint64 primReg)
{
	auto prim = make_convertible<PRMODE>(primReg);

	unsigned int context = prim.nContext;

	uint64 testReg = m_nReg[GS_REG_TEST_1 + context];
	uint64 frameReg = m_nReg[GS_REG_FRAME_1 + context];
	uint64 alphaReg = m_nReg[GS_REG_ALPHA_1 + context];
	uint64 zbufReg = m_nReg[GS_REG_ZBUF_1 + context];
	uint64 tex0Reg = m_nReg[GS_REG_TEX0_1 + context];
	uint64 tex1Reg = m_nReg[GS_REG_TEX1_1 + context];
	uint64 clampReg = m_nReg[GS_REG_CLAMP_1 + context];
	uint64 scissorReg = m_nReg[GS_REG_SCISSOR_1 + context];

	if(!m_renderState.isValid ||
		(m_renderState.primReg != primReg))
	{
		m_device->SetRenderState(D3DRS_ALPHABLENDENABLE, ((prim.nAlpha != 0) && m_alphaBlendingEnabled) ? TRUE : FALSE);
	}

	if(!m_renderState.isValid ||
		(m_renderState.alphaReg != alphaReg))
	{
		SetupBlendingFunction(alphaReg);
	}

	if(!m_renderState.isValid ||
		(m_renderState.testReg != testReg))
	{
		SetupTestFunctions(testReg);
	}

	if(!m_renderState.isValid ||
		(m_renderState.zbufReg != zbufReg) ||
		(m_renderState.frameReg != frameReg))
	{
		SetupDepthBuffer(zbufReg, frameReg);
	}

	if(!m_renderState.isValid ||
		(m_renderState.frameReg != frameReg) ||
		(m_renderState.scissorReg != scissorReg))
	{
		SetupFramebuffer(frameReg, scissorReg);
	}

	if(!m_renderState.isValid ||
		(m_renderState.tex0Reg != tex0Reg) ||
		(m_renderState.tex1Reg != tex1Reg) ||
		(m_renderState.clampReg != clampReg))
	{
		SetupTexture(tex0Reg, tex1Reg, clampReg);
	}

	m_renderState.isValid = true;
	m_renderState.primReg = primReg;
	m_renderState.alphaReg = alphaReg;
	m_renderState.testReg = testReg;
	m_renderState.zbufReg = zbufReg;
	m_renderState.frameReg = frameReg;
	m_renderState.tex0Reg = tex0Reg;
	m_renderState.tex1Reg = tex1Reg;
	m_renderState.clampReg = clampReg;
	m_renderState.scissorReg = scissorReg;

	auto offset = make_convertible<XYOFFSET>(m_nReg[GS_REG_XYOFFSET_1 + context]);
	m_nPrimOfsX = offset.GetX();
	m_nPrimOfsY = offset.GetY();
	
	if(GetCrtIsInterlaced() && GetCrtIsFrameMode())
	{
		if(m_nCSR & CSR_FIELD)
		{
			m_nPrimOfsY += 0.5;
		}
	}
}