Remade RenderWindow::CopyToImage

Former-commit-id: a903cc8ea67d13ff7cf231d075235c3c17593a60
This commit is contained in:
Lynix 2015-03-18 22:24:07 +01:00
parent cbf3b2cf4e
commit 5ecddb20c6
2 changed files with 41 additions and 55 deletions

View File

@ -11,13 +11,16 @@
#include <Nazara/Prerequesites.hpp> #include <Nazara/Prerequesites.hpp>
#include <Nazara/Core/Clock.hpp> #include <Nazara/Core/Clock.hpp>
#include <Nazara/Math/Rect.hpp>
#include <Nazara/Math/Vector3.hpp>
#include <Nazara/Renderer/Config.hpp> #include <Nazara/Renderer/Config.hpp>
#include <Nazara/Renderer/ContextParameters.hpp> #include <Nazara/Renderer/ContextParameters.hpp>
#include <Nazara/Renderer/RenderTarget.hpp> #include <Nazara/Renderer/RenderTarget.hpp>
#include <Nazara/Utility/Window.hpp> #include <Nazara/Utility/Window.hpp>
#include <vector>
class NzAbstractImage;
class NzContext; class NzContext;
class NzImage;
class NzTexture; class NzTexture;
struct NzContextParameters; struct NzContextParameters;
@ -29,8 +32,8 @@ class NAZARA_API NzRenderWindow : public NzRenderTarget, public NzWindow
NzRenderWindow(NzWindowHandle handle, const NzContextParameters& parameters = NzContextParameters()); NzRenderWindow(NzWindowHandle handle, const NzContextParameters& parameters = NzContextParameters());
virtual ~NzRenderWindow(); virtual ~NzRenderWindow();
bool CopyToImage(NzImage* image) const; bool CopyToImage(NzAbstractImage* image, const NzVector3ui& dstPos = NzVector3ui(0U)) const;
bool CopyToTexture(NzTexture* texture) const; bool CopyToImage(NzAbstractImage* image, const NzRectui& rect, const NzVector3ui& dstPos = NzVector3ui(0U)) const;
bool Create(NzVideoMode mode, const NzString& title, nzUInt32 style = nzWindowStyle_Default, const NzContextParameters& parameters = NzContextParameters()); bool Create(NzVideoMode mode, const NzString& title, nzUInt32 style = nzWindowStyle_Default, const NzContextParameters& parameters = NzContextParameters());
bool Create(NzWindowHandle handle, const NzContextParameters& parameters = NzContextParameters()); bool Create(NzWindowHandle handle, const NzContextParameters& parameters = NzContextParameters());
@ -61,6 +64,7 @@ class NAZARA_API NzRenderWindow : public NzRenderTarget, public NzWindow
void OnWindowDestroy() override; void OnWindowDestroy() override;
void OnWindowResized() override; void OnWindowResized() override;
mutable std::vector<nzUInt8> m_buffer;
NzClock m_clock; NzClock m_clock;
NzContextParameters m_parameters; NzContextParameters m_parameters;
mutable NzContext* m_context = nullptr; mutable NzContext* m_context = nullptr;

View File

