cef离屏渲染(osr)初识

cef离屏渲染(osr)初识

业务需要,客户端的webview需要使用使用osr,透明绘制,才能实现一些业务,于是有了这个经历,如果你是新手,不妨看看。

环境配置

先下一个cef官方的demo,如果找不到请:点它
我下载的是这个选择你和你环境匹配的版本就行
我的环境是win+vs2019所以我需要生成一个vs工程,
在这里插入图片描述
这是我解压后的目录,一看显然可以用cmake生成vs工程
于是在这里插入图片描述
如图,我是vs2019,下载是32位的,如此选择操作;于是工程就有了
在这里插入图片描述
打开工程:在这里插入图片描述
ceflient是一个五脏俱全的例子,所以选择它作为启动项,编译运行起来就是这个样子了:在这里插入图片描述
看到是网页加载失败,因为他默认是谷歌的地址,被墙挡住了,所以就失败,换成百度的看看:修改这里在这里插入图片描述
如图是在cefclient_win.cc里面。
于是成功的出来了出来了百度的首页在这里插入图片描述

离屏模式

1,官方的例子肯定不是离屏模式(osr),需要操作一下;
只需要在启动时候加上 --off-screen-rendering-enabled启动参数,那么他就是离屏模式启动了或者我们在初始化cef的时候:

// Create the main message loop object.
  scoped_ptr<MainMessageLoop> message_loop;
  if (settings.multi_threaded_message_loop)
    message_loop.reset(new MainMessageLoopMultithreadedWin);
  else if (settings.external_message_pump)
    message_loop = MainMessageLoopExternalPump::Create();
  else
    message_loop.reset(new MainMessageLoopStd);

  // Initialize CEF.
  settings.windowless_rendering_enabled = true;
  context->Initialize(main_args, settings, app, sandbox_info);

settings.windowless_rendering_enabled = true;设置成true,同样的效果。
2,离屏以后肉眼发现了个问题
在这里插入图片描述
网页边上出现了一条线,看着很恶心,开始还一度怀疑是不是,网页绘制出来的。最后发现,是官方ceflient例子,创建的渲染窗口是一个有边框的窗口,改下这里就可以了

void OsrWindowWin::Create(HWND parent_hwnd, const RECT& rect) {
  CEF_REQUIRE_UI_THREAD();
  DCHECK(!hwnd_ && !render_handler_.get());
  DCHECK(parent_hwnd);
  DCHECK(!::IsRectEmpty(&rect));

  HINSTANCE hInst = ::GetModuleHandle(NULL);

  const cef_color_t background_color = MainContext::Get()->GetBackgroundColor();
  const HBRUSH background_brush = CreateSolidBrush(
      RGB(CefColorGetR(background_color), CefColorGetG(background_color),
          CefColorGetB(background_color)));

  RegisterOsrClass(hInst, background_brush);

  DWORD ex_style = 0;
  if (GetWindowLongPtr(parent_hwnd, GWL_EXSTYLE) & WS_EX_NOACTIVATE) {
    // Don't activate the browser window on creation.
    ex_style |= WS_EX_NOACTIVATE;
  }

  // Create the native window with a border so it's easier to visually identify
  // OSR windows.
  //他这里加了这个边框的属性WS_BORDER 把他去掉
  //hwnd_ = ::CreateWindowEx(
  //    ex_style, kWndClass, 0,
  //    WS_BORDER | WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE,
  //    rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
  //    parent_hwnd, 0, hInst, 0);
  //CHECK(hwnd_);

  hwnd_ = ::CreateWindowEx(
      ex_style, kWndClass, 0,
      WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_VISIBLE,
      rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top,
      parent_hwnd, 0, hInst, 0);
  CHECK(hwnd_);

  client_rect_ = rect;

  // Associate |this| with the window.
  SetUserDataPtr(hwnd_, this);

#if defined(CEF_USE_ATL)
  accessibility_root_ = nullptr;

  // Create/register the drag&drop handler.
  drop_target_ = DropTargetWin::Create(this, hwnd_);
  HRESULT register_res = RegisterDragDrop(hwnd_, drop_target_);
  DCHECK_EQ(register_res, S_OK);
#endif

  ime_handler_.reset(new OsrImeHandlerWin(hwnd_));

  // Enable Touch Events if requested
  if (client::MainContext::Get()->TouchEventsEnabled())
    RegisterTouchWindow(hwnd_, 0);

  // Notify the window owner.
  NotifyNativeWindowCreated(hwnd_);
}

编译看下:
在这里插入图片描述
就没有了

透明绘制

如何启动透明绘制呢,也是启动的时候加上这俩参数--no-proxy-server --transparent-painting-enabled就可以了;但是却发现背景变成这样的了:在这里插入图片描述
这显然是不对头的,首先我怀疑是不是cef绘制给到数据就是这样的:于是找到继承这个类CefRenderHandler对象,找到改方法

oid ClientHandlerOsr::OnPaint(CefRefPtr<CefBrowser> browser,
                               PaintElementType type,
                               const RectList& dirtyRects,
                               const void* buffer,
                               int width,
                               int height) {
  CEF_REQUIRE_UI_THREAD();
  if (!osr_delegate_)
    return;
  osr_delegate_->OnPaint(browser, type, dirtyRects, buffer, width, height);
}

这里保存图片验证下看看:最后发现,出来的图片背景不是五彩缤纷的。
那么最后只能是,渲染到窗口这个过程,出的幺蛾子,最后发现

