【问题标题】:SKIA Rendering on Windows(SkCanvas from HDC)Windows 上的 SKIA 渲染(HDC 的 SkCanvas)
【发布时间】:2015-06-17 16:30:49
【问题描述】:

我正在尝试使用 SKIA 在 Windows 上绘图。

是否有从 HDC 启动 SkCanvas 的方法?

【问题讨论】:

    标签: chromium skia


    【解决方案1】:

    有几种方法可以在 Windows 上“使用”skia。这些方法在您 skia 文件夹中 skia\src\views\win 的 SkOSWindow_win.cpp 中进行了描述。

    例如:

    1. 您可以像在函数 SkOSWindow::attachGL

      中那样将 OpenGL 视口附加到您的窗口
      HDC dc = GetDC((HWND)fHWND);
      if (NULL == fHGLRC) {
          fHGLRC = SkCreateWGLContext(dc, msaaSampleCount,
              kGLPreferCompatibilityProfile_SkWGLContextRequest);
          if (NULL == fHGLRC) {
              return false;
          }
          glClearStencil(0);
          glClearColor(0, 0, 0, 0);
          glStencilMask(0xffffffff);
          glClear(GL_STENCIL_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
      }
      if (wglMakeCurrent(dc, (HGLRC)fHGLRC)) {
          // use DescribePixelFormat to get the stencil bit depth.
          int pixelFormat = GetPixelFormat(dc);
          PIXELFORMATDESCRIPTOR pfd;
          DescribePixelFormat(dc, pixelFormat, sizeof(pfd), &pfd);
          info->fStencilBits = pfd.cStencilBits;
      
          // Get sample count if the MSAA WGL extension is present
          SkWGLExtensions extensions;
          if (extensions.hasExtension(dc, "WGL_ARB_multisample")) {
              static const int kSampleCountAttr = SK_WGL_SAMPLES;
              extensions.getPixelFormatAttribiv(dc,
                  pixelFormat,
                  0,
                  1,
                  &kSampleCountAttr,
                  &info->fSampleCount);
          }
          else {
              info->fSampleCount = 0;
          }
      
          glViewport(0, 0,
              SkScalarRoundToInt(this->width()),
              SkScalarRoundToInt(this->height()));
          return true;
      }
      
    2. 您可以像 SkOSWindow::doPaint 中所做的那样,通过 BitBlt 操作将 SkCanvas 的内容复制到 HDC

      HDC hdc = (HDC)ctx;
      const SkBitmap& bitmap = this->getBitmap();
      
      BITMAPINFO bmi;
      memset(&bmi, 0, sizeof(bmi));
      bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
      bmi.bmiHeader.biWidth = bitmap.width();
      bmi.bmiHeader.biHeight = -bitmap.height(); // top-down image
      bmi.bmiHeader.biPlanes = 1;
      bmi.bmiHeader.biBitCount = 32;
      bmi.bmiHeader.biCompression = BI_RGB;
      bmi.bmiHeader.biSizeImage = 0;
      
      //
      // Do the SetDIBitsToDevice.
      //
      // TODO(wjmaclean):
      //       Fix this call to handle SkBitmaps that have rowBytes != width,
      //       i.e. may have padding at the end of lines. The SkASSERT below
      //       may be ignored by builds, and the only obviously safe option
      //       seems to be to copy the bitmap to a temporary (contiguous)
      //       buffer before passing to SetDIBitsToDevice().
      SkASSERT(bitmap.width() * bitmap.bytesPerPixel() == bitmap.rowBytes());
      bitmap.lockPixels();
      int ret = SetDIBitsToDevice(hdc,
          0, 0,
          bitmap.width(), bitmap.height(),
          0, 0,
          0, bitmap.height(),
          bitmap.getPixels(),
          &bmi,
          DIB_RGB_COLORS);
      (void)ret; // we're ignoring potential failures for now.
      bitmap.unlockPixels();
      

    【讨论】:

    • 我认为解决方案 2 是最好的方法。
    • 这取决于你想要得到什么。 #2 产生可预测的渲染结果并且更健壮,但不使用 OpenGL,因此速度显着变慢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-06
    • 2013-08-01
    • 2023-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多