diff --git a/src/she/skia/skia_surface.h b/src/she/skia/skia_surface.h index a665cad91..d888482f5 100644 --- a/src/she/skia/skia_surface.h +++ b/src/she/skia/skia_surface.h @@ -40,9 +40,12 @@ public: SkiaSurface(SkSurface* surface) : m_surface(surface) - , m_canvas(m_surface->getCanvas()) + , m_canvas(nullptr) , m_clip(0, 0, width(), height()) { + ASSERT(m_surface); + if (m_surface) + m_canvas = m_surface->getCanvas(); } ~SkiaSurface() { diff --git a/src/she/skia/skia_window_win.cpp b/src/she/skia/skia_window_win.cpp index 41f17972e..1e426c288 100644 --- a/src/she/skia/skia_window_win.cpp +++ b/src/she/skia/skia_window_win.cpp @@ -76,13 +76,35 @@ void SkiaWindow::paintImpl(HDC hdc) surface->flush(); } + // If we are drawing inside an off-screen texture, here we have + // to blit that texture into the main framebuffer. + if (m_skSurfaceDirect != m_skSurface) { + GrBackendObject texID = m_skSurface->getTextureHandle( + SkSurface::kFlushRead_BackendHandleAccess); + + GrBackendTextureDesc texDesc; + texDesc.fFlags = kNone_GrBackendTextureFlag; + texDesc.fOrigin = kBottomLeft_GrSurfaceOrigin; + texDesc.fWidth = m_lastSize.w / scale(); + texDesc.fHeight = m_lastSize.h / scale(); + texDesc.fConfig = kSkia8888_GrPixelConfig; + texDesc.fSampleCnt = m_sampleCount; + texDesc.fTextureHandle = texID; + SkAutoTUnref image(SkImage::NewFromTexture(m_grCtx, texDesc)); + + SkRect dstRect(SkRect::MakeWH(SkIntToScalar(m_lastSize.w), + SkIntToScalar(m_lastSize.h))); + + SkPaint paint; + m_skSurfaceDirect->getCanvas()->drawImageRect( + image, dstRect, &paint, + SkCanvas::kStrict_SrcRectConstraint); + + m_skSurfaceDirect->getCanvas()->flush(); + } + // Flush GL context m_grInterface->fFunctions.fFlush(); - - // We don't use double-buffer - //ASSERT(m_glCtx); - //if (m_glCtx) - // m_glCtx->swapBuffers(); break; #endif // SK_SUPPORT_GPU @@ -157,6 +179,9 @@ bool SkiaWindow::attachANGLE() void SkiaWindow::detachGL() { + m_skSurfaceDirect.reset(nullptr); + m_skSurface.reset(nullptr); + m_grRenderTarget.reset(nullptr); m_grCtx.reset(nullptr); m_grInterface.reset(nullptr); m_glCtx.reset(nullptr); @@ -164,20 +189,39 @@ void SkiaWindow::detachGL() void SkiaWindow::createRenderTarget(const gfx::Size& size) { + auto gl = &m_grInterface->fFunctions; + + int scale = m_display->scale(); + m_lastSize = size; + GrBackendRenderTargetDesc desc; - desc.fWidth = size.w / m_display->scale(); - desc.fHeight = size.h / m_display->scale(); + desc.fWidth = size.w; + desc.fHeight = size.h; desc.fConfig = kSkia8888_GrPixelConfig; desc.fOrigin = kBottomLeft_GrSurfaceOrigin; desc.fSampleCnt = m_sampleCount; desc.fStencilBits = m_stencilBits; - GrGLint buffer; - m_grInterface->fFunctions.fGetIntegerv(0x8CA6, &buffer); // GL_FRAMEBUFFER_BINDING = 0x8CA6 - desc.fRenderTargetHandle = buffer; - + desc.fRenderTargetHandle = 0; // direct frame buffer m_grRenderTarget.reset(m_grCtx->textureProvider()->wrapBackendRenderTarget(desc)); + m_skSurfaceDirect.reset( + SkSurface::NewRenderTargetDirect(m_grRenderTarget)); + + if (scale == 1) { + m_skSurface.reset(m_skSurfaceDirect); + } + else { + m_skSurface.reset( + SkSurface::NewRenderTarget( + m_grCtx, + SkSurface::kYes_Budgeted, + SkImageInfo::MakeN32Premul(MAX(1, size.w / scale), + MAX(1, size.h / scale)), + m_sampleCount)); + } + + if (!m_skSurface) + throw std::runtime_error("Error creating OpenGL surface for main display"); - m_skSurface.reset(SkSurface::NewRenderTargetDirect(m_grRenderTarget)); m_display->setSkiaSurface(new SkiaSurface(m_skSurface)); } diff --git a/src/she/skia/skia_window_win.h b/src/she/skia/skia_window_win.h index 4c3b272c5..d062b6bc5 100644 --- a/src/she/skia/skia_window_win.h +++ b/src/she/skia/skia_window_win.h @@ -52,9 +52,11 @@ private: SkAutoTUnref m_grInterface; SkAutoTUnref m_grCtx; SkAutoTUnref m_grRenderTarget; + SkAutoTDelete m_skSurfaceDirect; SkAutoTDelete m_skSurface; int m_sampleCount; int m_stencilBits; + gfx::Size m_lastSize; #endif // SK_SUPPORT_GPU DISABLE_COPYING(SkiaWindow);