You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
215 lines
6.3 KiB
215 lines
6.3 KiB
/* SdlWindow.cpp |
|
* |
|
* Implements a SDL2 rendering window. |
|
*/ |
|
|
|
#include <sstream> |
|
|
|
#include "Video/PlipVideoException.h" |
|
|
|
#include "SdlWindow.h" |
|
|
|
namespace PlipSdl { |
|
SdlWindow::SdlWindow(int scale, const std::string &title) { |
|
std::stringstream error; |
|
|
|
m_scale = scale; |
|
|
|
SDL_InitSubSystem(SDL_INIT_VIDEO); |
|
|
|
// Try to create a window. |
|
m_window = SDL_CreateWindow(title.c_str(), |
|
SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, |
|
m_width * m_scale, m_height * m_scale, 0); |
|
|
|
if(m_window == nullptr) { |
|
error << "Unable to create SDL window: " << SDL_GetError(); |
|
throw Plip::PlipVideoException(error.str().c_str()); |
|
} |
|
|
|
// Try to create a renderer. |
|
m_renderer = SDL_CreateRenderer(m_window, -1, 0); |
|
|
|
if(m_renderer == nullptr) { |
|
error << "Unable to create SDL renderer: " << SDL_GetError(); |
|
throw Plip::PlipVideoException(error.str().c_str()); |
|
} |
|
|
|
SDL_RendererInfo rendererInfo; |
|
if(SDL_GetRendererInfo(m_renderer, &rendererInfo)) { |
|
error << "Unable to retrieve SDL renderer info: " << SDL_GetError(); |
|
throw Plip::PlipVideoException(error.str().c_str()); |
|
} |
|
|
|
auto found = false; |
|
for(auto i = 0; i < rendererInfo.num_texture_formats; i++) { |
|
if(SelectFormat(rendererInfo.texture_formats[i])) { |
|
found = true; |
|
break; |
|
} |
|
} |
|
|
|
if(!found) { |
|
error << "No supported texture formats!"; |
|
throw Plip::PlipVideoException(error.str().c_str()); |
|
} |
|
|
|
// Try to create a small starting texture. This will be removed and |
|
// recreated later, but we want to ensure that we can make one in the |
|
// first place. |
|
CreateTexture(); |
|
} |
|
|
|
SdlWindow::~SdlWindow() { |
|
if(m_texture != nullptr) SDL_DestroyTexture(m_texture); |
|
if(m_renderer != nullptr) SDL_DestroyRenderer(m_renderer); |
|
if(m_window != nullptr) SDL_DestroyWindow(m_window); |
|
} |
|
|
|
bool SdlWindow::BeginDraw() { |
|
return SDL_LockTexture(m_texture, nullptr, &m_texData, &m_pitch) == 0; |
|
} |
|
|
|
void SdlWindow::Clear() { |
|
SDL_RenderClear(m_renderer); |
|
} |
|
|
|
void SdlWindow::CreateTexture() { |
|
if(m_texture != nullptr) SDL_DestroyTexture(m_texture); |
|
|
|
uint32_t pixelFormat = SelectSdlFormat(m_format); |
|
|
|
m_texture = nullptr; |
|
m_texture = SDL_CreateTexture(m_renderer, |
|
pixelFormat, SDL_TEXTUREACCESS_STREAMING, |
|
m_width, m_height); |
|
|
|
if(m_texture == nullptr) { |
|
std::stringstream error; |
|
error << "Unable to create SDL texture: " << SDL_GetError(); |
|
throw Plip::PlipVideoException(error.str().c_str()); |
|
} |
|
} |
|
|
|
void SdlWindow::Draw(void *data) { |
|
memcpy(m_texData, data, m_pitch * m_height); |
|
} |
|
|
|
bool SdlWindow::EndDraw() { |
|
SDL_UnlockTexture(m_texture); |
|
return true; |
|
} |
|
|
|
Plip::PlipVideoFormat SdlWindow::GetFormat() { |
|
return m_format; |
|
} |
|
|
|
int SdlWindow::GetHeight() { |
|
return m_height; |
|
} |
|
|
|
int SdlWindow::GetWidth() { |
|
return m_width; |
|
} |
|
|
|
void SdlWindow::Render() { |
|
SDL_RenderCopy(m_renderer, m_texture, nullptr, nullptr); |
|
SDL_RenderPresent(m_renderer); |
|
} |
|
|
|
void SdlWindow::Resize(int width, int height) { |
|
m_width = width; |
|
m_height = height; |
|
|
|
// Resize the window. |
|
SDL_SetWindowSize(m_window, m_width * m_scale, m_height * m_scale); |
|
|
|
// Destroy and recreate the texture. |
|
CreateTexture(); |
|
} |
|
|
|
bool SdlWindow::SelectFormat(uint32_t format) { |
|
switch(format) { |
|
case SDL_PIXELFORMAT_RGB24: |
|
m_format = Plip::PlipVideoFormat::RGB888; |
|
return true; |
|
|
|
case SDL_PIXELFORMAT_BGR24: |
|
m_format = Plip::PlipVideoFormat::BGR888; |
|
return true; |
|
|
|
case SDL_PIXELFORMAT_RGB888: |
|
m_format = Plip::PlipVideoFormat::XRGB8888; |
|
return true; |
|
|
|
case SDL_PIXELFORMAT_BGR888: |
|
m_format = Plip::PlipVideoFormat::XBGR8888; |
|
return true; |
|
|
|
case SDL_PIXELFORMAT_ARGB8888: |
|
m_format = Plip::PlipVideoFormat::ARGB8888; |
|
return true; |
|
|
|
case SDL_PIXELFORMAT_ABGR8888: |
|
m_format = Plip::PlipVideoFormat::ABGR8888; |
|
return true; |
|
|
|
case SDL_PIXELFORMAT_RGBX8888: |
|
m_format = Plip::PlipVideoFormat::RGBX8888; |
|
return true; |
|
|
|
case SDL_PIXELFORMAT_BGRX8888: |
|
m_format = Plip::PlipVideoFormat::BGRX8888; |
|
return true; |
|
|
|
case SDL_PIXELFORMAT_RGBA8888: |
|
m_format = Plip::PlipVideoFormat::RGBA8888; |
|
return true; |
|
|
|
case SDL_PIXELFORMAT_BGRA8888: |
|
m_format = Plip::PlipVideoFormat::BGRA8888; |
|
return true; |
|
|
|
default: |
|
return false; |
|
} |
|
} |
|
|
|
uint32_t SdlWindow::SelectSdlFormat(Plip::PlipVideoFormat format) { |
|
switch(format) { |
|
case Plip::PlipVideoFormat::RGB888: |
|
return SDL_PIXELFORMAT_RGB24; |
|
|
|
case Plip::PlipVideoFormat::BGR888: |
|
return SDL_PIXELFORMAT_BGR24; |
|
|
|
case Plip::PlipVideoFormat::XRGB8888: |
|
case Plip::PlipVideoFormat::ARGB8888: |
|
return SDL_PIXELFORMAT_ARGB8888; |
|
|
|
case Plip::PlipVideoFormat::XBGR8888: |
|
case Plip::PlipVideoFormat::ABGR8888: |
|
return SDL_PIXELFORMAT_ABGR8888; |
|
|
|
case Plip::PlipVideoFormat::RGBX8888: |
|
case Plip::PlipVideoFormat::RGBA8888: |
|
return SDL_PIXELFORMAT_RGBA8888; |
|
|
|
case Plip::PlipVideoFormat::BGRX8888: |
|
case Plip::PlipVideoFormat::BGRA8888: |
|
return SDL_PIXELFORMAT_BGRA8888; |
|
|
|
default: |
|
throw Plip::PlipVideoException("Unsupported pixel format."); |
|
} |
|
} |
|
|
|
void SdlWindow::SetScale(int scale) { |
|
m_scale = scale; |
|
SDL_SetWindowSize(m_window, m_width * m_scale, m_height * m_scale); |
|
} |
|
|
|
void SdlWindow::SetTitle(std::string title) { |
|
SDL_SetWindowTitle(m_window, title.c_str()); |
|
} |
|
}
|
|
|