【问题标题】:Qt QOpenGLWidget: Skia text disappears after resizeQt QOpenGLWidget:调整大小后Skia文本消失
【发布时间】:2021-06-24 08:53:05
【问题描述】:

我使用 QT 创建了一个带有单个 Skia 画布的基本应用程序。当使用QOpenGLWindow 作为基类时,它可以正常工作。但是使用QOpenGLWidget,调整窗口大小时文本会消失。主要区别在于QOpenGLWidget 在每次调整大小后都会重新创建其帧缓冲区。

调整大小之前:

调整大小后:

使用的skia版本是Arch Linux上的chrome/m90(git tag)(用wayland和X11测试)。早期版本也会出现同样的问题。对于 chrome/m80,文字不会消失,但字母会变成黑色块。 所以我怀疑是内存损坏问题,但解决方法是什么?

我的代码如下。如果需要,我也可以提供构建文件。

#include <QSurfaceFormat>
#include <QOpenGLContext>
#include <QApplication>
#include <QOpenGLWindow>
#include <QOpenGLWidget>
#include <QMainWindow>
#include <gpu/gl/GrGLAssembleInterface.h>
#include <core/SkSurfaceProps.h>
#include <gpu/GrDirectContext.h>
#include <core/SkSurface.h>
#include <QOpenGLFunctions>
#include <core/SkCanvas.h>
#include <core/SkFont.h>

bool AllowEGL;

void initGL() {
  QSurfaceFormat fmt;
  fmt.setDepthBufferSize(0);
  fmt.setRedBufferSize(8);
  fmt.setGreenBufferSize(8);
  fmt.setBlueBufferSize(8);
  fmt.setStencilBufferSize(8);
  fmt.setSamples(0);

  fmt.setSwapBehavior(QSurfaceFormat::DoubleBuffer);

  if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGL) {
    fmt.setVersion(3, 3);
    fmt.setProfile(QSurfaceFormat::CoreProfile);
  } else {
    fmt.setVersion(3, 0);
  }

  QSurfaceFormat::setDefaultFormat(fmt);
  AllowEGL = QApplication::platformName() != "xcb";
}

sk_sp<GrDirectContext> makeContext(QOpenGLContext *ctx) {
  auto interface = GrGLMakeAssembledInterface(ctx, [](auto ctx, auto name) {
    return AllowEGL || strncmp(name, "egl", 3) ? static_cast<QOpenGLContext *>(ctx)->getProcAddress(name) : nullptr;
  });
  return GrDirectContext::MakeGL(interface);
}

sk_sp<SkSurface> createSurface(GrRecordingContext *ctx, int w, int h, GrGLuint fbo) {
  GrGLFramebufferInfo info;
  info.fFBOID = fbo;
  info.fFormat = GL_RGBA8;
  GrBackendRenderTarget target(w, h, 0, 8, info);
  const SkSurfaceProps props(0, SkPixelGeometry::kBGR_H_SkPixelGeometry);
  return SkSurface::MakeFromBackendRenderTarget(ctx, target, kBottomLeft_GrSurfaceOrigin, kRGBA_8888_SkColorType,
                                                nullptr, &props, [](auto r) { qDebug("release"); });
}

void draw(SkCanvas *canvas) {
  canvas->clear(SK_ColorWHITE);
  SkFont font;
  SkPaint paint;
  canvas->drawString("Hello World!", 10, 30, font, paint);
  paint.setAntiAlias(true);
  canvas->drawCircle(100, 50, 10, paint);
  canvas->flush();
}

class SkiaWindow : public QOpenGLWindow {
protected:
  void initializeGL() override {
    ctx = makeContext(context());
    f = context()->functions();
  }

  void resizeGL(int w, int h) override {
    surface = createSurface(ctx.get(), w, h, defaultFramebufferObject());
    f->glViewport(0, 0, w, h);
  }

  void paintGL() override {
    f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    draw(surface->getCanvas());
  }

private:
  sk_sp<GrDirectContext> ctx{};
  sk_sp<SkSurface> surface{};
  QOpenGLFunctions *f{};
};

class SkiaWidget : public QOpenGLWidget {
  using QOpenGLWidget::QOpenGLWidget;
protected:
  void initializeGL() override {
    ctx = makeContext(context());
    f = context()->functions();
  }

  void resizeGL(int w, int h) override {
    f->glViewport(0, 0, w, h);
    surface = createSurface(ctx.get(), w, h, defaultFramebufferObject());
  }

  void paintGL() override {
    draw(surface->getCanvas());
  }

private:
  sk_sp<GrDirectContext> ctx{};
  sk_sp<SkSurface> surface{};
  QOpenGLFunctions *f{};
};

int main(int argc, char *argv[]) {
  QApplication app(argc, argv);
  app.setApplicationName("qtskia");
  initGL();

  // Works fine
  //SkiaWindow window;

  // Text disappears after resizing window
  QMainWindow window;
  SkiaWidget widget (&window);
  window.setCentralWidget(&widget);

  window.show();
  return QApplication::exec();
}

【问题讨论】:

    标签: c++ qt skia


    【解决方案1】:

    要解决此问题,只需将 GrDirectContext::resetContext() 添加到 resizeGL 函数即可。

    来自Skia documentation

    上下文通常假定没有外部人员在底层 3D API 的上下文/设备/任何内容中设置状态。

    此调用通知上下文状态已修改并且应该重新发送。不应该经常调用以获得良好的性能。标志位,状态,取决于上下文使用哪个后端,GL 或 D3D(将来可能)。

    resetGLTextureBindings() 似乎也可以工作,而且开销可能会更低。

    所以问题是 Qt 修改了 OpenGL 状态,但 Skia 假设状态没有被修改。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多