ecere: gfx/gui: add SDL 2.x support via new driver named SDL2.
authorRejean Loyer <redj@ecere.com>
Mon, 18 Aug 2014 16:46:43 +0000 (12:46 -0400)
committerRejean Loyer <redj@ecere.com>
Mon, 16 Mar 2015 05:31:50 +0000 (01:31 -0400)
ecere/ecere.epj
ecere/src/gfx/drivers/SDL2DisplayDriver.ec [new file with mode: 0644]
ecere/src/gui/drivers/SDL2Interface.ec [new file with mode: 0644]

index 632b9da..4d34cdc 100644 (file)
@@ -86,7 +86,9 @@ from wherever you obtained them.
          "png",
          "z",
          "freetype",
          "png",
          "z",
          "freetype",
-         "SDL"
+         "SDL",
+         "SDL2",
+         "SDL2main"
       ]
    },
    "Platforms" : [
       ]
    },
    "Platforms" : [
@@ -1588,6 +1590,18 @@ from wherever you obtained them.
                            "Options" : {
                               "ExcludeFromBuild" : false
                            }
                            "Options" : {
                               "ExcludeFromBuild" : false
                            }
+                        },
+                        {
+                           "FileName" : "SDL2DisplayDriver.ec",
+                           "Options" : {
+                              "ExcludeFromBuild" : false
+                           }
+                        },
+                        {
+                           "FileName" : "SDL2DisplayDriver.ec",
+                           "Options" : {
+                              "ExcludeFromBuild" : false
+                           }
                         }
                      ],
                      "Options" : {
                         }
                      ],
                      "Options" : {
@@ -1939,6 +1953,18 @@ from wherever you obtained them.
                            "Options" : {
                               "ExcludeFromBuild" : false
                            }
                            "Options" : {
                               "ExcludeFromBuild" : false
                            }
+                        },
+                        {
+                           "FileName" : "SDL2Interface.ec",
+                           "Options" : {
+                              "ExcludeFromBuild" : false
+                           }
+                        },
+                        {
+                           "FileName" : "SDL2Interface.ec",
+                           "Options" : {
+                              "ExcludeFromBuild" : false
+                           }
                         }
                      ],
                      "Options" : {
                         }
                      ],
                      "Options" : {
diff --git a/ecere/src/gfx/drivers/SDL2DisplayDriver.ec b/ecere/src/gfx/drivers/SDL2DisplayDriver.ec
new file mode 100644 (file)
index 0000000..1db5b16
--- /dev/null
@@ -0,0 +1,592 @@
+namespace gfx::drivers;
+
+#ifdef BUILDING_ECERE_COM
+import "instance"
+import "Display"
+#else
+#ifdef ECERE_STATIC
+public import static "ecere"
+#else
+public import "ecere"
+#endif
+#endif
+
+import "SDL2Interface"
+
+#if !defined(NO_SDL_DRIVERS) && !defined(NO_SDL2_DRIVER)
+
+#include <stdio.h>
+
+// source file line number printf (sflnprintf)
+#define sflnprintf(format,...) printf("%s:% 5d: " format, __FILE__, __LINE__, ##__VA_ARGS__)
+
+#include <SDL2/SDL.h> // <-- modified mingw32 "psdk_inc/intrin-impl.h" header in place awayting int128/uint128 support in eC
+#if 0
+#if __INTRINSIC_PROLOG(_umul128)
+unsigned __int64 _umul128(unsigned __int64, unsigned __int64, unsigned __int64 *);
+__INTRINSICS_USEINLINE
+unsigned __int64 _umul128(unsigned __int64 a, unsigned __int64 b, unsigned __int64 *hi)
+{
+   __MINGW_EXTENSION union { unsigned __int128 v; unsigned __int64 sv[2]; } var;
+   var.v = a;
+   var.v *= b;
+   if (hi) *hi = var.sv[1];
+   return var.sv[0];
+}
+#define __INTRINSIC_DEFINED__umul128
+#endif /* __INTRINSIC_PROLOG */
+
+#if __INTRINSIC_PROLOG(_mul128)
+__int64 _mul128(__int64, __int64, __int64 *);
+__INTRINSICS_USEINLINE
+__int64 _mul128(__int64 a, __int64 b, __int64 *hi)
+{
+   __MINGW_EXTENSION union { __int128 v; __int64 sv[2]; } var;
+   var.v = a;
+   var.v *= b;
+   if (hi) *hi = var.sv[1];
+   return var.sv[0];
+}
+#define __INTRINSIC_DEFINED__mul128
+#endif /* __INTRINSIC_PROLOG */
+#endif
+
+class SDL2Display : LFBDisplay
+{
+   SDL_Renderer * ren;
+};
+
+class SDL2DisplayDriver : DisplayDriver
+{
+   class_property(name) = "SDL2";
+
+
+   // Constructor / Destructor
+
+   bool ::CreateDisplaySystem(DisplaySystem displaySystem)
+   {
+      bool result = false;
+      sflnprintf("class(SDL2DisplayDriver) ::CreateDisplaySystem [WIP!]\n");
+      displaySystem.flags.memBackBuffer = true;
+      result = true;
+      return result;
+   }
+
+   void ::DestroyDisplaySystem(DisplaySystem displaySystem)
+   {
+      sflnprintf("class(SDL2DisplayDriver) ::DestroyDisplaySystem [STUB!]\n");
+   }
+
+   bool ::CreateDisplay(Display display)
+   {
+      bool result = false;
+      SDL_Window * wnd = display.window;
+      SDL_Renderer * ren = SDL_GetRenderer(wnd);
+      SDL2Display sdlDisplay = display.driverData = SDL2Display { ren = ren };
+      sflnprintf("class(SDL2DisplayDriver) ::CreateDisplay [WIP!]\n");
+      if(sdlDisplay)
+      {
+         // To find out the format...
+         DisplaySize(display, 1, 1);
+         result = true;
+      }
+      return result;
+   }
+
+   void ::DestroyDisplay(Display display)
+   {
+      SDL2Display sdlDisplay = display.driverData;
+      sflnprintf("class(SDL2DisplayDriver) ::DestroyDisplay [STUB!]\n");
+      if(display)
+         ((subclass(DisplayDriver))class(LFBDisplayDriver)).DestroyDisplay(display);
+
+      // TODO: Implementation
+
+      delete sdlDisplay;
+      display.driverData = null;
+   }
+
+
+   // Display Position and Size
+
+   bool ::DisplaySize(Display display, int width, int height)
+   {
+      SDL2Display sdlDisplay = display.driverData;
+      bool result = false;
+      sflnprintf("class(SDL2DisplayDriver) ::DisplaySize [WIP!]\n");
+
+      // TODO: Implementation
+
+      /*
+      bool validFormat = true;
+      switch(backDesc.ddpfPixelFormat.dwRGBBitCount)
+      {
+         case 8: bitmap.pixelFormat = pixelFormat8; break;
+         case 15: bitmap.pixelFormat = pixelFormat555; break;
+         case 16:
+            if(backDesc.ddpfPixelFormat.dwGBitMask == 0x3E0)
+               bitmap.pixelFormat = pixelFormat555;
+            else
+               bitmap.pixelFormat = pixelFormat565;
+            break;
+         case 32:
+            bitmap.pixelFormat = pixelFormat888; break;
+         default:
+            validFormat = false;
+            break;
+      }
+      if(validFormat)
+      {
+         bitmap.picture = (byte *)backDesc.lpSurface;
+         bitmap.stride = backDesc.lPitch;
+         bitmap.stride >>= GetColorDepthShifts(bitmap.pixelFormat);
+         bitmap.size = bitmap.stride * bitmap.height;
+      }
+      */
+      display.displaySystem.pixelFormat = sdlDisplay.bitmap.pixelFormat;
+      result = true;
+
+      ((subclass(DisplayDriver))class(LFBDisplayDriver)).DisplaySize(display, width, height);
+
+      display.width = width;
+      display.height = height;
+
+      return result;
+   }
+
+   void ::DisplayPosition(Display display, int x, int y)
+   {
+      ((subclass(DisplayDriver))class(LFBDisplayDriver)).DisplayPosition(display, x, y);
+   }
+
+
+   // Palettes
+
+   void ::SetPalette(Display display, ColorAlpha * palette, bool colorMatch)
+   {
+      SDL2Display sdlDisplay = display.driverData;
+      sflnprintf("class(SDL2DisplayDriver) ::SetPalette [WIP!]\n");
+      if(sdlDisplay.bitmap.pixelFormat == pixelFormat8)
+      {
+         // TODO: Implementation
+      }
+      else
+         ((subclass(DisplayDriver))class(LFBDisplayDriver)).SetPalette(display, palette, colorMatch);
+   }
+
+   void ::RestorePalette(Display display)
+   {
+      //SDL2Display sdlDisplay = display.driverData;
+      sflnprintf("class(SDL2DisplayDriver) ::RestorePalette [STUB!]\n");
+   }
+
+
+   // Display the back buffer content
+
+   void ::StartUpdate(Display display)
+   {
+      //SDL2Display sdlDisplay = display.driverData;
+      sflnprintf("class(SDL2DisplayDriver) ::StartUpdate [STUB!]\n");
+   }
+
+   void ::EndUpdate(Display display)
+   {
+      SDL2Display sdlDisplay = display.driverData;
+      sflnprintf("class(SDL2DisplayDriver) ::EndUpdate [STUB!]\n");
+      SDL_RenderPresent(sdlDisplay.ren);
+   }
+
+   void ::Scroll(Display display, Box scroll, int x, int y, Extent dirty)
+   {
+      sflnprintf("class(SDL2DisplayDriver) ::Scroll [STUB!]\n");
+   }
+
+   void ::Update(Display display, Box updateBox)
+   {
+      SDL2Display sdlDisplay = display.driverData;
+      //--//Box * box = updateBox;
+      sflnprintf("class(SDL2DisplayDriver) ::Update [STUB!]\n");
+      SDL_RenderPresent(sdlDisplay.ren);
+   }
+
+
+   // Allocate/free a bitmap
+
+   bool ::AllocateBitmap(DisplaySystem displaySystem, Bitmap bitmap, int width, int height, int stride, PixelFormat format, bool allocatePalette)
+   {
+      return ((subclass(DisplayDriver))class(LFBDisplayDriver)).AllocateBitmap(displaySystem, bitmap, width, height, stride, format, allocatePalette);
+   }
+
+   void ::FreeBitmap(DisplaySystem displaySystem, Bitmap bitmap)
+   {
+      ((subclass(DisplayDriver))class(LFBDisplayDriver)).FreeBitmap(displaySystem, bitmap);
+   }
+
+
+   // Lock
+
+   bool ::LockSystem(DisplaySystem displaySystem)
+   {
+      sflnprintf("class(SDL2DisplayDriver) ::LockSystem [STUB!]\n");
+      return false;
+   }
+
+   void ::UnlockSystem(DisplaySystem displaySystem)
+   {
+      sflnprintf("class(SDL2DisplayDriver) ::UnlockSystem [STUB!]\n");
+   }
+
+   bool ::Lock(Display display)
+   {
+      //SDL2Display sdlDisplay = display.driverData;
+      //sflnprintf("class(SDL2DisplayDriver) ::Lock [STUB!]\n");
+      return true;
+   }
+
+   void ::Unlock(Display display)
+   {
+      //SDL2Display sdlDisplay = display.driverData;
+      //sflnprintf("class(SDL2DisplayDriver) ::Unlock [STUB!]\n");
+   }
+
+
+   // Get/release a surface
+
+   bool ::GetSurface(Display display, Surface surface, int x, int y, Box clip)
+   {
+      //SDL2Display sdlDisplay = display.driverData;
+      LFBSurface lfbSurface;
+      bool result = false;
+      sflnprintf("class(SDL2DisplayDriver) ::GetSurface [WIP!]\n");
+      {
+         if((surface.driverData = lfbSurface = LFBSurface { }))
+         {
+            surface.offset.x = x;
+            surface.offset.y = y;
+            //surface.unclippedBox = surface.box = clip;
+            // TODO: Implementation
+            result = ((subclass(DisplayDriver))class(LFBDisplayDriver)).GetSurface(display, surface, x, y, clip);
+         }
+      }
+      return result;
+   }
+
+   bool ::GetBitmapSurface(DisplaySystem displaySystem, Surface surface, Bitmap bitmap, int x, int y, Box clip)
+   {
+      return ((subclass(DisplayDriver))class(LFBDisplayDriver)).GetBitmapSurface(displaySystem, surface, bitmap, x, y, clip);
+   }
+
+   void ::ReleaseSurface(Display display, Surface surface)
+   {
+      //SDL2Display sdlDisplay = display.driverData;
+      sflnprintf("class(SDL2DisplayDriver) ::ReleaseSurface [WIP!]\n");
+      ((subclass(DisplayDriver))class(LFBDisplayDriver)).ReleaseSurface(display, surface);
+      // TODO: Implementation
+   }
+
+
+   // Clip a surface
+
+   void ::Clip(Display display, Surface surface, Box clip)
+   {
+      ((subclass(DisplayDriver))class(LFBDisplayDriver)).Clip(display, surface, clip);
+   }
+
+
+   // Grab from the screen
+
+   bool ::GrabScreen(Display display, Bitmap bitmap, int x, int y, unsigned int w, unsigned int h)
+   {
+      bool result = false;
+      //SDL2Display sdlDisplay = display.driverData;
+      sflnprintf("class(SDL2DisplayDriver) ::GrabScreen [WIP!]\n");
+      // TODO: Implementation
+      result = ((subclass(DisplayDriver))class(LFBDisplayDriver)).GrabScreen(display, bitmap, x,y, w,h);
+      return result;
+   }
+
+
+   // Converts a bitmap format
+
+   bool ::ConvertBitmap(DisplaySystem displaySystem, Bitmap src, PixelFormat format, ColorAlpha * palette)
+   {
+      return ((subclass(DisplayDriver))class(LFBDisplayDriver)).ConvertBitmap(displaySystem, src, format, palette);
+   }
+
+
+   // Converts an LFB bitmap into an offscreen bitmap for this device
+
+   bool ::MakeDDBitmap(DisplaySystem displaySystem, Bitmap bitmap, bool mipMaps)
+   {
+      return ((subclass(DisplayDriver))class(LFBDisplayDriver)).MakeDDBitmap(displaySystem, bitmap, mipMaps);
+   }
+
+
+   // Font loading
+
+   Font ::LoadFont(DisplaySystem displaySystem, const char * faceName, float size, FontFlags flags)
+   {
+      Font font = (Font)((subclass(DisplayDriver))class(LFBDisplayDriver)).LoadFont(displaySystem, faceName, size, flags);
+      return font;
+   }
+
+   void ::UnloadFont(DisplaySystem displaySystem, Font font)
+   {
+      ((subclass(DisplayDriver))class(LFBDisplayDriver)).UnloadFont(displaySystem, font);
+   }
+
+
+   // 2D Drawing
+
+   void ::SetForeground(Display display, Surface surface, ColorAlpha color)
+   {
+      ((subclass(DisplayDriver))class(LFBDisplayDriver)).SetForeground(display, surface, color);
+   }
+
+   void ::SetBackground(Display display, Surface surface, ColorAlpha color)
+   {
+      ((subclass(DisplayDriver))class(LFBDisplayDriver)).SetBackground(display, surface, color);
+   }
+
+   void ::SetBlitTint(Display display, Surface surface, ColorAlpha tint)
+   {
+      sflnprintf("class(SDL2DisplayDriver) ::SetBlitTint [STUB!]\n");
+   }
+
+   void ::LineStipple(Display display, Surface surface, uint stipple)
+   {
+      ((subclass(DisplayDriver))class(LFBDisplayDriver)).LineStipple(display, surface, stipple);
+   }
+
+   ColorAlpha ::GetPixel(Display display, Surface surface, int x, int y)
+   {
+      sflnprintf("class(SDL2DisplayDriver) ::GetPixel [STUB!]\n");
+      return 0;
+   }
+
+   void ::PutPixel(Display display, Surface surface, int x, int y)
+   {
+      ((subclass(DisplayDriver))class(LFBDisplayDriver)).PutPixel(display, surface, x,y);
+   }
+
+   void ::DrawLine(Display display, Surface surface, int x1, int y1, int x2, int y2)
+   {
+      ((subclass(DisplayDriver))class(LFBDisplayDriver)).DrawLine(display, surface, x1,y1,x2,y2);
+   }
+
+   void ::Rectangle(Display display, Surface surface, int x1, int y1, int x2, int y2)
+   {
+      ((subclass(DisplayDriver))class(LFBDisplayDriver)).Rectangle(display, surface, x1,y1,x2,y2);
+   }
+
+   void ::Area(Display display, Surface surface, int x1, int y1, int x2, int y2)
+   {
+      SDL2Display sdlDisplay = display.driverData;
+      sflnprintf("class(SDL2DisplayDriver) ::Area [STUB!]\n");
+  /*    if(x1>x2) { int tmp = x2; x2 = x1; x1 = tmp; }
+
+      if(x1<surface.box.left)  x1=surface.box.left;
+      if(x2>surface.box.right) x2=surface.box.right;
+      if(y1<surface.box.top)   y1=surface.box.top;
+      if(y2>surface.box.bottom)  y2=surface.box.bottom;
+*/
+      x1 += surface.offset.x;
+      x2 += surface.offset.x;
+      y1 += surface.offset.y;
+      y2 += surface.offset.y;
+
+      {
+         /*SDL_Window * wnd = display.window;
+         SDL_Renderer * ren = SDL_GetRenderer(wnd);*/
+         if(sdlDisplay.ren)
+         {
+            SDL_Rect rect = { (short)x1, (short)y1, (short)(x2-x1+1), (short)(y2-y1+1) };
+            SDL_SetRenderDrawColor(sdlDisplay.ren, surface.background.color.r, surface.background.color.g, surface.background.color.b, surface.background.a);
+            SDL_RenderFillRect(sdlDisplay.ren, &rect);
+         }
+         //((subclass(DisplayDriver))class(LFBDisplayDriver)).Area(display, surface, x1,y1,x2,y2);
+      }
+   }
+
+   void ::Clear(Display display, Surface surface, ClearType type)
+   {
+      sflnprintf("class(SDL2DisplayDriver) ::Clear [WIP!]\n");
+      //--//SDL_Rect rect = { (short)surface.box.left, (short)surface.box.top, (short)(surface.box.right-surface.box.left+1), (short)(surface.box.bottom-surface.box.top+1) };
+      //--//SDL_SetRenderDrawColor(surface.background.color.r, surface.background.color.g, surface.background.color.b, surface.background.a);
+      //--//SDL_RenderFill(&rect);
+      ((subclass(DisplayDriver))class(LFBDisplayDriver)).Clear(display, surface, type);
+   }
+
+   void ::Blit(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
+   {
+      ((subclass(DisplayDriver))class(LFBDisplayDriver)).Blit(display, surface, src, dx, dy, sx, sy, w, h);
+   }
+
+   void ::Stretch(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
+   {
+      ((subclass(DisplayDriver))class(LFBDisplayDriver)).Stretch(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
+   }
+
+   void ::Filter(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
+   {
+      ((subclass(DisplayDriver))class(LFBDisplayDriver)).Filter(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
+   }
+
+   void ::BlitDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h)
+   {
+      // Using Blit()
+      ((subclass(DisplayDriver))class(LFBDisplayDriver)).Blit(display, surface, src, dx, dy, sx, sy, w, h);
+   }
+
+   void ::StretchDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
+   {
+      // Using Stretch()
+      ((subclass(DisplayDriver))class(LFBDisplayDriver)).Stretch(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
+   }
+
+   void ::FilterDI(Display display, Surface surface, Bitmap src, int dx, int dy, int sx, int sy, int w, int h, int sw, int sh)
+   {
+      // Using Filter()
+      //Filter(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
+      ((subclass(DisplayDriver))class(LFBDisplayDriver)).Filter(display, surface, src, dx, dy, sx, sy, w, h, sw, sh);
+   }
+
+   void ::TextFont(Display display, Surface surface, Font font)
+   {
+      ((subclass(DisplayDriver))class(LFBDisplayDriver)).TextFont(display, surface, font);
+      // why this?
+      SetForeground(display, surface, surface.foreground);
+   }
+
+   void ::TextOpacity(Display display, Surface surface, bool opaque)
+   {
+      ((subclass(DisplayDriver))class(LFBDisplayDriver)).TextOpacity(display, surface, opaque);
+   }
+
+   void ::WriteText(Display display, Surface surface, int x, int y, const char * text, int len)
+   {
+      if(surface.textOpacity)
+      {
+         int w, h;
+         ((subclass(DisplayDriver))class(LFBDisplayDriver)).FontExtent(display.displaySystem, surface.font, text, len, &w, &h);
+         Area(display, surface, x, y, x+w-1, y+h-1);
+      }
+      ((subclass(DisplayDriver))class(LFBDisplayDriver)).WriteText(display, surface, x,y, text, len);
+   }
+
+   void ::TextExtent(Display display, Surface surface, const char * text, int len, int * width, int * height)
+   {
+      ((subclass(DisplayDriver))class(LFBDisplayDriver)).TextExtent(display, surface, text, len, width, height);
+   }
+
+   void ::FontExtent(DisplaySystem displaySystem, Font font, const char * text, int len, int * width, int * height)
+   {
+      ((subclass(DisplayDriver))class(LFBDisplayDriver)).FontExtent(displaySystem, font, text, len, width, height);
+   }
+
+   void ::DrawingChar(Display display, Surface surface, char character)
+   {
+      //sflnprintf("class(SDL2DisplayDriver) ::DrawingChar [STUB!]\n");
+   }
+
+   void ::NextPage(Display display)
+   {
+      sflnprintf("class(SDL2DisplayDriver) ::NextPage [STUB!]\n");
+   }
+
+   // 3D Graphics
+
+#if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
+   void ::SetRenderState(Display display, RenderState state, uint value)
+   {
+      sflnprintf("class(SDL2DisplayDriver) ::SetRenderState [STUB!]\n");
+   }
+
+   void ::SetLight(Display display, int id, Light light)
+   {
+      sflnprintf("class(SDL2DisplayDriver) ::SetLight [STUB!]\n");
+   }
+
+   void ::SetCamera(Display display, Surface surface, Camera camera)
+   {
+      sflnprintf("class(SDL2DisplayDriver) ::SetCamera [STUB!]\n");
+   }
+
+   bool ::AllocateMesh(DisplaySystem displaySystem, Mesh mesh, MeshFeatures flags, int nVertices)
+   {
+      sflnprintf("class(SDL2DisplayDriver) ::AllocateMesh [STUB!]\n");
+      return false;
+   }
+
+   void ::FreeMesh(DisplaySystem displaySystem, Mesh mesh)
+   {
+      sflnprintf("class(SDL2DisplayDriver) ::FreeMesh [STUB!]\n");
+   }
+
+   bool ::LockMesh(DisplaySystem displaySystem, Mesh mesh, MeshFeatures flags)
+   {
+      sflnprintf("class(SDL2DisplayDriver) ::LockMesh [STUB!]\n");
+      return false;
+   }
+
+   void ::UnlockMesh(DisplaySystem displaySystem, Mesh mesh, MeshFeatures flags)
+   {
+      sflnprintf("class(SDL2DisplayDriver) ::UnlockMesh [STUB!]\n");
+   }
+
+   void * ::AllocateIndices(DisplaySystem displaySystem, int nIndices, bool indices32bit)
+   {
+      sflnprintf("class(SDL2DisplayDriver) ::AllocateIndices [STUB!]\n");
+      return null;
+   }
+
+   void ::FreeIndices(DisplaySystem displaySystem, void * indices)
+   {
+      sflnprintf("class(SDL2DisplayDriver) ::FreeIndices [STUB!]\n");
+   }
+
+   uint16 * ::LockIndices(DisplaySystem displaySystem, void * indices)
+   {
+      sflnprintf("class(SDL2DisplayDriver) ::LockIndices [STUB!]\n");
+      return null;
+   }
+
+   void ::UnlockIndices(DisplaySystem displaySystem, void * indices, bool indices32bit, int nIndices)
+   {
+      sflnprintf("class(SDL2DisplayDriver) ::UnlockIndices [STUB!]\n");
+   }
+
+   void ::SelectMesh(Display display, Mesh mesh)
+   {
+      sflnprintf("class(SDL2DisplayDriver) ::SelectMesh [STUB!]\n");
+   }
+
+   void ::ApplyMaterial(Display display, Material material, Mesh mesh)
+   {
+      sflnprintf("class(SDL2DisplayDriver) ::ApplyMaterial [STUB!]\n");
+   }
+
+   void ::DrawPrimitives(Display display, PrimitiveSingle * primitive, Mesh mesh)
+   {
+      sflnprintf("class(SDL2DisplayDriver) ::DrawPrimitives [STUB!]\n");
+   }
+
+   void ::PushMatrix(Display display)
+   {
+      sflnprintf("class(SDL2DisplayDriver) ::PushMatrix [STUB!]\n");
+   }
+
+   void ::PopMatrix(Display display, bool setMatrix)
+   {
+      sflnprintf("class(SDL2DisplayDriver) ::PopMatrix [STUB!]\n");
+   }
+
+   void ::SetTransform(Display display, Matrix transMatrix, bool viewSpace, bool useCamera)
+   {
+      sflnprintf("class(SDL2DisplayDriver) ::SetTransform [STUB!]\n");
+   }
+#endif
+
+}
+
+#endif // !defined(NO_SDL_DRIVERS) && !defined(NO_SDL2_DRIVER)
diff --git a/ecere/src/gui/drivers/SDL2Interface.ec b/ecere/src/gui/drivers/SDL2Interface.ec
new file mode 100644 (file)
index 0000000..f5abf67
--- /dev/null
@@ -0,0 +1,724 @@
+namespace gui::drivers;
+
+#ifdef BUILDING_ECERE_COM
+import "Window"
+import "Interface"
+#else
+#ifdef ECERE_STATIC
+public import static "ecere"
+#else
+public import "ecere"
+#endif
+#endif
+
+import "SDL2DisplayDriver"
+
+#if !defined(NO_SDL_DRIVERS) && !defined(NO_SDL2_DRIVER)
+
+#include <stdio.h>
+
+// source file line number printf (sflnprintf)
+#define sflnprintf(format,...) printf("%s:% 5d: " format, __FILE__, __LINE__, ##__VA_ARGS__)
+
+#include <SDL2/SDL.h> // <-- modified mingw32 "psdk_inc/intrin-impl.h" header in place awayting int128/uint128 support in eC
+#if 0
+#if __INTRINSIC_PROLOG(_umul128)
+unsigned __int64 _umul128(unsigned __int64, unsigned __int64, unsigned __int64 *);
+__INTRINSICS_USEINLINE
+unsigned __int64 _umul128(unsigned __int64 a, unsigned __int64 b, unsigned __int64 *hi)
+{
+   __MINGW_EXTENSION union { unsigned __int128 v; unsigned __int64 sv[2]; } var;
+   var.v = a;
+   var.v *= b;
+   if (hi) *hi = var.sv[1];
+   return var.sv[0];
+}
+#define __INTRINSIC_DEFINED__umul128
+#endif /* __INTRINSIC_PROLOG */
+
+#if __INTRINSIC_PROLOG(_mul128)
+__int64 _mul128(__int64, __int64, __int64 *);
+__INTRINSICS_USEINLINE
+__int64 _mul128(__int64 a, __int64 b, __int64 *hi)
+{
+   __MINGW_EXTENSION union { __int128 v; __int64 sv[2]; } var;
+   var.v = a;
+   var.v *= b;
+   if (hi) *hi = var.sv[1];
+   return var.sv[0];
+}
+#define __INTRINSIC_DEFINED__mul128
+#endif /* __INTRINSIC_PROLOG */
+#endif
+
+static bool fullScreenMode;
+
+class SDL2Interface : Interface
+{
+   class_property(name) = "SDL2";
+
+
+   /****************************************************************************
+      /// PRIVATE UTILITY FUNCTIONS /////////////
+   ****************************************************************************/
+   void ::RepositionDesktop(bool updateChildren)
+   {
+      // TODO: Implement this
+      int x = 0, y = 0, w = 0, h = 0;
+      guiApp.SetDesktopPosition(x, y, w, h, updateChildren);
+   }
+
+   bool ::ProcessKeyMessage(Key key, unichar ch)
+   {
+      bool result = true;
+      //Key code = key;
+
+      // TODO: Implement this
+
+      // MouseWheel
+      // result = window.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit, code, 0);
+
+      // KeyUp
+      // result = window.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyUp, code, ch);
+
+      // KeyDown
+      // result = window.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown, code, ch);
+
+      // KeyHit
+      // result = window.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit, code,ch);
+      return result;
+   }
+
+
+   // TODO: Implement these
+
+   // Activated (Special code to write to handle modal windows...)
+   // window.ExternalActivate(true, true, window, null);
+
+   // Application Activated
+   //  guiApp.SetAppFocus
+
+
+   // Window Redraw
+   //  window.UpdateDirty(box);
+
+
+   // Resolution changed
+   // guiApp.desktop.DisplayModeChanged()
+
+   // IME Code
+
+   // Keyboard and Mouse Messages
+
+
+   // Timer 18.2 times per second: Call guiApp.SignalEvent();
+
+   // Mouse Cursors
+
+   /****************************************************************************
+      /// DRIVER IMPLEMENTATION /////////////
+   ****************************************************************************/
+
+
+   // --- User Interface System ---
+
+   bool ::Initialize()
+   {
+      return SDL_Init(SDL_INIT_EVERYTHING) == 0;
+   }
+
+   void ::Terminate()
+   {
+      SDL_Quit();
+   }
+
+   bool ::ProcessInput(bool processAll)
+   {
+      bool result;
+      int count;
+      SDL_Event event;
+      //sflnprintf("class(SDL2Interface) ::ProcessInput [WIP!]\n");
+      for(count = SDL_PollEvent(&event), result = count > 0; count > 0; count = SDL_PollEvent(&event))
+      {
+         switch(event.type)
+         {
+            // Window
+            case SDL_WINDOWEVENT:
+            {
+               uint32 windowID = event.window.windowID;
+               SDL_Window * wnd = SDL_GetWindowFromID(windowID);
+               Window window = SDL_GetWindowData(wnd, "Ecere");
+               if(wnd && window)
+               {
+                  switch(event.window.event)
+                  {
+                     case SDL_WINDOWEVENT_SHOWN:
+                        //sflnprintf("class(SDL2Interface) ::ProcessInput [SDL_WINDOWEVENT_SHOWN]\n");
+                        break;
+                     case SDL_WINDOWEVENT_HIDDEN:
+                        //sflnprintf("class(SDL2Interface) ::ProcessInput [SDL_WINDOWEVENT_HIDDEN]\n");
+                        break;
+                     case SDL_WINDOWEVENT_EXPOSED:
+                     {
+                        //sflnprintf("class(SDL2Interface) ::ProcessInput [SDL_WINDOWEVENT_EXPOSED]\n");
+                        /*SDL_Rect rect = { 0,0,800,600};
+                        SDL_SetRenderDrawColor(0,120,200,255);
+                        SDL_RenderFill(&rect);
+                        SDL_RenderPresent();  */
+                        window.Update(null);
+                        break;
+                     }
+                     case SDL_WINDOWEVENT_MOVED:
+                     {
+                        int x,y,w,h;
+                        //sflnprintf("class(SDL2Interface) ::ProcessInput [SDL_WINDOWEVENT_MOVED]\n");
+                        SDL_GetWindowSize(wnd, &w, &h);
+                        SDL_GetWindowPosition(wnd, &x, &y);
+                        window.ExternalPosition(x, y, w, h);
+                        break;
+                     }
+                     case SDL_WINDOWEVENT_RESIZED:
+                     {
+                        int x,y,w,h;
+                        //sflnprintf("class(SDL2Interface) ::ProcessInput [SDL_WINDOWEVENT_RESIZED]\n");
+                        SDL_GetWindowSize(wnd, &w, &h);
+                        SDL_GetWindowPosition(wnd, &x, &y);
+                        window.ExternalPosition(x, y, w, h);
+                        break;
+                     }
+                     case SDL_WINDOWEVENT_SIZE_CHANGED:
+                        //sflnprintf("class(SDL2Interface) ::ProcessInput [SDL_WINDOWEVENT_SIZE_CHANGED]\n");
+                        break;
+                     case SDL_WINDOWEVENT_MINIMIZED:
+                        //sflnprintf("class(SDL2Interface) ::ProcessInput [SDL_WINDOWEVENT_MINIMIZED]\n");
+                        break;
+                     case SDL_WINDOWEVENT_MAXIMIZED:
+                        //sflnprintf("class(SDL2Interface) ::ProcessInput [SDL_WINDOWEVENT_MAXIMIZED]\n");
+                        break;
+                     case SDL_WINDOWEVENT_RESTORED:
+                        //sflnprintf("class(SDL2Interface) ::ProcessInput [SDL_WINDOWEVENT_RESTORED]\n");
+                        break;
+                     case SDL_WINDOWEVENT_ENTER:
+                        //sflnprintf("class(SDL2Interface) ::ProcessInput [SDL_WINDOWEVENT_ENTER]\n");
+                        break;
+                     case SDL_WINDOWEVENT_LEAVE:
+                        //sflnprintf("class(SDL2Interface) ::ProcessInput [SDL_WINDOWEVENT_LEAVE]\n");
+                        break;
+                     case SDL_WINDOWEVENT_FOCUS_GAINED:
+                        //sflnprintf("class(SDL2Interface) ::ProcessInput [SDL_WINDOWEVENT_FOCUS_GAINED]\n");
+                        break;
+                     case SDL_WINDOWEVENT_FOCUS_LOST:
+                        //sflnprintf("class(SDL2Interface) ::ProcessInput [SDL_WINDOWEVENT_FOCUS_LOST]\n");
+                        break;
+                     case SDL_WINDOWEVENT_CLOSE:
+                     {
+                        window.Destroy(0);
+                        break;
+                     }
+
+                  }
+               }
+               break;
+            }
+            case SDL_SYSWMEVENT:
+               sflnprintf("class(SDL2Interface) ::ProcessInput [Window Event]\n");
+               break;
+
+            // Keyboard
+            case SDL_KEYDOWN:
+            case SDL_KEYUP:
+            case SDL_TEXTEDITING:
+            case SDL_TEXTINPUT:
+               sflnprintf("class(SDL2Interface) ::ProcessInput [Keyboard Event]\n");
+               break;
+
+            // Mouse
+            case SDL_MOUSEMOTION:
+            case SDL_MOUSEBUTTONDOWN:
+            case SDL_MOUSEBUTTONUP:
+            case SDL_MOUSEWHEEL:
+               sflnprintf("class(SDL2Interface) ::ProcessInput [Mouse Event]\n");
+               break;
+
+            // Joystick
+            case SDL_JOYAXISMOTION:
+            case SDL_JOYBALLMOTION:
+            case SDL_JOYHATMOTION:
+            case SDL_JOYBUTTONDOWN:
+            case SDL_JOYBUTTONUP:
+            case SDL_JOYDEVICEADDED:
+            case SDL_JOYDEVICEREMOVED:
+               sflnprintf("class(SDL2Interface) ::ProcessInput [Joystick Event]\n");
+               break;
+
+            // Controller
+            case SDL_CONTROLLERAXISMOTION:
+            case SDL_CONTROLLERBUTTONDOWN:
+            case SDL_CONTROLLERBUTTONUP:
+            case SDL_CONTROLLERDEVICEADDED:
+            case SDL_CONTROLLERDEVICEREMOVED:
+            case SDL_CONTROLLERDEVICEREMAPPED:
+               sflnprintf("class(SDL2Interface) ::ProcessInput [Controller Event]\n");
+               break;
+
+            // Touch
+            case SDL_FINGERDOWN:
+            case SDL_FINGERUP:
+            case SDL_FINGERMOTION:
+               sflnprintf("class(SDL2Interface) ::ProcessInput [Touch Event]\n");
+               break;
+
+            // Gesture
+            case SDL_DOLLARGESTURE:
+            case SDL_DOLLARRECORD:
+            case SDL_MULTIGESTURE:
+               sflnprintf("class(SDL2Interface) ::ProcessInput [Gesture Event]\n");
+               break;
+
+            // Clipboard
+            case SDL_CLIPBOARDUPDATE:
+               sflnprintf("class(SDL2Interface) ::ProcessInput [Clipboard Event]\n");
+               break;
+
+            // Drag and Drop
+            case SDL_DROPFILE:
+               sflnprintf("class(SDL2Interface) ::ProcessInput [Drag and Drop Event]\n");
+               break;
+
+            // Render
+            case SDL_RENDER_TARGETS_RESET:
+            //case SDL_RENDER_DEVICE_RESET:
+               sflnprintf("class(SDL2Interface) ::ProcessInput [Render Event]\n");
+               break;
+
+            // Registered by SDL_RegisterEvents()
+            case SDL_USEREVENT:
+               sflnprintf("class(SDL2Interface) ::ProcessInput [User Event]\n");
+               break;
+
+            // Application
+            case SDL_QUIT:
+            {
+               sflnprintf("class(SDL2Interface) ::ProcessInput [SDL_QUIT]\n");
+               break;
+            }
+            case SDL_APP_TERMINATING:
+            case SDL_APP_LOWMEMORY:
+            case SDL_APP_WILLENTERBACKGROUND:
+            case SDL_APP_DIDENTERBACKGROUND:
+            case SDL_APP_WILLENTERFOREGROUND:
+            case SDL_APP_DIDENTERFOREGROUND:
+               sflnprintf("class(SDL2Interface) ::ProcessInput [Application Event]\n");
+               break;
+         }
+      }
+      return result;
+   }
+
+   void ::Wait()
+   {
+      //sflnprintf("class(SDL2Interface) ::Wait [WIP!]\n");
+      SDL_WaitEventTimeout(null, (int)(1000 / 18.2));
+   }
+
+   void ::Lock(Window window)
+   {
+      sflnprintf("class(SDL2Interface) ::Lock [STUB!]\n");
+   }
+
+   void ::Unlock(Window window)
+   {
+      sflnprintf("class(SDL2Interface) ::Unlock [STUB!]\n");
+   }
+
+   void ::SetTimerResolution(uint hertz)
+   {
+      sflnprintf("class(SDL2Interface) ::SetTimerResolution [STUB!] Implement high resolution timer here\n");
+   }
+
+   const char ** ::GraphicsDrivers(int * numDrivers)
+   {
+      static const char *graphicsDrivers[] = { "SDL2" };
+      *numDrivers = sizeof(graphicsDrivers) / sizeof(char *);
+      return (const char **)graphicsDrivers;
+   }
+
+   void ::EnsureFullScreen(bool * fullScreen)
+   {
+      sflnprintf("class(SDL2Interface) ::EnsureFullScreen [STUB!]\n");
+   }
+
+   void ::GetCurrentMode(bool * fullScreen, Resolution * resolution, PixelFormat * colorDepth, int * refreshRate)
+   {
+      int width = 0, height = 0, bpp = 0, freq = 0;
+      sflnprintf("class(SDL2Interface) ::GetCurrentMode [WIP!]\n");
+      *fullScreen = fullScreenMode;
+      if(fullScreenMode)
+      {
+         Resolution c;
+         for(c = 0; c<Resolution::enumSize; c++)
+            if(GetResolutionWidth(c) == width && GetResolutionHeight(c) == height)
+            {
+               *resolution = c;
+               break;
+            }
+         switch(bpp)
+         {
+            case 8: *colorDepth = pixelFormat8; break;
+            case 16: *colorDepth = pixelFormat555; break;
+            default: *colorDepth = pixelFormat888; break;
+         }
+         *refreshRate = freq;
+      }
+   }
+
+   bool ::ScreenMode(bool fullScreen, Resolution resolution, PixelFormat colorDepth, int refreshRate, bool * textMode)
+   {
+      bool result = true;
+      sflnprintf("class(SDL2Interface) ::ScreenMode [WIP!]\n");
+
+      fullScreenMode = fullScreen;
+      // TODO: Set resolution
+
+      if(fullScreen)
+      {
+      }
+      else
+      {
+      }
+      return result;
+   }
+
+
+   // --- Window Creation ---
+
+   void * ::CreateRootWindow(Window window)
+   {
+      SDL_Window * wnd = null;
+      SDL_Renderer * ren = null;
+      SDL_WindowFlags flags =
+            (fullScreenMode ? /*SDL_WINDOW_FULLSCREEN_DESKTOP*/SDL_WINDOW_FULLSCREEN_DESKTOP : 0) |
+            SDL_WINDOW_OPENGL |
+            (window.visible ? SDL_WINDOW_SHOWN : SDL_WINDOW_HIDDEN) |
+            (window.nativeDecorations ? 0 : SDL_WINDOW_BORDERLESS) |
+            (window.nativeDecorations && window.style.borderBits.sizable ? SDL_WINDOW_RESIZABLE : 0) |
+            (window.state == minimized ? SDL_WINDOW_MINIMIZED : window.state == maximized ? SDL_WINDOW_MAXIMIZED : 0);
+            //SDL_WINDOW_INPUT_GRABBED |
+            //SDL_WINDOW_INPUT_FOCUS |
+            //SDL_WINDOW_MOUSE_FOCUS |
+            //SDL_WINDOW_FOREIGN |
+            //SDL_WINDOW_ALLOW_HIGHDPI |
+            //SDL_WINDOW_MOUSE_CAPTURE |
+      int posFlag = SDL_WINDOWPOS_CENTERED/*SDL_WINDOWPOS_UNDEFINED*/;
+      SDL_RendererFlags rendererFlags =
+            //SDL_RENDERER_SOFTWARE |
+            SDL_RENDERER_ACCELERATED |
+            SDL_RENDERER_PRESENTVSYNC;
+            //SDL_RENDERER_TARGETTEXTURE;
+      sflnprintf("class(SDL2Interface) ::CreateRootWindow [WIP!] -- %d, %d\n", window.size.w, window.size.h);
+
+#if 0
+      //--//SDL_CreateRenderer(windowHandle, -1, SDL_RENDERER_PRESENTFLIP2|SDL_RENDERER_PRESENTVSYNC|SDL_RENDERER_ACCELERATED);
+      //--//SDL_SelectRenderer(windowHandle);
+#endif
+
+      if(fullScreenMode)
+      {
+      }
+      else if(window.systemParent)
+      {
+         wnd = SDL_CreateWindow(window.text, posFlag, posFlag, window.size.w, window.size.h, flags);
+      }
+      else
+      {
+         //HWND parentWindow = null; //HWND_DESKTOP; // we get different behaviors with desktop...
+         //Window master = window.master;, rootWindow = (master && master != guiApp.desktop) ? master.rootWindow : null;
+
+         /*if(rootWindow && (window._isModal || window.style.interim))
+            parentWindow = rootWindow.is3D ? rootWindow.parent.windowHandle : rootWindow.windowHandle;*/
+
+         if(window.windowHandle)
+            wnd = window.windowHandle;
+         else
+         {
+            wnd = SDL_CreateWindow(window.text, posFlag, posFlag, window.size.w, window.size.h, flags);
+            SDL_SetWindowData(wnd, "Ecere", window);
+            ren = SDL_CreateRenderer(wnd, -1, rendererFlags);
+            window.windowData = ren;
+            //window.display.driverData
+            //--//SDL_SelectRenderer(wnd);
+         }
+      }
+      return wnd;
+   }
+
+   void ::DestroyRootWindow(Window window)
+   {
+      sflnprintf("class(SDL2Interface) ::DestroyRootWindow [STUB!]\n");
+      SDL_DestroyWindow(window.systemHandle);
+   }
+
+
+   // --- Window manipulation ---
+
+   void ::SetRootWindowCaption(Window window, const char * name)
+   {
+      SDL_SetWindowTitle(window.systemHandle, name);
+   }
+
+   void ::PositionRootWindow(Window window, int x, int y, int w, int h, bool move, bool resize)
+   {
+      sflnprintf("class(SDL2Interface) ::PositionRootWindow [WIP!]\n");
+      if(move) SDL_SetWindowPosition(window.windowHandle, x, y);
+      if(resize) SDL_SetWindowSize(window.windowHandle, w, h);
+   }
+
+   void ::OffsetWindow(Window window, int * x, int * y)
+   {
+      sflnprintf("class(SDL2Interface) ::OffsetWindow [WIP!]\n");
+      //SDL_SetWindowPosition(window.windowHandle, *x, *y);
+   }
+
+   void ::UpdateRootWindow(Window window)
+   {
+      sflnprintf("class(SDL2Interface) ::UpdateRootWindow [STUB!]\n");
+   }
+
+   void ::SetRootWindowState(Window window, WindowState state, bool visible)
+   {
+      sflnprintf("class(SDL2Interface) ::SetRootWindowState [STUB!]\n");
+      if(visible)
+      {
+         SDL_ShowWindow(window.systemHandle);
+      }
+      else
+      {
+         SDL_HideWindow(window.systemHandle);
+      }
+   }
+
+   void ::ActivateRootWindow(Window window)
+   {
+      sflnprintf("class(SDL2Interface) ::ActivateRootWindow [STUB!]\n");
+   }
+
+   void ::OrderRootWindow(Window window, bool topMost)
+   {
+      sflnprintf("class(SDL2Interface) ::OrderRootWindow [STUB!]\n");
+   }
+
+   void ::SetRootWindowColor(Window window)
+   {
+      sflnprintf("class(SDL2Interface) ::SetRootWindowColor [STUB!]\n");
+   }
+
+   void ::FlashRootWindow(Window window)
+   {
+      sflnprintf("class(SDL2Interface) ::FlashRootWindow [STUB!]\n");
+   }
+
+
+   // --- Mouse-based window movement ---
+
+   void ::StartMoving(Window window, int x, int y, bool fromKeyBoard)
+   {
+      sflnprintf("class(SDL2Interface) ::StartMoving [STUB!]\n");
+   }
+
+   void ::StopMoving(Window window)
+   {
+      sflnprintf("class(SDL2Interface) ::StopMoving [STUB!]\n");
+   }
+
+
+   // --- Mouse manipulation ---
+
+   void ::GetMousePosition(int *x, int *y)
+   {
+      sflnprintf("class(SDL2Interface) ::GetMousePosition [STUB!]\n");
+   }
+
+   void ::SetMousePosition(int x, int y)
+   {
+      sflnprintf("class(SDL2Interface) ::SetMousePosition [STUB!]\n");
+   }
+
+   void ::SetMouseRange(Window window, Box box)
+   {
+      sflnprintf("class(SDL2Interface) ::SetMouseRange [STUB!]\n");
+   }
+
+   void ::SetMouseCapture(Window window)
+   {
+      sflnprintf("class(SDL2Interface) ::SetMouseCapture [STUB!]\n");
+   }
+
+
+   // --- Mouse cursor ---
+
+   void ::SetMouseCursor(Window window, SystemCursor cursor)
+   {
+      sflnprintf("class(SDL2Interface) ::SetMouseCursor [STUB!]\n");
+      // (cursor == (SystemCursor)-1) ? null : systemCursors[cursor]);
+   }
+
+
+   // --- Caret manipulation ---
+
+   void ::SetCaret(int caretX, int caretY, int size)
+   {
+      sflnprintf("class(SDL2Interface) ::SetCaret [STUB!]\n");
+   }
+
+
+   // --- Clipboard manipulation ---
+
+   void ::ClearClipboard()
+   {
+      sflnprintf("class(SDL2Interface) ::ClearClipboard [STUB!]\n");
+   }
+
+   bool ::AllocateClipboard(ClipBoard clipBoard, uint size)
+   {
+      bool result = false;
+      sflnprintf("class(SDL2Interface) ::AllocateClipboard [WIP!]\n");
+      clipBoard.text = new byte[size];
+      result = true;
+      return result;
+   }
+
+   bool ::SaveClipboard(ClipBoard clipBoard)
+   {
+      bool result = false;
+      sflnprintf("class(SDL2Interface) ::SaveClipboard [WIP!]\n");
+      if(clipBoard.text)
+      {
+
+      }
+      return result;
+   }
+
+   bool ::LoadClipboard(ClipBoard clipBoard)
+   {
+      bool result = false;
+      sflnprintf("class(SDL2Interface) ::LoadClipboard [STUB!]\n");
+      return result;
+   }
+
+   void ::UnloadClipboard(ClipBoard clipBoard)
+   {
+      sflnprintf("class(SDL2Interface) ::UnloadClipboard [WIP!]\n");
+      delete clipBoard.text;
+   }
+
+
+   // --- State based input ---
+
+   bool ::AcquireInput(Window window, bool state)
+   {
+      sflnprintf("class(SDL2Interface) ::AcquireInput [STUB!]\n");
+      return false;
+   }
+
+   bool ::GetMouseState(MouseButtons * buttons, int * x, int * y)
+   {
+      bool result = false;
+      sflnprintf("class(SDL2Interface) ::GetMouseState [STUB!]\n");
+      return result;
+   }
+
+   bool ::GetJoystickState(int device, Joystick joystick)
+   {
+      bool result = false;
+      sflnprintf("class(SDL2Interface) ::GetJoystickState [STUB!]\n");
+      return result;
+   }
+
+   bool ::GetKeyState(Key key)
+   {
+      bool keyState = false;
+      sflnprintf("class(SDL2Interface) ::GetKeyState [STUB!]\n");
+      return keyState;
+   }
+
+   bool ::SetIcon(Window window, BitmapResource icon)
+   {
+      sflnprintf("class(SDL2Interface) ::SetIcon [WIP!]\n");
+      if(icon)
+      {
+         Bitmap bitmap { };
+         if(bitmap.Load(icon.fileName, null, null))
+         {
+            Bitmap and { };
+            //int y, x;
+            PixelFormat format = window.display.pixelFormat;
+            //int bits = 8<<GetColorDepthShifts(format);
+            int bits;
+            bool blend;
+
+            bits = GetDepthBits(format);
+
+            bitmap.Convert(null, pixelFormat888, null);
+            and.Allocate(null, (bitmap.width+7/8), bitmap.height, 0, pixelFormat8, false);
+
+            blend = bits == 32 || bitmap.pixelFormat != pixelFormat888;
+
+            {
+               //byte * picture = and.picture;
+               int c = 0;
+               int b = 0;
+               uint size = bitmap.height * bitmap.width;
+               while(c < size)
+               {
+                  int m = 0;
+                  byte mask = 0;
+                  while(m < 8 && c < size)
+                  {
+                     mask <<= 1;
+                     mask |= blend ? (!((ColorAlpha *)bitmap.picture)[c].a) : (((ColorAlpha *)bitmap.picture)[c].a <= 192);
+                     c++;
+                     m++;
+                  }
+                  and.picture[b++] = mask;
+               }
+               c = 0;
+               while(c < size)
+               {
+                  ColorAlpha color = ((ColorAlpha *)bitmap.picture)[c];
+                  if(blend ? (!color.a) : (color.a <= 192))
+                  {
+                     color.color = { 0, 0, 0 };
+                     ((ColorAlpha *)bitmap.picture)[c] = color;
+                  }
+                  c++;
+               }
+            }
+            if(bits == 15) { bits = 16; format = pixelFormat565; };
+            bitmap.Convert(null, format, null);
+
+            // icon = CreateIcon(hInstance, bitmap.width, bitmap.height, 1, (byte)bits, and.picture, bitmap.picture);
+            delete and;
+         }
+         delete bitmap;
+      }
+      return true;
+   }
+
+   void ::GetScreenArea(Window window, Box box)
+   {
+      SDL_DisplayMode current;
+      int error = SDL_GetCurrentDisplayMode(0, &current);
+      sflnprintf("class(SDL2Interface) ::GetScreenArea [WIP!]\n");
+      // todo: support multiple displays.
+      if(error)
+      {
+         box = { 0, 0, 800, 600 };
+      }
+      else
+      {
+         box = { 0, 0, current.w, current.h };
+      }
+   }
+}
+
+#endif // !defined(NO_SDL_DRIVERS) && !defined(NO_SDL2_DRIVER)