1// LAF OS Library
2// Copyright (C) 2020-2022 Igara Studio S.A.
3// Copyright (C) 2016-2018 David Capello
4//
5// This file is released under the terms of the MIT license.
6// Read LICENSE.txt for more information.
7
8#ifdef HAVE_CONFIG_H
9#include "config.h"
10#endif
11
12#include "os/skia/skia_window_x11.h"
13
14#include "gfx/size.h"
15#include "os/event.h"
16#include "os/event_queue.h"
17#include "os/gl/gl_context_glx.h"
18#include "os/skia/skia_surface.h"
19#include "os/skia/skia_window.h"
20#include "os/system.h"
21#include "os/x11/x11.h"
22
23#include "include/core/SkBitmap.h"
24
25namespace os {
26
27namespace {
28
29bool convert_skia_bitmap_to_ximage(const SkBitmap& bitmap, XImage& image)
30{
31 memset(&image, 0, sizeof(image));
32 int bpp = 8*bitmap.bytesPerPixel();
33 image.width = bitmap.width();
34 image.height = bitmap.height();
35 image.format = ZPixmap;
36 image.data = (char*)bitmap.getPixels();
37 image.byte_order = LSBFirst;
38 image.bitmap_unit = bpp;
39 image.bitmap_bit_order = LSBFirst;
40 image.bitmap_pad = bpp;
41 image.depth = (bitmap.alphaType() == kPremul_SkAlphaType ? 32: 24);
42 image.bytes_per_line = bitmap.rowBytes() - 4*bitmap.width();
43 image.bits_per_pixel = bpp;
44
45 return (XInitImage(&image) ? true: false);
46}
47
48} // anonymous namespace
49
50SkiaWindowX11::SkiaWindowX11(const WindowSpec& spec)
51 : Base(X11::instance()->display(), spec)
52{
53#if SK_SUPPORT_GPU
54 m_glCtx = std::make_unique<GLContextGLX>(x11display(), x11window());
55#endif
56 initColorSpace();
57}
58
59void SkiaWindowX11::onPaint(const gfx::Rect& rc)
60{
61#if SK_SUPPORT_GPU
62 if (backend() == Backend::GL)
63 return;
64#endif
65
66 auto surface = static_cast<SkiaSurface*>(this->surface());
67 const SkBitmap& bitmap = surface->bitmap();
68
69 int scale = this->scale();
70 if (scale == 1) {
71 XImage image;
72 if (convert_skia_bitmap_to_ximage(bitmap, image)) {
73 XPutImage(
74 x11display(), x11window(), gc(), &image,
75 rc.x, rc.y,
76 rc.x, rc.y,
77 rc.w, rc.h);
78 }
79 }
80 else {
81 SkBitmap scaled;
82 const SkImageInfo info =
83 SkImageInfo::Make(rc.w, rc.h,
84 bitmap.info().colorType(),
85 bitmap.info().alphaType());
86
87 // Increase m_buffer for "scaled" pixels if needed.
88 const size_t rowBytes = info.minRowBytes();
89 const size_t requiredSize = info.computeByteSize(rowBytes);
90 if (requiredSize > m_buffer.size())
91 m_buffer.resize(requiredSize);
92
93 if (scaled.installPixels(info, (void*)&m_buffer[0], rowBytes)) {
94 SkPaint paint;
95 paint.setBlendMode(SkBlendMode::kSrc);
96
97 SkCanvas canvas(scaled);
98 SkRect srcRect = SkRect::Make(SkIRect::MakeXYWH(rc.x/scale, rc.y/scale, rc.w/scale, rc.h/scale));
99 SkRect dstRect = SkRect::Make(SkIRect::MakeXYWH(0, 0, rc.w, rc.h));
100 canvas.drawImageRect(SkImage::MakeFromRaster(bitmap.pixmap(), nullptr, nullptr),
101 srcRect, dstRect, SkSamplingOptions(),
102 &paint, SkCanvas::kStrict_SrcRectConstraint);
103
104 XImage image;
105 if (convert_skia_bitmap_to_ximage(scaled, image)) {
106 XPutImage(
107 x11display(), x11window(), gc(), &image,
108 0, 0,
109 rc.x, rc.y,
110 rc.w, rc.h);
111 }
112 }
113 }
114}
115
116} // namespace os
117