GCC Code Coverage Report


Directory: ./
File: submodules/raylib/src/external/glfw/src/osmesa_context.c
Date: 2023-09-29 04:53:15
Exec Total Coverage
Lines: 0 146 0.0%
Branches: 0 86 0.0%

Line Branch Exec Source
1 //========================================================================
2 // GLFW 3.4 OSMesa - www.glfw.org
3 //------------------------------------------------------------------------
4 // Copyright (c) 2016 Google Inc.
5 // Copyright (c) 2016-2017 Camilla Löwy <elmindreda@glfw.org>
6 //
7 // This software is provided 'as-is', without any express or implied
8 // warranty. In no event will the authors be held liable for any damages
9 // arising from the use of this software.
10 //
11 // Permission is granted to anyone to use this software for any purpose,
12 // including commercial applications, and to alter it and redistribute it
13 // freely, subject to the following restrictions:
14 //
15 // 1. The origin of this software must not be misrepresented; you must not
16 // claim that you wrote the original software. If you use this software
17 // in a product, an acknowledgment in the product documentation would
18 // be appreciated but is not required.
19 //
20 // 2. Altered source versions must be plainly marked as such, and must not
21 // be misrepresented as being the original software.
22 //
23 // 3. This notice may not be removed or altered from any source
24 // distribution.
25 //
26 //========================================================================
27 // Please use C89 style variable declarations in this file because VS 2010
28 //========================================================================
29
30 #include <stdlib.h>
31 #include <string.h>
32 #include <assert.h>
33
34 #include "internal.h"
35
36
37 static void makeContextCurrentOSMesa(_GLFWwindow* window)
38 {
39 if (window)
40 {
41 int width, height;
42 _glfw.platform.getFramebufferSize(window, &width, &height);
43
44 // Check to see if we need to allocate a new buffer
45 if ((window->context.osmesa.buffer == NULL) ||
46 (width != window->context.osmesa.width) ||
47 (height != window->context.osmesa.height))
48 {
49 _glfw_free(window->context.osmesa.buffer);
50
51 // Allocate the new buffer (width * height * 8-bit RGBA)
52 window->context.osmesa.buffer = _glfw_calloc(4, (size_t) width * height);
53 window->context.osmesa.width = width;
54 window->context.osmesa.height = height;
55 }
56
57 if (!OSMesaMakeCurrent(window->context.osmesa.handle,
58 window->context.osmesa.buffer,
59 GL_UNSIGNED_BYTE,
60 width, height))
61 {
62 _glfwInputError(GLFW_PLATFORM_ERROR,
63 "OSMesa: Failed to make context current");
64 return;
65 }
66 }
67
68 _glfwPlatformSetTls(&_glfw.contextSlot, window);
69 }
70
71 static GLFWglproc getProcAddressOSMesa(const char* procname)
72 {
73 return (GLFWglproc) OSMesaGetProcAddress(procname);
74 }
75
76 static void destroyContextOSMesa(_GLFWwindow* window)
77 {
78 if (window->context.osmesa.handle)
79 {
80 OSMesaDestroyContext(window->context.osmesa.handle);
81 window->context.osmesa.handle = NULL;
82 }
83
84 if (window->context.osmesa.buffer)
85 {
86 _glfw_free(window->context.osmesa.buffer);
87 window->context.osmesa.width = 0;
88 window->context.osmesa.height = 0;
89 }
90 }
91
92 static void swapBuffersOSMesa(_GLFWwindow* window)
93 {
94 // No double buffering on OSMesa
95 }
96
97 static void swapIntervalOSMesa(int interval)
98 {
99 // No swap interval on OSMesa
100 }
101
102 static int extensionSupportedOSMesa(const char* extension)
103 {
104 // OSMesa does not have extensions
105 return GLFW_FALSE;
106 }
107
108
109 //////////////////////////////////////////////////////////////////////////
110 ////// GLFW internal API //////
111 //////////////////////////////////////////////////////////////////////////
112
113 GLFWbool _glfwInitOSMesa(void)
114 {
115 int i;
116 const char* sonames[] =
117 {
118 #if defined(_GLFW_OSMESA_LIBRARY)
119 _GLFW_OSMESA_LIBRARY,
120 #elif defined(_WIN32)
121 "libOSMesa.dll",
122 "OSMesa.dll",
123 #elif defined(__APPLE__)
124 "libOSMesa.8.dylib",
125 #elif defined(__CYGWIN__)
126 "libOSMesa-8.so",
127 #elif defined(__OpenBSD__) || defined(__NetBSD__)
128 "libOSMesa.so",
129 #else
130 "libOSMesa.so.8",
131 "libOSMesa.so.6",
132 #endif
133 NULL
134 };
135
136 if (_glfw.osmesa.handle)
137 return GLFW_TRUE;
138
139 for (i = 0; sonames[i]; i++)
140 {
141 _glfw.osmesa.handle = _glfwPlatformLoadModule(sonames[i]);
142 if (_glfw.osmesa.handle)
143 break;
144 }
145
146 if (!_glfw.osmesa.handle)
147 {
148 _glfwInputError(GLFW_API_UNAVAILABLE, "OSMesa: Library not found");
149 return GLFW_FALSE;
150 }
151
152 _glfw.osmesa.CreateContextExt = (PFN_OSMesaCreateContextExt)
153 _glfwPlatformGetModuleSymbol(_glfw.osmesa.handle, "OSMesaCreateContextExt");
154 _glfw.osmesa.CreateContextAttribs = (PFN_OSMesaCreateContextAttribs)
155 _glfwPlatformGetModuleSymbol(_glfw.osmesa.handle, "OSMesaCreateContextAttribs");
156 _glfw.osmesa.DestroyContext = (PFN_OSMesaDestroyContext)
157 _glfwPlatformGetModuleSymbol(_glfw.osmesa.handle, "OSMesaDestroyContext");
158 _glfw.osmesa.MakeCurrent = (PFN_OSMesaMakeCurrent)
159 _glfwPlatformGetModuleSymbol(_glfw.osmesa.handle, "OSMesaMakeCurrent");
160 _glfw.osmesa.GetColorBuffer = (PFN_OSMesaGetColorBuffer)
161 _glfwPlatformGetModuleSymbol(_glfw.osmesa.handle, "OSMesaGetColorBuffer");
162 _glfw.osmesa.GetDepthBuffer = (PFN_OSMesaGetDepthBuffer)
163 _glfwPlatformGetModuleSymbol(_glfw.osmesa.handle, "OSMesaGetDepthBuffer");
164 _glfw.osmesa.GetProcAddress = (PFN_OSMesaGetProcAddress)
165 _glfwPlatformGetModuleSymbol(_glfw.osmesa.handle, "OSMesaGetProcAddress");
166
167 if (!_glfw.osmesa.CreateContextExt ||
168 !_glfw.osmesa.DestroyContext ||
169 !_glfw.osmesa.MakeCurrent ||
170 !_glfw.osmesa.GetColorBuffer ||
171 !_glfw.osmesa.GetDepthBuffer ||
172 !_glfw.osmesa.GetProcAddress)
173 {
174 _glfwInputError(GLFW_PLATFORM_ERROR,
175 "OSMesa: Failed to load required entry points");
176
177 _glfwTerminateOSMesa();
178 return GLFW_FALSE;
179 }
180
181 return GLFW_TRUE;
182 }
183
184 void _glfwTerminateOSMesa(void)
185 {
186 if (_glfw.osmesa.handle)
187 {
188 _glfwPlatformFreeModule(_glfw.osmesa.handle);
189 _glfw.osmesa.handle = NULL;
190 }
191 }
192
193 #define SET_ATTRIB(a, v) \
194 { \
195 assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
196 attribs[index++] = a; \
197 attribs[index++] = v; \
198 }
199
200 GLFWbool _glfwCreateContextOSMesa(_GLFWwindow* window,
201 const _GLFWctxconfig* ctxconfig,
202 const _GLFWfbconfig* fbconfig)
203 {
204 OSMesaContext share = NULL;
205 const int accumBits = fbconfig->accumRedBits +
206 fbconfig->accumGreenBits +
207 fbconfig->accumBlueBits +
208 fbconfig->accumAlphaBits;
209
210 if (ctxconfig->client == GLFW_OPENGL_ES_API)
211 {
212 _glfwInputError(GLFW_API_UNAVAILABLE,
213 "OSMesa: OpenGL ES is not available on OSMesa");
214 return GLFW_FALSE;
215 }
216
217 if (ctxconfig->share)
218 share = ctxconfig->share->context.osmesa.handle;
219
220 if (OSMesaCreateContextAttribs)
221 {
222 int index = 0, attribs[40];
223
224 SET_ATTRIB(OSMESA_FORMAT, OSMESA_RGBA);
225 SET_ATTRIB(OSMESA_DEPTH_BITS, fbconfig->depthBits);
226 SET_ATTRIB(OSMESA_STENCIL_BITS, fbconfig->stencilBits);
227 SET_ATTRIB(OSMESA_ACCUM_BITS, accumBits);
228
229 if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)
230 {
231 SET_ATTRIB(OSMESA_PROFILE, OSMESA_CORE_PROFILE);
232 }
233 else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
234 {
235 SET_ATTRIB(OSMESA_PROFILE, OSMESA_COMPAT_PROFILE);
236 }
237
238 if (ctxconfig->major != 1 || ctxconfig->minor != 0)
239 {
240 SET_ATTRIB(OSMESA_CONTEXT_MAJOR_VERSION, ctxconfig->major);
241 SET_ATTRIB(OSMESA_CONTEXT_MINOR_VERSION, ctxconfig->minor);
242 }
243
244 if (ctxconfig->forward)
245 {
246 _glfwInputError(GLFW_VERSION_UNAVAILABLE,
247 "OSMesa: Forward-compatible contexts not supported");
248 return GLFW_FALSE;
249 }
250
251 SET_ATTRIB(0, 0);
252
253 window->context.osmesa.handle =
254 OSMesaCreateContextAttribs(attribs, share);
255 }
256 else
257 {
258 if (ctxconfig->profile)
259 {
260 _glfwInputError(GLFW_VERSION_UNAVAILABLE,
261 "OSMesa: OpenGL profiles unavailable");
262 return GLFW_FALSE;
263 }
264
265 window->context.osmesa.handle =
266 OSMesaCreateContextExt(OSMESA_RGBA,
267 fbconfig->depthBits,
268 fbconfig->stencilBits,
269 accumBits,
270 share);
271 }
272
273 if (window->context.osmesa.handle == NULL)
274 {
275 _glfwInputError(GLFW_VERSION_UNAVAILABLE,
276 "OSMesa: Failed to create context");
277 return GLFW_FALSE;
278 }
279
280 window->context.makeCurrent = makeContextCurrentOSMesa;
281 window->context.swapBuffers = swapBuffersOSMesa;
282 window->context.swapInterval = swapIntervalOSMesa;
283 window->context.extensionSupported = extensionSupportedOSMesa;
284 window->context.getProcAddress = getProcAddressOSMesa;
285 window->context.destroy = destroyContextOSMesa;
286
287 return GLFW_TRUE;
288 }
289
290 #undef SET_ATTRIB
291
292
293 //////////////////////////////////////////////////////////////////////////
294 ////// GLFW native API //////
295 //////////////////////////////////////////////////////////////////////////
296
297 GLFWAPI int glfwGetOSMesaColorBuffer(GLFWwindow* handle, int* width,
298 int* height, int* format, void** buffer)
299 {
300 void* mesaBuffer;
301 GLint mesaWidth, mesaHeight, mesaFormat;
302 _GLFWwindow* window = (_GLFWwindow*) handle;
303 assert(window != NULL);
304
305 _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
306
307 if (window->context.source != GLFW_OSMESA_CONTEXT_API)
308 {
309 _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
310 return GLFW_FALSE;
311 }
312
313 if (!OSMesaGetColorBuffer(window->context.osmesa.handle,
314 &mesaWidth, &mesaHeight,
315 &mesaFormat, &mesaBuffer))
316 {
317 _glfwInputError(GLFW_PLATFORM_ERROR,
318 "OSMesa: Failed to retrieve color buffer");
319 return GLFW_FALSE;
320 }
321
322 if (width)
323 *width = mesaWidth;
324 if (height)
325 *height = mesaHeight;
326 if (format)
327 *format = mesaFormat;
328 if (buffer)
329 *buffer = mesaBuffer;
330
331 return GLFW_TRUE;
332 }
333
334 GLFWAPI int glfwGetOSMesaDepthBuffer(GLFWwindow* handle,
335 int* width, int* height,
336 int* bytesPerValue,
337 void** buffer)
338 {
339 void* mesaBuffer;
340 GLint mesaWidth, mesaHeight, mesaBytes;
341 _GLFWwindow* window = (_GLFWwindow*) handle;
342 assert(window != NULL);
343
344 _GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
345
346 if (window->context.source != GLFW_OSMESA_CONTEXT_API)
347 {
348 _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
349 return GLFW_FALSE;
350 }
351
352 if (!OSMesaGetDepthBuffer(window->context.osmesa.handle,
353 &mesaWidth, &mesaHeight,
354 &mesaBytes, &mesaBuffer))
355 {
356 _glfwInputError(GLFW_PLATFORM_ERROR,
357 "OSMesa: Failed to retrieve depth buffer");
358 return GLFW_FALSE;
359 }
360
361 if (width)
362 *width = mesaWidth;
363 if (height)
364 *height = mesaHeight;
365 if (bytesPerValue)
366 *bytesPerValue = mesaBytes;
367 if (buffer)
368 *buffer = mesaBuffer;
369
370 return GLFW_TRUE;
371 }
372
373 GLFWAPI OSMesaContext glfwGetOSMesaContext(GLFWwindow* handle)
374 {
375 _GLFWwindow* window = (_GLFWwindow*) handle;
376 _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
377
378 if (window->context.source != GLFW_OSMESA_CONTEXT_API)
379 {
380 _glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
381 return NULL;
382 }
383
384 return window->context.osmesa.handle;
385 }
386
387