blob: 50ca93a891500538b439acbce2d284917ba148f2 [file] [log] [blame]
/*
* Copyright 2024 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "include/core/SkCanvas.h"
#include "include/core/SkRRect.h"
#include "include/core/SkRect.h"
#include "include/core/SkStream.h"
#include "include/core/SkSurface.h"
#include "include/gpu/GrDirectContext.h"
#include "include/gpu/ganesh/SkSurfaceGanesh.h"
#include "include/gpu/ganesh/gl/GrGLDirectContext.h"
#include "include/gpu/gl/GrGLInterface.h"
#include "include/encode/SkWebpEncoder.h"
#if defined(__linux__)
#include "include/gpu/ganesh/gl/glx/GrGLMakeGLXInterface.h"
#include <X11/Xlib.h>
#include <GL/glx.h>
#include <GL/gl.h>
#endif
#if defined(__APPLE__) && TARGET_OS_MAC == 1
#include "include/gpu/ganesh/gl/mac/GrGLMakeMacInterface.h"
#include "gl_context_helper.h"
#endif
#include <cstdio>
#if defined(__linux__)
// Set up an X Display that can be rendered to GL. This will not be visible while
// the program runs. It is cribbed from how Skia's tooling sets itself up (e.g. viewer).
bool initialize_gl_linux() {
Display* display = XOpenDisplay(nullptr);
if (!display) {
printf("Could not open an X display\n");
return false;
}
static int constexpr kChooseFBConfigAtt[] = {
GLX_RENDER_TYPE, GLX_RGBA_BIT,
GLX_DOUBLEBUFFER, True,
GLX_STENCIL_SIZE, 8,
None
};
int n;
GLXFBConfig* fbConfig = glXChooseFBConfig(display, DefaultScreen(display), kChooseFBConfigAtt, &n);
XVisualInfo* visualInfo;
if (n > 0) {
visualInfo = glXGetVisualFromFBConfig(display, *fbConfig);
} else {
// For some reason glXChooseVisual takes a non-const pointer to the attributes.
int chooseVisualAtt[] = {
GLX_RGBA,
GLX_DOUBLEBUFFER,
GLX_STENCIL_SIZE, 8,
None
};
visualInfo = glXChooseVisual(display, DefaultScreen(display), chooseVisualAtt);
}
if (!visualInfo) {
printf("Could not get X visualInfo\n");
return false;
}
GLXContext glContext = glXCreateContext(display, visualInfo, nullptr, GL_TRUE);
if (!glContext) {
printf("Could not make GL X context\n");
return false;
}
Colormap colorMap = XCreateColormap(display,
RootWindow(display, visualInfo->screen),
visualInfo->visual,
AllocNone);
XSetWindowAttributes swa;
swa.colormap = colorMap;
swa.event_mask = 0;
Window window = XCreateWindow(display,
RootWindow(display, visualInfo->screen),
0, 0, // x, y
1280, 960, // width, height
0, // border width
visualInfo->depth,
InputOutput,
visualInfo->visual,
CWEventMask | CWColormap,
&swa);
if (!glXMakeCurrent(display, window, glContext)) {
printf("Could not set GL X context to be the created one\n");
return false;
}
return true;
}
#endif // defined(__linux__)
int main(int argc, char** argv) {
if (argc != 2) {
printf("Usage: %s <name.webp>\n", argv[0]);
return 1;
}
SkFILEWStream output(argv[1]);
if (!output.isValid()) {
printf("Cannot open output file %s\n", argv[1]);
return 1;
}
GrContextOptions opts;
opts.fSuppressPrints = true;
#if defined(__linux__)
if (!initialize_gl_linux()) {
return 1;
}
sk_sp<const GrGLInterface> interface = GrGLInterfaces::MakeGLX();
#elif defined(__APPLE__) && TARGET_OS_MAC == 1
if (!initialize_gl_mac()) {
return 1;
}
sk_sp<const GrGLInterface> interface = GrGLInterfaces::MakeMac();
#endif
if (!interface) {
printf("Could not make GL interface\n");
return 1;
}
sk_sp<GrDirectContext> ctx = GrDirectContexts::MakeGL(interface, opts);
if (!ctx) {
printf("Could not make GrDirectContext\n");
return 1;
}
printf("Context made, now to make the surface\n");
SkImageInfo imageInfo =
SkImageInfo::Make(200, 400, kRGBA_8888_SkColorType, kPremul_SkAlphaType);
sk_sp<SkSurface> surface =
SkSurfaces::RenderTarget(ctx.get(), skgpu::Budgeted::kYes, imageInfo);
if (!surface) {
printf("Could not make surface from GL DirectContext\n");
return 1;
}
SkCanvas* canvas = surface->getCanvas();
canvas->clear(SK_ColorRED);
SkRRect rrect = SkRRect::MakeRectXY(SkRect::MakeLTRB(10, 20, 50, 70), 10, 10);
SkPaint paint;
paint.setColor(SK_ColorBLUE);
paint.setAntiAlias(true);
canvas->drawRRect(rrect, paint);
ctx->flush();
printf("Drew to surface, now doing readback\n");
sk_sp<SkImage> img = surface->makeImageSnapshot();
sk_sp<SkData> webp = SkWebpEncoder::Encode(ctx.get(), img.get(), {});
if (!webp) {
printf("Readback of pixels (or encoding) failed\n");
return 1;
}
output.write(webp->data(), webp->size());
output.fsync();
return 0;
}