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