void OsrRenderer::Render() {
  if (view_width_ == 0 || view_height_ == 0)
    return;

  DCHECK(initialized_);

  struct {
    float tu, tv;
    float x, y, z;
  } static vertices[] = {{0.0f, 1.0f, -1.0f, -1.0f, 0.0f},
                         {1.0f, 1.0f, 1.0f, -1.0f, 0.0f},
                         {1.0f, 0.0f, 1.0f, 1.0f, 0.0f},
                         {0.0f, 0.0f, -1.0f, 1.0f, 0.0f}};

  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  VERIFY_NO_ERROR;

  glMatrixMode(GL_MODELVIEW);
  VERIFY_NO_ERROR;
  glLoadIdentity();
  VERIFY_NO_ERROR;

  // Match GL units to screen coordinates.
  glViewport(0, 0, view_width_, view_height_);
  VERIFY_NO_ERROR;
  glMatrixMode(GL_PROJECTION);
  VERIFY_NO_ERROR;
  glLoadIdentity();
  VERIFY_NO_ERROR;

  // Draw the background gradient.
  glPushAttrib(GL_ALL_ATTRIB_BITS);
  VERIFY_NO_ERROR;
  // Don't check for errors until glEnd().
  glBegin(GL_QUADS);
  glColor4f(1.0, 0.0, 0.0, 1.0);  // red
  glVertex2f(-1.0, -1.0);
  glVertex2f(1.0, -1.0);
  glColor4f(0.0, 0.0, 1.0, 1.0);  // blue
  glVertex2f(1.0, 1.0);
  glVertex2f(-1.0, 1.0);
  glEnd();
  VERIFY_NO_ERROR;
  glPopAttrib();
  VERIFY_NO_ERROR;

  // Rotate the view based on the mouse spin.
  if (spin_x_ != 0) {
    glRotatef(-spin_x_, 1.0f, 0.0f, 0.0f);
    VERIFY_NO_ERROR;
  }
  if (spin_y_ != 0) {
    glRotatef(-spin_y_, 0.0f, 1.0f, 0.0f);
    VERIFY_NO_ERROR;
  }

  if (IsTransparent()) {
    // Alpha blending style. Texture values have premultiplied alpha.
     //就真的是这里搞出来的
    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
    VERIFY_NO_ERROR;

    // Enable alpha blending.
    glEnable(GL_BLEND);
    VERIFY_NO_ERROR;
  }

  // Enable 2D textures.
  glEnable(GL_TEXTURE_2D);
  VERIFY_NO_ERROR;

  // Draw the facets with the texture.
  DCHECK_NE(texture_id_, 0U);
  VERIFY_NO_ERROR;
  glBindTexture(GL_TEXTURE_2D, texture_id_);
  VERIFY_NO_ERROR;
  glInterleavedArrays(GL_T2F_V3F, 0, vertices);
  VERIFY_NO_ERROR;
  glDrawArrays(GL_QUADS, 0, 4);
  VERIFY_NO_ERROR;

  // Disable 2D textures.
  glDisable(GL_TEXTURE_2D);
  VERIFY_NO_ERROR;

  if (IsTransparent()) {
    // Disable alpha blending.
    glDisable(GL_BLEND);
    VERIFY_NO_ERROR;
  }

  // Draw a rectangle around the update region.
  if (settings_.show_update_rect && !update_rect_.IsEmpty()) {
    int left = update_rect_.x;
    int right = update_rect_.x + update_rect_.width;
    int top = update_rect_.y;
    int bottom = update_rect_.y + update_rect_.height;

#if defined(OS_LINUX)
    // Shrink the box so that top & right sides are drawn.
    top += 1;
    right -= 1;
#else
    // Shrink the box so that left & bottom sides are drawn.
    left += 1;
    bottom -= 1;
#endif

    glPushAttrib(GL_ALL_ATTRIB_BITS);
    VERIFY_NO_ERROR
    glMatrixMode(GL_PROJECTION);
    VERIFY_NO_ERROR;
    glPushMatrix();
    VERIFY_NO_ERROR;
    glLoadIdentity();
    VERIFY_NO_ERROR;
    glOrtho(0, view_width_, view_height_, 0, 0, 1);
    VERIFY_NO_ERROR;

    glLineWidth(1);
    VERIFY_NO_ERROR;
    glColor3f(1.0f, 0.0f, 0.0f);
    VERIFY_NO_ERROR;
    // Don't check for errors until glEnd().
    glBegin(GL_LINE_STRIP);
    glVertex2i(left, top);
    glVertex2i(right, top);
    glVertex2i(right, bottom);
    glVertex2i(left, bottom);
    glVertex2i(left, top);
    glEnd();
    VERIFY_NO_ERROR;

    glPopMatrix();
    VERIFY_NO_ERROR;
    glPopAttrib();
    VERIFY_NO_ERROR;
  }
}

于是我把这里改成这样

if (IsTransparent()) {
    // Alpha blending style. Texture values have premultiplied alpha.
     //如下修改
    glBlendFunc(GL_ONE, GL_ZERO);
    VERIFY_NO_ERROR;

    // Enable alpha blending.
    glEnable(GL_BLEND);
    VERIFY_NO_ERROR;
  }

最后就变成这样了:
在这里插入图片描述
为啥是黑色的,因为这个窗口时透明背景,透下到窗口背景它就是这色的。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值