1 #include "ge211_render.h" 2 #include "ge211_error.h" 3 #include "ge211_util.h" 9 static inline SDL_RendererFlip&
10 operator|=(SDL_RendererFlip& f1, SDL_RendererFlip f2)
12 return f1 = SDL_RendererFlip(f1 | f2);
19 static const uint32_t renderer_flags_to_try[] = {
20 SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC,
21 SDL_RENDERER_SOFTWARE | SDL_RENDERER_PRESENTVSYNC,
22 SDL_RENDERER_ACCELERATED,
23 SDL_RENDERER_SOFTWARE,
27 SDL_Renderer* Renderer::create_renderer_(SDL_Window* window)
31 #if SDL_VIDEO_RENDER_METAL 32 SDL_SetHint(SDL_HINT_RENDER_DRIVER,
"metal");
35 for (
auto flags : renderer_flags_to_try) {
36 result = SDL_CreateRenderer(window, -1, flags);
38 SDL_SetRenderDrawBlendMode(result, SDL_BLENDMODE_BLEND);
43 <<
"Could not initialize preferred renderer (" 44 << flags <<
"); trying next.";
47 throw Host_error{
"Could not initialize renderer"};
50 Renderer::Renderer(
const Window& window)
51 : ptr_{create_renderer_(window.get_raw_()),
55 bool Renderer::is_vsync() const noexcept
57 SDL_RendererInfo info;
58 SDL_GetRendererInfo(get_raw_(), &info);
59 return (info.flags & SDL_RENDERER_PRESENTVSYNC) != 0;
62 void Renderer::clear()
64 if (SDL_RenderClear(get_raw_()))
65 throw Host_error{
"Could not clear window"};
68 SDL_Renderer* Renderer::get_raw_() const noexcept
73 void Renderer::set_color(Color color)
75 if (SDL_SetRenderDrawColor(
77 color.red(), color.green(), color.blue(), color.alpha()))
78 throw Host_error{
"Could not set renderer color"};
81 void Renderer::present() noexcept
83 SDL_RenderPresent(get_raw_());
86 void Renderer::copy(
const Texture& texture, Position xy)
88 auto raw_texture = texture.get_raw_(*
this);
89 if (!raw_texture)
return;
93 int render_result = SDL_RenderCopy(get_raw_(), raw_texture,
95 if (render_result < 0) {
96 warn_sdl() <<
"Could not render texture";
100 void Renderer::copy(
const Texture& texture,
102 const Transform& transform)
104 auto raw_texture = texture.get_raw_(*
this);
105 if (!raw_texture)
return;
108 dstrect.w = int(dstrect.w * transform.get_scale_x());
109 dstrect.h = int(dstrect.h * transform.get_scale_y());
111 SDL_RendererFlip flip = SDL_FLIP_NONE;
112 if (transform.get_flip_h()) flip |= SDL_FLIP_HORIZONTAL;
113 if (transform.get_flip_v()) flip |= SDL_FLIP_VERTICAL;
115 int render_result = SDL_RenderCopyEx(get_raw_(), raw_texture,
117 transform.get_rotation(),
120 if (render_result < 0) {
121 warn_sdl() <<
"Could not render texture";
125 void Renderer::prepare(
const Texture& texture)
const 127 texture.get_raw_(*
this);
130 Texture::Impl_::Impl_(SDL_Surface* surface) noexcept
131 : Impl_{{surface, &SDL_FreeSurface}}
134 Texture::Impl_::Impl_(SDL_Texture* texture) noexcept
135 : Impl_{{texture, &SDL_DestroyTexture}}
138 Texture::Impl_::Impl_(delete_ptr<SDL_Surface> surface) noexcept
139 : surface_{std::move(surface)},
140 texture_{
nullptr, &no_op_deleter}
143 Texture::Impl_::Impl_(delete_ptr<SDL_Texture> texture) noexcept
144 : surface_{
nullptr, &no_op_deleter},
145 texture_{std::move(texture)}
148 Texture::Texture() noexcept
152 Texture::Texture(SDL_Surface* surface)
153 : impl_{std::make_shared<Impl_>(surface)}
156 Texture::Texture(delete_ptr<SDL_Surface> surface)
157 : impl_{std::make_shared<Impl_>(std::move(surface))}
160 SDL_Texture* Texture::get_raw_(
const Renderer& renderer)
const 162 if (impl_->texture_)
return impl_->texture_.get();
164 if (!impl_->surface_)
return nullptr;
166 SDL_Texture* raw = SDL_CreateTextureFromSurface(renderer.get_raw_(),
167 impl_->surface_.get());
173 throw Host_error{
"Could not create texture from surface"};
176 Dimensions Texture::dimensions() const noexcept
180 if (impl_->texture_) {
181 SDL_QueryTexture(impl_->texture_.get(),
nullptr,
nullptr,
182 &result.width, &result.height);
183 }
else if (impl_->surface_) {
184 result.width = impl_->surface_->w;
185 result.height = impl_->surface_->h;
191 SDL_Surface* Texture::as_surface() noexcept
193 return impl_->surface_.get();
196 bool Texture::empty() const noexcept
198 return impl_ ==
nullptr;
static Basic_rectangle from_top_left(Position tl, Dimensions dims) noexcept(has_nothrow_arithmetic< Coordinate >())
Creates a Basic_rectangle given the position of its top left vertex and its dimensions.
The game engine namespace.
Basic_dimensions< int > Dimensions
Type alias for the most common use of Basic_dimensions, which is with a coordinate type of int...