text: 
  #include "SDL.h"
  
  #include "graphics_threaded.h"
  
  
  
  // platform dependent implementations for transfering render context from the main thread to the graphics thread
  // TODO: when SDL 1.3 comes, this can be removed
  #if defined(CONF_FAMILY_WINDOWS)
  	struct SGLContext
  	{
  		HDC m_hDC;
  		HGLRC m_hGLRC;
  	};
  
  	static SGLContext GL_GetCurrentContext()
  	{
  		SGLContext Context;
  		Context.m_hDC = wglGetCurrentDC();
  		Context.m_hGLRC = wglGetCurrentContext();
  		return Context;
  	}
  
  	static void GL_MakeCurrent(const SGLContext &Context) { wglMakeCurrent(Context.m_hDC, Context.m_hGLRC); }
  	static void GL_ReleaseContext(const SGLContext &Context) { wglMakeCurrent(NULL, NULL); }
  	static void GL_SwapBuffers(const SGLContext &Context) { SwapBuffers(Context.m_hDC); }
  #elif defined(CONF_PLATFORM_MACOSX)
  
  	#include <objc/objc-runtime.h>
  
  	class semaphore
  	{
  		SDL_sem *sem;
  	public:
  		semaphore() { sem = SDL_CreateSemaphore(0); }
  		~semaphore() { SDL_DestroySemaphore(sem); }
  		void wait() { SDL_SemWait(sem); }
  		void signal() { SDL_SemPost(sem); }
  	};
  
  	struct SGLContext
  	{
  		id m_Context;
  	};
  
  	static SGLContext GL_GetCurrentContext()
  	{
  		SGLContext Context;
  		Class NSOpenGLContextClass = (Class) objc_getClass("NSOpenGLContext");
  		SEL selector = sel_registerName("currentContext");
  		Context.m_Context = objc_msgSend((objc_object*) NSOpenGLContextClass, selector);
  		return Context;
  	}
  
  	static void GL_MakeCurrent(const SGLContext &Context)
  	{
  		SEL selector = sel_registerName("makeCurrentContext");
  		objc_msgSend(Context.m_Context, selector);
  	}
  
  	static void GL_ReleaseContext(const SGLContext &Context)
  	{
  		Class NSOpenGLContextClass = (Class) objc_getClass("NSOpenGLContext");
  		SEL selector = sel_registerName("clearCurrentContext");
  		objc_msgSend((objc_object*) NSOpenGLContextClass, selector);
  	}
  
  	static void GL_SwapBuffers(const SGLContext &Context)
  	{
  		SEL selector = sel_registerName("flushBuffer");
  		objc_msgSend(Context.m_Context, selector);
  	}
  
  	class CAutoreleasePool
  	{
  	private:
  		id m_Pool;
  
  	public:
  		CAutoreleasePool()
  		{
  			Class NSAutoreleasePoolClass = (Class) objc_getClass("NSAutoreleasePool");
  			m_Pool = class_createInstance(NSAutoreleasePoolClass, 0);
  			SEL selector = sel_registerName("init");
  			objc_msgSend(m_Pool, selector);
  		}
  
  		~CAutoreleasePool()
  		{
  			SEL selector = sel_registerName("drain");
  			objc_msgSend(m_Pool, selector);
  		}
  	};							
  
  #elif defined(CONF_FAMILY_UNIX)
  
  #if defined(__ANDROID__)
  
  	#include <EGL/egl.h>
  
  	struct SGLContext
  	{
  		EGLDisplay m_Display;
  		EGLSurface m_SurfaceDraw;
  		EGLSurface m_SurfaceRead;
  		EGLContext m_Context;
  	};
  
  	static SGLContext GL_GetCurrentContext()
  	{
  		SGLContext Context;
  		Context.m_Display = eglGetCurrentDisplay();
  		Context.m_SurfaceDraw = eglGetCurrentSurface(EGL_DRAW);
  		Context.m_SurfaceRead = eglGetCurrentSurface(EGL_READ);
  		Context.m_Context = eglGetCurrentContext();
  		return Context;
  	}
  
  	static void GL_MakeCurrent(const SGLContext &Context)
  	{
  		eglMakeCurrent(Context.m_Display, Context.m_SurfaceDraw, Context.m_SurfaceRead, Context.m_Context);
  	}
  	static void GL_ReleaseContext(const SGLContext &Context)
  	{
  		eglMakeCurrent(Context.m_Display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
  	}
  	static void GL_SwapBuffers(const SGLContext &Context)
  	{
  		// eglSwapBuffers(Context.m_Display, Context.m_SurfaceDraw);
  		SDL_GL_SwapBuffers(); // This will also draw on-screen keyboard
  	}
  
  #else
  
  	#include <GL/glx.h>
  
  	struct SGLContext
  	{
  		Display *m_pDisplay;
  		GLXDrawable m_Drawable;
  		GLXContext m_Context;
  	};
  
  	static SGLContext GL_GetCurrentContext()
  	{
  		SGLContext Context;
  		Context.m_pDisplay = glXGetCurrentDisplay();
  		Context.m_Drawable = glXGetCurrentDrawable();
  		Context.m_Context = glXGetCurrentContext();
  		return Context;
  	}
  
  	static void GL_MakeCurrent(const SGLContext &Context) { glXMakeCurrent(Context.m_pDisplay, Context.m_Drawable, Context.m_Context); }
  	static void GL_ReleaseContext(const SGLContext &Context) { glXMakeCurrent(Context.m_pDisplay, None, 0x0); }
  	static void GL_SwapBuffers(const SGLContext &Context) { glXSwapBuffers(Context.m_pDisplay, Context.m_Drawable); }
  
  #endif
  #else
  	#error missing implementation
  #endif
  
  
  // basic threaded backend, abstract, missing init and shutdown functions
  class CGraphicsBackend_Threaded : public IGraphicsBackend
  {
  public:
  	// constructed on the main thread, the rest of the functions is runned on the render thread
  	class ICommandProcessor
  	{
  	public:
  		virtual ~ICommandProcessor() {}
  		virtual void RunBuffer(CCommandBuffer *pBuffer) = 0;
  	};
  
  	CGraphicsBackend_Threaded();
  
  	virtual void RunBuffer(CCommandBuffer *pBuffer);
  	virtual bool IsIdle() const;
  	virtual void WaitForIdle();
  		
  protected:
  	void StartProcessor(ICommandProcessor *pProcessor);
  	void StopProcessor();
  
  private:
  	ICommandProcessor *m_pProcessor;
  	CCommandBuffer * volatile m_pBuffer;
  	volatile bool m_Shutdown;
  	semaphore m_Activity;
  	semaphore m_BufferDone;
  	void *m_pThread;
  
  	static void ThreadFunc(void *pUser);
  };
  
  // takes care of implementation independent operations
  class CCommandProcessorFragment_General
  {
  	void Cmd_Nop();
  	void Cmd_Signal(const CCommandBuffer::SCommand_Signal *pCommand);
  public:
  	bool RunCommand(const CCommandBuffer::SCommand * pBaseCommand);
  };
  
  // takes care of opengl related rendering
  class CCommandProcessorFragment_OpenGL
  {
  	struct CTexture
  	{
  		GLuint m_Tex;
  		int m_MemSize;
  	};
  	CTexture m_aTextures[CCommandBuffer::MAX_TEXTURES];
  	volatile int *m_pTextureMemoryUsage;
  
  public:
  	enum
  	{
  		CMD_INIT = CCommandBuffer::CMDGROUP_PLATFORM_OPENGL,
  	};
  
  	struct SCommand_Init : public CCommandBuffer::SCommand
  	{
  		SCommand_Init() : SCommand(CMD_INIT) {}
  		volatile int *m_pTextureMemoryUsage;
  	};
  
  private:
  	static int TexFormatToOpenGLFormat(int TexFormat);
  	static unsigned char Sample(int w, int h, const unsigned char *pData, int u, int v, int Offset, int ScaleW, int ScaleH, int Bpp);
  	static void *Rescale(int Width, int Height, int NewWidth, int NewHeight, int Format, const unsigned char *pData);
  
  	void SetState(const CCommandBuffer::SState &State);
  
  	void Cmd_Init(const SCommand_Init *pCommand);
  	void Cmd_Texture_Update(const CCommandBuffer::SCommand_Texture_Update *pCommand);
  	void Cmd_Texture_Destroy(const CCommandBuffer::SCommand_Texture_Destroy *pCommand);
  	void Cmd_Texture_Create(const CCommandBuffer::SCommand_Texture_Create *pCommand);
  	void Cmd_Clear(const CCommandBuffer::SCommand_Clear *pCommand);
  	void Cmd_Render(const CCommandBuffer::SCommand_Render *pCommand);
  	void Cmd_Screenshot(const CCommandBuffer::SCommand_Screenshot *pCommand);
  
  public:
  	CCommandProcessorFragment_OpenGL();
  
  	bool RunCommand(const CCommandBuffer::SCommand * pBaseCommand);
  };
  
  // takes care of sdl related commands
  class CCommandProcessorFragment_SDL
  {
  	// SDL stuff
  	SGLContext m_GLContext;
  public:
  	enum
  	{
  		CMD_INIT = CCommandBuffer::CMDGROUP_PLATFORM_SDL,
  		CMD_SHUTDOWN,
  	};
  
  	struct SCommand_Init : public CCommandBuffer::SCommand
  	{
  		SCommand_Init() : SCommand(CMD_INIT) {}
  		SGLContext m_Context;
  	};
  
  	struct SCommand_Shutdown : public CCommandBuffer::SCommand
  	{
  		SCommand_Shutdown() : SCommand(CMD_SHUTDOWN) {}
  	};
  
  private:
  	void Cmd_Init(const SCommand_Init *pCommand);
  	void Cmd_Shutdown(const SCommand_Shutdown *pCommand);
  	void Cmd_Swap(const CCommandBuffer::SCommand_Swap *pCommand);
  	void Cmd_VideoModes(const CCommandBuffer::SCommand_VideoModes *pCommand);
  public:
  	CCommandProcessorFragment_SDL();
  
  	bool RunCommand(const CCommandBuffer::SCommand *pBaseCommand);
  };
  
  // command processor impelementation, uses the fragments to combine into one processor
  class CCommandProcessor_SDL_OpenGL : public CGraphicsBackend_Threaded::ICommandProcessor
  {
   	CCommandProcessorFragment_OpenGL m_OpenGL;
   	CCommandProcessorFragment_SDL m_SDL;
   	CCommandProcessorFragment_General m_General;
   public:
  	virtual void RunBuffer(CCommandBuffer *pBuffer);
  };
  
  // graphics backend implemented with SDL and OpenGL
  class CGraphicsBackend_SDL_OpenGL : public CGraphicsBackend_Threaded
  {
  	SDL_Surface *m_pScreenSurface;
  	ICommandProcessor *m_pProcessor;
  	SGLContext m_GLContext;
  	volatile int m_TextureMemoryUsage;
  public:
  	virtual int Init(const char *pName, int *Width, int *Height, int FsaaSamples, int Flags);
  	virtual int Shutdown();
  
  	virtual int MemoryUsage() const;
  
  	virtual void Minimize();
  	virtual void Maximize();
  	virtual int WindowActive();
  	virtual int WindowOpen();
  };
  