winecfg: Widen "Folder" column to accommodate Catalan translation.
[wine.git] / dlls / gdi32 / dibdrv / opengl.c
blob41331169c4ab2a1b86488d13f58a64462e79728c
1 /*
2 * DIB driver OpenGL support
4 * Copyright 2012 Alexandre Julliard
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "config.h"
22 #include "wine/port.h"
24 #include "gdi_private.h"
25 #include "dibdrv.h"
27 #include "wine/library.h"
28 #include "wine/debug.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(dib);
32 #ifdef SONAME_LIBOSMESA
34 #include "wine/wgl.h"
35 #include "wine/wgl_driver.h"
37 #define OSMESA_COLOR_INDEX GL_COLOR_INDEX
38 #define OSMESA_RGBA GL_RGBA
39 #define OSMESA_BGRA 0x1
40 #define OSMESA_ARGB 0x2
41 #define OSMESA_RGB GL_RGB
42 #define OSMESA_BGR 0x4
43 #define OSMESA_RGB_565 0x5
44 #define OSMESA_ROW_LENGTH 0x10
45 #define OSMESA_Y_UP 0x11
47 typedef struct osmesa_context *OSMesaContext;
49 extern BOOL WINAPI GdiSetPixelFormat( HDC hdc, INT fmt, const PIXELFORMATDESCRIPTOR *pfd );
51 struct wgl_context
53 OSMesaContext context;
54 int format;
57 static struct opengl_funcs opengl_funcs;
59 #define USE_GL_FUNC(name) #name,
60 static const char *opengl_func_names[] = { ALL_WGL_FUNCS };
61 #undef USE_GL_FUNC
63 static OSMesaContext (*pOSMesaCreateContextExt)( GLenum format, GLint depthBits, GLint stencilBits,
64 GLint accumBits, OSMesaContext sharelist );
65 static void (*pOSMesaDestroyContext)( OSMesaContext ctx );
66 static void * (*pOSMesaGetProcAddress)( const char *funcName );
67 static GLboolean (*pOSMesaMakeCurrent)( OSMesaContext ctx, void *buffer, GLenum type,
68 GLsizei width, GLsizei height );
69 static void (*pOSMesaPixelStore)( GLint pname, GLint value );
71 static const struct
73 UINT mesa;
74 BYTE color_bits;
75 BYTE red_bits, red_shift;
76 BYTE green_bits, green_shift;
77 BYTE blue_bits, blue_shift;
78 BYTE alpha_bits, alpha_shift;
79 BYTE accum_bits;
80 BYTE depth_bits;
81 BYTE stencil_bits;
82 } pixel_formats[] =
84 { OSMESA_BGRA, 32, 8, 16, 8, 8, 8, 0, 8, 24, 16, 32, 8 },
85 { OSMESA_BGRA, 32, 8, 16, 8, 8, 8, 0, 8, 24, 16, 16, 8 },
86 { OSMESA_RGBA, 32, 8, 0, 8, 8, 8, 16, 8, 24, 16, 32, 8 },
87 { OSMESA_RGBA, 32, 8, 0, 8, 8, 8, 16, 8, 24, 16, 16, 8 },
88 { OSMESA_ARGB, 32, 8, 8, 8, 16, 8, 24, 8, 0, 16, 32, 8 },
89 { OSMESA_ARGB, 32, 8, 8, 8, 16, 8, 24, 8, 0, 16, 16, 8 },
90 { OSMESA_RGB, 24, 8, 0, 8, 8, 8, 16, 0, 0, 16, 32, 8 },
91 { OSMESA_RGB, 24, 8, 0, 8, 8, 8, 16, 0, 0, 16, 16, 8 },
92 { OSMESA_BGR, 24, 8, 16, 8, 8, 8, 0, 0, 0, 16, 32, 8 },
93 { OSMESA_BGR, 24, 8, 16, 8, 8, 8, 0, 0, 0, 16, 16, 8 },
94 { OSMESA_RGB_565, 16, 5, 0, 6, 5, 5, 11, 0, 0, 16, 32, 8 },
95 { OSMESA_RGB_565, 16, 5, 0, 6, 5, 5, 11, 0, 0, 16, 16, 8 },
97 static const int nb_formats = sizeof(pixel_formats) / sizeof(pixel_formats[0]);
99 static BOOL init_opengl(void)
101 static BOOL init_done = FALSE;
102 static void *osmesa_handle;
103 char buffer[200];
104 unsigned int i;
106 if (init_done) return (osmesa_handle != NULL);
107 init_done = TRUE;
109 osmesa_handle = wine_dlopen( SONAME_LIBOSMESA, RTLD_NOW, buffer, sizeof(buffer) );
110 if (osmesa_handle == NULL)
112 ERR( "Failed to load OSMesa: %s\n", buffer );
113 return FALSE;
116 for (i = 0; i < sizeof(opengl_func_names)/sizeof(opengl_func_names[0]); i++)
118 if (!(((void **)&opengl_funcs.gl)[i] = wine_dlsym( osmesa_handle, opengl_func_names[i], buffer, sizeof(buffer) )))
120 ERR( "%s not found in %s (%s), disabling.\n", opengl_func_names[i], SONAME_LIBOSMESA, buffer );
121 goto failed;
124 #define LOAD_FUNCPTR(f) do if (!(p##f = wine_dlsym( osmesa_handle, #f, buffer, sizeof(buffer) ))) \
126 ERR( "%s not found in %s (%s), disabling.\n", #f, SONAME_LIBOSMESA, buffer ); \
127 goto failed; \
128 } while(0)
130 LOAD_FUNCPTR(OSMesaCreateContextExt);
131 LOAD_FUNCPTR(OSMesaDestroyContext);
132 LOAD_FUNCPTR(OSMesaGetProcAddress);
133 LOAD_FUNCPTR(OSMesaMakeCurrent);
134 LOAD_FUNCPTR(OSMesaPixelStore);
135 #undef LOAD_FUNCPTR
137 return TRUE;
139 failed:
140 wine_dlclose( osmesa_handle, NULL, 0 );
141 osmesa_handle = NULL;
142 return FALSE;
145 /**********************************************************************
146 * dibdrv_wglDescribePixelFormat
148 static int dibdrv_wglDescribePixelFormat( HDC hdc, int fmt, UINT size, PIXELFORMATDESCRIPTOR *descr )
150 int ret = sizeof(pixel_formats) / sizeof(pixel_formats[0]);
152 if (!descr) return ret;
153 if (fmt <= 0 || fmt > ret) return 0;
154 if (size < sizeof(*descr)) return 0;
156 memset( descr, 0, sizeof(*descr) );
157 descr->nSize = sizeof(*descr);
158 descr->nVersion = 1;
159 descr->dwFlags = PFD_SUPPORT_GDI | PFD_SUPPORT_OPENGL | PFD_DRAW_TO_BITMAP | PFD_GENERIC_FORMAT;
160 descr->iPixelType = PFD_TYPE_RGBA;
161 descr->cColorBits = pixel_formats[fmt - 1].color_bits;
162 descr->cRedBits = pixel_formats[fmt - 1].red_bits;
163 descr->cRedShift = pixel_formats[fmt - 1].red_shift;
164 descr->cGreenBits = pixel_formats[fmt - 1].green_bits;
165 descr->cGreenShift = pixel_formats[fmt - 1].green_shift;
166 descr->cBlueBits = pixel_formats[fmt - 1].blue_bits;
167 descr->cBlueShift = pixel_formats[fmt - 1].blue_shift;
168 descr->cAlphaBits = pixel_formats[fmt - 1].alpha_bits;
169 descr->cAlphaShift = pixel_formats[fmt - 1].alpha_shift;
170 descr->cAccumBits = pixel_formats[fmt - 1].accum_bits;
171 descr->cAccumRedBits = pixel_formats[fmt - 1].accum_bits / 4;
172 descr->cAccumGreenBits = pixel_formats[fmt - 1].accum_bits / 4;
173 descr->cAccumBlueBits = pixel_formats[fmt - 1].accum_bits / 4;
174 descr->cAccumAlphaBits = pixel_formats[fmt - 1].accum_bits / 4;
175 descr->cDepthBits = pixel_formats[fmt - 1].depth_bits;
176 descr->cStencilBits = pixel_formats[fmt - 1].stencil_bits;
177 descr->cAuxBuffers = 0;
178 descr->iLayerType = PFD_MAIN_PLANE;
179 return ret;
182 /***********************************************************************
183 * dibdrv_wglCopyContext
185 static BOOL dibdrv_wglCopyContext( struct wgl_context *src, struct wgl_context *dst, UINT mask )
187 FIXME( "not supported yet\n" );
188 return FALSE;
191 /***********************************************************************
192 * dibdrv_wglCreateContext
194 static struct wgl_context *dibdrv_wglCreateContext( HDC hdc )
196 struct wgl_context *context;
198 if (!(context = HeapAlloc( GetProcessHeap(), 0, sizeof( *context )))) return NULL;
199 context->format = GetPixelFormat( hdc );
200 if (!context->format || context->format > nb_formats) context->format = 1;
202 if (!(context->context = pOSMesaCreateContextExt( pixel_formats[context->format - 1].mesa,
203 pixel_formats[context->format - 1].depth_bits,
204 pixel_formats[context->format - 1].stencil_bits,
205 pixel_formats[context->format - 1].accum_bits, 0 )))
207 HeapFree( GetProcessHeap(), 0, context );
208 return NULL;
210 return context;
213 /***********************************************************************
214 * dibdrv_wglDeleteContext
216 static void dibdrv_wglDeleteContext( struct wgl_context *context )
218 pOSMesaDestroyContext( context->context );
219 HeapFree( GetProcessHeap(), 0, context );
222 /***********************************************************************
223 * dibdrv_wglGetPixelFormat
225 static int dibdrv_wglGetPixelFormat( HDC hdc )
227 DC *dc = get_dc_ptr( hdc );
228 int ret = 0;
230 if (dc)
232 ret = dc->pixel_format;
233 release_dc_ptr( dc );
235 return ret;
238 /***********************************************************************
239 * dibdrv_wglGetProcAddress
241 static PROC dibdrv_wglGetProcAddress( const char *proc )
243 if (!strncmp( proc, "wgl", 3 )) return NULL;
244 return (PROC)pOSMesaGetProcAddress( proc );
247 /***********************************************************************
248 * dibdrv_wglMakeCurrent
250 static BOOL dibdrv_wglMakeCurrent( HDC hdc, struct wgl_context *context )
252 HBITMAP bitmap;
253 BITMAPOBJ *bmp;
254 dib_info dib;
255 GLenum type;
256 BOOL ret = FALSE;
258 if (!context)
260 pOSMesaMakeCurrent( NULL, NULL, GL_UNSIGNED_BYTE, 0, 0 );
261 return TRUE;
264 if (GetPixelFormat( hdc ) != context->format)
265 FIXME( "mismatched pixel formats %u/%u not supported yet\n",
266 GetPixelFormat( hdc ), context->format );
268 bitmap = GetCurrentObject( hdc, OBJ_BITMAP );
269 bmp = GDI_GetObjPtr( bitmap, OBJ_BITMAP );
270 if (!bmp) return FALSE;
272 if (init_dib_info_from_bitmapobj( &dib, bmp ))
274 char *bits;
275 int width = dib.rect.right - dib.rect.left;
276 int height = dib.rect.bottom - dib.rect.top;
278 if (dib.stride < 0)
279 bits = (char *)dib.bits.ptr + (dib.rect.bottom - 1) * dib.stride;
280 else
281 bits = (char *)dib.bits.ptr + dib.rect.top * dib.stride;
282 bits += dib.rect.left * dib.bit_count / 8;
284 TRACE( "context %p bits %p size %ux%u\n", context, bits, width, height );
286 if (pixel_formats[context->format - 1].mesa == OSMESA_RGB_565)
287 type = GL_UNSIGNED_SHORT_5_6_5;
288 else
289 type = GL_UNSIGNED_BYTE;
291 ret = pOSMesaMakeCurrent( context->context, bits, type, width, height );
292 if (ret)
294 pOSMesaPixelStore( OSMESA_ROW_LENGTH, abs( dib.stride ) * 8 / dib.bit_count );
295 pOSMesaPixelStore( OSMESA_Y_UP, 1 ); /* Windows seems to assume bottom-up */
298 GDI_ReleaseObj( bitmap );
299 return ret;
302 /**********************************************************************
303 * dibdrv_wglSetPixelFormat
305 static BOOL dibdrv_wglSetPixelFormat( HDC hdc, int fmt, const PIXELFORMATDESCRIPTOR *descr )
307 if (fmt <= 0 || fmt > nb_formats) return FALSE;
308 return GdiSetPixelFormat( hdc, fmt, descr );
311 /***********************************************************************
312 * dibdrv_wglShareLists
314 static BOOL dibdrv_wglShareLists( struct wgl_context *org, struct wgl_context *dest )
316 FIXME( "not supported yet\n" );
317 return FALSE;
320 /***********************************************************************
321 * dibdrv_wglSwapBuffers
323 static BOOL dibdrv_wglSwapBuffers( HDC hdc )
325 return TRUE;
328 static struct opengl_funcs opengl_funcs =
331 dibdrv_wglCopyContext, /* p_wglCopyContext */
332 dibdrv_wglCreateContext, /* p_wglCreateContext */
333 dibdrv_wglDeleteContext, /* p_wglDeleteContext */
334 dibdrv_wglDescribePixelFormat,/* p_wglDescribePixelFormat */
335 dibdrv_wglGetPixelFormat, /* p_wglGetPixelFormat */
336 dibdrv_wglGetProcAddress, /* p_wglGetProcAddress */
337 dibdrv_wglMakeCurrent, /* p_wglMakeCurrent */
338 dibdrv_wglSetPixelFormat, /* p_wglSetPixelFormat */
339 dibdrv_wglShareLists, /* p_wglShareLists */
340 dibdrv_wglSwapBuffers, /* p_wglSwapBuffers */
344 /**********************************************************************
345 * dibdrv_wine_get_wgl_driver
347 struct opengl_funcs *dibdrv_wine_get_wgl_driver( PHYSDEV dev, UINT version )
349 if (version != WINE_WGL_DRIVER_VERSION)
351 ERR( "version mismatch, opengl32 wants %u but dibdrv has %u\n", version, WINE_WGL_DRIVER_VERSION );
352 return NULL;
355 if (!init_opengl()) return (void *)-1;
357 return &opengl_funcs;
360 #else /* SONAME_LIBOSMESA */
362 /**********************************************************************
363 * dibdrv_wine_get_wgl_driver
365 struct opengl_funcs *dibdrv_wine_get_wgl_driver( PHYSDEV dev, UINT version )
367 static int warned;
368 if (!warned++) ERR( "OSMesa not compiled in, no OpenGL bitmap support\n" );
369 return (void *)-1;
372 #endif /* SONAME_LIBOSMESA */