/* * Copyright (C) 2007-2009 Gabest * http://www.gabest.org * * This Program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This Program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with GNU Make; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA USA. * http://www.gnu.org/copyleft/gpl.html * */ #include "stdafx.h" #include "GSTextureSW.h" #include "GSPng.h" GSTextureSW::GSTextureSW(int type, int width, int height) { m_mapped.clear(); m_size = GSVector2i(width, height); m_type = type; m_format = 0; m_pitch = ((width << 2) + 31) & ~31; m_data = _aligned_malloc(m_pitch * height, 32); } GSTextureSW::~GSTextureSW() { _aligned_free(m_data); } bool GSTextureSW::Update(const GSVector4i& r, const void* data, int pitch) { GSMap m; if(m_data != NULL && Map(m, &r)) { uint8* RESTRICT src = (uint8*)data; uint8* RESTRICT dst = m.bits; int rowbytes = r.width() << 2; for(int h = r.height(); h > 0; h--, src += pitch, dst += m.pitch) { memcpy(dst, src, rowbytes); } Unmap(); return true; } return false; } bool GSTextureSW::Map(GSMap& m, const GSVector4i* r) { GSVector4i r2 = r != NULL ? *r : GSVector4i(0, 0, m_size.x, m_size.y); if(m_data != NULL && r2.left >= 0 && r2.right <= m_size.x && r2.top >= 0 && r2.bottom <= m_size.y) { if (!m_mapped.test_and_set()) { m.bits = (uint8*)m_data + ((m_pitch * r2.top + r2.left) << 2); m.pitch = m_pitch; return true; } } return false; } void GSTextureSW::Unmap() { m_mapped.clear(); } #ifndef _WIN32 #pragma pack(push, 1) struct BITMAPFILEHEADER { uint16 bfType; uint32 bfSize; uint16 bfReserved1; uint16 bfReserved2; uint32 bfOffBits; }; struct BITMAPINFOHEADER { uint32 biSize; int32 biWidth; int32 biHeight; uint16 biPlanes; uint16 biBitCount; uint32 biCompression; uint32 biSizeImage; int32 biXPelsPerMeter; int32 biYPelsPerMeter; uint32 biClrUsed; uint32 biClrImportant; }; #define BI_RGB 0 #pragma pack(pop) #endif bool GSTextureSW::Save(const string& fn, bool dds) { if(dds) return false; // not implemented #ifdef ENABLE_OGL_PNG #ifdef ENABLE_OGL_DEBUG GSPng::Format fmt = GSPng::RGB_A_PNG; #else GSPng::Format fmt = GSPng::RGB_PNG; #endif GSPng::Save(fmt, fn, (char*)m_data, m_size.x, m_size.y, m_pitch); return true; #else if(FILE* fp = fopen(fn.c_str(), "wb")) { BITMAPINFOHEADER bih; memset(&bih, 0, sizeof(bih)); bih.biSize = sizeof(bih); bih.biWidth = m_size.x; bih.biHeight = m_size.y; bih.biPlanes = 1; bih.biBitCount = 32; bih.biCompression = BI_RGB; bih.biSizeImage = m_size.x * m_size.y << 2; BITMAPFILEHEADER bfh; memset(&bfh, 0, sizeof(bfh)); uint8* bfType = (uint8*)&bfh.bfType; // bfh.bfType = 'MB'; bfType[0] = 0x42; bfType[1] = 0x4d; bfh.bfOffBits = sizeof(bfh) + sizeof(bih); bfh.bfSize = bfh.bfOffBits + bih.biSizeImage; bfh.bfReserved1 = bfh.bfReserved2 = 0; fwrite(&bfh, 1, sizeof(bfh), fp); fwrite(&bih, 1, sizeof(bih), fp); uint8* data = (uint8*)m_data + (m_size.y - 1) * m_pitch; for(int h = m_size.y; h > 0; h--, data -= m_pitch) { for(int i = 0; i < m_size.x; i++) { uint32 c = ((uint32*)data)[i]; c = (c & 0xff00ff00) | ((c & 0x00ff0000) >> 16) | ((c & 0x000000ff) << 16); fwrite(&c, 1, sizeof(c), fp); } // fwrite(data, 1, m_size.x << 2, fp); // TODO: swap red-blue? } fclose(fp); return true; } return false; #endif }