コード例 #1
0
void FramebufferManagerGLES::MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height, float &u1, float &v1) {
	if (drawPixelsTex_) {
		render_->DeleteTexture(drawPixelsTex_);
	}

	drawPixelsTex_ = render_->CreateTexture(GL_TEXTURE_2D);
	drawPixelsTexW_ = width;
	drawPixelsTexH_ = height;

	drawPixelsTexFormat_ = srcPixelFormat;

	// TODO: We can just change the texture format and flip some bits around instead of this.
	// Could share code with the texture cache perhaps.
	u32 neededSize = width * height * 4;
	u8 *convBuf = new u8[neededSize];
	for (int y = 0; y < height; y++) {
		const u16_le *src16 = (const u16_le *)srcPixels + srcStride * y;
		const u32_le *src32 = (const u32_le *)srcPixels + srcStride * y;
		u32 *dst = (u32 *)convBuf + width * y;
		switch (srcPixelFormat) {
		case GE_FORMAT_565:
			ConvertRGBA565ToRGBA8888((u32 *)dst, src16, width);
			break;

		case GE_FORMAT_5551:
			ConvertRGBA5551ToRGBA8888((u32 *)dst, src16, width);
			break;

		case GE_FORMAT_4444:
			ConvertRGBA4444ToRGBA8888((u32 *)dst, src16, width);
			break;

		case GE_FORMAT_8888:
			memcpy(dst, src32, 4 * width);
			break;

		case GE_FORMAT_INVALID:
			_dbg_assert_msg_(G3D, false, "Invalid pixelFormat passed to DrawPixels().");
			break;
		}
	}
	render_->TextureImage(drawPixelsTex_, 0, width, height, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, convBuf, GLRAllocType::NEW, false);
	render_->FinalizeTexture(drawPixelsTex_, 0, false);

	// TODO: Return instead?
	render_->BindTexture(TEX_SLOT_PSP_TEXTURE, drawPixelsTex_);
}
コード例 #2
0
ファイル: SoftGpu.cpp プロジェクト: Sunderland93/ppsspp
// 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);
}
コード例 #3
0
ファイル: TextureReplacer.cpp プロジェクト: kg/ppsspp
void TextureReplacer::NotifyTextureDecoded(const ReplacedTextureDecodeInfo &replacedInfo, const void *data, int pitch, int level, int w, int h) {
	_assert_msg_(G3D, enabled_, "Replacement not enabled");
	if (!g_Config.bSaveNewTextures) {
		// Ignore.
		return;
	}
	if (replacedInfo.addr > 0x05000000 && replacedInfo.addr < 0x08800000) {
		// Don't save the PPGe texture.
		return;
	}
	if (replacedInfo.isVideo && !allowVideo_) {
		return;
	}

	std::string hashfile = LookupHashFile(replacedInfo.cachekey, replacedInfo.hash, level);
	const std::string filename = basePath_ + hashfile;
	const std::string saveFilename = basePath_ + NEW_TEXTURE_DIR + hashfile;

	// If it's empty, it's an ignored hash, we intentionally don't save.
	if (hashfile.empty() || File::Exists(filename)) {
		// If it exists, must've been decoded and saved as a new texture already.
		return;
	}

	ReplacementCacheKey replacementKey(replacedInfo.cachekey, replacedInfo.hash);
	auto it = savedCache_.find(replacementKey);
	if (it != savedCache_.end() && File::Exists(saveFilename)) {
		// We've already saved this texture.  Let's only save if it's bigger (e.g. scaled now.)
		if (it->second.w >= w && it->second.h >= h) {
			return;
		}
	}

#ifdef _WIN32
	size_t slash = hashfile.find_last_of("/\\");
#else
	size_t slash = hashfile.find_last_of("/");
#endif
	if (slash != hashfile.npos) {
		// Create any directory structure as needed.
		const std::string saveDirectory = basePath_ + NEW_TEXTURE_DIR + hashfile.substr(0, slash);
		if (!File::Exists(saveDirectory)) {
			File::CreateFullPath(saveDirectory);
		}
	}

	// Only save the hashed portion of the PNG.
	int lookupW = w / replacedInfo.scaleFactor;
	int lookupH = h / replacedInfo.scaleFactor;
	if (LookupHashRange(replacedInfo.addr, lookupW, lookupH)) {
		w = lookupW * replacedInfo.scaleFactor;
		h = lookupH * replacedInfo.scaleFactor;
	}

#ifdef USING_QT_UI
	ERROR_LOG(G3D, "Replacement texture saving not implemented for Qt");
#else
	if (replacedInfo.fmt != ReplacedTextureFormat::F_8888) {
		saveBuf.resize((pitch * h) / sizeof(u16));
		switch (replacedInfo.fmt) {
		case ReplacedTextureFormat::F_5650:
			ConvertRGBA565ToRGBA8888(saveBuf.data(), (const u16 *)data, (pitch * h) / sizeof(u16));
			break;
		case ReplacedTextureFormat::F_5551:
			ConvertRGBA5551ToRGBA8888(saveBuf.data(), (const u16 *)data, (pitch * h) / sizeof(u16));
			break;
		case ReplacedTextureFormat::F_4444:
			ConvertRGBA4444ToRGBA8888(saveBuf.data(), (const u16 *)data, (pitch * h) / sizeof(u16));
			break;
		case ReplacedTextureFormat::F_0565_ABGR:
			ConvertABGR565ToRGBA8888(saveBuf.data(), (const u16 *)data, (pitch * h) / sizeof(u16));
			break;
		case ReplacedTextureFormat::F_1555_ABGR:
			ConvertABGR1555ToRGBA8888(saveBuf.data(), (const u16 *)data, (pitch * h) / sizeof(u16));
			break;
		case ReplacedTextureFormat::F_4444_ABGR:
			ConvertABGR4444ToRGBA8888(saveBuf.data(), (const u16 *)data, (pitch * h) / sizeof(u16));
			break;
		case ReplacedTextureFormat::F_8888_BGRA:
			ConvertBGRA8888ToRGBA8888(saveBuf.data(), (const u32 *)data, (pitch * h) / sizeof(u32));
			break;
		case ReplacedTextureFormat::F_8888:
			// Impossible.  Just so we can get warnings on other missed formats.
			break;
		}

		data = saveBuf.data();
		if (replacedInfo.fmt != ReplacedTextureFormat::F_8888_BGRA) {
			// We doubled our pitch.
			pitch *= 2;
		}
	}

	png_image png;
	memset(&png, 0, sizeof(png));
	png.version = PNG_IMAGE_VERSION;
	png.format = PNG_FORMAT_RGBA;
	png.width = w;
	png.height = h;
	bool success = WriteTextureToPNG(&png, saveFilename, 0, data, pitch, nullptr);
	png_image_free(&png);

	if (png.warning_or_error >= 2) {
		ERROR_LOG(COMMON, "Saving screenshot to PNG produced errors.");
	} else if (success) {
		NOTICE_LOG(G3D, "Saving texture for replacement: %08x / %dx%d", replacedInfo.hash, w, h);
	}
#endif

	// Remember that we've saved this for next time.
	ReplacedTextureLevel saved;
	saved.fmt = ReplacedTextureFormat::F_8888;
	saved.file = filename;
	saved.w = w;
	saved.h = h;
	savedCache_[replacementKey] = saved;
}