1 //
2 // Copyright 2015 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 // WindowSurfaceWGL.cpp: WGL implementation of egl::Surface for windows
8
9 #include "libANGLE/renderer/gl/wgl/WindowSurfaceWGL.h"
10
11 #include "common/debug.h"
12 #include "libANGLE/renderer/gl/RendererGL.h"
13 #include "libANGLE/renderer/gl/wgl/FunctionsWGL.h"
14 #include "libANGLE/renderer/gl/wgl/wgl_utils.h"
15
16 namespace rx
17 {
18
WindowSurfaceWGL(const egl::SurfaceState & state,EGLNativeWindowType window,int pixelFormat,const FunctionsWGL * functions,EGLint orientation)19 WindowSurfaceWGL::WindowSurfaceWGL(const egl::SurfaceState &state,
20 EGLNativeWindowType window,
21 int pixelFormat,
22 const FunctionsWGL *functions,
23 EGLint orientation)
24 : SurfaceWGL(state),
25 mPixelFormat(pixelFormat),
26 mWindow(window),
27 mDeviceContext(nullptr),
28 mFunctionsWGL(functions),
29 mSwapBehavior(0)
30 {
31 // EGL_ANGLE_surface_orientation is not supported for regular WGL window surfaces
32 ASSERT(orientation == 0);
33 }
34
~WindowSurfaceWGL()35 WindowSurfaceWGL::~WindowSurfaceWGL()
36 {
37 ReleaseDC(mWindow, mDeviceContext);
38 mDeviceContext = nullptr;
39 }
40
initialize(const egl::Display * display)41 egl::Error WindowSurfaceWGL::initialize(const egl::Display *display)
42 {
43 mDeviceContext = GetDC(mWindow);
44 if (!mDeviceContext)
45 {
46 return egl::EglBadNativeWindow()
47 << "Failed to get the device context from the native window, "
48 << gl::FmtErr(GetLastError());
49 }
50
51 // Require that the pixel format for this window has not been set yet or is equal to the
52 // Display's pixel format.
53 int windowPixelFormat = GetPixelFormat(mDeviceContext);
54 if (windowPixelFormat == 0)
55 {
56 PIXELFORMATDESCRIPTOR pixelFormatDescriptor = {};
57 if (!DescribePixelFormat(mDeviceContext, mPixelFormat, sizeof(pixelFormatDescriptor),
58 &pixelFormatDescriptor))
59 {
60 return egl::EglBadNativeWindow()
61 << "Failed to DescribePixelFormat, " << gl::FmtErr(GetLastError());
62 }
63
64 if (!SetPixelFormat(mDeviceContext, mPixelFormat, &pixelFormatDescriptor))
65 {
66 return egl::EglNotInitialized()
67 << "Failed to set the pixel format on the device context, "
68 << gl::FmtErr(GetLastError());
69 }
70 }
71 else if (windowPixelFormat != mPixelFormat)
72 {
73 return egl::EglNotInitialized()
74 << "Pixel format of the NativeWindow and NativeDisplayType must match.";
75 }
76
77 // Check for the swap behavior of this pixel format
78 switch (
79 wgl::QueryWGLFormatAttrib(mDeviceContext, mPixelFormat, WGL_SWAP_METHOD_ARB, mFunctionsWGL))
80 {
81 case WGL_SWAP_COPY_ARB:
82 mSwapBehavior = EGL_BUFFER_PRESERVED;
83 break;
84
85 case WGL_SWAP_EXCHANGE_ARB:
86 case WGL_SWAP_UNDEFINED_ARB:
87 default:
88 mSwapBehavior = EGL_BUFFER_DESTROYED;
89 break;
90 }
91
92 return egl::NoError();
93 }
94
makeCurrent(const gl::Context * context)95 egl::Error WindowSurfaceWGL::makeCurrent(const gl::Context *context)
96 {
97 return egl::NoError();
98 }
99
swap(const gl::Context * context)100 egl::Error WindowSurfaceWGL::swap(const gl::Context *context)
101 {
102 if (!mFunctionsWGL->swapBuffers(mDeviceContext))
103 {
104 // TODO: What error type here?
105 return egl::EglContextLost() << "Failed to swap buffers on the child window.";
106 }
107
108 return egl::NoError();
109 }
110
postSubBuffer(const gl::Context * context,EGLint x,EGLint y,EGLint width,EGLint height)111 egl::Error WindowSurfaceWGL::postSubBuffer(const gl::Context *context,
112 EGLint x,
113 EGLint y,
114 EGLint width,
115 EGLint height)
116 {
117 UNIMPLEMENTED();
118 return egl::NoError();
119 }
120
querySurfacePointerANGLE(EGLint attribute,void ** value)121 egl::Error WindowSurfaceWGL::querySurfacePointerANGLE(EGLint attribute, void **value)
122 {
123 *value = nullptr;
124 return egl::NoError();
125 }
126
bindTexImage(const gl::Context * context,gl::Texture * texture,EGLint buffer)127 egl::Error WindowSurfaceWGL::bindTexImage(const gl::Context *context,
128 gl::Texture *texture,
129 EGLint buffer)
130 {
131 UNIMPLEMENTED();
132 return egl::NoError();
133 }
134
releaseTexImage(const gl::Context * context,EGLint buffer)135 egl::Error WindowSurfaceWGL::releaseTexImage(const gl::Context *context, EGLint buffer)
136 {
137 UNIMPLEMENTED();
138 return egl::NoError();
139 }
140
setSwapInterval(const egl::Display * display,EGLint interval)141 void WindowSurfaceWGL::setSwapInterval(const egl::Display *display, EGLint interval)
142 {
143 if (mFunctionsWGL->swapIntervalEXT)
144 {
145 mFunctionsWGL->swapIntervalEXT(interval);
146 }
147 }
148
getWidth() const149 EGLint WindowSurfaceWGL::getWidth() const
150 {
151 RECT rect;
152 if (!GetClientRect(mWindow, &rect))
153 {
154 return 0;
155 }
156 return rect.right - rect.left;
157 }
158
getHeight() const159 EGLint WindowSurfaceWGL::getHeight() const
160 {
161 RECT rect;
162 if (!GetClientRect(mWindow, &rect))
163 {
164 return 0;
165 }
166 return rect.bottom - rect.top;
167 }
168
isPostSubBufferSupported() const169 EGLint WindowSurfaceWGL::isPostSubBufferSupported() const
170 {
171 // PostSubBuffer extension not exposed on WGL.
172 UNIMPLEMENTED();
173 return EGL_FALSE;
174 }
175
getSwapBehavior() const176 EGLint WindowSurfaceWGL::getSwapBehavior() const
177 {
178 return mSwapBehavior;
179 }
180
getDC() const181 HDC WindowSurfaceWGL::getDC() const
182 {
183 return mDeviceContext;
184 }
185 } // namespace rx
186