예제 #1
0
void CenterDisplayOutputRect(float *x, float *y, float *w, float *h, float origW, float origH, float frameW, float frameH, int rotation) {
	float outW;
	float outH;

	bool rotated = rotation == ROTATION_LOCKED_VERTICAL || rotation == ROTATION_LOCKED_VERTICAL180;

	if (g_Config.iSmallDisplayZoomType == 0) { // Stretching
		outW = frameW;
		outH = frameH;
	} else {
		if (g_Config.iSmallDisplayZoomType == 3) { // Manual Scaling
			float offsetX = (g_Config.fSmallDisplayOffsetX - 0.5f) * 2.0f * frameW;
			float offsetY = (g_Config.fSmallDisplayOffsetY - 0.5f) * 2.0f * frameH;
			// Have to invert Y for GL
			if (GetGPUBackend() == GPUBackend::OPENGL) {
				offsetY = offsetY * -1.0f;
			}
			float customZoom = g_Config.fSmallDisplayZoomLevel;
			float smallDisplayW = origW * customZoom;
			float smallDisplayH = origH * customZoom;
			if (!rotated) {
				*x = floorf(((frameW - smallDisplayW) / 2.0f) + offsetX);
				*y = floorf(((frameH - smallDisplayH) / 2.0f) + offsetY);
				*w = floorf(smallDisplayW);
				*h = floorf(smallDisplayH);
				return;
			} else {
				*x = floorf(((frameW - smallDisplayH) / 2.0f) + offsetX);
				*y = floorf(((frameH - smallDisplayW) / 2.0f) + offsetY);
				*w = floorf(smallDisplayH);
				*h = floorf(smallDisplayW);
				return;
			}
		} else if (g_Config.iSmallDisplayZoomType == 2) { // Auto Scaling
			float pixelCrop = frameH / 270.0f;
			float resCommonWidescreen = pixelCrop - floor(pixelCrop);
			if (!rotated && resCommonWidescreen == 0.0f) {
				*x = 0;
				*y = floorf(-pixelCrop);
				*w = floorf(frameW);
				*h = floorf(pixelCrop * 272.0f);
				return;
			}
		}

		float origRatio = !rotated ? origW / origH : origH / origW;
		float frameRatio = frameW / frameH;
		
		if (origRatio > frameRatio) {
			// Image is wider than frame. Center vertically.
			outW = frameW;
			outH = frameW / origRatio;
			// Stretch a little bit
			if (!rotated && g_Config.iSmallDisplayZoomType == 1) // Partial Stretch
				outH = (frameH + outH) / 2.0f; // (408 + 720) / 2 = 564
		} else {
			// Image is taller than frame. Center horizontally.
			outW = frameH * origRatio;
			outH = frameH;
			if (rotated && g_Config.iSmallDisplayZoomType == 1) // Partial Stretch
				outW = (frameH + outH) / 2.0f; // (408 + 720) / 2 = 564
		}
	}

	*x = floorf((frameW - outW) / 2.0f);
	*y = floorf((frameH - outH) / 2.0f);
	*w = floorf(outW);
	*h = floorf(outH);
}
예제 #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;

	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);
}
void CenterDisplayOutputRect(float *x, float *y, float *w, float *h, float origW, float origH, float frameW, float frameH, int rotation) {
	float outW;
	float outH;

	bool rotated = rotation == ROTATION_LOCKED_VERTICAL || rotation == ROTATION_LOCKED_VERTICAL180;

	if (g_Config.bStretchToDisplay) {
		outW = frameW;
		outH = frameH;
	} else {
		bool fullScreenZoom = true;
#ifndef MOBILE_DEVICE
		// This would turn off small display in window mode. I think it's better to allow it.
		// fullScreenZoom = g_Config.bFullScreen;
#endif
		if (fullScreenZoom) {
			if (g_Config.iSmallDisplayZoom != 0) {
				float offsetX = (g_Config.fSmallDisplayOffsetX - 0.5f) * 2.0f * frameW;
				float offsetY = (g_Config.fSmallDisplayOffsetY - 0.5f) * 2.0f * frameH;
				// Have to invert Y for GL
				if (GetGPUBackend() == GPUBackend::OPENGL) {
					offsetY = offsetY * -1.0f;
				}
				float customZoom = g_Config.fSmallDisplayCustomZoom / 8.0f;
				float smallDisplayW = origW * customZoom;
				float smallDisplayH = origH * customZoom;
				if (!rotated) {
					*x = floorf(((frameW - smallDisplayW) / 2.0f) + offsetX);
					*y = floorf(((frameH - smallDisplayH) / 2.0f) + offsetY);
					*w = floorf(smallDisplayW);
					*h = floorf(smallDisplayH);
					return;
				} else {
					*x = floorf(((frameW - smallDisplayH) / 2.0f) + offsetX);
					*y = floorf(((frameH - smallDisplayW) / 2.0f) + offsetY);
					*w = floorf(smallDisplayH);
					*h = floorf(smallDisplayW);
					return;
				}
			} else {
				float pixelCrop = frameH / 270.0f;
				float resCommonWidescreen = pixelCrop - floor(pixelCrop);
				if (!rotated && resCommonWidescreen == 0.0f) {
					*x = 0;
					*y = floorf(-pixelCrop);
					*w = floorf(frameW);
					*h = floorf(pixelCrop * 272.0f);
					return;
				}
			}
		}


		float origRatio = !rotated ? origW / origH : origH / origW;
		float frameRatio = frameW / frameH;

		if (origRatio > frameRatio) {
			// Image is wider than frame. Center vertically.
			outW = frameW;
			outH = frameW / origRatio;
			// Stretch a little bit
			if (!rotated && g_Config.bPartialStretch)
				outH = (frameH + outH) / 2.0f; // (408 + 720) / 2 = 564
		} else {
			// Image is taller than frame. Center horizontally.
			outW = frameH * origRatio;
			outH = frameH;
		}
	}

	*x = floorf((frameW - outW) / 2.0f);
	*y = floorf((frameH - outH) / 2.0f);
	*w = floorf(outW);
	*h = floorf(outH);
}