Ejemplo n.º 1
0
// Copies RGBA8 data from RAM to the currently bound render target.
void SoftGPU::CopyToCurrentFboFromDisplayRam(int srcwidth, int srcheight)
{
	float dstwidth = (float)PSP_CoreParameter().pixelWidth;
	float dstheight = (float)PSP_CoreParameter().pixelHeight;

	T3DViewport viewport = {0.0f, 0.0f, dstwidth, dstheight, 0.0f, 1.0f};
	thin3d->SetViewports(1, &viewport);

	thin3d->SetBlendState(thin3d->GetBlendStatePreset(BS_OFF));
	Thin3DSamplerState *sampler;
	if (g_Config.iBufFilter == SCALE_NEAREST) {
		sampler = thin3d->GetSamplerStatePreset(T3DSamplerStatePreset::SAMPS_NEAREST);
	} else {
		sampler = thin3d->GetSamplerStatePreset(T3DSamplerStatePreset::SAMPS_LINEAR);
	}
	thin3d->SetSamplerStates(0, 1, &sampler);
	thin3d->SetDepthStencilState(depth);
	thin3d->SetRenderState(T3DRenderState::CULL_MODE, T3DCullMode::NO_CULL);
	thin3d->SetScissorEnabled(false);

	float u0 = 0.0f;
	float u1;
	if (displayFramebuf_ == 0) {
		u8 data[] = {0, 0, 0, 0};
		fbTex->SetImageData(0, 0, 0, 1, 1, 1, 0, 4, data);
		u1 = 1.0f;
	} else if (displayFormat_ == GE_FORMAT_8888) {
		u8 *data = Memory::GetPointer(displayFramebuf_);
		fbTex->SetImageData(0, 0, 0, displayStride_, srcheight, 1, 0, displayStride_ * 4, data);
		u1 = (float)srcwidth / displayStride_;
	} else {
		// TODO: This should probably be converted in a shader instead..
		fbTexBuffer.resize(srcwidth * srcheight);
		FormatBuffer displayBuffer;
		displayBuffer.data = Memory::GetPointer(displayFramebuf_);
		for (int y = 0; y < srcheight; ++y) {
			u32 *buf_line = &fbTexBuffer[y * srcwidth];
			const u16 *fb_line = &displayBuffer.as16[y * displayStride_];

			switch (displayFormat_) {
			case GE_FORMAT_565:
				ConvertRGBA565ToRGBA8888(buf_line, fb_line, srcwidth);
				break;

			case GE_FORMAT_5551:
				ConvertRGBA5551ToRGBA8888(buf_line, fb_line, srcwidth);
				break;

			case GE_FORMAT_4444:
				ConvertRGBA4444ToRGBA8888(buf_line, fb_line, srcwidth);
				break;

			default:
				ERROR_LOG_REPORT(G3D, "Software: Unexpected framebuffer format: %d", displayFormat_);
			}
		}

		fbTex->SetImageData(0, 0, 0, srcwidth, srcheight, 1, 0, srcwidth * 4, (const uint8_t *)&fbTexBuffer[0]);
		u1 = 1.0f;
	}
	fbTex->Finalize(0);

	float x, y, w, h;
	CenterDisplayOutputRect(&x, &y, &w, &h, 480.0f, 272.0f, dstwidth, dstheight, ROTATION_LOCKED_HORIZONTAL);

	if (GetGPUBackend() == GPUBackend::DIRECT3D9) {
		x += 0.5f;
		y += 0.5f;
	}

	x /= 0.5f * dstwidth;
	y /= 0.5f * dstheight;
	w /= 0.5f * dstwidth;
	h /= 0.5f * dstheight;
	float x2 = x + w;
	float y2 = y + h;
	x -= 1.0f;
	y -= 1.0f;
	x2 -= 1.0f;
	y2 -= 1.0f;

	struct Vertex {
		float x, y, z;
		float u, v;
		uint32_t rgba;
	};

	float v0 = 1.0f;
	float v1 = 0.0f;

	if (GetGPUBackend() == GPUBackend::VULKAN) {
		std::swap(v0, v1);
	}

	const Vertex verts[4] = {
		{x, y, 0,    u0, v0,  0xFFFFFFFF}, // TL
		{x, y2, 0,   u0, v1,  0xFFFFFFFF}, // BL
		{x2, y2, 0,  u1, v1,  0xFFFFFFFF}, // BR
		{x2, y, 0,   u1, v0,  0xFFFFFFFF}, // TR
	};
	vdata->SetData((const uint8_t *)verts, sizeof(verts));

	int indexes[] = {0, 1, 2, 0, 2, 3};
	idata->SetData((const uint8_t *)indexes, sizeof(indexes));

	thin3d->SetTexture(0, fbTex);
	Thin3DShaderSet *texColor = thin3d->GetShaderSetPreset(SS_TEXTURE_COLOR_2D);

	static const float identity4x4[16] = {
		1.0f, 0.0f, 0.0f, 0.0f,
		0.0f, 1.0f, 0.0f, 0.0f,
		0.0f, 0.0f, 1.0f, 0.0f,
		0.0f, 0.0f, 0.0f, 1.0f,
	};
	texColor->SetMatrix4x4("WorldViewProj", identity4x4);
	thin3d->DrawIndexed(T3DPrimitive::PRIM_TRIANGLES, texColor, vformat, vdata, idata, 6, 0);
}
Ejemplo n.º 2
0
// Copies RGBA8 data from RAM to the currently bound render target.
void SoftGPU::CopyToCurrentFboFromDisplayRam(int srcwidth, int srcheight)
{
	float dstwidth = (float)PSP_CoreParameter().pixelWidth;
	float dstheight = (float)PSP_CoreParameter().pixelHeight;

	glDisable(GL_BLEND);
	glViewport(0, 0, dstwidth, dstheight);
	glDisable(GL_SCISSOR_TEST);

	glBindTexture(GL_TEXTURE_2D, temp_texture);

	GLfloat texvert_u;
	if (displayFramebuf_ == 0) {
		u32 data[] = {0};
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
		texvert_u = 1.0f;
	} else if (displayFormat_ == GE_FORMAT_8888) {
		u8 *data = Memory::GetPointer(displayFramebuf_);
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)displayStride_, (GLsizei)srcheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
		texvert_u = (float)srcwidth / displayStride_;
	} else {
		// TODO: This should probably be converted in a shader instead..
		// TODO: Do something less brain damaged to manage this buffer...
		u32 *buf = new u32[srcwidth * srcheight];
		FormatBuffer displayBuffer;
		displayBuffer.data = Memory::GetPointer(displayFramebuf_);
		for (int y = 0; y < srcheight; ++y) {
			u32 *buf_line = &buf[y * srcwidth];
			const u16 *fb_line = &displayBuffer.as16[y * displayStride_];

			switch (displayFormat_) {
			case GE_FORMAT_565:
				for (int x = 0; x < srcwidth; ++x) {
					buf_line[x] = RGB565ToRGBA8888(fb_line[x]);
				}
				break;

			case GE_FORMAT_5551:
				for (int x = 0; x < srcwidth; ++x) {
					buf_line[x] = RGBA5551ToRGBA8888(fb_line[x]);
				}
				break;

			case GE_FORMAT_4444:
				for (int x = 0; x < srcwidth; ++x) {
					buf_line[x] = RGBA4444ToRGBA8888(fb_line[x]);
				}
				break;

			default:
				ERROR_LOG_REPORT(G3D, "Software: Unexpected framebuffer format: %d", displayFormat_);
			}
		}

		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)srcwidth, (GLsizei)srcheight, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);
		texvert_u = 1.0f;

		delete[] buf;
	}

	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

	glUseProgram(program);

	float x, y, w, h;
	CenterDisplayOutputRect(&x, &y, &w, &h, 480.0f, 272.0f, dstwidth, dstheight, ROTATION_LOCKED_HORIZONTAL);

	x /= 0.5f * dstwidth;
	y /= 0.5f * dstheight;
	w /= 0.5f * dstwidth;
	h /= 0.5f * dstheight;
	float x2 = x + w;
	float y2 = y + h;
	x -= 1.0f;
	y -= 1.0f;
	x2 -= 1.0f;
	y2 -= 1.0f;

	const GLfloat verts[4][2] = {
		{ x, y }, // Left top
		{ x, y2}, // left bottom
		{ x2, y2}, // right bottom
		{ x2, y}  // right top
	};

	const GLfloat texverts[4][2] = {
		{0, 1},
		{0, 0},
		{texvert_u, 0},
		{texvert_u, 1}
	};

	if (vao != 0) {
		glBindVertexArray(vao);
		glBindBuffer(GL_ARRAY_BUFFER, vbuf);
		glBufferData(GL_ARRAY_BUFFER, sizeof(verts) + sizeof(texverts), nullptr, GL_STREAM_DRAW);
		glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(verts), verts);
		glBufferSubData(GL_ARRAY_BUFFER, sizeof(verts), sizeof(texverts), texverts);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

		glVertexAttribPointer(attr_pos, 2, GL_FLOAT, GL_FALSE, 0, 0);
		glVertexAttribPointer(attr_tex, 2, GL_FLOAT, GL_FALSE, 0, (void *)sizeof(verts));
	} else {
		glBindBuffer(GL_ARRAY_BUFFER, 0);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);

		glVertexAttribPointer(attr_pos, 2, GL_FLOAT, GL_FALSE, 0, verts);
		glVertexAttribPointer(attr_tex, 2, GL_FLOAT, GL_FALSE, 0, texverts);
	}

	glEnableVertexAttribArray(attr_pos);
	glEnableVertexAttribArray(attr_tex);
	glUniform1i(uni_tex, 0);
	glActiveTexture(GL_TEXTURE0);
	glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
	glDisableVertexAttribArray(attr_pos);
	glDisableVertexAttribArray(attr_tex);

	glBindTexture(GL_TEXTURE_2D, 0);

	if (vao != 0) {
		glBindVertexArray(0);
		glBindBuffer(GL_ARRAY_BUFFER, 0);
		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
	}
}