• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2024 Google LLC
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #include "include/core/SkCanvas.h"
9 #include "include/core/SkRRect.h"
10 #include "include/core/SkRect.h"
11 #include "include/core/SkStream.h"
12 #include "include/core/SkSurface.h"
13 #include "include/gpu/GrDirectContext.h"
14 #include "include/gpu/ganesh/SkSurfaceGanesh.h"
15 #include "include/gpu/ganesh/gl/GrGLDirectContext.h"
16 #include "include/gpu/gl/GrGLInterface.h"
17 #include "include/encode/SkWebpEncoder.h"
18 
19 #if defined(__linux__)
20 #include "include/gpu/ganesh/gl/glx/GrGLMakeGLXInterface.h"
21 
22 #include <X11/Xlib.h>
23 #include <GL/glx.h>
24 #include <GL/gl.h>
25 #endif
26 
27 #if defined(__APPLE__) && TARGET_OS_MAC == 1
28 #include "include/gpu/ganesh/gl/mac/GrGLMakeMacInterface.h"
29 
30 #include "gl_context_helper.h"
31 #endif
32 
33 #include <cstdio>
34 
35 #if defined(__linux__)
36 
37 // Set up an X Display that can be rendered to GL. This will not be visible while
38 // the program runs. It is cribbed from how Skia's tooling sets itself up (e.g. viewer).
initialize_gl_linux()39 bool initialize_gl_linux() {
40     Display* display = XOpenDisplay(nullptr);
41     if (!display) {
42         printf("Could not open an X display\n");
43         return false;
44     }
45     static int constexpr kChooseFBConfigAtt[] = {
46         GLX_RENDER_TYPE, GLX_RGBA_BIT,
47         GLX_DOUBLEBUFFER, True,
48         GLX_STENCIL_SIZE, 8,
49         None
50     };
51     int n;
52     GLXFBConfig* fbConfig = glXChooseFBConfig(display, DefaultScreen(display), kChooseFBConfigAtt, &n);
53     XVisualInfo* visualInfo;
54     if (n > 0) {
55         visualInfo = glXGetVisualFromFBConfig(display, *fbConfig);
56     } else {
57         // For some reason glXChooseVisual takes a non-const pointer to the attributes.
58         int chooseVisualAtt[] = {
59             GLX_RGBA,
60             GLX_DOUBLEBUFFER,
61             GLX_STENCIL_SIZE, 8,
62             None
63         };
64         visualInfo = glXChooseVisual(display, DefaultScreen(display), chooseVisualAtt);
65     }
66     if (!visualInfo) {
67         printf("Could not get X visualInfo\n");
68         return false;
69     }
70     GLXContext glContext = glXCreateContext(display, visualInfo, nullptr, GL_TRUE);
71     if (!glContext) {
72         printf("Could not make GL X context\n");
73         return false;
74     }
75     Colormap colorMap = XCreateColormap(display,
76                                         RootWindow(display, visualInfo->screen),
77                                         visualInfo->visual,
78                                         AllocNone);
79     XSetWindowAttributes swa;
80     swa.colormap = colorMap;
81     swa.event_mask = 0;
82     Window window = XCreateWindow(display,
83                             RootWindow(display, visualInfo->screen),
84                             0, 0, // x, y
85                             1280, 960, // width, height
86                             0, // border width
87                             visualInfo->depth,
88                             InputOutput,
89                             visualInfo->visual,
90                             CWEventMask | CWColormap,
91                             &swa);
92 
93     if (!glXMakeCurrent(display, window, glContext)) {
94         printf("Could not set GL X context to be the created one\n");
95         return false;
96     }
97     return true;
98 }
99 #endif  // defined(__linux__)
100 
main(int argc,char ** argv)101 int main(int argc, char** argv) {
102     if (argc != 2) {
103         printf("Usage: %s <name.webp>\n", argv[0]);
104         return 1;
105     }
106 
107     SkFILEWStream output(argv[1]);
108     if (!output.isValid()) {
109         printf("Cannot open output file %s\n", argv[1]);
110         return 1;
111     }
112 
113     GrContextOptions opts;
114     opts.fSuppressPrints = true;
115 #if defined(__linux__)
116     if (!initialize_gl_linux()) {
117         return 1;
118     }
119     sk_sp<const GrGLInterface> interface = GrGLInterfaces::MakeGLX();
120 #elif defined(__APPLE__) && TARGET_OS_MAC == 1
121     if (!initialize_gl_mac()) {
122         return 1;
123     }
124     sk_sp<const GrGLInterface> interface = GrGLInterfaces::MakeMac();
125 #endif
126     if (!interface) {
127         printf("Could not make GL interface\n");
128         return 1;
129     }
130 
131     sk_sp<GrDirectContext> ctx = GrDirectContexts::MakeGL(interface, opts);
132     if (!ctx) {
133         printf("Could not make GrDirectContext\n");
134         return 1;
135     }
136     printf("Context made, now to make the surface\n");
137 
138     SkImageInfo imageInfo =
139             SkImageInfo::Make(200, 400, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
140 
141     sk_sp<SkSurface> surface =
142             SkSurfaces::RenderTarget(ctx.get(), skgpu::Budgeted::kYes, imageInfo);
143     if (!surface) {
144         printf("Could not make surface from GL DirectContext\n");
145         return 1;
146     }
147 
148     SkCanvas* canvas = surface->getCanvas();
149     canvas->clear(SK_ColorRED);
150     SkRRect rrect = SkRRect::MakeRectXY(SkRect::MakeLTRB(10, 20, 50, 70), 10, 10);
151 
152     SkPaint paint;
153     paint.setColor(SK_ColorBLUE);
154     paint.setAntiAlias(true);
155 
156     canvas->drawRRect(rrect, paint);
157 
158     ctx->flush();
159 
160     printf("Drew to surface, now doing readback\n");
161     sk_sp<SkImage> img = surface->makeImageSnapshot();
162     sk_sp<SkData> webp = SkWebpEncoder::Encode(ctx.get(), img.get(), {});
163     if (!webp) {
164         printf("Readback of pixels (or encoding) failed\n");
165         return 1;
166     }
167     output.write(webp->data(), webp->size());
168     output.fsync();
169 
170     return 0;
171 }
172