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 |