2010-04-25 00:31:27 +00:00
|
|
|
/*
|
2009-02-09 21:15:56 +00:00
|
|
|
* 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.
|
2010-04-25 00:31:27 +00:00
|
|
|
*
|
2009-02-09 21:15:56 +00:00
|
|
|
* 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.
|
2010-04-25 00:31:27 +00:00
|
|
|
*
|
2009-02-09 21:15:56 +00:00
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with GNU Make; see the file COPYING. If not, write to
|
2012-09-09 18:16:11 +00:00
|
|
|
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA USA.
|
2009-02-09 21:15:56 +00:00
|
|
|
* http://www.gnu.org/copyleft/gpl.html
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "stdafx.h"
|
|
|
|
#include "GSTexture9.h"
|
2016-02-19 18:05:39 +00:00
|
|
|
#include "GSPng.h"
|
2009-02-09 21:15:56 +00:00
|
|
|
|
|
|
|
GSTexture9::GSTexture9(IDirect3DSurface9* surface)
|
|
|
|
{
|
|
|
|
m_surface = surface;
|
|
|
|
|
|
|
|
surface->GetDevice(&m_dev);
|
|
|
|
surface->GetDesc(&m_desc);
|
2010-04-25 00:31:27 +00:00
|
|
|
|
2009-02-09 21:15:56 +00:00
|
|
|
if(m_desc.Type != D3DRTYPE_SURFACE)
|
|
|
|
{
|
2009-06-03 12:09:04 +00:00
|
|
|
surface->GetContainer(__uuidof(IDirect3DTexture9), (void**)&m_texture);
|
|
|
|
|
|
|
|
ASSERT(m_texture != NULL);
|
2009-02-09 21:15:56 +00:00
|
|
|
}
|
2009-07-16 21:36:07 +00:00
|
|
|
|
|
|
|
m_size.x = (int)m_desc.Width;
|
|
|
|
m_size.y = (int)m_desc.Height;
|
2009-08-02 23:07:30 +00:00
|
|
|
|
|
|
|
if(m_desc.Usage & D3DUSAGE_RENDERTARGET) m_type = RenderTarget;
|
|
|
|
else if(m_desc.Usage & D3DUSAGE_DEPTHSTENCIL) m_type = DepthStencil;
|
|
|
|
else if(m_desc.Pool == D3DPOOL_MANAGED) m_type = Texture;
|
|
|
|
else if(m_desc.Pool == D3DPOOL_SYSTEMMEM) m_type = Offscreen;
|
|
|
|
|
|
|
|
m_format = (int)m_desc.Format;
|
|
|
|
|
|
|
|
m_msaa = m_desc.MultiSampleType != D3DMULTISAMPLE_NONE;
|
2009-02-09 21:15:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
GSTexture9::GSTexture9(IDirect3DTexture9* texture)
|
|
|
|
{
|
|
|
|
m_texture = texture;
|
|
|
|
|
|
|
|
texture->GetDevice(&m_dev);
|
|
|
|
texture->GetLevelDesc(0, &m_desc);
|
|
|
|
texture->GetSurfaceLevel(0, &m_surface);
|
2009-06-05 15:15:02 +00:00
|
|
|
|
|
|
|
ASSERT(m_surface != NULL);
|
2009-07-16 21:36:07 +00:00
|
|
|
|
|
|
|
m_size.x = (int)m_desc.Width;
|
|
|
|
m_size.y = (int)m_desc.Height;
|
2009-02-09 21:15:56 +00:00
|
|
|
|
2009-08-02 23:07:30 +00:00
|
|
|
if(m_desc.Usage & D3DUSAGE_RENDERTARGET) m_type = RenderTarget;
|
|
|
|
else if(m_desc.Usage & D3DUSAGE_DEPTHSTENCIL) m_type = DepthStencil;
|
|
|
|
else if(m_desc.Pool == D3DPOOL_MANAGED) m_type = Texture;
|
|
|
|
else if(m_desc.Pool == D3DPOOL_SYSTEMMEM) m_type = Offscreen;
|
2009-02-09 21:15:56 +00:00
|
|
|
|
2009-08-02 23:07:30 +00:00
|
|
|
m_format = (int)m_desc.Format;
|
|
|
|
|
|
|
|
m_msaa = m_desc.MultiSampleType > 1;
|
2009-02-09 21:15:56 +00:00
|
|
|
}
|
|
|
|
|
2009-08-02 23:07:30 +00:00
|
|
|
GSTexture9::~GSTexture9()
|
2009-02-09 21:15:56 +00:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2009-05-14 16:41:52 +00:00
|
|
|
bool GSTexture9::Update(const GSVector4i& r, const void* data, int pitch)
|
2009-02-09 21:15:56 +00:00
|
|
|
{
|
2009-06-05 15:15:02 +00:00
|
|
|
if(m_surface)
|
2009-02-09 21:15:56 +00:00
|
|
|
{
|
|
|
|
D3DLOCKED_RECT lr;
|
|
|
|
|
2009-06-05 15:15:02 +00:00
|
|
|
if(SUCCEEDED(m_surface->LockRect(&lr, r, 0)))
|
2009-02-09 21:15:56 +00:00
|
|
|
{
|
2009-05-14 16:41:52 +00:00
|
|
|
uint8* src = (uint8*)data;
|
|
|
|
uint8* dst = (uint8*)lr.pBits;
|
2009-02-09 21:15:56 +00:00
|
|
|
|
2009-07-06 16:35:06 +00:00
|
|
|
int bytes = r.width() * sizeof(uint32);
|
2010-04-25 00:31:27 +00:00
|
|
|
|
2009-07-06 16:35:06 +00:00
|
|
|
switch(m_desc.Format)
|
|
|
|
{
|
|
|
|
case D3DFMT_A8: bytes >>= 2; break;
|
|
|
|
case D3DFMT_A1R5G5B5: bytes >>= 1; break;
|
|
|
|
default: ASSERT(m_desc.Format == D3DFMT_A8R8G8B8); break;
|
|
|
|
}
|
2009-05-15 07:48:51 +00:00
|
|
|
|
|
|
|
bytes = min(bytes, pitch);
|
|
|
|
bytes = min(bytes, lr.Pitch);
|
2009-02-09 21:15:56 +00:00
|
|
|
|
2009-05-14 16:41:52 +00:00
|
|
|
for(int i = 0, j = r.height(); i < j; i++, src += pitch, dst += lr.Pitch)
|
2009-02-09 21:15:56 +00:00
|
|
|
{
|
|
|
|
memcpy(dst, src, bytes);
|
|
|
|
}
|
|
|
|
|
2009-06-05 15:15:02 +00:00
|
|
|
m_surface->UnlockRect();
|
2009-02-09 21:15:56 +00:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2009-06-12 19:09:17 +00:00
|
|
|
bool GSTexture9::Map(GSMap& m, const GSVector4i* r)
|
2009-02-09 21:15:56 +00:00
|
|
|
{
|
|
|
|
HRESULT hr;
|
|
|
|
|
2009-06-05 15:15:02 +00:00
|
|
|
if(m_surface)
|
2009-02-09 21:15:56 +00:00
|
|
|
{
|
|
|
|
D3DLOCKED_RECT lr;
|
|
|
|
|
2009-06-05 15:15:02 +00:00
|
|
|
if(SUCCEEDED(hr = m_surface->LockRect(&lr, (LPRECT)r, 0)))
|
2009-02-09 21:15:56 +00:00
|
|
|
{
|
2009-06-12 19:09:17 +00:00
|
|
|
m.bits = (uint8*)lr.pBits;
|
|
|
|
m.pitch = (int)lr.Pitch;
|
2009-02-09 21:15:56 +00:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void GSTexture9::Unmap()
|
|
|
|
{
|
2009-06-05 15:15:02 +00:00
|
|
|
if(m_surface)
|
2009-02-09 21:15:56 +00:00
|
|
|
{
|
2009-06-05 15:15:02 +00:00
|
|
|
m_surface->UnlockRect();
|
2009-02-09 21:15:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-24 21:52:17 +00:00
|
|
|
bool GSTexture9::Save(const string& fn, bool user_image, bool dds)
|
2009-02-09 21:15:56 +00:00
|
|
|
{
|
2016-02-19 18:05:39 +00:00
|
|
|
bool rb_swapped = true;
|
2009-04-10 07:12:29 +00:00
|
|
|
CComPtr<IDirect3DSurface9> surface;
|
2010-04-25 00:31:27 +00:00
|
|
|
|
2016-02-19 18:05:39 +00:00
|
|
|
D3DSURFACE_DESC desc;
|
|
|
|
m_surface->GetDesc(&desc);
|
2009-02-09 21:15:56 +00:00
|
|
|
|
2016-02-19 18:05:39 +00:00
|
|
|
if (m_desc.Usage & D3DUSAGE_DEPTHSTENCIL && desc.Format != D3DFMT_D32F_LOCKABLE)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
2009-02-09 21:15:56 +00:00
|
|
|
|
2016-02-19 18:05:39 +00:00
|
|
|
if (desc.Format == D3DFMT_A8 || desc.Pool == D3DPOOL_MANAGED || desc.Usage == D3DUSAGE_DEPTHSTENCIL)
|
|
|
|
{
|
|
|
|
surface = m_surface;
|
|
|
|
rb_swapped = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
HRESULT hr;
|
2009-02-09 21:15:56 +00:00
|
|
|
|
2016-02-19 18:05:39 +00:00
|
|
|
hr = m_dev->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &surface, nullptr);
|
|
|
|
if (FAILED(hr))
|
|
|
|
{
|
2009-02-09 21:15:56 +00:00
|
|
|
return false;
|
2016-02-19 18:05:39 +00:00
|
|
|
}
|
2009-02-09 21:15:56 +00:00
|
|
|
|
2016-02-19 18:05:39 +00:00
|
|
|
hr = m_dev->GetRenderTargetData(m_surface, surface);
|
|
|
|
if (FAILED(hr))
|
2009-02-09 21:15:56 +00:00
|
|
|
{
|
2016-02-19 18:05:39 +00:00
|
|
|
return false;
|
2009-02-09 21:15:56 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-02-19 18:05:39 +00:00
|
|
|
GSPng::Format format;
|
|
|
|
switch (desc.Format)
|
2009-02-09 21:15:56 +00:00
|
|
|
{
|
2016-02-19 18:05:39 +00:00
|
|
|
case D3DFMT_A8:
|
|
|
|
format = GSPng::R8I_PNG;
|
|
|
|
break;
|
|
|
|
case D3DFMT_A8R8G8B8:
|
|
|
|
format = dds? GSPng::RGBA_PNG : GSPng::RGB_PNG;
|
|
|
|
break;
|
|
|
|
case D3DFMT_D32F_LOCKABLE:
|
|
|
|
format = GSPng::RGB_A_PNG;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
fprintf(stderr, "D3DFMT %d not saved to image\n", desc.Format);
|
|
|
|
return false;
|
2009-02-09 21:15:56 +00:00
|
|
|
}
|
2016-02-19 18:05:39 +00:00
|
|
|
|
|
|
|
D3DLOCKED_RECT slr;
|
|
|
|
HRESULT hr = surface->LockRect(&slr, nullptr, 0);
|
|
|
|
if (FAILED(hr))
|
2009-02-09 21:15:56 +00:00
|
|
|
{
|
2016-02-19 18:05:39 +00:00
|
|
|
return false;
|
2009-02-09 21:15:56 +00:00
|
|
|
}
|
2016-02-19 18:05:39 +00:00
|
|
|
|
2016-05-24 19:52:06 +00:00
|
|
|
int compression = user_image ? Z_BEST_COMPRESSION : theApp.GetConfigI("png_compression_level");
|
2016-02-24 21:52:17 +00:00
|
|
|
bool success = GSPng::Save(format, fn, static_cast<uint8*>(slr.pBits), desc.Width, desc.Height, slr.Pitch, compression, rb_swapped);
|
2016-02-19 18:05:39 +00:00
|
|
|
|
|
|
|
surface->UnlockRect();
|
|
|
|
return success;
|
2009-02-09 21:15:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
GSTexture9::operator IDirect3DSurface9*()
|
|
|
|
{
|
|
|
|
return m_surface;
|
|
|
|
}
|
|
|
|
|
|
|
|
GSTexture9::operator IDirect3DTexture9*()
|
|
|
|
{
|
|
|
|
return m_texture;
|
|
|
|
}
|