/* * Copyright 2016 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "include/core/SkSurface.h" #include "src/base/SkAutoMalloc.h" #include "tools/window/RasterWindowContext.h" #include "tools/window/win/WindowContextFactory_win.h" #include using skwindow::DisplayParams; using skwindow::internal::RasterWindowContext; namespace { class RasterWindowContext_win : public RasterWindowContext { public: RasterWindowContext_win(HWND, std::unique_ptr); sk_sp getBackbufferSurface() override; bool isValid() override { return SkToBool(fWnd); } void resize(int w, int h) override; void setDisplayParams(std::unique_ptr params) override; protected: void onSwapBuffers() override; SkAutoMalloc fSurfaceMemory; sk_sp fBackbufferSurface; HWND fWnd; }; RasterWindowContext_win::RasterWindowContext_win(HWND wnd, std::unique_ptr params) : RasterWindowContext(std::move(params)), fWnd(wnd) { RECT rect; GetClientRect(wnd, &rect); this->resize(rect.right - rect.left, rect.bottom - rect.top); } void RasterWindowContext_win::setDisplayParams(std::unique_ptr params) { fDisplayParams = std::move(params); RECT rect; GetClientRect(fWnd, &rect); this->resize(rect.right - rect.left, rect.bottom - rect.top); } void RasterWindowContext_win::resize(int w, int h) { fWidth = w; fHeight = h; fBackbufferSurface.reset(); const size_t bmpSize = sizeof(BITMAPINFOHEADER) + w * h * sizeof(uint32_t); fSurfaceMemory.reset(bmpSize); BITMAPINFO* bmpInfo = reinterpret_cast(fSurfaceMemory.get()); ZeroMemory(bmpInfo, sizeof(BITMAPINFO)); bmpInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmpInfo->bmiHeader.biWidth = w; bmpInfo->bmiHeader.biHeight = -h; // negative means top-down bitmap. Skia draws top-down. bmpInfo->bmiHeader.biPlanes = 1; bmpInfo->bmiHeader.biBitCount = 32; bmpInfo->bmiHeader.biCompression = BI_RGB; void* pixels = bmpInfo->bmiColors; SkImageInfo info = SkImageInfo::Make( w, h, fDisplayParams->colorType(), kPremul_SkAlphaType, fDisplayParams->colorSpace()); fBackbufferSurface = SkSurfaces::WrapPixels(info, pixels, sizeof(uint32_t) * w); } sk_sp RasterWindowContext_win::getBackbufferSurface() { return fBackbufferSurface; } void RasterWindowContext_win::onSwapBuffers() { BITMAPINFO* bmpInfo = reinterpret_cast(fSurfaceMemory.get()); HDC dc = GetDC(fWnd); StretchDIBits(dc, 0, 0, fWidth, fHeight, 0, 0, fWidth, fHeight, bmpInfo->bmiColors, bmpInfo, DIB_RGB_COLORS, SRCCOPY); ReleaseDC(fWnd, dc); } } // anonymous namespace namespace skwindow { std::unique_ptr MakeRasterForWin(HWND wnd, std::unique_ptr params) { std::unique_ptr ctx(new RasterWindowContext_win(wnd, std::move(params))); if (!ctx->isValid()) { ctx = nullptr; } return ctx; } } // namespace skwindow