commit 8aec6395284b08408359b5cb00f21fda0917156c
parent b8769268d8e46fc7bbed2c926fa7c1b9cb33caf8
Author: cnlohr <lohr85@gmail.com>
Date: Fri, 27 Sep 2019 00:54:42 -0400
Bring in line with rawdraw
(1) Include fix for black screen in Windows Closes #54
(2) Integrate os_generic the new way. This reduces executable usage a small amount.
Diffstat:
8 files changed, 819 insertions(+), 450 deletions(-)
diff --git a/Makefile b/Makefile
@@ -13,14 +13,14 @@ MINGW32?=i686-w64-mingw32-
#If you don't need admin priveleges
ADMINFLAGS:= $(ADMINFLAGS) -DWIN_USE_NO_ADMIN_PING
-cnping.exe : cnping.c rawdraw/CNFGFunctions.c rawdraw/CNFGWinDriver.c rawdraw/os_generic.c ping.c httping.c
+cnping.exe : cnping.c rawdraw/CNFGFunctions.c rawdraw/CNFGWinDriver.c ping.c httping.c
$(MINGW32)windres resources.rc -o resources.o $(ADMINFLAGS)
$(MINGW32)gcc -g -fno-ident -mwindows -m32 $(CFLAGS) resources.o -o $@ $^ -lgdi32 -lws2_32 -s -D_WIN32_WINNT=0x0600 -DWIN32 -liphlpapi -DMINGW_BUILD $(ADMINFLAGS)
-cnping : cnping.o rawdraw/CNFGFunctions.o rawdraw/CNFGXDriver.o rawdraw/os_generic.o ping.o httping.o
+cnping : cnping.o rawdraw/CNFGFunctions.o rawdraw/CNFGXDriver.o ping.o httping.o
$(CC) $(CFLAGS) -o $@ $^ -lX11 -lm -lpthread $(LDFLAGS)
-cnping_mac : cnping.c rawdraw/CNFGFunctions.c rawdraw/CNFGCocoaCGDriver.m rawdraw/os_generic.c ping.c httping.o
+cnping_mac : cnping.c rawdraw/CNFGFunctions.c rawdraw/CNFGCocoaCGDriver.m ping.c httping.o
$(CC) -o cnping $^ -x objective-c -framework Cocoa -framework QuartzCore -lm -lpthread
searchnet : rawdraw/os_generic.o ping.o searchnet.o
diff --git a/ping.c b/ping.c
@@ -9,7 +9,6 @@
#include <stdio.h>
#include <stdlib.h>
#include "ping.h"
-#include "rawdraw/os_generic.h"
#include "error_handling.h"
#ifdef TCC
@@ -27,13 +26,14 @@ struct sockaddr_in psaddr;
//...
#else
#include <inaddr.h>
-#include <winsock2.h>
-#include <windows.h>
#include <ws2tcpip.h>
#include <ipexport.h>
#include <icmpapi.h>
+#include <windows.h>
#endif
+#include "rawdraw/os_generic.h"
+
#define MAX_PING_SIZE 16384
diff --git a/rawdraw/CNFGFunctions.c b/rawdraw/CNFGFunctions.c
@@ -28,6 +28,8 @@ int CNFGPenX, CNFGPenY;
uint32_t CNFGBGColor;
uint32_t CNFGLastColor;
uint32_t CNFGDialogColor; //background for boxes
+
+// The following two arrays are generated by Fonter/fonter.cpp
const unsigned short FontCharMap[256] = {
65535, 0, 10, 20, 32, 44, 56, 68, 70, 65535, 65535, 80, 92, 65535, 104, 114,
126, 132, 138, 148, 156, 166, 180, 188, 200, 206, 212, 218, 224, 228, 238, 244,
@@ -184,10 +186,10 @@ void CNFGDrawText( const char * text, int scale )
switch( c )
{
- case 9:
+ case 9: // tab
iox += 12 * scale;
break;
- case 10:
+ case 10: // linefeed
iox = (float)CNFGPenX;
ioy += 6 * scale;
break;
@@ -272,8 +274,12 @@ void CNFGDrawTextbox( int x, int y, const char * text, int textsize )
}
-#ifdef CNFGOGL
+#if defined( CNFGOGL ) && !defined( HAS_XSHAPE )
+#ifdef _MSC_VER
+#include <windows.h>
+#pragma comment( lib, "OpenGL32.lib" )
+#endif
#include <GL/gl.h>
uint32_t CNFGColor( uint32_t RGB )
@@ -282,6 +288,7 @@ uint32_t CNFGColor( uint32_t RGB )
unsigned char grn = ( RGB >> 8 ) & 0xFF;
unsigned char blu = ( RGB >> 16 ) & 0xFF;
glColor3ub( red, grn, blu );
+ return RGB;
}
void CNFGClearFrame()
@@ -308,11 +315,14 @@ void CNFGTackSegment( short x1, short y1, short x2, short y2 )
{
glBegin( GL_POINTS );
glVertex2f( x1+.5, y1+.5 );
- glEnd();
+ glEnd();
}
else
{
- glBegin( GL_LINES );
+ // GL_LINE misses the last pixel if the line is not continued
+ // due to the Diamond-exit rule so we use GL_LINE_LOOP which
+ // draws the line back and forth catching all the pixels.
+ glBegin( GL_LINE_LOOP );
glVertex2f( x1+.5, y1+.5 );
glVertex2f( x2+.5, y2+.5 );
glEnd();
@@ -351,4 +361,9 @@ void CNFGTackPoly( RDPoint * points, int verts )
void CNFGInternalResize( short x, short y ) { }
+void CNFGSetLineWidth( short width )
+{
+ glLineWidth( width );
+}
+
#endif
diff --git a/rawdraw/CNFGFunctions.h b/rawdraw/CNFGFunctions.h
@@ -34,7 +34,7 @@ void CNFGClearFrame();
void CNFGSwapBuffers();
void CNFGGetDimensions( short * x, short * y );
-void CNFGSetup( const char * WindowName, int w, int h );
+int CNFGSetup( const char * WindowName, int w, int h ); //return 0 if ok.
void CNFGSetupFullscreen( const char * WindowName, int screen_number );
void CNFGHandleInput();
@@ -55,6 +55,16 @@ void CNFGSetVSync( int vson );
void * CNFGGetExtension( const char * extname );
#endif
+//Also not available on all systems. Transparency.
+void CNFGPrepareForTransparency();
+void CNFGDrawToTransparencyMode( int transp );
+void CNFGClearTransparencyLevel();
+
+//Only available on systems that support it.
+void CNFGSetLineWidth( short width );
+void CNFGChangeWindowTitle( const char * windowtitle );
+void CNFGSetWindowIconData( int w, int h, uint32_t * data );
+
#ifdef __cplusplus
};
#endif
diff --git a/rawdraw/CNFGWinDriver.c b/rawdraw/CNFGWinDriver.c
@@ -96,6 +96,13 @@ LRESULT CALLBACK MyWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
+ case WM_SYSCOMMAND: //Not sure why, if deactivated, the dc gets unassociated?
+ if( wParam == SC_RESTORE || wParam == SC_MAXIMIZE || wParam == SC_SCREENSAVE )
+ {
+ SelectObject( lsHDC, lsBitmap );
+ SelectObject( lsWindowHDC, lsBitmap );
+ }
+ break;
case WM_DESTROY:
HandleDestroy();
CNFGTearDown();
@@ -105,7 +112,7 @@ LRESULT CALLBACK MyWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
}
//This was from the article, too... well, mostly.
-void CNFGSetup( const char * name_of_window, int width, int height )
+int CNFGSetup( const char * name_of_window, int width, int height )
{
static LPSTR szClassName = "MyClass";
RECT client, window;
@@ -207,12 +214,12 @@ void CNFGSetup( const char * name_of_window, int width, int height )
MoveWindow( lsHWND, window.left, window.top, bufferx + wd, buffery + hd, 1 );
InternalHandleResize();
+
+ return 0;
}
void CNFGHandleInput()
{
- //int ldown = 0;
-
MSG msg;
while( PeekMessage( &msg, lsHWND, 0, 0xFFFF, 1 ) )
{
diff --git a/rawdraw/CNFGXDriver.c b/rawdraw/CNFGXDriver.c
@@ -1,8 +1,10 @@
-//Copyright (c) 2011, 2017 <>< Charles Lohr - Under the MIT/x11 or NewBSD License you choose.
-//portions from
+//Copyright (c) 2011, 2017, 2018 <>< Charles Lohr - Under the MIT/x11 or NewBSD License you choose.
+//portions from
//http://www.xmission.com/~georgeps/documentation/tutorials/Xlib_Beginner.html
//#define HAS_XINERAMA
+//#define HAS_XSHAPE
+//#define FULL_SCREEN_STEAL_FOCUS
#include "CNFGFunctions.h"
@@ -11,13 +13,27 @@
#include <X11/Xos.h>
#include <X11/Xatom.h>
#include <X11/keysym.h>
-#ifdef HAS_XINERAMA
-#include <X11/extensions/shape.h>
-#include <X11/extensions/Xinerama.h>
-#endif
+
#include <stdio.h>
#include <stdlib.h>
+#ifdef HAS_XINERAMA
+ #include <X11/extensions/shape.h>
+ #include <X11/extensions/Xinerama.h>
+#endif
+#ifdef HAS_XSHAPE
+ #include <X11/extensions/shape.h>
+ static XGCValues xsval;
+ static Pixmap xspixmap;
+ static GC xsgc;
+
+ static int taint_shape;
+ static int prepare_xshape;
+ static int was_transp;
+
+#endif
+
+
XWindowAttributes CNFGWinAtt;
XClassHint *CNFGClassHint;
Display *CNFGDisplay;
@@ -27,6 +43,60 @@ GC CNFGGC;
GC CNFGWindowGC;
Visual * CNFGVisual;
+int g_x_global_key_state;
+int g_x_global_shift_key;
+
+void CNFGSetWindowIconData( int w, int h, uint32_t * data )
+{
+ static Atom net_wm_icon;
+ static Atom cardinal;
+
+ if( !net_wm_icon ) net_wm_icon = XInternAtom( CNFGDisplay, "_NET_WM_ICON", False );
+ if( !cardinal ) cardinal = XInternAtom( CNFGDisplay, "CARDINAL", False );
+
+ unsigned long outdata[w*h];
+ int i;
+ for( i = 0; i < w*h; i++ )
+ {
+ outdata[i+2] = data[i];
+ }
+ outdata[0] = w;
+ outdata[1] = h;
+ XChangeProperty(CNFGDisplay, CNFGWindow, net_wm_icon, cardinal,
+ 32, PropModeReplace, (const unsigned char*)outdata, 2 + w*h);
+}
+
+
+#ifdef HAS_XSHAPE
+void CNFGPrepareForTransparency() { prepare_xshape = 1; }
+void CNFGDrawToTransparencyMode( int transp )
+{
+ static Pixmap BackupCNFGPixmap;
+ static GC BackupCNFGGC;
+ if( was_transp && ! transp )
+ {
+ CNFGGC = BackupCNFGGC;
+ CNFGPixmap = BackupCNFGPixmap;
+ }
+ if( !was_transp && transp )
+ {
+ BackupCNFGPixmap = CNFGPixmap;
+ BackupCNFGGC = CNFGGC;
+ taint_shape = 1;
+ CNFGGC = xsgc;
+ CNFGPixmap = xspixmap;
+ }
+ was_transp = transp;
+}
+void CNFGClearTransparencyLevel()
+{
+ taint_shape = 1;
+ XSetForeground(CNFGDisplay, xsgc, 0);
+ XFillRectangle(CNFGDisplay, xspixmap, xsgc, 0, 0, CNFGWinAtt.width, CNFGWinAtt.height);
+ XSetForeground(CNFGDisplay, xsgc, 1);
+}
+#endif
+
#ifdef CNFGOGL
#include <GL/glx.h>
@@ -54,16 +124,25 @@ void CNFGGetDimensions( short * x, short * y )
}
}
+void CNFGChangeWindowTitle( const char * WindowName )
+{
+ XSetStandardProperties( CNFGDisplay, CNFGWindow, WindowName, 0, 0, 0, 0, 0 );
+}
+
+
static void InternalLinkScreenAndGo( const char * WindowName )
{
+ XFlush(CNFGDisplay);
XGetWindowAttributes( CNFGDisplay, CNFGWindow, &CNFGWinAtt );
+/*
+ //Not sure of purpose of this. If we find it, let me know, if this code is still commented after 2019-12-31, please remove it.
XGetClassHint( CNFGDisplay, CNFGWindow, CNFGClassHint );
if (!CNFGClassHint) {
CNFGClassHint = XAllocClassHint();
if (CNFGClassHint) {
- CNFGClassHint->res_name = "cnping";
- CNFGClassHint->res_class = "cnping";
+ CNFGClassHint->res_name = "rawdraw";
+ CNFGClassHint->res_class = "rawdraw";
XSetClassHint( CNFGDisplay, CNFGWindow, CNFGClassHint );
} else {
fprintf( stderr, "Failed to allocate XClassHint!\n" );
@@ -71,14 +150,29 @@ static void InternalLinkScreenAndGo( const char * WindowName )
} else {
fprintf( stderr, "Pre-existing XClassHint\n" );
}
-
+*/
XSelectInput (CNFGDisplay, CNFGWindow, KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | ExposureMask | PointerMotionMask );
- XSetStandardProperties( CNFGDisplay, CNFGWindow, WindowName, WindowName, None, NULL, 0, NULL );
+
CNFGWindowGC = XCreateGC(CNFGDisplay, CNFGWindow, 0, 0);
CNFGPixmap = XCreatePixmap( CNFGDisplay, CNFGWindow, CNFGWinAtt.width, CNFGWinAtt.height, CNFGWinAtt.depth );
CNFGGC = XCreateGC(CNFGDisplay, CNFGPixmap, 0, 0);
+ XSetLineAttributes(CNFGDisplay, CNFGGC, 1, LineSolid, CapRound, JoinRound);
+ CNFGChangeWindowTitle( WindowName );
+ XMapWindow(CNFGDisplay, CNFGWindow);
+
+#ifdef HAS_XSHAPE
+ if( prepare_xshape )
+ {
+ xsval.foreground = 1;
+ xsval.line_width = 1;
+ xsval.line_style = LineSolid;
+ xspixmap = XCreatePixmap(CNFGDisplay, CNFGWindow, CNFGWinAtt.width, CNFGWinAtt.height, 1);
+ xsgc = XCreateGC(CNFGDisplay, xspixmap, 0, &xsval);
+ XSetLineAttributes(CNFGDisplay, xsgc, 1, LineSolid, CapRound, JoinRound);
+ }
+#endif
}
void CNFGSetupFullscreen( const char * WindowName, int screen_no )
@@ -99,6 +193,20 @@ void CNFGSetupFullscreen( const char * WindowName, int screen_no )
CNFGVisual = DefaultVisual(CNFGDisplay, screen);
CNFGWinAtt.depth = DefaultDepth(CNFGDisplay, screen);
+#ifdef CNFGOGL
+ int attribs[] = { GLX_RGBA,
+ GLX_DOUBLEBUFFER,
+ GLX_RED_SIZE, 1,
+ GLX_GREEN_SIZE, 1,
+ GLX_BLUE_SIZE, 1,
+ GLX_DEPTH_SIZE, 1,
+ None };
+ XVisualInfo * vis = glXChooseVisual(CNFGDisplay, screen, attribs);
+ CNFGVisual = vis->visual;
+ CNFGWinAtt.depth = vis->depth;
+ CNFGCtx = glXCreateContext( CNFGDisplay, vis, NULL, True );
+#endif
+
if (XineramaQueryExtension(CNFGDisplay, &a, &b ) &&
(screeninfo = XineramaQueryScreens(CNFGDisplay, &screens)) &&
XineramaIsActive(CNFGDisplay) && screen_no >= 0 &&
@@ -122,27 +230,35 @@ void CNFGSetupFullscreen( const char * WindowName, int screen_no )
XSetWindowAttributes setwinattr;
setwinattr.override_redirect = 1;
setwinattr.save_under = 1;
- setwinattr.event_mask = StructureNotifyMask | SubstructureNotifyMask | ExposureMask | ButtonPressMask | ButtonReleaseMask | ButtonPressMask | PointerMotionMask | ButtonMotionMask | EnterWindowMask | LeaveWindowMask |KeyPressMask |KeyReleaseMask | SubstructureNotifyMask | FocusChangeMask;
+#ifdef HAS_XSHAPE
+
+ if (prepare_xshape && !XShapeQueryExtension(CNFGDisplay, &event_basep, &error_basep))
+ {
+ fprintf( stderr, "X-Server does not support shape extension" );
+ exit( 1 );
+ }
+
+ setwinattr.event_mask = 0;
+#else
+ //This code is probably made irrelevant by the XSetEventMask in InternalLinkScreenAndGo, if this code is not found needed by 2019-12-31, please remove.
+ //setwinattr.event_mask = StructureNotifyMask | SubstructureNotifyMask | ExposureMask | ButtonPressMask | ButtonReleaseMask | ButtonPressMask | PointerMotionMask | ButtonMotionMask | EnterWindowMask | LeaveWindowMask |KeyPressMask |KeyReleaseMask | SubstructureNotifyMask | FocusChangeMask;
+#endif
setwinattr.border_pixel = 0;
+ setwinattr.colormap = XCreateColormap( CNFGDisplay, RootWindow(CNFGDisplay, 0), CNFGVisual, AllocNone);
CNFGWindow = XCreateWindow(CNFGDisplay, XRootWindow(CNFGDisplay, screen),
xpos, ypos, CNFGWinAtt.width, CNFGWinAtt.height,
- 0, CNFGWinAtt.depth, InputOutput, CNFGVisual,
- CWBorderPixel | CWEventMask | CWOverrideRedirect | CWSaveUnder,
+ 0, CNFGWinAtt.depth, InputOutput, CNFGVisual,
+ CWBorderPixel/* | CWEventMask */ | CWOverrideRedirect | CWSaveUnder | CWColormap,
&setwinattr);
- XMapWindow(CNFGDisplay, CNFGWindow);
- XSetInputFocus( CNFGDisplay, CNFGWindow, RevertToParent, CurrentTime );
- XFlush(CNFGDisplay);
FullScreen = 1;
-//printf( "%d %d %d %d\n", xpos, ypos, CNFGWinAtt.width, CNFGWinAtt.height );
InternalLinkScreenAndGo( WindowName );
-/*
- setwinattr.override_redirect = 1;
- XChangeWindowAttributes(
- CNFGDisplay, CNFGWindow,
- CWBorderPixel | CWEventMask | CWOverrideRedirect, &setwinattr);
-*/
+
+#ifdef CNFGOGL
+ glXMakeCurrent( CNFGDisplay, CNFGWindow, CNFGCtx );
+#endif
+
#else
CNFGSetup( WindowName, 640, 480 );
#endif
@@ -160,7 +276,7 @@ void CNFGTearDown()
CNFGClassHint = NULL;
}
-void CNFGSetup( const char * WindowName, int w, int h )
+int CNFGSetup( const char * WindowName, int w, int h )
{
CNFGDisplay = XOpenDisplay(NULL);
if ( !CNFGDisplay ) {
@@ -169,15 +285,15 @@ void CNFGSetup( const char * WindowName, int w, int h )
exit( 1 );
}
atexit( CNFGTearDown );
- XGetWindowAttributes( CNFGDisplay, RootWindow(CNFGDisplay, 0), &CNFGWinAtt );
- int depth = CNFGWinAtt.depth;
int screen = DefaultScreen(CNFGDisplay);
+ int depth = DefaultDepth(CNFGDisplay, screen);
CNFGVisual = DefaultVisual(CNFGDisplay, screen);
+ Window wnd = DefaultRootWindow( CNFGDisplay );
#ifdef CNFGOGL
int attribs[] = { GLX_RGBA,
- GLX_DOUBLEBUFFER,
+ GLX_DOUBLEBUFFER,
GLX_RED_SIZE, 1,
GLX_GREEN_SIZE, 1,
GLX_BLUE_SIZE, 1,
@@ -191,25 +307,19 @@ void CNFGSetup( const char * WindowName, int w, int h )
XSetWindowAttributes attr;
attr.background_pixel = 0;
- attr.border_pixel = 0;
- attr.colormap = XCreateColormap( CNFGDisplay, RootWindow(CNFGDisplay, 0), CNFGVisual, AllocNone);
- attr.event_mask = StructureNotifyMask | ExposureMask | KeyPressMask;
- int mask = CWBackPixel | CWBorderPixel | CWColormap | CWEventMask;
-
- CNFGWindow = XCreateWindow(CNFGDisplay, RootWindow(CNFGDisplay, 0), 1, 1, w, h, 0, depth, InputOutput, CNFGVisual, mask, &attr );
- XMapWindow(CNFGDisplay, CNFGWindow);
- XFlush(CNFGDisplay);
+ attr.colormap = XCreateColormap( CNFGDisplay, wnd, CNFGVisual, AllocNone);
+ CNFGWindow = XCreateWindow(CNFGDisplay, wnd, 1, 1, w, h, 0, depth, InputOutput, CNFGVisual, CWBackPixel | CWColormap, &attr );
InternalLinkScreenAndGo( WindowName );
- Atom WM_DELETE_WINDOW = XInternAtom( CNFGDisplay, "WM_DELETE_WINDOW", False );
- XSetWMProtocols( CNFGDisplay, CNFGWindow, &WM_DELETE_WINDOW, 1 );
-
- XSelectInput( CNFGDisplay, CNFGWindow, KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | ExposureMask | PointerMotionMask );
+//Not sure of the purpose of this code - if it's still commented out after 2019-12-31 and no one knows why, please delete it.
+// Atom WM_DELETE_WINDOW = XInternAtom( CNFGDisplay, "WM_DELETE_WINDOW", False );
+// XSetWMProtocols( CNFGDisplay, CNFGWindow, &WM_DELETE_WINDOW, 1 );
#ifdef CNFGOGL
glXMakeCurrent( CNFGDisplay, CNFGWindow, CNFGCtx );
#endif
+ return 0;
}
void CNFGHandleInput()
@@ -237,6 +347,8 @@ void CNFGHandleInput()
case KeyRelease:
bKeyDirection = 0;
case KeyPress:
+ g_x_global_key_state = report.xkey.state;
+ g_x_global_shift_key = XLookupKeysym(&report.xkey, 1);
HandleKey( XLookupKeysym(&report.xkey, 0), bKeyDirection );
break;
case ButtonRelease:
@@ -254,8 +366,8 @@ void CNFGHandleInput()
exit( 0 );
break;
default:
- //printf( "Event: %d\n", report.type );
break;
+ //printf( "Event: %d\n", report.type );
}
}
}
@@ -266,6 +378,7 @@ void CNFGUpdateScreenWithBitmap( unsigned long * data, int w, int h )
static XImage *xi;
static int depth;
static int lw, lh;
+ static unsigned char * lbuffer;
if( !xi )
{
@@ -283,6 +396,7 @@ void CNFGUpdateScreenWithBitmap( unsigned long * data, int w, int h )
lw = w;
lh = h;
}
+
XPutImage(CNFGDisplay, CNFGWindow, CNFGWindowGC, xi, 0, 0, 0, 0, w, h );
}
@@ -301,14 +415,33 @@ void CNFGSwapBuffers()
{
glFlush();
glFinish();
+
+#ifdef HAS_XSHAPE
+ if( taint_shape )
+ {
+ XShapeCombineMask(CNFGDisplay, CNFGWindow, ShapeBounding, 0, 0, xspixmap, ShapeSet);
+ taint_shape = 0;
+ }
+#endif
glXSwapBuffers( CNFGDisplay, CNFGWindow );
+
+#ifdef FULL_SCREEN_STEAL_FOCUS
+ if( FullScreen )
+ XSetInputFocus( CNFGDisplay, CNFGWindow, RevertToParent, CurrentTime );
+#endif
}
#endif
-#if !defined( RASTERIZER ) && !defined( CNFGOGL)
-
+#if !defined( CNFGOGL)
+#define AGLF(x) x
+#else
+#define AGLF(x) static BACKEND_##x
+#if defined( RASTERIZER )
+#include "CNFGRasterizer.h"
+#endif
+#endif
-uint32_t CNFGColor( uint32_t RGB )
+uint32_t AGLF(CNFGColor)( uint32_t RGB )
{
unsigned char red = RGB & 0xFF;
unsigned char grn = ( RGB >> 8 ) & 0xFF;
@@ -319,50 +452,177 @@ uint32_t CNFGColor( uint32_t RGB )
return color;
}
-void CNFGClearFrame()
+void AGLF(CNFGClearFrame)()
{
XGetWindowAttributes( CNFGDisplay, CNFGWindow, &CNFGWinAtt );
- XSetForeground(CNFGDisplay, CNFGGC, CNFGColor(CNFGBGColor) );
+ XSetForeground(CNFGDisplay, CNFGGC, CNFGColor(CNFGBGColor) );
XFillRectangle(CNFGDisplay, CNFGPixmap, CNFGGC, 0, 0, CNFGWinAtt.width, CNFGWinAtt.height );
}
-void CNFGSwapBuffers()
+void AGLF(CNFGSwapBuffers)()
{
+#ifdef HAS_XSHAPE
+ if( taint_shape )
+ {
+ XShapeCombineMask(CNFGDisplay, CNFGWindow, ShapeBounding, 0, 0, xspixmap, ShapeSet);
+ taint_shape = 0;
+ }
+#endif
XCopyArea(CNFGDisplay, CNFGPixmap, CNFGWindow, CNFGWindowGC, 0,0,CNFGWinAtt.width,CNFGWinAtt.height,0,0);
XFlush(CNFGDisplay);
+#ifdef FULL_SCREEN_STEAL_FOCUS
if( FullScreen )
XSetInputFocus( CNFGDisplay, CNFGWindow, RevertToParent, CurrentTime );
+#endif
}
-void CNFGTackSegment( short x1, short y1, short x2, short y2 )
+void AGLF(CNFGTackSegment)( short x1, short y1, short x2, short y2 )
{
XDrawLine( CNFGDisplay, CNFGPixmap, CNFGGC, x1, y1, x2, y2 );
+ XDrawPoint( CNFGDisplay, CNFGPixmap, CNFGGC, x2, y2 );
+}
+
+void AGLF(CNFGTackPixel)( short x1, short y1 )
+{
XDrawPoint( CNFGDisplay, CNFGPixmap, CNFGGC, x1, y1 );
}
+void AGLF(CNFGTackRectangle)( short x1, short y1, short x2, short y2 )
+{
+ XFillRectangle(CNFGDisplay, CNFGPixmap, CNFGGC, x1, y1, x2-x1, y2-y1 );
+}
+
+void AGLF(CNFGTackPoly)( RDPoint * points, int verts )
+{
+ XFillPolygon(CNFGDisplay, CNFGPixmap, CNFGGC, (XPoint *)points, 3, Convex, CoordModeOrigin );
+}
+
+void AGLF(CNFGInternalResize)( short x, short y ) { }
+
+void AGLF(CNFGSetLineWidth)( short width )
+{
+ XSetLineAttributes(CNFGDisplay, CNFGGC, width, LineSolid, CapRound, JoinRound);
+}
+
+
+
+
+#if defined( CNFGOGL ) && defined( HAS_XSHAPE )
+
+#include <GL/gl.h>
+
+uint32_t CNFGColor( uint32_t RGB )
+{
+ if( was_transp )
+ {
+ return BACKEND_CNFGColor( RGB );
+ }
+
+ unsigned char red = RGB & 0xFF;
+ unsigned char grn = ( RGB >> 8 ) & 0xFF;
+ unsigned char blu = ( RGB >> 16 ) & 0xFF;
+ glColor3ub( red, grn, blu );
+}
+
+void CNFGClearFrame()
+{
+ short w, h;
+ unsigned char red = CNFGBGColor & 0xFF;
+ unsigned char grn = ( CNFGBGColor >> 8 ) & 0xFF;
+ unsigned char blu = ( CNFGBGColor >> 16 ) & 0xFF;
+ glClearColor( red/255.0, grn/255.0, blu/255.0, 1.0 );
+ glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+ CNFGGetDimensions( &w, &h );
+ glMatrixMode( GL_PROJECTION );
+ glLoadIdentity();
+ glViewport( 0, 0, w, h );
+ glOrtho( 0, w, h, 0, 1, -1 );
+ glMatrixMode( GL_MODELVIEW );
+ glLoadIdentity();
+}
+
+
+void CNFGTackSegment( short x1, short y1, short x2, short y2 )
+{
+ if( was_transp )
+ {
+ BACKEND_CNFGTackSegment( x1,y1,x2,y2 );
+ return;
+ }
+
+ if( x1 == x2 && y1 == y2 )
+ {
+ glBegin( GL_POINTS );
+ glVertex2f( x1+.5, y1+.5 );
+ glEnd();
+ }
+ else
+ {
+ glBegin( GL_POINTS );
+ glVertex2f( x1+.5, y1+.5 );
+ glVertex2f( x2+.5, y2+.5 );
+ glEnd();
+ glBegin( GL_LINES );
+ glVertex2f( x1+.5, y1+.5 );
+ glVertex2f( x2+.5, y2+.5 );
+ glEnd();
+ }
+}
+
void CNFGTackPixel( short x1, short y1 )
{
- XDrawPoint( CNFGDisplay, CNFGPixmap, CNFGGC, x1, y1 );
+ if( was_transp )
+ {
+ BACKEND_CNFGTackPixel( x1,y1 );
+ return;
+ }
+
+ glBegin( GL_POINTS );
+ glVertex2f( x1, y1 );
+ glEnd();
}
void CNFGTackRectangle( short x1, short y1, short x2, short y2 )
{
- XFillRectangle(CNFGDisplay, CNFGPixmap, CNFGGC, x1, y1, x2-x1, y2-y1 );
+ if( was_transp )
+ {
+ BACKEND_CNFGTackRectangle( x1,y1,x2,y2 );
+ return;
+ }
+
+
+ glBegin( GL_QUADS );
+ glVertex2f( x1, y1 );
+ glVertex2f( x2, y1 );
+ glVertex2f( x2, y2 );
+ glVertex2f( x1, y2 );
+ glEnd();
}
void CNFGTackPoly( RDPoint * points, int verts )
{
- XFillPolygon(CNFGDisplay, CNFGPixmap, CNFGGC, (XPoint *)points, 3, Convex, CoordModeOrigin );
+ if( was_transp )
+ {
+ BACKEND_CNFGTackPoly( points,verts );
+ return;
+ }
+
+ int i;
+ glBegin( GL_TRIANGLE_FAN );
+ glVertex2f( points[0].x, points[0].y );
+ for( i = 1; i < verts; i++ )
+ {
+ glVertex2f( points[i].x, points[i].y );
+ }
+ glEnd();
}
void CNFGInternalResize( short x, short y ) { }
-#else
-#if defined( RASTERIZER )
-#include "CNFGRasterizer.h"
-#endif
+void CNFGSetLineWidth( short width )
+{
+ glLineWidth( width );
+}
#endif
-
-
diff --git a/rawdraw/os_generic.c b/rawdraw/os_generic.c
@@ -1,336 +0,0 @@
-#include "os_generic.h"
-
-#ifdef USE_WINDOWS
-
-#include <windows.h>
-
-void OGSleep( int is )
-{
- Sleep( is*1000 );
-}
-
-void OGUSleep( int ius )
-{
- Sleep( ius/1000 );
-}
-
-double OGGetAbsoluteTime()
-{
- static LARGE_INTEGER lpf;
- LARGE_INTEGER li;
-
- if( !lpf.QuadPart )
- {
- QueryPerformanceFrequency( &lpf );
- }
-
- QueryPerformanceCounter( &li );
- return (double)li.QuadPart / (double)lpf.QuadPart;
-}
-
-
-double OGGetFileTime( const char * file )
-{
- FILETIME ft;
-
- HANDLE h = CreateFile(file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
-
- if( h==INVALID_HANDLE_VALUE )
- return -1;
-
- GetFileTime( h, 0, 0, &ft );
-
- CloseHandle( h );
-
- return ft.dwHighDateTime + ft.dwLowDateTime;
-}
-
-
-og_thread_t OGCreateThread( void * (routine)( void * ), void * parameter )
-{
- return (og_thread_t)CreateThread( 0, 0, (LPTHREAD_START_ROUTINE)routine, parameter, 0, 0 );
-}
-
-void * OGJoinThread( og_thread_t ot )
-{
- WaitForSingleObject( ot, INFINITE );
- CloseHandle( ot );
- return 0;
-}
-
-void OGCancelThread( og_thread_t ot )
-{
- CloseHandle( ot );
-}
-
-og_mutex_t OGCreateMutex()
-{
- return CreateMutex( 0, 0, 0 );
-}
-
-void OGLockMutex( og_mutex_t om )
-{
- WaitForSingleObject(om, INFINITE);
-}
-
-void OGUnlockMutex( og_mutex_t om )
-{
- ReleaseMutex(om);
-}
-
-void OGDeleteMutex( og_mutex_t om )
-{
- CloseHandle( om );
-}
-
-
-
-og_sema_t OGCreateSema()
-{
- HANDLE sem = CreateSemaphore( 0, 0, 32767, 0 );
- return (og_sema_t)sem;
-}
-
-int OGGetSema( og_sema_t os )
-{
- typedef LONG NTSTATUS;
- HANDLE sem = (HANDLE)os;
- typedef NTSTATUS (NTAPI *_NtQuerySemaphore)(
- HANDLE SemaphoreHandle,
- DWORD SemaphoreInformationClass, /* Would be SEMAPHORE_INFORMATION_CLASS */
- PVOID SemaphoreInformation, /* but this is to much to dump here */
- ULONG SemaphoreInformationLength,
- PULONG ReturnLength OPTIONAL
- );
-
- typedef struct _SEMAPHORE_BASIC_INFORMATION {
- ULONG CurrentCount;
- ULONG MaximumCount;
- } SEMAPHORE_BASIC_INFORMATION;
-
-
- static _NtQuerySemaphore NtQuerySemaphore;
- SEMAPHORE_BASIC_INFORMATION BasicInfo;
- NTSTATUS Status;
-
- if( !NtQuerySemaphore )
- {
- NtQuerySemaphore = (_NtQuerySemaphore)GetProcAddress (GetModuleHandle ("ntdll.dll"), "NtQuerySemaphore");
- if( !NtQuerySemaphore )
- {
- return -1;
- }
- }
-
-
- Status = NtQuerySemaphore (sem, 0 /*SemaphoreBasicInformation*/,
- &BasicInfo, sizeof (SEMAPHORE_BASIC_INFORMATION), NULL);
-
- if (Status == ERROR_SUCCESS)
- {
- return BasicInfo.CurrentCount;
- }
-
- return -2;
-}
-
-void OGLockSema( og_sema_t os )
-{
- WaitForSingleObject( (HANDLE)os, INFINITE );
-}
-
-void OGUnlockSema( og_sema_t os )
-{
- ReleaseSemaphore( (HANDLE)os, 1, 0 );
-}
-
-void OGDeleteSema( og_sema_t os )
-{
- CloseHandle( os );
-}
-
-#else
-
-#define _GNU_SOURCE
-
-
-#include <sys/stat.h>
-#include <stdlib.h>
-#include <pthread.h>
-#include <sys/time.h>
-#include <semaphore.h>
-#include <unistd.h>
-
-pthread_mutex_t g_RawMutexStart = PTHREAD_MUTEX_INITIALIZER;
-
-void OGSleep( int is )
-{
- sleep( is );
-}
-
-void OGUSleep( int ius )
-{
- usleep( ius );
-}
-
-double OGGetAbsoluteTime()
-{
- struct timeval tv;
- gettimeofday( &tv, 0 );
- return ((double)tv.tv_usec)/1000000. + (tv.tv_sec);
-}
-
-double OGGetFileTime( const char * file )
-{
- struct stat buff;
-
- int r = stat( file, &buff );
-
- if( r < 0 )
- {
- return -1;
- }
-
- return buff.st_mtime;
-}
-
-
-
-og_thread_t OGCreateThread( void * (routine)( void * ), void * parameter )
-{
- pthread_t * ret = malloc( sizeof( pthread_t ) );
- int r = pthread_create( ret, 0, routine, parameter );
- if( r )
- {
- free( ret );
- return 0;
- }
- return (og_thread_t)ret;
-}
-
-void * OGJoinThread( og_thread_t ot )
-{
- void * retval;
- if( !ot )
- {
- return 0;
- }
- pthread_join( *(pthread_t*)ot, &retval );
- free( ot );
- return retval;
-}
-
-void OGCancelThread( og_thread_t ot )
-{
- if( !ot )
- {
- return;
- }
- pthread_cancel( *(pthread_t*)ot );
- free( ot );
-}
-
-og_mutex_t OGCreateMutex()
-{
- pthread_mutexattr_t mta;
- og_mutex_t r = malloc( sizeof( pthread_mutex_t ) );
-
- pthread_mutexattr_init(&mta);
- pthread_mutexattr_settype(&mta, PTHREAD_MUTEX_RECURSIVE);
-
- pthread_mutex_init( (pthread_mutex_t *)r, &mta );
-
- return r;
-}
-
-void OGLockMutex( og_mutex_t om )
-{
- if( !om )
- {
- return;
- }
- pthread_mutex_lock( (pthread_mutex_t*)om );
-}
-
-void OGUnlockMutex( og_mutex_t om )
-{
- if( !om )
- {
- return;
- }
- pthread_mutex_unlock( (pthread_mutex_t*)om );
-}
-
-void OGDeleteMutex( og_mutex_t om )
-{
- if( !om )
- {
- return;
- }
-
- pthread_mutex_destroy( (pthread_mutex_t*)om );
- free( om );
-}
-
-
-
-
-og_sema_t OGCreateSema()
-{
- sem_t * sem = malloc( sizeof( sem_t ) );
- sem_init( sem, 0, 0 );
- return (og_sema_t)sem;
-}
-
-int OGGetSema( og_sema_t os )
-{
- int valp;
- sem_getvalue( os, &valp );
- return valp;
-}
-
-
-void OGLockSema( og_sema_t os )
-{
- sem_wait( os );
-}
-
-void OGUnlockSema( og_sema_t os )
-{
- sem_post( os );
-}
-
-void OGDeleteSema( og_sema_t os )
-{
- sem_destroy( os );
- free(os);
-}
-
-
-
-#endif
-
-//Date Stamp: 2012-02-15
-
-/*
- Copyright (c) 2011-2012 <>< Charles Lohr
-
- Permission is hereby granted, free of charge, to any person obtaining a
- copy of this software and associated documentation files (the "Software"),
- to deal in the Software without restriction, including without limitation
- the rights to use, copy, modify, merge, publish, distribute, sublicense,
- and/or sell copies of the Software, and to permit persons to whom the
- Software is furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of this file.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- IN THE SOFTWARE.
-*/
-
diff --git a/rawdraw/os_generic.h b/rawdraw/os_generic.h
@@ -1,59 +1,56 @@
#ifndef _OS_GENERIC_H
#define _OS_GENERIC_H
+/*
+ "osgeneric" Generic, platform independent tool for threads and time.
+ Geared around Windows and Linux. Designed for operation on MSVC,
+ TCC, GCC and clang. Others may work.
-#if defined( WIN32 ) || defined (WINDOWS) || defined( _WIN32)
-#define USE_WINDOWS
-#endif
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-//Things that shouldn't be macro'd
-double OGGetAbsoluteTime();
-void OGSleep( int is );
-void OGUSleep( int ius );
-double OGGetFileTime( const char * file );
-
-//Threads and Mutices
-typedef void* og_thread_t;
-typedef void* og_mutex_t;
-typedef void* og_sema_t;
-
-og_thread_t OGCreateThread( void * (routine)( void * ), void * parameter );
-void * OGJoinThread( og_thread_t ot );
-void OGCancelThread( og_thread_t ot );
+ It offers the following operations:
-//Always a recursive mutex.
-og_mutex_t OGCreateMutex();
-void OGLockMutex( og_mutex_t om );
-void OGUnlockMutex( og_mutex_t om );
-void OGDeleteMutex( og_mutex_t om );
+ Delay functions:
+ void OGSleep( int is );
+ void OGUSleep( int ius );
-//Always a semaphore
-og_sema_t OGCreateSema(); //Create a semaphore, comes locked initially. NOTE: Max count is 32767
-void OGLockSema( og_sema_t os );
-int OGGetSema( og_sema_t os ); //if <0 there was a failure.
-void OGUnlockSema( og_sema_t os );
-void OGDeleteSema( og_sema_t os );
+ Getting current time (may be time from program start, boot, or epoc)
+ double OGGetAbsoluteTime();
+ double OGGetFileTime( const char * file );
-#ifdef __cplusplus
-};
-#endif
+ Thread functions
+ og_thread_t OGCreateThread( void * (routine)( void * ), void * parameter );
+ void * OGJoinThread( og_thread_t ot );
+ void OGCancelThread( og_thread_t ot );
+ Mutex functions, used for protecting data structures.
+ (recursive on platforms where available.)
+ og_mutex_t OGCreateMutex();
+ void OGLockMutex( og_mutex_t om );
+ void OGUnlockMutex( og_mutex_t om );
+ void OGDeleteMutex( og_mutex_t om );
+ Always a semaphore (not recursive)
+ og_sema_t OGCreateSema(); //Create a semaphore, comes locked initially.
+ NOTE: For platform compatibility, max count is 32767
+ void OGLockSema( og_sema_t os );
+ int OGGetSema( og_sema_t os ); //if <0 there was a failure.
+ void OGUnlockSema( og_sema_t os );
+ void OGDeleteSema( og_sema_t os );
-#endif
+ TLS (Thread-Local Storage)
+ og_tls_t OGCreateTLS();
+ void OGDeleteTLS( og_tls_t tls );
+ void OGSetTLS( og_tls_t tls, void * data );
+ void * OGGetTLS( og_tls_t tls );
+ You can permute the operations of this file by the following means:
+ OSG_NO_IMPLEMENTATION
+ OSG_PREFIX
+ OSG_NOSTATIC
-//Date Stamp: 2012-02-15
+ The default behavior is to do static inline.
-/*
- NOTE: Portions (namely the top section) are part of headers from other
- sources.
+ Copyright (c) 2011-2012,2013,2016,2018,2019 <>< Charles Lohr
- Copyright (c) 2011-2012 <>< Charles Lohr
+ This file may be licensed under the MIT/x11 license, NewBSD or CC0 licenses
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
@@ -72,5 +69,421 @@ void OGDeleteSema( og_sema_t os );
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
+
+ Date Stamp: 2019-09-05 CNL: Allow for noninstantiation and added TLS.
+ Date Stamp: 2018-03-25 CNL: Switched to header-only format.
*/
+
+#if defined( OSG_NOSTATIC ) && OSG_STATIC != 0
+#ifndef OSG_PREFIX
+#define OSG_PREFIX
+#endif
+#ifndef OSG_NO_IMPLEMENTATION
+#define OSG_NO_IMPLEMENTATION
+#endif
+#endif
+
+#ifndef OSG_PREFIX
+#define OSG_PREFIX static inline
+#endif
+
+//In case you want to hook the closure of a thread, i.e. if your system has thread-local storage.
+#ifndef OSG_TERM_THREAD_CODE
+#define OSG_TERM_THREAD_CODE
+#endif
+
+typedef void* og_thread_t;
+typedef void* og_mutex_t;
+typedef void* og_sema_t;
+typedef void* og_tls_t;
+
+OSG_PREFIX void OGSleep( int is );
+OSG_PREFIX void OGUSleep( int ius );
+OSG_PREFIX double OGGetAbsoluteTime();
+OSG_PREFIX double OGGetFileTime( const char * file );
+OSG_PREFIX og_thread_t OGCreateThread( void * (routine)( void * ), void * parameter );
+OSG_PREFIX void * OGJoinThread( og_thread_t ot );
+OSG_PREFIX void OGCancelThread( og_thread_t ot );
+OSG_PREFIX og_mutex_t OGCreateMutex();
+OSG_PREFIX void OGLockMutex( og_mutex_t om );
+OSG_PREFIX void OGUnlockMutex( og_mutex_t om );
+OSG_PREFIX void OGDeleteMutex( og_mutex_t om );
+OSG_PREFIX og_sema_t OGCreateSema();
+OSG_PREFIX int OGGetSema( og_sema_t os );
+OSG_PREFIX void OGLockSema( og_sema_t os );
+OSG_PREFIX void OGUnlockSema( og_sema_t os );
+OSG_PREFIX void OGDeleteSema( og_sema_t os );
+OSG_PREFIX og_tls_t OGCreateTLS();
+OSG_PREFIX void OGDeleteTLS( og_tls_t key );
+OSG_PREFIX void * OGGetTLS( og_tls_t key );
+OSG_PREFIX void OGSetTLS( og_tls_t key, void * data );
+
+#ifndef OSG_NO_IMPLEMENTATION
+
+#if defined( WIN32 ) || defined (WINDOWS) || defined( _WIN32)
+#define USE_WINDOWS
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#ifdef USE_WINDOWS
+
+#include <windows.h>
+
+OSG_PREFIX void OGSleep( int is )
+{
+ Sleep( is*1000 );
+}
+
+OSG_PREFIX void OGUSleep( int ius )
+{
+ Sleep( ius/1000 );
+}
+
+OSG_PREFIX double OGGetAbsoluteTime()
+{
+ static LARGE_INTEGER lpf;
+ LARGE_INTEGER li;
+
+ if( !lpf.QuadPart )
+ {
+ QueryPerformanceFrequency( &lpf );
+ }
+
+ QueryPerformanceCounter( &li );
+ return (double)li.QuadPart / (double)lpf.QuadPart;
+}
+
+
+OSG_PREFIX double OGGetFileTime( const char * file )
+{
+ FILETIME ft;
+
+ HANDLE h = CreateFile(file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
+
+ if( h==INVALID_HANDLE_VALUE )
+ return -1;
+
+ GetFileTime( h, 0, 0, &ft );
+
+ CloseHandle( h );
+
+ return ft.dwHighDateTime + ft.dwLowDateTime;
+}
+
+
+OSG_PREFIX og_thread_t OGCreateThread( void * (routine)( void * ), void * parameter )
+{
+ return (og_thread_t)CreateThread( 0, 0, (LPTHREAD_START_ROUTINE)routine, parameter, 0, 0 );
+}
+
+OSG_PREFIX void * OGJoinThread( og_thread_t ot )
+{
+ WaitForSingleObject( ot, INFINITE );
+ OSG_TERM_THREAD_CODE
+ CloseHandle( ot );
+ return 0;
+}
+
+OSG_PREFIX void OGCancelThread( og_thread_t ot )
+{
+ OSG_TERM_THREAD_CODE
+ CloseHandle( ot );
+}
+
+OSG_PREFIX og_mutex_t OGCreateMutex()
+{
+ return CreateMutex( 0, 0, 0 );
+}
+
+OSG_PREFIX void OGLockMutex( og_mutex_t om )
+{
+ WaitForSingleObject(om, INFINITE);
+}
+
+OSG_PREFIX void OGUnlockMutex( og_mutex_t om )
+{
+ ReleaseMutex(om);
+}
+
+OSG_PREFIX void OGDeleteMutex( og_mutex_t om )
+{
+ CloseHandle( om );
+}
+
+
+
+OSG_PREFIX og_sema_t OGCreateSema()
+{
+ HANDLE sem = CreateSemaphore( 0, 0, 32767, 0 );
+ return (og_sema_t)sem;
+}
+
+OSG_PREFIX int OGGetSema( og_sema_t os )
+{
+ typedef LONG NTSTATUS;
+ HANDLE sem = (HANDLE)os;
+ typedef NTSTATUS (NTAPI *_NtQuerySemaphore)(
+ HANDLE SemaphoreHandle,
+ DWORD SemaphoreInformationClass, /* Would be SEMAPHORE_INFORMATION_CLASS */
+ PVOID SemaphoreInformation, /* but this is to much to dump here */
+ ULONG SemaphoreInformationLength,
+ PULONG ReturnLength OPTIONAL
+ );
+
+ typedef struct _SEMAPHORE_BASIC_INFORMATION {
+ ULONG CurrentCount;
+ ULONG MaximumCount;
+ } SEMAPHORE_BASIC_INFORMATION;
+
+
+ static _NtQuerySemaphore NtQuerySemaphore;
+ SEMAPHORE_BASIC_INFORMATION BasicInfo;
+ NTSTATUS Status;
+
+ if( !NtQuerySemaphore )
+ {
+ NtQuerySemaphore = (_NtQuerySemaphore)GetProcAddress (GetModuleHandle ("ntdll.dll"), "NtQuerySemaphore");
+ if( !NtQuerySemaphore )
+ {
+ return -1;
+ }
+ }
+
+
+ Status = NtQuerySemaphore (sem, 0 /*SemaphoreBasicInformation*/,
+ &BasicInfo, sizeof (SEMAPHORE_BASIC_INFORMATION), NULL);
+
+ if (Status == ERROR_SUCCESS)
+ {
+ return BasicInfo.CurrentCount;
+ }
+
+ return -2;
+}
+
+OSG_PREFIX void OGLockSema( og_sema_t os )
+{
+ WaitForSingleObject( (HANDLE)os, INFINITE );
+}
+
+OSG_PREFIX void OGUnlockSema( og_sema_t os )
+{
+ ReleaseSemaphore( (HANDLE)os, 1, 0 );
+}
+
+OSG_PREFIX void OGDeleteSema( og_sema_t os )
+{
+ CloseHandle( os );
+}
+
+OSG_PREFIX og_tls_t OGCreateTLS()
+{
+ return (og_tls_t)TlsAlloc();
+}
+
+OSG_PREFIX void OGDeleteTLS( og_tls_t key )
+{
+ TlsFree( (DWORD)key );
+}
+
+OSG_PREFIX void * OGGetTLS( og_tls_t key )
+{
+ return TlsGetValue( (DWORD)key );
+}
+
+OSG_PREFIX void OGSetTLS( og_tls_t key, void * data )
+{
+ TlsSetValue( (DWORD)key, data );
+}
+
+#else
+
+#define _GNU_SOURCE
+
+
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <sys/time.h>
+#include <semaphore.h>
+#include <unistd.h>
+
+OSG_PREFIX void OGSleep( int is )
+{
+ sleep( is );
+}
+
+OSG_PREFIX void OGUSleep( int ius )
+{
+ usleep( ius );
+}
+
+OSG_PREFIX double OGGetAbsoluteTime()
+{
+ struct timeval tv;
+ gettimeofday( &tv, 0 );
+ return ((double)tv.tv_usec)/1000000. + (tv.tv_sec);
+}
+
+OSG_PREFIX double OGGetFileTime( const char * file )
+{
+ struct stat buff;
+
+ int r = stat( file, &buff );
+
+ if( r < 0 )
+ {
+ return -1;
+ }
+
+ return buff.st_mtime;
+}
+
+
+
+OSG_PREFIX og_thread_t OGCreateThread( void * (routine)( void * ), void * parameter )
+{
+ pthread_t * ret = malloc( sizeof( pthread_t ) );
+ int r = pthread_create( ret, 0, routine, parameter );
+ if( r )
+ {
+ free( ret );
+ return 0;
+ }
+ return (og_thread_t)ret;
+}
+
+OSG_PREFIX void * OGJoinThread( og_thread_t ot )
+{
+ void * retval;
+ if( !ot )
+ {
+ return 0;
+ }
+ pthread_join( *(pthread_t*)ot, &retval );
+ OSG_TERM_THREAD_CODE
+ free( ot );
+ return retval;
+}
+
+OSG_PREFIX void OGCancelThread( og_thread_t ot )
+{
+ if( !ot )
+ {
+ return;
+ }
+ pthread_cancel( *(pthread_t*)ot );
+ OSG_TERM_THREAD_CODE
+ free( ot );
+}
+
+OSG_PREFIX og_mutex_t OGCreateMutex()
+{
+ pthread_mutexattr_t mta;
+ og_mutex_t r = malloc( sizeof( pthread_mutex_t ) );
+
+ pthread_mutexattr_init(&mta);
+ pthread_mutexattr_settype(&mta, PTHREAD_MUTEX_RECURSIVE);
+
+ pthread_mutex_init( (pthread_mutex_t *)r, &mta );
+
+ return r;
+}
+
+OSG_PREFIX void OGLockMutex( og_mutex_t om )
+{
+ if( !om )
+ {
+ return;
+ }
+ pthread_mutex_lock( (pthread_mutex_t*)om );
+}
+
+OSG_PREFIX void OGUnlockMutex( og_mutex_t om )
+{
+ if( !om )
+ {
+ return;
+ }
+ pthread_mutex_unlock( (pthread_mutex_t*)om );
+}
+
+OSG_PREFIX void OGDeleteMutex( og_mutex_t om )
+{
+ if( !om )
+ {
+ return;
+ }
+
+ pthread_mutex_destroy( (pthread_mutex_t*)om );
+ free( om );
+}
+
+
+
+
+OSG_PREFIX og_sema_t OGCreateSema()
+{
+ sem_t * sem = malloc( sizeof( sem_t ) );
+ sem_init( sem, 0, 0 );
+ return (og_sema_t)sem;
+}
+
+OSG_PREFIX int OGGetSema( og_sema_t os )
+{
+ int valp;
+ sem_getvalue( os, &valp );
+ return valp;
+}
+
+
+OSG_PREFIX void OGLockSema( og_sema_t os )
+{
+ sem_wait( os );
+}
+
+OSG_PREFIX void OGUnlockSema( og_sema_t os )
+{
+ sem_post( os );
+}
+
+OSG_PREFIX void OGDeleteSema( og_sema_t os )
+{
+ sem_destroy( os );
+ free(os);
+}
+
+OSG_PREFIX og_tls_t OGCreateTLS()
+{
+ pthread_key_t ret = 0;
+ pthread_key_create(&ret, 0);
+ return (og_tls_t)(intptr_t)ret;
+}
+
+OSG_PREFIX void OGDeleteTLS( og_tls_t key )
+{
+ pthread_key_delete( (pthread_key_t)(intptr_t)key );
+}
+
+OSG_PREFIX void * OGGetTLS( og_tls_t key )
+{
+ return pthread_getspecific( (pthread_key_t)(intptr_t)key );
+}
+
+OSG_PREFIX void OGSetTLS( og_tls_t key, void * data )
+{
+ pthread_setspecific( (pthread_key_t)(intptr_t)key, data );
+}
+
+#endif
+
+#endif
+
+#endif
+