1 //
2 // Copyright © 2019 Jamie Madill
3 //
4 // This file is part of the glmark2 OpenGL (ES) 2.0 benchmark.
5 //
6 // glmark2 is free software: you can redistribute it and/or modify it under the
7 // terms of the GNU General Public License as published by the Free Software
8 // Foundation, either version 3 of the License, or (at your option) any later
9 // version.
10 //
11 // glmark2 is distributed in the hope that it will be useful, but WITHOUT ANY
12 // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 // FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14 // details.
15 //
16 // You should have received a copy of the GNU General Public License along with
17 // glmark2. If not, see <http://www.gnu.org/licenses/>.
18 //
19 // Authors:
20 // Jamie Madill
21 //
22 #include "gl-state-wgl.h"
23
24 #include <glad/wgl.h>
25 #include "gl-headers.h"
26 #include "log.h"
27 #include "options.h"
28
29 /******************
30 * Public methods *
31 ******************/
32
GLStateWGL()33 GLStateWGL::GLStateWGL() : hdc_(nullptr), wgl_context_(nullptr), get_proc_addr_(nullptr) {}
34
~GLStateWGL()35 GLStateWGL::~GLStateWGL()
36 {
37 if (wgl_context_) {
38 wglDeleteContext(wgl_context_);
39 wgl_context_ = nullptr;
40 }
41 }
42
43 bool
init_display(void * native_display,GLVisualConfig &)44 GLStateWGL::init_display(void* native_display, GLVisualConfig& /*visual_config*/)
45 {
46 if (!wgl_library_.open("opengl32.dll")) {
47 Log::error("Failed to load opengl32.dll\n");
48 return false;
49 }
50
51 hdc_ = reinterpret_cast<HDC>(native_display);
52
53 PIXELFORMATDESCRIPTOR pixel_format_desc = {};
54 pixel_format_desc.nSize = sizeof(pixel_format_desc);
55 pixel_format_desc.nVersion = 1;
56 pixel_format_desc.dwFlags =
57 PFD_DRAW_TO_WINDOW | PFD_GENERIC_ACCELERATED | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
58 pixel_format_desc.iPixelType = PFD_TYPE_RGBA;
59 pixel_format_desc.cColorBits = 24;
60 pixel_format_desc.cAlphaBits = 8;
61 pixel_format_desc.cDepthBits = 24;
62 pixel_format_desc.cStencilBits = 8;
63 pixel_format_desc.iLayerType = PFD_MAIN_PLANE;
64
65 int pixelFormat = ChoosePixelFormat(hdc_, &pixel_format_desc);
66 if (pixelFormat == 0) {
67 Log::error("Could not find a compatible pixel format\n");
68 return false;
69 }
70
71 if (SetPixelFormat(hdc_, pixelFormat, &pixel_format_desc) != TRUE) {
72 Log::error("Failed to set the pixel format\n");
73 return false;
74 }
75
76 wgl_context_ = wglCreateContext(hdc_);
77 if (!wgl_context_) {
78 Log::error("Failed to create a WGL context\n");
79 return false;
80 }
81
82 if (wglMakeCurrent(hdc_, wgl_context_) == FALSE) {
83 Log::error("Error during wglMakeCurrent\n");
84 return false;
85 }
86
87 get_proc_addr_ = wgl_library_.load("wglGetProcAddress");
88 if (!get_proc_addr_) {
89 Log::error("Failed to find wglGetProcAddress\n");
90 return false;
91 }
92
93 if (gladLoadGLUserPtr(load_proc, this) == 0) {
94 Log::error("Failed to load GL entry points\n");
95 return false;
96 }
97
98 if (gladLoadWGLUserPtr(hdc_, load_proc, this) == 0) {
99 Log::error("Failed to load WGL entry points\n");
100 return false;
101 }
102
103 return true;
104 }
105
106 bool
init_surface(void *)107 GLStateWGL::init_surface(void* /*native_window*/)
108 {
109 return true;
110 }
111
112 bool
init_gl_extensions()113 GLStateWGL::init_gl_extensions()
114 {
115 GLExtensions::MapBuffer = glMapBuffer;
116 GLExtensions::UnmapBuffer = glUnmapBuffer;
117
118 GLExtensions::GenFramebuffers = glGenFramebuffersEXT;
119 GLExtensions::DeleteFramebuffers = glDeleteFramebuffersEXT;
120 GLExtensions::BindFramebuffer = glBindFramebufferEXT;
121 GLExtensions::FramebufferTexture2D = glFramebufferTexture2DEXT;
122 GLExtensions::FramebufferRenderbuffer = glFramebufferRenderbufferEXT;
123 GLExtensions::CheckFramebufferStatus = glCheckFramebufferStatusEXT;
124
125 GLExtensions::GenRenderbuffers = glGenRenderbuffersEXT;
126 GLExtensions::DeleteRenderbuffers = glDeleteRenderbuffersEXT;
127 GLExtensions::BindRenderbuffer = glBindRenderbufferEXT;
128 GLExtensions::RenderbufferStorage = glRenderbufferStorageEXT;
129
130 GLExtensions::GenerateMipmap = glGenerateMipmapEXT;
131
132 return true;
133 }
134
135 bool
valid()136 GLStateWGL::valid()
137 {
138 if (!wglSwapIntervalEXT || wglSwapIntervalEXT(0) == FALSE) {
139 Log::info("** Failed to set swap interval. Results may be bounded above by refresh rate.\n");
140 }
141
142 return wgl_context_ != nullptr;
143 }
144
145
146 bool
reset()147 GLStateWGL::reset()
148 {
149 return true;
150 }
151
152 void
swap()153 GLStateWGL::swap()
154 {
155 if (SwapBuffers(hdc_) == FALSE) {
156 Log::error("Error during SwapBuffers\n");
157 }
158 }
159
160 bool
gotNativeConfig(intptr_t & vid)161 GLStateWGL::gotNativeConfig(intptr_t& vid)
162 {
163 vid = 1;
164 return true;
165 }
166
167 void
getVisualConfig(GLVisualConfig & vc)168 GLStateWGL::getVisualConfig(GLVisualConfig& vc)
169 {
170 vc.buffer = 32;
171 vc.red = 8;
172 vc.green = 8;
173 vc.blue = 8;
174 vc.alpha = 8;
175 vc.depth = 24;
176 vc.stencil = 8;
177 }
178
179 /*******************
180 * Private methods *
181 *******************/
182
load_proc(void * userptr,const char * name)183 GLStateWGL::api_proc GLStateWGL::load_proc(void *userptr, const char *name)
184 {
185 GLStateWGL* state = reinterpret_cast<GLStateWGL*>(userptr);
186 auto get_proc_addr = reinterpret_cast<decltype(&wglGetProcAddress)>(state->get_proc_addr_);
187 auto proc = reinterpret_cast<GLStateWGL::api_proc>(get_proc_addr(name));
188 if (proc) {
189 return proc;
190 }
191 return reinterpret_cast<GLStateWGL::api_proc>(state->wgl_library_.load(name));
192 }
193
194