// Copyright 2018 The Chromium Embedded Framework Authors. All rights // reserved. Use of this source code is governed by a BSD-style license that // can be found in the LICENSE file. #include "tests/cefclient/browser/osr_render_handler_win_gl.h" #include "include/base/cef_callback.h" #include "include/wrapper/cef_closure_task.h" #include "include/wrapper/cef_helpers.h" #include "tests/shared/browser/util_win.h" namespace client { namespace { // Helper that calls wglMakeCurrent. class ScopedGLContext { public: ScopedGLContext(HDC hdc, HGLRC hglrc, bool swap_buffers) : hdc_(hdc), swap_buffers_(swap_buffers) { [[maybe_unused]] BOOL result = wglMakeCurrent(hdc, hglrc); DCHECK(result); } ~ScopedGLContext() { BOOL result = wglMakeCurrent(nullptr, nullptr); DCHECK(result); if (swap_buffers_) { result = SwapBuffers(hdc_); DCHECK(result); } } private: const HDC hdc_; const bool swap_buffers_; }; } // namespace OsrRenderHandlerWinGL::OsrRenderHandlerWinGL( const OsrRendererSettings& settings, HWND hwnd) : OsrRenderHandlerWin(settings, hwnd), renderer_(settings) {} void OsrRenderHandlerWinGL::Initialize(CefRefPtr browser) { CEF_REQUIRE_UI_THREAD(); SetBrowser(browser); } OsrRenderHandlerWinGL::~OsrRenderHandlerWinGL() { CEF_REQUIRE_UI_THREAD(); DisableGL(); } void OsrRenderHandlerWinGL::SetSpin(float spinX, float spinY) { CEF_REQUIRE_UI_THREAD(); renderer_.SetSpin(spinX, spinY); Invalidate(); } void OsrRenderHandlerWinGL::IncrementSpin(float spinDX, float spinDY) { CEF_REQUIRE_UI_THREAD(); renderer_.IncrementSpin(spinDX, spinDY); Invalidate(); } bool OsrRenderHandlerWinGL::IsOverPopupWidget(int x, int y) const { CEF_REQUIRE_UI_THREAD(); const CefRect& rc = renderer_.popup_rect(); int popup_right = rc.x + rc.width; int popup_bottom = rc.y + rc.height; return (x >= rc.x) && (x < popup_right) && (y >= rc.y) && (y < popup_bottom); } int OsrRenderHandlerWinGL::GetPopupXOffset() const { CEF_REQUIRE_UI_THREAD(); return renderer_.original_popup_rect().x - renderer_.popup_rect().x; } int OsrRenderHandlerWinGL::GetPopupYOffset() const { CEF_REQUIRE_UI_THREAD(); return renderer_.original_popup_rect().y - renderer_.popup_rect().y; } void OsrRenderHandlerWinGL::OnPopupShow(CefRefPtr browser, bool show) { CEF_REQUIRE_UI_THREAD(); if (!show) { renderer_.ClearPopupRects(); browser->GetHost()->Invalidate(PET_VIEW); } renderer_.OnPopupShow(browser, show); } void OsrRenderHandlerWinGL::OnPopupSize(CefRefPtr browser, const CefRect& rect) { CEF_REQUIRE_UI_THREAD(); renderer_.OnPopupSize(browser, rect); } void OsrRenderHandlerWinGL::OnPaint( CefRefPtr browser, CefRenderHandler::PaintElementType type, const CefRenderHandler::RectList& dirtyRects, const void* buffer, int width, int height) { CEF_REQUIRE_UI_THREAD(); if (painting_popup_) { renderer_.OnPaint(browser, type, dirtyRects, buffer, width, height); return; } if (!hdc_) { EnableGL(); } ScopedGLContext scoped_gl_context(hdc_, hrc_, true); renderer_.OnPaint(browser, type, dirtyRects, buffer, width, height); if (type == PET_VIEW && !renderer_.popup_rect().IsEmpty()) { painting_popup_ = true; browser->GetHost()->Invalidate(PET_POPUP); painting_popup_ = false; } renderer_.Render(); } void OsrRenderHandlerWinGL::OnAcceleratedPaint( CefRefPtr browser, CefRenderHandler::PaintElementType type, const CefRenderHandler::RectList& dirtyRects, const CefAcceleratedPaintInfo& info) { // Not used with this implementation. NOTREACHED(); } void OsrRenderHandlerWinGL::Render() { if (!hdc_) { EnableGL(); } ScopedGLContext scoped_gl_context(hdc_, hrc_, true); renderer_.Render(); } void OsrRenderHandlerWinGL::EnableGL() { PIXELFORMATDESCRIPTOR pfd; int format; // Get the device context. hdc_ = GetDC(hwnd()); // Set the pixel format for the DC. ZeroMemory(&pfd, sizeof(pfd)); pfd.nSize = sizeof(pfd); pfd.nVersion = 1; pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER; pfd.iPixelType = PFD_TYPE_RGBA; pfd.cColorBits = 24; pfd.cDepthBits = 16; pfd.iLayerType = PFD_MAIN_PLANE; format = ChoosePixelFormat(hdc_, &pfd); SetPixelFormat(hdc_, format, &pfd); // Create and enable the render context. hrc_ = wglCreateContext(hdc_); ScopedGLContext scoped_gl_context(hdc_, hrc_, false); renderer_.Initialize(); } void OsrRenderHandlerWinGL::DisableGL() { if (!hdc_) { return; } { ScopedGLContext scoped_gl_context(hdc_, hrc_, false); renderer_.Cleanup(); } if (IsWindow(hwnd())) { // wglDeleteContext will make the context not current before deleting it. [[maybe_unused]] BOOL result = wglDeleteContext(hrc_); DCHECK(result); ReleaseDC(hwnd(), hdc_); } hdc_ = nullptr; hrc_ = nullptr; } } // namespace client