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 std::ostringstream err;
47 err << "Failed to get the device context from the native window, "
48 << gl::FmtErr(GetLastError());
49 return egl::Error(EGL_BAD_NATIVE_WINDOW, err.str());
50 }
51
52 // Require that the pixel format for this window has not been set yet or is equal to the
53 // Display's pixel format.
54 int windowPixelFormat = GetPixelFormat(mDeviceContext);
55 if (windowPixelFormat == 0)
56 {
57 PIXELFORMATDESCRIPTOR pixelFormatDescriptor = {};
58 if (!DescribePixelFormat(mDeviceContext, mPixelFormat, sizeof(pixelFormatDescriptor),
59 &pixelFormatDescriptor))
60 {
61 std::ostringstream err;
62 err << "Failed to DescribePixelFormat, " << gl::FmtErr(GetLastError());
63 return egl::Error(EGL_BAD_NATIVE_WINDOW, err.str());
64 }
65
66 if (!SetPixelFormat(mDeviceContext, mPixelFormat, &pixelFormatDescriptor))
67 {
68 std::ostringstream err;
69 err << "Failed to set the pixel format on the device context, "
70 << gl::FmtErr(GetLastError());
71 return egl::Error(EGL_NOT_INITIALIZED, err.str());
72 }
73 }
74 else if (windowPixelFormat != mPixelFormat)
75 {
76 return egl::Error(EGL_NOT_INITIALIZED,
77 "Pixel format of the NativeWindow and NativeDisplayType must match.");
78 }
79
80 // Check for the swap behavior of this pixel format
81 switch (
82 wgl::QueryWGLFormatAttrib(mDeviceContext, mPixelFormat, WGL_SWAP_METHOD_ARB, mFunctionsWGL))
83 {
84 case WGL_SWAP_COPY_ARB:
85 mSwapBehavior = EGL_BUFFER_PRESERVED;
86 break;
87
88 case WGL_SWAP_EXCHANGE_ARB:
89 case WGL_SWAP_UNDEFINED_ARB:
90 default:
91 mSwapBehavior = EGL_BUFFER_DESTROYED;
92 break;
93 }
94
95 return egl::NoError();
96 }
97
makeCurrent(const gl::Context * context)98 egl::Error WindowSurfaceWGL::makeCurrent(const gl::Context *context)
99 {
100 return egl::NoError();
101 }
102
swap(const gl::Context * context,SurfaceSwapFeedback * feedback)103 egl::Error WindowSurfaceWGL::swap(const gl::Context *context, SurfaceSwapFeedback *feedback)
104 {
105 if (!mFunctionsWGL->swapBuffers(mDeviceContext))
106 {
107 // TODO: What error type here?
108 return egl::Error(EGL_CONTEXT_LOST, "Failed to swap buffers on the child window.");
109 }
110
111 return egl::NoError();
112 }
113
postSubBuffer(const gl::Context * context,EGLint x,EGLint y,EGLint width,EGLint height)114 egl::Error WindowSurfaceWGL::postSubBuffer(const gl::Context *context,
115 EGLint x,
116 EGLint y,
117 EGLint width,
118 EGLint height)
119 {
120 UNIMPLEMENTED();
121 return egl::NoError();
122 }
123
querySurfacePointerANGLE(EGLint attribute,void ** value)124 egl::Error WindowSurfaceWGL::querySurfacePointerANGLE(EGLint attribute, void **value)
125 {
126 *value = nullptr;
127 return egl::NoError();
128 }
129
bindTexImage(const gl::Context * context,gl::Texture * texture,EGLint buffer)130 egl::Error WindowSurfaceWGL::bindTexImage(const gl::Context *context,
131 gl::Texture *texture,
132 EGLint buffer)
133 {
134 UNIMPLEMENTED();
135 return egl::NoError();
136 }
137
releaseTexImage(const gl::Context * context,EGLint buffer)138 egl::Error WindowSurfaceWGL::releaseTexImage(const gl::Context *context, EGLint buffer)
139 {
140 UNIMPLEMENTED();
141 return egl::NoError();
142 }
143
setSwapInterval(const egl::Display * display,EGLint interval)144 void WindowSurfaceWGL::setSwapInterval(const egl::Display *display, EGLint interval)
145 {
146 if (mFunctionsWGL->swapIntervalEXT)
147 {
148 mFunctionsWGL->swapIntervalEXT(interval);
149 }
150 }
151
getWidth() const152 EGLint WindowSurfaceWGL::getWidth() const
153 {
154 RECT rect;
155 if (!GetClientRect(mWindow, &rect))
156 {
157 return 0;
158 }
159 return rect.right - rect.left;
160 }
161
getHeight() const162 EGLint WindowSurfaceWGL::getHeight() const
163 {
164 RECT rect;
165 if (!GetClientRect(mWindow, &rect))
166 {
167 return 0;
168 }
169 return rect.bottom - rect.top;
170 }
171
isPostSubBufferSupported() const172 EGLint WindowSurfaceWGL::isPostSubBufferSupported() const
173 {
174 // PostSubBuffer extension not exposed on WGL.
175 UNIMPLEMENTED();
176 return EGL_FALSE;
177 }
178
getSwapBehavior() const179 EGLint WindowSurfaceWGL::getSwapBehavior() const
180 {
181 return mSwapBehavior;
182 }
183
getDC() const184 HDC WindowSurfaceWGL::getDC() const
185 {
186 return mDeviceContext;
187 }
188 } // namespace rx
189