123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- #ifndef SDLSURFACEPTR_HH
- #define SDLSURFACEPTR_HH
- #include "MemBuffer.hh"
- #include "InitException.hh"
- #include <SDL.h>
- #include <algorithm>
- #include <memory>
- #include <new>
- #include <cassert>
- #include <cstdlib>
- /** Wrapper around a SDL_Surface.
- *
- * Makes sure SDL_FreeSurface() is called when this object goes out of scope.
- * It's modeled after std::unique_ptr, so it has the usual get(), reset() and
- * release() methods. Like unique_ptr it can be moved but not copied.
- *
- * In addition to the SDL_Surface pointer, this wrapper also (optionally)
- * manages an extra memory buffer. Normally SDL_CreateRGBSurface() will
- * allocate/free an internal memory buffer for the surface. On construction
- * of the surface this buffer will be zero-initialized. Though in many cases
- * the surface will immediately be overwritten (so zero-initialization is
- * only extra overhead). It's possible to avoid this by creating the surface
- * using SDL_CreateRGBSurfaceFrom(). Though the downside of this is that you
- * have to manage the lifetime of the memory buffer yourself. And that's
- * exactly what this wrapper can do.
- *
- * As a bonus this wrapper has a getLinePtr() method to hide some of the
- * casting. But apart from this it doesn't try to abstract any SDL
- * functionality.
- */
- class SDLSurfacePtr
- {
- public:
- SDLSurfacePtr(const SDLSurfacePtr&) = delete;
- SDLSurfacePtr& operator=(const SDLSurfacePtr&) = delete;
- /** Create a (software) surface with uninitialized pixel content.
- * throws: bad_alloc (no need to check for nullptr). */
- SDLSurfacePtr(unsigned width, unsigned height, unsigned depth,
- Uint32 rMask, Uint32 gMask, Uint32 bMask, Uint32 aMask)
- {
- assert((depth % 8) == 0);
- unsigned pitch = width * (depth >> 3);
- unsigned size = height * pitch;
- buffer.resize(size);
- surface = SDL_CreateRGBSurfaceFrom(
- buffer.data(), width, height, depth, pitch,
- rMask, gMask, bMask, aMask);
- if (!surface) throw std::bad_alloc();
- }
- explicit SDLSurfacePtr(SDL_Surface* surface_ = nullptr)
- : surface(surface_)
- {
- }
- SDLSurfacePtr(SDLSurfacePtr&& other) noexcept
- : surface(other.surface)
- , buffer(std::move(other.buffer))
- {
- other.surface = nullptr;
- }
- ~SDLSurfacePtr()
- {
- if (surface) SDL_FreeSurface(surface);
- }
- void reset(SDL_Surface* surface_ = nullptr)
- {
- SDLSurfacePtr temp(surface_);
- temp.swap(*this);
- }
- SDL_Surface* get()
- {
- return surface;
- }
- const SDL_Surface* get() const
- {
- return surface;
- }
- void swap(SDLSurfacePtr& other) noexcept
- {
- std::swap(surface, other.surface);
- std::swap(buffer, other.buffer );
- }
- SDLSurfacePtr& operator=(SDLSurfacePtr&& other) noexcept
- {
- std::swap(surface, other.surface);
- std::swap(buffer, other.buffer);
- return *this;
- }
- SDL_Surface& operator*()
- {
- return *surface;
- }
- const SDL_Surface& operator*() const
- {
- return *surface;
- }
- SDL_Surface* operator->()
- {
- return surface;
- }
- const SDL_Surface* operator->() const
- {
- return surface;
- }
- explicit operator bool() const
- {
- return get() != nullptr;
- }
- void* getLinePtr(unsigned y)
- {
- assert(y < unsigned(surface->h));
- return static_cast<Uint8*>(surface->pixels) + y * surface->pitch;
- }
- const void* getLinePtr(unsigned y) const
- {
- return const_cast<SDLSurfacePtr*>(this)->getLinePtr(y);
- }
- private:
- SDL_Surface* surface;
- openmsx::MemBuffer<char> buffer;
- };
- struct SDLDestroyTexture {
- void operator()(SDL_Texture* t) { SDL_DestroyTexture(t); }
- };
- using SDLTexturePtr = std::unique_ptr<SDL_Texture, SDLDestroyTexture>;
- struct SDLDestroyRenderer {
- void operator()(SDL_Renderer* r) { SDL_DestroyRenderer(r); }
- };
- using SDLRendererPtr = std::unique_ptr<SDL_Renderer, SDLDestroyRenderer>;
- struct SDLDestroyWindow {
- void operator()(SDL_Window* w) { SDL_DestroyWindow(w); }
- };
- using SDLWindowPtr = std::unique_ptr<SDL_Window, SDLDestroyWindow>;
- struct SDLFreeFormat {
- void operator()(SDL_PixelFormat* p) { SDL_FreeFormat(p); }
- };
- using SDLAllocFormatPtr = std::unique_ptr<SDL_PixelFormat, SDLFreeFormat>;
- struct SDLFreeWav {
- void operator()(Uint8* w) { SDL_FreeWAV(w); }
- };
- using SDLWavPtr = std::unique_ptr<Uint8, SDLFreeWav>;
- template<Uint32 FLAGS>
- class SDLSubSystemInitializer
- {
- public:
- SDLSubSystemInitializer(const SDLSubSystemInitializer&) = delete;
- SDLSubSystemInitializer& operator=(const SDLSubSystemInitializer&) = delete;
- SDLSubSystemInitializer() {
- // SDL internally ref-counts sub-system initialization, so we
- // don't need to worry about it here.
- if (SDL_InitSubSystem(FLAGS) < 0) {
- throw openmsx::InitException(
- "SDL init failed (", FLAGS, "): ", SDL_GetError());
- }
- }
- ~SDLSubSystemInitializer() {
- SDL_QuitSubSystem(FLAGS);
- }
- };
- #endif
|