Refactor Bitmap SDL components to RAII

This commit is contained in:
Justin Scofield
2022-07-24 00:00:32 -04:00
parent fd73cc1bde
commit 54d4a340f7
2 changed files with 75 additions and 42 deletions

View File

@@ -11,47 +11,50 @@ namespace yaze {
namespace app { namespace app {
namespace gfx { namespace gfx {
namespace {
void GrayscalePalette(SDL_Palette *palette) {
for (int i = 0; i < 8; i++) {
palette->colors[i].r = i * 31;
palette->colors[i].g = i * 31;
palette->colors[i].b = i * 31;
}
}
} // namespace
Bitmap::Bitmap(int width, int height, int depth, uchar *data) Bitmap::Bitmap(int width, int height, int depth, uchar *data)
: width_(width), height_(height), depth_(depth), pixel_data_(data) { : width_(width), height_(height), depth_(depth), pixel_data_(data) {
surface_ = SDL_CreateRGBSurfaceWithFormat(0, width, height, depth, surface_ = std::unique_ptr<SDL_Surface, sdl_deleter>(
SDL_PIXELFORMAT_INDEX8); SDL_CreateRGBSurfaceWithFormat(0, width, height, depth,
// Default grayscale palette SDL_PIXELFORMAT_INDEX8),
for (int i = 0; i < 8; i++) { sdl_deleter());
surface_->format->palette->colors[i].r = i * 31; GrayscalePalette(surface_->format->palette);
surface_->format->palette->colors[i].g = i * 31;
surface_->format->palette->colors[i].b = i * 31;
}
surface_->pixels = data; surface_->pixels = data;
} }
Bitmap::Bitmap(int width, int height, int depth, int data_size) Bitmap::Bitmap(int width, int height, int depth, int data_size)
: width_(width), height_(height), depth_(depth), data_size_(data_size) { : width_(width), height_(height), depth_(depth), data_size_(data_size) {
surface_ = SDL_CreateRGBSurfaceWithFormat(0, width, height, depth, surface_ = std::unique_ptr<SDL_Surface, sdl_deleter>(
SDL_PIXELFORMAT_INDEX8); SDL_CreateRGBSurfaceWithFormat(0, width, height, depth,
// Default grayscale palette SDL_PIXELFORMAT_INDEX8),
for (int i = 0; i < 8; i++) { sdl_deleter());
surface_->format->palette->colors[i].r = i * 31; GrayscalePalette(surface_->format->palette);
surface_->format->palette->colors[i].g = i * 31;
surface_->format->palette->colors[i].b = i * 31;
}
pixel_data_ = (uchar *)SDL_malloc(data_size); pixel_data_ = (uchar *)SDL_malloc(data_size);
surface_->pixels = pixel_data_; surface_->pixels = pixel_data_;
} }
// Pass raw pixel data directly to the surface
// Be sure to know what the hell you're doing if you use this one.
void Bitmap::Create(int width, int height, int depth, uchar *data) { void Bitmap::Create(int width, int height, int depth, uchar *data) {
width_ = width; width_ = width;
height_ = height; height_ = height;
depth_ = depth; depth_ = depth;
pixel_data_ = data; pixel_data_ = data;
surface_ = SDL_CreateRGBSurfaceWithFormat(0, width, height, depth, surface_ = std::unique_ptr<SDL_Surface, sdl_deleter>(
SDL_PIXELFORMAT_INDEX8); SDL_CreateRGBSurfaceWithFormat(0, width, height, depth,
// Default grayscale palette SDL_PIXELFORMAT_INDEX8),
for (int i = 0; i < 8; i++) { sdl_deleter());
surface_->format->palette->colors[i].r = i * 31; GrayscalePalette(surface_->format->palette);
surface_->format->palette->colors[i].g = i * 31;
surface_->format->palette->colors[i].b = i * 31;
}
surface_->pixels = pixel_data_; surface_->pixels = pixel_data_;
} }
@@ -61,15 +64,11 @@ void Bitmap::Create(int width, int height, int depth, int size) {
height_ = height; height_ = height;
depth_ = depth; depth_ = depth;
data_size_ = size; data_size_ = size;
surface_ = SDL_CreateRGBSurfaceWithFormat(0, width, height, depth, surface_ = std::unique_ptr<SDL_Surface, sdl_deleter>(
SDL_PIXELFORMAT_INDEX8); SDL_CreateRGBSurfaceWithFormat(0, width, height, depth,
// Default grayscale palette SDL_PIXELFORMAT_INDEX8),
for (int i = 0; i < 8; i++) { sdl_deleter());
surface_->format->palette->colors[i].r = i * 31; GrayscalePalette(surface_->format->palette);
surface_->format->palette->colors[i].g = i * 31;
surface_->format->palette->colors[i].b = i * 31;
}
pixel_data_ = (uchar *)SDL_malloc(size); pixel_data_ = (uchar *)SDL_malloc(size);
surface_->pixels = pixel_data_; surface_->pixels = pixel_data_;
} }
@@ -80,14 +79,18 @@ void Bitmap::Create(int width, int height, int depth, uchar *data, int size,
height_ = height; height_ = height;
depth_ = depth; depth_ = depth;
pixel_data_ = data; pixel_data_ = data;
surface_ = SDL_CreateRGBSurfaceWithFormat(0, width, height, depth, surface_ = std::unique_ptr<SDL_Surface, sdl_deleter>(
SDL_PIXELFORMAT_INDEX8); SDL_CreateRGBSurfaceWithFormat(0, width, height, depth,
SDL_PIXELFORMAT_INDEX8),
sdl_deleter());
surface_->format->palette = palette.GetSDL_Palette(); surface_->format->palette = palette.GetSDL_Palette();
surface_->pixels = pixel_data_; surface_->pixels = pixel_data_;
} }
void Bitmap::CreateTexture(std::shared_ptr<SDL_Renderer> renderer) { void Bitmap::CreateTexture(std::shared_ptr<SDL_Renderer> renderer) {
texture_ = SDL_CreateTextureFromSurface(renderer.get(), surface_); texture_ = std::unique_ptr<SDL_Texture, sdl_deleter>(
SDL_CreateTextureFromSurface(renderer.get(), surface_.get()),
sdl_deleter());
} }
void Bitmap::ApplyPalette(const SNESPalette &palette) { palette_ = palette; } void Bitmap::ApplyPalette(const SNESPalette &palette) { palette_ = palette; }
@@ -100,7 +103,7 @@ absl::StatusOr<std::vector<Bitmap>> Bitmap::CreateTiles() {
bmp.Create(8, 8, 8, 32); bmp.Create(8, 8, 8, 32);
auto surface = bmp.GetSurface(); auto surface = bmp.GetSurface();
SDL_Rect src_rect = {i, j, 8, 8}; SDL_Rect src_rect = {i, j, 8, 8};
if (SDL_BlitSurface(surface_, &src_rect, surface, nullptr) != 0) { if (SDL_BlitSurface(surface_.get(), &src_rect, surface, nullptr) != 0) {
return absl::InvalidArgumentError( return absl::InvalidArgumentError(
"Failed to blit surface for Bitmap Tilesheet"); "Failed to blit surface for Bitmap Tilesheet");
} }
@@ -110,6 +113,30 @@ absl::StatusOr<std::vector<Bitmap>> Bitmap::CreateTiles() {
return tiles; return tiles;
} }
absl::Status Bitmap::CreateFromTiles(const std::vector<Bitmap> &tiles) {
if (tiles.empty()) {
return absl::InvalidArgumentError("Empty tiles");
}
SDL_Rect tile_rect = {0, 0, 8, 8};
SDL_Rect dest_rect = {0, 0, 8, 8};
for (const auto &tile : tiles) {
auto src = tile.GetSurface();
if (SDL_BlitSurface(src, &tile_rect, surface_.get(), &dest_rect) != 0) {
return absl::InvalidArgumentError(
"Failed to blit surface for Bitmap Tilesheet");
}
dest_rect.x++;
if (dest_rect.x == 15) {
dest_rect.x = 0;
dest_rect.y++;
}
}
return absl::OkStatus();
}
} // namespace gfx } // namespace gfx
} // namespace app } // namespace app
} // namespace yaze } // namespace yaze

View File

@@ -28,21 +28,27 @@ class Bitmap {
void ApplyPalette(const SNESPalette &palette); void ApplyPalette(const SNESPalette &palette);
absl::StatusOr<std::vector<Bitmap>> CreateTiles(); absl::StatusOr<std::vector<Bitmap>> CreateTiles();
absl::Status CreateFromTiles(const std::vector<Bitmap> &tiles);
int GetWidth() const { return width_; } int GetWidth() const { return width_; }
int GetHeight() const { return height_; } int GetHeight() const { return height_; }
auto GetData() const { return pixel_data_; } auto GetData() const { return pixel_data_; }
auto GetTexture() const { return texture_; } auto GetTexture() const { return texture_.get(); }
auto GetSurface() const { return surface_; } auto GetSurface() const { return surface_.get(); }
private: private:
struct sdl_deleter {
void operator()(SDL_Texture *p) const { SDL_DestroyTexture(p); }
void operator()(SDL_Surface *p) const { SDL_FreeSurface(p); }
};
int width_ = 0; int width_ = 0;
int height_ = 0; int height_ = 0;
int depth_ = 0; int depth_ = 0;
int data_size_ = 0; int data_size_ = 0;
uchar *pixel_data_; uchar *pixel_data_;
SDL_Surface *surface_; std::shared_ptr<SDL_Texture> texture_;
SDL_Texture *texture_; std::shared_ptr<SDL_Surface> surface_;
SNESPalette palette_; SNESPalette palette_;
}; };