Sweden-Number/dlls/gdi32/dibdrv/opengl.c

229 lines
6.5 KiB
C

/*
* DIB driver OpenGL support
*
* Copyright 2012 Alexandre Julliard
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#if 0
#pragma makedep unix
#endif
#include "config.h"
#include "wine/port.h"
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "gdi_private.h"
#include "dibdrv.h"
#include "wine/wgl.h"
#include "wine/wgl_driver.h"
#ifdef SONAME_LIBOSMESA
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(dib);
#define OSMESA_COLOR_INDEX GL_COLOR_INDEX
#define OSMESA_RGBA GL_RGBA
#define OSMESA_BGRA 0x1
#define OSMESA_ARGB 0x2
#define OSMESA_RGB GL_RGB
#define OSMESA_BGR 0x4
#define OSMESA_RGB_565 0x5
#define OSMESA_ROW_LENGTH 0x10
#define OSMESA_Y_UP 0x11
typedef struct osmesa_context *OSMesaContext;
struct wgl_context
{
OSMesaContext context;
UINT format;
};
static struct opengl_funcs opengl_funcs;
#define USE_GL_FUNC(name) #name,
static const char *opengl_func_names[] = { ALL_WGL_FUNCS };
#undef USE_GL_FUNC
static OSMesaContext (*pOSMesaCreateContextExt)( GLenum format, GLint depthBits, GLint stencilBits,
GLint accumBits, OSMesaContext sharelist );
static void (*pOSMesaDestroyContext)( OSMesaContext ctx );
static void * (*pOSMesaGetProcAddress)( const char *funcName );
static GLboolean (*pOSMesaMakeCurrent)( OSMesaContext ctx, void *buffer, GLenum type,
GLsizei width, GLsizei height );
static void (*pOSMesaPixelStore)( GLint pname, GLint value );
static BOOL init_opengl(void)
{
static BOOL init_done = FALSE;
static void *osmesa_handle;
unsigned int i;
if (init_done) return (osmesa_handle != NULL);
init_done = TRUE;
osmesa_handle = dlopen( SONAME_LIBOSMESA, RTLD_NOW );
if (osmesa_handle == NULL)
{
ERR( "Failed to load OSMesa: %s\n", dlerror() );
return FALSE;
}
#define LOAD_FUNCPTR(f) do if (!(p##f = dlsym( osmesa_handle, #f ))) \
{ \
ERR( "%s not found in %s (%s), disabling.\n", #f, SONAME_LIBOSMESA, dlerror() ); \
goto failed; \
} while(0)
LOAD_FUNCPTR(OSMesaCreateContextExt);
LOAD_FUNCPTR(OSMesaDestroyContext);
LOAD_FUNCPTR(OSMesaGetProcAddress);
LOAD_FUNCPTR(OSMesaMakeCurrent);
LOAD_FUNCPTR(OSMesaPixelStore);
#undef LOAD_FUNCPTR
for (i = 0; i < ARRAY_SIZE( opengl_func_names ); i++)
{
if (!(((void **)&opengl_funcs.gl)[i] = pOSMesaGetProcAddress( opengl_func_names[i] )))
{
ERR( "%s not found in %s, disabling.\n", opengl_func_names[i], SONAME_LIBOSMESA );
goto failed;
}
}
return TRUE;
failed:
dlclose( osmesa_handle );
osmesa_handle = NULL;
return FALSE;
}
/***********************************************************************
* osmesa_get_gl_funcs
*/
static void CDECL osmesa_get_gl_funcs( struct opengl_funcs *funcs )
{
funcs->gl = opengl_funcs.gl;
}
/***********************************************************************
* osmesa_create_context
*/
static struct wgl_context * CDECL osmesa_create_context( HDC hdc, const PIXELFORMATDESCRIPTOR *descr )
{
struct wgl_context *context;
UINT gl_format;
switch (descr->cColorBits)
{
case 32:
if (descr->cRedShift == 8) gl_format = OSMESA_ARGB;
else if (descr->cRedShift == 16) gl_format = OSMESA_BGRA;
else gl_format = OSMESA_RGBA;
break;
case 24:
gl_format = descr->cRedShift == 16 ? OSMESA_BGR : OSMESA_RGB;
break;
case 16:
gl_format = OSMESA_RGB_565;
break;
default:
return NULL;
}
if (!(context = RtlAllocateHeap( GetProcessHeap(), 0, sizeof( *context )))) return NULL;
context->format = gl_format;
if (!(context->context = pOSMesaCreateContextExt( gl_format, descr->cDepthBits, descr->cStencilBits,
descr->cAccumBits, 0 )))
{
RtlFreeHeap( GetProcessHeap(), 0, context );
return NULL;
}
return context;
}
/***********************************************************************
* osmesa_delete_context
*/
static BOOL CDECL osmesa_delete_context( struct wgl_context *context )
{
pOSMesaDestroyContext( context->context );
RtlFreeHeap( GetProcessHeap(), 0, context );
return TRUE;
}
/***********************************************************************
* osmesa_get_proc_address
*/
static PROC CDECL osmesa_get_proc_address( const char *proc )
{
return (PROC)pOSMesaGetProcAddress( proc );
}
/***********************************************************************
* osmesa_make_current
*/
static BOOL CDECL osmesa_make_current( struct wgl_context *context, void *bits,
int width, int height, int bpp, int stride )
{
BOOL ret;
GLenum type;
if (!context)
{
pOSMesaMakeCurrent( NULL, NULL, GL_UNSIGNED_BYTE, 0, 0 );
return TRUE;
}
type = context->format == OSMESA_RGB_565 ? GL_UNSIGNED_SHORT_5_6_5 : GL_UNSIGNED_BYTE;
ret = pOSMesaMakeCurrent( context->context, bits, type, width, height );
if (ret)
{
pOSMesaPixelStore( OSMESA_ROW_LENGTH, abs( stride ) * 8 / bpp );
pOSMesaPixelStore( OSMESA_Y_UP, 1 ); /* Windows seems to assume bottom-up */
}
return ret;
}
static const struct osmesa_funcs osmesa_funcs =
{
osmesa_get_gl_funcs,
osmesa_create_context,
osmesa_delete_context,
osmesa_get_proc_address,
osmesa_make_current
};
NTSTATUS init_opengl_lib( HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out )
{
if (!init_opengl()) return STATUS_DLL_NOT_FOUND;
*(const struct osmesa_funcs **)ptr_out = &osmesa_funcs;
return STATUS_SUCCESS;
}
#else /* SONAME_LIBOSMESA */
NTSTATUS init_opengl_lib( HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out )
{
return STATUS_DLL_NOT_FOUND;
}
#endif /* SONAME_LIBOSMESA */