cnping

Minimal Graphical Ping Tool
git clone https://git.sinitax.com/cnlohr/cnping
Log | Files | Refs | Submodules | README | LICENSE | sfeed.txt

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:
MMakefile | 6+++---
Mping.c | 6+++---
Mrawdraw/CNFGFunctions.c | 25++++++++++++++++++++-----
Mrawdraw/CNFGFunctions.h | 12+++++++++++-
Mrawdraw/CNFGWinDriver.c | 13++++++++++---
Mrawdraw/CNFGXDriver.c | 372+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------
Drawdraw/os_generic.c | 336-------------------------------------------------------------------------------
Mrawdraw/os_generic.h | 499++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
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 +