diff --git a/src/backends/sdl2_renderer.cpp b/src/backends/sdl2_renderer.cpp index 272a46b..f56b579 100644 --- a/src/backends/sdl2_renderer.cpp +++ b/src/backends/sdl2_renderer.cpp @@ -77,7 +77,7 @@ namespace { void showDriverInUse(const Context &ctx) { ctx.mLogger(LogSeverity::Message, "Driver in use:"); SDL_RendererInfo info; - SDL_GetRendererInfo(ctx.mSDLContext.mRenderer, &info); + SDL_GetRendererInfo(ctx.mSDLContext->mRenderer, &info); printDriverInfo(info); } @@ -178,10 +178,16 @@ ret_code Renderer::releaseRenderer(Context &ctx) { delete ctx.mDefaultFont; ctx.mDefaultFont = nullptr; } - IMG_Quit(); - SDL_DestroyRenderer(ctx.mSDLContext.mRenderer); - ctx.mSDLContext.mRenderer = nullptr; + if (ctx.mSDLContext == nullptr) { + SDL_Quit(); + return ResultOk; + } + + if (ctx.mSDLContext->mRenderer != nullptr) { + SDL_DestroyRenderer(ctx.mSDLContext->mRenderer); + ctx.mSDLContext->mRenderer = nullptr; + } SDL_Quit(); return ResultOk; @@ -214,7 +220,7 @@ ret_code Renderer::drawText(Context &ctx, const char *string, Font *font, const return ErrorCode; } - SDL_Texture *messageTexture = SDL_CreateTextureFromSurface(ctx.mSDLContext.mRenderer, surfaceMessage); + SDL_Texture *messageTexture = SDL_CreateTextureFromSurface(ctx.mSDLContext->mRenderer, surfaceMessage); if (messageTexture == nullptr) { const std::string msg = "Cannot create texture: " + std::string(SDL_GetError()) + "."; ctx.mLogger(LogSeverity::Error, msg.c_str()); @@ -244,7 +250,7 @@ ret_code Renderer::drawText(Context &ctx, const char *string, Font *font, const break; } - SDL_RenderCopy(ctx.mSDLContext.mRenderer, messageTexture, NULL, &Message_rect); + SDL_RenderCopy(ctx.mSDLContext->mRenderer, messageTexture, nullptr, &Message_rect); SDL_FreeSurface(surfaceMessage); SDL_DestroyTexture(messageTexture); @@ -256,8 +262,8 @@ ret_code Renderer::initScreen(Context &ctx, int32_t x, int32_t y, int32_t w, int ctx.mLogger(LogSeverity::Error, "Not initialzed."); return ErrorCode; } - - if (ctx.mSDLContext.mWindow != nullptr ) { + ctx.mSDLContext = SDLContext::create(); + if (ctx.mSDLContext->mWindow != nullptr) { ctx.mLogger(LogSeverity::Error, "Already created."); return ErrorCode; } @@ -277,8 +283,8 @@ ret_code Renderer::initScreen(Context &ctx, int32_t x, int32_t y, int32_t w, int title = "TinyUI Window"; } - ctx.mSDLContext.mWindow = SDL_CreateWindow(title, x, y, w, h, SDL_WINDOW_SHOWN|SDL_WINDOW_OPENGL|SDL_WINDOW_RESIZABLE); - if (ctx.mSDLContext.mWindow == nullptr) { + ctx.mSDLContext->mWindow = SDL_CreateWindow(title, x, y, w, h, SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE); + if (ctx.mSDLContext->mWindow == nullptr) { const std::string msg = "Error while SDL_CreateWindow: " + std::string(SDL_GetError()) + "."; ctx.mLogger(LogSeverity::Error, msg.c_str()); return ErrorCode; @@ -290,8 +296,8 @@ ret_code Renderer::initScreen(Context &ctx, int32_t x, int32_t y, int32_t w, int return ErrorCode; } - ctx.mSDLContext.mRenderer = SDL_CreateRenderer(ctx.mSDLContext.mWindow, driverIndex, SDL_RENDERER_ACCELERATED); - if (nullptr == ctx.mSDLContext.mRenderer) { + ctx.mSDLContext->mRenderer = SDL_CreateRenderer(ctx.mSDLContext->mWindow, driverIndex, SDL_RENDERER_ACCELERATED); + if (nullptr == ctx.mSDLContext->mRenderer) { const std::string msg = "Error while SDL_CreateRenderer: " + std::string(SDL_GetError()) + "."; ctx.mLogger(LogSeverity::Error, msg.c_str()); return ErrorCode; @@ -303,8 +309,8 @@ ret_code Renderer::initScreen(Context &ctx, int32_t x, int32_t y, int32_t w, int showDriverInUse(ctx); - ctx.mSDLContext.mSurface = SDL_GetWindowSurface(ctx.mSDLContext.mWindow); - if (ctx.mSDLContext.mSurface == nullptr) { + ctx.mSDLContext->mSurface = SDL_GetWindowSurface(ctx.mSDLContext->mWindow); + if (ctx.mSDLContext->mSurface == nullptr) { ctx.mLogger(LogSeverity::Error, "Surface pointer from window is nullptr."); return ErrorCode; } @@ -325,13 +331,13 @@ ret_code Renderer::initScreen(Context &ctx, SDL_Window *window, SDL_Renderer *re TTF_Init(); - ctx.mSDLContext.mRenderer = renderer; - ctx.mSDLContext.mWindow = window; + ctx.mSDLContext->mRenderer = renderer; + ctx.mSDLContext->mWindow = window; showDriverInUse(ctx); - ctx.mSDLContext.mSurface = SDL_GetWindowSurface(ctx.mSDLContext.mWindow); - ctx.mSDLContext.mOwner = false; + ctx.mSDLContext->mSurface = SDL_GetWindowSurface(ctx.mSDLContext->mWindow); + ctx.mSDLContext->mOwner = false; ctx.mCreated = true; return ResultOk; @@ -343,8 +349,8 @@ ret_code Renderer::releaseScreen(Context &ctx) { return ErrorCode; } - SDL_DestroyWindow(ctx.mSDLContext.mWindow); - ctx.mSDLContext.mWindow = nullptr; + SDL_DestroyWindow(ctx.mSDLContext->mWindow); + ctx.mSDLContext->mWindow = nullptr; return ResultOk; } @@ -356,19 +362,19 @@ ret_code Renderer::beginRender(Context &ctx, Color4 bg, SDL_Texture *renderTarge } const SDL_Color sdl_bg = getSDLColor(bg); - SDL_SetRenderDrawColor(ctx.mSDLContext.mRenderer, sdl_bg.r, sdl_bg.g, sdl_bg.b, sdl_bg.a); - SDL_RenderClear(ctx.mSDLContext.mRenderer); + SDL_SetRenderDrawColor(ctx.mSDLContext->mRenderer, sdl_bg.r, sdl_bg.g, sdl_bg.b, sdl_bg.a); + SDL_RenderClear(ctx.mSDLContext->mRenderer); return ResultOk; } ret_code Renderer::drawRect(Context &ctx, int32_t x, int32_t y, int32_t w, int32_t h, bool filled, Color4 fg) { SDL_Rect r = {x, y, w, h}; - SDL_SetRenderDrawColor(ctx.mSDLContext.mRenderer, fg.r, fg.g, fg.b, fg.a); + SDL_SetRenderDrawColor(ctx.mSDLContext->mRenderer, fg.r, fg.g, fg.b, fg.a); if (filled) { - SDL_RenderFillRect(ctx.mSDLContext.mRenderer, &r); + SDL_RenderFillRect(ctx.mSDLContext->mRenderer, &r); } else { - SDL_RenderDrawRect(ctx.mSDLContext.mRenderer, &r); + SDL_RenderDrawRect(ctx.mSDLContext->mRenderer, &r); } return ResultOk; @@ -380,28 +386,28 @@ ret_code Renderer::drawImage(Context &ctx, int32_t x, int32_t y, int32_t w, int3 } SDL_Rect imageRect = {x, y, w, h}; - SDL_Texture *tex = SDL_CreateTextureFromSurface(ctx.mSDLContext.mRenderer, image->mSurfaceImpl->mSurface); - SDL_RenderCopy(ctx.mSDLContext.mRenderer, tex, nullptr, &imageRect); + SDL_Texture *tex = SDL_CreateTextureFromSurface(ctx.mSDLContext->mRenderer, image->mSurfaceImpl->mSurface); + SDL_RenderCopy(ctx.mSDLContext->mRenderer, tex, nullptr, &imageRect); SDL_DestroyTexture(tex); return ResultOk; } ret_code Renderer::closeScreen(Context &ctx) { - if (ctx.mSDLContext.mWindow == nullptr) { + if (ctx.mSDLContext->mWindow == nullptr) { return ErrorCode; } TTF_Quit(); - SDL_DestroyWindow(ctx.mSDLContext.mWindow); - ctx.mSDLContext.mWindow = nullptr; + SDL_DestroyWindow(ctx.mSDLContext->mWindow); + ctx.mSDLContext->mWindow = nullptr; return ResultOk; } ret_code Renderer::endRender(Context &ctx) { - SDL_RenderPresent(ctx.mSDLContext.mRenderer); + SDL_RenderPresent(ctx.mSDLContext->mRenderer); return ResultOk; } @@ -410,7 +416,7 @@ ret_code Renderer::createRenderTexture(Context &ctx, int w, int h, SDL_Texture * if (texture == nullptr) { return ErrorCode; } - *texture = SDL_CreateTexture(ctx.mSDLContext.mRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, w, h); + *texture = SDL_CreateTexture(ctx.mSDLContext->mRenderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, w, h); return ResultOk; } diff --git a/src/backends/sdl2_renderer.h b/src/backends/sdl2_renderer.h index c5870c5..505ff67 100644 --- a/src/backends/sdl2_renderer.h +++ b/src/backends/sdl2_renderer.h @@ -71,6 +71,36 @@ struct FontImpl { } }; +/// @brief The SDL context. +struct SDLContext { + SDL_Window *mWindow{ nullptr }; ///< The window. + SDL_Surface *mSurface{ nullptr }; ///< The surface. + SDL_Renderer *mRenderer{ nullptr }; ///< The renderer. + bool mOwner{ false }; ///< The owner state. + + /// @brief Will create a new SDL context. + /// @return The created SDL context. + static SDLContext *create() { + return new SDLContext; + } + + /// @brief Will destroy the SDL context and all its resources. + void destroy() { + if (mOwner) { + if (mRenderer != nullptr) { + SDL_DestroyRenderer(mRenderer); + mRenderer = nullptr; + } + if (mWindow != nullptr) { + SDL_DestroyWindow(mWindow); + mWindow = nullptr; + } + } + delete this; + } +}; + + /// @brief The renderer implementation using the SDL2 library. struct Renderer { static ret_code initRenderer(Context &ctx); diff --git a/src/tinyui.cpp b/src/tinyui.cpp index e1f67fa..95f51c7 100644 --- a/src/tinyui.cpp +++ b/src/tinyui.cpp @@ -114,12 +114,12 @@ ret_code TinyUi::getSurfaceInfo(int32_t &w, int32_t &h) { return ErrorCode; } - if (ctx.mSDLContext.mSurface == nullptr) { + if (ctx.mSDLContext->mSurface == nullptr) { return ErrorCode; } - w = ctx.mSDLContext.mSurface->w; - h = ctx.mSDLContext.mSurface->h; + w = ctx.mSDLContext->mSurface->w; + h = ctx.mSDLContext->mSurface->h; return ResultOk; } @@ -171,8 +171,8 @@ ret_code TinyUi::release() { } Renderer::releaseRenderer(ctx); Renderer::releaseScreen(ctx); - ctx.mSDLContext.mRenderer = nullptr; - ctx.mSDLContext.mWindow = nullptr; + ctx.mSDLContext->mRenderer = nullptr; + ctx.mSDLContext->mWindow = nullptr; ctx.mRoot = nullptr; ctx.mCreated = false; diff --git a/src/tinyui.h b/src/tinyui.h index 004a7cd..bda6198 100644 --- a/src/tinyui.h +++ b/src/tinyui.h @@ -72,6 +72,8 @@ struct SurfaceImpl; struct FontImpl; struct Widget; +struct SDLContext; + // Type declarations ---------------------------------------------------------- /// @brief This enum is used to describe the alignment of a widget. @@ -380,14 +382,6 @@ using EventDispatchMap = std::map; /// @brief Function pointer declaration for callbacks. typedef void (*tui_log_func) (LogSeverity severity, const char *message); -/// @brief The SDL context. -struct SDLContext { - SDL_Window *mWindow{nullptr}; ///< The window. - SDL_Surface *mSurface{ nullptr }; ///< The surface. - SDL_Renderer *mRenderer{ nullptr }; ///< The renderer. - bool mOwner{ false }; ///< The owner state. -}; - /// @brief The update callback list. using UpdateCallbackList = std::list; @@ -397,7 +391,7 @@ struct Context { bool mRequestShutdown{false}; ///< The request shutdown state. const char *mAppTitle{nullptr}; ///< The application title. const char *mWindowsTitle{nullptr}; ///< The window title. - SDLContext mSDLContext; ///< The SDL context. + SDLContext *mSDLContext{ nullptr }; ///< The SDL context. Style mStyle{}; ///< The active style. Widget *mRoot{nullptr}; ///< The root widget. Widget *mFocus{nullptr}; ///< The widget which is in focus. diff --git a/src/widgets.cpp b/src/widgets.cpp index acac289..160451f 100644 --- a/src/widgets.cpp +++ b/src/widgets.cpp @@ -221,7 +221,7 @@ void Widgets::findSelectedWidget(int x, int y, Widget *currentChild, Widget **fo ret_code Widgets::label(Id id, Id parentId, const char *text, const Rect &rect, Alignment alignment) { auto &ctx = TinyUi::getContext(); - if (ctx.mSDLContext.mRenderer == nullptr) { + if (ctx.mSDLContext->mRenderer == nullptr) { return InvalidRenderHandle; } @@ -243,7 +243,7 @@ ret_code Widgets::label(Id id, Id parentId, const char *text, const Rect &rect, ret_code Widgets::inputText(Id id, Id parentId, const Rect &rect, Alignment alignment) { auto &ctx = TinyUi::getContext(); - if (ctx.mSDLContext.mRenderer == nullptr) { + if (ctx.mSDLContext->mRenderer == nullptr) { return InvalidRenderHandle; } @@ -263,7 +263,7 @@ ret_code Widgets::inputText(Id id, Id parentId, const Rect &rect, Alignment alig ret_code Widgets::button(Id id, Id parentId, const char *text, const Rect &rect, CallbackI *callback) { auto &ctx = TinyUi::getContext(); - if (ctx.mSDLContext.mRenderer == nullptr) { + if (ctx.mSDLContext->mRenderer == nullptr) { return InvalidRenderHandle; } @@ -289,7 +289,7 @@ ret_code Widgets::button(Id id, Id parentId, const char *text, const Rect &rect, ret_code Widgets::imageButton(Id id, Id parentId, const char *image, const Rect &rect, CallbackI *callback) { auto &ctx = TinyUi::getContext(); - if (ctx.mSDLContext.mRenderer == nullptr) { + if (ctx.mSDLContext->mRenderer == nullptr) { return InvalidRenderHandle; } @@ -316,7 +316,7 @@ ret_code Widgets::imageButton(Id id, Id parentId, const char *image, const Rect ret_code Widgets::box(Id id, Id parentId, const Rect &rect, bool filled) { auto &ctx = TinyUi::getContext(); - if (ctx.mSDLContext.mRenderer == nullptr) { + if (ctx.mSDLContext->mRenderer == nullptr) { return InvalidRenderHandle; } @@ -336,7 +336,7 @@ ret_code Widgets::box(Id id, Id parentId, const Rect &rect, bool filled) { ret_code Widgets::imageBox(Id id, Id parentId, const char* image, const Rect& rect, bool filled) { auto &ctx = TinyUi::getContext(); - if (ctx.mSDLContext.mRenderer == nullptr) { + if (ctx.mSDLContext->mRenderer == nullptr) { return InvalidRenderHandle; } @@ -358,7 +358,7 @@ ret_code Widgets::imageBox(Id id, Id parentId, const char* image, const Rect& re ret_code Widgets::panel(Id id, Id parentId, const char *title, const Rect &rect, CallbackI *callback) { auto &ctx = TinyUi::getContext(); - if (ctx.mSDLContext.mRenderer == nullptr) { + if (ctx.mSDLContext->mRenderer == nullptr) { return InvalidRenderHandle; } @@ -388,7 +388,7 @@ static int onTreeViewItemClicked(Id id, void *data) { ret_code Widgets::treeView(Id id, Id parentId, const char *title, const Rect &rect) { auto &ctx = TinyUi::getContext(); - if (ctx.mSDLContext.mRenderer == nullptr) { + if (ctx.mSDLContext->mRenderer == nullptr) { return InvalidRenderHandle; } @@ -417,7 +417,7 @@ ret_code Widgets::treeView(Id id, Id parentId, const char *title, const Rect &re ret_code Widgets::treeItem(Id id, Id parentItemId, const char *text) { auto &ctx = TinyUi::getContext(); - if (ctx.mSDLContext.mRenderer == nullptr) { + if (ctx.mSDLContext->mRenderer == nullptr) { return InvalidRenderHandle; } @@ -453,7 +453,7 @@ ret_code Widgets::treeItem(Id id, Id parentItemId, const char *text) { ret_code Widgets::progressBar(Id id, Id parentId, const Rect &rect, int fillRate, CallbackI *callback) { auto &ctx = TinyUi::getContext(); - if (ctx.mSDLContext.mRenderer == nullptr) { + if (ctx.mSDLContext->mRenderer == nullptr) { return InvalidRenderHandle; }