Implement surface locking

This commit is contained in:
Dmitry Marakasov 2014-12-27 18:59:10 +03:00
parent 7b9f951eff
commit 607e9e09d0
4 changed files with 193 additions and 0 deletions

View File

@ -99,6 +99,7 @@ SET(LIBRARY_SOURCES
SDL2pp/Renderer.cc
SDL2pp/SDL.cc
SDL2pp/Surface.cc
SDL2pp/SurfaceLock.cc
SDL2pp/Texture.cc
SDL2pp/TextureLock.cc
SDL2pp/Wav.cc

View File

@ -59,4 +59,8 @@ SDL_Surface* Surface::Get() const {
return surface_;
}
Surface::LockHandle Surface::Lock() {
return LockHandle(this);
}
}

View File

@ -25,6 +25,7 @@
#include <SDL2/SDL_stdinc.h>
struct SDL_Surface;
struct SDL_PixelFormat;
namespace SDL2pp {
@ -43,6 +44,102 @@ class Surface {
private:
SDL_Surface* surface_; ///< Contained SDL_Texture structure
public:
////////////////////////////////////////////////////////////
/// \brief SDL2pp::Surface lock
/// \ingroup rendering
///
/// \details
/// For direct pixel access, SDL surface may need to be locked.
/// This class represents the lock and controls its lifetime
/// as the lock is released as soon as LockHandle is destroyed.
///
////////////////////////////////////////////////////////////
class LockHandle {
friend class Surface;
private:
Surface* surface_; ///< SDL2pp::Surface this lock belongs to
private:
////////////////////////////////////////////////////////////
/// \brief Create lock for specific SDL2pp::Texture
///
/// \throws STL2pp::Exception
///
/// \see http://wiki.libsdl.org/SDL_LockSurface
///
////////////////////////////////////////////////////////////
LockHandle(Surface* surface);
public:
////////////////////////////////////////////////////////////
/// \brief Create no-op lock
///
/// \details
/// This may be initialized with real lock later with move
/// assignment operator
///
////////////////////////////////////////////////////////////
LockHandle();
////////////////////////////////////////////////////////////
/// \brief Destructor
///
/// \details
/// Releases the lock
///
/// \see http://wiki.libsdl.org/SDL_UnlockSurface
///
////////////////////////////////////////////////////////////
~LockHandle();
////////////////////////////////////////////////////////////
/// \brief Move constructor
///
/// \param other SDL2pp::Surface::LockHandle to move data from
///
////////////////////////////////////////////////////////////
LockHandle(LockHandle&& other) noexcept;
////////////////////////////////////////////////////////////
/// \brief Move assignment operator
///
/// \param other SDL2pp::Surface::LockHandle to move data from
///
/// \returns Reference to self
///
////////////////////////////////////////////////////////////
LockHandle& operator=(LockHandle&& other) noexcept;
// Deleted copy constructor and assignment
LockHandle(const LockHandle& other) = delete;
LockHandle& operator=(const LockHandle& other) = delete;
////////////////////////////////////////////////////////////
/// \brief Get pointer to raw pixel data of locked region
///
/// \returns Pointer to raw pixel data of locked region
///
////////////////////////////////////////////////////////////
void* GetPixels() const;
////////////////////////////////////////////////////////////
/// \brief Get pitch of locked pixel data
///
/// \returns Number of bytes in a row of pixel data, including
/// padding between lines
///
////////////////////////////////////////////////////////////
int GetPitch() const;
////////////////////////////////////////////////////////////
/// \brief Get pixel format of the surface
///
/// \returns Format of the pixels stored in the surface
///
////////////////////////////////////////////////////////////
const SDL_PixelFormat& GetFormat() const;
};
public:
////////////////////////////////////////////////////////////
/// \brief Create RGB surface
@ -120,6 +217,18 @@ public:
///
////////////////////////////////////////////////////////////
SDL_Surface* Get() const;
////////////////////////////////////////////////////////////
/// \brief Lock surface for direct pixel access
///
/// \return Lock handle used to access pixel data and to control lock lifetime
///
/// \throws SDL2pp::Exception
///
/// \see http://wiki.libsdl.org/SDL_LockSurface
///
////////////////////////////////////////////////////////////
LockHandle Lock();
};
}

79
SDL2pp/SurfaceLock.cc Normal file
View File

@ -0,0 +1,79 @@
/*
libSDL2pp - C++11 bindings/wrapper for SDL2
Copyright (C) 2014 Dmitry Marakasov <amdmi3@amdmi3.ru>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include <SDL2/SDL_surface.h>
#include <SDL2pp/Exception.hh>
#include <SDL2pp/Surface.hh>
namespace SDL2pp {
Surface::LockHandle::LockHandle() : surface_(nullptr) {
}
Surface::LockHandle::LockHandle(Surface* surface) : surface_(surface) {
if (SDL_MUSTLOCK(surface_->Get())) {
if (SDL_LockSurface(surface_->Get()))
throw Exception("SDL_LockSurface failed");
}
}
Surface::LockHandle::LockHandle(Surface::LockHandle&& other) noexcept : surface_(other.surface_) {
other.surface_ = nullptr;
}
Surface::LockHandle& Surface::LockHandle::operator=(Surface::LockHandle&& other) noexcept {
if (&other == this)
return *this;
if (surface_ != nullptr) {
if (SDL_MUSTLOCK(surface_->Get()))
SDL_UnlockSurface(surface_->Get());
}
surface_ = other.surface_;
other.surface_ = nullptr;
return *this;
}
Surface::LockHandle::~LockHandle() {
if (surface_ != nullptr) {
if (SDL_MUSTLOCK(surface_->Get()))
SDL_UnlockSurface(surface_->Get());
}
}
void* Surface::LockHandle::GetPixels() const {
return surface_->Get()->pixels;
}
int Surface::LockHandle::GetPitch() const {
return surface_->Get()->pitch;
}
const SDL_PixelFormat& Surface::LockHandle::GetFormat() const {
return *surface_->Get()->format;
}
}