void blend(drawable_type dw, const rectangle& area, pixel_color_t color, double fade_rate) { if (fade_rate <= 0) return; if (fade_rate > 1) fade_rate = 1; rectangle r; if (false == ::nana::overlap(rectangle{ drawable_size(dw) }, area, r)) return; unsigned red = static_cast<unsigned>((color.value & 0xFF0000) * fade_rate); unsigned green = static_cast<unsigned>((color.value & 0xFF00) * fade_rate); unsigned blue = static_cast<unsigned>((color.value & 0xFF) * fade_rate); double lrate = 1 - fade_rate; pixel_buffer pixbuf(dw, r.y, r.height); for (std::size_t row = 0; row < r.height; ++row) { auto i = pixbuf.raw_ptr(row) + r.x; const auto end = i + r.width; for (; i < end; ++i) { unsigned px_r = ((static_cast<unsigned>((i->value & 0xFF0000) * lrate) + red) & 0xFF0000); unsigned px_g = ((static_cast<unsigned>((i->value & 0xFF00) * lrate) + green) & 0xFF00); unsigned px_b = ((static_cast<unsigned>((i->value & 0xFF) * lrate) + blue) & 0xFF); i->value = (px_r | px_g | px_b); } } pixbuf.paste(nana::rectangle(r.x, 0, r.width, r.height), dw, point{r.x, r.y}); }
SDLContext::SDLContext(const rainbow::Config& config) : window_(nullptr), vsync_(false), fullscreen_(0), context_(nullptr) { if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMECONTROLLER) < 0) { LOGF("SDL: Unable to initialise video: %s", SDL_GetError()); return; } #ifdef RAINBOW_OS_MACOS // Prevent the full screen window from being minimized when losing focus. SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0"); #endif SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0); if (config.msaa() > 0) { SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, config.msaa()); } const uint32_t flags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | (config.high_dpi() ? SDL_WINDOW_ALLOW_HIGHDPI : 0); const Vec2i& size = ::window_size(config); window_ = SDL_CreateWindow(RAINBOW_BUILD, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, size.x, size.y, flags); if (!window_) { R_ABORT("SDL: Failed to create window: %s", SDL_GetError()); return; } context_ = SDL_GL_CreateContext(window_); if (!context_) { R_ABORT("SDL: Failed to create GL context: %s", SDL_GetError()); return; } #ifdef RAINBOW_JS vsync_ = true; #else SDL_GL_SetSwapInterval(1); vsync_ = SDL_GL_GetSwapInterval() == 1; #endif #ifndef NDEBUG const Vec2i& resolution = drawable_size(); LOGI("SDL: Resolution: %ix%i", resolution.x, resolution.y); int msaa = 0; SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &msaa); if (msaa > 0) LOGI("SDL: Anti-aliasing: %ix MSAA", msaa); else LOGI("SDL: Anti-aliasing: Disabled"); LOGI("SDL: Vertical sync: %s", (vsync_ ? "Enabled" : "Disabled")); #endif }