@ -13,8 +13,6 @@
#include <stdexcept> #include <stdexcept>
#include <Nazara/Renderer/Debug.hpp> #include <Nazara/Renderer/Debug.hpp>
///TODO: Améliorer les méthode CopyTo*
NzRenderWindow::NzRenderWindow(NzVideoMode mode, const NzString& title, nzUInt32 style, const NzContextParameters& parameters) NzRenderWindow::NzRenderWindow(NzVideoMode mode, const NzString& title, nzUInt32 style, const NzContextParameters& parameters)
{ {
NzErrorFlags flags(nzErrorFlag_ThrowException, true); NzErrorFlags flags(nzErrorFlag_ThrowException, true);
@ -33,7 +31,7 @@ NzRenderWindow::~NzRenderWindow()
OnWindowDestroy(); OnWindowDestroy();
} }
bool NzRenderWindow::CopyToImage(NzImage* image) const bool NzRenderWindow::CopyToImage(NzAbstractImage* image, const NzVector3ui& dstPos) const
{ {
#if NAZARA_RENDERER_SAFE #if NAZARA_RENDERER_SAFE
if (!m_context) if (!m_context)
@ -41,63 +39,47 @@ bool NzRenderWindow::CopyToImage(NzImage* image) const
NazaraError("Window has not been created"); NazaraError("Window has not been created");
return false; return false;
} }
#endif
return CopyToImage(image, NzRectui(NzVector2ui(0U), GetSize()));
}
bool NzRenderWindow::CopyToImage(NzAbstractImage* image, const NzRectui& rect, const NzVector3ui& dstPos) const
{
#if NAZARA_RENDERER_SAFE
if (!m_context)
{
NazaraError("Window has not been created");
return false;
}
#endif
NzVector2ui windowSize = GetSize();
#if NAZARA_RENDERER_SAFE
if (!image) if (!image)
{ {
NazaraError("Image must be valid"); NazaraError("Image must be valid");
return false; return false;
} }
#endif
const NzContext* currentContext = NzContext::GetCurrent(); if (image->GetFormat() != nzPixelFormat_RGBA8)
if (m_context != currentContext)
{ {
if (!m_context->SetActive(true)) // Pour plus de facilité, évidemment on peut faire sauter cette règle avec un peu de gestion
{ NazaraError("Image must be RGBA8-formatted");
NazaraError("Failed to activate context");
return false;
}
}
NzVector2ui size = GetSize();
if (!image->Create(nzImageType_2D, nzPixelFormat_RGBA8, size.x, size.y, 1, 1))
{
NazaraError("Failed to create image");
return false; return false;
} }
nzUInt8* pixels = image->GetPixels(); if (rect.x + rect.width > windowSize.x || rect.y + rect.height > windowSize.y)
glReadPixels(0, 0, size.x, size.y, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
image->FlipVertically();
if (m_context != currentContext)
{ {
if (currentContext) NazaraError("Rectangle dimensions are out of window's bounds");
{
if (!currentContext->SetActive(true))
NazaraWarning("Failed to reset current context");
}
else
m_context->SetActive(false);
}
return true;
}
bool NzRenderWindow::CopyToTexture(NzTexture* texture) const
{
#if NAZARA_RENDERER_SAFE
if (!m_context)
{
NazaraError("Window has not been created");
return false; return false;
} }
if (!texture) NzVector3ui imageSize = image->GetSize();
if (dstPos.x + rect.width > imageSize.x || dstPos.y + rect.height > imageSize.y || dstPos.z > imageSize.z)
{ {
NazaraError("Texture must be valid"); NazaraError("Cube dimensions are out of image's bounds");
return false; return false;
} }
#endif #endif
@ -112,22 +94,21 @@ bool NzRenderWindow::CopyToTexture(NzTexture* texture) const
} }
} }
NzVector2ui size = GetSize(); ///TODO: Fast-path pour les images en cas de copie du buffer entier
if (!texture->Create(nzImageType_2D, nzPixelFormat_RGBA8, size.x, size.y, 1, 1)) m_buffer.resize(rect.width*rect.height*4);
{ glReadPixels(rect.x, windowSize.y - rect.height - rect.y, rect.width, rect.height, GL_RGBA, GL_UNSIGNED_BYTE, m_buffer.data());
NazaraError("Failed to create texture");
return false;
}
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, size.x, size.y); // Les pixels sont retournés, nous devons envoyer les pixels par rangée
for (unsigned int i = 0; i < rect.height; ++i)
image->Update(&m_buffer[rect.width*4*i], NzBoxui(dstPos.x, rect.height - i - 1, dstPos.z, rect.width, 1, 1), rect.width);
if (m_context != currentContext) if (m_context != currentContext)
{ {
if (currentContext) if (currentContext)
{ {
if (!currentContext->SetActive(true)) if (!currentContext->SetActive(true))
NazaraWarning("Failed to reset current context"); NazaraWarning("Failed to reset old context");
} }
else else
m_context->SetActive(false); m_context->SetActive(false);
@ -136,6 +117,7 @@ bool NzRenderWindow::CopyToTexture(NzTexture* texture) const
return true; return true;
} }
bool NzRenderWindow::Create(NzVideoMode mode, const NzString& title, nzUInt32 style, const NzContextParameters& parameters) bool NzRenderWindow::Create(NzVideoMode mode, const NzString& title, nzUInt32 style, const NzContextParameters& parameters)
{ {
m_parameters = parameters; m_parameters = parameters;