| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/gl/gl_surface.h" | 5 #include "ui/gl/gl_surface.h" |
| 6 | 6 |
| 7 #include <dwmapi.h> | 7 #include <dwmapi.h> |
| 8 | 8 |
| 9 #include <memory> | |
| 10 | |
| 11 #include "base/command_line.h" | |
| 12 #include "base/logging.h" | |
| 13 #include "base/macros.h" | |
| 14 #include "base/trace_event/trace_event.h" | |
| 15 #include "base/win/windows_version.h" | |
| 16 #include "ui/gfx/native_widget_types.h" | |
| 17 #include "ui/gl/gl_bindings.h" | |
| 18 #include "ui/gl/gl_implementation.h" | |
| 19 #include "ui/gl/gl_surface_egl.h" | 9 #include "ui/gl/gl_surface_egl.h" |
| 20 #include "ui/gl/gl_surface_osmesa.h" | |
| 21 #include "ui/gl/gl_surface_stub.h" | |
| 22 #include "ui/gl/gl_surface_wgl.h" | |
| 23 #include "ui/gl/vsync_provider_win.h" | |
| 24 | |
| 25 // From ANGLE's egl/eglext.h. | |
| 26 #if !defined(EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE) | |
| 27 #define EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE \ | |
| 28 reinterpret_cast<EGLNativeDisplayType>(-2) | |
| 29 #endif | |
| 30 | 10 |
| 31 namespace gl { | 11 namespace gl { |
| 32 | 12 |
| 33 // This OSMesa GL surface can use GDI to swap the contents of the buffer to a | |
| 34 // view. | |
| 35 class NativeViewGLSurfaceOSMesa : public GLSurfaceOSMesa { | |
| 36 public: | |
| 37 explicit NativeViewGLSurfaceOSMesa(gfx::AcceleratedWidget window); | |
| 38 | |
| 39 // Implement subset of GLSurface. | |
| 40 bool Initialize(GLSurface::Format format) override; | |
| 41 void Destroy() override; | |
| 42 bool IsOffscreen() override; | |
| 43 gfx::SwapResult SwapBuffers() override; | |
| 44 bool SupportsPostSubBuffer() override; | |
| 45 gfx::SwapResult PostSubBuffer(int x, int y, int width, int height) override; | |
| 46 | |
| 47 private: | |
| 48 ~NativeViewGLSurfaceOSMesa() override; | |
| 49 | |
| 50 gfx::AcceleratedWidget window_; | |
| 51 HDC device_context_; | |
| 52 | |
| 53 DISALLOW_COPY_AND_ASSIGN(NativeViewGLSurfaceOSMesa); | |
| 54 }; | |
| 55 | |
| 56 NativeViewGLSurfaceOSMesa::NativeViewGLSurfaceOSMesa( | |
| 57 gfx::AcceleratedWidget window) | |
| 58 : GLSurfaceOSMesa(SURFACE_OSMESA_RGBA, gfx::Size(1, 1)), | |
| 59 window_(window), | |
| 60 device_context_(NULL) { | |
| 61 DCHECK(window); | |
| 62 } | |
| 63 | |
| 64 NativeViewGLSurfaceOSMesa::~NativeViewGLSurfaceOSMesa() { | |
| 65 Destroy(); | |
| 66 } | |
| 67 | |
| 68 bool NativeViewGLSurfaceOSMesa::Initialize(GLSurface::Format format) { | |
| 69 if (!GLSurfaceOSMesa::Initialize(format)) | |
| 70 return false; | |
| 71 | |
| 72 device_context_ = GetDC(window_); | |
| 73 return true; | |
| 74 } | |
| 75 | |
| 76 void NativeViewGLSurfaceOSMesa::Destroy() { | |
| 77 if (window_ && device_context_) | |
| 78 ReleaseDC(window_, device_context_); | |
| 79 | |
| 80 device_context_ = NULL; | |
| 81 | |
| 82 GLSurfaceOSMesa::Destroy(); | |
| 83 } | |
| 84 | |
| 85 bool NativeViewGLSurfaceOSMesa::IsOffscreen() { | |
| 86 return false; | |
| 87 } | |
| 88 | |
| 89 gfx::SwapResult NativeViewGLSurfaceOSMesa::SwapBuffers() { | |
| 90 DCHECK(device_context_); | |
| 91 | |
| 92 gfx::Size size = GetSize(); | |
| 93 | |
| 94 // Note: negating the height below causes GDI to treat the bitmap data as row | |
| 95 // 0 being at the top. | |
| 96 BITMAPV4HEADER info = { sizeof(BITMAPV4HEADER) }; | |
| 97 info.bV4Width = size.width(); | |
| 98 info.bV4Height = -size.height(); | |
| 99 info.bV4Planes = 1; | |
| 100 info.bV4BitCount = 32; | |
| 101 info.bV4V4Compression = BI_BITFIELDS; | |
| 102 info.bV4RedMask = 0x000000FF; | |
| 103 info.bV4GreenMask = 0x0000FF00; | |
| 104 info.bV4BlueMask = 0x00FF0000; | |
| 105 info.bV4AlphaMask = 0xFF000000; | |
| 106 | |
| 107 // Copy the back buffer to the window's device context. Do not check whether | |
| 108 // StretchDIBits succeeds or not. It will fail if the window has been | |
| 109 // destroyed but it is preferable to allow rendering to silently fail if the | |
| 110 // window is destroyed. This is because the primary application of this | |
| 111 // class of GLContext is for testing and we do not want every GL related ui / | |
| 112 // browser test to become flaky if there is a race condition between GL | |
| 113 // context destruction and window destruction. | |
| 114 StretchDIBits(device_context_, | |
| 115 0, 0, size.width(), size.height(), | |
| 116 0, 0, size.width(), size.height(), | |
| 117 GetHandle(), | |
| 118 reinterpret_cast<BITMAPINFO*>(&info), | |
| 119 DIB_RGB_COLORS, | |
| 120 SRCCOPY); | |
| 121 | |
| 122 return gfx::SwapResult::SWAP_ACK; | |
| 123 } | |
| 124 | |
| 125 bool NativeViewGLSurfaceOSMesa::SupportsPostSubBuffer() { | |
| 126 return true; | |
| 127 } | |
| 128 | |
| 129 gfx::SwapResult NativeViewGLSurfaceOSMesa::PostSubBuffer(int x, | |
| 130 int y, | |
| 131 int width, | |
| 132 int height) { | |
| 133 DCHECK(device_context_); | |
| 134 | |
| 135 gfx::Size size = GetSize(); | |
| 136 | |
| 137 // Note: negating the height below causes GDI to treat the bitmap data as row | |
| 138 // 0 being at the top. | |
| 139 BITMAPV4HEADER info = { sizeof(BITMAPV4HEADER) }; | |
| 140 info.bV4Width = size.width(); | |
| 141 info.bV4Height = -size.height(); | |
| 142 info.bV4Planes = 1; | |
| 143 info.bV4BitCount = 32; | |
| 144 info.bV4V4Compression = BI_BITFIELDS; | |
| 145 info.bV4RedMask = 0x000000FF; | |
| 146 info.bV4GreenMask = 0x0000FF00; | |
| 147 info.bV4BlueMask = 0x00FF0000; | |
| 148 info.bV4AlphaMask = 0xFF000000; | |
| 149 | |
| 150 // Copy the back buffer to the window's device context. Do not check whether | |
| 151 // StretchDIBits succeeds or not. It will fail if the window has been | |
| 152 // destroyed but it is preferable to allow rendering to silently fail if the | |
| 153 // window is destroyed. This is because the primary application of this | |
| 154 // class of GLContext is for testing and we do not want every GL related ui / | |
| 155 // browser test to become flaky if there is a race condition between GL | |
| 156 // context destruction and window destruction. | |
| 157 StretchDIBits(device_context_, | |
| 158 x, size.height() - y - height, width, height, | |
| 159 x, y, width, height, | |
| 160 GetHandle(), | |
| 161 reinterpret_cast<BITMAPINFO*>(&info), | |
| 162 DIB_RGB_COLORS, | |
| 163 SRCCOPY); | |
| 164 | |
| 165 return gfx::SwapResult::SWAP_ACK; | |
| 166 } | |
| 167 | |
| 168 scoped_refptr<GLSurface> GLSurface::CreateViewGLSurface( | |
| 169 gfx::AcceleratedWidget window) { | |
| 170 TRACE_EVENT0("gpu", "GLSurface::CreateViewGLSurface"); | |
| 171 switch (GetGLImplementation()) { | |
| 172 case kGLImplementationOSMesaGL: { | |
| 173 scoped_refptr<GLSurface> surface( | |
| 174 new NativeViewGLSurfaceOSMesa(window)); | |
| 175 if (!surface->Initialize()) | |
| 176 return NULL; | |
| 177 | |
| 178 return surface; | |
| 179 } | |
| 180 case kGLImplementationEGLGLES2: { | |
| 181 DCHECK(window != gfx::kNullAcceleratedWidget); | |
| 182 scoped_refptr<NativeViewGLSurfaceEGL> surface( | |
| 183 new NativeViewGLSurfaceEGL(window)); | |
| 184 std::unique_ptr<gfx::VSyncProvider> sync_provider; | |
| 185 sync_provider.reset(new VSyncProviderWin(window)); | |
| 186 if (!surface->Initialize(std::move(sync_provider))) | |
| 187 return NULL; | |
| 188 | |
| 189 return surface; | |
| 190 } | |
| 191 case kGLImplementationDesktopGL: { | |
| 192 scoped_refptr<GLSurface> surface(new NativeViewGLSurfaceWGL( | |
| 193 window)); | |
| 194 if (!surface->Initialize()) | |
| 195 return NULL; | |
| 196 | |
| 197 return surface; | |
| 198 } | |
| 199 case kGLImplementationMockGL: | |
| 200 return new GLSurfaceStub; | |
| 201 default: | |
| 202 NOTREACHED(); | |
| 203 return NULL; | |
| 204 } | |
| 205 } | |
| 206 | |
| 207 scoped_refptr<GLSurface> GLSurface::CreateOffscreenGLSurface( | |
| 208 const gfx::Size& size) { | |
| 209 TRACE_EVENT0("gpu", "GLSurface::CreateOffscreenGLSurface"); | |
| 210 switch (GetGLImplementation()) { | |
| 211 case kGLImplementationOSMesaGL: { | |
| 212 scoped_refptr<GLSurface> surface( | |
| 213 new GLSurfaceOSMesa(SURFACE_OSMESA_RGBA, size)); | |
| 214 if (!surface->Initialize()) | |
| 215 return NULL; | |
| 216 | |
| 217 return surface; | |
| 218 } | |
| 219 case kGLImplementationEGLGLES2: { | |
| 220 scoped_refptr<GLSurface> surface(new PbufferGLSurfaceEGL(size)); | |
| 221 if (!surface->Initialize()) | |
| 222 return NULL; | |
| 223 | |
| 224 return surface; | |
| 225 } | |
| 226 case kGLImplementationDesktopGL: { | |
| 227 scoped_refptr<GLSurface> surface(new PbufferGLSurfaceWGL(size)); | |
| 228 if (!surface->Initialize()) | |
| 229 return NULL; | |
| 230 | |
| 231 return surface; | |
| 232 } | |
| 233 case kGLImplementationMockGL: | |
| 234 return new GLSurfaceStub; | |
| 235 default: | |
| 236 NOTREACHED(); | |
| 237 return NULL; | |
| 238 } | |
| 239 } | |
| 240 | |
| 241 EGLNativeDisplayType GetPlatformDefaultEGLNativeDisplay() { | 13 EGLNativeDisplayType GetPlatformDefaultEGLNativeDisplay() { |
| 242 return GetDC(NULL); | 14 return GetDC(NULL); |
| 243 } | 15 } |
| 244 | 16 |
| 245 } // namespace gl | 17 } // namespace gl |
| OLD | NEW |